0
0
Fork 0
mirror of https://github.com/matrix-construct/construct synced 2024-06-30 07:48:22 +02:00

ircd: Support read-only and write-avoid modes via conf item / command line.

This commit is contained in:
Jason Volk 2019-04-15 11:08:40 -07:00
parent 726f131cc2
commit f9025cebb9
8 changed files with 57 additions and 11 deletions

View file

@ -34,6 +34,8 @@ bool nodirect;
bool noaio; bool noaio;
bool no6; bool no6;
bool norun; bool norun;
bool read_only;
bool write_avoid;
const char *execute; const char *execute;
lgetopt opts[] = lgetopt opts[] =
{ {
@ -52,6 +54,8 @@ lgetopt opts[] =
{ "noaio", &noaio, lgetopt::BOOL, "Disable the AIO interface in favor of traditional syscalls. " }, { "noaio", &noaio, lgetopt::BOOL, "Disable the AIO interface in favor of traditional syscalls. " },
{ "no6", &no6, lgetopt::BOOL, "Disable IPv6 operations" }, { "no6", &no6, lgetopt::BOOL, "Disable IPv6 operations" },
{ "norun", &norun, lgetopt::BOOL, "[debug & testing only] Initialize but never run the event loop." }, { "norun", &norun, lgetopt::BOOL, "[debug & testing only] Initialize but never run the event loop." },
{ "ro", &read_only, lgetopt::BOOL, "Read-only mode. No writes to database allowed." },
{ "wa", &write_avoid, lgetopt::BOOL, "Like read-only mode, but writes permitted if triggered." },
{ nullptr, nullptr, lgetopt::STRING, nullptr }, { nullptr, nullptr, lgetopt::STRING, nullptr },
}; };
@ -257,6 +261,13 @@ enable_coredumps()
void void
applyargs() applyargs()
{ {
if(read_only)
ircd::read_only.set("true");
// read_only implies write_avoid.
if(write_avoid || read_only)
ircd::write_avoid.set("true");
if(debugmode) if(debugmode)
ircd::debugmode.set("true"); ircd::debugmode.set("true");
else else

View file

@ -74,4 +74,6 @@ namespace ircd
extern conf::item<bool> restart; extern conf::item<bool> restart;
extern conf::item<bool> debugmode; extern conf::item<bool> debugmode;
extern conf::item<bool> read_only;
extern conf::item<bool> write_avoid;
} }

View file

