mirror of
https://github.com/matrix-construct/construct
synced 2024-11-29 10:12:39 +01:00
ircd:Ⓜ️ Convert db column keys to binary integers over a continuous sequence space.
This commit is contained in:
parent
e6a80082c8
commit
eefc7430bc
8 changed files with 809 additions and 330 deletions
|
@ -27,10 +27,11 @@ namespace ircd::m::dbs
|
|||
|
||||
// Event metadata columns
|
||||
extern db::column event_seq;
|
||||
extern db::column state_node;
|
||||
extern db::column event_idx;
|
||||
extern db::index room_events;
|
||||
extern db::index room_joined;
|
||||
extern db::index room_state;
|
||||
extern db::column state_node;
|
||||
|
||||
// Lowlevel util
|
||||
string_view room_state_key(const mutable_buffer &out, const id::room &, const string_view &type, const string_view &state_key);
|
||||
|
@ -41,14 +42,17 @@ namespace ircd::m::dbs
|
|||
string_view room_joined_key(const mutable_buffer &out, const id::room &, const string_view &origin);
|
||||
std::pair<string_view, string_view> room_joined_key(const string_view &amalgam);
|
||||
|
||||
string_view room_events_key(const mutable_buffer &out, const id::room &, const uint64_t &depth, const id::event &);
|
||||
string_view room_events_key(const mutable_buffer &out, const id::room &, const uint64_t &depth, const event::idx &);
|
||||
string_view room_events_key(const mutable_buffer &out, const id::room &, const uint64_t &depth);
|
||||
std::pair<uint64_t, string_view> room_events_key(const string_view &amalgam);
|
||||
std::pair<uint64_t, event::idx> room_events_key(const string_view &amalgam);
|
||||
|
||||
// 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 id::event &, const uint64_t &depth);
|
||||
string_view state_root(const mutable_buffer &out, const id::room &, const id::event &);
|
||||
string_view state_root(const mutable_buffer &out, const id::event &);
|
||||
// [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 &);
|
||||
|
||||
// [SET (txn)] Basic write suite
|
||||
|
@ -57,6 +61,7 @@ namespace ircd::m::dbs
|
|||
|
||||
struct ircd::m::dbs::write_opts
|
||||
{
|
||||
uint64_t idx {0};
|
||||
string_view root_in;
|
||||
mutable_buffer root_out;
|
||||
db::op op {db::op::SET};
|
||||
|
@ -97,9 +102,11 @@ namespace ircd::m::dbs::desc
|
|||
//
|
||||
|
||||
// events sequence
|
||||
extern const db::comparator events__event_seq__cmp;
|
||||
extern const database::descriptor events__event_seq;
|
||||
|
||||
// events index
|
||||
extern const database::descriptor events__event_idx;
|
||||
|
||||
// room events sequence
|
||||
extern const db::prefix_transform events__room_events__pfx;
|
||||
extern const db::comparator events__room_events__cmp;
|
||||
|
|
|
@ -84,8 +84,11 @@ struct ircd::m::event
|
|||
|
||||
// Common convenience aliases
|
||||
using id = m::id::event;
|
||||
using idx = uint64_t;
|
||||
using closure = std::function<void (const event &)>;
|
||||
using closure_bool = std::function<bool (const event &)>;
|
||||
using closure_idx = std::function<void (const idx &)>;
|
||||
using closure_idx_bool = std::function<bool (const idx &)>;
|
||||
using closure_iov_mutable = std::function<void (json::iov &)>;
|
||||
|
||||
static constexpr size_t MAX_SIZE = 64_KiB;
|
||||
|
@ -123,6 +126,7 @@ struct ircd::m::event
|
|||
using super_type::tuple;
|
||||
using super_type::operator=;
|
||||
|
||||
event(const idx &, const mutable_buffer &buf);
|
||||
event(const id &, const mutable_buffer &buf);
|
||||
event() = default;
|
||||
};
|
||||
|
@ -168,15 +172,27 @@ struct ircd::m::event::fetch
|
|||
{
|
||||
std::array<db::cell, event::size()> cell;
|
||||
db::row row;
|
||||
bool valid;
|
||||
|
||||
bool valid(const event::id &) const;
|
||||
|
||||
fetch(const event::id &, std::nothrow_t);
|
||||
fetch(const event::id &);
|
||||
public:
|
||||
fetch(const idx &, std::nothrow_t);
|
||||
fetch(const idx &);
|
||||
fetch(const id &, std::nothrow_t);
|
||||
fetch(const id &);
|
||||
fetch();
|
||||
|
||||
friend bool seek(fetch &, const event::id &, std::nothrow_t);
|
||||
friend void seek(fetch &, const event::id &);
|
||||
static bool event_id(const idx &, std::nothrow_t, const id::closure &);
|
||||
static void event_id(const idx &, const id::closure &);
|
||||
|
||||
static idx index(const id &, std::nothrow_t);
|
||||
static idx index(const id &);
|
||||
static idx index(const event &, std::nothrow_t);
|
||||
static idx index(const event &);
|
||||
|
||||
friend bool seek(fetch &, const idx &, std::nothrow_t);
|
||||
friend void seek(fetch &, const idx &);
|
||||
friend bool seek(fetch &, const id &, std::nothrow_t);
|
||||
friend void seek(fetch &, const id &);
|
||||
};
|
||||
|
||||
/// Device to evaluate the conformity of an event object. This is an 'in vitro'
|
||||
|
|
|
@ -113,13 +113,17 @@ struct ircd::m::room
|
|||
operator const id &() const;
|
||||
|
||||
// Convenience passthru to room::messages (linear query; newest first)
|
||||
void for_each(const string_view &type, const event::id::closure_bool &) const;
|
||||
bool for_each(const string_view &type, const event::closure_idx_bool &) const;
|
||||
void for_each(const string_view &type, const event::closure_idx &) const;
|
||||
bool for_each(const string_view &type, const event::id::closure_bool &) const;
|
||||
void for_each(const string_view &type, const event::id::closure &) const;
|
||||
void for_each(const string_view &type, const event::closure_bool &) const;
|
||||
bool for_each(const string_view &type, const event::closure_bool &) const;
|
||||
void for_each(const string_view &type, const event::closure &) const;
|
||||
void for_each(const event::id::closure_bool &) const;
|
||||
bool for_each(const event::closure_idx_bool &) const;
|
||||
void for_each(const event::closure_idx &) const;
|
||||
bool for_each(const event::id::closure_bool &) const;
|
||||
void for_each(const event::id::closure &) const;
|
||||
void for_each(const event::closure_bool &) const;
|
||||
bool for_each(const event::closure_bool &) const;
|
||||
void for_each(const event::closure &) const;
|
||||
|
||||
// Convenience passthru to room::state (logarithmic query)
|
||||
|
@ -155,22 +159,22 @@ struct ircd::m::room
|
|||
/// This interface has the form of an STL-style iterator over room messages
|
||||
/// which are state and non-state events from all integrated timelines.
|
||||
/// Moving the iterator is cheap, but the dereference operators fetch a
|
||||
/// full event. One can iterate just event_id's by using event_id() instead
|
||||
/// full event. One can iterate just event_idx's by using event_idx() instead
|
||||
/// of the dereference operators.
|
||||
///
|
||||
struct ircd::m::room::messages
|
||||
{
|
||||
m::room room;
|
||||
db::index::const_iterator it;
|
||||
event::id _event_id;
|
||||
event::idx _event_idx;
|
||||
event::fetch _event;
|
||||
|
||||
public:
|
||||
operator bool() const { return bool(it); }
|
||||
bool operator!() const { return !it; }
|
||||
|
||||
const event::id &event_id();
|
||||
operator const event::id &();
|
||||
event::id::buf event_id(); // deprecated; will remove
|
||||
const event::idx &event_idx();
|
||||
|
||||
const m::event &fetch(std::nothrow_t);
|
||||
const m::event &fetch();
|
||||
|
@ -218,17 +222,22 @@ struct ircd::m::room::state
|
|||
|
||||
// Iterate the state; for_each protocol
|
||||
void for_each(const string_view &type, const keys &) const;
|
||||
void for_each(const string_view &type, const event::closure_idx &) const;
|
||||
void for_each(const string_view &type, const event::id::closure &) const;
|
||||
void for_each(const string_view &type, const event::closure &) const;
|
||||
void for_each(const event::closure_idx &) const;
|
||||
void for_each(const event::id::closure &) const;
|
||||
void for_each(const event::closure &) const;
|
||||
|
||||
// Iterate the state; test protocol
|
||||
bool test(const string_view &type, const string_view &lower_bound, const event::closure_idx_bool &view) const;
|
||||
bool test(const string_view &type, const string_view &lower_bound, const event::id::closure_bool &view) const;
|
||||
bool test(const string_view &type, const string_view &lower_bound, const event::closure_bool &view) const;
|
||||
bool test(const string_view &type, const keys_bool &view) const;
|
||||
bool test(const string_view &type, const event::closure_idx_bool &view) const;
|
||||
bool test(const string_view &type, const event::id::closure_bool &view) const;
|
||||
bool test(const string_view &type, const event::closure_bool &view) const;
|
||||
bool test(const event::closure_idx_bool &view) const;
|
||||
bool test(const event::id::closure_bool &view) const;
|
||||
bool test(const event::closure_bool &view) const;
|
||||
|
||||
|
@ -241,8 +250,10 @@ struct ircd::m::room::state
|
|||
bool has(const string_view &type) const;
|
||||
|
||||
// Fetch a state event
|
||||
bool get(std::nothrow_t, const string_view &type, const string_view &state_key, const event::closure_idx &) const;
|
||||
bool get(std::nothrow_t, const string_view &type, const string_view &state_key, const event::id::closure &) const;
|
||||
bool get(std::nothrow_t, const string_view &type, const string_view &state_key, const event::closure &) const;
|
||||
void get(const string_view &type, const string_view &state_key, const event::closure_idx &) const;
|
||||
void get(const string_view &type, const string_view &state_key, const event::id::closure &) const;
|
||||
void get(const string_view &type, const string_view &state_key, const event::closure &) const;
|
||||
|
||||
|
|
|
@ -33,15 +33,15 @@ namespace ircd::m::vm
|
|||
|
||||
namespace ircd::m::vm::events
|
||||
{
|
||||
using id_closure_bool = std::function<bool (const uint64_t &, const event::id &)>;
|
||||
using idx_closure_bool = std::function<bool (const uint64_t &, const event::idx &)>;
|
||||
using closure_bool = std::function<bool (const uint64_t &, const event &)>;
|
||||
|
||||
// counts up from start
|
||||
bool for_each(const uint64_t &start, const id_closure_bool &);
|
||||
bool for_each(const uint64_t &start, const idx_closure_bool &);
|
||||
bool for_each(const uint64_t &start, const closure_bool &);
|
||||
|
||||
// -1 starts at newest event; counts down
|
||||
bool rfor_each(const uint64_t &start, const id_closure_bool &);
|
||||
bool rfor_each(const uint64_t &start, const idx_closure_bool &);
|
||||
bool rfor_each(const uint64_t &start, const closure_bool &);
|
||||
}
|
||||
|
||||
|
|
376
ircd/m/dbs.cc
376
ircd/m/dbs.cc
|
@ -28,6 +28,11 @@ decltype(ircd::m::dbs::event_seq)
|
|||
ircd::m::dbs::event_seq
|
||||
{};
|
||||
|
||||
/// Linkage for a reference to the event_seq column.
|
||||
decltype(ircd::m::dbs::event_idx)
|
||||
ircd::m::dbs::event_idx
|
||||
{};
|
||||
|
||||
/// Linkage for a reference to the state_node column.
|
||||
decltype(ircd::m::dbs::state_node)
|
||||
ircd::m::dbs::state_node
|
||||
|
@ -73,6 +78,7 @@ ircd::m::dbs::init::init(std::string dbopts)
|
|||
|
||||
// Cache the columns for the metadata
|
||||
event_seq = db::column{*events, desc::events__event_seq.name};
|
||||
event_idx = db::column{*events, desc::events__event_idx.name};
|
||||
state_node = db::column{*events, desc::events__state_node.name};
|
||||
room_events = db::index{*events, desc::events__room_events.name};
|
||||
room_joined = db::index{*events, desc::events__room_joined.name};
|
||||
|
@ -112,9 +118,21 @@ ircd::m::dbs::write(db::txn &txn,
|
|||
const event &event,
|
||||
const write_opts &opts)
|
||||
{
|
||||
assert(opts.idx != 0);
|
||||
|
||||
db::txn::append
|
||||
{
|
||||
txn, at<"event_id"_>(event), event, event_column, opts.op
|
||||
txn, dbs::event_idx,
|
||||
{
|
||||
db::op::SET,
|
||||
at<"event_id"_>(event),
|
||||
byte_view<string_view>(opts.idx)
|
||||
}
|
||||
};
|
||||
|
||||
db::txn::append
|
||||
{
|
||||
txn, byte_view<string_view>(opts.idx), event, event_column, opts.op
|
||||
};
|
||||
|
||||
if(defined(json::get<"state_key"_>(event)))
|
||||
|
@ -151,7 +169,7 @@ try
|
|||
target_id, std::nothrow
|
||||
};
|
||||
|
||||
if(unlikely(!target.valid(target_id)))
|
||||
if(unlikely(!target.valid))
|
||||
log::error
|
||||
{
|
||||
"Redaction from '%s' missing redaction target '%s'",
|
||||
|
@ -230,10 +248,10 @@ ircd::m::dbs::_index__room_events(db::txn &txn,
|
|||
const string_view &new_root)
|
||||
{
|
||||
const ctx::critical_assertion ca;
|
||||
thread_local char buf[768];
|
||||
thread_local char buf[256 + 1 + 8 + 8];
|
||||
const string_view &key
|
||||
{
|
||||
room_events_key(buf, at<"room_id"_>(event), at<"depth"_>(event), at<"event_id"_>(event))
|
||||
room_events_key(buf, at<"room_id"_>(event), at<"depth"_>(event), opts.idx)
|
||||
};
|
||||
|
||||
db::txn::append
|
||||
|
@ -321,9 +339,9 @@ ircd::m::dbs::_index__room_state(db::txn &txn,
|
|||
room_state_key(buf, at<"room_id"_>(event), at<"type"_>(event), at<"state_key"_>(event))
|
||||
};
|
||||
|
||||
const string_view &val
|
||||
const string_view val
|
||||
{
|
||||
at<"event_id"_>(event)
|
||||
byte_view<string_view>(opts.idx)
|
||||
};
|
||||
|
||||
const db::op op
|
||||
|
@ -354,6 +372,13 @@ ircd::m::dbs::state_root(const mutable_buffer &out,
|
|||
ircd::string_view
|
||||
ircd::m::dbs::state_root(const mutable_buffer &out,
|
||||
const id::event &event_id)
|
||||
{
|
||||
return state_root(out, event::fetch::index(event_id));
|
||||
}
|
||||
|
||||
ircd::string_view
|
||||
ircd::m::dbs::state_root(const mutable_buffer &out,
|
||||
const event::idx &event_idx)
|
||||
{
|
||||
static constexpr auto idx
|
||||
{
|
||||
|
@ -366,18 +391,27 @@ ircd::m::dbs::state_root(const mutable_buffer &out,
|
|||
};
|
||||
|
||||
id::room::buf room_id;
|
||||
column(event_id, [&room_id](const string_view &val)
|
||||
column(byte_view<string_view>(event_idx), [&room_id]
|
||||
(const string_view &val)
|
||||
{
|
||||
room_id = val;
|
||||
});
|
||||
|
||||
return state_root(out, room_id, event_id);
|
||||
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, event::fetch::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
|
||||
{
|
||||
|
@ -390,13 +424,13 @@ ircd::m::dbs::state_root(const mutable_buffer &out,
|
|||
};
|
||||
|
||||
uint64_t depth;
|
||||
column(event_id, [&](const string_view &binary)
|
||||
column(byte_view<string_view>(event_idx), [&depth]
|
||||
(const string_view &binary)
|
||||
{
|
||||
assert(size(binary) == sizeof(depth));
|
||||
depth = byte_view<uint64_t>(binary);
|
||||
});
|
||||
|
||||
return state_root(out, room_id, event_id, depth);
|
||||
return state_root(out, room_id, event_idx, depth);
|
||||
}
|
||||
|
||||
ircd::string_view
|
||||
|
@ -405,9 +439,18 @@ ircd::m::dbs::state_root(const mutable_buffer &out,
|
|||
const id::event &event_id,
|
||||
const uint64_t &depth)
|
||||
{
|
||||
char keybuf[768]; const auto key
|
||||
return state_root(out, room_id, event::fetch::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[256 + 1 + 8 + 8]; const auto key
|
||||
{
|
||||
room_events_key(keybuf, room_id, depth, event_id)
|
||||
room_events_key(keybuf, room_id, depth, event_idx)
|
||||
};
|
||||
|
||||
string_view ret;
|
||||
|
@ -423,62 +466,6 @@ ircd::m::dbs::state_root(const mutable_buffer &out,
|
|||
// Database descriptors
|
||||
//
|
||||
|
||||
/// 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::database::descriptor
|
||||
ircd::m::dbs::desc::events__state_node
|
||||
{
|
||||
// name
|
||||
"_state_node",
|
||||
|
||||
// explanation
|
||||
R"(### developer note:
|
||||
|
||||
)",
|
||||
|
||||
// typing (key, value)
|
||||
{
|
||||
typeid(ircd::string_view), typeid(ircd::string_view)
|
||||
},
|
||||
|
||||
// options
|
||||
{},
|
||||
|
||||
// comparator
|
||||
{},
|
||||
|
||||
// prefix transform
|
||||
{},
|
||||
|
||||
// cache size
|
||||
96_MiB, //TODO: conf
|
||||
|
||||
// cache size for compressed assets
|
||||
24_MiB, //TODO: conf
|
||||
};
|
||||
|
||||
const ircd::db::comparator
|
||||
ircd::m::dbs::desc::events__event_seq__cmp
|
||||
{
|
||||
"_event_seq",
|
||||
|
||||
// less
|
||||
[](const string_view &sa, const string_view &sb)
|
||||
{
|
||||
const byte_view<uint64_t> a{sa}, b{sb};
|
||||
return a < b;
|
||||
},
|
||||
|
||||
// equal
|
||||
[](const string_view &sa, const string_view &sb)
|
||||
{
|
||||
const byte_view<uint64_t> a{sa}, b{sb};
|
||||
return a == b;
|
||||
},
|
||||
};
|
||||
|
||||
const ircd::database::descriptor
|
||||
ircd::m::dbs::desc::events__event_seq
|
||||
{
|
||||
|
@ -488,19 +475,23 @@ ircd::m::dbs::desc::events__event_seq
|
|||
// explanation
|
||||
R"(### developer note:
|
||||
|
||||
Sequence counter.
|
||||
The key is an integer given by the m::vm. The value is the index number to
|
||||
be used as the key to all the event data columns. At the time of this
|
||||
comment these are actually the same thing.
|
||||
|
||||
)",
|
||||
|
||||
// typing (key, value)
|
||||
{
|
||||
typeid(uint64_t), typeid(ircd::string_view)
|
||||
typeid(uint64_t), typeid(uint64_t)
|
||||
},
|
||||
|
||||
// options
|
||||
{},
|
||||
|
||||
// comparator
|
||||
events__event_seq__cmp,
|
||||
{},
|
||||
|
||||
// prefix transform
|
||||
{},
|
||||
|
@ -515,6 +506,44 @@ ircd::m::dbs::desc::events__event_seq
|
|||
0, // no bloom filter because of possible comparator issues
|
||||
};
|
||||
|
||||
const ircd::database::descriptor
|
||||
ircd::m::dbs::desc::events__event_idx
|
||||
{
|
||||
// name
|
||||
"_event_idx",
|
||||
|
||||
// explanation
|
||||
R"(### developer note:
|
||||
|
||||
The key is an event_id and the value is the index number to be used as the
|
||||
key to all the event data columns.
|
||||
|
||||
)",
|
||||
|
||||
// typing (key, value)
|
||||
{
|
||||
typeid(string_view), typeid(uint64_t)
|
||||
},
|
||||
|
||||
// options
|
||||
{},
|
||||
|
||||
// comparator
|
||||
{},
|
||||
|
||||
// prefix transform
|
||||
{},
|
||||
|
||||
// cache size
|
||||
64_MiB, //TODO: conf
|
||||
|
||||
// cache size for compressed assets
|
||||
16_MiB, //TODO: conf
|
||||
|
||||
// bloom filter bits
|
||||
12,
|
||||
};
|
||||
|
||||
/// Prefix transform for the events__room_events. The prefix here is a room_id
|
||||
/// and the suffix is the depth+event_id concatenation.
|
||||
/// for efficient sequences
|
||||
|
@ -571,11 +600,11 @@ ircd::m::dbs::desc::events__room_events__cmp
|
|||
if(pre[0] != pre[1])
|
||||
return pre[0] < pre[1];
|
||||
|
||||
// After the prefix is the depth + event_id
|
||||
// After the prefix is the depth + event_idx
|
||||
const string_view post[2]
|
||||
{
|
||||
a.substr(size(pre[0])),
|
||||
b.substr(size(pre[1])),
|
||||
a.substr(sizes[0]),
|
||||
b.substr(sizes[1]),
|
||||
};
|
||||
|
||||
if(empty(post[0]))
|
||||
|
@ -585,17 +614,10 @@ ircd::m::dbs::desc::events__room_events__cmp
|
|||
return false;
|
||||
|
||||
// Now want just the depth...
|
||||
const string_view depths[2]
|
||||
const uint64_t depth[2]
|
||||
{
|
||||
between(post[0], "\0"_sv, "$"_sv),
|
||||
between(post[1], "\0"_sv, "$"_sv),
|
||||
};
|
||||
|
||||
// ...as machine words
|
||||
const int64_t depth[2]
|
||||
{
|
||||
lex_cast<int64_t>(depths[0]),
|
||||
lex_cast<int64_t>(depths[1]),
|
||||
room_events_key(post[0]).first,
|
||||
room_events_key(post[1]).first,
|
||||
};
|
||||
|
||||
// Highest to lowest sort so highest is first
|
||||
|
@ -608,10 +630,15 @@ ircd::m::dbs::room_events_key(const mutable_buffer &out_,
|
|||
const id::room &room_id,
|
||||
const uint64_t &depth)
|
||||
{
|
||||
const const_buffer depth_cb
|
||||
{
|
||||
reinterpret_cast<const char *>(&depth), sizeof(depth)
|
||||
};
|
||||
|
||||
mutable_buffer out{out_};
|
||||
consume(out, copy(out, room_id));
|
||||
consume(out, copy(out, "\0"_sv));
|
||||
consume(out, copy(out, lex_cast(depth)));
|
||||
consume(out, copy(out, depth_cb));
|
||||
return { data(out_), data(out) };
|
||||
}
|
||||
|
||||
|
@ -619,39 +646,52 @@ ircd::string_view
|
|||
ircd::m::dbs::room_events_key(const mutable_buffer &out_,
|
||||
const id::room &room_id,
|
||||
const uint64_t &depth,
|
||||
const id::event &event_id)
|
||||
const event::idx &event_idx)
|
||||
{
|
||||
const const_buffer depth_cb
|
||||
{
|
||||
reinterpret_cast<const char *>(&depth), sizeof(depth)
|
||||
};
|
||||
|
||||
const const_buffer event_idx_cb
|
||||
{
|
||||
reinterpret_cast<const char *>(&event_idx), sizeof(event_idx)
|
||||
};
|
||||
|
||||
mutable_buffer out{out_};
|
||||
consume(out, copy(out, room_id));
|
||||
consume(out, copy(out, "\0"_sv));
|
||||
consume(out, copy(out, lex_cast(depth)));
|
||||
consume(out, copy(out, event_id));
|
||||
consume(out, copy(out, depth_cb));
|
||||
consume(out, copy(out, event_idx_cb));
|
||||
return { data(out_), data(out) };
|
||||
}
|
||||
|
||||
std::pair<uint64_t, ircd::string_view>
|
||||
std::pair<uint64_t, ircd::m::event::idx>
|
||||
ircd::m::dbs::room_events_key(const string_view &amalgam)
|
||||
{
|
||||
const auto &key
|
||||
assert(size(amalgam) == 1 + 8 + 8 || size(amalgam) == 1 + 8);
|
||||
assert(amalgam.front() == '\0');
|
||||
|
||||
const uint64_t &depth
|
||||
{
|
||||
lstrip(amalgam, "\0"_sv)
|
||||
*reinterpret_cast<const uint64_t *>(data(amalgam) + 1)
|
||||
};
|
||||
|
||||
const auto &s
|
||||
const event::idx &event_idx
|
||||
{
|
||||
split(key, "$"_sv)
|
||||
size(amalgam) >= 1 + 8 + 8?
|
||||
*reinterpret_cast<const uint64_t *>(data(amalgam) + 1 + 8):
|
||||
0UL
|
||||
};
|
||||
|
||||
return
|
||||
{
|
||||
lex_cast<uint64_t>(s.first),
|
||||
{ end(s.first), end(s.second) }
|
||||
};
|
||||
// Make sure these are copied rather than ever returning references in
|
||||
// a tuple because the chance the integers will be aligned is low.
|
||||
return { depth, event_idx };
|
||||
}
|
||||
|
||||
/// This column stores events in sequence in a room. Consider the following:
|
||||
///
|
||||
/// [room_id | depth + event_id => state_root]
|
||||
/// [room_id | depth + event_idx => state_root]
|
||||
///
|
||||
/// The key is composed from three parts:
|
||||
///
|
||||
|
@ -661,17 +701,19 @@ ircd::m::dbs::room_events_key(const string_view &amalgam)
|
|||
///
|
||||
/// - `depth` is the ordering. Within the sequence, all elements are ordered by
|
||||
/// depth from HIGHEST TO LOWEST. The sequence will start at the highest depth.
|
||||
/// NOTE: Depth is a fixed 8 byte binary integer.
|
||||
///
|
||||
/// - `event_id` is the key suffix. This column serves to sequence all events
|
||||
/// - `event_idx` is the key suffix. This column serves to sequence all events
|
||||
/// within a room ordered by depth. There may be duplicate room_id|depth
|
||||
/// prefixing but the event_id 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.
|
||||
///
|
||||
/// 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_id
|
||||
/// 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
|
||||
|
@ -693,7 +735,7 @@ ircd::m::dbs::desc::events__room_events
|
|||
|
||||
// typing (key, value)
|
||||
{
|
||||
typeid(ircd::string_view), typeid(ircd::string_view)
|
||||
typeid(string_view), typeid(string_view)
|
||||
},
|
||||
|
||||
// options
|
||||
|
@ -801,7 +843,7 @@ ircd::m::dbs::desc::events__room_joined
|
|||
|
||||
// typing (key, value)
|
||||
{
|
||||
typeid(ircd::string_view), typeid(ircd::string_view)
|
||||
typeid(string_view), typeid(uint64_t)
|
||||
},
|
||||
|
||||
// options
|
||||
|
@ -904,7 +946,7 @@ ircd::m::dbs::desc::events__room_state
|
|||
|
||||
// typing (key, value)
|
||||
{
|
||||
typeid(ircd::string_view), typeid(ircd::string_view)
|
||||
typeid(string_view), typeid(uint64_t)
|
||||
},
|
||||
|
||||
// options
|
||||
|
@ -923,6 +965,42 @@ ircd::m::dbs::desc::events__room_state
|
|||
32_MiB, //TODO: conf
|
||||
};
|
||||
|
||||
/// 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::database::descriptor
|
||||
ircd::m::dbs::desc::events__state_node
|
||||
{
|
||||
// name
|
||||
"_state_node",
|
||||
|
||||
// explanation
|
||||
R"(### developer note:
|
||||
|
||||
)",
|
||||
|
||||
// typing (key, value)
|
||||
{
|
||||
typeid(ircd::string_view), typeid(ircd::string_view)
|
||||
},
|
||||
|
||||
// options
|
||||
{},
|
||||
|
||||
// comparator
|
||||
{},
|
||||
|
||||
// prefix transform
|
||||
{},
|
||||
|
||||
// cache size
|
||||
96_MiB, //TODO: conf
|
||||
|
||||
// cache size for compressed assets
|
||||
24_MiB, //TODO: conf
|
||||
};
|
||||
|
||||
//
|
||||
// Direct column descriptors
|
||||
//
|
||||
|
@ -943,12 +1021,12 @@ ircd::m::dbs::desc::events_event_id
|
|||
MUST NOT exceed 255 bytes.
|
||||
|
||||
### developer note:
|
||||
key is event_id. This is redundant data but we have to have it for now.
|
||||
key is event_idx number.
|
||||
)",
|
||||
|
||||
// typing (key, value)
|
||||
{
|
||||
typeid(ircd::string_view), typeid(ircd::string_view)
|
||||
typeid(uint64_t), typeid(string_view)
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -969,12 +1047,12 @@ ircd::m::dbs::desc::events_type
|
|||
MUST NOT exceed 255 bytes.
|
||||
|
||||
### developer note:
|
||||
key is event_id
|
||||
key is event_idx number.
|
||||
)",
|
||||
|
||||
// typing (key, value)
|
||||
{
|
||||
typeid(ircd::string_view), typeid(ircd::string_view)
|
||||
typeid(uint64_t), typeid(string_view)
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -995,12 +1073,12 @@ ircd::m::dbs::desc::events_content
|
|||
Since events must not exceed 64 KiB the maximum size for the content is the remaining
|
||||
space after all the other fields for the event are rendered.
|
||||
|
||||
key is event_id
|
||||
key is event_idx number.
|
||||
)",
|
||||
|
||||
// typing (key, value)
|
||||
{
|
||||
typeid(ircd::string_view), typeid(ircd::string_view)
|
||||
typeid(uint64_t), typeid(string_view)
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -1014,13 +1092,13 @@ ircd::m::dbs::desc::events_redacts
|
|||
R"(### protocol note:
|
||||
|
||||
### developer note:
|
||||
key is event_id
|
||||
key is event_idx number.
|
||||
value is targeted event_id
|
||||
)",
|
||||
|
||||
// typing (key, value)
|
||||
{
|
||||
typeid(ircd::string_view), typeid(ircd::string_view)
|
||||
typeid(uint64_t), typeid(string_view)
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -1040,12 +1118,12 @@ ircd::m::dbs::desc::events_room_id
|
|||
MUST NOT exceed 255 bytes.
|
||||
|
||||
### developer note:
|
||||
key is event_id
|
||||
key is event_idx number.
|
||||
)",
|
||||
|
||||
// typing (key, value)
|
||||
{
|
||||
typeid(ircd::string_view), typeid(ircd::string_view)
|
||||
typeid(uint64_t), typeid(string_view)
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -1065,12 +1143,12 @@ ircd::m::dbs::desc::events_sender
|
|||
MUST NOT exceed 255 bytes.
|
||||
|
||||
### developer note:
|
||||
key is event_id
|
||||
key is event_idx number.
|
||||
)",
|
||||
|
||||
// typing (key, value)
|
||||
{
|
||||
typeid(ircd::string_view), typeid(ircd::string_view)
|
||||
typeid(uint64_t), typeid(string_view)
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -1092,12 +1170,12 @@ ircd::m::dbs::desc::events_state_key
|
|||
MUST NOT exceed 255 bytes.
|
||||
|
||||
### developer note:
|
||||
key is event_id
|
||||
key is event_idx number.
|
||||
)",
|
||||
|
||||
// typing (key, value)
|
||||
{
|
||||
typeid(ircd::string_view), typeid(ircd::string_view)
|
||||
typeid(uint64_t), typeid(string_view)
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -1114,12 +1192,12 @@ ircd::m::dbs::desc::events_origin
|
|||
DNS name of homeserver that created this PDU
|
||||
|
||||
### developer note:
|
||||
key is event_id
|
||||
key is event_idx number.
|
||||
)",
|
||||
|
||||
// typing (key, value)
|
||||
{
|
||||
typeid(ircd::string_view), typeid(ircd::string_view)
|
||||
typeid(uint64_t), typeid(string_view)
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -1136,7 +1214,7 @@ ircd::m::dbs::desc::events_origin_server_ts
|
|||
Timestamp in milliseconds on origin homeserver when this PDU was created.
|
||||
|
||||
### developer note:
|
||||
key is event_id
|
||||
key is event_idx number.
|
||||
value is a machine integer (binary)
|
||||
|
||||
TODO: consider unsigned rather than time_t because of millisecond precision
|
||||
|
@ -1145,7 +1223,7 @@ ircd::m::dbs::desc::events_origin_server_ts
|
|||
|
||||
// typing (key, value)
|
||||
{
|
||||
typeid(ircd::string_view), typeid(time_t)
|
||||
typeid(uint64_t), typeid(time_t)
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -1159,13 +1237,13 @@ ircd::m::dbs::desc::events_signatures
|
|||
R"(### protocol note:
|
||||
|
||||
### developer note:
|
||||
key is event_id
|
||||
key is event_idx number.
|
||||
|
||||
)",
|
||||
|
||||
// typing (key, value)
|
||||
{
|
||||
typeid(ircd::string_view), typeid(ircd::string_view)
|
||||
typeid(uint64_t), typeid(string_view)
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -1179,12 +1257,12 @@ ircd::m::dbs::desc::events_auth_events
|
|||
R"(### protocol note:
|
||||
|
||||
### developer note:
|
||||
key is event_id.
|
||||
key is event_idx number..
|
||||
)",
|
||||
|
||||
// typing (key, value)
|
||||
{
|
||||
typeid(ircd::string_view), typeid(ircd::string_view)
|
||||
typeid(uint64_t), typeid(string_view)
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -1198,12 +1276,12 @@ ircd::m::dbs::desc::events_depth
|
|||
R"(### protocol note:
|
||||
|
||||
### developer note:
|
||||
key is event_id value is long integer
|
||||
key is event_idx number. value is long integer
|
||||
)",
|
||||
|
||||
// typing (key, value)
|
||||
{
|
||||
typeid(ircd::string_view), typeid(int64_t)
|
||||
typeid(uint64_t), typeid(int64_t)
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -1217,12 +1295,12 @@ ircd::m::dbs::desc::events_hashes
|
|||
R"(### protocol note:
|
||||
|
||||
### developer note:
|
||||
key is event_id.
|
||||
key is event_idx number..
|
||||
)",
|
||||
|
||||
// typing (key, value)
|
||||
{
|
||||
typeid(ircd::string_view), typeid(ircd::string_view)
|
||||
typeid(uint64_t), typeid(string_view)
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -1236,12 +1314,12 @@ ircd::m::dbs::desc::events_membership
|
|||
R"(### protocol note:
|
||||
|
||||
### developer note:
|
||||
key is event_id.
|
||||
key is event_idx number.
|
||||
)",
|
||||
|
||||
// typing (key, value)
|
||||
{
|
||||
typeid(ircd::string_view), typeid(ircd::string_view)
|
||||
typeid(uint64_t), typeid(string_view)
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -1255,12 +1333,12 @@ ircd::m::dbs::desc::events_prev_events
|
|||
R"(### protocol note:
|
||||
|
||||
### developer note:
|
||||
key is event_id.
|
||||
key is event_idx number.
|
||||
)",
|
||||
|
||||
// typing (key, value)
|
||||
{
|
||||
typeid(ircd::string_view), typeid(ircd::string_view)
|
||||
typeid(uint64_t), typeid(string_view)
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -1274,12 +1352,12 @@ ircd::m::dbs::desc::events_prev_state
|
|||
R"(### protocol note:
|
||||
|
||||
### developer note:
|
||||
key is event_id.
|
||||
key is event_idx number.
|
||||
)",
|
||||
|
||||
// typing (key, value)
|
||||
{
|
||||
typeid(ircd::string_view), typeid(ircd::string_view)
|
||||
typeid(uint64_t), typeid(ircd::string_view)
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -1290,9 +1368,9 @@ ircd::m::dbs::desc::events
|
|||
{ "default" },
|
||||
|
||||
//
|
||||
// These columns directly represent event fields indexed by event_id and
|
||||
// the value is the actual event values. Some values may be JSON, like
|
||||
// content.
|
||||
// These columns directly represent event fields indexed by event_idx
|
||||
// number and the value is the actual event values. Some values may be
|
||||
// JSON, like content.
|
||||
//
|
||||
|
||||
events_auth_events,
|
||||
|
@ -1313,15 +1391,18 @@ ircd::m::dbs::desc::events
|
|||
events_type,
|
||||
|
||||
//
|
||||
// These columns are metadata composed from the event data. Specifically,
|
||||
// they are designed for fast sequential iterations.
|
||||
// These columns are metadata oriented around the event data.
|
||||
//
|
||||
|
||||
// uint64_t => event_id
|
||||
// Sequence of all events counted by the m::vm.
|
||||
// uint64_t => uint64_t
|
||||
// Sequence number to event_idx number counted by the m::vm.
|
||||
events__event_seq,
|
||||
|
||||
// (room_id, (depth, event_id)) => (state_root)
|
||||
// event_id => uint64_t
|
||||
// Mapping of event_id to index number.
|
||||
events__event_idx,
|
||||
|
||||
// (room_id, (depth, event_idx)) => (state_root)
|
||||
// Sequence of all events for a room, ever.
|
||||
events__room_events,
|
||||
|
||||
|
@ -1333,10 +1414,7 @@ ircd::m::dbs::desc::events
|
|||
// Sequence of the PRESENT STATE of the room.
|
||||
events__room_state,
|
||||
|
||||
//
|
||||
// Other columns
|
||||
//
|
||||
|
||||
// (state tree node id) => (state tree node)
|
||||
// Mapping of state tree node id to node data.
|
||||
events__state_node,
|
||||
};
|
||||
|
|
199
ircd/m/event.cc
199
ircd/m/event.cc
|
@ -133,14 +133,9 @@ ircd::m::degree(const event::prev &prev)
|
|||
bool
|
||||
ircd::m::exists(const id::event &event_id)
|
||||
{
|
||||
static constexpr auto idx
|
||||
{
|
||||
json::indexof<event, "event_id"_>()
|
||||
};
|
||||
|
||||
auto &column
|
||||
{
|
||||
dbs::event_column.at(idx)
|
||||
dbs::event_idx
|
||||
};
|
||||
|
||||
return has(column, event_id);
|
||||
|
@ -503,24 +498,35 @@ ircd::m::event::max_size
|
|||
|
||||
ircd::m::event::event(const id &id,
|
||||
const mutable_buffer &buf)
|
||||
:event
|
||||
{
|
||||
fetch::index(id), buf
|
||||
}
|
||||
{
|
||||
}
|
||||
|
||||
ircd::m::event::event(const idx &idx,
|
||||
const mutable_buffer &buf)
|
||||
{
|
||||
assert(bool(dbs::events));
|
||||
|
||||
db::gopts opts;
|
||||
opts.snapshot = database::snapshot{*dbs::events};
|
||||
for(size_t i(0); i < dbs::event_column.size(); ++i)
|
||||
{
|
||||
const db::cell cell
|
||||
{
|
||||
dbs::event_column[i], id, opts
|
||||
dbs::event_column[i], byte_view<string_view>{idx}, opts
|
||||
};
|
||||
|
||||
db::assign(*this, cell, id);
|
||||
db::assign(*this, cell, byte_view<string_view>{idx});
|
||||
}
|
||||
|
||||
const json::object obj
|
||||
{
|
||||
string_view{data(buf), json::print(buf, *this)}
|
||||
string_view
|
||||
{
|
||||
data(buf), json::print(buf, *this)
|
||||
}
|
||||
};
|
||||
|
||||
new (this) m::event(obj);
|
||||
|
@ -1145,15 +1151,128 @@ ircd::m::seek(event::fetch &fetch,
|
|||
const event::id &event_id,
|
||||
std::nothrow_t)
|
||||
{
|
||||
db::seek(fetch.row, string_view{event_id});
|
||||
if(!fetch.row.valid(event_id))
|
||||
const event::idx &event_idx
|
||||
{
|
||||
event::fetch::index(event_id, std::nothrow)
|
||||
};
|
||||
|
||||
return seek(fetch, event_idx, std::nothrow);
|
||||
}
|
||||
|
||||
void
|
||||
ircd::m::seek(event::fetch &fetch,
|
||||
const event::idx &event_idx)
|
||||
{
|
||||
if(!seek(fetch, event_idx, std::nothrow))
|
||||
throw m::NOT_FOUND
|
||||
{
|
||||
"%lu not found in database", event_idx
|
||||
};
|
||||
}
|
||||
|
||||
bool
|
||||
ircd::m::seek(event::fetch &fetch,
|
||||
const event::idx &event_idx,
|
||||
std::nothrow_t)
|
||||
{
|
||||
const string_view &key
|
||||
{
|
||||
byte_view<string_view>(event_idx)
|
||||
};
|
||||
|
||||
db::seek(fetch.row, key);
|
||||
fetch.valid = fetch.row.valid(key);
|
||||
if(!fetch.valid)
|
||||
return false;
|
||||
|
||||
auto &event{static_cast<m::event &>(fetch)};
|
||||
assign(event, fetch.row, event_id);
|
||||
assign(event, fetch.row, key);
|
||||
return true;
|
||||
}
|
||||
|
||||
ircd::m::event::idx
|
||||
ircd::m::event::fetch::index(const event &event)
|
||||
{
|
||||
return index(at<"event_id"_>(event));
|
||||
}
|
||||
|
||||
ircd::m::event::idx
|
||||
ircd::m::event::fetch::index(const event &event,
|
||||
std::nothrow_t)
|
||||
{
|
||||
return index(at<"event_id"_>(event), std::nothrow);
|
||||
}
|
||||
|
||||
ircd::m::event::idx
|
||||
ircd::m::event::fetch::index(const id &event_id)
|
||||
{
|
||||
auto &column
|
||||
{
|
||||
dbs::event_idx
|
||||
};
|
||||
|
||||
event::idx ret;
|
||||
column(event_id, [&ret]
|
||||
(const string_view &value)
|
||||
{
|
||||
ret = byte_view<event::idx>(value);
|
||||
});
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
ircd::m::event::idx
|
||||
ircd::m::event::fetch::index(const id &event_id,
|
||||
std::nothrow_t)
|
||||
{
|
||||
auto &column
|
||||
{
|
||||
dbs::event_idx
|
||||
};
|
||||
|
||||
event::idx ret{0};
|
||||
column(event_id, std::nothrow, [&ret]
|
||||
(const string_view &value)
|
||||
{
|
||||
ret = byte_view<event::idx>(value);
|
||||
});
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
void
|
||||
ircd::m::event::fetch::event_id(const idx &idx,
|
||||
const id::closure &closure)
|
||||
{
|
||||
if(!event_id(idx, std::nothrow, closure))
|
||||
throw m::NOT_FOUND
|
||||
{
|
||||
"%lu not found in database", idx
|
||||
};
|
||||
}
|
||||
|
||||
bool
|
||||
ircd::m::event::fetch::event_id(const idx &idx,
|
||||
std::nothrow_t,
|
||||
const id::closure &closure)
|
||||
{
|
||||
static constexpr auto column_idx
|
||||
{
|
||||
json::indexof<event, "event_id"_>()
|
||||
};
|
||||
|
||||
auto &column
|
||||
{
|
||||
dbs::event_column.at(column_idx)
|
||||
};
|
||||
|
||||
return column(byte_view<string_view>{idx}, std::nothrow, [&closure]
|
||||
(const string_view &value)
|
||||
{
|
||||
closure(value);
|
||||
});
|
||||
}
|
||||
|
||||
// db::row finds the layout of an event tuple because we pass this as a
|
||||
// reference argument to its constructor, rather than making db::row into
|
||||
// a template type.
|
||||
|
@ -1166,44 +1285,64 @@ ircd::m::event::fetch::fetch()
|
|||
{
|
||||
*dbs::events, string_view{}, _dummy_event_, cell
|
||||
}
|
||||
,valid
|
||||
{
|
||||
false
|
||||
}
|
||||
{
|
||||
}
|
||||
|
||||
/// Seek to event_id and populate this event from database.
|
||||
/// Throws if event not in database.
|
||||
ircd::m::event::fetch::fetch(const event::id &event_id)
|
||||
:row
|
||||
:fetch
|
||||
{
|
||||
*dbs::events, event_id, _dummy_event_, cell
|
||||
index(event_id)
|
||||
}
|
||||
{
|
||||
if(!row.valid(event_id))
|
||||
throw m::NOT_FOUND
|
||||
{
|
||||
"%s not found in database", event_id
|
||||
};
|
||||
|
||||
assign(*this, row, event_id);
|
||||
}
|
||||
|
||||
/// Seek to event_id and populate this event from database.
|
||||
/// Event is not populated if not found in database.
|
||||
ircd::m::event::fetch::fetch(const event::id &event_id,
|
||||
std::nothrow_t)
|
||||
:row
|
||||
:fetch
|
||||
{
|
||||
*dbs::events, event_id, _dummy_event_, cell
|
||||
index(event_id, std::nothrow), std::nothrow
|
||||
}
|
||||
{
|
||||
if(row.valid(event_id))
|
||||
assign(*this, row, event_id);
|
||||
}
|
||||
|
||||
bool
|
||||
ircd::m::event::fetch::valid(const event::id &event_id)
|
||||
const
|
||||
/// Seek to event_idx and populate this event from database.
|
||||
/// Throws if event not in database.
|
||||
ircd::m::event::fetch::fetch(const event::idx &event_idx)
|
||||
:fetch
|
||||
{
|
||||
return row.valid(event_id);
|
||||
event_idx, std::nothrow
|
||||
}
|
||||
{
|
||||
if(!valid)
|
||||
throw m::NOT_FOUND
|
||||
{
|
||||
"idx %zu not found in database", event_idx
|
||||
};
|
||||
}
|
||||
|
||||
/// Seek to event_idx and populate this event from database.
|
||||
/// Event is not populated if not found in database.
|
||||
ircd::m::event::fetch::fetch(const event::idx &event_idx,
|
||||
std::nothrow_t)
|
||||
:row
|
||||
{
|
||||
*dbs::events, byte_view<string_view>{event_idx}, _dummy_event_, cell
|
||||
}
|
||||
,valid
|
||||
{
|
||||
row.valid(byte_view<string_view>{event_idx})
|
||||
}
|
||||
{
|
||||
if(valid)
|
||||
assign(*this, row, byte_view<string_view>{event_idx});
|
||||
}
|
||||
|
||||
//
|
||||
|
|
419
ircd/m/room.cc
419
ircd/m/room.cc
|
@ -45,7 +45,10 @@ ircd::m::top(const id::room &room_id)
|
|||
};
|
||||
|
||||
if(std::get<0>(ret) == -1)
|
||||
throw m::NOT_FOUND{};
|
||||
throw m::NOT_FOUND
|
||||
{
|
||||
"No head for room %s", string_view{room_id}
|
||||
};
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
@ -71,12 +74,20 @@ ircd::m::top(std::nothrow_t,
|
|||
dbs::room_events_key(key)
|
||||
};
|
||||
|
||||
const auto &depth{std::get<0>(part)};
|
||||
const auto &event_id{std::get<1>(part)};
|
||||
return
|
||||
const int64_t &depth(std::get<0>(part));
|
||||
std::tuple<int64_t, ircd::m::id::event::buf> ret
|
||||
{
|
||||
depth, event_id
|
||||
depth, {}
|
||||
};
|
||||
|
||||
const event::idx &event_idx{std::get<1>(part)};
|
||||
event::fetch::event_id(event_idx, std::nothrow, [&ret]
|
||||
(const event::id &event_id)
|
||||
{
|
||||
std::get<1>(ret) = event_id;
|
||||
});
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
bool
|
||||
|
@ -207,59 +218,42 @@ void
|
|||
ircd::m::room::for_each(const event::closure &closure)
|
||||
const
|
||||
{
|
||||
for_each(event::closure_bool{[&closure]
|
||||
(const event &event)
|
||||
{
|
||||
closure(event);
|
||||
return true;
|
||||
}});
|
||||
for_each(string_view{}, closure);
|
||||
}
|
||||
|
||||
void
|
||||
bool
|
||||
ircd::m::room::for_each(const event::closure_bool &closure)
|
||||
const
|
||||
{
|
||||
event::fetch event;
|
||||
for_each(event::id::closure_bool{[&closure, &event]
|
||||
(const event::id &event_id)
|
||||
{
|
||||
if(!seek(event, event_id, std::nothrow))
|
||||
return true;
|
||||
|
||||
return closure(event);
|
||||
}});
|
||||
return for_each(string_view{}, closure);
|
||||
}
|
||||
|
||||
void
|
||||
ircd::m::room::for_each(const event::id::closure &closure)
|
||||
const
|
||||
{
|
||||
for_each(event::id::closure_bool{[&closure]
|
||||
(const event::id &event_id)
|
||||
{
|
||||
closure(event_id);
|
||||
return true;
|
||||
}});
|
||||
for_each(string_view{}, closure);
|
||||
}
|
||||
|
||||
void
|
||||
bool
|
||||
ircd::m::room::for_each(const event::id::closure_bool &closure)
|
||||
const
|
||||
{
|
||||
static constexpr auto idx
|
||||
{
|
||||
json::indexof<event, "type"_>()
|
||||
};
|
||||
return for_each(string_view{}, closure);
|
||||
}
|
||||
|
||||
auto &column
|
||||
{
|
||||
dbs::event_column.at(idx)
|
||||
};
|
||||
void
|
||||
ircd::m::room::for_each(const event::closure_idx &closure)
|
||||
const
|
||||
{
|
||||
for_each(string_view{}, closure);
|
||||
}
|
||||
|
||||
messages it{*this};
|
||||
for(; it; --it)
|
||||
if(!closure(it.event_id()))
|
||||
break;
|
||||
bool
|
||||
ircd::m::room::for_each(const event::closure_idx_bool &closure)
|
||||
const
|
||||
{
|
||||
return for_each(string_view{}, closure);
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -275,16 +269,16 @@ const
|
|||
}});
|
||||
}
|
||||
|
||||
void
|
||||
bool
|
||||
ircd::m::room::for_each(const string_view &type,
|
||||
const event::closure_bool &closure)
|
||||
const
|
||||
{
|
||||
event::fetch event;
|
||||
for_each(type, event::id::closure_bool{[&closure, &event]
|
||||
(const event::id &event_id)
|
||||
return for_each(type, event::closure_idx_bool{[&closure, &event]
|
||||
(const event::idx &event_idx)
|
||||
{
|
||||
if(!seek(event, event_id, std::nothrow))
|
||||
if(!seek(event, event_idx, std::nothrow))
|
||||
return true;
|
||||
|
||||
return closure(event);
|
||||
|
@ -304,10 +298,42 @@ const
|
|||
}});
|
||||
}
|
||||
|
||||
void
|
||||
bool
|
||||
ircd::m::room::for_each(const string_view &type,
|
||||
const event::id::closure_bool &closure)
|
||||
const
|
||||
{
|
||||
return for_each(type, event::closure_idx_bool{[&closure]
|
||||
(const event::idx &idx)
|
||||
{
|
||||
bool ret{true};
|
||||
event::fetch::event_id(idx, std::nothrow, [&ret, &closure]
|
||||
(const event::id &event_id)
|
||||
{
|
||||
ret = closure(event_id);
|
||||
});
|
||||
|
||||
return ret;
|
||||
}});
|
||||
}
|
||||
|
||||
void
|
||||
ircd::m::room::for_each(const string_view &type,
|
||||
const event::closure_idx &closure)
|
||||
const
|
||||
{
|
||||
for_each(type, event::closure_idx_bool{[&closure]
|
||||
(const event::idx &idx)
|
||||
{
|
||||
closure(idx);
|
||||
return true;
|
||||
}});
|
||||
}
|
||||
|
||||
bool
|
||||
ircd::m::room::for_each(const string_view &type,
|
||||
const event::closure_idx_bool &closure)
|
||||
const
|
||||
{
|
||||
static constexpr auto idx
|
||||
{
|
||||
|
@ -322,22 +348,29 @@ const
|
|||
messages it{*this};
|
||||
for(; it; --it)
|
||||
{
|
||||
const auto &event_id
|
||||
const auto &event_idx
|
||||
{
|
||||
it.event_id()
|
||||
it.event_idx()
|
||||
};
|
||||
|
||||
bool match{false};
|
||||
column(event_id, [&match, &type]
|
||||
(const string_view &value)
|
||||
bool match
|
||||
{
|
||||
match = value == type;
|
||||
});
|
||||
empty(type) // allow empty type to always match and bypass query
|
||||
};
|
||||
|
||||
if(!match)
|
||||
column(byte_view<string_view>(event_idx), std::nothrow, [&match, &type]
|
||||
(const string_view &value)
|
||||
{
|
||||
match = value == type;
|
||||
});
|
||||
|
||||
if(match)
|
||||
if(!closure(event_id))
|
||||
break;
|
||||
if(!closure(event_idx))
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
//
|
||||
|
@ -380,27 +413,27 @@ ircd::m::room::messages::seek()
|
|||
bool
|
||||
ircd::m::room::messages::seek(const event::id &event_id)
|
||||
{
|
||||
static constexpr auto idx
|
||||
{
|
||||
json::indexof<event, "depth"_>()
|
||||
};
|
||||
|
||||
auto &column
|
||||
{
|
||||
dbs::event_column.at(idx)
|
||||
dbs::event_column.at(json::indexof<event, "depth"_>())
|
||||
};
|
||||
|
||||
const event::idx event_idx
|
||||
{
|
||||
event::fetch::index(event_id)
|
||||
};
|
||||
|
||||
uint64_t depth;
|
||||
column(event_id, [&](const string_view &binary)
|
||||
column(byte_view<string_view>(event_idx), [&depth]
|
||||
(const string_view &value)
|
||||
{
|
||||
assert(size(binary) == sizeof(depth));
|
||||
depth = byte_view<uint64_t>(binary);
|
||||
depth = byte_view<uint64_t>(value);
|
||||
});
|
||||
|
||||
char buf[m::state::KEY_MAX_SZ];
|
||||
const auto seek_key
|
||||
{
|
||||
dbs::room_events_key(buf, room.room_id, depth, event_id)
|
||||
dbs::room_events_key(buf, room.room_id, depth, event_idx)
|
||||
};
|
||||
|
||||
this->it = dbs::room_events.begin(seek_key);
|
||||
|
@ -420,33 +453,40 @@ ircd::m::room::messages::seek(const uint64_t &depth)
|
|||
return bool(*this);
|
||||
}
|
||||
|
||||
ircd::m::room::messages::operator
|
||||
const m::event::id &()
|
||||
ircd::m::event::id::buf
|
||||
ircd::m::room::messages::event_id()
|
||||
{
|
||||
return event_id();
|
||||
event::id::buf ret;
|
||||
event::fetch::event_id(this->event_idx(), [&ret]
|
||||
(const event::id &event_id)
|
||||
{
|
||||
ret = event_id;
|
||||
});
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
const ircd::m::event::id &
|
||||
ircd::m::room::messages::event_id()
|
||||
const ircd::m::event::idx &
|
||||
ircd::m::room::messages::event_idx()
|
||||
{
|
||||
assert(bool(*this));
|
||||
const auto &key{it->first};
|
||||
const auto part{dbs::room_events_key(key)};
|
||||
_event_id = std::get<1>(part);
|
||||
return _event_id;
|
||||
_event_idx = std::get<1>(part);
|
||||
return _event_idx;
|
||||
}
|
||||
|
||||
const ircd::m::event &
|
||||
ircd::m::room::messages::fetch()
|
||||
{
|
||||
m::seek(_event, event_id());
|
||||
m::seek(_event, event_idx());
|
||||
return _event;
|
||||
}
|
||||
|
||||
const ircd::m::event &
|
||||
ircd::m::room::messages::fetch(std::nothrow_t)
|
||||
{
|
||||
if(!m::seek(_event, event_id(), std::nothrow))
|
||||
if(!m::seek(_event, event_idx(), std::nothrow))
|
||||
_event = m::event::fetch{};
|
||||
|
||||
return _event;
|
||||
|
@ -524,12 +564,12 @@ ircd::m::room::state::get(const string_view &type,
|
|||
const event::closure &closure)
|
||||
const
|
||||
{
|
||||
get(type, state_key, event::id::closure{[&closure]
|
||||
(const event::id &event_id)
|
||||
get(type, state_key, event::closure_idx{[&closure]
|
||||
(const event::idx &event_idx)
|
||||
{
|
||||
const event::fetch event
|
||||
{
|
||||
event_id
|
||||
event_idx
|
||||
};
|
||||
|
||||
closure(event);
|
||||
|
@ -549,9 +589,44 @@ const try
|
|||
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,
|
||||
const string_view &state_key,
|
||||
const event::closure_idx &closure)
|
||||
const try
|
||||
{
|
||||
if(root_id)
|
||||
m::state::get(root_id, type, state_key, [&closure]
|
||||
(const string_view &event_id)
|
||||
{
|
||||
closure(event::fetch::index(unquote(event_id)));
|
||||
});
|
||||
|
||||
char key[768];
|
||||
auto &column{dbs::room_state};
|
||||
return column(dbs::room_state_key(key, room_id, type, state_key), closure);
|
||||
column(dbs::room_state_key(key, room_id, type, state_key), [&closure]
|
||||
(const string_view &value)
|
||||
{
|
||||
closure(byte_view<event::idx>(value));
|
||||
});
|
||||
}
|
||||
catch(const db::not_found &e)
|
||||
{
|
||||
|
@ -572,12 +647,12 @@ ircd::m::room::state::get(std::nothrow_t,
|
|||
const event::closure &closure)
|
||||
const
|
||||
{
|
||||
return get(std::nothrow, type, state_key, event::id::closure{[&closure]
|
||||
(const event::id &event_id)
|
||||
return get(std::nothrow, type, state_key, event::closure_idx{[&closure]
|
||||
(const event::idx &event_idx)
|
||||
{
|
||||
const event::fetch event
|
||||
{
|
||||
event_id
|
||||
event_idx, std::nothrow
|
||||
};
|
||||
|
||||
closure(event);
|
||||
|
@ -598,9 +673,34 @@ const
|
|||
closure(unquote(event_id));
|
||||
});
|
||||
|
||||
return get(std::nothrow, type, state_key, event::closure_idx{[&closure]
|
||||
(const event::idx &idx)
|
||||
{
|
||||
event::fetch::event_id(idx, std::nothrow, closure);
|
||||
}});
|
||||
}
|
||||
|
||||
bool
|
||||
ircd::m::room::state::get(std::nothrow_t,
|
||||
const string_view &type,
|
||||
const string_view &state_key,
|
||||
const event::closure_idx &closure)
|
||||
const
|
||||
{
|
||||
if(root_id)
|
||||
return m::state::get(std::nothrow, root_id, type, state_key, [&closure]
|
||||
(const string_view &event_id)
|
||||
{
|
||||
return closure(event::fetch::index(unquote(event_id), std::nothrow));
|
||||
});
|
||||
|
||||
char key[768];
|
||||
auto &column{dbs::room_state};
|
||||
return column(dbs::room_state_key(key, room_id, type, state_key), std::nothrow, closure);
|
||||
return column(dbs::room_state_key(key, room_id, type, state_key), std::nothrow, [&closure]
|
||||
(const string_view &value)
|
||||
{
|
||||
closure(byte_view<event::idx>(value));
|
||||
});
|
||||
}
|
||||
|
||||
bool
|
||||
|
@ -672,10 +772,10 @@ ircd::m::room::state::test(const event::closure_bool &closure)
|
|||
const
|
||||
{
|
||||
event::fetch event;
|
||||
return test(event::id::closure_bool{[&event, &closure]
|
||||
(const event::id &event_id)
|
||||
return test(event::closure_idx_bool{[&event, &closure]
|
||||
(const event::idx &event_idx)
|
||||
{
|
||||
if(seek(event, unquote(event_id), std::nothrow))
|
||||
if(seek(event, event_idx, std::nothrow))
|
||||
if(closure(event))
|
||||
return true;
|
||||
|
||||
|
@ -694,9 +794,34 @@ const
|
|||
return closure(unquote(event_id));
|
||||
});
|
||||
|
||||
return test(event::closure_idx_bool{[&closure]
|
||||
(const event::idx &idx)
|
||||
{
|
||||
bool ret{false};
|
||||
event::fetch::event_id(idx, std::nothrow, [&ret, &closure]
|
||||
(const event::id &id)
|
||||
{
|
||||
ret = closure(id);
|
||||
});
|
||||
|
||||
return ret;
|
||||
}});
|
||||
}
|
||||
|
||||
bool
|
||||
ircd::m::room::state::test(const event::closure_idx_bool &closure)
|
||||
const
|
||||
{
|
||||
if(root_id)
|
||||
return m::state::test(root_id, [&closure]
|
||||
(const json::array &key, const string_view &event_id)
|
||||
{
|
||||
return closure(event::fetch::index(unquote(event_id), std::nothrow));
|
||||
});
|
||||
|
||||
auto &column{dbs::room_state};
|
||||
for(auto it{column.begin(room_id)}; bool(it); ++it)
|
||||
if(closure(it->second))
|
||||
if(closure(byte_view<event::idx>(it->second)))
|
||||
return true;
|
||||
|
||||
return false;
|
||||
|
@ -708,10 +833,10 @@ ircd::m::room::state::test(const string_view &type,
|
|||
const
|
||||
{
|
||||
event::fetch event;
|
||||
return test(type, event::id::closure_bool{[&event, &closure]
|
||||
(const event::id &event_id)
|
||||
return test(type, event::closure_idx_bool{[&event, &closure]
|
||||
(const event::idx &event_idx)
|
||||
{
|
||||
if(seek(event, unquote(event_id), std::nothrow))
|
||||
if(seek(event, event_idx, std::nothrow))
|
||||
if(closure(event))
|
||||
return true;
|
||||
|
||||
|
@ -731,6 +856,32 @@ const
|
|||
return closure(unquote(event_id));
|
||||
});
|
||||
|
||||
return test(type, event::closure_idx_bool{[&closure]
|
||||
(const event::idx &idx)
|
||||
{
|
||||
bool ret{false};
|
||||
event::fetch::event_id(idx, std::nothrow, [&ret, &closure]
|
||||
(const event::id &id)
|
||||
{
|
||||
ret = closure(id);
|
||||
});
|
||||
|
||||
return ret;
|
||||
}});
|
||||
}
|
||||
|
||||
bool
|
||||
ircd::m::room::state::test(const string_view &type,
|
||||
const event::closure_idx_bool &closure)
|
||||
const
|
||||
{
|
||||
if(root_id)
|
||||
return m::state::test(root_id, type, [&closure]
|
||||
(const json::array &key, const string_view &event_id)
|
||||
{
|
||||
return closure(event::fetch::index(unquote(event_id), std::nothrow));
|
||||
});
|
||||
|
||||
char keybuf[768];
|
||||
const auto &key
|
||||
{
|
||||
|
@ -741,7 +892,7 @@ const
|
|||
for(auto it{column.begin(key)}; bool(it); ++it)
|
||||
if(std::get<0>(dbs::room_state_key(it->first)) == type)
|
||||
{
|
||||
if(closure(it->second))
|
||||
if(closure(byte_view<event::idx>(it->second)))
|
||||
return true;
|
||||
}
|
||||
else break;
|
||||
|
@ -794,10 +945,10 @@ ircd::m::room::state::test(const string_view &type,
|
|||
const
|
||||
{
|
||||
event::fetch event;
|
||||
return test(type, state_key_lb, event::id::closure_bool{[&event, &closure]
|
||||
(const event::id &event_id)
|
||||
return test(type, state_key_lb, event::closure_idx_bool{[&event, &closure]
|
||||
(const event::idx &event_idx)
|
||||
{
|
||||
if(seek(event, unquote(event_id), std::nothrow))
|
||||
if(seek(event, event_idx, std::nothrow))
|
||||
if(closure(event))
|
||||
return true;
|
||||
|
||||
|
@ -818,6 +969,33 @@ const
|
|||
return closure(unquote(event_id));
|
||||
});
|
||||
|
||||
return test(type, state_key_lb, event::closure_idx_bool{[&closure]
|
||||
(const event::idx &idx)
|
||||
{
|
||||
bool ret{false};
|
||||
event::fetch::event_id(idx, std::nothrow, [&ret, &closure]
|
||||
(const event::id &id)
|
||||
{
|
||||
ret = closure(id);
|
||||
});
|
||||
|
||||
return ret;
|
||||
}});
|
||||
}
|
||||
|
||||
bool
|
||||
ircd::m::room::state::test(const string_view &type,
|
||||
const string_view &state_key_lb,
|
||||
const event::closure_idx_bool &closure)
|
||||
const
|
||||
{
|
||||
if(root_id)
|
||||
return m::state::test(root_id, type, state_key_lb, [&closure]
|
||||
(const json::array &key, const string_view &event_id)
|
||||
{
|
||||
return closure(event::fetch::index(unquote(event_id), std::nothrow));
|
||||
});
|
||||
|
||||
char keybuf[768];
|
||||
const auto &key
|
||||
{
|
||||
|
@ -828,7 +1006,7 @@ const
|
|||
for(auto it{column.begin(key)}; bool(it); ++it)
|
||||
if(std::get<0>(dbs::room_state_key(it->first)) == type)
|
||||
{
|
||||
if(closure(it->second))
|
||||
if(closure(byte_view<event::idx>(it->second)))
|
||||
return true;
|
||||
}
|
||||
else break;
|
||||
|
@ -841,10 +1019,10 @@ ircd::m::room::state::for_each(const event::closure &closure)
|
|||
const
|
||||
{
|
||||
event::fetch event;
|
||||
for_each(event::id::closure{[&event, &closure]
|
||||
(const event::id &event_id)
|
||||
for_each(event::closure_idx{[&event, &closure]
|
||||
(const event::idx &event_idx)
|
||||
{
|
||||
if(seek(event, event_id, std::nothrow))
|
||||
if(seek(event, event_idx, std::nothrow))
|
||||
closure(event);
|
||||
}});
|
||||
}
|
||||
|
@ -860,9 +1038,27 @@ const
|
|||
closure(unquote(event_id));
|
||||
});
|
||||
|
||||
for_each(event::closure_idx{[&closure]
|
||||
(const event::idx &idx)
|
||||
{
|
||||
event::fetch::event_id(idx, std::nothrow, closure);
|
||||
}});
|
||||
}
|
||||
|
||||
void
|
||||
ircd::m::room::state::for_each(const event::closure_idx &closure)
|
||||
const
|
||||
{
|
||||
if(root_id)
|
||||
return m::state::for_each(root_id, [&closure]
|
||||
(const json::array &key, const string_view &event_id)
|
||||
{
|
||||
closure(event::fetch::index(unquote(event_id), std::nothrow));
|
||||
});
|
||||
|
||||
auto &column{dbs::room_state};
|
||||
for(auto it{column.begin(room_id)}; bool(it); ++it)
|
||||
closure(it->second);
|
||||
closure(byte_view<event::idx>(it->second));
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -871,10 +1067,10 @@ ircd::m::room::state::for_each(const string_view &type,
|
|||
const
|
||||
{
|
||||
event::fetch event;
|
||||
for_each(type, event::id::closure{[&event, &closure]
|
||||
(const event::id &event_id)
|
||||
for_each(type, event::closure_idx{[&event, &closure]
|
||||
(const event::idx &event_idx)
|
||||
{
|
||||
if(seek(event, event_id, std::nothrow))
|
||||
if(seek(event, event_idx, std::nothrow))
|
||||
closure(event);
|
||||
}});
|
||||
}
|
||||
|
@ -891,6 +1087,25 @@ const
|
|||
closure(unquote(event_id));
|
||||
});
|
||||
|
||||
for_each(type, event::closure_idx{[&closure]
|
||||
(const event::idx &idx)
|
||||
{
|
||||
event::fetch::event_id(idx, std::nothrow, closure);
|
||||
}});
|
||||
}
|
||||
|
||||
void
|
||||
ircd::m::room::state::for_each(const string_view &type,
|
||||
const event::closure_idx &closure)
|
||||
const
|
||||
{
|
||||
if(root_id)
|
||||
return m::state::for_each(root_id, type, [&closure]
|
||||
(const json::array &key, const string_view &event_id)
|
||||
{
|
||||
closure(event::fetch::index(unquote(event_id), std::nothrow));
|
||||
});
|
||||
|
||||
char keybuf[768];
|
||||
const auto &key
|
||||
{
|
||||
|
@ -900,7 +1115,7 @@ const
|
|||
auto &column{dbs::room_state};
|
||||
for(auto it{column.begin(key)}; bool(it); ++it)
|
||||
if(std::get<0>(dbs::room_state_key(it->first)) == type)
|
||||
closure(it->second);
|
||||
closure(byte_view<event::idx>(it->second));
|
||||
else
|
||||
break;
|
||||
}
|
||||
|
@ -912,7 +1127,7 @@ const
|
|||
{
|
||||
if(root_id)
|
||||
return m::state::for_each(root_id, type, [&closure]
|
||||
(const json::array &key, const string_view &event_id)
|
||||
(const json::array &key, const string_view &)
|
||||
{
|
||||
assert(size(key) >= 2);
|
||||
closure(unquote(key.at(1)));
|
||||
|
|
61
ircd/m/vm.cc
61
ircd/m/vm.cc
|
@ -450,13 +450,18 @@ ircd::m::vm::_eval_pdu(eval &eval,
|
|||
++vm::current_sequence
|
||||
};
|
||||
|
||||
m::dbs::write_opts wopts;
|
||||
wopts.present = opts.present;
|
||||
wopts.history = opts.history;
|
||||
wopts.idx = sequence_number;
|
||||
|
||||
db::txn::append
|
||||
{
|
||||
*eval.txn, dbs::event_seq,
|
||||
{
|
||||
db::op::SET,
|
||||
byte_view<string_view>(sequence_number),
|
||||
event_id
|
||||
byte_view<string_view>(sequence_number),
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -507,11 +512,8 @@ ircd::m::vm::_eval_pdu(eval &eval,
|
|||
m::room room{room_id, head};
|
||||
m::room::state state{room};
|
||||
m::state::id_buffer new_root_buf;
|
||||
m::dbs::write_opts wopts;
|
||||
wopts.root_in = state.root_id;
|
||||
wopts.root_out = new_root_buf;
|
||||
wopts.present = opts.present;
|
||||
wopts.history = opts.history;
|
||||
const auto new_root
|
||||
{
|
||||
dbs::write(*eval.txn, event, wopts)
|
||||
|
@ -520,10 +522,7 @@ ircd::m::vm::_eval_pdu(eval &eval,
|
|||
else if(opts.write)
|
||||
{
|
||||
m::state::id_buffer new_root_buf;
|
||||
m::dbs::write_opts wopts;
|
||||
wopts.root_out = new_root_buf;
|
||||
wopts.present = opts.present;
|
||||
wopts.history = opts.history;
|
||||
const auto new_root
|
||||
{
|
||||
dbs::write(*eval.txn, event, wopts)
|
||||
|
@ -553,10 +552,10 @@ ircd::m::vm::events::rfor_each(const uint64_t &start,
|
|||
const closure_bool &closure)
|
||||
{
|
||||
event::fetch event;
|
||||
return rfor_each(start, id_closure_bool{[&event, &closure]
|
||||
(const uint64_t &seq, const event::id &event_id)
|
||||
return rfor_each(start, idx_closure_bool{[&event, &closure]
|
||||
(const uint64_t &seq, const event::idx &event_idx)
|
||||
{
|
||||
if(!seek(event, event_id, std::nothrow))
|
||||
if(!seek(event, event_idx, std::nothrow))
|
||||
return true;
|
||||
|
||||
return closure(seq, event);
|
||||
|
@ -565,7 +564,7 @@ ircd::m::vm::events::rfor_each(const uint64_t &start,
|
|||
|
||||
bool
|
||||
ircd::m::vm::events::rfor_each(const uint64_t &start,
|
||||
const id_closure_bool &closure)
|
||||
const idx_closure_bool &closure)
|
||||
{
|
||||
auto &column
|
||||
{
|
||||
|
@ -575,7 +574,7 @@ ircd::m::vm::events::rfor_each(const uint64_t &start,
|
|||
if(start == uint64_t(-1))
|
||||
{
|
||||
for(auto it(column.rbegin()); it; ++it)
|
||||
if(!closure(byte_view<uint64_t>(it->first), it->second))
|
||||
if(!closure(byte_view<uint64_t>(it->first), byte_view<event::idx>(it->second)))
|
||||
return false;
|
||||
|
||||
return true;
|
||||
|
@ -587,7 +586,7 @@ ircd::m::vm::events::rfor_each(const uint64_t &start,
|
|||
};
|
||||
|
||||
for(; it; ++it)
|
||||
if(!closure(byte_view<uint64_t>(it->first), it->second))
|
||||
if(!closure(byte_view<uint64_t>(it->first), byte_view<event::idx>(it->second)))
|
||||
return false;
|
||||
|
||||
return true;
|
||||
|
@ -598,10 +597,10 @@ ircd::m::vm::events::for_each(const uint64_t &start,
|
|||
const closure_bool &closure)
|
||||
{
|
||||
event::fetch event;
|
||||
return for_each(start, id_closure_bool{[&event, &closure]
|
||||
(const uint64_t &seq, const event::id &event_id)
|
||||
return for_each(start, idx_closure_bool{[&event, &closure]
|
||||
(const uint64_t &seq, const event::idx &event_idx)
|
||||
{
|
||||
if(!seek(event, event_id, std::nothrow))
|
||||
if(!seek(event, event_idx, std::nothrow))
|
||||
return true;
|
||||
|
||||
return closure(seq, event);
|
||||
|
@ -610,7 +609,7 @@ ircd::m::vm::events::for_each(const uint64_t &start,
|
|||
|
||||
bool
|
||||
ircd::m::vm::events::for_each(const uint64_t &start,
|
||||
const id_closure_bool &closure)
|
||||
const idx_closure_bool &closure)
|
||||
{
|
||||
auto &column
|
||||
{
|
||||
|
@ -625,7 +624,7 @@ ircd::m::vm::events::for_each(const uint64_t &start,
|
|||
};
|
||||
|
||||
for(; it; ++it)
|
||||
if(!closure(byte_view<uint64_t>(it->first), it->second))
|
||||
if(!closure(byte_view<uint64_t>(it->first), byte_view<event::idx>(it->second)))
|
||||
return false;
|
||||
|
||||
return true;
|
||||
|
@ -650,14 +649,24 @@ ircd::m::vm::sequence(const eval &eval)
|
|||
}
|
||||
|
||||
uint64_t
|
||||
ircd::m::vm::last_sequence()
|
||||
ircd::m::vm::last_sequence(id::event::buf &event_id)
|
||||
{
|
||||
id::event::buf event_id;
|
||||
return last_sequence(event_id);
|
||||
const auto &ret
|
||||
{
|
||||
last_sequence()
|
||||
};
|
||||
|
||||
event::fetch::event_id(ret, std::nothrow, [&event_id]
|
||||
(const event::id &event_id_)
|
||||
{
|
||||
event_id = event_id_;
|
||||
});
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
uint64_t
|
||||
ircd::m::vm::last_sequence(id::event::buf &event_id)
|
||||
ircd::m::vm::last_sequence()
|
||||
{
|
||||
auto &column
|
||||
{
|
||||
|
@ -677,8 +686,12 @@ ircd::m::vm::last_sequence(id::event::buf &event_id)
|
|||
return 0;
|
||||
}
|
||||
|
||||
event_id = it->second;
|
||||
return byte_view<uint64_t>(it->first);
|
||||
const auto &ret
|
||||
{
|
||||
byte_view<uint64_t>(it->first)
|
||||
};
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
ircd::string_view
|
||||
|
|
Loading…
Reference in a new issue