summary refs log tree commit diff
path: root/src/Cache.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/Cache.cpp')
-rw-r--r--src/Cache.cpp118
1 files changed, 107 insertions, 11 deletions
diff --git a/src/Cache.cpp b/src/Cache.cpp
index 0c692d07..0d879584 100644
--- a/src/Cache.cpp
+++ b/src/Cache.cpp
@@ -2304,6 +2304,11 @@ Cache::saveTimelineMessages(lmdb::txn &txn,
 
                 lmdb::val event_id = event_id_val;
 
+                json orderEntry        = json::object();
+                orderEntry["event_id"] = event_id_val;
+                if (first && !res.prev_batch.empty())
+                        orderEntry["prev_batch"] = res.prev_batch;
+
                 lmdb::val txn_order;
                 if (!txn_id.empty() &&
                     lmdb::dbi_get(txn, evToOrderDb, lmdb::val(txn_id), txn_order)) {
@@ -2317,7 +2322,7 @@ Cache::saveTimelineMessages(lmdb::txn &txn,
                                 lmdb::dbi_del(txn, msg2orderDb, lmdb::val(txn_id));
                         }
 
-                        lmdb::dbi_put(txn, orderDb, txn_order, event_id);
+                        lmdb::dbi_put(txn, orderDb, txn_order, lmdb::val(orderEntry.dump()));
                         lmdb::dbi_put(txn, evToOrderDb, event_id, txn_order);
                         lmdb::dbi_del(txn, evToOrderDb, lmdb::val(txn_id));
 
@@ -2389,10 +2394,6 @@ Cache::saveTimelineMessages(lmdb::txn &txn,
 
                         ++index;
 
-                        json orderEntry        = json::object();
-                        orderEntry["event_id"] = event_id_val;
-                        if (first && !res.prev_batch.empty())
-                                orderEntry["prev_batch"] = res.prev_batch;
                         first = false;
 
                         nhlog::db()->debug("saving '{}'", orderEntry.dump());
@@ -2440,6 +2441,7 @@ Cache::saveOldMessages(const std::string &room_id, const mtx::responses::Message
         auto relationsDb = getRelationsDb(txn, room_id);
 
         auto orderDb     = getEventOrderDb(txn, room_id);
+        auto evToOrderDb = getEventToOrderDb(txn, room_id);
         auto msg2orderDb = getMessageToOrderDb(txn, room_id);
         auto order2msgDb = getOrderToMessageDb(txn, room_id);
 
@@ -2483,6 +2485,7 @@ Cache::saveOldMessages(const std::string &room_id, const mtx::responses::Message
 
                 lmdb::dbi_put(
                   txn, orderDb, lmdb::val(&index, sizeof(index)), lmdb::val(orderEntry.dump()));
+                lmdb::dbi_put(txn, evToOrderDb, event_id, lmdb::val(&index, sizeof(index)));
 
                 // TODO(Nico): Allow blacklisting more event types in UI
                 if (event["type"] != "m.reaction" && event["type"] != "m.dummy") {
@@ -2516,6 +2519,94 @@ Cache::saveOldMessages(const std::string &room_id, const mtx::responses::Message
         return msgIndex;
 }
 
+void
+Cache::clearTimeline(const std::string &room_id)
+{
+        auto txn         = lmdb::txn::begin(env_);
+        auto eventsDb    = getEventsDb(txn, room_id);
+        auto relationsDb = getRelationsDb(txn, room_id);
+
+        auto orderDb     = getEventOrderDb(txn, room_id);
+        auto evToOrderDb = getEventToOrderDb(txn, room_id);
+        auto msg2orderDb = getMessageToOrderDb(txn, room_id);
+        auto order2msgDb = getOrderToMessageDb(txn, room_id);
+
+        lmdb::val indexVal, val;
+        auto cursor = lmdb::cursor::open(txn, orderDb);
+
+        bool start                   = true;
+        bool passed_pagination_token = false;
+        while (cursor.get(indexVal, val, start ? MDB_LAST : MDB_PREV)) {
+                start = false;
+                json obj;
+
+                try {
+                        obj = json::parse(std::string_view(val.data(), val.size()));
+                } catch (std::exception &) {
+                        // workaround bug in the initial db format, where we sometimes didn't store
+                        // json...
+                        obj = {{"event_id", std::string(val.data(), val.size())}};
+                }
+
+                if (passed_pagination_token) {
+                        if (obj.count("event_id") != 0) {
+                                lmdb::val event_id = obj["event_id"].get<std::string>();
+                                lmdb::dbi_del(txn, evToOrderDb, event_id);
+                                lmdb::dbi_del(txn, eventsDb, event_id);
+
+                                lmdb::dbi_del(txn, relationsDb, event_id);
+
+                                lmdb::val order{};
+                                bool exists = lmdb::dbi_get(txn, msg2orderDb, event_id, order);
+                                if (exists) {
+                                        lmdb::dbi_del(txn, order2msgDb, order);
+                                        lmdb::dbi_del(txn, msg2orderDb, event_id);
+                                }
+                        }
+                        lmdb::cursor_del(cursor);
+                } else {
+                        if (obj.count("prev_batch") != 0)
+                                passed_pagination_token = true;
+                }
+        }
+
+        auto msgCursor = lmdb::cursor::open(txn, order2msgDb);
+        start          = true;
+        while (msgCursor.get(indexVal, val, start ? MDB_LAST : MDB_PREV)) {
+                start = false;
+
+                lmdb::val eventId;
+                bool innerStart = true;
+                bool found      = false;
+                while (cursor.get(indexVal, eventId, innerStart ? MDB_LAST : MDB_PREV)) {
+                        innerStart = false;
+
+                        json obj;
+                        try {
+                                obj = json::parse(std::string_view(eventId.data(), eventId.size()));
+                        } catch (std::exception &) {
+                                obj = {{"event_id", std::string(eventId.data(), eventId.size())}};
+                        }
+
+                        if (obj["event_id"] == std::string(val.data(), val.size())) {
+                                found = true;
+                                break;
+                        }
+                }
+
+                if (!found)
+                        break;
+        }
+
+        do {
+                lmdb::cursor_del(msgCursor);
+        } while (msgCursor.get(indexVal, val, MDB_PREV));
+
+        cursor.close();
+        msgCursor.close();
+        txn.commit();
+}
+
 mtx::responses::Notifications
 Cache::getTimelineMentionsForRoom(lmdb::txn &txn, const std::string &room_id)
 {
@@ -2654,11 +2745,13 @@ Cache::deleteOldMessages()
         auto room_ids = getRoomIds(txn);
 
         for (const auto &room_id : room_ids) {
-                auto orderDb  = getEventOrderDb(txn, room_id);
-                auto o2m      = getOrderToMessageDb(txn, room_id);
-                auto m2o      = getMessageToOrderDb(txn, room_id);
-                auto eventsDb = getEventsDb(txn, room_id);
-                auto cursor   = lmdb::cursor::open(txn, orderDb);
+                auto orderDb     = getEventOrderDb(txn, room_id);
+                auto evToOrderDb = getEventToOrderDb(txn, room_id);
+                auto o2m         = getOrderToMessageDb(txn, room_id);
+                auto m2o         = getMessageToOrderDb(txn, room_id);
+                auto eventsDb    = getEventsDb(txn, room_id);
+                auto relationsDb = getRelationsDb(txn, room_id);
+                auto cursor      = lmdb::cursor::open(txn, orderDb);
 
                 uint64_t first, last;
                 if (cursor.get(indexVal, val, MDB_LAST)) {
@@ -2678,14 +2771,17 @@ Cache::deleteOldMessages()
 
                 bool start = true;
                 while (cursor.get(indexVal, val, start ? MDB_FIRST : MDB_NEXT) &&
-                       message_count-- < MAX_RESTORED_MESSAGES) {
+                       message_count-- > MAX_RESTORED_MESSAGES) {
                         start    = false;
                         auto obj = json::parse(std::string_view(val.data(), val.size()));
 
                         if (obj.count("event_id") != 0) {
                                 lmdb::val event_id = obj["event_id"].get<std::string>();
+                                lmdb::dbi_del(txn, evToOrderDb, event_id);
                                 lmdb::dbi_del(txn, eventsDb, event_id);
 
+                                lmdb::dbi_del(txn, relationsDb, event_id);
+
                                 lmdb::val order{};
                                 bool exists = lmdb::dbi_get(txn, m2o, event_id, order);
                                 if (exists) {