mdbx: новые настройки clang-format (косметика).

This commit is contained in:
Леонид Юрьев (Leonid Yuriev)
2024-12-11 21:22:04 +03:00
parent 3c4d019d00
commit 8867c2ddc2
129 changed files with 6727 additions and 12640 deletions

View File

@@ -5,16 +5,14 @@
class testcase_append : public testcase {
public:
testcase_append(const actor_config &config, const mdbx_pid_t pid)
: testcase(config, pid) {}
testcase_append(const actor_config &config, const mdbx_pid_t pid) : testcase(config, pid) {}
bool run() override;
static bool review_params(actor_params &params, unsigned space_id) {
if (!testcase::review_params(params, space_id))
return false;
const bool ordered = !flipcoin_x3();
log_notice("the '%s' key-generation mode is selected",
ordered ? "ordered/linear" : "unordered/non-linear");
log_notice("the '%s' key-generation mode is selected", ordered ? "ordered/linear" : "unordered/non-linear");
if (ordered && !params.make_keygen_linear())
return false;
return true;
@@ -37,13 +35,10 @@ bool testcase_append::run() {
keyvalue_maker.setup(config.params, 0 /* thread_number */);
/* LY: тест наполнения таблиц в append-режиме,
* при котором записи добавляются строго в конец (в порядке сортировки) */
const MDBX_put_flags_t flags =
reverse
? ((config.params.table_flags & MDBX_DUPSORT) ? MDBX_UPSERT
: MDBX_NOOVERWRITE)
: ((config.params.table_flags & MDBX_DUPSORT)
? (flipcoin() ? MDBX_APPEND | MDBX_APPENDDUP : MDBX_APPENDDUP)
: MDBX_APPEND);
const MDBX_put_flags_t flags = reverse ? ((config.params.table_flags & MDBX_DUPSORT) ? MDBX_UPSERT : MDBX_NOOVERWRITE)
: ((config.params.table_flags & MDBX_DUPSORT)
? (flipcoin() ? MDBX_APPEND | MDBX_APPENDDUP : MDBX_APPENDDUP)
: MDBX_APPEND);
key = keygen::alloc(config.params.keylen_max);
data = keygen::alloc(config.params.datalen_max);
@@ -59,11 +54,9 @@ bool testcase_append::run() {
simple_checksum committed_inserted_checksum = inserted_checksum;
while (should_continue()) {
const keygen::serial_t serial = serial_count;
const bool turn_key = (config.params.table_flags & MDBX_DUPSORT) == 0 ||
flipcoin_n(config.params.keygen.split);
if (turn_key
? !keyvalue_maker.increment_key_part(serial_count, reverse ? -1 : 1)
: !keyvalue_maker.increment(serial_count, reverse ? -1 : 1)) {
const bool turn_key = (config.params.table_flags & MDBX_DUPSORT) == 0 || flipcoin_n(config.params.keygen.split);
if (turn_key ? !keyvalue_maker.increment_key_part(serial_count, reverse ? -1 : 1)
: !keyvalue_maker.increment(serial_count, reverse ? -1 : 1)) {
// дошли до границы пространства ключей
break;
}
@@ -106,8 +99,7 @@ bool testcase_append::run() {
break;
case MDBX_APPENDDUP:
assert((config.params.table_flags & MDBX_DUPSORT) != 0);
expect_key_mismatch =
mdbx_cmp(txn_guard.get(), dbi, &key->value, &ge_key) == 0;
expect_key_mismatch = mdbx_cmp(txn_guard.get(), dbi, &key->value, &ge_key) == 0;
break;
}
} else if (err == MDBX_NOTFOUND /* all pair are less than */) {
@@ -152,10 +144,9 @@ bool testcase_append::run() {
const auto insertion_result = speculum.insert(item);
if (!insertion_result.second) {
char dump_key[32], dump_value[32];
log_error(
"speculum.append: unexpected %s {%s, %s}", "MDBX_SUCCESS",
mdbx_dump_val(&key->value, dump_key, sizeof(dump_key)),
mdbx_dump_val(&data->value, dump_value, sizeof(dump_value)));
log_error("speculum.append: unexpected %s {%s, %s}", "MDBX_SUCCESS",
mdbx_dump_val(&key->value, dump_key, sizeof(dump_key)),
mdbx_dump_val(&data->value, dump_value, sizeof(dump_value)));
return false;
}
}
@@ -199,8 +190,7 @@ bool testcase_append::run() {
cursor_renew();
MDBX_val check_key, check_data;
err = mdbx_cursor_get(cursor_guard.get(), &check_key, &check_data,
reverse ? MDBX_LAST : MDBX_FIRST);
err = mdbx_cursor_get(cursor_guard.get(), &check_key, &check_data, reverse ? MDBX_LAST : MDBX_FIRST);
if (likely(inserted_number)) {
if (unlikely(err != MDBX_SUCCESS))
failure_perror("mdbx_cursor_get(MDBX_FIRST)", err);
@@ -213,19 +203,16 @@ bool testcase_append::run() {
read_checksum.push((uint32_t)read_count, check_key);
read_checksum.push(10639, check_data);
err = mdbx_cursor_get(cursor_guard.get(), &check_key, &check_data,
reverse ? MDBX_PREV : MDBX_NEXT);
err = mdbx_cursor_get(cursor_guard.get(), &check_key, &check_data, reverse ? MDBX_PREV : MDBX_NEXT);
}
if (unlikely(err != MDBX_NOTFOUND))
failure_perror("mdbx_cursor_get(MDBX_NEXT) != EOF", err);
if (unlikely(read_count != inserted_number))
failure("read_count(%" PRIu64 ") != inserted_number(%" PRIu64 ")",
read_count, inserted_number);
failure("read_count(%" PRIu64 ") != inserted_number(%" PRIu64 ")", read_count, inserted_number);
if (unlikely(read_checksum.value != inserted_checksum.value) &&
!keyvalue_maker.is_unordered())
if (unlikely(read_checksum.value != inserted_checksum.value) && !keyvalue_maker.is_unordered())
failure("read_checksum(0x%016" PRIu64 ") "
"!= inserted_checksum(0x%016" PRIu64 ")",
read_checksum.value, inserted_checksum.value);

View File

@@ -7,12 +7,12 @@
#ifdef _MSC_VER
#pragma warning(push, 1)
#pragma warning(disable : 4548) /* expression before comma has no effect; \
#pragma warning(disable : 4548) /* expression before comma has no effect; \
expected expression with side - effect */
#pragma warning(disable : 4530) /* C++ exception handler used, but unwind \
#pragma warning(disable : 4530) /* C++ exception handler used, but unwind \
semantics are not enabled. Specify /EHsc */
#pragma warning(disable : 4577) /* 'noexcept' used with no exception handling \
mode specified; termination on exception \
#pragma warning(disable : 4577) /* 'noexcept' used with no exception handling \
mode specified; termination on exception \
is not guaranteed. Specify /EHsc */
#endif /* _MSC_VER (warnings) */
@@ -71,24 +71,22 @@
#ifdef _MSC_VER
#pragma warning(pop)
#pragma warning(disable : 4201) /* nonstandard extension used: nameless \
#pragma warning(disable : 4201) /* nonstandard extension used: nameless \
struct/union */
#pragma warning(disable : 4127) /* conditional expression is constant */
#if _MSC_VER < 1900
#pragma warning(disable : 4510) /* default constructor could \
#pragma warning(disable : 4510) /* default constructor could \
not be generated */
#pragma warning(disable : 4512) /* assignment operator could \
#pragma warning(disable : 4512) /* assignment operator could \
not be generated */
#pragma warning(disable : 4610) /* user-defined constructor required */
#ifndef snprintf
#define snprintf(buffer, buffer_size, format, ...) \
_snprintf_s(buffer, buffer_size, _TRUNCATE, format, __VA_ARGS__)
#define snprintf(buffer, buffer_size, format, ...) _snprintf_s(buffer, buffer_size, _TRUNCATE, format, __VA_ARGS__)
#endif
#ifndef vsnprintf
#define vsnprintf(buffer, buffer_size, format, args) \
_vsnprintf_s(buffer, buffer_size, _TRUNCATE, format, args)
#define vsnprintf(buffer, buffer_size, format, args) _vsnprintf_s(buffer, buffer_size, _TRUNCATE, format, args)
#endif
#pragma warning(disable : 4996) /* 'vsnprintf': This function or variable \
#pragma warning(disable : 4996) /* 'vsnprintf': This function or variable \
may be unsafe */
#endif
#endif /* _MSC_VER */

View File

@@ -14,9 +14,7 @@ bool registry::add(const record *item) {
auto const singleton = instance();
assert(singleton->name2id.count(std::string(item->name)) == 0);
assert(singleton->id2record.count(item->id) == 0);
if (singleton->name2id.count(std::string(item->name)) +
singleton->id2record.count(item->id) ==
0) {
if (singleton->name2id.count(std::string(item->name)) + singleton->id2record.count(item->id) == 0) {
singleton->name2id[std::string(item->name)] = item;
singleton->id2record[item->id] = item;
return true;
@@ -24,28 +22,24 @@ bool registry::add(const record *item) {
return false;
}
testcase *registry::create_actor(const actor_config &config,
const mdbx_pid_t pid) {
testcase *registry::create_actor(const actor_config &config, const mdbx_pid_t pid) {
return instance()->id2record.at(config.testcase)->constructor(config, pid);
}
bool registry::review_actor_params(const actor_testcase id,
actor_params &params,
const unsigned space_id) {
bool registry::review_actor_params(const actor_testcase id, actor_params &params, const unsigned space_id) {
return instance()->id2record.at(id)->review_params(params, space_id);
}
//-----------------------------------------------------------------------------
void configure_actor(unsigned &last_space_id, const actor_testcase testcase,
const char *space_id_cstr, actor_params params) {
void configure_actor(unsigned &last_space_id, const actor_testcase testcase, const char *space_id_cstr,
actor_params params) {
unsigned wait4id = 0;
if (params.waitfor_nops) {
for (auto i = global::actors.rbegin(); i != global::actors.rend(); ++i) {
if (i->is_waitable(params.waitfor_nops)) {
if (i->signal_nops && i->signal_nops != params.waitfor_nops)
failure("Previous waitable actor (id=%u) already linked on %u-ops\n",
i->actor_id, i->signal_nops);
failure("Previous waitable actor (id=%u) already linked on %u-ops\n", i->actor_id, i->signal_nops);
wait4id = i->actor_id;
i->signal_nops = params.waitfor_nops;
break;
@@ -75,15 +69,12 @@ void configure_actor(unsigned &last_space_id, const actor_testcase testcase,
failure("Actor config-review failed for space-id %lu\n", space_id);
last_space_id = unsigned(space_id);
log_trace("configure_actor: space %lu for %s", space_id,
testcase2str(testcase));
global::actors.emplace_back(
actor_config(testcase, params, unsigned(space_id), wait4id));
log_trace("configure_actor: space %lu for %s", space_id, testcase2str(testcase));
global::actors.emplace_back(actor_config(testcase, params, unsigned(space_id), wait4id));
global::databases.insert(params.pathname_db);
}
void testcase_setup(const char *casename, const actor_params &params,
unsigned &last_space_id) {
void testcase_setup(const char *casename, const actor_params &params, unsigned &last_space_id) {
if (strcmp(casename, "basic") == 0) {
log_notice(">>> testcase_setup(%s)", casename);
configure_actor(last_space_id, ac_nested, nullptr, params);
@@ -111,8 +102,7 @@ void keycase_setup(const char *casename, actor_params &params) {
params.keygen.keycase = kc_random;
// TODO
log_notice("<<< keycase_setup(%s): done", casename);
} else if (strcmp(casename, "dashes") == 0 ||
strcmp(casename, "aside") == 0) {
} else if (strcmp(casename, "dashes") == 0 || strcmp(casename, "aside") == 0) {
log_notice(">>> keycase_setup(%s)", casename);
params.keygen.keycase = kc_dashes;
// TODO

View File

@@ -18,9 +18,7 @@ uint32_t ns2fractional(uint32_t ns) {
return uint32_t((uint64_t(ns) << 32) / NSEC_PER_SEC);
}
uint32_t fractional2ns(uint32_t fractional) {
return uint32_t((fractional * uint64_t(NSEC_PER_SEC)) >> 32);
}
uint32_t fractional2ns(uint32_t fractional) { return uint32_t((fractional * uint64_t(NSEC_PER_SEC)) >> 32); }
#ifndef USEC_PER_SEC
#define USEC_PER_SEC 1000000u
@@ -51,33 +49,27 @@ uint32_t ms2fractional(uint32_t ms) {
return uint32_t((uint64_t(ms) << 32) / MSEC_PER_SEC);
}
uint32_t fractional2ms(uint32_t fractional) {
return uint32_t((fractional * uint64_t(MSEC_PER_SEC)) >> 32);
}
uint32_t fractional2ms(uint32_t fractional) { return uint32_t((fractional * uint64_t(MSEC_PER_SEC)) >> 32); }
time from_ns(uint64_t ns) {
time result;
result.fixedpoint =
((ns / NSEC_PER_SEC) << 32) | ns2fractional(uint32_t(ns % NSEC_PER_SEC));
result.fixedpoint = ((ns / NSEC_PER_SEC) << 32) | ns2fractional(uint32_t(ns % NSEC_PER_SEC));
return result;
}
time from_us(uint64_t us) {
time result;
result.fixedpoint =
((us / USEC_PER_SEC) << 32) | us2fractional(uint32_t(us % USEC_PER_SEC));
result.fixedpoint = ((us / USEC_PER_SEC) << 32) | us2fractional(uint32_t(us % USEC_PER_SEC));
return result;
}
time from_ms(uint64_t ms) {
time result;
result.fixedpoint =
((ms / MSEC_PER_SEC) << 32) | ms2fractional(uint32_t(ms % MSEC_PER_SEC));
result.fixedpoint = ((ms / MSEC_PER_SEC) << 32) | ms2fractional(uint32_t(ms % MSEC_PER_SEC));
return result;
}
#if __GNUC_PREREQ(8, 0) && \
(defined(__MINGW__) || defined(__MINGW32__) || defined(__MINGW64__))
#if __GNUC_PREREQ(8, 0) && (defined(__MINGW__) || defined(__MINGW32__) || defined(__MINGW64__))
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wcast-function-type"
#endif /* GCC/MINGW */
@@ -88,16 +80,14 @@ time now_realtime() {
if (unlikely(!query_time)) {
HMODULE hModule = GetModuleHandle(TEXT("kernel32.dll"));
if (hModule)
query_time = (void(WINAPI *)(LPFILETIME))GetProcAddress(
hModule, "GetSystemTimePreciseAsFileTime");
query_time = (void(WINAPI *)(LPFILETIME))GetProcAddress(hModule, "GetSystemTimePreciseAsFileTime");
if (!query_time)
query_time = GetSystemTimeAsFileTime;
}
FILETIME filetime;
query_time(&filetime);
uint64_t ns100 =
(uint64_t)filetime.dwHighDateTime << 32 | filetime.dwLowDateTime;
uint64_t ns100 = (uint64_t)filetime.dwHighDateTime << 32 | filetime.dwLowDateTime;
return from_ns((ns100 - UINT64_C(116444736000000000)) * 100u);
#else
struct timespec ts;
@@ -115,8 +105,7 @@ time now_monotonic() {
if (reciprocal == 0) {
if (!QueryPerformanceFrequency(&Frequency))
failure_perror("QueryPerformanceFrequency()", GetLastError());
reciprocal = (((UINT64_C(1) << 48) + Frequency.QuadPart / 2 + 1) /
Frequency.QuadPart);
reciprocal = (((UINT64_C(1) << 48) + Frequency.QuadPart / 2 + 1) / Frequency.QuadPart);
assert(reciprocal);
}
@@ -138,8 +127,7 @@ time now_monotonic() {
#endif
}
#if __GNUC_PREREQ(8, 0) && \
(defined(__MINGW__) || defined(__MINGW32__) || defined(__MINGW64__))
#if __GNUC_PREREQ(8, 0) && (defined(__MINGW__) || defined(__MINGW32__) || defined(__MINGW64__))
#pragma GCC diagnostic pop
#endif /* GCC/MINGW */

View File

@@ -63,12 +63,10 @@ inline time infinite() {
return result;
}
#if defined(HAVE_TIMESPEC_TV_NSEC) || defined(__timespec_defined) || \
defined(CLOCK_REALTIME)
#if defined(HAVE_TIMESPEC_TV_NSEC) || defined(__timespec_defined) || defined(CLOCK_REALTIME)
inline time from_timespec(const struct timespec &ts) {
time result;
result.fixedpoint =
((uint64_t)ts.tv_sec << 32) | ns2fractional((uint32_t)ts.tv_nsec);
result.fixedpoint = ((uint64_t)ts.tv_sec << 32) | ns2fractional((uint32_t)ts.tv_nsec);
return result;
}
#endif /* HAVE_TIMESPEC_TV_NSEC */
@@ -76,8 +74,7 @@ inline time from_timespec(const struct timespec &ts) {
#if defined(HAVE_TIMEVAL_TV_USEC) || defined(_STRUCT_TIMEVAL)
inline time from_timeval(const struct timeval &tv) {
time result;
result.fixedpoint =
((uint64_t)tv.tv_sec << 32) | us2fractional((uint32_t)tv.tv_usec);
result.fixedpoint = ((uint64_t)tv.tv_sec << 32) | us2fractional((uint32_t)tv.tv_usec);
return result;
}
#endif /* HAVE_TIMEVAL_TV_USEC */

View File

@@ -9,8 +9,8 @@
namespace config {
bool parse_option(int argc, char *const argv[], int &narg, const char *option,
const char **value, const char *default_value) {
bool parse_option(int argc, char *const argv[], int &narg, const char *option, const char **value,
const char *default_value) {
assert(narg < argc);
const char *current = argv[narg];
const size_t optlen = strlen(option);
@@ -49,14 +49,11 @@ bool parse_option(int argc, char *const argv[], int &narg, const char *option,
failure("No value given for '--%s' option\n", option);
}
bool parse_option(int argc, char *const argv[], int &narg, const char *option,
std::string &value, bool allow_empty) {
return parse_option(argc, argv, narg, option, value, allow_empty,
allow_empty ? "" : nullptr);
bool parse_option(int argc, char *const argv[], int &narg, const char *option, std::string &value, bool allow_empty) {
return parse_option(argc, argv, narg, option, value, allow_empty, allow_empty ? "" : nullptr);
}
bool parse_option(int argc, char *const argv[], int &narg, const char *option,
std::string &value, bool allow_empty,
bool parse_option(int argc, char *const argv[], int &narg, const char *option, std::string &value, bool allow_empty,
const char *default_value) {
const char *value_cstr;
if (!parse_option(argc, argv, narg, option, &value_cstr, default_value))
@@ -70,8 +67,7 @@ bool parse_option(int argc, char *const argv[], int &narg, const char *option,
}
template <>
bool parse_option<unsigned>(int argc, char *const argv[], int &narg,
const char *option, unsigned &mask,
bool parse_option<unsigned>(int argc, char *const argv[], int &narg, const char *option, unsigned &mask,
const option_verb *verbs) {
const char *list;
if (!parse_option(argc, argv, narg, option, &list))
@@ -95,8 +91,7 @@ bool parse_option<unsigned>(int argc, char *const argv[], int &narg,
while (true) {
if (!scan->verb)
failure("Unknown verb '%.*s', for option '--%s'\n", (int)len, list,
option);
failure("Unknown verb '%.*s', for option '--%s'\n", (int)len, list, option);
if (strlen(scan->verb) == len && strncmp(list, scan->verb, len) == 0) {
mask = strikethrough ? mask & ~scan->mask : mask | scan->mask;
clear = strikethrough ? clear & ~scan->mask : clear | scan->mask;
@@ -110,10 +105,8 @@ bool parse_option<unsigned>(int argc, char *const argv[], int &narg,
return true;
}
bool parse_option(int argc, char *const argv[], int &narg, const char *option,
uint64_t &value, const scale_mode scale,
const uint64_t minval, const uint64_t maxval,
const uint64_t default_value) {
bool parse_option(int argc, char *const argv[], int &narg, const char *option, uint64_t &value, const scale_mode scale,
const uint64_t minval, const uint64_t maxval, const uint64_t default_value) {
const char *value_cstr;
if (!parse_option(argc, argv, narg, option, &value_cstr))
@@ -134,17 +127,13 @@ bool parse_option(int argc, char *const argv[], int &narg, const char *option,
return true;
}
if (strcmp(value_cstr, "rnd") == 0 || strcmp(value_cstr, "rand") == 0 ||
strcmp(value_cstr, "random") == 0) {
if (strcmp(value_cstr, "rnd") == 0 || strcmp(value_cstr, "rand") == 0 || strcmp(value_cstr, "random") == 0) {
value = minval;
if (maxval > minval) {
uint64_t salt = (scale != entropy)
? prng64() ^ UINT64_C(44263400549519813)
: (chrono::now_monotonic().fixedpoint ^
UINT64_C(0xD85794512ED321FD)) *
UINT64_C(0x9120038359EAF3) ^
chrono::now_realtime().fixedpoint *
UINT64_C(0x2FE5232BDC8E5F);
uint64_t salt = (scale != entropy) ? prng64() ^ UINT64_C(44263400549519813)
: (chrono::now_monotonic().fixedpoint ^ UINT64_C(0xD85794512ED321FD)) *
UINT64_C(0x9120038359EAF3) ^
chrono::now_realtime().fixedpoint * UINT64_C(0x2FE5232BDC8E5F);
value += salt % (maxval - minval);
}
if (scale == intkey)
@@ -161,43 +150,32 @@ bool parse_option(int argc, char *const argv[], int &narg, const char *option,
raw = strtoull(value_cstr, &suffix, 10);
}
if (errno)
failure("Option '--%s' expects a numeric value (%s)\n", option,
test_strerror(errno));
failure("Option '--%s' expects a numeric value (%s)\n", option, test_strerror(errno));
uint64_t multiplier = 1;
if (suffix && *suffix) {
if (scale == no_scale || scale == intkey)
failure("Option '--%s' doesn't accepts suffixes, so '%s' is unexpected\n",
option, suffix);
failure("Option '--%s' doesn't accepts suffixes, so '%s' is unexpected\n", option, suffix);
if (strcmp(suffix, "K") == 0 || strcasecmp(suffix, "Kilo") == 0)
multiplier = (scale == decimal) ? UINT64_C(1000) : UINT64_C(1024);
else if (strcmp(suffix, "M") == 0 || strcasecmp(suffix, "Mega") == 0)
multiplier =
(scale == decimal) ? UINT64_C(1000) * 1000 : UINT64_C(1024) * 1024;
multiplier = (scale == decimal) ? UINT64_C(1000) * 1000 : UINT64_C(1024) * 1024;
else if (strcmp(suffix, "G") == 0 || strcasecmp(suffix, "Giga") == 0)
multiplier = (scale == decimal) ? UINT64_C(1000) * 1000 * 1000
: UINT64_C(1024) * 1024 * 1024;
multiplier = (scale == decimal) ? UINT64_C(1000) * 1000 * 1000 : UINT64_C(1024) * 1024 * 1024;
else if (strcmp(suffix, "T") == 0 || strcasecmp(suffix, "Tera") == 0)
multiplier = (scale == decimal) ? UINT64_C(1000) * 1000 * 1000 * 1000
: UINT64_C(1024) * 1024 * 1024 * 1024;
else if (scale == duration &&
(strcmp(suffix, "s") == 0 || strcasecmp(suffix, "Seconds") == 0))
multiplier = (scale == decimal) ? UINT64_C(1000) * 1000 * 1000 * 1000 : UINT64_C(1024) * 1024 * 1024 * 1024;
else if (scale == duration && (strcmp(suffix, "s") == 0 || strcasecmp(suffix, "Seconds") == 0))
multiplier = 1;
else if (scale == duration &&
(strcmp(suffix, "m") == 0 || strcasecmp(suffix, "Minutes") == 0))
else if (scale == duration && (strcmp(suffix, "m") == 0 || strcasecmp(suffix, "Minutes") == 0))
multiplier = 60;
else if (scale == duration &&
(strcmp(suffix, "h") == 0 || strcasecmp(suffix, "Hours") == 0))
else if (scale == duration && (strcmp(suffix, "h") == 0 || strcasecmp(suffix, "Hours") == 0))
multiplier = 3600;
else if (scale == duration &&
(strcmp(suffix, "d") == 0 || strcasecmp(suffix, "Days") == 0))
else if (scale == duration && (strcmp(suffix, "d") == 0 || strcasecmp(suffix, "Days") == 0))
multiplier = 3600 * 24;
else
failure(
"Option '--%s' expects a numeric value with Kilo/Mega/Giga/Tera %s"
"suffixes, but '%s' is unexpected\n",
option, (scale == duration) ? "or Seconds/Minutes/Hours/Days " : "",
suffix);
failure("Option '--%s' expects a numeric value with Kilo/Mega/Giga/Tera %s"
"suffixes, but '%s' is unexpected\n",
option, (scale == duration) ? "or Seconds/Minutes/Hours/Days " : "", suffix);
}
if (raw >= UINT64_MAX / multiplier)
@@ -205,47 +183,38 @@ bool parse_option(int argc, char *const argv[], int &narg, const char *option,
value = raw * multiplier;
if (maxval && value > maxval)
failure("The maximal value for option '--%s' is %" PRIu64 "\n", option,
maxval);
failure("The maximal value for option '--%s' is %" PRIu64 "\n", option, maxval);
if (value < minval)
failure("The minimal value for option '--%s' is %" PRIu64 "\n", option,
minval);
failure("The minimal value for option '--%s' is %" PRIu64 "\n", option, minval);
if (scale == intkey)
value &= ~3u;
return true;
}
bool parse_option(int argc, char *const argv[], int &narg, const char *option,
unsigned &value, const scale_mode scale,
const unsigned minval, const unsigned maxval,
const unsigned default_value) {
bool parse_option(int argc, char *const argv[], int &narg, const char *option, unsigned &value, const scale_mode scale,
const unsigned minval, const unsigned maxval, const unsigned default_value) {
uint64_t huge;
if (!parse_option(argc, argv, narg, option, huge, scale, minval, maxval,
default_value))
if (!parse_option(argc, argv, narg, option, huge, scale, minval, maxval, default_value))
return false;
value = unsigned(huge);
return true;
}
bool parse_option(int argc, char *const argv[], int &narg, const char *option,
uint8_t &value, const uint8_t minval, const uint8_t maxval,
const uint8_t default_value) {
bool parse_option(int argc, char *const argv[], int &narg, const char *option, uint8_t &value, const uint8_t minval,
const uint8_t maxval, const uint8_t default_value) {
uint64_t huge;
if (!parse_option(argc, argv, narg, option, huge, no_scale, minval, maxval,
default_value))
if (!parse_option(argc, argv, narg, option, huge, no_scale, minval, maxval, default_value))
return false;
value = uint8_t(huge);
return true;
}
bool parse_option(int argc, char *const argv[], int &narg, const char *option,
int64_t &value, const int64_t minval, const int64_t maxval,
const int64_t default_value) {
bool parse_option(int argc, char *const argv[], int &narg, const char *option, int64_t &value, const int64_t minval,
const int64_t maxval, const int64_t default_value) {
uint64_t proxy = uint64_t(value);
if (parse_option(argc, argv, narg, option, proxy, config::binary,
uint64_t(minval), uint64_t(maxval),
if (parse_option(argc, argv, narg, option, proxy, config::binary, uint64_t(minval), uint64_t(maxval),
uint64_t(default_value))) {
value = int64_t(proxy);
return true;
@@ -253,12 +222,10 @@ bool parse_option(int argc, char *const argv[], int &narg, const char *option,
return false;
}
bool parse_option(int argc, char *const argv[], int &narg, const char *option,
int32_t &value, const int32_t minval, const int32_t maxval,
const int32_t default_value) {
bool parse_option(int argc, char *const argv[], int &narg, const char *option, int32_t &value, const int32_t minval,
const int32_t maxval, const int32_t default_value) {
uint64_t proxy = uint64_t(value);
if (parse_option(argc, argv, narg, option, proxy, config::binary,
uint64_t(minval), uint64_t(maxval),
if (parse_option(argc, argv, narg, option, proxy, config::binary, uint64_t(minval), uint64_t(maxval),
uint64_t(default_value))) {
value = int32_t(proxy);
return true;
@@ -266,14 +233,12 @@ bool parse_option(int argc, char *const argv[], int &narg, const char *option,
return false;
}
bool parse_option(int argc, char *const argv[], int &narg, const char *option,
logging::loglevel &loglevel) {
bool parse_option(int argc, char *const argv[], int &narg, const char *option, logging::loglevel &loglevel) {
const char *value_cstr;
if (!parse_option(argc, argv, narg, option, &value_cstr))
return false;
if (strcmp(value_cstr, "min") == 0 || strcmp(value_cstr, "minimal") == 0 ||
strcmp(value_cstr, "fatal") == 0) {
if (strcmp(value_cstr, "min") == 0 || strcmp(value_cstr, "minimal") == 0 || strcmp(value_cstr, "fatal") == 0) {
loglevel = logging::failure;
return true;
}
@@ -308,8 +273,7 @@ bool parse_option(int argc, char *const argv[], int &narg, const char *option,
return true;
}
if (strcmp(value_cstr, "max") == 0 || strcmp(value_cstr, "maximal") == 0 ||
strcmp(value_cstr, "extra") == 0) {
if (strcmp(value_cstr, "max") == 0 || strcmp(value_cstr, "maximal") == 0 || strcmp(value_cstr, "extra") == 0) {
loglevel = logging::extra;
return true;
}
@@ -329,8 +293,7 @@ bool parse_option(int argc, char *const argv[], int &narg, const char *option,
failure("Unknown log-level '%s', for option '--%s'\n", value_cstr, option);
}
bool parse_option(int argc, char *const argv[], int &narg, const char *option,
bool &value) {
bool parse_option(int argc, char *const argv[], int &narg, const char *option, bool &value) {
const char *value_cstr = nullptr;
if (!parse_option(argc, argv, narg, option, &value_cstr, "yes")) {
const char *current = argv[narg];
@@ -338,8 +301,7 @@ bool parse_option(int argc, char *const argv[], int &narg, const char *option,
value = false;
return true;
}
if (strncmp(current, "--dont-", 7) == 0 &&
strcmp(current + 7, option) == 0) {
if (strncmp(current, "--dont-", 7) == 0 && strcmp(current + 7, option) == 0) {
value = false;
return true;
}
@@ -361,41 +323,36 @@ bool parse_option(int argc, char *const argv[], int &narg, const char *option,
return true;
}
failure(
"Option '--%s' expects a 'boolean' value Yes/No, so '%s' is unexpected\n",
option, value_cstr);
failure("Option '--%s' expects a 'boolean' value Yes/No, so '%s' is unexpected\n", option, value_cstr);
}
//-----------------------------------------------------------------------------
const struct option_verb mode_bits[] = {
{"rdonly", unsigned(MDBX_RDONLY)},
{"nosync-utterly", unsigned(MDBX_UTTERLY_NOSYNC)},
{"nosubdir", unsigned(MDBX_NOSUBDIR)},
{"nosync-safe", unsigned(MDBX_SAFE_NOSYNC)},
{"nometasync", unsigned(MDBX_NOMETASYNC)},
{"writemap", unsigned(MDBX_WRITEMAP)},
{"nostickythreads", unsigned(MDBX_NOSTICKYTHREADS)},
{"no-sticky-threads", unsigned(MDBX_NOSTICKYTHREADS)},
{"nordahead", unsigned(MDBX_NORDAHEAD)},
{"nomeminit", unsigned(MDBX_NOMEMINIT)},
{"lifo", unsigned(MDBX_LIFORECLAIM)},
{"perturb", unsigned(MDBX_PAGEPERTURB)},
{"accede", unsigned(MDBX_ACCEDE)},
{"exclusive", unsigned(MDBX_EXCLUSIVE)},
{nullptr, 0}};
const struct option_verb mode_bits[] = {{"rdonly", unsigned(MDBX_RDONLY)},
{"nosync-utterly", unsigned(MDBX_UTTERLY_NOSYNC)},
{"nosubdir", unsigned(MDBX_NOSUBDIR)},
{"nosync-safe", unsigned(MDBX_SAFE_NOSYNC)},
{"nometasync", unsigned(MDBX_NOMETASYNC)},
{"writemap", unsigned(MDBX_WRITEMAP)},
{"nostickythreads", unsigned(MDBX_NOSTICKYTHREADS)},
{"no-sticky-threads", unsigned(MDBX_NOSTICKYTHREADS)},
{"nordahead", unsigned(MDBX_NORDAHEAD)},
{"nomeminit", unsigned(MDBX_NOMEMINIT)},
{"lifo", unsigned(MDBX_LIFORECLAIM)},
{"perturb", unsigned(MDBX_PAGEPERTURB)},
{"accede", unsigned(MDBX_ACCEDE)},
{"exclusive", unsigned(MDBX_EXCLUSIVE)},
{nullptr, 0}};
const struct option_verb table_bits[] = {
{"key.reverse", unsigned(MDBX_REVERSEKEY)},
{"key.integer", unsigned(MDBX_INTEGERKEY)},
{"data.integer", unsigned(MDBX_INTEGERDUP | MDBX_DUPFIXED | MDBX_DUPSORT)},
{"data.fixed", unsigned(MDBX_DUPFIXED | MDBX_DUPSORT)},
{"data.reverse", unsigned(MDBX_REVERSEDUP | MDBX_DUPSORT)},
{"data.dups", unsigned(MDBX_DUPSORT)},
{nullptr, 0}};
const struct option_verb table_bits[] = {{"key.reverse", unsigned(MDBX_REVERSEKEY)},
{"key.integer", unsigned(MDBX_INTEGERKEY)},
{"data.integer", unsigned(MDBX_INTEGERDUP | MDBX_DUPFIXED | MDBX_DUPSORT)},
{"data.fixed", unsigned(MDBX_DUPFIXED | MDBX_DUPSORT)},
{"data.reverse", unsigned(MDBX_REVERSEDUP | MDBX_DUPSORT)},
{"data.dups", unsigned(MDBX_DUPSORT)},
{nullptr, 0}};
static void dump_verbs(const char *caption, size_t bits,
const struct option_verb *verbs) {
static void dump_verbs(const char *caption, size_t bits, const struct option_verb *verbs) {
log_verbose("%s: 0x%" PRIx64 " = ", caption, (uint64_t)bits);
const char *comma = "";
@@ -429,28 +386,21 @@ void dump(const char *title) {
logging::local_suffix indent(title);
for (auto i = global::actors.begin(); i != global::actors.end(); ++i) {
log_verbose("#%u, testcase %s, space_id/table %u\n", i->actor_id,
testcase2str(i->testcase), i->space_id);
log_verbose("#%u, testcase %s, space_id/table %u\n", i->actor_id, testcase2str(i->testcase), i->space_id);
indent.push();
log_verbose("prng-seed: %u\n", i->params.prng_seed);
if (i->params.loglevel) {
log_verbose("log: level %u, %s\n", i->params.loglevel,
i->params.pathname_log.empty()
? "console"
: i->params.pathname_log.c_str());
i->params.pathname_log.empty() ? "console" : i->params.pathname_log.c_str());
}
log_verbose("database: %s, size %" PRIuPTR "[%" PRIiPTR "..%" PRIiPTR
", %i %i, %i]\n",
i->params.pathname_db.c_str(), i->params.size_now,
i->params.size_lower, i->params.size_upper,
i->params.shrink_threshold, i->params.growth_step,
i->params.pagesize);
log_verbose("database: %s, size %" PRIuPTR "[%" PRIiPTR "..%" PRIiPTR ", %i %i, %i]\n",
i->params.pathname_db.c_str(), i->params.size_now, i->params.size_lower, i->params.size_upper,
i->params.shrink_threshold, i->params.growth_step, i->params.pagesize);
dump_verbs("mode", i->params.mode_flags, mode_bits);
log_verbose("random-writemap: %s\n",
i->params.random_writemap ? "Yes" : "No");
log_verbose("random-writemap: %s\n", i->params.random_writemap ? "Yes" : "No");
dump_verbs("table", i->params.table_flags, table_bits);
if (i->params.test_nops)
@@ -465,62 +415,46 @@ void dump(const char *title) {
log_verbose("threads %u\n", i->params.nthreads);
log_verbose(
"keygen.params: case %s, width %u, mesh %u, rotate %u, offset %" PRIu64
", split %u/%u\n",
keygencase2str(i->params.keygen.keycase), i->params.keygen.width,
i->params.keygen.mesh, i->params.keygen.rotate, i->params.keygen.offset,
i->params.keygen.split,
i->params.keygen.width - i->params.keygen.split);
log_verbose("keygen.zerofill: %s\n",
i->params.keygen.zero_fill ? "Yes" : "No");
log_verbose("key: minlen %u, maxlen %u\n", i->params.keylen_min,
i->params.keylen_max);
log_verbose("data: minlen %u, maxlen %u\n", i->params.datalen_min,
i->params.datalen_max);
log_verbose("keygen.params: case %s, width %u, mesh %u, rotate %u, offset %" PRIu64 ", split %u/%u\n",
keygencase2str(i->params.keygen.keycase), i->params.keygen.width, i->params.keygen.mesh,
i->params.keygen.rotate, i->params.keygen.offset, i->params.keygen.split,
i->params.keygen.width - i->params.keygen.split);
log_verbose("keygen.zerofill: %s\n", i->params.keygen.zero_fill ? "Yes" : "No");
log_verbose("key: minlen %u, maxlen %u\n", i->params.keylen_min, i->params.keylen_max);
log_verbose("data: minlen %u, maxlen %u\n", i->params.datalen_min, i->params.datalen_max);
log_verbose("batch: read %u, write %u\n", i->params.batch_read,
i->params.batch_write);
log_verbose("batch: read %u, write %u\n", i->params.batch_read, i->params.batch_write);
if (i->params.waitfor_nops)
log_verbose("wait: actor %u for %u ops\n", i->wait4id,
i->params.waitfor_nops);
log_verbose("wait: actor %u for %u ops\n", i->wait4id, i->params.waitfor_nops);
else if (i->params.delaystart)
dump_duration("delay", i->params.delaystart);
else
log_verbose("no-delay\n");
if (i->params.inject_writefaultn)
log_verbose("inject-writefault on %u ops\n",
i->params.inject_writefaultn);
log_verbose("inject-writefault on %u ops\n", i->params.inject_writefaultn);
else
log_verbose("no-inject-writefault\n");
log_verbose("limits: readers %u, tables %u, txn-bytes %zu\n",
i->params.max_readers, i->params.max_tables,
log_verbose("limits: readers %u, tables %u, txn-bytes %zu\n", i->params.max_readers, i->params.max_tables,
mdbx_limits_txnsize_max(i->params.pagesize));
log_verbose("drop table: %s\n", i->params.drop_table ? "Yes" : "No");
log_verbose("ignore MDBX_MAP_FULL error: %s\n",
i->params.ignore_dbfull ? "Yes" : "No");
log_verbose("verifying by speculum: %s\n",
i->params.speculum ? "Yes" : "No");
log_verbose("ignore MDBX_MAP_FULL error: %s\n", i->params.ignore_dbfull ? "Yes" : "No");
log_verbose("verifying by speculum: %s\n", i->params.speculum ? "Yes" : "No");
indent.pop();
}
dump_duration("timeout", global::config::timeout_duration_seconds);
log_verbose("cleanup: before %s, after %s\n",
global::config::cleanup_before ? "Yes" : "No",
log_verbose("cleanup: before %s, after %s\n", global::config::cleanup_before ? "Yes" : "No",
global::config::cleanup_after ? "Yes" : "No");
log_verbose("failfast: %s\n", global::config::failfast ? "Yes" : "No");
log_verbose("progress indicator: %s\n",
global::config::progress_indicator ? "Yes" : "No");
log_verbose("console mode: %s\n",
global::config::console_mode ? "Yes" : "No");
log_verbose("geometry jitter: %s\n",
global::config::geometry_jitter ? "Yes" : "No");
log_verbose("progress indicator: %s\n", global::config::progress_indicator ? "Yes" : "No");
log_verbose("console mode: %s\n", global::config::console_mode ? "Yes" : "No");
log_verbose("geometry jitter: %s\n", global::config::geometry_jitter ? "Yes" : "No");
}
} /* namespace config */
@@ -529,11 +463,8 @@ void dump(const char *title) {
using namespace config;
actor_config::actor_config(actor_testcase testcase, const actor_params &params,
unsigned space_id, unsigned wait4id)
: actor_config_pod(1 + unsigned(global::actors.size()), testcase, space_id,
wait4id),
params(params) {}
actor_config::actor_config(actor_testcase testcase, const actor_params &params, unsigned space_id, unsigned wait4id)
: actor_config_pod(1 + unsigned(global::actors.size()), testcase, space_id, wait4id), params(params) {}
const std::string actor_config::serialize(const char *prefix) const {
simple_checksum checksum;
@@ -551,25 +482,19 @@ const std::string actor_config::serialize(const char *prefix) const {
result.push_back('|');
#if __cplusplus > 201400
static_assert(std::is_trivially_copyable<actor_params_pod>::value,
"actor_params_pod should by POD");
static_assert(std::is_trivially_copyable<actor_params_pod>::value, "actor_params_pod should by POD");
#else
static_assert(std::is_standard_layout<actor_params_pod>::value,
"actor_params_pod should by POD");
static_assert(std::is_standard_layout<actor_params_pod>::value, "actor_params_pod should by POD");
#endif
result.append(data2hex(static_cast<const actor_params_pod *>(&params),
sizeof(actor_params_pod), checksum));
result.append(data2hex(static_cast<const actor_params_pod *>(&params), sizeof(actor_params_pod), checksum));
result.push_back('|');
#if __cplusplus > 201400
static_assert(std::is_trivially_copyable<actor_config_pod>::value,
"actor_config_pod should by POD");
static_assert(std::is_trivially_copyable<actor_config_pod>::value, "actor_config_pod should by POD");
#else
static_assert(std::is_standard_layout<actor_config_pod>::value,
"actor_config_pod should by POD");
static_assert(std::is_standard_layout<actor_config_pod>::value, "actor_config_pod should by POD");
#endif
result.append(data2hex(static_cast<const actor_config_pod *>(this),
sizeof(actor_config_pod), checksum));
result.append(data2hex(static_cast<const actor_config_pod *>(this), sizeof(actor_config_pod), checksum));
result.push_back('|');
result.push_back(global::config::progress_indicator ? 'Y' : 'N');
checksum.push(global::config::progress_indicator);
@@ -615,16 +540,12 @@ bool actor_config::deserialize(const char *str, actor_config &config) {
return false;
}
#if __cplusplus > 201400
static_assert(std::is_trivially_copyable<actor_params_pod>::value,
"actor_params_pod should by POD");
static_assert(std::is_trivially_copyable<actor_params_pod>::value, "actor_params_pod should by POD");
#else
static_assert(std::is_standard_layout<actor_params_pod>::value,
"actor_params_pod should by POD");
static_assert(std::is_standard_layout<actor_params_pod>::value, "actor_params_pod should by POD");
#endif
if (!hex2data(str, slash, static_cast<actor_params_pod *>(&config.params),
sizeof(actor_params_pod), checksum)) {
TRACE("<< actor_config::deserialize: actor_params_pod(%.*s)\n",
(int)(slash - str), str);
if (!hex2data(str, slash, static_cast<actor_params_pod *>(&config.params), sizeof(actor_params_pod), checksum)) {
TRACE("<< actor_config::deserialize: actor_params_pod(%.*s)\n", (int)(slash - str), str);
return false;
}
str = slash + 1;
@@ -635,16 +556,12 @@ bool actor_config::deserialize(const char *str, actor_config &config) {
return false;
}
#if __cplusplus > 201400
static_assert(std::is_trivially_copyable<actor_config_pod>::value,
"actor_config_pod should by POD");
static_assert(std::is_trivially_copyable<actor_config_pod>::value, "actor_config_pod should by POD");
#else
static_assert(std::is_standard_layout<actor_config_pod>::value,
"actor_config_pod should by POD");
static_assert(std::is_standard_layout<actor_config_pod>::value, "actor_config_pod should by POD");
#endif
if (!hex2data(str, slash, static_cast<actor_config_pod *>(&config),
sizeof(actor_config_pod), checksum)) {
TRACE("<< actor_config::deserialize: actor_config_pod(%.*s)\n",
(int)(slash - str), str);
if (!hex2data(str, slash, static_cast<actor_config_pod *>(&config), sizeof(actor_config_pod), checksum)) {
TRACE("<< actor_config::deserialize: actor_config_pod(%.*s)\n", (int)(slash - str), str);
return false;
}
str = slash + 1;
@@ -654,8 +571,7 @@ bool actor_config::deserialize(const char *str, actor_config &config) {
TRACE("<< actor_config::deserialize: slash-5\n");
return false;
}
if ((str[0] == 'Y' || str[0] == 'N') && (str[1] == 'Y' || str[1] == 'N') &&
(str[2] == 'Y' || str[2] == 'N')) {
if ((str[0] == 'Y' || str[0] == 'N') && (str[1] == 'Y' || str[1] == 'N') && (str[2] == 'Y' || str[2] == 'N')) {
global::config::progress_indicator = str[0] == 'Y';
checksum.push(global::config::progress_indicator);
global::config::console_mode = str[1] == 'Y';
@@ -690,21 +606,14 @@ bool actor_config::deserialize(const char *str, actor_config &config) {
return true;
}
unsigned actor_params::mdbx_keylen_min() const {
return unsigned(mdbx_limits_keysize_min(table_flags));
}
unsigned actor_params::mdbx_keylen_min() const { return unsigned(mdbx_limits_keysize_min(table_flags)); }
unsigned actor_params::mdbx_keylen_max() const {
return unsigned(mdbx_limits_keysize_max(pagesize, table_flags));
}
unsigned actor_params::mdbx_keylen_max() const { return unsigned(mdbx_limits_keysize_max(pagesize, table_flags)); }
unsigned actor_params::mdbx_datalen_min() const {
return unsigned(mdbx_limits_valsize_min(table_flags));
}
unsigned actor_params::mdbx_datalen_min() const { return unsigned(mdbx_limits_valsize_min(table_flags)); }
unsigned actor_params::mdbx_datalen_max() const {
return std::min(unsigned(UINT16_MAX),
unsigned(mdbx_limits_valsize_max(pagesize, table_flags)));
return std::min(unsigned(UINT16_MAX), unsigned(mdbx_limits_valsize_max(pagesize, table_flags)));
}
bool actor_params::make_keygen_linear() {
@@ -713,26 +622,18 @@ bool actor_params::make_keygen_linear() {
keygen.rotate = 0;
keygen.offset = 0;
const auto max_serial = serial_mask(keygen.width) + base;
const auto max_key_serial = (keygen.split && (table_flags & MDBX_DUPSORT))
? max_serial >> keygen.split
: max_serial;
const auto max_value_serial = (keygen.split && (table_flags & MDBX_DUPSORT))
? serial_mask(keygen.split)
: 0;
const auto max_key_serial = (keygen.split && (table_flags & MDBX_DUPSORT)) ? max_serial >> keygen.split : max_serial;
const auto max_value_serial = (keygen.split && (table_flags & MDBX_DUPSORT)) ? serial_mask(keygen.split) : 0;
while (keylen_min < 8 &&
(keylen_min == 0 || serial_mask(keylen_min * 8) < max_key_serial)) {
while (keylen_min < 8 && (keylen_min == 0 || serial_mask(keylen_min * 8) < max_key_serial)) {
keylen_min += (table_flags & (MDBX_INTEGERKEY | MDBX_INTEGERDUP)) ? 4 : 1;
if (keylen_max < keylen_min)
keylen_max = keylen_min;
}
if (table_flags & MDBX_DUPSORT)
while (
datalen_min < 8 &&
(datalen_min == 0 || serial_mask(datalen_min * 8) < max_value_serial)) {
datalen_min +=
(table_flags & (MDBX_INTEGERKEY | MDBX_INTEGERDUP)) ? 4 : 1;
while (datalen_min < 8 && (datalen_min == 0 || serial_mask(datalen_min * 8) < max_value_serial)) {
datalen_min += (table_flags & (MDBX_INTEGERKEY | MDBX_INTEGERDUP)) ? 4 : 1;
if (datalen_max < datalen_min)
datalen_max = datalen_min;
}

View File

@@ -54,18 +54,16 @@ namespace config {
enum scale_mode { no_scale, decimal, binary, duration, intkey, entropy };
bool parse_option(int argc, char *const argv[], int &narg, const char *option,
const char **value, const char *default_value = nullptr);
bool parse_option(int argc, char *const argv[], int &narg, const char *option, const char **value,
const char *default_value = nullptr);
bool parse_option(int argc, char *const argv[], int &narg, const char *option,
std::string &value, bool allow_empty = false);
bool parse_option(int argc, char *const argv[], int &narg, const char *option, std::string &value,
bool allow_empty = false);
bool parse_option(int argc, char *const argv[], int &narg, const char *option,
std::string &value, bool allow_empty,
bool parse_option(int argc, char *const argv[], int &narg, const char *option, std::string &value, bool allow_empty,
const char *default_value);
bool parse_option(int argc, char *const argv[], int &narg, const char *option,
bool &value);
bool parse_option(int argc, char *const argv[], int &narg, const char *option, bool &value);
struct option_verb {
const char *const verb;
@@ -73,8 +71,7 @@ struct option_verb {
};
template <typename MASK>
bool parse_option(int argc, char *const argv[], int &narg, const char *option,
MASK &mask, const option_verb *verbs) {
bool parse_option(int argc, char *const argv[], int &narg, const char *option, MASK &mask, const option_verb *verbs) {
static_assert(sizeof(MASK) <= sizeof(unsigned), "WTF?");
unsigned u = unsigned(mask);
if (parse_option<unsigned>(argc, argv, narg, option, u, verbs)) {
@@ -85,49 +82,36 @@ bool parse_option(int argc, char *const argv[], int &narg, const char *option,
}
template <>
bool parse_option<unsigned>(int argc, char *const argv[], int &narg,
const char *option, unsigned &mask,
bool parse_option<unsigned>(int argc, char *const argv[], int &narg, const char *option, unsigned &mask,
const option_verb *verbs);
bool parse_option(int argc, char *const argv[], int &narg, const char *option,
uint64_t &value, const scale_mode scale,
const uint64_t minval = 0, const uint64_t maxval = INT64_MAX,
const uint64_t default_value = 0);
bool parse_option(int argc, char *const argv[], int &narg, const char *option, uint64_t &value, const scale_mode scale,
const uint64_t minval = 0, const uint64_t maxval = INT64_MAX, const uint64_t default_value = 0);
bool parse_option(int argc, char *const argv[], int &narg, const char *option,
unsigned &value, const scale_mode scale,
const unsigned minval = 0, const unsigned maxval = INT32_MAX,
const unsigned default_value = 0);
bool parse_option(int argc, char *const argv[], int &narg, const char *option, unsigned &value, const scale_mode scale,
const unsigned minval = 0, const unsigned maxval = INT32_MAX, const unsigned default_value = 0);
bool parse_option(int argc, char *const argv[], int &narg, const char *option,
uint8_t &value, const uint8_t minval = 0,
bool parse_option(int argc, char *const argv[], int &narg, const char *option, uint8_t &value, const uint8_t minval = 0,
const uint8_t maxval = 255, const uint8_t default_value = 0);
bool parse_option(int argc, char *const argv[], int &narg, const char *option,
int64_t &value, const int64_t minval, const int64_t maxval,
const int64_t default_value = -1);
bool parse_option(int argc, char *const argv[], int &narg, const char *option, int64_t &value, const int64_t minval,
const int64_t maxval, const int64_t default_value = -1);
bool parse_option(int argc, char *const argv[], int &narg, const char *option,
int32_t &value, const int32_t minval, const int32_t maxval,
const int32_t default_value = -1);
bool parse_option(int argc, char *const argv[], int &narg, const char *option, int32_t &value, const int32_t minval,
const int32_t maxval, const int32_t default_value = -1);
inline bool parse_option_intptr(int argc, char *const argv[], int &narg,
const char *option, intptr_t &value,
const intptr_t minval, const intptr_t maxval,
const intptr_t default_value = -1) {
inline bool parse_option_intptr(int argc, char *const argv[], int &narg, const char *option, intptr_t &value,
const intptr_t minval, const intptr_t maxval, const intptr_t default_value = -1) {
static_assert(sizeof(intptr_t) == 4 || sizeof(intptr_t) == 8, "WTF?");
if (sizeof(intptr_t) == 8)
return parse_option(argc, argv, narg, option,
*reinterpret_cast<int64_t *>(&value), int64_t(minval),
return parse_option(argc, argv, narg, option, *reinterpret_cast<int64_t *>(&value), int64_t(minval),
int64_t(maxval), int64_t(default_value));
else
return parse_option(argc, argv, narg, option,
*reinterpret_cast<int32_t *>(&value), int32_t(minval),
return parse_option(argc, argv, narg, option, *reinterpret_cast<int32_t *>(&value), int32_t(minval),
int32_t(maxval), int32_t(default_value));
}
bool parse_option(int argc, char *const argv[], int &narg, const char *option,
logging::loglevel &);
bool parse_option(int argc, char *const argv[], int &narg, const char *option, logging::loglevel &);
//-----------------------------------------------------------------------------
struct keygen_params_pod {
@@ -295,10 +279,8 @@ struct actor_config_pod {
unsigned signal_nops{0};
actor_config_pod() = default;
actor_config_pod(unsigned actor_id, actor_testcase testcase,
unsigned space_id, unsigned wait4id)
: actor_id(actor_id), space_id(space_id), testcase(testcase),
wait4id(wait4id) {}
actor_config_pod(unsigned actor_id, actor_testcase testcase, unsigned space_id, unsigned wait4id)
: actor_id(actor_id), space_id(space_id), testcase(testcase), wait4id(wait4id) {}
};
extern const struct option_verb mode_bits[];
@@ -326,8 +308,7 @@ struct actor_config : public config::actor_config_pod {
bool wanna_event4signalling() const { return true /* TODO ? */; }
actor_config() = default;
actor_config(actor_testcase testcase, const actor_params &params,
unsigned space_id, unsigned wait4id);
actor_config(actor_testcase testcase, const actor_params &params, unsigned space_id, unsigned wait4id);
actor_config(const char *str) : actor_config() {
if (!deserialize(str, *this))

View File

@@ -9,8 +9,7 @@ class testcase_copy : public testcase {
public:
testcase_copy(const actor_config &config, const mdbx_pid_t pid)
: testcase(config, pid),
copy_pathname(config.params.pathname_db + "-copy") {}
: testcase(config, pid), copy_pathname(config.params.pathname_db + "-copy") {}
bool run() override;
};
REGISTER_TESTCASE(copy);
@@ -21,14 +20,10 @@ void testcase_copy::copy_db(const bool with_compaction) {
failure_perror("osal_removefile()", err);
if (flipcoin()) {
err = mdbx_env_copy(db_guard.get(), copy_pathname.c_str(),
with_compaction ? MDBX_CP_COMPACT : MDBX_CP_DEFAULTS);
log_verbose("mdbx_env_copy(%s), err %d", with_compaction ? "true" : "false",
err);
err = mdbx_env_copy(db_guard.get(), copy_pathname.c_str(), with_compaction ? MDBX_CP_COMPACT : MDBX_CP_DEFAULTS);
log_verbose("mdbx_env_copy(%s), err %d", with_compaction ? "true" : "false", err);
if (unlikely(err != MDBX_SUCCESS))
failure_perror(with_compaction ? "mdbx_env_copy(MDBX_CP_COMPACT)"
: "mdbx_env_copy(MDBX_CP_ASIS)",
err);
failure_perror(with_compaction ? "mdbx_env_copy(MDBX_CP_COMPACT)" : "mdbx_env_copy(MDBX_CP_ASIS)", err);
} else {
do {
const bool ro = mode_readonly() || flipcoin();
@@ -36,26 +31,20 @@ void testcase_copy::copy_db(const bool with_compaction) {
const bool dynsize = flipcoin();
const bool flush = flipcoin();
const bool enable_renew = flipcoin();
const MDBX_copy_flags_t flags =
(with_compaction ? MDBX_CP_COMPACT : MDBX_CP_DEFAULTS) |
(dynsize ? MDBX_CP_FORCE_DYNAMIC_SIZE : MDBX_CP_DEFAULTS) |
(throttle ? MDBX_CP_THROTTLE_MVCC : MDBX_CP_DEFAULTS) |
(flush ? MDBX_CP_DEFAULTS : MDBX_CP_DONT_FLUSH) |
(enable_renew ? MDBX_CP_RENEW_TXN : MDBX_CP_DEFAULTS);
const MDBX_copy_flags_t flags = (with_compaction ? MDBX_CP_COMPACT : MDBX_CP_DEFAULTS) |
(dynsize ? MDBX_CP_FORCE_DYNAMIC_SIZE : MDBX_CP_DEFAULTS) |
(throttle ? MDBX_CP_THROTTLE_MVCC : MDBX_CP_DEFAULTS) |
(flush ? MDBX_CP_DEFAULTS : MDBX_CP_DONT_FLUSH) |
(enable_renew ? MDBX_CP_RENEW_TXN : MDBX_CP_DEFAULTS);
txn_begin(ro);
err =
mdbx_txn_copy2pathname(txn_guard.get(), copy_pathname.c_str(), flags);
err = mdbx_txn_copy2pathname(txn_guard.get(), copy_pathname.c_str(), flags);
log_verbose("mdbx_txn_copy2pathname(flags=0x%X), err %d", flags, err);
txn_end(err != MDBX_SUCCESS || flipcoin());
if (unlikely(
err != MDBX_SUCCESS && !(throttle && err == MDBX_OUSTED) &&
!(!enable_renew && err == MDBX_MVCC_RETARDED) &&
!(err == MDBX_EINVAL && !ro &&
(flags & (MDBX_CP_THROTTLE_MVCC | MDBX_CP_RENEW_TXN)) != 0)))
failure_perror(with_compaction
? "mdbx_txn_copy2pathname(MDBX_CP_COMPACT)"
: "mdbx_txn_copy2pathname(MDBX_CP_ASIS)",
err);
if (unlikely(err != MDBX_SUCCESS && !(throttle && err == MDBX_OUSTED) &&
!(!enable_renew && err == MDBX_MVCC_RETARDED) &&
!(err == MDBX_EINVAL && !ro && (flags & (MDBX_CP_THROTTLE_MVCC | MDBX_CP_RENEW_TXN)) != 0)))
failure_perror(
with_compaction ? "mdbx_txn_copy2pathname(MDBX_CP_COMPACT)" : "mdbx_txn_copy2pathname(MDBX_CP_ASIS)", err);
} while (err != MDBX_SUCCESS);
}
}

View File

@@ -5,8 +5,7 @@
class testcase_deadread : public testcase {
public:
testcase_deadread(const actor_config &config, const mdbx_pid_t pid)
: testcase(config, pid) {}
testcase_deadread(const actor_config &config, const mdbx_pid_t pid) : testcase(config, pid) {}
bool run() override;
};
REGISTER_TESTCASE(deadread);
@@ -24,8 +23,7 @@ bool testcase_deadread::run() {
class testcase_deadwrite : public testcase {
public:
testcase_deadwrite(const actor_config &config, const mdbx_pid_t pid)
: testcase(config, pid) {}
testcase_deadwrite(const actor_config &config, const mdbx_pid_t pid) : testcase(config, pid) {}
bool run() override;
};

View File

@@ -26,8 +26,7 @@ std::string format_va(const char *fmt, va_list ap) {
result.reserve(size_t(needed + 1));
result.resize(size_t(needed), '\0');
assert(int(result.capacity()) > needed);
int actual = vsnprintf(const_cast<char *>(result.data()), result.capacity(),
fmt, ones);
int actual = vsnprintf(const_cast<char *>(result.data()), result.capacity(), fmt, ones);
assert(actual == needed);
(void)actual;
va_end(ones);
@@ -47,10 +46,8 @@ struct acase {
unsigned vlen_min, vlen_max;
unsigned dupmax_log2;
acase(unsigned klen_min, unsigned klen_max, unsigned vlen_min,
unsigned vlen_max, unsigned dupmax_log2)
: klen_min(klen_min), klen_max(klen_max), vlen_min(vlen_min),
vlen_max(vlen_max), dupmax_log2(dupmax_log2) {}
acase(unsigned klen_min, unsigned klen_max, unsigned vlen_min, unsigned vlen_max, unsigned dupmax_log2)
: klen_min(klen_min), klen_max(klen_max), vlen_min(vlen_min), vlen_max(vlen_max), dupmax_log2(dupmax_log2) {}
};
// std::random_device rd;
@@ -80,33 +77,26 @@ static mdbx::slice mk_val(mdbx::default_buffer &buf, const acase &thecase) {
static std::string name(unsigned n) { return format("Commitment_%05u", n); }
static mdbx::map_handle create_and_fill(mdbx::txn txn, const acase &thecase,
const unsigned n) {
static mdbx::map_handle create_and_fill(mdbx::txn txn, const acase &thecase, const unsigned n) {
auto map = txn.create_map(name(n),
(thecase.klen_min == thecase.klen_max &&
(thecase.klen_min == 4 || thecase.klen_max == 8))
(thecase.klen_min == thecase.klen_max && (thecase.klen_min == 4 || thecase.klen_max == 8))
? mdbx::key_mode::ordinal
: mdbx::key_mode::usual,
(thecase.vlen_min == thecase.vlen_max)
? mdbx::value_mode::multi_samelength
: mdbx::value_mode::multi);
(thecase.vlen_min == thecase.vlen_max) ? mdbx::value_mode::multi_samelength
: mdbx::value_mode::multi);
if (txn.get_map_stat(map).ms_entries < NN) {
mdbx::default_buffer k, v;
for (auto i = 0u; i < NN; i++) {
mk_key(k, thecase);
for (auto ii = thecase.dupmax_log2
? 1u + (rnd() & ((2u << thecase.dupmax_log2) - 1u))
: 1u;
ii > 0; --ii)
for (auto ii = thecase.dupmax_log2 ? 1u + (rnd() & ((2u << thecase.dupmax_log2) - 1u)) : 1u; ii > 0; --ii)
txn.upsert(map, k, mk_val(v, thecase));
}
}
return map;
}
static void chunched_delete(mdbx::txn txn, const acase &thecase,
const unsigned n) {
static void chunched_delete(mdbx::txn txn, const acase &thecase, const unsigned n) {
// printf(">> %s, case #%i\n", __FUNCTION__, n);
mdbx::default_buffer k, v;
auto map = txn.open_map_accede(name(n));
@@ -121,27 +111,20 @@ static void chunched_delete(mdbx::txn txn, const acase &thecase,
bool last_r;
if (true == ((last_op = "MDBX_GET_BOTH"),
(last_r = cursor.find_multivalue(
mk_key(k, thecase), mk_val(v, thecase), false))) ||
(last_r = cursor.find_multivalue(mk_key(k, thecase), mk_val(v, thecase), false))) ||
rnd() % 3 == 0 ||
true == ((last_op = "MDBX_SET_RANGE"),
(last_r = cursor.lower_bound(mk_key(k, thecase), false)))) {
true == ((last_op = "MDBX_SET_RANGE"), (last_r = cursor.lower_bound(mk_key(k, thecase), false)))) {
int i = int(rnd() % 7) - 3;
// if (i)
// printf(" %s -> %s\n", last_op, last_r ? "true" : "false");
// printf("== shift multi %i\n", i);
try {
while (i < 0 &&
true == ((last_op = "MDBX_PREV_DUP"),
(last_r = cursor.to_current_prev_multi(false))))
while (i < 0 && true == ((last_op = "MDBX_PREV_DUP"), (last_r = cursor.to_current_prev_multi(false))))
++i;
while (i > 0 &&
true == ((last_op = "MDBX_NEXT_DUP"),
(last_r = cursor.to_current_next_multi(false))))
while (i > 0 && true == ((last_op = "MDBX_NEXT_DUP"), (last_r = cursor.to_current_next_multi(false))))
--i;
} catch (const mdbx::no_data &) {
printf("cursor_del() -> exception, last %s %s\n", last_op,
last_r ? "true" : "false");
printf("cursor_del() -> exception, last %s %s\n", last_op, last_r ? "true" : "false");
continue;
}
}
@@ -159,8 +142,7 @@ static void chunched_delete(mdbx::txn txn, const acase &thecase,
// printf(" cursor_del() -> %s\n", last_r ? "true" : "false");
} while (cursor.to_next(false) && --i > 0);
} catch (const mdbx::no_data &) {
printf("cursor_del() -> exception, last %s %s\n", last_op,
last_r ? "true" : "false");
printf("cursor_del() -> exception, last %s %s\n", last_op, last_r ? "true" : "false");
}
// (void) last_op;
@@ -178,8 +160,8 @@ static void chunched_delete(mdbx::txn txn, const acase &thecase,
static char log_buffer[1024];
static void logger_nofmt(MDBX_log_level_t loglevel, const char *function,
int line, const char *msg, unsigned length) noexcept {
static void logger_nofmt(MDBX_log_level_t loglevel, const char *function, int line, const char *msg,
unsigned length) noexcept {
(void)length;
(void)loglevel;
fprintf(stdout, "%s:%u %s", function, line, msg);
@@ -187,12 +169,10 @@ static void logger_nofmt(MDBX_log_level_t loglevel, const char *function,
bool outofrange_prev(mdbx::env env) {
mdbx::cursor_managed cursor;
const std::array<mdbx::pair, 4> items = {
{{"k1", "v1"}, {"k1", "v2"}, {"k2", "v1"}, {"k2", "v2"}}};
const std::array<mdbx::pair, 4> items = {{{"k1", "v1"}, {"k1", "v2"}, {"k2", "v1"}, {"k2", "v2"}}};
auto txn = env.start_write();
auto multi =
txn.create_map("multi", mdbx::key_mode::usual, mdbx::value_mode::multi);
auto multi = txn.create_map("multi", mdbx::key_mode::usual, mdbx::value_mode::multi);
auto simple = txn.create_map("simple");
txn.clear_map(multi);
txn.clear_map(simple);
@@ -242,12 +222,10 @@ bool outofrange_prev(mdbx::env env) {
}
bool next_prev_current(mdbx::env env) {
const std::array<mdbx::pair, 4> items = {
{{"k1", "v1"}, {"k1", "v2"}, {"k2", "v1"}, {"k2", "v2"}}};
const std::array<mdbx::pair, 4> items = {{{"k1", "v1"}, {"k1", "v2"}, {"k2", "v1"}, {"k2", "v2"}}};
auto txn = env.start_write();
auto map =
txn.create_map("multi", mdbx::key_mode::usual, mdbx::value_mode::multi);
auto map = txn.create_map("multi", mdbx::key_mode::usual, mdbx::value_mode::multi);
txn.clear_map(map);
for (const auto &i : items)
txn.upsert(map, i);
@@ -309,8 +287,7 @@ bool next_prev_current(mdbx::env env) {
}
bool simple(mdbx::env env) {
const std::array<mdbx::pair, 3> items = {
{{"k0", "v0"}, {"k1", "v1"}, {"k2", "v2"}}};
const std::array<mdbx::pair, 3> items = {{{"k0", "v0"}, {"k1", "v1"}, {"k2", "v2"}}};
auto txn = env.start_write();
auto map = txn.create_map("simple");
@@ -376,14 +353,12 @@ int main(int argc, const char *argv[]) {
(void)argc;
(void)argv;
mdbx_setup_debug_nofmt(MDBX_LOG_NOTICE, MDBX_DBG_ASSERT, logger_nofmt,
log_buffer, sizeof(log_buffer));
mdbx_setup_debug_nofmt(MDBX_LOG_NOTICE, MDBX_DBG_ASSERT, logger_nofmt, log_buffer, sizeof(log_buffer));
mdbx::path db_filename = "test-crunched-del";
mdbx::env::remove(db_filename);
mdbx::env_managed env(db_filename, mdbx::env_managed::create_parameters(),
mdbx::env::operate_parameters(42));
mdbx::env_managed env(db_filename, mdbx::env_managed::create_parameters(), mdbx::env::operate_parameters(42));
if (!simple(env) || !next_prev_current(env) || !outofrange_prev(env))
return EXIT_FAILURE;
@@ -392,8 +367,7 @@ int main(int argc, const char *argv[]) {
// Значения разной длины от 100 до 1000 байт.
testset.emplace_back(/* keylen_min */ 1, /* keylen_max */ 64,
/* datalen_min */ 100, /* datalen_max */
mdbx_env_get_valsize4page_max(
env, MDBX_db_flags_t(mdbx::value_mode::multi)),
mdbx_env_get_valsize4page_max(env, MDBX_db_flags_t(mdbx::value_mode::multi)),
/* dups_log2 */ 6);
// В одной таблице DupSort: path -> version_u64+data
// path - это префикс в дереве. Самые частые длины: 1-5 байт и 32-36 байт.

View File

@@ -2,8 +2,8 @@
#include <iostream>
static void logger_nofmt(MDBX_log_level_t loglevel, const char *function,
int line, const char *msg, unsigned length) noexcept {
static void logger_nofmt(MDBX_log_level_t loglevel, const char *function, int line, const char *msg,
unsigned length) noexcept {
(void)length;
(void)loglevel;
std::cout << function << ":" << line << " " << msg;
@@ -15,20 +15,17 @@ int main(int argc, const char *argv[]) {
(void)argc;
(void)argv;
mdbx_setup_debug_nofmt(MDBX_LOG_NOTICE, MDBX_DBG_ASSERT, logger_nofmt,
log_buffer, sizeof(log_buffer));
mdbx_setup_debug_nofmt(MDBX_LOG_NOTICE, MDBX_DBG_ASSERT, logger_nofmt, log_buffer, sizeof(log_buffer));
mdbx::path db_filename = "test-cursor-closing";
mdbx::env::remove(db_filename);
mdbx::env_managed env(
db_filename, mdbx::env_managed::create_parameters(),
mdbx::env::operate_parameters(42, 0, mdbx::env::nested_transactions));
mdbx::env_managed env(db_filename, mdbx::env_managed::create_parameters(),
mdbx::env::operate_parameters(42, 0, mdbx::env::nested_transactions));
{
auto txn = env.start_write();
auto table = txn.create_map("dummy", mdbx::key_mode::usual,
mdbx::value_mode::single);
auto table = txn.create_map("dummy", mdbx::key_mode::usual, mdbx::value_mode::single);
auto cursor_1 = txn.open_cursor(table);
auto cursor_2 = cursor_1.clone();

View File

@@ -4,8 +4,8 @@
static char log_buffer[1024];
static void logger_nofmt(MDBX_log_level_t loglevel, const char *function,
int line, const char *msg, unsigned length) noexcept {
static void logger_nofmt(MDBX_log_level_t loglevel, const char *function, int line, const char *msg,
unsigned length) noexcept {
(void)length;
(void)loglevel;
fprintf(stdout, "%s:%u %s", function, line, msg);
@@ -15,8 +15,7 @@ int main(int argc, const char *argv[]) {
(void)argc;
(void)argv;
mdbx_setup_debug_nofmt(MDBX_LOG_NOTICE, MDBX_DBG_ASSERT, logger_nofmt,
log_buffer, sizeof(log_buffer));
mdbx_setup_debug_nofmt(MDBX_LOG_NOTICE, MDBX_DBG_ASSERT, logger_nofmt, log_buffer, sizeof(log_buffer));
mdbx::path db_filename = "test-dbi";
mdbx::env::remove(db_filename);
@@ -26,14 +25,12 @@ int main(int argc, const char *argv[]) {
{
mdbx::env_managed env2(db_filename, createParameters, operateParameters);
mdbx::txn_managed txn2 = env2.start_write(false);
/* mdbx::map_handle testHandle2 = */ txn2.create_map(
"fap1", mdbx::key_mode::reverse, mdbx::value_mode::single);
/* mdbx::map_handle testHandle2 = */ txn2.create_map("fap1", mdbx::key_mode::reverse, mdbx::value_mode::single);
txn2.commit();
}
mdbx::env_managed env(db_filename, createParameters, operateParameters);
mdbx::txn_managed txn = env.start_write(false);
/* mdbx::map_handle testHandle = */ txn.create_map(
"fap1", mdbx::key_mode::usual, mdbx::value_mode::single);
/* mdbx::map_handle testHandle = */ txn.create_map("fap1", mdbx::key_mode::usual, mdbx::value_mode::single);
txn.commit();
std::cout << "OK\n";

View File

@@ -7,8 +7,7 @@
#include <iostream>
#include <random>
static ::std::ostream &operator<<(::std::ostream &out,
const mdbx::cursor::move_operation op) {
static ::std::ostream &operator<<(::std::ostream &out, const mdbx::cursor::move_operation op) {
static const char *const str[] = {"FIRST",
"FIRST_DUP",
"GET_BOTH",
@@ -70,54 +69,45 @@ static buffer random_value() { return random(prng() % 47); }
using predicate = std::function<bool(const mdbx::pair &, const mdbx::pair &)>;
static bool probe(mdbx::txn txn, mdbx::map_handle dbi,
mdbx::cursor::move_operation op, predicate cmp,
static bool probe(mdbx::txn txn, mdbx::map_handle dbi, mdbx::cursor::move_operation op, predicate cmp,
const buffer_pair &pair) {
auto seeker = txn.open_cursor(dbi);
auto scanner = seeker.clone();
const bool scan_backward =
op == mdbx::cursor::key_lesser_than ||
op == mdbx::cursor::key_lesser_or_equal ||
op == mdbx::cursor::multi_exactkey_value_lesser_than ||
op == mdbx::cursor::multi_exactkey_value_lesser_or_equal ||
op == mdbx::cursor::pair_lesser_than ||
op == mdbx::cursor::pair_lesser_or_equal;
const bool scan_backward = op == mdbx::cursor::key_lesser_than || op == mdbx::cursor::key_lesser_or_equal ||
op == mdbx::cursor::multi_exactkey_value_lesser_than ||
op == mdbx::cursor::multi_exactkey_value_lesser_or_equal ||
op == mdbx::cursor::pair_lesser_than || op == mdbx::cursor::pair_lesser_or_equal;
const bool is_multi = mdbx::is_multi(txn.get_handle_info(dbi).value_mode());
auto seek_result = seeker.move(op, pair.key, pair.value, false);
auto scan_result = scanner.fullscan(
[cmp, &pair](const mdbx::pair &scan) -> bool { return cmp(scan, pair); },
scan_backward);
auto scan_result =
scanner.fullscan([cmp, &pair](const mdbx::pair &scan) -> bool { return cmp(scan, pair); }, scan_backward);
if (seek_result.done == scan_result &&
(!scan_result ||
seeker.is_same_position(
scanner,
op < mdbx::cursor::multi_exactkey_value_lesser_than && is_multi)))
seeker.is_same_position(scanner, op < mdbx::cursor::multi_exactkey_value_lesser_than && is_multi)))
return true;
std::cerr << std::endl;
std::cerr << "bug:";
std::cerr << std::endl;
std::cerr << std::string(is_multi ? "multi" : "single") << "-map, op " << op
<< ", key " << pair.key << ", value " << pair.value;
std::cerr << std::string(is_multi ? "multi" : "single") << "-map, op " << op << ", key " << pair.key << ", value "
<< pair.value;
std::cerr << std::endl;
std::cerr << "\tscanner: ";
if (scan_result)
std::cerr << " done, key " << scanner.current(false).key << ", value "
<< scanner.current(false).value;
std::cerr << " done, key " << scanner.current(false).key << ", value " << scanner.current(false).value;
else
std::cerr << "not-found";
std::cerr << std::endl;
std::cerr << "\t seeker: " << (seek_result.done ? " done" : "not-found")
<< ", key " << seek_result.key << ", value " << seek_result.value;
std::cerr << "\t seeker: " << (seek_result.done ? " done" : "not-found") << ", key " << seek_result.key
<< ", value " << seek_result.value;
std::cerr << std::endl;
return false;
}
static bool probe(mdbx::txn txn, mdbx::map_handle dbi,
mdbx::cursor::move_operation op, predicate cmp) {
static bool probe(mdbx::txn txn, mdbx::map_handle dbi, mdbx::cursor::move_operation op, predicate cmp) {
const auto pair = buffer_pair(random_key(), random_value());
const bool ok = probe(txn, dbi, op, cmp, pair);
#if MDBX_DEBUG
@@ -159,32 +149,27 @@ static bool test(mdbx::txn txn, mdbx::map_handle dbi) {
ok = probe(txn, dbi, mdbx::cursor::multi_exactkey_value_lesser_than,
[txn, dbi](const mdbx::pair &l, const mdbx::pair &r) -> bool {
return mdbx_cmp(txn, dbi, l.key, r.key) == 0 &&
mdbx_dcmp(txn, dbi, l.value, r.value) < 0;
return mdbx_cmp(txn, dbi, l.key, r.key) == 0 && mdbx_dcmp(txn, dbi, l.value, r.value) < 0;
}) &&
ok;
ok = probe(txn, dbi, mdbx::cursor::multi_exactkey_value_lesser_or_equal,
[txn, dbi](const mdbx::pair &l, const mdbx::pair &r) -> bool {
return mdbx_cmp(txn, dbi, l.key, r.key) == 0 &&
mdbx_dcmp(txn, dbi, l.value, r.value) <= 0;
return mdbx_cmp(txn, dbi, l.key, r.key) == 0 && mdbx_dcmp(txn, dbi, l.value, r.value) <= 0;
}) &&
ok;
ok = probe(txn, dbi, mdbx::cursor::multi_exactkey_value_equal,
[txn, dbi](const mdbx::pair &l, const mdbx::pair &r) -> bool {
return mdbx_cmp(txn, dbi, l.key, r.key) == 0 &&
mdbx_dcmp(txn, dbi, l.value, r.value) == 0;
return mdbx_cmp(txn, dbi, l.key, r.key) == 0 && mdbx_dcmp(txn, dbi, l.value, r.value) == 0;
}) &&
ok;
ok = probe(txn, dbi, mdbx::cursor::multi_exactkey_value_greater_or_equal,
[txn, dbi](const mdbx::pair &l, const mdbx::pair &r) -> bool {
return mdbx_cmp(txn, dbi, l.key, r.key) == 0 &&
mdbx_dcmp(txn, dbi, l.value, r.value) >= 0;
return mdbx_cmp(txn, dbi, l.key, r.key) == 0 && mdbx_dcmp(txn, dbi, l.value, r.value) >= 0;
}) &&
ok;
ok = probe(txn, dbi, mdbx::cursor::multi_exactkey_value_greater,
[txn, dbi](const mdbx::pair &l, const mdbx::pair &r) -> bool {
return mdbx_cmp(txn, dbi, l.key, r.key) == 0 &&
mdbx_dcmp(txn, dbi, l.value, r.value) > 0;
return mdbx_cmp(txn, dbi, l.key, r.key) == 0 && mdbx_dcmp(txn, dbi, l.value, r.value) > 0;
}) &&
ok;
@@ -205,9 +190,7 @@ static bool test(mdbx::txn txn, mdbx::map_handle dbi) {
}) &&
ok;
ok = probe(txn, dbi, mdbx::cursor::pair_equal,
[](const mdbx::pair &l, const mdbx::pair &r) -> bool {
return l == r;
}) &&
[](const mdbx::pair &l, const mdbx::pair &r) -> bool { return l == r; }) &&
ok;
ok = probe(txn, dbi, mdbx::cursor::pair_greater_or_equal,
[txn, dbi](const mdbx::pair &l, const mdbx::pair &r) -> bool {
@@ -234,14 +217,11 @@ int main(int argc, const char *argv[]) {
mdbx::path db_filename = "test-posi";
mdbx::env_managed::remove(db_filename);
mdbx::env_managed env(db_filename, mdbx::env_managed::create_parameters(),
mdbx::env::operate_parameters(3));
mdbx::env_managed env(db_filename, mdbx::env_managed::create_parameters(), mdbx::env::operate_parameters(3));
auto txn = env.start_write();
auto single =
txn.create_map("single", mdbx::key_mode::usual, mdbx::value_mode::single);
auto multi =
txn.create_map("multi", mdbx::key_mode::usual, mdbx::value_mode::multi);
auto single = txn.create_map("single", mdbx::key_mode::usual, mdbx::value_mode::single);
auto multi = txn.create_map("multi", mdbx::key_mode::usual, mdbx::value_mode::multi);
for (size_t i = 0; i < 1000; ++i) {
auto key = random_key();
txn.upsert(single, key, random_value());

View File

@@ -37,8 +37,7 @@ int main() {
exit(EXIT_FAILURE);
}
rc = mdbx_env_open(env, "./example-db", MDBX_NOSUBDIR | MDBX_LIFORECLAIM,
0664);
rc = mdbx_env_open(env, "./example-db", MDBX_NOSUBDIR | MDBX_LIFORECLAIM, 0664);
if (rc != MDBX_SUCCESS) {
fprintf(stderr, "mdbx_env_open: (%d) %s\n", rc, mdbx_strerror(rc));
exit(EXIT_FAILURE);
@@ -50,8 +49,7 @@ int main() {
exit(EXIT_FAILURE);
}
rc = mdbx_dbi_open(txn, "test", MDBX_DUPSORT | MDBX_DUPFIXED | MDBX_CREATE,
&dbi);
rc = mdbx_dbi_open(txn, "test", MDBX_DUPSORT | MDBX_DUPFIXED | MDBX_CREATE, &dbi);
if (rc != MDBX_SUCCESS) {
fprintf(stderr, "mdbx_dbi_open: (%d) %s\n", rc, mdbx_strerror(rc));
exit(EXIT_FAILURE);

View File

@@ -8,14 +8,11 @@
int doit() {
mdbx::path db_filename = "test-dupfix-multiple";
mdbx::env_managed::remove(db_filename);
mdbx::env_managed env(db_filename, mdbx::env_managed::create_parameters(),
mdbx::env::operate_parameters());
mdbx::env_managed env(db_filename, mdbx::env_managed::create_parameters(), mdbx::env::operate_parameters());
using buffer =
mdbx::buffer<mdbx::default_allocator, mdbx::default_capacity_policy>;
using buffer = mdbx::buffer<mdbx::default_allocator, mdbx::default_capacity_policy>;
auto txn = env.start_write();
auto map = txn.create_map(nullptr, mdbx::key_mode::ordinal,
mdbx::value_mode::multi_ordinal);
auto map = txn.create_map(nullptr, mdbx::key_mode::ordinal, mdbx::value_mode::multi_ordinal);
txn.insert(map, buffer::key_from_u64(21), buffer::key_from_u64(18));
txn.insert(map, buffer::key_from_u64(7), buffer::key_from_u64(19));
@@ -29,15 +26,11 @@ int doit() {
txn = env.start_read();
auto cursor = txn.open_cursor(map);
if (cursor.to_first().value.as_uint64() != 19 ||
cursor.to_next().value.as_uint64() != 18 ||
cursor.to_next().value.as_uint64() != 17 ||
cursor.to_next().value.as_uint64() != 16 ||
cursor.to_next().value.as_uint64() != 15 ||
cursor.to_next().value.as_uint64() != 14 ||
cursor.to_next().value.as_uint64() != 13 ||
cursor.to_next().value.as_uint64() != 12 || cursor.to_next(false).done ||
!cursor.eof()) {
if (cursor.to_first().value.as_uint64() != 19 || cursor.to_next().value.as_uint64() != 18 ||
cursor.to_next().value.as_uint64() != 17 || cursor.to_next().value.as_uint64() != 16 ||
cursor.to_next().value.as_uint64() != 15 || cursor.to_next().value.as_uint64() != 14 ||
cursor.to_next().value.as_uint64() != 13 || cursor.to_next().value.as_uint64() != 12 ||
cursor.to_next(false).done || !cursor.eof()) {
std::cerr << "Fail\n";
return EXIT_FAILURE;
}
@@ -45,20 +38,13 @@ int doit() {
const uint64_t array[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 42, 17, 99, 0, 33, 333};
txn = env.start_write();
txn.put_multiple_samelength(map, buffer::key_from_u64(13), array + 3, 4,
mdbx::upsert);
txn.put_multiple_samelength(map, buffer::key_from_u64(10), array + 0, 1,
mdbx::upsert);
txn.put_multiple_samelength(map, buffer::key_from_u64(12), array + 2, 3,
mdbx::upsert);
txn.put_multiple_samelength(map, buffer::key_from_u64(15), array + 5, 6,
mdbx::upsert);
txn.put_multiple_samelength(map, buffer::key_from_u64(14), array + 4, 5,
mdbx::upsert);
txn.put_multiple_samelength(map, buffer::key_from_u64(11), array + 1, 2,
mdbx::upsert);
txn.put_multiple_samelength(map, buffer::key_from_u64(16), array + 6, 7,
mdbx::upsert);
txn.put_multiple_samelength(map, buffer::key_from_u64(13), array + 3, 4, mdbx::upsert);
txn.put_multiple_samelength(map, buffer::key_from_u64(10), array + 0, 1, mdbx::upsert);
txn.put_multiple_samelength(map, buffer::key_from_u64(12), array + 2, 3, mdbx::upsert);
txn.put_multiple_samelength(map, buffer::key_from_u64(15), array + 5, 6, mdbx::upsert);
txn.put_multiple_samelength(map, buffer::key_from_u64(14), array + 4, 5, mdbx::upsert);
txn.put_multiple_samelength(map, buffer::key_from_u64(11), array + 1, 2, mdbx::upsert);
txn.put_multiple_samelength(map, buffer::key_from_u64(16), array + 6, 7, mdbx::upsert);
txn.commit();
txn = env.start_read();
@@ -69,42 +55,30 @@ int doit() {
cursor.to_next().value.as_uint64() != 1 ||
/* key = 11: 2 элемента, пропуск 1 */
cursor.to_next().value.as_uint64() != 2 ||
cursor.to_next().value.as_uint64() != 3 ||
cursor.to_next().value.as_uint64() != 2 || cursor.to_next().value.as_uint64() != 3 ||
/* key = 12: 3 элемента, пропуск 2 */
cursor.to_next().value.as_uint64() != 3 ||
cursor.to_next().value.as_uint64() != 4 ||
cursor.to_next().value.as_uint64() != 3 || cursor.to_next().value.as_uint64() != 4 ||
cursor.to_next().value.as_uint64() != 5 ||
/* key = 13: 4 элемента, пропуск 3 */
cursor.to_next().value.as_uint64() != 4 ||
cursor.to_next().value.as_uint64() != 5 ||
cursor.to_next().value.as_uint64() != 6 ||
cursor.to_next().value.as_uint64() != 7 ||
cursor.to_next().value.as_uint64() != 4 || cursor.to_next().value.as_uint64() != 5 ||
cursor.to_next().value.as_uint64() != 6 || cursor.to_next().value.as_uint64() != 7 ||
/* key = 14: 5 элементов, пропуск 4 */
cursor.to_next().value.as_uint64() != 5 ||
cursor.to_next().value.as_uint64() != 6 ||
cursor.to_next().value.as_uint64() != 7 ||
cursor.to_next().value.as_uint64() != 8 ||
cursor.to_next().value.as_uint64() != 5 || cursor.to_next().value.as_uint64() != 6 ||
cursor.to_next().value.as_uint64() != 7 || cursor.to_next().value.as_uint64() != 8 ||
cursor.to_next().value.as_uint64() != 9 ||
/* key = 15: 6 элементов, пропуск 5 */
cursor.to_next().value.as_uint64() != 6 ||
cursor.to_next().value.as_uint64() != 7 ||
cursor.to_next().value.as_uint64() != 8 ||
cursor.to_next().value.as_uint64() != 9 ||
cursor.to_next().value.as_uint64() != 17 ||
cursor.to_next().value.as_uint64() != 42 ||
cursor.to_next().value.as_uint64() != 6 || cursor.to_next().value.as_uint64() != 7 ||
cursor.to_next().value.as_uint64() != 8 || cursor.to_next().value.as_uint64() != 9 ||
cursor.to_next().value.as_uint64() != 17 || cursor.to_next().value.as_uint64() != 42 ||
/* key = 16: 7 элементов, пропуск 6 */
cursor.to_next().value.as_uint64() != 0 ||
cursor.to_next().value.as_uint64() != 7 ||
cursor.to_next().value.as_uint64() != 8 ||
cursor.to_next().value.as_uint64() != 9 ||
cursor.to_next().value.as_uint64() != 17 ||
cursor.to_next().value.as_uint64() != 42 ||
cursor.to_next().value.as_uint64() != 0 || cursor.to_next().value.as_uint64() != 7 ||
cursor.to_next().value.as_uint64() != 8 || cursor.to_next().value.as_uint64() != 9 ||
cursor.to_next().value.as_uint64() != 17 || cursor.to_next().value.as_uint64() != 42 ||
cursor.to_next().value.as_uint64() != 99 ||
/* key = 21 */ cursor.to_next().value.as_uint64() != 18 ||
@@ -113,46 +87,35 @@ int doit() {
/* key = 24 */ cursor.to_next().value.as_uint64() != 15 ||
/* key = 25 */ cursor.to_next().value.as_uint64() != 14 ||
/* key = 26 */ cursor.to_next().value.as_uint64() != 13 ||
/* key = 27 */ cursor.to_next().value.as_uint64() != 12 ||
cursor.to_next(false).done || !cursor.eof()) {
/* key = 27 */ cursor.to_next().value.as_uint64() != 12 || cursor.to_next(false).done || !cursor.eof()) {
std::cerr << "Fail\n";
return EXIT_FAILURE;
}
txn.abort();
txn = env.start_write();
txn.put_multiple_samelength(map, buffer::key_from_u64(7), array + 3, 4,
mdbx::update);
txn.put_multiple_samelength(map, buffer::key_from_u64(7), array + 3, 4, mdbx::update);
txn.upsert(map, buffer::key_from_u64(10), buffer::key_from_u64(14));
txn.put_multiple_samelength(map, buffer::key_from_u64(11), array + 4, 5,
mdbx::upsert);
txn.put_multiple_samelength(map, buffer::key_from_u64(12), array + 0, 1,
mdbx::update);
txn.put_multiple_samelength(map, buffer::key_from_u64(11), array + 4, 5, mdbx::upsert);
txn.put_multiple_samelength(map, buffer::key_from_u64(12), array + 0, 1, mdbx::update);
txn.update(map, buffer::key_from_u64(13), buffer::key_from_u64(18));
txn.put_multiple_samelength(map, buffer::key_from_u64(14), array + 2, 3,
mdbx::update);
txn.put_multiple_samelength(map, buffer::key_from_u64(14), array + 2, 3, mdbx::update);
txn.update(map, buffer::key_from_u64(15), buffer::key_from_u64(13));
txn.put_multiple_samelength(map, buffer::key_from_u64(16), array + 6, 9,
mdbx::update);
txn.put_multiple_samelength(map, buffer::key_from_u64(16), array + 6, 9, mdbx::update);
txn.update(map, buffer::key_from_u64(21), buffer::key_from_u64(17));
txn.update(map, buffer::key_from_u64(22), buffer::key_from_u64(15));
txn.put_multiple_samelength(map, buffer::key_from_u64(23), array + 1, 2,
mdbx::update);
txn.put_multiple_samelength(map, buffer::key_from_u64(23), array + 1, 2, mdbx::update);
txn.update(map, buffer::key_from_u64(24), buffer::key_from_u64(16));
txn.put_multiple_samelength(map, buffer::key_from_u64(25), array + 5, 6,
mdbx::update);
txn.put_multiple_samelength(map, buffer::key_from_u64(25), array + 5, 6, mdbx::update);
txn.upsert(map, buffer::key_from_u64(26), buffer::key_from_u64(12));
txn.put_multiple_samelength(map, buffer::key_from_u64(27), array + 12, 3,
mdbx::update);
txn.put_multiple_samelength(map, buffer::key_from_u64(27), array + 12, 3, mdbx::update);
txn.commit();
txn = env.start_read();
cursor = txn.open_cursor(map);
if (/* key = 7 */
cursor.to_first().value.as_uint64() != 4 ||
cursor.to_next().value.as_uint64() != 5 ||
cursor.to_next().value.as_uint64() != 6 ||
cursor.to_next().value.as_uint64() != 7 ||
cursor.to_first().value.as_uint64() != 4 || cursor.to_next().value.as_uint64() != 5 ||
cursor.to_next().value.as_uint64() != 6 || cursor.to_next().value.as_uint64() != 7 ||
/* key = 10: 1 элемент */
cursor.to_next().value.as_uint64() != 1 ||
@@ -160,13 +123,10 @@ int doit() {
cursor.to_next().value.as_uint64() != 14 ||
/* key = 11: 2 элемента, пропуск 1 */
cursor.to_next().value.as_uint64() != 2 ||
cursor.to_next().value.as_uint64() != 3 ||
cursor.to_next().value.as_uint64() != 2 || cursor.to_next().value.as_uint64() != 3 ||
/* +5 элементов, пропуск 4 */
cursor.to_next().value.as_uint64() != 5 ||
cursor.to_next().value.as_uint64() != 6 ||
cursor.to_next().value.as_uint64() != 7 ||
cursor.to_next().value.as_uint64() != 8 ||
cursor.to_next().value.as_uint64() != 5 || cursor.to_next().value.as_uint64() != 6 ||
cursor.to_next().value.as_uint64() != 7 || cursor.to_next().value.as_uint64() != 8 ||
cursor.to_next().value.as_uint64() != 9 ||
/* key = 12: 1 элемент */
@@ -174,44 +134,33 @@ int doit() {
/* key = 13 */ cursor.to_next().value.as_uint64() != 18 ||
/* key = 14: 3 элемента, пропуск 2 */
cursor.to_next().value.as_uint64() != 3 ||
cursor.to_next().value.as_uint64() != 4 ||
cursor.to_next().value.as_uint64() != 3 || cursor.to_next().value.as_uint64() != 4 ||
cursor.to_next().value.as_uint64() != 5 ||
/* key = 15 */ cursor.to_next().value.as_uint64() != 13 ||
/* key = 16: 9 элементов, пропуск 6 */
cursor.to_next().value.as_uint64() != 0 ||
cursor.to_next().value.as_uint64() != 7 ||
cursor.to_next().value.as_uint64() != 8 ||
cursor.to_next().value.as_uint64() != 9 ||
cursor.to_next().value.as_uint64() != 17 ||
cursor.to_next().value.as_uint64() != 33 ||
cursor.to_next().value.as_uint64() != 42 ||
cursor.to_next().value.as_uint64() != 99 ||
cursor.to_next().value.as_uint64() != 0 || cursor.to_next().value.as_uint64() != 7 ||
cursor.to_next().value.as_uint64() != 8 || cursor.to_next().value.as_uint64() != 9 ||
cursor.to_next().value.as_uint64() != 17 || cursor.to_next().value.as_uint64() != 33 ||
cursor.to_next().value.as_uint64() != 42 || cursor.to_next().value.as_uint64() != 99 ||
cursor.to_next().value.as_uint64() != 333 ||
/* key = 21 */ cursor.to_next().value.as_uint64() != 17 ||
/* key = 22 */ cursor.to_next().value.as_uint64() != 15 ||
/* key = 23: 2 элемента, пропуск 1 */
cursor.to_next().value.as_uint64() != 2 ||
cursor.to_next().value.as_uint64() != 3 ||
cursor.to_next().value.as_uint64() != 2 || cursor.to_next().value.as_uint64() != 3 ||
/* key = 24 */ cursor.to_next().value.as_uint64() != 16 ||
/* key = 25: 6 элемента, пропуск 5 */
cursor.to_next().value.as_uint64() != 6 ||
cursor.to_next().value.as_uint64() != 7 ||
cursor.to_next().value.as_uint64() != 8 ||
cursor.to_next().value.as_uint64() != 9 ||
cursor.to_next().value.as_uint64() != 17 ||
cursor.to_next().value.as_uint64() != 42 ||
cursor.to_next().value.as_uint64() != 6 || cursor.to_next().value.as_uint64() != 7 ||
cursor.to_next().value.as_uint64() != 8 || cursor.to_next().value.as_uint64() != 9 ||
cursor.to_next().value.as_uint64() != 17 || cursor.to_next().value.as_uint64() != 42 ||
/* key = 26, 1+1 upsert */
cursor.to_next().value.as_uint64() != 12 ||
cursor.to_next().value.as_uint64() != 13 ||
cursor.to_next().value.as_uint64() != 12 || cursor.to_next().value.as_uint64() != 13 ||
/* key = 27: 3 элемента, пропуск 12 */
cursor.to_next().value.as_uint64() != 0 ||
cursor.to_next().value.as_uint64() != 33 ||
cursor.to_next().value.as_uint64() != 0 || cursor.to_next().value.as_uint64() != 33 ||
cursor.to_next().value.as_uint64() != 333 ||
cursor.to_next(false).done || !cursor.eof()) {
@@ -247,8 +196,7 @@ int doit() {
txn = env.start_write();
txn.clear_map(map);
map = txn.create_map(nullptr, mdbx::key_mode::usual,
mdbx::value_mode::multi_samelength);
map = txn.create_map(nullptr, mdbx::key_mode::usual, mdbx::value_mode::multi_samelength);
txn.upsert(map, mdbx::slice("key1"), mdbx::slice("val1"));
txn.upsert(map, mdbx::pair("key1", "val2"));
txn.upsert(map, mdbx::pair("key1", "val3"));

View File

@@ -23,14 +23,11 @@ int main(int argc, char *argv[]) {
// 1); assert(err == MDBX_SUCCESS);
intptr_t lowerbound(0), size(0), upperbound(mdbx::env::geometry::GiB / 2);
intptr_t step(128 * mdbx::env::geometry::MiB),
shrink(256 * mdbx::env::geometry::MiB), pagesize(-1);
err = mdbx_env_set_geometry(environment, lowerbound, size, upperbound, step,
shrink, pagesize);
intptr_t step(128 * mdbx::env::geometry::MiB), shrink(256 * mdbx::env::geometry::MiB), pagesize(-1);
err = mdbx_env_set_geometry(environment, lowerbound, size, upperbound, step, shrink, pagesize);
assert(err == MDBX_SUCCESS);
MDBX_env_flags_t flags(MDBX_NOSUBDIR | MDBX_WRITEMAP | MDBX_LIFORECLAIM |
MDBX_NORDAHEAD);
MDBX_env_flags_t flags(MDBX_NOSUBDIR | MDBX_WRITEMAP | MDBX_LIFORECLAIM | MDBX_NORDAHEAD);
err = mdbx_env_openT(environment, db_filename.c_str(), flags, 0644);
assert(err == MDBX_SUCCESS);

View File

@@ -27,20 +27,16 @@ static buffer random(size_t length) {
static bool basic() {
bool ok = true;
const char *const hex_dump = "1D58fa\n2e46E3\nBd9c7A\nC0bF";
const uint8_t native[] = {0x1D, 0x58, 0xfa, 0x2e, 0x46, 0xE3,
0xBd, 0x9c, 0x7A, 0xC0, 0xbF};
const uint8_t native[] = {0x1D, 0x58, 0xfa, 0x2e, 0x46, 0xE3, 0xBd, 0x9c, 0x7A, 0xC0, 0xbF};
if (mdbx::slice(hex_dump).hex_decode(true) != mdbx::slice::wrap(native))
std::cerr << "hex_decode() failed\n";
else if (mdbx::slice::wrap(native).encode_hex(true, 4).hex_decode(true) !=
mdbx::slice::wrap(native))
else if (mdbx::slice::wrap(native).encode_hex(true, 4).hex_decode(true) != mdbx::slice::wrap(native))
std::cerr << "hex_encode(UPPERCASE) failed\n";
else if (mdbx::slice::wrap(native).encode_hex(false).hex_decode(true) !=
mdbx::slice::wrap(native))
else if (mdbx::slice::wrap(native).encode_hex(false).hex_decode(true) != mdbx::slice::wrap(native))
std::cerr << "hex_encode(lowercase) failed\n";
if (mdbx::slice("").as_base64_string() != "" ||
mdbx::slice(" ").encode_base64().as_string() != "IA==" ||
if (mdbx::slice("").as_base64_string() != "" || mdbx::slice(" ").encode_base64().as_string() != "IA==" ||
mdbx::slice("~0").encode_base64().as_string() != "fjA=" ||
mdbx::slice("A_z").encode_base64().as_string() != "QV96" ||
mdbx::slice("Ka9q").encode_base64().as_string() != "S2E5cQ==" ||
@@ -50,12 +46,9 @@ static bool basic() {
}
const uint8_t base58_rfc[] = {0x00, 0x00, 0x28, 0x7f, 0xb4, 0xcd};
if (mdbx::slice("").as_base58_string() != "" ||
mdbx::slice(" ").encode_base58().as_string() != "Z" ||
if (mdbx::slice("").as_base58_string() != "" || mdbx::slice(" ").encode_base58().as_string() != "Z" ||
mdbx::slice("Hello World!").as_base58_string() != "2NEpo7TZRRrLZSi2U" ||
mdbx::slice("The quick brown fox jumps over the lazy dog.")
.encode_base58()
.as_string() !=
mdbx::slice("The quick brown fox jumps over the lazy dog.").encode_base58().as_string() !=
"USm3fpXnKG5EUBx2ndxBDMPVciP5hGey2Jh4NDv6gmeo1LkMeiKrLJUUBk6Z" ||
mdbx::slice::wrap(base58_rfc).as_base58_string() != "11233QC4" ||
mdbx::slice("~0").encode_base58().as_string() != "Aby" ||
@@ -66,15 +59,11 @@ static bool basic() {
ok = false;
}
if (mdbx::slice("").base58_decode() != mdbx::slice() ||
mdbx::slice("Z").base58_decode() != mdbx::slice(" ") ||
if (mdbx::slice("").base58_decode() != mdbx::slice() || mdbx::slice("Z").base58_decode() != mdbx::slice(" ") ||
mdbx::slice("2NEpo7TZRRrLZSi2U").base58_decode() != "Hello World!" ||
mdbx::slice(
"USm3fpXnKG5EUBx2ndxBDMPVciP5hGey2Jh4NDv6gmeo1LkMeiKrLJUUBk6Z")
.base58_decode() !=
mdbx::slice("USm3fpXnKG5EUBx2ndxBDMPVciP5hGey2Jh4NDv6gmeo1LkMeiKrLJUUBk6Z").base58_decode() !=
mdbx::slice("The quick brown fox jumps over the lazy dog.") ||
mdbx::slice("11233QC4").base58_decode() !=
mdbx::slice::wrap(base58_rfc) ||
mdbx::slice("11233QC4").base58_decode() != mdbx::slice::wrap(base58_rfc) ||
mdbx::slice("Aby").base58_decode() != mdbx::slice("~0") ||
mdbx::slice("NxZw").base58_decode() != mdbx::slice("A_z") ||
mdbx::slice("2vkjDi").base58_decode() != mdbx::slice("Ka9q") ||
@@ -94,28 +83,19 @@ int main(int argc, const char *argv[]) {
for (size_t n = 0; n < 1000; ++n) {
for (size_t length = 0; ok && length < 111; ++length) {
const auto pattern = random(length);
if (pattern != pattern.encode_hex(bool(prng() & 1), prng() % 111)
.hex_decode(true)
.encode_hex()
.hex_decode(false)) {
std::cerr << "hex encode/decode failed: n " << n << ", length "
<< length << std::endl;
if (pattern !=
pattern.encode_hex(bool(prng() & 1), prng() % 111).hex_decode(true).encode_hex().hex_decode(false)) {
std::cerr << "hex encode/decode failed: n " << n << ", length " << length << std::endl;
ok = false;
}
if (pattern != pattern.encode_base64(unsigned(prng() % 111))
.base64_decode(true)
.encode_base64()
.base64_decode(false)) {
std::cerr << "base64 encode/decode failed: n " << n << ", length "
<< length << std::endl;
if (pattern !=
pattern.encode_base64(unsigned(prng() % 111)).base64_decode(true).encode_base64().base64_decode(false)) {
std::cerr << "base64 encode/decode failed: n " << n << ", length " << length << std::endl;
ok = false;
}
if (pattern != pattern.encode_base58(unsigned(prng() % 111))
.base58_decode(true)
.encode_base58()
.base58_decode(false)) {
std::cerr << "base58 encode/decode failed: n " << n << ", length "
<< length << std::endl;
if (pattern !=
pattern.encode_base58(unsigned(prng() % 111)).base58_decode(true).encode_base58().base58_decode(false)) {
std::cerr << "base58 encode/decode failed: n " << n << ", length " << length << std::endl;
ok = false;
}
}

View File

@@ -10,14 +10,11 @@ int main(int argc, const char *argv[]) {
mdbx::path db_filename = "test-dupfix-multiple";
mdbx::env_managed::remove(db_filename);
mdbx::env_managed env(db_filename, mdbx::env_managed::create_parameters(),
mdbx::env::operate_parameters());
mdbx::env_managed env(db_filename, mdbx::env_managed::create_parameters(), mdbx::env::operate_parameters());
using buffer =
mdbx::buffer<mdbx::default_allocator, mdbx::default_capacity_policy>;
using buffer = mdbx::buffer<mdbx::default_allocator, mdbx::default_capacity_policy>;
auto txn = env.start_write();
auto map = txn.create_map(nullptr, mdbx::key_mode::ordinal,
mdbx::value_mode::single);
auto map = txn.create_map(nullptr, mdbx::key_mode::ordinal, mdbx::value_mode::single);
#if 0 /* workaround */
txn.commit();
env.close();
@@ -39,14 +36,10 @@ int main(int argc, const char *argv[]) {
txn = env.start_read();
auto cursor = txn.open_cursor(map);
#if defined(__cpp_lib_string_view) && __cpp_lib_string_view >= 201606L
if (cursor.to_first().value.string_view() == "a" &&
cursor.to_next().value.string_view() == "b" &&
cursor.to_next().value.string_view() == "c" &&
cursor.to_next().value.string_view() == "d" &&
cursor.to_next().value.string_view() == "e" &&
cursor.to_next().value.string_view() == "f" &&
cursor.to_next().value.string_view() == "g" &&
cursor.to_next().value.string_view() == "h" &&
if (cursor.to_first().value.string_view() == "a" && cursor.to_next().value.string_view() == "b" &&
cursor.to_next().value.string_view() == "c" && cursor.to_next().value.string_view() == "d" &&
cursor.to_next().value.string_view() == "e" && cursor.to_next().value.string_view() == "f" &&
cursor.to_next().value.string_view() == "g" && cursor.to_next().value.string_view() == "h" &&
!cursor.to_next(false).done && cursor.eof()) {
std::cout << "OK\n";
return EXIT_SUCCESS;

View File

@@ -18,8 +18,8 @@ int main(int argc, const char *argv[]) {
static char log_buffer[1024];
static void logger_nofmt(MDBX_log_level_t loglevel, const char *function,
int line, const char *msg, unsigned length) noexcept {
static void logger_nofmt(MDBX_log_level_t loglevel, const char *function, int line, const char *msg,
unsigned length) noexcept {
(void)length;
(void)loglevel;
fprintf(stdout, "%s:%u %s", function, line, msg);
@@ -29,8 +29,7 @@ int main(int argc, const char *argv[]) {
(void)argc;
(void)argv;
mdbx_setup_debug_nofmt(MDBX_LOG_VERBOSE, MDBX_DBG_ASSERT, logger_nofmt,
log_buffer, sizeof(log_buffer));
mdbx_setup_debug_nofmt(MDBX_LOG_VERBOSE, MDBX_DBG_ASSERT, logger_nofmt, log_buffer, sizeof(log_buffer));
mdbx::path path = "test-open";
mdbx::env::remove(path);
@@ -41,19 +40,16 @@ int main(int argc, const char *argv[]) {
createParameters2.geometry.make_fixed(42 * mdbx::env::geometry::MiB);
mdbx::env_managed env2(path, createParameters2, operateParameters2);
mdbx::txn_managed txn2 = env2.start_write(false);
/* mdbx::map_handle testHandle2 = */ txn2.create_map(
"fap1", mdbx::key_mode::reverse, mdbx::value_mode::single);
/* mdbx::map_handle testHandle2 = */ txn2.create_map("fap1", mdbx::key_mode::reverse, mdbx::value_mode::single);
txn2.commit();
}
mdbx::env::operate_parameters operateParameters(100, 10);
mdbx::env_managed::create_parameters createParameters;
createParameters.geometry.make_dynamic(21 * mdbx::env::geometry::MiB,
84 * mdbx::env::geometry::MiB);
createParameters.geometry.make_dynamic(21 * mdbx::env::geometry::MiB, 84 * mdbx::env::geometry::MiB);
mdbx::env_managed env(path, createParameters, operateParameters);
mdbx::txn_managed txn = env.start_write(false);
/* mdbx::map_handle testHandle = */ txn.create_map(
"fap1", mdbx::key_mode::usual, mdbx::value_mode::single);
/* mdbx::map_handle testHandle = */ txn.create_map("fap1", mdbx::key_mode::usual, mdbx::value_mode::single);
txn.commit();
std::latch starter(1);
@@ -62,8 +58,7 @@ int main(int argc, const char *argv[]) {
starter.wait();
// mdbx::env_managed env(path, createParameters, operateParameters);
mdbx::txn_managed txn = env.start_write(false);
/* mdbx::map_handle testHandle = */ txn.create_map(
"fap1", mdbx::key_mode::usual, mdbx::value_mode::single);
/* mdbx::map_handle testHandle = */ txn.create_map("fap1", mdbx::key_mode::usual, mdbx::value_mode::single);
txn.commit();
});
@@ -71,8 +66,7 @@ int main(int argc, const char *argv[]) {
starter.wait();
// mdbx::env_managed env(path, createParameters, operateParameters);
mdbx::txn_managed txn = env.start_write(false);
/* mdbx::map_handle testHandle = */ txn.create_map(
"fap1", mdbx::key_mode::usual, mdbx::value_mode::single);
/* mdbx::map_handle testHandle = */ txn.create_map("fap1", mdbx::key_mode::usual, mdbx::value_mode::single);
txn.commit();
});

View File

@@ -32,9 +32,8 @@
#include <stdlib.h>
#include <string.h>
#define IP_PRINTF_ARG_HOST(addr) \
(int)((addr) >> 24), (int)((addr) >> 16 & 0xff), (int)((addr) >> 8 & 0xff), \
(int)((addr) & 0xff)
#define IP_PRINTF_ARG_HOST(addr) \
(int)((addr) >> 24), (int)((addr) >> 16 & 0xff), (int)((addr) >> 8 & 0xff), (int)((addr) & 0xff)
char opt_db_path[PATH_MAX] = "./mdbx_bench2";
static MDBX_env *env;
@@ -88,14 +87,13 @@ static int64_t get_id_from_pool() {
return id;
}
#define MDBX_CHECK(x) \
do { \
const int rc = (x); \
if (rc != MDBX_SUCCESS) { \
printf("Error [%d] %s in %s at %s:%d\n", rc, mdbx_strerror(rc), #x, \
__FILE__, __LINE__); \
exit(EXIT_FAILURE); \
} \
#define MDBX_CHECK(x) \
do { \
const int rc = (x); \
if (rc != MDBX_SUCCESS) { \
printf("Error [%d] %s in %s at %s:%d\n", rc, mdbx_strerror(rc), #x, __FILE__, __LINE__); \
exit(EXIT_FAILURE); \
} \
} while (0)
static void db_connect() {
@@ -105,13 +103,10 @@ static void db_connect() {
MDBX_dbi dbi_ip;
MDBX_CHECK(mdbx_env_create(&env));
MDBX_CHECK(mdbx_env_set_geometry(
env, 0, 0, REC_COUNT * sizeof(session_data_t) * 10, -1, -1, -1));
MDBX_CHECK(mdbx_env_set_geometry(env, 0, 0, REC_COUNT * sizeof(session_data_t) * 10, -1, -1, -1));
MDBX_CHECK(mdbx_env_set_maxdbs(env, 30));
MDBX_CHECK(mdbx_env_open(env, opt_db_path,
MDBX_CREATE | MDBX_WRITEMAP | MDBX_UTTERLY_NOSYNC |
MDBX_LIFORECLAIM,
0664));
MDBX_CHECK(
mdbx_env_open(env, opt_db_path, MDBX_CREATE | MDBX_WRITEMAP | MDBX_UTTERLY_NOSYNC | MDBX_LIFORECLAIM, 0664));
MDBX_txn *txn;
// transaction init
@@ -135,16 +130,11 @@ static void create_record(uint64_t record_id) {
MDBX_txn *txn;
session_data_t data;
// transaction init
snprintf(data.session_id1, sizeof(data.session_id1),
"prefix%02u_%02u.fill.fill.fill.fill.fill.fill;%" PRIu64,
(unsigned)(record_id % 3) + 1, (unsigned)(record_id % 9) + 1,
record_id);
snprintf(data.session_id2, sizeof(data.session_id2),
"dprefix%" PRIu64 ";%" PRIu64 ".fill.fill.;suffix", record_id,
(record_id + UINT64_C(1442695040888963407)) %
UINT64_C(6364136223846793005));
snprintf(data.ip, sizeof(data.ip), "%d.%d.%d.%d",
IP_PRINTF_ARG_HOST(record_id & 0xFFFFFFFF));
snprintf(data.session_id1, sizeof(data.session_id1), "prefix%02u_%02u.fill.fill.fill.fill.fill.fill;%" PRIu64,
(unsigned)(record_id % 3) + 1, (unsigned)(record_id % 9) + 1, record_id);
snprintf(data.session_id2, sizeof(data.session_id2), "dprefix%" PRIu64 ";%" PRIu64 ".fill.fill.;suffix", record_id,
(record_id + UINT64_C(1442695040888963407)) % UINT64_C(6364136223846793005));
snprintf(data.ip, sizeof(data.ip), "%d.%d.%d.%d", IP_PRINTF_ARG_HOST(record_id & 0xFFFFFFFF));
event.obj_id = record_id;
event.event_type = 1;
@@ -152,8 +142,7 @@ static void create_record(uint64_t record_id) {
MDBX_val _session_id2_rec = {data.session_id2, strlen(data.session_id2)};
MDBX_val _ip_rec = {data.ip, strlen(data.ip)};
MDBX_val _obj_id_rec = {&record_id, sizeof(record_id)};
MDBX_val _data_rec = {&data, offsetof(session_data_t, fill) +
(rand() % sizeof(data.fill))};
MDBX_val _data_rec = {&data, offsetof(session_data_t, fill) + (rand() % sizeof(data.fill))};
MDBX_val _event_rec = {&event, sizeof(event)};
uint64_t start = getClockUs();
@@ -162,20 +151,16 @@ static void create_record(uint64_t record_id) {
MDBX_CHECK(mdbx_dbi_open(txn, "session_id", MDBX_CREATE, &dbi_session_id));
MDBX_CHECK(mdbx_dbi_open(txn, "event", MDBX_CREATE, &dbi_event));
MDBX_CHECK(mdbx_dbi_open(txn, "ip", MDBX_CREATE, &dbi_ip));
MDBX_CHECK(mdbx_put(txn, dbi_session, &_obj_id_rec, &_data_rec,
MDBX_NOOVERWRITE | MDBX_NODUPDATA));
MDBX_CHECK(mdbx_put(txn, dbi_session_id, &_session_id1_rec, &_obj_id_rec,
MDBX_NOOVERWRITE | MDBX_NODUPDATA));
MDBX_CHECK(mdbx_put(txn, dbi_session_id, &_session_id2_rec, &_obj_id_rec,
MDBX_NOOVERWRITE | MDBX_NODUPDATA));
MDBX_CHECK(mdbx_put(txn, dbi_session, &_obj_id_rec, &_data_rec, MDBX_NOOVERWRITE | MDBX_NODUPDATA));
MDBX_CHECK(mdbx_put(txn, dbi_session_id, &_session_id1_rec, &_obj_id_rec, MDBX_NOOVERWRITE | MDBX_NODUPDATA));
MDBX_CHECK(mdbx_put(txn, dbi_session_id, &_session_id2_rec, &_obj_id_rec, MDBX_NOOVERWRITE | MDBX_NODUPDATA));
MDBX_CHECK(mdbx_put(txn, dbi_ip, &_ip_rec, &_obj_id_rec, 0));
MDBX_CHECK(mdbx_put(txn, dbi_event, &_event_rec, &_obj_id_rec, 0));
MDBX_CHECK(mdbx_txn_commit(txn));
mdbx_data_size += (_data_rec.iov_len + _obj_id_rec.iov_len * 4);
mdbx_key_size +=
(_obj_id_rec.iov_len + _session_id1_rec.iov_len +
_session_id2_rec.iov_len + _ip_rec.iov_len + _event_rec.iov_len);
mdbx_key_size += (_obj_id_rec.iov_len + _session_id1_rec.iov_len + _session_id2_rec.iov_len + _ip_rec.iov_len +
_event_rec.iov_len);
// transaction commit
mdbx_add_count++;
@@ -218,9 +203,8 @@ static void delete_record(int64_t record_id) {
MDBX_CHECK(mdbx_del(txn, dbi_session, &_obj_id_rec, NULL));
mdbx_data_size -= (_data_rec.iov_len + _obj_id_rec.iov_len * 4);
mdbx_key_size -=
(_obj_id_rec.iov_len + _session_id1_rec.iov_len +
_session_id2_rec.iov_len + _ip_rec.iov_len + _event_rec.iov_len);
mdbx_key_size -= (_obj_id_rec.iov_len + _session_id1_rec.iov_len + _session_id2_rec.iov_len + _ip_rec.iov_len +
_event_rec.iov_len);
// transaction commit
MDBX_CHECK(mdbx_txn_commit(txn));
@@ -233,8 +217,7 @@ static void db_disconnect() {
printf("Connection closed\n");
}
static void get_db_stat(const char *db, int64_t *ms_branch_pages,
int64_t *ms_leaf_pages) {
static void get_db_stat(const char *db, int64_t *ms_branch_pages, int64_t *ms_leaf_pages) {
MDBX_txn *txn;
MDBX_stat stat;
MDBX_dbi dbi;
@@ -243,10 +226,8 @@ static void get_db_stat(const char *db, int64_t *ms_branch_pages,
MDBX_CHECK(mdbx_dbi_open(txn, db, MDBX_CREATE, &dbi));
MDBX_CHECK(mdbx_dbi_stat(txn, dbi, &stat, sizeof(stat)));
mdbx_txn_abort(txn);
printf("%15s | %15" PRIu64 " | %5u | %10" PRIu64 " | %10" PRIu64
" | %11" PRIu64 " |\n",
db, stat.ms_branch_pages, stat.ms_depth, stat.ms_entries,
stat.ms_leaf_pages, stat.ms_overflow_pages);
printf("%15s | %15" PRIu64 " | %5u | %10" PRIu64 " | %10" PRIu64 " | %11" PRIu64 " |\n", db, stat.ms_branch_pages,
stat.ms_depth, stat.ms_entries, stat.ms_leaf_pages, stat.ms_overflow_pages);
(*ms_branch_pages) += stat.ms_branch_pages;
(*ms_leaf_pages) += stat.ms_leaf_pages;
}
@@ -261,25 +242,20 @@ static void periodic_stat(void) {
printf("Environment Info\n");
printf(" Pagesize: %u\n", mst.ms_psize);
if (mei.mi_geo.lower != mei.mi_geo.upper) {
printf(" Dynamic datafile: %" PRIu64 "..%" PRIu64 " bytes (+%" PRIu64
"/-%" PRIu64 "), %" PRIu64 "..%" PRIu64 " pages (+%" PRIu64
"/-%" PRIu64 ")\n",
mei.mi_geo.lower, mei.mi_geo.upper, mei.mi_geo.grow,
mei.mi_geo.shrink, mei.mi_geo.lower / mst.ms_psize,
mei.mi_geo.upper / mst.ms_psize, mei.mi_geo.grow / mst.ms_psize,
mei.mi_geo.shrink / mst.ms_psize);
printf(" Current datafile: %" PRIu64 " bytes, %" PRIu64 " pages\n",
mei.mi_geo.current, mei.mi_geo.current / mst.ms_psize);
printf(" Dynamic datafile: %" PRIu64 "..%" PRIu64 " bytes (+%" PRIu64 "/-%" PRIu64 "), %" PRIu64 "..%" PRIu64
" pages (+%" PRIu64 "/-%" PRIu64 ")\n",
mei.mi_geo.lower, mei.mi_geo.upper, mei.mi_geo.grow, mei.mi_geo.shrink, mei.mi_geo.lower / mst.ms_psize,
mei.mi_geo.upper / mst.ms_psize, mei.mi_geo.grow / mst.ms_psize, mei.mi_geo.shrink / mst.ms_psize);
printf(" Current datafile: %" PRIu64 " bytes, %" PRIu64 " pages\n", mei.mi_geo.current,
mei.mi_geo.current / mst.ms_psize);
} else {
printf(" Fixed datafile: %" PRIu64 " bytes, %" PRIu64 " pages\n",
mei.mi_geo.current, mei.mi_geo.current / mst.ms_psize);
printf(" Fixed datafile: %" PRIu64 " bytes, %" PRIu64 " pages\n", mei.mi_geo.current,
mei.mi_geo.current / mst.ms_psize);
}
printf(" Current mapsize: %" PRIu64 " bytes, %" PRIu64 " pages \n",
mei.mi_mapsize, mei.mi_mapsize / mst.ms_psize);
printf(" Current mapsize: %" PRIu64 " bytes, %" PRIu64 " pages \n", mei.mi_mapsize, mei.mi_mapsize / mst.ms_psize);
printf(" Number of pages used: %" PRIu64 "\n", mei.mi_last_pgno + 1);
printf(" Last transaction ID: %" PRIu64 "\n", mei.mi_recent_txnid);
printf(" Tail transaction ID: %" PRIu64 " (%" PRIi64 ")\n",
mei.mi_latter_reader_txnid,
printf(" Tail transaction ID: %" PRIu64 " (%" PRIi64 ")\n", mei.mi_latter_reader_txnid,
mei.mi_latter_reader_txnid - mei.mi_recent_txnid);
printf(" Max readers: %u\n", mei.mi_maxreaders);
printf(" Number of readers used: %u\n", mei.mi_numreaders);
@@ -290,8 +266,8 @@ static void periodic_stat(void) {
get_db_stat("session_id", &ms_branch_pages, &ms_leaf_pages);
get_db_stat("event", &ms_branch_pages, &ms_leaf_pages);
get_db_stat("ip", &ms_branch_pages, &ms_leaf_pages);
printf("%15s | %15" PRIu64 " | %5s | %10s | %10" PRIu64 " | %11s |\n", "",
ms_branch_pages, "", "", ms_leaf_pages, "");
printf("%15s | %15" PRIu64 " | %5s | %10s | %10" PRIu64 " | %11s |\n", "", ms_branch_pages, "", "", ms_leaf_pages,
"");
static int64_t prev_add_count;
static int64_t prev_del_count;
@@ -300,32 +276,23 @@ static void periodic_stat(void) {
static int64_t t = -1;
if (t > 0) {
int64_t delta = (getClockUs() - t);
printf("CPS: add %" PRIu64 ", delete %" PRIu64
", items processed - %" PRIu64 "K data=%" PRIu64 "K key=%" PRIu64
printf("CPS: add %" PRIu64 ", delete %" PRIu64 ", items processed - %" PRIu64 "K data=%" PRIu64 "K key=%" PRIu64
"K\n",
(mdbx_add_count - prev_add_count) * 1000000 / delta,
(mdbx_del_count - prev_del_count) * 1000000 / delta, obj_id / 1024,
mdbx_data_size / 1024, mdbx_key_size / 1024);
(mdbx_add_count - prev_add_count) * 1000000 / delta, (mdbx_del_count - prev_del_count) * 1000000 / delta,
obj_id / 1024, mdbx_data_size / 1024, mdbx_key_size / 1024);
printf("usage data=%" PRIu64 "%%",
((mdbx_data_size + mdbx_key_size) * 100) /
((ms_leaf_pages + ms_branch_pages) * 4096));
((mdbx_data_size + mdbx_key_size) * 100) / ((ms_leaf_pages + ms_branch_pages) * 4096));
if (prev_add_time != mdbx_add_time) {
printf(" Add : %" PRIu64 " c/s", (mdbx_add_count - prev_add_count) *
1000000 /
(mdbx_add_time - prev_add_time));
printf(" Add : %" PRIu64 " c/s", (mdbx_add_count - prev_add_count) * 1000000 / (mdbx_add_time - prev_add_time));
}
if (prev_del_time != mdbx_del_time) {
printf(" Del : %" PRIu64 " c/s", (mdbx_del_count - prev_del_count) *
1000000 /
(mdbx_del_time - prev_del_time));
printf(" Del : %" PRIu64 " c/s", (mdbx_del_count - prev_del_count) * 1000000 / (mdbx_del_time - prev_del_time));
}
if (mdbx_add_time) {
printf(" tAdd : %" PRIu64 " c/s",
mdbx_add_count * 1000000 / mdbx_add_time);
printf(" tAdd : %" PRIu64 " c/s", mdbx_add_count * 1000000 / mdbx_add_time);
}
if (mdbx_del_time) {
printf(" tDel : %" PRIu64 " c/s",
mdbx_del_count * 1000000 / mdbx_del_time);
printf(" tDel : %" PRIu64 " c/s", mdbx_del_count * 1000000 / mdbx_del_time);
}
puts("");
}

View File

@@ -5,7 +5,6 @@
int main(int argc, const char *argv[]) {
(void)argc;
(void)argv;
std::cout
<< "OK (but this is do-nothing test just for a check for compilation)\n";
std::cout << "OK (but this is do-nothing test just for a check for compilation)\n";
return EXIT_SUCCESS;
}

View File

@@ -17,8 +17,8 @@ static int dump(MDBX_cursor *cur) {
int rc = mdbx_cursor_get(cur, &key, &data, MDBX_FIRST);
while (rc == 0) {
printf("(%.*s) = (%.*s)\n", (int)key.iov_len, (const char *)key.iov_base,
(int)data.iov_len, (const char *)data.iov_base);
printf("(%.*s) = (%.*s)\n", (int)key.iov_len, (const char *)key.iov_base, (int)data.iov_len,
(const char *)data.iov_base);
rc = mdbx_cursor_get(cur, &key, &data, MDBX_NEXT);
}
return rc;
@@ -38,8 +38,7 @@ static int clear(MDBX_cursor *cur) {
return (rc == MDBX_NOTFOUND) ? 0 : rc;
}
static int put(MDBX_txn *txn, MDBX_dbi dbi, const char *k, const char *v,
MDBX_put_flags_t flags) {
static int put(MDBX_txn *txn, MDBX_dbi dbi, const char *k, const char *v, MDBX_put_flags_t flags) {
MDBX_val key = {.iov_base = (void *)k, .iov_len = strlen(k)};
MDBX_val data = {.iov_base = (void *)v, .iov_len = strlen(v)};
return mdbx_put(txn, dbi, &key, &data, flags);
@@ -79,21 +78,21 @@ int main(int argc, const char *argv[]) {
goto Fail;
}
#define DUMP() \
do { \
if ((rc = dump(cur)) && rc != MDBX_NOTFOUND) { \
errmsg = "failed to mdbx_cursor_get(FIRST): %s\n"; \
goto Fail; \
} \
puts(""); \
#define DUMP() \
do { \
if ((rc = dump(cur)) && rc != MDBX_NOTFOUND) { \
errmsg = "failed to mdbx_cursor_get(FIRST): %s\n"; \
goto Fail; \
} \
puts(""); \
} while (0)
#define PUTVAL(k, v, flags) \
do { \
if ((rc = put(txn, dbi, k, v, flags))) { \
errmsg = "failed to mdbx_put: %s\n"; \
goto Fail; \
} \
#define PUTVAL(k, v, flags) \
do { \
if ((rc = put(txn, dbi, k, v, flags))) { \
errmsg = "failed to mdbx_put: %s\n"; \
goto Fail; \
} \
} while (0)
puts("TEST WITH MULTIPLE KEYS ====================");

View File

@@ -17,8 +17,7 @@ protected:
unsigned dbi_state{0};
public:
testcase_smoke4fork(const actor_config &config, const mdbx_pid_t pid)
: testcase(config, pid) {}
testcase_smoke4fork(const actor_config &config, const mdbx_pid_t pid) : testcase(config, pid) {}
virtual void txn_end(bool abort) override;
bool run() override;
virtual bool smoke() = 0;
@@ -27,8 +26,7 @@ public:
bool testcase_smoke4fork::open_dbi() {
if (!dbi || dbi_invalid) {
if (dbi_stable ||
(mdbx_txn_flags(txn_guard.get()) & MDBX_TXN_RDONLY) == 0) {
if (dbi_stable || (mdbx_txn_flags(txn_guard.get()) & MDBX_TXN_RDONLY) == 0) {
dbi = db_table_open(!dbi_stable);
dbi_invalid = false;
}
@@ -37,8 +35,7 @@ bool testcase_smoke4fork::open_dbi() {
dbi_state = 0;
if (dbi && !dbi_invalid) {
unsigned unused_dbi_flags;
int err =
mdbx_dbi_flags_ex(txn_guard.get(), dbi, &unused_dbi_flags, &dbi_state);
int err = mdbx_dbi_flags_ex(txn_guard.get(), dbi, &unused_dbi_flags, &dbi_state);
if (unlikely(err != MDBX_SUCCESS))
failure_perror("mdbx_dbi_flags_ex()", err);
if ((dbi_state & (MDBX_DBI_CREAT | MDBX_DBI_FRESH)) == 0)
@@ -69,8 +66,7 @@ bool testcase_smoke4fork::run() {
if (history.empty() || current_pid != history.front()) {
history.push_back(current_pid);
if (history.size() > /* TODO: add test option */ 2) {
log_notice("force exit to avoid fork-bomb: deep %zu, pid stack",
history.size());
log_notice("force exit to avoid fork-bomb: deep %zu, pid stack", history.size());
for (const auto pid : history)
logging::feed(" %d", pid);
logging::ln();
@@ -82,23 +78,19 @@ bool testcase_smoke4fork::run() {
int err = db_open__begin__table_create_open_clean(dbi);
if (unlikely(err != MDBX_SUCCESS)) {
log_notice("fork[deep %d, pid %d]: bailout-prepare due '%s'", deep,
current_pid, mdbx_strerror(err));
log_notice("fork[deep %d, pid %d]: bailout-prepare due '%s'", deep, current_pid, mdbx_strerror(err));
return false;
}
open_dbi();
if (flipcoin()) {
if (!smoke()) {
log_notice("%s[deep %d, pid %d] probe %s", "pre-fork", deep, current_pid,
"failed");
log_notice("%s[deep %d, pid %d] probe %s", "pre-fork", deep, current_pid, "failed");
return false;
}
log_verbose("%s[deep %d, pid %d] probe %s", "pre-fork", deep, current_pid,
"done");
log_verbose("%s[deep %d, pid %d] probe %s", "pre-fork", deep, current_pid, "done");
} else {
log_verbose("%s[deep %d, pid %d] probe %s", "pre-fork", deep, current_pid,
"skipped");
log_verbose("%s[deep %d, pid %d] probe %s", "pre-fork", deep, current_pid, "skipped");
#ifdef __SANITIZE_ADDRESS__
const bool commit_txn_to_avoid_memleak = true;
#else
@@ -115,13 +107,12 @@ bool testcase_smoke4fork::run() {
if (child == 0) {
const pid_t new_pid = getpid();
log_verbose(">>> %s, deep %d, parent-pid %d, child-pid %d",
"mdbx_env_resurrect_after_fork()", deep, current_pid, new_pid);
log_verbose(">>> %s, deep %d, parent-pid %d, child-pid %d", "mdbx_env_resurrect_after_fork()", deep, current_pid,
new_pid);
log_flush();
int err = mdbx_env_resurrect_after_fork(db_guard.get());
log_verbose("<<< %s, deep %d, parent-pid %d, child-pid %d, err %d",
"mdbx_env_resurrect_after_fork()", deep, current_pid, new_pid,
err);
log_verbose("<<< %s, deep %d, parent-pid %d, child-pid %d, err %d", "mdbx_env_resurrect_after_fork()", deep,
current_pid, new_pid, err);
log_flush();
if (err != MDBX_SUCCESS)
failure_perror("mdbx_env_resurrect_after_fork()", err);
@@ -134,12 +125,10 @@ bool testcase_smoke4fork::run() {
mdbx_txn_abort(txn_guard.release());
}
if (!smoke()) {
log_notice("%s[deep %d, pid %d] probe %s", "fork-child", deep, new_pid,
"failed");
log_notice("%s[deep %d, pid %d] probe %s", "fork-child", deep, new_pid, "failed");
return false;
}
log_verbose("%s[deep %d, pid %d] probe %s", "fork-child", deep, new_pid,
"done");
log_verbose("%s[deep %d, pid %d] probe %s", "fork-child", deep, new_pid, "done");
log_flush();
return true;
}
@@ -154,12 +143,10 @@ bool testcase_smoke4fork::run() {
if (WIFEXITED(status)) {
const int code = WEXITSTATUS(status);
if (code != EXIT_SUCCESS) {
log_notice("%s[deep %d, pid %d] child-pid %d failed, err %d",
"fork-child", deep, current_pid, child, code);
log_notice("%s[deep %d, pid %d] child-pid %d failed, err %d", "fork-child", deep, current_pid, child, code);
return false;
}
log_notice("%s[deep %d, pid %d] child-pid %d done", "fork-child", deep,
current_pid, child);
log_notice("%s[deep %d, pid %d] child-pid %d done", "fork-child", deep, current_pid, child);
} else if (WIFSIGNALED(status)) {
const int sig = WTERMSIG(status);
switch (sig) {
@@ -168,12 +155,12 @@ bool testcase_smoke4fork::run() {
case SIGFPE:
case SIGILL:
case SIGSEGV:
log_notice("%s[deep %d, pid %d] child-pid %d %s by SIG%s", "fork-child",
deep, current_pid, child, "terminated", signal_name(sig));
log_notice("%s[deep %d, pid %d] child-pid %d %s by SIG%s", "fork-child", deep, current_pid, child, "terminated",
signal_name(sig));
break;
default:
log_notice("%s[deep %d, pid %d] child-id %d %s by SIG%s", "fork-child",
deep, current_pid, child, "killed", signal_name(sig));
log_notice("%s[deep %d, pid %d] child-id %d %s by SIG%s", "fork-child", deep, current_pid, child, "killed",
signal_name(sig));
}
return false;
} else {
@@ -181,12 +168,10 @@ bool testcase_smoke4fork::run() {
}
if (!smoke()) {
log_notice("%s[deep %d, pid %d] probe %s", "post-fork", deep, current_pid,
"failed");
log_notice("%s[deep %d, pid %d] probe %s", "post-fork", deep, current_pid, "failed");
return false;
}
log_verbose("%s[deep %d, pid %d] probe %s", "post-fork", deep, current_pid,
"done");
log_verbose("%s[deep %d, pid %d] probe %s", "post-fork", deep, current_pid, "done");
return true;
}
@@ -196,16 +181,14 @@ class testcase_forkread : public testcase_smoke4fork {
using inherited = testcase_smoke4fork;
public:
testcase_forkread(const actor_config &config, const mdbx_pid_t pid)
: testcase_smoke4fork(config, pid) {}
testcase_forkread(const actor_config &config, const mdbx_pid_t pid) : testcase_smoke4fork(config, pid) {}
bool smoke() override;
};
REGISTER_TESTCASE(forkread);
bool testcase_forkread::smoke() {
MDBX_envinfo env_info;
int err = mdbx_env_info_ex(db_guard.get(), txn_guard.get(), &env_info,
sizeof(env_info));
int err = mdbx_env_info_ex(db_guard.get(), txn_guard.get(), &env_info, sizeof(env_info));
if (err)
failure_perror("mdbx_env_info_ex()", err);
@@ -217,8 +200,7 @@ bool testcase_forkread::smoke() {
if (err)
failure_perror("mdbx_txn_info()", err);
fetch_canary();
err = mdbx_env_info_ex(db_guard.get(), txn_guard.get(), &env_info,
sizeof(env_info));
err = mdbx_env_info_ex(db_guard.get(), txn_guard.get(), &env_info, sizeof(env_info));
if (err)
failure_perror("mdbx_env_info_ex()", err);
@@ -226,15 +208,13 @@ bool testcase_forkread::smoke() {
if (dbi_invalid) {
err = mdbx_dbi_sequence(txn_guard.get(), dbi, &seq, 0);
if (unlikely(err != (dbi ? MDBX_BAD_DBI : MDBX_SUCCESS)))
failure("unexpected '%s' from mdbx_dbi_sequence(get, bad_dbi %d)",
mdbx_strerror(err), dbi);
failure("unexpected '%s' from mdbx_dbi_sequence(get, bad_dbi %d)", mdbx_strerror(err), dbi);
open_dbi();
}
if (!dbi_invalid) {
err = mdbx_dbi_sequence(txn_guard.get(), dbi, &seq, 0);
if (unlikely(err != MDBX_SUCCESS))
failure("unexpected '%s' from mdbx_dbi_sequence(get, dbi %d)",
mdbx_strerror(err), dbi);
failure("unexpected '%s' from mdbx_dbi_sequence(get, dbi %d)", mdbx_strerror(err), dbi);
}
txn_end(false);
return true;
@@ -246,8 +226,7 @@ class testcase_forkwrite : public testcase_forkread {
using inherited = testcase_forkread;
public:
testcase_forkwrite(const actor_config &config, const mdbx_pid_t pid)
: testcase_forkread(config, pid) {}
testcase_forkwrite(const actor_config &config, const mdbx_pid_t pid) : testcase_forkread(config, pid) {}
bool smoke() override;
};
REGISTER_TESTCASE(forkwrite);
@@ -266,15 +245,13 @@ bool testcase_forkwrite::smoke() {
if (dbi_invalid) {
int err = mdbx_dbi_sequence(txn_guard.get(), dbi, &seq, 0);
if (unlikely(err != (dbi ? MDBX_BAD_DBI : MDBX_EACCESS)))
failure("unexpected '%s' from mdbx_dbi_sequence(get, bad_dbi %d)",
mdbx_strerror(err), dbi);
failure("unexpected '%s' from mdbx_dbi_sequence(get, bad_dbi %d)", mdbx_strerror(err), dbi);
open_dbi();
}
if (!dbi_invalid) {
int err = mdbx_dbi_sequence(txn_guard.get(), dbi, &seq, 1);
if (unlikely(err != MDBX_SUCCESS))
failure("unexpected '%s' from mdbx_dbi_sequence(inc, dbi %d)",
mdbx_strerror(err), dbi);
failure("unexpected '%s' from mdbx_dbi_sequence(inc, dbi %d)", mdbx_strerror(err), dbi);
}
txn_end(false);

View File

@@ -25,8 +25,7 @@
class testcase_hill : public testcase {
public:
testcase_hill(const actor_config &config, const mdbx_pid_t pid)
: testcase(config, pid) {}
testcase_hill(const actor_config &config, const mdbx_pid_t pid) : testcase(config, pid) {}
bool run() override;
};
REGISTER_TESTCASE(hill);
@@ -50,13 +49,9 @@ bool testcase_hill::run() {
keygen::buffer b_data = keygen::alloc(config.params.datalen_max);
const MDBX_put_flags_t insert_flags =
(config.params.table_flags & MDBX_DUPSORT)
? MDBX_NODUPDATA
: MDBX_NODUPDATA | MDBX_NOOVERWRITE;
(config.params.table_flags & MDBX_DUPSORT) ? MDBX_NODUPDATA : MDBX_NODUPDATA | MDBX_NOOVERWRITE;
const MDBX_put_flags_t update_flags =
(config.params.table_flags & MDBX_DUPSORT)
? MDBX_CURRENT | MDBX_NODUPDATA | MDBX_NOOVERWRITE
: MDBX_NODUPDATA;
(config.params.table_flags & MDBX_DUPSORT) ? MDBX_CURRENT | MDBX_NODUPDATA | MDBX_NOOVERWRITE : MDBX_NODUPDATA;
uint64_t serial_count = 0;
uint64_t committed_serial = serial_count;
@@ -80,8 +75,7 @@ bool testcase_hill::run() {
// создаем первую запись из пары
const keygen::serial_t age_shift = keyvalue_maker.remix_age(a_serial);
log_trace("uphill: insert-a (age %" PRIu64 ") %" PRIu64, age_shift,
a_serial);
log_trace("uphill: insert-a (age %" PRIu64 ") %" PRIu64, age_shift, a_serial);
generate_pair(a_serial, a_key, a_data_1, age_shift);
err = insert(a_key, a_data_1, insert_flags);
@@ -154,8 +148,7 @@ bool testcase_hill::run() {
}
// обновляем данные в первой записи
log_trace("uphill: update-a (age %" PRIu64 "->0) %" PRIu64, age_shift,
a_serial);
log_trace("uphill: update-a (age %" PRIu64 "->0) %" PRIu64, age_shift, a_serial);
generate_pair(a_serial, a_key, a_data_0, 0);
checkdata("uphill: update-a", dbi, a_key->value, a_data_1->value);
err = replace(a_key, a_data_0, a_data_1, update_flags);
@@ -271,8 +264,7 @@ bool testcase_hill::run() {
if (str.back() == '-')
str.append(std::to_string(prev));
log_notice("hill: reached %d tree depth & %s sub-tree depth(s)",
stat.ms_depth, str.c_str());
log_notice("hill: reached %d tree depth & %s sub-tree depth(s)", stat.ms_depth, str.c_str());
}
if ((config.params.table_flags & MDBX_DUPSORT) == 0) {
@@ -292,16 +284,14 @@ bool testcase_hill::run() {
// обновляем первую запись из пары
const keygen::serial_t age_shift = keyvalue_maker.remix_age(a_serial);
log_trace("downhill: update-a (age 0->%" PRIu64 ") %" PRIu64, age_shift,
a_serial);
log_trace("downhill: update-a (age 0->%" PRIu64 ") %" PRIu64, age_shift, a_serial);
generate_pair(a_serial, a_key, a_data_0, 0);
generate_pair(a_serial, a_key, a_data_1, age_shift);
checkdata("downhill: update-a", dbi, a_key->value, a_data_0->value);
err = replace(a_key, a_data_1, a_data_0, update_flags);
if (unlikely(err != MDBX_SUCCESS)) {
if (err == MDBX_MAP_FULL && config.params.ignore_dbfull) {
log_notice("downhill: bailout at update-a due '%s'",
mdbx_strerror(err));
log_notice("downhill: bailout at update-a due '%s'", mdbx_strerror(err));
txn_end(true);
speculum = speculum_committed;
break;
@@ -334,8 +324,7 @@ bool testcase_hill::run() {
err = insert(b_key, b_data, insert_flags);
if (unlikely(err != MDBX_SUCCESS)) {
if (err == MDBX_MAP_FULL && config.params.ignore_dbfull) {
log_notice("downhill: bailout at insert-a due '%s'",
mdbx_strerror(err));
log_notice("downhill: bailout at insert-a due '%s'", mdbx_strerror(err));
txn_end(true);
speculum = speculum_committed;
break;
@@ -363,14 +352,12 @@ bool testcase_hill::run() {
}
// удаляем первую запись
log_trace("downhill: delete-a (age %" PRIu64 ") %" PRIu64, age_shift,
a_serial);
log_trace("downhill: delete-a (age %" PRIu64 ") %" PRIu64, age_shift, a_serial);
checkdata("downhill: delete-a", dbi, a_key->value, a_data_1->value);
err = remove(a_key, a_data_1);
if (unlikely(err != MDBX_SUCCESS)) {
if (err == MDBX_MAP_FULL && config.params.ignore_dbfull) {
log_notice("downhill: bailout at delete-a due '%s'",
mdbx_strerror(err));
log_notice("downhill: bailout at delete-a due '%s'", mdbx_strerror(err));
txn_end(true);
speculum = speculum_committed;
break;
@@ -403,8 +390,7 @@ bool testcase_hill::run() {
err = remove(b_key, b_data);
if (unlikely(err != MDBX_SUCCESS)) {
if (err == MDBX_MAP_FULL && config.params.ignore_dbfull) {
log_notice("downhill: bailout at delete-b due '%s'",
mdbx_strerror(err));
log_notice("downhill: bailout at delete-b due '%s'", mdbx_strerror(err));
txn_end(true);
speculum = speculum_committed;
break;

View File

@@ -8,8 +8,7 @@ protected:
void check_dbi_error(int expect, const char *stage);
public:
testcase_jitter(const actor_config &config, const mdbx_pid_t pid)
: testcase(config, pid) {}
testcase_jitter(const actor_config &config, const mdbx_pid_t pid) : testcase(config, pid) {}
bool run() override;
};
REGISTER_TESTCASE(jitter);
@@ -18,8 +17,7 @@ void testcase_jitter::check_dbi_error(int expect, const char *stage) {
MDBX_stat stat;
int err = mdbx_dbi_stat(txn_guard.get(), dbi, &stat, sizeof(stat));
if (err != expect)
failure("unexpected result for %s dbi-handle: expect %d, got %d", stage,
expect, err);
failure("unexpected result for %s dbi-handle: expect %d, got %d", stage, expect, err);
}
bool testcase_jitter::run() {
@@ -31,8 +29,7 @@ bool testcase_jitter::run() {
tablename_buf buffer;
const char *const tablename = db_tablename(buffer);
tablename_buf buffer_renamed;
const char *const tablename_renamed =
db_tablename(buffer_renamed, ".renamed");
const char *const tablename_renamed = db_tablename(buffer_renamed, ".renamed");
while (should_continue()) {
jitter_delay();
@@ -81,9 +78,8 @@ bool testcase_jitter::run() {
// restore DBI
dbi = db_table_open(false, renamed);
if (renamed) {
err = mdbx_dbi_open(
txn_guard.get(), tablename_renamed,
flipcoin() ? MDBX_DB_ACCEDE : config.params.table_flags, &dbi);
err = mdbx_dbi_open(txn_guard.get(), tablename_renamed, flipcoin() ? MDBX_DB_ACCEDE : config.params.table_flags,
&dbi);
if (unlikely(err != MDBX_SUCCESS))
failure_perror("open-renamed", err);
err = mdbx_dbi_rename(txn_guard.get(), dbi, tablename);
@@ -100,13 +96,10 @@ bool testcase_jitter::run() {
if (upper_limit < 1) {
MDBX_envinfo info;
err = mdbx_env_info_ex(db_guard.get(), txn_guard.get(), &info,
sizeof(info));
err = mdbx_env_info_ex(db_guard.get(), txn_guard.get(), &info, sizeof(info));
if (err)
failure_perror("mdbx_env_info_ex()", err);
upper_limit = (info.mi_geo.upper < INTPTR_MAX)
? (intptr_t)info.mi_geo.upper
: INTPTR_MAX;
upper_limit = (info.mi_geo.upper < INTPTR_MAX) ? (intptr_t)info.mi_geo.upper : INTPTR_MAX;
}
if (flipcoin()) {
@@ -156,29 +149,26 @@ bool testcase_jitter::run() {
fetch_canary();
update_canary(1);
if (global::config::geometry_jitter) {
err = mdbx_env_set_geometry(
db_guard.get(), -1, -1,
coin4size ? upper_limit * 2 / 3 : upper_limit * 3 / 2, -1, -1, -1);
if (err != MDBX_SUCCESS && err != MDBX_UNABLE_EXTEND_MAPSIZE &&
err != MDBX_MAP_FULL && err != MDBX_TOO_LARGE && err != MDBX_EPERM)
err = mdbx_env_set_geometry(db_guard.get(), -1, -1, coin4size ? upper_limit * 2 / 3 : upper_limit * 3 / 2, -1,
-1, -1);
if (err != MDBX_SUCCESS && err != MDBX_UNABLE_EXTEND_MAPSIZE && err != MDBX_MAP_FULL && err != MDBX_TOO_LARGE &&
err != MDBX_EPERM)
failure_perror("mdbx_env_set_geometry-1", err);
}
}
if (flipcoin()) {
uint64_t unused;
err = mdbx_dbi_sequence(txn_guard.get(), MAIN_DBI, &unused,
mode_readonly() ? 0 : 1);
err = mdbx_dbi_sequence(txn_guard.get(), MAIN_DBI, &unused, mode_readonly() ? 0 : 1);
if (err)
failure_perror("mdbx_dbi_sequence()", err);
}
txn_end(flipcoin());
if (global::config::geometry_jitter) {
err = mdbx_env_set_geometry(
db_guard.get(), -1, -1,
!coin4size ? upper_limit * 2 / 3 : upper_limit * 3 / 2, -1, -1, -1);
if (err != MDBX_SUCCESS && err != MDBX_UNABLE_EXTEND_MAPSIZE &&
err != MDBX_MAP_FULL && err != MDBX_TOO_LARGE && err != MDBX_EPERM)
err = mdbx_env_set_geometry(db_guard.get(), -1, -1, !coin4size ? upper_limit * 2 / 3 : upper_limit * 3 / 2, -1,
-1, -1);
if (err != MDBX_SUCCESS && err != MDBX_UNABLE_EXTEND_MAPSIZE && err != MDBX_MAP_FULL && err != MDBX_TOO_LARGE &&
err != MDBX_EPERM)
failure_perror("mdbx_env_set_geometry-2", err);
}
@@ -191,18 +181,16 @@ bool testcase_jitter::run() {
if (global::config::geometry_jitter) {
jitter_delay();
err = mdbx_env_set_geometry(db_guard.get(), -1, -1, upper_limit, -1, -1,
-1);
if (err != MDBX_SUCCESS && err != MDBX_UNABLE_EXTEND_MAPSIZE &&
err != MDBX_MAP_FULL && err != MDBX_TOO_LARGE && err != MDBX_EPERM)
err = mdbx_env_set_geometry(db_guard.get(), -1, -1, upper_limit, -1, -1, -1);
if (err != MDBX_SUCCESS && err != MDBX_UNABLE_EXTEND_MAPSIZE && err != MDBX_MAP_FULL && err != MDBX_TOO_LARGE &&
err != MDBX_EPERM)
failure_perror("mdbx_env_set_geometry-3", err);
}
db_close();
/* just 'align' nops with other tests with batching */
const auto batching =
std::max(config.params.batch_read, config.params.batch_write);
const auto batching = std::max(config.params.batch_read, config.params.batch_write);
report(std::max(1u, batching / 2));
}
return true;

View File

@@ -7,25 +7,18 @@ static const uint64_t primes[64] = {
/* */
0, 1, 3, 7, 13, 31, 61, 127, 251, 509, 1021, 2039, 4093, 8191, 16381,
/* */
UINT64_C(32749), UINT64_C(65521), UINT64_C(131071), UINT64_C(262139),
UINT64_C(524287), UINT64_C(1048573), UINT64_C(2097143), UINT64_C(4194301),
UINT64_C(8388593), UINT64_C(16777213), UINT64_C(33554393),
UINT64_C(67108859), UINT64_C(134217689), UINT64_C(268435399),
UINT64_C(536870909), UINT64_C(1073741789), UINT64_C(2147483647),
UINT64_C(4294967291), UINT64_C(8589934583), UINT64_C(17179869143),
UINT64_C(34359738337), UINT64_C(68719476731), UINT64_C(137438953447),
UINT64_C(274877906899), UINT64_C(549755813881), UINT64_C(1099511627689),
UINT64_C(2199023255531), UINT64_C(4398046511093), UINT64_C(8796093022151),
UINT64_C(17592186044399), UINT64_C(35184372088777),
UINT64_C(70368744177643), UINT64_C(140737488355213),
UINT64_C(281474976710597), UINT64_C(562949953421231),
UINT64_C(1125899906842597), UINT64_C(2251799813685119),
UINT64_C(4503599627370449), UINT64_C(9007199254740881),
UINT64_C(18014398509481951), UINT64_C(36028797018963913),
UINT64_C(72057594037927931), UINT64_C(144115188075855859),
UINT64_C(288230376151711717), UINT64_C(576460752303423433),
UINT64_C(1152921504606846883), UINT64_C(2305843009213693951),
UINT64_C(4611686018427387847), UINT64_C(9223372036854775783)};
UINT64_C(32749), UINT64_C(65521), UINT64_C(131071), UINT64_C(262139), UINT64_C(524287), UINT64_C(1048573),
UINT64_C(2097143), UINT64_C(4194301), UINT64_C(8388593), UINT64_C(16777213), UINT64_C(33554393), UINT64_C(67108859),
UINT64_C(134217689), UINT64_C(268435399), UINT64_C(536870909), UINT64_C(1073741789), UINT64_C(2147483647),
UINT64_C(4294967291), UINT64_C(8589934583), UINT64_C(17179869143), UINT64_C(34359738337), UINT64_C(68719476731),
UINT64_C(137438953447), UINT64_C(274877906899), UINT64_C(549755813881), UINT64_C(1099511627689),
UINT64_C(2199023255531), UINT64_C(4398046511093), UINT64_C(8796093022151), UINT64_C(17592186044399),
UINT64_C(35184372088777), UINT64_C(70368744177643), UINT64_C(140737488355213), UINT64_C(281474976710597),
UINT64_C(562949953421231), UINT64_C(1125899906842597), UINT64_C(2251799813685119), UINT64_C(4503599627370449),
UINT64_C(9007199254740881), UINT64_C(18014398509481951), UINT64_C(36028797018963913), UINT64_C(72057594037927931),
UINT64_C(144115188075855859), UINT64_C(288230376151711717), UINT64_C(576460752303423433),
UINT64_C(1152921504606846883), UINT64_C(2305843009213693951), UINT64_C(4611686018427387847),
UINT64_C(9223372036854775783)};
/* static unsigned supid_log2(uint64_t v) {
unsigned r = 0;
@@ -39,9 +32,7 @@ static const uint64_t primes[64] = {
namespace keygen {
/* LY: https://en.wikipedia.org/wiki/Injective_function */
serial_t injective(const serial_t serial,
const unsigned bits /* at least serial_minwith (8) */,
const serial_t salt) {
serial_t injective(const serial_t serial, const unsigned bits /* at least serial_minwith (8) */, const serial_t salt) {
assert(bits >= serial_minwith && bits <= serial_maxwith);
/* LY: All these "magic" prime numbers were found
@@ -49,26 +40,21 @@ serial_t injective(const serial_t serial,
static const uint64_t m[64 - serial_minwith + 1] = {
/* 8 - 24 */
113, 157, 397, 653, 1753, 5641, 9697, 23873, 25693, 80833, 105953, 316937,
309277, 834497, 1499933, 4373441, 10184137,
113, 157, 397, 653, 1753, 5641, 9697, 23873, 25693, 80833, 105953, 316937, 309277, 834497, 1499933, 4373441,
10184137,
/* 25 - 64 */
10184137, 17279209, 33990377, 67295161, 284404553, 1075238767, 6346721573,
6924051577, 19204053433, 45840188887, 53625693977, 73447827913,
141638870249, 745683604649, 1283334050489, 1100828289853, 2201656586197,
5871903036137, 11238507001417, 45264020802263, 105008404482889,
81921776907059, 199987980256399, 307207457507641, 946769023178273,
2420886491930041, 3601632139991929, 11984491914483833, 21805846439714153,
23171543400565993, 53353226456762893, 155627817337932409,
227827205384840249, 816509268558278821, 576933057762605689,
2623957345935638441, 5048241705479929949, 4634245581946485653,
4613509448041658233, 4952535426879925961};
static const uint8_t s[64 - serial_minwith + 1] = {
/* 8 - 24 */
2, 3, 4, 4, 2, 4, 3, 3, 7, 3, 3, 4, 8, 3, 10, 3, 11,
/* 25 - 64 */
11, 9, 9, 9, 11, 10, 5, 14, 11, 16, 14, 12, 13, 16, 19, 10, 10, 21, 7, 20,
10, 14, 22, 19, 3, 21, 18, 19, 26, 24, 2, 21, 25, 29, 24, 10, 11, 14, 20,
19};
10184137, 17279209, 33990377, 67295161, 284404553, 1075238767, 6346721573, 6924051577, 19204053433, 45840188887,
53625693977, 73447827913, 141638870249, 745683604649, 1283334050489, 1100828289853, 2201656586197, 5871903036137,
11238507001417, 45264020802263, 105008404482889, 81921776907059, 199987980256399, 307207457507641,
946769023178273, 2420886491930041, 3601632139991929, 11984491914483833, 21805846439714153, 23171543400565993,
53353226456762893, 155627817337932409, 227827205384840249, 816509268558278821, 576933057762605689,
2623957345935638441, 5048241705479929949, 4634245581946485653, 4613509448041658233, 4952535426879925961};
static const uint8_t s[64 - serial_minwith + 1] = {/* 8 - 24 */
2, 3, 4, 4, 2, 4, 3, 3, 7, 3, 3, 4, 8, 3, 10, 3, 11,
/* 25 - 64 */
11, 9, 9, 9, 11, 10, 5, 14, 11, 16, 14, 12, 13, 16, 19, 10, 10, 21,
7, 20, 10, 14, 22, 19, 3, 21, 18, 19, 26, 24, 2, 21, 25, 29, 24,
10, 11, 14, 20, 19};
const auto mask = actor_params::serial_mask(bits);
const auto mult = m[bits - 8];
@@ -83,49 +69,40 @@ serial_t injective(const serial_t serial,
result ^= (result & mask) >> shift;
result &= mask;
log_trace("keygen-injective: serial %" PRIu64 "/%u @%" PRIx64 ",%u,%" PRIu64
" => %" PRIu64 "/%u",
serial, bits, mult, shift, salt, result, bits);
log_trace("keygen-injective: serial %" PRIu64 "/%u @%" PRIx64 ",%u,%" PRIu64 " => %" PRIu64 "/%u", serial, bits, mult,
shift, salt, result, bits);
return result;
}
void __hot maker::pair(serial_t serial, const buffer &key, buffer &value,
serial_t value_age, const bool keylen_changeable) {
void __hot maker::pair(serial_t serial, const buffer &key, buffer &value, serial_t value_age,
const bool keylen_changeable) {
assert(mapping.width >= serial_minwith && mapping.width <= serial_maxwith);
assert(mapping.split <= mapping.width);
assert(mapping.mesh <= mapping.width);
assert(mapping.rotate <= mapping.width);
assert(mapping.offset <= actor_params::serial_mask(mapping.width));
assert(!(key_essentials.flags &
~(essentials::prng_fill_flag |
unsigned(MDBX_INTEGERKEY | MDBX_REVERSEKEY | MDBX_DUPSORT))));
~(essentials::prng_fill_flag | unsigned(MDBX_INTEGERKEY | MDBX_REVERSEKEY | MDBX_DUPSORT))));
assert(!(value_essentials.flags &
~(essentials::prng_fill_flag |
unsigned(MDBX_INTEGERDUP | MDBX_REVERSEDUP | MDBX_DUPFIXED))));
~(essentials::prng_fill_flag | unsigned(MDBX_INTEGERDUP | MDBX_REVERSEDUP | MDBX_DUPFIXED))));
log_trace("keygen-pair: serial %" PRIu64 ", data-age %" PRIu64, serial,
value_age);
log_trace("keygen-pair: serial %" PRIu64 ", data-age %" PRIu64, serial, value_age);
if (mapping.mesh >= serial_minwith) {
serial = (serial & ~actor_params::serial_mask(mapping.mesh)) |
injective(serial, mapping.mesh, salt);
serial = (serial & ~actor_params::serial_mask(mapping.mesh)) | injective(serial, mapping.mesh, salt);
log_trace("keygen-pair: mesh@%u => %" PRIu64, mapping.mesh, serial);
}
if (mapping.rotate) {
const unsigned right = mapping.rotate;
const unsigned left = mapping.width - right;
serial = (serial << left) |
((serial & actor_params::serial_mask(mapping.width)) >> right);
log_trace("keygen-pair: rotate@%u => %" PRIu64 ", 0x%" PRIx64,
mapping.rotate, serial, serial);
serial = (serial << left) | ((serial & actor_params::serial_mask(mapping.width)) >> right);
log_trace("keygen-pair: rotate@%u => %" PRIu64 ", 0x%" PRIx64, mapping.rotate, serial, serial);
}
if (mapping.offset) {
serial =
(serial + mapping.offset) & actor_params::serial_mask(mapping.width);
log_trace("keygen-pair: offset@%" PRIu64 " => %" PRIu64, mapping.offset,
serial);
serial = (serial + mapping.offset) & actor_params::serial_mask(mapping.width);
log_trace("keygen-pair: offset@%" PRIu64 " => %" PRIu64, mapping.offset, serial);
}
if (base) {
serial += base;
@@ -144,16 +121,13 @@ void __hot maker::pair(serial_t serial, const buffer &key, buffer &value,
* Поэтому key_serial не трогаем, а в value_serial нелинейно вмешиваем
* запрошенное количество бит из serial */
value_serial +=
(serial ^ (serial >> mapping.split) * UINT64_C(57035339200100753)) &
actor_params::serial_mask(mapping.split);
(serial ^ (serial >> mapping.split) * UINT64_C(57035339200100753)) & actor_params::serial_mask(mapping.split);
}
log_trace("keygen-pair: split@%u => k%" PRIu64 ", v%" PRIu64, mapping.split,
key_serial, value_serial);
log_trace("keygen-pair: split@%u => k%" PRIu64 ", v%" PRIu64, mapping.split, key_serial, value_serial);
}
log_trace("keygen-pair: key %" PRIu64 ", value %" PRIu64, key_serial,
value_serial);
log_trace("keygen-pair: key %" PRIu64 ", value %" PRIu64, key_serial, value_serial);
key_serial = mk_begin(key_serial, key_essentials, *key);
value_serial = mk_begin(value_serial, value_essentials, *value);
@@ -210,50 +184,39 @@ void __hot maker::pair(serial_t serial, const buffer &key, buffer &value,
log_pair(logging::trace, "kv", key, value);
}
void maker::setup(const config::actor_params_pod &actor,
unsigned thread_number) {
void maker::setup(const config::actor_params_pod &actor, unsigned thread_number) {
#if CONSTEXPR_ENUM_FLAGS_OPERATIONS
static_assert(unsigned(MDBX_INTEGERKEY | MDBX_REVERSEKEY | MDBX_DUPSORT |
MDBX_DUPFIXED | MDBX_INTEGERDUP | MDBX_REVERSEDUP) <
UINT16_MAX,
static_assert(unsigned(MDBX_INTEGERKEY | MDBX_REVERSEKEY | MDBX_DUPSORT | MDBX_DUPFIXED | MDBX_INTEGERDUP |
MDBX_REVERSEDUP) < UINT16_MAX,
"WTF?");
#else
assert(unsigned(MDBX_INTEGERKEY | MDBX_REVERSEKEY | MDBX_DUPSORT |
MDBX_DUPFIXED | MDBX_INTEGERDUP | MDBX_REVERSEDUP) <
UINT16_MAX);
assert(unsigned(MDBX_INTEGERKEY | MDBX_REVERSEKEY | MDBX_DUPSORT | MDBX_DUPFIXED | MDBX_INTEGERDUP |
MDBX_REVERSEDUP) < UINT16_MAX);
#endif
key_essentials.flags = uint16_t(
actor.table_flags &
MDBX_db_flags_t(MDBX_INTEGERKEY | MDBX_REVERSEKEY | MDBX_DUPSORT));
key_essentials.flags =
uint16_t(actor.table_flags & MDBX_db_flags_t(MDBX_INTEGERKEY | MDBX_REVERSEKEY | MDBX_DUPSORT));
assert(actor.keylen_min <= UINT16_MAX);
key_essentials.minlen = uint16_t(actor.keylen_min);
assert(actor.keylen_max <= UINT32_MAX);
key_essentials.maxlen = std::min(
uint32_t(actor.keylen_max),
uint32_t(mdbx_limits_keysize_max(actor.pagesize, actor.table_flags)));
key_essentials.bits = (key_essentials.maxlen < sizeof(serial_t))
? key_essentials.maxlen * CHAR_BIT
: sizeof(serial_t) * CHAR_BIT;
key_essentials.maxlen =
std::min(uint32_t(actor.keylen_max), uint32_t(mdbx_limits_keysize_max(actor.pagesize, actor.table_flags)));
key_essentials.bits =
(key_essentials.maxlen < sizeof(serial_t)) ? key_essentials.maxlen * CHAR_BIT : sizeof(serial_t) * CHAR_BIT;
key_essentials.mask = actor_params::serial_mask(key_essentials.bits);
assert(key_essentials.bits > 63 ||
key_essentials.mask > primes[key_essentials.bits]);
assert(key_essentials.bits > 63 || key_essentials.mask > primes[key_essentials.bits]);
value_essentials.flags = uint16_t(
actor.table_flags &
MDBX_db_flags_t(MDBX_INTEGERDUP | MDBX_REVERSEDUP | MDBX_DUPFIXED));
value_essentials.flags =
uint16_t(actor.table_flags & MDBX_db_flags_t(MDBX_INTEGERDUP | MDBX_REVERSEDUP | MDBX_DUPFIXED));
assert(actor.datalen_min <= UINT16_MAX);
value_essentials.minlen = uint16_t(actor.datalen_min);
assert(actor.datalen_max <= UINT32_MAX);
value_essentials.maxlen = std::min(
uint32_t(actor.datalen_max),
uint32_t(mdbx_limits_valsize_max(actor.pagesize, actor.table_flags)));
value_essentials.bits = (value_essentials.maxlen < sizeof(serial_t))
? value_essentials.maxlen * CHAR_BIT
: sizeof(serial_t) * CHAR_BIT;
value_essentials.maxlen =
std::min(uint32_t(actor.datalen_max), uint32_t(mdbx_limits_valsize_max(actor.pagesize, actor.table_flags)));
value_essentials.bits =
(value_essentials.maxlen < sizeof(serial_t)) ? value_essentials.maxlen * CHAR_BIT : sizeof(serial_t) * CHAR_BIT;
value_essentials.mask = actor_params::serial_mask(value_essentials.bits);
assert(value_essentials.bits > 63 ||
value_essentials.mask > primes[value_essentials.bits]);
assert(value_essentials.bits > 63 || value_essentials.mask > primes[value_essentials.bits]);
if (!actor.keygen.zero_fill) {
key_essentials.flags |= essentials::prng_fill_flag;
@@ -262,43 +225,31 @@ void maker::setup(const config::actor_params_pod &actor,
mapping = actor.keygen;
const auto split = mapping.split;
while (mapping.split >
value_essentials.bits - essentials::value_age_minwidth ||
mapping.split >= mapping.width)
while (mapping.split > value_essentials.bits - essentials::value_age_minwidth || mapping.split >= mapping.width)
mapping.split -= 1;
if (split != mapping.split)
log_notice("keygen: reduce mapping-split from %u to %u", split,
mapping.split);
log_notice("keygen: reduce mapping-split from %u to %u", split, mapping.split);
const auto width = mapping.width;
while (unsigned((actor.table_flags & MDBX_DUPSORT)
? mapping.width - mapping.split
: mapping.width) > key_essentials.bits)
while (unsigned((actor.table_flags & MDBX_DUPSORT) ? mapping.width - mapping.split : mapping.width) >
key_essentials.bits)
mapping.width -= 1;
if (width != mapping.width)
log_notice("keygen: reduce mapping-width from %u to %u", width,
mapping.width);
log_notice("keygen: reduce mapping-width from %u to %u", width, mapping.width);
value_age_bits = value_essentials.bits - mapping.split;
value_age_mask = actor_params::serial_mask(value_age_bits);
assert(value_age_bits >= essentials::value_age_minwidth);
salt = (prng_state ^
(thread_number * 1575554837) * UINT64_C(59386707711075671)) *
UINT64_C(14653293970879851569);
salt = (prng_state ^ (thread_number * 1575554837) * UINT64_C(59386707711075671)) * UINT64_C(14653293970879851569);
base = actor.serial_base();
}
bool maker::is_unordered() const {
return mapping.rotate ||
mapping.mesh > ((MDBX_db_flags_t(key_essentials.flags) & MDBX_DUPSORT)
? 0
: mapping.split);
return mapping.rotate || mapping.mesh > ((MDBX_db_flags_t(key_essentials.flags) & MDBX_DUPSORT) ? 0 : mapping.split);
}
void maker::seek2end(serial_t &serial) const {
serial = actor_params::serial_mask(mapping.width) - 1;
}
void maker::seek2end(serial_t &serial) const { serial = actor_params::serial_mask(mapping.width) - 1; }
bool maker::increment(serial_t &serial, int64_t delta) const {
if (serial > actor_params::serial_mask(mapping.width)) {
@@ -308,17 +259,12 @@ bool maker::increment(serial_t &serial, int64_t delta) const {
}
serial_t target = serial + delta;
if (target > actor_params::serial_mask(mapping.width) ||
((delta > 0) ? target < serial : target > serial)) {
log_extra("keygen-increment: %" PRIu64 "%-" PRId64 " => %" PRIu64
", overflow",
serial, delta, target);
if (target > actor_params::serial_mask(mapping.width) || ((delta > 0) ? target < serial : target > serial)) {
log_extra("keygen-increment: %" PRIu64 "%-" PRId64 " => %" PRIu64 ", overflow", serial, delta, target);
return false;
}
log_extra("keygen-increment: %" PRIu64 "%-" PRId64 " => %" PRIu64
", continue",
serial, delta, target);
log_extra("keygen-increment: %" PRIu64 "%-" PRId64 " => %" PRIu64 ", continue", serial, delta, target);
serial = target;
return true;
}
@@ -363,8 +309,7 @@ buffer alloc(size_t limit) {
return buffer(ptr);
}
serial_t __hot maker::mk_begin(serial_t serial, const essentials &params,
result &out) {
serial_t __hot maker::mk_begin(serial_t serial, const essentials &params, result &out) {
assert(out.limit >= params.maxlen);
assert(params.maxlen >= params.minlen);
assert(serial <= params.mask);
@@ -374,9 +319,8 @@ serial_t __hot maker::mk_begin(serial_t serial, const essentials &params,
assert(params.mask > primes[params.bits]);
#else
const serial_t maxbits = params.maxlen * CHAR_BIT;
serial ^= (serial >> maxbits / 2) *
serial_t((sizeof(serial_t) > 4) ? UINT64_C(40719303417517073)
: UINT32_C(3708688457));
serial ^=
(serial >> maxbits / 2) * serial_t((sizeof(serial_t) > 4) ? UINT64_C(40719303417517073) : UINT32_C(3708688457));
serial &= params.mask;
#endif
assert(params.maxlen >= length(serial));
@@ -388,9 +332,7 @@ serial_t __hot maker::mk_begin(serial_t serial, const essentials &params,
if (serial % (variation + serial_t(1))) {
auto refix = serial * UINT64_C(48835288005252737);
refix ^= refix >> 32;
out.value.iov_len =
std::max(out.value.iov_len,
params.minlen + size_t(1) + size_t(refix) % variation);
out.value.iov_len = std::max(out.value.iov_len, params.minlen + size_t(1) + size_t(refix) % variation);
}
}
@@ -400,18 +342,14 @@ serial_t __hot maker::mk_begin(serial_t serial, const essentials &params,
return serial;
}
void __hot maker::mk_continue(const serial_t serial, const essentials &params,
result &out) {
void __hot maker::mk_continue(const serial_t serial, const essentials &params, result &out) {
#if CONSTEXPR_ENUM_FLAGS_OPERATIONS
static_assert(
(essentials::prng_fill_flag &
unsigned(MDBX_DUPSORT | MDBX_DUPFIXED | MDBX_INTEGERKEY |
MDBX_INTEGERDUP | MDBX_REVERSEKEY | MDBX_REVERSEDUP)) == 0,
"WTF?");
static_assert((essentials::prng_fill_flag & unsigned(MDBX_DUPSORT | MDBX_DUPFIXED | MDBX_INTEGERKEY |
MDBX_INTEGERDUP | MDBX_REVERSEKEY | MDBX_REVERSEDUP)) == 0,
"WTF?");
#else
assert((essentials::prng_fill_flag &
unsigned(MDBX_DUPSORT | MDBX_DUPFIXED | MDBX_INTEGERKEY |
MDBX_INTEGERDUP | MDBX_REVERSEKEY | MDBX_REVERSEDUP)) == 0);
assert((essentials::prng_fill_flag & unsigned(MDBX_DUPSORT | MDBX_DUPFIXED | MDBX_INTEGERKEY | MDBX_INTEGERDUP |
MDBX_REVERSEKEY | MDBX_REVERSEDUP)) == 0);
#endif
assert(length(serial) <= out.value.iov_len);
out.value.iov_base = out.bytes;
@@ -423,8 +361,7 @@ void __hot maker::mk_continue(const serial_t serial, const essentials &params,
if (!is_byteorder_le() && out.value.iov_len != 8)
out.u32 = uint32_t(serial);
} else {
const auto prefix =
std::max(std::min(unsigned(params.minlen), 8u), length(serial));
const auto prefix = std::max(std::min(unsigned(params.minlen), 8u), length(serial));
out.u64 = htobe64(serial);
out.value.iov_base = out.bytes + 8 - prefix;
if (out.value.iov_len > prefix) {
@@ -434,28 +371,22 @@ void __hot maker::mk_continue(const serial_t serial, const essentials &params,
} else
memset(out.bytes + 8, '\0', out.value.iov_len - prefix);
}
if (unlikely(MDBX_db_flags_t(params.flags) &
(MDBX_REVERSEKEY | MDBX_REVERSEDUP)))
std::reverse((char *)out.value.iov_base,
(char *)out.value.iov_base + out.value.iov_len);
if (unlikely(MDBX_db_flags_t(params.flags) & (MDBX_REVERSEKEY | MDBX_REVERSEDUP)))
std::reverse((char *)out.value.iov_base, (char *)out.value.iov_base + out.value.iov_len);
}
assert(out.value.iov_len >= params.minlen);
assert(out.value.iov_len <= params.maxlen);
assert(out.value.iov_len >= length(serial));
assert(out.value.iov_base >= out.bytes);
assert((char *)out.value.iov_base + out.value.iov_len <=
(char *)&out.bytes + out.limit);
assert((char *)out.value.iov_base + out.value.iov_len <= (char *)&out.bytes + out.limit);
}
void log_pair(logging::loglevel level, const char *prefix, const buffer &key,
buffer &value) {
void log_pair(logging::loglevel level, const char *prefix, const buffer &key, buffer &value) {
if (log_enabled(level)) {
char dump_key[4096], dump_value[4096];
logging::output(
level, "%s-pair: key %s, value %s", prefix,
mdbx_dump_val(&key->value, dump_key, sizeof(dump_key)),
mdbx_dump_val(&value->value, dump_value, sizeof(dump_value)));
logging::output(level, "%s-pair: key %s, value %s", prefix, mdbx_dump_val(&key->value, dump_key, sizeof(dump_key)),
mdbx_dump_val(&value->value, dump_value, sizeof(dump_value)));
}
}

View File

@@ -60,11 +60,7 @@ namespace keygen {
typedef uint64_t serial_t;
enum : serial_t {
serial_minwith = 8,
serial_maxwith = sizeof(serial_t) * 8,
serial_allones = ~(serial_t)0u
};
enum : serial_t { serial_minwith = 8, serial_maxwith = sizeof(serial_t) * 8, serial_allones = ~(serial_t)0u };
struct result {
MDBX_val value;
@@ -75,9 +71,7 @@ struct result {
uint64_t u64;
};
std::string as_string() const {
return std::string((const char *)value.iov_base, value.iov_len);
}
std::string as_string() const { return std::string((const char *)value.iov_base, value.iov_len); }
};
//-----------------------------------------------------------------------------
@@ -106,21 +100,17 @@ class maker {
unsigned value_age_bits{0};
serial_t value_age_mask{0};
static serial_t mk_begin(serial_t serial, const essentials &params,
result &out);
static void mk_continue(const serial_t serial, const essentials &params,
result &out);
static serial_t mk_begin(serial_t serial, const essentials &params, result &out);
static void mk_continue(const serial_t serial, const essentials &params, result &out);
public:
void pair(serial_t serial, const buffer &key, buffer &value,
serial_t value_age, const bool keylen_changeable);
void pair(serial_t serial, const buffer &key, buffer &value, serial_t value_age, const bool keylen_changeable);
void setup(const config::actor_params_pod &actor, unsigned thread_number);
bool is_unordered() const;
void seek2end(serial_t &serial) const;
bool increment(serial_t &serial, int64_t delta) const;
bool increment_key_part(serial_t &serial, int64_t delta,
bool reset_value_part = true) const {
bool increment_key_part(serial_t &serial, int64_t delta, bool reset_value_part = true) const {
if (reset_value_part) {
serial_t value_part_bits = ((serial_t(1) << mapping.split) - 1);
serial |= value_part_bits;
@@ -131,12 +121,10 @@ public:
}
serial_t remix_age(serial_t serial) const {
return (UINT64_C(768097847591) * (serial ^ UINT64_C(768097847591))) &
value_age_mask;
return (UINT64_C(768097847591) * (serial ^ UINT64_C(768097847591))) & value_age_mask;
}
};
void log_pair(logging::loglevel level, const char *prefix, const buffer &key,
buffer &value);
void log_pair(logging::loglevel level, const char *prefix, const buffer &key, buffer &value);
} /* namespace keygen */

View File

@@ -26,15 +26,13 @@ MDBX_NORETURN void failure_perror(const char *what, int errnum) {
//-----------------------------------------------------------------------------
static void mdbx_logger(MDBX_log_level_t priority, const char *function,
int line, const char *fmt,
static void mdbx_logger(MDBX_log_level_t priority, const char *function, int line, const char *fmt,
va_list args) MDBX_CXX17_NOEXCEPT {
if (function) {
if (priority == MDBX_LOG_FATAL)
log_error("mdbx: fatal failure: %s, %d", function, line);
logging::output_nocheckloglevel(
logging::loglevel(priority),
strncmp(function, "mdbx_", 5) == 0 ? "%s: " : "mdbx %s: ", function);
logging::output_nocheckloglevel(logging::loglevel(priority),
strncmp(function, "mdbx_", 5) == 0 ? "%s: " : "mdbx %s: ", function);
logging::feed_ap(fmt, args);
} else
logging::feed_ap(fmt, args);
@@ -58,9 +56,7 @@ static FILE *flow;
void setlevel(loglevel priority) {
level = priority;
int rc = mdbx_setup_debug(MDBX_log_level_t(priority),
MDBX_DBG_ASSERT | MDBX_DBG_AUDIT | MDBX_DBG_JITTER |
MDBX_DBG_DUMP,
mdbx_logger);
MDBX_DBG_ASSERT | MDBX_DBG_AUDIT | MDBX_DBG_JITTER | MDBX_DBG_DUMP, mdbx_logger);
log_trace("set mdbx debug-opts: 0x%02x", rc);
}
@@ -117,8 +113,7 @@ void ln() {
}
}
void output_nocheckloglevel_ap(const logging::loglevel priority,
const char *format, va_list ap) {
void output_nocheckloglevel_ap(const logging::loglevel priority, const char *format, va_list ap) {
ln();
chrono::time now = chrono::now_realtime();
struct tm tm;
@@ -134,11 +129,9 @@ void output_nocheckloglevel_ap(const logging::loglevel priority,
if (rc != MDBX_SUCCESS)
failure_perror("localtime_r()", rc);
fprintf(stdout,
"[ %02d%02d%02d-%02d:%02d:%02d.%06d_%05lu %-10s %.4s ] %s" /* TODO */,
tm.tm_year - 100, tm.tm_mon + 1, tm.tm_mday, tm.tm_hour, tm.tm_min,
tm.tm_sec, chrono::fractional2us(now.fractional), (long)osal_getpid(),
prefix_buf, level2str(priority), suffix_ptr);
fprintf(stdout, "[ %02d%02d%02d-%02d:%02d:%02d.%06d_%05lu %-10s %.4s ] %s" /* TODO */, tm.tm_year - 100,
tm.tm_mon + 1, tm.tm_mday, tm.tm_hour, tm.tm_min, tm.tm_sec, chrono::fractional2us(now.fractional),
(long)osal_getpid(), prefix_buf, level2str(priority), suffix_ptr);
va_list ones;
memset(&ones, 0, sizeof(ones)) /* zap MSVC and other goofy compilers */;
@@ -171,8 +164,7 @@ void output_nocheckloglevel_ap(const logging::loglevel priority,
if (same_or_higher(priority, error)) {
if (flow)
flow = stderr;
fprintf(stderr, "[ %05lu %-10s %.4s ] %s", (long)osal_getpid(), prefix_buf,
level2str(priority), suffix_ptr);
fprintf(stderr, "[ %05lu %-10s %.4s ] %s", (long)osal_getpid(), prefix_buf, level2str(priority), suffix_ptr);
vfprintf(stderr, format, ones);
va_end(ones);
}
@@ -206,14 +198,12 @@ bool feed(const char *format, ...) {
return true;
}
local_suffix::local_suffix(const char *c_str)
: trim_pos(suffix_buf.size()), indent(0) {
local_suffix::local_suffix(const char *c_str) : trim_pos(suffix_buf.size()), indent(0) {
suffix_buf.append(c_str);
suffix_ptr = suffix_buf.c_str();
}
local_suffix::local_suffix(const std::string &str)
: trim_pos(suffix_buf.size()), indent(0) {
local_suffix::local_suffix(const std::string &str) : trim_pos(suffix_buf.size()), indent(0) {
suffix_buf.append(str);
suffix_ptr = suffix_buf.c_str();
}
@@ -242,8 +232,7 @@ void progress_canary(bool active) {
static chrono::time progress_timestamp;
chrono::time now = chrono::now_monotonic();
if (now.fixedpoint - progress_timestamp.fixedpoint <
chrono::from_ms(42).fixedpoint)
if (now.fixedpoint - progress_timestamp.fixedpoint < chrono::from_ms(42).fixedpoint)
return;
if (osal_progress_push(active)) {
@@ -262,20 +251,17 @@ void progress_canary(bool active) {
progress_timestamp = now;
fprintf(stderr, "%c\b", "-\\|/"[last_point = point]);
}
} else if (now.fixedpoint - progress_timestamp.fixedpoint >
chrono::from_seconds(2).fixedpoint) {
} else if (now.fixedpoint - progress_timestamp.fixedpoint > chrono::from_seconds(2).fixedpoint) {
progress_timestamp = now;
fprintf(stderr, "%c\b", "@*"[now.utc & 1]);
}
} else {
static int count;
if (active && now.fixedpoint - progress_timestamp.fixedpoint >
chrono::from_seconds(1).fixedpoint) {
if (active && now.fixedpoint - progress_timestamp.fixedpoint > chrono::from_seconds(1).fixedpoint) {
putc('.', stderr);
progress_timestamp = now;
++count;
} else if (now.fixedpoint - progress_timestamp.fixedpoint >
chrono::from_seconds(5).fixedpoint) {
} else if (now.fixedpoint - progress_timestamp.fixedpoint > chrono::from_seconds(5).fixedpoint) {
putc("@*"[now.utc & 1], stderr);
progress_timestamp = now;
++count;
@@ -364,9 +350,7 @@ void log_trouble(const char *where, const char *what, int errnum) {
log_error("%s: %s %s", where, what, test_strerror(errnum));
}
bool log_enabled(const logging::loglevel priority) {
return logging::same_or_higher(priority, logging::level);
}
bool log_enabled(const logging::loglevel priority) { return logging::same_or_higher(priority, logging::level); }
void log_flush(void) {
logging::ln();

View File

@@ -29,25 +29,20 @@ inline bool lower(loglevel left, loglevel right) {
return left > right;
}
inline bool same_or_higher(loglevel left, loglevel right) {
return left <= right;
}
inline bool same_or_higher(loglevel left, loglevel right) { return left <= right; }
const char *level2str(const loglevel level);
void setup(loglevel priority, const std::string &prefix);
void setup(const std::string &prefix);
void setlevel(loglevel priority);
void output_nocheckloglevel_ap(const loglevel priority, const char *format,
va_list ap);
bool MDBX_PRINTF_ARGS(2, 3)
output(const loglevel priority, const char *format, ...);
void output_nocheckloglevel_ap(const loglevel priority, const char *format, va_list ap);
bool MDBX_PRINTF_ARGS(2, 3) output(const loglevel priority, const char *format, ...);
bool feed_ap(const char *format, va_list ap);
bool MDBX_PRINTF_ARGS(1, 2) feed(const char *format, ...);
void ln();
void inline MDBX_PRINTF_ARGS(2, 3)
output_nocheckloglevel(const loglevel priority, const char *format, ...) {
void inline MDBX_PRINTF_ARGS(2, 3) output_nocheckloglevel(const loglevel priority, const char *format, ...) {
va_list ap;
va_start(ap, format);
output_nocheckloglevel_ap(priority, format, ap);
@@ -75,9 +70,7 @@ public:
} // namespace logging
void MDBX_PRINTF_ARGS(1, 2) static inline log_null(const char *msg, ...) {
return (void)msg;
}
void MDBX_PRINTF_ARGS(1, 2) static inline log_null(const char *msg, ...) { return (void)msg; }
void MDBX_PRINTF_ARGS(1, 2) log_extra(const char *msg, ...);
void MDBX_PRINTF_ARGS(1, 2) log_trace(const char *msg, ...);
void MDBX_PRINTF_ARGS(1, 2) log_debug(const char *msg, ...);

View File

@@ -9,104 +9,103 @@
#endif /* !Windows */
MDBX_NORETURN void usage(void) {
puts(
"usage:\n"
" --help or -h Show this text\n"
"Common parameters:\n"
" --loglevel=[0-7]|[fatal..extra]s"
" --pathname=... Path and/or name of database files\n"
" --repeat=N Set repeat counter\n"
" --threads=N Number of thread (unsupported for now)\n"
" --timeout=N[s|m|h|d] Set timeout in seconds/minutes/hours/days\n"
" --failfast[=YES/no] Lill all actors on first failure/error\n"
" --max-readers=N See mdbx_env_set_maxreaders() description\n"
" --max-tables=N Se mdbx_env_set_maxdbs() description\n"
" --dump-config[=YES/no] Dump entire test config before run\n"
" --progress[=YES/no] Enable/disable progress `canary`\n"
" --console[=yes/no] Enable/disable console-like output\n"
" --cleanup-before[=YES/no] Cleanup/remove and re-create database\n"
" --cleanup-after[=YES/no] Cleanup/remove database after completion\n"
" --prng-seed=N Seed PRNG\n"
"Database size control:\n"
" --pagesize=... Database page size: min, max, 256..65536\n"
" --size-lower=N[K|M|G|T] Lower-bound of size in Kb/Mb/Gb/Tb\n"
" --size-upper Upper-bound of size in Kb/Mb/Gb/Tb\n"
" --size Initial size in Kb/Mb/Gb/Tb\n"
" --shrink-threshold Shrink threshold in Kb/Mb/Gb/Tb\n"
" --growth-step Grow step in Kb/Mb/Gb/Tb\n"
"Predefined complex scenarios/cases:\n"
" --case=... Only `basic` scenario implemented for now\n"
" basic == Simultaneous multi-process execution\n"
" of test-actors: nested,hill,ttl,copy,append,jitter,try\n"
"Test actors:\n"
" --hill Fill-up and empty-down\n"
" by CRUD-operation quads\n"
" --ttl Stochastic time-to-live simulation\n"
" --nested Nested transactionы\n"
" with stochastic-size bellows\n"
" --jitter Jitter/delays simulation\n"
" --try Try write-transaction, no more\n"
" --copy Online copy/backup\n"
" --append Append-mode insertions\n"
" --dead.reader Dead-reader simulator\n"
" --dead.writer Dead-writer simulator\n"
puts("usage:\n"
" --help or -h Show this text\n"
"Common parameters:\n"
" --loglevel=[0-7]|[fatal..extra]s"
" --pathname=... Path and/or name of database files\n"
" --repeat=N Set repeat counter\n"
" --threads=N Number of thread (unsupported for now)\n"
" --timeout=N[s|m|h|d] Set timeout in seconds/minutes/hours/days\n"
" --failfast[=YES/no] Lill all actors on first failure/error\n"
" --max-readers=N See mdbx_env_set_maxreaders() description\n"
" --max-tables=N Se mdbx_env_set_maxdbs() description\n"
" --dump-config[=YES/no] Dump entire test config before run\n"
" --progress[=YES/no] Enable/disable progress `canary`\n"
" --console[=yes/no] Enable/disable console-like output\n"
" --cleanup-before[=YES/no] Cleanup/remove and re-create database\n"
" --cleanup-after[=YES/no] Cleanup/remove database after completion\n"
" --prng-seed=N Seed PRNG\n"
"Database size control:\n"
" --pagesize=... Database page size: min, max, 256..65536\n"
" --size-lower=N[K|M|G|T] Lower-bound of size in Kb/Mb/Gb/Tb\n"
" --size-upper Upper-bound of size in Kb/Mb/Gb/Tb\n"
" --size Initial size in Kb/Mb/Gb/Tb\n"
" --shrink-threshold Shrink threshold in Kb/Mb/Gb/Tb\n"
" --growth-step Grow step in Kb/Mb/Gb/Tb\n"
"Predefined complex scenarios/cases:\n"
" --case=... Only `basic` scenario implemented for now\n"
" basic == Simultaneous multi-process execution\n"
" of test-actors: nested,hill,ttl,copy,append,jitter,try\n"
"Test actors:\n"
" --hill Fill-up and empty-down\n"
" by CRUD-operation quads\n"
" --ttl Stochastic time-to-live simulation\n"
" --nested Nested transactionы\n"
" with stochastic-size bellows\n"
" --jitter Jitter/delays simulation\n"
" --try Try write-transaction, no more\n"
" --copy Online copy/backup\n"
" --append Append-mode insertions\n"
" --dead.reader Dead-reader simulator\n"
" --dead.writer Dead-writer simulator\n"
#if !defined(_WIN32) && !defined(_WIN64)
" --fork.reader After-fork reader\n"
" --fork.writer After-fork writer\n"
" --fork.reader After-fork reader\n"
" --fork.writer After-fork writer\n"
#endif /* Windows */
"Actor options:\n"
" --batch.read=N Read-operations batch size\n"
" --batch.write=N Write-operations batch size\n"
" --delay=N | --no-delay (no)Delay test-actor before start\n"
" --wait4ops=N | --no-wait4ops (no)Wait for previous test-actor\n"
" completes # ops before start\n"
" --duration=N[s|m|h|d] Define running duration\n"
" --nops=N[K|M|G|T] Define number of operations/steps\n"
" --inject-writefault[=yes|NO] TBD (see the source code)\n"
" --drop[=yes|NO] Drop key-value space/table on "
"completion\n"
" --ignore-dbfull[=yes|NO] Ignore MDBX_MAP_FULL error\n"
" --speculum[=yes|NO] Use internal `speculum` to check "
"dataset\n"
" --geometry-jitter[=YES|no] Use jitter for geometry upper-limit\n"
"Keys and Value:\n"
" --keylen.min=N Minimal keys length\n"
" --keylen.max=N Miximal keys length\n"
" --keylen=N Set both min/max for keys length\n"
" --datalen.min=N Minimal data length\n"
" --datalen.max=N Miximal data length\n"
" --datalen=N Set both min/max for data length\n"
" --keygen.width=N TBD (see the source code)\n"
" --keygen.mesh=N TBD (see the source code)\n"
" --keygen.zerofill=yes|NO TBD (see the source code)\n"
" --keygen.split=N TBD (see the source code)\n"
" --keygen.rotate=N TBD (see the source code)\n"
" --keygen.offset=N TBD (see the source code)\n"
" --keygen.case=random Generator case (only `random` for now)\n"
"Database operation mode:\n"
" --mode={[+-]FLAG}[,[+-]FLAG]...\n"
" nosubdir == MDBX_NOSUBDIR\n"
" rdonly == MDBX_RDONLY\n"
" exclusive == MDBX_EXCLUSIVE\n"
" accede == MDBX_ACCEDE\n"
" nometasync == MDBX_NOMETASYNC\n"
" lifo == MDBX_LIFORECLAIM\n"
" nosync-safe == MDBX_SAFE_NOSYNC\n"
" writemap == MDBX_WRITEMAP\n"
" nosync-utterly == MDBX_UTTERLY_NOSYNC\n"
" perturb == MDBX_PAGEPERTURB\n"
" nostickythreads== MDBX_NOSTICKYTHREADS\n"
" nordahead == MDBX_NORDAHEAD\n"
" nomeminit == MDBX_NOMEMINIT\n"
" --random-writemap[=YES|no] Toggle MDBX_WRITEMAP randomly\n"
"Key-value space/table options:\n"
" --table={[+-]FLAG}[,[+-]FLAG]...\n"
" key.reverse == MDBX_REVERSEKEY\n"
" key.integer == MDBX_INTEGERKEY\n"
" data.dups == MDBX_DUPSORT\n"
" data.integer == MDBX_INTEGERDUP | MDBX_DUPFIXED | MDBX_DUPSORT\n"
" data.fixed == MDBX_DUPFIXED | MDBX_DUPSORT\n"
" data.reverse == MDBX_REVERSEDUP | MDBX_DUPSORT\n");
"Actor options:\n"
" --batch.read=N Read-operations batch size\n"
" --batch.write=N Write-operations batch size\n"
" --delay=N | --no-delay (no)Delay test-actor before start\n"
" --wait4ops=N | --no-wait4ops (no)Wait for previous test-actor\n"
" completes # ops before start\n"
" --duration=N[s|m|h|d] Define running duration\n"
" --nops=N[K|M|G|T] Define number of operations/steps\n"
" --inject-writefault[=yes|NO] TBD (see the source code)\n"
" --drop[=yes|NO] Drop key-value space/table on "
"completion\n"
" --ignore-dbfull[=yes|NO] Ignore MDBX_MAP_FULL error\n"
" --speculum[=yes|NO] Use internal `speculum` to check "
"dataset\n"
" --geometry-jitter[=YES|no] Use jitter for geometry upper-limit\n"
"Keys and Value:\n"
" --keylen.min=N Minimal keys length\n"
" --keylen.max=N Miximal keys length\n"
" --keylen=N Set both min/max for keys length\n"
" --datalen.min=N Minimal data length\n"
" --datalen.max=N Miximal data length\n"
" --datalen=N Set both min/max for data length\n"
" --keygen.width=N TBD (see the source code)\n"
" --keygen.mesh=N TBD (see the source code)\n"
" --keygen.zerofill=yes|NO TBD (see the source code)\n"
" --keygen.split=N TBD (see the source code)\n"
" --keygen.rotate=N TBD (see the source code)\n"
" --keygen.offset=N TBD (see the source code)\n"
" --keygen.case=random Generator case (only `random` for now)\n"
"Database operation mode:\n"
" --mode={[+-]FLAG}[,[+-]FLAG]...\n"
" nosubdir == MDBX_NOSUBDIR\n"
" rdonly == MDBX_RDONLY\n"
" exclusive == MDBX_EXCLUSIVE\n"
" accede == MDBX_ACCEDE\n"
" nometasync == MDBX_NOMETASYNC\n"
" lifo == MDBX_LIFORECLAIM\n"
" nosync-safe == MDBX_SAFE_NOSYNC\n"
" writemap == MDBX_WRITEMAP\n"
" nosync-utterly == MDBX_UTTERLY_NOSYNC\n"
" perturb == MDBX_PAGEPERTURB\n"
" nostickythreads== MDBX_NOSTICKYTHREADS\n"
" nordahead == MDBX_NORDAHEAD\n"
" nomeminit == MDBX_NOMEMINIT\n"
" --random-writemap[=YES|no] Toggle MDBX_WRITEMAP randomly\n"
"Key-value space/table options:\n"
" --table={[+-]FLAG}[,[+-]FLAG]...\n"
" key.reverse == MDBX_REVERSEKEY\n"
" key.integer == MDBX_INTEGERKEY\n"
" data.dups == MDBX_DUPSORT\n"
" data.integer == MDBX_INTEGERDUP | MDBX_DUPFIXED | MDBX_DUPSORT\n"
" data.fixed == MDBX_DUPFIXED | MDBX_DUPSORT\n"
" data.reverse == MDBX_REVERSEDUP | MDBX_DUPSORT\n");
exit(EXIT_FAILURE);
}
@@ -209,9 +208,7 @@ bool geometry_jitter;
const char global::thunk_param_prefix[] = "--execute=";
std::string thunk_param(const actor_config &config) {
return config.serialize(global::thunk_param_prefix);
}
std::string thunk_param(const actor_config &config) { return config.serialize(global::thunk_param_prefix); }
void cleanup() {
log_trace(">> cleanup");
@@ -234,9 +231,7 @@ static void fixup4qemu(actor_params &params) {
safe4qemu_limit >>= 1;
#endif /* __SANITIZE_ADDRESS__ */
if (params.size_lower > safe4qemu_limit ||
params.size_now > safe4qemu_limit ||
params.size_upper > safe4qemu_limit) {
if (params.size_lower > safe4qemu_limit || params.size_now > safe4qemu_limit || params.size_upper > safe4qemu_limit) {
params.size_upper = std::min(params.size_upper, safe4qemu_limit);
params.size_now = std::min(params.size_now, params.size_upper);
params.size_lower = std::min(params.size_lower, params.size_now);
@@ -246,13 +241,12 @@ static void fixup4qemu(actor_params &params) {
}
#endif /* MDBX_WORDBITS == 32 */
#if defined(__alpha__) || defined(__alpha) || defined(__sparc__) || \
defined(__sparc) || defined(__sparc64__) || defined(__sparc64)
#if defined(__alpha__) || defined(__alpha) || defined(__sparc__) || defined(__sparc) || defined(__sparc64__) || \
defined(__sparc64)
if (params.size_lower != params.size_upper) {
log_notice(
"workaround: for conformance Alpha/Sparc build with QEMU/ASAN/Valgrind "
"enforce fixed database size %zu megabytes",
params.size_upper >> 20);
log_notice("workaround: for conformance Alpha/Sparc build with QEMU/ASAN/Valgrind "
"enforce fixed database size %zu megabytes",
params.size_upper >> 20);
params.size_lower = params.size_now = params.size_upper;
}
#endif /* Alpha || Sparc */
@@ -282,15 +276,10 @@ int main(int argc, char *const argv[]) {
if (argc < 2)
failure("No parameters given. Try --help\n");
if (argc == 2 && strncmp(argv[1], global::thunk_param_prefix,
strlen(global::thunk_param_prefix)) == 0)
return test_execute(
actor_config(argv[1] + strlen(global::thunk_param_prefix)))
? EXIT_SUCCESS
: EXIT_FAILURE;
if (argc == 2 && strncmp(argv[1], global::thunk_param_prefix, strlen(global::thunk_param_prefix)) == 0)
return test_execute(actor_config(argv[1] + strlen(global::thunk_param_prefix))) ? EXIT_SUCCESS : EXIT_FAILURE;
if (argc == 2 &&
(strcmp(argv[1], "--help") == 0 || strcmp(argv[1], "-h") == 0))
if (argc == 2 && (strcmp(argv[1], "--help") == 0 || strcmp(argv[1], "-h") == 0))
usage();
actor_params params;
@@ -300,30 +289,22 @@ int main(int argc, char *const argv[]) {
unsigned last_space_id = 0;
for (int narg = 1; narg < argc; ++narg) {
if (config::parse_option(argc, argv, narg, "dump-config",
global::config::dump_config))
if (config::parse_option(argc, argv, narg, "dump-config", global::config::dump_config))
continue;
if (config::parse_option(argc, argv, narg, "cleanup-before",
global::config::cleanup_before))
if (config::parse_option(argc, argv, narg, "cleanup-before", global::config::cleanup_before))
continue;
if (config::parse_option(argc, argv, narg, "cleanup-after",
global::config::cleanup_after))
if (config::parse_option(argc, argv, narg, "cleanup-after", global::config::cleanup_after))
continue;
if (config::parse_option(argc, argv, narg, "failfast",
global::config::failfast))
if (config::parse_option(argc, argv, narg, "failfast", global::config::failfast))
continue;
if (config::parse_option(argc, argv, narg, "progress",
global::config::progress_indicator))
if (config::parse_option(argc, argv, narg, "progress", global::config::progress_indicator))
continue;
if (config::parse_option(argc, argv, narg, "console",
global::config::console_mode))
if (config::parse_option(argc, argv, narg, "console", global::config::console_mode))
continue;
if (config::parse_option(argc, argv, narg, "geometry-jitter",
global::config::geometry_jitter))
if (config::parse_option(argc, argv, narg, "geometry-jitter", global::config::geometry_jitter))
continue;
if (config::parse_option(argc, argv, narg, "timeout",
global::config::timeout_duration_seconds,
config::duration, 1))
if (config::parse_option(argc, argv, narg, "timeout", global::config::timeout_duration_seconds, config::duration,
1))
continue;
logging::loglevel loglevel;
@@ -341,19 +322,15 @@ int main(int argc, char *const argv[]) {
}
if (config::parse_option(argc, argv, narg, "pathname", params.pathname_db))
continue;
if (config::parse_option(argc, argv, narg, "mode", params.mode_flags,
config::mode_bits))
if (config::parse_option(argc, argv, narg, "mode", params.mode_flags, config::mode_bits))
continue;
if (config::parse_option(argc, argv, narg, "random-writemap",
params.random_writemap))
if (config::parse_option(argc, argv, narg, "random-writemap", params.random_writemap))
continue;
if (config::parse_option(argc, argv, narg, "table", params.table_flags,
config::table_bits)) {
if (config::parse_option(argc, argv, narg, "table", params.table_flags, config::table_bits)) {
if ((params.table_flags & MDBX_DUPFIXED) == 0)
params.table_flags &= ~MDBX_INTEGERDUP;
if ((params.table_flags & MDBX_DUPSORT) == 0)
params.table_flags &=
~(MDBX_DUPFIXED | MDBX_REVERSEDUP | MDBX_INTEGERDUP);
params.table_flags &= ~(MDBX_DUPFIXED | MDBX_REVERSEDUP | MDBX_INTEGERDUP);
const unsigned keylen_max = params.mdbx_keylen_max();
if (params.keylen_min > keylen_max)
params.keylen_min = keylen_max;
@@ -378,8 +355,7 @@ int main(int argc, char *const argv[]) {
continue;
}
if (config::parse_option(argc, argv, narg, "pagesize", params.pagesize,
int(mdbx_limits_pgsize_min()),
if (config::parse_option(argc, argv, narg, "pagesize", params.pagesize, int(mdbx_limits_pgsize_min()),
int(mdbx_limits_pgsize_max()))) {
const unsigned keylen_max = params.mdbx_keylen_max();
if (params.keylen_min > keylen_max)
@@ -393,159 +369,116 @@ int main(int argc, char *const argv[]) {
params.datalen_max = datalen_max;
continue;
}
if (config::parse_option(argc, argv, narg, "repeat", params.nrepeat,
config::entropy))
if (config::parse_option(argc, argv, narg, "repeat", params.nrepeat, config::entropy))
continue;
if (config::parse_option(argc, argv, narg, "threads", params.nthreads,
config::no_scale, 1, 64))
if (config::parse_option(argc, argv, narg, "threads", params.nthreads, config::no_scale, 1, 64))
continue;
if (config::parse_option_intptr(argc, argv, narg, "size-lower",
params.size_lower,
mdbx_limits_dbsize_min(params.pagesize),
mdbx_limits_dbsize_max(params.pagesize)))
if (config::parse_option_intptr(argc, argv, narg, "size-lower", params.size_lower,
mdbx_limits_dbsize_min(params.pagesize), mdbx_limits_dbsize_max(params.pagesize)))
continue;
int64_t i64 = params.size_upper;
if (config::parse_option(argc, argv, narg, "size-upper-upto", i64,
int64_t(mdbx_limits_dbsize_min(params.pagesize)),
if (config::parse_option(argc, argv, narg, "size-upper-upto", i64, int64_t(mdbx_limits_dbsize_min(params.pagesize)),
INT64_MAX, -1)) {
if (i64 > mdbx_limits_dbsize_max(params.pagesize))
i64 = mdbx_limits_dbsize_max(params.pagesize);
params.size_upper = intptr_t(i64);
continue;
}
if (config::parse_option_intptr(argc, argv, narg, "size-upper",
params.size_upper,
mdbx_limits_dbsize_min(params.pagesize),
if (config::parse_option_intptr(argc, argv, narg, "size-upper", params.size_upper,
mdbx_limits_dbsize_min(params.pagesize), mdbx_limits_dbsize_max(params.pagesize)))
continue;
if (config::parse_option_intptr(argc, argv, narg, "size", params.size_now, mdbx_limits_dbsize_min(params.pagesize),
mdbx_limits_dbsize_max(params.pagesize)))
continue;
if (config::parse_option_intptr(argc, argv, narg, "size", params.size_now,
mdbx_limits_dbsize_min(params.pagesize),
mdbx_limits_dbsize_max(params.pagesize)))
if (config::parse_option(argc, argv, narg, "shrink-threshold", params.shrink_threshold, 0,
(int)std::min((intptr_t)INT_MAX, mdbx_limits_dbsize_max(params.pagesize) -
mdbx_limits_dbsize_min(params.pagesize))))
continue;
if (config::parse_option(
argc, argv, narg, "shrink-threshold", params.shrink_threshold, 0,
(int)std::min((intptr_t)INT_MAX,
mdbx_limits_dbsize_max(params.pagesize) -
mdbx_limits_dbsize_min(params.pagesize))))
continue;
if (config::parse_option(
argc, argv, narg, "growth-step", params.growth_step, 0,
(int)std::min((intptr_t)INT_MAX,
mdbx_limits_dbsize_max(params.pagesize) -
mdbx_limits_dbsize_min(params.pagesize))))
if (config::parse_option(argc, argv, narg, "growth-step", params.growth_step, 0,
(int)std::min((intptr_t)INT_MAX, mdbx_limits_dbsize_max(params.pagesize) -
mdbx_limits_dbsize_min(params.pagesize))))
continue;
if (config::parse_option(argc, argv, narg, "keygen.width",
params.keygen.width, 8, 64))
if (config::parse_option(argc, argv, narg, "keygen.width", params.keygen.width, 8, 64))
continue;
if (config::parse_option(argc, argv, narg, "keygen.mesh",
params.keygen.mesh, 0, 64))
if (config::parse_option(argc, argv, narg, "keygen.mesh", params.keygen.mesh, 0, 64))
continue;
if (config::parse_option(argc, argv, narg, "prng-seed", params.prng_seed,
config::entropy)) {
if (config::parse_option(argc, argv, narg, "prng-seed", params.prng_seed, config::entropy)) {
prng_seed(params.prng_seed);
continue;
}
if (config::parse_option(argc, argv, narg, "keygen.zerofill",
params.keygen.zero_fill))
if (config::parse_option(argc, argv, narg, "keygen.zerofill", params.keygen.zero_fill))
continue;
if (config::parse_option(argc, argv, narg, "keygen.split",
params.keygen.split, 0, 63))
if (config::parse_option(argc, argv, narg, "keygen.split", params.keygen.split, 0, 63))
continue;
if (config::parse_option(argc, argv, narg, "keygen.rotate",
params.keygen.rotate, 0, 63))
if (config::parse_option(argc, argv, narg, "keygen.rotate", params.keygen.rotate, 0, 63))
continue;
if (config::parse_option(argc, argv, narg, "keygen.offset",
params.keygen.offset, config::binary))
if (config::parse_option(argc, argv, narg, "keygen.offset", params.keygen.offset, config::binary))
continue;
if (config::parse_option(argc, argv, narg, "keygen.case", &value)) {
keycase_setup(value, params);
continue;
}
if (config::parse_option(
argc, argv, narg, "keylen.min", params.keylen_min,
(params.table_flags & MDBX_INTEGERKEY) ? config::intkey
: config::no_scale,
params.mdbx_keylen_min(), params.mdbx_keylen_max())) {
if ((params.table_flags & MDBX_INTEGERKEY) ||
params.keylen_max < params.keylen_min)
if (config::parse_option(argc, argv, narg, "keylen.min", params.keylen_min,
(params.table_flags & MDBX_INTEGERKEY) ? config::intkey : config::no_scale,
params.mdbx_keylen_min(), params.mdbx_keylen_max())) {
if ((params.table_flags & MDBX_INTEGERKEY) || params.keylen_max < params.keylen_min)
params.keylen_max = params.keylen_min;
continue;
}
if (config::parse_option(
argc, argv, narg, "keylen.max", params.keylen_max,
(params.table_flags & MDBX_INTEGERKEY) ? config::intkey
: config::no_scale,
params.mdbx_keylen_min(), params.mdbx_keylen_max())) {
if ((params.table_flags & MDBX_INTEGERKEY) ||
params.keylen_min > params.keylen_max)
if (config::parse_option(argc, argv, narg, "keylen.max", params.keylen_max,
(params.table_flags & MDBX_INTEGERKEY) ? config::intkey : config::no_scale,
params.mdbx_keylen_min(), params.mdbx_keylen_max())) {
if ((params.table_flags & MDBX_INTEGERKEY) || params.keylen_min > params.keylen_max)
params.keylen_min = params.keylen_max;
continue;
}
if (config::parse_option(
argc, argv, narg, "keylen", params.keylen_min,
(params.table_flags & MDBX_INTEGERKEY) ? config::intkey
: config::no_scale,
params.mdbx_keylen_min(), params.mdbx_keylen_max())) {
if (config::parse_option(argc, argv, narg, "keylen", params.keylen_min,
(params.table_flags & MDBX_INTEGERKEY) ? config::intkey : config::no_scale,
params.mdbx_keylen_min(), params.mdbx_keylen_max())) {
params.keylen_max = params.keylen_min;
continue;
}
if (config::parse_option(
argc, argv, narg, "datalen.min", params.datalen_min,
(params.table_flags & MDBX_INTEGERDUP) ? config::intkey
: config::no_scale,
params.mdbx_datalen_min(), params.mdbx_datalen_max())) {
if ((params.table_flags & (MDBX_INTEGERDUP | MDBX_DUPFIXED)) ||
params.datalen_max < params.datalen_min)
if (config::parse_option(argc, argv, narg, "datalen.min", params.datalen_min,
(params.table_flags & MDBX_INTEGERDUP) ? config::intkey : config::no_scale,
params.mdbx_datalen_min(), params.mdbx_datalen_max())) {
if ((params.table_flags & (MDBX_INTEGERDUP | MDBX_DUPFIXED)) || params.datalen_max < params.datalen_min)
params.datalen_max = params.datalen_min;
continue;
}
if (config::parse_option(
argc, argv, narg, "datalen.max", params.datalen_max,
(params.table_flags & MDBX_INTEGERDUP) ? config::intkey
: config::no_scale,
params.mdbx_datalen_min(), params.mdbx_datalen_max())) {
if ((params.table_flags & (MDBX_INTEGERDUP | MDBX_DUPFIXED)) ||
params.datalen_min > params.datalen_max)
if (config::parse_option(argc, argv, narg, "datalen.max", params.datalen_max,
(params.table_flags & MDBX_INTEGERDUP) ? config::intkey : config::no_scale,
params.mdbx_datalen_min(), params.mdbx_datalen_max())) {
if ((params.table_flags & (MDBX_INTEGERDUP | MDBX_DUPFIXED)) || params.datalen_min > params.datalen_max)
params.datalen_min = params.datalen_max;
continue;
}
if (config::parse_option(
argc, argv, narg, "datalen", params.datalen_min,
(params.table_flags & MDBX_INTEGERDUP) ? config::intkey
: config::no_scale,
params.mdbx_datalen_min(), params.mdbx_datalen_max())) {
if (config::parse_option(argc, argv, narg, "datalen", params.datalen_min,
(params.table_flags & MDBX_INTEGERDUP) ? config::intkey : config::no_scale,
params.mdbx_datalen_min(), params.mdbx_datalen_max())) {
params.datalen_max = params.datalen_min;
continue;
}
if (config::parse_option(argc, argv, narg, "batch.read", params.batch_read,
config::no_scale, 1))
if (config::parse_option(argc, argv, narg, "batch.read", params.batch_read, config::no_scale, 1))
continue;
if (config::parse_option(argc, argv, narg, "batch.write",
params.batch_write, config::no_scale, 1))
if (config::parse_option(argc, argv, narg, "batch.write", params.batch_write, config::no_scale, 1))
continue;
if (config::parse_option(argc, argv, narg, "delay", params.delaystart,
config::duration))
if (config::parse_option(argc, argv, narg, "delay", params.delaystart, config::duration))
continue;
if (config::parse_option(argc, argv, narg, "wait4ops", params.waitfor_nops,
config::decimal))
if (config::parse_option(argc, argv, narg, "wait4ops", params.waitfor_nops, config::decimal))
continue;
if (config::parse_option(argc, argv, narg, "inject-writefault",
params.inject_writefaultn, config::decimal))
if (config::parse_option(argc, argv, narg, "inject-writefault", params.inject_writefaultn, config::decimal))
continue;
if (config::parse_option(argc, argv, narg, "drop", params.drop_table))
continue;
if (config::parse_option(argc, argv, narg, "ignore-dbfull",
params.ignore_dbfull))
if (config::parse_option(argc, argv, narg, "ignore-dbfull", params.ignore_dbfull))
continue;
if (config::parse_option(argc, argv, narg, "speculum", params.speculum))
continue;
if (config::parse_option(argc, argv, narg, "max-readers",
params.max_readers, config::no_scale, 1, 255))
if (config::parse_option(argc, argv, narg, "max-readers", params.max_readers, config::no_scale, 1, 255))
continue;
if (config::parse_option(argc, argv, narg, "max-tables", params.max_tables,
config::no_scale, 1, INT16_MAX))
if (config::parse_option(argc, argv, narg, "max-tables", params.max_tables, config::no_scale, 1, INT16_MAX))
continue;
if (config::parse_option(argc, argv, narg, "no-delay", nullptr)) {
@@ -556,13 +489,11 @@ int main(int argc, char *const argv[]) {
params.waitfor_nops = 0;
continue;
}
if (config::parse_option(argc, argv, narg, "duration", params.test_duration,
config::duration, 1)) {
if (config::parse_option(argc, argv, narg, "duration", params.test_duration, config::duration, 1)) {
params.test_nops = 0;
continue;
}
if (config::parse_option(argc, argv, narg, "nops", params.test_nops,
config::decimal, 1)) {
if (config::parse_option(argc, argv, narg, "nops", params.test_nops, config::decimal, 1)) {
params.test_duration = 0;
continue;
}
@@ -647,8 +578,7 @@ int main(int argc, char *const argv[]) {
(global::config::timeout_duration_seconds == 0)
? chrono::infinite().fixedpoint
: global::start_monotonic.fixedpoint +
chrono::from_seconds(global::config::timeout_duration_seconds)
.fixedpoint;
chrono::from_seconds(global::config::timeout_duration_seconds).fixedpoint;
if (global::config::cleanup_before)
cleanup();
@@ -675,8 +605,7 @@ int main(int argc, char *const argv[]) {
log_trace(">> killall_actors: (%s)", "start failed");
osal_killall_actors();
log_trace("<< killall_actors");
failure("Failed to start actor #%u (%s)\n", a.actor_id,
test_strerror(rc));
failure("Failed to start actor #%u (%s)\n", a.actor_id, test_strerror(rc));
}
global::pid2actor[pid] = &a;
}
@@ -696,8 +625,7 @@ int main(int argc, char *const argv[]) {
timeout_seconds_left = 0;
else {
chrono::time left_monotonic;
left_monotonic.fixedpoint =
global::deadline_monotonic.fixedpoint - now_monotonic.fixedpoint;
left_monotonic.fixedpoint = global::deadline_monotonic.fixedpoint - now_monotonic.fixedpoint;
timeout_seconds_left = left_monotonic.seconds();
}
@@ -713,8 +641,8 @@ int main(int argc, char *const argv[]) {
continue;
if (status > as_running) {
log_notice("actor #%u, id %d, pid %ld: %s\n", actor->actor_id,
actor->space_id, (long)pid, status2str(status));
log_notice("actor #%u, id %d, pid %ld: %s\n", actor->actor_id, actor->space_id, (long)pid,
status2str(status));
left -= 1;
if (status != as_successful) {
if (global::config::failfast && !failed) {
@@ -725,8 +653,8 @@ int main(int argc, char *const argv[]) {
failed = true;
}
} else {
log_verbose("actor #%u, id %d, pid %ld: %s\n", actor->actor_id,
actor->space_id, (long)pid, status2str(status));
log_verbose("actor #%u, id %d, pid %ld: %s\n", actor->actor_id, actor->space_id, (long)pid,
status2str(status));
}
} else {
if (timeout_seconds_left == 0)
@@ -738,8 +666,7 @@ int main(int argc, char *const argv[]) {
if (!failed) {
MDBX_envinfo info;
int err =
mdbx_preopen_snapinfo(params.pathname_db.c_str(), &info, sizeof(info));
int err = mdbx_preopen_snapinfo(params.pathname_db.c_str(), &info, sizeof(info));
if (err != MDBX_SUCCESS)
failure_perror("mdbx_preopen_snapinfo()", err);
}
@@ -755,15 +682,12 @@ int main(int argc, char *const argv[]) {
#if !(defined(_WIN32) || defined(_WIN64))
struct rusage spent;
if (!getrusage(global::singlemode ? RUSAGE_SELF : RUSAGE_CHILDREN, &spent)) {
log_notice("%6s: user %f, system %f", "CPU",
spent.ru_utime.tv_sec + spent.ru_utime.tv_usec * 1e-6,
log_notice("%6s: user %f, system %f", "CPU", spent.ru_utime.tv_sec + spent.ru_utime.tv_usec * 1e-6,
spent.ru_stime.tv_sec + spent.ru_stime.tv_usec * 1e-6);
#if defined(__linux__) || defined(__gnu_linux__) || defined(__FreeBSD__) || \
defined(__NetBSD__) || defined(__OpenBSD__) || defined(__BSD__) || \
defined(__bsdi__) || defined(__DragonFly__) || defined(__APPLE__) || \
#if defined(__linux__) || defined(__gnu_linux__) || defined(__FreeBSD__) || defined(__NetBSD__) || \
defined(__OpenBSD__) || defined(__BSD__) || defined(__bsdi__) || defined(__DragonFly__) || defined(__APPLE__) || \
defined(__MACH__) || defined(__sun)
log_notice("%6s: read %ld, write %ld", "IOPs", spent.ru_inblock,
spent.ru_oublock);
log_notice("%6s: read %ld, write %ld", "IOPs", spent.ru_inblock, spent.ru_oublock);
if (spent.ru_maxrss > 0)
log_notice("%6s: %ld Kb", "RAM",
spent.ru_maxrss
@@ -773,8 +697,7 @@ int main(int argc, char *const argv[]) {
/ 1024u
#endif
);
log_notice("%6s: reclaims %ld, faults %ld, swaps %ld", "Paging",
spent.ru_minflt, spent.ru_majflt, spent.ru_nswap);
log_notice("%6s: reclaims %ld, faults %ld, swaps %ld", "Paging", spent.ru_minflt, spent.ru_majflt, spent.ru_nswap);
#endif /* Linux */
}
#endif /* !Windows */

View File

@@ -38,16 +38,12 @@ class testcase_nested : public testcase_ttl {
bool trim_tail(unsigned window_width);
bool grow_head(unsigned head_count);
bool pop_txn(bool abort);
bool pop_txn() {
return pop_txn(inherited::is_nested_txn_available() ? flipcoin_x3()
: flipcoin_x2());
}
bool pop_txn() { return pop_txn(inherited::is_nested_txn_available() ? flipcoin_x3() : flipcoin_x2()); }
void push_txn();
bool stochastic_breakable_restart_with_nested(bool force_restart = false);
public:
testcase_nested(const actor_config &config, const mdbx_pid_t pid)
: inherited(config, pid) {}
testcase_nested(const actor_config &config, const mdbx_pid_t pid) : inherited(config, pid) {}
bool setup() override;
bool run() override;
bool teardown() override;
@@ -84,8 +80,7 @@ bool testcase_nested::teardown() {
txn_begin(false);
db_table_drop(dbi);
int err = breakable_commit();
if (unlikely(err != MDBX_SUCCESS) &&
(err != MDBX_MAP_FULL || !config.params.ignore_dbfull)) {
if (unlikely(err != MDBX_SUCCESS) && (err != MDBX_MAP_FULL || !config.params.ignore_dbfull)) {
log_notice("nested: bailout-clean due '%s'", mdbx_strerror(err));
ok = false;
}
@@ -101,8 +96,7 @@ bool testcase_nested::teardown() {
void testcase_nested::push_txn() {
MDBX_txn *nested_txn;
MDBX_txn_flags_t flags = MDBX_txn_flags_t(
prng32() & uint32_t(MDBX_TXN_NOSYNC | MDBX_TXN_NOMETASYNC));
MDBX_txn_flags_t flags = MDBX_txn_flags_t(prng32() & uint32_t(MDBX_TXN_NOSYNC | MDBX_TXN_NOMETASYNC));
int err = mdbx_txn_begin(db_guard.get(), txn_guard.get(), flags, &nested_txn);
if (unlikely(err != MDBX_SUCCESS))
failure_perror("mdbx_txn_begin(nested)", err);
@@ -114,10 +108,9 @@ void testcase_nested::push_txn() {
scoped_txn_guard nested_txn_guard(nested_txn);
txn_guard.swap(nested_txn_guard);
SET speculum_snapshot(speculum);
stack.emplace(std::move(nested_txn_guard), serial, fifo,
std::move(speculum_snapshot));
log_verbose("begin level#%zu txn #%" PRIu64 ", flags 0x%x, serial %" PRIu64,
stack.size(), mdbx_txn_id(nested_txn), flags, serial);
stack.emplace(std::move(nested_txn_guard), serial, fifo, std::move(speculum_snapshot));
log_verbose("begin level#%zu txn #%" PRIu64 ", flags 0x%x, serial %" PRIu64, stack.size(), mdbx_txn_id(nested_txn),
flags, serial);
if (!dbi && stack.size() == 1)
dbi = db_table_open(true);
}
@@ -128,18 +121,16 @@ bool testcase_nested::pop_txn(bool abort) {
MDBX_txn *txn = txn_guard.release();
bool committed = false;
if (abort) {
log_verbose(
"abort level#%zu txn #%" PRIu64 ", undo serial %" PRIu64 " <- %" PRIu64,
stack.size(), mdbx_txn_id(txn), serial, std::get<1>(stack.top()));
if (dbi > 0 && stack.size() == 1 &&
is_handle_created_in_current_txn(dbi, txn))
log_verbose("abort level#%zu txn #%" PRIu64 ", undo serial %" PRIu64 " <- %" PRIu64, stack.size(), mdbx_txn_id(txn),
serial, std::get<1>(stack.top()));
if (dbi > 0 && stack.size() == 1 && is_handle_created_in_current_txn(dbi, txn))
dbi = 0;
int err = mdbx_txn_abort(txn);
if (unlikely(err != MDBX_SUCCESS))
failure_perror("mdbx_txn_abort()", err);
} else {
log_verbose("commit level#%zu txn, nested serial %" PRIu64 " -> %" PRIu64,
stack.size(), serial, std::get<1>(stack.top()));
log_verbose("commit level#%zu txn, nested serial %" PRIu64 " -> %" PRIu64, stack.size(), serial,
std::get<1>(stack.top()));
int err = mdbx_txn_commit(txn);
if (likely(err == MDBX_SUCCESS))
committed = true;
@@ -147,8 +138,7 @@ bool testcase_nested::pop_txn(bool abort) {
should_continue = false;
if (err == MDBX_MAP_FULL && config.params.ignore_dbfull) {
err = mdbx_txn_abort(txn);
if (unlikely(err != MDBX_SUCCESS && err != MDBX_THREAD_MISMATCH &&
err != MDBX_BAD_TXN))
if (unlikely(err != MDBX_SUCCESS && err != MDBX_THREAD_MISMATCH && err != MDBX_BAD_TXN))
failure_perror("mdbx_txn_abort()", err);
} else
failure_perror("mdbx_txn_commit()", err);
@@ -165,18 +155,15 @@ bool testcase_nested::pop_txn(bool abort) {
return should_continue;
}
bool testcase_nested::stochastic_breakable_restart_with_nested(
bool force_restart) {
log_trace(">> stochastic_breakable_restart_with_nested%s",
force_restart ? ": force_restart" : "");
bool testcase_nested::stochastic_breakable_restart_with_nested(bool force_restart) {
log_trace(">> stochastic_breakable_restart_with_nested%s", force_restart ? ": force_restart" : "");
if (force_restart)
while (txn_guard)
pop_txn(true);
bool should_continue = true;
while (!stack.empty() &&
(flipcoin() || txn_underutilization_x256(txn_guard.get()) < 42))
while (!stack.empty() && (flipcoin() || txn_underutilization_x256(txn_guard.get()) < 42))
should_continue &= pop_txn();
if (flipcoin_x3()) {
@@ -200,12 +187,10 @@ bool testcase_nested::stochastic_breakable_restart_with_nested(
}
if (should_continue)
while (stack.empty() ||
(is_nested_txn_available() && flipcoin() && stack.size() < 5))
while (stack.empty() || (is_nested_txn_available() && flipcoin() && stack.size() < 5))
push_txn();
log_trace("<< stochastic_breakable_restart_with_nested: should_continue=%s",
should_continue ? "yes" : "no");
log_trace("<< stochastic_breakable_restart_with_nested: should_continue=%s", should_continue ? "yes" : "no");
return should_continue;
}
@@ -215,8 +200,7 @@ bool testcase_nested::trim_tail(unsigned window_width) {
while (fifo.size() > window_width) {
uint64_t tail_serial = fifo.back().first;
const unsigned tail_count = fifo.back().second;
log_verbose("nested: trim-tail (serial %" PRIu64 ", count %u)",
tail_serial, tail_count);
log_verbose("nested: trim-tail (serial %" PRIu64 ", count %u)", tail_serial, tail_count);
fifo.pop_back();
for (unsigned n = 0; n < tail_count; ++n) {
log_trace("nested: remove-tail %" PRIu64, tail_serial);
@@ -235,9 +219,8 @@ bool testcase_nested::trim_tail(unsigned window_width) {
report(tail_count);
}
} else if (!fifo.empty()) {
log_verbose("nested: purge state %" PRIu64 " - %" PRIu64 ", fifo-items %zu",
fifo.front().first, fifo.back().first + fifo.back().second,
fifo.size());
log_verbose("nested: purge state %" PRIu64 " - %" PRIu64 ", fifo-items %zu", fifo.front().first,
fifo.back().first + fifo.back().second, fifo.size());
db_table_clear(dbi, txn_guard.get());
fifo.clear();
clear_wholetable_passed += 1;
@@ -248,9 +231,7 @@ bool testcase_nested::trim_tail(unsigned window_width) {
bool testcase_nested::grow_head(unsigned head_count) {
const MDBX_put_flags_t insert_flags =
(config.params.table_flags & MDBX_DUPSORT)
? MDBX_NODUPDATA
: MDBX_NODUPDATA | MDBX_NOOVERWRITE;
(config.params.table_flags & MDBX_DUPSORT) ? MDBX_NODUPDATA : MDBX_NODUPDATA | MDBX_NOOVERWRITE;
retry:
fifo.push_front(std::make_pair(serial, head_count));
for (unsigned n = 0; n < head_count; ++n) {
@@ -289,12 +270,10 @@ bool testcase_nested::run() {
unsigned loops = 0;
while (true) {
const uint64_t salt = prng64_white(seed) /* mdbx_txn_id(txn_guard.get()) */;
const unsigned window_width =
(!should_continue() || flipcoin_x4()) ? 0 : edge2window(salt);
const unsigned window_width = (!should_continue() || flipcoin_x4()) ? 0 : edge2window(salt);
const unsigned head_count = edge2count(salt);
log_debug("nested: step #%" PRIu64 " (serial %" PRIu64
", window %u, count %u) salt %" PRIu64,
nops_completed, serial, window_width, head_count, salt);
log_debug("nested: step #%" PRIu64 " (serial %" PRIu64 ", window %u, count %u) salt %" PRIu64, nops_completed,
serial, window_width, head_count, salt);
if (!trim_tail(window_width))
return false;
@@ -307,10 +286,8 @@ bool testcase_nested::run() {
return false;
}
if (!keyspace_overflow && (should_continue() || !clear_wholetable_passed ||
!clear_stepbystep_passed)) {
unsigned underutilization_x256 =
txn_underutilization_x256(txn_guard.get());
if (!keyspace_overflow && (should_continue() || !clear_wholetable_passed || !clear_stepbystep_passed)) {
unsigned underutilization_x256 = txn_underutilization_x256(txn_guard.get());
if (dbfull_passed > underutilization_x256) {
log_notice("nested: skip head-grow to avoid one more dbfull (was %u, "
"underutilization %.2f%%)",
@@ -327,9 +304,7 @@ bool testcase_nested::run() {
}
loops += 1;
} else if (fifo.empty()) {
log_notice("nested: done %u whole loops, %" PRIu64 " ops, %" PRIu64
" items",
loops, nops_completed, serial);
log_notice("nested: done %u whole loops, %" PRIu64 " ops, %" PRIu64 " items", loops, nops_completed, serial);
break;
} else {
log_notice("nested: done, wait for empty, skip head-grow");

View File

@@ -19,14 +19,12 @@
#error "Oops, MDBX_LOCKING is undefined!"
#endif
#if defined(__APPLE__) && (MDBX_LOCKING == MDBX_LOCKING_POSIX2001 || \
MDBX_LOCKING == MDBX_LOCKING_POSIX2008)
#if defined(__APPLE__) && (MDBX_LOCKING == MDBX_LOCKING_POSIX2001 || MDBX_LOCKING == MDBX_LOCKING_POSIX2008)
#include "stub/pthread_barrier.c"
#endif /* __APPLE__ && MDBX_LOCKING >= MDBX_LOCKING_POSIX2001 */
#if defined(__ANDROID_API__) && __ANDROID_API__ < 24 && \
(MDBX_LOCKING == MDBX_LOCKING_POSIX2001 || \
MDBX_LOCKING == MDBX_LOCKING_POSIX2008)
#if defined(__ANDROID_API__) && __ANDROID_API__ < 24 && \
(MDBX_LOCKING == MDBX_LOCKING_POSIX2001 || MDBX_LOCKING == MDBX_LOCKING_POSIX2008)
#include "stub/pthread_barrier.c"
#endif /* __ANDROID_API__ < 24 && MDBX_LOCKING >= MDBX_LOCKING_POSIX2001 */
@@ -40,9 +38,7 @@
#if __cplusplus >= 201103L
#include <atomic>
MDBX_MAYBE_UNUSED static inline int atomic_decrement(std::atomic_int *p) {
return std::atomic_fetch_sub(p, 1) - 1;
}
MDBX_MAYBE_UNUSED static inline int atomic_decrement(std::atomic_int *p) { return std::atomic_fetch_sub(p, 1) - 1; }
#else
MDBX_MAYBE_UNUSED static inline int atomic_decrement(volatile int *p) {
#if defined(__GNUC__) || defined(__clang__)
@@ -69,8 +65,7 @@ static void ipc_remove(void) {
#else
struct shared_t {
#if MDBX_LOCKING == MDBX_LOCKING_POSIX2001 || \
MDBX_LOCKING == MDBX_LOCKING_POSIX2008
#if MDBX_LOCKING == MDBX_LOCKING_POSIX2001 || MDBX_LOCKING == MDBX_LOCKING_POSIX2008
pthread_barrier_t barrier;
pthread_mutex_t mutex;
size_t count;
@@ -105,18 +100,14 @@ void osal_wait4barrier(void) {
op.sem_flg = 0;
if (semop(ipc, &op, 1))
failure_perror("semop(wait)", errno);
#elif MDBX_LOCKING == MDBX_LOCKING_POSIX2001 || \
MDBX_LOCKING == MDBX_LOCKING_POSIX2008
#elif MDBX_LOCKING == MDBX_LOCKING_POSIX2001 || MDBX_LOCKING == MDBX_LOCKING_POSIX2008
assert(shared != nullptr && shared != MAP_FAILED);
int err = pthread_barrier_wait(&shared->barrier);
if (err != 0 && err != PTHREAD_BARRIER_SERIAL_THREAD)
failure_perror("pthread_barrier_wait(shared)", err);
#elif MDBX_LOCKING == MDBX_LOCKING_POSIX1988
assert(shared != nullptr && shared != MAP_FAILED);
int err = (atomic_decrement(&shared->barrier.countdown) > 0 &&
sem_wait(&shared->barrier.sema))
? errno
: 0;
int err = (atomic_decrement(&shared->barrier.countdown) > 0 && sem_wait(&shared->barrier.sema)) ? errno : 0;
if (err != 0)
failure_perror("sem_wait(shared)", err);
if (sem_post(&shared->barrier.sema))
@@ -149,22 +140,20 @@ void osal_setup(const std::vector<actor_config> &actors) {
failure_perror("semctl(SETVAL.N, shared_sems)", errno);
#else
assert(shared == nullptr);
shared = (shared_t *)mmap(
nullptr, sizeof(shared_t) + actors.size() * sizeof(shared->events[0]),
PROT_READ | PROT_WRITE,
MAP_SHARED | MAP_ANONYMOUS
shared =
(shared_t *)mmap(nullptr, sizeof(shared_t) + actors.size() * sizeof(shared->events[0]), PROT_READ | PROT_WRITE,
MAP_SHARED | MAP_ANONYMOUS
#ifdef MAP_HASSEMAPHORE
| MAP_HASSEMAPHORE
| MAP_HASSEMAPHORE
#endif
,
-1, 0);
,
-1, 0);
if (MAP_FAILED == (void *)shared)
failure_perror("mmap(shared)", errno);
shared->count = actors.size() + 1;
#if MDBX_LOCKING == MDBX_LOCKING_POSIX2001 || \
MDBX_LOCKING == MDBX_LOCKING_POSIX2008
#if MDBX_LOCKING == MDBX_LOCKING_POSIX2001 || MDBX_LOCKING == MDBX_LOCKING_POSIX2008
pthread_barrierattr_t barrierattr;
int err = pthread_barrierattr_init(&barrierattr);
if (err)
@@ -173,8 +162,7 @@ void osal_setup(const std::vector<actor_config> &actors) {
if (err)
failure_perror("pthread_barrierattr_setpshared()", err);
err = pthread_barrier_init(&shared->barrier, &barrierattr,
unsigned(shared->count));
err = pthread_barrier_init(&shared->barrier, &barrierattr, unsigned(shared->count));
if (err)
failure_perror("pthread_barrier_init(shared)", err);
pthread_barrierattr_destroy(&barrierattr);
@@ -204,8 +192,7 @@ void osal_setup(const std::vector<actor_config> &actors) {
err = pthread_cond_init(event, &condattr);
if (err)
failure_perror("pthread_cond_init(shared)", err);
log_trace("osal_setup: event(shared pthread_cond) %" PRIuPTR " -> %p", i,
__Wpedantic_format_voidptr(event));
log_trace("osal_setup: event(shared pthread_cond) %" PRIuPTR " -> %p", i, __Wpedantic_format_voidptr(event));
}
pthread_condattr_destroy(&condattr);
pthread_mutexattr_destroy(&mutexattr);
@@ -217,8 +204,7 @@ void osal_setup(const std::vector<actor_config> &actors) {
sem_t *event = &shared->events[i];
if (sem_init(event, true, 0))
failure_perror("sem_init(shared.event)", errno);
log_trace("osal_setup: event(shared sem_init) %" PRIuPTR " -> %p", i,
__Wpedantic_format_voidptr(event));
log_trace("osal_setup: event(shared sem_init) %" PRIuPTR " -> %p", i, __Wpedantic_format_voidptr(event));
}
#else
#error "FIXME"
@@ -235,8 +221,7 @@ void osal_broadcast(unsigned id) {
assert(shared != nullptr && shared != MAP_FAILED);
if (id >= shared->count)
failure("osal_broadcast: id > limit");
#if MDBX_LOCKING == MDBX_LOCKING_POSIX2001 || \
MDBX_LOCKING == MDBX_LOCKING_POSIX2008
#if MDBX_LOCKING == MDBX_LOCKING_POSIX2001 || MDBX_LOCKING == MDBX_LOCKING_POSIX2008
int err = pthread_cond_broadcast(shared->events + id);
if (err)
failure_perror("pthread_cond_broadcast(shared)", err);
@@ -261,8 +246,7 @@ int osal_waitfor(unsigned id) {
if (id >= shared->count)
failure("osal_waitfor: id > limit");
#if MDBX_LOCKING == MDBX_LOCKING_POSIX2001 || \
MDBX_LOCKING == MDBX_LOCKING_POSIX2008
#if MDBX_LOCKING == MDBX_LOCKING_POSIX2001 || MDBX_LOCKING == MDBX_LOCKING_POSIX2008
int rc = pthread_mutex_lock(&shared->mutex);
if (rc != 0)
failure_perror("pthread_mutex_lock(shared)", rc);
@@ -288,15 +272,13 @@ int osal_waitfor(unsigned id) {
//-----------------------------------------------------------------------------
const std::string
actor_config::osal_serialize(simple_checksum &checksum) const {
const std::string actor_config::osal_serialize(simple_checksum &checksum) const {
(void)checksum;
/* not used in workload, but just for testing */
return "unix.fork";
}
bool actor_config::osal_deserialize(const char *str, const char *end,
simple_checksum &checksum) {
bool actor_config::osal_deserialize(const char *str, const char *end, simple_checksum &checksum) {
(void)checksum;
/* not used in workload, but just for testing */
return strncmp(str, "unix.fork", 9) == 0 && str + 9 == end;
@@ -392,8 +374,7 @@ int osal_actor_start(const actor_config &config, mdbx_pid_t &pid) {
if (pid < 0)
return errno;
log_trace("osal_actor_start: fork pid %ld for %u", (long)pid,
config.actor_id);
log_trace("osal_actor_start: fork pid %ld for %u", (long)pid, config.actor_id);
children[pid] = as_running;
return 0;
}
@@ -536,8 +517,7 @@ int osal_actor_poll(mdbx_pid_t &pid, unsigned timeout) {
if (pid > 0) {
if (WIFEXITED(status))
children[pid] =
(WEXITSTATUS(status) == EXIT_SUCCESS) ? as_successful : as_failed;
children[pid] = (WEXITSTATUS(status) == EXIT_SUCCESS) ? as_successful : as_failed;
else if (WIFSIGNALED(status)) {
int sig = WTERMSIG(status);
#ifdef WCOREDUMP
@@ -551,13 +531,11 @@ int osal_actor_poll(mdbx_pid_t &pid, unsigned timeout) {
case SIGFPE:
case SIGILL:
case SIGSEGV:
log_notice("child pid %lu %s by SIG%s", (long)pid, "terminated",
signal_name(sig));
log_notice("child pid %lu %s by SIG%s", (long)pid, "terminated", signal_name(sig));
children[pid] = as_coredump;
break;
default:
log_notice("child pid %lu %s by SIG%s", (long)pid, "killed",
signal_name(sig));
log_notice("child pid %lu %s by SIG%s", (long)pid, "killed", signal_name(sig));
children[pid] = as_killed;
}
} else if (WIFSTOPPED(status))
@@ -605,12 +583,10 @@ void osal_udelay(size_t us) {
static size_t threshold_us;
if (threshold_us == 0) {
#if defined(_POSIX_CPUTIME) && _POSIX_CPUTIME > -1 && \
defined(CLOCK_PROCESS_CPUTIME_ID)
#if defined(_POSIX_CPUTIME) && _POSIX_CPUTIME > -1 && defined(CLOCK_PROCESS_CPUTIME_ID)
if (clock_getres(CLOCK_PROCESS_CPUTIME_ID, &ts)) {
int rc = errno;
log_warning("clock_getres(CLOCK_PROCESS_CPUTIME_ID), failed errno %d",
rc);
log_warning("clock_getres(CLOCK_PROCESS_CPUTIME_ID), failed errno %d", rc);
}
#endif /* CLOCK_PROCESS_CPUTIME_ID */
if (threshold_us == 0 && clock_getres(CLOCK_MONOTONIC, &ts)) {

View File

@@ -30,13 +30,11 @@ void osal_wait4barrier(void) {
DWORD rc = WaitForSingleObject(hBarrierSemaphore, 0);
switch (rc) {
default:
failure_perror("WaitForSingleObject(BarrierSemaphore)",
waitstatus2errcode(rc));
failure_perror("WaitForSingleObject(BarrierSemaphore)", waitstatus2errcode(rc));
case WAIT_OBJECT_0:
rc = WaitForSingleObject(hBarrierEvent, INFINITE);
if (rc != WAIT_OBJECT_0)
failure_perror("WaitForSingleObject(BarrierEvent)",
waitstatus2errcode(rc));
failure_perror("WaitForSingleObject(BarrierEvent)", waitstatus2errcode(rc));
break;
case WAIT_TIMEOUT:
if (!SetEvent(hBarrierEvent))
@@ -47,8 +45,7 @@ void osal_wait4barrier(void) {
static HANDLE make_inheritable(HANDLE hHandle) {
assert(hHandle != NULL && hHandle != INVALID_HANDLE_VALUE);
if (!DuplicateHandle(GetCurrentProcess(), hHandle, GetCurrentProcess(),
&hHandle, 0, TRUE,
if (!DuplicateHandle(GetCurrentProcess(), hHandle, GetCurrentProcess(), &hHandle, 0, TRUE,
DUPLICATE_CLOSE_SOURCE | DUPLICATE_SAME_ACCESS))
failure_perror("DuplicateHandle()", GetLastError());
return hHandle;
@@ -108,8 +105,7 @@ int osal_delay(unsigned seconds) {
//-----------------------------------------------------------------------------
const std::string
actor_config::osal_serialize(simple_checksum &checksum) const {
const std::string actor_config::osal_serialize(simple_checksum &checksum) const {
checksum.push(hBarrierSemaphore);
checksum.push(hBarrierEvent);
checksum.push(hProgressActiveEvent);
@@ -127,12 +123,11 @@ actor_config::osal_serialize(simple_checksum &checksum) const {
checksum.push(hSignal);
}
return format("%p.%p.%p.%p.%p.%p", hBarrierSemaphore, hBarrierEvent, hWait,
hSignal, hProgressActiveEvent, hProgressPassiveEvent);
return format("%p.%p.%p.%p.%p.%p", hBarrierSemaphore, hBarrierEvent, hWait, hSignal, hProgressActiveEvent,
hProgressPassiveEvent);
}
bool actor_config::osal_deserialize(const char *str, const char *end,
simple_checksum &checksum) {
bool actor_config::osal_deserialize(const char *str, const char *end, simple_checksum &checksum) {
std::string copy(str, end - str);
TRACE(">> osal_deserialize(%s)\n", copy.c_str());
@@ -144,9 +139,8 @@ bool actor_config::osal_deserialize(const char *str, const char *end,
assert(events.empty());
HANDLE hWait, hSignal;
if (sscanf_s(copy.c_str(), "%p.%p.%p.%p.%p.%p", &hBarrierSemaphore,
&hBarrierEvent, &hWait, &hSignal, &hProgressActiveEvent,
&hProgressPassiveEvent) != 6) {
if (sscanf_s(copy.c_str(), "%p.%p.%p.%p.%p.%p", &hBarrierSemaphore, &hBarrierEvent, &hWait, &hSignal,
&hProgressActiveEvent, &hProgressPassiveEvent) != 6) {
TRACE("<< osal_deserialize: failed\n");
return false;
}
@@ -175,23 +169,19 @@ bool actor_config::osal_deserialize(const char *str, const char *end,
typedef std::pair<HANDLE, actor_status> child;
static std::unordered_map<mdbx_pid_t, child> children;
bool osal_multiactor_mode(void) {
return hProgressActiveEvent || hProgressPassiveEvent;
}
bool osal_multiactor_mode(void) { return hProgressActiveEvent || hProgressPassiveEvent; }
bool osal_progress_push(bool active) {
if (!children.empty()) {
if (!SetEvent(active ? hProgressActiveEvent : hProgressPassiveEvent))
failure_perror("osal_progress_push: SetEvent(overlord.progress)",
GetLastError());
failure_perror("osal_progress_push: SetEvent(overlord.progress)", GetLastError());
return true;
}
return false;
}
static void ArgvQuote(std::string &CommandLine, const std::string &Argument,
bool Force = false)
static void ArgvQuote(std::string &CommandLine, const std::string &Argument, bool Force = false)
/*++
@@ -232,8 +222,7 @@ Environment:
// parse quotes properly
//
if (Force == false && Argument.empty() == false &&
Argument.find_first_of(" \t\n\v\"") == Argument.npos) {
if (Force == false && Argument.empty() == false && Argument.find_first_of(" \t\n\v\"") == Argument.npos) {
CommandLine.append(Argument);
} else {
CommandLine.push_back('"');
@@ -276,8 +265,7 @@ Environment:
int osal_actor_start(const actor_config &config, mdbx_pid_t &pid) {
if (children.size() == MAXIMUM_WAIT_OBJECTS)
failure("Couldn't manage more that %u actors on Windows\n",
MAXIMUM_WAIT_OBJECTS);
failure("Couldn't manage more that %u actors on Windows\n", MAXIMUM_WAIT_OBJECTS);
_flushall();
@@ -286,8 +274,7 @@ int osal_actor_start(const actor_config &config, mdbx_pid_t &pid) {
char exename[_MAX_PATH + 1];
DWORD exename_size = sizeof(exename);
if (!QueryFullProcessImageNameA(GetCurrentProcess(), 0, exename,
&exename_size))
if (!QueryFullProcessImageNameA(GetCurrentProcess(), 0, exename, &exename_size))
failure_perror("QueryFullProcessImageName()", GetLastError());
if (exename[1] != ':') {
@@ -383,8 +370,7 @@ int osal_actor_poll(mdbx_pid_t &pid, unsigned timeout) {
while (true) {
DWORD rc =
MsgWaitForMultipleObjectsEx((DWORD)handles.size(), &handles[0],
(timeout > 60) ? 60 * 1000 : timeout * 1000,
MsgWaitForMultipleObjectsEx((DWORD)handles.size(), &handles[0], (timeout > 60) ? 60 * 1000 : timeout * 1000,
QS_ALLINPUT | QS_ALLPOSTMESSAGE, 0);
if (rc == WAIT_OBJECT_0) {

View File

@@ -42,8 +42,7 @@ int pthread_barrierattr_destroy(pthread_barrierattr_t *attr) {
return m ? m : c;
}
int pthread_barrierattr_getpshared(const pthread_barrierattr_t *__restrict attr,
int *__restrict pshared) {
int pthread_barrierattr_getpshared(const pthread_barrierattr_t *__restrict attr, int *__restrict pshared) {
return pthread_condattr_getpshared(&attr->cattr, pshared);
}
@@ -53,8 +52,7 @@ int pthread_barrierattr_setpshared(pthread_barrierattr_t *attr, int pshared) {
return m ? m : c;
}
int pthread_barrier_init(pthread_barrier_t *__restrict barrier,
const pthread_barrierattr_t *__restrict attr,
int pthread_barrier_init(pthread_barrier_t *__restrict barrier, const pthread_barrierattr_t *__restrict attr,
unsigned count) {
if (count == 0)
return errno = EINVAL;

View File

@@ -61,12 +61,10 @@ typedef struct {
int pthread_barrierattr_init(pthread_barrierattr_t *attr);
int pthread_barrierattr_destroy(pthread_barrierattr_t *attr);
int pthread_barrierattr_getpshared(const pthread_barrierattr_t *__restrict attr,
int *__restrict pshared);
int pthread_barrierattr_getpshared(const pthread_barrierattr_t *__restrict attr, int *__restrict pshared);
int pthread_barrierattr_setpshared(pthread_barrierattr_t *attr, int pshared);
int pthread_barrier_init(pthread_barrier_t *__restrict barrier,
const pthread_barrierattr_t *__restrict attr,
int pthread_barrier_init(pthread_barrier_t *__restrict barrier, const pthread_barrierattr_t *__restrict attr,
unsigned int count);
int pthread_barrier_destroy(pthread_barrier_t *barrier);

File diff suppressed because it is too large Load Diff

View File

@@ -31,10 +31,9 @@
bool test_execute(const actor_config &config);
std::string thunk_param(const actor_config &config);
void testcase_setup(const char *casename, const actor_params &params,
unsigned &last_space_id);
void configure_actor(unsigned &last_space_id, const actor_testcase testcase,
const char *space_id_cstr, actor_params params);
void testcase_setup(const char *casename, const actor_params &params, unsigned &last_space_id);
void configure_actor(unsigned &last_space_id, const actor_testcase testcase, const char *space_id_cstr,
actor_params params);
void keycase_setup(const char *casename, actor_params &params);
namespace global {
@@ -106,34 +105,26 @@ public:
this->id = id;
this->name = name;
review_params = TESTCASE::review_params;
constructor = [](const actor_config &config,
const mdbx_pid_t pid) -> testcase * {
constructor = [](const actor_config &config, const mdbx_pid_t pid) -> testcase * {
return new TESTCASE(config, pid);
};
add(this);
}
};
static bool review_actor_params(const actor_testcase id, actor_params &params,
const unsigned space_id);
static testcase *create_actor(const actor_config &config,
const mdbx_pid_t pid);
static bool review_actor_params(const actor_testcase id, actor_params &params, const unsigned space_id);
static testcase *create_actor(const actor_config &config, const mdbx_pid_t pid);
};
#define REGISTER_TESTCASE(NAME) \
static registry::factory<testcase_##NAME> gRegister_##NAME( \
ac_##NAME, MDBX_STRINGIFY(NAME))
#define REGISTER_TESTCASE(NAME) \
static registry::factory<testcase_##NAME> gRegister_##NAME(ac_##NAME, MDBX_STRINGIFY(NAME))
class testcase {
protected:
using data_view = mdbx::slice;
static inline data_view iov2dataview(const MDBX_val &v) {
return (v.iov_base && v.iov_len)
? data_view(static_cast<const char *>(v.iov_base), v.iov_len)
: data_view();
}
static inline data_view iov2dataview(const keygen::buffer &b) {
return iov2dataview(b->value);
return (v.iov_base && v.iov_len) ? data_view(static_cast<const char *>(v.iov_base), v.iov_len) : data_view();
}
static inline data_view iov2dataview(const keygen::buffer &b) { return iov2dataview(b->value); }
using Item = std::pair<::mdbx::buffer<>, ::mdbx::buffer<>>;
@@ -145,16 +136,13 @@ protected:
}
struct ItemCompare {
const testcase *context;
ItemCompare(const testcase *owner) : context(owner) {
/* The context->txn_guard may be empty/null here */
}
ItemCompare(const testcase *owner) : context(owner) { /* The context->txn_guard may be empty/null here */ }
bool operator()(const Item &a, const Item &b) const {
MDBX_val va = dataview2iov(a.first), vb = dataview2iov(b.first);
assert(context->txn_guard.get() != nullptr);
int cmp = mdbx_cmp(context->txn_guard.get(), context->dbi, &va, &vb);
if (cmp == 0 &&
(context->config.params.table_flags & MDBX_DUPSORT) != 0) {
if (cmp == 0 && (context->config.params.table_flags & MDBX_DUPSORT) != 0) {
va = dataview2iov(a.second);
vb = dataview2iov(b.second);
cmp = mdbx_dcmp(context->txn_guard.get(), context->dbi, &va, &vb);
@@ -194,61 +182,44 @@ protected:
#if SPECULUM_CURSORS
scoped_cursor_guard speculum_cursors[5 + 1];
void speculum_prepare_cursors(const Item &item);
bool speculum_check_cursor(const char *where, const char *stage,
const testcase::SET::const_iterator &it,
int cursor_err, const MDBX_val &cursor_key,
const MDBX_val &cursor_data,
bool speculum_check_cursor(const char *where, const char *stage, const testcase::SET::const_iterator &it,
int cursor_err, const MDBX_val &cursor_key, const MDBX_val &cursor_data,
MDBX_cursor *cursor) const;
bool speculum_check_cursor(const char *where, const char *stage,
const testcase::SET::const_iterator &it,
MDBX_cursor *cursor,
const MDBX_cursor_op op) const;
void speculum_render(const testcase::SET::const_iterator &it,
const MDBX_cursor *ref) const;
bool speculum_check_cursor(const char *where, const char *stage, const testcase::SET::const_iterator &it,
MDBX_cursor *cursor, const MDBX_cursor_op op) const;
void speculum_render(const testcase::SET::const_iterator &it, const MDBX_cursor *ref) const;
#endif /* SPECULUM_CURSORS */
bool speculum_check_iterator(const char *where, const char *stage,
const testcase::SET::const_iterator &it,
const MDBX_val &k, const MDBX_val &v,
MDBX_cursor *cursor) const;
bool speculum_check_iterator(const char *where, const char *stage, const testcase::SET::const_iterator &it,
const MDBX_val &k, const MDBX_val &v, MDBX_cursor *cursor) const;
void verbose(const char *where, const char *stage,
const testcase::SET::const_iterator &it) const;
void verbose(const char *where, const char *stage, const MDBX_val &k,
const MDBX_val &v, int err = MDBX_SUCCESS) const;
void verbose(const char *where, const char *stage, const testcase::SET::const_iterator &it) const;
void verbose(const char *where, const char *stage, const MDBX_val &k, const MDBX_val &v,
int err = MDBX_SUCCESS) const;
bool is_same(const Item &a, const Item &b) const;
bool is_same(const SET::const_iterator &it, const MDBX_val &k,
const MDBX_val &v) const;
bool is_same(const SET::const_iterator &it, const MDBX_val &k, const MDBX_val &v) const;
bool speculum_verify();
bool check_batch_get();
int insert(const keygen::buffer &akey, const keygen::buffer &adata,
MDBX_put_flags_t flags);
int replace(const keygen::buffer &akey, const keygen::buffer &new_value,
const keygen::buffer &old_value, MDBX_put_flags_t flags,
bool hush_keygen_mistakes = true);
int insert(const keygen::buffer &akey, const keygen::buffer &adata, MDBX_put_flags_t flags);
int replace(const keygen::buffer &akey, const keygen::buffer &new_value, const keygen::buffer &old_value,
MDBX_put_flags_t flags, bool hush_keygen_mistakes = true);
int remove(const keygen::buffer &akey, const keygen::buffer &adata);
static int hsr_callback(const MDBX_env *env, const MDBX_txn *txn,
mdbx_pid_t pid, mdbx_tid_t tid, uint64_t laggard,
unsigned gap, size_t space,
int retry) MDBX_CXX17_NOEXCEPT;
static int hsr_callback(const MDBX_env *env, const MDBX_txn *txn, mdbx_pid_t pid, mdbx_tid_t tid, uint64_t laggard,
unsigned gap, size_t space, int retry) MDBX_CXX17_NOEXCEPT;
MDBX_env_flags_t actual_env_mode{MDBX_ENV_DEFAULTS};
bool is_nested_txn_available() const {
return (actual_env_mode & MDBX_WRITEMAP) == 0;
}
bool is_nested_txn_available() const { return (actual_env_mode & MDBX_WRITEMAP) == 0; }
void kick_progress(bool active) const;
void db_prepare();
void db_open();
void db_close();
virtual void txn_begin(bool readonly,
MDBX_txn_flags_t flags = MDBX_TXN_READWRITE);
virtual void txn_begin(bool readonly, MDBX_txn_flags_t flags = MDBX_TXN_READWRITE);
int breakable_commit();
virtual void txn_end(bool abort);
int breakable_restart();
void txn_restart(bool abort, bool readonly,
MDBX_txn_flags_t flags = MDBX_TXN_READWRITE);
void txn_restart(bool abort, bool readonly, MDBX_txn_flags_t flags = MDBX_TXN_READWRITE);
void cursor_open(MDBX_dbi handle);
void cursor_close();
void cursor_renew();
@@ -258,13 +229,11 @@ protected:
void fetch_canary();
void update_canary(uint64_t increment);
bool checkdata(const char *step, MDBX_dbi handle, MDBX_val key2check,
MDBX_val expected_valued);
bool checkdata(const char *step, MDBX_dbi handle, MDBX_val key2check, MDBX_val expected_valued);
unsigned txn_underutilization_x256(MDBX_txn *txn) const;
using tablename_buf = char[32];
const char *db_tablename(tablename_buf &buffer,
const char *suffix = "") const;
const char *db_tablename(tablename_buf &buffer, const char *suffix = "") const;
MDBX_dbi db_table_open(bool create, bool expect_failure = false);
void db_table_drop(MDBX_dbi handle);
void db_table_clear(MDBX_dbi handle, MDBX_txn *txn = nullptr);
@@ -278,22 +247,17 @@ protected:
bool should_continue(bool check_timeout_only = false) const;
bool MDBX_PRINTF_ARGS(2, 3) failure(const char *fmt, ...) const;
void generate_pair(const keygen::serial_t serial, keygen::buffer &out_key,
keygen::buffer &out_value, keygen::serial_t data_age) {
void generate_pair(const keygen::serial_t serial, keygen::buffer &out_key, keygen::buffer &out_value,
keygen::serial_t data_age) {
keyvalue_maker.pair(serial, out_key, out_value, data_age, false);
}
void generate_pair(const keygen::serial_t serial) {
keyvalue_maker.pair(serial, key, data, 0, true);
}
void generate_pair(const keygen::serial_t serial) { keyvalue_maker.pair(serial, key, data, 0, true); }
bool mode_readonly() const {
return (config.params.mode_flags & MDBX_RDONLY) ? true : false;
}
bool mode_readonly() const { return (config.params.mode_flags & MDBX_RDONLY) ? true : false; }
public:
testcase(const actor_config &config, const mdbx_pid_t pid)
: config(config), pid(pid) {
testcase(const actor_config &config, const mdbx_pid_t pid) : config(config), pid(pid) {
start_timestamp.reset();
memset(&last, 0, sizeof(last));
}
@@ -301,11 +265,9 @@ public:
static bool review_params(actor_params &params, unsigned space_id) {
// silently fix key/data length for fixed-length modes
params.prng_seed += bleach32(space_id);
if ((params.table_flags & MDBX_INTEGERKEY) &&
params.keylen_min != params.keylen_max)
if ((params.table_flags & MDBX_INTEGERKEY) && params.keylen_min != params.keylen_max)
params.keylen_min = params.keylen_max;
if ((params.table_flags & (MDBX_INTEGERDUP | MDBX_DUPFIXED)) &&
params.datalen_min != params.datalen_max)
if ((params.table_flags & (MDBX_INTEGERDUP | MDBX_DUPFIXED)) && params.datalen_min != params.datalen_max)
params.datalen_min = params.datalen_max;
return true;
}
@@ -330,8 +292,7 @@ protected:
unsigned edge2count(uint64_t edge);
public:
testcase_ttl(const actor_config &config, const mdbx_pid_t pid)
: inherited(config, pid) {}
testcase_ttl(const actor_config &config, const mdbx_pid_t pid) : inherited(config, pid) {}
bool setup() override;
bool run() override;
};

View File

@@ -5,8 +5,7 @@
class testcase_try : public testcase {
public:
testcase_try(const actor_config &config, const mdbx_pid_t pid)
: testcase(config, pid) {}
testcase_try(const actor_config &config, const mdbx_pid_t pid) : testcase(config, pid) {}
bool run() override;
};
REGISTER_TESTCASE(try);

View File

@@ -24,17 +24,14 @@ REGISTER_TESTCASE(ttl);
unsigned testcase_ttl::edge2count(uint64_t edge) {
const double rnd = u64_to_double1(prng64_map1_white(edge));
const unsigned count =
unsigned(std::lrint(std::pow(sliding.max_step_size, rnd)));
const unsigned count = unsigned(std::lrint(std::pow(sliding.max_step_size, rnd)));
// average value: (X - 1) / ln(X), where X = sliding.max_step_size
return count;
}
unsigned testcase_ttl::edge2window(uint64_t edge) {
const double rnd = u64_to_double1(bleach64(edge));
const unsigned size =
sliding.max_window_size -
unsigned(std::lrint(std::pow(sliding.max_window_size, rnd)));
const unsigned size = sliding.max_window_size - unsigned(std::lrint(std::pow(sliding.max_window_size, rnd)));
// average value: Y - (Y - 1) / ln(Y), where Y = sliding.max_window_size
return size;
}
@@ -48,20 +45,17 @@ static inline double estimate(const double x, const double y) {
}
bool testcase_ttl::setup() {
const unsigned window_top_lower =
7 /* нижний предел для верхней границы диапазона, в котором будет
стохастически колебаться размер окна */
const unsigned window_top_lower = 7 /* нижний предел для верхней границы диапазона, в котором будет
стохастически колебаться размер окна */
;
const unsigned count_top_lower =
7 /* нижний предел для верхней границы диапазона, в котором будет
стохастически колебаться кол-во записей добавляемых на одном шаге */
const unsigned count_top_lower = 7 /* нижний предел для верхней границы диапазона, в котором будет
стохастически колебаться кол-во записей добавляемых на одном шаге */
;
/* для параметризации используем подходящие параметры,
* которые не имеют здесь смысла в первоначальном значении. */
const double ratio =
double(config.params.batch_read ? config.params.batch_read : 1) /
double(config.params.batch_write ? config.params.batch_write : 1);
const double ratio = double(config.params.batch_read ? config.params.batch_read : 1) /
double(config.params.batch_write ? config.params.batch_write : 1);
/* проще найти двоичным поиском (вариация метода Ньютона) */
double hi = config.params.test_nops, lo = 1;
@@ -82,8 +76,7 @@ bool testcase_ttl::setup() {
if (sliding.max_window_size < window_top_lower)
sliding.max_window_size = window_top_lower;
while (estimate(sliding.max_step_size, sliding.max_window_size) >
config.params.test_nops * 2.0) {
while (estimate(sliding.max_step_size, sliding.max_window_size) > config.params.test_nops * 2.0) {
if (ratio * sliding.max_step_size > sliding.max_window_size) {
if (sliding.max_step_size < count_top_lower)
break;
@@ -95,8 +88,7 @@ bool testcase_ttl::setup() {
}
}
log_verbose("come up window_max %u from `batch_read`",
sliding.max_window_size);
log_verbose("come up window_max %u from `batch_read`", sliding.max_window_size);
log_verbose("come up step_max %u from `batch_write`", sliding.max_step_size);
return inherited::setup();
}
@@ -113,9 +105,7 @@ bool testcase_ttl::run() {
key = keygen::alloc(config.params.keylen_max);
data = keygen::alloc(config.params.datalen_max);
const MDBX_put_flags_t insert_flags =
(config.params.table_flags & MDBX_DUPSORT)
? MDBX_NODUPDATA
: MDBX_NODUPDATA | MDBX_NOOVERWRITE;
(config.params.table_flags & MDBX_DUPSORT) ? MDBX_NODUPDATA : MDBX_NODUPDATA | MDBX_NOOVERWRITE;
std::deque<std::pair<uint64_t, unsigned>> fifo;
uint64_t serial = 0;
@@ -128,20 +118,17 @@ bool testcase_ttl::run() {
while (true) {
const uint64_t salt = prng64_white(seed) /* mdbx_txn_id(txn_guard.get()) */;
const unsigned window_width =
(!should_continue() || flipcoin_x4()) ? 0 : edge2window(salt);
const unsigned window_width = (!should_continue() || flipcoin_x4()) ? 0 : edge2window(salt);
unsigned head_count = edge2count(salt);
log_debug("ttl: step #%" PRIu64 " (serial %" PRIu64
", window %u, count %u) salt %" PRIu64,
nops_completed, serial, window_width, head_count, salt);
log_debug("ttl: step #%" PRIu64 " (serial %" PRIu64 ", window %u, count %u) salt %" PRIu64, nops_completed, serial,
window_width, head_count, salt);
if (window_width || flipcoin()) {
clear_stepbystep_passed += window_width == 0;
while (fifo.size() > window_width) {
uint64_t tail_serial = fifo.back().first;
const unsigned tail_count = fifo.back().second;
log_trace("ttl: pop-tail (serial %" PRIu64 ", count %u)", tail_serial,
tail_count);
log_trace("ttl: pop-tail (serial %" PRIu64 ", count %u)", tail_serial, tail_count);
fifo.pop_back();
for (unsigned n = 0; n < tail_count; ++n) {
log_trace("ttl: remove-tail %" PRIu64, tail_serial);
@@ -177,10 +164,8 @@ bool testcase_ttl::run() {
return false;
}
if (!keyspace_overflow && (should_continue() || !clear_wholetable_passed ||
!clear_stepbystep_passed)) {
unsigned underutilization_x256 =
txn_underutilization_x256(txn_guard.get());
if (!keyspace_overflow && (should_continue() || !clear_wholetable_passed || !clear_stepbystep_passed)) {
unsigned underutilization_x256 = txn_underutilization_x256(txn_guard.get());
if (dbfull_passed > underutilization_x256) {
log_notice("ttl: skip head-grow to avoid one more dbfull (was %u, "
"underutilization %.2f%%)",
@@ -194,8 +179,7 @@ bool testcase_ttl::run() {
generate_pair(serial);
err = insert(key, data, insert_flags);
if (unlikely(err != MDBX_SUCCESS)) {
if ((err == MDBX_TXN_FULL || err == MDBX_MAP_FULL) &&
config.params.ignore_dbfull) {
if ((err == MDBX_TXN_FULL || err == MDBX_MAP_FULL) && config.params.ignore_dbfull) {
log_notice("ttl: head-insert skip due '%s'", mdbx_strerror(err));
txn_restart(true, false);
serial = fifo.front().first;
@@ -227,8 +211,7 @@ bool testcase_ttl::run() {
}
loops += 1;
} else if (fifo.empty()) {
log_notice("ttl: done %u whole loops, %" PRIu64 " ops, %" PRIu64 " items",
loops, nops_completed, serial);
log_notice("ttl: done %u whole loops, %" PRIu64 " ops, %" PRIu64 " items", loops, nops_completed, serial);
rc = true;
break;
} else {

View File

@@ -24,8 +24,7 @@ std::string format(const char *fmt, ...) {
std::string result;
result.reserve((size_t)needed + 1);
result.resize((size_t)needed, '\0');
MDBX_MAYBE_UNUSED int actual =
vsnprintf((char *)result.data(), result.capacity(), fmt, ones);
MDBX_MAYBE_UNUSED int actual = vsnprintf((char *)result.data(), result.capacity(), fmt, ones);
assert(actual == needed);
(void)actual;
va_end(ones);
@@ -50,8 +49,7 @@ std::string data2hex(const void *ptr, size_t bytes, simple_checksum &checksum) {
return result;
}
bool hex2data(const char *hex_begin, const char *hex_end, void *ptr,
size_t bytes, simple_checksum &checksum) {
bool hex2data(const char *hex_begin, const char *hex_end, void *ptr, size_t bytes, simple_checksum &checksum) {
if (bytes * 2 != (size_t)(hex_end - hex_begin))
return false;
@@ -85,8 +83,7 @@ bool hex2data(const char *hex_begin, const char *hex_end, void *ptr,
}
bool is_samedata(const MDBX_val *a, const MDBX_val *b) {
return a->iov_len == b->iov_len &&
memcmp(a->iov_base, b->iov_base, a->iov_len) == 0;
return a->iov_len == b->iov_len && memcmp(a->iov_base, b->iov_base, a->iov_len) == 0;
}
//-----------------------------------------------------------------------------
@@ -96,13 +93,9 @@ uint64_t prng64_white(uint64_t &state) {
return bleach64(state);
}
uint32_t prng32_fast(uint64_t &state) {
return uint32_t(prng64_careless(state) >> 32);
}
uint32_t prng32_fast(uint64_t &state) { return uint32_t(prng64_careless(state) >> 32); }
uint32_t prng32_white(uint64_t &state) {
return bleach32(uint32_t(prng64_careless(state) >> 32));
}
uint32_t prng32_white(uint64_t &state) { return bleach32(uint32_t(prng64_careless(state) >> 32)); }
void prng_fill(uint64_t &state, void *ptr, size_t bytes) {
uint32_t u32 = prng32_fast(state);
@@ -174,9 +167,7 @@ bool flipcoin() { return prng32() & 1; }
bool flipcoin_x2() { return (prng32() & 3) == 0; }
bool flipcoin_x3() { return (prng32() & 7) == 0; }
bool flipcoin_x4() { return (prng32() & 15) == 0; }
bool flipcoin_n(unsigned n) {
return (prng64() & ((UINT64_C(1) << n) - 1)) == 0;
}
bool flipcoin_n(unsigned n) { return (prng64() & ((UINT64_C(1) << n) - 1)) == 0; }
bool jitter(unsigned probability_percent) {
const uint32_t top = UINT32_MAX - UINT32_MAX % 100;
@@ -201,8 +192,7 @@ void jitter_delay(bool extra) {
osal_yield();
cpu_relax();
if (dice > 2) {
size_t us =
prng32() & (extra ? 0xffff /* 656 ms */ : 0x3ff /* 1 ms */);
size_t us = prng32() & (extra ? 0xffff /* 656 ms */ : 0x3ff /* 1 ms */);
log_trace("== jitter.delay: %0.6f", us / 1000000.0);
osal_udelay(us);
}

View File

@@ -4,13 +4,11 @@
#pragma once
#include "base.h++"
#if !defined(__BYTE_ORDER__) || !defined(__ORDER_LITTLE_ENDIAN__) || \
!defined(__ORDER_BIG_ENDIAN__)
#if !defined(__BYTE_ORDER__) || !defined(__ORDER_LITTLE_ENDIAN__) || !defined(__ORDER_BIG_ENDIAN__)
#error __BYTE_ORDER__ should be defined.
#endif
#if __BYTE_ORDER__ != __ORDER_LITTLE_ENDIAN__ && \
__BYTE_ORDER__ != __ORDER_BIG_ENDIAN__
#if __BYTE_ORDER__ != __ORDER_LITTLE_ENDIAN__ && __BYTE_ORDER__ != __ORDER_BIG_ENDIAN__
#error Unsupported byte order.
#endif
@@ -21,16 +19,14 @@
#ifndef bswap32
#define bswap32(v) __builtin_bswap32(v)
#endif
#if (__GNUC_PREREQ(4, 8) || __has_builtin(__builtin_bswap16)) && \
!defined(bswap16)
#if (__GNUC_PREREQ(4, 8) || __has_builtin(__builtin_bswap16)) && !defined(bswap16)
#define bswap16(v) __builtin_bswap16(v)
#endif
#elif defined(_MSC_VER)
#if _MSC_FULL_VER < 190024215
#pragma message( \
"It is recommended to use Visual Studio 2015 (MSC 19.0) or newer.")
#pragma message("It is recommended to use Visual Studio 2015 (MSC 19.0) or newer.")
#endif
#define bswap64(v) _byteswap_uint64(v)
@@ -60,12 +56,9 @@
#define bswap64(v) __bswap_64(v)
#else
static inline uint64_t bswap64(uint64_t v) {
return v << 56 | v >> 56 | ((v << 40) & UINT64_C(0x00ff000000000000)) |
((v << 24) & UINT64_C(0x0000ff0000000000)) |
((v << 8) & UINT64_C(0x000000ff00000000)) |
((v >> 8) & UINT64_C(0x00000000ff0000000)) |
((v >> 24) & UINT64_C(0x0000000000ff0000)) |
((v >> 40) & UINT64_C(0x000000000000ff00));
return v << 56 | v >> 56 | ((v << 40) & UINT64_C(0x00ff000000000000)) | ((v << 24) & UINT64_C(0x0000ff0000000000)) |
((v << 8) & UINT64_C(0x000000ff00000000)) | ((v >> 8) & UINT64_C(0x00000000ff0000000)) |
((v >> 24) & UINT64_C(0x0000000000ff0000)) | ((v >> 40) & UINT64_C(0x000000000000ff00));
}
#endif
#endif /* bswap64 */
@@ -75,8 +68,7 @@ static inline uint64_t bswap64(uint64_t v) {
#define bswap32(v) __bswap_32(v)
#else
static inline uint32_t bswap32(uint32_t v) {
return v << 24 | v >> 24 | ((v << 8) & UINT32_C(0x00ff0000)) |
((v >> 8) & UINT32_C(0x0000ff00));
return v << 24 | v >> 24 | ((v << 8) & UINT32_C(0x00ff0000)) | ((v >> 8) & UINT32_C(0x0000ff00));
}
#endif
#endif /* bswap32 */
@@ -140,8 +132,7 @@ template <typename T> static inline T load(const void *ptr) {
if (MDBX_UNALIGNED_OK >= sizeof(T))
return *(const T *)ptr;
else {
#if defined(__unaligned) || defined(_M_ARM) || defined(_M_ARM64) || \
defined(_M_X64) || defined(_M_IA64)
#if defined(__unaligned) || defined(_M_ARM) || defined(_M_ARM64) || defined(_M_X64) || defined(_M_IA64)
return *(const T __unaligned *)ptr;
#else
T local;
@@ -155,8 +146,7 @@ template <typename T> static inline void store(void *ptr, const T &value) {
if (MDBX_UNALIGNED_OK >= sizeof(T))
*(T *)ptr = value;
else {
#if defined(__unaligned) || defined(_M_ARM) || defined(_M_ARM64) || \
defined(_M_X64) || defined(_M_IA64)
#if defined(__unaligned) || defined(_M_ARM) || defined(_M_ARM64) || defined(_M_X64) || defined(_M_IA64)
*((T __unaligned *)ptr) = value;
#else
memcpy(ptr, &value, sizeof(T));
@@ -169,9 +159,7 @@ template <typename T> static inline void store(void *ptr, const T &value) {
//-----------------------------------------------------------------------------
#ifndef rot64
static inline uint64_t rot64(uint64_t v, unsigned s) {
return (v >> s) | (v << (64 - s));
}
static inline uint64_t rot64(uint64_t v, unsigned s) { return (v >> s) | (v << (64 - s)); }
#endif /* rot64 */
static inline bool is_power2(size_t x) { return (x & (x - 1)) == 0; }
@@ -203,11 +191,9 @@ static inline void memory_barrier(void) {
#endif
#elif defined(__SUNPRO_C) || defined(__sun) || defined(sun)
__machine_rw_barrier();
#elif (defined(_HPUX_SOURCE) || defined(__hpux) || defined(__HP_aCC)) && \
(defined(HP_IA64) || defined(__ia64))
#elif (defined(_HPUX_SOURCE) || defined(__hpux) || defined(__HP_aCC)) && (defined(HP_IA64) || defined(__ia64))
_Asm_mf();
#elif defined(_AIX) || defined(__ppc__) || defined(__powerpc__) || \
defined(__ppc64__) || defined(__powerpc64__)
#elif defined(_AIX) || defined(__ppc__) || defined(__powerpc__) || defined(__ppc64__) || defined(__powerpc64__)
__lwsync();
#else
#error "Could not guess the kind of compiler, please report to us."
@@ -217,8 +203,7 @@ static inline void memory_barrier(void) {
static inline void cpu_relax() {
#if defined(__ia32__)
_mm_pause();
#elif defined(_WIN32) || defined(_WIN64) || defined(_WINDOWS) || \
defined(YieldProcessor)
#elif defined(_WIN32) || defined(_WIN64) || defined(_WINDOWS) || defined(YieldProcessor)
YieldProcessor();
#else
/* nope */
@@ -243,9 +228,7 @@ struct simple_checksum {
push((uint32_t)(data >> 32));
}
void push(const bool data) {
push(data ? UINT32_C(0x780E) : UINT32_C(0xFA18E));
}
void push(const bool data) { push(data ? UINT32_C(0x780E) : UINT32_C(0xFA18E)); }
void push(const void *ptr, size_t bytes) {
const uint8_t *data = (const uint8_t *)ptr;
@@ -269,12 +252,9 @@ struct simple_checksum {
};
std::string data2hex(const void *ptr, size_t bytes, simple_checksum &checksum);
bool hex2data(const char *hex_begin, const char *hex_end, void *ptr,
size_t bytes, simple_checksum &checksum);
bool hex2data(const char *hex_begin, const char *hex_end, void *ptr, size_t bytes, simple_checksum &checksum);
bool is_samedata(const MDBX_val *a, const MDBX_val *b);
inline bool is_samedata(const MDBX_val &a, const MDBX_val &b) {
return is_samedata(&a, &b);
}
inline bool is_samedata(const MDBX_val &a, const MDBX_val &b) { return is_samedata(&a, &b); }
std::string format(const char *fmt, ...);
static inline uint64_t bleach64(uint64_t x) {
@@ -300,22 +280,15 @@ static inline uint32_t bleach32(uint32_t x) {
return x;
}
static inline uint64_t prng64_map1_careless(uint64_t state) {
return state * UINT64_C(6364136223846793005) + 1;
}
static inline uint64_t prng64_map1_careless(uint64_t state) { return state * UINT64_C(6364136223846793005) + 1; }
static inline uint64_t prng64_map2_careless(uint64_t state) {
return (state + UINT64_C(1442695040888963407)) *
UINT64_C(6364136223846793005);
return (state + UINT64_C(1442695040888963407)) * UINT64_C(6364136223846793005);
}
static inline uint64_t prng64_map1_white(uint64_t state) {
return bleach64(prng64_map1_careless(state));
}
static inline uint64_t prng64_map1_white(uint64_t state) { return bleach64(prng64_map1_careless(state)); }
static inline uint64_t prng64_map2_white(uint64_t state) {
return bleach64(prng64_map2_careless(state));
}
static inline uint64_t prng64_map2_white(uint64_t state) { return bleach64(prng64_map2_careless(state)); }
static inline uint64_t prng64_careless(uint64_t &state) {
state = prng64_map1_careless(state);