diff --git a/include/Cache.h b/include/Cache.h index c16654d0..031c8b16 100644 --- a/include/Cache.h +++ b/include/Cache.h @@ -39,6 +39,9 @@ public: void removeRoom(const QString &roomid); void setup(); + bool isFormatValid(); + void setCurrentFormat(); + private: void setNextBatchToken(lmdb::txn &txn, const QString &token); void insertRoomState(lmdb::txn &txn, const QString &roomid, const RoomState &state); diff --git a/src/Cache.cc b/src/Cache.cc index 087dd4bc..7d044e8f 100644 --- a/src/Cache.cc +++ b/src/Cache.cc @@ -24,8 +24,10 @@ #include "Cache.h" #include "RoomState.h" +static const std::string CURRENT_CACHE_FORMAT_VERSION("2017.12.10"); + static const lmdb::val NEXT_BATCH_KEY("next_batch"); -static const lmdb::val transactionID("transaction_id"); +static const lmdb::val CACHE_FORMAT_VERSION_KEY("cache_format_version"); Cache::Cache(const QString &userId) : env_{nullptr} @@ -270,3 +272,41 @@ Cache::deleteData() if (!cacheDirectory_.isEmpty()) QDir(cacheDirectory_).removeRecursively(); } + +bool +Cache::isFormatValid() +{ + auto txn = lmdb::txn::begin(env_, nullptr, MDB_RDONLY); + + lmdb::val current_version; + bool res = lmdb::dbi_get(txn, stateDb_, CACHE_FORMAT_VERSION_KEY, current_version); + + txn.commit(); + + if (!res) + return false; + + std::string stored_version(current_version.data(), current_version.size()); + + if (stored_version != CURRENT_CACHE_FORMAT_VERSION) { + qWarning() << "Stored format version" << QString::fromStdString(stored_version); + qWarning() << "There are breaking changes in the cache format."; + return false; + } + + return true; +} + +void +Cache::setCurrentFormat() +{ + auto txn = lmdb::txn::begin(env_); + + lmdb::dbi_put( + txn, + stateDb_, + CACHE_FORMAT_VERSION_KEY, + lmdb::val(CURRENT_CACHE_FORMAT_VERSION.data(), CURRENT_CACHE_FORMAT_VERSION.size())); + + txn.commit(); +} diff --git a/src/ChatPage.cc b/src/ChatPage.cc index ab5aa263..100c18f4 100644 --- a/src/ChatPage.cc +++ b/src/ChatPage.cc @@ -334,6 +334,12 @@ ChatPage::bootstrap(QString userid, QString homeserver, QString token) try { cache_->setup(); + if (!cache_->isFormatValid()) { + cache_->deleteData(); + cache_->setup(); + cache_->setCurrentFormat(); + } + if (cache_->isInitialized()) { loadStateFromCache(); return;