0
0
Fork 0
mirror of https://github.com/matrix-construct/construct synced 2024-05-23 21:33:44 +02:00

ircd:Ⓜ️:room::head: Improve/cleanup generator related.

This commit is contained in:
Jason Volk 2019-12-10 11:07:44 -08:00
parent 5c74bfbd7f
commit 275f5aa3cd

View file

@ -8,12 +8,18 @@
// copyright notice and this permission notice is present in all copies. The
// full license for this software is available in the LICENSE file.
namespace ircd::m
{
static void append_v1(json::stack::array &, const event::id &);
static void append_v3(json::stack::array &, const event::id &);
}
IRCD_MODULE_EXPORT
ircd::m::room::head::generate::generate(const mutable_buffer &buf,
const m::room::head &head,
const opts &opts)
{
if(!head.room)
if(empty(buf))
return;
json::stack out{buf};
@ -42,37 +48,23 @@ ircd::m::room::head::generate::generate(json::stack::array &out,
if(!head.room)
return;
const m::event::id::closure &v1_ref{[&out]
(const auto &event_id)
{
json::stack::array prev{out};
prev.append(event_id);
{
json::stack::object nilly{prev};
json::stack::member willy
{
nilly, "", ""
};
}
}};
const m::event::id::closure &v3_ref{[&out]
(const auto &event_id)
{
out.append(event_id);
}};
// Query the room version unless hinted in the opts
char versionbuf[32];
const auto version
{
m::version(versionbuf, head.room, std::nothrow)
};
// The output format depends on the room version; we select an output
// function for the format here so we can abstractly call append().
const auto &append
{
version == "1" || version == "2"? v1_ref : v3_ref
version == "1" || version == "2"?
append_v1:
append_v3
};
// When the top_head option is given we query for that here
const auto top_head
{
opts.need_top_head?
@ -80,89 +72,121 @@ ircd::m::room::head::generate::generate(json::stack::array &out,
std::tuple<m::id::event::buf, int64_t, m::event::idx>{}
};
m::event::fetch event;
size_t limit{opts.limit};
// Iterate the room head; starts with oldest events
bool need_top_head{opts.need_top_head};
bool need_my_head{opts.need_my_head};
head.for_each([&](const m::event::idx &event_idx, const m::event::id &event_id)
ssize_t limit(opts.limit);
head.for_each([&]
(const event::idx &event_idx, const event::id &event_id)
{
if(!seek(event, event_idx, event_id, std::nothrow))
// When using the need_my_head option, if we hit a head which
// originated from this server we mark that is no longer needed.
if(need_my_head && event::my(event_idx))
need_my_head = false;
// If we hit the top_head during the loop we can mark that satisfied.
if(need_top_head && event_id == std::get<0>(top_head))
need_top_head = false;
// Two reference slots are reserved to fulfill these features; the
// loop will iterate without appending anything else.
const ssize_t remain
{
limit - need_my_head - need_top_head
};
// Skip/continue the loop if all that remains are reserved slots.
if(remain <= 0)
return true;
if(need_top_head)
if(event.event_id == std::get<0>(top_head))
need_top_head = false;
// Add this head reference to result to output.
append(out, event_id);
const auto _append{[&]() -> bool
// Determine the depth for metrics
const int64_t depth
{
if(need_my_head && my(event))
need_my_head = false;
event_id == std::get<0>(top_head)?
std::get<int64_t>(top_head):
m::get<int64_t>(event_idx, "depth")
};
append(event_id);
this->depth[0] = std::min(json::get<"depth"_>(event), this->depth[0]);
this->depth[1] = std::max(json::get<"depth"_>(event), this->depth[1]);
return --limit - need_top_head - need_my_head > 0;
}};
// Indicate if this depth is highest or lowest of the set.
this->depth[0] = std::min(depth, this->depth[0]);
this->depth[1] = std::max(depth, this->depth[1]);
if(limit - need_top_head - need_my_head > 0)
{
if(need_my_head && my(event))
need_my_head = false;
return _append();
}
if(!need_my_head)
return false;
if(my(event))
return _append();
else
return limit > 0;
// Continue loop until we're out of slots.
return --limit > 0;
});
// If the iteration did not provide us with the top_head and the opts
// require it, we add that here.
if(need_top_head)
{
assert(limit > 0);
append(std::get<0>(top_head));
append(out, std::get<0>(top_head));
this->depth[1] = std::get<1>(top_head);
need_top_head = false;
--limit;
}
if(!need_my_head || limit <= 0)
return;
for(m::room::events it{head.room}; it; --it)
{
const bool my_sender
// If the iteration did not provide us with any heads from this origin
// and the opts require it, we find and add that here.
if(need_my_head)
for(m::room::events it{head.room}; it; --it)
{
m::query<bool>(std::nothrow, event::idx{it}, "sender", false, []
(const m::user::id &user_id)
if(!event::my(it.event_idx()))
continue;
const auto event_id
{
return m::my(user_id);
})
};
m::event_id(it.event_idx(), std::nothrow)
};
if(!my_sender)
continue;
if(unlikely(!event_id))
continue;
const auto event_id
{
m::event_id(event::idx{it}, std::nothrow)
};
assert(limit > 0);
append(out, event_id);
const int64_t &depth(it.depth());
this->depth[0] = std::min(depth, this->depth[0]);
this->depth[1] = std::max(depth, this->depth[1]);
need_my_head = false;
--limit;
break;
}
if(!event_id)
continue;
assert(limit >= 0);
}
assert(limit > 0);
append(event_id);
const int64_t &depth(it.depth());
this->depth[0] = std::min(depth, this->depth[0]);
this->depth[1] = std::max(depth, this->depth[1]);
need_my_head = false;
--limit;
break;
}
void
ircd::m::append_v1(json::stack::array &out,
const event::id &event_id)
{
json::stack::array prev
{
out
};
// [0]
prev.append(event_id);
// [1]
json::stack::object nilly
{
prev
};
json::stack::member
{
nilly, "", ""
};
}
void
ircd::m::append_v3(json::stack::array &out,
const event::id &event_id)
{
out.append(event_id);
}
size_t