Remove db bottleneck by caching ro txn for 100 requests

This commit is contained in:
Nicolas Werner 2021-07-10 16:12:38 +02:00
parent f38650edf0
commit c755d54243
No known key found for this signature in database
GPG Key ID: C8D75E610773F2D9
4 changed files with 116 additions and 90 deletions

View File

@ -84,7 +84,7 @@ Item {
} }
EncryptionIndicator { EncryptionIndicator {
visible: model.isRoomEncrypted visible: room.isEncrypted
encrypted: model.isEncrypted encrypted: model.isEncrypted
trust: model.trustlevel trust: model.trustlevel
Layout.alignment: Qt.AlignRight | Qt.AlignTop Layout.alignment: Qt.AlignRight | Qt.AlignTop

View File

@ -92,6 +92,33 @@ namespace {
std::unique_ptr<Cache> instance_ = nullptr; std::unique_ptr<Cache> instance_ = nullptr;
} }
struct RO_txn
{
~RO_txn() { txn.reset(); }
operator MDB_txn *() const noexcept { return txn.handle(); }
operator lmdb::txn &() noexcept { return txn; }
lmdb::txn &txn;
};
RO_txn
ro_txn(lmdb::env &env)
{
thread_local lmdb::txn txn = lmdb::txn::begin(env, nullptr, MDB_RDONLY);
thread_local int reuse_counter = 0;
if (reuse_counter >= 100 || txn.env() != env.handle()) {
txn.abort();
txn = lmdb::txn::begin(env, nullptr, MDB_RDONLY);
reuse_counter = 0;
} else if (reuse_counter > 0) {
txn.renew();
}
reuse_counter++;
return RO_txn{txn};
}
template<class T> template<class T>
bool bool
containsStateUpdates(const T &e) containsStateUpdates(const T &e)
@ -277,10 +304,9 @@ Cache::isRoomEncrypted(const std::string &room_id)
{ {
std::string_view unused; std::string_view unused;
auto txn = lmdb::txn::begin(env_); auto txn = ro_txn(env_);
auto db = lmdb::dbi::open(txn, ENCRYPTED_ROOMS_DB, MDB_CREATE); auto db = lmdb::dbi::open(txn, ENCRYPTED_ROOMS_DB, MDB_CREATE);
auto res = db.get(txn, room_id, unused); auto res = db.get(txn, room_id, unused);
txn.commit();
return res; return res;
} }
@ -292,7 +318,7 @@ Cache::roomEncryptionSettings(const std::string &room_id)
using namespace mtx::events::state; using namespace mtx::events::state;
try { try {
auto txn = lmdb::txn::begin(env_, nullptr, MDB_RDONLY); auto txn = ro_txn(env_);
auto statesdb = getStatesDb(txn, room_id); auto statesdb = getStatesDb(txn, room_id);
std::string_view event; std::string_view event;
bool res = bool res =
@ -322,7 +348,7 @@ Cache::exportSessionKeys()
ExportedSessionKeys keys; ExportedSessionKeys keys;
auto txn = lmdb::txn::begin(env_, nullptr, MDB_RDONLY); auto txn = ro_txn(env_);
auto cursor = lmdb::cursor::open(txn, inboundMegolmSessionDb_); auto cursor = lmdb::cursor::open(txn, inboundMegolmSessionDb_);
std::string_view key, value; std::string_view key, value;
@ -348,7 +374,6 @@ Cache::exportSessionKeys()
} }
cursor.close(); cursor.close();
txn.commit();
return keys; return keys;
} }
@ -404,7 +429,7 @@ Cache::getInboundMegolmSession(const MegolmSessionIndex &index)
using namespace mtx::crypto; using namespace mtx::crypto;
try { try {
auto txn = lmdb::txn::begin(env_, nullptr, MDB_RDONLY); auto txn = ro_txn(env_);
std::string key = json(index).dump(); std::string key = json(index).dump();
std::string_view value; std::string_view value;
@ -425,7 +450,7 @@ Cache::inboundMegolmSessionExists(const MegolmSessionIndex &index)
using namespace mtx::crypto; using namespace mtx::crypto;
try { try {
auto txn = lmdb::txn::begin(env_, nullptr, MDB_RDONLY); auto txn = ro_txn(env_);
std::string key = json(index).dump(); std::string key = json(index).dump();
std::string_view value; std::string_view value;
@ -498,7 +523,7 @@ bool
Cache::outboundMegolmSessionExists(const std::string &room_id) noexcept Cache::outboundMegolmSessionExists(const std::string &room_id) noexcept
{ {
try { try {
auto txn = lmdb::txn::begin(env_, nullptr, MDB_RDONLY); auto txn = ro_txn(env_);
std::string_view value; std::string_view value;
return outboundMegolmSessionDb_.get(txn, room_id, value); return outboundMegolmSessionDb_.get(txn, room_id, value);
} catch (std::exception &e) { } catch (std::exception &e) {
@ -513,7 +538,7 @@ Cache::getOutboundMegolmSession(const std::string &room_id)
try { try {
using namespace mtx::crypto; using namespace mtx::crypto;
auto txn = lmdb::txn::begin(env_, nullptr, MDB_RDONLY); auto txn = ro_txn(env_);
std::string_view value; std::string_view value;
outboundMegolmSessionDb_.get(txn, room_id, value); outboundMegolmSessionDb_.get(txn, room_id, value);
auto obj = json::parse(value); auto obj = json::parse(value);
@ -634,10 +659,9 @@ Cache::saveOlmAccount(const std::string &data)
std::string std::string
Cache::restoreOlmAccount() Cache::restoreOlmAccount()
{ {
auto txn = lmdb::txn::begin(env_, nullptr, MDB_RDONLY); auto txn = ro_txn(env_);
std::string_view pickled; std::string_view pickled;
syncStateDb_.get(txn, OLM_ACCOUNT_KEY, pickled); syncStateDb_.get(txn, OLM_ACCOUNT_KEY, pickled);
txn.commit();
return std::string(pickled.data(), pickled.size()); return std::string(pickled.data(), pickled.size());
} }
@ -764,12 +788,11 @@ Cache::setNextBatchToken(lmdb::txn &txn, const QString &token)
bool bool
Cache::isInitialized() Cache::isInitialized()
{ {
auto txn = lmdb::txn::begin(env_, nullptr, MDB_RDONLY); auto txn = ro_txn(env_);
std::string_view token; std::string_view token;
bool res = syncStateDb_.get(txn, NEXT_BATCH_KEY, token); bool res = syncStateDb_.get(txn, NEXT_BATCH_KEY, token);
txn.commit();
return res; return res;
} }
@ -780,12 +803,11 @@ Cache::nextBatchToken()
if (!env_.handle()) if (!env_.handle())
throw lmdb::error("Env already closed", MDB_INVALID); throw lmdb::error("Env already closed", MDB_INVALID);
auto txn = lmdb::txn::begin(env_, nullptr, MDB_RDONLY); auto txn = ro_txn(env_);
std::string_view token; std::string_view token;
bool result = syncStateDb_.get(txn, NEXT_BATCH_KEY, token); bool result = syncStateDb_.get(txn, NEXT_BATCH_KEY, token);
txn.commit();
if (result) if (result)
return std::string(token.data(), token.size()); return std::string(token.data(), token.size());
@ -829,17 +851,18 @@ Cache::deleteData()
bool bool
Cache::runMigrations() Cache::runMigrations()
{ {
auto txn = lmdb::txn::begin(env_, nullptr, MDB_RDONLY); std::string stored_version;
{
auto txn = ro_txn(env_);
std::string_view current_version; std::string_view current_version;
bool res = syncStateDb_.get(txn, CACHE_FORMAT_VERSION_KEY, current_version); bool res = syncStateDb_.get(txn, CACHE_FORMAT_VERSION_KEY, current_version);
txn.commit(); if (!res)
return false;
if (!res) stored_version = std::string(current_version);
return false; }
std::string stored_version(current_version.data(), current_version.size());
std::vector<std::pair<std::string, std::function<bool()>>> migrations{ std::vector<std::pair<std::string, std::function<bool()>>> migrations{
{"2020.05.01", {"2020.05.01",
@ -1019,13 +1042,11 @@ Cache::runMigrations()
cache::CacheVersion cache::CacheVersion
Cache::formatVersion() Cache::formatVersion()
{ {
auto txn = lmdb::txn::begin(env_, nullptr, MDB_RDONLY); auto txn = ro_txn(env_);
std::string_view current_version; std::string_view current_version;
bool res = syncStateDb_.get(txn, CACHE_FORMAT_VERSION_KEY, current_version); bool res = syncStateDb_.get(txn, CACHE_FORMAT_VERSION_KEY, current_version);
txn.commit();
if (!res) if (!res)
return cache::CacheVersion::Older; return cache::CacheVersion::Older;
@ -1058,15 +1079,13 @@ Cache::readReceipts(const QString &event_id, const QString &room_id)
nlohmann::json json_key = receipt_key; nlohmann::json json_key = receipt_key;
try { try {
auto txn = lmdb::txn::begin(env_, nullptr, MDB_RDONLY); auto txn = ro_txn(env_);
auto key = json_key.dump(); auto key = json_key.dump();
std::string_view value; std::string_view value;
bool res = readReceiptsDb_.get(txn, key, value); bool res = readReceiptsDb_.get(txn, key, value);
txn.commit();
if (res) { if (res) {
auto json_response = auto json_response =
json::parse(std::string_view(value.data(), value.size())); json::parse(std::string_view(value.data(), value.size()));
@ -1151,21 +1170,22 @@ Cache::calculateRoomReadStatus()
bool bool
Cache::calculateRoomReadStatus(const std::string &room_id) Cache::calculateRoomReadStatus(const std::string &room_id)
{ {
auto txn = lmdb::txn::begin(env_); std::string last_event_id_, fullyReadEventId_;
{
auto txn = ro_txn(env_);
// Get last event id on the room. // Get last event id on the room.
const auto last_event_id = getLastEventId(txn, room_id); const auto last_event_id = getLastEventId(txn, room_id);
const auto localUser = utils::localUser().toStdString(); const auto localUser = utils::localUser().toStdString();
std::string fullyReadEventId; std::string fullyReadEventId;
if (auto ev = getAccountData(txn, mtx::events::EventType::FullyRead, room_id)) { if (auto ev = getAccountData(txn, mtx::events::EventType::FullyRead, room_id)) {
if (auto fr = std::get_if< if (auto fr = std::get_if<
mtx::events::AccountDataEvent<mtx::events::account_data::FullyRead>>( mtx::events::AccountDataEvent<mtx::events::account_data::FullyRead>>(
&ev.value())) { &ev.value())) {
fullyReadEventId = fr->content.event_id; fullyReadEventId = fr->content.event_id;
}
} }
}
txn.commit();
if (last_event_id.empty() || fullyReadEventId.empty()) if (last_event_id.empty() || fullyReadEventId.empty())
return true; return true;
@ -1173,8 +1193,12 @@ Cache::calculateRoomReadStatus(const std::string &room_id)
if (last_event_id == fullyReadEventId) if (last_event_id == fullyReadEventId)
return false; return false;
last_event_id_ = std::string(last_event_id);
fullyReadEventId_ = std::string(fullyReadEventId);
}
// Retrieve all read receipts for that event. // Retrieve all read receipts for that event.
return getEventIndex(room_id, last_event_id) > getEventIndex(room_id, fullyReadEventId); return getEventIndex(room_id, last_event_id_) > getEventIndex(room_id, fullyReadEventId_);
} }
void void
@ -1490,7 +1514,7 @@ Cache::roomsWithStateUpdates(const mtx::responses::Sync &res)
RoomInfo RoomInfo
Cache::singleRoomInfo(const std::string &room_id) Cache::singleRoomInfo(const std::string &room_id)
{ {
auto txn = lmdb::txn::begin(env_, nullptr, MDB_RDONLY); auto txn = ro_txn(env_);
auto statesdb = getStatesDb(txn, room_id); auto statesdb = getStatesDb(txn, room_id);
std::string_view data; std::string_view data;
@ -1503,7 +1527,6 @@ Cache::singleRoomInfo(const std::string &room_id)
tmp.join_rule = getRoomJoinRule(txn, statesdb); tmp.join_rule = getRoomJoinRule(txn, statesdb);
tmp.guest_access = getRoomGuestAccess(txn, statesdb); tmp.guest_access = getRoomGuestAccess(txn, statesdb);
txn.commit();
return tmp; return tmp;
} catch (const json::exception &e) { } catch (const json::exception &e) {
@ -1514,7 +1537,6 @@ Cache::singleRoomInfo(const std::string &room_id)
} }
} }
txn.commit();
return RoomInfo(); return RoomInfo();
} }
@ -1574,7 +1596,7 @@ Cache::getRoomInfo(const std::vector<std::string> &rooms)
std::vector<QString> std::vector<QString>
Cache::roomIds() Cache::roomIds()
{ {
auto txn = lmdb::txn::begin(env_, nullptr, MDB_RDONLY); auto txn = ro_txn(env_);
std::vector<QString> rooms; std::vector<QString> rooms;
std::string_view room_id, unused; std::string_view room_id, unused;
@ -1584,7 +1606,6 @@ Cache::roomIds()
rooms.push_back(QString::fromStdString(std::string(room_id))); rooms.push_back(QString::fromStdString(std::string(room_id)));
roomsCursor.close(); roomsCursor.close();
txn.commit();
return rooms; return rooms;
} }
@ -1690,7 +1711,7 @@ Cache::getTimelineMessages(lmdb::txn &txn, const std::string &room_id, uint64_t
std::optional<mtx::events::collections::TimelineEvent> std::optional<mtx::events::collections::TimelineEvent>
Cache::getEvent(const std::string &room_id, const std::string &event_id) Cache::getEvent(const std::string &room_id, const std::string &event_id)
{ {
auto txn = lmdb::txn::begin(env_, nullptr, MDB_RDONLY); auto txn = ro_txn(env_);
auto eventsDb = getEventsDb(txn, room_id); auto eventsDb = getEventsDb(txn, room_id);
std::string_view event{}; std::string_view event{};
@ -1744,7 +1765,7 @@ Cache::replaceEvent(const std::string &room_id,
std::vector<std::string> std::vector<std::string>
Cache::relatedEvents(const std::string &room_id, const std::string &event_id) Cache::relatedEvents(const std::string &room_id, const std::string &event_id)
{ {
auto txn = lmdb::txn::begin(env_, nullptr, MDB_RDONLY); auto txn = ro_txn(env_);
auto relationsDb = getRelationsDb(txn, room_id); auto relationsDb = getRelationsDb(txn, room_id);
std::vector<std::string> related_ids; std::vector<std::string> related_ids;
@ -1775,7 +1796,7 @@ Cache::relatedEvents(const std::string &room_id, const std::string &event_id)
size_t size_t
Cache::memberCount(const std::string &room_id) Cache::memberCount(const std::string &room_id)
{ {
auto txn = lmdb::txn::begin(env_, nullptr, MDB_RDONLY); auto txn = ro_txn(env_);
return getMembersDb(txn, room_id).size(txn); return getMembersDb(txn, room_id).size(txn);
} }
@ -1784,7 +1805,7 @@ Cache::roomInfo(bool withInvites)
{ {
QMap<QString, RoomInfo> result; QMap<QString, RoomInfo> result;
auto txn = lmdb::txn::begin(env_, nullptr, MDB_RDONLY); auto txn = ro_txn(env_);
std::string_view room_id; std::string_view room_id;
std::string_view room_data; std::string_view room_data;
@ -1809,8 +1830,6 @@ Cache::roomInfo(bool withInvites)
invitesCursor.close(); invitesCursor.close();
} }
txn.commit();
return result; return result;
} }
@ -1840,7 +1859,7 @@ Cache::getLastEventId(lmdb::txn &txn, const std::string &room_id)
std::optional<Cache::TimelineRange> std::optional<Cache::TimelineRange>
Cache::getTimelineRange(const std::string &room_id) Cache::getTimelineRange(const std::string &room_id)
{ {
auto txn = lmdb::txn::begin(env_, nullptr, MDB_RDONLY); auto txn = ro_txn(env_);
lmdb::dbi orderDb; lmdb::dbi orderDb;
try { try {
orderDb = getOrderToMessageDb(txn, room_id); orderDb = getOrderToMessageDb(txn, room_id);
@ -1874,7 +1893,7 @@ Cache::getTimelineIndex(const std::string &room_id, std::string_view event_id)
if (event_id.empty() || room_id.empty()) if (event_id.empty() || room_id.empty())
return {}; return {};
auto txn = lmdb::txn::begin(env_, nullptr, MDB_RDONLY); auto txn = ro_txn(env_);
lmdb::dbi orderDb; lmdb::dbi orderDb;
try { try {
@ -1902,7 +1921,7 @@ Cache::getEventIndex(const std::string &room_id, std::string_view event_id)
if (event_id.empty()) if (event_id.empty())
return {}; return {};
auto txn = lmdb::txn::begin(env_, nullptr, MDB_RDONLY); auto txn = ro_txn(env_);
lmdb::dbi orderDb; lmdb::dbi orderDb;
try { try {
@ -1930,7 +1949,7 @@ Cache::lastInvisibleEventAfter(const std::string &room_id, std::string_view even
if (event_id.empty()) if (event_id.empty())
return {}; return {};
auto txn = lmdb::txn::begin(env_, nullptr, MDB_RDONLY); auto txn = ro_txn(env_);
lmdb::dbi orderDb; lmdb::dbi orderDb;
lmdb::dbi eventOrderDb; lmdb::dbi eventOrderDb;
@ -1974,7 +1993,7 @@ Cache::lastInvisibleEventAfter(const std::string &room_id, std::string_view even
std::optional<uint64_t> std::optional<uint64_t>
Cache::getArrivalIndex(const std::string &room_id, std::string_view event_id) Cache::getArrivalIndex(const std::string &room_id, std::string_view event_id)
{ {
auto txn = lmdb::txn::begin(env_, nullptr, MDB_RDONLY); auto txn = ro_txn(env_);
lmdb::dbi orderDb; lmdb::dbi orderDb;
try { try {
@ -1999,7 +2018,7 @@ Cache::getArrivalIndex(const std::string &room_id, std::string_view event_id)
std::optional<std::string> std::optional<std::string>
Cache::getTimelineEventId(const std::string &room_id, uint64_t index) Cache::getTimelineEventId(const std::string &room_id, uint64_t index)
{ {
auto txn = lmdb::txn::begin(env_, nullptr, MDB_RDONLY); auto txn = ro_txn(env_);
lmdb::dbi orderDb; lmdb::dbi orderDb;
try { try {
orderDb = getOrderToMessageDb(txn, room_id); orderDb = getOrderToMessageDb(txn, room_id);
@ -2025,7 +2044,7 @@ Cache::invites()
{ {
QHash<QString, RoomInfo> result; QHash<QString, RoomInfo> result;
auto txn = lmdb::txn::begin(env_, nullptr, MDB_RDONLY); auto txn = ro_txn(env_);
auto cursor = lmdb::cursor::open(txn, invitesDb_); auto cursor = lmdb::cursor::open(txn, invitesDb_);
std::string_view room_id, room_data; std::string_view room_id, room_data;
@ -2054,7 +2073,7 @@ Cache::invite(std::string_view roomid)
{ {
std::optional<RoomInfo> result; std::optional<RoomInfo> result;
auto txn = lmdb::txn::begin(env_, nullptr, MDB_RDONLY); auto txn = ro_txn(env_);
std::string_view room_data; std::string_view room_data;
@ -2320,7 +2339,7 @@ Cache::getRoomAliases(const std::string &roomid)
using namespace mtx::events; using namespace mtx::events;
using namespace mtx::events::state; using namespace mtx::events::state;
auto txn = lmdb::txn::begin(env_, nullptr, MDB_RDONLY); auto txn = ro_txn(env_);
auto statesdb = getStatesDb(txn, roomid); auto statesdb = getStatesDb(txn, roomid);
std::string_view event; std::string_view event;
@ -2465,7 +2484,7 @@ Cache::getInviteRoomIsSpace(lmdb::txn &txn, lmdb::dbi &db)
std::vector<std::string> std::vector<std::string>
Cache::joinedRooms() Cache::joinedRooms()
{ {
auto txn = lmdb::txn::begin(env_, nullptr, MDB_RDONLY); auto txn = ro_txn(env_);
auto roomsCursor = lmdb::cursor::open(txn, roomsDb_); auto roomsCursor = lmdb::cursor::open(txn, roomsDb_);
std::string_view id, data; std::string_view id, data;
@ -2476,7 +2495,6 @@ Cache::joinedRooms()
room_ids.emplace_back(id); room_ids.emplace_back(id);
roomsCursor.close(); roomsCursor.close();
txn.commit();
return room_ids; return room_ids;
} }
@ -2488,7 +2506,7 @@ Cache::getMember(const std::string &room_id, const std::string &user_id)
return std::nullopt; return std::nullopt;
try { try {
auto txn = lmdb::txn::begin(env_, nullptr, MDB_RDONLY); auto txn = ro_txn(env_);
auto membersdb = getMembersDb(txn, room_id); auto membersdb = getMembersDb(txn, room_id);
@ -2507,7 +2525,7 @@ Cache::getMember(const std::string &room_id, const std::string &user_id)
std::vector<RoomMember> std::vector<RoomMember>
Cache::getMembers(const std::string &room_id, std::size_t startIndex, std::size_t len) Cache::getMembers(const std::string &room_id, std::size_t startIndex, std::size_t len)
{ {
auto txn = lmdb::txn::begin(env_, nullptr, MDB_RDONLY); auto txn = ro_txn(env_);
auto db = getMembersDb(txn, room_id); auto db = getMembersDb(txn, room_id);
auto cursor = lmdb::cursor::open(txn, db); auto cursor = lmdb::cursor::open(txn, db);
@ -2540,7 +2558,6 @@ Cache::getMembers(const std::string &room_id, std::size_t startIndex, std::size_
} }
cursor.close(); cursor.close();
txn.commit();
return members; return members;
} }
@ -2548,14 +2565,21 @@ Cache::getMembers(const std::string &room_id, std::size_t startIndex, std::size_
bool bool
Cache::isRoomMember(const std::string &user_id, const std::string &room_id) Cache::isRoomMember(const std::string &user_id, const std::string &room_id)
{ {
auto txn = lmdb::txn::begin(env_); try {
auto db = getMembersDb(txn, room_id); auto txn = ro_txn(env_);
auto db = getMembersDb(txn, room_id);
std::string_view value; std::string_view value;
bool res = db.get(txn, user_id, value); bool res = db.get(txn, user_id, value);
txn.commit();
return res; return res;
} catch (std::exception &e) {
nhlog::db()->warn("Failed to read member membership ({}) in room ({}): {}",
user_id,
room_id,
e.what());
}
return false;
} }
void void
@ -3070,11 +3094,10 @@ Cache::removeReadNotification(const std::string &event_id)
bool bool
Cache::isNotificationSent(const std::string &event_id) Cache::isNotificationSent(const std::string &event_id)
{ {
auto txn = lmdb::txn::begin(env_, nullptr, MDB_RDONLY); auto txn = ro_txn(env_);
std::string_view value; std::string_view value;
bool res = notificationsDb_.get(txn, event_id, value); bool res = notificationsDb_.get(txn, event_id, value);
txn.commit();
return res; return res;
} }
@ -3230,7 +3253,7 @@ Cache::updateSpaces(lmdb::txn &txn,
QMap<QString, std::optional<RoomInfo>> QMap<QString, std::optional<RoomInfo>>
Cache::spaces() Cache::spaces()
{ {
auto txn = lmdb::txn::begin(env_, nullptr, MDB_RDONLY); auto txn = ro_txn(env_);
QMap<QString, std::optional<RoomInfo>> ret; QMap<QString, std::optional<RoomInfo>> ret;
{ {
@ -3262,7 +3285,7 @@ Cache::spaces()
std::vector<std::string> std::vector<std::string>
Cache::getParentRoomIds(const std::string &room_id) Cache::getParentRoomIds(const std::string &room_id)
{ {
auto txn = lmdb::txn::begin(env_, nullptr, MDB_RDONLY); auto txn = ro_txn(env_);
std::vector<std::string> roomids; std::vector<std::string> roomids;
{ {
@ -3286,7 +3309,7 @@ Cache::getParentRoomIds(const std::string &room_id)
std::vector<std::string> std::vector<std::string>
Cache::getChildRoomIds(const std::string &room_id) Cache::getChildRoomIds(const std::string &room_id)
{ {
auto txn = lmdb::txn::begin(env_, nullptr, MDB_RDONLY); auto txn = ro_txn(env_);
std::vector<std::string> roomids; std::vector<std::string> roomids;
{ {
@ -3369,7 +3392,7 @@ Cache::hasEnoughPowerLevel(const std::vector<mtx::events::EventType> &eventTypes
std::vector<std::string> std::vector<std::string>
Cache::roomMembers(const std::string &room_id) Cache::roomMembers(const std::string &room_id)
{ {
auto txn = lmdb::txn::begin(env_, nullptr, MDB_RDONLY); auto txn = ro_txn(env_);
std::vector<std::string> members; std::vector<std::string> members;
std::string_view user_id, unused; std::string_view user_id, unused;
@ -3381,8 +3404,6 @@ Cache::roomMembers(const std::string &room_id)
members.emplace_back(user_id); members.emplace_back(user_id);
cursor.close(); cursor.close();
txn.commit();
return members; return members;
} }
@ -3392,7 +3413,7 @@ Cache::getMembersWithKeys(const std::string &room_id)
std::string_view keys; std::string_view keys;
try { try {
auto txn = lmdb::txn::begin(env_, nullptr, MDB_RDONLY); auto txn = ro_txn(env_);
std::map<std::string, std::optional<UserKeyCache>> members; std::map<std::string, std::optional<UserKeyCache>> members;
auto db = getMembersDb(txn, room_id); auto db = getMembersDb(txn, room_id);
@ -3528,7 +3549,7 @@ Cache::userKeys(const std::string &user_id)
std::string_view keys; std::string_view keys;
try { try {
auto txn = lmdb::txn::begin(env_, nullptr, MDB_RDONLY); auto txn = ro_txn(env_);
auto db = getUserKeysDb(txn); auto db = getUserKeysDb(txn);
auto res = db.get(txn, user_id, keys); auto res = db.get(txn, user_id, keys);

View File

@ -323,6 +323,7 @@ TimelineModel::TimelineModel(TimelineViewManager *manager, QString room_id, QObj
if (auto create = if (auto create =
cache::client()->getStateEvent<mtx::events::state::Create>(room_id.toStdString())) cache::client()->getStateEvent<mtx::events::state::Create>(room_id.toStdString()))
this->isSpace_ = create->content.type == mtx::events::state::room_type::space; this->isSpace_ = create->content.type == mtx::events::state::room_type::space;
this->isEncrypted_ = cache::isRoomEncrypted(room_id_.toStdString());
connect( connect(
this, this,
@ -435,7 +436,6 @@ TimelineModel::roleNames() const
{IsEditable, "isEditable"}, {IsEditable, "isEditable"},
{IsEncrypted, "isEncrypted"}, {IsEncrypted, "isEncrypted"},
{Trustlevel, "trustlevel"}, {Trustlevel, "trustlevel"},
{IsRoomEncrypted, "isRoomEncrypted"},
{ReplyTo, "replyTo"}, {ReplyTo, "replyTo"},
{Reactions, "reactions"}, {Reactions, "reactions"},
{RoomId, "roomId"}, {RoomId, "roomId"},
@ -622,9 +622,6 @@ TimelineModel::data(const mtx::events::collections::TimelineEvents &event, int r
return crypto::Trust::Unverified; return crypto::Trust::Unverified;
} }
case IsRoomEncrypted: {
return cache::isRoomEncrypted(room_id_.toStdString());
}
case ReplyTo: case ReplyTo:
return QVariant(QString::fromStdString(relations(event).reply_to().value_or(""))); return QVariant(QString::fromStdString(relations(event).reply_to().value_or("")));
case Reactions: { case Reactions: {
@ -672,7 +669,6 @@ TimelineModel::data(const mtx::events::collections::TimelineEvents &event, int r
m.insert(names[IsEdited], data(event, static_cast<int>(IsEdited))); m.insert(names[IsEdited], data(event, static_cast<int>(IsEdited)));
m.insert(names[IsEditable], data(event, static_cast<int>(IsEditable))); m.insert(names[IsEditable], data(event, static_cast<int>(IsEditable)));
m.insert(names[IsEncrypted], data(event, static_cast<int>(IsEncrypted))); m.insert(names[IsEncrypted], data(event, static_cast<int>(IsEncrypted)));
m.insert(names[IsRoomEncrypted], data(event, static_cast<int>(IsRoomEncrypted)));
m.insert(names[ReplyTo], data(event, static_cast<int>(ReplyTo))); m.insert(names[ReplyTo], data(event, static_cast<int>(ReplyTo)));
m.insert(names[RoomName], data(event, static_cast<int>(RoomName))); m.insert(names[RoomName], data(event, static_cast<int>(RoomName)));
m.insert(names[RoomTopic], data(event, static_cast<int>(RoomTopic))); m.insert(names[RoomTopic], data(event, static_cast<int>(RoomTopic)));
@ -785,6 +781,9 @@ TimelineModel::syncState(const mtx::responses::State &s)
emit roomAvatarUrlChanged(); emit roomAvatarUrlChanged();
emit roomNameChanged(); emit roomNameChanged();
emit roomMemberCountChanged(); emit roomMemberCountChanged();
} else if (std::holds_alternative<StateEvent<state::Encryption>>(e)) {
this->isEncrypted_ = cache::isRoomEncrypted(room_id_.toStdString());
emit encryptionChanged();
} }
} }
} }
@ -842,6 +841,9 @@ TimelineModel::addEvents(const mtx::responses::Timeline &timeline)
emit roomAvatarUrlChanged(); emit roomAvatarUrlChanged();
emit roomNameChanged(); emit roomNameChanged();
emit roomMemberCountChanged(); emit roomMemberCountChanged();
} else if (std::holds_alternative<StateEvent<state::Encryption>>(e)) {
this->isEncrypted_ = cache::isRoomEncrypted(room_id_.toStdString());
emit encryptionChanged();
} }
} }
updateLastMessage(); updateLastMessage();

View File

@ -162,6 +162,7 @@ class TimelineModel : public QAbstractListModel
Q_PROPERTY(QString roomAvatarUrl READ roomAvatarUrl NOTIFY roomAvatarUrlChanged) Q_PROPERTY(QString roomAvatarUrl READ roomAvatarUrl NOTIFY roomAvatarUrlChanged)
Q_PROPERTY(QString roomTopic READ roomTopic NOTIFY roomTopicChanged) Q_PROPERTY(QString roomTopic READ roomTopic NOTIFY roomTopicChanged)
Q_PROPERTY(int roomMemberCount READ roomMemberCount NOTIFY roomMemberCountChanged) Q_PROPERTY(int roomMemberCount READ roomMemberCount NOTIFY roomMemberCountChanged)
Q_PROPERTY(bool isEncrypted READ isEncrypted NOTIFY encryptionChanged)
Q_PROPERTY(bool isSpace READ isSpace CONSTANT) Q_PROPERTY(bool isSpace READ isSpace CONSTANT)
Q_PROPERTY(InputBar *input READ input CONSTANT) Q_PROPERTY(InputBar *input READ input CONSTANT)
Q_PROPERTY(Permissions *permissions READ permissions NOTIFY permissionsChanged) Q_PROPERTY(Permissions *permissions READ permissions NOTIFY permissionsChanged)
@ -200,7 +201,6 @@ public:
IsEditable, IsEditable,
IsEncrypted, IsEncrypted,
Trustlevel, Trustlevel,
IsRoomEncrypted,
ReplyTo, ReplyTo,
Reactions, Reactions,
RoomId, RoomId,
@ -265,6 +265,7 @@ public:
DescInfo lastMessage() const { return lastMessage_; } DescInfo lastMessage() const { return lastMessage_; }
bool isSpace() const { return isSpace_; } bool isSpace() const { return isSpace_; }
bool isEncrypted() const { return isEncrypted_; }
int roomMemberCount() const; int roomMemberCount() const;
public slots: public slots:
@ -349,6 +350,7 @@ signals:
void addPendingMessageToStore(mtx::events::collections::TimelineEvents event); void addPendingMessageToStore(mtx::events::collections::TimelineEvents event);
void updateFlowEventId(std::string event_id); void updateFlowEventId(std::string event_id);
void encryptionChanged();
void roomNameChanged(); void roomNameChanged();
void roomTopicChanged(); void roomTopicChanged();
void roomAvatarUrlChanged(); void roomAvatarUrlChanged();
@ -394,6 +396,7 @@ private:
bool decryptDescription = true; bool decryptDescription = true;
bool m_paginationInProgress = false; bool m_paginationInProgress = false;
bool isSpace_ = false; bool isSpace_ = false;
bool isEncrypted_ = false;
}; };
template<class T> template<class T>