0
0
Fork 0
mirror of https://github.com/matrix-construct/construct synced 2024-06-11 06:28:55 +02:00

ircd:Ⓜ️:vm: Move eval entry related into modules/vm; convert phase to struct.

This commit is contained in:
Jason Volk 2018-05-29 04:04:32 -07:00
parent 52767c836f
commit de8e7b5908
3 changed files with 122 additions and 99 deletions

View file

@ -19,6 +19,7 @@ namespace ircd::m::vm
struct opts;
struct copts;
struct eval;
struct phase;
struct accepted;
enum fault :uint;
using fault_t = std::underlying_type<fault>::type;
@ -45,8 +46,6 @@ namespace ircd::m::vm
struct ircd::m::vm::eval
:instance_list<eval>
{
enum phase :uint8_t;
static uint64_t id_ctr; // monotonic
const vm::opts *opts {&default_opts};
@ -56,7 +55,7 @@ struct ircd::m::vm::eval
string_view room_id;
const json::iov *issue {nullptr};
const event *event_ {nullptr};
enum phase phase {(enum phase)0};
vm::phase *phase {nullptr};
uint64_t sequence {0};
db::txn *txn {nullptr};
event::id::buf event_id;
@ -77,16 +76,6 @@ struct ircd::m::vm::eval
eval(eval &&) = delete;
eval(const eval &) = delete;
~eval() noexcept;
friend string_view reflect(const enum phase &);
};
/// Evaluation phases
enum ircd::m::vm::eval::phase
:uint8_t
{
ACCEPT = 0x00,
ENTER = 0x01,
};
/// Evaluation faults. These are reasons which evaluation has halted but may
@ -253,6 +242,14 @@ struct ircd::m::vm::copts
bool infolog_postcommit {false};
};
struct ircd::m::vm::phase
:instance_list<phase>
{
string_view name;
phase(const string_view &name);
};
struct ircd::m::vm::accepted
:m::event
{

View file

@ -402,6 +402,13 @@ decltype(ircd::m::vm::default_copts)
ircd::m::vm::default_copts
{};
//
// Eval
//
// Processes any event from any place from any time and does whatever is
// necessary to validate, reject, learn from new information, ignore old
// information and advance the state of IRCd as best as possible.
/// Instance list linkage for all of the evaluations.
template<>
decltype(ircd::util::instance_list<ircd::m::vm::eval>::list)
@ -412,13 +419,6 @@ decltype(ircd::m::vm::eval::id_ctr)
ircd::m::vm::eval::id_ctr
{};
//
// Eval
//
// Processes any event from any place from any time and does whatever is
// necessary to validate, reject, learn from new information, ignore old
// information and advance the state of IRCd as best as possible.
//
// eval::eval
//
@ -501,31 +501,6 @@ ircd::m::vm::eval::operator()(const room &room,
"vm", "eval__commit_room"
};
// This eval entry point is only used for commits. We try to find the
// commit opts the user supplied directly to this eval or with the room.
if(!copts)
copts = room.copts;
if(!copts)
copts = &vm::default_copts;
// Note that the regular opts is unconditionally overridden because the
// user should have provided copts instead.
this->opts = copts;
// Set a member pointer to the json::iov currently being composed. This
// allows other parallel evals to have deep access to exactly what this
// eval is attempting to do.
issue = &event;
room_id = room.room_id;
phase = phase::ENTER;
const unwind deissue{[this]
{
phase = phase::ACCEPT;
room_id = {};
issue = nullptr;
}};
return function(*this, room, event, contents);
}
@ -542,36 +517,6 @@ ircd::m::vm::eval::operator()(json::iov &event,
"vm", "eval__commit"
};
// This eval entry point is only used for commits. If the user did not
// supply commit opts we supply the default ones here.
if(!copts)
copts = &vm::default_copts;
// Note that the regular opts is unconditionally overridden because the
// user should have provided copts instead.
this->opts = copts;
// Set a member pointer to the json::iov currently being composed. This
// allows other parallel evals to have deep access to exactly what this
// eval is attempting to do.
assert(!room_id || issue == &event);
if(!room_id)
{
issue = &event;
phase = phase::ENTER;
}
const unwind deissue{[this]
{
// issue is untouched when room_id is set; that indicates it was set
// and will be unset by another eval function (i.e above).
if(!room_id)
{
phase = phase::ACCEPT;
issue = nullptr;
}
}};
return function(*this, event, contents);
}
@ -585,21 +530,6 @@ ircd::m::vm::eval::operator()(const event &event)
"vm", "eval__event"
};
// Set a member pointer to the event currently being evaluated. This
// allows other parallel evals to have deep access to exactly what this
// eval is working on. The pointer must be nulled on the way out.
this->event_= &event;
if(!issue)
phase = phase::ENTER;
const unwind null_event{[this]
{
if(!issue)
phase = phase::ACCEPT;
this->event_ = nullptr;
}};
return function(*this, event);
}
@ -670,16 +600,20 @@ ircd::m::vm::reflect(const enum fault &code)
return "??????";
}
ircd::string_view
ircd::m::vm::reflect(const enum eval::phase &phase)
{
switch(phase)
{
case eval::phase::ACCEPT: return "ACCEPT";
case eval::phase::ENTER: return "ENTER";
}
//
// vm::phase
//
return "??????";
/// Instance list linkage for all of the vm phases
template<>
decltype(ircd::util::instance_list<ircd::m::vm::phase>::list)
ircd::util::instance_list<ircd::m::vm::phase>::list
{};
ircd::m::vm::phase::phase(const string_view &name)
:name{name}
{
}
//

View file

@ -14,6 +14,8 @@ namespace ircd::m::vm
extern hook::site<> commit_hook;
extern hook::site<> eval_hook;
extern hook::site<> notify_hook;
extern phase enter;
extern phase leave;
static void write(eval &);
static fault _eval_edu(eval &, const event &);
@ -105,6 +107,31 @@ ircd::m::vm::eval__commit_room(eval &eval,
json::iov &event,
const json::iov &contents)
{
// This eval entry point is only used for commits. We try to find the
// commit opts the user supplied directly to this eval or with the room.
if(!eval.copts)
eval.copts = room.copts;
if(!eval.copts)
eval.copts = &vm::default_copts;
// Note that the regular opts is unconditionally overridden because the
// user should have provided copts instead.
eval.opts = eval.copts;
// Set a member pointer to the json::iov currently being composed. This
// allows other parallel evals to have deep access to exactly what this
// eval is attempting to do.
eval.issue = &event;
eval.room_id = room.room_id;
eval.phase = &vm::enter;
const unwind deissue{[&eval]
{
eval.phase = &vm::leave;
eval.room_id = {};
eval.issue = nullptr;
}};
assert(eval.issue);
assert(eval.room_id);
assert(eval.copts);
@ -276,6 +303,36 @@ ircd::m::vm::eval__commit(eval &eval,
json::iov &event,
const json::iov &contents)
{
// This eval entry point is only used for commits. If the user did not
// supply commit opts we supply the default ones here.
if(!eval.copts)
eval.copts = &vm::default_copts;
// Note that the regular opts is unconditionally overridden because the
// user should have provided copts instead.
eval.opts = eval.copts;
// Set a member pointer to the json::iov currently being composed. This
// allows other parallel evals to have deep access to exactly what this
// eval is attempting to do.
assert(!eval.room_id || eval.issue == &event);
if(!eval.room_id)
{
eval.issue = &event;
eval.phase = &enter;
}
const unwind deissue{[&eval]
{
// issue is untouched when room_id is set; that indicates it was set
// and will be unset by another eval function (i.e above).
if(!eval.room_id)
{
eval.phase = &leave;
eval.issue = nullptr;
}
}};
assert(eval.issue);
assert(eval.copts);
assert(eval.opts);
@ -388,6 +445,21 @@ ircd::m::vm::eval__event(eval &eval,
const event &event)
try
{
// Set a member pointer to the event currently being evaluated. This
// allows other parallel evals to have deep access to exactly what this
// eval is working on. The pointer must be nulled on the way out.
eval.event_ = &event;
if(!eval.issue)
eval.phase = &enter;
const unwind null_event{[&eval]
{
if(!eval.issue)
eval.phase = &leave;
eval.event_ = nullptr;
}};
assert(eval.opts);
assert(eval.event_);
assert(eval.id);
@ -754,3 +826,23 @@ ircd::m::vm::retired_sequence(event::id::buf &event_id)
event_id = it->second;
return ret;
}
//
// phase enter
//
decltype(ircd::m::vm::enter)
ircd::m::vm::enter
{
"enter"
};
//
// phase leave
//
decltype(ircd::m::vm::leave)
ircd::m::vm::leave
{
"leave"
};