mirror of
https://github.com/matrix-construct/construct
synced 2024-09-27 11:18:51 +02:00
ircd:Ⓜ️:room::head: Simplify interface; move to module.
This commit is contained in:
parent
59618c6a44
commit
8454ae0275
9 changed files with 324 additions and 332 deletions
|
@ -40,29 +40,23 @@ namespace ircd::m
|
|||
///
|
||||
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 &)>;
|
||||
using closure = 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;
|
||||
void for_each(const closure &) const;
|
||||
bool for_each(const closure &) const;
|
||||
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;
|
||||
int64_t generate(json::stack::array &, const size_t &, const bool &) const;
|
||||
std::pair<json::array, int64_t> generate(const mutable_buffer &, const size_t &, const bool &) const;
|
||||
|
||||
head() = default;
|
||||
head(const m::room &room)
|
||||
:room{room}
|
||||
{}
|
||||
|
||||
head() = default;
|
||||
static void modify(const event::id &, const db::op &, const bool &);
|
||||
static size_t rebuild(const head &);
|
||||
static size_t reset(const head &);
|
||||
};
|
||||
|
|
|
@ -212,6 +212,7 @@ ircd::m::module_names
|
|||
"m_user_profile",
|
||||
"m_room",
|
||||
"m_room_auth",
|
||||
"m_room_head",
|
||||
"m_room_timeline",
|
||||
"m_room_aliases",
|
||||
"m_room_canonical_alias",
|
||||
|
|
314
ircd/m_room.cc
314
ircd/m_room.cc
|
@ -3389,320 +3389,6 @@ ircd::m::room::origins::_for_each(const origins &origins,
|
|||
return true;
|
||||
}
|
||||
|
||||
//
|
||||
// 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
|
||||
{
|
||||
size_t ret(0);
|
||||
for_each([&ret]
|
||||
(const event::idx &event_idx, const event::id &event_id)
|
||||
{
|
||||
++ret;
|
||||
});
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
bool
|
||||
ircd::m::room::head::has(const event::id &event_id)
|
||||
const
|
||||
{
|
||||
bool ret{false};
|
||||
for_each(closure_bool{[&ret, &event_id]
|
||||
(const event::idx &event_idx, const event::id &event_id_)
|
||||
{
|
||||
ret = event_id_ == event_id;
|
||||
return !ret; // for_each protocol: false to break
|
||||
}});
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
void
|
||||
ircd::m::room::head::for_each(const closure &closure)
|
||||
const
|
||||
{
|
||||
for_each(closure_bool{[&closure]
|
||||
(const event::idx &event_idx, const event::id &event_id)
|
||||
{
|
||||
closure(event_idx, event_id);
|
||||
return true;
|
||||
}});
|
||||
}
|
||||
|
||||
bool
|
||||
ircd::m::room::head::for_each(const closure_bool &closure)
|
||||
const
|
||||
{
|
||||
return for_each(*this, closure);
|
||||
}
|
||||
|
||||
size_t
|
||||
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;
|
||||
for(; it; ++it)
|
||||
{
|
||||
const m::event &event{*it};
|
||||
opts.event_idx = it.event_idx();
|
||||
opts.appendix.reset();
|
||||
opts.appendix.set(dbs::appendix::ROOM_HEAD);
|
||||
m::dbs::write(txn, event, opts);
|
||||
++ret;
|
||||
}
|
||||
|
||||
txn();
|
||||
return ret;
|
||||
}
|
||||
|
||||
size_t
|
||||
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.appendix.reset();
|
||||
opts.appendix.set(dbs::appendix::ROOM_HEAD);
|
||||
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::write(txn, event, opts);
|
||||
++ret;
|
||||
});
|
||||
|
||||
// Finally add the replacement to the txn
|
||||
opts.op = db::op::SET;
|
||||
opts.event_idx = it.event_idx();
|
||||
m::dbs::write(txn, replacement, opts);
|
||||
|
||||
// Commit txn
|
||||
txn();
|
||||
return ret;
|
||||
}
|
||||
|
||||
void
|
||||
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.event_idx = event.event_idx;
|
||||
opts.appendix.reset();
|
||||
opts.appendix.set(dbs::appendix::ROOM_HEAD);
|
||||
m::dbs::write(txn, event, opts);
|
||||
|
||||
// Commit txn
|
||||
txn();
|
||||
}
|
||||
|
||||
int64_t
|
||||
ircd::m::room::head::make_refs(const head &head,
|
||||
json::stack::array &out,
|
||||
const size_t &_limit,
|
||||
const bool &_need_tophead)
|
||||
{
|
||||
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);
|
||||
}};
|
||||
|
||||
char versionbuf[32];
|
||||
const auto version
|
||||
{
|
||||
m::version(versionbuf, head.room, std::nothrow)
|
||||
};
|
||||
|
||||
const auto &append
|
||||
{
|
||||
version == "1" || version == "2"? v1_ref : v3_ref
|
||||
};
|
||||
|
||||
bool need_tophead{_need_tophead};
|
||||
const auto top_head
|
||||
{
|
||||
need_tophead?
|
||||
m::top(std::nothrow, head.room.room_id):
|
||||
std::tuple<m::id::event::buf, int64_t, m::event::idx>{}
|
||||
};
|
||||
|
||||
size_t limit{_limit};
|
||||
int64_t depth{-1};
|
||||
m::event::fetch event;
|
||||
head.for_each(m::room::head::closure_bool{[&]
|
||||
(const m::event::idx &idx, const m::event::id &event_id)
|
||||
{
|
||||
if(!seek(event, idx, event_id, std::nothrow))
|
||||
return true;
|
||||
|
||||
if(need_tophead)
|
||||
if(event.event_id == std::get<0>(top_head))
|
||||
need_tophead = false;
|
||||
|
||||
append(event_id);
|
||||
depth = std::max(json::get<"depth"_>(event), depth);
|
||||
return --limit - need_tophead > 0;
|
||||
}});
|
||||
|
||||
if(need_tophead)
|
||||
{
|
||||
append(std::get<0>(top_head));
|
||||
depth = std::get<1>(top_head);
|
||||
}
|
||||
|
||||
return depth;
|
||||
}
|
||||
|
||||
bool
|
||||
ircd::m::room::head::for_each(const head &head,
|
||||
const closure_bool &closure)
|
||||
{
|
||||
auto it
|
||||
{
|
||||
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 true;
|
||||
}
|
||||
|
||||
//
|
||||
// room::aliases
|
||||
//
|
||||
|
|
|
@ -130,6 +130,7 @@ m_rooms_la_SOURCES = m_rooms.cc
|
|||
m_rooms_summary_la_SOURCES = m_rooms_summary.cc
|
||||
m_room_la_SOURCES = m_room.cc
|
||||
m_room_auth_la_SOURCES = m_room_auth.cc
|
||||
m_room_head_la_SOURCES = m_room_head.cc
|
||||
m_room_timeline_la_SOURCES = m_room_timeline.cc
|
||||
m_room_create_la_SOURCES = m_room_create.cc
|
||||
m_room_member_la_SOURCES = m_room_member.cc
|
||||
|
@ -181,6 +182,7 @@ m_module_LTLIBRARIES = \
|
|||
m_rooms_summary.la \
|
||||
m_room.la \
|
||||
m_room_auth.la \
|
||||
m_room_head.la \
|
||||
m_room_timeline.la \
|
||||
m_room_create.la \
|
||||
m_room_member.la \
|
||||
|
|
|
@ -5881,7 +5881,7 @@ console_cmd__stage__make_prev(opt &out, const string_view &line)
|
|||
thread_local char buf[8192];
|
||||
const auto prev
|
||||
{
|
||||
head.make_refs(buf, limit, true)
|
||||
head.generate(buf, limit, true)
|
||||
};
|
||||
|
||||
json::get<"prev_events"_>(event) = prev.first;
|
||||
|
@ -7819,6 +7819,7 @@ console_cmd__room__head(opt &out, const string_view &line)
|
|||
};
|
||||
|
||||
out << pretty_oneline(event) << std::endl;
|
||||
return true;
|
||||
});
|
||||
|
||||
return true;
|
||||
|
|
|
@ -181,7 +181,7 @@ get__make_join(client &client,
|
|||
event, "prev_events"
|
||||
};
|
||||
|
||||
head.make_refs(prev_events, 32, true);
|
||||
head.generate(prev_events, 32, true);
|
||||
}
|
||||
|
||||
json::stack::member
|
||||
|
|
|
@ -152,7 +152,7 @@ get__make_leave(client &client,
|
|||
event, "prev_events"
|
||||
};
|
||||
|
||||
head.make_refs(prev_events, 32, true);
|
||||
head.generate(prev_events, 32, true);
|
||||
}
|
||||
|
||||
json::stack::member
|
||||
|
|
308
modules/m_room_head.cc
Normal file
308
modules/m_room_head.cc
Normal file
|
@ -0,0 +1,308 @@
|
|||
// Matrix Construct
|
||||
//
|
||||
// Copyright (C) Matrix Construct Developers, Authors & Contributors
|
||||
// Copyright (C) 2016-2018 Jason Volk <jason@zemos.net>
|
||||
//
|
||||
// Permission to use, copy, modify, and/or distribute this software for any
|
||||
// purpose with or without fee is hereby granted, provided that the above
|
||||
// copyright notice and this permission notice is present in all copies. The
|
||||
// full license for this software is available in the LICENSE file.
|
||||
|
||||
ircd::mapi::header
|
||||
IRCD_MODULE
|
||||
{
|
||||
"Matrix room head"
|
||||
};
|
||||
|
||||
//
|
||||
// room::head
|
||||
//
|
||||
|
||||
std::pair<ircd::json::array, int64_t>
|
||||
IRCD_MODULE_EXPORT
|
||||
ircd::m::room::head::generate(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
|
||||
{
|
||||
generate(array, limit, need_top)
|
||||
};
|
||||
array.~array();
|
||||
return
|
||||
{
|
||||
json::array{out.completed()},
|
||||
depth
|
||||
};
|
||||
}
|
||||
|
||||
int64_t
|
||||
IRCD_MODULE_EXPORT
|
||||
ircd::m::room::head::generate(json::stack::array &out,
|
||||
const size_t &_limit,
|
||||
const bool &_need_tophead)
|
||||
const
|
||||
{
|
||||
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);
|
||||
}};
|
||||
|
||||
char versionbuf[32];
|
||||
const auto version
|
||||
{
|
||||
m::version(versionbuf, room, std::nothrow)
|
||||
};
|
||||
|
||||
const auto &append
|
||||
{
|
||||
version == "1" || version == "2"? v1_ref : v3_ref
|
||||
};
|
||||
|
||||
bool need_tophead{_need_tophead};
|
||||
const auto top_head
|
||||
{
|
||||
need_tophead?
|
||||
m::top(std::nothrow, room.room_id):
|
||||
std::tuple<m::id::event::buf, int64_t, m::event::idx>{}
|
||||
};
|
||||
|
||||
int64_t depth{-1};
|
||||
size_t limit{_limit};
|
||||
m::event::fetch event;
|
||||
for_each([&event, &need_tophead, &top_head, &depth, &append, &limit]
|
||||
(const m::event::idx &idx, const m::event::id &event_id)
|
||||
{
|
||||
if(!seek(event, idx, event_id, std::nothrow))
|
||||
return true;
|
||||
|
||||
if(need_tophead)
|
||||
if(event.event_id == std::get<0>(top_head))
|
||||
need_tophead = false;
|
||||
|
||||
append(event_id);
|
||||
depth = std::max(json::get<"depth"_>(event), depth);
|
||||
return --limit - need_tophead > 0;
|
||||
});
|
||||
|
||||
if(need_tophead)
|
||||
{
|
||||
append(std::get<0>(top_head));
|
||||
depth = std::get<1>(top_head);
|
||||
}
|
||||
|
||||
return depth;
|
||||
}
|
||||
|
||||
size_t
|
||||
IRCD_MODULE_EXPORT
|
||||
ircd::m::room::head::count()
|
||||
const
|
||||
{
|
||||
size_t ret(0);
|
||||
for_each([&ret]
|
||||
(const event::idx &event_idx, const event::id &event_id)
|
||||
{
|
||||
++ret;
|
||||
return true;
|
||||
});
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
bool
|
||||
IRCD_MODULE_EXPORT
|
||||
ircd::m::room::head::has(const event::id &event_id)
|
||||
const
|
||||
{
|
||||
bool ret{false};
|
||||
for_each([&ret, &event_id]
|
||||
(const event::idx &event_idx, const event::id &event_id_)
|
||||
{
|
||||
ret = event_id_ == event_id;
|
||||
return !ret; // for_each protocol: false to break
|
||||
});
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
bool
|
||||
IRCD_MODULE_EXPORT
|
||||
ircd::m::room::head::for_each(const closure &closure)
|
||||
const
|
||||
{
|
||||
auto it
|
||||
{
|
||||
dbs::room_head.begin(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 true;
|
||||
}
|
||||
|
||||
//
|
||||
// special tools
|
||||
//
|
||||
|
||||
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.appendix.reset();
|
||||
opts.appendix.set(dbs::appendix::ROOM_HEAD);
|
||||
head.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 true;
|
||||
}
|
||||
|
||||
opts.event_idx = event_idx;
|
||||
m::dbs::write(txn, event, opts);
|
||||
++ret;
|
||||
return true;
|
||||
});
|
||||
|
||||
// Finally add the replacement to the txn
|
||||
opts.op = db::op::SET;
|
||||
opts.event_idx = it.event_idx();
|
||||
m::dbs::write(txn, replacement, opts);
|
||||
|
||||
// Commit txn
|
||||
txn();
|
||||
return ret;
|
||||
}
|
||||
|
||||
size_t
|
||||
IRCD_MODULE_EXPORT
|
||||
ircd::m::room::head::rebuild(const head &head)
|
||||
{
|
||||
size_t ret{0};
|
||||
static const m::event::fetch::opts fopts
|
||||
{
|
||||
{ db::get::NO_CACHE }
|
||||
};
|
||||
|
||||
m::room::messages it
|
||||
{
|
||||
head.room, 0UL, &fopts
|
||||
};
|
||||
|
||||
if(!it)
|
||||
return ret;
|
||||
|
||||
db::txn txn
|
||||
{
|
||||
*m::dbs::events
|
||||
};
|
||||
|
||||
m::dbs::write_opts opts;
|
||||
opts.op = db::op::SET;
|
||||
for(; it; ++it)
|
||||
{
|
||||
const m::event &event{*it};
|
||||
opts.event_idx = it.event_idx();
|
||||
opts.appendix.reset();
|
||||
opts.appendix.set(dbs::appendix::ROOM_HEAD);
|
||||
m::dbs::write(txn, event, opts);
|
||||
++ret;
|
||||
}
|
||||
|
||||
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.event_idx = event.event_idx;
|
||||
opts.appendix.reset();
|
||||
opts.appendix.set(dbs::appendix::ROOM_HEAD);
|
||||
m::dbs::write(txn, event, opts);
|
||||
|
||||
// Commit txn
|
||||
txn();
|
||||
}
|
|
@ -372,7 +372,7 @@ ircd::m::vm::inject(eval &eval,
|
|||
const auto &[prev_events, depth]
|
||||
{
|
||||
add_prev_events?
|
||||
head.make_refs(prev_buf, size_t(prev_limit), true):
|
||||
head.generate(prev_buf, size_t(prev_limit), true):
|
||||
std::pair<json::array, int64_t>{{}, -1}
|
||||
};
|
||||
|
||||
|
|
Loading…
Reference in a new issue