From 2020ce5907e05338ec8f7e9fbda3a457dd198df0 Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Thu, 15 Feb 2018 11:20:02 -0800 Subject: [PATCH] add API to recover from content archive --- .../src/DomainContentBackupManager.cpp | 54 ++++++++++++++----- .../src/DomainContentBackupManager.h | 3 ++ domain-server/src/DomainServer.cpp | 17 +++++- 3 files changed, 60 insertions(+), 14 deletions(-) diff --git a/domain-server/src/DomainContentBackupManager.cpp b/domain-server/src/DomainContentBackupManager.cpp index 345faffec4..379aa640f8 100644 --- a/domain-server/src/DomainContentBackupManager.cpp +++ b/domain-server/src/DomainContentBackupManager.cpp @@ -18,6 +18,7 @@ #include #include +#include #include #include #include @@ -256,6 +257,22 @@ void DomainContentBackupManager::deleteBackup(MiniPromise::Promise promise, cons }); } +bool DomainContentBackupManager::recoverFromBackupZip(QuaZip& zip, const QString& backupName) { + if (!zip.open(QuaZip::Mode::mdUnzip)) { + qWarning() << "Failed to unzip file: " << zip.getZipName(); + return false; + } else { + _isRecovering = true; + + for (auto& handler : _backupHandlers) { + handler->recoverBackup(zip); + } + + qDebug() << "Successfully started recovering from " << zip.getZipName(); + return true; + } +} + void DomainContentBackupManager::recoverFromBackup(MiniPromise::Promise promise, const QString& backupName) { if (_isRecovering) { promise->resolve({ @@ -277,19 +294,9 @@ void DomainContentBackupManager::recoverFromBackup(MiniPromise::Promise promise, QFile backupFile { backupDir.filePath(backupName) }; if (backupFile.open(QIODevice::ReadOnly)) { QuaZip zip { &backupFile }; - if (!zip.open(QuaZip::Mode::mdUnzip)) { - qWarning() << "Failed to unzip file: " << backupName; - success = false; - } else { - _isRecovering = true; - _recoveryFilename = backupName; - for (auto& handler : _backupHandlers) { - handler->recoverBackup(zip); - } - - qDebug() << "Successfully started recovering from " << backupName; - success = true; - } + + success = recoverFromBackupZip(zip, backupName); + backupFile.close(); } else { success = false; @@ -301,7 +308,28 @@ void DomainContentBackupManager::recoverFromBackup(MiniPromise::Promise promise, }); } +void DomainContentBackupManager::recoverFromUploadedBackup(MiniPromise::Promise promise, QByteArray uploadedBackup) { + if (QThread::currentThread() != thread()) { + QMetaObject::invokeMethod(this, "recoverFromUploadedBackup", Q_ARG(MiniPromise::Promise, promise), + Q_ARG(QByteArray, uploadedBackup)); + return; + } + + qDebug() << "Recovering from uploaded content archive"; + + // create a buffer and then a QuaZip from that buffer + QBuffer uploadedBackupBuffer { &uploadedBackup }; + QuaZip uploadedZip { &uploadedBackupBuffer }; + + bool success = recoverFromBackupZip(uploadedZip, MANUAL_BACKUP_PREFIX + "uploaded.zip"); + + promise->resolve({ + { "success", success } + }); +} + std::vector DomainContentBackupManager::getAllBackups() { + QDir backupDir { _backupDirectory }; auto matchingFiles = backupDir.entryInfoList({ AUTOMATIC_BACKUP_PREFIX + "*.zip", MANUAL_BACKUP_PREFIX + "*.zip" }, diff --git a/domain-server/src/DomainContentBackupManager.h b/domain-server/src/DomainContentBackupManager.h index f1aa4acab2..d4b1f60b87 100644 --- a/domain-server/src/DomainContentBackupManager.h +++ b/domain-server/src/DomainContentBackupManager.h @@ -63,6 +63,7 @@ public slots: void getAllBackupsAndStatus(MiniPromise::Promise promise); void createManualBackup(MiniPromise::Promise promise, const QString& name); void recoverFromBackup(MiniPromise::Promise promise, const QString& backupName); + void recoverFromUploadedBackup(MiniPromise::Promise promise, QByteArray uploadedBackup); void deleteBackup(MiniPromise::Promise promise, const QString& backupName); void consolidateBackup(MiniPromise::Promise promise, QString fileName); @@ -85,6 +86,8 @@ protected: std::pair createBackup(const QString& prefix, const QString& name); + bool recoverFromBackupZip(QuaZip& backupZip, const QString& backupName); + private: const QString _backupDirectory; std::vector _backupHandlers; diff --git a/domain-server/src/DomainServer.cpp b/domain-server/src/DomainServer.cpp index c23d17ed95..7fe1d1a0ab 100644 --- a/domain-server/src/DomainServer.cpp +++ b/domain-server/src/DomainServer.cpp @@ -2273,10 +2273,25 @@ bool DomainServer::handleHTTPRequest(HTTPConnection* connection, const QUrl& url || uploadedFilename.endsWith(".json.gz", Qt::CaseInsensitive)) { // invoke our method to hand the new octree file off to the octree server QMetaObject::invokeMethod(this, "handleOctreeFileReplacement", - Qt::QueuedConnection, Q_ARG(QByteArray, formData[0].second)); + Qt::QueuedConnection, Q_ARG(QByteArray, firstFormData.second)); // respond with a 200 for success connection->respond(HTTPConnection::StatusCode200); + } else if (uploadedFilename.endsWith(".zip", Qt::CaseInsensitive)) { + auto deferred = makePromise("recoverFromUploadedBackup"); + + deferred->then([connection, JSON_MIME_TYPE](QString error, QVariantMap result) { + QJsonObject rootJSON; + auto success = result["success"].toBool(); + rootJSON["success"] = success; + QJsonDocument docJSON(rootJSON); + connection->respond(success ? HTTPConnection::StatusCode200 : HTTPConnection::StatusCode400, docJSON.toJson(), + JSON_MIME_TYPE.toUtf8()); + }); + + _contentManager->recoverFromUploadedBackup(deferred, firstFormData.second); + + return true; } else { // we don't have handling for this filetype, send back a 400 for failure connection->respond(HTTPConnection::StatusCode400);