mirror of
https://github.com/matrix-construct/construct
synced 2025-03-13 21:10:32 +01:00
ircd:Ⓜ️:vm: Move vm::eval inner-loop logic into vm::execute; fix room_version/event_id.
This commit is contained in:
parent
ebae05d1f3
commit
8db2bf629e
2 changed files with 73 additions and 50 deletions
|
@ -299,46 +299,11 @@ ircd::m::vm::eval::operator()(const vector_view<m::event> &events)
|
|||
size_t ret(0);
|
||||
for(auto it(begin(events)); it != end(events); ++it) try
|
||||
{
|
||||
auto &event
|
||||
const m::event &event
|
||||
{
|
||||
const_cast<m::event &>(*it)
|
||||
*it
|
||||
};
|
||||
|
||||
// We have to set the event_id in the event instance if it didn't come
|
||||
// with the event JSON.
|
||||
if(!opts->edu && !event.event_id)
|
||||
event.event_id = opts->room_version == "3"?
|
||||
event::id{event::id::v3{this->event_id, event}}:
|
||||
event::id{event::id::v4{this->event_id, event}};
|
||||
|
||||
// If we set the event_id in the event instance we have to unset
|
||||
// it so other contexts don't see an invalid reference.
|
||||
const unwind event_id{[&event]
|
||||
{
|
||||
event.event_id = json::get<"event_id"_>(event)?
|
||||
event.event_id:
|
||||
m::event::id{};
|
||||
}};
|
||||
|
||||
// When a fault::EXISTS would not actually be revealed to the user in
|
||||
// any way we can elide a lot of grief by checking this here first and
|
||||
// skipping the event. The query path will be adequately cached anyway.
|
||||
if(event.event_id && ~(opts->warnlog | opts->errorlog) & fault::EXISTS)
|
||||
{
|
||||
// If the event is already being evaluated, wait here until the other
|
||||
// evaluation is finished. If the other was successful, the exists()
|
||||
// check will skip this, otherwise we have to try again here because
|
||||
// this evaluator might be using different options/credentials.
|
||||
if(likely(opts->unique))
|
||||
sequence::dock.wait([&event]
|
||||
{
|
||||
return eval::count(event.event_id) == 0;
|
||||
});
|
||||
|
||||
if(likely(!opts->replays) && m::exists(event.event_id))
|
||||
continue;
|
||||
}
|
||||
|
||||
const auto status
|
||||
{
|
||||
operator()(event)
|
||||
|
|
|
@ -18,6 +18,7 @@ namespace ircd::m::vm
|
|||
static void write_prepare(eval &, const event &);
|
||||
static fault execute_edu(eval &, const event &);
|
||||
static fault execute_pdu(eval &, const event &);
|
||||
static fault execute_du(eval &, const event &);
|
||||
static fault inject3(eval &, json::iov &, const json::iov &);
|
||||
static fault inject1(eval &, json::iov &, const json::iov &);
|
||||
static void fini();
|
||||
|
@ -115,7 +116,6 @@ ircd::m::vm::effect_hook
|
|||
ircd::m::vm::fault
|
||||
ircd::m::vm::execute(eval &eval,
|
||||
const event &event)
|
||||
try
|
||||
{
|
||||
// This assertion is tripped if the end of your context's stack is
|
||||
// danger close; try increasing your stack size.
|
||||
|
@ -132,17 +132,10 @@ try
|
|||
vm::dock
|
||||
};
|
||||
|
||||
// Set a member pointer to the event currently being evaluated. This
|
||||
// allows other parallel evals to have deep access to this eval.
|
||||
assert(!eval.event_);
|
||||
const scope_restore eval_event
|
||||
assert(eval.opts);
|
||||
const auto &opts
|
||||
{
|
||||
eval.event_, &event
|
||||
};
|
||||
|
||||
const scope_restore<event::id> eval_event_id
|
||||
{
|
||||
eval.event_id, event.event_id? event.event_id : eval.event_id
|
||||
*eval.opts
|
||||
};
|
||||
|
||||
// Set a member to the room_id for convenient access, without stepping on
|
||||
|
@ -180,15 +173,80 @@ try
|
|||
m::version(room_version_buf, room{eval.room_id}, std::nothrow)
|
||||
};
|
||||
|
||||
assert(eval.opts);
|
||||
assert(eval.event_);
|
||||
// We have to set the event_id in the event instance if it didn't come
|
||||
// with the event JSON.
|
||||
if(!opts.edu && !event.event_id)
|
||||
const_cast<m::event &>(event).event_id = eval.room_version == "3"?
|
||||
event::id{event::id::v3{eval.event_id, event}}:
|
||||
event::id{event::id::v4{eval.event_id, event}};
|
||||
|
||||
// If we set the event_id in the event instance we have to unset
|
||||
// it so other contexts don't see an invalid reference.
|
||||
const unwind restore_event_id{[&event]
|
||||
{
|
||||
const_cast<m::event &>(event).event_id = json::get<"event_id"_>(event)?
|
||||
event.event_id:
|
||||
m::event::id{};
|
||||
}};
|
||||
|
||||
// If the event is already being evaluated, wait here until the other
|
||||
// evaluation is finished. If the other was successful, the exists()
|
||||
// check will skip this, otherwise we have to try again here because
|
||||
// this evaluator might be using different options/credentials.
|
||||
if(likely(opts.unique) && event.event_id)
|
||||
sequence::dock.wait([&event]
|
||||
{
|
||||
return eval::count(event.event_id) <= 1;
|
||||
});
|
||||
|
||||
// We can elide a lot of grief here by not proceeding further and simply
|
||||
// returning fault::EXISTS after an existence check. If we had to wait for
|
||||
// a duplicate eval this check will indicate its success.
|
||||
if(likely(!opts.replays && opts.nothrows & fault::EXISTS) && event.event_id)
|
||||
if(m::exists(event.event_id))
|
||||
return fault::EXISTS;
|
||||
|
||||
return execute_du(eval, event);
|
||||
}
|
||||
|
||||
ircd::m::vm::fault
|
||||
ircd::m::vm::execute_du(eval &eval,
|
||||
const event &event)
|
||||
try
|
||||
{
|
||||
assert(eval.id);
|
||||
assert(eval.ctx);
|
||||
assert(eval.opts);
|
||||
const auto &opts
|
||||
{
|
||||
*eval.opts
|
||||
};
|
||||
|
||||
// Set a member pointer to the event currently being evaluated. This
|
||||
// allows other parallel evals to have deep access to this eval. It also
|
||||
// will be used to count this event as currently being evaluated.
|
||||
assert(!eval.event_);
|
||||
const scope_restore eval_event
|
||||
{
|
||||
eval.event_, &event
|
||||
};
|
||||
|
||||
// Ensure the member pointer/buffer to the eval's event_id is set in case
|
||||
// anything needs this to be in sync with event.event_id. This may be also
|
||||
// be used to onsider this event as currently being evaluated.
|
||||
const scope_restore<event::id> eval_event_id
|
||||
{
|
||||
eval.event_id,
|
||||
event.event_id?
|
||||
event.event_id:
|
||||
eval.event_id
|
||||
};
|
||||
|
||||
assert(eval.opts->edu || event.event_id);
|
||||
assert(eval.opts->edu || eval.event_id);
|
||||
assert(eval.event_id == event.event_id);
|
||||
assert(eval.event_);
|
||||
|
||||
// The issue hook is only called when this server is injecting a newly
|
||||
// created event.
|
||||
if(eval.copts && eval.copts->issue)
|
||||
|
|
Loading…
Add table
Reference in a new issue