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 interface/linkage for head utils / prev_events generation.

This commit is contained in:
Jason Volk 2019-03-05 23:19:16 -08:00
parent 1a1939e2c7
commit c2966275c6
5 changed files with 289 additions and 207 deletions

View file

@ -43,6 +43,13 @@ struct ircd::m::room::head
using closure = std::function<void (const event::idx &, const event::id &)>;
using closure_bool = std::function<bool (const event::idx &, const event::id &)>;
static size_t reset(const head &);
static size_t rebuild(const head &);
static void modify(const event::id &, const db::op &, const bool &);
static int64_t make_refs(const head &, json::stack::array &, const size_t &, const bool &);
static bool for_each(const head &, const closure_bool &);
public:
m::room room;
bool for_each(const closure_bool &) const;
@ -50,6 +57,9 @@ struct ircd::m::room::head
bool has(const event::id &) const;
size_t count() const;
int64_t make_refs(json::stack::array &, const size_t &, const bool &) const;
std::pair<json::array, int64_t> make_refs(const mutable_buffer &, const size_t &, const bool &) const;
head(const m::room &room)
:room{room}
{}

View file

@ -2036,6 +2036,35 @@ const
// room::head
//
std::pair<ircd::json::array, int64_t>
ircd::m::room::head::make_refs(const mutable_buffer &buf,
const size_t &limit,
const bool &need_top)
const
{
json::stack out{buf};
json::stack::array array{out};
const auto depth
{
make_refs(array, limit, need_top)
};
array.~array();
return
{
json::array{out.completed()},
depth
};
}
int64_t
ircd::m::room::head::make_refs(json::stack::array &out,
const size_t &limit,
const bool &need_top)
const
{
return make_refs(*this, out, limit, need_top);
}
size_t
ircd::m::room::head::count()
const
@ -2081,33 +2110,78 @@ bool
ircd::m::room::head::for_each(const closure_bool &closure)
const
{
auto &index
return for_each(*this, closure);
}
bool
ircd::m::room::head::for_each(const head &h,
const closure_bool &c)
{
using prototype = bool (const head &, const closure_bool &);
static mods::import<prototype> call
{
dbs::room_head
"m_room", "ircd::m::room::head::for_each"
};
auto it
return call(h, c);
}
int64_t
ircd::m::room::head::make_refs(const head &h,
json::stack::array &a,
const size_t &limit,
const bool &need_top)
{
using prototype = int64_t (const head &, json::stack::array &, const size_t &, const bool &);
static mods::import<prototype> call
{
index.begin(room.room_id)
"m_room", "ircd::m::room::head::make_refs"
};
for(; it; ++it)
return call(h, a, limit, need_top);
}
void
ircd::m::room::head::modify(const event::id &event_id,
const db::op &op,
const bool &refs)
{
using prototype = void (const event::id &, const db::op &, const bool &);
static mods::import<prototype> call
{
const event::id &event_id
{
dbs::room_head_key(it->first)
};
"m_room", "ircd::m::room::head::modify"
};
const event::idx &event_idx
{
byte_view<event::idx>{it->second}
};
return call(event_id, op, refs);
}
if(!closure(event_idx, event_id))
return false;
}
size_t
ircd::m::room::head::rebuild(const head &h)
{
using prototype = size_t (const head &);
return true;
static mods::import<prototype> call
{
"m_room", "ircd::m::room::head::rebuild"
};
return call(h);
}
size_t
ircd::m::room::head::reset(const head &h)
{
using prototype = size_t (const head &);
static mods::import<prototype> call
{
"m_room", "ircd::m::room::head::reset"
};
return call(h);
}
//

View file

