Add backup directory setting to domain server

This commit is contained in:
Ryan Huffman 2016-08-16 17:33:32 -07:00
parent 8d12a23efb
commit 727d59ab27
5 changed files with 70 additions and 22 deletions

View file

@ -1063,6 +1063,12 @@ void OctreeServer::readConfiguration() {
_wantBackup = !noBackup; _wantBackup = !noBackup;
qDebug() << "wantBackup=" << _wantBackup; qDebug() << "wantBackup=" << _wantBackup;
if (!readOptionString("backupDirectoryPath", settingsSectionObject, _backupDirectoryPath)) {
_backupDirectoryPath = "";
}
qDebug() << "backupDirectoryPath=" << _backupDirectoryPath;
readOptionBool(QString("persistFileDownload"), settingsSectionObject, _persistFileDownload); readOptionBool(QString("persistFileDownload"), settingsSectionObject, _persistFileDownload);
qDebug() << "persistFileDownload=" << _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 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 // If there is, let's copy it over to our target persist directory
QDir persistPath { _persistFilePath }; QDir persistPath { _persistFilePath };
QString absoluteFilePath = persistPath.absolutePath(); QString persistAbsoluteFilePath = persistPath.absolutePath();
if (persistPath.isRelative()) { if (persistPath.isRelative()) {
// if the domain settings passed us a relative path, make an absolute path that is relative to the // if the domain settings passed us a relative path, make an absolute path that is relative to the
// default data directory // 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"; static const QString ENTITY_PERSIST_EXTENSION = ".json.gz";
// force the persist file to end with .json.gz // force the persist file to end with .json.gz
if (!absoluteFilePath.endsWith(ENTITY_PERSIST_EXTENSION, Qt::CaseInsensitive)) { if (!persistAbsoluteFilePath.endsWith(ENTITY_PERSIST_EXTENSION, Qt::CaseInsensitive)) {
absoluteFilePath += ENTITY_PERSIST_EXTENSION; persistAbsoluteFilePath += ENTITY_PERSIST_EXTENSION;
} else { } else {
// make sure the casing of .json.gz is correct // 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"; 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"; static const QString OLD_DEFAULT_PERSIST_FILENAME = "resources/models.json.gz";
@ -1204,7 +1210,7 @@ void OctreeServer::domainSettingsRequestComplete() {
pathToCopyFrom = oldDefaultPersistPath; pathToCopyFrom = oldDefaultPersistPath;
} }
QDir persistFileDirectory { QDir::cleanPath(absoluteFilePath + "/..") }; QDir persistFileDirectory { QDir::cleanPath(persistAbsoluteFilePath + "/..") };
if (!persistFileDirectory.exists()) { if (!persistFileDirectory.exists()) {
qDebug() << "Creating data directory " << persistFileDirectory.absolutePath(); qDebug() << "Creating data directory " << persistFileDirectory.absolutePath();
@ -1212,16 +1218,46 @@ void OctreeServer::domainSettingsRequestComplete() {
} }
if (shouldCopy) { 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 { } else {
qDebug() << "No existing persist file found"; 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 // now set up PersistThread
_persistThread = new OctreePersistThread(_tree, absoluteFilePath, _persistInterval, _persistThread = new OctreePersistThread(_tree, persistAbsoluteFilePath, _backupDirectoryPath, _persistInterval,
_wantBackup, _settings, _debugTimestampNow, _persistAsFileType); _wantBackup, _settings, _debugTimestampNow, _persistAsFileType);
_persistThread->initialize(true); _persistThread->initialize(true);
} }

View file

@ -172,6 +172,7 @@ protected:
QString _persistFilePath; QString _persistFilePath;
QString _persistAsFileType; QString _persistAsFileType;
QString _backupDirectoryPath;
int _packetsPerClientPerInterval; int _packetsPerClientPerInterval;
int _packetsTotalPerInterval; int _packetsTotalPerInterval;
OctreePointer _tree; // this IS a reaveraging tree OctreePointer _tree; // this IS a reaveraging tree

View file

@ -1108,6 +1108,14 @@
"default": "models.json.gz", "default": "models.json.gz",
"advanced": true "advanced": true
}, },
{
"name": "backupDirectoryPath",
"label": "Entities Backup Directory Path",
"help": "The path to the directory to store backups in.<br/>If this path is relative it will be relative to the application data directory.",
"placeholder": "",
"default": "",
"advanced": true
},
{ {
"name": "persistInterval", "name": "persistInterval",
"label": "Save Check Interval", "label": "Save Check Interval",

View file

@ -34,11 +34,12 @@
const int OctreePersistThread::DEFAULT_PERSIST_INTERVAL = 1000 * 30; // every 30 seconds 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, bool wantBackup, const QJsonObject& settings, bool debugTimestampNow,
QString persistAsFileType) : QString persistAsFileType) :
_tree(tree), _tree(tree),
_filename(filename), _filename(filename),
_backupDirectory(backupDirectory),
_persistInterval(persistInterval), _persistInterval(persistInterval),
_initialLoadComplete(false), _initialLoadComplete(false),
_loadTimeUSecs(0), _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 // Based on our backup file name, determine the path and file name pattern for backup files
QFileInfo persistFileInfo(_filename); QFileInfo persistFileInfo(_filename);
QString path = persistFileInfo.path(); QString path = _backupDirectory;
QString fileNamePart = persistFileInfo.fileName(); QString fileNamePart = persistFileInfo.fileName();
QStringList filters; QStringList filters;
@ -369,10 +370,12 @@ void OctreePersistThread::rollOldBackupVersions(const BackupRule& rule) {
if (rule.maxBackupVersions > 0) { if (rule.maxBackupVersions > 0) {
qCDebug(octree) << "Rolling old backup versions for rule" << rule.name << "..."; 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 // Delete maximum rolling file because rename() fails on Windows if target exists
QString backupMaxExtensionN = rule.extensionFormat; QString backupMaxExtensionN = rule.extensionFormat;
backupMaxExtensionN.replace(QString("%N"), QString::number(rule.maxBackupVersions)); backupMaxExtensionN.replace(QString("%N"), QString::number(rule.maxBackupVersions));
QString backupMaxFilenameN = _filename + backupMaxExtensionN; QString backupMaxFilenameN = backupFileName + backupMaxExtensionN;
QFile backupMaxFileN(backupMaxFilenameN); QFile backupMaxFileN(backupMaxFilenameN);
if (backupMaxFileN.exists()) { if (backupMaxFileN.exists()) {
int result = remove(qPrintable(backupMaxFilenameN)); int result = remove(qPrintable(backupMaxFilenameN));
@ -387,8 +390,8 @@ void OctreePersistThread::rollOldBackupVersions(const BackupRule& rule) {
backupExtensionN.replace(QString("%N"), QString::number(n)); backupExtensionN.replace(QString("%N"), QString::number(n));
backupExtensionNplusOne.replace(QString("%N"), QString::number(n+1)); backupExtensionNplusOne.replace(QString("%N"), QString::number(n+1));
QString backupFilenameN = findMostRecentFileExtension(_filename, PERSIST_EXTENSIONS) + backupExtensionN; QString backupFilenameN = findMostRecentFileExtension(backupFileName, PERSIST_EXTENSIONS) + backupExtensionN;
QString backupFilenameNplusOne = _filename + backupExtensionNplusOne; QString backupFilenameNplusOne = backupFileName + backupExtensionNplusOne;
QFile backupFileN(backupFilenameN); QFile backupFileN(backupFilenameN);
@ -434,21 +437,20 @@ void OctreePersistThread::backup() {
struct tm* localTime = localtime(&_lastPersistTime); struct tm* localTime = localtime(&_lastPersistTime);
QString backupFileName; QString backupFileName = _backupDirectory + "/" + QUrl(_filename).fileName();
// check to see if they asked for version rolling format // check to see if they asked for version rolling format
if (rule.extensionFormat.contains("%N")) { if (rule.extensionFormat.contains("%N")) {
rollOldBackupVersions(rule); // rename all the old backup files accordingly rollOldBackupVersions(rule); // rename all the old backup files accordingly
QString backupExtension = rule.extensionFormat; QString backupExtension = rule.extensionFormat;
backupExtension.replace(QString("%N"), QString("1")); backupExtension.replace(QString("%N"), QString("1"));
backupFileName = _filename + backupExtension; backupFileName += backupExtension;
} else { } else {
char backupExtension[256]; char backupExtension[256];
strftime(backupExtension, sizeof(backupExtension), qPrintable(rule.extensionFormat), localTime); strftime(backupExtension, sizeof(backupExtension), qPrintable(rule.extensionFormat), localTime);
backupFileName = _filename + backupExtension; backupFileName += backupExtension;
} }
if (rule.maxBackupVersions > 0) { if (rule.maxBackupVersions > 0) {
QFile persistFile(_filename); QFile persistFile(_filename);
if (persistFile.exists()) { if (persistFile.exists()) {

View file

@ -33,9 +33,9 @@ public:
static const int DEFAULT_PERSIST_INTERVAL; static const int DEFAULT_PERSIST_INTERVAL;
OctreePersistThread(OctreePointer tree, const QString& filename, int persistInterval = DEFAULT_PERSIST_INTERVAL, OctreePersistThread(OctreePointer tree, const QString& filename, const QString& backupDirectory,
bool wantBackup = false, const QJsonObject& settings = QJsonObject(), int persistInterval = DEFAULT_PERSIST_INTERVAL, bool wantBackup = false,
bool debugTimestampNow = false, QString persistAsFileType="svo"); const QJsonObject& settings = QJsonObject(), bool debugTimestampNow = false, QString persistAsFileType="svo");
bool isInitialLoadComplete() const { return _initialLoadComplete; } bool isInitialLoadComplete() const { return _initialLoadComplete; }
quint64 getLoadElapsedTime() const { return _loadTimeUSecs; } quint64 getLoadElapsedTime() const { return _loadTimeUSecs; }
@ -64,6 +64,7 @@ protected:
private: private:
OctreePointer _tree; OctreePointer _tree;
QString _filename; QString _filename;
QString _backupDirectory;
int _persistInterval; int _persistInterval;
bool _initialLoadComplete; bool _initialLoadComplete;