From d6a63be1fe4588f0b535cd26f8bb0567f1755f89 Mon Sep 17 00:00:00 2001 From: Pawel Olejniczak Date: Tue, 13 Sep 2022 20:16:35 +0200 Subject: [PATCH] [CP-1484] Add new mechanism for data synchronization between MOS and MC This mechanism is similar to the current backup implementation, but is stripped of irrelevant data that is not required by the MC to perform data synchronization. --- module-services/service-db/DBServiceAPI.cpp | 14 + .../include/service-db/DBServiceAPI.hpp | 1 + .../include/service-db/DBServiceMessage.hpp | 9 +- .../service-db/messages/DBServiceMessage.cpp | 6 +- .../service-desktop/BackupRestore.cpp | 259 +++++++++++++++--- .../service-desktop/ServiceDesktop.cpp | 79 ++++-- .../endpoints/backup/BackupHelper.cpp | 78 +++++- .../include/endpoints/JsonKeyNames.hpp | 59 ++-- .../include/endpoints/backup/BackupHelper.hpp | 4 +- .../endpoints/restore/RestoreHelper.cpp | 12 +- .../include/service-desktop/BackupRestore.hpp | 7 +- .../service-desktop/DesktopMessages.hpp | 10 +- .../service-desktop/ServiceDesktop.hpp | 9 +- module-vfs/paths/filesystem_paths.cpp | 6 + .../paths/include/purefs/filesystem_paths.hpp | 1 + products/PurePhone/services/db/ServiceDB.cpp | 22 ++ .../services/db/include/db/ServiceDB.hpp | 1 + .../deviceInfo/DeviceInfoEndpoint.cpp | 1 + source/MessageType.hpp | 2 + 19 files changed, 478 insertions(+), 102 deletions(-) diff --git a/module-services/service-db/DBServiceAPI.cpp b/module-services/service-db/DBServiceAPI.cpp index 064da0b2052a3f2ad657ceca62e14ab2e4288ec0..8d2e5a3078ae6acf8672dc20d86a2132ebd6512c 100644 --- a/module-services/service-db/DBServiceAPI.cpp +++ b/module-services/service-db/DBServiceAPI.cpp @@ -295,6 +295,20 @@ auto DBServiceAPI::DBBackup(sys::Service *serv, std::string backupPath) -> bool return false; } +auto DBServiceAPI::DBPrepareSyncPackage(sys::Service *serv, const std::string &syncPackagePath) -> bool +{ + LOG_INFO("DBPrepareSyncPackage %s", syncPackagePath.c_str()); + + auto msg = std::make_shared(MessageType::DBSyncPackage, syncPackagePath); + + auto ret = serv->bus.sendUnicastSync(std::move(msg), service::name::db, DefaultTimeoutInMs); + if (auto retMsg = dynamic_cast(ret.second.get()); retMsg) { + return retMsg->retCode; + } + LOG_ERROR("DBPrepareSyncPackage error, return code: %s", c_str(ret.first)); + return false; +} + bool DBServiceAPI::AddSMS(sys::Service *serv, const SMSRecord &record, std::unique_ptr &&listener) { auto query = std::make_unique(record); diff --git a/module-services/service-db/include/service-db/DBServiceAPI.hpp b/module-services/service-db/include/service-db/DBServiceAPI.hpp index 546510571f76a2b717d07a7ccb4a3f0ff3528318..c5f61a8ad1cb961a81e1960a352c17aac2b97301 100644 --- a/module-services/service-db/include/service-db/DBServiceAPI.hpp +++ b/module-services/service-db/include/service-db/DBServiceAPI.hpp @@ -111,6 +111,7 @@ class DBServiceAPI [[deprecated]] static auto CalllogUpdate(sys::Service *serv, const CalllogRecord &rec) -> bool; static auto DBBackup(sys::Service *serv, std::string backupPath) -> bool; + static auto DBPrepareSyncPackage(sys::Service *serv, const std::string &syncPackagePath) -> bool; static auto IsContactInFavourites(sys::Service *serv, const utils::PhoneNumber::View &numberView) -> bool; static auto IsContactInEmergency(sys::Service *serv, const utils::PhoneNumber::View &numberView) -> bool; diff --git a/module-services/service-db/include/service-db/DBServiceMessage.hpp b/module-services/service-db/include/service-db/DBServiceMessage.hpp index 928d4a04dd52baef1e415e0b8640e97db58f325f..9b3adff6deb8217713e936acf09b656d3291c2d8 100644 --- a/module-services/service-db/include/service-db/DBServiceMessage.hpp +++ b/module-services/service-db/include/service-db/DBServiceMessage.hpp @@ -1,4 +1,4 @@ -// Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved. +// Copyright (c) 2017-2022, Mudita Sp. z.o.o. All rights reserved. // For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md #pragma once @@ -17,6 +17,13 @@ class DBServiceMessageBackup : public DBMessage std::string backupPath; }; +class DBServiceMessageSyncPackage : public DBMessage +{ + public: + DBServiceMessageSyncPackage(MessageType messageType, const std::string &syncPackagePath); + std::string syncPackagePath; +}; + class DBServiceResponseMessage : public DBResponseMessage { public: diff --git a/module-services/service-db/messages/DBServiceMessage.cpp b/module-services/service-db/messages/DBServiceMessage.cpp index b2783bb7df78fd43feebfa5fd04c6d96342a5446..b3f1e7463695e047a16e5a55f34c5ac3c8097d73 100644 --- a/module-services/service-db/messages/DBServiceMessage.cpp +++ b/module-services/service-db/messages/DBServiceMessage.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved. +// Copyright (c) 2017-2022, Mudita Sp. z.o.o. All rights reserved. // For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md #include @@ -7,5 +7,9 @@ DBServiceMessageBackup::DBServiceMessageBackup(MessageType messageType, std::str : DBMessage(messageType), backupPath(backupPath) {} +DBServiceMessageSyncPackage::DBServiceMessageSyncPackage(MessageType messageType, const std::string &syncPackagePath) + : DBMessage(messageType), syncPackagePath(syncPackagePath) +{} + DBServiceResponseMessage::DBServiceResponseMessage(uint32_t retCode, uint32_t count, MessageType respTo) : DBResponseMessage(retCode, count, respTo){}; diff --git a/module-services/service-desktop/BackupRestore.cpp b/module-services/service-desktop/BackupRestore.cpp index bd71ab58159f4f982647ec4ae9a999331646b505..956aa4114e8e699b0fd28d9730569e9dc83313a9 100644 --- a/module-services/service-desktop/BackupRestore.cpp +++ b/module-services/service-desktop/BackupRestore.cpp @@ -40,43 +40,75 @@ static bool isValidDirentry(const std::filesystem::directory_entry &direntry) return direntry.path() != "." && direntry.path() != ".." && direntry.path() != "..."; } -BackupRestore::CompletionCode BackupRestore::BackupUserFiles(sys::Service *ownerService, std::filesystem::path &path) +BackupSyncRestore::CompletionCode BackupSyncRestore::BackupUserFiles(sys::Service *ownerService, + std::filesystem::path &path) { assert(ownerService != nullptr); LOG_INFO("Backup started..."); - if (BackupRestore::RemoveBackupDir(path) == false) { + if (BackupSyncRestore::RemoveBackupDir(path) == false) { return CompletionCode::FSError; } - if (BackupRestore::CreateBackupDir(path) == false) { + if (BackupSyncRestore::CreateBackupDir(path) == false) { return CompletionCode::FSError; } LOG_DEBUG("Database backup started..."); if (DBServiceAPI::DBBackup(ownerService, path) == false) { LOG_ERROR("Database backup failed, quitting..."); - BackupRestore::RemoveBackupDir(path); + BackupSyncRestore::RemoveBackupDir(path); return CompletionCode::DBError; } if (WriteBackupInfo(ownerService, path) == false) { LOG_ERROR("Failed to save backup info"); - BackupRestore::RemoveBackupDir(path); + BackupSyncRestore::RemoveBackupDir(path); return CompletionCode::CopyError; } LOG_DEBUG("Packing files"); - if (BackupRestore::PackUserFiles(path) == false) { + if (BackupSyncRestore::PackUserFiles(path) == false) { LOG_ERROR("Failed pack backup"); - BackupRestore::RemoveBackupDir(path); + BackupSyncRestore::RemoveBackupDir(path); return CompletionCode::PackError; } return CompletionCode::Success; } -bool BackupRestore::WriteBackupInfo(sys::Service *ownerService, const std::filesystem::path &path) +BackupSyncRestore::CompletionCode BackupSyncRestore::PrepareSyncPackage(sys::Service *ownerService, + std::filesystem::path &path) +{ + assert(ownerService != nullptr); + LOG_INFO("Sync package preparation started..."); + + if (!BackupSyncRestore::RemoveSyncDir(path)) { + return CompletionCode::FSError; + } + + if (!BackupSyncRestore::CreateSyncDir(path)) { + return CompletionCode::FSError; + } + + LOG_DEBUG("Sync package preparation started..."); + if (!DBServiceAPI::DBPrepareSyncPackage(ownerService, path)) { + LOG_ERROR("Sync package preparation, quitting..."); + BackupSyncRestore::RemoveSyncDir(path); + return CompletionCode::DBError; + } + + LOG_DEBUG("Packing files"); + if (!BackupSyncRestore::PackSyncFiles(path)) { + LOG_ERROR("Failed pack sync files"); + BackupSyncRestore::RemoveSyncDir(path); + return CompletionCode::PackError; + } + + return CompletionCode::Success; +} + +bool BackupSyncRestore::WriteBackupInfo(sys::Service *ownerService, const std::filesystem::path &path) { LOG_INFO("Writing backup info"); @@ -100,19 +132,19 @@ bool BackupRestore::WriteBackupInfo(sys::Service *ownerService, const std::files return true; } -BackupRestore::CompletionCode BackupRestore::RestoreUserFiles(sys::Service *ownerService, - const std::filesystem::path &path) +BackupSyncRestore::CompletionCode BackupSyncRestore::RestoreUserFiles(sys::Service *ownerService, + const std::filesystem::path &path) { assert(ownerService != nullptr); LOG_INFO("Restore started"); - if (BackupRestore::UnpackBackupFile(path) == false) { + if (BackupSyncRestore::UnpackBackupFile(path) == false) { LOG_ERROR("Can't unpack user files"); return CompletionCode::UnpackError; } - if (BackupRestore::CanRestoreFromBackup(TempPathForBackupFile(path)) == false) { + if (BackupSyncRestore::CanRestoreFromBackup(TempPathForBackupFile(path)) == false) { LOG_ERROR("Can't restore user files"); return CompletionCode::FSError; } @@ -124,7 +156,7 @@ BackupRestore::CompletionCode BackupRestore::RestoreUserFiles(sys::Service *owne LOG_INFO("Entered restore state"); - if (BackupRestore::ReplaceUserFiles(path) == false) { + if (BackupSyncRestore::ReplaceUserFiles(path) == false) { LOG_ERROR("Can't restore user files"); return CompletionCode::CopyError; } @@ -132,7 +164,7 @@ BackupRestore::CompletionCode BackupRestore::RestoreUserFiles(sys::Service *owne return CompletionCode::Success; } -bool BackupRestore::RemoveBackupDir(const std::filesystem::path &path) +bool BackupSyncRestore::RemoveBackupDir(const std::filesystem::path &path) { /* prepare directories */ if (std::filesystem::is_directory(path)) { @@ -148,7 +180,23 @@ bool BackupRestore::RemoveBackupDir(const std::filesystem::path &path) return true; } -bool BackupRestore::CreateBackupDir(const std::filesystem::path &path) +bool BackupSyncRestore::RemoveSyncDir(const std::filesystem::path &path) +{ + /* prepare directories */ + if (std::filesystem::is_directory(path)) { + LOG_INFO("Removing sync directory %s...", path.c_str()); + std::error_code errorCode; + + if (std::filesystem::remove_all(path, errorCode) == 0) { + LOG_ERROR("Removing sync directory %s failed, error: %d.", path.c_str(), errorCode.value()); + return false; + } + } + + return true; +} + +bool BackupSyncRestore::CreateBackupDir(const std::filesystem::path &path) { LOG_INFO("Creating backup directory %s...", path.c_str()); std::error_code errorCode; @@ -163,11 +211,26 @@ bool BackupRestore::CreateBackupDir(const std::filesystem::path &path) return true; } -bool BackupRestore::PackUserFiles(const std::filesystem::path &path) +bool BackupSyncRestore::CreateSyncDir(const std::filesystem::path &path) +{ + LOG_INFO("Creating sync directory %s...", path.c_str()); + std::error_code errorCode; + + if (!std::filesystem::exists(path)) { + if (!std::filesystem::create_directories(path, errorCode)) { + LOG_ERROR("Failed to create directory: %s, error: %d", path.c_str(), errorCode.value()); + return false; + } + } + + return true; +} + +bool BackupSyncRestore::PackUserFiles(const std::filesystem::path &path) { if (std::filesystem::is_empty(path)) { LOG_ERROR("Backup dir is empty, nothing to backup, quitting..."); - BackupRestore::RemoveBackupDir(path); + BackupSyncRestore::RemoveBackupDir(path); return false; } @@ -179,7 +242,7 @@ bool BackupRestore::PackUserFiles(const std::filesystem::path &path) int ret = mtar_open(&tarFile, tarFilePath.c_str(), "w"); if (ret != MTAR_ESUCCESS) { LOG_ERROR("Opening tar file failed, quitting..."); - BackupRestore::RemoveBackupDir(path); + BackupSyncRestore::RemoveBackupDir(path); return false; } @@ -200,7 +263,7 @@ bool BackupRestore::PackUserFiles(const std::filesystem::path &path) if (file == nullptr) { LOG_ERROR("Archiving file failed, cannot open file, quitting..."); mtar_close(&tarFile); - BackupRestore::RemoveBackupDir(path); + BackupSyncRestore::RemoveBackupDir(path); return false; } @@ -212,14 +275,14 @@ bool BackupRestore::PackUserFiles(const std::filesystem::path &path) LOG_ERROR("Writing tar header failed"); std::fclose(file); mtar_close(&tarFile); - BackupRestore::RemoveBackupDir(path); + BackupSyncRestore::RemoveBackupDir(path); return false; } uintmax_t filesize = std::filesystem::file_size(direntry.path(), errorCode); if (errorCode) { LOG_ERROR("Failed to get size for file %s, error: %d", direntry.path().c_str(), errorCode.value()); - BackupRestore::RemoveBackupDir(path); + BackupSyncRestore::RemoveBackupDir(path); return false; } uint32_t loopcount = (filesize / purefs::buffer::tar_buf) + 1u; @@ -239,7 +302,7 @@ bool BackupRestore::PackUserFiles(const std::filesystem::path &path) LOG_ERROR("Reading file failed, quitting..."); std::fclose(file); mtar_close(&tarFile); - BackupRestore::RemoveBackupDir(path); + BackupSyncRestore::RemoveBackupDir(path); return false; } @@ -248,7 +311,133 @@ bool BackupRestore::PackUserFiles(const std::filesystem::path &path) LOG_ERROR("Writting into backup failed, quitting..."); std::fclose(file); mtar_close(&tarFile); - BackupRestore::RemoveBackupDir(path); + BackupSyncRestore::RemoveBackupDir(path); + return false; + } + } + + LOG_INFO("Closing file..."); + if (std::fclose(file) != 0) { + LOG_ERROR("Closing file failed, quitting..."); + mtar_close(&tarFile); + BackupSyncRestore::RemoveBackupDir(path); + return false; + } + + LOG_INFO("Deleting file ..."); + + if (!std::filesystem::remove(direntry.path(), errorCode)) { + LOG_ERROR("Deleting file failed, error: %d, quitting...", errorCode.value()); + mtar_close(&tarFile); + BackupSyncRestore::RemoveBackupDir(path); + return false; + } + } + + LOG_INFO("Finalizing tar file..."); + if (mtar_finalize(&tarFile) != MTAR_ESUCCESS) { + LOG_ERROR("Finalizing tar file failed, quitting...."); + mtar_close(&tarFile); + BackupSyncRestore::RemoveBackupDir(path); + return false; + } + + LOG_INFO("Closing tar file..."); + if (mtar_close(&tarFile) != MTAR_ESUCCESS) { + LOG_ERROR("Closing tar file failed, quitting..."); + BackupSyncRestore::RemoveBackupDir(path); + return false; + } + + return true; +} + +bool BackupSyncRestore::PackSyncFiles(const std::filesystem::path &path) +{ + if (std::filesystem::is_empty(path)) { + LOG_ERROR("Sync dir is empty, quitting..."); + BackupSyncRestore::RemoveSyncDir(path); + return false; + } + + std::filesystem::path tarFilePath = (purefs::dir::getSyncPackagePath() / path.filename()); + mtar_t tarFile; + + LOG_INFO("Opening tar %s file...", tarFilePath.c_str()); + + int ret = mtar_open(&tarFile, tarFilePath.c_str(), "w"); + if (ret != MTAR_ESUCCESS) { + LOG_ERROR("Opening tar file failed, quitting..."); + BackupSyncRestore::RemoveSyncDir(path); + return false; + } + + auto buffer = std::make_unique(purefs::buffer::tar_buf); + constexpr size_t streamBufferSize = 64 * 1024; + auto streamBuffer = std::make_unique(streamBufferSize); + setvbuf(tarFile.stream, streamBuffer.get(), _IOFBF, streamBufferSize); + std::error_code errorCode; + + for (auto &direntry : std::filesystem::directory_iterator(path)) { + if (!isValidDirentry(direntry)) { + continue; + } + + LOG_INFO("Archiving file ..."); + auto *file = std::fopen(direntry.path().string().c_str(), "r"); + + if (file == nullptr) { + LOG_ERROR("Archiving file failed, cannot open file, quitting..."); + mtar_close(&tarFile); + BackupSyncRestore::RemoveSyncDir(path); + return false; + } + + LOG_DEBUG("Writting tar header ..."); + + if (mtar_write_file_header(&tarFile, + direntry.path().filename().c_str(), + static_cast(std::filesystem::file_size(direntry))) != MTAR_ESUCCESS) { + LOG_ERROR("Writing tar header failed"); + std::fclose(file); + mtar_close(&tarFile); + BackupSyncRestore::RemoveSyncDir(path); + return false; + } + + uintmax_t filesize = std::filesystem::file_size(direntry.path(), errorCode); + if (errorCode) { + LOG_ERROR("Failed to get size for file %s, error: %d", direntry.path().c_str(), errorCode.value()); + BackupSyncRestore::RemoveSyncDir(path); + return false; + } + uint32_t loopcount = (filesize / purefs::buffer::tar_buf) + 1u; + uint32_t readsize; + + for (uint32_t i = 0u; i < loopcount; i++) { + if (i + 1u == loopcount) { + readsize = filesize % purefs::buffer::tar_buf; + } + else { + readsize = purefs::buffer::tar_buf; + } + + LOG_DEBUG("Reading file ..."); + + if (std::fread(buffer.get(), 1, readsize, file) != readsize) { + LOG_ERROR("Reading file failed, quitting..."); + std::fclose(file); + mtar_close(&tarFile); + BackupSyncRestore::RemoveSyncDir(path); + return false; + } + + LOG_DEBUG("Writting into sync package..."); + if (mtar_write_data(&tarFile, buffer.get(), readsize) != MTAR_ESUCCESS) { + LOG_ERROR("Writting into sync package failed, quitting..."); + std::fclose(file); + mtar_close(&tarFile); + BackupSyncRestore::RemoveSyncDir(path); return false; } } @@ -257,7 +446,7 @@ bool BackupRestore::PackUserFiles(const std::filesystem::path &path) if (std::fclose(file) != 0) { LOG_ERROR("Closing file failed, quitting..."); mtar_close(&tarFile); - BackupRestore::RemoveBackupDir(path); + BackupSyncRestore::RemoveSyncDir(path); return false; } @@ -266,7 +455,7 @@ bool BackupRestore::PackUserFiles(const std::filesystem::path &path) if (!std::filesystem::remove(direntry.path(), errorCode)) { LOG_ERROR("Deleting file failed, error: %d, quitting...", errorCode.value()); mtar_close(&tarFile); - BackupRestore::RemoveBackupDir(path); + BackupSyncRestore::RemoveSyncDir(path); return false; } } @@ -275,21 +464,21 @@ bool BackupRestore::PackUserFiles(const std::filesystem::path &path) if (mtar_finalize(&tarFile) != MTAR_ESUCCESS) { LOG_ERROR("Finalizing tar file failed, quitting...."); mtar_close(&tarFile); - BackupRestore::RemoveBackupDir(path); + BackupSyncRestore::RemoveSyncDir(path); return false; } LOG_INFO("Closing tar file..."); if (mtar_close(&tarFile) != MTAR_ESUCCESS) { LOG_ERROR("Closing tar file failed, quitting..."); - BackupRestore::RemoveBackupDir(path); + BackupSyncRestore::RemoveSyncDir(path); return false; } return true; } -auto BackupRestore::TempPathForBackupFile(const std::filesystem::path &tarFilePath) -> std::filesystem::path const +auto BackupSyncRestore::TempPathForBackupFile(const std::filesystem::path &tarFilePath) -> std::filesystem::path const { std::filesystem::path extractFolder; @@ -303,7 +492,7 @@ auto BackupRestore::TempPathForBackupFile(const std::filesystem::path &tarFilePa return purefs::dir::getTemporaryPath() / extractFolder; } -bool BackupRestore::UnpackBackupFile(const std::filesystem::path &tarFilePath) +bool BackupSyncRestore::UnpackBackupFile(const std::filesystem::path &tarFilePath) { mtar_t tarFile; mtar_header_t tarHeader; @@ -402,7 +591,7 @@ bool BackupRestore::UnpackBackupFile(const std::filesystem::path &tarFilePath) return ret == MTAR_ENULLRECORD ? true : false; } -std::string BackupRestore::ReadFileAsString(const std::filesystem::path &fileToRead) +std::string BackupSyncRestore::ReadFileAsString(const std::filesystem::path &fileToRead) { const auto file = std::ifstream(fileToRead); @@ -419,7 +608,7 @@ std::string BackupRestore::ReadFileAsString(const std::filesystem::path &fileToR using namespace sdesktop::endpoints; -std::string BackupRestore::ReadVersionFromJsonFile(const std::filesystem::path &jsonFilePath) +std::string BackupSyncRestore::ReadVersionFromJsonFile(const std::filesystem::path &jsonFilePath) { const auto jsonFile = ReadFileAsString(jsonFilePath); @@ -445,7 +634,7 @@ std::string BackupRestore::ReadVersionFromJsonFile(const std::filesystem::path & return (bootVersionObject[json::version]).string_value(); } -bool BackupRestore::CheckBackupVersion(const std::filesystem::path &extractedBackup) +bool BackupSyncRestore::CheckBackupVersion(const std::filesystem::path &extractedBackup) { auto versionOK = true; const auto backupVersion = ReadVersionFromJsonFile(extractedBackup / bkp::backupInfo); @@ -486,12 +675,12 @@ bool BackupRestore::CheckBackupVersion(const std::filesystem::path &extractedBac return versionOK; } -bool BackupRestore::CanRestoreFromBackup(const std::filesystem::path &extractedBackup) +bool BackupSyncRestore::CanRestoreFromBackup(const std::filesystem::path &extractedBackup) { return CheckBackupVersion(extractedBackup); } -bool BackupRestore::ReplaceUserFiles(const std::filesystem::path &path) +bool BackupSyncRestore::ReplaceUserFiles(const std::filesystem::path &path) { /* replace existing files that have respective backup files existing */ const auto tempDir = purefs::dir::getTemporaryPath() / path.stem(); @@ -539,7 +728,7 @@ bool BackupRestore::ReplaceUserFiles(const std::filesystem::path &path) return true; } -json11::Json BackupRestore::GetBackupFiles() +json11::Json BackupSyncRestore::GetBackupFiles() { auto dirEntryVector = std::vector(); std::error_code errorCode; diff --git a/module-services/service-desktop/ServiceDesktop.cpp b/module-services/service-desktop/ServiceDesktop.cpp index 00e69188dd591c63575362ae0c1da7a635a03db3..d8ff765fe6b55173358a446a026517f663723ed1 100644 --- a/module-services/service-desktop/ServiceDesktop.cpp +++ b/module-services/service-desktop/ServiceDesktop.cpp @@ -46,6 +46,7 @@ sys::ReturnCodes ServiceDesktop::InitHandler() connectHandler(); connectHandler(); connectHandler(); + connectHandler(); connectHandler(); connectHandler(); connectHandler(); @@ -101,20 +102,39 @@ std::string ServiceDesktop::prepareBackupFilename() return std::string(backupFileName.data()); } +std::string ServiceDesktop::prepareSyncFilename() +{ + const std::size_t maxFileNameSize = 64; + std::array syncFileName{}; + std::time_t now; + std::time(&now); + std::strftime(syncFileName.data(), syncFileName.size(), "%FT%OH%OM%OSZ", std::localtime(&now)); + + return std::string(syncFileName.data()); +} + void ServiceDesktop::prepareBackupData() { - backupRestoreStatus.operation = BackupRestore::Operation::Backup; - backupRestoreStatus.taskId = prepareBackupFilename(); - backupRestoreStatus.state = BackupRestore::OperationState::Stopped; - backupRestoreStatus.backupTempDir = purefs::dir::getTemporaryPath() / backupRestoreStatus.taskId; + backupSyncRestoreStatus.operation = BackupSyncRestore::Operation::Backup; + backupSyncRestoreStatus.taskId = prepareBackupFilename(); + backupSyncRestoreStatus.state = BackupSyncRestore::OperationState::Stopped; + backupSyncRestoreStatus.backupTempDir = purefs::dir::getTemporaryPath() / backupSyncRestoreStatus.taskId; +} + +void ServiceDesktop::prepareSyncData() +{ + backupSyncRestoreStatus.operation = BackupSyncRestore::Operation::Sync; + backupSyncRestoreStatus.taskId = prepareSyncFilename(); + backupSyncRestoreStatus.state = BackupSyncRestore::OperationState::Stopped; + backupSyncRestoreStatus.backupTempDir = purefs::dir::getTemporaryPath() / backupSyncRestoreStatus.taskId; } void ServiceDesktop::prepareRestoreData(const std::filesystem::path &restoreLocation) { - backupRestoreStatus.operation = BackupRestore::Operation::Restore; - backupRestoreStatus.taskId = restoreLocation.filename(); - backupRestoreStatus.state = BackupRestore::OperationState::Stopped; - backupRestoreStatus.location = purefs::dir::getBackupOSPath() / backupRestoreStatus.taskId; + backupSyncRestoreStatus.operation = BackupSyncRestore::Operation::Restore; + backupSyncRestoreStatus.taskId = restoreLocation.filename(); + backupSyncRestoreStatus.state = BackupSyncRestore::OperationState::Stopped; + backupSyncRestoreStatus.location = purefs::dir::getBackupOSPath() / backupSyncRestoreStatus.taskId; } auto ServiceDesktop::requestLogsFlush() -> void @@ -315,17 +335,37 @@ auto ServiceDesktop::handle(sdesktop::developerMode::DeveloperModeRequest *msg) auto ServiceDesktop::handle(sdesktop::BackupMessage * /*msg*/) -> std::shared_ptr { - backupRestoreStatus.state = BackupRestore::OperationState::Running; - backupRestoreStatus.completionCode = BackupRestore::BackupUserFiles(this, backupRestoreStatus.backupTempDir); - backupRestoreStatus.location = backupRestoreStatus.taskId; + backupSyncRestoreStatus.state = BackupSyncRestore::OperationState::Running; + backupSyncRestoreStatus.completionCode = + BackupSyncRestore::BackupUserFiles(this, backupSyncRestoreStatus.backupTempDir); + backupSyncRestoreStatus.location = backupSyncRestoreStatus.taskId; - if (backupRestoreStatus.completionCode == BackupRestore::CompletionCode::Success) { + if (backupSyncRestoreStatus.completionCode == BackupSyncRestore::CompletionCode::Success) { LOG_INFO("Backup finished"); - backupRestoreStatus.state = BackupRestore::OperationState::Finished; + backupSyncRestoreStatus.state = BackupSyncRestore::OperationState::Finished; } else { LOG_ERROR("Backup failed"); - backupRestoreStatus.state = BackupRestore::OperationState::Error; + backupSyncRestoreStatus.state = BackupSyncRestore::OperationState::Error; + } + + return sys::MessageNone{}; +} + +auto ServiceDesktop::handle(sdesktop::SyncMessage * /*msg*/) -> std::shared_ptr +{ + backupSyncRestoreStatus.state = BackupSyncRestore::OperationState::Running; + backupSyncRestoreStatus.completionCode = + BackupSyncRestore::PrepareSyncPackage(this, backupSyncRestoreStatus.backupTempDir); + backupSyncRestoreStatus.location = backupSyncRestoreStatus.taskId; + + if (backupSyncRestoreStatus.completionCode == BackupSyncRestore::CompletionCode::Success) { + LOG_INFO("Sync package preparation finished"); + backupSyncRestoreStatus.state = BackupSyncRestore::OperationState::Finished; + } + else { + LOG_ERROR("Sync package preparation failed"); + backupSyncRestoreStatus.state = BackupSyncRestore::OperationState::Error; } return sys::MessageNone{}; @@ -333,17 +373,18 @@ auto ServiceDesktop::handle(sdesktop::BackupMessage * /*msg*/) -> std::shared_pt auto ServiceDesktop::handle(sdesktop::RestoreMessage * /*msg*/) -> std::shared_ptr { - backupRestoreStatus.state = BackupRestore::OperationState::Running; - backupRestoreStatus.completionCode = BackupRestore::RestoreUserFiles(this, backupRestoreStatus.location); + backupSyncRestoreStatus.state = BackupSyncRestore::OperationState::Running; + backupSyncRestoreStatus.completionCode = + BackupSyncRestore::RestoreUserFiles(this, backupSyncRestoreStatus.location); - if (backupRestoreStatus.completionCode == BackupRestore::CompletionCode::Success) { + if (backupSyncRestoreStatus.completionCode == BackupSyncRestore::CompletionCode::Success) { LOG_DEBUG("Restore finished"); - backupRestoreStatus.state = BackupRestore::OperationState::Finished; + backupSyncRestoreStatus.state = BackupSyncRestore::OperationState::Finished; sys::SystemManagerCommon::Reboot(this); } else { LOG_ERROR("Restore failed"); - backupRestoreStatus.state = BackupRestore::OperationState::Error; + backupSyncRestoreStatus.state = BackupSyncRestore::OperationState::Error; } return sys::MessageNone{}; diff --git a/module-services/service-desktop/endpoints/backup/BackupHelper.cpp b/module-services/service-desktop/endpoints/backup/BackupHelper.cpp index 3a5ccda12755805618e6af7a878e15c6e941cc02..8e7f1396ea31fe2d515873e9a6affe859ae70cea 100644 --- a/module-services/service-desktop/endpoints/backup/BackupHelper.cpp +++ b/module-services/service-desktop/endpoints/backup/BackupHelper.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved. +// Copyright (c) 2017-2022, Mudita Sp. z.o.o. All rights reserved. // For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md #include @@ -19,11 +19,17 @@ namespace sdesktop::endpoints auto BackupHelper::processGet(Context &context) -> ProcessResult { + if (context.getBody()[json::messages::category].string_value() == json::messages::categorySync) { + return checkSyncState(context); + } return checkState(context); } auto BackupHelper::processPost(Context &context) -> ProcessResult { + if (context.getBody()[json::messages::category].string_value() == json::messages::categorySync) { + return executeSyncRequest(context); + } return executeRequest(context); } @@ -31,7 +37,7 @@ namespace sdesktop::endpoints { auto ownerServicePtr = static_cast(owner); - if (ownerServicePtr->getBackupRestoreStatus().state == BackupRestore::OperationState::Running) { + if (ownerServicePtr->getBackupSyncRestoreStatus().state == BackupSyncRestore::OperationState::Running) { LOG_DEBUG("Backup already running"); // a backup is already running, don't start a second task context.setResponseStatus(http::Code::NotAcceptable); @@ -46,7 +52,7 @@ namespace sdesktop::endpoints service::name::service_desktop); // return new generated backup info - context.setResponseBody(ownerServicePtr->getBackupRestoreStatus()); + context.setResponseBody(ownerServicePtr->getBackupSyncRestoreStatus()); } putToSendQueue(context.createSimpleResponse()); @@ -59,15 +65,75 @@ namespace sdesktop::endpoints auto ownerServicePtr = static_cast(owner); if (context.getBody()[json::taskId].is_string()) { - if (ownerServicePtr->getBackupRestoreStatus().taskId == context.getBody()[json::taskId].string_value()) { - if (ownerServicePtr->getBackupRestoreStatus().state == BackupRestore::OperationState::Finished) { + if (ownerServicePtr->getBackupSyncRestoreStatus().taskId == + context.getBody()[json::taskId].string_value()) { + if (ownerServicePtr->getBackupSyncRestoreStatus().state == + BackupSyncRestore::OperationState::Finished) { + context.setResponseStatus(http::Code::SeeOther); + } + else { + context.setResponseStatus(http::Code::OK); + } + + context.setResponseBody(ownerServicePtr->getBackupSyncRestoreStatus()); + } + else { + context.setResponseStatus(http::Code::NotFound); + } + } + else { + LOG_DEBUG("Backup task not found"); + context.setResponseStatus(http::Code::BadRequest); + } + + LOG_DEBUG("Responding"); + putToSendQueue(context.createSimpleResponse()); + + return {sent::yes, std::nullopt}; + } + + auto BackupHelper::executeSyncRequest(Context &context) -> ProcessResult + { + auto ownerServicePtr = static_cast(owner); + + if (ownerServicePtr->getBackupSyncRestoreStatus().state == BackupSyncRestore::OperationState::Running) { + LOG_DEBUG("Sync already running"); + // a sync package preparation is already running, don't start a second task + context.setResponseStatus(http::Code::NotAcceptable); + } + else { + LOG_DEBUG("Starting a sync package preparation"); + // initialize new sync information + ownerServicePtr->prepareSyncData(); + + // start the sync package preparation process in the background + ownerServicePtr->bus.sendUnicast(std::make_shared(), service::name::service_desktop); + + // return new generated sync package info + context.setResponseBody(ownerServicePtr->getBackupSyncRestoreStatus()); + } + + putToSendQueue(context.createSimpleResponse()); + + return {sent::yes, std::nullopt}; + } + + auto BackupHelper::checkSyncState(Context &context) -> ProcessResult + { + auto ownerServicePtr = static_cast(owner); + + if (context.getBody()[json::taskId].is_string()) { + if (ownerServicePtr->getBackupSyncRestoreStatus().taskId == + context.getBody()[json::taskId].string_value()) { + if (ownerServicePtr->getBackupSyncRestoreStatus().state == + BackupSyncRestore::OperationState::Finished) { context.setResponseStatus(http::Code::SeeOther); } else { context.setResponseStatus(http::Code::OK); } - context.setResponseBody(ownerServicePtr->getBackupRestoreStatus()); + context.setResponseBody(ownerServicePtr->getBackupSyncRestoreStatus()); } else { context.setResponseStatus(http::Code::NotFound); diff --git a/module-services/service-desktop/endpoints/include/endpoints/JsonKeyNames.hpp b/module-services/service-desktop/endpoints/include/endpoints/JsonKeyNames.hpp index ee8efb01d28122fb1fb98b4d594c7e018f0da5cc..9e502a95adc7bc239c2c30bebb786a0dae47c967 100644 --- a/module-services/service-desktop/endpoints/include/endpoints/JsonKeyNames.hpp +++ b/module-services/service-desktop/endpoints/include/endpoints/JsonKeyNames.hpp @@ -25,34 +25,35 @@ namespace sdesktop::endpoints::json inline constexpr auto networkOperatorName = "networkOperatorName"; inline constexpr auto accessTechnology = "accessTechnology"; - inline constexpr auto update = "update"; - inline constexpr auto updateInfo = "updateInfo"; - inline constexpr auto updateError = "updateError"; - inline constexpr auto errorCode = "errorCode"; - inline constexpr auto statusCode = "statusCode"; - inline constexpr auto updateHistory = "updateHistory"; - inline constexpr auto usbMscMode = "usbMscMode"; - inline constexpr auto versionString = "string"; - inline constexpr auto fileExists = "fileExists"; - inline constexpr auto boot = "boot"; - inline constexpr auto version = "version"; - inline constexpr auto taskId = "id"; - inline constexpr auto state = "state"; - inline constexpr auto success = "success"; - inline constexpr auto reboot = "reboot"; - inline constexpr auto rebootMode = "rebootMode"; - inline constexpr auto request = "request"; - inline constexpr auto restore = "restore"; - inline constexpr auto finished = "finished"; - inline constexpr auto pending = "pending"; - inline constexpr auto location = "location"; - inline constexpr auto reason = "reason"; - inline constexpr auto serialNumber = "serialNumber"; - inline constexpr auto caseColour = "caseColour"; - inline constexpr auto fileList = "fileList"; - inline constexpr auto files = "files"; - inline constexpr auto backupLocation = "backupLocation"; - inline constexpr auto deviceToken = "deviceToken"; + inline constexpr auto update = "update"; + inline constexpr auto updateInfo = "updateInfo"; + inline constexpr auto updateError = "updateError"; + inline constexpr auto errorCode = "errorCode"; + inline constexpr auto statusCode = "statusCode"; + inline constexpr auto updateHistory = "updateHistory"; + inline constexpr auto usbMscMode = "usbMscMode"; + inline constexpr auto versionString = "string"; + inline constexpr auto fileExists = "fileExists"; + inline constexpr auto boot = "boot"; + inline constexpr auto version = "version"; + inline constexpr auto taskId = "id"; + inline constexpr auto state = "state"; + inline constexpr auto success = "success"; + inline constexpr auto reboot = "reboot"; + inline constexpr auto rebootMode = "rebootMode"; + inline constexpr auto request = "request"; + inline constexpr auto restore = "restore"; + inline constexpr auto finished = "finished"; + inline constexpr auto pending = "pending"; + inline constexpr auto location = "location"; + inline constexpr auto reason = "reason"; + inline constexpr auto serialNumber = "serialNumber"; + inline constexpr auto caseColour = "caseColour"; + inline constexpr auto fileList = "fileList"; + inline constexpr auto files = "files"; + inline constexpr auto backupLocation = "backupLocation"; + inline constexpr auto syncPackageLocation = "syncPackageLocation"; + inline constexpr auto deviceToken = "deviceToken"; namespace updateprocess { @@ -71,6 +72,8 @@ namespace sdesktop::endpoints::json inline constexpr auto categoryMessage = "message"; inline constexpr auto categoryThread = "thread"; inline constexpr auto categoryTemplate = "template"; + inline constexpr auto categoryBackup = "backup"; + inline constexpr auto categorySync = "sync"; inline constexpr auto limit = "limit"; inline constexpr auto offset = "offset"; diff --git a/module-services/service-desktop/endpoints/include/endpoints/backup/BackupHelper.hpp b/module-services/service-desktop/endpoints/include/endpoints/backup/BackupHelper.hpp index a711d9ebf1c0092b12e21167bdb6c1db006d94b8..39705c0a5e568f26e46aaea1433d5c8558f4ad15 100644 --- a/module-services/service-desktop/endpoints/include/endpoints/backup/BackupHelper.hpp +++ b/module-services/service-desktop/endpoints/include/endpoints/backup/BackupHelper.hpp @@ -1,4 +1,4 @@ -// Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved. +// Copyright (c) 2017-2022, Mudita Sp. z.o.o. All rights reserved. // For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md #pragma once @@ -19,5 +19,7 @@ namespace sdesktop::endpoints private: auto executeRequest(Context &context) -> ProcessResult; auto checkState(Context &context) -> ProcessResult; + auto executeSyncRequest(Context &context) -> ProcessResult; + auto checkSyncState(Context &context) -> ProcessResult; }; } // namespace sdesktop::endpoints diff --git a/module-services/service-desktop/endpoints/restore/RestoreHelper.cpp b/module-services/service-desktop/endpoints/restore/RestoreHelper.cpp index d61aca313f0a757f5ff7ded8eb0aac1893df6e36..64b9797d19d45a5dceca025612b3da48e5450328 100644 --- a/module-services/service-desktop/endpoints/restore/RestoreHelper.cpp +++ b/module-services/service-desktop/endpoints/restore/RestoreHelper.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved. +// Copyright (c) 2017-2022, Mudita Sp. z.o.o. All rights reserved. // For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md #include @@ -31,9 +31,9 @@ namespace sdesktop::endpoints auto ownerService = static_cast(owner); if (context.getBody()[json::taskId].is_string()) { - if (ownerService->getBackupRestoreStatus().taskId == context.getBody()[json::taskId].string_value()) { + if (ownerService->getBackupSyncRestoreStatus().taskId == context.getBody()[json::taskId].string_value()) { context.setResponseStatus(http::Code::OK); - context.setResponseBody(ownerService->getBackupRestoreStatus()); + context.setResponseBody(ownerService->getBackupSyncRestoreStatus()); } else { return {sent::no, ResponseContext{.status = http::Code::NotFound}}; @@ -46,7 +46,7 @@ namespace sdesktop::endpoints return {sent::no, ResponseContext{.status = http::Code::BadRequest}}; } - auto filesList = json11::Json::object{{json::files, BackupRestore::GetBackupFiles()}}; + auto filesList = json11::Json::object{{json::files, BackupSyncRestore::GetBackupFiles()}}; context.setResponseBody(filesList); } @@ -61,7 +61,7 @@ namespace sdesktop::endpoints auto ownerService = static_cast(owner); if (context.getBody()[json::restore].is_string()) { - if (ownerService->getBackupRestoreStatus().state == BackupRestore::OperationState::Running) { + if (ownerService->getBackupSyncRestoreStatus().state == BackupSyncRestore::OperationState::Running) { LOG_WARN("Restore is running, try again later"); return {sent::no, ResponseContext{.status = http::Code::NotAcceptable}}; @@ -88,7 +88,7 @@ namespace sdesktop::endpoints service::name::service_desktop); // return new generated restore info - context.setResponseBody(ownerService->getBackupRestoreStatus()); + context.setResponseBody(ownerService->getBackupSyncRestoreStatus()); } } else { diff --git a/module-services/service-desktop/include/service-desktop/BackupRestore.hpp b/module-services/service-desktop/include/service-desktop/BackupRestore.hpp index cc7a11dc8ef312aa840c82b1e8cccfa5c960f67c..6797f703aa0513e58064814cb28e2313b358b70e 100644 --- a/module-services/service-desktop/include/service-desktop/BackupRestore.hpp +++ b/module-services/service-desktop/include/service-desktop/BackupRestore.hpp @@ -13,12 +13,13 @@ namespace sys class Service; } // namespace sys -class BackupRestore +class BackupSyncRestore { public: enum class Operation { Backup, + Sync, Restore }; @@ -102,13 +103,17 @@ class BackupRestore }; static CompletionCode BackupUserFiles(sys::Service *ownerService, std::filesystem::path &path); + static CompletionCode PrepareSyncPackage(sys::Service *ownerService, std::filesystem::path &path); static CompletionCode RestoreUserFiles(sys::Service *ownerService, const std::filesystem::path &path); static json11::Json GetBackupFiles(); private: static bool RemoveBackupDir(const std::filesystem::path &path); static bool CreateBackupDir(const std::filesystem::path &path); + static bool RemoveSyncDir(const std::filesystem::path &path); + static bool CreateSyncDir(const std::filesystem::path &path); static bool PackUserFiles(const std::filesystem::path &path); + static bool PackSyncFiles(const std::filesystem::path &path); static bool UnpackBackupFile(const std::filesystem::path &path); static std::string ReadVersionFromJsonFile(const std::filesystem::path &jsonFilePath); static bool CheckBackupVersion(const std::filesystem::path &extractedBackup); diff --git a/module-services/service-desktop/include/service-desktop/DesktopMessages.hpp b/module-services/service-desktop/include/service-desktop/DesktopMessages.hpp index 108deb0a9596851c739888bab2f957c8c2dd0ba8..4bc5624c5bb9d7e915d7c357c67bc97cf865b537 100644 --- a/module-services/service-desktop/include/service-desktop/DesktopMessages.hpp +++ b/module-services/service-desktop/include/service-desktop/DesktopMessages.hpp @@ -1,4 +1,4 @@ -// Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved. +// Copyright (c) 2017-2022, Mudita Sp. z.o.o. All rights reserved. // For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md #pragma once @@ -20,6 +20,14 @@ namespace sdesktop ~BackupMessage() override = default; }; + class SyncMessage : public sys::DataMessage + { + public: + SyncMessage() : sys::DataMessage(MessageType::Sync) + {} + ~SyncMessage() override = default; + }; + class RestoreMessage : public sys::DataMessage { public: diff --git a/module-services/service-desktop/include/service-desktop/ServiceDesktop.hpp b/module-services/service-desktop/include/service-desktop/ServiceDesktop.hpp index 3a561287cc59102153da0810af87625920954797..3ec0ee888af738321b6821325f48c328a814e3b5 100644 --- a/module-services/service-desktop/include/service-desktop/ServiceDesktop.hpp +++ b/module-services/service-desktop/include/service-desktop/ServiceDesktop.hpp @@ -55,7 +55,7 @@ class ServiceDesktop : public sys::Service ~ServiceDesktop() override; std::unique_ptr desktopWorker; - BackupRestore::OperationStatus backupRestoreStatus; + BackupSyncRestore::OperationStatus backupSyncRestoreStatus; sys::ReturnCodes InitHandler() override; sys::ReturnCodes DeinitHandler() override; @@ -63,11 +63,13 @@ class ServiceDesktop : public sys::Service sys::MessagePointer DataReceivedHandler(sys::DataMessage *msg, sys::ResponseMessage *resp) override; std::string prepareBackupFilename(); + std::string prepareSyncFilename(); void prepareBackupData(); + void prepareSyncData(); void prepareRestoreData(const std::filesystem::path &restoreLocation); - const BackupRestore::OperationStatus getBackupRestoreStatus() + const BackupSyncRestore::OperationStatus getBackupSyncRestoreStatus() { - return backupRestoreStatus; + return backupSyncRestoreStatus; } const sdesktop::USBSecurityModel *getSecurity() { @@ -120,6 +122,7 @@ class ServiceDesktop : public sys::Service [[nodiscard]] auto handle(message::bluetooth::ResponseVisibleDevices *msg) -> std::shared_ptr; [[nodiscard]] auto handle(sdesktop::developerMode::DeveloperModeRequest *msg) -> std::shared_ptr; [[nodiscard]] auto handle(sdesktop::BackupMessage *msg) -> std::shared_ptr; + [[nodiscard]] auto handle(sdesktop::SyncMessage *msg) -> std::shared_ptr; [[nodiscard]] auto handle(sdesktop::RestoreMessage *msg) -> std::shared_ptr; [[nodiscard]] auto handle(sdesktop::FactoryMessage *msg) -> std::shared_ptr; [[nodiscard]] auto handle(sdesktop::usb::USBConfigured *msg) -> std::shared_ptr; diff --git a/module-vfs/paths/filesystem_paths.cpp b/module-vfs/paths/filesystem_paths.cpp index 4e169b17e3900a57901326ca85bedbcb2869fb0a..148f700a8212149c68f9f1768f37a400421da066 100644 --- a/module-vfs/paths/filesystem_paths.cpp +++ b/module-vfs/paths/filesystem_paths.cpp @@ -14,6 +14,7 @@ namespace constexpr inline auto PATH_UPDATES = "updates"; constexpr inline auto PATH_TMP = "tmp"; constexpr inline auto PATH_BACKUP = "backup"; + constexpr inline auto PATH_SYNC = "sync"; constexpr inline auto PATH_FACTORY = "factory"; constexpr inline auto PATH_LOGS = "logs"; constexpr inline auto PATH_CRASH_DUMPS = "crash_dumps"; @@ -71,6 +72,11 @@ namespace purefs return getUserDiskPath() / PATH_BACKUP; } + std::filesystem::path getSyncPackagePath() noexcept + { + return getUserDiskPath() / PATH_SYNC; + } + std::filesystem::path getFactoryOSPath() noexcept { return std::filesystem::path{eMMC_disk} / PATH_FACTORY; diff --git a/module-vfs/paths/include/purefs/filesystem_paths.hpp b/module-vfs/paths/include/purefs/filesystem_paths.hpp index 237fc85adfe83974eddd19ee4f8cf5aa5002fa42..7d75b8269eb2975766b8cd2368b91786a2dad0a0 100644 --- a/module-vfs/paths/include/purefs/filesystem_paths.hpp +++ b/module-vfs/paths/include/purefs/filesystem_paths.hpp @@ -19,6 +19,7 @@ namespace purefs std::filesystem::path getUpdatesOSPath() noexcept; std::filesystem::path getTemporaryPath() noexcept; std::filesystem::path getBackupOSPath() noexcept; + std::filesystem::path getSyncPackagePath() noexcept; std::filesystem::path getFactoryOSPath() noexcept; std::filesystem::path getLogsPath() noexcept; std::filesystem::path getCrashDumpsPath() noexcept; diff --git a/products/PurePhone/services/db/ServiceDB.cpp b/products/PurePhone/services/db/ServiceDB.cpp index b79eefd21d83729d1b6003ee70a398378d0cd58c..bd2e52323c6401c3a3622501fb0e2c6e32a12cec 100644 --- a/products/PurePhone/services/db/ServiceDB.cpp +++ b/products/PurePhone/services/db/ServiceDB.cpp @@ -228,6 +228,13 @@ sys::MessagePointer ServiceDB::DataReceivedHandler(sys::DataMessage *msgl, sys:: responseMsg = std::make_shared(ret); } break; + case MessageType::DBSyncPackage: { + auto time = utils::time::Scoped("DBSyncPackage"); + auto msg = static_cast(msgl); + auto ret = StoreIntoSyncPackage({msg->syncPackagePath}); + responseMsg = std::make_shared(ret); + } break; + default: break; } @@ -348,3 +355,18 @@ bool ServiceDB::StoreIntoBackup(const std::filesystem::path &backupPath) return true; } + +bool ServiceDB::StoreIntoSyncPackage(const std::filesystem::path &syncPackagePath) +{ + if (!contactsDB->storeIntoFile(syncPackagePath / std::filesystem::path(contactsDB->getName()).filename())) { + LOG_ERROR("Store contactsDB in sync package failed"); + return false; + } + + if (!smsDB->storeIntoFile(syncPackagePath / std::filesystem::path(smsDB->getName()).filename())) { + LOG_ERROR("Store smsDB in sync package failed"); + return false; + } + + return true; +} diff --git a/products/PurePhone/services/db/include/db/ServiceDB.hpp b/products/PurePhone/services/db/include/db/ServiceDB.hpp index ffe500ed9ca1074bd9458403c8be6de206adcea3..12bd49026713eee7d379d2531eb9445b92009912 100644 --- a/products/PurePhone/services/db/include/db/ServiceDB.hpp +++ b/products/PurePhone/services/db/include/db/ServiceDB.hpp @@ -43,6 +43,7 @@ class ServiceDB : public ServiceDBCommon ~ServiceDB() override; bool StoreIntoBackup(const std::filesystem::path &backupPath); + bool StoreIntoSyncPackage(const std::filesystem::path &syncPackagePath); private: std::unique_ptr eventsDB; diff --git a/products/PurePhone/services/desktop/endpoints/deviceInfo/DeviceInfoEndpoint.cpp b/products/PurePhone/services/desktop/endpoints/deviceInfo/DeviceInfoEndpoint.cpp index 90bb298a9398e7a1d9bf3154d9a61771ce1ded3f..02cefd8a4707f8772fadbde27a36543d4748cf19 100644 --- a/products/PurePhone/services/desktop/endpoints/deviceInfo/DeviceInfoEndpoint.cpp +++ b/products/PurePhone/services/desktop/endpoints/deviceInfo/DeviceInfoEndpoint.cpp @@ -59,6 +59,7 @@ namespace sdesktop::endpoints {json::serialNumber, getSerialNumber()}, {json::caseColour, getCaseColour()}, {json::backupLocation, purefs::dir::getBackupOSPath().string()}, + {json::syncPackageLocation, purefs::dir::getSyncPackagePath().string()}, {json::deviceToken, getDeviceToken()}})); return http::Code::OK; diff --git a/source/MessageType.hpp b/source/MessageType.hpp index 7ba18c5fcb017192e19053d1f94245350a4405ea..3f534f74386cd75ca1af9b1bfbf804aec71ae653 100644 --- a/source/MessageType.hpp +++ b/source/MessageType.hpp @@ -17,6 +17,7 @@ enum class MessageType DBServiceNotification, ///< Common service-db notification message. DBServiceBackup, + DBSyncPackage, DBSettingsGet, ///< get current settings from database DBSettingsUpdate, ///< update settings @@ -119,6 +120,7 @@ enum class MessageType // service-desktop messages UpdateOS, Backup, + Sync, Restore, Factory, DeveloperModeRequest,