0
0
Fork 0
mirror of https://github.com/matrix-construct/construct synced 2024-05-28 15:53:46 +02:00

ircd:Ⓜ️ Add dbs namespace; remove old interfaces; checkpoint various.

This commit is contained in:
Jason Volk 2018-01-26 12:26:09 -08:00
parent ed5b4d0641
commit a9cada32db
14 changed files with 1502 additions and 2217 deletions

View file

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

View file

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

View file

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

View file

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

View file

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

File diff suppressed because it is too large Load diff

View file

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

View file

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

File diff suppressed because it is too large Load diff

View file

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

View file

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

View file

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

View file

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