matrixion/src/Cache_p.h

694 lines
30 KiB
C
Raw Normal View History

2021-03-05 02:35:15 +03:00
// SPDX-FileCopyrightText: 2017 Konstantinos Sideris <siderisk@auth.gr>
// SPDX-FileCopyrightText: 2019 The nheko authors
// SPDX-FileCopyrightText: 2021 Nheko Contributors
//
// SPDX-License-Identifier: GPL-3.0-or-later
2019-12-15 04:56:04 +03:00
#pragma once
2020-07-05 06:29:07 +03:00
#include <limits>
2019-12-15 04:56:04 +03:00
#include <optional>
#include <QDateTime>
#include <QDir>
#include <QImage>
#include <QString>
2020-01-24 20:39:26 +03:00
#if __has_include(<lmdbxx/lmdb++.h>)
#include <lmdbxx/lmdb++.h>
#else
2019-12-15 04:56:04 +03:00
#include <lmdb++.h>
2020-01-24 20:39:26 +03:00
#endif
2019-12-15 04:56:04 +03:00
#include <nlohmann/json.hpp>
2020-10-27 19:45:28 +03:00
#include <mtx/responses/messages.hpp>
#include <mtx/responses/notifications.hpp>
#include <mtx/responses/sync.hpp>
2019-12-15 04:56:04 +03:00
#include <mtxclient/crypto/client.hpp>
2020-10-27 19:45:28 +03:00
#include <mtxclient/http/client.hpp>
2019-12-15 04:56:04 +03:00
#include "CacheCryptoStructs.h"
#include "CacheStructs.h"
class Cache : public QObject
{
Q_OBJECT
public:
Cache(const QString &userId, QObject *parent = nullptr);
std::string displayName(const std::string &room_id, const std::string &user_id);
QString displayName(const QString &room_id, const QString &user_id);
QString avatarUrl(const QString &room_id, const QString &user_id);
2019-12-15 04:56:04 +03:00
// presence
mtx::presence::PresenceState presenceState(const std::string &user_id);
std::string statusMessage(const std::string &user_id);
2020-06-28 18:31:34 +03:00
// user cache stores user keys
std::optional<UserKeyCache> userKeys(const std::string &user_id);
std::map<std::string, std::optional<UserKeyCache>> getMembersWithKeys(
const std::string &room_id);
void updateUserKeys(const std::string &sync_token,
const mtx::responses::QueryKeys &keyQuery);
void markUserKeysOutOfDate(lmdb::txn &txn,
lmdb::dbi &db,
const std::vector<std::string> &user_ids,
const std::string &sync_token);
void deleteUserKeys(lmdb::txn &txn,
lmdb::dbi &db,
const std::vector<std::string> &user_ids);
2020-10-27 19:45:28 +03:00
void query_keys(const std::string &user_id,
std::function<void(const UserKeyCache &, mtx::http::RequestErr)> cb);
// device & user verification cache
VerificationStatus verificationStatus(const std::string &user_id);
void markDeviceVerified(const std::string &user_id, const std::string &device);
void markDeviceUnverified(const std::string &user_id, const std::string &device);
2020-06-28 18:31:34 +03:00
2019-12-15 04:56:04 +03:00
std::vector<std::string> joinedRooms();
QMap<QString, RoomInfo> roomInfo(bool withInvites = true);
std::optional<mtx::events::state::CanonicalAlias> getRoomAliases(const std::string &roomid);
2021-05-24 15:04:07 +03:00
QHash<QString, RoomInfo> invites();
std::optional<RoomInfo> invite(std::string_view roomid);
QMap<QString, std::optional<RoomInfo>> spaces();
2019-12-15 04:56:04 +03:00
//! Calculate & return the name of the room.
QString getRoomName(lmdb::txn &txn, lmdb::dbi &statesdb, lmdb::dbi &membersdb);
//! Get room join rules
mtx::events::state::JoinRule getRoomJoinRule(lmdb::txn &txn, lmdb::dbi &statesdb);
bool getRoomGuestAccess(lmdb::txn &txn, lmdb::dbi &statesdb);
//! Retrieve the topic of the room if any.
QString getRoomTopic(lmdb::txn &txn, lmdb::dbi &statesdb);
//! Retrieve the room avatar's url if any.
QString getRoomAvatarUrl(lmdb::txn &txn, lmdb::dbi &statesdb, lmdb::dbi &membersdb);
2019-12-15 04:56:04 +03:00
//! Retrieve the version of the room if any.
QString getRoomVersion(lmdb::txn &txn, lmdb::dbi &statesdb);
//! Retrieve if the room is a space
bool getRoomIsSpace(lmdb::txn &txn, lmdb::dbi &statesdb);
2019-12-15 04:56:04 +03:00
//! Get a specific state event
template<typename T>
std::optional<mtx::events::StateEvent<T>> getStateEvent(const std::string &room_id,
std::string_view state_key = "")
{
auto txn = lmdb::txn::begin(env_, nullptr, MDB_RDONLY);
return getStateEvent<T>(txn, room_id, state_key);
}
2019-12-15 04:56:04 +03:00
//! Retrieve member info from a room.
std::vector<RoomMember> getMembers(const std::string &room_id,
std::size_t startIndex = 0,
std::size_t len = 30);
2021-06-18 17:22:06 +03:00
size_t memberCount(const std::string &room_id);
2019-12-15 04:56:04 +03:00
void saveState(const mtx::responses::Sync &res);
2021-03-03 01:15:12 +03:00
bool isInitialized();
2021-05-15 00:35:34 +03:00
bool isDatabaseReady() { return databaseReady_ && isInitialized(); }
2019-12-15 04:56:04 +03:00
2021-03-03 01:15:12 +03:00
std::string nextBatchToken();
2019-12-15 04:56:04 +03:00
void deleteData();
void removeInvite(lmdb::txn &txn, const std::string &room_id);
void removeInvite(const std::string &room_id);
void removeRoom(lmdb::txn &txn, const std::string &roomid);
void removeRoom(const std::string &roomid);
void setup();
2020-05-02 17:44:50 +03:00
cache::CacheVersion formatVersion();
2019-12-15 04:56:04 +03:00
void setCurrentFormat();
2020-05-02 17:44:50 +03:00
bool runMigrations();
2019-12-15 04:56:04 +03:00
2020-10-28 15:06:28 +03:00
std::vector<QString> roomIds();
2019-12-15 04:56:04 +03:00
QMap<QString, mtx::responses::Notifications> getTimelineMentions();
//! Retrieve all the user ids from a room.
std::vector<std::string> roomMembers(const std::string &room_id);
//! Check if the given user has power leve greater than than
//! lowest power level of the given events.
bool hasEnoughPowerLevel(const std::vector<mtx::events::EventType> &eventTypes,
const std::string &room_id,
const std::string &user_id);
//! Adds a user to the read list for the given event.
//!
//! There should be only one user id present in a receipt list per room.
//! The user id should be removed from any other lists.
using Receipts = std::map<std::string, std::map<std::string, uint64_t>>;
void updateReadReceipt(lmdb::txn &txn,
const std::string &room_id,
const Receipts &receipts);
//! Retrieve all the read receipts for the given event id and room.
//!
//! Returns a map of user ids and the time of the read receipt in milliseconds.
using UserReceipts = std::multimap<uint64_t, std::string, std::greater<uint64_t>>;
UserReceipts readReceipts(const QString &event_id, const QString &room_id);
RoomInfo singleRoomInfo(const std::string &room_id);
std::vector<std::string> roomsWithStateUpdates(const mtx::responses::Sync &res);
std::map<QString, RoomInfo> getRoomInfo(const std::vector<std::string> &rooms);
//! Calculates which the read status of a room.
//! Whether all the events in the timeline have been read.
bool calculateRoomReadStatus(const std::string &room_id);
void calculateRoomReadStatus();
void markSentNotification(const std::string &event_id);
//! Removes an event from the sent notifications.
void removeReadNotification(const std::string &event_id);
//! Check if we have sent a desktop notification for the given event id.
bool isNotificationSent(const std::string &event_id);
//! Add all notifications containing a user mention to the db.
void saveTimelineMentions(const mtx::responses::Notifications &res);
2020-07-10 00:15:22 +03:00
//! retrieve events in timeline and related functions
struct Messages
{
mtx::responses::Timeline timeline;
uint64_t next_index;
bool end_of_cache = false;
};
Messages getTimelineMessages(lmdb::txn &txn,
const std::string &room_id,
2020-07-13 01:08:58 +03:00
uint64_t index = std::numeric_limits<uint64_t>::max(),
bool forward = false);
2020-07-10 00:15:22 +03:00
std::optional<mtx::events::collections::TimelineEvent> getEvent(
const std::string &room_id,
const std::string &event_id);
2020-07-10 02:37:55 +03:00
void storeEvent(const std::string &room_id,
const std::string &event_id,
const mtx::events::collections::TimelineEvent &event);
void replaceEvent(const std::string &room_id,
const std::string &event_id,
const mtx::events::collections::TimelineEvent &event);
2020-07-19 13:22:54 +03:00
std::vector<std::string> relatedEvents(const std::string &room_id,
const std::string &event_id);
2020-07-10 00:15:22 +03:00
struct TimelineRange
{
2020-07-13 01:08:58 +03:00
uint64_t first, last;
2020-07-10 00:15:22 +03:00
};
std::optional<TimelineRange> getTimelineRange(const std::string &room_id);
2020-07-13 01:08:58 +03:00
std::optional<uint64_t> getTimelineIndex(const std::string &room_id,
std::string_view event_id);
std::optional<uint64_t> getEventIndex(const std::string &room_id,
std::string_view event_id);
std::optional<std::pair<uint64_t, std::string>> lastInvisibleEventAfter(
const std::string &room_id,
std::string_view event_id);
2020-07-13 01:08:58 +03:00
std::optional<std::string> getTimelineEventId(const std::string &room_id, uint64_t index);
2021-01-27 04:45:33 +03:00
std::optional<uint64_t> getArrivalIndex(const std::string &room_id,
std::string_view event_id);
2020-07-13 01:08:58 +03:00
std::string previousBatchToken(const std::string &room_id);
uint64_t saveOldMessages(const std::string &room_id, const mtx::responses::Messages &res);
2020-07-18 18:43:49 +03:00
void savePendingMessage(const std::string &room_id,
const mtx::events::collections::TimelineEvent &message);
std::optional<mtx::events::collections::TimelineEvent> firstPendingMessage(
const std::string &room_id);
void removePendingStatus(const std::string &room_id, const std::string &txn_id);
2020-07-10 00:15:22 +03:00
2020-08-10 00:36:47 +03:00
//! clear timeline keeping only the latest batch
void clearTimeline(const std::string &room_id);
2019-12-15 04:56:04 +03:00
//! Remove old unused data.
void deleteOldMessages();
void deleteOldData() noexcept;
//! Retrieve all saved room ids.
std::vector<std::string> getRoomIds(lmdb::txn &txn);
std::vector<std::string> getParentRoomIds(const std::string &room_id);
std::vector<std::string> getChildRoomIds(const std::string &room_id);
2019-12-15 04:56:04 +03:00
//! Mark a room that uses e2e encryption.
void setEncryptedRoom(lmdb::txn &txn, const std::string &room_id);
bool isRoomEncrypted(const std::string &room_id);
2021-03-15 18:24:01 +03:00
std::optional<mtx::events::state::Encryption> roomEncryptionSettings(
const std::string &room_id);
2019-12-15 04:56:04 +03:00
//! Check if a user is a member of the room.
bool isRoomMember(const std::string &user_id, const std::string &room_id);
//
// Outbound Megolm Sessions
//
void saveOutboundMegolmSession(const std::string &room_id,
const GroupSessionData &data,
mtx::crypto::OutboundGroupSessionPtr &session);
2019-12-15 04:56:04 +03:00
OutboundGroupSessionDataRef getOutboundMegolmSession(const std::string &room_id);
bool outboundMegolmSessionExists(const std::string &room_id) noexcept;
2020-11-27 06:56:44 +03:00
void updateOutboundMegolmSession(const std::string &room_id,
const GroupSessionData &data,
2020-11-27 06:56:44 +03:00
mtx::crypto::OutboundGroupSessionPtr &session);
void dropOutboundMegolmSession(const std::string &room_id);
2019-12-15 04:56:04 +03:00
void importSessionKeys(const mtx::crypto::ExportedSessionKeys &keys);
mtx::crypto::ExportedSessionKeys exportSessionKeys();
//
// Inbound Megolm Sessions
//
void saveInboundMegolmSession(const MegolmSessionIndex &index,
mtx::crypto::InboundGroupSessionPtr session,
const GroupSessionData &data);
2020-11-27 06:19:03 +03:00
mtx::crypto::InboundGroupSessionPtr getInboundMegolmSession(
const MegolmSessionIndex &index);
2019-12-15 04:56:04 +03:00
bool inboundMegolmSessionExists(const MegolmSessionIndex &index);
//
// Olm Sessions
//
2020-10-20 14:46:05 +03:00
void saveOlmSession(const std::string &curve25519,
mtx::crypto::OlmSessionPtr session,
uint64_t timestamp);
2019-12-15 04:56:04 +03:00
std::vector<std::string> getOlmSessions(const std::string &curve25519);
std::optional<mtx::crypto::OlmSessionPtr> getOlmSession(const std::string &curve25519,
const std::string &session_id);
2020-10-20 14:46:05 +03:00
std::optional<mtx::crypto::OlmSessionPtr> getLatestOlmSession(
const std::string &curve25519);
2019-12-15 04:56:04 +03:00
void saveOlmAccount(const std::string &pickled);
std::string restoreOlmAccount();
2020-12-17 00:10:09 +03:00
void storeSecret(const std::string &name, const std::string &secret);
void deleteSecret(const std::string &name);
std::optional<std::string> secret(const std::string &name);
2021-03-15 19:11:02 +03:00
template<class T>
static constexpr bool isStateEvent(const mtx::events::StateEvent<T> &)
{
return true;
}
template<class T>
static constexpr bool isStateEvent(const mtx::events::Event<T> &)
{
return false;
}
2021-04-03 14:15:35 +03:00
static int compare_state_key(const MDB_val *a, const MDB_val *b)
{
auto get_skey = [](const MDB_val *v) {
return nlohmann::json::parse(
std::string_view(static_cast<const char *>(v->mv_data),
v->mv_size))
.value("key", "");
};
return get_skey(a).compare(get_skey(b));
}
2019-12-15 04:56:04 +03:00
signals:
void newReadReceipts(const QString &room_id, const std::vector<QString> &event_ids);
void roomReadStatus(const std::map<QString, bool> &status);
2020-04-09 21:52:50 +03:00
void removeNotification(const QString &room_id, const QString &event_id);
void userKeysUpdate(const std::string &sync_token,
const mtx::responses::QueryKeys &keyQuery);
void verificationStatusChanged(const std::string &userid);
2020-12-17 00:10:09 +03:00
void secretChanged(const std::string name);
2019-12-15 04:56:04 +03:00
private:
//! Save an invited room.
void saveInvite(lmdb::txn &txn,
lmdb::dbi &statesdb,
lmdb::dbi &membersdb,
const mtx::responses::InvitedRoom &room);
//! Add a notification containing a user mention to the db.
void saveTimelineMentions(lmdb::txn &txn,
const std::string &room_id,
const QList<mtx::responses::Notification> &res);
//! Get timeline items that a user was mentions in for a given room
mtx::responses::Notifications getTimelineMentionsForRoom(lmdb::txn &txn,
const std::string &room_id);
QString getInviteRoomName(lmdb::txn &txn, lmdb::dbi &statesdb, lmdb::dbi &membersdb);
QString getInviteRoomTopic(lmdb::txn &txn, lmdb::dbi &statesdb);
QString getInviteRoomAvatarUrl(lmdb::txn &txn, lmdb::dbi &statesdb, lmdb::dbi &membersdb);
bool getInviteRoomIsSpace(lmdb::txn &txn, lmdb::dbi &db);
2019-12-15 04:56:04 +03:00
std::optional<MemberInfo> getMember(const std::string &room_id, const std::string &user_id);
std::string getLastEventId(lmdb::txn &txn, const std::string &room_id);
2019-12-15 04:56:04 +03:00
void saveTimelineMessages(lmdb::txn &txn,
2021-06-16 23:59:41 +03:00
lmdb::dbi &eventsDb,
2019-12-15 04:56:04 +03:00
const std::string &room_id,
const mtx::responses::Timeline &res);
//! retrieve a specific event from account data
//! pass empty room_id for global account data
std::optional<mtx::events::collections::RoomAccountDataEvents>
getAccountData(lmdb::txn &txn, mtx::events::EventType type, const std::string &room_id);
bool isHiddenEvent(lmdb::txn &txn,
mtx::events::collections::TimelineEvents e,
const std::string &room_id);
2019-12-15 04:56:04 +03:00
//! Remove a room from the cache.
// void removeLeftRoom(lmdb::txn &txn, const std::string &room_id);
template<class T>
void saveStateEvents(lmdb::txn &txn,
2021-03-03 01:15:12 +03:00
lmdb::dbi &statesdb,
2021-04-03 14:15:35 +03:00
lmdb::dbi &stateskeydb,
2021-03-03 01:15:12 +03:00
lmdb::dbi &membersdb,
2021-06-16 23:59:41 +03:00
lmdb::dbi &eventsDb,
2019-12-15 04:56:04 +03:00
const std::string &room_id,
const std::vector<T> &events)
{
for (const auto &e : events)
2021-06-16 23:59:41 +03:00
saveStateEvent(txn, statesdb, stateskeydb, membersdb, eventsDb, room_id, e);
2019-12-15 04:56:04 +03:00
}
template<class T>
void saveStateEvent(lmdb::txn &txn,
2021-03-03 01:15:12 +03:00
lmdb::dbi &statesdb,
2021-04-03 14:15:35 +03:00
lmdb::dbi &stateskeydb,
2021-03-03 01:15:12 +03:00
lmdb::dbi &membersdb,
2021-06-16 23:59:41 +03:00
lmdb::dbi &eventsDb,
2019-12-15 04:56:04 +03:00
const std::string &room_id,
const T &event)
{
using namespace mtx::events;
using namespace mtx::events::state;
if (auto e = std::get_if<StateEvent<Member>>(&event); e != nullptr) {
switch (e->content.membership) {
//
// We only keep users with invite or join membership.
//
case Membership::Invite:
case Membership::Join: {
auto display_name = e->content.display_name.empty()
? e->state_key
: e->content.display_name;
// Lightweight representation of a member.
MemberInfo tmp{display_name, e->content.avatar_url};
2021-03-03 01:15:12 +03:00
membersdb.put(txn, e->state_key, json(tmp).dump());
2019-12-15 04:56:04 +03:00
break;
}
default: {
2021-03-03 01:15:12 +03:00
membersdb.del(txn, e->state_key, "");
2019-12-15 04:56:04 +03:00
break;
}
}
return;
} else if (std::holds_alternative<StateEvent<Encryption>>(event)) {
setEncryptedRoom(txn, room_id);
return;
}
2021-03-15 19:11:02 +03:00
std::visit(
2021-06-16 23:59:41 +03:00
[&txn, &statesdb, &stateskeydb, &eventsDb](auto e) {
if constexpr (isStateEvent(e)) {
eventsDb.put(txn, e.event_id, json(e).dump());
2021-04-03 14:15:35 +03:00
if (e.type != EventType::Unsupported) {
if (e.state_key.empty())
statesdb.put(
txn, to_string(e.type), json(e).dump());
else
stateskeydb.put(
txn,
to_string(e.type),
json::object({
{"key", e.state_key},
{"id", e.event_id},
})
.dump());
}
2021-06-16 23:59:41 +03:00
}
2021-03-15 19:11:02 +03:00
},
event);
2019-12-15 04:56:04 +03:00
}
template<typename T>
std::optional<mtx::events::StateEvent<T>> getStateEvent(lmdb::txn &txn,
const std::string &room_id,
std::string_view state_key = "")
{
constexpr auto type = mtx::events::state_content_to_type<T>;
static_assert(type != mtx::events::EventType::Unsupported,
"Not a supported type in state events.");
if (room_id.empty())
return std::nullopt;
const auto typeStr = to_string(type);
std::string_view value;
if (state_key.empty()) {
auto db = getStatesDb(txn, room_id);
if (!db.get(txn, typeStr, value)) {
return std::nullopt;
}
} else {
auto db = getStatesKeyDb(txn, room_id);
std::string d = json::object({{"key", state_key}}).dump();
std::string_view data = d;
std::string_view typeStrV = typeStr;
auto cursor = lmdb::cursor::open(txn, db);
if (!cursor.get(typeStrV, data, MDB_GET_BOTH))
return std::nullopt;
try {
auto eventsDb = getEventsDb(txn, room_id);
if (!eventsDb.get(
txn, json::parse(data)["id"].get<std::string>(), value))
return std::nullopt;
} catch (std::exception &e) {
return std::nullopt;
}
}
try {
return json::parse(value).get<mtx::events::StateEvent<T>>();
} catch (std::exception &e) {
return std::nullopt;
}
}
template<typename T>
std::vector<mtx::events::StateEvent<T>> getStateEventsWithType(lmdb::txn &txn,
const std::string &room_id)
{
constexpr auto type = mtx::events::state_content_to_type<T>;
static_assert(type != mtx::events::EventType::Unsupported,
"Not a supported type in state events.");
if (room_id.empty())
return {};
std::vector<mtx::events::StateEvent<T>> events;
{
auto db = getStatesKeyDb(txn, room_id);
auto eventsDb = getEventsDb(txn, room_id);
const auto typeStr = to_string(type);
std::string_view typeStrV = typeStr;
std::string_view data;
std::string_view value;
auto cursor = lmdb::cursor::open(txn, db);
bool first = true;
if (cursor.get(typeStrV, data, MDB_SET)) {
while (cursor.get(
typeStrV, data, first ? MDB_FIRST_DUP : MDB_NEXT_DUP)) {
first = false;
if (eventsDb.get(txn,
json::parse(data)["id"].get<std::string>(),
value))
events.push_back(
json::parse(value)
.get<mtx::events::StateEvent<T>>());
}
}
}
return events;
}
2019-12-15 04:56:04 +03:00
void saveInvites(lmdb::txn &txn,
const std::map<std::string, mtx::responses::InvitedRoom> &rooms);
void savePresence(
lmdb::txn &txn,
const std::vector<mtx::events::Event<mtx::events::presence::Presence>> &presenceUpdates);
2019-12-15 04:56:04 +03:00
//! Sends signals for the rooms that are removed.
void removeLeftRooms(lmdb::txn &txn,
const std::map<std::string, mtx::responses::LeftRoom> &rooms)
{
for (const auto &room : rooms) {
removeRoom(txn, room.first);
// Clean up leftover invites.
removeInvite(txn, room.first);
}
}
void updateSpaces(lmdb::txn &txn,
const std::set<std::string> &spaces_with_updates,
std::set<std::string> rooms_with_updates);
2019-12-15 04:56:04 +03:00
lmdb::dbi getPendingReceiptsDb(lmdb::txn &txn)
{
return lmdb::dbi::open(txn, "pending_receipts", MDB_CREATE);
}
2020-07-01 21:15:39 +03:00
lmdb::dbi getEventsDb(lmdb::txn &txn, const std::string &room_id)
{
return lmdb::dbi::open(txn, std::string(room_id + "/events").c_str(), MDB_CREATE);
}
2020-07-04 03:09:12 +03:00
lmdb::dbi getEventOrderDb(lmdb::txn &txn, const std::string &room_id)
{
return lmdb::dbi::open(
txn, std::string(room_id + "/event_order").c_str(), MDB_CREATE | MDB_INTEGERKEY);
}
2020-07-18 18:43:49 +03:00
// inverse of EventOrderDb
lmdb::dbi getEventToOrderDb(lmdb::txn &txn, const std::string &room_id)
{
return lmdb::dbi::open(
txn, std::string(room_id + "/event2order").c_str(), MDB_CREATE);
}
lmdb::dbi getMessageToOrderDb(lmdb::txn &txn, const std::string &room_id)
{
return lmdb::dbi::open(
txn, std::string(room_id + "/msg2order").c_str(), MDB_CREATE);
}
lmdb::dbi getOrderToMessageDb(lmdb::txn &txn, const std::string &room_id)
{
return lmdb::dbi::open(
txn, std::string(room_id + "/order2msg").c_str(), MDB_CREATE | MDB_INTEGERKEY);
2020-07-18 18:43:49 +03:00
}
lmdb::dbi getPendingMessagesDb(lmdb::txn &txn, const std::string &room_id)
{
return lmdb::dbi::open(
txn, std::string(room_id + "/pending").c_str(), MDB_CREATE | MDB_INTEGERKEY);
}
lmdb::dbi getRelationsDb(lmdb::txn &txn, const std::string &room_id)
{
return lmdb::dbi::open(
txn, std::string(room_id + "/related").c_str(), MDB_CREATE | MDB_DUPSORT);
}
2019-12-15 04:56:04 +03:00
lmdb::dbi getInviteStatesDb(lmdb::txn &txn, const std::string &room_id)
{
return lmdb::dbi::open(
txn, std::string(room_id + "/invite_state").c_str(), MDB_CREATE);
}
lmdb::dbi getInviteMembersDb(lmdb::txn &txn, const std::string &room_id)
{
return lmdb::dbi::open(
txn, std::string(room_id + "/invite_members").c_str(), MDB_CREATE);
}
lmdb::dbi getStatesDb(lmdb::txn &txn, const std::string &room_id)
{
return lmdb::dbi::open(txn, std::string(room_id + "/state").c_str(), MDB_CREATE);
}
2021-04-03 14:15:35 +03:00
lmdb::dbi getStatesKeyDb(lmdb::txn &txn, const std::string &room_id)
{
auto db = lmdb::dbi::open(
txn, std::string(room_id + "/state_by_key").c_str(), MDB_CREATE | MDB_DUPSORT);
2021-04-03 14:15:35 +03:00
lmdb::dbi_set_dupsort(txn, db, compare_state_key);
return db;
}
lmdb::dbi getAccountDataDb(lmdb::txn &txn, const std::string &room_id)
{
return lmdb::dbi::open(
txn, std::string(room_id + "/account_data").c_str(), MDB_CREATE);
}
2019-12-15 04:56:04 +03:00
lmdb::dbi getMembersDb(lmdb::txn &txn, const std::string &room_id)
{
return lmdb::dbi::open(txn, std::string(room_id + "/members").c_str(), MDB_CREATE);
}
lmdb::dbi getMentionsDb(lmdb::txn &txn, const std::string &room_id)
{
return lmdb::dbi::open(txn, std::string(room_id + "/mentions").c_str(), MDB_CREATE);
}
lmdb::dbi getPresenceDb(lmdb::txn &txn)
{
return lmdb::dbi::open(txn, "presence", MDB_CREATE);
}
lmdb::dbi getUserKeysDb(lmdb::txn &txn)
2020-06-28 18:31:34 +03:00
{
return lmdb::dbi::open(txn, "user_key", MDB_CREATE);
2020-06-28 18:31:34 +03:00
}
lmdb::dbi getVerificationDb(lmdb::txn &txn)
2020-06-28 18:31:34 +03:00
{
return lmdb::dbi::open(txn, "verified", MDB_CREATE);
2020-06-28 18:31:34 +03:00
}
2019-12-15 04:56:04 +03:00
//! Retrieves or creates the database that stores the open OLM sessions between our device
//! and the given curve25519 key which represents another device.
//!
//! Each entry is a map from the session_id to the pickled representation of the session.
lmdb::dbi getOlmSessionsDb(lmdb::txn &txn, const std::string &curve25519_key)
{
return lmdb::dbi::open(
2020-10-20 14:46:05 +03:00
txn, std::string("olm_sessions.v2/" + curve25519_key).c_str(), MDB_CREATE);
2019-12-15 04:56:04 +03:00
}
QString getDisplayName(const mtx::events::StateEvent<mtx::events::state::Member> &event)
{
if (!event.content.display_name.empty())
return QString::fromStdString(event.content.display_name);
return QString::fromStdString(event.state_key);
}
std::optional<VerificationCache> verificationCache(const std::string &user_id);
2019-12-15 04:56:04 +03:00
void setNextBatchToken(lmdb::txn &txn, const std::string &token);
void setNextBatchToken(lmdb::txn &txn, const QString &token);
lmdb::env env_;
lmdb::dbi syncStateDb_;
lmdb::dbi roomsDb_;
lmdb::dbi spacesChildrenDb_, spacesParentsDb_;
2019-12-15 04:56:04 +03:00
lmdb::dbi invitesDb_;
lmdb::dbi readReceiptsDb_;
lmdb::dbi notificationsDb_;
lmdb::dbi devicesDb_;
lmdb::dbi deviceKeysDb_;
lmdb::dbi inboundMegolmSessionDb_;
lmdb::dbi outboundMegolmSessionDb_;
lmdb::dbi megolmSessionDataDb_;
2019-12-15 04:56:04 +03:00
QString localUserId_;
QString cacheDirectory_;
VerificationStorage verification_storage;
2021-05-15 00:35:34 +03:00
bool databaseReady_ = false;
2019-12-15 04:56:04 +03:00
};
namespace cache {
Cache *
client();
}