@ -183,7 +183,12 @@ try
fs::path(fs::DB) fs::path(fs::DB)
}; };
if(fs::mkdir(dbdir)) if(!fs::is_dir(dbdir) && (ircd::read_only || ircd::write_avoid))
log::warning
{
log, "Not creating database directory `%s' in read-only/write-avoid mode.", dbdir
};
else if(fs::mkdir(dbdir))
log::notice log::notice
{ {
log, "Created new database directory at `%s'", dbdir log, "Created new database directory at `%s'", dbdir
@ -964,7 +969,7 @@ try
} }
,read_only ,read_only
{ {
false ircd::read_only
} }
,env ,env
{ {
@ -1213,7 +1218,7 @@ try
// If the directory does not exist, though rocksdb will create it, we can // If the directory does not exist, though rocksdb will create it, we can
// avoid scaring the user with an error log message if we just do that.. // avoid scaring the user with an error log message if we just do that..
if(opts->create_if_missing && !fs::is_dir(path)) if(opts->create_if_missing && !fs::is_dir(path) && !ircd::write_avoid)
fs::mkdir(path); fs::mkdir(path);
// Announce attempt before usual point where exceptions are thrown // Announce attempt before usual point where exceptions are thrown
@ -1225,6 +1230,14 @@ try
columns.size() columns.size()
}; };
if(read_only)
log::warning
{
log, "Database \"%s\" @ `%s' will be opened in read-only mode.",
this->name,
path,
};
// Open DB into ptr // Open DB into ptr
rocksdb::DB *ptr; rocksdb::DB *ptr;
if(read_only) if(read_only)
@ -7285,14 +7298,14 @@ ircd::db::make_dbopts(std::string optstr,
// RocksDB doesn't parse a read_only option, so we allow that to be added // RocksDB doesn't parse a read_only option, so we allow that to be added
// to open the database as read_only and then remove that from the string. // to open the database as read_only and then remove that from the string.
if(read_only) if(read_only)
*read_only = optstr_find_and_remove(optstr, "read_only=true;"s); *read_only |= optstr_find_and_remove(optstr, "read_only=true;"s);
else else
optstr_find_and_remove(optstr, "read_only=true;"s); optstr_find_and_remove(optstr, "read_only=true;"s);
// We also allow the user to specify fsck=true to run a repair operation on // We also allow the user to specify fsck=true to run a repair operation on
// the db. This may be expensive to do by default every startup. // the db. This may be expensive to do by default every startup.
if(fsck) if(fsck)
*fsck = optstr_find_and_remove(optstr, "fsck=true;"s); *fsck |= optstr_find_and_remove(optstr, "fsck=true;"s);
else else
optstr_find_and_remove(optstr, "fsck=true;"s); optstr_find_and_remove(optstr, "fsck=true;"s);

View file

@ -17,6 +17,22 @@ namespace ircd
void main() noexcept; void main() noexcept;
} }
decltype(ircd::write_avoid)
ircd::write_avoid
{
{ "name", "ircd.write_avoid" },
{ "default", false },
{ "persist", false },
};
decltype(ircd::read_only)
ircd::read_only
{
{ "name", "ircd.read_only" },
{ "default", false },
{ "persist", false },
};
decltype(ircd::debugmode) decltype(ircd::debugmode)
ircd::debugmode ircd::debugmode
{ {

View file

@ -109,6 +109,9 @@ ircd::log::init()
if(!ircd::debugmode) if(!ircd::debugmode)
console_disable(level::DEBUG); console_disable(level::DEBUG);
if(ircd::write_avoid)
return;
mkdir(); mkdir();
} }

View file

@ -48,7 +48,8 @@ try
std::make_unique<modules>() std::make_unique<modules>()
} }
{ {
presence::set(me, "online", me_online_status_msg); if(!ircd::write_avoid)
presence::set(me, "online", me_online_status_msg);
if(room::state::disable_history) if(room::state::disable_history)
log::warning log::warning
@ -83,7 +84,7 @@ noexcept try
{ {
m::sync::pool.join(); m::sync::pool.join();
if(!std::current_exception()) if(!std::uncaught_exceptions() && !ircd::write_avoid)
presence::set(me, "offline", me_offline_status_msg); presence::set(me, "offline", me_offline_status_msg);
} }
catch(const m::error &e) catch(const m::error &e)

View file

@ -121,7 +121,7 @@ try
reinterpret_cast<char *>(key.get()), SK_SZ reinterpret_cast<char *>(key.get()), SK_SZ
}; };
if(!fs::exists(filename)) if(!fs::exists(filename) && !ircd::write_avoid)
{ {
throw_on_error throw_on_error
{ {

View file

@ -90,7 +90,7 @@ init_my_tls_crt()
fs::path_string(certificate_path_parts) fs::path_string(certificate_path_parts)
}; };
if(!fs::exists(private_key_file)) if(!fs::exists(private_key_file) && !ircd::write_avoid)
{ {
log::warning log::warning
{ {
@ -121,7 +121,7 @@ init_my_tls_crt()
*/ */
const json::object config{}; const json::object config{};
if(!fs::exists(cert_file)) if(!fs::exists(cert_file) && !ircd::write_avoid)
{ {
const json::object &certificate const json::object &certificate
{ {
@ -248,7 +248,7 @@ init_my_ed25519()
}) })
}; };
if(fs::exists(sk_file)) if(fs::exists(sk_file) || ircd::write_avoid)
log::info log::info
{ {
m::log, "Using ed25519 secret key @ `%s'", sk_file m::log, "Using ed25519 secret key @ `%s'", sk_file