mirror of
https://github.com/isar/libmdbx.git
synced 2025-08-19 19:39:26 +08:00
mdbx: новые настройки clang-format (косметика).
This commit is contained in:
@@ -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 ¶ms, 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);
|
||||
|
@@ -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 */
|
||||
|
@@ -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 ¶ms,
|
||||
const unsigned space_id) {
|
||||
bool registry::review_actor_params(const actor_testcase id, actor_params ¶ms, 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 ¶ms,
|
||||
unsigned &last_space_id) {
|
||||
void testcase_setup(const char *casename, const actor_params ¶ms, 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 ¶ms) {
|
||||
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
|
||||
|
@@ -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 */
|
||||
|
||||
|
@@ -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 */
|
||||
|
335
test/config.c++
335
test/config.c++
@@ -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 ¶ms,
|
||||
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 ¶ms, 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 *>(¶ms),
|
||||
sizeof(actor_params_pod), checksum));
|
||||
result.append(data2hex(static_cast<const actor_params_pod *>(¶ms), 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;
|
||||
}
|
||||
|
@@ -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 ¶ms,
|
||||
unsigned space_id, unsigned wait4id);
|
||||
actor_config(actor_testcase testcase, const actor_params ¶ms, unsigned space_id, unsigned wait4id);
|
||||
|
||||
actor_config(const char *str) : actor_config() {
|
||||
if (!deserialize(str, *this))
|
||||
|
@@ -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);
|
||||
}
|
||||
}
|
||||
|
@@ -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;
|
||||
};
|
||||
|
||||
|
@@ -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 байт.
|
||||
|
@@ -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();
|
||||
|
||||
|
@@ -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";
|
||||
|
@@ -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());
|
||||
|
@@ -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);
|
||||
|
@@ -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"));
|
||||
|
@@ -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);
|
||||
|
||||
|
@@ -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;
|
||||
}
|
||||
}
|
||||
|
@@ -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;
|
||||
|
@@ -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();
|
||||
});
|
||||
|
||||
|
@@ -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("");
|
||||
}
|
||||
|
@@ -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;
|
||||
}
|
||||
|
@@ -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 ====================");
|
||||
|
@@ -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);
|
||||
|
||||
|
@@ -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;
|
||||
|
@@ -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;
|
||||
|
247
test/keygen.c++
247
test/keygen.c++
@@ -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 ¶ms,
|
||||
result &out) {
|
||||
serial_t __hot maker::mk_begin(serial_t serial, const essentials ¶ms, 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 ¶ms,
|
||||
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 ¶ms,
|
||||
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 ¶ms,
|
||||
return serial;
|
||||
}
|
||||
|
||||
void __hot maker::mk_continue(const serial_t serial, const essentials ¶ms,
|
||||
result &out) {
|
||||
void __hot maker::mk_continue(const serial_t serial, const essentials ¶ms, 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 ¶ms,
|
||||
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 ¶ms,
|
||||
} 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)));
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -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 ¶ms,
|
||||
result &out);
|
||||
static void mk_continue(const serial_t serial, const essentials ¶ms,
|
||||
result &out);
|
||||
static serial_t mk_begin(serial_t serial, const essentials ¶ms, result &out);
|
||||
static void mk_continue(const serial_t serial, const essentials ¶ms, 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 */
|
||||
|
48
test/log.c++
48
test/log.c++
@@ -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();
|
||||
|
17
test/log.h++
17
test/log.h++
@@ -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, ...);
|
||||
|
449
test/main.c++
449
test/main.c++
@@ -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 ¶ms) {
|
||||
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 ¶ms) {
|
||||
}
|
||||
#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 */
|
||||
|
@@ -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");
|
||||
|
@@ -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)) {
|
||||
|
@@ -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) {
|
||||
|
@@ -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;
|
||||
|
@@ -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);
|
||||
|
||||
|
492
test/test.c++
492
test/test.c++
File diff suppressed because it is too large
Load Diff
121
test/test.h++
121
test/test.h++
@@ -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 ¶ms,
|
||||
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 ¶ms, 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 ¶ms);
|
||||
|
||||
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 ¶ms,
|
||||
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 ¶ms, 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 ¶ms, 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;
|
||||
};
|
||||
|
@@ -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);
|
||||
|
55
test/ttl.c++
55
test/ttl.c++
@@ -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 {
|
||||
|
@@ -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);
|
||||
}
|
||||
|
@@ -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);
|
||||
|
Reference in New Issue
Block a user