mirror of
https://github.com/matrix-construct/construct
synced 2024-11-29 18:22:50 +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
|
#pragma once
|
||||||
#define HAVE_IRCD_M_ROOM_EVENTS_H
|
#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
|
/// Interface to room events
|
||||||
///
|
///
|
||||||
/// This interface has the form of an STL-style iterator over 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 ircd::m::room::events
|
||||||
{
|
{
|
||||||
struct sounding;
|
struct sounding;
|
||||||
struct horizon;
|
|
||||||
struct missing;
|
struct missing;
|
||||||
|
struct horizon;
|
||||||
|
|
||||||
static conf::item<ssize_t> viewport_size;
|
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 m::room &, const event::idx_range &);
|
||||||
static size_t count(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.h"
|
||||||
|
#include "events_sounding.h"
|
||||||
|
#include "events_missing.h"
|
||||||
|
#include "events_horizon.h"
|
||||||
#include "state.h"
|
#include "state.h"
|
||||||
#include "state_space.h"
|
#include "state_space.h"
|
||||||
#include "state_history.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_bootstrap.cc
|
||||||
libircd_matrix_la_SOURCES += room_create.cc
|
libircd_matrix_la_SOURCES += room_create.cc
|
||||||
libircd_matrix_la_SOURCES += room_events.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.cc
|
||||||
libircd_matrix_la_SOURCES += room_head_fetch.cc
|
libircd_matrix_la_SOURCES += room_head_fetch.cc
|
||||||
libircd_matrix_la_SOURCES += room_state_fetch.cc
|
libircd_matrix_la_SOURCES += room_state_fetch.cc
|
||||||
|
|
|
@ -15,103 +15,6 @@ ircd::m::room::events::viewport_size
|
||||||
{ "default", 96L },
|
{ "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
|
// room::events
|
||||||
//
|
//
|
||||||
|
@ -436,289 +339,3 @@ const
|
||||||
|
|
||||||
return std::get<0>(part);
|
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