mirror of
https://github.com/matrix-construct/construct
synced 2024-11-12 13:01:07 +01:00
ircd::db: Simplify options wrappings; eliminate bitflags.
This commit is contained in:
parent
4e7f5af457
commit
94a6cd0d90
9 changed files with 107 additions and 185 deletions
|
@ -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 = {});
|
||||
|
|
|
@ -13,82 +13,72 @@
|
|||
|
||||
namespace ircd::db
|
||||
{
|
||||
enum class set :uint64_t;
|
||||
enum class get :uint64_t;
|
||||
|
||||
struct options;
|
||||
template<class> struct opts;
|
||||
struct sopts;
|
||||
struct gopts;
|
||||
|
||||
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);
|
||||
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<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)
|
||||
/// Options for setting (writes)
|
||||
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
|
||||
:opts<get>
|
||||
{
|
||||
database::snapshot snapshot;
|
||||
const rocksdb::Slice *lower_bound { nullptr };
|
||||
const rocksdb::Slice *upper_bound { nullptr };
|
||||
/// Keep iter data in memory for iter lifetime (good for lots ++/--).
|
||||
bool pin {false};
|
||||
|
||||
/// 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};
|
||||
|
||||
using opts<get>::opts;
|
||||
/// 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::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);
|
||||
}
|
||||
|
|
|
@ -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.
|
||||
|
|
59
ircd/db.cc
59
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<column::const_iterator_base &>(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<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_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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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<size_t>(ascending),
|
||||
};
|
||||
gopts.readahead = size_t(readahead);
|
||||
gopts.readahead &= boolmask<size_t>(ascending);
|
||||
|
||||
auto it
|
||||
{
|
||||
|
@ -375,18 +375,18 @@ ircd::m::events::content::for_each(const closure &closure)
|
|||
json::indexof<event, "content"_>()
|
||||
};
|
||||
|
||||
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
|
||||
{
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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,
|
||||
},
|
||||
};
|
||||
|
||||
|
|
Loading…
Reference in a new issue