Merge pull request #12420 from birarda/feat/content-settings-backup-handler

Add a content settings backup handler
This commit is contained in:
Clément Brisset 2018-02-15 16:46:22 -08:00 committed by GitHub
commit f67931c936
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
9 changed files with 156 additions and 17 deletions

View file

@ -0,0 +1,66 @@
//
// ContentSettingsBackupHandler.cpp
// domain-server/src
//
// Created by Stephen Birarda on 2/15/18.
// Copyright 2018 High Fidelity, Inc.
//
// Distributed under the Apache License, Version 2.0.
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
//
#include "ContentSettingsBackupHandler.h"
#include <quazip5/quazip.h>
#include <quazip5/quazipfile.h>
ContentSettingsBackupHandler::ContentSettingsBackupHandler(DomainServerSettingsManager& domainServerSettingsManager) :
_settingsManager(domainServerSettingsManager)
{
}
static const QString CONTENT_SETTINGS_BACKUP_FILENAME = "content-settings.json";
void ContentSettingsBackupHandler::createBackup(QuaZip& zip) {
// grab the content settings as JSON,excluding default values and values hidden from backup
QJsonObject contentSettingsJSON = _settingsManager.settingsResponseObjectForType("", true, false, true, false, true);
// make a QJSonDocument using the object
QJsonDocument contentSettingsDocument { contentSettingsJSON };
QuaZipFile zipFile { &zip };
zipFile.open(QIODevice::WriteOnly, QuaZipNewInfo(CONTENT_SETTINGS_BACKUP_FILENAME));
zipFile.write(contentSettingsDocument.toJson());
zipFile.close();
if (zipFile.getZipError() != UNZ_OK) {
qCritical().nospace() << "Failed to zip " << CONTENT_SETTINGS_BACKUP_FILENAME << ": " << zipFile.getZipError();
}
}
void ContentSettingsBackupHandler::recoverBackup(QuaZip& zip) {
if (!zip.setCurrentFile(CONTENT_SETTINGS_BACKUP_FILENAME)) {
qWarning() << "Failed to find" << CONTENT_SETTINGS_BACKUP_FILENAME << "while recovering backup";
return;
}
QuaZipFile zipFile { &zip };
if (!zipFile.open(QIODevice::ReadOnly)) {
qCritical() << "Failed to open" << CONTENT_SETTINGS_BACKUP_FILENAME << "in backup";
return;
}
auto rawData = zipFile.readAll();
zipFile.close();
QJsonDocument jsonDocument = QJsonDocument::fromJson(rawData);
if (!_settingsManager.restoreSettingsFromObject(jsonDocument.object(), ContentSettings)) {
qCritical() << "Failed to restore settings from" << CONTENT_SETTINGS_BACKUP_FILENAME << "in content archive";
return;
}
}

View file

@ -0,0 +1,35 @@
//
// ContentSettingsBackupHandler.h
// domain-server/src
//
// Created by Stephen Birarda on 2/15/18.
// Copyright 2018 High Fidelity, Inc.
//
// Distributed under the Apache License, Version 2.0.
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
//
#ifndef hifi_ContentSettingsBackupHandler_h
#define hifi_ContentSettingsBackupHandler_h
#include "BackupHandler.h"
#include "DomainServerSettingsManager.h"
class ContentSettingsBackupHandler : public BackupHandlerInterface {
public:
ContentSettingsBackupHandler(DomainServerSettingsManager& domainServerSettingsManager);
void loadBackup(QuaZip& zip) {};
void createBackup(QuaZip& zip);
void recoverBackup(QuaZip& zip);
void deleteBackup(QuaZip& zip) {};
void consolidateBackup(QuaZip& zip) {};
private:
DomainServerSettingsManager& _settingsManager;
};
#endif // hifi_ContentSettingsBackupHandler_h

View file

@ -155,9 +155,6 @@ bool DomainContentBackupManager::process() {
}
void DomainContentBackupManager::aboutToFinish() {
qCDebug(domain_server) << "Persist thread about to finish...";
backup();
qCDebug(domain_server) << "Persist thread done with about to finish...";
_stopThread = true;
}

