0
0
Fork 0
mirror of https://github.com/matrix-construct/construct synced 2024-06-16 08:58:20 +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 // copyright notice and this permission notice is present in all copies. The
// full license for this software is available in the LICENSE file. // 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_MODULE_EXPORT
ircd::m::room::head::generate::generate(const mutable_buffer &buf, ircd::m::room::head::generate::generate(const mutable_buffer &buf,
const m::room::head &head, const m::room::head &head,
const opts &opts) const opts &opts)
{ {
if(!head.room) if(empty(buf))
return; return;
json::stack out{buf}; json::stack out{buf};
@ -42,37 +48,23 @@ ircd::m::room::head::generate::generate(json::stack::array &out,
if(!head.room) if(!head.room)
return; return;
const m::event::id::closure &v1_ref{[&out] // Query the room version unless hinted in the opts
(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);
}};
char versionbuf[32]; char versionbuf[32];
const auto version const auto version
{ {
m::version(versionbuf, head.room, std::nothrow) 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 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 const auto top_head
{ {
opts.need_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>{} std::tuple<m::id::event::buf, int64_t, m::event::idx>{}
}; };
m::event::fetch event; // Iterate the room head; starts with oldest events
size_t limit{opts.limit};
bool need_top_head{opts.need_top_head}; bool need_top_head{opts.need_top_head};
bool need_my_head{opts.need_my_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; return true;
if(need_top_head) // Add this head reference to result to output.
if(event.event_id == std::get<0>(top_head)) append(out, event_id);
need_top_head = false;
const auto _append{[&]() -> bool // Determine the depth for metrics
const int64_t depth
{ {
if(need_my_head && my(event)) event_id == std::get<0>(top_head)?
need_my_head = false; std::get<int64_t>(top_head):
m::get<int64_t>(event_idx, "depth")
};
append(event_id); // Indicate if this depth is highest or lowest of the set.
this->depth[0] = std::min(json::get<"depth"_>(event), this->depth[0]); this->depth[0] = std::min(depth, this->depth[0]);
this->depth[1] = std::max(json::get<"depth"_>(event), this->depth[1]); this->depth[1] = std::max(depth, this->depth[1]);
return --limit - need_top_head - need_my_head > 0;
}};
if(limit - need_top_head - need_my_head > 0) // Continue loop until we're out of slots.
{ return --limit > 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;
}); });
// If the iteration did not provide us with the top_head and the opts
// require it, we add that here.
if(need_top_head) if(need_top_head)
{ {
assert(limit > 0); assert(limit > 0);
append(std::get<0>(top_head)); append(out, std::get<0>(top_head));
this->depth[1] = std::get<1>(top_head); this->depth[1] = std::get<1>(top_head);
need_top_head = false;
--limit; --limit;
} }
if(!need_my_head || limit <= 0) // If the iteration did not provide us with any heads from this origin
return; // and the opts require it, we find and add that here.
if(need_my_head)
for(m::room::events it{head.room}; it; --it) for(m::room::events it{head.room}; it; --it)
{
const bool my_sender
{ {
m::query<bool>(std::nothrow, event::idx{it}, "sender", false, [] if(!event::my(it.event_idx()))
(const m::user::id &user_id) continue;
const auto event_id
{ {
return m::my(user_id); m::event_id(it.event_idx(), std::nothrow)
}) };
};
if(!my_sender) if(unlikely(!event_id))
continue; continue;
const auto event_id assert(limit > 0);
{ append(out, event_id);
m::event_id(event::idx{it}, std::nothrow) 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) assert(limit >= 0);
continue; }
assert(limit > 0); void
append(event_id); ircd::m::append_v1(json::stack::array &out,
const int64_t &depth(it.depth()); const event::id &event_id)
this->depth[0] = std::min(depth, this->depth[0]); {
this->depth[1] = std::max(depth, this->depth[1]); json::stack::array prev
need_my_head = false; {
--limit; out
break; };
}
// [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 size_t