mirror of
https://github.com/matrix-construct/construct
synced 2024-12-27 07:54:05 +01:00
parent
9b34f75e0d
commit
390b8bf2fb
15 changed files with 70 additions and 2336 deletions
|
@ -55,7 +55,6 @@ namespace ircd::m::dbs::appendix
|
||||||
#include "room_joined.h" // room_id | origin, member => event_idx
|
#include "room_joined.h" // room_id | origin, member => event_idx
|
||||||
#include "room_state.h" // room_id | type, state_key => event_idx
|
#include "room_state.h" // room_id | type, state_key => event_idx
|
||||||
#include "room_state_space.h" // room_id | type, state_key, depth, event_idx
|
#include "room_state_space.h" // room_id | type, state_key, depth, event_idx
|
||||||
#include "state_node.h" // node_id => (m::state::node JSON)
|
|
||||||
|
|
||||||
/// Options that affect the dbs::write() of an event to the transaction.
|
/// Options that affect the dbs::write() of an event to the transaction.
|
||||||
struct ircd::m::dbs::write_opts
|
struct ircd::m::dbs::write_opts
|
||||||
|
|
|
@ -1,37 +0,0 @@
|
||||||
// Matrix Construct
|
|
||||||
//
|
|
||||||
// Copyright (C) Matrix Construct Developers, Authors & Contributors
|
|
||||||
// Copyright (C) 2016-2019 Jason Volk <jason@zemos.net>
|
|
||||||
//
|
|
||||||
// Permission to use, copy, modify, and/or distribute this software for any
|
|
||||||
// purpose with or without fee is hereby granted, provided that the above
|
|
||||||
// copyright notice and this permission notice is present in all copies. The
|
|
||||||
// full license for this software is available in the LICENSE file.
|
|
||||||
|
|
||||||
#pragma once
|
|
||||||
#define HAVE_IRCD_M_DBS_STATE_NODE_H
|
|
||||||
|
|
||||||
namespace ircd::m::dbs
|
|
||||||
{
|
|
||||||
// [GET] the state root for an event (with as much information as you have)
|
|
||||||
string_view state_root(const mutable_buffer &out, const id::room &, const event::idx &, const uint64_t &depth);
|
|
||||||
string_view state_root(const mutable_buffer &out, const id::room &, const event::id &, const uint64_t &depth);
|
|
||||||
string_view state_root(const mutable_buffer &out, const id::room &, const event::idx &);
|
|
||||||
string_view state_root(const mutable_buffer &out, const id::room &, const event::id &);
|
|
||||||
string_view state_root(const mutable_buffer &out, const event::idx &);
|
|
||||||
string_view state_root(const mutable_buffer &out, const event::id &);
|
|
||||||
string_view state_root(const mutable_buffer &out, const event &);
|
|
||||||
|
|
||||||
// node_id => state::node
|
|
||||||
extern db::column state_node;
|
|
||||||
}
|
|
||||||
|
|
||||||
namespace ircd::m::dbs::desc
|
|
||||||
{
|
|
||||||
extern conf::item<size_t> events__state_node__block__size;
|
|
||||||
extern conf::item<size_t> events__state_node__meta_block__size;
|
|
||||||
extern conf::item<size_t> events__state_node__cache__size;
|
|
||||||
extern conf::item<size_t> events__state_node__cache_comp__size;
|
|
||||||
extern conf::item<size_t> events__state_node__bloom__bits;
|
|
||||||
extern const db::descriptor events__state_node;
|
|
||||||
}
|
|
|
@ -34,7 +34,6 @@ namespace ircd::m::vm
|
||||||
#include "id.h"
|
#include "id.h"
|
||||||
#include "event/event.h"
|
#include "event/event.h"
|
||||||
#include "dbs/dbs.h"
|
#include "dbs/dbs.h"
|
||||||
#include "state.h"
|
|
||||||
#include "vm.h"
|
#include "vm.h"
|
||||||
#include "invite_3pid.h"
|
#include "invite_3pid.h"
|
||||||
#include "createroom.h"
|
#include "createroom.h"
|
||||||
|
|
|
@ -56,7 +56,6 @@ struct ircd::m::room::messages
|
||||||
event::id::buf event_id() const; // deprecated; will remove
|
event::id::buf event_id() const; // deprecated; will remove
|
||||||
event::idx event_idx() const; // Available from the iterator key.
|
event::idx event_idx() const; // Available from the iterator key.
|
||||||
uint64_t depth() const; // Available from the iterator key.
|
uint64_t depth() const; // Available from the iterator key.
|
||||||
string_view state_root() const; // Available from the iterator value.
|
|
||||||
|
|
||||||
explicit operator event::idx() const;
|
explicit operator event::idx() const;
|
||||||
|
|
||||||
|
|
|
@ -33,13 +33,10 @@ struct ircd::m::room::state
|
||||||
using closure_bool = std::function<bool (const string_view &, const string_view &, const event::idx &)>;
|
using closure_bool = std::function<bool (const string_view &, const string_view &, const event::idx &)>;
|
||||||
IRCD_STRONG_TYPEDEF(string_view, type_prefix)
|
IRCD_STRONG_TYPEDEF(string_view, type_prefix)
|
||||||
|
|
||||||
static conf::item<bool> disable_history;
|
|
||||||
static conf::item<size_t> readahead_size;
|
static conf::item<size_t> readahead_size;
|
||||||
|
|
||||||
room::id room_id;
|
room::id room_id;
|
||||||
event::id::buf event_id;
|
event::id::buf event_id;
|
||||||
m::state::id_buffer root_id_buf;
|
|
||||||
m::state::id root_id;
|
|
||||||
const event::fetch::opts *fopts {nullptr};
|
const event::fetch::opts *fopts {nullptr};
|
||||||
mutable bool _not_present {false}; // cached result of !present()
|
mutable bool _not_present {false}; // cached result of !present()
|
||||||
|
|
||||||
|
@ -105,8 +102,6 @@ struct ircd::m::room::state
|
||||||
static event::idx next(const event::idx &);
|
static event::idx next(const event::idx &);
|
||||||
|
|
||||||
static size_t prefetch(const state &, const string_view &, const event::idx_range &);
|
static size_t prefetch(const state &, const string_view &, const event::idx_range &);
|
||||||
static size_t clear_history(const state &);
|
|
||||||
static size_t rebuild_history(const state &);
|
|
||||||
static size_t rebuild_present(const state &);
|
static size_t rebuild_present(const state &);
|
||||||
static bool force_present(const event &);
|
static bool force_present(const event &);
|
||||||
static size_t purge_replaced(const state &);
|
static size_t purge_replaced(const state &);
|
||||||
|
|
|
@ -1,219 +0,0 @@
|
||||||
// Matrix Construct
|
|
||||||
//
|
|
||||||
// Copyright (C) Matrix Construct Developers, Authors & Contributors
|
|
||||||
// Copyright (C) 2016-2018 Jason Volk <jason@zemos.net>
|
|
||||||
//
|
|
||||||
// Permission to use, copy, modify, and/or distribute this software for any
|
|
||||||
// purpose with or without fee is hereby granted, provided that the above
|
|
||||||
// copyright notice and this permission notice is present in all copies. The
|
|
||||||
// full license for this software is available in the LICENSE file.
|
|
||||||
|
|
||||||
#pragma once
|
|
||||||
#define HAVE_IRCD_M_STATE_H
|
|
||||||
|
|
||||||
/// Matrix machine state unit and bus.
|
|
||||||
///
|
|
||||||
/// !!! note: This is actually a really low-level interface. If you don't
|
|
||||||
/// know that you are almost certainly looking for the room::state interface
|
|
||||||
/// and not this.
|
|
||||||
///
|
|
||||||
/// This section deals specifically with the aspect of Matrix called "state"
|
|
||||||
/// providing tools and utilities as well as local databasing. IO is done for
|
|
||||||
/// reads, and indirect into db::txn's for writes. No network activities are
|
|
||||||
/// conducted here.
|
|
||||||
///
|
|
||||||
/// These tools allow the user to query aspects of the "state" of a room at
|
|
||||||
/// the point of any event. Composed out of these queries are a suite of more
|
|
||||||
/// utilities to efficiently aid the Matrix virtual machine with the rest of
|
|
||||||
/// its tasks.
|
|
||||||
///
|
|
||||||
namespace ircd::m::state
|
|
||||||
{
|
|
||||||
struct name;
|
|
||||||
struct node;
|
|
||||||
|
|
||||||
constexpr size_t ID_MAX_SZ { 64 };
|
|
||||||
constexpr size_t KEY_MAX_SZ { 256 + 256 + 16 };
|
|
||||||
constexpr size_t VAL_MAX_SZ { 256 + 16 };
|
|
||||||
constexpr size_t NODE_MAX_SZ { 4_KiB };
|
|
||||||
constexpr size_t NODE_MAX_KEY { 2 }; // tmp for now
|
|
||||||
constexpr size_t NODE_MAX_VAL { NODE_MAX_KEY };
|
|
||||||
constexpr size_t NODE_MAX_DEG { NODE_MAX_KEY + 1 }; // tmp for now
|
|
||||||
constexpr int8_t MAX_HEIGHT { 16 }; // good for few mil at any degree :)
|
|
||||||
|
|
||||||
using id = string_view;
|
|
||||||
using id_buffer = fixed_buffer<mutable_buffer, ID_MAX_SZ>;
|
|
||||||
using id_closure = std::function<void (const id &)>;
|
|
||||||
using val_closure = std::function<void (const string_view &)>;
|
|
||||||
using node_closure = std::function<void (const json::object &)>;
|
|
||||||
using search_closure = std::function<bool (const json::array &, const string_view &, const uint &, const uint &)>;
|
|
||||||
using iter_closure = std::function<void (const json::array &, const string_view &)>;
|
|
||||||
using iter_bool_closure = std::function<bool (const json::array &, const string_view &)>;
|
|
||||||
|
|
||||||
int keycmp(const json::array &a, const json::array &b);
|
|
||||||
bool prefix_eq(const json::array &a, const json::array &b);
|
|
||||||
json::array make_key(const mutable_buffer &out, const string_view &type, const string_view &state_key);
|
|
||||||
json::array make_key(const mutable_buffer &out, const string_view &type);
|
|
||||||
string_view unmake_key(const mutable_buffer &out, const json::array &);
|
|
||||||
|
|
||||||
id set_node(db::txn &txn, const mutable_buffer &id, const json::object &node);
|
|
||||||
bool get_node(const std::nothrow_t, const string_view &id, const node_closure &);
|
|
||||||
void get_node(const string_view &id, const node_closure &);
|
|
||||||
|
|
||||||
id remove(db::txn &, const mutable_buffer &rootout, const id &rootin, const json::array &key);
|
|
||||||
id remove(db::txn &, const mutable_buffer &rootout, const id &rootin, const string_view &type, const string_view &state_key);
|
|
||||||
id remove(db::txn &, const mutable_buffer &rootout, const id &rootin, const event &);
|
|
||||||
|
|
||||||
id insert(db::txn &, const mutable_buffer &rootout, const id &rootin, const json::array &key, const m::id::event &);
|
|
||||||
id insert(db::txn &, const mutable_buffer &rootout, const id &rootin, const string_view &type, const string_view &state_key, const m::id::event &);
|
|
||||||
id insert(db::txn &, const mutable_buffer &rootout, const id &rootin, const event &);
|
|
||||||
|
|
||||||
bool dfs(const id &root, const json::array &key, const search_closure &);
|
|
||||||
bool dfs(const id &root, const search_closure &);
|
|
||||||
|
|
||||||
size_t count(const id &root, const string_view &type);
|
|
||||||
size_t count(const id &root);
|
|
||||||
|
|
||||||
bool for_each(const id &root, const iter_bool_closure &);
|
|
||||||
void for_each(const id &root, const iter_closure &);
|
|
||||||
bool for_each(const id &root, const string_view &type, const iter_bool_closure &);
|
|
||||||
void for_each(const id &root, const string_view &type, const iter_closure &);
|
|
||||||
bool for_each(const id &root, const string_view &type, const string_view &state_key_lb, const iter_bool_closure &);
|
|
||||||
|
|
||||||
size_t accumulate(const id &root, const iter_bool_closure &);
|
|
||||||
|
|
||||||
bool get(std::nothrow_t, const id &root, const json::array &key, const val_closure &);
|
|
||||||
void get(const id &root, const json::array &key, const val_closure &);
|
|
||||||
|
|
||||||
bool get(std::nothrow_t, const id &root, const string_view &type, const string_view &state_key, const val_closure &);
|
|
||||||
void get(const id &root, const string_view &type, const string_view &state_key, const val_closure &);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// JSON property name strings specifically for use in m::state
|
|
||||||
struct ircd::m::state::name
|
|
||||||
{
|
|
||||||
static constexpr const char *const key {"k"};
|
|
||||||
static constexpr const char *const val {"v"};
|
|
||||||
static constexpr const char *const child {"c"};
|
|
||||||
static constexpr const char *const count {"n"};
|
|
||||||
};
|
|
||||||
|
|
||||||
/// Format for node: Node is plaintext and not binary at this time. In fact,
|
|
||||||
/// *evil chuckle*, node might as well be JSON and can easily become content
|
|
||||||
/// of another event sent to other rooms over network *snorts*. (important:
|
|
||||||
/// database is well compressed).
|
|
||||||
///
|
|
||||||
/// { ;
|
|
||||||
/// "k": ; Key array
|
|
||||||
/// [ ;
|
|
||||||
/// ["m.room.member", "@ar4an:matrix.org"], ; Left key
|
|
||||||
/// ["m.room.member", "@jzk:matrix.org"] ; Right key
|
|
||||||
/// ], ;
|
|
||||||
/// "v": ; Value array
|
|
||||||
/// [ ;
|
|
||||||
/// "$14961836116kXQRA:matrix.org", ; Left accept
|
|
||||||
/// "$15018692261xPQDB:matrix.org", ; Right accept
|
|
||||||
/// ] ;
|
|
||||||
/// "c": ; Child array
|
|
||||||
/// [ ;
|
|
||||||
/// "nPKN9twTF9a8k5dD7AApFcaraHTX", ; Left child
|
|
||||||
/// "PcxAAACvkvyUMz19AZcCfrC3S84s", ; Center child
|
|
||||||
/// "2jVYKIMKErJ6w6BLMhfVjsXearhB", ; Right child
|
|
||||||
/// ] ;
|
|
||||||
/// "n": ; Counting array
|
|
||||||
/// [ ;
|
|
||||||
/// 15, ; Left child value count
|
|
||||||
/// 12, ; Center child value count
|
|
||||||
/// 19, ; Right child value count
|
|
||||||
/// ] ;
|
|
||||||
/// } ;
|
|
||||||
///
|
|
||||||
/// Elements are ordered based on type+state_key lexical sort. The type and
|
|
||||||
/// the state_key strings are literally concatenated to this effect. They're
|
|
||||||
/// not hashed. We can have some more control over data locality this way. Any
|
|
||||||
/// number of values may be in a key array, not just type+state_key. The
|
|
||||||
/// concatenation involves the string with its surrounding quotes as to not
|
|
||||||
/// allow the user to mess about conflicting values:
|
|
||||||
/// ```
|
|
||||||
/// "m.room.member""@jzk" > "m.room.create"""
|
|
||||||
/// ```
|
|
||||||
/// Unlike traditional trees of such variety, the number of elements is not
|
|
||||||
/// really well defined and not even fixed. There just can be one more value
|
|
||||||
/// in the "child" list than there are keys in the "key" list. We have an
|
|
||||||
/// opportunity to vary the degree for different levels in different areas.
|
|
||||||
struct ircd::m::state::node
|
|
||||||
:json::tuple
|
|
||||||
<
|
|
||||||
json::property<name::key, json::array>,
|
|
||||||
json::property<name::val, json::array>,
|
|
||||||
json::property<name::child, json::array>,
|
|
||||||
json::property<name::count, json::array>
|
|
||||||
>
|
|
||||||
{
|
|
||||||
struct rep;
|
|
||||||
|
|
||||||
size_t keys() const;
|
|
||||||
size_t vals() const;
|
|
||||||
size_t childs() const;
|
|
||||||
size_t counts() const;
|
|
||||||
size_t totals() const;
|
|
||||||
|
|
||||||
json::array key(const size_t &) const;
|
|
||||||
string_view val(const size_t &) const;
|
|
||||||
state::id child(const size_t &) const;
|
|
||||||
size_t count(const size_t &) const;
|
|
||||||
|
|
||||||
size_t keys(json::array *const &out, const size_t &max) const;
|
|
||||||
size_t vals(string_view *const &out, const size_t &max) const;
|
|
||||||
size_t childs(state::id *const &out, const size_t &max) const;
|
|
||||||
size_t counts(size_t *const &out, const size_t &max) const;
|
|
||||||
|
|
||||||
size_t find(const json::array &key) const;
|
|
||||||
bool has_key(const json::array &key) const;
|
|
||||||
bool has_child(const size_t &) const;
|
|
||||||
|
|
||||||
using super_type::tuple;
|
|
||||||
using super_type::operator=;
|
|
||||||
};
|
|
||||||
|
|
||||||
/// Internal representation of a node for manipulation purposes. This is
|
|
||||||
/// because json::tuple's (like most of json::) are oriented around the
|
|
||||||
/// dominant use-case of reading const datas. These arrays could be
|
|
||||||
/// vectors optimized with a local allocator but the size_t members are
|
|
||||||
/// used to count active elements instead. One more element than the node
|
|
||||||
/// maximum is provided so that insertions and sorts can safely take place
|
|
||||||
/// before splits.
|
|
||||||
struct ircd::m::state::node::rep
|
|
||||||
{
|
|
||||||
std::array<json::array, NODE_MAX_KEY + 1> keys;
|
|
||||||
std::array<string_view, NODE_MAX_VAL + 1> vals;
|
|
||||||
std::array<state::id, NODE_MAX_DEG + 1> chld;
|
|
||||||
std::array<size_t, NODE_MAX_DEG + 1> cnts;
|
|
||||||
size_t kn {0};
|
|
||||||
size_t vn {0};
|
|
||||||
size_t cn {0};
|
|
||||||
size_t nn {0};
|
|
||||||
|
|
||||||
bool full() const;
|
|
||||||
bool last() const;
|
|
||||||
bool overfull() const;
|
|
||||||
bool duplicates() const;
|
|
||||||
size_t childs() const;
|
|
||||||
size_t counts() const;
|
|
||||||
size_t totals() const;
|
|
||||||
size_t find(const json::array &key) const;
|
|
||||||
|
|
||||||
void shl(const size_t &pos);
|
|
||||||
void shr(const size_t &pos);
|
|
||||||
|
|
||||||
json::object write(const mutable_buffer &out);
|
|
||||||
state::id write(db::txn &, const mutable_buffer &id);
|
|
||||||
|
|
||||||
rep(const node &node);
|
|
||||||
rep() = default;
|
|
||||||
};
|
|
||||||
|
|
||||||
static_assert
|
|
||||||
(
|
|
||||||
ircd::m::state::NODE_MAX_KEY == ircd::m::state::NODE_MAX_VAL
|
|
||||||
);
|
|
|
@ -88,7 +88,7 @@ IRCD_MAPI_VERSION
|
||||||
constexpr const ircd::mapi::serial_t
|
constexpr const ircd::mapi::serial_t
|
||||||
IRCD_MAPI_SERIAL
|
IRCD_MAPI_SERIAL
|
||||||
{
|
{
|
||||||
2
|
3
|
||||||
};
|
};
|
||||||
|
|
||||||
/// Module Header
|
/// Module Header
|
||||||
|
|
|
@ -150,7 +150,6 @@ endif
|
||||||
libircd_la_SOURCES += m_name.cc
|
libircd_la_SOURCES += m_name.cc
|
||||||
libircd_la_SOURCES += m_id.cc
|
libircd_la_SOURCES += m_id.cc
|
||||||
libircd_la_SOURCES += m_dbs.cc
|
libircd_la_SOURCES += m_dbs.cc
|
||||||
libircd_la_SOURCES += m_state.cc
|
|
||||||
libircd_la_SOURCES += m_room.cc
|
libircd_la_SOURCES += m_room.cc
|
||||||
libircd_la_SOURCES += m_v1.cc
|
libircd_la_SOURCES += m_v1.cc
|
||||||
libircd_la_SOURCES += m.cc
|
libircd_la_SOURCES += m.cc
|
||||||
|
|
|
@ -198,7 +198,6 @@ ircd::m::module_names
|
||||||
"s_feds",
|
"s_feds",
|
||||||
"s_node",
|
"s_node",
|
||||||
"m_events",
|
"m_events",
|
||||||
"m_state",
|
|
||||||
"m_rooms",
|
"m_rooms",
|
||||||
"m_user",
|
"m_user",
|
||||||
"m_room_aliases",
|
"m_room_aliases",
|
||||||
|
|
270
ircd/m_dbs.cc
270
ircd/m_dbs.cc
|
@ -76,11 +76,6 @@ decltype(ircd::m::dbs::room_state_space)
|
||||||
ircd::m::dbs::room_state_space
|
ircd::m::dbs::room_state_space
|
||||||
{};
|
{};
|
||||||
|
|
||||||
/// Linkage for a reference to the state_node column.
|
|
||||||
decltype(ircd::m::dbs::state_node)
|
|
||||||
ircd::m::dbs::state_node
|
|
||||||
{};
|
|
||||||
|
|
||||||
/// Coarse variable for enabling the uncompressed cache on the events database;
|
/// Coarse variable for enabling the uncompressed cache on the events database;
|
||||||
/// note this conf item is only effective by setting an environmental variable
|
/// note this conf item is only effective by setting an environmental variable
|
||||||
/// before daemon startup. It has no effect in any other regard.
|
/// before daemon startup. It has no effect in any other regard.
|
||||||
|
@ -194,7 +189,6 @@ ircd::m::dbs::init::init(const string_view &servername,
|
||||||
room_joined = db::domain{*events, desc::events__room_joined.name};
|
room_joined = db::domain{*events, desc::events__room_joined.name};
|
||||||
room_state = db::domain{*events, desc::events__room_state.name};
|
room_state = db::domain{*events, desc::events__room_state.name};
|
||||||
room_state_space = db::domain{*events, desc::events__room_state_space.name};
|
room_state_space = db::domain{*events, desc::events__room_state_space.name};
|
||||||
state_node = db::column{*events, desc::events__state_node.name};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Shuts down the m::dbs subsystem; closes the events database. The extern
|
/// Shuts down the m::dbs subsystem; closes the events database. The extern
|
||||||
|
@ -1350,106 +1344,6 @@ ircd::m::dbs::find_event_idx(const event::id &event_id,
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
ircd::string_view
|
|
||||||
ircd::m::dbs::state_root(const mutable_buffer &out,
|
|
||||||
const event &event)
|
|
||||||
{
|
|
||||||
return state_root(out, at<"room_id"_>(event), at<"event_id"_>(event), at<"depth"_>(event));
|
|
||||||
}
|
|
||||||
|
|
||||||
ircd::string_view
|
|
||||||
ircd::m::dbs::state_root(const mutable_buffer &out,
|
|
||||||
const id::event &event_id)
|
|
||||||
{
|
|
||||||
return state_root(out, index(event_id));
|
|
||||||
}
|
|
||||||
|
|
||||||
ircd::string_view
|
|
||||||
ircd::m::dbs::state_root(const mutable_buffer &out,
|
|
||||||
const event::idx &event_idx)
|
|
||||||
{
|
|
||||||
static constexpr auto idx
|
|
||||||
{
|
|
||||||
json::indexof<event, "room_id"_>()
|
|
||||||
};
|
|
||||||
|
|
||||||
auto &column
|
|
||||||
{
|
|
||||||
event_column.at(idx)
|
|
||||||
};
|
|
||||||
|
|
||||||
id::room::buf room_id;
|
|
||||||
column(byte_view<string_view>(event_idx), [&room_id]
|
|
||||||
(const string_view &val)
|
|
||||||
{
|
|
||||||
room_id = val;
|
|
||||||
});
|
|
||||||
|
|
||||||
return state_root(out, room_id, event_idx);
|
|
||||||
}
|
|
||||||
|
|
||||||
ircd::string_view
|
|
||||||
ircd::m::dbs::state_root(const mutable_buffer &out,
|
|
||||||
const id::room &room_id,
|
|
||||||
const id::event &event_id)
|
|
||||||
{
|
|
||||||
return state_root(out, room_id, index(event_id));
|
|
||||||
}
|
|
||||||
|
|
||||||
ircd::string_view
|
|
||||||
ircd::m::dbs::state_root(const mutable_buffer &out,
|
|
||||||
const id::room &room_id,
|
|
||||||
const event::idx &event_idx)
|
|
||||||
{
|
|
||||||
static constexpr auto idx
|
|
||||||
{
|
|
||||||
json::indexof<event, "depth"_>()
|
|
||||||
};
|
|
||||||
|
|
||||||
auto &column
|
|
||||||
{
|
|
||||||
event_column.at(idx)
|
|
||||||
};
|
|
||||||
|
|
||||||
uint64_t depth;
|
|
||||||
column(byte_view<string_view>(event_idx), [&depth]
|
|
||||||
(const string_view &binary)
|
|
||||||
{
|
|
||||||
depth = byte_view<uint64_t>(binary);
|
|
||||||
});
|
|
||||||
|
|
||||||
return state_root(out, room_id, event_idx, depth);
|
|
||||||
}
|
|
||||||
|
|
||||||
ircd::string_view
|
|
||||||
ircd::m::dbs::state_root(const mutable_buffer &out,
|
|
||||||
const id::room &room_id,
|
|
||||||
const id::event &event_id,
|
|
||||||
const uint64_t &depth)
|
|
||||||
{
|
|
||||||
return state_root(out, room_id, index(event_id), depth);
|
|
||||||
}
|
|
||||||
|
|
||||||
ircd::string_view
|
|
||||||
ircd::m::dbs::state_root(const mutable_buffer &out,
|
|
||||||
const id::room &room_id,
|
|
||||||
const event::idx &event_idx,
|
|
||||||
const uint64_t &depth)
|
|
||||||
{
|
|
||||||
char keybuf[ROOM_EVENTS_KEY_MAX_SIZE]; const auto key
|
|
||||||
{
|
|
||||||
room_events_key(keybuf, room_id, depth, event_idx)
|
|
||||||
};
|
|
||||||
|
|
||||||
string_view ret;
|
|
||||||
room_events(key, [&out, &ret](const string_view &val)
|
|
||||||
{
|
|
||||||
ret = { data(out), copy(out, val) };
|
|
||||||
});
|
|
||||||
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
//
|
//
|
||||||
// Database descriptors
|
// Database descriptors
|
||||||
//
|
//
|
||||||
|
@ -2713,7 +2607,7 @@ ircd::m::dbs::room_events_key(const string_view &amalgam)
|
||||||
|
|
||||||
/// This column stores events in sequence in a room. Consider the following:
|
/// This column stores events in sequence in a room. Consider the following:
|
||||||
///
|
///
|
||||||
/// [room_id | depth + event_idx => state_root]
|
/// [room_id | depth + event_idx]
|
||||||
///
|
///
|
||||||
/// The key is composed from three parts:
|
/// The key is composed from three parts:
|
||||||
///
|
///
|
||||||
|
@ -2730,17 +2624,6 @@ ircd::m::dbs::room_events_key(const string_view &amalgam)
|
||||||
/// prefixing but the event_idx suffix gives the key total uniqueness.
|
/// prefixing but the event_idx suffix gives the key total uniqueness.
|
||||||
/// NOTE: event_idx is a fixed 8 byte binary integer.
|
/// NOTE: event_idx is a fixed 8 byte binary integer.
|
||||||
///
|
///
|
||||||
/// The value is then used to store the node ID of the state tree root at this
|
|
||||||
/// event. Nodes of the state tree are stored in the state_node column. From
|
|
||||||
/// that root node the state of the room at the time of this event_id can be
|
|
||||||
/// queried.
|
|
||||||
///
|
|
||||||
/// There is one caveat here: we can't directly take a room_id and an event_idx
|
|
||||||
/// and make a trivial query to find the state root, since the depth number
|
|
||||||
/// gets in the way. Rather than creating yet another column without the depth,
|
|
||||||
/// for the time being, we pay the cost of an extra query to events_depth and
|
|
||||||
/// find that missing piece to make the exact query with all three key parts.
|
|
||||||
///
|
|
||||||
const ircd::db::descriptor
|
const ircd::db::descriptor
|
||||||
ircd::m::dbs::desc::events__room_events
|
ircd::m::dbs::desc::events__room_events
|
||||||
{
|
{
|
||||||
|
@ -2748,9 +2631,9 @@ ircd::m::dbs::desc::events__room_events
|
||||||
"_room_events",
|
"_room_events",
|
||||||
|
|
||||||
// explanation
|
// explanation
|
||||||
R"(Indexes events in timeline sequence for a room; maps to m::state root.
|
R"(Indexes events in timeline sequence for a room
|
||||||
|
|
||||||
[room_id | depth + event_idx => state_root]
|
[room_id | depth + event_idx]
|
||||||
|
|
||||||
)",
|
)",
|
||||||
|
|
||||||
|
@ -3405,111 +3288,6 @@ ircd::m::dbs::desc::events__room_state_space
|
||||||
size_t(events__room_state_space__meta_block__size),
|
size_t(events__room_state_space__meta_block__size),
|
||||||
};
|
};
|
||||||
|
|
||||||
//
|
|
||||||
// state node
|
|
||||||
//
|
|
||||||
|
|
||||||
decltype(ircd::m::dbs::desc::events__state_node__block__size)
|
|
||||||
ircd::m::dbs::desc::events__state_node__block__size
|
|
||||||
{
|
|
||||||
{ "name", "ircd.m.dbs.events._state_node.block.size" },
|
|
||||||
{ "default", 1024L },
|
|
||||||
};
|
|
||||||
|
|
||||||
decltype(ircd::m::dbs::desc::events__state_node__meta_block__size)
|
|
||||||
ircd::m::dbs::desc::events__state_node__meta_block__size
|
|
||||||
{
|
|
||||||
{ "name", "ircd.m.dbs.events._state_node.meta_block.size" },
|
|
||||||
{ "default", 1024L },
|
|
||||||
};
|
|
||||||
|
|
||||||
decltype(ircd::m::dbs::desc::events__state_node__cache__size)
|
|
||||||
ircd::m::dbs::desc::events__state_node__cache__size
|
|
||||||
{
|
|
||||||
{
|
|
||||||
{ "name", "ircd.m.dbs.events._state_node.cache.size" },
|
|
||||||
{ "default", long(64_MiB) },
|
|
||||||
}, []
|
|
||||||
{
|
|
||||||
const size_t &value{events__state_node__cache__size};
|
|
||||||
db::capacity(db::cache(state_node), value);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
decltype(ircd::m::dbs::desc::events__state_node__cache_comp__size)
|
|
||||||
ircd::m::dbs::desc::events__state_node__cache_comp__size
|
|
||||||
{
|
|
||||||
{
|
|
||||||
{ "name", "ircd.m.dbs.events._state_node.cache_comp.size" },
|
|
||||||
{ "default", long(32_MiB) },
|
|
||||||
}, []
|
|
||||||
{
|
|
||||||
const size_t &value{events__state_node__cache_comp__size};
|
|
||||||
db::capacity(db::cache_compressed(state_node), value);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
decltype(ircd::m::dbs::desc::events__state_node__bloom__bits)
|
|
||||||
ircd::m::dbs::desc::events__state_node__bloom__bits
|
|
||||||
{
|
|
||||||
{ "name", "ircd.m.dbs.events._state_node.bloom.bits" },
|
|
||||||
{ "default", 0L },
|
|
||||||
};
|
|
||||||
|
|
||||||
/// State nodes are pieces of the m::state:: b-tree. The key is the hash
|
|
||||||
/// of the value, which serves as the ID of the node when referenced in
|
|
||||||
/// the tree. see: m/state.h for details.
|
|
||||||
///
|
|
||||||
const ircd::db::descriptor
|
|
||||||
ircd::m::dbs::desc::events__state_node
|
|
||||||
{
|
|
||||||
// name
|
|
||||||
"_state_node",
|
|
||||||
|
|
||||||
// explanation
|
|
||||||
R"(Node data in the m::state b-tree.
|
|
||||||
|
|
||||||
The key is the node_id (a hash of the node's value). The value is JSON.
|
|
||||||
See the m::state system for more information.
|
|
||||||
|
|
||||||
)",
|
|
||||||
|
|
||||||
// typing (key, value)
|
|
||||||
{
|
|
||||||
typeid(ircd::string_view), typeid(ircd::string_view)
|
|
||||||
},
|
|
||||||
|
|
||||||
// options
|
|
||||||
{},
|
|
||||||
|
|
||||||
// comparator
|
|
||||||
{},
|
|
||||||
|
|
||||||
// prefix transform
|
|
||||||
{},
|
|
||||||
|
|
||||||
// drop column
|
|
||||||
false,
|
|
||||||
|
|
||||||
// cache size
|
|
||||||
bool(events_cache_enable)? -1 : 0,
|
|
||||||
|
|
||||||
// cache size for compressed assets
|
|
||||||
bool(events_cache_comp_enable)? -1 : 0,
|
|
||||||
|
|
||||||
// bloom filter bits
|
|
||||||
size_t(events__state_node__bloom__bits),
|
|
||||||
|
|
||||||
// expect queries hit
|
|
||||||
true,
|
|
||||||
|
|
||||||
// block size
|
|
||||||
size_t(events__state_node__block__size),
|
|
||||||
|
|
||||||
// meta_block size
|
|
||||||
size_t(events__state_node__meta_block__size),
|
|
||||||
};
|
|
||||||
|
|
||||||
//
|
//
|
||||||
// Direct column descriptors
|
// Direct column descriptors
|
||||||
//
|
//
|
||||||
|
@ -4355,6 +4133,7 @@ namespace ircd::m::dbs::desc
|
||||||
extern const ircd::db::comparator events__event_auth__cmp;
|
extern const ircd::db::comparator events__event_auth__cmp;
|
||||||
extern const ircd::db::prefix_transform events__event_auth__pfx;
|
extern const ircd::db::prefix_transform events__event_auth__pfx;
|
||||||
extern const ircd::db::descriptor events__event_bad;
|
extern const ircd::db::descriptor events__event_bad;
|
||||||
|
extern const ircd::db::descriptor events__state_node;
|
||||||
|
|
||||||
//
|
//
|
||||||
// Required by RocksDB
|
// Required by RocksDB
|
||||||
|
@ -4752,6 +4531,38 @@ ircd::m::dbs::desc::events_signatures
|
||||||
true,
|
true,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const ircd::db::descriptor
|
||||||
|
ircd::m::dbs::desc::events__state_node
|
||||||
|
{
|
||||||
|
// name
|
||||||
|
"_state_node",
|
||||||
|
|
||||||
|
// explanation
|
||||||
|
R"(
|
||||||
|
|
||||||
|
This column is deprecated and has been dropped from the schema. This
|
||||||
|
descriptor will erase its presence in the database upon next open.
|
||||||
|
|
||||||
|
)",
|
||||||
|
|
||||||
|
// typing (key, value)
|
||||||
|
{
|
||||||
|
typeid(ircd::string_view), typeid(ircd::string_view)
|
||||||
|
},
|
||||||
|
|
||||||
|
// options
|
||||||
|
{},
|
||||||
|
|
||||||
|
// comparator
|
||||||
|
{},
|
||||||
|
|
||||||
|
// prefix transform
|
||||||
|
{},
|
||||||
|
|
||||||
|
// drop column
|
||||||
|
true,
|
||||||
|
};
|
||||||
|
|
||||||
const ircd::db::descriptor
|
const ircd::db::descriptor
|
||||||
ircd::m::dbs::desc::events__default
|
ircd::m::dbs::desc::events__default
|
||||||
{
|
{
|
||||||
|
@ -4847,11 +4658,11 @@ ircd::m::dbs::desc::events
|
||||||
// Mapping of type strings to event_idx's of that type.
|
// Mapping of type strings to event_idx's of that type.
|
||||||
events__event_type,
|
events__event_type,
|
||||||
|
|
||||||
// (room_id, (depth, event_idx)) => (state_root)
|
// (room_id, (depth, event_idx))
|
||||||
// Sequence of all events for a room, ever.
|
// Sequence of all events for a room, ever.
|
||||||
events__room_events,
|
events__room_events,
|
||||||
|
|
||||||
// (room_id, (origin, user_id)) => ()
|
// (room_id, (origin, user_id))
|
||||||
// Sequence of all PRESENTLY JOINED joined for a room.
|
// Sequence of all PRESENTLY JOINED joined for a room.
|
||||||
events__room_joined,
|
events__room_joined,
|
||||||
|
|
||||||
|
@ -4863,10 +4674,6 @@ ircd::m::dbs::desc::events
|
||||||
// Sequence of all states of the room.
|
// Sequence of all states of the room.
|
||||||
events__room_state_space,
|
events__room_state_space,
|
||||||
|
|
||||||
// (state tree node id) => (state tree node)
|
|
||||||
// Mapping of state tree node id to node data.
|
|
||||||
events__state_node,
|
|
||||||
|
|
||||||
// (room_id, event_id) => (event_idx)
|
// (room_id, event_id) => (event_idx)
|
||||||
// Mapping of all current head events for a room.
|
// Mapping of all current head events for a room.
|
||||||
events__room_head,
|
events__room_head,
|
||||||
|
@ -4884,4 +4691,5 @@ ircd::m::dbs::desc::events
|
||||||
events_signatures,
|
events_signatures,
|
||||||
events__event_auth,
|
events__event_auth,
|
||||||
events__event_bad,
|
events__event_bad,
|
||||||
|
events__state_node,
|
||||||
};
|
};
|
||||||
|
|
170
ircd/m_room.cc
170
ircd/m_room.cc
|
@ -165,18 +165,6 @@ ircd::m::room::state::rebuild_present(const state &state)
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t
|
|
||||||
ircd::m::room::state::rebuild_history(const state &state)
|
|
||||||
{
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
size_t
|
|
||||||
ircd::m::room::state::clear_history(const state &state)
|
|
||||||
{
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
namespace ircd::m
|
namespace ircd::m
|
||||||
{
|
{
|
||||||
extern conf::item<ulong> state__prefetch__yield_modulus;
|
extern conf::item<ulong> state__prefetch__yield_modulus;
|
||||||
|
@ -1826,14 +1814,6 @@ const
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
ircd::string_view
|
|
||||||
ircd::m::room::messages::state_root()
|
|
||||||
const
|
|
||||||
{
|
|
||||||
assert(bool(*this));
|
|
||||||
return it->second;
|
|
||||||
}
|
|
||||||
|
|
||||||
uint64_t
|
uint64_t
|
||||||
ircd::m::room::messages::depth()
|
ircd::m::room::messages::depth()
|
||||||
const
|
const
|
||||||
|
@ -1878,13 +1858,6 @@ ircd::m::room::messages::fetch(std::nothrow_t)
|
||||||
// room::state
|
// room::state
|
||||||
//
|
//
|
||||||
|
|
||||||
decltype(ircd::m::room::state::disable_history)
|
|
||||||
ircd::m::room::state::disable_history
|
|
||||||
{
|
|
||||||
{ "name", "ircd.m.room.state.disable_history" },
|
|
||||||
{ "default", true },
|
|
||||||
};
|
|
||||||
|
|
||||||
decltype(ircd::m::room::state::readahead_size)
|
decltype(ircd::m::room::state::readahead_size)
|
||||||
ircd::m::room::state::readahead_size
|
ircd::m::room::state::readahead_size
|
||||||
{
|
{
|
||||||
|
@ -1908,12 +1881,6 @@ ircd::m::room::state::state(const m::room &room,
|
||||||
event::id::buf{room.event_id}:
|
event::id::buf{room.event_id}:
|
||||||
event::id::buf{}
|
event::id::buf{}
|
||||||
}
|
}
|
||||||
,root_id
|
|
||||||
{
|
|
||||||
event_id && !bool(disable_history)?
|
|
||||||
dbs::state_root(root_id_buf, room_id, event_id):
|
|
||||||
m::state::id{}
|
|
||||||
}
|
|
||||||
,fopts
|
,fopts
|
||||||
{
|
{
|
||||||
fopts?
|
fopts?
|
||||||
|
@ -1993,32 +1960,14 @@ void
|
||||||
ircd::m::room::state::get(const string_view &type,
|
ircd::m::room::state::get(const string_view &type,
|
||||||
const string_view &state_key,
|
const string_view &state_key,
|
||||||
const event::id::closure &closure)
|
const event::id::closure &closure)
|
||||||
const try
|
const
|
||||||
{
|
{
|
||||||
if(!present())
|
|
||||||
return m::state::get(root_id, type, state_key, [&closure]
|
|
||||||
(const string_view &event_id)
|
|
||||||
{
|
|
||||||
closure(unquote(event_id));
|
|
||||||
});
|
|
||||||
|
|
||||||
get(type, state_key, event::closure_idx{[&closure]
|
get(type, state_key, event::closure_idx{[&closure]
|
||||||
(const event::idx &idx)
|
(const event::idx &idx)
|
||||||
{
|
{
|
||||||
event::fetch::event_id(idx, closure);
|
event::fetch::event_id(idx, closure);
|
||||||
}});
|
}});
|
||||||
}
|
}
|
||||||
catch(const db::not_found &e)
|
|
||||||
{
|
|
||||||
throw m::NOT_FOUND
|
|
||||||
{
|
|
||||||
"(%s,%s) in %s :%s",
|
|
||||||
type,
|
|
||||||
state_key,
|
|
||||||
string_view{room_id},
|
|
||||||
e.what()
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
void
|
||||||
ircd::m::room::state::get(const string_view &type,
|
ircd::m::room::state::get(const string_view &type,
|
||||||
|
@ -2027,11 +1976,10 @@ ircd::m::room::state::get(const string_view &type,
|
||||||
const try
|
const try
|
||||||
{
|
{
|
||||||
if(!present())
|
if(!present())
|
||||||
m::state::get(root_id, type, state_key, [&closure]
|
{
|
||||||
(const string_view &event_id)
|
assert(0);
|
||||||
{
|
return;
|
||||||
closure(index(m::event::id(unquote(event_id))));
|
}
|
||||||
});
|
|
||||||
|
|
||||||
auto &column{dbs::room_state};
|
auto &column{dbs::room_state};
|
||||||
char key[dbs::ROOM_STATE_KEY_MAX_SIZE];
|
char key[dbs::ROOM_STATE_KEY_MAX_SIZE];
|
||||||
|
@ -2079,13 +2027,6 @@ ircd::m::room::state::get(std::nothrow_t,
|
||||||
const event::id::closure &closure)
|
const event::id::closure &closure)
|
||||||
const
|
const
|
||||||
{
|
{
|
||||||
if(!present())
|
|
||||||
return m::state::get(std::nothrow, root_id, type, state_key, [&closure]
|
|
||||||
(const string_view &event_id)
|
|
||||||
{
|
|
||||||
closure(unquote(event_id));
|
|
||||||
});
|
|
||||||
|
|
||||||
return get(std::nothrow, type, state_key, event::closure_idx{[&closure]
|
return get(std::nothrow, type, state_key, event::closure_idx{[&closure]
|
||||||
(const event::idx &idx)
|
(const event::idx &idx)
|
||||||
{
|
{
|
||||||
|
@ -2101,11 +2042,10 @@ ircd::m::room::state::get(std::nothrow_t,
|
||||||
const
|
const
|
||||||
{
|
{
|
||||||
if(!present())
|
if(!present())
|
||||||
return m::state::get(std::nothrow, root_id, type, state_key, [&closure]
|
{
|
||||||
(const string_view &event_id)
|
assert(0);
|
||||||
{
|
return false;
|
||||||
return closure(index(m::event::id(unquote(event_id)), std::nothrow));
|
}
|
||||||
});
|
|
||||||
|
|
||||||
auto &column{dbs::room_state};
|
auto &column{dbs::room_state};
|
||||||
char key[dbs::ROOM_STATE_KEY_MAX_SIZE];
|
char key[dbs::ROOM_STATE_KEY_MAX_SIZE];
|
||||||
|
@ -2132,9 +2072,10 @@ ircd::m::room::state::has(const string_view &type,
|
||||||
const
|
const
|
||||||
{
|
{
|
||||||
if(!present())
|
if(!present())
|
||||||
return m::state::get(std::nothrow, root_id, type, state_key, []
|
{
|
||||||
(const string_view &event_id)
|
assert(0);
|
||||||
{});
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
auto &column{dbs::room_state};
|
auto &column{dbs::room_state};
|
||||||
char key[dbs::ROOM_STATE_KEY_MAX_SIZE];
|
char key[dbs::ROOM_STATE_KEY_MAX_SIZE];
|
||||||
|
@ -2152,9 +2093,6 @@ size_t
|
||||||
ircd::m::room::state::count(const string_view &type)
|
ircd::m::room::state::count(const string_view &type)
|
||||||
const
|
const
|
||||||
{
|
{
|
||||||
if(!present())
|
|
||||||
return m::state::count(root_id, type);
|
|
||||||
|
|
||||||
size_t ret{0};
|
size_t ret{0};
|
||||||
for_each(type, event::closure_idx{[&ret]
|
for_each(type, event::closure_idx{[&ret]
|
||||||
(const event::idx &event_idx)
|
(const event::idx &event_idx)
|
||||||
|
@ -2213,13 +2151,6 @@ bool
|
||||||
ircd::m::room::state::for_each(const event::id::closure_bool &closure)
|
ircd::m::room::state::for_each(const event::id::closure_bool &closure)
|
||||||
const
|
const
|
||||||
{
|
{
|
||||||
if(!present())
|
|
||||||
return m::state::for_each(root_id, m::state::iter_bool_closure{[&closure]
|
|
||||||
(const json::array &key, const string_view &event_id)
|
|
||||||
{
|
|
||||||
return closure(unquote(event_id));
|
|
||||||
}});
|
|
||||||
|
|
||||||
return for_each(event::closure_idx_bool{[&closure]
|
return for_each(event::closure_idx_bool{[&closure]
|
||||||
(const event::idx &idx)
|
(const event::idx &idx)
|
||||||
{
|
{
|
||||||
|
@ -2262,12 +2193,10 @@ ircd::m::room::state::for_each(const closure_bool &closure)
|
||||||
const
|
const
|
||||||
{
|
{
|
||||||
if(!present())
|
if(!present())
|
||||||
return m::state::for_each(root_id, m::state::iter_bool_closure{[&closure]
|
{
|
||||||
(const json::array &key, const string_view &event_id)
|
assert(0);
|
||||||
{
|
return true;
|
||||||
const auto idx(index(m::event::id(unquote(event_id)), std::nothrow));
|
}
|
||||||
return closure(key.at(0), key.at(1), idx);
|
|
||||||
}});
|
|
||||||
|
|
||||||
db::gopts opts
|
db::gopts opts
|
||||||
{
|
{
|
||||||
|
@ -2396,13 +2325,6 @@ ircd::m::room::state::for_each(const string_view &type,
|
||||||
const event::id::closure_bool &closure)
|
const event::id::closure_bool &closure)
|
||||||
const
|
const
|
||||||
{
|
{
|
||||||
if(!present())
|
|
||||||
return m::state::for_each(root_id, type, state_key_lb, [&closure]
|
|
||||||
(const json::array &key, const string_view &event_id)
|
|
||||||
{
|
|
||||||
return closure(unquote(event_id));
|
|
||||||
});
|
|
||||||
|
|
||||||
return for_each(type, state_key_lb, event::closure_idx_bool{[&closure]
|
return for_each(type, state_key_lb, event::closure_idx_bool{[&closure]
|
||||||
(const event::idx &idx)
|
(const event::idx &idx)
|
||||||
{
|
{
|
||||||
|
@ -2437,12 +2359,10 @@ ircd::m::room::state::for_each(const string_view &type,
|
||||||
const
|
const
|
||||||
{
|
{
|
||||||
if(!present())
|
if(!present())
|
||||||
return m::state::for_each(root_id, type, state_key_lb, [&closure]
|
{
|
||||||
(const json::array &key, const string_view &event_id)
|
assert(0);
|
||||||
{
|
return true;
|
||||||
const auto idx(index(m::event::id(unquote(event_id)), std::nothrow));
|
}
|
||||||
return closure(key.at(0), key.at(1), idx);
|
|
||||||
});
|
|
||||||
|
|
||||||
char keybuf[dbs::ROOM_STATE_KEY_MAX_SIZE];
|
char keybuf[dbs::ROOM_STATE_KEY_MAX_SIZE];
|
||||||
const auto &key
|
const auto &key
|
||||||
|
@ -2505,12 +2425,10 @@ ircd::m::room::state::for_each(const string_view &type,
|
||||||
const
|
const
|
||||||
{
|
{
|
||||||
if(!present())
|
if(!present())
|
||||||
return m::state::for_each(root_id, type, state_key_lb, [&closure]
|
{
|
||||||
(const json::array &key, const string_view &event_id)
|
assert(0);
|
||||||
{
|
return true;
|
||||||
assert(size(key) >= 2);
|
}
|
||||||
return closure(unquote(key.at(1)));
|
|
||||||
});
|
|
||||||
|
|
||||||
char keybuf[dbs::ROOM_STATE_KEY_MAX_SIZE];
|
char keybuf[dbs::ROOM_STATE_KEY_MAX_SIZE];
|
||||||
const auto &key
|
const auto &key
|
||||||
|
@ -2582,24 +2500,10 @@ const
|
||||||
{
|
{
|
||||||
string_view last;
|
string_view last;
|
||||||
char lastbuf[m::event::TYPE_MAX_SIZE];
|
char lastbuf[m::event::TYPE_MAX_SIZE];
|
||||||
|
|
||||||
if(!present())
|
if(!present())
|
||||||
{
|
{
|
||||||
m::state::for_each(root_id, m::state::iter_bool_closure{[&closure, &last, &lastbuf]
|
assert(0);
|
||||||
(const json::array &key, const string_view &)
|
|
||||||
{
|
|
||||||
assert(size(key) >= 2);
|
|
||||||
const auto type
|
|
||||||
{
|
|
||||||
unquote(key.at(0))
|
|
||||||
};
|
|
||||||
|
|
||||||
if(type == last)
|
|
||||||
return true;
|
|
||||||
|
|
||||||
last = strlcpy(lastbuf, type);
|
|
||||||
return closure(type);
|
|
||||||
}});
|
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2653,15 +2557,6 @@ const
|
||||||
if(!event_id)
|
if(!event_id)
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
// When an event_id is passed but no state btree root_id was found
|
|
||||||
// that means there is no state btree generated for this room or at
|
|
||||||
// this event_id. Right now we fall back to using the present state
|
|
||||||
// of the room, which may be confusing behavior. In production this
|
|
||||||
// shouldn't happen; if it does, the ctor should probably throw rather
|
|
||||||
// than this. We just fallback to considering present state here.
|
|
||||||
if(!root_id)
|
|
||||||
return true;
|
|
||||||
|
|
||||||
// Check the cached value from a previous false result of this function
|
// Check the cached value from a previous false result of this function
|
||||||
// before doing any real work/IO below. If this function ever returned
|
// before doing any real work/IO below. If this function ever returned
|
||||||
// false it will never return true after.
|
// false it will never return true after.
|
||||||
|
@ -2678,17 +2573,6 @@ const
|
||||||
if(!head_id || head_id == event_id)
|
if(!head_id || head_id == event_id)
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
m::state::id_buffer root_id_buf;
|
|
||||||
const auto head_root
|
|
||||||
{
|
|
||||||
dbs::state_root(root_id_buf, room_id, head_id)
|
|
||||||
};
|
|
||||||
|
|
||||||
// If the room's state has not changed between the event_id desired
|
|
||||||
// here and the latest event we can also consider this the present state.
|
|
||||||
if(head_root && head_root == root_id)
|
|
||||||
return true;
|
|
||||||
|
|
||||||
// This result is cacheable because once it's no longer the present
|
// This result is cacheable because once it's no longer the present
|
||||||
// it will never be again. Panta chorei kai ouden menei. Note that this
|
// it will never be again. Panta chorei kai ouden menei. Note that this
|
||||||
// is a const member function; the cache variable is an appropriate case
|
// is a const member function; the cache variable is an appropriate case
|
||||||
|
|
1322
ircd/m_state.cc
1322
ircd/m_state.cc
File diff suppressed because it is too large
Load diff
|
@ -118,7 +118,6 @@ m_presence_la_SOURCES = m_presence.cc
|
||||||
m_direct_to_device_la_SOURCES = m_direct_to_device.cc
|
m_direct_to_device_la_SOURCES = m_direct_to_device.cc
|
||||||
m_device_list_update_la_SOURCES = m_device_list_update.cc
|
m_device_list_update_la_SOURCES = m_device_list_update.cc
|
||||||
m_ignored_user_list_la_SOURCES = m_ignored_user_list.cc
|
m_ignored_user_list_la_SOURCES = m_ignored_user_list.cc
|
||||||
m_state_la_SOURCES = m_state.cc
|
|
||||||
m_events_la_SOURCES = m_events.cc
|
m_events_la_SOURCES = m_events.cc
|
||||||
m_rooms_la_SOURCES = m_rooms.cc
|
m_rooms_la_SOURCES = m_rooms.cc
|
||||||
m_room_create_la_SOURCES = m_room_create.cc
|
m_room_create_la_SOURCES = m_room_create.cc
|
||||||
|
@ -142,7 +141,6 @@ m_module_LTLIBRARIES = \
|
||||||
m_direct_to_device.la \
|
m_direct_to_device.la \
|
||||||
m_device_list_update.la \
|
m_device_list_update.la \
|
||||||
m_ignored_user_list.la \
|
m_ignored_user_list.la \
|
||||||
m_state.la \
|
|
||||||
m_events.la \
|
m_events.la \
|
||||||
m_rooms.la \
|
m_rooms.la \
|
||||||
m_room_create.la \
|
m_room_create.la \
|
||||||
|
|
|
@ -7122,161 +7122,6 @@ console_cmd__event__refs__auth(opt &out, const string_view &line)
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
|
||||||
// state
|
|
||||||
//
|
|
||||||
|
|
||||||
bool
|
|
||||||
console_cmd__state__count(opt &out, const string_view &line)
|
|
||||||
{
|
|
||||||
const string_view arg
|
|
||||||
{
|
|
||||||
token(line, ' ', 0)
|
|
||||||
};
|
|
||||||
|
|
||||||
const string_view root
|
|
||||||
{
|
|
||||||
arg
|
|
||||||
};
|
|
||||||
|
|
||||||
out << m::state::count(root) << std::endl;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool
|
|
||||||
console_cmd__state__each(opt &out, const string_view &line)
|
|
||||||
{
|
|
||||||
const string_view arg
|
|
||||||
{
|
|
||||||
token(line, ' ', 0)
|
|
||||||
};
|
|
||||||
|
|
||||||
const string_view type
|
|
||||||
{
|
|
||||||
token(line, ' ', 1)
|
|
||||||
};
|
|
||||||
|
|
||||||
const string_view root
|
|
||||||
{
|
|
||||||
arg
|
|
||||||
};
|
|
||||||
|
|
||||||
m::state::for_each(root, type, [&out]
|
|
||||||
(const string_view &key, const string_view &val)
|
|
||||||
{
|
|
||||||
out << key << " => " << val << std::endl;
|
|
||||||
});
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool
|
|
||||||
console_cmd__state__get(opt &out, const string_view &line)
|
|
||||||
{
|
|
||||||
const string_view root
|
|
||||||
{
|
|
||||||
token(line, ' ', 0)
|
|
||||||
};
|
|
||||||
|
|
||||||
const string_view type
|
|
||||||
{
|
|
||||||
token(line, ' ', 1)
|
|
||||||
};
|
|
||||||
|
|
||||||
const string_view state_key
|
|
||||||
{
|
|
||||||
token(line, ' ', 2)
|
|
||||||
};
|
|
||||||
|
|
||||||
m::state::get(root, type, state_key, [&out]
|
|
||||||
(const auto &value)
|
|
||||||
{
|
|
||||||
out << "got: " << value << std::endl;
|
|
||||||
});
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool
|
|
||||||
console_cmd__state__find(opt &out, const string_view &line)
|
|
||||||
{
|
|
||||||
const params param{line, " ",
|
|
||||||
{
|
|
||||||
"root", "[type]" "[state_key]"
|
|
||||||
}};
|
|
||||||
|
|
||||||
const string_view &root
|
|
||||||
{
|
|
||||||
param.at(0)
|
|
||||||
};
|
|
||||||
|
|
||||||
const string_view &type
|
|
||||||
{
|
|
||||||
param[1]
|
|
||||||
};
|
|
||||||
|
|
||||||
const string_view &state_key
|
|
||||||
{
|
|
||||||
param[2]
|
|
||||||
};
|
|
||||||
|
|
||||||
const auto closure{[&out]
|
|
||||||
(const auto &key, const string_view &val)
|
|
||||||
{
|
|
||||||
out << key << " => " << val << std::endl;
|
|
||||||
return true;
|
|
||||||
}};
|
|
||||||
|
|
||||||
m::state::for_each(root, type, state_key, closure);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool
|
|
||||||
console_cmd__state__root(opt &out, const string_view &line)
|
|
||||||
{
|
|
||||||
const m::event::id event_id
|
|
||||||
{
|
|
||||||
token(line, ' ', 0)
|
|
||||||
};
|
|
||||||
|
|
||||||
char buf[m::state::ID_MAX_SZ];
|
|
||||||
out << m::dbs::state_root(buf, event_id) << std::endl;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool
|
|
||||||
console_cmd__state__gc(opt &out, const string_view &line)
|
|
||||||
{
|
|
||||||
using prototype = size_t ();
|
|
||||||
static mods::import<prototype> gc
|
|
||||||
{
|
|
||||||
"m_state", "ircd__m__state__gc"
|
|
||||||
};
|
|
||||||
|
|
||||||
const size_t count
|
|
||||||
{
|
|
||||||
gc()
|
|
||||||
};
|
|
||||||
|
|
||||||
out << "done: " << count << std::endl;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool
|
|
||||||
console_cmd__state__CLEAR__CLEAR__CLEAR(opt &out, const string_view &line)
|
|
||||||
{
|
|
||||||
using prototype = void ();
|
|
||||||
static mods::import<prototype> clear
|
|
||||||
{
|
|
||||||
"m_state", "ircd__m__state__clear"
|
|
||||||
};
|
|
||||||
|
|
||||||
clear();
|
|
||||||
|
|
||||||
out << "done" << std::endl;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
//
|
//
|
||||||
// commit
|
// commit
|
||||||
//
|
//
|
||||||
|
@ -8925,66 +8770,6 @@ console_cmd__room__state__rebuild__present(opt &out, const string_view &line)
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool
|
|
||||||
console_cmd__room__state__rebuild__history(opt &out, const string_view &line)
|
|
||||||
{
|
|
||||||
const params param{line, " ",
|
|
||||||
{
|
|
||||||
"room_id"
|
|
||||||
}};
|
|
||||||
|
|
||||||
const auto &room_id
|
|
||||||
{
|
|
||||||
m::room_id(param.at(0))
|
|
||||||
};
|
|
||||||
|
|
||||||
const m::room::state state
|
|
||||||
{
|
|
||||||
room_id
|
|
||||||
};
|
|
||||||
|
|
||||||
const size_t count
|
|
||||||
{
|
|
||||||
state.rebuild_history(state)
|
|
||||||
};
|
|
||||||
|
|
||||||
out << "done " << count << std::endl;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool
|
|
||||||
console_cmd__room__state__history__clear(opt &out, const string_view &line)
|
|
||||||
{
|
|
||||||
const params param{line, " ",
|
|
||||||
{
|
|
||||||
"room_id"
|
|
||||||
}};
|
|
||||||
|
|
||||||
const auto &room_id
|
|
||||||
{
|
|
||||||
m::room_id(param.at(0))
|
|
||||||
};
|
|
||||||
|
|
||||||
const m::room::state state
|
|
||||||
{
|
|
||||||
room_id
|
|
||||||
};
|
|
||||||
|
|
||||||
using prototype = size_t (const m::room &);
|
|
||||||
static mods::import<prototype> state__clear_history
|
|
||||||
{
|
|
||||||
"m_room", "state__clear_history"
|
|
||||||
};
|
|
||||||
|
|
||||||
const size_t count
|
|
||||||
{
|
|
||||||
state.clear_history(state)
|
|
||||||
};
|
|
||||||
|
|
||||||
out << "done " << count << std::endl;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool
|
bool
|
||||||
console_cmd__room__state__prefetch(opt &out, const string_view &line)
|
console_cmd__room__state__prefetch(opt &out, const string_view &line)
|
||||||
{
|
{
|
||||||
|
@ -9186,11 +8971,6 @@ console_cmd__room__events(opt &out, const string_view &line)
|
||||||
param.at(3, ssize_t(32))
|
param.at(3, ssize_t(32))
|
||||||
};
|
};
|
||||||
|
|
||||||
const bool roots
|
|
||||||
{
|
|
||||||
has(out.special, "roots")
|
|
||||||
};
|
|
||||||
|
|
||||||
const m::room room
|
const m::room room
|
||||||
{
|
{
|
||||||
room_id
|
room_id
|
||||||
|
@ -9202,16 +8982,9 @@ console_cmd__room__events(opt &out, const string_view &line)
|
||||||
};
|
};
|
||||||
|
|
||||||
for(; it && limit >= 0; order == 'b'? --it : ++it, --limit)
|
for(; it && limit >= 0; order == 'b'? --it : ++it, --limit)
|
||||||
if(roots)
|
out << std::left << std::setw(10) << it.event_idx() << " "
|
||||||
out << std::setw(48) << std::left << it.state_root()
|
<< pretty_oneline(*it)
|
||||||
<< " " << std::setw(8) << std::right << it.event_idx()
|
<< std::endl;
|
||||||
<< " " << std::setw(8) << std::right << it.depth()
|
|
||||||
<< " " << it.event_id()
|
|
||||||
<< std::endl;
|
|
||||||
else
|
|
||||||
out << std::left << std::setw(10) << it.event_idx() << " "
|
|
||||||
<< pretty_oneline(*it)
|
|
||||||
<< std::endl;
|
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -9346,14 +9119,6 @@ console_cmd__room__timeline__rebuild(opt &out, const string_view &line)
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool
|
|
||||||
console_cmd__room__roots(opt &out, const string_view &line)
|
|
||||||
{
|
|
||||||
assert(!out.special);
|
|
||||||
out.special = "roots";
|
|
||||||
return console_cmd__room__events(out, line);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool
|
bool
|
||||||
console_cmd__room__get(opt &out, const string_view &line)
|
console_cmd__room__get(opt &out, const string_view &line)
|
||||||
{
|
{
|
||||||
|
|
|
@ -1,133 +0,0 @@
|
||||||
// Matrix Construct
|
|
||||||
//
|
|
||||||
// Copyright (C) Matrix Construct Developers, Authors & Contributors
|
|
||||||
// Copyright (C) 2016-2018 Jason Volk <jason@zemos.net>
|
|
||||||
//
|
|
||||||
// Permission to use, copy, modify, and/or distribute this software for any
|
|
||||||
// purpose with or without fee is hereby granted, provided that the above
|
|
||||||
// copyright notice and this permission notice is present in all copies. The
|
|
||||||
// full license for this software is available in the LICENSE file.
|
|
||||||
|
|
||||||
using namespace ircd;
|
|
||||||
|
|
||||||
mapi::header
|
|
||||||
IRCD_MODULE
|
|
||||||
{
|
|
||||||
"Matrix state library; modular components."
|
|
||||||
};
|
|
||||||
|
|
||||||
namespace ircd::m::state
|
|
||||||
{
|
|
||||||
extern "C" void ircd__m__state__clear(void);
|
|
||||||
extern "C" size_t ircd__m__state__gc(void);
|
|
||||||
}
|
|
||||||
|
|
||||||
size_t
|
|
||||||
ircd::m::state::ircd__m__state__gc()
|
|
||||||
{
|
|
||||||
std::set<id_buffer> heads;
|
|
||||||
{
|
|
||||||
const db::gopts opts{db::get::NO_CACHE};
|
|
||||||
//opts.readahead = 4_MiB;
|
|
||||||
|
|
||||||
db::column &column{m::dbs::room_events};
|
|
||||||
for(auto it(column.begin(opts)); it; ++it)
|
|
||||||
{
|
|
||||||
const auto &root(it->second);
|
|
||||||
id_buffer buf;
|
|
||||||
copy(buf, root);
|
|
||||||
heads.emplace(buf);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
std::set<id_buffer> active;
|
|
||||||
for(auto it(begin(heads)); it != end(heads); it = heads.erase(it))
|
|
||||||
{
|
|
||||||
const auto &root(*it);
|
|
||||||
std::cout << "root: " << string_view{root} << std::endl;
|
|
||||||
state::for_each(root, state::iter_bool_closure{[&active]
|
|
||||||
(const json::array &key, const string_view &val)
|
|
||||||
{
|
|
||||||
std::cout << "key: " << key << std::endl;
|
|
||||||
std::cout << "val: " << val << std::endl;
|
|
||||||
return true;
|
|
||||||
}});
|
|
||||||
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
/*
|
|
||||||
static const db::gopts opts
|
|
||||||
{
|
|
||||||
db::get::NO_CACHE
|
|
||||||
};
|
|
||||||
|
|
||||||
auto &column{m::dbs::state_node};
|
|
||||||
for(auto it(column.begin(opts)); it; ++it)
|
|
||||||
{
|
|
||||||
id_buffer buf;
|
|
||||||
const auto &root(it->second);
|
|
||||||
copy(buf, root);
|
|
||||||
active.emplace(buf);
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
size_t ret(active.size());
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
ircd::m::state::ircd__m__state__clear()
|
|
||||||
{
|
|
||||||
auto &column
|
|
||||||
{
|
|
||||||
m::dbs::state_node
|
|
||||||
};
|
|
||||||
|
|
||||||
// Find the key range for the column. The key is copied here so we don't
|
|
||||||
// hold an iterator on it and prevent its demise.
|
|
||||||
std::pair<std::string, std::string> range;
|
|
||||||
{
|
|
||||||
const auto front
|
|
||||||
{
|
|
||||||
column.begin()
|
|
||||||
};
|
|
||||||
|
|
||||||
const auto back
|
|
||||||
{
|
|
||||||
column.rbegin()
|
|
||||||
};
|
|
||||||
|
|
||||||
// If these iterators are invalid there is nothing to delete
|
|
||||||
if(!front || !back)
|
|
||||||
return;
|
|
||||||
|
|
||||||
range =
|
|
||||||
{
|
|
||||||
front->first, back->first
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
db::txn txn
|
|
||||||
{
|
|
||||||
*m::dbs::events
|
|
||||||
};
|
|
||||||
|
|
||||||
db::txn::append
|
|
||||||
{
|
|
||||||
txn, column, db::column::delta
|
|
||||||
{
|
|
||||||
db::op::DELETE_RANGE, range.first, range.second
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
// DELETE_RANGE second key is exclusive and won't be included in the
|
|
||||||
// range so we have to add a single delete for it.
|
|
||||||
db::txn::append
|
|
||||||
{
|
|
||||||
txn, column, db::column::delta
|
|
||||||
{
|
|
||||||
db::op::DELETE, range.second
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
txn();
|
|
||||||
}
|
|
Loading…
Reference in a new issue