summary refs log tree commit diff
path: root/src
diff options
context:
space:
mode:
authorNicolas Werner <nicolas.werner@hotmail.de>2020-05-02 16:44:50 +0200
committerNicolas Werner <nicolas.werner@hotmail.de>2020-05-02 16:44:50 +0200
commitdad2de7ba2323ff0f5c229968ec95f05b10b6f45 (patch)
tree598406032493e10456a440ceb16a3586267cf550 /src
parentMerge pull request #184 from shocklateboy92/features/backlog-progress (diff)
downloadnheko-dad2de7ba2323ff0f5c229968ec95f05b10b6f45.tar.xz
Add support for db migrations
Diffstat (limited to 'src')
-rw-r--r--src/Cache.cpp36
-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, 71 insertions, 26 deletions
diff --git a/src/Cache.cpp b/src/Cache.cpp
index eb5c93aa..1a097cff 100644
--- a/src/Cache.cpp
+++ b/src/Cache.cpp
@@ -665,8 +665,15 @@ Cache::deleteData()
         }
 }
 
+//! migrates db to the current format
 bool
-Cache::isFormatValid()
+Cache::runMigrations()
+{
+        return true;
+}
+
+cache::CacheVersion
+Cache::formatVersion()
 {
         auto txn = lmdb::txn::begin(env_, nullptr, MDB_RDONLY);
 
@@ -676,18 +683,16 @@ Cache::isFormatValid()
         txn.commit();
 
         if (!res)
-                return false;
+                return cache::CacheVersion::Older;
 
         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;
-        }
-
-        return true;
+        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
@@ -2468,10 +2473,17 @@ setup()
 }
 
 bool
-isFormatValid()
+runMigrations()
+{
+        return instance_->runMigrations();
+}
+
+cache::CacheVersion
+formatVersion()
 {
-        return instance_->isFormatValid();
+        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) {