0
0
Fork 0
mirror of https://github.com/matrix-construct/construct synced 2024-06-10 22:18:54 +02:00

ircd:Ⓜ️ Remove remaining vestiges of m::state.

closes #15.
This commit is contained in:
Jason Volk 2019-06-14 16:58:49 -06:00
parent 9b34f75e0d
commit 390b8bf2fb
15 changed files with 70 additions and 2336 deletions

View file

@ -55,7 +55,6 @@ namespace ircd::m::dbs::appendix
#include "room_joined.h" // room_id | origin, member => 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 "state_node.h" // node_id => (m::state::node JSON)
/// Options that affect the dbs::write() of an event to the transaction.
struct ircd::m::dbs::write_opts

View file

@ -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;
}

View file

@ -34,7 +34,6 @@ namespace ircd::m::vm
#include "id.h"
#include "event/event.h"
#include "dbs/dbs.h"
#include "state.h"
#include "vm.h"
#include "invite_3pid.h"
#include "createroom.h"

View file

@ -56,7 +56,6 @@ struct ircd::m::room::messages
event::id::buf event_id() const; // deprecated; will remove
event::idx event_idx() 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;

View file

@ -33,13 +33,10 @@ struct ircd::m::room::state
using closure_bool = std::function<bool (const string_view &, const string_view &, const event::idx &)>;
IRCD_STRONG_TYPEDEF(string_view, type_prefix)
static conf::item<bool> disable_history;
static conf::item<size_t> readahead_size;
room::id room_id;
event::id::buf event_id;
m::state::id_buffer root_id_buf;
m::state::id root_id;
const event::fetch::opts *fopts {nullptr};
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 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 bool force_present(const event &);
static size_t purge_replaced(const state &);

View file

@ -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
);

View file

@ -88,7 +88,7 @@ IRCD_MAPI_VERSION
constexpr const ircd::mapi::serial_t
IRCD_MAPI_SERIAL
{
2
3
};
/// Module Header

View file

@ -150,7 +150,6 @@ endif
libircd_la_SOURCES += m_name.cc
libircd_la_SOURCES += m_id.cc
libircd_la_SOURCES += m_dbs.cc
libircd_la_SOURCES += m_state.cc
libircd_la_SOURCES += m_room.cc
libircd_la_SOURCES += m_v1.cc
libircd_la_SOURCES += m.cc

View file

@ -198,7 +198,6 @@ ircd::m::module_names
"s_feds",
"s_node",
"m_events",
"m_state",
"m_rooms",
"m_user",
"m_room_aliases",

View file

@ -76,11 +76,6 @@ decltype(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;
/// note this conf item is only effective by setting an environmental variable
/// 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_state = db::domain{*events, desc::events__room_state.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
@ -1350,106 +1344,6 @@ ircd::m::dbs::find_event_idx(const event::id &event_id,
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
//
@ -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:
///
/// [room_id | depth + event_idx => state_root]
/// [room_id | depth + event_idx]
///
/// 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.
/// 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
ircd::m::dbs::desc::events__room_events
{
@ -2748,9 +2631,9 @@ ircd::m::dbs::desc::events__room_events
"_room_events",
// 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),
};
//
// 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
//
@ -4355,6 +4133,7 @@ namespace ircd::m::dbs::desc
extern const ircd::db::comparator events__event_auth__cmp;
extern const ircd::db::prefix_transform events__event_auth__pfx;
extern const ircd::db::descriptor events__event_bad;
extern const ircd::db::descriptor events__state_node;
//
// Required by RocksDB
@ -4752,6 +4531,38 @@ ircd::m::dbs::desc::events_signatures
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
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.
events__event_type,
// (room_id, (depth, event_idx)) => (state_root)
// (room_id, (depth, event_idx))
// Sequence of all events for a room, ever.
events__room_events,
// (room_id, (origin, user_id)) => ()
// (room_id, (origin, user_id))
// Sequence of all PRESENTLY JOINED joined for a room.
events__room_joined,
@ -4863,10 +4674,6 @@ ircd::m::dbs::desc::events
// Sequence of all states of the room.
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)
// Mapping of all current head events for a room.
events__room_head,
@ -4884,4 +4691,5 @@ ircd::m::dbs::desc::events
events_signatures,
events__event_auth,
events__event_bad,
events__state_node,
};

View file

