Merge pull request #12431 from Atlante45/feat/backups-integration

Index backups by filename
This commit is contained in:
Stephen Birarda 2018-02-16 18:21:30 -07:00 committed by GitHub
commit df236aaeb0
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
10 changed files with 106 additions and 132 deletions

View file

@ -112,9 +112,9 @@ void AssetsBackupHandler::checkForAssetsToDelete() {
}
std::pair<bool, float> AssetsBackupHandler::isAvailable(QString filePath) {
auto it = find_if(begin(_backups), end(_backups), [&](const std::vector<AssetServerBackup>::value_type& value) {
return value.filePath == filePath;
std::pair<bool, float> AssetsBackupHandler::isAvailable(const QString& backupName) {
const auto it = find_if(begin(_backups), end(_backups), [&](const AssetServerBackup& backup) {
return backup.name == backupName;
});
if (it == end(_backups)) {
return { true, 1.0f };
@ -154,10 +154,10 @@ std::pair<bool, float> AssetsBackupHandler::getRecoveryStatus() {
return { true, progress };
}
void AssetsBackupHandler::loadBackup(QuaZip& zip) {
void AssetsBackupHandler::loadBackup(const QString& backupName, QuaZip& zip) {
Q_ASSERT(QThread::currentThread() == thread());
_backups.push_back({ zip.getZipName(), {}, false });
_backups.emplace_back(backupName, AssetUtils::Mappings(), false);
auto& backup = _backups.back();
if (!zip.setCurrentFile(MAPPINGS_FILE)) {
@ -170,7 +170,7 @@ void AssetsBackupHandler::loadBackup(QuaZip& zip) {
QuaZipFile zipFile { &zip };
if (!zipFile.open(QFile::ReadOnly)) {
qCCritical(asset_backup) << "Could not unzip backup file for load:" << zip.getZipName();
qCCritical(asset_backup) << "Could not unzip backup file for load:" << backupName;
qCCritical(asset_backup) << " Error:" << zip.getZipError();
backup.corruptedBackup = true;
_allBackupsLoadedSuccessfully = false;
@ -180,7 +180,7 @@ void AssetsBackupHandler::loadBackup(QuaZip& zip) {
QJsonParseError error;
auto document = QJsonDocument::fromJson(zipFile.readAll(), &error);
if (document.isNull() || !document.isObject()) {
qCCritical(asset_backup) << "Could not parse backup file to JSON object for load:" << zip.getZipName();
qCCritical(asset_backup) << "Could not parse backup file to JSON object for load:" << backupName;
qCCritical(asset_backup) << " Error:" << error.errorString();
backup.corruptedBackup = true;
_allBackupsLoadedSuccessfully = false;
@ -193,7 +193,7 @@ void AssetsBackupHandler::loadBackup(QuaZip& zip) {
const auto& assetHash = it.value().toString();
if (!AssetUtils::isValidHash(assetHash)) {
qCCritical(asset_backup) << "Corrupted mapping in loading backup file" << zip.getZipName() << ":" << it.key();
qCCritical(asset_backup) << "Corrupted mapping in loading backup file" << backupName << ":" << it.key();
backup.corruptedBackup = true;
_allBackupsLoadedSuccessfully = false;
continue;
@ -208,7 +208,7 @@ void AssetsBackupHandler::loadBackup(QuaZip& zip) {
return;
}
void AssetsBackupHandler::createBackup(QuaZip& zip) {
void AssetsBackupHandler::createBackup(const QString& backupName, QuaZip& zip) {
Q_ASSERT(QThread::currentThread() == thread());
if (operationInProgress()) {
@ -226,12 +226,11 @@ void AssetsBackupHandler::createBackup(QuaZip& zip) {
qCWarning(asset_backup) << "Backing up asset mappings that might be stale.";
}
AssetServerBackup backup;
backup.filePath = zip.getZipName();
AssetUtils::Mappings mappings;
QJsonObject jsonObject;
for (const auto& mapping : _currentMappings) {
backup.mappings[mapping.first] = mapping.second;
mappings[mapping.first] = mapping.second;
_assetsInBackups.insert(mapping.second);
jsonObject.insert(mapping.first, mapping.second);
}
@ -248,10 +247,11 @@ void AssetsBackupHandler::createBackup(QuaZip& zip) {
qCDebug(asset_backup) << "Could not close zip file: " << zipFile.getZipError();
return;
}
_backups.push_back(backup);
_backups.emplace_back(backupName, mappings, false);
qDebug() << "Created asset backup:" << backupName;
}
void AssetsBackupHandler::recoverBackup(QuaZip& zip) {
void AssetsBackupHandler::recoverBackup(const QString& backupName, QuaZip& zip) {
Q_ASSERT(QThread::currentThread() == thread());
if (operationInProgress()) {
@ -269,13 +269,11 @@ void AssetsBackupHandler::recoverBackup(QuaZip& zip) {
qCWarning(asset_backup) << "Current asset mappings that might be stale.";
}
auto it = find_if(begin(_backups), end(_backups), [&](const std::vector<AssetServerBackup>::value_type& value) {
return value.filePath == zip.getZipName();
const auto it = find_if(begin(_backups), end(_backups), [&](const AssetServerBackup& backup) {
return backup.name == backupName;
});
if (it == end(_backups)) {
qCDebug(asset_backup) << "Could not find backup" << zip.getZipName() << "to restore.";
loadBackup(zip);
loadBackup(backupName, zip);
QuaZipDir zipDir { &zip, ZIP_ASSETS_FOLDER };
@ -306,7 +304,7 @@ void AssetsBackupHandler::recoverBackup(QuaZip& zip) {
restoreAllAssets();
}
void AssetsBackupHandler::deleteBackup(const QString& absoluteFilePath) {
void AssetsBackupHandler::deleteBackup(const QString& backupName) {
Q_ASSERT(QThread::currentThread() == thread());
if (operationInProgress()) {
@ -314,33 +312,32 @@ void AssetsBackupHandler::deleteBackup(const QString& absoluteFilePath) {
return;
}
auto it = find_if(begin(_backups), end(_backups), [&](const std::vector<AssetServerBackup>::value_type& value) {
return value.filePath == absoluteFilePath;
const auto it = find_if(begin(_backups), end(_backups), [&](const AssetServerBackup& backup) {
return backup.name == backupName;
});
if (it == end(_backups)) {
qCDebug(asset_backup) << "Could not find backup" << absoluteFilePath << "to delete.";
qCDebug(asset_backup) << "Could not find backup" << backupName << "to delete.";
return;
}
refreshAssetsInBackups();
checkForAssetsToDelete();
qDebug() << "Deleted asset backup:" << backupName;
}
void AssetsBackupHandler::consolidateBackup(QuaZip& zip) {
void AssetsBackupHandler::consolidateBackup(const QString& backupName, QuaZip& zip) {
Q_ASSERT(QThread::currentThread() == thread());
if (operationInProgress()) {
qCWarning(asset_backup) << "There is a backup/restore in progress.";
return;
}
QFileInfo zipInfo(zip.getZipName());
auto it = find_if(begin(_backups), end(_backups), [&](const std::vector<AssetServerBackup>::value_type& value) {
QFileInfo info(value.filePath);
return info.fileName() == zipInfo.fileName();
const auto it = find_if(begin(_backups), end(_backups), [&](const AssetServerBackup& backup) {
return backup.name == backupName;
});
if (it == end(_backups)) {
qCDebug(asset_backup) << "Could not find backup" << zip.getZipName() << "to consolidate.";
qCDebug(asset_backup) << "Could not find backup" << backupName << "to consolidate.";
return;
}
@ -465,7 +462,7 @@ bool AssetsBackupHandler::writeAssetFile(const AssetUtils::AssetHash& hash, cons
}
void AssetsBackupHandler::computeServerStateDifference(const AssetUtils::Mappings& currentMappings,
const AssetUtils::Mappings& newMappings) {
const AssetUtils::Mappings& newMappings) {
_mappingsLeftToSet.reserve((int)newMappings.size());
_assetsLeftToUpload.reserve((int)newMappings.size());
_mappingsLeftToDelete.reserve((int)currentMappings.size());

View file

@ -31,14 +31,14 @@ class AssetsBackupHandler : public QObject, public BackupHandlerInterface {
public:
AssetsBackupHandler(const QString& backupDirectory);
std::pair<bool, float> isAvailable(QString filePath) override;
std::pair<bool, float> isAvailable(const QString& backupName) override;
std::pair<bool, float> getRecoveryStatus() override;
void loadBackup(QuaZip& zip) override;
void createBackup(QuaZip& zip) override;
void recoverBackup(QuaZip& zip) override;
void deleteBackup(const QString& absoluteFilePath) override;
void consolidateBackup(QuaZip& zip) override;
void loadBackup(const QString& backupName, QuaZip& zip) override;
void createBackup(const QString& backupName, QuaZip& zip) override;
void recoverBackup(const QString& backupName, QuaZip& zip) override;
void deleteBackup(const QString& backupName) override;
void consolidateBackup(const QString& backupName, QuaZip& zip) override;
bool operationInProgress() { return getRecoveryStatus().first; }
@ -68,7 +68,10 @@ private:
AssetUtils::Mappings _currentMappings;
struct AssetServerBackup {
QString filePath;
AssetServerBackup(const QString& pName, AssetUtils::Mappings pMappings, bool pCorruptedBackup) :
name(pName), mappings(pMappings), corruptedBackup(pCorruptedBackup) {}
QString name;
AssetUtils::Mappings mappings;
bool corruptedBackup;
};

View file

@ -22,16 +22,16 @@ class BackupHandlerInterface {
public:
virtual ~BackupHandlerInterface() = default;
virtual std::pair<bool, float> isAvailable(QString filePath) = 0;
virtual std::pair<bool, float> isAvailable(const QString& backupName) = 0;
// Returns whether a recovery is ongoing and a progress between 0 and 1 if one is.
virtual std::pair<bool, float> getRecoveryStatus() = 0;
virtual void loadBackup(QuaZip& zip) = 0;
virtual void createBackup(QuaZip& zip) = 0;
virtual void recoverBackup(QuaZip& zip) = 0;
virtual void deleteBackup(const QString& absoluteFilePath) = 0;
virtual void consolidateBackup(QuaZip& zip) = 0;
virtual void loadBackup(const QString& backupName, QuaZip& zip) = 0;
virtual void createBackup(const QString& backupName, QuaZip& zip) = 0;
virtual void recoverBackup(const QString& backupName, QuaZip& zip) = 0;
virtual void deleteBackup(const QString& backupName) = 0;
virtual void consolidateBackup(const QString& backupName, QuaZip& zip) = 0;
};
using BackupHandlerPointer = std::unique_ptr<BackupHandlerInterface>;

View file

@ -17,12 +17,11 @@
ContentSettingsBackupHandler::ContentSettingsBackupHandler(DomainServerSettingsManager& domainServerSettingsManager) :
_settingsManager(domainServerSettingsManager)
{
}
static const QString CONTENT_SETTINGS_BACKUP_FILENAME = "content-settings.json";
void ContentSettingsBackupHandler::createBackup(QuaZip& zip) {
void ContentSettingsBackupHandler::createBackup(const QString& backupName, 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);
@ -41,7 +40,7 @@ void ContentSettingsBackupHandler::createBackup(QuaZip& zip) {
}
}
void ContentSettingsBackupHandler::recoverBackup(QuaZip& zip) {
void ContentSettingsBackupHandler::recoverBackup(const QString& backupName, QuaZip& zip) {
if (!zip.setCurrentFile(CONTENT_SETTINGS_BACKUP_FILENAME)) {
qWarning() << "Failed to find" << CONTENT_SETTINGS_BACKUP_FILENAME << "while recovering backup";
return;

View file

@ -19,18 +19,18 @@ class ContentSettingsBackupHandler : public BackupHandlerInterface {
public:
ContentSettingsBackupHandler(DomainServerSettingsManager& domainServerSettingsManager);
std::pair<bool, float> isAvailable(QString filePath) override { return { true, 1.0f }; }
std::pair<bool, float> isAvailable(const QString& backupName) override { return { true, 1.0f }; }
std::pair<bool, float> getRecoveryStatus() override { return { false, 1.0f }; }
void loadBackup(QuaZip& zip) override {}
void loadBackup(const QString& backupName, QuaZip& zip) override {}
void createBackup(QuaZip& zip) override;
void createBackup(const QString& backupName, QuaZip& zip) override;
void recoverBackup(QuaZip& zip) override;
void recoverBackup(const QString& backupName, QuaZip& zip) override;
void deleteBackup(const QString& absoluteFilePath) override {}
void deleteBackup(const QString& backupName) override {}
void consolidateBackup(QuaZip& zip) override {}
void consolidateBackup(const QString& backupName, QuaZip& zip) override {}
private:
DomainServerSettingsManager& _settingsManager;
};

View file

@ -50,7 +50,7 @@ void DomainContentBackupManager::addBackupHandler(BackupHandlerPointer handler)
}
DomainContentBackupManager::DomainContentBackupManager(const QString& backupDirectory,
const QJsonObject& settings,
const QVariantList& backupRules,
int persistInterval,
bool debugTimestampNow)
: _backupDirectory(backupDirectory),
@ -62,59 +62,38 @@ DomainContentBackupManager::DomainContentBackupManager(const QString& backupDire
// Make sure the backup directory exists.
QDir(_backupDirectory).mkpath(".");
parseSettings(settings);
parseBackupRules(backupRules);
}
void DomainContentBackupManager::parseSettings(const QJsonObject& settings) {
static const QString BACKUP_RULES_KEY = "backup_rules";
if (settings[BACKUP_RULES_KEY].isArray()) {
const QJsonArray& backupRules = settings[BACKUP_RULES_KEY].toArray();
qCDebug(domain_server) << "BACKUP RULES:";
void DomainContentBackupManager::parseBackupRules(const QVariantList& backupRules) {
qCDebug(domain_server) << "BACKUP RULES:";
for (const QJsonValue& value : backupRules) {
QJsonObject obj = value.toObject();
for (const QVariant& value : backupRules) {
QVariantMap map = value.toMap();
int interval = 0;
int count = 0;
int interval = map["backupInterval"].toInt();
int count = map["maxBackupVersions"].toInt();
auto name = map["Name"].toString();
auto format = name.replace(" ", "_").toLower();
QJsonValue intervalVal = obj["backupInterval"];
if (intervalVal.isString()) {
interval = intervalVal.toString().toInt();
} else {
interval = intervalVal.toInt();
}
qCDebug(domain_server) << " Name:" << name;
qCDebug(domain_server) << " format:" << format;
qCDebug(domain_server) << " interval:" << interval;
qCDebug(domain_server) << " count:" << count;
QJsonValue countVal = obj["maxBackupVersions"];
if (countVal.isString()) {
count = countVal.toString().toInt();
} else {
count = countVal.toInt();
}
BackupRule newRule = { name, interval, format, count, 0 };
auto name = obj["Name"].toString();
auto format = name.replace(" ", "_").toLower();
newRule.lastBackupSeconds = getMostRecentBackupTimeInSecs(format);
qCDebug(domain_server) << " Name:" << name;
qCDebug(domain_server) << " format:" << format;
qCDebug(domain_server) << " interval:" << interval;
qCDebug(domain_server) << " count:" << count;
BackupRule newRule = { name, interval, format, count, 0 };
newRule.lastBackupSeconds = getMostRecentBackupTimeInSecs(format);
if (newRule.lastBackupSeconds > 0) {
auto now = QDateTime::currentSecsSinceEpoch();
auto sinceLastBackup = now - newRule.lastBackupSeconds;
qCDebug(domain_server).noquote() << " lastBackup:" << formatSecTime(sinceLastBackup) << "ago";
} else {
qCDebug(domain_server) << " lastBackup: NEVER";
}
_backupRules.push_back(newRule);
if (newRule.lastBackupSeconds > 0) {
auto now = QDateTime::currentSecsSinceEpoch();
auto sinceLastBackup = now - newRule.lastBackupSeconds;
qCDebug(domain_server).noquote() << " lastBackup:" << formatSecTime(sinceLastBackup) << "ago";
} else {
qCDebug(domain_server) << " lastBackup: NEVER";
}
} else {
qCDebug(domain_server) << "BACKUP RULES: NONE";
_backupRules.push_back(newRule);
}
}
@ -156,8 +135,7 @@ bool DomainContentBackupManager::process() {
if (sinceLastSave > intervalToCheck) {
_lastCheck = now;
if (_isRecovering) {
using Value = std::vector<BackupHandlerPointer>::value_type;
bool isStillRecovering = std::any_of(begin(_backupHandlers), end(_backupHandlers), [](const Value& handler) {
bool isStillRecovering = any_of(begin(_backupHandlers), end(_backupHandlers), [](const BackupHandlerPointer& handler) {
return handler->getRecoveryStatus().first;
});
@ -244,14 +222,13 @@ void DomainContentBackupManager::deleteBackup(MiniPromise::Promise promise, cons
}
QDir backupDir { _backupDirectory };
auto absoluteFilePath { backupDir.filePath(backupName) };
QFile backupFile { absoluteFilePath };
QFile backupFile { backupDir.filePath(backupName) };
auto success = backupFile.remove();
refreshBackupRules();
for (auto& handler : _backupHandlers) {
handler->deleteBackup(absoluteFilePath);
handler->deleteBackup(backupName);
}
promise->resolve({
@ -259,18 +236,18 @@ void DomainContentBackupManager::deleteBackup(MiniPromise::Promise promise, cons
});
}
bool DomainContentBackupManager::recoverFromBackupZip(QuaZip& zip, const QString& backupName) {
bool DomainContentBackupManager::recoverFromBackupZip(const QString& backupName, QuaZip& zip) {
if (!zip.open(QuaZip::Mode::mdUnzip)) {
qWarning() << "Failed to unzip file: " << zip.getZipName();
qWarning() << "Failed to unzip file: " << backupName;
return false;
} else {
_isRecovering = true;
for (auto& handler : _backupHandlers) {
handler->recoverBackup(zip);
handler->recoverBackup(backupName, zip);
}
qDebug() << "Successfully started recovering from " << zip.getZipName();
qDebug() << "Successfully started recovering from " << backupName;
return true;
}
}
@ -297,7 +274,7 @@ void DomainContentBackupManager::recoverFromBackup(MiniPromise::Promise promise,
if (backupFile.open(QIODevice::ReadOnly)) {
QuaZip zip { &backupFile };
success = recoverFromBackupZip(zip, backupName);
success = recoverFromBackupZip(backupName, zip);
backupFile.close();
} else {
@ -324,7 +301,8 @@ void DomainContentBackupManager::recoverFromUploadedBackup(MiniPromise::Promise
QBuffer uploadedBackupBuffer { &uploadedBackup };
QuaZip uploadedZip { &uploadedBackupBuffer };
bool success = recoverFromBackupZip(uploadedZip, MANUAL_BACKUP_PREFIX + "uploaded.zip");
QString backupName = MANUAL_BACKUP_PREFIX + "uploaded.zip";
bool success = recoverFromBackupZip(backupName, uploadedZip);
promise->resolve({
{ "success", success }
@ -360,7 +338,7 @@ std::vector<BackupItemInfo> DomainContentBackupManager::getAllBackups() {
for (auto& handler : _backupHandlers) {
bool handlerIsAvailable { true };
float progress { 0.0f };
std::tie(handlerIsAvailable, progress) = handler->isAvailable(fileInfo.absoluteFilePath());
std::tie(handlerIsAvailable, progress) = handler->isAvailable(fileName);
isAvailable &= handlerIsAvailable;
availabilityProgress += progress / _backupHandlers.size();
}
@ -398,7 +376,7 @@ void DomainContentBackupManager::getAllBackupsAndStatus(MiniPromise::Promise pro
for (auto& handler : _backupHandlers) {
bool handlerIsAvailable { true };
float progress { 0.0f };
std::tie(handlerIsAvailable, progress) = handler->isAvailable(backup.absolutePath);
std::tie(handlerIsAvailable, progress) = handler->isAvailable(backup.name);
isAvailable &= handlerIsAvailable;
availabilityProgress += progress / _backupHandlers.size();
}
@ -484,7 +462,7 @@ void DomainContentBackupManager::load() {
}
for (auto& handler : _backupHandlers) {
handler->loadBackup(zip);
handler->loadBackup(backup.name, zip);
}
zip.close();
@ -528,7 +506,7 @@ void DomainContentBackupManager::backup() {
void DomainContentBackupManager::consolidateBackup(MiniPromise::Promise promise, QString fileName) {
if (QThread::currentThread() != thread()) {
QMetaObject::invokeMethod(this, "consolidateBackup", Q_ARG(MiniPromise::Promise, promise),
Q_ARG(const QString&, fileName));
Q_ARG(QString, fileName));
return;
}
@ -564,7 +542,7 @@ void DomainContentBackupManager::consolidateBackup(MiniPromise::Promise promise,
}
for (auto& handler : _backupHandlers) {
handler->consolidateBackup(zip);
handler->consolidateBackup(fileName, zip);
}
zip.close();
@ -609,7 +587,7 @@ std::pair<bool, QString> DomainContentBackupManager::createBackup(const QString&
}
for (auto& handler : _backupHandlers) {
handler->createBackup(zip);
handler->createBackup(fileName, zip);
}
zip.close();

View file

@ -50,7 +50,7 @@ public:
static const int DEFAULT_PERSIST_INTERVAL;
DomainContentBackupManager(const QString& rootBackupDirectory,
const QJsonObject& settings,
const QVariantList& settings,
int persistInterval = DEFAULT_PERSIST_INTERVAL,
bool debugTimestampNow = false);
@ -82,11 +82,11 @@ protected:
void refreshBackupRules();
bool getMostRecentBackup(const QString& format, QString& mostRecentBackupFileName, QDateTime& mostRecentBackupTime);
int64_t getMostRecentBackupTimeInSecs(const QString& format);
void parseSettings(const QJsonObject& settings);
void parseBackupRules(const QVariantList& backupRules);
std::pair<bool, QString> createBackup(const QString& prefix, const QString& name);
bool recoverFromBackupZip(QuaZip& backupZip, const QString& backupName);
bool recoverFromBackupZip(const QString& backupName, QuaZip& backupZip);
private:
const QString _backupDirectory;

View file

@ -296,15 +296,12 @@ DomainServer::DomainServer(int argc, char* argv[]) :
qCDebug(domain_server) << "Created entities data directory";
}
maybeHandleReplacementEntityFile();
auto contentArchivesGroup = _settingsManager.valueOrDefaultValueForKeyPath(AUTOMATIC_CONTENT_ARCHIVES_GROUP);
auto archivesIntervalObject = QJsonObject();
if (contentArchivesGroup.canConvert<QVariantMap>()) {
archivesIntervalObject = QJsonObject::fromVariantMap(contentArchivesGroup.toMap());
}
_contentManager.reset(new DomainContentBackupManager(getContentBackupDir(), archivesIntervalObject));
static const QString BACKUP_RULES_KEYPATH = AUTOMATIC_CONTENT_ARCHIVES_GROUP + ".backup_rules";
auto backupRulesVariant = _settingsManager.valueOrDefaultValueForKeyPath(BACKUP_RULES_KEYPATH);
_contentManager.reset(new DomainContentBackupManager(getContentBackupDir(), backupRulesVariant.toList()));
connect(_contentManager.get(), &DomainContentBackupManager::started, _contentManager.get(), [this](){
_contentManager->addBackupHandler(BackupHandlerPointer(new EntitiesBackupHandler(getEntitiesFilePath(), getEntitiesReplacementFilePath())));

View file

@ -26,7 +26,7 @@ EntitiesBackupHandler::EntitiesBackupHandler(QString entitiesFilePath, QString e
static const QString ENTITIES_BACKUP_FILENAME = "models.json.gz";
void EntitiesBackupHandler::createBackup(QuaZip& zip) {
void EntitiesBackupHandler::createBackup(const QString& backupName, QuaZip& zip) {
QFile entitiesFile { _entitiesFilePath };
if (entitiesFile.open(QIODevice::ReadOnly)) {
@ -40,7 +40,7 @@ void EntitiesBackupHandler::createBackup(QuaZip& zip) {
}
}
void EntitiesBackupHandler::recoverBackup(QuaZip& zip) {
void EntitiesBackupHandler::recoverBackup(const QString& backupName, QuaZip& zip) {
if (!zip.setCurrentFile(ENTITIES_BACKUP_FILENAME)) {
qWarning() << "Failed to find" << ENTITIES_BACKUP_FILENAME << "while recovering backup";
return;

View file

@ -18,22 +18,22 @@ class EntitiesBackupHandler : public BackupHandlerInterface {
public:
EntitiesBackupHandler(QString entitiesFilePath, QString entitiesReplacementFilePath);
std::pair<bool, float> isAvailable(QString filePath) override { return { true, 1.0f }; }
std::pair<bool, float> isAvailable(const QString& backupName) override { return { true, 1.0f }; }
std::pair<bool, float> getRecoveryStatus() override { return { false, 1.0f }; }
void loadBackup(QuaZip& zip) override {}
void loadBackup(const QString& backupName, QuaZip& zip) override {}
// Create a skeleton backup
void createBackup(QuaZip& zip) override;
void createBackup(const QString& backupName, QuaZip& zip) override;
// Recover from a full backup
void recoverBackup(QuaZip& zip) override;
void recoverBackup(const QString& backupName, QuaZip& zip) override;
// Delete a skeleton backup
void deleteBackup(const QString& absoluteFilePath) override {}
void deleteBackup(const QString& backupName) override {}
// Create a full backup
void consolidateBackup(QuaZip& zip) override {}
void consolidateBackup(const QString& backupName, QuaZip& zip) override {}
private:
QString _entitiesFilePath;