diff --git a/bridgeinfodb.cpp b/bridgeinfodb.cpp index 4f90bdf..a06482d 100644 --- a/bridgeinfodb.cpp +++ b/bridgeinfodb.cpp @@ -36,9 +36,10 @@ void BridgeInfoDb::openWrite() void BridgeInfoDb::openRead() { - PersistenceFile::openRead(); + const std::string current_magic_string(MAGIC_STRING_BRIDGEINFO_FILE_V1); + PersistenceFile::openRead(current_magic_string); - if (detectedVersionString == MAGIC_STRING_BRIDGEINFO_FILE_V1) + if (detectedVersionString == current_magic_string) readVersion = ReadVersion::v1; else throw std::runtime_error("Unknown file version."); diff --git a/persistencefile.cpp b/persistencefile.cpp index 50dc8d8..b1c3a8c 100644 --- a/persistencefile.cpp +++ b/persistencefile.cpp @@ -19,6 +19,7 @@ See LICENSE for license details. #include #include #include +#include #include "utils.h" #include "logger.h" @@ -321,7 +322,7 @@ void PersistenceFile::openWrite(const std::string &versionString) writeCheck(buf.data(), 1, HASH_SIZE, f); } -void PersistenceFile::openRead() +void PersistenceFile::openRead(const std::string &expected_version_string) { if (openMode != FileMode::unknown) throw std::runtime_error("File is already open."); @@ -339,6 +340,38 @@ void PersistenceFile::openRead() readCheck(buf.data(), 1, MAGIC_STRING_LENGH, f); detectedVersionString = std::string(buf.data(), strlen(buf.data())); + // In case people want to downgrade, the old file is still there. + if (detectedVersionString != expected_version_string) + { + const std::string copy_file_path = filePath + "." + detectedVersionString; + + try + { + const size_t file_size = getFileSize(filePath); + const size_t free_space = getFreeSpace(filePath); + + if (free_space > file_size * 3) + { + logger->log(LOG_NOTICE) << "File version change detected. Copying '" << filePath << "' to '" + << copy_file_path << "' to support downgrading FlashMQ."; + std::ifstream src(filePath, std::ios::binary); + std::ofstream dst(copy_file_path, std::ios::binary); + src.exceptions(std::ifstream::failbit | std::ifstream::badbit); + dst.exceptions(std::ifstream::failbit | std::ifstream::badbit); + dst << src.rdbuf(); + } + else + { + logger->log(LOG_NOTICE) << "File version change detected, but not copying '" << filePath << "' to '" + << copy_file_path << "' because disk space is running low."; + } + } + catch (std::exception &ex) + { + logger->log(LOG_ERROR) << "Backing up to '" << copy_file_path << "' failed."; + } + } + fseek(f, TOTAL_HEADER_SIZE, SEEK_SET); } diff --git a/persistencefile.h b/persistencefile.h index 46b8cd6..faf3014 100644 --- a/persistencefile.h +++ b/persistencefile.h @@ -83,7 +83,7 @@ class PersistenceFile virtual ~PersistenceFile(); void openWrite(const std::string &versionString); - void openRead(); + void openRead(const std::string &expected_version_string); void closeFile(); const std::string &getFilePath() const; diff --git a/retainedmessagesdb.cpp b/retainedmessagesdb.cpp index 46babd7..051f0bb 100644 --- a/retainedmessagesdb.cpp +++ b/retainedmessagesdb.cpp @@ -38,7 +38,9 @@ void RetainedMessagesDB::openWrite() void RetainedMessagesDB::openRead() { - PersistenceFile::openRead(); + const std::string current_magic_string(MAGIC_STRING_V4); + + PersistenceFile::openRead(current_magic_string); if (detectedVersionString == MAGIC_STRING_V1) readVersion = ReadVersion::v1; @@ -46,7 +48,7 @@ void RetainedMessagesDB::openRead() readVersion = ReadVersion::v2; else if (detectedVersionString == MAGIC_STRING_V3) readVersion = ReadVersion::v3; - else if (detectedVersionString == MAGIC_STRING_V4) + else if (detectedVersionString == current_magic_string) readVersion = ReadVersion::v4; else throw std::runtime_error("Unknown file version."); diff --git a/sessionsandsubscriptionsdb.cpp b/sessionsandsubscriptionsdb.cpp index 74d89fb..d224460 100644 --- a/sessionsandsubscriptionsdb.cpp +++ b/sessionsandsubscriptionsdb.cpp @@ -84,7 +84,9 @@ void SessionsAndSubscriptionsDB::openWrite() void SessionsAndSubscriptionsDB::openRead() { - PersistenceFile::openRead(); + const std::string current_magic_string(MAGIC_STRING_SESSION_FILE_V6); + + PersistenceFile::openRead(current_magic_string); if (detectedVersionString == MAGIC_STRING_SESSION_FILE_V1) readVersion = ReadVersion::v1; @@ -96,7 +98,7 @@ void SessionsAndSubscriptionsDB::openRead() readVersion = ReadVersion::v4; else if (detectedVersionString == MAGIC_STRING_SESSION_FILE_V5) readVersion = ReadVersion::v5; - else if (detectedVersionString == MAGIC_STRING_SESSION_FILE_V6) + else if (detectedVersionString == current_magic_string) readVersion = ReadVersion::v6; else throw std::runtime_error("Unknown file version.");