From dd0b8a0c2fd3a22a82857c06e6027c56735222be Mon Sep 17 00:00:00 2001 From: Ryan Huffman Date: Thu, 15 Feb 2018 14:17:32 -0800 Subject: [PATCH] Add backup download API to DS --- .../src/DomainContentBackupManager.cpp | 78 +++++++++++++------ .../src/DomainContentBackupManager.h | 2 +- domain-server/src/DomainServer.cpp | 22 ++++++ 3 files changed, 76 insertions(+), 26 deletions(-) diff --git a/domain-server/src/DomainContentBackupManager.cpp b/domain-server/src/DomainContentBackupManager.cpp index c68ff0c6ea..f56c41dacd 100644 --- a/domain-server/src/DomainContentBackupManager.cpp +++ b/domain-server/src/DomainContentBackupManager.cpp @@ -383,32 +383,60 @@ void DomainContentBackupManager::backup() { } } -void DomainContentBackupManager::consolidate(QString fileName) { - QDir backupDir { _backupDirectory }; - if (backupDir.exists()) { - auto filePath = backupDir.absoluteFilePath(fileName); - - auto copyFilePath = QDir::tempPath() + "/" + fileName; - - auto copySuccess = QFile::copy(filePath, copyFilePath); - if (!copySuccess) { - qCritical() << "Failed to create full backup."; - return; - } - - QuaZip zip(copyFilePath); - if (!zip.open(QuaZip::mdAdd)) { - qCritical() << "Could not open backup archive:" << filePath; - qCritical() << " ERROR:" << zip.getZipError(); - return; - } - - for (auto& handler : _backupHandlers) { - handler->consolidateBackup(zip); - } - - zip.close(); +void DomainContentBackupManager::consolidateBackup(MiniPromise::Promise promise, QString fileName) { + if (QThread::currentThread() != thread()) { + QMetaObject::invokeMethod(this, "consolidateBackup", Q_ARG(MiniPromise::Promise, promise), + Q_ARG(const QString&, fileName)); + return; } + + QDir backupDir { _backupDirectory }; + if (!backupDir.exists()) { + qCritical() << "Backup directory does not exist, bailing consolidation of backup"; + promise->resolve({ { "success", false } }); + return; + } + + auto filePath = backupDir.absoluteFilePath(fileName); + + auto copyFilePath = QDir::tempPath() + "/" + fileName; + + { + QFile copyFile(copyFilePath); + copyFile.remove(); + copyFile.close(); + } + auto copySuccess = QFile::copy(filePath, copyFilePath); + if (!copySuccess) { + qCritical() << "Failed to create copy of backup."; + promise->resolve({ { "success", false } }); + return; + } + + QuaZip zip(copyFilePath); + if (!zip.open(QuaZip::mdAdd)) { + qCritical() << "Could not open backup archive:" << filePath; + qCritical() << " ERROR:" << zip.getZipError(); + promise->resolve({ { "success", false } }); + return; + } + + for (auto& handler : _backupHandlers) { + handler->consolidateBackup(zip); + } + + zip.close(); + + if (zip.getZipError() != UNZ_OK) { + qCritical() << "Failed to consolidate backup: " << zip.getZipError(); + promise->resolve({ { "success", false } }); + return; + } + + promise->resolve({ + { "success", true }, + { "backupFilePath", copyFilePath } + }); } void DomainContentBackupManager::createManualBackup(MiniPromise::Promise promise, const QString& name) { diff --git a/domain-server/src/DomainContentBackupManager.h b/domain-server/src/DomainContentBackupManager.h index 1e1b2360a8..9ec7eb9950 100644 --- a/domain-server/src/DomainContentBackupManager.h +++ b/domain-server/src/DomainContentBackupManager.h @@ -62,6 +62,7 @@ public slots: void createManualBackup(MiniPromise::Promise promise, const QString& name); void recoverFromBackup(MiniPromise::Promise promise, const QString& backupName); void deleteBackup(MiniPromise::Promise promise, const QString& backupName); + void consolidateBackup(MiniPromise::Promise promise, QString fileName); signals: void loadCompleted(); @@ -73,7 +74,6 @@ protected: void load(); void backup(); - void consolidate(QString fileName); void removeOldBackupVersions(const BackupRule& rule); bool getMostRecentBackup(const QString& format, QString& mostRecentBackupFileName, QDateTime& mostRecentBackupTime); int64_t getMostRecentBackupTimeInSecs(const QString& format); diff --git a/domain-server/src/DomainServer.cpp b/domain-server/src/DomainServer.cpp index 2f8d8f6d03..b91e12a9cf 100644 --- a/domain-server/src/DomainServer.cpp +++ b/domain-server/src/DomainServer.cpp @@ -2149,6 +2149,28 @@ bool DomainServer::handleHTTPRequest(HTTPConnection* connection, const QUrl& url QJsonDocument docJSON(rootJSON); connection->respond(HTTPConnection::StatusCode200, docJSON.toJson(), JSON_MIME_TYPE.toUtf8()); + return true; + } else if (url.path().startsWith(URI_API_BACKUPS_ID)) { + auto id = url.path().mid(QString(URI_API_BACKUPS_ID).length()); + auto deferred = makePromise("consolidateBackup"); + deferred->then([connection, JSON_MIME_TYPE](QString error, QVariantMap result) { + QJsonObject rootJSON; + auto success = result["success"].toBool(); + if (success) { + auto path = result["backupFilePath"].toString(); + auto file { std::unique_ptr(new QFile(path)) }; + if (file->open(QIODevice::ReadOnly)) { + connection->respond(HTTPConnection::StatusCode200, std::move(file)); + } else { + qCritical(domain_server) << "Unable to load consolidated backup at:" << path << result; + connection->respond(HTTPConnection::StatusCode500, "Error opening backup"); + } + } else { + connection->respond(HTTPConnection::StatusCode400); + } + }); + _contentManager->consolidateBackup(deferred, id); + return true; } else if (url.path() == URI_RESTART) { connection->respond(HTTPConnection::StatusCode200);