mirror of
https://github.com/matrix-construct/construct
synced 2024-09-28 03:38:53 +02:00
ircd: Improve runlevel changed callback related.
This commit is contained in:
parent
8ad264f72d
commit
91c9737f29
4 changed files with 59 additions and 26 deletions
|
@ -123,9 +123,10 @@ try
|
|||
// is now shared between those handlers and libircd. This means the run()
|
||||
// won't return even if we call ircd::quit(). We use the callback to then
|
||||
// cancel the handlers so run() can return and the program can exit.
|
||||
ircd::runlevel_changed = [](const enum ircd::runlevel &mode)
|
||||
const ircd::runlevel_changed handler{[]
|
||||
(const auto &runlevel)
|
||||
{
|
||||
switch(mode)
|
||||
switch(runlevel)
|
||||
{
|
||||
case ircd::runlevel::HALT:
|
||||
case ircd::runlevel::FAULT:
|
||||
|
@ -135,7 +136,7 @@ try
|
|||
default:
|
||||
break;
|
||||
}
|
||||
};
|
||||
}};
|
||||
|
||||
// If the user wants to immediately drop to a command line without having to
|
||||
// send a ctrl-c for it, that is provided here.
|
||||
|
|
|
@ -23,15 +23,35 @@
|
|||
namespace ircd
|
||||
{
|
||||
struct init;
|
||||
|
||||
extern runlevel_handler runlevel_changed;
|
||||
struct runlevel_changed;
|
||||
|
||||
string_view reflect(const enum runlevel &);
|
||||
void init(boost::asio::io_context &ios, const std::string &conf, runlevel_handler = {});
|
||||
void init(boost::asio::io_context &ios, runlevel_handler = {});
|
||||
void init(boost::asio::io_context &ios, const std::string &conf);
|
||||
void init(boost::asio::io_context &ios);
|
||||
bool quit() noexcept;
|
||||
}
|
||||
|
||||
/// An instance of this class registers itself to be called back when
|
||||
/// the ircd::runlevel has changed.
|
||||
///
|
||||
/// Note: Its destructor will access a list in libircd; after a callback
|
||||
/// for a HALT do not unload libircd.so until destructing this object.
|
||||
///
|
||||
/// A static ctx::dock is also available for contexts to wait for a runlevel
|
||||
/// change notification.
|
||||
///
|
||||
struct ircd::runlevel_changed
|
||||
:instance_list<ircd::runlevel_changed>
|
||||
,std::function<void (const enum runlevel &)>
|
||||
{
|
||||
using handler = std::function<void (const enum runlevel &)>;
|
||||
|
||||
static ctx::dock dock;
|
||||
|
||||
runlevel_changed(handler function);
|
||||
~runlevel_changed() noexcept;
|
||||
};
|
||||
|
||||
/// The runlevel allows all observers to know the coarse state of IRCd and to
|
||||
/// react accordingly. This can be used by the embedder of libircd to know
|
||||
/// when it's safe to use or delete libircd resources. It is also used
|
||||
|
|
|
@ -179,7 +179,6 @@ namespace ircd
|
|||
namespace ircd
|
||||
{
|
||||
enum class runlevel :int;
|
||||
using runlevel_handler = std::function<void (const enum runlevel &)>;
|
||||
|
||||
constexpr size_t BUFSIZE { 512 };
|
||||
extern const enum runlevel &runlevel;
|
||||
|
|
49
ircd/ircd.cc
49
ircd/ircd.cc
|
@ -13,9 +13,8 @@
|
|||
|
||||
namespace ircd
|
||||
{
|
||||
enum runlevel _runlevel; // Current libircd runlevel
|
||||
enum runlevel _runlevel {runlevel::HALT}; // Current libircd runlevel
|
||||
const enum runlevel &runlevel{_runlevel}; // Observer for current RL
|
||||
runlevel_handler runlevel_changed; // user's callback
|
||||
|
||||
boost::asio::io_context *ios; // user's io service
|
||||
struct strand *strand; // libircd event serializer
|
||||
|
@ -43,10 +42,9 @@ ircd::thread_id
|
|||
{};
|
||||
|
||||
void
|
||||
ircd::init(boost::asio::io_context &ios,
|
||||
runlevel_handler function)
|
||||
ircd::init(boost::asio::io_context &ios)
|
||||
{
|
||||
init(ios, std::string{}, std::move(function));
|
||||
init(ios, std::string{});
|
||||
}
|
||||
|
||||
/// Sets up the IRCd and its main context, then returns without blocking.
|
||||
|
@ -60,8 +58,7 @@ ircd::init(boost::asio::io_context &ios,
|
|||
/// init() can only be called from a runlevel::HALT state
|
||||
void
|
||||
ircd::init(boost::asio::io_context &ios,
|
||||
const std::string &configfile,
|
||||
runlevel_handler runlevel_changed)
|
||||
const std::string &configfile)
|
||||
try
|
||||
{
|
||||
if(runlevel != runlevel::HALT)
|
||||
|
@ -82,9 +79,6 @@ try
|
|||
ircd::ios = &ios;
|
||||
ircd::strand = new struct strand(ios);
|
||||
|
||||
// Saves the user's runlevel_changed callback which we invoke.
|
||||
ircd::runlevel_changed = std::move(runlevel_changed);
|
||||
|
||||
// The log is available. but it is console-only until conf opens files.
|
||||
log::init();
|
||||
log::mark("READY");
|
||||
|
@ -266,6 +260,23 @@ noexcept
|
|||
});
|
||||
}
|
||||
|
||||
template<>
|
||||
decltype(ircd::runlevel_changed::list)
|
||||
ircd::util::instance_list<ircd::runlevel_changed>::list
|
||||
{};
|
||||
|
||||
decltype(ircd::runlevel_changed::dock)
|
||||
ircd::runlevel_changed::dock
|
||||
{};
|
||||
|
||||
ircd::runlevel_changed::runlevel_changed(handler function)
|
||||
:handler{std::move(function)}
|
||||
{}
|
||||
|
||||
ircd::runlevel_changed::~runlevel_changed()
|
||||
noexcept
|
||||
{}
|
||||
|
||||
/// Sets the runlevel of IRCd and notifies users. This should never be called
|
||||
/// manually/directly, as it doesn't trigger a runlevel change itself, it just
|
||||
/// notifies of one.
|
||||
|
@ -280,18 +291,20 @@ try
|
|||
{
|
||||
log::debug
|
||||
{
|
||||
"IRCd runlevel transition from '%s' to '%s'%s",
|
||||
"IRCd runlevel transition from '%s' to '%s' (notifying %zu)",
|
||||
reflect(ircd::runlevel),
|
||||
reflect(new_runlevel),
|
||||
ircd::runlevel_changed? " (notifying user)" : ""
|
||||
runlevel_changed::list.size()
|
||||
};
|
||||
|
||||
ircd::_runlevel = new_runlevel;
|
||||
ircd::runlevel_changed::dock.notify_all();
|
||||
|
||||
// This function will notify the user of the change to IRCd. The
|
||||
// notification is posted to the io_context ensuring THERE IS NO
|
||||
// CONTINUATION ON THIS STACK by the user.
|
||||
if(ircd::runlevel_changed)
|
||||
if(!ircd::runlevel_changed::list.empty())
|
||||
{
|
||||
ios->post([new_runlevel]
|
||||
{
|
||||
if(new_runlevel == runlevel::HALT)
|
||||
|
@ -301,18 +314,18 @@ try
|
|||
};
|
||||
|
||||
ircd::log::fini();
|
||||
ircd::runlevel_changed(new_runlevel);
|
||||
for(const auto &handler : ircd::runlevel_changed::list)
|
||||
(*handler)(new_runlevel);
|
||||
});
|
||||
}
|
||||
|
||||
if(!ircd::runlevel_changed || new_runlevel != runlevel::HALT)
|
||||
{
|
||||
if(new_runlevel != runlevel::HALT)
|
||||
log::notice
|
||||
{
|
||||
"IRCd %s", reflect(new_runlevel)
|
||||
};
|
||||
|
||||
ircd::log::flush();
|
||||
}
|
||||
ircd::log::flush();
|
||||
}
|
||||
catch(const std::exception &e)
|
||||
{
|
||||
|
|
Loading…
Reference in a new issue