mirror of
https://github.com/matrix-construct/construct
synced 2024-11-25 16:22:35 +01:00
134 lines
3 KiB
C++
134 lines
3 KiB
C++
|
// The Construct
|
||
|
//
|
||
|
// Copyright (C) The Construct Developers, Authors & Contributors
|
||
|
// Copyright (C) 2016-2020 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.
|
||
|
|
||
|
namespace ircd::m
|
||
|
{
|
||
|
static bool room_state_fetch_result(room::state::fetch &, const room::state::fetch::opts &, const room::state::fetch::closure &, const json::array &, const string_view &);
|
||
|
}
|
||
|
|
||
|
ircd::m::room::state::fetch::fetch(const opts &opts,
|
||
|
const closure &closure)
|
||
|
{
|
||
|
m::room room
|
||
|
{
|
||
|
opts.room
|
||
|
};
|
||
|
|
||
|
feds::opts fopts;
|
||
|
fopts.op = feds::op::state;
|
||
|
fopts.room_id = room.room_id;
|
||
|
fopts.event_id = room.event_id;
|
||
|
fopts.arg[0] = "ids";
|
||
|
fopts.exclude_myself = true;
|
||
|
fopts.closure_errors = false;
|
||
|
log::debug
|
||
|
{
|
||
|
log, "Resynchronizing %s state at %s from %zu joined servers...",
|
||
|
string_view{room.room_id},
|
||
|
room.event_id?
|
||
|
string_view{room.event_id}:
|
||
|
"HEAD"_sv,
|
||
|
room::origins(room).count(),
|
||
|
};
|
||
|
|
||
|
feds::execute(fopts, [this, &opts, &closure]
|
||
|
(const auto &result)
|
||
|
{
|
||
|
this->respond++;
|
||
|
|
||
|
const json::array &auth_chain_ids
|
||
|
{
|
||
|
result.object["auth_chain_ids"]
|
||
|
};
|
||
|
|
||
|
const json::array &pdu_ids
|
||
|
{
|
||
|
result.object["pdu_ids"]
|
||
|
};
|
||
|
|
||
|
if(!room_state_fetch_result(*this, opts, closure, auth_chain_ids, result.origin))
|
||
|
return false;
|
||
|
|
||
|
if(!room_state_fetch_result(*this, opts, closure, pdu_ids, result.origin))
|
||
|
return false;
|
||
|
|
||
|
return true;
|
||
|
});
|
||
|
}
|
||
|
|
||
|
bool
|
||
|
ircd::m::room_state_fetch_result(room::state::fetch &f,
|
||
|
const room::state::fetch::opts &opts,
|
||
|
const room::state::fetch::closure &closure,
|
||
|
const json::array &ids,
|
||
|
const string_view &remote)
|
||
|
{
|
||
|
event::id event_id[64];
|
||
|
auto it(begin(ids)); do
|
||
|
{
|
||
|
size_t i(0);
|
||
|
for(; i < 64 && it != end(ids); ++it)
|
||
|
event_id[i++] = json::string{*it};
|
||
|
|
||
|
const vector_view<const event::id> event_ids
|
||
|
(
|
||
|
event_id, i
|
||
|
);
|
||
|
|
||
|
const uint64_t exists
|
||
|
{
|
||
|
!opts.existing?
|
||
|
m::exists(event_ids):
|
||
|
0UL
|
||
|
};
|
||
|
|
||
|
f.responses += i;
|
||
|
f.exists += __builtin_popcountl(exists);
|
||
|
for(size_t j(0); j < i; ++j)
|
||
|
{
|
||
|
if(exists & (1UL << j))
|
||
|
continue;
|
||
|
|
||
|
auto it
|
||
|
{
|
||
|
f.result.lower_bound(event_id[j])
|
||
|
};
|
||
|
|
||
|
if(likely(opts.unique))
|
||
|
{
|
||
|
if(it != std::end(f.result) && *it == event_id[j])
|
||
|
{
|
||
|
f.concur++;
|
||
|
continue;
|
||
|
}
|
||
|
|
||
|
it = f.result.emplace_hint(it, event_id[j]);
|
||
|
}
|
||
|
|
||
|
if(closure && opts.unique)
|
||
|
{
|
||
|
// When a reference can be made to the result set: prefer it.
|
||
|
assert(it != std::end(f.result));
|
||
|
assert(*it == event_id[j]);
|
||
|
if(!closure(*it, remote))
|
||
|
return false;
|
||
|
}
|
||
|
else if(closure)
|
||
|
{
|
||
|
if(!closure(event_id[j], remote))
|
||
|
return false;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
while(it != end(ids));
|
||
|
|
||
|
return true;
|
||
|
}
|