From 65e87c6c70fc1e5af8f0c3fb762ca13e6aa6a8e4 Mon Sep 17 00:00:00 2001 From: Alexander Tkachev Date: Sat, 18 Jun 2016 19:35:57 +0600 Subject: CLOUD: Update save's timestamp on rewrite This commit moves save/load timestamps static methods into DefaultSaveFileManager and fixes a few related bugs. --- backends/saves/default/default-saves.cpp | 109 +++++++++++++++++++++++++++++++ backends/saves/default/default-saves.h | 14 +++- 2 files changed, 122 insertions(+), 1 deletion(-) (limited to 'backends/saves') diff --git a/backends/saves/default/default-saves.cpp b/backends/saves/default/default-saves.cpp index e20ce31d18..54dc1c2966 100644 --- a/backends/saves/default/default-saves.cpp +++ b/backends/saves/default/default-saves.cpp @@ -29,6 +29,7 @@ #ifdef USE_CLOUD #include "backends/cloud/cloudmanager.h" +#include "common/file.h" #endif #if !defined(DISABLE_DEFAULT_SAVEFILEMANAGER) @@ -46,6 +47,10 @@ #include // for removeSavefile() #endif +#ifdef USE_CLOUD +const char *DefaultSaveFileManager::TIMESTAMPS_FILENAME = "timestamps"; +#endif + DefaultSaveFileManager::DefaultSaveFileManager() { } @@ -142,6 +147,13 @@ Common::OutSaveFile *DefaultSaveFileManager::openForSaving(const Common::String } } +#ifdef USE_CLOUD + // Update file's timestamp + Common::HashMap timestamps = loadTimestamps(); + timestamps[filename] = INVALID_TIMESTAMP; + saveTimestamps(timestamps); +#endif + // Obtain node. SaveFileCache::const_iterator file = _saveFileCache.find(filename); Common::FSNode fileNode; @@ -266,4 +278,101 @@ void DefaultSaveFileManager::assureCached(const Common::String &savePathName) { _cachedDirectory = savePathName; } +#ifdef USE_CLOUD + +Common::HashMap DefaultSaveFileManager::loadTimestamps() { + Common::HashMap timestamps; + + //refresh the files list + Common::Array files; + g_system->getSavefileManager()->updateSavefilesList(files); + + //start with listing all the files in saves/ directory and setting invalid timestamp to them + Common::StringArray localFiles = g_system->getSavefileManager()->listSavefiles("*"); + for (uint32 i = 0; i < localFiles.size(); ++i) + timestamps[localFiles[i]] = INVALID_TIMESTAMP; + + //now actually load timestamps from file + Common::InSaveFile *file = g_system->getSavefileManager()->openRawFile(TIMESTAMPS_FILENAME); + if (!file) { + warning("DefaultSaveFileManager: failed to open '%s' file to load timestamps", TIMESTAMPS_FILENAME); + return timestamps; + } + + while (!file->eos()) { + //read filename into buffer (reading until the first ' ') + Common::String buffer; + while (!file->eos()) { + byte b = file->readByte(); + if (b == ' ') break; + buffer += (char)b; + } + + //read timestamp info buffer (reading until ' ' or some line ending char) + Common::String filename = buffer; + while (true) { + bool lineEnded = false; + buffer = ""; + while (!file->eos()) { + byte b = file->readByte(); + if (b == ' ' || b == '\n' || b == '\r') { + lineEnded = (b == '\n'); + break; + } + buffer += (char)b; + } + + if (buffer == "" && file->eos()) break; + if (!lineEnded) filename += " " + buffer; + else break; + } + + //parse timestamp + uint32 timestamp = buffer.asUint64(); + if (buffer == "" || timestamp == 0) break; + timestamps[filename] = timestamp; + } + + delete file; + return timestamps; +} + +void DefaultSaveFileManager::saveTimestamps(Common::HashMap ×tamps) { + Common::DumpFile f; + Common::String filename = concatWithSavesPath(TIMESTAMPS_FILENAME); + if (!f.open(filename, true)) { + warning("DefaultSaveFileManager: failed to open '%s' file to save timestamps", filename.c_str()); + return; + } + + for (Common::HashMap::iterator i = timestamps.begin(); i != timestamps.end(); ++i) { + Common::String data = i->_key + Common::String::format(" %u\n", i->_value); + if (f.write(data.c_str(), data.size()) != data.size()) { + warning("DefaultSaveFileManager: failed to write timestamps data into '%s'", filename.c_str()); + return; + } + } + + f.flush(); + f.finalize(); + f.close(); +} + +Common::String DefaultSaveFileManager::concatWithSavesPath(Common::String name) { + Common::String path = ConfMan.get("savepath"); + if (path.size() > 0 && (path.lastChar() == '/' || path.lastChar() == '\\')) + return path + name; + + //simple heuristic to determine which path separator to use + int backslashes = 0; + for (uint32 i = 0; i < path.size(); ++i) + if (path[i] == '/') --backslashes; + else if (path[i] == '\\') ++backslashes; + + if (backslashes) return path + '\\' + name; + return path + '/' + name; +} + +#endif // ifdef USE_CLOUD + #endif // !defined(DISABLE_DEFAULT_SAVEFILEMANAGER) diff --git a/backends/saves/default/default-saves.h b/backends/saves/default/default-saves.h index af30cf45e9..e9edfb1f36 100644 --- a/backends/saves/default/default-saves.h +++ b/backends/saves/default/default-saves.h @@ -27,7 +27,8 @@ #include "common/savefile.h" #include "common/str.h" #include "common/fs.h" -#include "common/hashmap.h" +#include "common/hash-str.h" +#include /** * Provides a default savefile manager implementation for common platforms. @@ -44,6 +45,17 @@ public: virtual Common::OutSaveFile *openForSaving(const Common::String &filename, bool compress = true); virtual bool removeSavefile(const Common::String &filename); +#ifdef USE_CLOUD + + static const uint32 INVALID_TIMESTAMP = UINT_MAX; + static const char *TIMESTAMPS_FILENAME; + + static Common::HashMap loadTimestamps(); + static void saveTimestamps(Common::HashMap ×tamps); + static Common::String concatWithSavesPath(Common::String name); + +#endif + protected: /** * Get the path to the savegame directory. -- cgit v1.2.3