This commit is contained in:
Ryan Huffman 2018-02-26 13:43:33 -08:00
parent b18d5db062
commit dbfbee5406
9 changed files with 53 additions and 70 deletions

View file

@ -1041,8 +1041,6 @@ void OctreeServer::readConfiguration() {
_persistFilePath = getMyDefaultPersistFilename();
}
// 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 };
if (persistPath.isRelative()) {

View file

@ -38,8 +38,7 @@
#include "DomainServer.h"
const int DomainContentBackupManager::DEFAULT_PERSIST_INTERVAL = 1000 * 30; // every 30 seconds
const std::chrono::milliseconds DomainContentBackupManager::DEFAULT_PERSIST_INTERVAL { 30 * 1000 }; // every 30 seconds
// Backup format looks like: daily_backup-TIMESTAMP.zip
static const QString DATETIME_FORMAT { "yyyy-MM-dd_HH-mm-ss" };
static const QString DATETIME_FORMAT_RE { "\\d{4}-\\d{2}-\\d{2}_\\d{2}-\\d{2}-\\d{2}" };
@ -53,12 +52,11 @@ void DomainContentBackupManager::addBackupHandler(BackupHandlerPointer handler)
DomainContentBackupManager::DomainContentBackupManager(const QString& backupDirectory,
const QVariantList& backupRules,
int persistInterval,
bool debugTimestampNow)
: _backupDirectory(backupDirectory),
_persistInterval(persistInterval),
_lastCheck(usecTimestampNow())
std::chrono::milliseconds persistInterval,
bool debugTimestampNow) :
_backupDirectory(backupDirectory), _persistInterval(persistInterval), _lastCheck(p_high_resolution_clock::now())
{
setObjectName("DomainContentBackupManager");
// Make sure the backup directory exists.
@ -121,7 +119,32 @@ int64_t DomainContentBackupManager::getMostRecentBackupTimeInSecs(const QString&
}
void DomainContentBackupManager::setup() {
load();
auto backups = getAllBackups();
for (auto& backup : backups) {
QFile backupFile { backup.absolutePath };
if (!backupFile.open(QIODevice::ReadOnly)) {
qCritical() << "Could not open file:" << backup.absolutePath;
qCritical() << " ERROR:" << backupFile.errorString();
continue;
}
QuaZip zip { &backupFile };
if (!zip.open(QuaZip::mdUnzip)) {
qCritical() << "Could not open backup archive:" << backup.absolutePath;
qCritical() << " ERROR:" << zip.getZipError();
continue;
}
for (auto& handler : _backupHandlers) {
handler->loadBackup(backup.id, zip);
}
zip.close();
}
for (auto& handler : _backupHandlers) {
handler->loadingComplete();
}
}
bool DomainContentBackupManager::process() {
@ -130,10 +153,6 @@ bool DomainContentBackupManager::process() {
constexpr int64_t USECS_TO_SLEEP = 10 * MSECS_TO_USECS; // every 10ms
std::this_thread::sleep_for(std::chrono::microseconds(USECS_TO_SLEEP));
int64_t now = usecTimestampNow();
int64_t sinceLastSave = now - _lastCheck;
int64_t intervalToCheck = _persistInterval * MSECS_TO_USECS;
if (_isRecovering) {
bool isStillRecovering = any_of(begin(_backupHandlers), end(_backupHandlers), [](const BackupHandlerPointer& handler) {
return handler->getRecoveryStatus().first;
@ -146,7 +165,9 @@ bool DomainContentBackupManager::process() {
}
}
if (sinceLastSave > intervalToCheck) {
auto now = p_high_resolution_clock::now();
auto sinceLastSave = now - _lastCheck;
if (sinceLastSave > _persistInterval) {
_lastCheck = now;
if (!_isRecovering) {
@ -279,7 +300,8 @@ void DomainContentBackupManager::recoverFromBackup(MiniPromise::Promise promise,
bool success { false };
QDir backupDir { _backupDirectory };
QFile backupFile { backupDir.filePath(backupName) };
auto backupFilePath { backupDir.filePath(backupName) };
QFile backupFile { backupFilePath };
if (backupFile.open(QIODevice::ReadOnly)) {
QuaZip zip { &backupFile };
@ -288,7 +310,7 @@ void DomainContentBackupManager::recoverFromBackup(MiniPromise::Promise promise,
backupFile.close();
} else {
success = false;
qWarning() << "Invalid id: " << backupName;
qWarning() << "Failed to open backup file for reading: " << backupFilePath;
}
promise->resolve({
@ -339,19 +361,10 @@ std::vector<BackupItemInfo> DomainContentBackupManager::getAllBackups() {
auto dateTime = backupNameFormat.cap(3);
auto createdAt = QDateTime::fromString(dateTime, DATETIME_FORMAT);
if (!createdAt.isValid()) {
qDebug().nospace() << "Skipping backup (" << fileName << ") with invalid timestamp: " << dateTime;
continue;
}
bool isAvailable { true };
float availabilityProgress { 0.0f };
for (auto& handler : _backupHandlers) {
bool handlerIsAvailable { true };
float progress { 0.0f };
std::tie(handlerIsAvailable, progress) = handler->isAvailable(fileName);
isAvailable &= handlerIsAvailable;
availabilityProgress += progress / _backupHandlers.size();
}
backups.emplace_back(fileInfo.fileName(), name, fileInfo.absoluteFilePath(), createdAt,
type == MANUAL_BACKUP_PREFIX);
}
@ -448,35 +461,6 @@ void DomainContentBackupManager::removeOldBackupVersions(const BackupRule& rule)
}
}
void DomainContentBackupManager::load() {
auto backups = getAllBackups();
for (auto& backup : backups) {
QFile backupFile { backup.absolutePath };
if (!backupFile.open(QIODevice::ReadOnly)) {
qCritical() << "Could not open file:" << backup.absolutePath;
qCritical() << " ERROR:" << backupFile.errorString();
continue;
}
QuaZip zip { &backupFile };
if (!zip.open(QuaZip::mdUnzip)) {
qCritical() << "Could not open backup archive:" << backup.absolutePath;
qCritical() << " ERROR:" << zip.getZipError();
continue;
}
for (auto& handler : _backupHandlers) {
handler->loadBackup(backup.id, zip);
}
zip.close();
}
for (auto& handler : _backupHandlers) {
handler->loadingComplete();
}
}
void DomainContentBackupManager::backup() {
auto nowDateTime = QDateTime::currentDateTime();
auto nowSeconds = nowDateTime.toSecsSinceEpoch();

View file

@ -25,6 +25,8 @@
#include <shared/MiniPromises.h>
#include <PortableHighResolutionClock.h>
struct BackupItemInfo {
BackupItemInfo(QString pId, QString pName, QString pAbsolutePath, QDateTime pCreatedAt, bool pIsManualBackup) :
id(pId), name(pName), absolutePath(pAbsolutePath), createdAt(pCreatedAt), isManualBackup(pIsManualBackup) { };
@ -48,11 +50,11 @@ public:
qint64 lastBackupSeconds;
};
static const int DEFAULT_PERSIST_INTERVAL;
static const std::chrono::milliseconds DEFAULT_PERSIST_INTERVAL;
DomainContentBackupManager(const QString& rootBackupDirectory,
const QVariantList& settings,
int persistInterval = DEFAULT_PERSIST_INTERVAL,
std::chrono::milliseconds persistInterval = DEFAULT_PERSIST_INTERVAL,
bool debugTimestampNow = false);
std::vector<BackupItemInfo> getAllBackups();
@ -78,7 +80,6 @@ protected:
virtual bool process() override;
virtual void shutdown() override;
void load();
void backup();
void removeOldBackupVersions(const BackupRule& rule);
void refreshBackupRules();
@ -93,12 +94,12 @@ protected:
private:
const QString _backupDirectory;
std::vector<BackupHandlerPointer> _backupHandlers;
int _persistInterval { 0 };
std::chrono::milliseconds _persistInterval { 0 };
std::atomic<bool> _isRecovering { false };
QString _recoveryFilename { };
int64_t _lastCheck { 0 };
std::chrono::time_point<std::chrono::high_resolution_clock> _lastCheck;
std::vector<BackupRule> _backupRules;
};

View file

@ -3354,8 +3354,7 @@ void DomainServer::maybeHandleReplacementEntityFile() {
if (!replacementFile.remove()) {
// If we can't remove the replacement file, we are at risk of getting into a state where
// we continually replace the primary entity file with the replacement entity file.
qCWarning(domain_server)
<< "Unable to remove replacement file, bailing";
qCWarning(domain_server) << "Unable to remove replacement file, bailing";
} else {
data.resetIdAndVersion();
auto gzippedData = data.toGzippedByteArray();

View file

@ -31,7 +31,10 @@ void EntitiesBackupHandler::createBackup(const QString& backupName, QuaZip& zip)
if (entitiesFile.open(QIODevice::ReadOnly)) {
QuaZipFile zipFile { &zip };
zipFile.open(QIODevice::WriteOnly, QuaZipNewInfo(ENTITIES_BACKUP_FILENAME, _entitiesFilePath));
if (!zipFile.open(QIODevice::WriteOnly, QuaZipNewInfo(ENTITIES_BACKUP_FILENAME, _entitiesFilePath))) {
qCritical().nospace() << "Failed to open " << ENTITIES_BACKUP_FILENAME << " for writing in zip";
return;
}
zipFile.write(entitiesFile.readAll());
zipFile.close();
if (zipFile.getZipError() != UNZ_OK) {

View file

@ -1816,8 +1816,6 @@ bool Octree::toGzippedJSON(QByteArray* data, const OctreeElementPointer& element
if (!gzip(jsonData, *data, -1)) {
qCritical("Unable to gzip data while saving to json.");
return false;
} else {
qDebug() <<"Did gzip!";
}
return true;

View file

@ -35,7 +35,7 @@ public:
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="json.gz", const QByteArray& replacementData = QByteArray());
QString persistAsFileType = "json.gz", const QByteArray& replacementData = QByteArray());
bool isInitialLoadComplete() const { return _initialLoadComplete; }
quint64 getLoadElapsedTime() const { return _loadTimeUSecs; }

View file

@ -17,6 +17,7 @@
#include <AABox.h>
#include <Gzip.h>
#include <udt/PacketHeaders.h>
#include <QJsonObject>
#include <QJsonDocument>
@ -140,10 +141,11 @@ bool OctreeUtils::readOctreeDataInfoFromFile(QString path, OctreeUtils::RawOctre
}
QByteArray OctreeUtils::RawOctreeData::toByteArray() {
const auto protocolVersion = (int)versionForPacketType(PacketType::EntityData);
QJsonObject obj {
{ "DataVersion", QJsonValue((qint64)version) },
{ "Id", QJsonValue(id.toString()) },
{ "Version", QJsonValue(5) },
{ "Version", protocolVersion },
{ "Entities", octreeData }
};

View file

@ -37,8 +37,6 @@ void GenericThread::initialize(bool isThreaded, QThread::Priority priority) {
// match the thread name to our object name
_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);