From 6abad768a6728a37706348cadbc147e7975666e5 Mon Sep 17 00:00:00 2001 From: Kae <80987908+Novaenia@users.noreply.github.com> Date: Wed, 2 Aug 2023 22:56:36 +1000 Subject: [PATCH] Backups are now placed in their own directory --- source/core/StarFile.cpp | 14 ++++++++---- source/core/StarFile.hpp | 1 + source/game/StarPlayerStorage.cpp | 36 ++++++++++++++++++++----------- source/game/StarPlayerStorage.hpp | 1 + 4 files changed, 36 insertions(+), 16 deletions(-) diff --git a/source/core/StarFile.cpp b/source/core/StarFile.cpp index ec09ff7..873a10e 100644 --- a/source/core/StarFile.cpp +++ b/source/core/StarFile.cpp @@ -102,16 +102,22 @@ void File::overwriteFileWithRename(String const& data, String const& filename, S overwriteFileWithRename(data.utf8Ptr(), data.utf8Size(), filename, newSuffix); } -void File::backupFileInSequence(String const& targetFile, unsigned maximumBackups, String const& backupExtensionPrefix) { +void File::backupFileInSequence(String const& initialFile, String const& targetFile, unsigned maximumBackups, String const& backupExtensionPrefix) { for (unsigned i = maximumBackups; i > 0; --i) { - String curExtension = i == 1 ? "" : strf("{}{}", backupExtensionPrefix, i - 1); + bool initial = i == 1; + String const& sourceFile = initial ? initialFile : targetFile; + String curExtension = initial ? "" : strf("{}{}", backupExtensionPrefix, i - 1); String nextExtension = strf("{}{}", backupExtensionPrefix, i); - if (File::isFile(targetFile + curExtension)) - File::copy(targetFile + curExtension, targetFile + nextExtension); + if (File::isFile(sourceFile + curExtension)) + File::copy(sourceFile + curExtension, targetFile + nextExtension); } } +void File::backupFileInSequence(String const& targetFile, unsigned maximumBackups, String const& backupExtensionPrefix) { + backupFileInSequence(targetFile, targetFile, maximumBackups, backupExtensionPrefix); +} + File::File() : IODevice(IOMode::Closed) { m_file = 0; diff --git a/source/core/StarFile.hpp b/source/core/StarFile.hpp index c75dd4c..517c148 100644 --- a/source/core/StarFile.hpp +++ b/source/core/StarFile.hpp @@ -91,6 +91,7 @@ public: static void overwriteFileWithRename(ByteArray const& data, String const& filename, String const& newSuffix = ".new"); static void overwriteFileWithRename(String const& data, String const& filename, String const& newSuffix = ".new"); + static void backupFileInSequence(String const& initialFile, String const& targetFile, unsigned maximumBackups, String const& backupExtensionPrefix = "."); static void backupFileInSequence(String const& targetFile, unsigned maximumBackups, String const& backupExtensionPrefix = "."); static FilePtr open(String const& filename, IOMode mode); diff --git a/source/game/StarPlayerStorage.cpp b/source/game/StarPlayerStorage.cpp index bdff700..558d12b 100644 --- a/source/game/StarPlayerStorage.cpp +++ b/source/game/StarPlayerStorage.cpp @@ -14,7 +14,7 @@ namespace Star { PlayerStorage::PlayerStorage(String const& storageDir) { m_storageDirectory = storageDir; - + m_backupDirectory = File::relativeTo(m_storageDirectory, File::convertDirSeparators("backup")); if (!File::isDirectory(m_storageDirectory)) { Logger::info("Creating player storage directory"); File::makeDirectory(m_storageDirectory); @@ -183,23 +183,25 @@ void PlayerStorage::deletePlayer(Uuid const& uuid) { m_savedPlayersCache.remove(uuid); - auto filePrefix = File::relativeTo(m_storageDirectory, uuid.hex()); + auto uuidHex = uuid.hex(); + auto storagePrefix = File::relativeTo(m_storageDirectory, uuidHex); + auto backupPrefix = File::relativeTo(m_backupDirectory, uuidHex); - auto removeIfExists = [&filePrefix](String suffix) { - if (File::exists(filePrefix + suffix)) { - File::remove(filePrefix + suffix); + auto removeIfExists = [](String const& prefix, String const& suffix) { + if (File::exists(prefix + suffix)) { + File::remove(prefix + suffix); } }; - removeIfExists(".player"); - removeIfExists(".shipworld"); + removeIfExists(storagePrefix, ".player"); + removeIfExists(storagePrefix, ".shipworld"); auto configuration = Root::singleton().configuration(); unsigned playerBackupFileCount = configuration->get("playerBackupFileCount").toUInt(); for (unsigned i = 1; i <= playerBackupFileCount; ++i) { - removeIfExists(strf(".player.bak{}", i)); - removeIfExists(strf(".shipworld.bak{}", i)); + removeIfExists(backupPrefix, strf(".player.bak{}", i)); + removeIfExists(backupPrefix, strf(".shipworld.bak{}", i)); } } @@ -243,9 +245,19 @@ void PlayerStorage::backupCycle(Uuid const& uuid) { unsigned playerBackupFileCount = configuration->get("playerBackupFileCount").toUInt(); auto& fileName = uuidFileName(uuid); - File::backupFileInSequence(File::relativeTo(m_storageDirectory, strf("{}.player", fileName)), playerBackupFileCount, ".bak"); - File::backupFileInSequence(File::relativeTo(m_storageDirectory, strf("{}.shipworld", fileName)), playerBackupFileCount, ".bak"); - File::backupFileInSequence(File::relativeTo(m_storageDirectory, strf("{}.metadata", fileName)), playerBackupFileCount, ".bak"); + auto path = [&](String const& dir, String const& extension) { + return File::relativeTo(dir, strf("{}.{}", fileName, extension)); + }; + + if (!File::isDirectory(m_backupDirectory)) { + Logger::info("Creating player backup directory"); + File::makeDirectory(m_backupDirectory); + return; + } + + File::backupFileInSequence(path(m_storageDirectory, "player"), path(m_backupDirectory, "player"), playerBackupFileCount, ".bak"); + File::backupFileInSequence(path(m_storageDirectory, "shipworld"), path(m_backupDirectory, "shipworld"), playerBackupFileCount, ".bak"); + File::backupFileInSequence(path(m_storageDirectory, "metadata"), path(m_backupDirectory, "metadata"), playerBackupFileCount, ".bak"); } void PlayerStorage::setMetadata(String key, Json value) { diff --git a/source/game/StarPlayerStorage.hpp b/source/game/StarPlayerStorage.hpp index 519ef86..807aa7f 100644 --- a/source/game/StarPlayerStorage.hpp +++ b/source/game/StarPlayerStorage.hpp @@ -49,6 +49,7 @@ private: mutable RecursiveMutex m_mutex; String m_storageDirectory; + String m_backupDirectory; OrderedHashMap m_savedPlayersCache; BiMap m_playerFileNames; JsonObject m_metadata;