aboutsummaryrefslogtreecommitdiff
path: root/src/backup.cpp
diff options
context:
space:
mode:
authorJan Sucan <jan@jansucan.com>2024-04-14 11:51:34 +0200
committerJán Sučan <jan@jansucan.com>2024-05-04 15:46:47 +0200
commit16ff70613a95d7f85f4cab09f2b3316f67e5901b (patch)
treec7b7768dd048d2ca040ea09c2e9df554d6f1e5ad /src/backup.cpp
parent451be15d119d4d485d06f19f15d9a996cefb5288 (diff)
Move input and output buffering to classes
Diffstat (limited to 'src/backup.cpp')
-rw-r--r--src/backup.cpp179
1 files changed, 39 insertions, 140 deletions
diff --git a/src/backup.cpp b/src/backup.cpp
index 99a9141..111d3f3 100644
--- a/src/backup.cpp
+++ b/src/backup.cpp
@@ -25,79 +25,12 @@
*/
#include "backup.h"
+#include "buffered_file.h"
#include <cstring>
#include <fstream>
-typedef struct {
- std::ifstream in_file;
- std::ifstream ref_file;
- std::ofstream out_file;
-
- std::unique_ptr<char[]> in_buffer;
- std::unique_ptr<char[]> ref_buffer;
- std::unique_ptr<char[]> out_buffer;
-
- size_t out_buffer_size;
-} resources_backup_t;
-
static void check_files(const OptionsBackup &opts);
-static void write_out_buffer(const char *const buffer, size_t size,
- std::ofstream &file);
-
-static resources_backup_t
-resources_allocate_for_backup(const OptionsBackup &opts)
-{
- resources_backup_t res;
-
- res.in_file.open(opts.getInFilePath(),
- std::ifstream::in | std::ifstream::binary);
- if (!res.in_file) {
- throw BackupError("cannot open input file");
- }
-
- res.ref_file.open(opts.getRefFilePath(),
- std::ifstream::in | std::ifstream::binary);
- if (!res.ref_file) {
- throw BackupError("cannot open reference file");
- }
-
- /* When backing up, the output file is truncated to hold the
- * new data
- */
- res.out_file.open(opts.getOutFilePath(), std::ifstream::out |
- std::ifstream::trunc |
- std::ifstream::binary);
- if (!res.out_file) {
- throw BackupError("cannot open output file");
- }
-
- /* The output buffer contains also the offsets */
- res.out_buffer_size =
- ((opts.getBufferSize() / opts.getSectorSize()) * sizeof(uint64_t)) +
- opts.getBufferSize();
-
- // TODO: separate function
- try {
- res.in_buffer = std::make_unique<char[]>(opts.getBufferSize());
- } catch (const std::bad_alloc &e) {
- throw BackupError("cannot allocate buffer for input file data");
- }
-
- try {
- res.ref_buffer = std::make_unique<char[]>(opts.getBufferSize());
- } catch (const std::bad_alloc &e) {
- throw BackupError("cannot allocate buffer for reference file data");
- }
-
- try {
- res.out_buffer = std::make_unique<char[]>(res.out_buffer_size);
- } catch (const std::bad_alloc &e) {
- throw BackupError("cannot allocate buffer for output file data");
- }
-
- return res;
-}
static void
check_files(const OptionsBackup &opts)
@@ -128,91 +61,57 @@ check_files(const OptionsBackup &opts)
}
}
-static void
-write_out_buffer(const char *const buffer, size_t size, std::ofstream &file)
+void
+backup(const OptionsBackup &opts)
{
- file.write(buffer, size);
+ check_files(opts);
- if (!file) {
- throw BackupError("cannot write to output file");
- }
-}
+ BufferedFileReader in_file(opts.getInFilePath(), opts.getBufferSize());
+ BufferedFileReader ref_file(opts.getRefFilePath(), opts.getBufferSize());
+ BufferedFileWriter out_file(opts.getOutFilePath(), opts.getBufferSize());
-static size_t
-read_sectors(std::ifstream &file, char *const buffer, uint32_t buffer_size,
- uint32_t sector_size)
-{
- file.read(buffer, buffer_size);
- const size_t bytes_read = file.gcount();
+ std::unique_ptr<char[]> in_buffer;
+ try {
+ in_buffer = std::make_unique<char[]>(opts.getSectorSize());
+ } catch (const std::bad_alloc &e) {
+ throw BackupError("cannot allocate sector buffer for input file data");
+ }
- if (!file.good() && !file.eof()) {
- throw BackupError("cannot read from file");
- } else if ((bytes_read % sector_size) != 0) {
+ std::unique_ptr<char[]> ref_buffer;
+ try {
+ ref_buffer = std::make_unique<char[]>(opts.getSectorSize());
+ } catch (const std::bad_alloc &e) {
throw BackupError(
- "data read from input file is not multiple of sector size");
- } else {
- return (bytes_read / sector_size);
+ "cannot allocate sector buffer for reference file data");
}
-}
-
-void
-backup(const OptionsBackup &opts)
-{
- resources_backup_t res{resources_allocate_for_backup(opts)};
- check_files(opts);
-
- size_t out_buffer_index = 0;
- uint64_t input_file_offset = 0;
+ uint64_t input_file_offset{0};
for (;;) {
- /* Read the sectors from the input and reference files into the buffers
- */
- const size_t in_sectors_read =
- read_sectors(res.in_file, res.in_buffer.get(), opts.getBufferSize(),
- opts.getSectorSize());
- const size_t ref_sectors_read =
- read_sectors(res.ref_file, res.ref_buffer.get(),
- opts.getBufferSize(), opts.getSectorSize());
+ // Read sectors
+ const size_t in_read_size =
+ in_file.read(in_buffer.get(), opts.getSectorSize());
+ const size_t ref_read_size =
+ ref_file.read(ref_buffer.get(), opts.getSectorSize());
- if ((in_sectors_read == 0) || (ref_sectors_read == 0)) {
- break;
- } else if (in_sectors_read != ref_sectors_read) {
+ if (in_read_size != ref_read_size) {
throw BackupError(
- "cannot read equal amount of sectors from the input files");
+ "cannot read equal amount of bytes from the input files");
+ } else if (in_read_size == 0) {
+ break;
+ } else if (in_read_size != opts.getSectorSize()) {
+ throw BackupError("cannot read full sectors from the input files");
}
- /* Process the sectors in the buffers */
- for (size_t sector = 0; sector < in_sectors_read; ++sector) {
- const size_t buffer_offset = sector * opts.getSectorSize();
-
- if (memcmp(res.in_buffer.get() + buffer_offset,
- res.ref_buffer.get() + buffer_offset,
- opts.getSectorSize()) != 0) {
- /* Backup the changed sector */
- if (out_buffer_index >= res.out_buffer_size) {
- /* The output buffer is full. Write it to the output file */
- write_out_buffer(res.out_buffer.get(), out_buffer_index,
- res.out_file);
- out_buffer_index = 0;
- }
- /* Write the next backup record */
- const uint64_t o = htole64(input_file_offset);
- memcpy(res.out_buffer.get() + out_buffer_index,
- reinterpret_cast<const void *>(&o), sizeof(o));
- out_buffer_index += sizeof(o);
-
- memcpy(res.out_buffer.get() + out_buffer_index,
- res.in_buffer.get() + buffer_offset,
- opts.getSectorSize());
- out_buffer_index += opts.getSectorSize();
- }
-
- input_file_offset += opts.getSectorSize();
+ // Check for difference
+ const bool differ = (memcmp(in_buffer.get(), ref_buffer.get(),
+ opts.getSectorSize()) != 0);
+ if (differ) {
+ // Backup sector
+ uint64_t o = htole64(input_file_offset);
+ out_file.write(reinterpret_cast<char *>(&o), sizeof(o));
+ out_file.write(in_buffer.get(), opts.getSectorSize());
}
- }
- /* Write out the output buffer */
- if (out_buffer_index > 0) {
- write_out_buffer(res.out_buffer.get(), out_buffer_index, res.out_file);
+ input_file_offset += opts.getSectorSize();
}
}