From 4ecb2d0d5fd6e014ce90c571471727a0ae564158 Mon Sep 17 00:00:00 2001 From: Jason Volk Date: Tue, 15 Sep 2020 18:01:40 -0700 Subject: [PATCH] ircd: Add distinct maintenance mode; chain write-avoid/read-only and net listen modes. --- construct/construct.cc | 8 ++-- include/ircd/ircd.h | 6 ++- ircd/ircd.cc | 95 ++++++++++++++++++++++++++++++----------- ircd/logger.cc | 2 +- matrix/homeserver.cc | 12 +++--- matrix/init_backfill.cc | 10 ----- 6 files changed, 85 insertions(+), 48 deletions(-) diff --git a/construct/construct.cc b/construct/construct.cc index ed5be04b8..5a113b93f 100644 --- a/construct/construct.cc +++ b/construct/construct.cc @@ -472,13 +472,15 @@ enable_coredumps() void applyargs() { - if(single) + if(single && !bootstrap) { - nolisten = true; - write_avoid = true; + ircd::write_avoid.set("true"); cmdline = true; } + if(bootstrap) + ircd::maintenance.set("true"); + if(defaults) ircd::defaults.set("true"); diff --git a/include/ircd/ircd.h b/include/ircd/ircd.h index c67d654ff..bed3a6b23 100644 --- a/include/ircd/ircd.h +++ b/include/ircd/ircd.h @@ -111,11 +111,13 @@ namespace ircd extern const info::versions version_api; extern const info::versions version_abi; + // Operating Mode Selectors extern conf::item restart; extern conf::item debugmode; - extern conf::item read_only; - extern conf::item write_avoid; + extern conf::item maintenance; extern conf::item soft_assert; + extern conf::item write_avoid; // implies maintenance + extern conf::item read_only; // implies write_avoid extern conf::item defaults; // Informational diff --git a/ircd/ircd.cc b/ircd/ircd.cc index 4936ecfff..b26776e67 100644 --- a/ircd/ircd.cc +++ b/ircd/ircd.cc @@ -41,6 +41,33 @@ ircd::version_abi "IRCd", info::versions::ABI, 0, {0, 0, 0}, ircd::info::version }; +/// Courtesy indicator; this item allows the library to indicate to the +/// embedder that they should restart their application (or reload this library +/// if available). The use-case here is for features like the `restart` command +/// in the console module. Such a command triggers a normal quit and the +/// application may exit normally; therefor the embedder should check this +/// item to perform a restart rather than exiting. +decltype(ircd::restart) +ircd::restart +{ + { "name", "ircd.restart" }, + { "default", false }, + { "persist", false }, +}; + +/// Coarse mode indicator for debug/developer behavior when and if possible. +/// For example: additional log messages may be enabled by this mode. This +/// option is technically effective in both release builds and debug builds +/// but it controls far less in non-debug builds. This item may be toggled +/// at any time. It doesn't change operational functionality. +decltype(ircd::debugmode) +ircd::debugmode +{ + { "name", "ircd.debugmode" }, + { "default", false }, + { "persist", false }, +}; + /// When assertions are enabled this further softens runtime behavior to be /// non-disruptive/non-terminating for diagnostic purposes. Debugging/developer /// use only. This item may be toggled at any time. @@ -52,6 +79,26 @@ ircd::soft_assert { "persist", false }, }; +/// Coarse mode declaration for "maintenance mode" a.k.a. "single user mode" +/// which is intended to be similar to normal operating mode but without +/// services to clients or some background tasks. It is implied and set when +/// write_avoid=true which is itself implied and set by read_only. +decltype(ircd::maintenance) +ircd::maintenance +{ + { + { "name", "ircd.maintenance" }, + { "default", false }, + { "persist", false }, + }, [] + { + if(!maintenance) + return; + + net::listen.set("false"); + } +}; + /// Coarse mode indicator for degraded operation known as "write-avoid" which /// is similar to read_only but not hard-enforced. Writes may still occur, /// such as those manually triggered by an admin. All subsystems and background @@ -59,9 +106,18 @@ ircd::soft_assert decltype(ircd::write_avoid) ircd::write_avoid { - { "name", "ircd.write_avoid" }, - { "default", false }, - { "persist", false }, + { + { "name", "ircd.write_avoid" }, + { "default", false }, + { "persist", false }, + }, [] + { + if(!write_avoid) + return; + + maintenance.set("true"); + db::auto_compact.set("false"); + } }; /// Coarse mode declaration for read-only behavior. All subsystems and feature @@ -71,30 +127,17 @@ ircd::write_avoid decltype(ircd::read_only) ircd::read_only { - { "name", "ircd.read_only" }, - { "default", false }, - { "persist", false }, -}; + { + { "name", "ircd.read_only" }, + { "default", false }, + { "persist", false }, + }, [] + { + if(!read_only) + return; -/// Coarse mode indicator for debug/developer behavior when and if possible. -/// For example: additional log messages may be enabled by this mode. This -/// option is technically effective in both release builds and debug builds -/// but it controls far less in non-debug builds. This item may be toggled -/// at any time. -decltype(ircd::debugmode) -ircd::debugmode -{ - { "name", "ircd.debugmode" }, - { "default", false }, - { "persist", false }, -}; - -decltype(ircd::restart) -ircd::restart -{ - { "name", "ircd.restart" }, - { "default", false }, - { "persist", false }, + write_avoid.set("true"); + } }; /// Main context pointer placement. diff --git a/ircd/logger.cc b/ircd/logger.cc index 2d81d4bec..e95376958 100644 --- a/ircd/logger.cc +++ b/ircd/logger.cc @@ -136,7 +136,7 @@ ircd::log::init() console_disable(level::DWARNING); } - if(!ircd::write_avoid || ircd::debugmode) + if(!ircd::write_avoid) { mkdir(); open(); diff --git a/matrix/homeserver.cc b/matrix/homeserver.cc index d97a1c5f5..3c139d03b 100644 --- a/matrix/homeserver.cc +++ b/matrix/homeserver.cc @@ -261,7 +261,6 @@ try const bool need_bootstrap { (sequence(*dbs::events) == 0 || opts->bootstrap_vector_path) - && !ircd::write_avoid && dbs::events }; @@ -271,13 +270,14 @@ try mods::imports.emplace("net_dns_cache"s, "net_dns_cache"s); if(!ircd::write_avoid) - { if(key && !key->verify_keys.empty()) m::keys::cache::set(key->verify_keys); + if(!ircd::maintenance) signon(*this); + + if(!ircd::maintenance) m::init::backfill::init(); - } } catch(const std::exception &e) { @@ -304,7 +304,7 @@ noexcept try server::init::wait(); m::sync::pool.join(); - if(!ircd::write_avoid && _vm) + if(!ircd::maintenance && _vm) signoff(*this); ///TODO: XXX primary @@ -826,7 +826,7 @@ ircd::m::offline_status_msg void ircd::m::signon(homeserver &homeserver) { - if(!ircd::write_avoid && vm::sequence::retired != 0) + if(vm::sequence::retired != 0) presence::set(homeserver.self, "online", online_status_msg); } @@ -834,7 +834,7 @@ void ircd::m::signoff(homeserver &homeserver) noexcept try { - if(!std::uncaught_exceptions() && !ircd::write_avoid && vm::sequence::retired != 0) + if(!std::uncaught_exceptions() && vm::sequence::retired != 0) presence::set(homeserver.self, "offline", offline_status_msg); } catch(const std::exception &e) diff --git a/matrix/init_backfill.cc b/matrix/init_backfill.cc index b64020f43..506b585de 100644 --- a/matrix/init_backfill.cc +++ b/matrix/init_backfill.cc @@ -114,16 +114,6 @@ ircd::m::init::backfill::init() return; } - if(ircd::read_only || ircd::write_avoid) - { - log::warning - { - log, "Not performing initial backfill because write-avoid flag is set." - }; - - return; - } - assert(!worker_context); worker_context.reset(new context {