View file

@ -46,6 +46,7 @@
#include <StatTracker.h>
#include "AssetsBackupHandler.h"
#include "ContentSettingsBackupHandler.h"
#include "DomainServerNodeData.h"
#include "EntitiesBackupHandler.h"
#include "NodeConnectionData.h"
@ -297,8 +298,13 @@ DomainServer::DomainServer(int argc, char* argv[]) :
maybeHandleReplacementEntityFile();
_contentManager.reset(new DomainContentBackupManager(getContentBackupDir(), _settingsManager.settingsResponseObjectForType("6")["entity_server_settings"].toObject()));
_contentManager->addBackupHandler(BackupHandlerPointer(new EntitiesBackupHandler(getEntitiesFilePath(), getEntitiesReplacementFilePath())));
_contentManager->addBackupHandler(BackupHandlerPointer(new AssetsBackupHandler(getContentBackupDir())));
connect(_contentManager.get(), &DomainContentBackupManager::started, _contentManager.get(), [this](){
_contentManager->addBackupHandler(BackupHandlerPointer(new EntitiesBackupHandler(getEntitiesFilePath(), getEntitiesReplacementFilePath())));
_contentManager->addBackupHandler(BackupHandlerPointer(new AssetsBackupHandler(getContentBackupDir())));
_contentManager->addBackupHandler(BackupHandlerPointer(new ContentSettingsBackupHandler(_settingsManager)));
});
_contentManager->initialize(true);
qDebug() << "Existing backups:";
@ -380,7 +386,7 @@ DomainServer::~DomainServer() {
if (_contentManager) {
_contentManager->aboutToFinish();
_contentManager->terminating();
_contentManager->terminate();
}
}

View file

