diff --git a/include/ircd/m/vm.h b/include/ircd/m/vm.h index ce1338917..04072e580 100644 --- a/include/ircd/m/vm.h +++ b/include/ircd/m/vm.h @@ -28,6 +28,7 @@ namespace ircd::m::vm extern const opts default_opts; extern const copts default_copts; + string_view reflect(const fault &); const uint64_t &sequence(const eval &); uint64_t retired_sequence(id::event::buf &); uint64_t retired_sequence(); @@ -44,19 +45,23 @@ namespace ircd::m::vm struct ircd::m::vm::eval :instance_list { + enum phase :uint8_t; + static uint64_t id_ctr; // monotonic const vm::opts *opts {&default_opts}; const vm::copts *copts {nullptr}; ctx::ctx *ctx {ctx::current}; uint64_t id {++id_ctr}; - uint64_t sequence {0}; - db::txn *txn {nullptr}; + string_view room_id; const json::iov *issue {nullptr}; const event *event_ {nullptr}; - string_view room_id; + enum phase phase {(enum phase)0}; + uint64_t sequence {0}; + db::txn *txn {nullptr}; event::id::buf event_id; + public: operator const event::id::buf &() const; fault operator()(const event &); @@ -73,7 +78,15 @@ struct ircd::m::vm::eval eval(const eval &) = delete; ~eval() noexcept; - friend string_view reflect(const fault &); + 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 diff --git a/ircd/m/m.cc b/ircd/m/m.cc index 3e971853b..fc916a930 100644 --- a/ircd/m/m.cc +++ b/ircd/m/m.cc @@ -513,8 +513,10 @@ ircd::m::vm::eval::operator()(const room &room, // 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; }}; @@ -548,13 +550,21 @@ ircd::m::vm::eval::operator()(json::iov &event, // allows other parallel evals to have deep access to exactly what this // eval is attempting to do. assert(!room_id || issue == &event); - 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); @@ -574,8 +584,14 @@ ircd::m::vm::eval::operator()(const event &event) // 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; }}; @@ -649,6 +665,18 @@ 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"; + } + + return "??????"; +} + // // accepted //