mirror of
https://github.com/matrix-construct/construct
synced 2024-11-26 00:32:35 +01:00
ircd:Ⓜ️:room::events: Split nested interfaces into headers/units.
This commit is contained in:
parent
edab741e9f
commit
47f670b7a2
10 changed files with 546 additions and 485 deletions
|
@ -11,33 +11,6 @@
|
|||
#pragma once
|
||||
#define HAVE_IRCD_M_ROOM_EVENTS_H
|
||||
|
||||
// The "viewport" is comprised of events starting from the tophead (most recent
|
||||
// in room timeline) and covering about ~20 events leading up to that. Note
|
||||
// that this is a completely ad hoc and configurable server value. Events in
|
||||
// the viewport must be eval'ed and synced to clients in the order they will
|
||||
// be displayed. Events not in the viewport are not /synced to clients and any
|
||||
// client request provides event ordering: thus older events (backfills, etc)
|
||||
// can be eval'ed without this constraint.
|
||||
//
|
||||
// The "sounding" is the depth of the first gap. In any attempt to trace
|
||||
// the room timeline from the tophead to the m.room.create event: the sounding
|
||||
// is the [highest number] depth preventing that.
|
||||
//
|
||||
// The "twain" marks the depth at the end of the first gap; the server is in
|
||||
// possession of one or more events again at the twain.
|
||||
//
|
||||
// The "hazard" is the depth of the first gap starting from the m.room.create
|
||||
// event toward the tophead. In any attempt to trace the room timeline with
|
||||
// an increasing depth, the hazard is the next gap to frontfill.
|
||||
|
||||
namespace ircd::m
|
||||
{
|
||||
std::pair<int64_t, event::idx> viewport(const room &);
|
||||
std::pair<int64_t, event::idx> sounding(const room &); // Last missing (one)
|
||||
std::pair<int64_t, event::idx> twain(const room &);
|
||||
std::pair<int64_t, event::idx> hazard(const room &); // First missing (one)
|
||||
}
|
||||
|
||||
/// Interface to room events
|
||||
///
|
||||
/// This interface has the form of an STL-style iterator over room events
|
||||
|
@ -49,8 +22,8 @@ namespace ircd::m
|
|||
struct ircd::m::room::events
|
||||
{
|
||||
struct sounding;
|
||||
struct horizon;
|
||||
struct missing;
|
||||
struct horizon;
|
||||
|
||||
static conf::item<ssize_t> viewport_size;
|
||||
|
||||
|
@ -121,77 +94,3 @@ struct ircd::m::room::events
|
|||
static size_t count(const m::room &, const event::idx_range &);
|
||||
static size_t count(const event::idx_range &);
|
||||
};
|
||||
|
||||
/// Find missing room events. This is a breadth-first iteration of missing
|
||||
/// references from the tophead (or at the event provided in the room arg)
|
||||
///
|
||||
/// The closure is invoked with the first argument being the event_id unknown
|
||||
/// to the server, followed by the depth and event::idx of the event making the
|
||||
/// reference.
|
||||
///
|
||||
struct ircd::m::room::events::missing
|
||||
{
|
||||
using closure = std::function<bool (const event::id &, const uint64_t &, const event::idx &)>;
|
||||
|
||||
m::room room;
|
||||
|
||||
private:
|
||||
bool _each(m::room::events &, const closure &) const;
|
||||
|
||||
public:
|
||||
bool rfor_each(const pair<int64_t> &depth, const closure &) const;
|
||||
bool for_each(const pair<int64_t> &depth, const closure &) const;
|
||||
bool for_each(const closure &) const;
|
||||
size_t count() const;
|
||||
|
||||
missing() = default;
|
||||
missing(const m::room &room)
|
||||
:room{room}
|
||||
{}
|
||||
};
|
||||
|
||||
/// Find gaps in the room's events. A gap is where this server has no events
|
||||
/// at a certain depth. This is a path-finding diagnostic interface, useful to
|
||||
/// understand what areas of the timeline have not been acquired by the server
|
||||
/// to calculate backfill requests, etc. This interface is depth-first oriented,
|
||||
/// rather than the breadth-first room::events::missing interface.
|
||||
///
|
||||
struct ircd::m::room::events::sounding
|
||||
{
|
||||
using range = std::pair<int64_t, int64_t>;
|
||||
using closure = std::function<bool (const range &, const event::idx &)>;
|
||||
|
||||
m::room room;
|
||||
|
||||
public:
|
||||
bool for_each(const closure &) const;
|
||||
bool rfor_each(const closure &) const;
|
||||
|
||||
sounding() = default;
|
||||
sounding(const m::room &room)
|
||||
:room{room}
|
||||
{}
|
||||
};
|
||||
|
||||
/// Find missing room events. This is an interface to the event-horizon for
|
||||
/// this room. The event horizon is keyed by event_id and the value is the
|
||||
/// event::idx of the event referencing it. There can be multiple entries for
|
||||
/// an event_id. The closure is also invoked with the depth of the referencer.
|
||||
///
|
||||
struct ircd::m::room::events::horizon
|
||||
{
|
||||
using closure = std::function<bool (const event::id &, const uint64_t &, const event::idx &)>;
|
||||
|
||||
m::room room;
|
||||
|
||||
public:
|
||||
bool for_each(const closure &) const;
|
||||
size_t count() const;
|
||||
|
||||
size_t rebuild();
|
||||
|
||||
horizon() = default;
|
||||
horizon(const m::room &room)
|
||||
:room{room}
|
||||
{}
|
||||
};
|
||||
|
|
35
include/ircd/m/room/events_horizon.h
Normal file
35
include/ircd/m/room/events_horizon.h
Normal file
|
@ -0,0 +1,35 @@
|
|||
// Matrix Construct
|
||||
//
|
||||
// Copyright (C) Matrix Construct Developers, Authors & Contributors
|
||||
// Copyright (C) 2016-2023 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.
|
||||
|
||||
#pragma once
|
||||
#define HAVE_IRCD_M_ROOM_EVENTS_HORIZON_H
|
||||
|
||||
/// Find missing room events. This is an interface to the event-horizon for
|
||||
/// this room. The event horizon is keyed by event_id and the value is the
|
||||
/// event::idx of the event referencing it. There can be multiple entries for
|
||||
/// an event_id. The closure is also invoked with the depth of the referencer.
|
||||
///
|
||||
struct ircd::m::room::events::horizon
|
||||
{
|
||||
using closure = std::function<bool (const event::id &, const uint64_t &, const event::idx &)>;
|
||||
|
||||
m::room room;
|
||||
|
||||
public:
|
||||
bool for_each(const closure &) const;
|
||||
size_t count() const;
|
||||
|
||||
size_t rebuild();
|
||||
|
||||
horizon() = default;
|
||||
horizon(const m::room &room)
|
||||
:room{room}
|
||||
{}
|
||||
};
|
40
include/ircd/m/room/events_missing.h
Normal file
40
include/ircd/m/room/events_missing.h
Normal file
|
@ -0,0 +1,40 @@
|
|||
// Matrix Construct
|
||||
//
|
||||
// Copyright (C) Matrix Construct Developers, Authors & Contributors
|
||||
// Copyright (C) 2016-2023 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.
|
||||
|
||||
#pragma once
|
||||
#define HAVE_IRCD_M_ROOM_EVENTS_MISSING_H
|
||||
|
||||
/// Find missing room events. This is a breadth-first iteration of missing
|
||||
/// references from the tophead (or at the event provided in the room arg)
|
||||
///
|
||||
/// The closure is invoked with the first argument being the event_id unknown
|
||||
/// to the server, followed by the depth and event::idx of the event making the
|
||||
/// reference.
|
||||
///
|
||||
struct ircd::m::room::events::missing
|
||||
{
|
||||
using closure = std::function<bool (const event::id &, const uint64_t &, const event::idx &)>;
|
||||
|
||||
m::room room;
|
||||
|
||||
private:
|
||||
bool _each(m::room::events &, const closure &) const;
|
||||
|
||||
public:
|
||||
bool rfor_each(const pair<int64_t> &depth, const closure &) const;
|
||||
bool for_each(const pair<int64_t> &depth, const closure &) const;
|
||||
bool for_each(const closure &) const;
|
||||
size_t count() const;
|
||||
|
||||
missing() = default;
|
||||
missing(const m::room &room)
|
||||
:room{room}
|
||||
{}
|
||||
};
|
62
include/ircd/m/room/events_sounding.h
Normal file
62
include/ircd/m/room/events_sounding.h
Normal file
|
@ -0,0 +1,62 @@
|
|||
// Matrix Construct
|
||||
//
|
||||
// Copyright (C) Matrix Construct Developers, Authors & Contributors
|
||||
// Copyright (C) 2016-2023 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.
|
||||
|
||||
#pragma once
|
||||
#define HAVE_IRCD_M_ROOM_EVENTS_SOUNDING_H
|
||||
|
||||
// The "viewport" is comprised of events starting from the tophead (most recent
|
||||
// in room timeline) and covering about ~20 events leading up to that. Note
|
||||
// that this is a completely ad hoc and configurable server value. Events in
|
||||
// the viewport must be eval'ed and synced to clients in the order they will
|
||||
// be displayed. Events not in the viewport are not /synced to clients and any
|
||||
// client request provides event ordering: thus older events (backfills, etc)
|
||||
// can be eval'ed without this constraint.
|
||||
//
|
||||
// The "sounding" is the depth of the first gap. In any attempt to trace
|
||||
// the room timeline from the tophead to the m.room.create event: the sounding
|
||||
// is the [highest number] depth preventing that.
|
||||
//
|
||||
// The "twain" marks the depth at the end of the first gap; the server is in
|
||||
// possession of one or more events again at the twain.
|
||||
//
|
||||
// The "hazard" is the depth of the first gap starting from the m.room.create
|
||||
// event toward the tophead. In any attempt to trace the room timeline with
|
||||
// an increasing depth, the hazard is the next gap to frontfill.
|
||||
|
||||
namespace ircd::m
|
||||
{
|
||||
std::pair<int64_t, event::idx> viewport(const room &);
|
||||
std::pair<int64_t, event::idx> sounding(const room &); // Last missing (one)
|
||||
std::pair<int64_t, event::idx> twain(const room &);
|
||||
std::pair<int64_t, event::idx> hazard(const room &); // First missing (one)
|
||||
}
|
||||
|
||||
/// Find gaps in the room's events. A gap is where this server has no events
|
||||
/// at a certain depth. This is a path-finding diagnostic interface, useful to
|
||||
/// understand what areas of the timeline have not been acquired by the server
|
||||
/// to calculate backfill requests, etc. This interface is depth-first oriented,
|
||||
/// rather than the breadth-first room::missing interface.
|
||||
///
|
||||
struct ircd::m::room::events::sounding
|
||||
{
|
||||
using range = std::pair<int64_t, int64_t>;
|
||||
using closure = std::function<bool (const range &, const event::idx &)>;
|
||||
|
||||
m::room room;
|
||||
|
||||
public:
|
||||
bool for_each(const closure &) const;
|
||||
bool rfor_each(const closure &) const;
|
||||
|
||||
sounding() = default;
|
||||
sounding(const m::room &room)
|
||||
:room{room}
|
||||
{}
|
||||
};
|
|
@ -189,6 +189,9 @@ struct ircd::m::room
|
|||
};
|
||||
|
||||
#include "events.h"
|
||||
#include "events_sounding.h"
|
||||
#include "events_missing.h"
|
||||
#include "events_horizon.h"
|
||||
#include "state.h"
|
||||
#include "state_space.h"
|
||||
#include "state_history.h"
|
||||
|
|
|
@ -109,6 +109,9 @@ libircd_matrix_la_SOURCES += room_aliases.cc
|
|||
libircd_matrix_la_SOURCES += room_bootstrap.cc
|
||||
libircd_matrix_la_SOURCES += room_create.cc
|
||||
libircd_matrix_la_SOURCES += room_events.cc
|
||||
libircd_matrix_la_SOURCES += room_events_sounding.cc
|
||||
libircd_matrix_la_SOURCES += room_events_missing.cc
|
||||
libircd_matrix_la_SOURCES += room_events_horizon.cc
|
||||
libircd_matrix_la_SOURCES += room_head.cc
|
||||
libircd_matrix_la_SOURCES += room_head_fetch.cc
|
||||
libircd_matrix_la_SOURCES += room_state_fetch.cc
|
||||
|
|
|
@ -15,103 +15,6 @@ ircd::m::room::events::viewport_size
|
|||
{ "default", 96L },
|
||||
};
|
||||
|
||||
std::pair<int64_t, ircd::m::event::idx>
|
||||
ircd::m::viewport(const room &room)
|
||||
{
|
||||
std::pair<int64_t, m::event::idx> ret
|
||||
{
|
||||
-1, 0
|
||||
};
|
||||
|
||||
m::room::events it
|
||||
{
|
||||
room
|
||||
};
|
||||
|
||||
const ssize_t &max
|
||||
{
|
||||
room::events::viewport_size
|
||||
};
|
||||
|
||||
for(auto i(0); it && i < max; --it, ++i)
|
||||
{
|
||||
ret.first = it.depth();
|
||||
ret.second = it.event_idx();
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
std::pair<int64_t, ircd::m::event::idx>
|
||||
ircd::m::twain(const room &room)
|
||||
{
|
||||
std::pair<int64_t, m::event::idx> ret
|
||||
{
|
||||
-1, 0
|
||||
};
|
||||
|
||||
const room::events::sounding s
|
||||
{
|
||||
room
|
||||
};
|
||||
|
||||
s.rfor_each([&ret]
|
||||
(const auto &range, const auto &event_idx) noexcept
|
||||
{
|
||||
ret.first = range.first - 1;
|
||||
return false;
|
||||
});
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
std::pair<int64_t, ircd::m::event::idx>
|
||||
ircd::m::sounding(const room &room)
|
||||
{
|
||||
std::pair<int64_t, m::event::idx> ret
|
||||
{
|
||||
-1, 0
|
||||
};
|
||||
|
||||
const room::events::sounding s
|
||||
{
|
||||
room
|
||||
};
|
||||
|
||||
s.rfor_each([&ret]
|
||||
(const auto &range, const auto &event_idx) noexcept
|
||||
{
|
||||
ret.first = range.second;
|
||||
ret.second = event_idx;
|
||||
return false;
|
||||
});
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
std::pair<int64_t, ircd::m::event::idx>
|
||||
ircd::m::hazard(const room &room)
|
||||
{
|
||||
std::pair<int64_t, m::event::idx> ret
|
||||
{
|
||||
0, 0
|
||||
};
|
||||
|
||||
const room::events::sounding s
|
||||
{
|
||||
room
|
||||
};
|
||||
|
||||
s.for_each([&ret]
|
||||
(const auto &range, const auto &event_idx) noexcept
|
||||
{
|
||||
ret.first = range.first;
|
||||
return false;
|
||||
});
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
//
|
||||
// room::events
|
||||
//
|
||||
|
@ -436,289 +339,3 @@ const
|
|||
|
||||
return std::get<0>(part);
|
||||
}
|
||||
|
||||
//
|
||||
// room::events::missing
|
||||
//
|
||||
|
||||
size_t
|
||||
ircd::m::room::events::missing::count()
|
||||
const
|
||||
{
|
||||
size_t ret{0};
|
||||
for_each([&ret]
|
||||
(const auto &event_id, const auto &depth, const auto &event_idx) noexcept
|
||||
{
|
||||
++ret;
|
||||
return true;
|
||||
});
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
bool
|
||||
ircd::m::room::events::missing::for_each(const closure &closure)
|
||||
const
|
||||
{
|
||||
return for_each({0L, 0L}, closure);
|
||||
}
|
||||
|
||||
bool
|
||||
ircd::m::room::events::missing::for_each(const pair<int64_t> &depth,
|
||||
const closure &closure)
|
||||
const
|
||||
{
|
||||
room::events it
|
||||
{
|
||||
room, uint64_t(depth.first)
|
||||
};
|
||||
|
||||
for(; it; ++it)
|
||||
{
|
||||
if(depth.second && int64_t(it.depth()) > depth.second)
|
||||
break;
|
||||
|
||||
if(!_each(it, closure))
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
ircd::m::room::events::missing::rfor_each(const pair<int64_t> &depth,
|
||||
const closure &closure)
|
||||
const
|
||||
{
|
||||
room::events it
|
||||
{
|
||||
room, depth.second?: -1UL
|
||||
};
|
||||
|
||||
for(; it; --it)
|
||||
{
|
||||
if(depth.second && int64_t(it.depth()) > depth.second)
|
||||
continue;
|
||||
|
||||
if(int64_t(it.depth()) < depth.first)
|
||||
break;
|
||||
|
||||
if(!_each(it, closure))
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
ircd::m::room::events::missing::_each(m::room::events &it,
|
||||
const closure &closure)
|
||||
const
|
||||
{
|
||||
const m::event event
|
||||
{
|
||||
*it
|
||||
};
|
||||
|
||||
const event::prev prev
|
||||
{
|
||||
event
|
||||
};
|
||||
|
||||
event::idx idx_buf[event::prev::MAX];
|
||||
const auto idx
|
||||
{
|
||||
prev.idxs(idx_buf)
|
||||
};
|
||||
|
||||
for(size_t i(0); i < idx.size(); ++i)
|
||||
{
|
||||
if(idx[i])
|
||||
continue;
|
||||
|
||||
if(!closure(prev.prev_event(i), it.depth(), it.event_idx()))
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
//
|
||||
// room::events::sounding
|
||||
//
|
||||
|
||||
bool
|
||||
ircd::m::room::events::sounding::rfor_each(const closure &closure)
|
||||
const
|
||||
{
|
||||
const int64_t depth
|
||||
{
|
||||
room.event_id?
|
||||
m::get(std::nothrow, m::index(std::nothrow, room.event_id), "depth", -1L):
|
||||
-1L
|
||||
};
|
||||
|
||||
room::events it
|
||||
{
|
||||
room, uint64_t(depth)
|
||||
};
|
||||
|
||||
if(!it)
|
||||
return true;
|
||||
|
||||
event::idx idx{0};
|
||||
for(sounding::range range{0L, it.depth()}; it; --it)
|
||||
{
|
||||
range.first = it.depth();
|
||||
if(range.first == range.second)
|
||||
{
|
||||
idx = it.event_idx();
|
||||
continue;
|
||||
}
|
||||
|
||||
--range.second;
|
||||
if(range.first == range.second)
|
||||
{
|
||||
idx = it.event_idx();
|
||||
continue;
|
||||
}
|
||||
|
||||
if(!closure({range.first+1, range.second+1}, idx))
|
||||
return false;
|
||||
|
||||
range.second = range.first;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
ircd::m::room::events::sounding::for_each(const closure &closure)
|
||||
const
|
||||
{
|
||||
const int64_t depth
|
||||
{
|
||||
room.event_id?
|
||||
m::get(std::nothrow, m::index(std::nothrow, room.event_id), "depth", 0L):
|
||||
0L
|
||||
};
|
||||
|
||||
room::events it
|
||||
{
|
||||
room, uint64_t(depth)
|
||||
};
|
||||
|
||||
for(sounding::range range{depth, 0L}; it; ++it)
|
||||
{
|
||||
range.second = it.depth();
|
||||
if(range.first == range.second)
|
||||
continue;
|
||||
|
||||
++range.first;
|
||||
if(range.first == range.second)
|
||||
continue;
|
||||
|
||||
if(!closure(range, it.event_idx()))
|
||||
return false;
|
||||
|
||||
range.first = range.second;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
//
|
||||
// room::events::horizon
|
||||
//
|
||||
|
||||
//TODO: XXX remove fwd decl
|
||||
namespace ircd::m::dbs
|
||||
{
|
||||
void _index_event_horizon(db::txn &, const event &, const opts &, const m::event::id &);
|
||||
}
|
||||
|
||||
size_t
|
||||
ircd::m::room::events::horizon::rebuild()
|
||||
{
|
||||
m::dbs::opts opts;
|
||||
opts.appendix.reset();
|
||||
opts.appendix.set(dbs::appendix::EVENT_HORIZON);
|
||||
db::txn txn
|
||||
{
|
||||
*dbs::events
|
||||
};
|
||||
|
||||
size_t ret(0);
|
||||
m::room::events it
|
||||
{
|
||||
room
|
||||
};
|
||||
|
||||
for(; it; --it)
|
||||
{
|
||||
const m::event &event{*it};
|
||||
const event::prev prev_events{event};
|
||||
|
||||
opts.event_idx = it.event_idx();
|
||||
m::for_each(prev_events, [&]
|
||||
(const m::event::id &event_id)
|
||||
{
|
||||
if(m::exists(event_id))
|
||||
return true;
|
||||
|
||||
m::dbs::_index_event_horizon(txn, event, opts, event_id);
|
||||
++ret;
|
||||
return true;
|
||||
});
|
||||
}
|
||||
|
||||
txn();
|
||||
return ret;
|
||||
}
|
||||
|
||||
size_t
|
||||
ircd::m::room::events::horizon::count()
|
||||
const
|
||||
{
|
||||
size_t ret{0};
|
||||
for_each([&ret]
|
||||
(const auto &event_id, const auto &depth, const auto &event_idx) noexcept
|
||||
{
|
||||
++ret;
|
||||
return true;
|
||||
});
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
bool
|
||||
ircd::m::room::events::horizon::for_each(const closure &closure)
|
||||
const
|
||||
{
|
||||
const std::function<bool (const string_view &)> in_room
|
||||
{
|
||||
[this](const string_view &room_id) noexcept
|
||||
{
|
||||
return room_id == this->room.room_id;
|
||||
}
|
||||
};
|
||||
|
||||
return event::horizon::for_every([&in_room, &closure]
|
||||
(const event::id &event_id, const event::idx &event_idx)
|
||||
{
|
||||
if(!m::query(event_idx, "room_id", false, in_room))
|
||||
return true;
|
||||
|
||||
if(m::exists(event_id))
|
||||
return true;
|
||||
|
||||
uint64_t depth;
|
||||
if(!m::get(event_idx, "depth", depth))
|
||||
return true;
|
||||
|
||||
if(!closure(event_id, depth, event_idx))
|
||||
return false;
|
||||
|
||||
return true;
|
||||
});
|
||||
}
|
||||
|
|
101
matrix/room_events_horizon.cc
Normal file
101
matrix/room_events_horizon.cc
Normal file
|
@ -0,0 +1,101 @@
|
|||
// Matrix Construct
|
||||
//
|
||||
// Copyright (C) Matrix Construct Developers, Authors & Contributors
|
||||
// Copyright (C) 2016-2023 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.
|
||||
|
||||
//TODO: XXX remove fwd decl
|
||||
namespace ircd::m::dbs
|
||||
{
|
||||
void _index_event_horizon(db::txn &, const event &, const opts &, const m::event::id &);
|
||||
}
|
||||
|
||||
size_t
|
||||
ircd::m::room::events::horizon::rebuild()
|
||||
{
|
||||
m::dbs::opts opts;
|
||||
opts.appendix.reset();
|
||||
opts.appendix.set(dbs::appendix::EVENT_HORIZON);
|
||||
db::txn txn
|
||||
{
|
||||
*dbs::events
|
||||
};
|
||||
|
||||
size_t ret(0);
|
||||
m::room::events it
|
||||
{
|
||||
room
|
||||
};
|
||||
|
||||
for(; it; --it)
|
||||
{
|
||||
const m::event &event{*it};
|
||||
const event::prev prev_events{event};
|
||||
|
||||
opts.event_idx = it.event_idx();
|
||||
m::for_each(prev_events, [&]
|
||||
(const m::event::id &event_id)
|
||||
{
|
||||
if(m::exists(event_id))
|
||||
return true;
|
||||
|
||||
m::dbs::_index_event_horizon(txn, event, opts, event_id);
|
||||
++ret;
|
||||
return true;
|
||||
});
|
||||
}
|
||||
|
||||
txn();
|
||||
return ret;
|
||||
}
|
||||
|
||||
size_t
|
||||
ircd::m::room::events::horizon::count()
|
||||
const
|
||||
{
|
||||
size_t ret{0};
|
||||
for_each([&ret]
|
||||
(const auto &event_id, const auto &depth, const auto &event_idx) noexcept
|
||||
{
|
||||
++ret;
|
||||
return true;
|
||||
});
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
bool
|
||||
ircd::m::room::events::horizon::for_each(const closure &closure)
|
||||
const
|
||||
{
|
||||
const std::function<bool (const string_view &)> in_room
|
||||
{
|
||||
[this](const string_view &room_id) noexcept
|
||||
{
|
||||
return room_id == this->room.room_id;
|
||||
}
|
||||
};
|
||||
|
||||
return event::horizon::for_every([&in_room, &closure]
|
||||
(const event::id &event_id, const event::idx &event_idx)
|
||||
{
|
||||
if(!m::query(event_idx, "room_id", false, in_room))
|
||||
return true;
|
||||
|
||||
if(m::exists(event_id))
|
||||
return true;
|
||||
|
||||
uint64_t depth;
|
||||
if(!m::get(event_idx, "depth", depth))
|
||||
return true;
|
||||
|
||||
if(!closure(event_id, depth, event_idx))
|
||||
return false;
|
||||
|
||||
return true;
|
||||
});
|
||||
}
|
111
matrix/room_events_missing.cc
Normal file
111
matrix/room_events_missing.cc
Normal file
|
@ -0,0 +1,111 @@
|
|||
// Matrix Construct
|
||||
//
|
||||
// Copyright (C) Matrix Construct Developers, Authors & Contributors
|
||||
// Copyright (C) 2016-2023 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.
|
||||
|
||||
size_t
|
||||
ircd::m::room::events::missing::count()
|
||||
const
|
||||
{
|
||||
size_t ret{0};
|
||||
for_each([&ret]
|
||||
(const auto &event_id, const auto &depth, const auto &event_idx) noexcept
|
||||
{
|
||||
++ret;
|
||||
return true;
|
||||
});
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
bool
|
||||
ircd::m::room::events::missing::for_each(const closure &closure)
|
||||
const
|
||||
{
|
||||
return for_each({0L, 0L}, closure);
|
||||
}
|
||||
|
||||
bool
|
||||
ircd::m::room::events::missing::for_each(const pair<int64_t> &depth,
|
||||
const closure &closure)
|
||||
const
|
||||
{
|
||||
room::events it
|
||||
{
|
||||
room, uint64_t(depth.first)
|
||||
};
|
||||
|
||||
for(; it; ++it)
|
||||
{
|
||||
if(depth.second && int64_t(it.depth()) > depth.second)
|
||||
break;
|
||||
|
||||
if(!_each(it, closure))
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
ircd::m::room::events::missing::rfor_each(const pair<int64_t> &depth,
|
||||
const closure &closure)
|
||||
const
|
||||
{
|
||||
room::events it
|
||||
{
|
||||
room, depth.second?: -1UL
|
||||
};
|
||||
|
||||
for(; it; --it)
|
||||
{
|
||||
if(depth.second && int64_t(it.depth()) > depth.second)
|
||||
continue;
|
||||
|
||||
if(int64_t(it.depth()) < depth.first)
|
||||
break;
|
||||
|
||||
if(!_each(it, closure))
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
ircd::m::room::events::missing::_each(m::room::events &it,
|
||||
const closure &closure)
|
||||
const
|
||||
{
|
||||
const m::event event
|
||||
{
|
||||
*it
|
||||
};
|
||||
|
||||
const event::prev prev
|
||||
{
|
||||
event
|
||||
};
|
||||
|
||||
event::idx idx_buf[event::prev::MAX];
|
||||
const auto idx
|
||||
{
|
||||
prev.idxs(idx_buf)
|
||||
};
|
||||
|
||||
for(size_t i(0); i < idx.size(); ++i)
|
||||
{
|
||||
if(idx[i])
|
||||
continue;
|
||||
|
||||
if(!closure(prev.prev_event(i), it.depth(), it.event_idx()))
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
190
matrix/room_events_sounding.cc
Normal file
190
matrix/room_events_sounding.cc
Normal file
|
@ -0,0 +1,190 @@
|
|||
// Matrix Construct
|
||||
//
|
||||
// Copyright (C) Matrix Construct Developers, Authors & Contributors
|
||||
// Copyright (C) 2016-2023 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.
|
||||
|
||||
std::pair<int64_t, ircd::m::event::idx>
|
||||
ircd::m::viewport(const room &room)
|
||||
{
|
||||
std::pair<int64_t, m::event::idx> ret
|
||||
{
|
||||
-1, 0
|
||||
};
|
||||
|
||||
m::room::events it
|
||||
{
|
||||
room
|
||||
};
|
||||
|
||||
const ssize_t &max
|
||||
{
|
||||
room::events::viewport_size
|
||||
};
|
||||
|
||||
for(auto i(0); it && i < max; --it, ++i)
|
||||
{
|
||||
ret.first = it.depth();
|
||||
ret.second = it.event_idx();
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
std::pair<int64_t, ircd::m::event::idx>
|
||||
ircd::m::twain(const room &room)
|
||||
{
|
||||
std::pair<int64_t, m::event::idx> ret
|
||||
{
|
||||
-1, 0
|
||||
};
|
||||
|
||||
const room::events::sounding s
|
||||
{
|
||||
room
|
||||
};
|
||||
|
||||
s.rfor_each([&ret]
|
||||
(const auto &range, const auto &event_idx) noexcept
|
||||
{
|
||||
ret.first = range.first - 1;
|
||||
return false;
|
||||
});
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
std::pair<int64_t, ircd::m::event::idx>
|
||||
ircd::m::sounding(const room &room)
|
||||
{
|
||||
std::pair<int64_t, m::event::idx> ret
|
||||
{
|
||||
-1, 0
|
||||
};
|
||||
|
||||
const room::events::sounding s
|
||||
{
|
||||
room
|
||||
};
|
||||
|
||||
s.rfor_each([&ret]
|
||||
(const auto &range, const auto &event_idx) noexcept
|
||||
{
|
||||
ret.first = range.second;
|
||||
ret.second = event_idx;
|
||||
return false;
|
||||
});
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
std::pair<int64_t, ircd::m::event::idx>
|
||||
ircd::m::hazard(const room &room)
|
||||
{
|
||||
std::pair<int64_t, m::event::idx> ret
|
||||
{
|
||||
0, 0
|
||||
};
|
||||
|
||||
const room::events::sounding s
|
||||
{
|
||||
room
|
||||
};
|
||||
|
||||
s.for_each([&ret]
|
||||
(const auto &range, const auto &event_idx) noexcept
|
||||
{
|
||||
ret.first = range.first;
|
||||
return false;
|
||||
});
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
//
|
||||
// room::events::sounding
|
||||
//
|
||||
|
||||
bool
|
||||
ircd::m::room::events::sounding::rfor_each(const closure &closure)
|
||||
const
|
||||
{
|
||||
const int64_t depth
|
||||
{
|
||||
room.event_id?
|
||||
m::get(std::nothrow, m::index(std::nothrow, room.event_id), "depth", -1L):
|
||||
-1L
|
||||
};
|
||||
|
||||
room::events it
|
||||
{
|
||||
room, uint64_t(depth)
|
||||
};
|
||||
|
||||
if(!it)
|
||||
return true;
|
||||
|
||||
event::idx idx{0};
|
||||
for(sounding::range range{0L, it.depth()}; it; --it)
|
||||
{
|
||||
range.first = it.depth();
|
||||
if(range.first == range.second)
|
||||
{
|
||||
idx = it.event_idx();
|
||||
continue;
|
||||
}
|
||||
|
||||
--range.second;
|
||||
if(range.first == range.second)
|
||||
{
|
||||
idx = it.event_idx();
|
||||
continue;
|
||||
}
|
||||
|
||||
if(!closure({range.first+1, range.second+1}, idx))
|
||||
return false;
|
||||
|
||||
range.second = range.first;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
ircd::m::room::events::sounding::for_each(const closure &closure)
|
||||
const
|
||||
{
|
||||
const int64_t depth
|
||||
{
|
||||
room.event_id?
|
||||
m::get(std::nothrow, m::index(std::nothrow, room.event_id), "depth", 0L):
|
||||
0L
|
||||
};
|
||||
|
||||
room::events it
|
||||
{
|
||||
room, uint64_t(depth)
|
||||
};
|
||||
|
||||
for(sounding::range range{depth, 0L}; it; ++it)
|
||||
{
|
||||
range.second = it.depth();
|
||||
if(range.first == range.second)
|
||||
continue;
|
||||
|
||||
++range.first;
|
||||
if(range.first == range.second)
|
||||
continue;
|
||||
|
||||
if(!closure(range, it.event_idx()))
|
||||
return false;
|
||||
|
||||
range.first = range.second;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
Loading…
Reference in a new issue