diff --git a/src/Cache.cpp b/src/Cache.cpp
index b12c8679..d67a2e90 100644
--- a/src/Cache.cpp
+++ b/src/Cache.cpp
@@ -41,6 +41,9 @@ static const lmdb::val CACHE_FORMAT_VERSION_KEY("cache_format_version");
constexpr size_t MAX_RESTORED_MESSAGES = 30;
+constexpr auto DB_SIZE = 256UL * 1024UL * 1024UL; // 256 MB
+constexpr auto MAX_DBS = 1024UL;
+
//! Cache databases and their format.
//!
//! Contains UI information for the joined rooms. (i.e name, topic, avatar url etc).
@@ -134,8 +137,8 @@ Cache::setup()
bool isInitial = !QFile::exists(statePath);
env_ = lmdb::env::create();
- env_.set_mapsize(256UL * 1024UL * 1024UL); /* 256 MB */
- env_.set_max_dbs(1024UL);
+ env_.set_mapsize(DB_SIZE);
+ env_.set_max_dbs(MAX_DBS);
if (isInitial) {
nhlog::db()->info("initializing LMDB");
@@ -1786,6 +1789,67 @@ Cache::isNotificationSent(const std::string &event_id)
return res;
}
+std::vector<std::string>
+Cache::getRoomIds(lmdb::txn &txn)
+{
+ auto db = lmdb::dbi::open(txn, ROOMS_DB, MDB_CREATE);
+ auto cursor = lmdb::cursor::open(txn, db);
+
+ std::vector<std::string> rooms;
+
+ std::string room_id, _unused;
+ while (cursor.get(room_id, _unused, MDB_NEXT))
+ rooms.emplace_back(room_id);
+
+ cursor.close();
+
+ return rooms;
+}
+
+void
+Cache::deleteOldMessages()
+{
+ auto txn = lmdb::txn::begin(env_);
+ auto room_ids = getRoomIds(txn);
+
+ for (const auto &id : room_ids) {
+ auto msg_db = getMessagesDb(txn, id);
+
+ std::string ts, event;
+ uint64_t idx = 0;
+
+ const auto db_size = msg_db.size(txn);
+ if (db_size <= 3 * MAX_RESTORED_MESSAGES)
+ continue;
+
+ nhlog::db()->info("[{}] message count: {}", id, db_size);
+
+ auto cursor = lmdb::cursor::open(txn, msg_db);
+ while (cursor.get(ts, event, MDB_NEXT)) {
+ idx += 1;
+
+ if (idx > MAX_RESTORED_MESSAGES)
+ lmdb::cursor_del(cursor);
+ }
+
+ cursor.close();
+
+ nhlog::db()->info("[{}] updated message count: {}", id, msg_db.size(txn));
+ }
+
+ txn.commit();
+}
+
+void
+Cache::deleteOldData() noexcept
+{
+ try {
+ deleteOldMessages();
+ } catch (const lmdb::error &e) {
+ nhlog::db()->error("failed to delete old messages: {}", e.what());
+ }
+}
+
bool
Cache::hasEnoughPowerLevel(const std::vector<mtx::events::EventType> &eventTypes,
const std::string &room_id,
diff --git a/src/Cache.h b/src/Cache.h
index beca502f..c2f8cfc8 100644
--- a/src/Cache.h
+++ b/src/Cache.h
@@ -388,6 +388,12 @@ public:
//! Check if we have sent a desktop notification for the given event id.
bool isNotificationSent(const std::string &event_id);
+ //! Remove old unused data.
+ void deleteOldMessages();
+ void deleteOldData() noexcept;
+ //! Retrieve all saved room ids.
+ std::vector<std::string> getRoomIds(lmdb::txn &txn);
+
//! Mark a room that uses e2e encryption.
void setEncryptedRoom(lmdb::txn &txn, const std::string &room_id);
bool isRoomEncrypted(const std::string &room_id);
diff --git a/src/ChatPage.cpp b/src/ChatPage.cpp
index 9f408a73..250d106d 100644
--- a/src/ChatPage.cpp
+++ b/src/ChatPage.cpp
@@ -1070,6 +1070,11 @@ ChatPage::trySync()
emit syncTopBar(updates);
emit syncRoomlist(updates);
+
+ cache::client()->deleteOldData();
+ } catch (const lmdb::map_full_error &e) {
+ nhlog::db()->error("lmdb is full: {}", e.what());
+ cache::client()->deleteOldData();
} catch (const lmdb::error &e) {
nhlog::db()->error("saving sync response: {}", e.what());
}
|