summary refs log tree commit diff
path: root/src
diff options
context:
space:
mode:
authorDeepBlueV7.X <nicolas.werner@hotmail.de>2020-05-03 01:56:06 +0200
committerGitHub <noreply@github.com>2020-05-03 01:56:06 +0200
commitccd55c70df1ad57c848e06944d8eef49dc85cdec (patch)
treea9bfae6a1cd69ddde2c076e04b181c2adc1062fd /src
parentMerge pull request #184 from shocklateboy92/features/backlog-progress (diff)
parentAdd delete pending_receipts migration (diff)
downloadnheko-ccd55c70df1ad57c848e06944d8eef49dc85cdec.tar.xz
Merge pull request #189 from Nheko-Reborn/db-migrations
Db migrations
Diffstat (limited to 'src')
-rw-r--r--src/Cache.cpp71
-rw-r--r--src/Cache.h9
-rw-r--r--src/CacheStructs.h9
-rw-r--r--src/Cache_p.h3
-rw-r--r--src/ChatPage.cpp40
5 files changed, 109 insertions, 23 deletions
diff --git a/src/Cache.cpp b/src/Cache.cpp

index eb5c93aa..1ae7a846 100644 --- a/src/Cache.cpp +++ b/src/Cache.cpp
@@ -36,7 +36,7 @@ //! Should be changed when a breaking change occurs in the cache format. //! This will reset client's data. -static const std::string CURRENT_CACHE_FORMAT_VERSION("2018.09.21"); +static const std::string CURRENT_CACHE_FORMAT_VERSION("2020.05.01"); static const std::string SECRET("secret"); static lmdb::val NEXT_BATCH_KEY("next_batch"); @@ -665,8 +665,9 @@ Cache::deleteData() } } +//! migrates db to the current format bool -Cache::isFormatValid() +Cache::runMigrations() { auto txn = lmdb::txn::begin(env_, nullptr, MDB_RDONLY); @@ -680,16 +681,61 @@ Cache::isFormatValid() std::string stored_version(current_version.data(), current_version.size()); - if (stored_version != CURRENT_CACHE_FORMAT_VERSION) { - nhlog::db()->warn("breaking changes in the cache format. stored: {}, current: {}", - stored_version, - CURRENT_CACHE_FORMAT_VERSION); - return false; + std::vector<std::pair<std::string, std::function<bool()>>> migrations{ + {"2020.05.01", + [this]() { + try { + auto txn = lmdb::txn::begin(env_, nullptr); + auto pending_receipts = + lmdb::dbi::open(txn, "pending_receipts", MDB_CREATE); + lmdb::dbi_drop(txn, pending_receipts, true); + txn.commit(); + } catch (const lmdb::error &) { + nhlog::db()->critical( + "Failed to delete pending_receipts database in migration!"); + return false; + } + + nhlog::db()->info("Successfully deleted pending receipts database."); + return true; + }}, + }; + + for (const auto &[target_version, migration] : migrations) { + if (target_version > stored_version) + if (!migration()) { + nhlog::db()->critical("migration failure!"); + return false; + } } + setCurrentFormat(); return true; } +cache::CacheVersion +Cache::formatVersion() +{ + auto txn = lmdb::txn::begin(env_, nullptr, MDB_RDONLY); + + lmdb::val current_version; + bool res = lmdb::dbi_get(txn, syncStateDb_, CACHE_FORMAT_VERSION_KEY, current_version); + + txn.commit(); + + if (!res) + return cache::CacheVersion::Older; + + std::string stored_version(current_version.data(), current_version.size()); + + if (stored_version < CURRENT_CACHE_FORMAT_VERSION) + return cache::CacheVersion::Older; + else if (stored_version > CURRENT_CACHE_FORMAT_VERSION) + return cache::CacheVersion::Older; + else + return cache::CacheVersion::Current; +} + void Cache::setCurrentFormat() { @@ -2468,10 +2514,17 @@ setup() } bool -isFormatValid() +runMigrations() { - return instance_->isFormatValid(); + return instance_->runMigrations(); } + +cache::CacheVersion +formatVersion() +{ + return instance_->formatVersion(); +} + void setCurrentFormat() { diff --git a/src/Cache.h b/src/Cache.h
index 99c63550..12465c9d 100644 --- a/src/Cache.h +++ b/src/Cache.h
@@ -111,10 +111,15 @@ removeRoom(const QString &roomid); void setup(); -bool -isFormatValid(); +//! returns if the format is current, older or newer +cache::CacheVersion +formatVersion(); +//! set the format version to the current version void setCurrentFormat(); +//! migrates db to the current format +bool +runMigrations(); std::map<QString, mtx::responses::Timeline> roomMessages(); diff --git a/src/CacheStructs.h b/src/CacheStructs.h
index ab7bbc71..ef08cfcb 100644 --- a/src/CacheStructs.h +++ b/src/CacheStructs.h
@@ -8,6 +8,15 @@ #include <mtx/events/join_rules.hpp> +namespace cache { +enum class CacheVersion : int +{ + Older = -1, + Current = 0, + Newer = 1, +}; +} + struct RoomMember { QString user_id; diff --git a/src/Cache_p.h b/src/Cache_p.h
index 982099ea..0d66a608 100644 --- a/src/Cache_p.h +++ b/src/Cache_p.h
@@ -102,8 +102,9 @@ public: void removeRoom(const std::string &roomid); void setup(); - bool isFormatValid(); + cache::CacheVersion formatVersion(); void setCurrentFormat(); + bool runMigrations(); std::map<QString, mtx::responses::Timeline> roomMessages(); diff --git a/src/ChatPage.cpp b/src/ChatPage.cpp
index 981e6b80..689e9ca4 100644 --- a/src/ChatPage.cpp +++ b/src/ChatPage.cpp
@@ -17,6 +17,7 @@ #include <QApplication> #include <QImageReader> +#include <QMessageBox> #include <QSettings> #include <QShortcut> #include <QtConcurrent> @@ -642,20 +643,37 @@ ChatPage::bootstrap(QString userid, QString homeserver, QString token) &NotificationsManager::removeNotification); const bool isInitialized = cache::isInitialized(); - const bool isValid = cache::isFormatValid(); + const auto cacheVersion = cache::formatVersion(); if (!isInitialized) { cache::setCurrentFormat(); - } else if (isInitialized && !isValid) { - // TODO: Deleting session data but keep using the - // same device doesn't work. - cache::deleteData(); - - cache::init(userid); - cache::setCurrentFormat(); - } else if (isInitialized) { - loadStateFromCache(); - return; + } else { + if (cacheVersion == cache::CacheVersion::Current) { + loadStateFromCache(); + return; + } else if (cacheVersion == cache::CacheVersion::Older) { + if (!cache::runMigrations()) { + QMessageBox::critical( + this, + tr("Cache migration failed!"), + tr("Migrating the cache to the current version failed. " + "This can have different reasons. Please open an " + "issue and try to use an older version in the mean " + "time. Alternatively you can try deleting the cache " + "manually")); + QCoreApplication::quit(); + } + loadStateFromCache(); + return; + } else if (cacheVersion == cache::CacheVersion::Newer) { + QMessageBox::critical( + this, + tr("Incompatible cache version"), + tr("The cache on your disk is newer than this version of Nheko " + "supports. Please update or clear your cache.")); + QCoreApplication::quit(); + return; + } } } catch (const lmdb::error &e) {