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.cpp133
1 files changed, 123 insertions, 10 deletions
diff --git a/src/Cache.cpp b/src/Cache.cpp

index 852d45ec..d2c790dd 100644 --- a/src/Cache.cpp +++ b/src/Cache.cpp
@@ -1272,7 +1272,10 @@ Cache::getTimelineMessages(lmdb::txn &txn, const std::string &room_id, int64_t i int counter = 0; bool ret; - while ((ret = cursor.get(indexVal, event_id, forward ? MDB_NEXT : MDB_LAST)) && + while ((ret = cursor.get(indexVal, + event_id, + counter == 0 ? (forward ? MDB_FIRST : MDB_LAST) + : (forward ? MDB_NEXT : MDB_PREV))) && counter++ < BATCH_SIZE) { lmdb::val event; bool success = lmdb::dbi_get(txn, eventsDb, event_id, event); @@ -1280,8 +1283,13 @@ Cache::getTimelineMessages(lmdb::txn &txn, const std::string &room_id, int64_t i continue; mtx::events::collections::TimelineEvent te; - mtx::events::collections::from_json( - json::parse(std::string_view(event.data(), event.size())), te); + try { + mtx::events::collections::from_json( + json::parse(std::string_view(event.data(), event.size())), te); + } catch (std::exception &e) { + nhlog::db()->error("Failed to parse message from cache {}", e.what()); + continue; + } messages.timeline.events.push_back(std::move(te.data)); } @@ -1306,8 +1314,13 @@ Cache::getEvent(const std::string &room_id, const std::string &event_id) return {}; mtx::events::collections::TimelineEvent te; - mtx::events::collections::from_json( - json::parse(std::string_view(event.data(), event.size())), te); + try { + mtx::events::collections::from_json( + json::parse(std::string_view(event.data(), event.size())), te); + } catch (std::exception &e) { + nhlog::db()->error("Failed to parse message from cache {}", e.what()); + return std::nullopt; + } return te; } @@ -1364,6 +1377,61 @@ Cache::getLastEventId(lmdb::txn &txn, const std::string &room_id) return std::string(val.data(), val.size()); } +std::optional<Cache::TimelineRange> +Cache::getTimelineRange(const std::string &room_id) +{ + auto txn = lmdb::txn::begin(env_, nullptr, MDB_RDONLY); + auto orderDb = getOrderToMessageDb(txn, room_id); + + lmdb::val indexVal, val; + + auto cursor = lmdb::cursor::open(txn, orderDb); + if (!cursor.get(indexVal, val, MDB_LAST)) { + return {}; + } + + TimelineRange range{}; + range.last = *indexVal.data<int64_t>(); + + if (!cursor.get(indexVal, val, MDB_FIRST)) { + return {}; + } + range.first = *indexVal.data<int64_t>(); + + return range; +} +std::optional<int64_t> +Cache::getTimelineIndex(const std::string &room_id, std::string_view event_id) +{ + auto txn = lmdb::txn::begin(env_, nullptr, MDB_RDONLY); + auto orderDb = getMessageToOrderDb(txn, room_id); + + lmdb::val indexVal{event_id.data(), event_id.size()}, val; + + bool success = lmdb::dbi_get(txn, orderDb, indexVal, val); + if (!success) { + return {}; + } + + return *val.data<int64_t>(); +} + +std::optional<std::string> +Cache::getTimelineEventId(const std::string &room_id, int64_t index) +{ + auto txn = lmdb::txn::begin(env_, nullptr, MDB_RDONLY); + auto orderDb = getOrderToMessageDb(txn, room_id); + + lmdb::val indexVal{&index, sizeof(index)}, val; + + bool success = lmdb::dbi_get(txn, orderDb, indexVal, val); + if (!success) { + return {}; + } + + return std::string(val.data(), val.size()); +} + DescInfo Cache::getLastMessageInfo(lmdb::txn &txn, const std::string &room_id) { @@ -1379,8 +1447,10 @@ Cache::getLastMessageInfo(lmdb::txn &txn, const std::string &room_id) lmdb::val indexVal, event_id; auto cursor = lmdb::cursor::open(txn, orderDb); - cursor.get(indexVal, event_id, MDB_LAST); - while (cursor.get(indexVal, event_id, MDB_PREV)) { + bool first = true; + while (cursor.get(indexVal, event_id, first ? MDB_LAST : MDB_PREV)) { + first = false; + lmdb::val event; bool success = lmdb::dbi_get(txn, eventsDb, event_id, event); if (!success) @@ -2026,8 +2096,43 @@ Cache::saveTimelineMessages(lmdb::txn &txn, auto event = mtx::accessors::serialize_event(e); if (auto redaction = std::get_if<mtx::events::RedactionEvent<mtx::events::msg::Redaction>>(&e)) { - lmdb::dbi_put( - txn, eventsDb, lmdb::val(redaction->redacts), lmdb::val(event.dump())); + if (redaction->redacts.empty()) + continue; + + lmdb::val ev{}; + bool success = + lmdb::dbi_get(txn, eventsDb, lmdb::val(redaction->redacts), ev); + if (!success) + continue; + + mtx::events::collections::TimelineEvent te; + + try { + mtx::events::collections::from_json( + json::parse(std::string_view(ev.data(), ev.size())), te); + } catch (std::exception &e) { + nhlog::db()->error("Failed to parse message from cache {}", + e.what()); + continue; + } + + auto redactedEvent = std::visit( + [](const auto &ev) -> mtx::events::RoomEvent<mtx::events::msg::Redacted> { + mtx::events::RoomEvent<mtx::events::msg::Redacted> replacement = + {}; + replacement.event_id = ev.event_id; + replacement.room_id = ev.room_id; + replacement.sender = ev.sender; + replacement.origin_server_ts = ev.origin_server_ts; + replacement.type = ev.type; + return replacement; + }, + te.data); + + lmdb::dbi_put(txn, + eventsDb, + lmdb::val(redaction->redacts), + lmdb::val(json(redactedEvent).dump())); } else { std::string event_id_val = event["event_id"].get<std::string>(); lmdb::val event_id = event_id_val; @@ -2237,8 +2342,10 @@ Cache::deleteOldMessages() if (message_count < MAX_RESTORED_MESSAGES) continue; - while (cursor.get(indexVal, val, MDB_NEXT) && + bool start = true; + while (cursor.get(indexVal, val, start ? MDB_FIRST : MDB_NEXT) && message_count-- < MAX_RESTORED_MESSAGES) { + start = false; auto obj = json::parse(std::string_view(val.data(), val.size())); if (obj.count("event_id") != 0) { @@ -2394,6 +2501,9 @@ Cache::removeAvatarUrl(const QString &room_id, const QString &user_id) mtx::presence::PresenceState Cache::presenceState(const std::string &user_id) { + if (user_id.empty()) + return {}; + lmdb::val presenceVal; auto txn = lmdb::txn::begin(env_); @@ -2416,6 +2526,9 @@ Cache::presenceState(const std::string &user_id) std::string Cache::statusMessage(const std::string &user_id) { + if (user_id.empty()) + return {}; + lmdb::val presenceVal; auto txn = lmdb::txn::begin(env_);