@ -5033,19 +5033,20 @@ console_cmd__stage__make_prev(opt &out, const string_view &line)
stage.at(id)
};
using prototype = std::pair<json::array, int64_t> (const m::room &,
const mutable_buffer &,
const size_t &,
const bool &);
static mods::import<prototype> make_prev__buf
const m::room room
{
"m_room", "make_prev__buf"
at<"room_id"_>(event)
};
const m::room::head head
{
room
};
thread_local char buf[8192];
const auto prev
{
make_prev__buf(m::room{at<"room_id"_>(event)}, buf, limit, true)
head.make_refs(buf, limit, true)
};
json::get<"prev_events"_>(event) = prev.first;
@ -6790,15 +6791,14 @@ console_cmd__room__head__rebuild(opt &out, const string_view &line)
room_id
};
using prototype = size_t (const m::room &);
static mods::import<prototype> head__rebuild
const m::room::head head
{
"m_room", "head__rebuild"
room
};
const size_t count
{
head__rebuild(room)
head.rebuild(head)
};
out << "done " << count << std::endl;
@ -6818,13 +6818,7 @@ console_cmd__room__head__add(opt &out, const string_view &line)
param.at(0)
};
using prototype = void (const m::event::id &, const db::op &, const bool &);
static mods::import<prototype> head__modify
{
"m_room", "head__modify"
};
head__modify(event_id, db::op::SET, true);
m::room::head::modify(event_id, db::op::SET, true);
out << "Added " << event_id << " to head " << std::endl;
return true;
}
@ -6842,13 +6836,7 @@ console_cmd__room__head__del(opt &out, const string_view &line)
param.at(0)
};
using prototype = void (const m::event::id &, const db::op &, const bool &);
static mods::import<prototype> head__modify
{
"m_room", "head__modify"
};
head__modify(event_id, db::op::DELETE, true);
m::room::head::modify(event_id, db::op::DELETE, true);
out << "Deleted " << event_id << " from head (if existed)" << std::endl;
return true;
}
@ -6900,15 +6888,14 @@ console_cmd__room__head__reset(opt &out, const string_view &line)
room_id
};
using prototype = size_t (const m::room &);
static mods::import<prototype> head__reset
const m::room::head head
{
"m_room", "head__reset"
room
};
const size_t count
{
head__reset(room)
head.reset(head)
};
out << "done " << count << std::endl;

View file

