Compare commits
17 Commits
70b49b96d2
...
c6ce4d3229
Author | SHA1 | Date |
---|---|---|
Jason Volk | c6ce4d3229 | |
Jason Volk | 76def3378f | |
Jason Volk | 767f6cbae5 | |
Jason Volk | dcfae310ab | |
Jason Volk | 2331de3f3e | |
Jason Volk | 0b6669ca20 | |
Jason Volk | 43838608fd | |
Jason Volk | f85781b65a | |
Jason Volk | d01e937f3e | |
Jason Volk | 9558637c20 | |
Jason Volk | e3edcefe17 | |
Jason Volk | ac3b85114b | |
Jason Volk | 684dd18497 | |
Jason Volk | fb9b68b4e3 | |
Jason Volk | 00094e272f | |
Jason Volk | 98e366e012 | |
Jason Volk | b5932ba33c |
|
@ -1,8 +1,9 @@
|
|||
version: master_{build}
|
||||
clone_depth: 1
|
||||
skip_tags: true
|
||||
|
||||
services:
|
||||
- docker
|
||||
- docker
|
||||
|
||||
environment:
|
||||
COMMAND: if [[ "${APPVEYOR_REPO_COMMIT_MESSAGE@Q}" == *"[ci debug]"* ]]; then export DEBUG_FLAGS="--enable-debug"; fi; if [[ "${APPVEYOR_REPO_COMMIT_MESSAGE@Q}" == *"[ci gdb]"* ]]; then apt-get update && apt-get -y install gdb && export CONSTRUCT="gdb --batch -ex r -ex bt --return-child-result --args construct"; else export CONSTRUCT="construct"; fi && rmdir -v deps/rocksdb && ln -sv /usr/src/rocksdb deps && ./autogen.sh && ./configure --enable-assert ${DEBUG_FLAGS} && make install && ${CONSTRUCT} -smoketest -debug localhost
|
||||
|
@ -18,8 +19,8 @@ environment:
|
|||
DOCKER_IMAGE: jevolk/construct:ubuntu-22.04-full-build-clang-15-amd64
|
||||
|
||||
for:
|
||||
-
|
||||
build_script:
|
||||
-
|
||||
build_script:
|
||||
- docker run -v `pwd`:/build "${DOCKER_IMAGE}" /bin/bash -c "${COMMAND}"
|
||||
|
||||
matrix:
|
||||
|
|
|
@ -14,9 +14,9 @@
|
|||
namespace ircd::fs::dev
|
||||
{
|
||||
struct blk;
|
||||
struct stats;
|
||||
|
||||
using major_minor = std::pair<ulong, ulong>;
|
||||
using blk_closure = std::function<bool (const ulong &id, const blk &)>;
|
||||
|
||||
// Convert device ID's with the major(3) / minor(3) / makedev(3)
|
||||
ulong id(const major_minor &);
|
||||
|
@ -36,13 +36,12 @@ namespace ircd::fs::dev
|
|||
sysfs(const ulong &id,
|
||||
const string_view &path,
|
||||
const R &def = 0);
|
||||
|
||||
bool for_each(const string_view &devtype, const blk_closure &);
|
||||
bool for_each(const blk_closure &);
|
||||
}
|
||||
|
||||
struct ircd::fs::dev::blk
|
||||
{
|
||||
using closure = util::function_bool<const ulong &, const blk &>;
|
||||
|
||||
static const size_t SECTOR_SIZE;
|
||||
static const string_view BASE_PATH;
|
||||
|
||||
|
@ -66,6 +65,47 @@ struct ircd::fs::dev::blk
|
|||
|
||||
blk(const ulong &id);
|
||||
blk() = default;
|
||||
|
||||
static bool for_each(const string_view &devtype, const closure &);
|
||||
static bool for_each(const closure &);
|
||||
};
|
||||
|
||||
struct ircd::fs::dev::stats
|
||||
{
|
||||
using closure = util::function_bool<const stats &>;
|
||||
|
||||
char name[32] {0};
|
||||
major_minor id {0, 0};
|
||||
|
||||
uint64_t read {0};
|
||||
uint64_t read_merged {0};
|
||||
uint64_t read_sectors {0};
|
||||
milliseconds read_time {0ms};
|
||||
|
||||
uint64_t write {0};
|
||||
uint64_t write_merged {0};
|
||||
uint64_t write_sectors {0};
|
||||
milliseconds write_time {0ms};
|
||||
|
||||
uint64_t io_current {0};
|
||||
milliseconds io_time {0ms};
|
||||
milliseconds io_weighted_time {0ms};
|
||||
|
||||
// 4.18+
|
||||
uint64_t discard {0};
|
||||
uint64_t discard_merged {0};
|
||||
uint64_t discard_sectors {0};
|
||||
milliseconds discard_time {0ms};
|
||||
|
||||
// 5.5+
|
||||
uint64_t flush {0};
|
||||
milliseconds flush_time {0ms};
|
||||
|
||||
stats(const string_view &line);
|
||||
stats() = default;
|
||||
|
||||
static bool for_each(const closure &);
|
||||
static stats get(const major_minor &id);
|
||||
};
|
||||
|
||||
/// Return a lex_cast'able (an integer) from a sysfs target.
|
||||
|
|
|
@ -41,11 +41,12 @@ namespace ircd::m
|
|||
size_t degree(const event &);
|
||||
bool before(const event &a, const event &b);
|
||||
|
||||
json::object hashes(const mutable_buffer &, const event &);
|
||||
event signatures(const mutable_buffer &, const m::event &, const string_view &origin);
|
||||
event signatures(const mutable_buffer &, const m::event &);
|
||||
event essential(event, const mutable_buffer &content, const bool &sigs = false);
|
||||
event signatures(const mutable_buffer &, const event &, const string_view &origin, const ed25519::sk &, const string_view &pkid);
|
||||
event signatures(const mutable_buffer &, const event &, const string_view &origin);
|
||||
event signatures(const mutable_buffer &, const event &);
|
||||
|
||||
json::object hashes(const mutable_buffer &, const event &);
|
||||
bool verify_hash(const event &, const sha256::buf &);
|
||||
bool verify_hash(const event &);
|
||||
|
||||
|
|
|
@ -13,9 +13,12 @@
|
|||
|
||||
namespace ircd::m::vm::notify
|
||||
{
|
||||
using value_type = std::pair<const event::id, ctx::ctx *>;
|
||||
struct future;
|
||||
|
||||
using value_type = std::pair<const event::id, ctx::promise<> *>;
|
||||
using alloc_type = allocator::node<value_type>;
|
||||
using map_type = std::multimap<event::id, ctx::ctx *, std::less<>, alloc_type::allocator>;
|
||||
using map_type = std::multimap<const event::id, ctx::promise<> *, std::less<>, alloc_type::allocator>;
|
||||
using node_type = std::pair<map_type::node_type, value_type>;
|
||||
|
||||
extern map_type map;
|
||||
|
||||
|
@ -23,6 +26,19 @@ namespace ircd::m::vm::notify
|
|||
bool wait(const event::id &, const milliseconds);
|
||||
}
|
||||
|
||||
class ircd::m::vm::notify::future
|
||||
:public ctx::future<>
|
||||
{
|
||||
node_type node;
|
||||
ctx::promise<> promise;
|
||||
unique_iterator<map_type> it;
|
||||
|
||||
public:
|
||||
future(const event::id &);
|
||||
future(future &&) = delete;
|
||||
future(const future &) = delete;
|
||||
};
|
||||
|
||||
/// Yields ctx until event was successfully evaluated. Returns false if
|
||||
/// timeout occurred.
|
||||
inline bool
|
||||
|
|
|
@ -37,6 +37,7 @@ ircd::net::dns::resolver
|
|||
static conf::item<milliseconds> send_rate;
|
||||
static conf::item<size_t> send_burst;
|
||||
static conf::item<size_t> retry_max;
|
||||
static conf::item<bool> retry_serv_fail;
|
||||
|
||||
answers_callback callback;
|
||||
std::vector<ip::udp::endpoint> server; // The list of active servers
|
||||
|
|
|
@ -32,41 +32,24 @@ template<class container,
|
|||
class iterator>
|
||||
struct ircd::util::unique_iterator
|
||||
{
|
||||
container *c;
|
||||
container *c {nullptr};
|
||||
iterator it;
|
||||
|
||||
unique_iterator(container &c, iterator it)
|
||||
:c{&c}
|
||||
,it{std::move(it)}
|
||||
{}
|
||||
operator const iterator &() const;
|
||||
decltype(auto) operator->() const;
|
||||
decltype(auto) operator*() const;
|
||||
|
||||
unique_iterator()
|
||||
:c{nullptr}
|
||||
{}
|
||||
operator iterator &();
|
||||
decltype(auto) operator->();
|
||||
decltype(auto) operator*();
|
||||
|
||||
unique_iterator(container &c, iterator it);
|
||||
unique_iterator() = default;
|
||||
unique_iterator(unique_iterator &&o) noexcept;
|
||||
unique_iterator(const unique_iterator &) = delete;
|
||||
unique_iterator(unique_iterator &&o) noexcept
|
||||
:c{std::move(o.c)}
|
||||
,it{std::move(o.it)}
|
||||
{
|
||||
o.c = nullptr;
|
||||
}
|
||||
|
||||
unique_iterator &operator=(unique_iterator &&o) noexcept;
|
||||
unique_iterator &operator=(const unique_iterator &) = delete;
|
||||
unique_iterator &operator=(unique_iterator &&o) noexcept
|
||||
{
|
||||
this->~unique_iterator();
|
||||
c = std::move(o.c);
|
||||
it = std::move(o.it);
|
||||
o.c = nullptr;
|
||||
return *this;
|
||||
}
|
||||
|
||||
~unique_iterator() noexcept
|
||||
{
|
||||
if(c)
|
||||
c->erase(it);
|
||||
}
|
||||
~unique_iterator() noexcept;
|
||||
};
|
||||
|
||||
template<class container>
|
||||
|
@ -76,3 +59,89 @@ struct ircd::util::unique_const_iterator
|
|||
using iterator_type = typename container::const_iterator;
|
||||
using unique_iterator<container, iterator_type>::unique_iterator;
|
||||
};
|
||||
|
||||
template<class container,
|
||||
class iterator>
|
||||
inline
|
||||
ircd::util::unique_iterator<container, iterator>::unique_iterator(container &c,
|
||||
iterator it)
|
||||
:c{&c}
|
||||
,it{std::move(it)}
|
||||
{}
|
||||
|
||||
template<class container,
|
||||
class iterator>
|
||||
inline
|
||||
ircd::util::unique_iterator<container, iterator>::unique_iterator(unique_iterator &&o)
|
||||
noexcept
|
||||
:c{std::move(o.c)}
|
||||
,it{std::move(o.it)}
|
||||
{
|
||||
o.c = nullptr;
|
||||
}
|
||||
|
||||
template<class container,
|
||||
class iterator>
|
||||
inline ircd::util::unique_iterator<container, iterator> &
|
||||
ircd::util::unique_iterator<container, iterator>::operator=(unique_iterator &&o)
|
||||
noexcept
|
||||
{
|
||||
this->~unique_iterator();
|
||||
c = std::move(o.c);
|
||||
it = std::move(o.it);
|
||||
o.c = nullptr;
|
||||
return *this;
|
||||
}
|
||||
|
||||
template<class container,
|
||||
class iterator>
|
||||
inline
|
||||
ircd::util::unique_iterator<container, iterator>::~unique_iterator()
|
||||
noexcept
|
||||
{
|
||||
if(c)
|
||||
c->erase(it);
|
||||
}
|
||||
|
||||
template<class container,
|
||||
class iterator>
|
||||
inline decltype(auto)
|
||||
ircd::util::unique_iterator<container, iterator>::operator*()
|
||||
{
|
||||
return it.operator*();
|
||||
}
|
||||
|
||||
template<class container,
|
||||
class iterator>
|
||||
inline decltype(auto)
|
||||
ircd::util::unique_iterator<container, iterator>::operator->()
|
||||
{
|
||||
return it.operator->();
|
||||
}
|
||||
|
||||
template<class container,
|
||||
class iterator>
|
||||
inline decltype(auto)
|
||||
ircd::util::unique_iterator<container, iterator>::operator*()
|
||||
const
|
||||
{
|
||||
return it.operator*();
|
||||
}
|
||||
|
||||
template<class container,
|
||||
class iterator>
|
||||
inline decltype(auto)
|
||||
ircd::util::unique_iterator<container, iterator>::operator->()
|
||||
const
|
||||
{
|
||||
return it.operator->();
|
||||
}
|
||||
|
||||
template<class container,
|
||||
class iterator>
|
||||
inline ircd::util::unique_iterator<container, iterator>::operator
|
||||
const iterator &()
|
||||
const
|
||||
{
|
||||
return it;
|
||||
}
|
||||
|
|
|
@ -114,15 +114,13 @@ size_t
|
|||
ircd::fs::aio::init::query_max_events()
|
||||
{
|
||||
size_t ret(0);
|
||||
fs::dev::for_each("disk", [&ret]
|
||||
fs::dev::blk::for_each("disk", [&ret]
|
||||
(const ulong &id, const fs::dev::blk &device)
|
||||
{
|
||||
ret = std::clamp
|
||||
(
|
||||
device.queue_depth, ret, MAX_EVENTS
|
||||
);
|
||||
|
||||
return true;
|
||||
});
|
||||
|
||||
if(!ret)
|
||||
|
|
199
ircd/fs_dev.cc
199
ircd/fs_dev.cc
|
@ -10,55 +10,6 @@
|
|||
|
||||
#include <RB_INC_SYS_SYSMACROS_H
|
||||
|
||||
bool
|
||||
ircd::fs::dev::for_each(const blk_closure &closure)
|
||||
{
|
||||
return for_each(string_view{}, closure);
|
||||
}
|
||||
|
||||
bool
|
||||
ircd::fs::dev::for_each(const string_view &type,
|
||||
const blk_closure &closure)
|
||||
{
|
||||
for(const auto &dir : fs::ls(blk::BASE_PATH)) try
|
||||
{
|
||||
const auto &[major, minor]
|
||||
{
|
||||
split(filename(path_scratch, dir), ':')
|
||||
};
|
||||
|
||||
if(!major || !minor)
|
||||
continue;
|
||||
|
||||
const ulong id
|
||||
{
|
||||
dev::id({lex_cast<ulong>(major), lex_cast<ulong>(minor)})
|
||||
};
|
||||
|
||||
char dtbuf[32];
|
||||
if(type && blk::devtype(dtbuf, id) != type)
|
||||
continue;
|
||||
|
||||
if(!closure(id, blk(id)))
|
||||
return false;
|
||||
}
|
||||
catch(const ctx::interrupted &)
|
||||
{
|
||||
throw;
|
||||
}
|
||||
catch(const std::exception &e)
|
||||
{
|
||||
log::error
|
||||
{
|
||||
log, "%s :%s",
|
||||
dir,
|
||||
e.what(),
|
||||
};
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
ircd::string_view
|
||||
ircd::fs::dev::sysfs(const mutable_buffer &out,
|
||||
const ulong &id,
|
||||
|
@ -123,6 +74,59 @@ ircd::fs::dev::blk::BASE_PATH
|
|||
"/sys/dev/block"
|
||||
};
|
||||
|
||||
bool
|
||||
ircd::fs::dev::blk::for_each(const closure &closure)
|
||||
{
|
||||
return for_each(string_view{}, closure);
|
||||
}
|
||||
|
||||
bool
|
||||
ircd::fs::dev::blk::for_each(const string_view &type,
|
||||
const closure &closure)
|
||||
{
|
||||
for(const auto &dir : fs::ls(blk::BASE_PATH)) try
|
||||
{
|
||||
const auto &[major, minor]
|
||||
{
|
||||
split(filename(path_scratch, dir), ':')
|
||||
};
|
||||
|
||||
if(!major || !minor)
|
||||
continue;
|
||||
|
||||
const ulong id
|
||||
{
|
||||
dev::id({lex_cast<ulong>(major), lex_cast<ulong>(minor)})
|
||||
};
|
||||
|
||||
char dtbuf[32];
|
||||
if(type && blk::devtype(dtbuf, id) != type)
|
||||
continue;
|
||||
|
||||
if(!closure(id, blk(id)))
|
||||
return false;
|
||||
}
|
||||
catch(const ctx::interrupted &)
|
||||
{
|
||||
throw;
|
||||
}
|
||||
catch(const std::exception &e)
|
||||
{
|
||||
log::error
|
||||
{
|
||||
log, "%s :%s",
|
||||
dir,
|
||||
e.what(),
|
||||
};
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
//
|
||||
// dev::blk::blk
|
||||
//
|
||||
|
||||
ircd::fs::dev::blk::blk(const ulong &id)
|
||||
:type
|
||||
{
|
||||
|
@ -227,3 +231,100 @@ ircd::fs::dev::blk::devtype(const mutable_buffer &buf,
|
|||
|
||||
return ret;
|
||||
}
|
||||
|
||||
//
|
||||
// dev::stats
|
||||
//
|
||||
|
||||
ircd::fs::dev::stats
|
||||
ircd::fs::dev::stats::get(const major_minor &id)
|
||||
{
|
||||
stats ret;
|
||||
for_each([&id, &ret]
|
||||
(const auto &stats)
|
||||
{
|
||||
if(stats.id == id)
|
||||
{
|
||||
ret = stats;
|
||||
return false;
|
||||
}
|
||||
else return true;
|
||||
});
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
bool
|
||||
ircd::fs::dev::stats::for_each(const closure &closure)
|
||||
{
|
||||
thread_local char buf[16_KiB];
|
||||
|
||||
const fs::fd fd
|
||||
{
|
||||
"/proc/diskstats", fs::fd::opts
|
||||
{
|
||||
.mode = std::ios::in,
|
||||
},
|
||||
};
|
||||
|
||||
fs::read_opts opts;
|
||||
opts.aio = false;
|
||||
const string_view read
|
||||
{
|
||||
fs::read(fd, buf, opts)
|
||||
};
|
||||
|
||||
return tokens(read, '\n', [&closure]
|
||||
(const auto &line)
|
||||
{
|
||||
return closure(stats(line));
|
||||
});
|
||||
}
|
||||
|
||||
//
|
||||
// dev::stats::stats
|
||||
//
|
||||
|
||||
ircd::fs::dev::stats::stats(const string_view &line)
|
||||
{
|
||||
string_view item[20];
|
||||
const auto items
|
||||
{
|
||||
tokens(line, ' ', item)
|
||||
};
|
||||
|
||||
id.first = lex_cast<uint64_t>(item[0]);
|
||||
id.second = lex_cast<uint64_t>(item[1]);
|
||||
strlcpy(name, item[2]);
|
||||
|
||||
read = lex_cast<uint64_t>(item[3]);
|
||||
read_merged = lex_cast<uint64_t>(item[4]);
|
||||
read_sectors = lex_cast<uint64_t>(item[5]);
|
||||
read_time = lex_cast<milliseconds>(item[6]);
|
||||
|
||||
write = lex_cast<uint64_t>(item[7]);
|
||||
write_merged = lex_cast<uint64_t>(item[8]);
|
||||
write_sectors = lex_cast<uint64_t>(item[9]);
|
||||
write_time = lex_cast<milliseconds>(item[10]);
|
||||
|
||||
io_current = lex_cast<uint64_t>(item[11]);
|
||||
io_time = lex_cast<milliseconds>(item[12]);
|
||||
io_weighted_time = lex_cast<milliseconds>(item[13]);
|
||||
|
||||
if(items <= 14)
|
||||
return;
|
||||
|
||||
discard = lex_cast<uint64_t>(item[14]);
|
||||
discard_merged = lex_cast<uint64_t>(item[15]);
|
||||
discard_sectors = lex_cast<uint64_t>(item[16]);
|
||||
discard_time = lex_cast<milliseconds>(item[17]);
|
||||
|
||||
if(items <= 18)
|
||||
return;
|
||||
|
||||
flush = lex_cast<uint64_t>(item[18]);
|
||||
flush_time = lex_cast<milliseconds>(item[19]);
|
||||
|
||||
if(items <= 20)
|
||||
return;
|
||||
}
|
||||
|
|
|
@ -39,6 +39,13 @@ ircd::net::dns::resolver::retry_max
|
|||
{ "default", 20L },
|
||||
};
|
||||
|
||||
decltype(ircd::net::dns::resolver::retry_serv_fail)
|
||||
ircd::net::dns::resolver::retry_serv_fail
|
||||
{
|
||||
{ "name", "ircd.net.dns.resolver.retry_serv_fail" },
|
||||
{ "default", true },
|
||||
};
|
||||
|
||||
decltype(ircd::net::dns::resolver::servers)
|
||||
ircd::net::dns::resolver::servers
|
||||
{
|
||||
|
@ -726,7 +733,14 @@ ircd::net::dns::resolver::handle_reply(const ipport &from,
|
|||
|
||||
// Handle ServFail as a special case here. We can try again without
|
||||
// handling this tag or propagating this error any further yet.
|
||||
if(header.rcode == 2 && tag.tries < size_t(server.size()))
|
||||
const bool serv_fail_retry
|
||||
{
|
||||
retry_serv_fail
|
||||
&& header.rcode == 2
|
||||
&& tag.tries < size_t(server.size())
|
||||
};
|
||||
|
||||
if(serv_fail_retry)
|
||||
{
|
||||
log::error
|
||||
{
|
||||
|
|
|
@ -322,10 +322,30 @@ ircd::m::signatures(const mutable_buffer &out,
|
|||
return signatures(out, event, origin);
|
||||
}
|
||||
|
||||
ircd::m::event
|
||||
ircd::m::signatures(const mutable_buffer &out,
|
||||
const m::event &event,
|
||||
const string_view &origin)
|
||||
{
|
||||
const auto &secret_key
|
||||
{
|
||||
m::secret_key(my(origin))
|
||||
};
|
||||
|
||||
const string_view public_key_id
|
||||
{
|
||||
m::public_key_id(my(origin))
|
||||
};
|
||||
|
||||
return signatures(out, event, origin, secret_key, public_key_id);
|
||||
}
|
||||
|
||||
ircd::m::event
|
||||
ircd::m::signatures(const mutable_buffer &out_,
|
||||
const m::event &event_,
|
||||
const string_view &origin)
|
||||
const string_view &origin,
|
||||
const ed25519::sk &secret_key,
|
||||
const string_view &public_key_id)
|
||||
{
|
||||
m::event event
|
||||
{
|
||||
|
@ -337,16 +357,6 @@ ircd::m::signatures(const mutable_buffer &out_,
|
|||
stringify(event::buf[2], event)
|
||||
};
|
||||
|
||||
const auto &secret_key
|
||||
{
|
||||
m::secret_key(my(origin))
|
||||
};
|
||||
|
||||
const string_view public_key_id
|
||||
{
|
||||
m::public_key_id(my(origin))
|
||||
};
|
||||
|
||||
const ed25519::sig my_sig
|
||||
{
|
||||
event::sign(preimage, secret_key)
|
||||
|
|
|
@ -1145,7 +1145,7 @@ ircd::m::push::rules::defaults{R"(
|
|||
{
|
||||
"rule_id": ".m.rule.message",
|
||||
"default": true,
|
||||
"enabled": false,
|
||||
"enabled": true,
|
||||
"conditions":
|
||||
[
|
||||
{
|
||||
|
|
|
@ -211,17 +211,37 @@ try
|
|||
if(at<"type"_>(event) == "m.room.create")
|
||||
return {true, {}};
|
||||
|
||||
if(!m::exists(event.event_id))
|
||||
return {true, {}};
|
||||
|
||||
const auto &room_id
|
||||
{
|
||||
at<"room_id"_>(event)
|
||||
};
|
||||
|
||||
const auto event_idx
|
||||
{
|
||||
m::index(std::nothrow, event.event_id)
|
||||
};
|
||||
|
||||
if(!event_idx)
|
||||
return {true, {}};
|
||||
|
||||
const auto prev_idx
|
||||
{
|
||||
m::room::state::prev(event_idx)
|
||||
};
|
||||
|
||||
const auto prev_id
|
||||
{
|
||||
m::event_id(std::nothrow, prev_idx)
|
||||
};
|
||||
|
||||
const auto state_id
|
||||
{
|
||||
prev_id?: event.event_id
|
||||
};
|
||||
|
||||
const m::room room
|
||||
{
|
||||
room_id, event.event_id
|
||||
room_id, state_id
|
||||
};
|
||||
|
||||
const auto idxs
|
||||
|
|
|
@ -13,7 +13,7 @@ namespace ircd::m::vm::fetch
|
|||
static void prev_check(const event &, vm::eval &);
|
||||
static bool prev_wait(const event &, vm::eval &);
|
||||
static std::forward_list<ctx::future<m::fetch::result>> prev_fetch(const event &, vm::eval &, const room &);
|
||||
static void prev_eval(const event &, vm::eval &, ctx::future<m::fetch::result> &);
|
||||
static void prev_eval(const event &, vm::eval &, ctx::future<m::fetch::result> &, const system_point &);
|
||||
static void prev(const event &, vm::eval &, const room &);
|
||||
static std::forward_list<ctx::future<m::fetch::result>> state_fetch(const event &, vm::eval &, const room &);
|
||||
static void state(const event &, vm::eval &, const room &);
|
||||
|
@ -22,9 +22,8 @@ namespace ircd::m::vm::fetch
|
|||
static void auth(const event &, vm::eval &, const room &);
|
||||
static void handle(const event &, vm::eval &);
|
||||
|
||||
extern conf::item<milliseconds> prev_fetch_check_interval;
|
||||
extern conf::item<milliseconds> prev_preempt_time;
|
||||
extern conf::item<milliseconds> prev_wait_time;
|
||||
extern conf::item<size_t> prev_wait_count;
|
||||
extern conf::item<size_t> prev_backfill_limit;
|
||||
extern conf::item<seconds> event_timeout;
|
||||
extern conf::item<seconds> state_timeout;
|
||||
|
@ -36,6 +35,23 @@ namespace ircd::m::vm::fetch
|
|||
extern log::log log;
|
||||
}
|
||||
|
||||
namespace ircd::m::vm::fetch::stats
|
||||
{
|
||||
using ircd::stats::item;
|
||||
|
||||
extern item<uint64_t> prev_noempts;
|
||||
extern item<uint64_t> prev_preempts;
|
||||
extern item<uint64_t> prev_evals;
|
||||
extern item<uint64_t> prev_fetched;
|
||||
extern item<uint64_t> prev_fetches;
|
||||
extern item<uint64_t> auth_evals;
|
||||
extern item<uint64_t> auth_fetched;
|
||||
extern item<uint64_t> auth_fetches;
|
||||
extern item<uint64_t> state_evals;
|
||||
extern item<uint64_t> state_fetched;
|
||||
extern item<uint64_t> state_fetches;
|
||||
}
|
||||
|
||||
decltype(ircd::m::vm::fetch::log)
|
||||
ircd::m::vm::fetch::log
|
||||
{
|
||||
|
@ -104,25 +120,84 @@ ircd::m::vm::fetch::prev_backfill_limit
|
|||
{ "default", 128L },
|
||||
};
|
||||
|
||||
decltype(ircd::m::vm::fetch::prev_wait_count)
|
||||
ircd::m::vm::fetch::prev_wait_count
|
||||
{
|
||||
{ "name", "ircd.m.vm.fetch.prev.wait.count" },
|
||||
{ "default", 4L },
|
||||
};
|
||||
|
||||
decltype(ircd::m::vm::fetch::prev_wait_time)
|
||||
ircd::m::vm::fetch::prev_wait_time
|
||||
{
|
||||
{ "name", "ircd.m.vm.fetch.prev.wait.time" },
|
||||
{ "default", 200L },
|
||||
{ "default", 750L },
|
||||
};
|
||||
|
||||
decltype(ircd::m::vm::fetch::prev_fetch_check_interval)
|
||||
ircd::m::vm::fetch::prev_fetch_check_interval
|
||||
decltype(ircd::m::vm::fetch::prev_preempt_time)
|
||||
ircd::m::vm::fetch::prev_preempt_time
|
||||
{
|
||||
{ "name", "ircd.m.vm.fetch.prev.fetch.check_interval" },
|
||||
{ "default", 500L },
|
||||
{ "name", "ircd.m.vm.fetch.prev.preempt.time" },
|
||||
{ "default", 5000L },
|
||||
};
|
||||
|
||||
decltype(ircd::m::vm::fetch::stats::state_fetches)
|
||||
ircd::m::vm::fetch::stats::state_fetches
|
||||
{
|
||||
{ "name", "ircd.m.vm.fetch.state.fetches" },
|
||||
};
|
||||
|
||||
decltype(ircd::m::vm::fetch::stats::state_fetched)
|
||||
ircd::m::vm::fetch::stats::state_fetched
|
||||
{
|
||||
{ "name", "ircd.m.vm.fetch.state.fetched" },
|
||||
};
|
||||
|
||||
decltype(ircd::m::vm::fetch::stats::state_evals)
|
||||
ircd::m::vm::fetch::stats::state_evals
|
||||
{
|
||||
{ "name", "ircd.m.vm.fetch.state.evals" },
|
||||
};
|
||||
|
||||
decltype(ircd::m::vm::fetch::stats::auth_fetches)
|
||||
ircd::m::vm::fetch::stats::auth_fetches
|
||||
{
|
||||
{ "name", "ircd.m.vm.fetch.auth.fetches" },
|
||||
};
|
||||
|
||||
decltype(ircd::m::vm::fetch::stats::auth_fetched)
|
||||
ircd::m::vm::fetch::stats::auth_fetched
|
||||
{
|
||||
{ "name", "ircd.m.vm.fetch.auth.fetched" },
|
||||
};
|
||||
|
||||
decltype(ircd::m::vm::fetch::stats::auth_evals)
|
||||
ircd::m::vm::fetch::stats::auth_evals
|
||||
{
|
||||
{ "name", "ircd.m.vm.fetch.auth.evals" },
|
||||
};
|
||||
|
||||
decltype(ircd::m::vm::fetch::stats::prev_fetches)
|
||||
ircd::m::vm::fetch::stats::prev_fetches
|
||||
{
|
||||
{ "name", "ircd.m.vm.fetch.prev.fetches" },
|
||||
};
|
||||
|
||||
decltype(ircd::m::vm::fetch::stats::prev_fetched)
|
||||
ircd::m::vm::fetch::stats::prev_fetched
|
||||
{
|
||||
{ "name", "ircd.m.vm.fetch.prev.fetched" },
|
||||
};
|
||||
|
||||
decltype(ircd::m::vm::fetch::stats::prev_evals)
|
||||
ircd::m::vm::fetch::stats::prev_evals
|
||||
{
|
||||
{ "name", "ircd.m.vm.fetch.prev.evals" },
|
||||
};
|
||||
|
||||
decltype(ircd::m::vm::fetch::stats::prev_preempts)
|
||||
ircd::m::vm::fetch::stats::prev_preempts
|
||||
{
|
||||
{ "name", "ircd.m.vm.fetch.prev.preempts" },
|
||||
};
|
||||
|
||||
decltype(ircd::m::vm::fetch::stats::prev_noempts)
|
||||
ircd::m::vm::fetch::stats::prev_noempts
|
||||
{
|
||||
{ "name", "ircd.m.vm.fetch.prev.noempts" },
|
||||
};
|
||||
|
||||
//
|
||||
|
@ -303,11 +378,13 @@ try
|
|||
};
|
||||
|
||||
// recv
|
||||
stats::auth_fetches++;
|
||||
const auto result
|
||||
{
|
||||
future.get(seconds(auth_timeout))
|
||||
};
|
||||
|
||||
stats::auth_fetched++;
|
||||
const json::object response
|
||||
{
|
||||
result
|
||||
|
@ -320,6 +397,7 @@ try
|
|||
};
|
||||
|
||||
auth_chain_eval(event, eval, room, auth_chain, result.origin);
|
||||
stats::auth_evals++;
|
||||
}
|
||||
catch(const vm::error &e)
|
||||
{
|
||||
|
@ -435,6 +513,7 @@ try
|
|||
return;
|
||||
}
|
||||
|
||||
stats::state_fetches++;
|
||||
log::dwarning
|
||||
{
|
||||
log, "%s fetching possible missing state in %s",
|
||||
|
@ -454,6 +533,7 @@ try
|
|||
};
|
||||
|
||||
//TODO: XXX
|
||||
stats::state_fetched++;
|
||||
log::info
|
||||
{
|
||||
log, "%s evaluated missing state in %s fetched:-- good:-- fail:--",
|
||||
|
@ -504,21 +584,32 @@ ircd::m::vm::fetch::prev(const event &event,
|
|||
|
||||
// Attempt to wait for missing prev_events without issuing fetches here.
|
||||
if(prev_wait(event, eval))
|
||||
{
|
||||
stats::prev_noempts += prev_count;
|
||||
return;
|
||||
}
|
||||
|
||||
if(!m::vm::fetch::enable)
|
||||
{
|
||||
// No fetches will take place; only check if satisfied.
|
||||
prev_check(event, eval);
|
||||
return;
|
||||
}
|
||||
|
||||
auto futures
|
||||
// Launch fetches for missing prev events
|
||||
auto fetching
|
||||
{
|
||||
prev_fetch(event, eval, room)
|
||||
};
|
||||
|
||||
const auto fetching_count
|
||||
{
|
||||
std::distance(begin(fetching), end(fetching))
|
||||
};
|
||||
|
||||
// At this point one or more prev_events are missing; the fetches were
|
||||
// launched asynchronously if the options allowed for it.
|
||||
stats::prev_fetches += fetching_count;
|
||||
log::dwarning
|
||||
{
|
||||
log, "%s depth:%ld prev_events:%zu miss:%zu fetching:%zu fetching ...",
|
||||
|
@ -526,43 +617,63 @@ ircd::m::vm::fetch::prev(const event &event,
|
|||
at<"depth"_>(event),
|
||||
prev_count,
|
||||
prev_count - prev_exists,
|
||||
std::distance(begin(futures), end(futures)),
|
||||
};
|
||||
|
||||
auto fetching
|
||||
{
|
||||
ctx::when_all(begin(futures), end(futures))
|
||||
};
|
||||
|
||||
const auto timeout
|
||||
{
|
||||
now<system_point>() + seconds(event_timeout)
|
||||
};
|
||||
|
||||
const milliseconds &check_interval
|
||||
{
|
||||
prev_fetch_check_interval
|
||||
fetching_count,
|
||||
};
|
||||
|
||||
// Rather than waiting for all of the events to arrive or for the entire
|
||||
// timeout to expire, we check if the sought events made it to the server
|
||||
// in the meantime. If so we can drop these requests and bail.
|
||||
//TODO: Ideally should be replaced with listener/notification/hook on the
|
||||
//TODO: events arriving rather than this coarse sleep cycles.
|
||||
while(now<system_point>() < timeout)
|
||||
{
|
||||
// Wait for an interval to give this loop some iterations.
|
||||
if(fetching.wait(check_interval, std::nothrow))
|
||||
break;
|
||||
// in the meantime. If so we can drop these fetches and bail.
|
||||
std::optional<vm::notify::future> evaling[prev_count];
|
||||
for(size_t i(0); i < prev_count; ++i)
|
||||
evaling[i].emplace(prev.prev_event(i));
|
||||
|
||||
// Check for satisfaction.
|
||||
if(prev.prev_events_exist() == prev_count)
|
||||
return;
|
||||
// Either all of the fetches are done and we can start evaluating or all
|
||||
// of the events arrived elsehow and we don't need any of the fetches.
|
||||
// XXX: Ideally this could be refactored with mix-and-match granularity
|
||||
// but at this time it's unknown if there's practical benefit.
|
||||
ctx::future<> when[]
|
||||
{
|
||||
ctx::when_all(begin(fetching), end(fetching)),
|
||||
ctx::when_all(evaling, evaling + prev_count, []
|
||||
(auto &optional) -> ctx::future<> &
|
||||
{
|
||||
return optional->value();
|
||||
}),
|
||||
};
|
||||
|
||||
// Represents one of the two outcomes.
|
||||
auto future
|
||||
{
|
||||
ctx::when_any(begin(when), end(when))
|
||||
};
|
||||
|
||||
const auto prev_wait_until
|
||||
{
|
||||
now<system_point>() + milliseconds(prev_preempt_time)
|
||||
};
|
||||
|
||||
// Wait for one of the two outcomes.
|
||||
const bool finished
|
||||
{
|
||||
future.wait_until(prev_wait_until, std::nothrow)
|
||||
};
|
||||
|
||||
// Check for satisfaction.
|
||||
if(prev.prev_events_exist() == prev_count)
|
||||
{
|
||||
stats::prev_preempts += prev_count;
|
||||
assert(finished);
|
||||
return;
|
||||
}
|
||||
|
||||
// evaluate results
|
||||
for(auto &future : futures)
|
||||
prev_eval(event, eval, future);
|
||||
const auto event_wait_until
|
||||
{
|
||||
now<system_point>() + seconds(event_timeout)
|
||||
};
|
||||
|
||||
// If we're not satisfied we commit to evaluating the fetches.
|
||||
for(auto &fetch : fetching)
|
||||
prev_eval(event, eval, fetch, event_wait_until);
|
||||
|
||||
// check if result evals have satisfied this eval now; or throw
|
||||
prev_check(event, eval);
|
||||
|
@ -571,14 +682,16 @@ ircd::m::vm::fetch::prev(const event &event,
|
|||
void
|
||||
ircd::m::vm::fetch::prev_eval(const event &event,
|
||||
vm::eval &eval,
|
||||
ctx::future<m::fetch::result> &future)
|
||||
ctx::future<m::fetch::result> &future,
|
||||
const system_point &until)
|
||||
try
|
||||
{
|
||||
m::fetch::result result
|
||||
{
|
||||
future.get()
|
||||
future.get_until(until)
|
||||
};
|
||||
|
||||
stats::prev_fetched++;
|
||||
const json::object content
|
||||
{
|
||||
result
|
||||
|
@ -605,6 +718,8 @@ try
|
|||
{
|
||||
pdus, opts
|
||||
};
|
||||
|
||||
stats::prev_evals++;
|
||||
}
|
||||
catch(const ctx::interrupted &)
|
||||
{
|
||||
|
|
|
@ -267,6 +267,17 @@ ircd::m::vm::inject(eval &eval,
|
|||
}
|
||||
};
|
||||
|
||||
const json::iov::defaults membership_
|
||||
{
|
||||
event, event.at("type") == "m.room.member",
|
||||
{
|
||||
"membership", [&contents]()
|
||||
{
|
||||
return contents.at("membership");
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
const bool add_auth_events
|
||||
{
|
||||
!is_room_create
|
||||
|
|
|
@ -42,12 +42,7 @@ ircd::m::vm::notify::wait(const vector_view<const event::id> &event_id,
|
|||
const milliseconds to)
|
||||
{
|
||||
using iterator_type = unique_iterator<map_type>;
|
||||
using node_type = std::pair<map_type::node_type, value_type>;
|
||||
|
||||
static const size_t max_ids
|
||||
{
|
||||
64
|
||||
};
|
||||
static const size_t max_ids {64};
|
||||
|
||||
assume(event_id.size() <= max_ids);
|
||||
const auto event_ids
|
||||
|
@ -60,14 +55,15 @@ ircd::m::vm::notify::wait(const vector_view<const event::id> &event_id,
|
|||
m::exists(event_id)
|
||||
};
|
||||
|
||||
size_t exists(0);
|
||||
node_type node[max_ids];
|
||||
iterator_type it[event_ids];
|
||||
ctx::future<> future[event_ids];
|
||||
ctx::promise<> promise[event_ids];
|
||||
for(size_t i(0); i < event_ids; ++i)
|
||||
{
|
||||
if(exists_mask & (1UL << i))
|
||||
{
|
||||
exists++;
|
||||
future[i] = ctx::future<>{ctx::already};
|
||||
continue;
|
||||
}
|
||||
|
||||
|
@ -85,22 +81,75 @@ ircd::m::vm::notify::wait(const vector_view<const event::id> &event_id,
|
|||
|
||||
it[i] =
|
||||
{
|
||||
map, map.emplace(event_id[i], ctx::current)
|
||||
map, map.emplace(event_id[i], promise + i)
|
||||
};
|
||||
|
||||
assert(it[i]->second);
|
||||
future[i] = ctx::future<>
|
||||
{
|
||||
*it[i]->second
|
||||
};
|
||||
}
|
||||
|
||||
bool timeout(false);
|
||||
const auto tp(now<system_point>() + to);
|
||||
while(exists < event_ids && !timeout)
|
||||
auto all
|
||||
{
|
||||
timeout = ctx::wait_until(tp, std::nothrow);
|
||||
exists = m::exists_count(event_id);
|
||||
}
|
||||
ctx::when_all(future, future + event_ids)
|
||||
};
|
||||
|
||||
const bool ok
|
||||
{
|
||||
all.wait_until(now<system_point>() + to, std::nothrow)
|
||||
};
|
||||
|
||||
const size_t exists
|
||||
{
|
||||
!ok?
|
||||
m::exists_count(event_id):
|
||||
event_ids
|
||||
};
|
||||
|
||||
assert(exists <= event_ids);
|
||||
return exists;
|
||||
}
|
||||
|
||||
//
|
||||
// future::future
|
||||
//
|
||||
|
||||
ircd::m::vm::notify::future::future(const event::id &event_id)
|
||||
:ctx::future<>{ctx::already}
|
||||
{
|
||||
if(m::exists(event_id))
|
||||
return;
|
||||
|
||||
const auto &s
|
||||
{
|
||||
map.get_allocator().s
|
||||
};
|
||||
|
||||
assert(s);
|
||||
assert(!s->next);
|
||||
const scope_restore next
|
||||
{
|
||||
s->next, reinterpret_cast<notify::value_type *>(&node)
|
||||
};
|
||||
|
||||
it =
|
||||
{
|
||||
map, map.emplace(event_id, &promise)
|
||||
};
|
||||
|
||||
assert(it->second);
|
||||
static_cast<ctx::future<> &>(*this) = ctx::future<>
|
||||
{
|
||||
*it->second
|
||||
};
|
||||
}
|
||||
|
||||
//
|
||||
// internal
|
||||
//
|
||||
|
||||
void
|
||||
ircd::m::vm::notify::hook_handle(const m::event &event,
|
||||
vm::eval &)
|
||||
|
@ -112,11 +161,13 @@ ircd::m::vm::notify::hook_handle(const m::event &event,
|
|||
|
||||
for(; pit.first != pit.second; ++pit.first)
|
||||
{
|
||||
const auto &[event_id, ctx] {*pit.first};
|
||||
const auto &[event_id, promise] {*pit.first};
|
||||
|
||||
assert(promise);
|
||||
assert(promise->valid());
|
||||
assert(event_id == event.event_id);
|
||||
assert(ctx != nullptr);
|
||||
|
||||
ctx::notify(*ctx);
|
||||
if(likely(*promise))
|
||||
promise->set_value();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -37,29 +37,21 @@ method_get
|
|||
}
|
||||
};
|
||||
|
||||
mods::import<void (const m::id::user &)>
|
||||
validate_user_id
|
||||
{
|
||||
"client_register", "validate_user_id"
|
||||
};
|
||||
|
||||
mods::import<ircd::conf::item<bool>>
|
||||
register_enable
|
||||
{
|
||||
"client_register", "register_enable"
|
||||
};
|
||||
|
||||
mods::import<ircd::conf::item<bool>>
|
||||
register_user_enable
|
||||
{
|
||||
"client_register", "register_user_enable"
|
||||
};
|
||||
|
||||
m::resource::response
|
||||
get__register_available(client &client,
|
||||
const m::resource::request &request)
|
||||
{
|
||||
if(!bool(register_enable) || !bool(register_user_enable))
|
||||
const bool register_enable
|
||||
{
|
||||
conf::as("ircd.client.register.enable", false)
|
||||
};
|
||||
|
||||
const bool register_user_enable
|
||||
{
|
||||
conf::as("ircd.client.register.user.enable", false)
|
||||
};
|
||||
|
||||
if(!register_enable || !register_user_enable)
|
||||
throw m::error
|
||||
{
|
||||
http::FORBIDDEN, "M_REGISTRATION_DISABLED",
|
||||
|
@ -74,7 +66,7 @@ get__register_available(client &client,
|
|||
};
|
||||
|
||||
// Performs additional custom checks on the user_id else throws.
|
||||
validate_user_id(user_id);
|
||||
m::user::registar::validate_user_id(user_id);
|
||||
|
||||
// We indicate availability of a valid mxid in the cacheable 200 OK
|
||||
return resource::response
|
||||
|
|
|
@ -1057,7 +1057,7 @@ console_cmd__fs__dev(opt &out, const string_view &line)
|
|||
<< std::setw(24) << std::left << "SCHED" << ' '
|
||||
<< std::endl;
|
||||
|
||||
fs::dev::for_each(type, [&out]
|
||||
fs::dev::blk::for_each(type, [&out]
|
||||
(const ulong &id, const fs::dev::blk &dev)
|
||||
{
|
||||
const auto mm(fs::dev::id(id));
|
||||
|
@ -1082,12 +1082,83 @@ console_cmd__fs__dev(opt &out, const string_view &line)
|
|||
<< std::setw(16) << std::left << dev.vendor << ' '
|
||||
<< std::setw(24) << std::left << dev.scheduler << ' '
|
||||
<< std::endl;
|
||||
return true;
|
||||
});
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
console_cmd__fs__dev__stats(opt &out, const string_view &line)
|
||||
{
|
||||
const params param{line, " ",
|
||||
{
|
||||
"name"
|
||||
}};
|
||||
|
||||
const string_view name
|
||||
{
|
||||
param["name"]
|
||||
};
|
||||
|
||||
out
|
||||
<< std::setw(3) << std::right << "maj" << ':'
|
||||
<< std::setw(3) << std::left << "min" << ' '
|
||||
<< std::setw(18) << std::left << "name" << ' '
|
||||
<< std::setw(6) << std::right << "io cur" << ' '
|
||||
<< std::setw(12) << std::right << "io time" << ' '
|
||||
<< std::setw(12) << std::right << "io weighted" << ' '
|
||||
<< std::setw(12) << std::right << "reads" << ' '
|
||||
<< std::setw(12) << std::right << "read sect" << ' '
|
||||
<< std::setw(12) << std::right << "read merge" << ' '
|
||||
<< std::setw(12) << std::right << "read time" << ' '
|
||||
<< std::setw(12) << std::right << "writes" << ' '
|
||||
<< std::setw(12) << std::right << "write sect" << ' '
|
||||
<< std::setw(12) << std::right << "write merge" << ' '
|
||||
<< std::setw(12) << std::right << "write time" << ' '
|
||||
<< std::setw(12) << std::right << "discards" << ' '
|
||||
<< std::setw(12) << std::right << "discard sect" << ' '
|
||||
<< std::setw(12) << std::right << "discard merg" << ' '
|
||||
<< std::setw(12) << std::right << "discard time" << ' '
|
||||
<< std::setw(12) << std::right << "flushes" << ' '
|
||||
<< std::setw(12) << std::right << "flush time" << ' '
|
||||
<< std::endl;
|
||||
|
||||
fs::dev::stats::for_each([&out, &name]
|
||||
(const auto &stats)
|
||||
{
|
||||
if(name && !startswith(stats.name, name))
|
||||
return true;
|
||||
|
||||
char tmbuf[8][32];
|
||||
out
|
||||
<< std::setw(3) << std::right << stats.id.first << ':'
|
||||
<< std::setw(3) << std::left << stats.id.second << ' '
|
||||
<< std::setw(18) << std::left << stats.name << ' '
|
||||
<< std::setw(6) << std::right << stats.io_current << ' '
|
||||
<< std::setw(12) << std::right << pretty(tmbuf[0], stats.io_time, 1) << ' '
|
||||
<< std::setw(12) << std::right << pretty(tmbuf[1], stats.io_weighted_time, 1) << ' '
|
||||
<< std::setw(12) << std::right << stats.read << ' '
|
||||
<< std::setw(12) << std::right << stats.read_merged << ' '
|
||||
<< std::setw(12) << std::right << stats.read_sectors << ' '
|
||||
<< std::setw(12) << std::right << pretty(tmbuf[2], stats.read_time, 1) << ' '
|
||||
<< std::setw(12) << std::right << stats.write << ' '
|
||||
<< std::setw(12) << std::right << stats.write_merged << ' '
|
||||
<< std::setw(12) << std::right << stats.write_sectors << ' '
|
||||
<< std::setw(12) << std::right << pretty(tmbuf[3], stats.write_time, 1) << ' '
|
||||
<< std::setw(12) << std::right << stats.discard << ' '
|
||||
<< std::setw(12) << std::right << stats.discard_merged << ' '
|
||||
<< std::setw(12) << std::right << stats.discard_sectors << ' '
|
||||
<< std::setw(12) << std::right << pretty(tmbuf[4], stats.discard_time, 1) << ' '
|
||||
<< std::setw(12) << std::right << stats.flush << ' '
|
||||
<< std::setw(12) << std::right << pretty(tmbuf[5], stats.flush_time, 1) << ' '
|
||||
<< '\n';
|
||||
return !name;
|
||||
});
|
||||
|
||||
out << std::endl;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
console_cmd__ls(opt &out, const string_view &line)
|
||||
{
|
||||
|
@ -5343,7 +5414,7 @@ try
|
|||
{
|
||||
const params param{line, " ",
|
||||
{
|
||||
"dbname", "column"
|
||||
"dbname", "column|file"
|
||||
}};
|
||||
|
||||
const auto &dbname
|
||||
|
@ -5353,7 +5424,14 @@ try
|
|||
|
||||
const auto &colname
|
||||
{
|
||||
param["column"]
|
||||
param["column|file"]
|
||||
};
|
||||
|
||||
const auto &fname
|
||||
{
|
||||
!startswith(colname, '/')?
|
||||
string_view{}:
|
||||
lstrip(colname, '/')
|
||||
};
|
||||
|
||||
auto &database
|
||||
|
@ -5361,6 +5439,15 @@ try
|
|||
db::database::get(dbname)
|
||||
};
|
||||
|
||||
if(fname)
|
||||
{
|
||||
check(database, fname);
|
||||
out << "Check of file " << fname << " in " << dbname << " completed without error."
|
||||
<< std::endl;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
if(colname)
|
||||
{
|
||||
db::column column
|
||||
|
@ -16616,6 +16703,108 @@ console_cmd__fed__auth(opt &out, const string_view &line)
|
|||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
console_cmd__fed__auth__space(opt &out, const string_view &line)
|
||||
{
|
||||
const params param{line, " ",
|
||||
{
|
||||
"room_id", "type", "state_key", "remote", "depth", "limit"
|
||||
}};
|
||||
|
||||
const auto &room_id
|
||||
{
|
||||
m::room_id(param.at("room_id"))
|
||||
};
|
||||
|
||||
const string_view &type
|
||||
{
|
||||
param["type"] != "*"?
|
||||
param["type"] : string_view{},
|
||||
};
|
||||
|
||||
const string_view &state_key
|
||||
{
|
||||
param["state_key"] != "\"\""?
|
||||
param["state_key"] : string_view{},
|
||||
};
|
||||
|
||||
const string_view remote
|
||||
{
|
||||
param.at("remote")
|
||||
};
|
||||
|
||||
const int64_t depth
|
||||
{
|
||||
param.at("depth", -1L)
|
||||
};
|
||||
|
||||
const uint64_t limit
|
||||
{
|
||||
param.at("limit", -1UL)
|
||||
};
|
||||
|
||||
const m::room::state state
|
||||
{
|
||||
room_id
|
||||
};
|
||||
|
||||
const m::room::state::space space
|
||||
{
|
||||
room_id
|
||||
};
|
||||
|
||||
const unique_buffer<mutable_buffer> buf
|
||||
{
|
||||
16_KiB
|
||||
};
|
||||
|
||||
const server::request::opts sopts
|
||||
{
|
||||
.http_exceptions = false,
|
||||
};
|
||||
|
||||
size_t i(0);
|
||||
space.for_each(type, state_key, depth, [&]
|
||||
(const auto &type, const auto &state_key, const auto &depth, const auto &event_idx)
|
||||
{
|
||||
const m::event::fetch event
|
||||
{
|
||||
std::nothrow, event_idx
|
||||
};
|
||||
|
||||
if(!event.valid)
|
||||
return true;
|
||||
|
||||
m::fed::event_auth::opts opts;
|
||||
opts.remote = remote;
|
||||
opts.sopts = &sopts;
|
||||
m::fed::event_auth request
|
||||
{
|
||||
room_id, event.event_id, buf, std::move(opts)
|
||||
};
|
||||
|
||||
request.wait(out.timeout);
|
||||
const auto code
|
||||
{
|
||||
request.get()
|
||||
};
|
||||
|
||||
const char report
|
||||
{
|
||||
code == 200? '+':
|
||||
code == 404? '-':
|
||||
code == 403? 'X':
|
||||
'?'
|
||||
};
|
||||
|
||||
out << report << ' ';
|
||||
m::pretty_stateline(out, event, event_idx);
|
||||
return ++i < limit;
|
||||
});
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
console_cmd__fed__query_auth(opt &out, const string_view &line)
|
||||
{
|
||||
|
|
|
@ -26,6 +26,20 @@ server_resource
|
|||
}
|
||||
};
|
||||
|
||||
conf::item<std::string>
|
||||
occlusion_blacklist
|
||||
{
|
||||
{ "name", "ircd.key.occlude.blacklist" },
|
||||
{ "default", "" },
|
||||
};
|
||||
|
||||
conf::item<std::string>
|
||||
occlusion_whitelist
|
||||
{
|
||||
{ "name", "ircd.key.occlude.whitelist" },
|
||||
{ "default", "" },
|
||||
};
|
||||
|
||||
m::resource::response
|
||||
handle_get(client &client,
|
||||
const m::resource::request &request)
|
||||
|
@ -36,6 +50,38 @@ handle_get(client &client,
|
|||
url::decode(key_id_buf, request.params)
|
||||
};
|
||||
|
||||
const blackwhite::list acl
|
||||
{
|
||||
' ', occlusion_blacklist, occlusion_whitelist
|
||||
};
|
||||
|
||||
char remote_buf[256];
|
||||
const auto ip_str
|
||||
{
|
||||
occlusion_blacklist || occlusion_whitelist?
|
||||
host(string(remote_buf, remote(client))):
|
||||
string_view{}
|
||||
};
|
||||
|
||||
const bool allow
|
||||
{
|
||||
acl(ip_str)
|
||||
};
|
||||
|
||||
log::debug
|
||||
{
|
||||
m::log, "%s requested key %s (%s)",
|
||||
loghead(client),
|
||||
key_id?: "*"_sv,
|
||||
allow? "ALLOWED": "DENIED",
|
||||
};
|
||||
|
||||
if(!allow)
|
||||
return m::resource::response
|
||||
{
|
||||
client, http::FORBIDDEN
|
||||
};
|
||||
|
||||
m::keys::get(my_host(), key_id, [&client]
|
||||
(const json::object &keys)
|
||||
{
|
||||
|
|
|
@ -196,6 +196,7 @@ ircd::m::push::execute(const event &event,
|
|||
const event::idx &rule_idx)
|
||||
try
|
||||
{
|
||||
assert(json::get<"enabled"_>(rule));
|
||||
const auto &[scope, kind, ruleid]
|
||||
{
|
||||
path
|
||||
|
|
Loading…
Reference in New Issue