@ -165,18 +165,6 @@ ircd::m::room::state::rebuild_present(const state &state)
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
{
extern conf::item<ulong> state__prefetch__yield_modulus;
@ -1826,14 +1814,6 @@ const
return ret;
}
ircd::string_view
ircd::m::room::messages::state_root()
const
{
assert(bool(*this));
return it->second;
}
uint64_t
ircd::m::room::messages::depth()
const
@ -1878,13 +1858,6 @@ ircd::m::room::messages::fetch(std::nothrow_t)
// 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)
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{}
}
,root_id
{
event_id && !bool(disable_history)?
dbs::state_root(root_id_buf, room_id, event_id):
m::state::id{}
}
,fopts
{
fopts?
@ -1993,32 +1960,14 @@ void
ircd::m::room::state::get(const string_view &type,
const string_view &state_key,
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]
(const event::idx &idx)
{
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
ircd::m::room::state::get(const string_view &type,
@ -2027,11 +1976,10 @@ ircd::m::room::state::get(const string_view &type,
const try
{
if(!present())
m::state::get(root_id, type, state_key, [&closure]
(const string_view &event_id)
{
closure(index(m::event::id(unquote(event_id))));
});
{
assert(0);
return;
}
auto &column{dbs::room_state};
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
{
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]
(const event::idx &idx)
{
@ -2101,11 +2042,10 @@ ircd::m::room::state::get(std::nothrow_t,
const
{
if(!present())
return m::state::get(std::nothrow, root_id, type, state_key, [&closure]
(const string_view &event_id)
{
return closure(index(m::event::id(unquote(event_id)), std::nothrow));
});
{
assert(0);
return false;
}
auto &column{dbs::room_state};
char key[dbs::ROOM_STATE_KEY_MAX_SIZE];
@ -2132,9 +2072,10 @@ ircd::m::room::state::has(const string_view &type,
const
{
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};
char key[dbs::ROOM_STATE_KEY_MAX_SIZE];
@ -2152,9 +2093,6 @@ size_t
ircd::m::room::state::count(const string_view &type)
const
{
if(!present())
return m::state::count(root_id, type);
size_t ret{0};
for_each(type, event::closure_idx{[&ret]
(const event::idx &event_idx)
@ -2213,13 +2151,6 @@ bool
ircd::m::room::state::for_each(const event::id::closure_bool &closure)
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]
(const event::idx &idx)
{
@ -2262,12 +2193,10 @@ ircd::m::room::state::for_each(const closure_bool &closure)
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)
{
const auto idx(index(m::event::id(unquote(event_id)), std::nothrow));
return closure(key.at(0), key.at(1), idx);
}});
{
assert(0);
return true;
}
db::gopts opts
{
@ -2396,13 +2325,6 @@ ircd::m::room::state::for_each(const string_view &type,
const event::id::closure_bool &closure)
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]
(const event::idx &idx)
{
@ -2437,12 +2359,10 @@ ircd::m::room::state::for_each(const string_view &type,
const
{
if(!present())
return m::state::for_each(root_id, type, state_key_lb, [&closure]
(const json::array &key, const string_view &event_id)
{
const auto idx(index(m::event::id(unquote(event_id)), std::nothrow));
return closure(key.at(0), key.at(1), idx);
});
{
assert(0);
return true;
}
char keybuf[dbs::ROOM_STATE_KEY_MAX_SIZE];
const auto &key
@ -2505,12 +2425,10 @@ ircd::m::room::state::for_each(const string_view &type,
const
{
if(!present())
return m::state::for_each(root_id, type, state_key_lb, [&closure]
(const json::array &key, const string_view &event_id)
{
assert(size(key) >= 2);
return closure(unquote(key.at(1)));
});
{
assert(0);
return true;
}
char keybuf[dbs::ROOM_STATE_KEY_MAX_SIZE];
const auto &key
@ -2582,24 +2500,10 @@ const
{
string_view last;
char lastbuf[m::event::TYPE_MAX_SIZE];
if(!present())
{
m::state::for_each(root_id, m::state::iter_bool_closure{[&closure, &last, &lastbuf]
(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);
}});
assert(0);
return true;
}
@ -2653,15 +2557,6 @@ const
if(!event_id)
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
// before doing any real work/IO below. If this function ever returned
// false it will never return true after.
@ -2678,17 +2573,6 @@ const
if(!head_id || head_id == event_id)
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
// 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

File diff suppressed because it is too large Load diff

View file

@ -118,7 +118,6 @@ m_presence_la_SOURCES = m_presence.cc
m_direct_to_device_la_SOURCES = m_direct_to_device.cc
m_device_list_update_la_SOURCES = m_device_list_update.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_rooms_la_SOURCES = m_rooms.cc
m_room_create_la_SOURCES = m_room_create.cc
@ -142,7 +141,6 @@ m_module_LTLIBRARIES = \
m_direct_to_device.la \
m_device_list_update.la \
m_ignored_user_list.la \
m_state.la \
m_events.la \
m_rooms.la \
m_room_create.la \

View file

@ -7122,161 +7122,6 @@ console_cmd__event__refs__auth(opt &out, const string_view &line)
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
//
@ -8925,66 +8770,6 @@ console_cmd__room__state__rebuild__present(opt &out, const string_view &line)
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
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))
};
const bool roots
{
has(out.special, "roots")
};
const m::room room
{
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)
if(roots)
out << std::setw(48) << std::left << it.state_root()
<< " " << std::setw(8) << std::right << it.event_idx()
<< " " << 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;
out << std::left << std::setw(10) << it.event_idx() << " "
<< pretty_oneline(*it)
<< std::endl;
return true;
}
@ -9346,14 +9119,6 @@ console_cmd__room__timeline__rebuild(opt &out, const string_view &line)
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
console_cmd__room__get(opt &out, const string_view &line)
{

View file

@ -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();
}