From 94a6cd0d908fd2c7677a8fb5789fc0ecf8b4640c Mon Sep 17 00:00:00 2001 From: Jason Volk Date: Sat, 2 Jul 2022 11:37:49 -0700 Subject: [PATCH] ircd::db: Simplify options wrappings; eliminate bitflags. --- include/ircd/db/domain.h | 2 - include/ircd/db/opts.h | 180 ++++++++++----------------------- include/ircd/m/dbs/dbs.h | 2 +- ircd/db.cc | 59 +++++------ matrix/events.cc | 34 +++---- matrix/homeserver_bootstrap.cc | 2 +- matrix/room_head.cc | 7 +- matrix/room_stats.cc | 2 +- modules/console.cc | 4 +- 9 files changed, 107 insertions(+), 185 deletions(-) diff --git a/include/ircd/db/domain.h b/include/ircd/db/domain.h index 8c15aaa47..898dabeea 100644 --- a/include/ircd/db/domain.h +++ b/include/ircd/db/domain.h @@ -46,8 +46,6 @@ struct ircd::db::domain using iterator_type = const_iterator; using const_iterator_type = const_iterator; - static const gopts applied_opts; - const_iterator end(const string_view &key, gopts = {}); const_iterator begin(const string_view &key, gopts = {}); const_reverse_iterator rend(const string_view &key, gopts = {}); diff --git a/include/ircd/db/opts.h b/include/ircd/db/opts.h index 4560cf7f8..702211fbe 100644 --- a/include/ircd/db/opts.h +++ b/include/ircd/db/opts.h @@ -13,82 +13,72 @@ namespace ircd::db { - enum class set :uint64_t; - enum class get :uint64_t; - - struct options; - template struct opts; struct sopts; struct gopts; - - template bool test(const opts &, const typename std::underlying_type::type &); - template bool test(const opts &, const T &value); - - template opts &operator|=(opts &, const opts &); - template opts &operator|=(opts &, const T &value); - - template opts &operator&=(opts &, const opts &); - template opts &operator&=(opts &, const T &value); + struct options; } -enum class ircd::db::set -:uint64_t -{ - FSYNC = 0x0001, ///< Uses kernel filesystem synchronization after write (slow). - NO_JOURNAL = 0x0002, ///< Write Ahead Log (WAL) for some crash recovery (danger). - NO_BLOCKING = 0x0004, ///< Fail if write would block. - NO_COLUMN_ERR = 0x0008, ///< No exception thrown when writing to a deleted column. - PRIO_LOW = 0x0010, ///< Mark for low priority behavior. - PRIO_HIGH = 0x0020, ///< Mark for high priority behavior. -}; - -enum class ircd::db::get -:uint64_t -{ - PIN = 0x0001, ///< Keep iter data in memory for iter lifetime (good for lots ++/--). - PREFIX = 0x0002, ///< (prefix_same_as_start); automatic for index columns with pfx. - ORDERED = 0x0004, ///< (total_order_seek); relevant to index columns. - CACHE = 0x0008, ///< Update the cache. - NO_CACHE = 0x0010, ///< Do not update the cache. - CHECKSUM = 0x0020, ///< Integrity of data will be checked (overrides conf). - NO_CHECKSUM = 0x0040, ///< Integrity of data will not be checked (overrides conf). - NO_BLOCKING = 0x0080, ///< Fail if read would block from not being cached. - NO_SNAPSHOT = 0x0100, ///< This iterator will have the latest data (tailing). - NO_PARALLEL = 0x0200, ///< Don't submit requests in parallel (relevant to db::row). - THROW = 0x0400, ///< Throw exceptions more than usual. - NO_THROW = 0x0800, ///< Suppress exceptions if possible. -}; - -template -struct ircd::db::opts -{ - using flag_t = typename std::underlying_type::type; - - flag_t value {0}; - - opts() = default; - opts(const std::initializer_list &list) - :value{combine_flags(list)} - {} -}; - -/// options for writing (set) +/// Options for setting (writes) struct ircd::db::sopts -:opts { - using opts::opts; + /// Uses kernel filesystem synchronization after this write (slow). + bool fsync {false}; + + /// Write Ahead Log (WAL) for some crash recovery. + bool journal {true}; + + /// Set to false to fail if write would block. + bool blocking {true}; + + /// Mark for low priority behavior. + bool prio_low {false}; + + /// Mark for high priority behavior. + bool prio_high {false}; }; -/// options for reading (get) +/// Options for getting (reads) struct ircd::db::gopts -:opts { - database::snapshot snapshot; - const rocksdb::Slice *lower_bound { nullptr }; - const rocksdb::Slice *upper_bound { nullptr }; - size_t readahead { 0 }; + /// Keep iter data in memory for iter lifetime (good for lots ++/--). + bool pin {false}; - using opts::opts; + /// Fill the cache with results. + bool cache {true}; + + /// Allow query to continue after cache miss. + bool blocking {true}; + + /// Submit requests in parallel (relevant to db::row). + bool parallel {true}; + + /// (prefix_same_as_start); automatic for index columns with pfx. + bool prefix {false}; + + /// (total_order_seek); relevant to index columns. + bool ordered {false}; + + /// Ensures no snapshot is used; this iterator will have the latest data. + bool tailing {false}; + + /// 1 = Throw exceptions more than usual. + /// 0 = Throw exceptions less than usual. + int8_t throwing {-1}; + + /// 1 = Integrity of data will be checked (overrides conf). + /// 0 = Checksums will not be checked (overrides conf). + int8_t checksum {-1}; + + /// Readahead bytes. + size_t readahead {0}; + + /// Bounding keys + const rocksdb::Slice + *lower_bound {nullptr}, + *upper_bound {nullptr}; + + /// Attached snapshot + database::snapshot snapshot; }; /// options <-> string @@ -134,63 +124,3 @@ struct ircd::db::options::map :std::unordered_map{std::move(m)} {} }; - -template -inline ircd::db::opts & -ircd::db::operator&=(opts &a, - const T &value) -{ - using flag_t = typename opts::flag_t; - - a.value &= flag_t(value); - return a; -} - -template -inline ircd::db::opts & -ircd::db::operator&=(opts &a, - const opts &b) -{ - a.value &= b.value; - return a; -} - -template -inline ircd::db::opts & -ircd::db::operator|=(opts &a, - const T &value) -{ - using flag_t = typename opts::flag_t; - - a.value |= flag_t(value); - return a; -} - -template -inline ircd::db::opts & -ircd::db::operator|=(opts &a, - const opts &b) -{ - a.value |= b.value; - return a; -} - -template -inline bool -ircd::db::test(const opts &a, - const T &value) -{ - using flag_t = typename opts::flag_t; - - return a.value & flag_t(value); -} - -template -inline bool -ircd::db::test(const opts &a, - const typename std::underlying_type::type &value) -{ - using flag_t = typename opts::flag_t; - - return a.value & flag_t(value); -} diff --git a/include/ircd/m/dbs/dbs.h b/include/ircd/m/dbs/dbs.h index c2118a7ce..ef466d65e 100644 --- a/include/ircd/m/dbs/dbs.h +++ b/include/ircd/m/dbs/dbs.h @@ -72,7 +72,7 @@ struct ircd::m::dbs::write_opts db::op op {db::op::SET}; /// Lower-level write options passed to the transaction's execution. - db::sopts sopts {(db::set)0}; + db::sopts sopts; /// Principal's index number. Most codepaths do not permit zero. This may /// be zero for blacklisting, but the blacklist option must be set. diff --git a/ircd/db.cc b/ircd/db.cc index aadadeb61..00ad34e30 100644 --- a/ircd/db.cc +++ b/ircd/db.cc @@ -614,7 +614,7 @@ ircd::db::prefetcher::operator()(column &c, // control queue growth, so we insert voluntary yield here to allow // prefetch operations to at least be processed before returning to // the user submitting more prefetches. - if(likely(!test(opts, db::get::NO_BLOCKING))) + if(likely(opts.blocking)) ctx::yield(); return true; @@ -1725,15 +1725,15 @@ ircd::db::seek(row &r, { // If there's a pending error from another cell by the time this // closure is executed we don't perform the seek() unless the user - // specifies db::get::NO_THROW to suppress it. - if(!eptr || test(opts, get::NO_THROW)) try + // specifies db::gopts::throwing=0 to suppress it. + if(!eptr || opts.throwing == false) try { if(!seek(cell, key)) { // If the cell is not_found that's not a thrown exception here; - // the cell will just be !valid(). The user can specify - // get::THROW to propagate a not_found from the seek(row); - if(test(opts, get::THROW)) + // the cell will just be !valid(). The user can option + // throwing=1 to propagate a not_found from the seek(row). + if(opts.throwing == true) throw not_found { "column '%s' key '%s'", cell.col(), key @@ -1787,7 +1787,7 @@ ircd::db::seek(row &r, const bool submit { r.size() > 1 && - !test(opts, get::NO_PARALLEL) && + opts.parallel && !db::cached(column, key, opts) }; @@ -1824,7 +1824,7 @@ ircd::db::seek(row &r, }; } - if(eptr && !test(opts, get::NO_THROW)) + if(eptr && opts.throwing != false) std::rethrow_exception(eptr); return ret; @@ -2346,12 +2346,6 @@ const // db/domain.h // -const ircd::db::gopts -ircd::db::domain::applied_opts -{ - get::PREFIX -}; - bool ircd::db::seek(domain::const_iterator_base &it, const pos &p) @@ -2373,7 +2367,7 @@ ircd::db::seek(domain::const_iterator_base &it, break; } - it.opts |= domain::applied_opts; + it.opts.prefix = true; return seek(static_cast(it), p); } @@ -2381,7 +2375,7 @@ bool ircd::db::seek(domain::const_iterator_base &it, const string_view &p) { - it.opts |= domain::applied_opts; + it.opts.prefix = true; return seek(static_cast(it), p); } @@ -5277,29 +5271,26 @@ ircd::db::make_opts(const gopts &opts) ret.iterate_lower_bound = opts.lower_bound; ret.iterate_upper_bound = opts.upper_bound; - ret.verify_checksums = bool(read_checksum); - if(test(opts, get::CHECKSUM) && !test(opts, get::NO_CHECKSUM)) - ret.verify_checksums = true; + ret.verify_checksums = opts.checksum <= -1? + bool(read_checksum): + opts.checksum; - if(test(opts, get::NO_SNAPSHOT)) + if(opts.tailing) ret.tailing = true; - if(test(opts, get::ORDERED)) + if(opts.ordered) ret.total_order_seek = true; - if(test(opts, get::PIN)) + if(opts.pin) ret.pin_data = true; - if(test(opts, get::CACHE)) + if(opts.cache) ret.fill_cache = true; - if(likely(test(opts, get::NO_CACHE))) - ret.fill_cache = false; - - if(likely(test(opts, get::PREFIX))) + if(opts.prefix) ret.prefix_same_as_start = true; - if(likely(test(opts, get::NO_BLOCKING))) + if(!opts.blocking) ret.read_tier = rocksdb::ReadTier::kBlockCacheTier; return ret; @@ -5318,13 +5309,11 @@ rocksdb::WriteOptions ircd::db::make_opts(const sopts &opts) { rocksdb::WriteOptions ret; - //ret.no_slowdown = true; // read_tier = NON_BLOCKING for writes - - ret.sync = test(opts, set::FSYNC); - ret.disableWAL = !enable_wal || test(opts, set::NO_JOURNAL); - ret.ignore_missing_column_families = test(opts, set::NO_COLUMN_ERR); - ret.no_slowdown = test(opts, set::NO_BLOCKING); - ret.low_pri = test(opts, set::PRIO_LOW); + ret.sync = opts.fsync; + ret.disableWAL = !enable_wal || !opts.journal; + ret.ignore_missing_column_families = true; + ret.no_slowdown = !opts.blocking; + ret.low_pri = opts.prio_low; return ret; } diff --git a/matrix/events.cc b/matrix/events.cc index 912531274..4554b1876 100644 --- a/matrix/events.cc +++ b/matrix/events.cc @@ -89,7 +89,8 @@ ircd::m::events::dump__file(const string_view &filename) { static const db::gopts gopts { - db::get::NO_CACHE, db::get::NO_CHECKSUM + .cache = false, + .checksum = false, }; const fs::fd::opts fileopts @@ -313,13 +314,12 @@ ircd::m::events::source::for_each(const range &range, range.second }; - db::gopts gopts + const db::gopts gopts { - db::get::NO_CACHE, - db::get::NO_CHECKSUM + .cache = false, + .checksum = false, + .readahead = size_t(readahead) & boolmask(ascending), }; - gopts.readahead = size_t(readahead); - gopts.readahead &= boolmask(ascending); auto it { @@ -375,18 +375,18 @@ ircd::m::events::content::for_each(const closure &closure) json::indexof() }; + const db::gopts gopts + { + .cache = false, + .checksum = false, + .readahead = size_t(readahead), + }; + db::column &column { dbs::event_column.at(content_idx) }; - db::gopts gopts - { - db::get::NO_CACHE, - db::get::NO_CHECKSUM - }; - gopts.readahead = size_t(readahead); - auto it(column.begin(gopts)); for(; it; ++it) { @@ -432,12 +432,12 @@ ircd::m::events::refs::for_each(const range &range, dbs::event_refs }; - db::gopts gopts + const db::gopts gopts { - db::get::NO_CACHE, - db::get::NO_CHECKSUM + .cache = false, + .checksum = false, + .readahead = size_t(readahead), }; - gopts.readahead = size_t(readahead); const auto start { diff --git a/matrix/homeserver_bootstrap.cc b/matrix/homeserver_bootstrap.cc index 041da2cd3..849d3936d 100644 --- a/matrix/homeserver_bootstrap.cc +++ b/matrix/homeserver_bootstrap.cc @@ -251,7 +251,7 @@ try //vmopts.phase.set(vm::phase::PREINDEX, true); // Optimize the bootstrap by disabling WAL journaling. - vmopts.wopts.sopts |= db::set::NO_JOURNAL; + vmopts.wopts.sopts.journal = false; // Optimize the bootstrap by not updating room heads at every step. vmopts.wopts.appendix.set(dbs::appendix::ROOM_HEAD, false); diff --git a/matrix/room_head.cc b/matrix/room_head.cc index 543ca2e08..ee00567de 100644 --- a/matrix/room_head.cc +++ b/matrix/room_head.cc @@ -346,12 +346,15 @@ ircd::m::room::head::reset(const head &head) size_t ircd::m::room::head::rebuild(const head &head) { - size_t ret{0}; static const m::event::fetch::opts fopts { - { db::get::NO_CACHE } + db::gopts + { + .cache = false, + }, }; + size_t ret{0}; m::room::events it { head.room, 0UL, &fopts diff --git a/matrix/room_stats.cc b/matrix/room_stats.cc index 31dcb2eab..65e1382f7 100644 --- a/matrix/room_stats.cc +++ b/matrix/room_stats.cc @@ -46,7 +46,7 @@ ircd::m::room::stats::bytes_json(const m::room &room) static const db::gopts gopts { - db::get::NO_CACHE + .cache = false, }; ret += db::bytes_value(m::dbs::event_json, key, gopts); diff --git a/modules/console.cc b/modules/console.cc index ae11bec21..b8ed52456 100644 --- a/modules/console.cc +++ b/modules/console.cc @@ -10143,8 +10143,10 @@ console_cmd__room__members__read(opt &out, const string_view &line) { "event_id", "content", "origin_server_ts", "sender" }, + + db::gopts { - db::get::NO_CACHE + .cache = false, }, };