Use camelCase for FDB API & Mako classes

This commit is contained in:
Junhyun Shim 2022-03-07 04:51:10 +01:00
parent bcf52e6760
commit 8c0d3e9469
7 changed files with 438 additions and 426 deletions

View File

@ -27,28 +27,28 @@ using CharsRef = std::string_view;
using KeyRef = BytesRef;
using ValueRef = BytesRef;
inline uint8_t const* to_byte_ptr(char const* ptr) noexcept {
inline uint8_t const* toBytePtr(char const* ptr) noexcept {
return reinterpret_cast<uint8_t const*>(ptr);
}
// get bytestring view from charstring: e.g. std::basic_string{_view}<char>
template <template <class...> class StringLike, class Char>
BytesRef to_bytes_ref(const StringLike<Char>& s) noexcept {
BytesRef toBytesRef(const StringLike<Char>& s) noexcept {
static_assert(sizeof(Char) == 1);
return BytesRef(reinterpret_cast<uint8_t const*>(s.data()), s.size());
}
// get charstring view from bytestring: e.g. std::basic_string{_view}<uint8_t>
template <template <class...> class StringLike, class Char>
CharsRef to_chars_ref(const StringLike<Char>& s) noexcept {
CharsRef toCharsRef(const StringLike<Char>& s) noexcept {
static_assert(sizeof(Char) == 1);
return CharsRef(reinterpret_cast<char const*>(s.data()), s.size());
}
[[maybe_unused]] constexpr const bool overflow_check = false;
[[maybe_unused]] constexpr const bool OverflowCheck = false;
inline int intsize(BytesRef b) {
if constexpr (overflow_check) {
inline int intSize(BytesRef b) {
if constexpr (OverflowCheck) {
if (b.size() > static_cast<size_t>(std::numeric_limits<int>::max()))
throw std::overflow_error("byte strlen goes beyond int bounds");
}
@ -57,49 +57,49 @@ inline int intsize(BytesRef b) {
class Error {
public:
using code_type = native::fdb_error_t;
using CodeType = native::fdb_error_t;
Error() noexcept : err(0) {}
explicit Error(code_type err) noexcept : err(err) {}
explicit Error(CodeType err) noexcept : err(err) {}
char const* what() noexcept { return native::fdb_get_error(err); }
explicit operator bool() const noexcept { return err != 0; }
bool is(code_type other) const noexcept { return err != other; }
bool is(CodeType other) const noexcept { return err != other; }
code_type code() const noexcept { return err; }
CodeType code() const noexcept { return err; }
bool retryable() const noexcept { return native::fdb_error_predicate(FDB_ERROR_PREDICATE_RETRYABLE, err) != 0; }
private:
code_type err;
CodeType err;
};
/* Traits of value types held by ready futures.
Holds type and value extraction function. */
namespace future_var {
struct None {
struct type {};
static Error extract(native::FDBFuture*, type&) noexcept { return Error(0); }
struct Type {};
static Error extract(native::FDBFuture*, Type&) noexcept { return Error(0); }
};
struct Int64 {
using type = int64_t;
static Error extract(native::FDBFuture* f, type& out) noexcept {
using Type = int64_t;
static Error extract(native::FDBFuture* f, Type& out) noexcept {
return Error(native::fdb_future_get_int64(f, &out));
}
};
struct Key {
using type = std::pair<uint8_t const*, int>;
static Error extract(native::FDBFuture* f, type& out) noexcept {
using Type = std::pair<uint8_t const*, int>;
static Error extract(native::FDBFuture* f, Type& out) noexcept {
auto& [out_key, out_key_length] = out;
return Error(native::fdb_future_get_key(f, &out_key, &out_key_length));
}
};
struct Value {
using type = std::tuple<bool, uint8_t const*, int>;
static Error extract(native::FDBFuture* f, type& out) noexcept {
using Type = std::tuple<bool, uint8_t const*, int>;
static Error extract(native::FDBFuture* f, Type& out) noexcept {
auto& [out_present, out_value, out_value_length] = out;
auto out_present_native = native::fdb_bool_t{};
auto err = native::fdb_future_get_value(f, &out_present_native, &out_value, &out_value_length);
@ -108,15 +108,15 @@ struct Value {
}
};
struct StringArray {
using type = std::pair<const char**, int>;
static Error extract(native::FDBFuture* f, type& out) noexcept {
using Type = std::pair<const char**, int>;
static Error extract(native::FDBFuture* f, Type& out) noexcept {
auto& [out_strings, out_count] = out;
return Error(native::fdb_future_get_string_array(f, &out_strings, &out_count));
}
};
struct KeyValueArray {
using type = std::tuple<native::FDBKeyValue const*, int, bool>;
static Error extract(native::FDBFuture* f, type& out) noexcept {
using Type = std::tuple<native::FDBKeyValue const*, int, bool>;
static Error extract(native::FDBFuture* f, Type& out) noexcept {
auto& [out_kv, out_count, out_more] = out;
auto out_more_native = native::fdb_bool_t{};
auto err = native::fdb_future_get_keyvalue_array(f, &out_kv, &out_count, &out_more_native);
@ -126,61 +126,61 @@ struct KeyValueArray {
};
} // namespace future_var
[[noreturn]] inline void throw_error(std::string_view preamble, Error err) {
[[noreturn]] inline void throwError(std::string_view preamble, Error err) {
auto msg = std::string(preamble);
msg.append(err.what());
throw std::runtime_error(msg);
}
inline int max_api_version() {
inline int maxApiVersion() {
return native::fdb_get_max_api_version();
}
inline Error select_api_version_nothrow(int version) {
inline Error selectApiVersionNothrow(int version) {
return Error(native::fdb_select_api_version(version));
}
inline void select_api_version(int version) {
if (auto err = select_api_version_nothrow(version)) {
throw_error(fmt::format("ERROR: fdb_select_api_version({}): ", version), err);
inline void selectApiVersion(int version) {
if (auto err = selectApiVersionNothrow(version)) {
throwError(fmt::format("ERROR: fdb_select_api_version({}): ", version), err);
}
}
namespace network {
inline Error set_option_nothrow(FDBNetworkOption option, BytesRef str) noexcept {
return Error(native::fdb_network_set_option(option, str.data(), intsize(str)));
inline Error setOptionNothrow(FDBNetworkOption option, BytesRef str) noexcept {
return Error(native::fdb_network_set_option(option, str.data(), intSize(str)));
}
inline Error set_option_nothrow(FDBNetworkOption option, int64_t value) noexcept {
inline Error setOptionNothrow(FDBNetworkOption option, int64_t value) noexcept {
return Error(native::fdb_network_set_option(
option, reinterpret_cast<const uint8_t*>(&value), static_cast<int>(sizeof(value))));
}
inline void set_option(FDBNetworkOption option, BytesRef str) {
if (auto err = set_option_nothrow(option, str)) {
throw_error(fmt::format("ERROR: fdb_network_set_option({}): ",
static_cast<std::underlying_type_t<FDBNetworkOption>>(option)),
err);
inline void setOption(FDBNetworkOption option, BytesRef str) {
if (auto err = setOptionNothrow(option, str)) {
throwError(fmt::format("ERROR: fdb_network_set_option({}): ",
static_cast<std::underlying_type_t<FDBNetworkOption>>(option)),
err);
}
}
inline void set_option(FDBNetworkOption option, int64_t value) {
if (auto err = set_option_nothrow(option, value)) {
throw_error(fmt::format("ERROR: fdb_network_set_option({}, {}): ",
static_cast<std::underlying_type_t<FDBNetworkOption>>(option),
value),
err);
inline void setOption(FDBNetworkOption option, int64_t value) {
if (auto err = setOptionNothrow(option, value)) {
throwError(fmt::format("ERROR: fdb_network_set_option({}, {}): ",
static_cast<std::underlying_type_t<FDBNetworkOption>>(option),
value),
err);
}
}
inline Error setup_nothrow() noexcept {
inline Error setupNothrow() noexcept {
return Error(native::fdb_setup_network());
}
inline void setup() {
if (auto err = setup_nothrow())
throw_error("ERROR: fdb_network_setup(): ", err);
if (auto err = setupNothrow())
throwError("ERROR: fdb_network_setup(): ", err);
}
inline Error run() {
@ -193,11 +193,11 @@ inline Error stop() {
} // namespace network
class TX;
class Transaction;
class Database;
class Result {
friend class TX;
friend class Transaction;
std::shared_ptr<native::FDBResult> r;
Result(native::FDBResult* result) {
@ -206,9 +206,9 @@ class Result {
}
public:
using KeyValueArray = future_var::KeyValueArray::type;
using KeyValueArray = future_var::KeyValueArray::Type;
Error get_keyvalue_array_nothrow(KeyValueArray& out) const noexcept {
Error getKeyValueArrayNothrow(KeyValueArray& out) const noexcept {
auto out_more_native = native::fdb_bool_t{};
auto& [out_kv, out_count, out_more] = out;
auto err_raw = native::fdb_result_get_keyvalue_array(r.get(), &out_kv, &out_count, &out_more_native);
@ -216,17 +216,17 @@ public:
return Error(err_raw);
}
KeyValueArray get_keyvalue_array() const {
KeyValueArray getKeyValueArray() const {
auto ret = KeyValueArray{};
if (auto err = get_keyvalue_array_nothrow(ret))
throw_error("ERROR: result_get_keyvalue_array(): ", err);
if (auto err = getKeyValueArrayNothrow(ret))
throwError("ERROR: result_get_keyvalue_array(): ", err);
return ret;
}
};
class Future {
protected:
friend class TX;
friend class Transaction;
std::shared_ptr<native::FDBFuture> f;
Future(native::FDBFuture* future) {
@ -270,7 +270,7 @@ public:
return native::fdb_future_is_ready(f.get()) != 0;
}
Error block_until_ready() const noexcept {
Error blockUntilReady() const noexcept {
assert(valid());
return Error(native::fdb_future_block_until_ready(f.get()));
}
@ -283,18 +283,18 @@ public:
void cancel() noexcept { native::fdb_future_cancel(f.get()); }
template <class VarTraits>
typename VarTraits::type get() const {
typename VarTraits::Type get() const {
assert(valid());
assert(!error());
auto out = typename VarTraits::Type{};
if (auto err = VarTraits::extract(f.get(), out)) {
throw_error("future_get: ", err);
throwError("future_get: ", err);
}
return out;
}
template <class VarTraits>
Error get_nothrow(typename VarTraits::type& var) const noexcept {
Error getNothrow(typename VarTraits::Type& var) const noexcept {
assert(valid());
assert(!error());
auto out = typename VarTraits::Type{};
@ -309,95 +309,95 @@ public:
template <typename VarTraits>
class TypedFuture : public Future {
friend class TX;
using self_type = TypedFuture<VarTraits>;
friend class Transaction;
using SelfType = TypedFuture<VarTraits>;
using Future::Future;
// hide type-unsafe inherited functions
using Future::get;
using Future::get_nothrow;
using Future::getNothrow;
using Future::then;
TypedFuture(const Future& f) noexcept : Future(f) {}
public:
using contained_type = typename VarTraits::type;
using ContainedType = typename VarTraits::Type;
Future erase_type() const noexcept { return static_cast<Future const&>(*this); }
Future eraseType() const noexcept { return static_cast<Future const&>(*this); }
contained_type get() const { return get<VarTraits>(); }
ContainedType get() const { return get<VarTraits>(); }
Error get_nothrow(contained_type& out) const noexcept { return get_nothrow<VarTraits>(out); }
Error getNothrow(ContainedType& out) const noexcept { return getNothrow<VarTraits>(out); }
template <class UserFunc>
void then(UserFunc&& fn) {
Future::then<self_type>(std::forward<UserFunc>(fn));
Future::then<SelfType>(std::forward<UserFunc>(fn));
}
};
namespace key_select {
namespace KeySelect {
struct inclusive {
struct Inclusive {
static constexpr const bool value = true;
};
struct exclusive {
struct Exclusive {
static constexpr const bool value = false;
};
} // namespace key_select
} // namespace KeySelect
class TX {
class Transaction {
friend class Database;
std::shared_ptr<native::FDBTransaction> tr;
explicit TX(native::FDBTransaction* tr_raw) {
explicit Transaction(native::FDBTransaction* tr_raw) {
if (tr_raw)
tr = std::shared_ptr<native::FDBTransaction>(tr_raw, &native::fdb_transaction_destroy);
}
public:
TX() noexcept : TX(nullptr) {}
TX(const TX&) noexcept = default;
TX& operator=(const TX&) noexcept = default;
Transaction() noexcept : Transaction(nullptr) {}
Transaction(const Transaction&) noexcept = default;
Transaction& operator=(const Transaction&) noexcept = default;
bool valid() const noexcept { return tr != nullptr; }
explicit operator bool() const noexcept { return valid(); }
Error set_option_nothrow(FDBTransactionOption option, int64_t value) noexcept {
Error setOptionNothrow(FDBTransactionOption option, int64_t value) noexcept {
return Error(native::fdb_transaction_set_option(
tr.get(), option, reinterpret_cast<const uint8_t*>(&value), static_cast<int>(sizeof(value))));
}
Error set_option_nothrow(FDBTransactionOption option, BytesRef str) noexcept {
return Error(native::fdb_transaction_set_option(tr.get(), option, str.data(), intsize(str)));
Error setOptionNothrow(FDBTransactionOption option, BytesRef str) noexcept {
return Error(native::fdb_transaction_set_option(tr.get(), option, str.data(), intSize(str)));
}
void set_option(FDBTransactionOption option, int64_t value) {
if (auto err = set_option_nothrow(option, value)) {
throw_error(fmt::format("transaction_set_option({}, {}) returned error: ",
static_cast<std::underlying_type_t<FDBTransactionOption>>(option),
value),
err);
void setOption(FDBTransactionOption option, int64_t value) {
if (auto err = setOptionNothrow(option, value)) {
throwError(fmt::format("transaction_set_option({}, {}) returned error: ",
static_cast<std::underlying_type_t<FDBTransactionOption>>(option),
value),
err);
}
}
void set_option(FDBTransactionOption option, BytesRef str) {
if (auto err = set_option_nothrow(option, str)) {
throw_error(fmt::format("transaction_set_option({}) returned error: ",
static_cast<std::underlying_type_t<FDBTransactionOption>>(option)),
err);
void setOption(FDBTransactionOption option, BytesRef str) {
if (auto err = setOptionNothrow(option, str)) {
throwError(fmt::format("transaction_set_option({}) returned error: ",
static_cast<std::underlying_type_t<FDBTransactionOption>>(option)),
err);
}
}
TypedFuture<future_var::Int64> get_read_version() { return native::fdb_transaction_get_read_version(tr.get()); }
TypedFuture<future_var::Int64> getReadVersion() { return native::fdb_transaction_get_read_version(tr.get()); }
Error get_committed_version_nothrow(int64_t& out) {
Error getCommittedVersionNothrow(int64_t& out) {
return Error(native::fdb_transaction_get_committed_version(tr.get(), &out));
}
int64_t get_committed_version() {
int64_t getCommittedVersion() {
auto out = int64_t{};
if (auto err = get_committed_version_nothrow(out)) {
throw_error("get_committed_version: ", err);
if (auto err = getCommittedVersionNothrow(out)) {
throwError("get_committed_version: ", err);
}
return out;
}
@ -406,24 +406,24 @@ public:
// Func should first check that retry == false and f.error() == 0
// before attempting to extract value from f
TypedFuture<future_var::Value> get(KeyRef key, bool snapshot) {
return native::fdb_transaction_get(tr.get(), key.data(), intsize(key), snapshot);
return native::fdb_transaction_get(tr.get(), key.data(), intSize(key), snapshot);
}
// Usage: tx.get_range<key_select::inclusive, key_select::exclusive>(begin, end, ...);
// Usage: tx.get_range<KeySelect::inclusive, KeySelect::exclusive>(begin, end, ...);
// gets key-value pairs in key range [begin, end)
template <class FirstInclusive, class LastInclusive>
TypedFuture<future_var::KeyValueArray> get_range(KeyRef begin,
KeyRef end,
int limit,
int target_bytes,
FDBStreamingMode mode,
int iteration,
bool snapshot,
bool reverse) {
TypedFuture<future_var::KeyValueArray> getRange(KeyRef begin,
KeyRef end,
int limit,
int target_bytes,
FDBStreamingMode mode,
int iteration,
bool snapshot,
bool reverse) {
if constexpr (FirstInclusive::value && LastInclusive::value) {
return native::fdb_transaction_get_range(tr.get(),
FDB_KEYSEL_FIRST_GREATER_OR_EQUAL(begin.data(), intsize(begin)),
FDB_KEYSEL_LAST_LESS_OR_EQUAL(end.data(), intsize(end)),
FDB_KEYSEL_FIRST_GREATER_OR_EQUAL(begin.data(), intSize(begin)),
FDB_KEYSEL_LAST_LESS_OR_EQUAL(end.data(), intSize(end)),
limit,
target_bytes,
mode,
@ -432,8 +432,8 @@ public:
reverse);
} else if constexpr (FirstInclusive::value && !LastInclusive::value) {
return native::fdb_transaction_get_range(tr.get(),
FDB_KEYSEL_FIRST_GREATER_OR_EQUAL(begin.data(), intsize(begin)),
FDB_KEYSEL_LAST_LESS_THAN(end.data(), intsize(end)),
FDB_KEYSEL_FIRST_GREATER_OR_EQUAL(begin.data(), intSize(begin)),
FDB_KEYSEL_LAST_LESS_THAN(end.data(), intSize(end)),
limit,
target_bytes,
mode,
@ -442,8 +442,8 @@ public:
reverse);
} else if constexpr (!FirstInclusive::value && LastInclusive::value) {
return native::fdb_transaction_get_range(tr.get(),
FDB_KEYSEL_FIRST_GREATER_THAN(begin.data(), intsize(begin)),
FDB_KEYSEL_LAST_LESS_OR_EQUAL(end.data(), intsize(end)),
FDB_KEYSEL_FIRST_GREATER_THAN(begin.data(), intSize(begin)),
FDB_KEYSEL_LAST_LESS_OR_EQUAL(end.data(), intSize(end)),
limit,
target_bytes,
mode,
@ -452,8 +452,8 @@ public:
reverse);
} else {
return native::fdb_transaction_get_range(tr.get(),
FDB_KEYSEL_FIRST_GREATER_THAN(begin.data(), intsize(begin)),
FDB_KEYSEL_LAST_LESS_THAN(end.data(), intsize(end)),
FDB_KEYSEL_FIRST_GREATER_THAN(begin.data(), intSize(begin)),
FDB_KEYSEL_LAST_LESS_THAN(end.data(), intSize(end)),
limit,
target_bytes,
mode,
@ -463,29 +463,29 @@ public:
}
}
Result read_blob_granules(KeyRef begin,
KeyRef end,
int64_t begin_version,
int64_t read_version,
native::FDBReadBlobGranuleContext context) {
Result readBlobGranules(KeyRef begin,
KeyRef end,
int64_t begin_version,
int64_t read_version,
native::FDBReadBlobGranuleContext context) {
return Result(native::fdb_transaction_read_blob_granules(
tr.get(), begin.data(), intsize(begin), end.data(), intsize(end), begin_version, read_version, context));
tr.get(), begin.data(), intSize(begin), end.data(), intSize(end), begin_version, read_version, context));
}
TypedFuture<future_var::None> commit() { return native::fdb_transaction_commit(tr.get()); }
TypedFuture<future_var::None> on_error(Error err) { return native::fdb_transaction_on_error(tr.get(), err.code()); }
TypedFuture<future_var::None> onError(Error err) { return native::fdb_transaction_on_error(tr.get(), err.code()); }
void reset() { return native::fdb_transaction_reset(tr.get()); }
void set(KeyRef key, ValueRef value) {
native::fdb_transaction_set(tr.get(), key.data(), intsize(key), value.data(), intsize(value));
native::fdb_transaction_set(tr.get(), key.data(), intSize(key), value.data(), intSize(value));
}
void clear(KeyRef key) { native::fdb_transaction_clear(tr.get(), key.data(), intsize(key)); }
void clear(KeyRef key) { native::fdb_transaction_clear(tr.get(), key.data(), intSize(key)); }
void clear_range(KeyRef begin, KeyRef end) {
native::fdb_transaction_clear_range(tr.get(), begin.data(), intsize(begin), end.data(), intsize(end));
void clearRange(KeyRef begin, KeyRef end) {
native::fdb_transaction_clear_range(tr.get(), begin.data(), intSize(begin), end.data(), intSize(end));
}
};
@ -498,45 +498,45 @@ public:
Database(const std::string& cluster_file_path) : db(nullptr) {
auto db_raw = static_cast<native::FDBDatabase*>(nullptr);
if (auto err = Error(native::fdb_create_database(cluster_file_path.c_str(), &db_raw)))
throw_error(fmt::format("Failed to create database with '{}': ", cluster_file_path), err);
throwError(fmt::format("Failed to create database with '{}': ", cluster_file_path), err);
db = std::shared_ptr<native::FDBDatabase>(db_raw, &native::fdb_database_destroy);
}
Database() noexcept : db(nullptr) {}
Error set_option_nothrow(FDBDatabaseOption option, int64_t value) noexcept {
Error setOptionNothrow(FDBDatabaseOption option, int64_t value) noexcept {
return Error(native::fdb_database_set_option(
db.get(), option, reinterpret_cast<const uint8_t*>(&value), static_cast<int>(sizeof(value))));
}
Error set_option_nothrow(FDBDatabaseOption option, BytesRef str) noexcept {
return Error(native::fdb_database_set_option(db.get(), option, str.data(), intsize(str)));
Error setOptionNothrow(FDBDatabaseOption option, BytesRef str) noexcept {
return Error(native::fdb_database_set_option(db.get(), option, str.data(), intSize(str)));
}
void set_option(FDBDatabaseOption option, int64_t value) {
if (auto err = set_option_nothrow(option, value)) {
throw_error(fmt::format("database_set_option({}, {}) returned error: ",
static_cast<std::underlying_type_t<FDBDatabaseOption>>(option),
value),
err);
void setOption(FDBDatabaseOption option, int64_t value) {
if (auto err = setOptionNothrow(option, value)) {
throwError(fmt::format("database_set_option({}, {}) returned error: ",
static_cast<std::underlying_type_t<FDBDatabaseOption>>(option),
value),
err);
}
}
void set_option(FDBDatabaseOption option, BytesRef str) {
if (auto err = set_option_nothrow(option, str)) {
throw_error(fmt::format("database_set_option({}) returned error: ",
static_cast<std::underlying_type_t<FDBDatabaseOption>>(option)),
err);
void setOption(FDBDatabaseOption option, BytesRef str) {
if (auto err = setOptionNothrow(option, str)) {
throwError(fmt::format("database_set_option({}) returned error: ",
static_cast<std::underlying_type_t<FDBDatabaseOption>>(option)),
err);
}
}
TX create_tx() {
Transaction createTransaction() {
if (!db)
throw std::runtime_error("create_transaction from null database");
auto tx_native = static_cast<native::FDBTransaction*>(nullptr);
auto err = Error(native::fdb_database_create_transaction(db.get(), &tx_native));
if (err)
throw_error("Failed to create transaction: ", err);
return TX(tx_native);
throwError("Failed to create transaction: ", err);
return Transaction(tx_native);
}
};

File diff suppressed because it is too large Load Diff

View File

@ -41,7 +41,7 @@ constexpr const int MODE_BUILD = 1;
constexpr const int MODE_RUN = 2;
/* for long arguments */
enum Arguments {
enum ArgKind {
ARG_KEYLEN,
ARG_VALLEN,
ARG_TPS,
@ -71,11 +71,11 @@ enum Arguments {
enum TPSChangeTypes { TPS_SIN, TPS_SQUARE, TPS_PULSE };
/* we set txnspec_t and args_t only once in the master process,
/* we set WorkloadSpec and Arguments only once in the master process,
* and won't be touched by child processes.
*/
struct txnspec_t {
struct WorkloadSpec {
/* for each operation, it stores "count", "range" and "reverse" */
int ops[MAX_OP][3];
};
@ -88,7 +88,7 @@ constexpr const int NUM_DATABASES_MAX = 10;
constexpr const int MAX_BG_IDS = 1000;
/* benchmark parameters */
struct args_t {
struct Arguments {
int api_version;
int json;
int num_processes;
@ -108,7 +108,7 @@ struct args_t {
int zipf;
int commit_get;
int verbose;
txnspec_t txnspec;
WorkloadSpec txnspec;
char cluster_files[NUM_CLUSTERS_MAX][PATH_MAX];
int num_fdb_clusters;
int num_databases;
@ -135,20 +135,19 @@ constexpr const int SIGNAL_RED = 0;
constexpr const int SIGNAL_GREEN = 1;
constexpr const int SIGNAL_OFF = 2;
using sample_bin_array_t = std::array<sample_bin, MAX_OP>;
/* args for threads */
struct alignas(64) thread_args_t {
struct alignas(64) ThreadArgs {
int worker_id;
int thread_id;
pid_t parent_id;
sample_bin_array_t sample_bins;
args_t const* args;
shm_access_t shm;
LatencySampleBinArray sample_bins;
Arguments const* args;
shared_memory::Access shm;
fdb::Database database; // database to work with
};
/* process type */
typedef enum { proc_master = 0, proc_worker, proc_stats } proc_type_t;
typedef enum { PROC_MASTER = 0, PROC_WORKER, PROC_STATS } ProcKind;
} // namespace mako

View File

@ -6,70 +6,72 @@
#include <cstdint>
#include "stats.hpp"
namespace mako {
namespace mako::shared_memory {
struct shmhdr_t {
struct Header {
std::atomic<int> signal;
std::atomic<int> readycount;
std::atomic<double> throttle_factor;
std::atomic<int> stopcount;
};
struct shm_layout_helper {
shmhdr_t hdr;
stats_t stats;
struct LayoutHelper {
Header hdr;
ThreadStatistics stats;
};
inline size_t shm_storage_size(int num_processes, int num_threads) noexcept {
inline size_t storageSize(int num_processes, int num_threads) noexcept {
assert(num_processes >= 1 && num_threads >= 1);
return sizeof(shm_layout_helper) + sizeof(stats_t) * ((num_processes * num_threads) - 1);
return sizeof(LayoutHelper) + sizeof(ThreadStatistics) * ((num_processes * num_threads) - 1);
}
inline stats_t& shm_stats_slot(void* shm_base, int num_threads, int process_idx, int thread_idx) noexcept {
return (&static_cast<shm_layout_helper*>(shm_base)->stats)[process_idx * num_threads + thread_idx];
}
class shm_access_t {
protected:
class Access {
void* base;
int num_processes;
int num_threads;
static inline ThreadStatistics& statsSlot(void* shm_base,
int num_threads,
int process_idx,
int thread_idx) noexcept {
return (&static_cast<LayoutHelper*>(shm_base)->stats)[process_idx * num_threads + thread_idx];
}
public:
shm_access_t(void* shm, int num_processes, int num_threads) noexcept
Access(void* shm, int num_processes, int num_threads) noexcept
: base(shm), num_processes(num_processes), num_threads(num_threads) {}
shm_access_t() noexcept : shm_access_t(nullptr, 0, 0) {}
Access() noexcept : Access(nullptr, 0, 0) {}
shm_access_t(const shm_access_t&) noexcept = default;
Access(const Access&) noexcept = default;
shm_access_t& operator=(const shm_access_t&) noexcept = default;
Access& operator=(const Access&) noexcept = default;
size_t storage_size() const noexcept { return shm_storage_size(num_processes, num_threads); }
size_t size() const noexcept { return storageSize(num_processes, num_threads); }
void reset() noexcept { memset(base, 0, storage_size()); }
void reset() noexcept { memset(base, 0, size()); }
shmhdr_t const& header_const() const noexcept { return *static_cast<shmhdr_t const*>(base); }
Header const& headerConst() const noexcept { return *static_cast<Header const*>(base); }
shmhdr_t& header() const noexcept { return *static_cast<shmhdr_t*>(base); }
Header& header() const noexcept { return *static_cast<Header*>(base); }
stats_t const* stats_const_array() const noexcept {
return &shm_stats_slot(base, num_threads, 0 /*process_id*/, 0 /*thread_id*/);
ThreadStatistics const* statsConstArray() const noexcept {
return &statsSlot(base, num_threads, 0 /*process_id*/, 0 /*thread_id*/);
}
stats_t* stats_array() const noexcept {
return &shm_stats_slot(base, num_threads, 0 /*process_id*/, 0 /*thread_id*/);
ThreadStatistics* statsArray() const noexcept {
return &statsSlot(base, num_threads, 0 /*process_id*/, 0 /*thread_id*/);
}
stats_t const& stats_const_slot(int process_idx, int thread_idx) const noexcept {
return shm_stats_slot(base, num_threads, process_idx, thread_idx);
ThreadStatistics const& statsConstSlot(int process_idx, int thread_idx) const noexcept {
return statsSlot(base, num_threads, process_idx, thread_idx);
}
stats_t& stats_slot(int process_idx, int thread_idx) const noexcept {
return shm_stats_slot(base, num_threads, process_idx, thread_idx);
ThreadStatistics& statsSlot(int process_idx, int thread_idx) const noexcept {
return statsSlot(base, num_threads, process_idx, thread_idx);
}
};
} // namespace mako
} // namespace mako::shared_memory
#endif /* MAKO_SHM_HPP */

View File

@ -1,6 +1,7 @@
#ifndef MAKO_STATS_HPP
#define MAKO_STATS_HPP
#include <array>
#include <cstdint>
#include <cstring>
#include <list>
@ -14,14 +15,14 @@ namespace mako {
constexpr const size_t LAT_BLOCK_SIZE = 4095;
/* memory block allocated to each operation when collecting detailed latency */
class lat_block_t {
class LatencySampleBlock {
uint64_t samples[LAT_BLOCK_SIZE]{
0,
};
uint32_t index{ 0 };
public:
lat_block_t() noexcept = default;
LatencySampleBlock() noexcept = default;
bool full() const noexcept { return index >= LAT_BLOCK_SIZE; }
void put(timediff_t td) {
assert(!full());
@ -32,11 +33,11 @@ public:
};
/* collect sampled latencies */
class sample_bin {
std::list<lat_block_t> blocks;
class LatencySampleBin {
std::list<LatencySampleBlock> blocks;
public:
void reserve_one() {
void reserveOneBlock() {
if (blocks.empty())
blocks.emplace_back();
}
@ -49,7 +50,7 @@ public:
// iterate & apply for each block user function void(uint64_t const*, size_t)
template <typename Func>
void for_each_block(Func&& fn) const {
void forEachBlock(Func&& fn) const {
for (const auto& block : blocks) {
auto [ptr, cnt] = block.data();
fn(ptr, cnt);
@ -57,7 +58,7 @@ public:
}
};
class alignas(64) stats_t {
class alignas(64) ThreadStatistics {
uint64_t xacts;
uint64_t conflicts;
uint64_t total_errors;
@ -69,13 +70,13 @@ class alignas(64) stats_t {
uint64_t latency_us_max[MAX_OP];
public:
stats_t() noexcept {
memset(this, 0, sizeof(stats_t));
ThreadStatistics() noexcept {
memset(this, 0, sizeof(ThreadStatistics));
memset(latency_us_min, 0xff, sizeof(latency_us_min));
}
stats_t(const stats_t& other) noexcept = default;
stats_t& operator=(const stats_t& other) noexcept = default;
ThreadStatistics(const ThreadStatistics& other) noexcept = default;
ThreadStatistics& operator=(const ThreadStatistics& other) noexcept = default;
uint64_t get_tx_count() const noexcept { return xacts; }
@ -96,7 +97,7 @@ public:
uint64_t get_latency_us_max(int op) const noexcept { return latency_us_max[op]; }
// with 'this' as final aggregation, factor in 'other'
void combine(const stats_t& other) {
void combine(const ThreadStatistics& other) {
xacts += other.xacts;
conflicts += other.conflicts;
for (auto op = 0; op < MAX_OP; op++) {
@ -134,6 +135,8 @@ public:
}
};
using LatencySampleBinArray = std::array<LatencySampleBin, MAX_OP>;
} // namespace mako
#endif /* MAKO_STATS_HPP */

View File

@ -16,19 +16,19 @@ int urand(int low, int high) {
}
/* return the first key to be inserted */
int insert_begin(int rows, int p_idx, int t_idx, int total_p, int total_t) {
int insertBegin(int rows, int p_idx, int t_idx, int total_p, int total_t) {
double interval = (double)rows / total_p / total_t;
return (int)(round(interval * ((p_idx * total_t) + t_idx)));
}
/* return the last key to be inserted */
int insert_end(int rows, int p_idx, int t_idx, int total_p, int total_t) {
int insertEnd(int rows, int p_idx, int t_idx, int total_p, int total_t) {
double interval = (double)rows / total_p / total_t;
return (int)(round(interval * ((p_idx * total_t) + t_idx + 1) - 1));
}
/* devide val equally among threads */
int compute_thread_portion(int val, int p_idx, int t_idx, int total_p, int total_t) {
int computeThreadPortion(int val, int p_idx, int t_idx, int total_p, int total_t) {
int interval = val / total_p / total_t;
int remaining = val - (interval * total_p * total_t);
if ((p_idx * total_t + t_idx) < remaining) {

View File

@ -18,7 +18,7 @@ int urand(int low, int high);
/* random string */
template <bool Clear = true, typename Char>
void randstr(std::basic_string<Char>& str, int len) {
void randomString(std::basic_string<Char>& str, int len) {
if constexpr (Clear)
str.clear();
assert(len >= 0);
@ -30,7 +30,7 @@ void randstr(std::basic_string<Char>& str, int len) {
/* random numeric string */
template <bool Clear = true, typename Char>
void randnumstr(std::basic_string<Char>& str, int len) {
void randomNumericString(std::basic_string<Char>& str, int len) {
if constexpr (Clear)
str.clear();
assert(len >= 0);
@ -45,25 +45,25 @@ void randnumstr(std::basic_string<Char>& str, int len) {
* and the total number of processes, total_p, and threads, total_t,
* returns the first row number assigned to this partition.
*/
int insert_begin(int rows, int p_idx, int t_idx, int total_p, int total_t);
int insertBegin(int rows, int p_idx, int t_idx, int total_p, int total_t);
/* similar to insert_begin, insert_end returns the last row numer */
int insert_end(int rows, int p_idx, int t_idx, int total_p, int total_t);
/* similar to insertBegin, insertEnd returns the last row numer */
int insertEnd(int rows, int p_idx, int t_idx, int total_p, int total_t);
/* devide a value equally among threads */
int compute_thread_portion(int val, int p_idx, int t_idx, int total_p, int total_t);
int computeThreadPortion(int val, int p_idx, int t_idx, int total_p, int total_t);
/* similar to insert_begin/end, compute_thread_tps computes
/* similar to insertBegin/end, computeThreadTps computes
* the per-thread target TPS for given configuration.
*/
#define compute_thread_tps(val, p_idx, t_idx, total_p, total_t) \
compute_thread_portion(val, p_idx, t_idx, total_p, total_t)
#define computeThreadTps(val, p_idx, t_idx, total_p, total_t) \
computeThreadPortion(val, p_idx, t_idx, total_p, total_t)
/* similar to compute_thread_tps,
* compute_thread_iters computs the number of iterations.
/* similar to computeThreadTps,
* computeThreadIters computs the number of iterations.
*/
#define compute_thread_iters(val, p_idx, t_idx, total_p, total_t) \
compute_thread_portion(val, p_idx, t_idx, total_p, total_t)
#define computeThreadIters(val, p_idx, t_idx, total_p, total_t) \
computeThreadPortion(val, p_idx, t_idx, total_p, total_t)
/* get the number of digits */
int digits(int num);
@ -72,7 +72,7 @@ int digits(int num);
* (str) is appended with concat([padding], PREFIX)
*/
template <bool Clear = true, typename Char>
void genkeyprefix(std::basic_string<Char>& str, std::string_view prefix, args_t const& args) {
void genKeyPrefix(std::basic_string<Char>& str, std::string_view prefix, Arguments const& args) {
// concat('x' * padding_len, key_prefix)
if constexpr (Clear)
str.clear();
@ -86,7 +86,7 @@ void genkeyprefix(std::basic_string<Char>& str, std::string_view prefix, args_t
/* generate a key for a given key number */
/* prefix is "mako" by default, prefixpadding = 1 means 'x' will be in front rather than trailing the keyname */
template <bool Clear = true, typename Char>
void genkey(std::basic_string<Char>& str, std::string_view prefix, args_t const& args, int num) {
void genKey(std::basic_string<Char>& str, std::string_view prefix, Arguments const& args, int num) {
static_assert(sizeof(Char) == 1);
const auto pad_len = args.prefixpadding ? args.key_length - (static_cast<int>(prefix.size()) + args.row_digits) : 0;
assert(pad_len >= 0);
@ -135,30 +135,30 @@ constexpr const int STATS_TITLE_WIDTH = 12;
constexpr const int STATS_FIELD_WIDTH = 12;
template <typename Value>
void put_title(Value&& value) {
void putTitle(Value&& value) {
fmt::print("{0: <{1}} ", std::forward<Value>(value), STATS_TITLE_WIDTH);
}
template <typename Value>
void put_title_r(Value&& value) {
void putTitleRight(Value&& value) {
fmt::print("{0: >{1}} ", std::forward<Value>(value), STATS_TITLE_WIDTH);
}
inline void put_title_bar() {
inline void putTitleBar() {
fmt::print("{0:=<{1}} ", "", STATS_TITLE_WIDTH);
}
template <typename Value>
void put_field(Value&& value) {
void putField(Value&& value) {
fmt::print("{0: >{1}} ", std::forward<Value>(value), STATS_FIELD_WIDTH);
}
inline void put_field_bar() {
inline void putFieldBar() {
fmt::print("{0:=>{1}} ", "", STATS_FIELD_WIDTH);
}
template <typename Value>
void put_field_f(Value&& value, int precision) {
void putFieldFloat(Value&& value, int precision) {
fmt::print("{0: >{1}.{2}f} ", std::forward<Value>(value), STATS_FIELD_WIDTH, precision);
}