@ -287,12 +287,151 @@ ircd::m::room::auth::make_refs(const auth &auth,
fetch("m.room.member", user_id);
}
extern "C" int64_t
make_prev(const m::room &room,
json::stack::array &out,
size_t limit,
bool need_tophead = true)
size_t
IRCD_MODULE_EXPORT
ircd::m::room::head::rebuild(const head &head)
{
size_t ret{0};
const auto &room{head.room};
const m::room::state state{room};
const auto create_idx
{
state.get("m.room.create")
};
static const m::event::fetch::opts fopts
{
{ db::get::NO_CACHE }
};
m::room::messages it
{
room, create_idx, &fopts
};
if(!it)
return ret;
db::txn txn
{
*m::dbs::events
};
m::dbs::write_opts opts;
opts.op = db::op::SET;
opts.room_head = true;
opts.room_refs = true;
for(; it; ++it)
{
const m::event &event{*it};
opts.event_idx = it.event_idx();
m::dbs::_index__room_head(txn, event, opts);
++ret;
}
txn();
return ret;
}
size_t
IRCD_MODULE_EXPORT
ircd::m::room::head::reset(const head &head)
{
size_t ret{0};
const auto &room{head.room};
m::room::messages it{room};
if(!it)
return ret;
// Replacement will be the single new head
const m::event replacement
{
*it
};
db::txn txn
{
*m::dbs::events
};
// Iterate all of the existing heads with a delete operation
m::dbs::write_opts opts;
opts.op = db::op::DELETE;
opts.room_head = true;
m::room::head{room}.for_each([&room, &opts, &txn, &ret]
(const m::event::idx &event_idx, const m::event::id &event_id)
{
const m::event::fetch event
{
event_idx, std::nothrow
};
if(!event.valid)
{
log::derror
{
m::log, "Invalid event '%s' idx %lu in head for %s",
string_view{event_id},
event_idx,
string_view{room.room_id}
};
return;
}
opts.event_idx = event_idx;
m::dbs::_index__room_head(txn, event, opts);
++ret;
});
// Finally add the replacement to the txn
opts.op = db::op::SET;
opts.event_idx = it.event_idx();
m::dbs::_index__room_head(txn, replacement, opts);
// Commit txn
txn();
return ret;
}
void
IRCD_MODULE_EXPORT
ircd::m::room::head::modify(const m::event::id &event_id,
const db::op &op,
const bool &refs)
{
const m::event::fetch event
{
event_id
};
db::txn txn
{
*m::dbs::events
};
// Iterate all of the existing heads with a delete operation
m::dbs::write_opts opts;
opts.op = op;
opts.room_head = true;
opts.room_refs = refs;
opts.event_idx = event.event_idx;
m::dbs::_index__room_head(txn, event, opts);
// Commit txn
txn();
}
int64_t
IRCD_MODULE_EXPORT
ircd::m::room::head::make_refs(const head &head,
json::stack::array &out,
const size_t &_limit,
const bool &_need_tophead)
{
size_t limit{_limit};
bool need_tophead{_need_tophead};
const auto &room{head.room};
const auto top_head
{
need_tophead?
@ -302,7 +441,6 @@ make_prev(const m::room &room,
int64_t depth{-1};
m::event::fetch event;
const m::room::head head{room};
head.for_each(m::room::head::closure_bool{[&]
(const m::event::idx &idx, const m::event::id &event_id)
{
@ -345,23 +483,33 @@ make_prev(const m::room &room,
return depth;
}
extern "C" std::pair<json::array, int64_t>
make_prev__buf(const m::room &room,
const mutable_buffer &buf,
const size_t &limit,
const bool &need_tophead)
bool
IRCD_MODULE_EXPORT
ircd::m::room::head::for_each(const head &head,
const closure_bool &closure)
{
int64_t depth;
json::stack ps{buf};
auto it
{
json::stack::array top{ps};
depth = make_prev(room, top, limit, need_tophead);
dbs::room_head.begin(head.room.room_id)
};
for(; it; ++it)
{
const event::id &event_id
{
dbs::room_head_key(it->first)
};
const event::idx &event_idx
{
byte_view<event::idx>{it->second}
};
if(!closure(event_idx, event_id))
return false;
}
return
{
json::array{ps.completed()}, depth
};
return true;
}
std::pair<bool, int64_t>
@ -678,140 +826,6 @@ ircd::m::room::state::prefetch(const state &state,
return ret;
}
extern "C" size_t
head__rebuild(const m::room &room)
{
size_t ret{0};
const m::room::state state{room};
const auto create_idx
{
state.get("m.room.create")
};
static const m::event::fetch::opts fopts
{
{ db::get::NO_CACHE }
};
m::room::messages it
{
room, create_idx, &fopts
};
if(!it)
return ret;
db::txn txn
{
*m::dbs::events
};
m::dbs::write_opts opts;
opts.op = db::op::SET;
opts.room_head = true;
opts.room_refs = true;
for(; it; ++it)
{
const m::event &event{*it};
opts.event_idx = it.event_idx();
m::dbs::_index__room_head(txn, event, opts);
++ret;
}
txn();
return ret;
}
extern "C" size_t
head__reset(const m::room &room)
{
size_t ret{0};
m::room::messages it
{
room
};
if(!it)
return ret;
// Replacement will be the single new head
const m::event replacement
{
*it
};
db::txn txn
{
*m::dbs::events
};
// Iterate all of the existing heads with a delete operation
m::dbs::write_opts opts;
opts.op = db::op::DELETE;
opts.room_head = true;
m::room::head{room}.for_each([&room, &opts, &txn, &ret]
(const m::event::idx &event_idx, const m::event::id &event_id)
{
const m::event::fetch event
{
event_idx, std::nothrow
};
if(!event.valid)
{
log::derror
{
m::log, "Invalid event '%s' idx %lu in head for %s",
string_view{event_id},
event_idx,
string_view{room.room_id}
};
return;
}
opts.event_idx = event_idx;
m::dbs::_index__room_head(txn, event, opts);
++ret;
});
// Finally add the replacement to the txn
opts.op = db::op::SET;
opts.event_idx = it.event_idx();
m::dbs::_index__room_head(txn, replacement, opts);
// Commit txn
txn();
return ret;
}
extern "C" void
head__modify(const m::event::id &event_id,
const db::op &op,
const bool &refs)
{
const m::event::fetch event
{
event_id
};
db::txn txn
{
*m::dbs::events
};
// Iterate all of the existing heads with a delete operation
m::dbs::write_opts opts;
opts.op = op;
opts.room_head = true;
opts.room_refs = refs;
opts.event_idx = index(event);
m::dbs::_index__room_head(txn, event, opts);
// Commit txn
txn();
}
extern "C" size_t
dagree_histogram(const m::room &room,
std::vector<size_t> &vec)
@ -902,7 +916,7 @@ room_herd(const m::room &room,
for(const m::event::id &event_id : event_ids)
if(exists(event_id))
{
head__modify(event_id, db::op::SET, false);
m::room::head::modify(event_id, db::op::SET, false);
++i;
}

View file

@ -180,20 +180,17 @@ ircd::m::vm::eval__commit_room(eval &eval,
event, { "room_id", room.room_id }
};
using prev_prototype = std::pair<json::array, int64_t> (const m::room &,
const mutable_buffer &,
const size_t &,
const bool &);
static mods::import<prev_prototype> make_prev__buf
const m::room::head head
{
"m_room", "make_prev__buf"
room
};
const bool need_tophead{event.at("type") != "m.room.create"};
const unique_buffer<mutable_buffer> prev_buf{8192};
static const size_t prev_limit{16};
const auto prev
{
make_prev__buf(room, prev_buf, 16, need_tophead)
head.make_refs(prev_buf, prev_limit, need_tophead)
};
const auto &prev_events{prev.first};