diff --git a/native/cpp/CommonCpp/DatabaseManagers/DatabaseManager.h b/native/cpp/CommonCpp/DatabaseManagers/DatabaseManager.h --- a/native/cpp/CommonCpp/DatabaseManagers/DatabaseManager.h +++ b/native/cpp/CommonCpp/DatabaseManagers/DatabaseManager.h @@ -50,6 +50,7 @@ // Backup methods static void captureBackupLogs(); static void triggerBackupFileUpload(); + static void createMainCompaction(std::string backupID); }; } // namespace comm diff --git a/native/cpp/CommonCpp/DatabaseManagers/DatabaseManager.cpp b/native/cpp/CommonCpp/DatabaseManagers/DatabaseManager.cpp --- a/native/cpp/CommonCpp/DatabaseManagers/DatabaseManager.cpp +++ b/native/cpp/CommonCpp/DatabaseManagers/DatabaseManager.cpp @@ -4,12 +4,15 @@ #include "../Tools/CommSecureStore.h" #include "Logger.h" #include "PlatformSpecificTools.h" +#include "SQLiteBackup.h" #include "SQLiteQueryExecutor.h" #include "SQLiteUtils.h" +#include "entities/EntityQueryHelpers.h" #include "../Tools/ServicesUtils.h" #include "lib.rs.h" +#include #include namespace comm { @@ -229,4 +232,108 @@ ::triggerBackupFileUpload(); } +void DatabaseManager::createMainCompaction(std::string backupID) { + std::string finalBackupPath = + PlatformSpecificTools::getBackupFilePath(backupID, false); + std::string finalAttachmentsPath = + PlatformSpecificTools::getBackupFilePath(backupID, true); + + std::string tempBackupPath = finalBackupPath + "_tmp"; + std::string tempAttachmentsPath = finalAttachmentsPath + "_tmp"; + + if (SQLiteUtils::fileExists(tempBackupPath)) { + Logger::log( + "Attempting to delete temporary backup file from previous backup " + "attempt."); + SQLiteUtils::attemptDeleteFile( + tempBackupPath, + "Failed to delete temporary backup file from previous backup " + "attempt."); + } + + if (SQLiteUtils::fileExists(tempAttachmentsPath)) { + Logger::log( + "Attempting to delete temporary attachments file from previous " + "backup " + "attempt."); + SQLiteUtils::attemptDeleteFile( + tempAttachmentsPath, + "Failed to delete temporary attachments file from previous backup " + "attempt."); + } + + sqlite3 *backupDB; + sqlite3_open(tempBackupPath.c_str(), &backupDB); + SQLiteUtils::setEncryptionKey(backupDB, SQLiteQueryExecutor::backupDataKey); + + sqlite3_backup *backupObj = sqlite3_backup_init( + backupDB, "main", SQLiteQueryExecutor::getConnection(), "main"); + if (!backupObj) { + std::stringstream error_message; + error_message << "Failed to init backup for main compaction. Details: " + << sqlite3_errmsg(backupDB) << std::endl; + sqlite3_close(backupDB); + Logger::log(error_message.str()); + throw std::runtime_error(error_message.str()); + } + + int backupResult = sqlite3_backup_step(backupObj, -1); + sqlite3_backup_finish(backupObj); + if (backupResult == SQLITE_BUSY || backupResult == SQLITE_LOCKED) { + sqlite3_close(backupDB); + throw std::runtime_error( + "Programmer error. Database in transaction during backup attempt."); + } else if (backupResult != SQLITE_DONE) { + sqlite3_close(backupDB); + std::stringstream error_message; + error_message << "Failed to create database backup. Details: " + << sqlite3_errstr(backupResult); + Logger::log(error_message.str()); + throw std::runtime_error(error_message.str()); + } + + SQLiteBackup::cleanupDatabaseExceptAllowlist(backupDB); + executeQuery(backupDB, "VACUUM;"); + sqlite3_close(backupDB); + + SQLiteUtils::attemptRenameFile( + tempBackupPath, + finalBackupPath, + "Failed to rename complete temporary backup file to final backup " + "file."); + + std::ofstream tempAttachmentsFile(tempAttachmentsPath); + if (!tempAttachmentsFile.is_open()) { + std::string errorMessage{ + "Unable to create attachments file for backup id: " + backupID}; + Logger::log(errorMessage); + throw std::runtime_error(errorMessage); + } + + std::string getAllBlobServiceMediaSQL = + "SELECT * FROM media WHERE uri LIKE 'comm-blob-service://%';"; + std::vector blobServiceMedia = getAllEntities( + SQLiteQueryExecutor::getConnection(), getAllBlobServiceMediaSQL); + + for (const auto &media : blobServiceMedia) { + std::string blobServiceURI = media.uri; + std::string blobHash = + SQLiteUtils::blobHashFromBlobServiceURI(blobServiceURI); + tempAttachmentsFile << blobHash << "\n"; + } + tempAttachmentsFile.close(); + + SQLiteUtils::attemptRenameFile( + tempAttachmentsPath, + finalAttachmentsPath, + "Failed to rename complete temporary attachments file to final " + "attachments file."); + + DatabaseManager::getQueryExecutor().setMetadata("backupID", backupID); + DatabaseManager::getQueryExecutor().clearMetadata("logID"); + if (ServicesUtils::fullBackupSupport) { + SQLiteQueryExecutor::connectionManager.setLogsMonitoring(true); + } +} + } // namespace comm diff --git a/native/cpp/CommonCpp/DatabaseManagers/DatabaseQueryExecutor.h b/native/cpp/CommonCpp/DatabaseManagers/DatabaseQueryExecutor.h --- a/native/cpp/CommonCpp/DatabaseManagers/DatabaseQueryExecutor.h +++ b/native/cpp/CommonCpp/DatabaseManagers/DatabaseQueryExecutor.h @@ -198,10 +198,6 @@ virtual std::vector getDMOperationsByType(const std::string &operationType) const = 0; virtual ~DatabaseQueryExecutor() = default; - -#ifndef EMSCRIPTEN - virtual void createMainCompaction(std::string backupID) const = 0; -#endif }; } // namespace comm diff --git a/native/cpp/CommonCpp/DatabaseManagers/SQLiteQueryExecutor.h b/native/cpp/CommonCpp/DatabaseManagers/SQLiteQueryExecutor.h --- a/native/cpp/CommonCpp/DatabaseManagers/SQLiteQueryExecutor.h +++ b/native/cpp/CommonCpp/DatabaseManagers/SQLiteQueryExecutor.h @@ -211,7 +211,6 @@ std::string &databasePath, std::string &backupDataKey, std::string &backupLogDataKey); - void createMainCompaction(std::string backupID) const override; #endif }; diff --git a/native/cpp/CommonCpp/DatabaseManagers/SQLiteQueryExecutor.cpp b/native/cpp/CommonCpp/DatabaseManagers/SQLiteQueryExecutor.cpp --- a/native/cpp/CommonCpp/DatabaseManagers/SQLiteQueryExecutor.cpp +++ b/native/cpp/CommonCpp/DatabaseManagers/SQLiteQueryExecutor.cpp @@ -1640,110 +1640,6 @@ SQLiteQueryExecutor::backupLogDataKey = backupLogDataKey; } -void SQLiteQueryExecutor::createMainCompaction(std::string backupID) const { - std::string finalBackupPath = - PlatformSpecificTools::getBackupFilePath(backupID, false); - std::string finalAttachmentsPath = - PlatformSpecificTools::getBackupFilePath(backupID, true); - - std::string tempBackupPath = finalBackupPath + "_tmp"; - std::string tempAttachmentsPath = finalAttachmentsPath + "_tmp"; - - if (SQLiteUtils::fileExists(tempBackupPath)) { - Logger::log( - "Attempting to delete temporary backup file from previous backup " - "attempt."); - SQLiteUtils::attemptDeleteFile( - tempBackupPath, - "Failed to delete temporary backup file from previous backup " - "attempt."); - } - - if (SQLiteUtils::fileExists(tempAttachmentsPath)) { - Logger::log( - "Attempting to delete temporary attachments file from previous " - "backup " - "attempt."); - SQLiteUtils::attemptDeleteFile( - tempAttachmentsPath, - "Failed to delete temporary attachments file from previous backup " - "attempt."); - } - - sqlite3 *backupDB; - sqlite3_open(tempBackupPath.c_str(), &backupDB); - SQLiteUtils::setEncryptionKey(backupDB, SQLiteQueryExecutor::backupDataKey); - - sqlite3_backup *backupObj = sqlite3_backup_init( - backupDB, "main", SQLiteQueryExecutor::getConnection(), "main"); - if (!backupObj) { - std::stringstream error_message; - error_message << "Failed to init backup for main compaction. Details: " - << sqlite3_errmsg(backupDB) << std::endl; - sqlite3_close(backupDB); - Logger::log(error_message.str()); - throw std::runtime_error(error_message.str()); - } - - int backupResult = sqlite3_backup_step(backupObj, -1); - sqlite3_backup_finish(backupObj); - if (backupResult == SQLITE_BUSY || backupResult == SQLITE_LOCKED) { - sqlite3_close(backupDB); - throw std::runtime_error( - "Programmer error. Database in transaction during backup attempt."); - } else if (backupResult != SQLITE_DONE) { - sqlite3_close(backupDB); - std::stringstream error_message; - error_message << "Failed to create database backup. Details: " - << sqlite3_errstr(backupResult); - Logger::log(error_message.str()); - throw std::runtime_error(error_message.str()); - } - - SQLiteBackup::cleanupDatabaseExceptAllowlist(backupDB); - executeQuery(backupDB, "VACUUM;"); - sqlite3_close(backupDB); - - SQLiteUtils::attemptRenameFile( - tempBackupPath, - finalBackupPath, - "Failed to rename complete temporary backup file to final backup " - "file."); - - std::ofstream tempAttachmentsFile(tempAttachmentsPath); - if (!tempAttachmentsFile.is_open()) { - std::string errorMessage{ - "Unable to create attachments file for backup id: " + backupID}; - Logger::log(errorMessage); - throw std::runtime_error(errorMessage); - } - - std::string getAllBlobServiceMediaSQL = - "SELECT * FROM media WHERE uri LIKE 'comm-blob-service://%';"; - std::vector blobServiceMedia = getAllEntities( - SQLiteQueryExecutor::getConnection(), getAllBlobServiceMediaSQL); - - for (const auto &media : blobServiceMedia) { - std::string blobServiceURI = media.uri; - std::string blobHash = - SQLiteUtils::blobHashFromBlobServiceURI(blobServiceURI); - tempAttachmentsFile << blobHash << "\n"; - } - tempAttachmentsFile.close(); - - SQLiteUtils::attemptRenameFile( - tempAttachmentsPath, - finalAttachmentsPath, - "Failed to rename complete temporary attachments file to final " - "attachments file."); - - this->setMetadata("backupID", backupID); - this->clearMetadata("logID"); - if (ServicesUtils::fullBackupSupport) { - SQLiteQueryExecutor::connectionManager.setLogsMonitoring(true); - } -} - #endif void SQLiteQueryExecutor::copyTablesDataUsingAttach( diff --git a/native/cpp/CommonCpp/NativeModules/PersistentStorageUtilities/BackupOperationsUtilities/BackupOperationsExecutor.cpp b/native/cpp/CommonCpp/NativeModules/PersistentStorageUtilities/BackupOperationsUtilities/BackupOperationsExecutor.cpp --- a/native/cpp/CommonCpp/NativeModules/PersistentStorageUtilities/BackupOperationsUtilities/BackupOperationsExecutor.cpp +++ b/native/cpp/CommonCpp/NativeModules/PersistentStorageUtilities/BackupOperationsUtilities/BackupOperationsExecutor.cpp @@ -12,7 +12,7 @@ size_t futureID) { taskType job = [backupID, futureID]() { try { - DatabaseManager::getQueryExecutor().createMainCompaction(backupID); + DatabaseManager::createMainCompaction(backupID); ::resolveUnitFuture(futureID); } catch (const std::exception &e) { ::rejectFuture(futureID, rust::String(e.what()));