ircd::db: Simplify options wrappings; eliminate bitflags.

This commit is contained in:
Jason Volk 2022-07-02 11:37:49 -07:00
parent 4e7f5af457
commit 94a6cd0d90
9 changed files with 107 additions and 185 deletions

View File

@ -46,8 +46,6 @@ struct ircd::db::domain
using iterator_type = const_iterator; using iterator_type = const_iterator;
using const_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 end(const string_view &key, gopts = {});
const_iterator begin(const string_view &key, gopts = {}); const_iterator begin(const string_view &key, gopts = {});
const_reverse_iterator rend(const string_view &key, gopts = {}); const_reverse_iterator rend(const string_view &key, gopts = {});

View File

@ -13,82 +13,72 @@
namespace ircd::db namespace ircd::db
{ {
enum class set :uint64_t;
enum class get :uint64_t;
struct options;
template<class> struct opts;
struct sopts; struct sopts;
struct gopts; struct gopts;
struct options;
template<class T> bool test(const opts<T> &, const typename std::underlying_type<T>::type &);
template<class T> bool test(const opts<T> &, const T &value);
template<class T> opts<T> &operator|=(opts<T> &, const opts<T> &);
template<class T> opts<T> &operator|=(opts<T> &, const T &value);
template<class T> opts<T> &operator&=(opts<T> &, const opts<T> &);
template<class T> opts<T> &operator&=(opts<T> &, const T &value);
} }
enum class ircd::db::set /// Options for setting (writes)
: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<class T>
struct ircd::db::opts
{
using flag_t = typename std::underlying_type<T>::type;
flag_t value {0};
opts() = default;
opts(const std::initializer_list<T> &list)
:value{combine_flags(list)}
{}
};
/// options for writing (set)
struct ircd::db::sopts struct ircd::db::sopts
:opts<set>
{ {
using opts<set>::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 struct ircd::db::gopts
:opts<get>
{ {
database::snapshot snapshot; /// Keep iter data in memory for iter lifetime (good for lots ++/--).
const rocksdb::Slice *lower_bound { nullptr }; bool pin {false};
const rocksdb::Slice *upper_bound { nullptr };
size_t readahead { 0 };
using opts<get>::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 /// options <-> string
@ -134,63 +124,3 @@ struct ircd::db::options::map
:std::unordered_map<std::string, std::string>{std::move(m)} :std::unordered_map<std::string, std::string>{std::move(m)}
{} {}
}; };
template<class T>
inline ircd::db::opts<T> &
ircd::db::operator&=(opts<T> &a,
const T &value)
{
using flag_t = typename opts<T>::flag_t;
a.value &= flag_t(value);
return a;
}
template<class T>
inline ircd::db::opts<T> &
ircd::db::operator&=(opts<T> &a,
const opts<T> &b)
{
a.value &= b.value;
return a;
}
template<class T>
inline ircd::db::opts<T> &
ircd::db::operator|=(opts<T> &a,
const T &value)
{
using flag_t = typename opts<T>::flag_t;
a.value |= flag_t(value);
return a;
}
template<class T>
inline ircd::db::opts<T> &
ircd::db::operator|=(opts<T> &a,
const opts<T> &b)
{
a.value |= b.value;
return a;
}
template<class T>
inline bool
ircd::db::test(const opts<T> &a,
const T &value)
{
using flag_t = typename opts<T>::flag_t;
return a.value & flag_t(value);
}
template<class T>
inline bool
ircd::db::test(const opts<T> &a,
const typename std::underlying_type<T>::type &value)
{
using flag_t = typename opts<T>::flag_t;
return a.value & flag_t(value);
}

View File

@ -72,7 +72,7 @@ struct ircd::m::dbs::write_opts
db::op op {db::op::SET}; db::op op {db::op::SET};
/// Lower-level write options passed to the transaction's execution. /// 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 /// Principal's index number. Most codepaths do not permit zero. This may
/// be zero for blacklisting, but the blacklist option must be set. /// be zero for blacklisting, but the blacklist option must be set.

View File

@ -614,7 +614,7 @@ ircd::db::prefetcher::operator()(column &c,
// control queue growth, so we insert voluntary yield here to allow // control queue growth, so we insert voluntary yield here to allow
// prefetch operations to at least be processed before returning to // prefetch operations to at least be processed before returning to
// the user submitting more prefetches. // the user submitting more prefetches.
if(likely(!test(opts, db::get::NO_BLOCKING))) if(likely(opts.blocking))
ctx::yield(); ctx::yield();
return true; return true;
@ -1725,15 +1725,15 @@ ircd::db::seek(row &r,
{ {
// If there's a pending error from another cell by the time this // 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 // closure is executed we don't perform the seek() unless the user
// specifies db::get::NO_THROW to suppress it. // specifies db::gopts::throwing=0 to suppress it.
if(!eptr || test(opts, get::NO_THROW)) try if(!eptr || opts.throwing == false) try
{ {
if(!seek(cell, key)) if(!seek(cell, key))
{ {
// If the cell is not_found that's not a thrown exception here; // If the cell is not_found that's not a thrown exception here;
// the cell will just be !valid(). The user can specify // the cell will just be !valid(). The user can option
// get::THROW to propagate a not_found from the seek(row); // throwing=1 to propagate a not_found from the seek(row).
if(test(opts, get::THROW)) if(opts.throwing == true)
throw not_found throw not_found
{ {
"column '%s' key '%s'", cell.col(), key "column '%s' key '%s'", cell.col(), key
@ -1787,7 +1787,7 @@ ircd::db::seek(row &r,
const bool submit const bool submit
{ {
r.size() > 1 && r.size() > 1 &&
!test(opts, get::NO_PARALLEL) && opts.parallel &&
!db::cached(column, key, opts) !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); std::rethrow_exception(eptr);
return ret; return ret;
@ -2346,12 +2346,6 @@ const
// db/domain.h // db/domain.h
// //
const ircd::db::gopts
ircd::db::domain::applied_opts
{
get::PREFIX
};
bool bool
ircd::db::seek(domain::const_iterator_base &it, ircd::db::seek(domain::const_iterator_base &it,
const pos &p) const pos &p)
@ -2373,7 +2367,7 @@ ircd::db::seek(domain::const_iterator_base &it,
break; break;
} }
it.opts |= domain::applied_opts; it.opts.prefix = true;
return seek(static_cast<column::const_iterator_base &>(it), p); return seek(static_cast<column::const_iterator_base &>(it), p);
} }
@ -2381,7 +2375,7 @@ bool
ircd::db::seek(domain::const_iterator_base &it, ircd::db::seek(domain::const_iterator_base &it,
const string_view &p) const string_view &p)
{ {
it.opts |= domain::applied_opts; it.opts.prefix = true;
return seek(static_cast<column::const_iterator_base &>(it), p); return seek(static_cast<column::const_iterator_base &>(it), p);
} }
@ -5277,29 +5271,26 @@ ircd::db::make_opts(const gopts &opts)
ret.iterate_lower_bound = opts.lower_bound; ret.iterate_lower_bound = opts.lower_bound;
ret.iterate_upper_bound = opts.upper_bound; ret.iterate_upper_bound = opts.upper_bound;
ret.verify_checksums = bool(read_checksum); ret.verify_checksums = opts.checksum <= -1?
if(test(opts, get::CHECKSUM) && !test(opts, get::NO_CHECKSUM)) bool(read_checksum):
ret.verify_checksums = true; opts.checksum;
if(test(opts, get::NO_SNAPSHOT)) if(opts.tailing)
ret.tailing = true; ret.tailing = true;
if(test(opts, get::ORDERED)) if(opts.ordered)
ret.total_order_seek = true; ret.total_order_seek = true;
if(test(opts, get::PIN)) if(opts.pin)
ret.pin_data = true; ret.pin_data = true;
if(test(opts, get::CACHE)) if(opts.cache)
ret.fill_cache = true; ret.fill_cache = true;
if(likely(test(opts, get::NO_CACHE))) if(opts.prefix)
ret.fill_cache = false;
if(likely(test(opts, get::PREFIX)))
ret.prefix_same_as_start = true; ret.prefix_same_as_start = true;
if(likely(test(opts, get::NO_BLOCKING))) if(!opts.blocking)
ret.read_tier = rocksdb::ReadTier::kBlockCacheTier; ret.read_tier = rocksdb::ReadTier::kBlockCacheTier;
return ret; return ret;
@ -5318,13 +5309,11 @@ rocksdb::WriteOptions
ircd::db::make_opts(const sopts &opts) ircd::db::make_opts(const sopts &opts)
{ {
rocksdb::WriteOptions ret; rocksdb::WriteOptions ret;
//ret.no_slowdown = true; // read_tier = NON_BLOCKING for writes ret.sync = opts.fsync;
ret.disableWAL = !enable_wal || !opts.journal;
ret.sync = test(opts, set::FSYNC); ret.ignore_missing_column_families = true;
ret.disableWAL = !enable_wal || test(opts, set::NO_JOURNAL); ret.no_slowdown = !opts.blocking;
ret.ignore_missing_column_families = test(opts, set::NO_COLUMN_ERR); ret.low_pri = opts.prio_low;
ret.no_slowdown = test(opts, set::NO_BLOCKING);
ret.low_pri = test(opts, set::PRIO_LOW);
return ret; return ret;
} }

View File

@ -89,7 +89,8 @@ ircd::m::events::dump__file(const string_view &filename)
{ {
static const db::gopts gopts static const db::gopts gopts
{ {
db::get::NO_CACHE, db::get::NO_CHECKSUM .cache = false,
.checksum = false,
}; };
const fs::fd::opts fileopts const fs::fd::opts fileopts
@ -313,13 +314,12 @@ ircd::m::events::source::for_each(const range &range,
range.second range.second
}; };
db::gopts gopts const db::gopts gopts
{ {
db::get::NO_CACHE, .cache = false,
db::get::NO_CHECKSUM .checksum = false,
.readahead = size_t(readahead) & boolmask<size_t>(ascending),
}; };
gopts.readahead = size_t(readahead);
gopts.readahead &= boolmask<size_t>(ascending);
auto it auto it
{ {
@ -375,18 +375,18 @@ ircd::m::events::content::for_each(const closure &closure)
json::indexof<event, "content"_>() json::indexof<event, "content"_>()
}; };
const db::gopts gopts
{
.cache = false,
.checksum = false,
.readahead = size_t(readahead),
};
db::column &column db::column &column
{ {
dbs::event_column.at(content_idx) 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)); auto it(column.begin(gopts));
for(; it; ++it) for(; it; ++it)
{ {
@ -432,12 +432,12 @@ ircd::m::events::refs::for_each(const range &range,
dbs::event_refs dbs::event_refs
}; };
db::gopts gopts const db::gopts gopts
{ {
db::get::NO_CACHE, .cache = false,
db::get::NO_CHECKSUM .checksum = false,
.readahead = size_t(readahead),
}; };
gopts.readahead = size_t(readahead);
const auto start const auto start
{ {

View File

@ -251,7 +251,7 @@ try
//vmopts.phase.set(vm::phase::PREINDEX, true); //vmopts.phase.set(vm::phase::PREINDEX, true);
// Optimize the bootstrap by disabling WAL journaling. // 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. // Optimize the bootstrap by not updating room heads at every step.
vmopts.wopts.appendix.set(dbs::appendix::ROOM_HEAD, false); vmopts.wopts.appendix.set(dbs::appendix::ROOM_HEAD, false);

View File

@ -346,12 +346,15 @@ ircd::m::room::head::reset(const head &head)
size_t size_t
ircd::m::room::head::rebuild(const head &head) ircd::m::room::head::rebuild(const head &head)
{ {
size_t ret{0};
static const m::event::fetch::opts fopts static const m::event::fetch::opts fopts
{ {
{ db::get::NO_CACHE } db::gopts
{
.cache = false,
},
}; };
size_t ret{0};
m::room::events it m::room::events it
{ {
head.room, 0UL, &fopts head.room, 0UL, &fopts

View File

@ -46,7 +46,7 @@ ircd::m::room::stats::bytes_json(const m::room &room)
static const db::gopts gopts static const db::gopts gopts
{ {
db::get::NO_CACHE .cache = false,
}; };
ret += db::bytes_value(m::dbs::event_json, key, gopts); ret += db::bytes_value(m::dbs::event_json, key, gopts);

View File

@ -10143,8 +10143,10 @@ console_cmd__room__members__read(opt &out, const string_view &line)
{ {
"event_id", "content", "origin_server_ts", "sender" "event_id", "content", "origin_server_ts", "sender"
}, },
db::gopts
{ {
db::get::NO_CACHE .cache = false,
}, },
}; };