|
@@ -2,29 +2,124 @@
|
|
|
|
|
|
|
|
|
|
|
|
+#include <DatFile.h>
|
|
|
+#include <DatSubsystems/DatBackupManager.h>
|
|
|
+
|
|
|
#include "DatSubsystems/DatBackupManager.h"
|
|
|
#include "EasyLogging++/easylogging++.h"
|
|
|
|
|
|
-LOTRO_DAT::DatBackupManager::DatBackupManager(LOTRO_DAT::DatFile *datFilePtr) {
|
|
|
+namespace LOTRO_DAT {
|
|
|
+ DatBackupManager::DatBackupManager(DatFile *datFilePtr) {}
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+ * \author Gi1dor
|
|
|
+ * \date 11.07.2018
|
|
|
+ * Проверка доступности и корректности бэкапа dat файла
|
|
|
+ * \param[in] backup_datname путь к файлу бэкапа
|
|
|
+ * \returns true - если файл доступен для чтения его структура корректна. Иначе false
|
|
|
+ */
|
|
|
+
|
|
|
+ bool DatBackupManager::CheckIfBackupAvailable(const std::string &backup_datname) {
|
|
|
+ DatFile file;
|
|
|
+ return file.Initialise(backup_datname, 0).result == SUCCESS && file.Initialized();
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+ * \author Gi1dor
|
|
|
+ * \date 11.07.2018
|
|
|
+ * Создание резервной копии инициализированного Dat файла.
|
|
|
+ *
|
|
|
+ * \param[in] backup_datname путь к файлу создаваемого бэкапа
|
|
|
+ */
|
|
|
+
|
|
|
+ DatOperationResult<> DatBackupManager::CreateBackup(const std::string &backup_datname) {
|
|
|
+ FILE* file = fopen(backup_datname.c_str(), "w+b");
|
|
|
+ if (!file)
|
|
|
+ return DatOperationResult<>(ERROR, "CREATEBACKUP: cannot open file " + backup_datname);
|
|
|
+
|
|
|
+ auto operation = CopyDatFile(*dat, file);
|
|
|
+
|
|
|
+ fclose(file);
|
|
|
+
|
|
|
+ if (operation.result != SUCCESS)
|
|
|
+ return DatOperationResult<>(ERROR, "CREATEBACKUP: Error in copy dat file");
|
|
|
+ return DatOperationResult<>(SUCCESS);
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+ * \author Gi1dor
|
|
|
+ * \date 11.07.2018
|
|
|
+ * Восстановление dat файла из резервной копии. Если восстановление не удалось, DatFile будет деинициализирован.
|
|
|
+ * \param[in] backup_datname путь к файлу резервной копии
|
|
|
+ */
|
|
|
+
|
|
|
+ DatOperationResult<> DatBackupManager::RestoreFromBackup(const std::string &backup_datname) {
|
|
|
+ if (!CheckIfBackupAvailable(backup_datname))
|
|
|
+ return DatOperationResult<>(ERROR, "RESTOREFROMBACKUP: incorrect backup file " + backup_datname);
|
|
|
+
|
|
|
+ DatFile backup_file;
|
|
|
+ backup_file.Initialise(backup_datname, 0);
|
|
|
+
|
|
|
+ std::string dat_filename = dat->getIO().GetFilename().value;
|
|
|
+ dat->Deinitialize();
|
|
|
+
|
|
|
+ FILE* file = fopen(backup_datname.c_str(), "w+b");
|
|
|
+ if (!file)
|
|
|
+ return DatOperationResult<>(ERROR, "RESTOREFROMBACKUP: cannot open file " + backup_datname);
|
|
|
+
|
|
|
+ auto operation = CopyDatFile(backup_file, file);
|
|
|
+
|
|
|
+ fclose(file);
|
|
|
+ if (operation.result == ERROR)
|
|
|
+ return DatOperationResult<>(ERROR, "RESTOREFROMBACKUP: error in copy dat file");
|
|
|
+
|
|
|
+ dat->Initialise(dat_filename, dat->dat_id_);
|
|
|
+ return DatOperationResult<>(SUCCESS);
|
|
|
+ }
|
|
|
+
|
|
|
|
|
|
-}
|
|
|
+
|
|
|
+ * \author Gi1dor
|
|
|
+ * \date 11.07.2018
|
|
|
+ * Удаление резервной копии.
|
|
|
+ * \param[in] backup_datname путь к файлу резервной копии
|
|
|
+ */
|
|
|
|
|
|
-void LOTRO_DAT::DatBackupManager::Init() {
|
|
|
+ DatOperationResult<> DatBackupManager::RemoveBackup(const std::string &backup_datname) {
|
|
|
+ if (remove(backup_datname.c_str()) != 0)
|
|
|
+ LOG(INFO) << "Removed backup file " << backup_datname;
|
|
|
+ return DatOperationResult<>(SUCCESS);
|
|
|
+ }
|
|
|
|
|
|
-}
|
|
|
+
|
|
|
+ * \author Gi1dor
|
|
|
+ * \date 11.07.2018
|
|
|
+ * Копирует содержимое dat файла в файл target
|
|
|
+ * \param[in] source dat файл для копирования. Должен быть проинициализирован
|
|
|
+ * \param[in] target файл для записи. Должен быть открыт на запись.
|
|
|
+ * \warning Файл target после выполнения функции НЕ будет закрыт. Требуется закрыть командой fclose;
|
|
|
+ */
|
|
|
|
|
|
-bool LOTRO_DAT::DatBackupManager::CheckIfBackupExists(const std::string &backup_datname) {
|
|
|
- return false;
|
|
|
-}
|
|
|
+ DatOperationResult<> DatBackupManager::CopyDatFile(DatFile &source, FILE *target) {
|
|
|
+ long long parts_count = source.getIO().file_size / COPY_BLOCK_SIZE + (source.getIO().file_size % COPY_BLOCK_SIZE != 0);
|
|
|
+ long long newfile_size = 0;
|
|
|
+ long long elapsed_size = source.getIO().file_size - newfile_size;
|
|
|
|
|
|
-LOTRO_DAT::DatOperationResult<> LOTRO_DAT::DatBackupManager::CreateBackup(const std::string &backup_datname) {
|
|
|
-}
|
|
|
+ BinaryData data(COPY_BLOCK_SIZE);
|
|
|
+ for (unsigned i = 0; i < parts_count; i++) {
|
|
|
+ auto operation = source.getIO().ReadData(data, std::min((long long)(COPY_BLOCK_SIZE), elapsed_size), newfile_size);
|
|
|
+ if (operation.result == ERROR)
|
|
|
+ return DatOperationResult<>(ERROR, "Copy failed. Read data error");
|
|
|
+ fwrite(data.data(), data.size(), 1, target);
|
|
|
|
|
|
-LOTRO_DAT::DatOperationResult<> LOTRO_DAT::DatBackupManager::RestoreFromBackup(const std::string &backup_datname) {
|
|
|
-}
|
|
|
+ newfile_size += std::min((long long)(COPY_BLOCK_SIZE), elapsed_size);
|
|
|
+ elapsed_size -= std::min((long long)(COPY_BLOCK_SIZE), elapsed_size);
|
|
|
+ }
|
|
|
|
|
|
-LOTRO_DAT::DatOperationResult<> LOTRO_DAT::DatBackupManager::RemoveBackup(const std::string &backup_datname) {
|
|
|
-}
|
|
|
+ return DatOperationResult<>(SUCCESS);
|
|
|
+ }
|
|
|
|
|
|
-void LOTRO_DAT::DatBackupManager::DeInit() {
|
|
|
-}
|
|
|
+}
|