DatBackupManager.cpp 6.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147
  1. //
  2. // Created by kikab on 04.06.2018.
  3. //
  4. #include <DatFile.h>
  5. #include <DatSubsystems/DatBackupManager.h>
  6. #include "DatSubsystems/DatBackupManager.h"
  7. #include "EasyLogging++/easylogging++.h"
  8. namespace LOTRO_DAT {
  9. DatBackupManager::DatBackupManager(DatFile *datFilePtr): dat(datFilePtr) {}
  10. /*!
  11. * \author Gi1dor
  12. * \date 11.07.2018
  13. * Проверка доступности и корректности бэкапа dat файла
  14. * \param[in] backup_datname путь к файлу бэкапа
  15. * \returns true - если файл доступен для чтения его структура корректна. Иначе false
  16. */
  17. bool DatBackupManager::CheckIfBackupAvailable(const std::string &backup_datname) {
  18. DatFile file;
  19. bool result = (file.Initialise(backup_datname, 0).result == SUCCESS && file.Initialized());
  20. file.Deinitialize();
  21. return result;
  22. }
  23. /*!
  24. * \author Gi1dor
  25. * \date 11.07.2018
  26. * Создание резервной копии инициализированного Dat файла.
  27. *
  28. * \param[in] backup_datname путь к файлу создаваемого бэкапа
  29. */
  30. DatOperationResult<> DatBackupManager::CreateBackup(const std::string &backup_datname) {
  31. FILE* file = fopen(backup_datname.c_str(), "w+b");
  32. if (!file)
  33. return DatOperationResult<>(ERROR, "CREATEBACKUP: cannot open file " + backup_datname);
  34. dat->GetStatusModule().SetStatus(DatStatus::E_BACKUP_CREATING);
  35. dat->GetStatusModule().SetDebugMessage("Creating backup " + backup_datname + " from " + dat->GetIO().GetFilename().value);
  36. auto operation = CopyDatFile(*dat, file);
  37. dat->GetStatusModule().SetDefaultStatus();
  38. fclose(file);
  39. if (operation.result != SUCCESS)
  40. return DatOperationResult<>(ERROR, "CREATEBACKUP: Error in copy dat file");
  41. return DatOperationResult<>(SUCCESS);
  42. }
  43. /*!
  44. * \author Gi1dor
  45. * \date 11.07.2018
  46. * Восстановление dat файла из резервной копии. Если восстановление не удалось, DatFile будет деинициализирован.
  47. * \param[in] backup_datname путь к файлу резервной копии
  48. */
  49. DatOperationResult<> DatBackupManager::RestoreFromBackup(const std::string &backup_datname) {
  50. if (!CheckIfBackupAvailable(backup_datname))
  51. return DatOperationResult<>(ERROR, "RESTOREFROMBACKUP: incorrect backup file " + backup_datname);
  52. DatFile backup_file;
  53. backup_file.Initialise(backup_datname, 0);
  54. std::string dat_filename = dat->GetIO().GetFilename().value;
  55. dat->Deinitialize();
  56. FILE* file = fopen(dat_filename.c_str(), "w+b");
  57. if (!file)
  58. return DatOperationResult<>(ERROR, "RESTOREFROMBACKUP: cannot open file " + backup_datname);
  59. dat->GetStatusModule().SetStatus(DatStatus::E_BACKUP_RESTORING);
  60. dat->GetStatusModule().SetFinishedParts(0);
  61. dat->GetStatusModule().SetDebugMessage("Restoring file " + dat->GetIO().GetFilename().value + " from backup " + backup_datname);
  62. auto operation = CopyDatFile(backup_file, file);
  63. dat->GetStatusModule().SetDefaultStatus();
  64. fclose(file);
  65. if (operation.result == ERROR)
  66. return DatOperationResult<>(ERROR, "RESTOREFROMBACKUP: error in copy dat file");
  67. dat->Initialise(dat_filename, dat->GetDatID());
  68. return DatOperationResult<>(SUCCESS);
  69. }
  70. /*!
  71. * \author Gi1dor
  72. * \date 11.07.2018
  73. * Удаление резервной копии.
  74. * \param[in] backup_datname путь к файлу резервной копии
  75. */
  76. DatOperationResult<> DatBackupManager::RemoveBackup(const std::string &backup_datname) {
  77. dat->GetStatusModule().SetStatus(DatStatus::E_BACKUP_REMOVING);
  78. dat->GetStatusModule().SetFinishedParts(0);
  79. dat->GetStatusModule().SetTotalParts(1);
  80. dat->GetStatusModule().SetDebugMessage("Removing backup file " + backup_datname);
  81. if (remove(backup_datname.c_str()) != 0)
  82. LOG(INFO) << "Removed backup file " << backup_datname;
  83. dat->GetStatusModule().SetDefaultStatus();
  84. return DatOperationResult<>(SUCCESS);
  85. }
  86. /*!
  87. * \author Gi1dor
  88. * \date 11.07.2018
  89. * Копирует содержимое dat файла в файл target
  90. * \param[in] source dat файл для копирования. Должен быть проинициализирован
  91. * \param[in] target файл для записи. Должен быть открыт на запись.
  92. * \warning Файл target после выполнения функции НЕ будет закрыт. Требуется закрыть командой fclose;
  93. */
  94. DatOperationResult<> DatBackupManager::CopyDatFile(DatFile &source, FILE *target) {
  95. long long parts_count =
  96. source.GetIO().GetActualDatSize().value / COPY_BLOCK_SIZE + (source.GetIO().GetActualDatSize().value % COPY_BLOCK_SIZE != 0);
  97. long long newfile_size = 0;
  98. unsigned elapsed_size = unsigned(source.GetIO().GetActualDatSize().value - newfile_size);
  99. dat->GetStatusModule().SetTotalParts(source.GetIO().GetActualDatSize().value);
  100. BinaryData data(COPY_BLOCK_SIZE);
  101. for (unsigned i = 0; i < parts_count; i++) {
  102. dat->GetStatusModule().SetFinishedParts(i * COPY_BLOCK_SIZE);
  103. auto operation = source.GetIO().ReadData(data, std::min(COPY_BLOCK_SIZE, elapsed_size), newfile_size);
  104. if (operation.result == ERROR)
  105. return DatOperationResult<>(ERROR, "Copy failed. Read data error");
  106. fwrite(data.data(), std::min(COPY_BLOCK_SIZE, elapsed_size), 1, target);
  107. newfile_size += std::min(COPY_BLOCK_SIZE, elapsed_size);
  108. elapsed_size -= std::min(COPY_BLOCK_SIZE, elapsed_size);
  109. }
  110. return DatOperationResult<>(SUCCESS);
  111. }
  112. }