diff --git a/include/ircd/m/room/events.h b/include/ircd/m/room/events.h index cced78373..6328aae8a 100644 --- a/include/ircd/m/room/events.h +++ b/include/ircd/m/room/events.h @@ -21,20 +21,30 @@ /// struct ircd::m::room::events { + using depth_range = std::pair; + using entry = std::tuple; + static conf::item viewport_size; m::room room; db::domain::const_iterator it; - event::fetch _event; + mutable entry _entry; public: - explicit operator bool() const { return bool(it); } - bool operator!() const { return !it; } + explicit operator bool() const; + bool operator!() const; + + // Fetch the actual event data at the iterator's position + const entry *operator->() const; + const entry &operator*() const; // Observers from the current valid iterator - uint64_t depth() const; event::idx event_idx() const; - explicit operator event::idx() const; + uint64_t depth() const; + + // Move the iterator + auto &operator++(); + auto &operator--(); // Perform a new lookup / iterator bool seek_idx(const event::idx &, const bool &lower_bound = false); @@ -44,16 +54,6 @@ struct ircd::m::room::events // Prefetch a new iterator lookup (async) bool preseek(const uint64_t &depth = -1); - // Move the iterator - auto &operator++() { return --it; } - auto &operator--() { return ++it; } - - // Fetch the actual event data at the iterator's position - const m::event &fetch(std::nothrow_t, bool *valid = nullptr); - const m::event &fetch(); - const m::event &operator*() { return fetch(std::nothrow); } - const m::event *operator->() { return &operator*(); } - // Prefetch the actual event data at the iterator's position (async) bool prefetch(const string_view &event_prop); bool prefetch(); // uses supplied fetch::opts. @@ -61,17 +61,17 @@ struct ircd::m::room::events // Seeks to closest event in the room by depth; room.event_id ignored. events(const m::room &, const uint64_t &depth, - const event::fetch::opts *const & = nullptr); + const event::fetch::opts * = nullptr); // Seeks to event_id; null iteration when not found; seekless when empty. events(const m::room &, const event::id &, - const event::fetch::opts *const & = nullptr); + const event::fetch::opts * = nullptr); // Seeks to latest event in the room unless room.event_id given. Null // iteration when given and not found. events(const m::room &, - const event::fetch::opts *const & = nullptr); + const event::fetch::opts * = nullptr); events() = default; events(const events &) = delete; @@ -81,7 +81,6 @@ struct ircd::m::room::events static bool preseek(const m::room &, const uint64_t &depth = -1); // Prefetch the actual room event data for a range; or most recent. - using depth_range = std::pair; static size_t prefetch(const m::room &, const depth_range &); static size_t prefetch_viewport(const m::room &); @@ -90,3 +89,51 @@ struct ircd::m::room::events static size_t count(const m::room &, const event::idx_range &); static size_t count(const event::idx_range &); }; + +inline auto & +ircd::m::room::events::operator++() +{ + return --it; +} + +inline auto & +ircd::m::room::events::operator--() +{ + return ++it; +} + +inline uint64_t +ircd::m::room::events::depth() +const +{ + return std::get<0>(operator*()); +} + +inline ircd::m::event::idx +ircd::m::room::events::event_idx() +const +{ + return std::get<1>(operator*()); +} + +inline +const ircd::m::room::events::entry & +ircd::m::room::events::operator*() +const +{ + return *(operator->()); +} + +inline bool +ircd::m::room::events::operator!() +const +{ + return !it; +} + +inline ircd::m::room::events::operator +bool() +const +{ + return bool(it); +} diff --git a/matrix/media.cc b/matrix/media.cc index 0e9221f6a..be20c3c49 100644 --- a/matrix/media.cc +++ b/matrix/media.cc @@ -367,16 +367,14 @@ ircd::m::media::file::read(const m::room &room, encoding_bytes(0), events_fetched(0), events_prefetched(0); + m::event::fetch event; for(; it; ++it) try { for(; epf && events_prefetched < events_fetched + events_prefetch; ++epf) events_prefetched += epf.prefetch(); + seek(event, it.event_idx()); ++events_fetched; - const m::event &event - { - *it - }; if(json::get<"type"_>(event) != "ircd.file.block.b64") continue; diff --git a/matrix/room_events.cc b/matrix/room_events.cc index 8df58f550..01c494af6 100644 --- a/matrix/room_events.cc +++ b/matrix/room_events.cc @@ -15,10 +15,6 @@ ircd::m::room::events::viewport_size { "default", 96L }, }; -// -// room::events -// - size_t ircd::m::room::events::count(const m::event::idx_range &range) { @@ -137,18 +133,14 @@ ircd::m::room::events::preseek(const m::room &room, // ircd::m::room::events::events(const m::room &room, - const event::fetch::opts *const &fopts) + const event::fetch::opts *const fopts) :room{room} -,_event -{ - fopts? - *fopts: - room.fopts? - *room.fopts: - event::fetch::default_opts -} { assert(room.room_id); + + if(fopts) + this->room.fopts = fopts; + const bool found { room.event_id? @@ -161,18 +153,14 @@ ircd::m::room::events::events(const m::room &room, ircd::m::room::events::events(const m::room &room, const event::id &event_id, - const event::fetch::opts *const &fopts) + const event::fetch::opts *const fopts) :room{room} -,_event -{ - fopts? - *fopts: - room.fopts? - *room.fopts: - event::fetch::default_opts -} { assert(room.room_id); + + if(fopts) + this->room.fopts = fopts; + const bool found { seek(event_id) @@ -183,19 +171,14 @@ ircd::m::room::events::events(const m::room &room, ircd::m::room::events::events(const m::room &room, const uint64_t &depth, - const event::fetch::opts *const &fopts) + const event::fetch::opts *const fopts) :room{room} -,_event -{ - fopts? - *fopts: - room.fopts? - *room.fopts: - event::fetch::default_opts -} { assert(room.room_id); + if(fopts) + this->room.fopts = fopts; + // As a special convenience for the ctor only, if the depth=0 and // nothing is found another attempt is made for depth=1 for synapse // rooms which start at depth=1. @@ -206,8 +189,14 @@ ircd::m::room::events::events(const m::room &room, bool ircd::m::room::events::prefetch() { - assert(_event.fopts); - return m::prefetch(event_idx(), *_event.fopts); + const auto &fopts + { + room.fopts? + *room.fopts: + event::fetch::default_opts + }; + + return m::prefetch(event_idx(), fopts); } bool @@ -216,28 +205,6 @@ ircd::m::room::events::prefetch(const string_view &event_prop) return m::prefetch(event_idx(), event_prop); } -const ircd::m::event & -ircd::m::room::events::fetch() -{ - m::seek(_event, event_idx()); - return _event; -} - -const ircd::m::event & -ircd::m::room::events::fetch(std::nothrow_t, - bool *const valid_) -{ - const bool valid - { - m::seek(std::nothrow, _event, event_idx()) - }; - - if(valid_) - *valid_ = valid; - - return _event; -} - bool ircd::m::room::events::preseek(const uint64_t &depth) { @@ -307,35 +274,11 @@ ircd::m::room::events::seek_idx(const event::idx &event_idx, return true; } -ircd::m::room::events::operator -ircd::m::event::idx() -const -{ - return event_idx(); -} - -ircd::m::event::idx -ircd::m::room::events::event_idx() +const ircd::m::room::events::entry * +ircd::m::room::events::operator->() const { assert(bool(*this)); - const auto part - { - dbs::room_events_key(it->first) - }; - - return std::get<1>(part); -} - -uint64_t -ircd::m::room::events::depth() -const -{ - assert(bool(*this)); - const auto part - { - dbs::room_events_key(it->first) - }; - - return std::get<0>(part); + _entry = dbs::room_events_key(it->first); + return &_entry; } diff --git a/matrix/room_head.cc b/matrix/room_head.cc index ffc9131f2..499e1ef3c 100644 --- a/matrix/room_head.cc +++ b/matrix/room_head.cc @@ -291,9 +291,9 @@ ircd::m::room::head::reset(const head &head) return ret; // Replacement will be the single new head - const m::event replacement + const m::event::fetch replacement { - *it + it.event_idx() }; db::txn txn @@ -368,11 +368,17 @@ ircd::m::room::head::rebuild(const head &head) *m::dbs::events }; - m::dbs::opts opts; - opts.op = db::op::SET; + m::dbs::opts opts + { + .op = db::op::SET, + }; + + m::event::fetch event; for(; it; ++it) { - const m::event &event{*it}; + if(!seek(std::nothrow, event, it.event_idx())) + continue; + opts.event_idx = it.event_idx(); opts.appendix.reset(); opts.appendix.set(dbs::appendix::ROOM_HEAD); diff --git a/matrix/room_horizon.cc b/matrix/room_horizon.cc index f2e0fa39b..ca0b8f231 100644 --- a/matrix/room_horizon.cc +++ b/matrix/room_horizon.cc @@ -31,11 +31,13 @@ ircd::m::room::horizon::rebuild() room }; + m::event::fetch event; for(; it; --it) { - const m::event &event{*it}; - const event::prev prev_events{event}; + if(!seek(std::nothrow, event, it.event_idx())) + continue; + const event::prev prev_events{event}; opts.event_idx = it.event_idx(); m::for_each(prev_events, [&] (const m::event::id &event_id) diff --git a/matrix/room_missing.cc b/matrix/room_missing.cc index 18ca92c0e..dfe0a05fc 100644 --- a/matrix/room_missing.cc +++ b/matrix/room_missing.cc @@ -82,28 +82,33 @@ ircd::m::room::missing::_each(m::room::events &it, const closure &closure) const { - const m::event event + const auto &[depth, event_idx] { *it }; + const m::event::fetch event + { + std::nothrow, event_idx + }; + const event::prev prev { event }; event::idx idx_buf[event::prev::MAX]; - const auto idx + const auto prev_idx { prev.idxs(idx_buf) }; - for(size_t i(0); i < idx.size(); ++i) + for(size_t i(0); i < prev_idx.size(); ++i) { - if(idx[i]) + if(prev_idx[i]) continue; - if(!closure(prev.prev_event(i), it.depth(), it.event_idx())) + if(!closure(prev.prev_event(i), depth, event_idx)) return false; } diff --git a/matrix/room_purge.cc b/matrix/room_purge.cc index 80e31f2b1..d2d56ac7d 100644 --- a/matrix/room_purge.cc +++ b/matrix/room_purge.cc @@ -114,18 +114,13 @@ ircd::m::room::purge::timeline() room, opts.depth.second }; + m::event::fetch event; for(; it && it.depth() >= opts.depth.first; --it) { if(!match(it.depth(), it.event_idx())) continue; - bool valid; - const event &event - { - it.fetch(std::nothrow, &valid) - }; - - if(unlikely(!valid)) + if(unlikely(!seek(std::nothrow, event, it.event_idx()))) continue; if(!match(it.event_idx(), event)) diff --git a/matrix/room_state_space.cc b/matrix/room_state_space.cc index f0f3423f1..3015fbda1 100644 --- a/matrix/room_state_space.cc +++ b/matrix/room_state_space.cc @@ -212,6 +212,7 @@ ircd::m::room::state::space::rebuild::rebuild(const room::id &room_id) !m::internal(room_id) }; + m::event::fetch event; size_t state_count(0), messages_count(0), state_deleted(0); for(; it; ++it, ++messages_count) try { @@ -223,8 +224,10 @@ ircd::m::room::state::space::rebuild::rebuild(const room::id &room_id) if(!state::is(std::nothrow, event_idx)) continue; + if(!seek(std::nothrow, event, event_idx)) + continue; + ++state_count; - const m::event &event{*it}; const auto &[pass_static, reason_static] { check_auth? diff --git a/modules/client/events.cc b/modules/client/events.cc index c5598fc41..63536646e 100644 --- a/modules/client/events.cc +++ b/modules/client/events.cc @@ -333,13 +333,16 @@ get_events_from(client &client, }; size_t i(0), j(0); + m::event::fetch event; for(; it && i < size_t(events_limit); --it, ++i) { - const m::event &event{*it}; + const auto &event_idx(it.event_idx()); + if(!seek(std::nothrow, event, event_idx)) + continue; + if(!visible(event, request.user_id)) continue; - const auto &event_idx(it.event_idx()); j += append_event(chunk, event, event_idx, room_depth, user_room); } diff --git a/modules/client/initialsync.cc b/modules/client/initialsync.cc index 346b23ecc..30af810b4 100644 --- a/modules/client/initialsync.cc +++ b/modules/client/initialsync.cc @@ -554,6 +554,7 @@ initialsync_room_timeline_events(client &client, m::event::idx event_idx{0}; m::event::id::buf event_id; m::room::events it{room}; + m::event::fetch event; for(; it && i < 10; --it, ++i) { event_idx = it.event_idx(); @@ -565,7 +566,8 @@ initialsync_room_timeline_events(client &client, if(i > 0) for(; it && i > -1; ++it, --i) - out.append(*it); + if(seek(std::nothrow, event, it.event_idx())) + out.append(event); return event_id; } diff --git a/modules/client/rooms/context.cc b/modules/client/rooms/context.cc index 97cf4485d..137c02d30 100644 --- a/modules/client/rooms/context.cc +++ b/modules/client/rooms/context.cc @@ -164,14 +164,17 @@ get__context(client &client, if(before) --before; + m::event::fetch event; for(size_t i(0); i < limit && before; --before, ++i) { - const m::event &event{*before}; + const auto event_idx(before.event_idx()); + if(!seek(std::nothrow, event, event_idx)) + continue; + start = event.event_id; if(!visible(event, request.user_id)) continue; - const auto event_idx(before.event_idx()); counts.before += m::event::append { array, event, @@ -215,14 +218,17 @@ get__context(client &client, if(after) ++after; + m::event::fetch event; for(size_t i(0); i < limit && after; ++after, ++i) { - const m::event &event{*after}; + const auto event_idx(after.event_idx()); + if(!seek(std::nothrow, event, event_idx)) + continue; + end = event.event_id; if(!visible(event, request.user_id)) continue; - const auto event_idx(after.event_idx()); counts.after += m::event::append { array, event, diff --git a/modules/client/rooms/initialsync.cc b/modules/client/rooms/initialsync.cc index 232413ae9..883d7c6d4 100644 --- a/modules/client/rooms/initialsync.cc +++ b/modules/client/rooms/initialsync.cc @@ -245,10 +245,13 @@ get__initialsync_local(client &client, messages, "chunk" }; + m::event::fetch event; for(; it; ++it) { const auto &event_idx(it.event_idx()); - const m::event &event(*it); + if(!seek(std::nothrow, event, event_idx)) + continue; + if(!visible(event, user.user_id)) continue; diff --git a/modules/client/rooms/messages.cc b/modules/client/rooms/messages.cc index abedef901..f577b040f 100644 --- a/modules/client/rooms/messages.cc +++ b/modules/client/rooms/messages.cc @@ -131,18 +131,17 @@ get__messages(client &client, room }; + m::event::fetch event; for(; it; page.dir == 'b'? --it : ++it) { - const m::event &event - { - *it - }; + const auto &event_idx(it.event_idx()); + if(!seek(std::nothrow, event, event_idx)) + continue; end = event.event_id; if(hit >= page.limit || miss >= size_t(max_filter_miss)) break; - const m::event::idx event_idx{it}; const bool ok { (empty(filter_json) || match(filter, event)) diff --git a/modules/client/sync/rooms/timeline.cc b/modules/client/sync/rooms/timeline.cc index 6b4f568be..a0b8e6d78 100644 --- a/modules/client/sync/rooms/timeline.cc +++ b/modules/client/sync/rooms/timeline.cc @@ -382,9 +382,10 @@ ircd::m::sync::_room_timeline_polylog_events(data &data, if(i > 1 && it) --i, ++it; + m::event::fetch event; for(; i >= 0 && it; --i, ++it) { - const auto event_idx + const auto &event_idx { it.event_idx() }; @@ -392,9 +393,12 @@ ircd::m::sync::_room_timeline_polylog_events(data &data, if(event_idx == batch_idx) continue; + if(!seek(std::nothrow, event, event_idx)) + continue; + ret |= m::event::append { - array, *it, + array, event, { .event_idx = &event_idx, .client_txnid = &data.client_txnid, diff --git a/modules/console.cc b/modules/console.cc index 98db1011e..981122c44 100644 --- a/modules/console.cc +++ b/modules/console.cc @@ -11196,12 +11196,11 @@ console_cmd__room__count(opt &out, const string_view &line) if(param[1]) { size_t count{0}; + m::event::fetch event; m::room::events it{room}; for(; it && limit; --it, --limit) - { - const m::event &event{*it}; - count += match(filter, event); - } + if(seek(std::nothrow, event, it.event_idx())) + count += match(filter, event); out << count << std::endl; return true; @@ -11256,10 +11255,17 @@ console_cmd__room__events(opt &out, const string_view &line) room, uint64_t(depth >= 0? depth : -1) }; + m::event::fetch event; for(; it && limit > 0; order == 'b'? --it : ++it, --limit) - out << std::left << std::setw(10) << it.event_idx() << " " - << pretty_oneline(*it) - << std::endl; + { + if(!seek(std::nothrow, event, it.event_idx())) + continue; + + out + << std::left << std::setw(10) << it.event_idx() << " " + << pretty_oneline(event) + << std::endl; + } return true; } diff --git a/modules/federation/backfill.cc b/modules/federation/backfill.cc index 55c6e13fe..a42f41d6e 100644 --- a/modules/federation/backfill.cc +++ b/modules/federation/backfill.cc @@ -123,12 +123,11 @@ get__backfill(client &client, }; size_t count{0}; + m::event::fetch event; for(; it && count < limit; ++count, --it) { - const m::event &event - { - *it - }; + if(!seek(std::nothrow, event, it.event_idx())) + continue; assert(event.event_id); if(!visible(event, request.node_id))