mirror of
https://github.com/matrix-construct/construct
synced 2024-11-25 16:22:35 +01:00
ircd:Ⓜ️ Add dbs namespace; remove old interfaces; checkpoint various.
This commit is contained in:
parent
ed5b4d0641
commit
a9cada32db
14 changed files with 1502 additions and 2217 deletions
|
@ -23,18 +23,18 @@
|
|||
#pragma once
|
||||
#define HAVE_IRCD_M_VM_CURSOR_H
|
||||
|
||||
namespace ircd::m::vm
|
||||
namespace ircd::m::dbs
|
||||
{
|
||||
struct cursor;
|
||||
}
|
||||
|
||||
struct ircd::m::vm::cursor
|
||||
struct ircd::m::dbs::cursor
|
||||
{
|
||||
template<class index_iterator> struct const_iterator_base;
|
||||
struct const_reverse_iterator;
|
||||
struct const_iterator;
|
||||
|
||||
template<enum where where = where::noop> using query_type = vm::query<where>;
|
||||
template<enum where where = where::noop> using query_type = dbs::query<where>;
|
||||
using iterator_type = const_iterator;
|
||||
|
||||
db::index index;
|
||||
|
@ -53,7 +53,7 @@ struct ircd::m::vm::cursor
|
|||
};
|
||||
|
||||
template<class index_iterator>
|
||||
struct ircd::m::vm::cursor::const_iterator_base
|
||||
struct ircd::m::dbs::cursor::const_iterator_base
|
||||
{
|
||||
using value_type = const event;
|
||||
using pointer = value_type *;
|
||||
|
@ -105,13 +105,13 @@ struct ircd::m::vm::cursor::const_iterator_base
|
|||
const_iterator_base(const cursor &, index_iterator, const db::gopts & = {});
|
||||
};
|
||||
|
||||
struct ircd::m::vm::cursor::const_iterator
|
||||
struct ircd::m::dbs::cursor::const_iterator
|
||||
:const_iterator_base<db::index::const_iterator>
|
||||
{
|
||||
using const_iterator_base<db::index::const_iterator>::const_iterator_base;
|
||||
};
|
||||
|
||||
struct ircd::m::vm::cursor::const_reverse_iterator
|
||||
struct ircd::m::dbs::cursor::const_reverse_iterator
|
||||
:const_iterator_base<db::index::const_reverse_iterator>
|
||||
{
|
||||
using const_iterator_base<db::index::const_reverse_iterator>::const_iterator_base;
|
||||
|
@ -121,26 +121,26 @@ struct ircd::m::vm::cursor::const_reverse_iterator
|
|||
// cursor
|
||||
//
|
||||
|
||||
inline ircd::m::vm::cursor::const_reverse_iterator
|
||||
ircd::m::vm::cursor::rbegin(const string_view &key)
|
||||
inline ircd::m::dbs::cursor::const_reverse_iterator
|
||||
ircd::m::dbs::cursor::rbegin(const string_view &key)
|
||||
{
|
||||
return const_reverse_iterator { *this, index.rbegin(key), {} };
|
||||
}
|
||||
|
||||
inline ircd::m::vm::cursor::const_reverse_iterator
|
||||
ircd::m::vm::cursor::rend(const string_view &key)
|
||||
inline ircd::m::dbs::cursor::const_reverse_iterator
|
||||
ircd::m::dbs::cursor::rend(const string_view &key)
|
||||
{
|
||||
return const_reverse_iterator { *this, index.rend(key), {} };
|
||||
}
|
||||
|
||||
inline ircd::m::vm::cursor::const_iterator
|
||||
ircd::m::vm::cursor::begin(const string_view &key)
|
||||
inline ircd::m::dbs::cursor::const_iterator
|
||||
ircd::m::dbs::cursor::begin(const string_view &key)
|
||||
{
|
||||
return const_iterator { *this, index.begin(key), {} };
|
||||
}
|
||||
|
||||
inline ircd::m::vm::cursor::const_iterator
|
||||
ircd::m::vm::cursor::end(const string_view &key)
|
||||
inline ircd::m::dbs::cursor::const_iterator
|
||||
ircd::m::dbs::cursor::end(const string_view &key)
|
||||
{
|
||||
return const_iterator { *this, index.end(key), {} };
|
||||
}
|
||||
|
@ -150,7 +150,7 @@ ircd::m::vm::cursor::end(const string_view &key)
|
|||
//
|
||||
|
||||
template<class index_iterator>
|
||||
ircd::m::vm::cursor::const_iterator_base<index_iterator>::const_iterator_base(const cursor &c,
|
||||
ircd::m::dbs::cursor::const_iterator_base<index_iterator>::const_iterator_base(const cursor &c,
|
||||
index_iterator idx,
|
||||
const db::gopts &opts)
|
||||
:query{c.query}
|
||||
|
@ -186,8 +186,8 @@ ircd::m::vm::cursor::const_iterator_base<index_iterator>::const_iterator_base(co
|
|||
}
|
||||
|
||||
template<class index_iterator>
|
||||
ircd::m::vm::cursor::const_iterator_base<index_iterator> &
|
||||
ircd::m::vm::cursor::const_iterator_base<index_iterator>::operator++()
|
||||
ircd::m::dbs::cursor::const_iterator_base<index_iterator> &
|
||||
ircd::m::dbs::cursor::const_iterator_base<index_iterator>::operator++()
|
||||
{
|
||||
while(!(invalid = !bool(++idx)))
|
||||
if(seek_row())
|
||||
|
@ -197,8 +197,8 @@ ircd::m::vm::cursor::const_iterator_base<index_iterator>::operator++()
|
|||
}
|
||||
|
||||
template<class index_iterator>
|
||||
ircd::m::vm::cursor::const_iterator_base<index_iterator> &
|
||||
ircd::m::vm::cursor::const_iterator_base<index_iterator>::operator--()
|
||||
ircd::m::dbs::cursor::const_iterator_base<index_iterator> &
|
||||
ircd::m::dbs::cursor::const_iterator_base<index_iterator>::operator--()
|
||||
{
|
||||
while(!(invalid = !bool(--idx)))
|
||||
if(seek_row())
|
||||
|
@ -209,7 +209,7 @@ ircd::m::vm::cursor::const_iterator_base<index_iterator>::operator--()
|
|||
|
||||
template<class index_iterator>
|
||||
bool
|
||||
ircd::m::vm::cursor::const_iterator_base<index_iterator>::seek_row()
|
||||
ircd::m::dbs::cursor::const_iterator_base<index_iterator>::seek_row()
|
||||
{
|
||||
if(!db::seek(row, row_key()))
|
||||
return false;
|
||||
|
@ -223,7 +223,7 @@ ircd::m::vm::cursor::const_iterator_base<index_iterator>::seek_row()
|
|||
|
||||
template<class index_iterator>
|
||||
bool
|
||||
ircd::m::vm::cursor::const_iterator_base<index_iterator>::row_valid()
|
||||
ircd::m::dbs::cursor::const_iterator_base<index_iterator>::row_valid()
|
||||
const
|
||||
{
|
||||
return row.valid(row_key());
|
||||
|
@ -231,7 +231,7 @@ const
|
|||
|
||||
template<class index_iterator>
|
||||
ircd::string_view
|
||||
ircd::m::vm::cursor::const_iterator_base<index_iterator>::row_key()
|
||||
ircd::m::dbs::cursor::const_iterator_base<index_iterator>::row_key()
|
||||
const
|
||||
{
|
||||
if(!idx)
|
||||
|
@ -246,14 +246,14 @@ const
|
|||
|
||||
template<class index_iterator>
|
||||
bool
|
||||
ircd::m::vm::cursor::const_iterator_base<index_iterator>::operator!()
|
||||
ircd::m::dbs::cursor::const_iterator_base<index_iterator>::operator!()
|
||||
const
|
||||
{
|
||||
return !static_cast<bool>(*this);
|
||||
}
|
||||
|
||||
template<class index_iterator>
|
||||
ircd::m::vm::cursor::const_iterator_base<index_iterator>::operator
|
||||
ircd::m::dbs::cursor::const_iterator_base<index_iterator>::operator
|
||||
bool()
|
||||
const
|
||||
{
|
||||
|
@ -268,7 +268,7 @@ const
|
|||
|
||||
template<class index_iterator>
|
||||
bool
|
||||
ircd::m::vm::cursor::const_iterator_base<index_iterator>::operator!=(const const_iterator_base<index_iterator> &o)
|
||||
ircd::m::dbs::cursor::const_iterator_base<index_iterator>::operator!=(const const_iterator_base<index_iterator> &o)
|
||||
const
|
||||
{
|
||||
return !(*this == o);
|
||||
|
@ -276,7 +276,7 @@ const
|
|||
|
||||
template<class index_iterator>
|
||||
bool
|
||||
ircd::m::vm::cursor::const_iterator_base<index_iterator>::operator==(const const_iterator_base<index_iterator> &o)
|
||||
ircd::m::dbs::cursor::const_iterator_base<index_iterator>::operator==(const const_iterator_base<index_iterator> &o)
|
||||
const
|
||||
{
|
||||
if(row_key() != o.row_key())
|
||||
|
|
93
include/ircd/m/dbs.h
Normal file
93
include/ircd/m/dbs.h
Normal file
|
@ -0,0 +1,93 @@
|
|||
// 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_DBS_H
|
||||
|
||||
namespace ircd::m::dbs
|
||||
{
|
||||
struct init;
|
||||
struct node;
|
||||
|
||||
extern std::map<std::string, ircd::module> modules;
|
||||
extern std::map<std::string, import_shared<database>> databases;
|
||||
|
||||
bool exists(const event::id &);
|
||||
|
||||
size_t keys(const node &);
|
||||
size_t vals(const node &);
|
||||
json::array key(const node &, const size_t &);
|
||||
string_view val(const node &, const size_t &);
|
||||
json::array make_key(const mutable_buffer &out, const string_view &type, const string_view &state_key);
|
||||
size_t find(const node &, const json::array &key);
|
||||
size_t find(const node &, const string_view &type, const string_view &state_key);
|
||||
json::object make_node(const mutable_buffer &out, const std::initializer_list<json::array> &keys, const std::initializer_list<string_view> &vals);
|
||||
string_view make_node(db::iov &txn, const mutable_buffer &hash, const std::initializer_list<json::array> &keys, const std::initializer_list<string_view> &vals);
|
||||
json::object get_node(db::column &, const mutable_buffer &buf, const string_view &id);
|
||||
json::object get_node(const mutable_buffer &buf, const string_view &id);
|
||||
|
||||
void append_indexes(const event &, db::iov &iov);
|
||||
void append_nodes(const event &, db::iov &iov);
|
||||
void write(const event &, db::iov &txn);
|
||||
}
|
||||
|
||||
namespace ircd::m::dbs::name
|
||||
{
|
||||
constexpr const char *const k {"k"};
|
||||
constexpr const char *const v {"v"};
|
||||
}
|
||||
|
||||
#pragma GCC diagnostic push
|
||||
#pragma GCC diagnostic ignored "-Wsubobject-linkage"
|
||||
struct ircd::m::dbs::node
|
||||
:json::tuple
|
||||
<
|
||||
json::property<name::k, json::array>,
|
||||
json::property<name::v, json::array>
|
||||
>
|
||||
{
|
||||
using super_type::tuple;
|
||||
using super_type::operator=;
|
||||
};
|
||||
#pragma GCC diagnostic pop
|
||||
|
||||
class ircd::m::dbs::init
|
||||
{
|
||||
void _modules();
|
||||
void _databases();
|
||||
|
||||
public:
|
||||
init();
|
||||
~init() noexcept;
|
||||
};
|
||||
|
||||
namespace ircd::m::dbs
|
||||
{
|
||||
using closure = std::function<void (const event &)>;
|
||||
using closure_bool = std::function<bool (const event &)>;
|
||||
|
||||
bool _query(const query<> &, const closure_bool &);
|
||||
bool _query_event_id(const query<> &, const closure_bool &);
|
||||
bool _query_in_room_id(const query<> &, const closure_bool &, const id::room &);
|
||||
bool _query_for_type_state_key_in_room_id(const query<> &, const closure_bool &, const id::room &, const string_view &type, const string_view &state_key);
|
||||
|
||||
int _query_where_event_id(const query<where::equal> &, const closure_bool &);
|
||||
int _query_where_room_id_at_event_id(const query<where::equal> &, const closure_bool &);
|
||||
int _query_where_room_id(const query<where::equal> &, const closure_bool &);
|
||||
int _query_where(const query<where::equal> &where, const closure_bool &closure);
|
||||
int _query_where(const query<where::logical_and> &where, const closure_bool &closure);
|
||||
}
|
||||
|
||||
namespace ircd::m
|
||||
{
|
||||
void _index_special0(const event &event, db::iov &iov, const db::op &, const string_view &prev_event_id);
|
||||
void _index_special1(const event &event, db::iov &iov, const db::op &, const string_view &prev_event_id);
|
||||
}
|
||||
|
|
@ -30,11 +30,6 @@ namespace ircd::m
|
|||
{
|
||||
struct init;
|
||||
|
||||
namespace dbs
|
||||
{
|
||||
struct init;
|
||||
}
|
||||
|
||||
extern struct user me;
|
||||
extern struct room my_room;
|
||||
extern struct room control;
|
||||
|
@ -60,29 +55,24 @@ namespace ircd
|
|||
using m::my_host;
|
||||
}
|
||||
|
||||
#include "error.h"
|
||||
#include "name.h"
|
||||
#include "error.h"
|
||||
#include "id.h"
|
||||
#include "event.h"
|
||||
#include "query.h"
|
||||
#include "cursor.h"
|
||||
#include "dbs.h"
|
||||
#include "room.h"
|
||||
#include "user.h"
|
||||
#include "request.h"
|
||||
#include "session.h"
|
||||
#include "v1/v1.h"
|
||||
#include "io.h"
|
||||
#include "vm.h"
|
||||
#include "user.h"
|
||||
#include "filter.h"
|
||||
#include "keys.h"
|
||||
#include "txn.h"
|
||||
|
||||
struct ircd::m::dbs::init
|
||||
{
|
||||
init();
|
||||
~init() noexcept;
|
||||
};
|
||||
|
||||
struct ircd::m::init
|
||||
{
|
||||
json::object conf;
|
||||
|
|
|
@ -23,7 +23,7 @@
|
|||
#pragma once
|
||||
#define HAVE_IRCD_M_VM_QUERY_H
|
||||
|
||||
namespace ircd::m::vm
|
||||
namespace ircd::m::dbs
|
||||
{
|
||||
/// Types of query clauses.
|
||||
enum class where
|
||||
|
@ -60,9 +60,11 @@ namespace ircd::m::vm
|
|||
query<where::logical_or> operator||(const query<> &a, const query<> &b);
|
||||
query<where::logical_and> operator&&(const query<> &a, const query<> &b);
|
||||
query<where::logical_not> operator!(const query<> &a);
|
||||
|
||||
extern const query<> noop;
|
||||
}
|
||||
|
||||
struct ircd::m::vm::query<ircd::m::vm::where::noop>
|
||||
struct ircd::m::dbs::query<ircd::m::dbs::where::noop>
|
||||
{
|
||||
virtual bool operator()(const event &) const
|
||||
{
|
||||
|
@ -80,7 +82,7 @@ struct ircd::m::vm::query<ircd::m::vm::where::noop>
|
|||
virtual ~query() noexcept;
|
||||
};
|
||||
|
||||
struct ircd::m::vm::query<ircd::m::vm::where::test>
|
||||
struct ircd::m::dbs::query<ircd::m::dbs::where::test>
|
||||
:query<>
|
||||
{
|
||||
using function = std::function<bool (const event &)>;
|
||||
|
@ -98,7 +100,7 @@ struct ircd::m::vm::query<ircd::m::vm::where::test>
|
|||
{}
|
||||
};
|
||||
|
||||
struct ircd::m::vm::query<ircd::m::vm::where::equal>
|
||||
struct ircd::m::dbs::query<ircd::m::dbs::where::equal>
|
||||
:query<>
|
||||
{
|
||||
event value;
|
||||
|
@ -117,7 +119,7 @@ struct ircd::m::vm::query<ircd::m::vm::where::equal>
|
|||
};
|
||||
|
||||
inline bool
|
||||
ircd::m::vm::query<ircd::m::vm::where::equal>::operator()(const event &value)
|
||||
ircd::m::dbs::query<ircd::m::dbs::where::equal>::operator()(const event &value)
|
||||
const
|
||||
{
|
||||
return json::until(this->value, value, []
|
||||
|
@ -130,7 +132,7 @@ const
|
|||
});
|
||||
}
|
||||
|
||||
struct ircd::m::vm::query<ircd::m::vm::where::not_equal>
|
||||
struct ircd::m::dbs::query<ircd::m::dbs::where::not_equal>
|
||||
:query<>
|
||||
{
|
||||
event value;
|
||||
|
@ -149,7 +151,7 @@ struct ircd::m::vm::query<ircd::m::vm::where::not_equal>
|
|||
};
|
||||
|
||||
inline bool
|
||||
ircd::m::vm::query<ircd::m::vm::where::not_equal>::operator()(const event &value)
|
||||
ircd::m::dbs::query<ircd::m::dbs::where::not_equal>::operator()(const event &value)
|
||||
const
|
||||
{
|
||||
return !json::until(this->value, value, []
|
||||
|
@ -162,7 +164,7 @@ const
|
|||
});
|
||||
}
|
||||
|
||||
struct ircd::m::vm::query<ircd::m::vm::where::logical_or>
|
||||
struct ircd::m::dbs::query<ircd::m::dbs::where::logical_or>
|
||||
:query<>
|
||||
{
|
||||
const query<> *a, *b;
|
||||
|
@ -179,7 +181,7 @@ struct ircd::m::vm::query<ircd::m::vm::where::logical_or>
|
|||
{}
|
||||
};
|
||||
|
||||
struct ircd::m::vm::query<ircd::m::vm::where::logical_and>
|
||||
struct ircd::m::dbs::query<ircd::m::dbs::where::logical_and>
|
||||
:query<>
|
||||
{
|
||||
const query<> *a, *b;
|
||||
|
@ -196,7 +198,7 @@ struct ircd::m::vm::query<ircd::m::vm::where::logical_and>
|
|||
{}
|
||||
};
|
||||
|
||||
struct ircd::m::vm::query<ircd::m::vm::where::logical_not>
|
||||
struct ircd::m::dbs::query<ircd::m::dbs::where::logical_not>
|
||||
:query<>
|
||||
{
|
||||
const query<> *a;
|
||||
|
@ -212,20 +214,20 @@ struct ircd::m::vm::query<ircd::m::vm::where::logical_not>
|
|||
{}
|
||||
};
|
||||
|
||||
inline ircd::m::vm::query<ircd::m::vm::where::logical_or>
|
||||
ircd::m::vm::operator||(const query<> &a, const query<> &b)
|
||||
inline ircd::m::dbs::query<ircd::m::dbs::where::logical_or>
|
||||
ircd::m::dbs::operator||(const query<> &a, const query<> &b)
|
||||
{
|
||||
return { a, b };
|
||||
}
|
||||
|
||||
inline ircd::m::vm::query<ircd::m::vm::where::logical_and>
|
||||
ircd::m::vm::operator&&(const query<> &a, const query<> &b)
|
||||
inline ircd::m::dbs::query<ircd::m::dbs::where::logical_and>
|
||||
ircd::m::dbs::operator&&(const query<> &a, const query<> &b)
|
||||
{
|
||||
return { a, b };
|
||||
}
|
||||
|
||||
inline ircd::m::vm::query<ircd::m::vm::where::logical_not>
|
||||
ircd::m::vm::operator!(const query<> &a)
|
||||
inline ircd::m::dbs::query<ircd::m::dbs::where::logical_not>
|
||||
ircd::m::dbs::operator!(const query<> &a)
|
||||
{
|
||||
return { a };
|
||||
}
|
||||
|
|
|
@ -56,25 +56,20 @@ namespace ircd::m::vm
|
|||
IRCD_M_EXCEPTION(VM_ERROR, VM_FAULT, http::BAD_REQUEST);
|
||||
|
||||
enum fault :uint;
|
||||
struct frame;
|
||||
struct capstan;
|
||||
struct witness;
|
||||
struct accumulator;
|
||||
struct front;
|
||||
struct eval;
|
||||
struct pipe;
|
||||
struct port;
|
||||
struct space;
|
||||
struct opts;
|
||||
|
||||
using closure = std::function<void (const event &)>;
|
||||
using closure_bool = std::function<bool (const event &)>;
|
||||
using dbs::where;
|
||||
using dbs::query;
|
||||
using dbs::cursor;
|
||||
|
||||
extern struct log::log log;
|
||||
extern struct fronts fronts;
|
||||
extern uint64_t current_sequence;
|
||||
extern ctx::view<const event> inserted;
|
||||
extern struct fronts fronts;
|
||||
extern struct pipe pipe;
|
||||
|
||||
bool test(const query<> &, const closure_bool &);
|
||||
bool test(const query<> &);
|
||||
|
@ -84,10 +79,9 @@ namespace ircd::m::vm
|
|||
void for_each(const closure &);
|
||||
size_t count(const query<> &, const closure_bool &);
|
||||
size_t count(const query<> &);
|
||||
bool exists(const event::id &);
|
||||
|
||||
int test(eval &, const query<> &, const closure_bool &);
|
||||
int test(eval &, const query<> &);
|
||||
event::id::buf commit(json::iov &event);
|
||||
event::id::buf commit(json::iov &event, const json::iov &content);
|
||||
}
|
||||
|
||||
/// Evaluation Options
|
||||
|
@ -158,41 +152,6 @@ enum ircd::m::vm::fault
|
|||
STATE, ///< Required state is missing (#st)
|
||||
};
|
||||
|
||||
struct ircd::m::vm::capstan
|
||||
{
|
||||
int64_t dc{0};
|
||||
std::vector<std::unique_ptr<vm::accumulator>> acc;
|
||||
|
||||
ssize_t count(const query<> &) const;
|
||||
int test(const query<> &) const;
|
||||
|
||||
void fwd(const event &);
|
||||
void rev(const event &);
|
||||
|
||||
capstan();
|
||||
~capstan() noexcept;
|
||||
};
|
||||
|
||||
struct ircd::m::vm::port
|
||||
{
|
||||
const m::event *event {nullptr};
|
||||
std::exception_ptr error;
|
||||
fault code;
|
||||
bool h {false};
|
||||
bool w {false};
|
||||
};
|
||||
|
||||
struct ircd::m::vm::space
|
||||
{
|
||||
struct capstan capstan;
|
||||
};
|
||||
|
||||
struct ircd::m::vm::pipe
|
||||
{
|
||||
std::unordered_map<string_view, space> s;
|
||||
std::deque<port> p;
|
||||
};
|
||||
|
||||
/// Event Evaluation Device
|
||||
///
|
||||
/// This object conducts the evaluation of an event or a tape of multiple
|
||||
|
@ -216,7 +175,6 @@ struct ircd::m::vm::eval
|
|||
static const struct opts default_opts;
|
||||
|
||||
const struct opts *opts;
|
||||
struct capstan capstan;
|
||||
db::iov txn{*event::events};
|
||||
std::set<event::id> ef;
|
||||
uint64_t cs {0};
|
||||
|
@ -252,67 +210,6 @@ ircd::m::vm::eval::eval(const struct opts &opts,
|
|||
operator()(std::forward<events>(event));
|
||||
}
|
||||
|
||||
// state accumulators:
|
||||
//
|
||||
// - (bool) event_id: Adds all event_ids to accumulator. On eval, capstan
|
||||
// checks if event_id is not in set: accepts; Otherwise event_id duplicate in
|
||||
// set: rejects.
|
||||
//
|
||||
// - (bool) membership: Capstan has a accumulator for each membership state.
|
||||
// Adds accumulator[membership] = state_key. On eval, capstan knows about user not
|
||||
// having membership of claimed type. Negative for all accumulators indicates no
|
||||
// membership in the set.
|
||||
//
|
||||
// - (count) types: Counts all type names encountered to respond to
|
||||
// queries about that type maybe or definitely not being in the poset.
|
||||
//
|
||||
// - (count) state types: Counts all type names encountered when there is
|
||||
// a state_key defined.
|
||||
//
|
||||
// - (count) sender: Counts all sender strings. Responds to queries about
|
||||
// whether a sender may have or definitely did not take part in the poset.
|
||||
//
|
||||
// - (count) origin: Counts all origin strings.
|
||||
//
|
||||
struct ircd::m::vm::witness
|
||||
:ircd::instance_list<witness>
|
||||
{
|
||||
std::string name;
|
||||
|
||||
virtual ssize_t count(const accumulator *const &, const query<> &)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
virtual int test(const accumulator *const &, const query<> &)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
virtual int add(accumulator *const &, const event &)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
virtual int del(accumulator *const &, const event &)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
virtual std::unique_ptr<accumulator> init()
|
||||
{
|
||||
return {};
|
||||
}
|
||||
|
||||
witness(std::string name);
|
||||
virtual ~witness() noexcept;
|
||||
};
|
||||
|
||||
struct ircd::m::vm::accumulator
|
||||
{
|
||||
virtual ~accumulator() noexcept;
|
||||
};
|
||||
|
||||
/// The "event front" for a graph. This holds all of the childless events
|
||||
/// for a room. Each childless event may exist at a different depth, but
|
||||
/// we track the highest depth to increment it for issuing the next event.
|
||||
|
@ -324,7 +221,6 @@ struct ircd::m::vm::front
|
|||
{
|
||||
int64_t top {0};
|
||||
std::map<std::string, uint64_t, std::less<std::string_view>> map;
|
||||
vm::capstan capstan;
|
||||
};
|
||||
|
||||
/// Singleton iface to all "event fronts" - the top depth in an active graph
|
||||
|
@ -350,18 +246,3 @@ struct ircd::m::vm::fronts
|
|||
front &get(const room::id &, const event &);
|
||||
front &get(const room::id &);
|
||||
};
|
||||
|
||||
namespace ircd::m::vm
|
||||
{
|
||||
// Synchronous fetch and eval
|
||||
size_t acquire(const vector_view<const id::event> &, const vector_view<const mutable_buffer> &);
|
||||
json::object acquire(const id::event &, const mutable_buffer &);
|
||||
void statefill(const room::id &, const event::id &);
|
||||
void backfill(const room::id &, const event::id &v, const size_t &limit);
|
||||
|
||||
using tracer = std::function<bool (const event &, event::id::buf &)>;
|
||||
void trace(const id::event &, const tracer &);
|
||||
|
||||
event::id::buf commit(json::iov &event);
|
||||
event::id::buf join(const room::id &, json::iov &iov);
|
||||
}
|
||||
|
|
|
@ -75,6 +75,7 @@ libircd_la_SOURCES = \
|
|||
base.cc \
|
||||
locale.cc \
|
||||
logger.cc \
|
||||
m/dbs.cc \
|
||||
m/event.cc \
|
||||
m/id.cc \
|
||||
m/v1.cc \
|
||||
|
|
1028
ircd/m/dbs.cc
Normal file
1028
ircd/m/dbs.cc
Normal file
File diff suppressed because it is too large
Load diff
|
@ -448,31 +448,27 @@ ircd::m::keys::get_local(const string_view &server_name,
|
|||
void
|
||||
ircd::m::keys::set(const keys &keys)
|
||||
{
|
||||
const auto &state_key
|
||||
const auto &server_name
|
||||
{
|
||||
unquote(at<"server_name"_>(keys))
|
||||
};
|
||||
|
||||
const m::user::id::buf sender
|
||||
const auto &state_key
|
||||
{
|
||||
"ircd", unquote(at<"server_name"_>(keys))
|
||||
server_name
|
||||
};
|
||||
|
||||
const json::strung content
|
||||
const m::user::id::buf sender
|
||||
{
|
||||
"ircd", server_name
|
||||
};
|
||||
|
||||
const json::strung derp
|
||||
{
|
||||
keys
|
||||
};
|
||||
|
||||
json::iov event;
|
||||
json::iov::push members[]
|
||||
{
|
||||
{ event, { "type", "ircd.key" }},
|
||||
{ event, { "state_key", state_key }},
|
||||
{ event, { "sender", sender }},
|
||||
{ event, { "content", content }}
|
||||
};
|
||||
|
||||
keys::room.send(event);
|
||||
send(keys::room, sender, "ircd.key", state_key, json::object{derp});
|
||||
}
|
||||
|
||||
/// Verify this key data (with itself).
|
||||
|
|
54
ircd/m/m.cc
54
ircd/m/m.cc
|
@ -285,60 +285,6 @@ ircd::m::leave_ircd_room()
|
|||
leave(my_room, me.user_id);
|
||||
}
|
||||
|
||||
//
|
||||
// dbs
|
||||
//
|
||||
|
||||
namespace ircd::m::dbs
|
||||
{
|
||||
std::map<std::string, ircd::module> modules;
|
||||
std::map<std::string, import_shared<database>> databases;
|
||||
|
||||
void init_modules();
|
||||
void init_databases();
|
||||
}
|
||||
|
||||
ircd::m::dbs::init::init()
|
||||
{
|
||||
init_modules();
|
||||
init_databases();
|
||||
|
||||
ircd::m::event::events = databases.at("events").get();
|
||||
}
|
||||
|
||||
ircd::m::dbs::init::~init()
|
||||
noexcept
|
||||
{
|
||||
ircd::m::event::events = nullptr;
|
||||
|
||||
databases.clear();
|
||||
modules.clear();
|
||||
}
|
||||
|
||||
void
|
||||
ircd::m::dbs::init_databases()
|
||||
{
|
||||
for(const auto &pair : modules)
|
||||
{
|
||||
const auto &name(pair.first);
|
||||
const auto dbname(mods::unpostfixed(name));
|
||||
const std::string shortname(lstrip(dbname, "db_"));
|
||||
const std::string symname(shortname + "_database"s);
|
||||
databases.emplace(shortname, import_shared<database>
|
||||
{
|
||||
dbname, symname
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
ircd::m::dbs::init_modules()
|
||||
{
|
||||
for(const auto &name : mods::available())
|
||||
if(startswith(name, "db_"))
|
||||
modules.emplace(name, name);
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// m/filter.h
|
||||
|
|
1791
ircd/m/vm.cc
1791
ircd/m/vm.cc
File diff suppressed because it is too large
Load diff
|
@ -41,29 +41,6 @@ m::room public_
|
|||
public_room_id
|
||||
};
|
||||
|
||||
//TODO: not a vm witness; use event release state update hook
|
||||
struct witness
|
||||
:m::vm::witness
|
||||
{
|
||||
int add(m::vm::accumulator *const &a, const m::event &event) override final
|
||||
{
|
||||
if(json::get<"type"_>(event) != "m.room.join_rules")
|
||||
return -1;
|
||||
|
||||
const json::object &content{at<"content"_>(event)};
|
||||
const auto &join_rule{content.at("join_rule")};
|
||||
return -1;
|
||||
}
|
||||
|
||||
int del(m::vm::accumulator *const &a, const m::event &event) override final
|
||||
{
|
||||
if(json::get<"type"_>(event) != "m.room.join_rules")
|
||||
return -1;
|
||||
|
||||
return -1;
|
||||
}
|
||||
};
|
||||
|
||||
resource::response
|
||||
get_publicrooms(client &client, const resource::request &request)
|
||||
{
|
||||
|
|
|
@ -339,23 +339,6 @@ put_send(client &client,
|
|||
request.parv[3]
|
||||
};
|
||||
|
||||
json::iov event;
|
||||
|
||||
const json::iov::push _type
|
||||
{
|
||||
event, { "type", type }
|
||||
};
|
||||
|
||||
const json::iov::push _sender
|
||||
{
|
||||
event, { "sender", request.user_id }
|
||||
};
|
||||
|
||||
const json::iov::push _content
|
||||
{
|
||||
event, { "content", json::object{request} }
|
||||
};
|
||||
|
||||
m::room room
|
||||
{
|
||||
room_id
|
||||
|
@ -363,7 +346,7 @@ put_send(client &client,
|
|||
|
||||
const auto event_id
|
||||
{
|
||||
room.send(event)
|
||||
send(room, request.user_id, type, json::object{request})
|
||||
};
|
||||
|
||||
return resource::response
|
||||
|
|
|
@ -489,6 +489,35 @@ const database::descriptor origin_in_room_id
|
|||
origin_in,
|
||||
};
|
||||
|
||||
const database::descriptor origin_joined_in_room_id
|
||||
{
|
||||
// name
|
||||
"origin_joined in room_id",
|
||||
|
||||
// explanation
|
||||
R"(### developer note:
|
||||
|
||||
key is "!room_id:origin"
|
||||
the prefix transform is in effect. this column indexes origins in a
|
||||
room_id offering an iterable bound of the index prefixed by room_id
|
||||
|
||||
)",
|
||||
|
||||
// typing (key, value)
|
||||
{
|
||||
typeid(string_view), typeid(string_view)
|
||||
},
|
||||
|
||||
// options
|
||||
{},
|
||||
|
||||
// comparator - sorts from highest to lowest
|
||||
{}, //ircd::db::reverse_cmp_string_view{},
|
||||
|
||||
// prefix transform
|
||||
origin_in,
|
||||
};
|
||||
|
||||
/// prefix transform for room_id
|
||||
///
|
||||
/// This transform expects a concatenation ending with a room_id which means
|
||||
|
@ -508,31 +537,6 @@ const ircd::db::prefix_transform room_id_in
|
|||
}
|
||||
};
|
||||
|
||||
const database::descriptor event_id_for_room_id_in_sender
|
||||
{
|
||||
// name
|
||||
"event_id for room_id in sender",
|
||||
|
||||
// explanation
|
||||
R"(### developer note:
|
||||
|
||||
)",
|
||||
|
||||
// typing (key, value)
|
||||
{
|
||||
typeid(string_view), typeid(string_view)
|
||||
},
|
||||
|
||||
// options
|
||||
{},
|
||||
|
||||
// comparator
|
||||
{},
|
||||
|
||||
// prefix transform
|
||||
room_id_in,
|
||||
};
|
||||
|
||||
/// prefix transform for type,state_key in room_id
|
||||
///
|
||||
/// This transform is special for concatenating room_id with type and state_key
|
||||
|
@ -653,13 +657,69 @@ const database::descriptor prev_event_id_for_type_state_key_event_id_in_room_id
|
|||
event_id_in_room_id_type_state_key
|
||||
};
|
||||
|
||||
const database::descriptor state_head
|
||||
{
|
||||
// name
|
||||
"state_head",
|
||||
|
||||
// explanation
|
||||
R"(### developer note:
|
||||
|
||||
key is "!room_id"
|
||||
value is the key of a state_node
|
||||
|
||||
)",
|
||||
|
||||
// typing (key, value)
|
||||
{
|
||||
typeid(string_view), typeid(string_view)
|
||||
},
|
||||
|
||||
// options
|
||||
{},
|
||||
|
||||
// comparator
|
||||
{},
|
||||
|
||||
// prefix transform
|
||||
{},
|
||||
};
|
||||
|
||||
const database::descriptor state_node
|
||||
{
|
||||
// name
|
||||
"state_node",
|
||||
|
||||
// explanation
|
||||
R"(### developer note:
|
||||
|
||||
)",
|
||||
|
||||
// typing (key, value)
|
||||
{
|
||||
typeid(string_view), typeid(string_view)
|
||||
},
|
||||
|
||||
// options
|
||||
{},
|
||||
|
||||
// comparator
|
||||
{},
|
||||
|
||||
// prefix transform
|
||||
{},
|
||||
};
|
||||
|
||||
const database::description events_description
|
||||
{
|
||||
{ "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.
|
||||
//
|
||||
events_event_id_descriptor,
|
||||
events_type_descriptor,
|
||||
events_content_descriptor,
|
||||
|
@ -677,43 +737,125 @@ const database::description events_description
|
|||
events_prev_events_descriptor,
|
||||
events_prev_state_descriptor,
|
||||
|
||||
// These columns are metadata composed from the event data. Each column has
|
||||
// a different approach specific to what the query is and value being sought.
|
||||
////////
|
||||
//
|
||||
// These columns are metadata composed from the event data. Specifically,
|
||||
// they are designed for fast sequential iterations.
|
||||
//
|
||||
|
||||
// (sender, event_id) => ()
|
||||
// All events for a sender
|
||||
// Sequence of all events in all rooms for a sender, EVER
|
||||
// * broad but useful in cases
|
||||
event_id_in_sender,
|
||||
|
||||
// (room_id, event_id) => ()
|
||||
// All events for a room
|
||||
// (room_id, event_id) => (state_head)
|
||||
// Sequence of all events for a room, EVER
|
||||
// * broad but useful in cases
|
||||
// * ?eliminate for prev_event?
|
||||
// ? eliminate for prev_event?
|
||||
// ? eliminate/combine with state tree related?
|
||||
event_id_in_room_id,
|
||||
|
||||
// (room_id, origin) => ()
|
||||
// All origins for a room
|
||||
// Sequence of all origins for a room, EVER
|
||||
//TODO: value should have [JOIN, LEAVE, ...) counts/data
|
||||
//TODO: remove?
|
||||
origin_in_room_id,
|
||||
|
||||
// (sender, room_id) => (event_id)
|
||||
// The _last written_ event from a sender in a room
|
||||
event_id_for_room_id_in_sender,
|
||||
// (room_id, origin) => ()
|
||||
// Sequence of all origins with joined member for a room, AT PRESENT
|
||||
// * Intended to be a fast sequential iteration for sending out messages.
|
||||
origin_joined_in_room_id,
|
||||
|
||||
// (room_id, type, state_key) => (event_id)
|
||||
// The _last written_ event of type + state_key in a room
|
||||
// * Proper for room state algorithm, but only works in the present based
|
||||
// on our subjective tape order.
|
||||
// Sequence of events of type+state_key in a room, AT PRESENT
|
||||
// * Fast for current room state iteration, but only works for the present.
|
||||
event_id_for_type_state_key_in_room_id,
|
||||
|
||||
////////
|
||||
//
|
||||
// These columns are metadata composed from the event data. They are
|
||||
// linked forward lists where the value is used to lookup the next key
|
||||
// TODO: these might be better as sequences; if not removed altogether.
|
||||
//
|
||||
|
||||
// (room_id, event_id) => (prev event_id)
|
||||
// Events in a room resolving to the previous event in a room in
|
||||
// our subjective euclidean tape order.
|
||||
// List of events in a room resolving to the previous event in a room
|
||||
// in our subjective euclidean tape TOTAL order.
|
||||
// * This is where any branches in the DAG are linearized based on how we
|
||||
// feel the state machine should execute them one by one.
|
||||
// * This is not a sequence; each value is the key for another lookup.
|
||||
prev_event_id_for_event_id_in_room_id,
|
||||
|
||||
// (room_id, type, state_key, event_id) => (prev event_id)
|
||||
// Events of a (type, state_key) in a room resolving to the previous event
|
||||
// of (type, state_key) in a room in our subjective euclidean tape order.
|
||||
// * Similar to the above but focuses only on state events for various
|
||||
// "state chains"
|
||||
prev_event_id_for_type_state_key_event_id_in_room_id,
|
||||
|
||||
////////
|
||||
//
|
||||
// These columns are metadata composed from the event data. They are
|
||||
// used to create structures that can represent the state of a room
|
||||
// at any given event.
|
||||
//
|
||||
|
||||
// (room_id) => (state_head)
|
||||
state_head,
|
||||
|
||||
// (state tree node id) => (state tree node)
|
||||
//
|
||||
// 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"], ; Left key
|
||||
// ["m.room.member", "@jzk"] ; Right key
|
||||
// ], ;
|
||||
// "v": ; Value array
|
||||
// [ ;
|
||||
// "$14961836116kXQRA:matrix.org", ; Left accept
|
||||
// "GFkS15QjKBKjxSZpz", ; Center child
|
||||
// "HLacMRucdEPdJrzBz" ; Right child
|
||||
// ] ;
|
||||
// } ;
|
||||
//
|
||||
// (note: actual JSON used is canonical and spaceless)
|
||||
//
|
||||
// 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. There is no prefix/trie keying yet, but that should probably
|
||||
// happen. 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"""
|
||||
// ```
|
||||
// The values are either event MXID's or some identifier of a child node.
|
||||
// The event MXID is leaf-data, no child node will be found there. The
|
||||
// common tree traversal rules then apply: if the query value is less
|
||||
// than the first element key, val[0] is followed; if compares between the
|
||||
// first and second key, then val[1] is followed; if it compares greater
|
||||
// than the last key, the last val is followed.
|
||||
//
|
||||
// Unlike traditional trees of such variety, the number of elements is not
|
||||
// really well defined and not even fixed. There just has to be one more
|
||||
// value in the "val" list than there are keys in the "key" list. To make
|
||||
// this structure efficient we have to figure out a good number of
|
||||
// children per node, and that might even be a contextual decision. The
|
||||
// more children, the less depth to the query, but at the cost of a larger
|
||||
// node size. A larger node in this system isn't just relevant to
|
||||
// retrieval, but consider nodes are also immutable. Changes to the tree
|
||||
// create new nodes for each changed path so the old nodes can still
|
||||
// represent the old state. Repacking nodes to represent slightly different
|
||||
// states within the same node is a possible exercise left for the future.
|
||||
//
|
||||
state_node,
|
||||
};
|
||||
|
||||
std::shared_ptr<database> events_database
|
||||
|
|
|
@ -25,234 +25,3 @@ mapi::header IRCD_MODULE
|
|||
{
|
||||
"Matrix virtual Machine - No Operation"
|
||||
};
|
||||
|
||||
namespace ircd::m::vm
|
||||
{
|
||||
extern struct filter_event_id const filter_event_id;
|
||||
extern struct filter_types const filter_types;
|
||||
extern struct isa const isa;
|
||||
}
|
||||
|
||||
struct ircd::m::vm::isa
|
||||
:witness
|
||||
{
|
||||
struct accumulator
|
||||
:vm::accumulator
|
||||
{
|
||||
|
||||
};
|
||||
|
||||
int add(accumulator *const &a, const event &event)
|
||||
{
|
||||
const event::prev &prev{event};
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
int del(accumulator *const &a, const event &event)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
std::unique_ptr<vm::accumulator> init() override final
|
||||
{
|
||||
return std::make_unique<accumulator>();
|
||||
}
|
||||
|
||||
int add(vm::accumulator *const &a, const event &event) override final
|
||||
{
|
||||
return this->add(dynamic_cast<accumulator *>(a), event);
|
||||
}
|
||||
|
||||
int del(vm::accumulator *const &a, const event &event) override final
|
||||
{
|
||||
return this->del(dynamic_cast<accumulator *>(a), event);
|
||||
}
|
||||
|
||||
int test(const vm::accumulator *const &a, const query<> &q) override final
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
isa()
|
||||
:witness
|
||||
{
|
||||
"instruction set architecture"
|
||||
}{}
|
||||
}
|
||||
const ircd::m::vm::isa;
|
||||
|
||||
struct ircd::m::vm::filter_event_id
|
||||
:witness
|
||||
{
|
||||
struct accumulator
|
||||
:vm::accumulator
|
||||
{
|
||||
std::set<std::string, std::less<>> ids;
|
||||
};
|
||||
|
||||
int add(accumulator *const &a, const event &event)
|
||||
{
|
||||
const auto &event_id{at<"event_id"_>(event)};
|
||||
const auto iit
|
||||
{
|
||||
a->ids.emplace(std::string(event_id))
|
||||
};
|
||||
|
||||
//std::cout << "added: " << iit.second << std::endl;
|
||||
return iit.second;
|
||||
}
|
||||
|
||||
int del(accumulator *const &a, const event &event)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
int test(const accumulator *const &a, const query<> &q)
|
||||
{
|
||||
if(q.type != vm::where::equal)
|
||||
return -1;
|
||||
|
||||
const auto &qq
|
||||
{
|
||||
dynamic_cast<const query<where::equal> &>(q)
|
||||
};
|
||||
|
||||
const string_view &event_id
|
||||
{
|
||||
at<"event_id"_>(qq.value)
|
||||
};
|
||||
|
||||
return a->ids.find(event_id) != end(a->ids);
|
||||
}
|
||||
|
||||
std::unique_ptr<vm::accumulator> init() override final
|
||||
{
|
||||
return std::make_unique<accumulator>();
|
||||
}
|
||||
|
||||
int add(vm::accumulator *const &a, const event &event) override final
|
||||
{
|
||||
return this->add(dynamic_cast<accumulator *>(a), event);
|
||||
}
|
||||
|
||||
int del(vm::accumulator *const &a, const event &event) override final
|
||||
{
|
||||
return this->del(dynamic_cast<accumulator *>(a), event);
|
||||
}
|
||||
|
||||
int test(const vm::accumulator *const &a, const query<> &q) override final
|
||||
{
|
||||
return this->test(dynamic_cast<const accumulator *>(a), q);
|
||||
}
|
||||
|
||||
filter_event_id()
|
||||
:witness
|
||||
{
|
||||
"event_id does not exist"
|
||||
}{}
|
||||
}
|
||||
const ircd::m::vm::filter_event_id;
|
||||
|
||||
struct ircd::m::vm::filter_types
|
||||
:witness
|
||||
{
|
||||
struct accumulator
|
||||
:vm::accumulator
|
||||
{
|
||||
std::set<std::string, std::less<>> types;
|
||||
};
|
||||
|
||||
int add(accumulator *const &a, const event &event)
|
||||
{
|
||||
const string_view &type{json::get<"type"_>(event)};
|
||||
if(empty(type))
|
||||
return -1;
|
||||
|
||||
const auto iit
|
||||
{
|
||||
a->types.emplace(std::string(type))
|
||||
};
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
int del(accumulator *const &a, const event &event)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
int test(const accumulator *const &a, const query<> &q)
|
||||
{
|
||||
if(q.type != vm::where::equal)
|
||||
return -1;
|
||||
|
||||
const auto &qq
|
||||
{
|
||||
dynamic_cast<const query<where::equal> &>(q)
|
||||
};
|
||||
|
||||
const string_view &type{json::get<"type"_>(qq.value)};
|
||||
if(empty(type))
|
||||
return -1;
|
||||
|
||||
const auto count
|
||||
{
|
||||
a->types.count(type)
|
||||
};
|
||||
|
||||
return count > 0;
|
||||
}
|
||||
|
||||
ssize_t count(const accumulator *const &a, const query<> &q)
|
||||
{
|
||||
if(q.type != vm::where::equal)
|
||||
return -1;
|
||||
|
||||
const auto &qq
|
||||
{
|
||||
dynamic_cast<const query<where::equal> &>(q)
|
||||
};
|
||||
|
||||
const string_view &type{json::get<"type"_>(qq.value)};
|
||||
if(empty(type))
|
||||
return -1;
|
||||
|
||||
if(!a->types.count(type))
|
||||
return 0;
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
std::unique_ptr<vm::accumulator> init() override final
|
||||
{
|
||||
return std::make_unique<accumulator>();
|
||||
}
|
||||
|
||||
int add(vm::accumulator *const &a, const event &event) override final
|
||||
{
|
||||
return this->add(dynamic_cast<accumulator *>(a), event);
|
||||
}
|
||||
|
||||
int del(vm::accumulator *const &a, const event &event) override final
|
||||
{
|
||||
return this->del(dynamic_cast<accumulator *>(a), event);
|
||||
}
|
||||
|
||||
int test(const vm::accumulator *const &a, const query<> &query) override final
|
||||
{
|
||||
return this->test(dynamic_cast<const accumulator *>(a), query);
|
||||
}
|
||||
|
||||
ssize_t count(const vm::accumulator *const &a, const query<> &query) override final
|
||||
{
|
||||
return this->count(dynamic_cast<const accumulator *>(a), query);
|
||||
}
|
||||
|
||||
filter_types()
|
||||
:witness
|
||||
{
|
||||
"type has not been seen"
|
||||
}{}
|
||||
}
|
||||
const ircd::m::vm::filter_types;
|
||||
|
|
Loading…
Reference in a new issue