diff --git a/include/ircd/m/dbs.h b/include/ircd/m/dbs.h index 40ae5dcd8..4ae7d9f8b 100644 --- a/include/ircd/m/dbs.h +++ b/include/ircd/m/dbs.h @@ -28,12 +28,17 @@ namespace ircd::m::dbs // Event metadata columns extern db::column event_idx; // event_id => event_idx extern db::column event_bad; // event_id => event_idx + extern db::index room_head; // room_id | event_id => event_idx extern db::index room_events; // room_id | depth, event_idx => state_root extern db::index room_joined; // room_id | origin, member => event_idx extern db::index room_state; // room_id | type, state_key => event_idx extern db::column state_node; // node_id => state::node // Lowlevel util + constexpr size_t ROOM_HEAD_KEY_MAX_SIZE {id::MAX_SIZE + 1 + id::MAX_SIZE}; + string_view room_head_key(const mutable_buffer &out, const id::room &, const id::event &); + string_view room_head_key(const string_view &amalgam); + constexpr size_t ROOM_STATE_KEY_MAX_SIZE {id::MAX_SIZE + 256 + 256}; string_view room_state_key(const mutable_buffer &out, const id::room &, const string_view &type, const string_view &state_key); string_view room_state_key(const mutable_buffer &out, const id::room &, const string_view &type); @@ -112,6 +117,10 @@ namespace ircd::m::dbs::desc // events blacklist extern const database::descriptor events__event_bad; + // room head mapping sequence + extern const db::prefix_transform events__room_head__pfx; + extern const database::descriptor events__room_head; + // room events sequence extern const db::prefix_transform events__room_events__pfx; extern const db::comparator events__room_events__cmp; diff --git a/ircd/m/dbs.cc b/ircd/m/dbs.cc index 54a2930f9..7a40b9416 100644 --- a/ircd/m/dbs.cc +++ b/ircd/m/dbs.cc @@ -31,9 +31,9 @@ decltype(ircd::m::dbs::event_bad) ircd::m::dbs::event_bad {}; -/// Linkage for a reference to the state_node column. -decltype(ircd::m::dbs::state_node) -ircd::m::dbs::state_node +/// Linkage for a reference to the room_head column +decltype(ircd::m::dbs::room_head) +ircd::m::dbs::room_head {}; /// Linkage for a reference to the room_events column @@ -51,6 +51,11 @@ decltype(ircd::m::dbs::room_state) ircd::m::dbs::room_state {}; +/// Linkage for a reference to the state_node column. +decltype(ircd::m::dbs::state_node) +ircd::m::dbs::state_node +{}; + // // init // @@ -77,10 +82,11 @@ ircd::m::dbs::init::init(std::string dbopts) // Cache the columns for the metadata event_idx = db::column{*events, desc::events__event_idx.name}; event_bad = db::column{*events, desc::events__event_bad.name}; - state_node = db::column{*events, desc::events__state_node.name}; + room_head = db::index{*events, desc::events__room_head.name}; room_events = db::index{*events, desc::events__room_events.name}; room_joined = db::index{*events, desc::events__room_joined.name}; room_state = db::index{*events, desc::events__room_state.name}; + state_node = db::column{*events, desc::events__state_node.name}; } /// Shuts down the m::dbs subsystem; closes the events database. The extern @@ -569,6 +575,111 @@ ircd::m::dbs::desc::events__event_bad false, }; +// +// room_head +// + +/// prefix transform for room_id,event_id in room_id +/// +const ircd::db::prefix_transform +ircd::m::dbs::desc::events__room_head__pfx +{ + "_room_head", + [](const string_view &key) + { + return has(key, "\0"_sv); + }, + + [](const string_view &key) + { + return split(key, "\0"_sv).first; + } +}; + +ircd::string_view +ircd::m::dbs::room_head_key(const mutable_buffer &out_, + const id::room &room_id, + const id::event &event_id) +{ + mutable_buffer out{out_}; + consume(out, copy(out, room_id)); + consume(out, copy(out, "\0"_sv)); + consume(out, copy(out, event_id)); + return { data(out_), data(out) }; +} + +ircd::string_view +ircd::m::dbs::room_head_key(const string_view &amalgam) +{ + const auto &key + { + lstrip(amalgam, "\0"_sv) + }; + + return + { + key + }; +} + +/// This column stores unreferenced (head) events for a room. +/// +/// [room_id | event_id => event_idx] +/// +/// The key is composed of two parts: the room_id which forms a domain for +/// iteration, and the event_id of the unreferenced event. +/// +/// The value is a gratuitious event_idx of the event_id in the key. This +/// allows foregoing the query for event_id=>event_idx when one wants to fetch +/// more data for the event. +/// +/// The way this column works is simple: when the m::vm writes any event (that +/// means full valid acceptance) it will SET an entry into this column for it. +/// At that time the prev_events of that event will be iterated and DELETE +/// ops will be appended in the transaction. +/// +const ircd::database::descriptor +ircd::m::dbs::desc::events__room_head +{ + // name + "_room_head", + + // explanation + R"(### developer note: + + )", + + // typing (key, value) + { + typeid(string_view), typeid(uint64_t) + }, + + // options + {}, + + // comparator + {}, + + // prefix transform + events__room_head__pfx, + + // cache size + 32_MiB, //TODO: conf + + // cache size for compressed assets + 0, //TODO: conf + + // bloom filter bits + 0, + + // expect queries hit + false, +}; + +// +// room_events +// + /// Prefix transform for the events__room_events. The prefix here is a room_id /// and the suffix is the depth+event_id concatenation. /// for efficient sequences @@ -1791,6 +1902,10 @@ ircd::m::dbs::desc::events // Mapping of faulty event_id to possible alternative event_idx. events__event_bad, + // (room_id, event_id) => (event_idx) + // Mapping of all current head events for a room. + events__room_head, + // (room_id, (depth, event_idx)) => (state_root) // Sequence of all events for a room, ever. events__room_events,