@ -19,6 +19,7 @@
#include <QtCore/QJsonArray>
#include <QtCore/QJsonObject>
#include <QtCore/QStandardPaths>
#include <QtCore/QThread>
#include <QtCore/QUrl>
#include <QtCore/QUrlQuery>
@ -32,6 +33,8 @@
#include <SettingHelpers.h>
#include <AvatarData.h> //for KillAvatarReason
#include <FingerprintUtils.h>
#include <shared/QtHelpers.h>
#include "DomainServerNodeData.h"
const QString SETTINGS_DESCRIPTION_RELATIVE_PATH = "/resources/describe-settings.json";
@ -1196,6 +1199,17 @@ bool DomainServerSettingsManager::handleAuthenticatedHTTPRequest(HTTPConnection
}
bool DomainServerSettingsManager::restoreSettingsFromObject(QJsonObject settingsToRestore, SettingsType settingsType) {
if (thread() != QThread::currentThread()) {
bool success;
BLOCKING_INVOKE_METHOD(this, "restoreSettingsFromObject",
Q_RETURN_ARG(bool, success),
Q_ARG(QJsonObject, settingsToRestore),
Q_ARG(SettingsType, settingsType));
return success;
}
QJsonArray& filteredDescriptionArray = settingsType == DomainSettings
? _domainSettingsDescription : _contentSettingsDescription;
@ -1321,6 +1335,20 @@ QJsonObject DomainServerSettingsManager::settingsResponseObjectForType(const QSt
bool includeDefaults, bool isForBackup) {
QJsonObject responseObject;
if (thread() != QThread::currentThread()) {
BLOCKING_INVOKE_METHOD(this, "settingsResponseObjectForType",
Q_RETURN_ARG(QJsonObject, responseObject),
Q_ARG(const QString&, typeValue),
Q_ARG(bool, isAuthenticated),
Q_ARG(bool, includeDomainSettings),
Q_ARG(bool, includeContentSettings),
Q_ARG(bool, includeDefaults),
Q_ARG(bool, isForBackup));
return responseObject;
}
if (!typeValue.isEmpty() || isAuthenticated) {
// convert the string type value to a QJsonValue
QJsonValue queryType = typeValue.isEmpty() ? QJsonValue() : QJsonValue(typeValue.toInt());

View file

@ -111,6 +111,13 @@ public:
void debugDumpGroupsState();
/// thread safe method to retrieve a JSON representation of settings
Q_INVOKABLE QJsonObject settingsResponseObjectForType(const QString& typeValue, bool isAuthenticated = false,
bool includeDomainSettings = true, bool includeContentSettings = true,
bool includeDefaults = true, bool isForBackup = false);
/// thread safe method to restore settings from a JSON object
Q_INVOKABLE bool restoreSettingsFromObject(QJsonObject settingsToRestore, SettingsType settingsType);
signals:
void updateNodePermissions();
void settingsUpdated();
@ -130,9 +137,6 @@ private:
QStringList _argumentList;
QJsonArray filteredDescriptionArray(bool isContentSettings);
QJsonObject settingsResponseObjectForType(const QString& typeValue, bool isAuthenticated = false,
bool includeDomainSettings = true, bool includeContentSettings = true,
bool includeDefaults = true, bool isForBackup = false);
bool recurseJSONObjectAndOverwriteSettings(const QJsonObject& postedObject, SettingsType settingsType);
void updateSetting(const QString& key, const QJsonValue& newValue, QVariantMap& settingMap,
@ -143,8 +147,6 @@ private:
void splitSettingsDescription();
bool restoreSettingsFromObject(QJsonObject settingsToRestore, SettingsType settingsType);
double _descriptionVersion;
QJsonArray _descriptionArray;

View file

@ -24,28 +24,30 @@ EntitiesBackupHandler::EntitiesBackupHandler(QString entitiesFilePath, QString e
{
}
static const QString ENTITIES_BACKUP_FILENAME = "models.json.gz";
void EntitiesBackupHandler::createBackup(QuaZip& zip) {
QFile entitiesFile { _entitiesFilePath };
if (entitiesFile.open(QIODevice::ReadOnly)) {
QuaZipFile zipFile { &zip };
zipFile.open(QIODevice::WriteOnly, QuaZipNewInfo("models.json.gz", _entitiesFilePath));
zipFile.open(QIODevice::WriteOnly, QuaZipNewInfo(ENTITIES_BACKUP_FILENAME, _entitiesFilePath));
zipFile.write(entitiesFile.readAll());
zipFile.close();
if (zipFile.getZipError() != UNZ_OK) {
qCritical() << "Failed to zip models.json.gz: " << zipFile.getZipError();
qCritical().nospace() << "Failed to zip " << ENTITIES_BACKUP_FILENAME << ": " << zipFile.getZipError();
}
}
}
void EntitiesBackupHandler::recoverBackup(QuaZip& zip) {
if (!zip.setCurrentFile("models.json.gz")) {
qWarning() << "Failed to find models.json.gz while recovering backup";
if (!zip.setCurrentFile(ENTITIES_BACKUP_FILENAME)) {
qWarning() << "Failed to find" << ENTITIES_BACKUP_FILENAME << "while recovering backup";
return;
}
QuaZipFile zipFile { &zip };
if (!zipFile.open(QIODevice::ReadOnly)) {
qCritical() << "Failed to open models.json.gz in backup";
qCritical() << "Failed to open" << ENTITIES_BACKUP_FILENAME << "in backup";
return;
}
auto rawData = zipFile.readAll();
@ -61,7 +63,7 @@ void EntitiesBackupHandler::recoverBackup(QuaZip& zip) {
data.resetIdAndVersion();
if (zipFile.getZipError() != UNZ_OK) {
qCritical() << "Failed to unzip models.json.gz: " << zipFile.getZipError();
qCritical().nospace() << "Failed to unzip " << ENTITIES_BACKUP_FILENAME << ": " << zipFile.getZipError();
return;
}

View file

@ -38,6 +38,8 @@ void GenericThread::initialize(bool isThreaded, QThread::Priority priority) {
_thread->setObjectName(objectName());
// when the worker thread is started, call our engine's run..
connect(_thread, &QThread::started, this, &GenericThread::started);
connect(_thread, &QThread::started, this, &GenericThread::threadRoutine);
connect(_thread, &QThread::finished, this, &GenericThread::finished);

View file

@ -47,6 +47,7 @@ public slots:
void threadRoutine();
signals:
void started();
void finished();
protected: