From 727d59ab27f290317654902e1f1903824643ed70 Mon Sep 17 00:00:00 2001 From: Ryan Huffman Date: Tue, 16 Aug 2016 17:33:32 -0700 Subject: [PATCH] Add backup directory setting to domain server --- assignment-client/src/octree/OctreeServer.cpp | 56 +++++++++++++++---- assignment-client/src/octree/OctreeServer.h | 1 + .../resources/describe-settings.json | 8 +++ libraries/octree/src/OctreePersistThread.cpp | 20 ++++--- libraries/octree/src/OctreePersistThread.h | 7 ++- 5 files changed, 70 insertions(+), 22 deletions(-) diff --git a/assignment-client/src/octree/OctreeServer.cpp b/assignment-client/src/octree/OctreeServer.cpp index d763d1abe7..48ffc2fdbc 100644 --- a/assignment-client/src/octree/OctreeServer.cpp +++ b/assignment-client/src/octree/OctreeServer.cpp @@ -1063,6 +1063,12 @@ void OctreeServer::readConfiguration() { _wantBackup = !noBackup; qDebug() << "wantBackup=" << _wantBackup; + if (!readOptionString("backupDirectoryPath", settingsSectionObject, _backupDirectoryPath)) { + _backupDirectoryPath = ""; + } + + qDebug() << "backupDirectoryPath=" << _backupDirectoryPath; + readOptionBool(QString("persistFileDownload"), settingsSectionObject, _persistFileDownload); qDebug() << "persistFileDownload=" << _persistFileDownload; @@ -1160,25 +1166,25 @@ void OctreeServer::domainSettingsRequestComplete() { // If persist filename does not exist, let's see if there is one beside the application binary // If there is, let's copy it over to our target persist directory QDir persistPath { _persistFilePath }; - QString absoluteFilePath = persistPath.absolutePath(); + QString persistAbsoluteFilePath = persistPath.absolutePath(); if (persistPath.isRelative()) { // if the domain settings passed us a relative path, make an absolute path that is relative to the // default data directory - absoluteFilePath = QDir(ServerPathUtils::getDataFilePath("entities/")).absoluteFilePath(_persistFilePath); + persistAbsoluteFilePath = QDir(ServerPathUtils::getDataFilePath("entities/")).absoluteFilePath(_persistFilePath); } static const QString ENTITY_PERSIST_EXTENSION = ".json.gz"; // force the persist file to end with .json.gz - if (!absoluteFilePath.endsWith(ENTITY_PERSIST_EXTENSION, Qt::CaseInsensitive)) { - absoluteFilePath += ENTITY_PERSIST_EXTENSION; + if (!persistAbsoluteFilePath.endsWith(ENTITY_PERSIST_EXTENSION, Qt::CaseInsensitive)) { + persistAbsoluteFilePath += ENTITY_PERSIST_EXTENSION; } else { // make sure the casing of .json.gz is correct - absoluteFilePath.replace(ENTITY_PERSIST_EXTENSION, ENTITY_PERSIST_EXTENSION, Qt::CaseInsensitive); + persistAbsoluteFilePath.replace(ENTITY_PERSIST_EXTENSION, ENTITY_PERSIST_EXTENSION, Qt::CaseInsensitive); } - if (!QFile::exists(absoluteFilePath)) { + if (!QFile::exists(persistAbsoluteFilePath)) { qDebug() << "Persist file does not exist, checking for existence of persist file next to application"; static const QString OLD_DEFAULT_PERSIST_FILENAME = "resources/models.json.gz"; @@ -1204,7 +1210,7 @@ void OctreeServer::domainSettingsRequestComplete() { pathToCopyFrom = oldDefaultPersistPath; } - QDir persistFileDirectory { QDir::cleanPath(absoluteFilePath + "/..") }; + QDir persistFileDirectory { QDir::cleanPath(persistAbsoluteFilePath + "/..") }; if (!persistFileDirectory.exists()) { qDebug() << "Creating data directory " << persistFileDirectory.absolutePath(); @@ -1212,16 +1218,46 @@ void OctreeServer::domainSettingsRequestComplete() { } if (shouldCopy) { - qDebug() << "Old persist file found, copying from " << pathToCopyFrom << " to " << absoluteFilePath; + qDebug() << "Old persist file found, copying from " << pathToCopyFrom << " to " << persistAbsoluteFilePath; - QFile::copy(pathToCopyFrom, absoluteFilePath); + QFile::copy(pathToCopyFrom, persistAbsoluteFilePath); } else { qDebug() << "No existing persist file found"; } } + + auto persistFileDirectory = QFileInfo(persistAbsoluteFilePath).absolutePath(); + if (_backupDirectoryPath.isEmpty()) { + // Use the persist file's directory to store backups + _backupDirectoryPath = persistFileDirectory; + } else { + // The backup directory has been set. + // If relative, make it relative to the entities directory in the application data directory + // If absolute, no resolution is necessary + QDir backupDirectory { _backupDirectoryPath }; + QString absoluteBackupDirectory; + if (backupDirectory.isRelative()) { + absoluteBackupDirectory = QDir(ServerPathUtils::getDataFilePath("entities/")).absoluteFilePath(_backupDirectoryPath); + absoluteBackupDirectory = QDir(absoluteBackupDirectory).absolutePath(); + } else { + absoluteBackupDirectory = backupDirectory.absolutePath(); + } + backupDirectory = QDir(absoluteBackupDirectory); + if (!backupDirectory.exists()) { + if (backupDirectory.mkpath(".")) { + qDebug() << "Created backup directory"; + } else { + qDebug() << "ERROR creating backup directory, using persist file directory"; + _backupDirectoryPath = persistFileDirectory; + } + } else { + _backupDirectoryPath = absoluteBackupDirectory; + } + } + qDebug() << "Backups will be stored in: " << _backupDirectoryPath; // now set up PersistThread - _persistThread = new OctreePersistThread(_tree, absoluteFilePath, _persistInterval, + _persistThread = new OctreePersistThread(_tree, persistAbsoluteFilePath, _backupDirectoryPath, _persistInterval, _wantBackup, _settings, _debugTimestampNow, _persistAsFileType); _persistThread->initialize(true); } diff --git a/assignment-client/src/octree/OctreeServer.h b/assignment-client/src/octree/OctreeServer.h index d153f31154..35436997a6 100644 --- a/assignment-client/src/octree/OctreeServer.h +++ b/assignment-client/src/octree/OctreeServer.h @@ -172,6 +172,7 @@ protected: QString _persistFilePath; QString _persistAsFileType; + QString _backupDirectoryPath; int _packetsPerClientPerInterval; int _packetsTotalPerInterval; OctreePointer _tree; // this IS a reaveraging tree diff --git a/domain-server/resources/describe-settings.json b/domain-server/resources/describe-settings.json index c888fa301b..c9d7ea77d5 100644 --- a/domain-server/resources/describe-settings.json +++ b/domain-server/resources/describe-settings.json @@ -1108,6 +1108,14 @@ "default": "models.json.gz", "advanced": true }, + { + "name": "backupDirectoryPath", + "label": "Entities Backup Directory Path", + "help": "The path to the directory to store backups in.
If this path is relative it will be relative to the application data directory.", + "placeholder": "", + "default": "", + "advanced": true + }, { "name": "persistInterval", "label": "Save Check Interval", diff --git a/libraries/octree/src/OctreePersistThread.cpp b/libraries/octree/src/OctreePersistThread.cpp index d48c35d542..7034790eaf 100644 --- a/libraries/octree/src/OctreePersistThread.cpp +++ b/libraries/octree/src/OctreePersistThread.cpp @@ -34,11 +34,12 @@ const int OctreePersistThread::DEFAULT_PERSIST_INTERVAL = 1000 * 30; // every 30 seconds -OctreePersistThread::OctreePersistThread(OctreePointer tree, const QString& filename, int persistInterval, +OctreePersistThread::OctreePersistThread(OctreePointer tree, const QString& filename, const QString& backupDirectory, int persistInterval, bool wantBackup, const QJsonObject& settings, bool debugTimestampNow, QString persistAsFileType) : _tree(tree), _filename(filename), + _backupDirectory(backupDirectory), _persistInterval(persistInterval), _initialLoadComplete(false), _loadTimeUSecs(0), @@ -316,7 +317,7 @@ bool OctreePersistThread::getMostRecentBackup(const QString& format, // Based on our backup file name, determine the path and file name pattern for backup files QFileInfo persistFileInfo(_filename); - QString path = persistFileInfo.path(); + QString path = _backupDirectory; QString fileNamePart = persistFileInfo.fileName(); QStringList filters; @@ -369,10 +370,12 @@ void OctreePersistThread::rollOldBackupVersions(const BackupRule& rule) { if (rule.maxBackupVersions > 0) { qCDebug(octree) << "Rolling old backup versions for rule" << rule.name << "..."; + QString backupFileName = _backupDirectory + "/" + QUrl(_filename).fileName(); + // Delete maximum rolling file because rename() fails on Windows if target exists QString backupMaxExtensionN = rule.extensionFormat; backupMaxExtensionN.replace(QString("%N"), QString::number(rule.maxBackupVersions)); - QString backupMaxFilenameN = _filename + backupMaxExtensionN; + QString backupMaxFilenameN = backupFileName + backupMaxExtensionN; QFile backupMaxFileN(backupMaxFilenameN); if (backupMaxFileN.exists()) { int result = remove(qPrintable(backupMaxFilenameN)); @@ -387,8 +390,8 @@ void OctreePersistThread::rollOldBackupVersions(const BackupRule& rule) { backupExtensionN.replace(QString("%N"), QString::number(n)); backupExtensionNplusOne.replace(QString("%N"), QString::number(n+1)); - QString backupFilenameN = findMostRecentFileExtension(_filename, PERSIST_EXTENSIONS) + backupExtensionN; - QString backupFilenameNplusOne = _filename + backupExtensionNplusOne; + QString backupFilenameN = findMostRecentFileExtension(backupFileName, PERSIST_EXTENSIONS) + backupExtensionN; + QString backupFilenameNplusOne = backupFileName + backupExtensionNplusOne; QFile backupFileN(backupFilenameN); @@ -434,21 +437,20 @@ void OctreePersistThread::backup() { struct tm* localTime = localtime(&_lastPersistTime); - QString backupFileName; + QString backupFileName = _backupDirectory + "/" + QUrl(_filename).fileName(); // check to see if they asked for version rolling format if (rule.extensionFormat.contains("%N")) { rollOldBackupVersions(rule); // rename all the old backup files accordingly QString backupExtension = rule.extensionFormat; backupExtension.replace(QString("%N"), QString("1")); - backupFileName = _filename + backupExtension; + backupFileName += backupExtension; } else { char backupExtension[256]; strftime(backupExtension, sizeof(backupExtension), qPrintable(rule.extensionFormat), localTime); - backupFileName = _filename + backupExtension; + backupFileName += backupExtension; } - if (rule.maxBackupVersions > 0) { QFile persistFile(_filename); if (persistFile.exists()) { diff --git a/libraries/octree/src/OctreePersistThread.h b/libraries/octree/src/OctreePersistThread.h index 061a7a0e15..2a939216c4 100644 --- a/libraries/octree/src/OctreePersistThread.h +++ b/libraries/octree/src/OctreePersistThread.h @@ -33,9 +33,9 @@ public: static const int DEFAULT_PERSIST_INTERVAL; - OctreePersistThread(OctreePointer tree, const QString& filename, int persistInterval = DEFAULT_PERSIST_INTERVAL, - bool wantBackup = false, const QJsonObject& settings = QJsonObject(), - bool debugTimestampNow = false, QString persistAsFileType="svo"); + OctreePersistThread(OctreePointer tree, const QString& filename, const QString& backupDirectory, + int persistInterval = DEFAULT_PERSIST_INTERVAL, bool wantBackup = false, + const QJsonObject& settings = QJsonObject(), bool debugTimestampNow = false, QString persistAsFileType="svo"); bool isInitialLoadComplete() const { return _initialLoadComplete; } quint64 getLoadElapsedTime() const { return _loadTimeUSecs; } @@ -64,6 +64,7 @@ protected: private: OctreePointer _tree; QString _filename; + QString _backupDirectory; int _persistInterval; bool _initialLoadComplete;