diff options
| author | George Hazan <ghazan@miranda.im> | 2018-07-11 12:29:02 +0300 |
|---|---|---|
| committer | George Hazan <ghazan@miranda.im> | 2018-07-11 12:29:10 +0300 |
| commit | 92a5c27c4ea88f2f7c4810c789f7b5aebe06d03c (patch) | |
| tree | e24f375b06c781077d22028a5d86f2d56585dc6c /plugins/Dbx_mdbx/src/libmdbx/test | |
| parent | 09693d256f7a0ec0c24dce56f9aca87d3a01856d (diff) | |
libmdbx extracted to separate dll
Diffstat (limited to 'plugins/Dbx_mdbx/src/libmdbx/test')
27 files changed, 0 insertions, 5492 deletions
diff --git a/plugins/Dbx_mdbx/src/libmdbx/test/CMakeLists.txt b/plugins/Dbx_mdbx/src/libmdbx/test/CMakeLists.txt deleted file mode 100644 index 3ed01bddf9..0000000000 --- a/plugins/Dbx_mdbx/src/libmdbx/test/CMakeLists.txt +++ /dev/null @@ -1,34 +0,0 @@ -set(TARGET mdbx_test) -project(${TARGET}) - -set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wno-missing-declarations") -set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wno-cast-qual") - -add_executable(${TARGET} - base.h - cases.cc - chrono.cc - chrono.h - config.cc - config.h - dead.cc - hill.cc - jitter.cc - keygen.cc - keygen.h - log.cc - log.h - main.cc - osal.h - osal-unix.cc - test.cc - test.h - try.cc - utils.cc - utils.h -) - -target_link_libraries(${TARGET} - mdbx - ) - diff --git a/plugins/Dbx_mdbx/src/libmdbx/test/base.h b/plugins/Dbx_mdbx/src/libmdbx/test/base.h deleted file mode 100644 index b23f776aa3..0000000000 --- a/plugins/Dbx_mdbx/src/libmdbx/test/base.h +++ /dev/null @@ -1,109 +0,0 @@ -/* - * Copyright 2017-2018 Leonid Yuriev <leo@yuriev.ru> - * and other libmdbx authors: please see AUTHORS file. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted only as authorized by the OpenLDAP - * Public License. - * - * A copy of this license is available in the file LICENSE in the - * top-level directory of the distribution or, alternatively, at - * <http://www.OpenLDAP.org/license.html>. - */ - -#pragma once - -#ifndef NOMINMAX -#define NOMINMAX -#endif - -#if defined(_WIN32) || defined(_WIN64) || defined(_WINDOWS) -#ifdef _MSC_VER -#define _CRT_SECURE_NO_WARNINGS -#pragma warning(push, 1) -#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 \ - semantics are not enabled. Specify /EHsc */ -#pragma warning(disable : 4577) /* 'noexcept' used with no exception handling \ - mode specified; termination on exception \ - is not guaranteed. Specify /EHsc */ -#endif /* _MSC_VER (warnings) */ - -/* If you wish to build your application for a previous Windows platform, - * include WinSDKVer.h and set the _WIN32_WINNT macro to the platform you - * wish to support before including SDKDDKVer.h. - * - * TODO: #define _WIN32_WINNT WIN32_MUSTDIE */ -#include <SDKDDKVer.h> -#endif /* WINDOWS */ - -#include <errno.h> -#include <limits.h> -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include <time.h> - -#if defined(_WIN32) || defined(_WIN64) || defined(_WINDOWS) -#include <io.h> -#else -#include <fcntl.h> -#include <sys/param.h> -#include <sys/stat.h> -#include <sys/time.h> -#include <sys/types.h> -#include <unistd.h> -#endif - -#ifdef _BSD_SOURCE -#include <endian.h> -#endif - -#include <algorithm> -#include <cassert> -#include <cinttypes> // for PRId64, PRIu64 -#include <cstdarg> -#include <cstddef> -#include <cstdint> -#include <map> -#include <memory> -#include <set> -#include <string> -#include <type_traits> -#include <unordered_map> -#include <unordered_set> -#include <vector> - -#include "../mdbx.h" -#include "../src/defs.h" -#include "../src/osal.h" - -#if !defined(__thread) && (defined(_MSC_VER) || defined(__DMC__)) -#define __thread __declspec(thread) -#endif /* __thread */ - -#ifdef _MSC_VER -#pragma warning(pop) -#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 \ - not be generated */ -#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__) -#endif -#ifndef vsnprintf -#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 \ - may be unsafe */ -#endif -#endif /* _MSC_VER */ diff --git a/plugins/Dbx_mdbx/src/libmdbx/test/cases.cc b/plugins/Dbx_mdbx/src/libmdbx/test/cases.cc deleted file mode 100644 index 4f4306d58e..0000000000 --- a/plugins/Dbx_mdbx/src/libmdbx/test/cases.cc +++ /dev/null @@ -1,97 +0,0 @@ -/* - * Copyright 2017-2018 Leonid Yuriev <leo@yuriev.ru> - * and other libmdbx authors: please see AUTHORS file. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted only as authorized by the OpenLDAP - * Public License. - * - * A copy of this license is available in the file LICENSE in the - * top-level directory of the distribution or, alternatively, at - * <http://www.OpenLDAP.org/license.html>. - */ - -#include "test.h" - -void configure_actor(unsigned &last_space_id, const actor_testcase testcase, - const char *space_id_cstr, const actor_params ¶ms) { - 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); - wait4id = i->actor_id; - i->signal_nops = params.waitfor_nops; - break; - } - } - if (!wait4id) - failure("No previous waitable actor for %u-ops\n", params.waitfor_nops); - } - - unsigned space_id = 0; - if (!space_id_cstr || strcmp(space_id_cstr, "auto") == 0) - space_id = last_space_id + 1; - else { - char *end = nullptr; - errno = 0; - space_id = strtoul(space_id_cstr, &end, 0); - if (errno) - failure_perror("Expects an integer value for space-id\n", errno); - if (end && *end) - failure("The '%s' is unexpected for space-id\n", end); - } - - if (space_id > ACTOR_ID_MAX) - failure("Invalid space-id %u\n", space_id); - last_space_id = space_id; - - log_trace("configure_actor: space %u for %s", space_id, - testcase2str(testcase)); - global::actors.emplace_back( - actor_config(testcase, params, space_id, wait4id)); - global::databases.insert(params.pathname_db); -} - -void testcase_setup(const char *casename, actor_params ¶ms, - unsigned &last_space_id) { - if (strcmp(casename, "basic") == 0) { - log_notice(">>> testcase_setup(%s)", casename); - configure_actor(last_space_id, ac_jitter, nullptr, params); - configure_actor(last_space_id, ac_hill, nullptr, params); - configure_actor(last_space_id, ac_jitter, nullptr, params); - configure_actor(last_space_id, ac_hill, nullptr, params); - configure_actor(last_space_id, ac_jitter, nullptr, params); - configure_actor(last_space_id, ac_hill, nullptr, params); - configure_actor(last_space_id, ac_try, nullptr, params); - log_notice("<<< testcase_setup(%s): done", casename); - } else { - failure("unknown testcase `%s`", casename); - } -} - -void keycase_setup(const char *casename, actor_params ¶ms) { - if (strcmp(casename, "random") == 0 || strcmp(casename, "prng") == 0) { - log_notice(">>> keycase_setup(%s)", casename); - params.keygen.keycase = kc_random; - // TODO - log_notice("<<< keycase_setup(%s): done", casename); - } else if (strcmp(casename, "dashes") == 0 || - strcmp(casename, "aside") == 0) { - log_notice(">>> keycase_setup(%s)", casename); - params.keygen.keycase = kc_dashes; - // TODO - log_notice("<<< keycase_setup(%s): done", casename); - } else if (strcmp(casename, "custom") == 0) { - log_notice("=== keycase_setup(%s): skip", casename); - params.keygen.keycase = kc_custom; - } else { - failure("unknown keycase `%s`", casename); - } -} - -/* TODO */ diff --git a/plugins/Dbx_mdbx/src/libmdbx/test/chrono.cc b/plugins/Dbx_mdbx/src/libmdbx/test/chrono.cc deleted file mode 100644 index f734668628..0000000000 --- a/plugins/Dbx_mdbx/src/libmdbx/test/chrono.cc +++ /dev/null @@ -1,129 +0,0 @@ -/* - * Copyright 2017-2018 Leonid Yuriev <leo@yuriev.ru> - * and other libmdbx authors: please see AUTHORS file. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted only as authorized by the OpenLDAP - * Public License. - * - * A copy of this license is available in the file LICENSE in the - * top-level directory of the distribution or, alternatively, at - * <http://www.OpenLDAP.org/license.html>. - */ - -#include "test.h" - -namespace chrono { - -#define NSEC_PER_SEC 1000000000u -uint32_t ns2fractional(uint32_t ns) { - assert(ns < NSEC_PER_SEC); - /* LY: здесь и далее используется "длинное деление", которое - * для ясности кода оставлено как есть (без ручной оптимизации). Так как - * GCC, Clang и даже MSVC сами давно умеют конвертировать деление на - * константу в быструю reciprocal-форму. */ - return ((uint64_t)ns << 32) / NSEC_PER_SEC; -} - -uint32_t fractional2ns(uint32_t fractional) { - return (fractional * (uint64_t)NSEC_PER_SEC) >> 32; -} - -#define USEC_PER_SEC 1000000u -uint32_t us2fractional(uint32_t us) { - assert(us < USEC_PER_SEC); - return ((uint64_t)us << 32) / USEC_PER_SEC; -} - -uint32_t fractional2us(uint32_t fractional) { - return (fractional * (uint64_t)USEC_PER_SEC) >> 32; -} - -#define MSEC_PER_SEC 1000u -uint32_t ms2fractional(uint32_t ms) { - assert(ms < MSEC_PER_SEC); - return ((uint64_t)ms << 32) / MSEC_PER_SEC; -} - -uint32_t fractional2ms(uint32_t fractional) { - return (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)); - return result; -} - -time from_us(uint64_t us) { - time result; - 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)); - return result; -} - -time now_realtime() { -#if defined(_WIN32) || defined(_WIN64) || defined(_WINDOWS) - static void(WINAPI * query_time)(LPFILETIME); - if (!query_time) { - query_time = (void(WINAPI *)(LPFILETIME))GetProcAddress( - GetModuleHandle(TEXT("kernel32.dll")), - "GetSystemTimePreciseAsFileTime"); - if (!query_time) - query_time = GetSystemTimeAsFileTime; - } - - FILETIME filetime; - query_time(&filetime); - uint64_t ns100 = - (uint64_t)filetime.dwHighDateTime << 32 | filetime.dwLowDateTime; - return from_ns((ns100 - UINT64_C(116444736000000000)) * 100u); -#else - struct timespec ts; - if (unlikely(clock_gettime(CLOCK_REALTIME, &ts))) - failure_perror("clock_gettime(CLOCK_REALTIME", errno); - - return from_timespec(ts); -#endif -} - -time now_motonic() { -#if defined(_WIN32) || defined(_WIN64) || defined(_WINDOWS) - static uint64_t reciprocal; - static LARGE_INTEGER Frequency; - if (reciprocal == 0) { - if (!QueryPerformanceFrequency(&Frequency)) - failure_perror("QueryPerformanceFrequency()", GetLastError()); - reciprocal = (((UINT64_C(1) << 48) + Frequency.QuadPart / 2 + 1) / - Frequency.QuadPart); - assert(reciprocal); - } - - LARGE_INTEGER Counter; - if (!QueryPerformanceCounter(&Counter)) - failure_perror("QueryPerformanceCounter()", GetLastError()); - - time result; - result.fixedpoint = (Counter.QuadPart / Frequency.QuadPart) << 32; - uint64_t mod = Counter.QuadPart % Frequency.QuadPart; - result.fixedpoint += (mod * reciprocal) >> 16; - return result; -#else - struct timespec ts; - if (unlikely(clock_gettime(CLOCK_MONOTONIC, &ts))) - failure_perror("clock_gettime(CLOCK_MONOTONIC)", errno); - - return from_timespec(ts); -#endif -} - -} /* namespace chrono */ diff --git a/plugins/Dbx_mdbx/src/libmdbx/test/chrono.h b/plugins/Dbx_mdbx/src/libmdbx/test/chrono.h deleted file mode 100644 index c2bd5627a6..0000000000 --- a/plugins/Dbx_mdbx/src/libmdbx/test/chrono.h +++ /dev/null @@ -1,100 +0,0 @@ -/* - * Copyright 2017-2018 Leonid Yuriev <leo@yuriev.ru> - * and other libmdbx authors: please see AUTHORS file. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted only as authorized by the OpenLDAP - * Public License. - * - * A copy of this license is available in the file LICENSE in the - * top-level directory of the distribution or, alternatively, at - * <http://www.OpenLDAP.org/license.html>. - */ - -#pragma once - -#include "base.h" -#include "log.h" -#include "utils.h" - -namespace chrono { - -#pragma pack(push, 1) - -typedef union time { - uint64_t fixedpoint; - struct { -#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ - uint32_t fractional; - union { - uint32_t utc; - uint32_t integer; - }; -#else - union { - uint32_t utc; - uint32_t integer; - }; - uint32_t fractional; -#endif - }; - - void reset() { fixedpoint = 0; } - uint32_t seconds() const { return utc; } -} time; - -#pragma pack(pop) - -uint32_t ns2fractional(uint32_t); -uint32_t fractional2ns(uint32_t); -uint32_t us2fractional(uint32_t); -uint32_t fractional2us(uint32_t); -uint32_t ms2fractional(uint32_t); -uint32_t fractional2ms(uint32_t); - -time from_ns(uint64_t us); -time from_us(uint64_t ns); -time from_ms(uint64_t ms); - -inline time from_seconds(uint64_t seconds) { - assert(seconds < UINT32_MAX); - time result; - result.fixedpoint = seconds << 32; - return result; -} - -inline time from_utc(time_t utc) { - assert(utc >= 0); - return from_seconds((uint64_t)utc); -} - -inline time infinite() { - time result; - result.fixedpoint = UINT64_MAX; - return result; -} - -#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); - return result; -} -#endif /* HAVE_TIMESPEC_TV_NSEC */ - -#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); - return result; -} -#endif /* HAVE_TIMEVAL_TV_USEC */ - -time now_realtime(); -time now_motonic(); - -} /* namespace chrono */ diff --git a/plugins/Dbx_mdbx/src/libmdbx/test/config.cc b/plugins/Dbx_mdbx/src/libmdbx/test/config.cc deleted file mode 100644 index cbff68ce4e..0000000000 --- a/plugins/Dbx_mdbx/src/libmdbx/test/config.cc +++ /dev/null @@ -1,471 +0,0 @@ -/* - * Copyright 2017-2018 Leonid Yuriev <leo@yuriev.ru> - * and other libmdbx authors: please see AUTHORS file. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted only as authorized by the OpenLDAP - * Public License. - * - * A copy of this license is available in the file LICENSE in the - * top-level directory of the distribution or, alternatively, at - * <http://www.OpenLDAP.org/license.html>. - */ - -#include "test.h" - -#if defined(_MSC_VER) && !defined(strcasecmp) -#define strcasecmp(str, len) _stricmp(str, len) -#endif /* _MSC_VER && strcasecmp() */ - -namespace config { - -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); - - if (strncmp(current, "--", 2) || strncmp(current + 2, option, optlen)) - return false; - - if (!value) { - if (current[optlen + 2] == '=') - failure("Option '--%s' doen't accept any value\n", option); - return true; - } - - *value = nullptr; - if (current[optlen + 2] == '=') { - *value = ¤t[optlen + 3]; - return true; - } - - if (narg + 1 < argc && strncmp("--", argv[narg + 1], 2) != 0) { - *value = argv[narg + 1]; - ++narg; - return true; - } - - if (default_value) { - *value = default_value; - return true; - } - - 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) { - const char *value_cstr; - if (!parse_option(argc, argv, narg, option, &value_cstr, - allow_empty ? "" : nullptr)) - return false; - - if (!allow_empty && strlen(value_cstr) == 0) - failure("Value for option '--%s' could't be empty\n", option); - - value = value_cstr; - return true; -} - -bool parse_option(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)) - return false; - - mask = 0; - while (*list) { - if (*list == ',' || *list == ' ' || *list == '\t') { - ++list; - continue; - } - - const char *const comma = strchr(list, ','); - const size_t len = (comma) ? comma - list : strlen(list); - const option_verb *scan = verbs; - while (true) { - if (!scan->verb) - failure("Unknown verb '%.*s', for option '==%s'\n", (int)len, list, - option); - if (strlen(scan->verb) == len && strncmp(list, scan->verb, len) == 0) { - mask |= scan->mask; - list += len; - break; - } - ++scan; - } - } - - 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 char *value_cstr; - if (!parse_option(argc, argv, narg, option, &value_cstr)) - return false; - - char *suffix = nullptr; - errno = 0; - unsigned long raw = strtoul(value_cstr, &suffix, 0); - if (errno) - failure("Option '--%s' expects a numeric value (%s)\n", option, - test_strerror(errno)); - - uint64_t multipler = 1; - if (suffix && *suffix) { - if (scale == no_scale) - failure("Option '--%s' doen't accepts suffixes, so '%s' is unexpected\n", - option, suffix); - if (strcmp(suffix, "K") == 0 || strcasecmp(suffix, "Kilo") == 0) - multipler = (scale == decimal) ? UINT64_C(1000) : UINT64_C(1024); - else if (strcmp(suffix, "M") == 0 || strcasecmp(suffix, "Mega") == 0) - multipler = - (scale == decimal) ? UINT64_C(1000) * 1000 : UINT64_C(1024) * 1024; - else if (strcmp(suffix, "G") == 0 || strcasecmp(suffix, "Giga") == 0) - multipler = (scale == decimal) ? UINT64_C(1000) * 1000 * 1000 - : UINT64_C(1024) * 1024 * 1024; - else if (strcmp(suffix, "T") == 0 || strcasecmp(suffix, "Tera") == 0) - multipler = (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)) - multipler = 1; - else if (scale == duration && - (strcmp(suffix, "m") == 0 || strcasecmp(suffix, "Minutes") == 0)) - multipler = 60; - else if (scale == duration && - (strcmp(suffix, "h") == 0 || strcasecmp(suffix, "Hours") == 0)) - multipler = 3600; - else if (scale == duration && - (strcmp(suffix, "d") == 0 || strcasecmp(suffix, "Days") == 0)) - multipler = 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); - } - - if (raw >= UINT64_MAX / multipler) - failure("The value for option '--%s' is too huge\n", option); - - value = raw * multipler; - if (maxval && value > 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); - 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) { - - uint64_t huge; - if (!parse_option(argc, argv, narg, option, huge, scale, minval, maxval)) - 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) { - - uint64_t huge; - if (!parse_option(argc, argv, narg, option, huge, no_scale, minval, maxval)) - return false; - value = (uint8_t)huge; - return true; -} - -bool parse_option(int argc, char *const argv[], int &narg, const char *option, - bool &value) { - const char *value_cstr = NULL; - if (!parse_option(argc, argv, narg, option, &value_cstr, "yes")) { - const char *current = argv[narg]; - if (strncmp(current, "--no-", 5) == 0 && strcmp(current + 5, option) == 0) { - value = false; - return true; - } - if (strncmp(current, "--dont-", 7) == 0 && - strcmp(current + 7, option) == 0) { - value = false; - return true; - } - return false; - } - - if (!value_cstr) { - value = true; - return true; - } - - if (strcasecmp(value_cstr, "yes") == 0 || strcasecmp(value_cstr, "1") == 0) { - value = true; - return true; - } - - if (strcasecmp(value_cstr, "no") == 0 || strcasecmp(value_cstr, "0") == 0) { - value = false; - return true; - } - - failure( - "Option '--%s' expects a 'boolean' value Yes/No, so '%s' is unexpected\n", - option, value_cstr); -} - -//----------------------------------------------------------------------------- - -const struct option_verb mode_bits[] = { - {"rdonly", MDBX_RDONLY}, {"mapasync", MDBX_MAPASYNC}, - {"utterly", MDBX_UTTERLY_NOSYNC}, {"nosubdir", MDBX_NOSUBDIR}, - {"nosync", MDBX_NOSYNC}, {"nometasync", MDBX_NOMETASYNC}, - {"writemap", MDBX_WRITEMAP}, {"notls", MDBX_NOTLS}, - {"nordahead", MDBX_NORDAHEAD}, {"nomeminit", MDBX_NOMEMINIT}, - {"coalesce", MDBX_COALESCE}, {"lifo", MDBX_LIFORECLAIM}, - {"perturb", MDBX_PAGEPERTURB}, {nullptr, 0}}; - -const struct option_verb table_bits[] = { - {"key.reverse", MDBX_REVERSEKEY}, - {"key.integer", MDBX_INTEGERKEY}, - {"data.integer", MDBX_INTEGERDUP | MDBX_DUPFIXED | MDBX_DUPSORT}, - {"data.fixed", MDBX_DUPFIXED | MDBX_DUPSORT}, - {"data.reverse", MDBX_REVERSEDUP | MDBX_DUPSORT}, - {"data.dups", MDBX_DUPSORT}, - {nullptr, 0}}; - -static void dump_verbs(const char *caption, size_t bits, - const struct option_verb *verbs) { - log_info("%s: 0x%" PRIx64 " = ", caption, (uint64_t)bits); - - const char *comma = ""; - while (verbs->mask && bits) { - if ((bits & verbs->mask) == verbs->mask) { - logging::feed("%s%s", comma, verbs->verb); - bits -= verbs->mask; - comma = ", "; - } - ++verbs; - } - - logging::feed("\n"); -} - -static void dump_duration(const char *caption, unsigned duration) { - log_info("%s: ", caption); - if (duration) { - if (duration > 24 * 3600) - logging::feed("%u_", duration / (24 * 3600)); - if (duration > 3600) - logging::feed("%02u:", (duration % (24 * 3600)) / 3600); - logging::feed("%02u:%02u", (duration % 3600) / 60, duration % 60); - } else { - logging::feed("INFINITE"); - } - logging::feed("\n"); -} - -void dump(const char *title) { - logging::local_suffix indent(title); - - for (auto i = global::actors.begin(); i != global::actors.end(); ++i) { - log_info("#%u, testcase %s, space_id/table %u\n", i->actor_id, - testcase2str(i->testcase), i->space_id); - indent.push(); - - if (i->params.loglevel) { - log_info("log: level %u, %s\n", i->params.loglevel, - i->params.pathname_log.empty() ? "console" - : i->params.pathname_log.c_str()); - } - - log_info("database: %s, size %" PRIu64 "\n", i->params.pathname_db.c_str(), - i->params.size); - - dump_verbs("mode", i->params.mode_flags, mode_bits); - dump_verbs("table", i->params.table_flags, table_bits); - - if (i->params.test_nops) - log_info("iterations/records %u\n", i->params.test_nops); - else - dump_duration("duration", i->params.test_duration); - - if (i->params.nrepeat) - log_info("repeat %u\n", i->params.nrepeat); - else - log_info("repeat ETERNALLY\n"); - - log_info("threads %u\n", i->params.nthreads); - - log_info("keygen.case: %s\n", keygencase2str(i->params.keygen.keycase)); - log_info("keygen.seed: %u\n", i->params.keygen.seed); - log_info("key: minlen %u, maxlen %u\n", i->params.keylen_min, - i->params.keylen_max); - log_info("data: minlen %u, maxlen %u\n", i->params.datalen_min, - i->params.datalen_max); - - log_info("batch: read %u, write %u\n", i->params.batch_read, - i->params.batch_write); - - if (i->params.waitfor_nops) - log_info("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_info("no-delay\n"); - - if (i->params.inject_writefaultn) - log_info("inject-writefault on %u ops\n", i->params.inject_writefaultn); - else - log_info("no-inject-writefault\n"); - - log_info("limits: readers %u, tables %u\n", i->params.max_readers, - i->params.max_tables); - - log_info("drop table: %s\n", i->params.drop_table ? "Yes" : "No"); - indent.pop(); - } - - dump_duration("timeout", global::config::timeout_duration_seconds); - log_info("cleanup: before %s, after %s\n", - global::config::cleanup_before ? "Yes" : "No", - global::config::cleanup_after ? "Yes" : "No"); - - log_info("failfast: %s\n", global::config::failfast ? "Yes" : "No"); - log_info("progress indicator: %s\n", - global::config::progress_indicator ? "Yes" : "No"); -} - -} /* namespace config */ - -//----------------------------------------------------------------------------- - -using namespace config; - -actor_config::actor_config(actor_testcase testcase, const actor_params ¶ms, - unsigned space_id, unsigned wait4id) - : params(params) { - this->space_id = space_id; - this->actor_id = 1 + (unsigned)global::actors.size(); - this->testcase = testcase; - this->wait4id = wait4id; - signal_nops = 0; -} - -const std::string actor_config::serialize(const char *prefix) const { - simple_checksum checksum; - - std::string result; - if (prefix) - result.append(prefix); - - checksum.push(params.pathname_db); - result.append(params.pathname_db); - result.append("|"); - - checksum.push(params.pathname_log); - result.append(params.pathname_log); - result.append("|"); - - static_assert(std::is_pod<actor_params_pod>::value, - "actor_params_pod should by POD"); - result.append(data2hex(static_cast<const actor_params_pod *>(¶ms), - sizeof(actor_params_pod), checksum)); - result.append("|"); - - static_assert(std::is_pod<actor_config_pod>::value, - "actor_config_pod should by POD"); - result.append(data2hex(static_cast<const actor_config_pod *>(this), - sizeof(actor_config_pod), checksum)); - result.append("|"); - - result.append(osal_serialize(checksum)); - result.append("|"); - - result.append(std::to_string(checksum.value)); - return result; -} - -bool actor_config::deserialize(const char *str, actor_config &config) { - simple_checksum checksum; - - TRACE(">> actor_config::deserialize: %s\n", str); - - const char *slash = strchr(str, '|'); - if (!slash) { - TRACE("<< actor_config::deserialize: slash-1\n"); - return false; - } - config.params.pathname_db.assign(str, slash - str); - checksum.push(config.params.pathname_db); - str = slash + 1; - - slash = strchr(str, '|'); - if (!slash) { - TRACE("<< actor_config::deserialize: slash-2\n"); - return false; - } - config.params.pathname_log.assign(str, slash - str); - checksum.push(config.params.pathname_log); - str = slash + 1; - - slash = strchr(str, '|'); - if (!slash) { - TRACE("<< actor_config::deserialize: slash-3\n"); - return false; - } - static_assert(std::is_pod<actor_params_pod>::value, - "actor_params_pod should by POD"); - 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; - - slash = strchr(str, '|'); - if (!slash) { - TRACE("<< actor_config::deserialize: slash-4\n"); - return false; - } - static_assert(std::is_pod<actor_config_pod>::value, - "actor_config_pod should by POD"); - 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; - - slash = strchr(str, '|'); - if (!slash) { - TRACE("<< actor_config::deserialize: slash-5\n"); - return false; - } - if (!config.osal_deserialize(str, slash, checksum)) { - TRACE("<< actor_config::deserialize: osal\n"); - return false; - } - str = slash + 1; - - uint64_t verify = std::stoull(std::string(str)); - if (checksum.value != verify) { - TRACE("<< actor_config::deserialize: checksum mismatch\n"); - return false; - } - - TRACE("<< actor_config::deserialize: OK\n"); - return true; -} diff --git a/plugins/Dbx_mdbx/src/libmdbx/test/config.h b/plugins/Dbx_mdbx/src/libmdbx/test/config.h deleted file mode 100644 index 86f37fbed8..0000000000 --- a/plugins/Dbx_mdbx/src/libmdbx/test/config.h +++ /dev/null @@ -1,280 +0,0 @@ -/* - * Copyright 2017-2018 Leonid Yuriev <leo@yuriev.ru> - * and other libmdbx authors: please see AUTHORS file. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted only as authorized by the OpenLDAP - * Public License. - * - * A copy of this license is available in the file LICENSE in the - * top-level directory of the distribution or, alternatively, at - * <http://www.OpenLDAP.org/license.html>. - */ - -#pragma once - -#include "base.h" -#include "log.h" -#include "utils.h" - -#define ACTOR_ID_MAX INT16_MAX - -enum actor_testcase { - ac_none, - ac_hill, - ac_deadread, - ac_deadwrite, - ac_jitter, - ac_try -}; - -enum actor_status { - as_unknown, - as_debuging, - as_running, - as_successful, - as_killed, - as_failed -}; - -const char *testcase2str(const actor_testcase); -const char *status2str(actor_status status); - -enum keygen_case { - kc_random, /* [ 6.. 2.. 7.. 4.. 0.. 1.. 5.. 3.. ] */ - kc_dashes, /* [ 0123.. 4567.. ] */ - kc_custom, - /* TODO: more cases */ -}; - -const char *keygencase2str(const keygen_case); - -//----------------------------------------------------------------------------- - -namespace config { - -enum scale_mode { no_scale, decimal, binary, duration }; - -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, - bool &value); - -struct option_verb { - const char *const verb; - unsigned mask; -}; - -bool parse_option(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); - -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); - -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); - -//----------------------------------------------------------------------------- - -#pragma pack(push, 1) - -struct keygen_params_pod { - keygen_case keycase; - - /* Параметры генератора пар key-value. - * - * Ключи и значения генерируются по задаваемым параметрам на основе "плоской" - * исходной координаты. При этом, в общем случае, в процессе тестов исходная - * координата последовательно итерируется в заданном диапазоне, а необходимые - * паттерны/последовательности/узоры получаются за счет преобразования - * исходной координаты, согласно описанным ниже параметрам. - * - * Стоит отметить, что порядок описания параметров для удобства совпадает с - * порядком их использования, т.е. с порядком соответствующих преобразований. - * - * Второе важное замечание касается ограничений одновременной координированной - * генерации паттеров как для ключей, так и для значений. Суть в том, что - * такая возможность не нужна по следующим причинам: - * - libmdbx поддерживает два существенно различающихся вида таблиц, - * "уникальные" (без дубликатов и без multi-value), и так называемые - * "с дубликатами" (c multi-value). - * - Для таблиц "без дубликатов" только размер связанных к ключами значений - * (данных) оказывает влияния на работу движка, непосредственно содержимое - * данных не анализируется движком и не оказывает влияния на его работу. - * - Для таблиц "с дубликатами", при наличии более одного значения для - * некоторого ключа, формируется дочернее btree-поддерево. Это дерево - * формируется в отдельном "кусте" страниц и обслуживается независимо - * от окружения родительского ключа. - * - Таким образом, паттерн генерации значений имеет смысл только для - * таблиц "с дубликатами" и только в контексте одного значения ключа. - * Иначе говоря, нет смысла в со-координации генерации паттернов для - * ключей и значений. Более того, генерацию значений всегда необходимо - * рассматривать в контексте связки с одним значением ключа. - * - * width: - * Большинство тестов предполагают создание или итерирование некоторого - * количества записей. При этом требуется итерирование или генерация - * значений и ключей из некоторого ограниченного пространства вариантов. - * - * Параметр width задает такую ширину пространства вариантов в битах. - * Таким образом мощность пространства вариантов (пока) всегда равна - * степени двойки. Это ограничение можно снять, но ценой увеличения - * вычислительной сложности, включая потерю простоты и прозрачности. - * - * С другой стороны, не-битовый width может быть полезен: - * - Позволит генерировать ключи/значения в точно задаваемом диапазоне. - * Например, перебрать в псевдо-случайном порядке 10001 значение. - * - Позволит поровну разделять заданное пространство (диапазон) - * ключей/значений между количеством потоков некратным степени двойки. - * - * mesh и seed: - * Позволяют получить псевдо-случайные последовательности ключей/значений. - * Параметр mesh задает сколько младших бит исходной плоской координаты - * будет "перемешано" (инъективно отображено), а параметр seed позволяет - * выбрать конкретный вариант "перемешивания". - * - * Перемешивание выполняется при ненулевом значении mesh. Перемешивание - * реализуется посредством применения двух инъективных функций для - * заданного количества бит: - * - применяется первая инъективная функция; - * - к результату добавляется salt полученный из seed; - * - применяется вторая инъективная функция; - * - * Следует отметить, что mesh умышленно позволяет перемешать только младшую - * часть, что при ненулевом значении split (см далее) не позволяет получать - * псевдо-случайные значений ключей без псевдо-случайности в значениях. - * - * Такое ограничение соответствуют внутренней алгоритмике libmdbx. Проще - * говоря мы можем проверить движок псевдо-случайной последовательностью - * ключей на таблицах без дубликатов (без multi-value), а затем проверить - * корректность работу псевдо-случайной последовательностью значений на - * таблицах с дубликатами (с multi-value), опционально добавляя - * псевдо-случайности к последовательности ключей. Однако, нет смысла - * генерировать псевдо-случайные ключи, одновременно с формированием - * какого-либо паттерна в значениях, так как содержимое в данных либо - * не будет иметь значения (для таблиц без дубликатов), либо будет - * обрабатываться в отдельных btree-поддеревьях. - * - * rotate и offset: - * Для проверки слияния и разделения страниц внутри движка требуются - * генерация ключей/значений в виде не-смежных последовательностей, как-бы - * в виде "пунктира", который постепенно заполняет весь заданных диапазон. - * - * Параметры позволяют генерировать такой "пунктир". Соответственно rotate - * задает циклический сдвиг вправо, а offset задает смещение, точнее говоря - * сложение по модулю внутри диапазона заданного посредством width. - * - * Например, при rotate равном 1 (циклический сдвиг вправо на 1 бит), - * четные и нечетные исходные значения сложатся в две линейные - * последовательности, которые постепенно закроют старшую и младшую - * половины диапазона. - * - * split: - * Для таблиц без дубликатов (без multi-value ключей) фактически требуется - * генерация только ключей, а данные могут быть постоянным. Но для таблиц с - * дубликатами (с multi-value ключами) также требуется генерация значений. - * - * Ненулевое значение параметра split фактически включает генерацию значений, - * при этом значение split определяет сколько бит исходного абстрактного - * номера будет отрезано для генерации значения. - */ - - uint8_t width; - uint8_t mesh; - uint8_t rotate; - uint8_t split; - uint32_t seed; - uint64_t offset; -}; - -struct actor_params_pod { - unsigned loglevel; - - unsigned mode_flags; - unsigned table_flags; - uint64_t size; - - unsigned test_duration; - unsigned test_nops; - unsigned nrepeat; - unsigned nthreads; - - unsigned keylen_min, keylen_max; - unsigned datalen_min, datalen_max; - - unsigned batch_read; - unsigned batch_write; - - unsigned delaystart; - unsigned waitfor_nops; - unsigned inject_writefaultn; - - unsigned max_readers; - unsigned max_tables; - keygen_params_pod keygen; - - bool drop_table; -}; - -struct actor_config_pod { - unsigned actor_id, space_id; - actor_testcase testcase; - unsigned wait4id; - unsigned signal_nops; -}; - -#pragma pack(pop) - -extern const struct option_verb mode_bits[]; -extern const struct option_verb table_bits[]; -void dump(const char *title = "config-dump: "); - -} /* namespace config */ - -struct actor_params : public config::actor_params_pod { - std::string pathname_log; - std::string pathname_db; - void set_defaults(const std::string &tmpdir); -}; - -struct actor_config : public config::actor_config_pod { - actor_params params; - - bool wanna_event4signalling() const { return true /* TODO ? */; } - - actor_config(actor_testcase testcase, const actor_params ¶ms, - unsigned space_id, unsigned wait4id); - - actor_config(const char *str) { - if (!deserialize(str, *this)) - failure("Invalid internal parameter '%s'\n", str); - } - - const std::string osal_serialize(simple_checksum &) const; - bool osal_deserialize(const char *str, const char *end, simple_checksum &); - - const std::string serialize(const char *prefix) const; - static bool deserialize(const char *str, actor_config &config); - - bool is_waitable(size_t nops) const { - switch (testcase) { - case ac_hill: - if (!params.test_nops || params.test_nops >= nops) - return true; - __fallthrough; - default: - return false; - } - } -}; diff --git a/plugins/Dbx_mdbx/src/libmdbx/test/dead.cc b/plugins/Dbx_mdbx/src/libmdbx/test/dead.cc deleted file mode 100644 index ee13fbd0ae..0000000000 --- a/plugins/Dbx_mdbx/src/libmdbx/test/dead.cc +++ /dev/null @@ -1,63 +0,0 @@ -/* - * Copyright 2017-2018 Leonid Yuriev <leo@yuriev.ru> - * and other libmdbx authors: please see AUTHORS file. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted only as authorized by the OpenLDAP - * Public License. - * - * A copy of this license is available in the file LICENSE in the - * top-level directory of the distribution or, alternatively, at - * <http://www.OpenLDAP.org/license.html>. - */ - -#include "test.h" - -bool testcase_deadread::setup() { - log_trace(">> setup"); - if (!inherited::setup()) - return false; - - log_trace("<< setup"); - return true; -} - -bool testcase_deadread::run() { - db_open(); - txn_begin(true); - return true; -} - -bool testcase_deadread::teardown() { - log_trace(">> teardown"); - cursor_guard.release(); - txn_guard.release(); - db_guard.release(); - return inherited::teardown(); -} - -//----------------------------------------------------------------------------- - -bool testcase_deadwrite::setup() { - log_trace(">> setup"); - if (!inherited::setup()) - return false; - - log_trace("<< setup"); - return true; -} - -bool testcase_deadwrite::run() { - db_open(); - txn_begin(false); - return true; -} - -bool testcase_deadwrite::teardown() { - log_trace(">> teardown"); - cursor_guard.release(); - txn_guard.release(); - db_guard.release(); - return inherited::teardown(); -} diff --git a/plugins/Dbx_mdbx/src/libmdbx/test/hill.cc b/plugins/Dbx_mdbx/src/libmdbx/test/hill.cc deleted file mode 100644 index c9115784d4..0000000000 --- a/plugins/Dbx_mdbx/src/libmdbx/test/hill.cc +++ /dev/null @@ -1,227 +0,0 @@ -/* - * Copyright 2017-2018 Leonid Yuriev <leo@yuriev.ru> - * and other libmdbx authors: please see AUTHORS file. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted only as authorized by the OpenLDAP - * Public License. - * - * A copy of this license is available in the file LICENSE in the - * top-level directory of the distribution or, alternatively, at - * <http://www.OpenLDAP.org/license.html>. - */ - -#include "test.h" - -bool testcase_hill::setup() { - log_trace(">> setup"); - if (!inherited::setup()) - return false; - - /* TODO */ - - log_trace("<< setup"); - return true; -} - -bool testcase_hill::run() { - db_open(); - - txn_begin(false); - MDBX_dbi dbi = db_table_open(true); - txn_end(false); - - /* LY: тест "холмиком": - * - сначала наполняем таблицу циклическими CRUD-манипуляциями, - * которые в каждом цикле делают несколько операций, включая удаление, - * но в результате добавляют записи. - * - затем очищаем таблицу также CRUD-манипуляциями, но уже с другой - * пропорцией удалений. - * - * При этом очень многое зависит от порядка перебора ключей: - * - (псевдо)случайное распределение требуется лишь для полноты картины, - * но в целом не покрывает важных кейсов. - * - кроме (псевдо)случайного перебора требуется последовательное - * итерирование ключей интервалами различной ширины, с тем чтобы - * проверить различные варианты как разделения, так и слияния страниц - * внутри движка. - * - при не-уникальных ключах (MDBX_DUPSORT с подвариантами), для каждого - * повтора внутри движка формируется вложенное btree-дерево, - * соответственно требуется соблюдение аналогичных принципов - * итерирования для значений. - */ - - /* TODO: работа в несколько потоков */ - keyvalue_maker.setup(config.params, 0 /* thread_number */); - - keygen::buffer a_key = keygen::alloc(config.params.keylen_max); - keygen::buffer a_data_0 = keygen::alloc(config.params.datalen_max); - keygen::buffer a_data_1 = keygen::alloc(config.params.datalen_max); - keygen::buffer b_key = keygen::alloc(config.params.keylen_max); - keygen::buffer b_data = keygen::alloc(config.params.datalen_max); - - const unsigned insert_flags = (config.params.table_flags & MDBX_DUPSORT) - ? MDBX_NODUPDATA - : MDBX_NODUPDATA | MDBX_NOOVERWRITE; - const unsigned update_flags = - MDBX_CURRENT | MDBX_NODUPDATA | MDBX_NOOVERWRITE; - - uint64_t serial_count = 0; - unsigned txn_nops = 0; - if (!txn_guard) - txn_begin(false); - - while (should_continue()) { - const keygen::serial_t a_serial = serial_count; - if (unlikely(!keyvalue_maker.increment(serial_count, 1))) - failure("uphill: unexpected key-space overflow"); - - const keygen::serial_t b_serial = serial_count; - assert(b_serial > a_serial); - - // создаем первую запись из пары - const keygen::serial_t age_shift = UINT64_C(1) << (a_serial % 31); - log_trace("uphill: insert-a (age %" PRIu64 ") %" PRIu64, age_shift, - a_serial); - generate_pair(a_serial, a_key, a_data_1, age_shift); - int rc = mdbx_put(txn_guard.get(), dbi, &a_key->value, &a_data_1->value, - insert_flags); - if (unlikely(rc != MDBX_SUCCESS)) - failure_perror("mdbx_put(insert-a.1)", rc); - - if (++txn_nops >= config.params.batch_write) { - txn_restart(false, false); - txn_nops = 0; - } - - // создаем вторую запись из пары - log_trace("uphill: insert-b %" PRIu64, b_serial); - generate_pair(b_serial, b_key, b_data, 0); - rc = mdbx_put(txn_guard.get(), dbi, &b_key->value, &b_data->value, - insert_flags); - if (unlikely(rc != MDBX_SUCCESS)) - failure_perror("mdbx_put(insert-b)", rc); - - if (++txn_nops >= config.params.batch_write) { - txn_restart(false, false); - txn_nops = 0; - } - - // обновляем данные в первой записи - log_trace("uphill: update-a (age %" PRIu64 "->0) %" PRIu64, age_shift, - a_serial); - generate_pair(a_serial, a_key, a_data_0, 0); - rc = mdbx_replace(txn_guard.get(), dbi, &a_key->value, &a_data_0->value, - &a_data_1->value, update_flags); - if (unlikely(rc != MDBX_SUCCESS)) - failure_perror("mdbx_put(update-a: 1->0)", rc); - - if (++txn_nops >= config.params.batch_write) { - txn_restart(false, false); - txn_nops = 0; - } - - // удаляем вторую запись - log_trace("uphill: delete-b %" PRIu64, b_serial); - rc = mdbx_del(txn_guard.get(), dbi, &b_key->value, &b_data->value); - if (unlikely(rc != MDBX_SUCCESS)) - failure_perror("mdbx_del(b)", rc); - - if (++txn_nops >= config.params.batch_write) { - txn_restart(false, false); - txn_nops = 0; - } - - report(1); - if (!keyvalue_maker.increment(serial_count, 1)) { - // дошли до границы пространства ключей - serial_count = a_serial; - goto overflow; - } - } - - while (serial_count > 0) { - if (unlikely(!keyvalue_maker.increment(serial_count, -2))) - failure("downhill: unexpected key-space underflow"); - - overflow: - const keygen::serial_t a_serial = serial_count; - const keygen::serial_t b_serial = a_serial + 1; - assert(b_serial > a_serial); - - // обновляем первую запись из пары - const keygen::serial_t age_shift = UINT64_C(1) << (a_serial % 31); - 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); - if (a_serial == 808) - log_trace("!!!"); - int rc = mdbx_replace(txn_guard.get(), dbi, &a_key->value, &a_data_1->value, - &a_data_0->value, update_flags); - if (unlikely(rc != MDBX_SUCCESS)) - failure_perror("mdbx_put(update-a: 0->1)", rc); - - if (++txn_nops >= config.params.batch_write) { - txn_restart(false, false); - txn_nops = 0; - } - - // создаем вторую запись из пары - log_trace("downhill: insert-b %" PRIu64, b_serial); - generate_pair(b_serial, b_key, b_data, 0); - rc = mdbx_put(txn_guard.get(), dbi, &b_key->value, &b_data->value, - insert_flags); - if (unlikely(rc != MDBX_SUCCESS)) - failure_perror("mdbx_put(insert-b)", rc); - - if (++txn_nops >= config.params.batch_write) { - txn_restart(false, false); - txn_nops = 0; - } - - // удаляем первую запись - log_trace("downhill: delete-a (age %" PRIu64 ") %" PRIu64, age_shift, - a_serial); - rc = mdbx_del(txn_guard.get(), dbi, &a_key->value, &a_data_1->value); - if (unlikely(rc != MDBX_SUCCESS)) - failure_perror("mdbx_del(a)", rc); - - if (++txn_nops >= config.params.batch_write) { - txn_restart(false, false); - txn_nops = 0; - } - - // удаляем вторую запись - log_trace("downhill: delete-b %" PRIu64, b_serial); - rc = mdbx_del(txn_guard.get(), dbi, &b_key->value, &b_data->value); - if (unlikely(rc != MDBX_SUCCESS)) - failure_perror("mdbx_del(b)", rc); - - if (++txn_nops >= config.params.batch_write) { - txn_restart(false, false); - txn_nops = 0; - } - - report(1); - } - - if (txn_guard) - txn_end(false); - - if (dbi) { - if (config.params.drop_table && !mode_readonly()) { - txn_begin(false); - db_table_drop(dbi); - txn_end(false); - } else - db_table_close(dbi); - } - return true; -} - -bool testcase_hill::teardown() { - log_trace(">> teardown"); - return inherited::teardown(); -} diff --git a/plugins/Dbx_mdbx/src/libmdbx/test/jitter.cc b/plugins/Dbx_mdbx/src/libmdbx/test/jitter.cc deleted file mode 100644 index e7faf2a3f9..0000000000 --- a/plugins/Dbx_mdbx/src/libmdbx/test/jitter.cc +++ /dev/null @@ -1,69 +0,0 @@ -/* - * Copyright 2017-2018 Leonid Yuriev <leo@yuriev.ru> - * and other libmdbx authors: please see AUTHORS file. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted only as authorized by the OpenLDAP - * Public License. - * - * A copy of this license is available in the file LICENSE in the - * top-level directory of the distribution or, alternatively, at - * <http://www.OpenLDAP.org/license.html>. - */ - -#include "test.h" - -bool testcase_jitter::setup() { - log_trace(">> setup"); - if (!inherited::setup()) - return false; - - log_trace("<< setup"); - return true; -} - -bool testcase_jitter::run() { - while (should_continue()) { - jitter_delay(); - db_open(); - - if (flipcoin()) { - jitter_delay(); - txn_begin(true); - fetch_canary(); - jitter_delay(); - txn_end(flipcoin()); - } - - jitter_delay(); - txn_begin(mode_readonly()); - jitter_delay(); - if (!mode_readonly()) { - fetch_canary(); - update_canary(1); - /* TODO: - * - db_setsize() - * ... - */ - } - txn_end(flipcoin()); - - if (flipcoin()) { - jitter_delay(); - txn_begin(true); - jitter_delay(); - txn_end(flipcoin()); - } - - jitter_delay(); - db_close(); - report(1); - } - return true; -} - -bool testcase_jitter::teardown() { - log_trace(">> teardown"); - return inherited::teardown(); -} diff --git a/plugins/Dbx_mdbx/src/libmdbx/test/keygen.cc b/plugins/Dbx_mdbx/src/libmdbx/test/keygen.cc deleted file mode 100644 index 99b46f2976..0000000000 --- a/plugins/Dbx_mdbx/src/libmdbx/test/keygen.cc +++ /dev/null @@ -1,238 +0,0 @@ -/* - * Copyright 2017-2018 Leonid Yuriev <leo@yuriev.ru> - * and other libmdbx authors: please see AUTHORS file. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted only as authorized by the OpenLDAP - * Public License. - * - * A copy of this license is available in the file LICENSE in the - * top-level directory of the distribution or, alternatively, at - * <http://www.OpenLDAP.org/license.html>. - */ - -#include "test.h" - -namespace keygen { - -static inline __pure_function serial_t mask(unsigned bits) { - assert(bits > 0 && bits <= serial_maxwith); - return serial_allones >> (serial_maxwith - bits); -} - -/* 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) { - assert(bits > serial_minwith && bits <= serial_maxwith); - - /* LY: All these "magic" prime numbers were found - * and verified with a bit of brute force. */ - - static const uint64_t m[64 - serial_minwith] = { - /* 8 - 24 */ - 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}; - static const uint8_t s[64 - serial_minwith] = { - /* 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}; - - serial_t result = serial * m[bits - 8]; - if (salt) { - const unsigned left = bits / 2; - const unsigned right = bits - left; - result = (result << left) | ((result & mask(bits)) >> right); - result = (result ^ salt) * m[bits - 8]; - } - - result ^= result << s[bits - 8]; - result &= mask(bits); - log_trace("keygen-injective: serial %" PRIu64 " into %" PRIu64, serial, - result); - return result; -} - -void __hot maker::pair(serial_t serial, const buffer &key, buffer &value, - serial_t value_age) { - 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 <= mask(mapping.width)); - assert(!(key_essentials.flags & (MDBX_INTEGERDUP | MDBX_REVERSEDUP))); - assert(!(value_essentials.flags & (MDBX_INTEGERKEY | MDBX_REVERSEKEY))); - - log_trace("keygen-pair: serial %" PRIu64 ", data-age %" PRIu64, serial, - value_age); - - if (mapping.mesh >= serial_minwith) { - serial = - (serial & ~mask(mapping.mesh)) | injective(serial, mapping.mesh, salt); - log_trace("keygen-pair: mesh %" PRIu64, serial); - } - - if (mapping.rotate) { - const unsigned right = mapping.rotate; - const unsigned left = mapping.width - right; - serial = (serial << left) | ((serial & mask(mapping.width)) >> right); - log_trace("keygen-pair: rotate %" PRIu64 ", 0x%" PRIx64, serial, serial); - } - - serial = (serial + mapping.offset) & mask(mapping.width); - log_trace("keygen-pair: offset %" PRIu64, serial); - serial += base; - - serial_t key_serial = serial; - serial_t value_serial = value_age; - if (mapping.split) { - key_serial = serial >> mapping.split; - value_serial = - (serial & mask(mapping.split)) | (value_age << mapping.split); - } - - log_trace("keygen-pair: key %" PRIu64 ", value %" PRIu64, key_serial, - value_serial); - - mk(key_serial, key_essentials, *key); - mk(value_serial, value_essentials, *value); - - if (log_enabled(logging::trace)) { - char dump_key[128], dump_value[128]; - log_trace("keygen-pair: key %s, value %s", - mdbx_dkey(&key->value, dump_key, sizeof(dump_key)), - mdbx_dkey(&value->value, dump_value, sizeof(dump_value))); - } -} - -void maker::setup(const config::actor_params_pod &actor, - unsigned thread_number) { - key_essentials.flags = - actor.table_flags & (MDBX_INTEGERKEY | MDBX_REVERSEKEY); - assert(actor.keylen_min < UINT8_MAX); - key_essentials.minlen = (uint8_t)actor.keylen_min; - assert(actor.keylen_max < UINT16_MAX); - key_essentials.maxlen = (uint16_t)actor.keylen_max; - - value_essentials.flags = - actor.table_flags & (MDBX_INTEGERDUP | MDBX_REVERSEDUP); - assert(actor.datalen_min < UINT8_MAX); - value_essentials.minlen = (uint8_t)actor.datalen_min; - assert(actor.datalen_max < UINT16_MAX); - value_essentials.maxlen = (uint16_t)actor.datalen_max; - - assert(thread_number < 2); - (void)thread_number; - mapping = actor.keygen; - salt = actor.keygen.seed * UINT64_C(14653293970879851569); - - // FIXME: TODO - base = 0; -} - -bool maker::increment(serial_t &serial, int delta) { - if (serial > mask(mapping.width)) { - log_extra("keygen-increment: %" PRIu64 " > %" PRIu64 ", overflow", serial, - mask(mapping.width)); - return false; - } - - serial_t target = serial + (int64_t)delta; - if (target > mask(mapping.width)) { - log_extra("keygen-increment: %" PRIu64 "%-d => %" PRIu64 ", overflow", - serial, delta, target); - return false; - } - - log_extra("keygen-increment: %" PRIu64 "%-d => %" PRIu64 ", continue", serial, - delta, target); - serial = target; - return true; -} - -//----------------------------------------------------------------------------- - -size_t length(serial_t serial) { - size_t n = 0; - if (serial > UINT32_MAX) { - n = 4; - serial >>= 32; - } - if (serial > UINT16_MAX) { - n += 2; - serial >>= 16; - } - if (serial > UINT8_MAX) { - n += 1; - serial >>= 8; - } - return (serial > 0) ? n + 1 : n; -} - -buffer alloc(size_t limit) { - result *ptr = (result *)malloc(sizeof(result) + limit); - if (unlikely(ptr == nullptr)) - failure_perror("malloc(keyvalue_buffer)", errno); - ptr->value.iov_base = ptr->bytes; - ptr->value.iov_len = 0; - ptr->limit = limit; - return buffer(ptr); -} - -void __hot maker::mk(const serial_t serial, const essentials ¶ms, - result &out) { - assert(out.limit >= params.maxlen); - assert(params.maxlen >= params.minlen); - assert(params.maxlen >= length(serial)); - - out.value.iov_base = out.bytes; - out.value.iov_len = params.minlen; - - if (params.flags & (MDBX_INTEGERKEY | MDBX_INTEGERDUP)) { - assert(params.maxlen == params.minlen); - assert(params.minlen == 4 || params.minlen == 8); - if (is_byteorder_le() || params.minlen == 8) - out.u64 = serial; - else - out.u32 = (uint32_t)serial; - } else if (params.flags & (MDBX_REVERSEKEY | MDBX_REVERSEDUP)) { - if (out.value.iov_len > 8) { - memset(out.bytes, '\0', out.value.iov_len - 8); - unaligned::store(out.bytes + out.value.iov_len - 8, htobe64(serial)); - } else { - out.u64 = htobe64(serial); - if (out.value.iov_len < 8) { - out.value.iov_len = std::max(length(serial), out.value.iov_len); - out.value.iov_base = out.bytes + 8 - out.value.iov_len; - } - } - } else { - out.u64 = htole64(serial); - if (out.value.iov_len > 8) - memset(out.bytes + 8, '\0', out.value.iov_len - 8); - else - out.value.iov_len = std::max(length(serial), 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((uint8_t *)out.value.iov_base + out.value.iov_len <= - out.bytes + out.limit); -} - -} /* namespace keygen */ diff --git a/plugins/Dbx_mdbx/src/libmdbx/test/keygen.h b/plugins/Dbx_mdbx/src/libmdbx/test/keygen.h deleted file mode 100644 index c1e907bc0b..0000000000 --- a/plugins/Dbx_mdbx/src/libmdbx/test/keygen.h +++ /dev/null @@ -1,125 +0,0 @@ -/* - * Copyright 2017-2018 Leonid Yuriev <leo@yuriev.ru> - * and other libmdbx authors: please see AUTHORS file. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted only as authorized by the OpenLDAP - * Public License. - * - * A copy of this license is available in the file LICENSE in the - * top-level directory of the distribution or, alternatively, at - * <http://www.OpenLDAP.org/license.html>. - */ - -#pragma once - -#include "base.h" -#include "config.h" -#include "log.h" -#include "utils.h" - -namespace keygen { - -/* Под "генерацией ключей" здесь понимается генерация обоих значений для - * пар key-value, т.е. не только ключей, но и ассоциированных с ними данных. - */ - -/* Генерацию ключей нельзя отнести к простым задачам, так как требования - * примерно следующие: - * - генерация разного количества уникальных ключей различной длины - * в задаваемом диапазоне; - * - возможность выбора как псевдо-случайного порядка ключей, - * так и по некоторым специфическим законам (ограниченными упорядоченными - * последовательностями, в шахматном порядке по граница диапазона и т.д.); - * - возможность генерации дубликатов с задаваемым законом распределения; - * - возможность генерации непересекающимися кластерами для параллельного - * использования в нескольких потоках; - * - использовать минимум ресурсов, как CPU, так и RAM, в том числе - * включая cache pollution и ram bandwidth. - * - * При этом заведомо известно, что для MDBX не имеет значения: - * - используемый алфавит (значения байтов); - * - частотное распределение по алфавиту; - * - абсолютное значение ключей или разность между отдельными значениями; - * - * Соответственно, в общих чертах, схема генерации следующая: - * - вводится плоская одномерная "координата" uint64_t; - * - генерация специфических паттернов (последовательностей) - * реализуется посредством соответствующих преобразований "координат", при - * этом все подобные преобразования выполняются только над "координатой"; - * - итоговая "координата" преобразуется в 8-байтное суррогатное значение - * ключа; - * - для получения ключей длиной МЕНЕЕ 8 байт суррогат может усекаться - * до ненулевых байт, в том числе до нулевой длины; - * - для получения ключей длиной БОЛЕЕ 8 байт суррогат дополняется - * нулями или псевдослучайной последовательностью; - * - * Механизм генерации паттернов: - * - реализованный механизм является компромиссом между скоростью/простотой - * и гибкостью, необходимой для получения последовательностей, которых - * будет достаточно для проверки сценариев разделения и слияния страниц - * с данными внутри mdbx; - * - псевдо-случайные паттерны реализуются посредством набора инъективных - * отображающих функций; - * - не-псевдо-случайные паттерны реализуются посредством параметризируемого - * трех-этапного преобразования: - * 1) смещение (сложение) по модулю; - * 2) циклический сдвиг; - * 3) добавление абсолютного смещения (базы); - */ - -typedef uint64_t serial_t; - -enum : serial_t { - serial_minwith = 8, - serial_maxwith = sizeof(serial_t) * 8, - serial_allones = ~(serial_t)0 -}; - -struct result { - MDBX_val value; - size_t limit; - union { - uint8_t bytes[sizeof(uint64_t)]; - uint32_t u32; - uint64_t u64; - }; -}; - -//----------------------------------------------------------------------------- - -struct buffer_deleter : public std::unary_function<void, result *> { - void operator()(result *buffer) const { free(buffer); } -}; - -typedef std::unique_ptr<result, buffer_deleter> buffer; - -buffer alloc(size_t limit); - -class maker { - config::keygen_params_pod mapping; - serial_t base; - serial_t salt; - - struct essentials { - uint8_t minlen; - uint8_t flags; - uint16_t maxlen; - } key_essentials, value_essentials; - - static void mk(const serial_t serial, const essentials ¶ms, result &out); - -public: - maker() { memset(this, 0, sizeof(*this)); } - - void pair(serial_t serial, const buffer &key, buffer &value, - serial_t value_age); - void setup(const config::actor_params_pod &actor, unsigned thread_number); - - bool increment(serial_t &serial, int delta); -}; - -size_t length(serial_t serial); - -} /* namespace keygen */ diff --git a/plugins/Dbx_mdbx/src/libmdbx/test/log.cc b/plugins/Dbx_mdbx/src/libmdbx/test/log.cc deleted file mode 100644 index 521e1d6900..0000000000 --- a/plugins/Dbx_mdbx/src/libmdbx/test/log.cc +++ /dev/null @@ -1,289 +0,0 @@ -/* - * Copyright 2017-2018 Leonid Yuriev <leo@yuriev.ru> - * and other libmdbx authors: please see AUTHORS file. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted only as authorized by the OpenLDAP - * Public License. - * - * A copy of this license is available in the file LICENSE in the - * top-level directory of the distribution or, alternatively, at - * <http://www.OpenLDAP.org/license.html>. - */ - -#include "test.h" - -static void fflushall() { fflush(nullptr); } - -void failure(const char *fmt, ...) { - va_list ap; - va_start(ap, fmt); - fflushall(); - logging::output(logging::failure, fmt, ap); - va_end(ap); - fflushall(); - exit(EXIT_FAILURE); -} - -const char *test_strerror(int errnum) { - static __thread char buf[1024]; - return mdbx_strerror_r(errnum, buf, sizeof(buf)); -} - -void __noreturn failure_perror(const char *what, int errnum) { - failure("%s failed: %s (%d)\n", what, test_strerror(errnum), errnum); -} - -//----------------------------------------------------------------------------- - -namespace logging { - -static std::string prefix; -static std::string suffix; -static loglevel level; -static FILE *last; - -void setup(loglevel _level, const std::string &_prefix) { - level = (_level > error) ? failure : _level; - prefix = _prefix; -} - -void setup(const std::string &_prefix) { prefix = _prefix; } - -const char *level2str(const loglevel alevel) { - switch (alevel) { - default: - return "invalid/unknown"; - case extra: - return "extra"; - case trace: - return "trace"; - case verbose: - return "verbose"; - case info: - return "info"; - case notice: - return "notice"; - case warning: - return "warning"; - case error: - return "error"; - case failure: - return "failure"; - } -} - -bool output(const loglevel priority, const char *format, ...) { - if (priority < level) - return false; - - va_list ap; - va_start(ap, format); - output(priority, format, ap); - va_end(ap); - return true; -} - -bool output(const logging::loglevel priority, const char *format, va_list ap) { - if (last) { - putc('\n', last); - fflush(last); - last = nullptr; - } - - if (priority < level) - return false; - - chrono::time now = chrono::now_realtime(); - struct tm tm; -#ifdef _MSC_VER - int rc = _localtime32_s(&tm, (const __time32_t *)&now.utc); -#else - time_t time = now.utc; - int rc = localtime_r(&time, &tm) ? MDBX_SUCCESS : errno; -#endif - if (rc != MDBX_SUCCESS) - failure_perror("localtime_r()", rc); - - last = stdout; - fprintf(last, - "[ %02d%02d%02d-%02d:%02d:%02d.%06d_%05u %-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), osal_getpid(), - prefix.c_str(), level2str(priority), suffix.c_str()); - - va_list ones; - memset(&ones, 0, sizeof(ones)) /* zap MSVC and other stupid compilers */; - if (priority >= error) - va_copy(ones, ap); - vfprintf(last, format, ap); - - size_t len = strlen(format); - char end = len ? format[len - 1] : '\0'; - - switch (end) { - default: - putc('\n', last); - // fall through - case '\n': - fflush(last); - last = nullptr; - // fall through - case ' ': - case '_': - case ':': - case '|': - case ',': - case '\t': - case '\b': - case '\r': - case '\0': - break; - } - - if (priority >= error) { - if (last != stderr) { - fprintf(stderr, "[ %05u %-10s %.4s ] %s", osal_getpid(), prefix.c_str(), - level2str(priority), suffix.c_str()); - vfprintf(stderr, format, ones); - if (end != '\n') - putc('\n', stderr); - fflush(stderr); - } - va_end(ones); - } - - return true; -} - -bool feed(const char *format, va_list ap) { - if (!last) - return false; - - vfprintf(last, format, ap); - size_t len = strlen(format); - if (len && format[len - 1] == '\n') { - fflush(last); - last = nullptr; - } - return true; -} - -bool feed(const char *format, ...) { - if (!last) - return false; - - va_list ap; - va_start(ap, format); - feed(format, ap); - va_end(ap); - return true; -} - -local_suffix::local_suffix(const char *c_str) - : trim_pos(suffix.size()), indent(0) { - suffix.append(c_str); -} - -local_suffix::local_suffix(const std::string &str) - : trim_pos(suffix.size()), indent(0) { - suffix.append(str); -} - -void local_suffix::push() { - indent += 1; - suffix.push_back('\t'); -} - -void local_suffix::pop() { - assert(indent > 0); - if (indent > 0) { - indent -= 1; - suffix.pop_back(); - } -} - -local_suffix::~local_suffix() { suffix.erase(trim_pos); } - -} // namespace logging - -void log_extra(const char *msg, ...) { - if (logging::extra >= logging::level) { - va_list ap; - va_start(ap, msg); - logging::output(logging::extra, msg, ap); - va_end(ap); - } else - logging::last = nullptr; -} - -void log_trace(const char *msg, ...) { - if (logging::trace >= logging::level) { - va_list ap; - va_start(ap, msg); - logging::output(logging::trace, msg, ap); - va_end(ap); - } else - logging::last = nullptr; -} - -void log_verbose(const char *msg, ...) { - if (logging::verbose >= logging::level) { - va_list ap; - va_start(ap, msg); - logging::output(logging::verbose, msg, ap); - va_end(ap); - } else - logging::last = nullptr; -} - -void log_info(const char *msg, ...) { - if (logging::info >= logging::level) { - va_list ap; - va_start(ap, msg); - logging::output(logging::info, msg, ap); - va_end(ap); - } else - logging::last = nullptr; -} - -void log_notice(const char *msg, ...) { - if (logging::notice >= logging::level) { - va_list ap; - va_start(ap, msg); - logging::output(logging::notice, msg, ap); - va_end(ap); - } else - logging::last = nullptr; -} - -void log_warning(const char *msg, ...) { - if (logging::warning >= logging::level) { - va_list ap; - va_start(ap, msg); - logging::output(logging::warning, msg, ap); - va_end(ap); - } else - logging::last = nullptr; -} - -void log_error(const char *msg, ...) { - if (logging::error >= logging::level) { - va_list ap; - va_start(ap, msg); - logging::output(logging::error, msg, ap); - va_end(ap); - } else - logging::last = nullptr; -} - -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 (priority >= logging::level); -} - -void log_flush(void) { fflushall(); } diff --git a/plugins/Dbx_mdbx/src/libmdbx/test/log.h b/plugins/Dbx_mdbx/src/libmdbx/test/log.h deleted file mode 100644 index e97e954cea..0000000000 --- a/plugins/Dbx_mdbx/src/libmdbx/test/log.h +++ /dev/null @@ -1,91 +0,0 @@ -/* - * Copyright 2017-2018 Leonid Yuriev <leo@yuriev.ru> - * and other libmdbx authors: please see AUTHORS file. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted only as authorized by the OpenLDAP - * Public License. - * - * A copy of this license is available in the file LICENSE in the - * top-level directory of the distribution or, alternatively, at - * <http://www.OpenLDAP.org/license.html>. - */ - -#pragma once - -#include "base.h" - -void __noreturn usage(void); - -#ifdef __GNUC__ -#define __printf_args(format_index, first_arg) \ - __attribute__((format(printf, format_index, first_arg))) -#else -#define __printf_args(format_index, first_arg) -#endif - -void __noreturn __printf_args(1, 2) failure(const char *fmt, ...); - -void __noreturn failure_perror(const char *what, int errnum); -const char *test_strerror(int errnum); - -namespace logging { - -enum loglevel { - extra, - trace, - verbose, - info, - notice, - warning, - error, - failure, -}; - -const char *level2str(const loglevel level); -void setup(loglevel level, const std::string &prefix); -void setup(const std::string &prefix); - -bool output(const loglevel priority, const char *format, va_list ap); -bool __printf_args(2, 3) - output(const loglevel priority, const char *format, ...); -bool feed(const char *format, va_list ap); -bool __printf_args(1, 2) feed(const char *format, ...); - -class local_suffix { -protected: - size_t trim_pos; - int indent; - -public: - local_suffix(const local_suffix &) = delete; - local_suffix(const local_suffix &&) = delete; - const local_suffix &operator=(const local_suffix &) = delete; - - local_suffix(const char *c_str); - local_suffix(const std::string &str); - void push(); - void pop(); - ~local_suffix(); -}; - -} // namespace logging - -void __printf_args(1, 2) log_extra(const char *msg, ...); -void __printf_args(1, 2) log_trace(const char *msg, ...); -void __printf_args(1, 2) log_verbose(const char *msg, ...); -void __printf_args(1, 2) log_info(const char *msg, ...); -void __printf_args(1, 2) log_notice(const char *msg, ...); -void __printf_args(1, 2) log_warning(const char *msg, ...); -void __printf_args(1, 2) log_error(const char *msg, ...); - -void log_trouble(const char *where, const char *what, int errnum); -void log_flush(void); -bool log_enabled(const logging::loglevel priority); - -#ifdef _DEBUG -#define TRACE(...) log_trace(__VA_ARGS__) -#else -#define TRACE(...) __noop(__VA_ARGS__) -#endif diff --git a/plugins/Dbx_mdbx/src/libmdbx/test/main.cc b/plugins/Dbx_mdbx/src/libmdbx/test/main.cc deleted file mode 100644 index bc3198ed3a..0000000000 --- a/plugins/Dbx_mdbx/src/libmdbx/test/main.cc +++ /dev/null @@ -1,395 +0,0 @@ -/* - * Copyright 2017-2018 Leonid Yuriev <leo@yuriev.ru> - * and other libmdbx authors: please see AUTHORS file. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted only as authorized by the OpenLDAP - * Public License. - * - * A copy of this license is available in the file LICENSE in the - * top-level directory of the distribution or, alternatively, at - * <http://www.OpenLDAP.org/license.html>. - */ - -#include "test.h" - -void __noreturn usage(void) { - printf("usage:\n" - "\tFIXME\n"); - exit(EXIT_FAILURE); -} - -//----------------------------------------------------------------------------- - -void actor_params::set_defaults(const std::string &tmpdir) { - pathname_log = ""; - loglevel = -#ifdef NDEBUG - logging::info; -#else - logging::trace; -#endif - - pathname_db = tmpdir + "mdbx-test.db"; - mode_flags = MDBX_NOSUBDIR | MDBX_WRITEMAP | MDBX_MAPASYNC | MDBX_NORDAHEAD | - MDBX_NOMEMINIT | MDBX_COALESCE | MDBX_LIFORECLAIM; - table_flags = MDBX_DUPSORT; - size = 1024 * 1024 * 4; - - keygen.seed = 1; - keygen.keycase = kc_random; - keygen.width = 32; - keygen.mesh = 32; - keygen.split = keygen.width / 2; - keygen.rotate = 0; - keygen.offset = 0; - - test_duration = 0; - test_nops = 1000; - nrepeat = 1; - nthreads = 1; - - keylen_min = 0; - keylen_max = 42; - datalen_min = 0; - datalen_max = 256; - - batch_read = 4; - batch_write = 4; - - delaystart = 0; - waitfor_nops = 0; - inject_writefaultn = 0; - - drop_table = false; - - max_readers = 42; - max_tables = 42; - - global::config::timeout_duration_seconds = 0 /* infinite */; - global::config::dump_config = true; - global::config::cleanup_before = true; - global::config::cleanup_after = true; - global::config::failfast = true; - global::config::progress_indicator = osal_istty(STDERR_FILENO); -} - -namespace global { - -std::vector<actor_config> actors; -std::unordered_map<unsigned, actor_config *> events; -std::unordered_map<mdbx_pid_t, actor_config *> pid2actor; -std::set<std::string> databases; -unsigned nactors; -chrono::time start_motonic; -chrono::time deadline_motonic; -bool singlemode; - -namespace config { -unsigned timeout_duration_seconds; -bool dump_config; -bool cleanup_before; -bool cleanup_after; -bool failfast; -bool progress_indicator; -} /* namespace config */ - -} /* namespace global */ - -//----------------------------------------------------------------------------- - -const char global::thunk_param_prefix[] = "--execute="; - -std::string thunk_param(const actor_config &config) { - return config.serialize(global::thunk_param_prefix); -} - -void cleanup() { - log_trace(">> cleanup"); - /* TODO: remove each database */ - log_trace("<< cleanup"); -} - -int main(int argc, char *const argv[]) { - -#ifdef _DEBUG - log_trace("#argc = %d", argc); - for (int i = 0; i < argc; ++i) - log_trace("#argv[%d] = %s", i, argv[i]); -#endif /* _DEBUG */ - - if (argc < 2) - failure("No parameters given\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; - - actor_params params; - params.set_defaults(osal_tempdir()); - global::config::dump_config = true; - logging::setup((logging::loglevel)params.loglevel, "main"); - unsigned last_space_id = 0; - - for (int narg = 1; narg < argc; ++narg) { - const char *value = nullptr; - - if (config::parse_option(argc, argv, narg, "case", &value)) { - testcase_setup(value, params, last_space_id); - continue; - } - 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)) - continue; - if (config::parse_option(argc, argv, narg, "table", params.table_flags, - config::table_bits)) - continue; - if (config::parse_option(argc, argv, narg, "size", params.size, - config::binary, 4096 * 4)) - continue; - - if (config::parse_option(argc, argv, narg, "keygen.width", - params.keygen.width, 1, 64)) - continue; - if (config::parse_option(argc, argv, narg, "keygen.mesh", - params.keygen.mesh, 1, 64)) - continue; - if (config::parse_option(argc, argv, narg, "keygen.seed", - params.keygen.seed, config::no_scale)) - continue; - if (config::parse_option(argc, argv, narg, "keygen.split", - params.keygen.split, 1, 64)) - continue; - if (config::parse_option(argc, argv, narg, "keygen.rotate", - params.keygen.rotate, 1, 64)) - continue; - 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, "repeat", params.nrepeat, - config::no_scale)) - continue; - if (config::parse_option(argc, argv, narg, "threads", params.nthreads, - config::no_scale, 1, 64)) - continue; - if (config::parse_option(argc, argv, narg, "timeout", - global::config::timeout_duration_seconds, - config::duration, 1)) - continue; - if (config::parse_option(argc, argv, narg, "keylen.min", params.keylen_min, - config::no_scale, 0, params.keylen_max)) - continue; - if (config::parse_option(argc, argv, narg, "keylen.max", params.keylen_max, - config::no_scale, params.keylen_min, - mdbx_get_maxkeysize(0))) - continue; - if (config::parse_option(argc, argv, narg, "datalen.min", - params.datalen_min, config::no_scale, 0, - params.datalen_max)) - continue; - if (config::parse_option(argc, argv, narg, "datalen.max", - params.datalen_max, config::no_scale, - params.datalen_min, MDBX_MAXDATASIZE)) - continue; - 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)) - continue; - 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)) - continue; - 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, "dump-config", - global::config::dump_config)) - continue; - 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)) - continue; - 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)) - continue; - - if (config::parse_option(argc, argv, narg, "no-delay", nullptr)) { - params.delaystart = 0; - continue; - } - if (config::parse_option(argc, argv, narg, "no-wait", nullptr)) { - params.waitfor_nops = 0; - continue; - } - 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)) { - params.test_duration = 0; - continue; - } - if (config::parse_option(argc, argv, narg, "hill", &value, "auto")) { - configure_actor(last_space_id, ac_hill, value, params); - continue; - } - if (config::parse_option(argc, argv, narg, "jitter", nullptr)) { - configure_actor(last_space_id, ac_jitter, value, params); - continue; - } - if (config::parse_option(argc, argv, narg, "dead.reader", nullptr)) { - configure_actor(last_space_id, ac_deadread, value, params); - continue; - } - if (config::parse_option(argc, argv, narg, "dead.writer", nullptr)) { - configure_actor(last_space_id, ac_deadwrite, value, params); - continue; - } - if (config::parse_option(argc, argv, narg, "failfast", - global::config::failfast)) - continue; - if (config::parse_option(argc, argv, narg, "progress", - global::config::progress_indicator)) - continue; - - if (*argv[narg] != '-') - testcase_setup(argv[narg], params, last_space_id); - else - failure("Unknown option '%s'\n", argv[narg]); - } - - if (global::config::dump_config) - config::dump(); - - //-------------------------------------------------------------------------- - - if (global::actors.empty()) { - log_notice("no testcase(s) configured, exiting"); - return EXIT_SUCCESS; - } - - bool failed = false; - global::start_motonic = chrono::now_motonic(); - global::deadline_motonic.fixedpoint = - (global::config::timeout_duration_seconds == 0) - ? chrono::infinite().fixedpoint - : global::start_motonic.fixedpoint + - chrono::from_seconds(global::config::timeout_duration_seconds) - .fixedpoint; - - if (global::config::cleanup_before) - cleanup(); - - if (global::actors.size() == 1) { - logging::setup("main"); - global::singlemode = true; - if (!test_execute(global::actors.front())) - failed = true; - } else { - logging::setup("overlord"); - - log_trace("=== preparing..."); - log_trace(">> osal_setup"); - osal_setup(global::actors); - log_trace("<< osal_setup"); - - for (auto &a : global::actors) { - mdbx_pid_t pid; - log_trace(">> actor_start"); - int rc = osal_actor_start(a, pid); - log_trace("<< actor_start"); - if (rc) { - 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)); - } - global::pid2actor[pid] = &a; - } - - log_trace("=== ready to start..."); - atexit(osal_killall_actors); - log_trace(">> wait4barrier"); - osal_wait4barrier(); - log_trace("<< wait4barrier"); - - size_t left = global::actors.size(); - log_trace("=== polling..."); - while (left > 0) { - unsigned timeout_seconds_left = INT_MAX; - chrono::time now_motonic = chrono::now_motonic(); - if (now_motonic.fixedpoint >= global::deadline_motonic.fixedpoint) - timeout_seconds_left = 0; - else { - chrono::time left_motonic; - left_motonic.fixedpoint = - global::deadline_motonic.fixedpoint - now_motonic.fixedpoint; - timeout_seconds_left = left_motonic.seconds(); - } - - mdbx_pid_t pid; - int rc = osal_actor_poll(pid, timeout_seconds_left); - if (rc) - failure("Poll error: %s (%d)\n", test_strerror(rc), rc); - - if (pid) { - actor_status status = osal_actor_info(pid); - actor_config *actor = global::pid2actor.at(pid); - if (!actor) - continue; - - log_info("actor #%u, id %d, pid %u: %s\n", actor->actor_id, - actor->space_id, pid, status2str(status)); - if (status > as_running) { - left -= 1; - if (status != as_successful) { - if (global::config::failfast && !failed) { - log_trace(">> killall_actors: (%s)", "failfast"); - osal_killall_actors(); - log_trace("<< killall_actors"); - } - failed = true; - } - } - } else { - if (timeout_seconds_left == 0) - failure("Timeout\n"); - } - } - log_trace("=== done..."); - } - - log_notice("RESULT: %s\n", failed ? "Failed" : "Successful"); - if (global::config::cleanup_before) { - if (failed) - log_info("skip cleanup"); - else - cleanup(); - } - return failed ? EXIT_FAILURE : EXIT_SUCCESS; -} diff --git a/plugins/Dbx_mdbx/src/libmdbx/test/osal-unix.cc b/plugins/Dbx_mdbx/src/libmdbx/test/osal-unix.cc deleted file mode 100644 index 8132e267ef..0000000000 --- a/plugins/Dbx_mdbx/src/libmdbx/test/osal-unix.cc +++ /dev/null @@ -1,293 +0,0 @@ -/* - * Copyright 2017-2018 Leonid Yuriev <leo@yuriev.ru> - * and other libmdbx authors: please see AUTHORS file. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted only as authorized by the OpenLDAP - * Public License. - * - * A copy of this license is available in the file LICENSE in the - * top-level directory of the distribution or, alternatively, at - * <http://www.OpenLDAP.org/license.html>. - */ - -#include "test.h" - -#include <pthread.h> -#include <signal.h> -#include <sys/mman.h> -#include <sys/types.h> -#include <sys/wait.h> -#include <unistd.h> - -struct shared_t { - pthread_barrier_t barrier; - pthread_mutex_t mutex; - size_t conds_size; - pthread_cond_t conds[1]; -}; - -static shared_t *shared; - -void osal_wait4barrier(void) { - assert(shared != nullptr && shared != MAP_FAILED); - int rc = pthread_barrier_wait(&shared->barrier); - if (rc != 0 && rc != PTHREAD_BARRIER_SERIAL_THREAD) { - failure_perror("pthread_barrier_wait(shared)", rc); - } -} - -void osal_setup(const std::vector<actor_config> &actors) { - assert(shared == nullptr); - - pthread_mutexattr_t mutexattr; - int rc = pthread_mutexattr_init(&mutexattr); - if (rc) - failure_perror("pthread_mutexattr_init()", rc); - rc = pthread_mutexattr_setpshared(&mutexattr, PTHREAD_PROCESS_SHARED); - if (rc) - failure_perror("pthread_mutexattr_setpshared()", rc); - - pthread_barrierattr_t barrierattr; - rc = pthread_barrierattr_init(&barrierattr); - if (rc) - failure_perror("pthread_barrierattr_init()", rc); - rc = pthread_barrierattr_setpshared(&barrierattr, PTHREAD_PROCESS_SHARED); - if (rc) - failure_perror("pthread_barrierattr_setpshared()", rc); - - pthread_condattr_t condattr; - rc = pthread_condattr_init(&condattr); - if (rc) - failure_perror("pthread_condattr_init()", rc); - rc = pthread_condattr_setpshared(&condattr, PTHREAD_PROCESS_SHARED); - if (rc) - failure_perror("pthread_condattr_setpshared()", rc); - - shared = (shared_t *)mmap( - nullptr, sizeof(shared_t) + actors.size() * sizeof(pthread_cond_t), - PROT_READ | PROT_WRITE, MAP_SHARED | MAP_ANONYMOUS, -1, 0); - if (MAP_FAILED == (void *)shared) - failure_perror("mmap(shared_conds)", errno); - - rc = pthread_mutex_init(&shared->mutex, &mutexattr); - if (rc) - failure_perror("pthread_mutex_init(shared)", rc); - - rc = pthread_barrier_init(&shared->barrier, &barrierattr, actors.size() + 1); - if (rc) - failure_perror("pthread_barrier_init(shared)", rc); - - const size_t n = actors.size() + 1; - for (size_t i = 0; i < n; ++i) { - pthread_cond_t *event = &shared->conds[i]; - rc = pthread_cond_init(event, &condattr); - if (rc) - failure_perror("pthread_cond_init(shared)", rc); - log_trace("osal_setup: event(shared pthread_cond) %" PRIuPTR " -> %p", i, - event); - } - shared->conds_size = actors.size() + 1; - - pthread_barrierattr_destroy(&barrierattr); - pthread_condattr_destroy(&condattr); - pthread_mutexattr_destroy(&mutexattr); -} - -void osal_broadcast(unsigned id) { - assert(shared != nullptr && shared != MAP_FAILED); - log_trace("osal_broadcast: event %u", id); - if (id >= shared->conds_size) - failure("osal_broadcast: id > limit"); - int rc = pthread_cond_broadcast(shared->conds + id); - if (rc) - failure_perror("sem_post(shared)", rc); -} - -int osal_waitfor(unsigned id) { - assert(shared != nullptr && shared != MAP_FAILED); - - log_trace("osal_waitfor: event %u", id); - if (id >= shared->conds_size) - failure("osal_waitfor: id > limit"); - - int rc = pthread_mutex_lock(&shared->mutex); - if (rc != 0) - failure_perror("pthread_mutex_lock(shared)", rc); - - rc = pthread_cond_wait(shared->conds + id, &shared->mutex); - if (rc && rc != EINTR) - failure_perror("pthread_cond_wait(shared)", rc); - - rc = pthread_mutex_unlock(&shared->mutex); - if (rc != 0) - failure_perror("pthread_mutex_unlock(shared)", rc); - - return (rc == 0) ? true : false; -} - -//----------------------------------------------------------------------------- - -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) { - (void)checksum; - /* not used in workload, but just for testing */ - return strncmp(str, "unix.fork", 9) == 0 && str + 9 == end; -} - -//----------------------------------------------------------------------------- - -static std::unordered_map<pid_t, actor_status> childs; - -static void handler_SIGCHLD(int unused) { (void)unused; } - -mdbx_pid_t osal_getpid(void) { return getpid(); } - -int osal_delay(unsigned seconds) { return sleep(seconds) ? errno : 0; } - -int osal_actor_start(const actor_config &config, mdbx_pid_t &pid) { - if (childs.empty()) - signal(SIGCHLD, handler_SIGCHLD); - - pid = fork(); - - if (pid == 0) { - const bool result = test_execute(config); - exit(result ? EXIT_SUCCESS : EXIT_FAILURE); - } - - if (pid < 0) - return errno; - - log_trace("osal_actor_start: fork pid %i for %u", pid, config.actor_id); - childs[pid] = as_running; - return 0; -} - -actor_status osal_actor_info(const mdbx_pid_t pid) { return childs.at(pid); } - -void osal_killall_actors(void) { - for (auto &pair : childs) { - kill(pair.first, SIGKILL); - pair.second = as_killed; - } -} - -int osal_actor_poll(mdbx_pid_t &pid, unsigned timeout) { -retry: - int status, options = WNOHANG; -#ifdef WUNTRACED - options |= WUNTRACED; -#endif -#ifdef WCONTINUED - options |= WCONTINUED; -#endif - pid = waitpid(0, &status, options); - - if (pid > 0) { - if (WIFEXITED(status)) - childs[pid] = - (WEXITSTATUS(status) == EXIT_SUCCESS) ? as_successful : as_failed; - else if (WIFSIGNALED(status) || WCOREDUMP(status)) - childs[pid] = as_killed; - else if (WIFSTOPPED(status)) - childs[pid] = as_debuging; - else if (WIFCONTINUED(status)) - childs[pid] = as_running; - else { - assert(false); - } - return 0; - } - - if (pid == 0) { - if (timeout && sleep(timeout)) - goto retry; - return 0; - } - - switch (errno) { - case EINTR: - pid = 0; - return 0; - - case ECHILD: - default: - pid = 0; - return errno; - } -} - -void osal_yield(void) { - if (sched_yield()) - failure_perror("sched_yield()", errno); -} - -void osal_udelay(unsigned us) { - chrono::time until, now = chrono::now_motonic(); - until.fixedpoint = now.fixedpoint + chrono::from_us(us).fixedpoint; - struct timespec ts; - - static unsigned threshold_us; - if (threshold_us == 0) { - if (clock_getres(CLOCK_PROCESS_CPUTIME_ID, &ts)) { - int rc = errno; - failure_perror("clock_getres(CLOCK_PROCESS_CPUTIME_ID)", rc); - } - chrono::time threshold = chrono::from_timespec(ts); - assert(threshold.seconds() == 0); - - threshold_us = chrono::fractional2us(threshold.fractional); - if (threshold_us < 1000) - threshold_us = 1000; - } - - ts.tv_sec = ts.tv_nsec = 0; - if (us > threshold_us) { - ts.tv_sec = us / 1000000u; - ts.tv_nsec = (us % 1000000u) * 1000u; - } - - do { - if (us > threshold_us) { - if (nanosleep(&ts, &ts)) { - int rc = errno; - /* if (rc == EINTR) { ... } ? */ - failure_perror("usleep()", rc); - } - us = ts.tv_sec * 1000000u + ts.tv_nsec / 1000u; - } - cpu_relax(); - - now = chrono::now_motonic(); - } while (until.fixedpoint > now.fixedpoint); -} - -bool osal_istty(int fd) { return isatty(fd) == 1; } - -std::string osal_tempdir(void) { - const char *tempdir = getenv("TMPDIR"); - if (!tempdir) - tempdir = getenv("TMP"); - if (!tempdir) - tempdir = getenv("TEMPDIR"); - if (!tempdir) - tempdir = getenv("TEMP"); - if (tempdir) { - std::string dir(tempdir); - if (!dir.empty() && dir.at(dir.length() - 1) != '/') - dir.append("/"); - return dir; - } - if (access("/dev/shm/", R_OK | W_OK | X_OK) == 0) - return "/dev/shm/"; - return ""; -} diff --git a/plugins/Dbx_mdbx/src/libmdbx/test/osal-windows.cc b/plugins/Dbx_mdbx/src/libmdbx/test/osal-windows.cc deleted file mode 100644 index 109c835a96..0000000000 --- a/plugins/Dbx_mdbx/src/libmdbx/test/osal-windows.cc +++ /dev/null @@ -1,398 +0,0 @@ -/* - * Copyright 2017-2018 Leonid Yuriev <leo@yuriev.ru> - * and other libmdbx authors: please see AUTHORS file. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted only as authorized by the OpenLDAP - * Public License. - * - * A copy of this license is available in the file LICENSE in the - * top-level directory of the distribution or, alternatively, at - * <http://www.OpenLDAP.org/license.html>. - */ - -#include "test.h" - -static std::unordered_map<unsigned, HANDLE> events; -static HANDLE hBarrierSemaphore, hBarrierEvent; - -static int waitstatus2errcode(DWORD result) { - switch (result) { - case WAIT_OBJECT_0: - return MDBX_SUCCESS; - case WAIT_FAILED: - return GetLastError(); - case WAIT_ABANDONED: - return ERROR_ABANDONED_WAIT_0; - case WAIT_IO_COMPLETION: - return ERROR_USER_APC; - case WAIT_TIMEOUT: - return ERROR_TIMEOUT; - default: - return ERROR_UNHANDLED_ERROR; - } -} - -void osal_wait4barrier(void) { - DWORD rc = WaitForSingleObject(hBarrierSemaphore, 0); - switch (rc) { - default: - 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)); - break; - case WAIT_TIMEOUT: - if (!SetEvent(hBarrierEvent)) - failure_perror("SetEvent(BarrierEvent)", GetLastError()); - break; - } -} - -static HANDLE make_inharitable(HANDLE hHandle) { - assert(hHandle != NULL && hHandle != INVALID_HANDLE_VALUE); - if (!DuplicateHandle(GetCurrentProcess(), hHandle, GetCurrentProcess(), - &hHandle, 0, TRUE, - DUPLICATE_CLOSE_SOURCE | DUPLICATE_SAME_ACCESS)) - failure_perror("DuplicateHandle()", GetLastError()); - return hHandle; -} - -void osal_setup(const std::vector<actor_config> &actors) { - assert(events.empty()); - const size_t n = actors.size() + 1; - events.reserve(n); - - for (unsigned i = 0; i < n; ++i) { - HANDLE hEvent = CreateEvent(NULL, TRUE, FALSE, NULL); - if (!hEvent) - failure_perror("CreateEvent()", GetLastError()); - hEvent = make_inharitable(hEvent); - log_trace("osal_setup: event %" PRIuPTR " -> %p", i, hEvent); - events[i] = hEvent; - } - - hBarrierSemaphore = CreateSemaphore(NULL, 0, (LONG)actors.size(), NULL); - if (!hBarrierSemaphore) - failure_perror("CreateSemaphore(BarrierSemaphore)", GetLastError()); - hBarrierSemaphore = make_inharitable(hBarrierSemaphore); - - hBarrierEvent = CreateEvent(NULL, TRUE, FALSE, NULL); - if (!hBarrierEvent) - failure_perror("CreateEvent(BarrierEvent)", GetLastError()); - hBarrierEvent = make_inharitable(hBarrierEvent); -} - -void osal_broadcast(unsigned id) { - log_trace("osal_broadcast: event %u", id); - if (!SetEvent(events.at(id))) - failure_perror("SetEvent()", GetLastError()); -} - -int osal_waitfor(unsigned id) { - log_trace("osal_waitfor: event %u", id); - DWORD rc = WaitForSingleObject(events.at(id), INFINITE); - return waitstatus2errcode(rc); -} - -mdbx_pid_t osal_getpid(void) { return GetCurrentProcessId(); } - -int osal_delay(unsigned seconds) { - Sleep(seconds * 1000u); - return 0; -} - -//----------------------------------------------------------------------------- - -const std::string -actor_config::osal_serialize(simple_checksum &checksum) const { - checksum.push(hBarrierSemaphore); - checksum.push(hBarrierEvent); - - HANDLE hWait = INVALID_HANDLE_VALUE; - if (wait4id) { - hWait = events.at(wait4id); - checksum.push(hWait); - } - - HANDLE hSignal = INVALID_HANDLE_VALUE; - if (wanna_event4signalling()) { - hSignal = events.at(actor_id); - checksum.push(hSignal); - } - - return format("%p.%p.%p.%p", hBarrierSemaphore, hBarrierEvent, hWait, - hSignal); -} - -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()); - - assert(hBarrierSemaphore == 0); - assert(hBarrierEvent == 0); - assert(events.empty()); - - HANDLE hWait, hSignal; - if (sscanf_s(copy.c_str(), "%p.%p.%p.%p", &hBarrierSemaphore, &hBarrierEvent, - &hWait, &hSignal) != 4) { - TRACE("<< osal_deserialize: failed\n"); - return false; - } - - checksum.push(hBarrierSemaphore); - checksum.push(hBarrierEvent); - - if (wait4id) { - checksum.push(hWait); - events[wait4id] = hWait; - } - - if (wanna_event4signalling()) { - checksum.push(hSignal); - events[actor_id] = hSignal; - } - - TRACE("<< osal_deserialize: OK\n"); - return true; -} - -//----------------------------------------------------------------------------- - -typedef std::pair<HANDLE, actor_status> child; -static std::unordered_map<mdbx_pid_t, child> childs; - -static void ArgvQuote(std::string &CommandLine, const std::string &Argument, - bool Force = false) - -/*++ - -https://blogs.msdn.microsoft.com/twistylittlepassagesallalike/2011/04/23/everyone-quotes-command-line-arguments-the-wrong-way/ - -Routine Description: - - This routine appends the given argument to a command line such - that CommandLineToArgvW will return the argument string unchanged. - Arguments in a command line should be separated by spaces; this - function does not add these spaces. - -Arguments: - - Argument - Supplies the argument to encode. - - CommandLine - Supplies the command line to which we append the encoded -argument string. - - Force - Supplies an indication of whether we should quote - the argument even if it does not contain any characters that would - ordinarily require quoting. - -Return Value: - - None. - -Environment: - - Arbitrary. - ---*/ - -{ - // - // Unless we're told otherwise, don't quote unless we actually - // need to do so --- hopefully avoid problems if programs won't - // parse quotes properly - // - - if (Force == false && Argument.empty() == false && - Argument.find_first_of(" \t\n\v\"") == Argument.npos) { - CommandLine.append(Argument); - } else { - CommandLine.push_back('"'); - - for (auto It = Argument.begin();; ++It) { - unsigned NumberBackslashes = 0; - - while (It != Argument.end() && *It == '\\') { - ++It; - ++NumberBackslashes; - } - - if (It == Argument.end()) { - // - // Escape all backslashes, but let the terminating - // double quotation mark we add below be interpreted - // as a metacharacter. - // - CommandLine.append(NumberBackslashes * 2, '\\'); - break; - } else if (*It == L'"') { - // - // Escape all backslashes and the following - // double quotation mark. - // - CommandLine.append(NumberBackslashes * 2 + 1, '\\'); - CommandLine.push_back(*It); - } else { - // - // Backslashes aren't special here. - // - CommandLine.append(NumberBackslashes, '\\'); - CommandLine.push_back(*It); - } - } - - CommandLine.push_back('"'); - } -} - -int osal_actor_start(const actor_config &config, mdbx_pid_t &pid) { - if (childs.size() == MAXIMUM_WAIT_OBJECTS) - failure("Could't manage more that %u actors on Windows\n", - MAXIMUM_WAIT_OBJECTS); - - _flushall(); - - STARTUPINFOA StartupInfo; - GetStartupInfoA(&StartupInfo); - - char exename[_MAX_PATH]; - DWORD exename_size = sizeof(exename); - if (!QueryFullProcessImageNameA(GetCurrentProcess(), 0, exename, - &exename_size)) - failure_perror("QueryFullProcessImageName()", GetLastError()); - - std::string cmdline = "test_mdbx.child "; - ArgvQuote(cmdline, thunk_param(config)); - - PROCESS_INFORMATION ProcessInformation; - if (!CreateProcessA(exename, const_cast<char *>(cmdline.c_str()), - NULL, // Retuned process handle is not inheritable. - NULL, // Retuned thread handle is not inheritable. - TRUE, // Child inherits all inheritable handles. - NORMAL_PRIORITY_CLASS | INHERIT_PARENT_AFFINITY, - NULL, // Inherit the parent's environment. - NULL, // Inherit the parent's current directory. - &StartupInfo, &ProcessInformation)) - return GetLastError(); - - CloseHandle(ProcessInformation.hThread); - pid = ProcessInformation.dwProcessId; - childs[pid] = std::make_pair(ProcessInformation.hProcess, as_running); - return 0; -} - -actor_status osal_actor_info(const mdbx_pid_t pid) { - actor_status status = childs.at(pid).second; - if (status > as_running) - return status; - - DWORD ExitCode; - if (!GetExitCodeProcess(childs.at(pid).first, &ExitCode)) - failure_perror("GetExitCodeProcess()", GetLastError()); - - switch (ExitCode) { - case STILL_ACTIVE: - return as_running; - case EXIT_SUCCESS: - status = as_successful; - break; - // case EXCEPTION_BREAKPOINT: - case EXCEPTION_SINGLE_STEP: - status = as_debuging; - break; - case STATUS_CONTROL_C_EXIT: - case EXCEPTION_NONCONTINUABLE_EXCEPTION: - status = as_killed; - break; - default: - status = as_failed; - break; - } - - childs.at(pid).second = status; - return status; -} - -void osal_killall_actors(void) { - for (auto &pair : childs) - TerminateProcess(pair.second.first, STATUS_CONTROL_C_EXIT); -} - -int osal_actor_poll(mdbx_pid_t &pid, unsigned timeout) { - std::vector<HANDLE> handles; - handles.reserve(childs.size()); - for (const auto &pair : childs) - if (pair.second.second <= as_running) - handles.push_back(pair.second.first); - - DWORD rc = - MsgWaitForMultipleObjectsEx((DWORD)handles.size(), &handles[0], - (timeout > 60) ? 60 * 1000 : timeout * 1000, - QS_ALLINPUT | QS_ALLPOSTMESSAGE, 0); - - if (rc >= WAIT_OBJECT_0 && rc < WAIT_OBJECT_0 + handles.size()) { - pid = 0; - for (const auto &pair : childs) - if (pair.second.first == handles[rc - WAIT_OBJECT_0]) { - pid = pair.first; - break; - } - return 0; - } - - if (rc == WAIT_TIMEOUT) { - pid = 0; - return 0; - } - - return waitstatus2errcode(rc); -} - -void osal_yield(void) { SwitchToThread(); } - -void osal_udelay(unsigned us) { - chrono::time until, now = chrono::now_motonic(); - until.fixedpoint = now.fixedpoint + chrono::from_us(us).fixedpoint; - - static unsigned threshold_us; - if (threshold_us == 0) { -#if 1 - unsigned timeslice_ms = 1; - while (timeBeginPeriod(timeslice_ms) == TIMERR_NOCANDO) - ++timeslice_ms; - threshold_us = timeslice_ms * 1500u; -#else - ULONGLONG InterruptTimePrecise_100ns; - QueryInterruptTimePrecise(&InterruptTimePrecise_100ns); - threshold_us = InterruptTimePrecise_100ns / 5; -#endif - assert(threshold_us > 0); - } - - do { - if (us > threshold_us && us > 1000) { - DWORD rc = SleepEx(us / 1000, TRUE); - if (rc) - failure_perror("SleepEx()", waitstatus2errcode(rc)); - us = 0; - } - - YieldProcessor(); - now = chrono::now_motonic(); - } while (now.fixedpoint < until.fixedpoint); -} - -bool osal_istty(int fd) { return _isatty(fd) != 0; } - -std::string osal_tempdir(void) { - char buf[MAX_PATH + 1]; - DWORD len = GetTempPathA(sizeof(buf), buf); - return std::string(buf, len); -} diff --git a/plugins/Dbx_mdbx/src/libmdbx/test/osal.h b/plugins/Dbx_mdbx/src/libmdbx/test/osal.h deleted file mode 100644 index c27282a656..0000000000 --- a/plugins/Dbx_mdbx/src/libmdbx/test/osal.h +++ /dev/null @@ -1,46 +0,0 @@ -/* - * Copyright 2017-2018 Leonid Yuriev <leo@yuriev.ru> - * and other libmdbx authors: please see AUTHORS file. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted only as authorized by the OpenLDAP - * Public License. - * - * A copy of this license is available in the file LICENSE in the - * top-level directory of the distribution or, alternatively, at - * <http://www.OpenLDAP.org/license.html>. - */ - -#pragma once - -#include "base.h" - -void osal_setup(const std::vector<actor_config> &actors); -void osal_broadcast(unsigned id); -int osal_waitfor(unsigned id); - -int osal_actor_start(const actor_config &config, mdbx_pid_t &pid); -actor_status osal_actor_info(const mdbx_pid_t pid); -void osal_killall_actors(void); -int osal_actor_poll(mdbx_pid_t &pid, unsigned timeout); -void osal_wait4barrier(void); - -mdbx_pid_t osal_getpid(void); -int osal_delay(unsigned seconds); -void osal_udelay(unsigned us); -void osal_yield(void); -bool osal_istty(int fd); -std::string osal_tempdir(void); - -#ifdef _MSC_VER -#ifndef STDIN_FILENO -#define STDIN_FILENO _fileno(stdin) -#endif -#ifndef STDOUT_FILENO -#define STDOUT_FILENO _fileno(stdout) -#endif -#ifndef STDERR_FILENO -#define STDERR_FILENO _fileno(stderr) -#endif -#endif /* _MSC_VER */ diff --git a/plugins/Dbx_mdbx/src/libmdbx/test/pcrf/CMakeLists.txt b/plugins/Dbx_mdbx/src/libmdbx/test/pcrf/CMakeLists.txt deleted file mode 100644 index 399c33f88f..0000000000 --- a/plugins/Dbx_mdbx/src/libmdbx/test/pcrf/CMakeLists.txt +++ /dev/null @@ -1,7 +0,0 @@ -set(TARGET pcrf_test) -project(${TARGET}) - -add_executable(${TARGET} pcrf_test.c) - -target_link_libraries(${TARGET} mdbx) - diff --git a/plugins/Dbx_mdbx/src/libmdbx/test/pcrf/README.md b/plugins/Dbx_mdbx/src/libmdbx/test/pcrf/README.md deleted file mode 100644 index b2c9b5ce95..0000000000 --- a/plugins/Dbx_mdbx/src/libmdbx/test/pcrf/README.md +++ /dev/null @@ -1,2 +0,0 @@ -PCRF Session DB emulation test - diff --git a/plugins/Dbx_mdbx/src/libmdbx/test/pcrf/pcrf_test.c b/plugins/Dbx_mdbx/src/libmdbx/test/pcrf/pcrf_test.c deleted file mode 100644 index 213c8b1d80..0000000000 --- a/plugins/Dbx_mdbx/src/libmdbx/test/pcrf/pcrf_test.c +++ /dev/null @@ -1,404 +0,0 @@ -/* - * Copyright 2016-2017 Leonid Yuriev <leo@yuriev.ru>. - * Copyright 2015 Vladimir Romanov - * <https://www.linkedin.com/in/vladimirromanov>, Yota Lab. - * - * This file is part of libmdbx. - * - * ReOpenMDBX is free software; you can redistribute it and/or modify it under - * the terms of the GNU Affero General Public License as published by - * the Free Software Foundation; either version 3 of the License, or - * (at your option) any later version. - * - * ReOpenMDBX is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Affero General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with this program. If not, see <http://www.gnu.org/licenses/>. - */ - -#include <sys/stat.h> -#include <sys/time.h> - -#include "mdbx.h" -#include <assert.h> -#include <inttypes.h> -#include <limits.h> -#include <stddef.h> -#include <stdint.h> -#include <stdio.h> -#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) - -char opt_db_path[PATH_MAX] = "/root/lmdbx_bench2"; -static MDBX_env *env; -#define REC_COUNT 10240000 -int64_t ids[REC_COUNT * 10]; -int32_t ids_count = 0; - -int64_t mdbx_add_count = 0; -int64_t mdbx_del_count = 0; -uint64_t mdbx_add_time = 0; -uint64_t mdbx_del_time = 0; -int64_t obj_id = 0; -int64_t mdbx_data_size = 0; -int64_t mdbx_key_size = 0; - -typedef struct { - char session_id1[100]; - char session_id2[100]; - char ip[20]; - uint8_t fill[100]; -} session_data_t; - -typedef struct { - int64_t obj_id; - int8_t event_type; -} __attribute__((__packed__)) event_data_t; - -static void add_id_to_pool(int64_t id) { - ids[ids_count] = id; - ids_count++; -} - -static inline int64_t getClockUs(void) { - struct timespec val; -#ifdef CYGWIN - clock_gettime(CLOCK_REALTIME, &val); -#else - clock_gettime(CLOCK_MONOTONIC, &val); -#endif - return val.tv_sec * ((int64_t)1000000) + val.tv_nsec / 1000; -} - -static int64_t get_id_from_pool() { - if (ids_count == 0) { - return -1; - } - int32_t index = rand() % ids_count; - int64_t id = ids[index]; - ids[index] = ids[ids_count - 1]; - ids_count--; - 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); \ - } \ - } while (0) - -static void db_connect() { - MDBX_dbi dbi_session; - MDBX_dbi dbi_session_id; - MDBX_dbi dbi_event; - MDBX_dbi dbi_ip; - - MDBX_CHECK(mdbx_env_create(&env)); - MDBX_CHECK( - mdbx_env_set_mapsize(env, REC_COUNT * sizeof(session_data_t) * 10)); - MDBX_CHECK(mdbx_env_set_maxdbs(env, 30)); - MDBX_CHECK(mdbx_env_open(env, opt_db_path, - MDBX_CREATE | MDBX_WRITEMAP | MDBX_MAPASYNC | - MDBX_NOSYNC | MDBX_LIFORECLAIM, - 0664)); - MDBX_txn *txn; - - // transaction init - MDBX_CHECK(mdbx_txn_begin(env, NULL, 0, &txn)); - // open database in read-write mode - MDBX_CHECK(mdbx_dbi_open(txn, "session", MDBX_CREATE, &dbi_session)); - 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)); - // transaction commit - MDBX_CHECK(mdbx_txn_commit(txn)); - printf("Connection open\n"); -} - -static void create_record(int64_t record_id) { - MDBX_dbi dbi_session; - MDBX_dbi dbi_session_id; - MDBX_dbi dbi_event; - MDBX_dbi dbi_ip; - event_data_t event; - MDBX_txn *txn; - session_data_t data; - // transaction init - snprintf(data.session_id1, sizeof(data.session_id1), - "prefix%02ld_%02ld.fill.fill.fill.fill.fill.fill;%ld", - record_id % 3 + 1, record_id % 9 + 1, record_id); - snprintf(data.session_id2, sizeof(data.session_id2), - "dprefix%ld;%ld.fill.fill.;suffix", record_id, - record_id % 1000000000 + 99999); - 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; - - MDBX_val _session_id1_rec = {data.session_id1, strlen(data.session_id1)}; - 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 _event_rec = {&event, sizeof(event)}; - - uint64_t start = getClockUs(); - MDBX_CHECK(mdbx_txn_begin(env, NULL, 0, &txn)); - MDBX_CHECK(mdbx_dbi_open(txn, "session", MDBX_CREATE, &dbi_session)); - 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_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); - - // transaction commit - mdbx_add_count++; - mdbx_add_time += (getClockUs() - start); -} - -static void delete_record(int64_t record_id) { - MDBX_dbi dbi_session; - MDBX_dbi dbi_session_id; - MDBX_dbi dbi_event; - MDBX_dbi dbi_ip; - event_data_t event; - MDBX_txn *txn; - - // transaction init - uint64_t start = getClockUs(); - MDBX_CHECK(mdbx_txn_begin(env, NULL, 0, &txn)); - // open database in read-write mode - MDBX_CHECK(mdbx_dbi_open(txn, "session", MDBX_CREATE, &dbi_session)); - 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)); - // put data - MDBX_val _obj_id_rec = {&record_id, sizeof(record_id)}; - MDBX_val _data_rec; - // get data - MDBX_CHECK(mdbx_get(txn, dbi_session, &_obj_id_rec, &_data_rec)); - session_data_t *data = (session_data_t *)_data_rec.iov_base; - - MDBX_val _session_id1_rec = {data->session_id1, strlen(data->session_id1)}; - MDBX_val _session_id2_rec = {data->session_id2, strlen(data->session_id2)}; - MDBX_val _ip_rec = {data->ip, strlen(data->ip)}; - MDBX_CHECK(mdbx_del(txn, dbi_session_id, &_session_id1_rec, NULL)); - MDBX_CHECK(mdbx_del(txn, dbi_session_id, &_session_id2_rec, NULL)); - MDBX_CHECK(mdbx_del(txn, dbi_ip, &_ip_rec, NULL)); - event.obj_id = record_id; - event.event_type = 1; - MDBX_val _event_rec = {&event, sizeof(event)}; - MDBX_CHECK(mdbx_del(txn, dbi_event, &_event_rec, NULL)); - 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); - - // transaction commit - MDBX_CHECK(mdbx_txn_commit(txn)); - mdbx_del_count++; - mdbx_del_time += (getClockUs() - start); -} - -static void db_disconnect() { - mdbx_env_close(env); - printf("Connection closed\n"); -} - -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; - - MDBX_CHECK(mdbx_txn_begin(env, NULL, MDBX_RDONLY, &txn)); - 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 | %15ld | %5u | %10ld | %10ld | %11ld |\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; -} - -static void periodic_stat(void) { - int64_t ms_branch_pages = 0; - int64_t ms_leaf_pages = 0; - MDBX_stat mst; - MDBX_envinfo mei; - MDBX_CHECK(mdbx_env_stat(env, &mst, sizeof(mst))); - MDBX_CHECK(mdbx_env_info(env, &mei, sizeof(mei))); - 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); - } else { - 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(" 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, - 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); - - printf(" Name | ms_branch_pages | depth | entries | leaf_pages " - "| overf_pages |\n"); - get_db_stat("session", &ms_branch_pages, &ms_leaf_pages); - 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 | %15ld | %5s | %10s | %10ld | %11s |\n", "", ms_branch_pages, - "", "", ms_leaf_pages, ""); - - static int64_t prev_add_count; - static int64_t prev_del_count; - static uint64_t prev_add_time; - static uint64_t prev_del_time; - static int64_t t = -1; - if (t > 0) { - int64_t delta = (getClockUs() - t); - printf( - "CPS: add %ld, delete %ld, items processed - %ldK data=%ldK key=%ldK\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); - printf("usage data=%ld%%", ((mdbx_data_size + mdbx_key_size) * 100) / - ((ms_leaf_pages + ms_branch_pages) * 4096)); - if (prev_add_time != mdbx_add_time) { - printf(" Add : %ld c/s", (mdbx_add_count - prev_add_count) * 1000000 / - (mdbx_add_time - prev_add_time)); - } - if (prev_del_time != mdbx_del_time) { - printf(" Del : %ld c/s", (mdbx_del_count - prev_del_count) * 1000000 / - (mdbx_del_time - prev_del_time)); - } - if (mdbx_add_time) { - printf(" tAdd : %ld c/s", mdbx_add_count * 1000000 / mdbx_add_time); - } - if (mdbx_del_time) { - printf(" tDel : %ld c/s", mdbx_del_count * 1000000 / mdbx_del_time); - } - puts(""); - } - t = getClockUs(); - prev_add_count = mdbx_add_count; - prev_del_count = mdbx_del_count; - prev_add_time = mdbx_add_time; - prev_del_time = mdbx_del_time; -} - -// static void periodic_add_rec() { -// for (int i = 0; i < 10240; i++) { -// if (ids_count <= REC_COUNT) { -// int64_t id = obj_id++; -// create_record(id); -// add_id_to_pool(id); -// } -// if (ids_count > REC_COUNT) { -// int64_t id = get_id_from_pool(); -// delete_record(id); -// } -// } -// periodic_stat(); -//} - -int main(int argc, char **argv) { - (void)argc; - (void)argv; - - char filename[PATH_MAX]; - int i; - - mkdir(opt_db_path, 0775); - - strcpy(filename, opt_db_path); - strcat(filename, "/mdbx.dat"); - remove(filename); - - strcpy(filename, opt_db_path); - strcat(filename, "/mdbx.lck"); - remove(filename); - - puts("Open DB..."); - db_connect(); - puts("Create data..."); - int64_t t = getClockUs(); - for (i = 0; i < REC_COUNT; i++) { - int64_t id = obj_id++; - create_record(id); - add_id_to_pool(id); - if (i % 1000 == 0) { - int64_t now = getClockUs(); - if ((now - t) > 1000000L) { - periodic_stat(); - t = now; - } - } - } - periodic_stat(); - while (1) { - int i; - for (i = 0; i < 1000; i++) { - int64_t id = obj_id++; - create_record(id); - add_id_to_pool(id); - id = get_id_from_pool(); - delete_record(id); - } - // for (i = 0; i < 50; i++) { - // int64_t id = obj_id++; - // create_record(id); - // add_id_to_pool(id); - // } - // int64_t id = obj_id++; - // create_record(id); - // add_id_to_pool(id); - int64_t now = getClockUs(); - if ((now - t) > 10000000L) { - periodic_stat(); - t = now; - } - } - db_disconnect(); - return 0; -} diff --git a/plugins/Dbx_mdbx/src/libmdbx/test/test.cc b/plugins/Dbx_mdbx/src/libmdbx/test/test.cc deleted file mode 100644 index 3750af525f..0000000000 --- a/plugins/Dbx_mdbx/src/libmdbx/test/test.cc +++ /dev/null @@ -1,495 +0,0 @@ -/* - * Copyright 2017-2018 Leonid Yuriev <leo@yuriev.ru> - * and other libmdbx authors: please see AUTHORS file. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted only as authorized by the OpenLDAP - * Public License. - * - * A copy of this license is available in the file LICENSE in the - * top-level directory of the distribution or, alternatively, at - * <http://www.OpenLDAP.org/license.html>. - */ - -#include "test.h" - -const char *testcase2str(const actor_testcase testcase) { - switch (testcase) { - default: - assert(false); - return "?!"; - case ac_none: - return "none"; - case ac_hill: - return "hill"; - case ac_deadread: - return "deadread"; - case ac_deadwrite: - return "deadwrite"; - case ac_jitter: - return "jitter"; - case ac_try: - return "try"; - } -} - -const char *status2str(actor_status status) { - switch (status) { - default: - assert(false); - return "?!"; - case as_debuging: - return "debuging"; - case as_running: - return "running"; - case as_successful: - return "successful"; - case as_killed: - return "killed"; - case as_failed: - return "failed"; - } -} - -const char *keygencase2str(const keygen_case keycase) { - switch (keycase) { - default: - assert(false); - return "?!"; - case kc_random: - return "random"; - case kc_dashes: - return "dashes"; - case kc_custom: - return "custom"; - } -} - -//----------------------------------------------------------------------------- - -static void mdbx_logger(int type, const char *function, int line, - const char *msg, va_list args) { - logging::loglevel level = logging::info; - if (type & MDBX_DBG_EXTRA) - level = logging::extra; - if (type & MDBX_DBG_TRACE) - level = logging::trace; - if (type & MDBX_DBG_PRINT) - level = logging::verbose; - - if (!function) - function = "unknown"; - if (type & MDBX_DBG_ASSERT) { - log_error("mdbx: assertion failure: %s, %d", function, line); - level = logging::failure; - } - - if (logging::output( - level, - strncmp(function, "mdbx_", 5) == 0 ? "%s: " : "mdbx: %s: ", function)) - logging::feed(msg, args); - if (type & MDBX_DBG_ASSERT) - abort(); -} - -int testcase::oom_callback(MDBX_env *env, int pid, mdbx_tid_t tid, uint64_t txn, - unsigned gap, int retry) { - - testcase *self = (testcase *)mdbx_env_get_userctx(env); - - if (retry == 0) - log_notice("oom_callback: waitfor pid %u, thread %" PRIuPTR - ", txn #%" PRIu64 ", gap %d", - pid, (size_t)tid, txn, gap); - - if (self->should_continue(true)) { - osal_yield(); - if (retry > 0) - osal_udelay(retry * 100); - return 0 /* always retry */; - } - - return -1; -} - -void testcase::db_prepare() { - log_trace(">> db_prepare"); - assert(!db_guard); - - int mdbx_dbg_opts = MDBX_DBG_ASSERT | MDBX_DBG_JITTER | MDBX_DBG_DUMP; - if (config.params.loglevel <= logging::trace) - mdbx_dbg_opts |= MDBX_DBG_TRACE; - if (config.params.loglevel <= logging::verbose) - mdbx_dbg_opts |= MDBX_DBG_PRINT; - int rc = mdbx_setup_debug(mdbx_dbg_opts, mdbx_logger); - log_trace("set mdbx debug-opts: 0x%02x", rc); - - MDBX_env *env = nullptr; - rc = mdbx_env_create(&env); - if (unlikely(rc != MDBX_SUCCESS)) - failure_perror("mdbx_env_create()", rc); - - assert(env != nullptr); - db_guard.reset(env); - - rc = mdbx_env_set_userctx(env, this); - if (unlikely(rc != MDBX_SUCCESS)) - failure_perror("mdbx_env_set_userctx()", rc); - - rc = mdbx_env_set_maxreaders(env, config.params.max_readers); - if (unlikely(rc != MDBX_SUCCESS)) - failure_perror("mdbx_env_set_maxreaders()", rc); - - rc = mdbx_env_set_maxdbs(env, config.params.max_tables); - if (unlikely(rc != MDBX_SUCCESS)) - failure_perror("mdbx_env_set_maxdbs()", rc); - - rc = mdbx_env_set_oomfunc(env, testcase::oom_callback); - if (unlikely(rc != MDBX_SUCCESS)) - failure_perror("mdbx_env_set_oomfunc()", rc); - - rc = mdbx_env_set_mapsize(env, (size_t)config.params.size); - if (unlikely(rc != MDBX_SUCCESS)) - failure_perror("mdbx_env_set_mapsize()", rc); - - log_trace("<< db_prepare"); -} - -void testcase::db_open() { - log_trace(">> db_open"); - - if (!db_guard) - db_prepare(); - int rc = mdbx_env_open(db_guard.get(), config.params.pathname_db.c_str(), - (unsigned)config.params.mode_flags, 0640); - if (unlikely(rc != MDBX_SUCCESS)) - failure_perror("mdbx_env_open()", rc); - - log_trace("<< db_open"); -} - -void testcase::db_close() { - log_trace(">> db_close"); - cursor_guard.reset(); - txn_guard.reset(); - db_guard.reset(); - log_trace("<< db_close"); -} - -void testcase::txn_begin(bool readonly, unsigned flags) { - assert((flags & MDBX_RDONLY) == 0); - log_trace(">> txn_begin(%s, 0x%04X)", readonly ? "read-only" : "read-write", - flags); - assert(!txn_guard); - - MDBX_txn *txn = nullptr; - int rc = mdbx_txn_begin(db_guard.get(), nullptr, - readonly ? flags | MDBX_RDONLY : flags, &txn); - if (unlikely(rc != MDBX_SUCCESS)) - failure_perror("mdbx_txn_begin()", rc); - txn_guard.reset(txn); - - log_trace("<< txn_begin(%s, 0x%04X)", readonly ? "read-only" : "read-write", - flags); -} - -void testcase::txn_end(bool abort) { - log_trace(">> txn_end(%s)", abort ? "abort" : "commit"); - assert(txn_guard); - - MDBX_txn *txn = txn_guard.release(); - if (abort) { - int rc = mdbx_txn_abort(txn); - if (unlikely(rc != MDBX_SUCCESS)) - failure_perror("mdbx_txn_abort()", rc); - } else { - txn_inject_writefault(txn); - int rc = mdbx_txn_commit(txn); - if (unlikely(rc != MDBX_SUCCESS)) - failure_perror("mdbx_txn_commit()", rc); - } - - log_trace("<< txn_end(%s)", abort ? "abort" : "commit"); -} - -void testcase::txn_restart(bool abort, bool readonly, unsigned flags) { - if (txn_guard) - txn_end(abort); - txn_begin(readonly, flags); -} - -void testcase::txn_inject_writefault(void) { - if (txn_guard) - txn_inject_writefault(txn_guard.get()); -} - -void testcase::txn_inject_writefault(MDBX_txn *txn) { - if (config.params.inject_writefaultn && txn) { - if (config.params.inject_writefaultn <= nops_completed && - (mdbx_txn_flags(txn) & MDBX_RDONLY) == 0) { - log_info("== txn_inject_writefault(): got %u nops or more, inject FAULT", - config.params.inject_writefaultn); - log_flush(); -#if defined(_WIN32) || defined(_WIN64) || defined(_WINDOWS) - TerminateProcess(GetCurrentProcess(), 42); -#else - raise(SIGKILL); -#endif - } - } -} - -bool testcase::wait4start() { - if (config.wait4id) { - log_trace(">> wait4start(%u)", config.wait4id); - assert(!global::singlemode); - int rc = osal_waitfor(config.wait4id); - if (rc) { - log_trace("<< wait4start(%u), failed %s", config.wait4id, - test_strerror(rc)); - return false; - } - } else { - log_trace("== skip wait4start: not needed"); - } - - if (config.params.delaystart) { - int rc = osal_delay(config.params.delaystart); - if (rc) { - log_trace("<< delay(%u), failed %s", config.params.delaystart, - test_strerror(rc)); - return false; - } - } else { - log_trace("== skip delay: not needed"); - } - - return true; -} - -void testcase::kick_progress(bool active) const { - chrono::time now = chrono::now_motonic(); - if (active) { - static int last_point = -1; - int point = (now.fixedpoint >> 29) & 3; - if (point != last_point) { - last.progress_timestamp = now; - fprintf(stderr, "%c\b", "-\\|/"[last_point = point]); - fflush(stderr); - } - } else if (now.fixedpoint - last.progress_timestamp.fixedpoint > - chrono::from_seconds(2).fixedpoint) { - last.progress_timestamp = now; - fprintf(stderr, "%c\b", "@*"[now.utc & 1]); - fflush(stderr); - } -} - -void testcase::report(size_t nops_done) { - assert(nops_done > 0); - if (!nops_done) - return; - - nops_completed += nops_done; - log_verbose("== complete +%" PRIuPTR " iteration, total %" PRIuPTR " done", - nops_done, nops_completed); - - if (global::config::progress_indicator) - kick_progress(true); - - if (config.signal_nops && !signalled && - config.signal_nops <= nops_completed) { - log_trace(">> signal(n-ops %" PRIuPTR ")", nops_completed); - if (!global::singlemode) - osal_broadcast(config.actor_id); - signalled = true; - log_trace("<< signal(n-ops %" PRIuPTR ")", nops_completed); - } -} - -void testcase::signal() { - if (!signalled) { - log_trace(">> signal(forced)"); - if (!global::singlemode) - osal_broadcast(config.actor_id); - signalled = true; - log_trace("<< signal(forced)"); - } -} - -bool testcase::setup() { - db_prepare(); - if (!wait4start()) - return false; - - start_timestamp = chrono::now_motonic(); - return true; -} - -bool testcase::teardown() { - log_trace(">> testcase::teardown"); - signal(); - db_close(); - log_trace("<< testcase::teardown"); - return true; -} - -bool testcase::should_continue(bool check_timeout_only) const { - bool result = true; - - if (config.params.test_duration) { - chrono::time since; - since.fixedpoint = - chrono::now_motonic().fixedpoint - start_timestamp.fixedpoint; - if (since.seconds() >= config.params.test_duration) - result = false; - } - - if (!check_timeout_only && config.params.test_nops && - nops_completed >= config.params.test_nops) - result = false; - - if (result && global::config::progress_indicator) - kick_progress(false); - - return result; -} - -void testcase::fetch_canary() { - mdbx_canary canary_now; - log_trace(">> fetch_canary"); - - int rc = mdbx_canary_get(txn_guard.get(), &canary_now); - if (unlikely(rc != MDBX_SUCCESS)) - failure_perror("mdbx_canary_get()", rc); - - if (canary_now.v < last.canary.v) - failure("fetch_canary: %" PRIu64 "(canary-now.v) < %" PRIu64 - "(canary-last.v)", - canary_now.v, last.canary.v); - if (canary_now.y < last.canary.y) - failure("fetch_canary: %" PRIu64 "(canary-now.y) < %" PRIu64 - "(canary-last.y)", - canary_now.y, last.canary.y); - - last.canary = canary_now; - log_trace("<< fetch_canary: db-sequence %" PRIu64 - ", db-sequence.txnid %" PRIu64, - last.canary.y, last.canary.v); -} - -void testcase::update_canary(uint64_t increment) { - mdbx_canary canary_now = last.canary; - - log_trace(">> update_canary: sequence %" PRIu64 " += %" PRIu64, canary_now.y, - increment); - canary_now.y += increment; - - int rc = mdbx_canary_put(txn_guard.get(), &canary_now); - if (unlikely(rc != MDBX_SUCCESS)) - failure_perror("mdbx_canary_put()", rc); - - log_trace("<< update_canary: sequence = %" PRIu64, canary_now.y); -} - -MDBX_dbi testcase::db_table_open(bool create) { - log_trace(">> testcase::db_table_create"); - - char tablename_buf[16]; - const char *tablename = nullptr; - if (config.space_id) { - int rc = snprintf(tablename_buf, sizeof(tablename_buf), "TBL%04u", - config.space_id); - if (rc < 4 || rc >= (int)sizeof(tablename_buf) - 1) - failure("snprintf(tablename): %d", rc); - tablename = tablename_buf; - } - log_verbose("use %s table", tablename ? tablename : "MAINDB"); - - MDBX_dbi handle = 0; - int rc = mdbx_dbi_open(txn_guard.get(), tablename, - (create ? MDBX_CREATE : 0) | config.params.table_flags, - &handle); - if (unlikely(rc != MDBX_SUCCESS)) - failure_perror("mdbx_dbi_open()", rc); - - log_trace("<< testcase::db_table_create, handle %u", handle); - return handle; -} - -void testcase::db_table_drop(MDBX_dbi handle) { - log_trace(">> testcase::db_table_drop, handle %u", handle); - - if (config.params.drop_table) { - int rc = mdbx_drop(txn_guard.get(), handle, true); - if (unlikely(rc != MDBX_SUCCESS)) - failure_perror("mdbx_drop()", rc); - log_trace("<< testcase::db_table_drop"); - } else { - log_trace("<< testcase::db_table_drop: not needed"); - } -} - -void testcase::db_table_close(MDBX_dbi handle) { - log_trace(">> testcase::db_table_close, handle %u", handle); - assert(!txn_guard); - int rc = mdbx_dbi_close(db_guard.get(), handle); - if (unlikely(rc != MDBX_SUCCESS)) - failure_perror("mdbx_dbi_close()", rc); - log_trace("<< testcase::db_table_close"); -} - -//----------------------------------------------------------------------------- - -bool test_execute(const actor_config &config) { - const mdbx_pid_t pid = osal_getpid(); - - if (global::singlemode) { - logging::setup(format("single_%s", testcase2str(config.testcase))); - } else { - logging::setup((logging::loglevel)config.params.loglevel, - format("child_%u.%u", config.actor_id, config.space_id)); - log_trace(">> wait4barrier"); - osal_wait4barrier(); - log_trace("<< wait4barrier"); - } - - try { - std::unique_ptr<testcase> test; - switch (config.testcase) { - case ac_hill: - test.reset(new testcase_hill(config, pid)); - break; - case ac_deadread: - test.reset(new testcase_deadread(config, pid)); - break; - case ac_deadwrite: - test.reset(new testcase_deadwrite(config, pid)); - break; - case ac_jitter: - test.reset(new testcase_jitter(config, pid)); - break; - case ac_try: - test.reset(new testcase_try(config, pid)); - break; - default: - test.reset(new testcase(config, pid)); - break; - } - - if (!test->setup()) - log_notice("test setup failed"); - else if (!test->run()) - log_notice("test failed"); - else if (!test->teardown()) - log_notice("test teardown failed"); - else { - log_info("test successed"); - return true; - } - } catch (const std::exception &pipets) { - failure("***** Exception: %s *****", pipets.what()); - } - return false; -} diff --git a/plugins/Dbx_mdbx/src/libmdbx/test/test.h b/plugins/Dbx_mdbx/src/libmdbx/test/test.h deleted file mode 100644 index ef1c4caa47..0000000000 --- a/plugins/Dbx_mdbx/src/libmdbx/test/test.h +++ /dev/null @@ -1,205 +0,0 @@ -/* - * Copyright 2017-2018 Leonid Yuriev <leo@yuriev.ru> - * and other libmdbx authors: please see AUTHORS file. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted only as authorized by the OpenLDAP - * Public License. - * - * A copy of this license is available in the file LICENSE in the - * top-level directory of the distribution or, alternatively, at - * <http://www.OpenLDAP.org/license.html>. - */ - -#pragma once - -#include "base.h" -#include "chrono.h" -#include "config.h" -#include "keygen.h" -#include "log.h" -#include "osal.h" -#include "utils.h" - -bool test_execute(const actor_config &config); -std::string thunk_param(const actor_config &config); -void testcase_setup(const char *casename, actor_params ¶ms, - unsigned &last_space_id); -void configure_actor(unsigned &last_space_id, const actor_testcase testcase, - const char *space_id_cstr, const actor_params ¶ms); -void keycase_setup(const char *casename, actor_params ¶ms); - -namespace global { - -extern const char thunk_param_prefix[]; -extern std::vector<actor_config> actors; -extern std::unordered_map<unsigned, actor_config *> events; -extern std::unordered_map<mdbx_pid_t, actor_config *> pid2actor; -extern std::set<std::string> databases; -extern unsigned nactors; -extern chrono::time start_motonic; -extern chrono::time deadline_motonic; -extern bool singlemode; - -namespace config { -extern unsigned timeout_duration_seconds; -extern bool dump_config; -extern bool cleanup_before; -extern bool cleanup_after; -extern bool failfast; -extern bool progress_indicator; -} /* namespace config */ - -} /* namespace global */ - -//----------------------------------------------------------------------------- - -struct db_deleter : public std::unary_function<void, MDBX_env *> { - void operator()(MDBX_env *env) const { mdbx_env_close(env); } -}; - -struct txn_deleter : public std::unary_function<void, MDBX_txn *> { - void operator()(MDBX_txn *txn) const { - int rc = mdbx_txn_abort(txn); - if (rc) - log_trouble(mdbx_func_, "mdbx_txn_abort()", rc); - } -}; - -struct cursor_deleter : public std::unary_function<void, MDBX_cursor *> { - void operator()(MDBX_cursor *cursor) const { mdbx_cursor_close(cursor); } -}; - -typedef std::unique_ptr<MDBX_env, db_deleter> scoped_db_guard; -typedef std::unique_ptr<MDBX_txn, txn_deleter> scoped_txn_guard; -typedef std::unique_ptr<MDBX_cursor, cursor_deleter> scoped_cursor_guard; - -//----------------------------------------------------------------------------- - -class testcase { -protected: - const actor_config &config; - const mdbx_pid_t pid; - - scoped_db_guard db_guard; - scoped_txn_guard txn_guard; - scoped_cursor_guard cursor_guard; - bool signalled; - - size_t nops_completed; - chrono::time start_timestamp; - keygen::buffer key; - keygen::buffer data; - keygen::maker keyvalue_maker; - - struct { - mdbx_canary canary; - mutable chrono::time progress_timestamp; - } last; - - static int oom_callback(MDBX_env *env, int pid, mdbx_tid_t tid, uint64_t txn, - unsigned gap, int retry); - - void db_prepare(); - void db_open(); - void db_close(); - void txn_begin(bool readonly, unsigned flags = 0); - void txn_end(bool abort); - void txn_restart(bool abort, bool readonly, unsigned flags = 0); - void txn_inject_writefault(void); - void txn_inject_writefault(MDBX_txn *txn); - void fetch_canary(); - void update_canary(uint64_t increment); - void kick_progress(bool active) const; - - MDBX_dbi db_table_open(bool create); - void db_table_drop(MDBX_dbi handle); - void db_table_close(MDBX_dbi handle); - - bool wait4start(); - void report(size_t nops_done); - void signal(); - bool should_continue(bool check_timeout_only = false) const; - - void generate_pair(const keygen::serial_t serial, keygen::buffer &out_key, - keygen::buffer &out_value, keygen::serial_t data_age = 0) { - keyvalue_maker.pair(serial, out_key, out_value, data_age); - } - - void generate_pair(const keygen::serial_t serial, - keygen::serial_t data_age = 0) { - generate_pair(serial, key, data, data_age); - } - - 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), signalled(false), nops_completed(0) { - start_timestamp.reset(); - memset(&last, 0, sizeof(last)); - } - - virtual bool setup(); - virtual bool run() { return true; } - virtual bool teardown(); - virtual ~testcase() {} -}; - -class testcase_hill : public testcase { - typedef testcase inherited; - -public: - testcase_hill(const actor_config &config, const mdbx_pid_t pid) - : testcase(config, pid) {} - bool setup(); - bool run(); - bool teardown(); -}; - -class testcase_deadread : public testcase { - typedef testcase inherited; - -public: - testcase_deadread(const actor_config &config, const mdbx_pid_t pid) - : testcase(config, pid) {} - bool setup(); - bool run(); - bool teardown(); -}; - -class testcase_deadwrite : public testcase { - typedef testcase inherited; - -public: - testcase_deadwrite(const actor_config &config, const mdbx_pid_t pid) - : testcase(config, pid) {} - bool setup(); - bool run(); - bool teardown(); -}; - -class testcase_jitter : public testcase { - typedef testcase inherited; - -public: - testcase_jitter(const actor_config &config, const mdbx_pid_t pid) - : testcase(config, pid) {} - bool setup(); - bool run(); - bool teardown(); -}; - -class testcase_try : public testcase { - typedef testcase inherited; - -public: - testcase_try(const actor_config &config, const mdbx_pid_t pid) - : testcase(config, pid) {} - bool setup(); - bool run(); - bool teardown(); -}; diff --git a/plugins/Dbx_mdbx/src/libmdbx/test/test.vcxproj b/plugins/Dbx_mdbx/src/libmdbx/test/test.vcxproj deleted file mode 100644 index 3ee13cf8cf..0000000000 --- a/plugins/Dbx_mdbx/src/libmdbx/test/test.vcxproj +++ /dev/null @@ -1,202 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<Project DefaultTargets="Build" ToolsVersion="14.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> - <ItemGroup Label="ProjectConfigurations"> - <ProjectConfiguration Include="Debug|Win32"> - <Configuration>Debug</Configuration> - <Platform>Win32</Platform> - </ProjectConfiguration> - <ProjectConfiguration Include="Release|Win32"> - <Configuration>Release</Configuration> - <Platform>Win32</Platform> - </ProjectConfiguration> - <ProjectConfiguration Include="Debug|x64"> - <Configuration>Debug</Configuration> - <Platform>x64</Platform> - </ProjectConfiguration> - <ProjectConfiguration Include="Release|x64"> - <Configuration>Release</Configuration> - <Platform>x64</Platform> - </ProjectConfiguration> - </ItemGroup> - <ItemGroup> - <ProjectReference Include="..\dll.vcxproj"> - <Project>{6d19209b-ece7-4b9c-941c-0aa2b484f199}</Project> - </ProjectReference> - </ItemGroup> - <PropertyGroup Label="Globals"> - <ProjectGuid>{30E29CE6-E6FC-4D32-AA07-46A55FAF3A31}</ProjectGuid> - <Keyword>Win32Proj</Keyword> - <RootNamespace>mdbxtest</RootNamespace> - <WindowsTargetPlatformVersion>8.1</WindowsTargetPlatformVersion> - </PropertyGroup> - <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" /> - <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration"> - <ConfigurationType>Application</ConfigurationType> - <UseDebugLibraries>true</UseDebugLibraries> - <PlatformToolset>v140</PlatformToolset> - <CharacterSet>MultiByte</CharacterSet> - </PropertyGroup> - <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration"> - <ConfigurationType>Application</ConfigurationType> - <UseDebugLibraries>false</UseDebugLibraries> - <PlatformToolset>v140</PlatformToolset> - <WholeProgramOptimization>true</WholeProgramOptimization> - <CharacterSet>MultiByte</CharacterSet> - </PropertyGroup> - <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration"> - <ConfigurationType>Application</ConfigurationType> - <UseDebugLibraries>true</UseDebugLibraries> - <PlatformToolset>v140</PlatformToolset> - <CharacterSet>MultiByte</CharacterSet> - </PropertyGroup> - <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration"> - <ConfigurationType>Application</ConfigurationType> - <UseDebugLibraries>false</UseDebugLibraries> - <PlatformToolset>v140</PlatformToolset> - <WholeProgramOptimization>true</WholeProgramOptimization> - <CharacterSet>MultiByte</CharacterSet> - </PropertyGroup> - <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" /> - <ImportGroup Label="ExtensionSettings"> - </ImportGroup> - <ImportGroup Label="Shared"> - </ImportGroup> - <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'"> - <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" /> - </ImportGroup> - <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'"> - <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" /> - </ImportGroup> - <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|x64'"> - <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" /> - </ImportGroup> - <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|x64'"> - <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" /> - </ImportGroup> - <PropertyGroup Label="UserMacros" /> - <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'"> - <LinkIncremental>true</LinkIncremental> - <OutDir>$(SolutionDir)$(Platform)\$(Configuration)\</OutDir> - <IntDir>$(SolutionDir)$(Platform)\$(Configuration)\$(ProjectName)\</IntDir> - </PropertyGroup> - <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'"> - <LinkIncremental>false</LinkIncremental> - <OutDir>$(SolutionDir)$(Platform)\$(Configuration)\</OutDir> - <IntDir>$(SolutionDir)$(Platform)\$(Configuration)\$(ProjectName)\</IntDir> - </PropertyGroup> - <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'"> - <LinkIncremental>true</LinkIncremental> - <OutDir>$(SolutionDir)$(Platform)\$(Configuration)\</OutDir> - <IntDir>$(SolutionDir)$(Platform)\$(Configuration)\$(ProjectName)\</IntDir> - </PropertyGroup> - <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'"> - <LinkIncremental>false</LinkIncremental> - <OutDir>$(SolutionDir)$(Platform)\$(Configuration)\</OutDir> - <IntDir>$(SolutionDir)$(Platform)\$(Configuration)\$(ProjectName)\</IntDir> - </PropertyGroup> - <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'"> - <ClCompile> - <PrecompiledHeader>Use</PrecompiledHeader> - <WarningLevel>Level4</WarningLevel> - <Optimization>Disabled</Optimization> - <PreprocessorDefinitions>WIN32;_DEBUG;_CONSOLE;MDBX_DEBUG=1;%(PreprocessorDefinitions);LIBMDBX_IMPORTS=1</PreprocessorDefinitions> - <SDLCheck>true</SDLCheck> - <PrecompiledHeaderFile>test.h</PrecompiledHeaderFile> - <TreatWarningAsError>true</TreatWarningAsError> - </ClCompile> - <Link> - <SubSystem>Console</SubSystem> - <GenerateDebugInformation>true</GenerateDebugInformation> - <AdditionalDependencies>winmm.lib;%(AdditionalDependencies)</AdditionalDependencies> - </Link> - </ItemDefinitionGroup> - <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'"> - <ClCompile> - <PrecompiledHeader>Use</PrecompiledHeader> - <WarningLevel>Level4</WarningLevel> - <Optimization>Disabled</Optimization> - <PreprocessorDefinitions>_DEBUG;_CONSOLE;MDBX_DEBUG=1;%(PreprocessorDefinitions);LIBMDBX_IMPORTS=1</PreprocessorDefinitions> - <SDLCheck>true</SDLCheck> - <PrecompiledHeaderFile>test.h</PrecompiledHeaderFile> - <TreatWarningAsError>true</TreatWarningAsError> - </ClCompile> - <Link> - <SubSystem>Console</SubSystem> - <GenerateDebugInformation>true</GenerateDebugInformation> - <AdditionalDependencies>winmm.lib;%(AdditionalDependencies)</AdditionalDependencies> - </Link> - </ItemDefinitionGroup> - <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'"> - <ClCompile> - <WarningLevel>Level4</WarningLevel> - <PrecompiledHeader>Use</PrecompiledHeader> - <Optimization>MaxSpeed</Optimization> - <FunctionLevelLinking>true</FunctionLevelLinking> - <IntrinsicFunctions>true</IntrinsicFunctions> - <PreprocessorDefinitions>WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions);LIBMDBX_IMPORTS=1</PreprocessorDefinitions> - <SDLCheck>true</SDLCheck> - <PrecompiledHeaderFile>test.h</PrecompiledHeaderFile> - <OmitFramePointers>true</OmitFramePointers> - </ClCompile> - <Link> - <SubSystem>Console</SubSystem> - <EnableCOMDATFolding>true</EnableCOMDATFolding> - <OptimizeReferences>true</OptimizeReferences> - <GenerateDebugInformation>true</GenerateDebugInformation> - <AdditionalDependencies>winmm.lib;%(AdditionalDependencies)</AdditionalDependencies> - </Link> - </ItemDefinitionGroup> - <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'"> - <ClCompile> - <WarningLevel>Level4</WarningLevel> - <PrecompiledHeader>Use</PrecompiledHeader> - <Optimization>MaxSpeed</Optimization> - <FunctionLevelLinking>true</FunctionLevelLinking> - <IntrinsicFunctions>true</IntrinsicFunctions> - <PreprocessorDefinitions>NDEBUG;_CONSOLE;%(PreprocessorDefinitions);LIBMDBX_IMPORTS=1</PreprocessorDefinitions> - <SDLCheck>true</SDLCheck> - <PrecompiledHeaderFile>test.h</PrecompiledHeaderFile> - <OmitFramePointers>true</OmitFramePointers> - </ClCompile> - <Link> - <SubSystem>Console</SubSystem> - <EnableCOMDATFolding>true</EnableCOMDATFolding> - <OptimizeReferences>true</OptimizeReferences> - <GenerateDebugInformation>true</GenerateDebugInformation> - <AdditionalDependencies>winmm.lib;%(AdditionalDependencies)</AdditionalDependencies> - </Link> - </ItemDefinitionGroup> - <ItemGroup> - <ClInclude Include="base.h" /> - <ClInclude Include="chrono.h" /> - <ClInclude Include="config.h" /> - <ClInclude Include="keygen.h" /> - <ClInclude Include="log.h" /> - <ClInclude Include="osal.h" /> - <ClInclude Include="test.h" /> - <ClInclude Include="utils.h" /> - </ItemGroup> - <ItemGroup> - <ClCompile Include="cases.cc" /> - <ClCompile Include="chrono.cc" /> - <ClCompile Include="config.cc" /> - <ClCompile Include="dead.cc" /> - <ClCompile Include="hill.cc" /> - <ClCompile Include="try.cc" /> - <ClCompile Include="jitter.cc" /> - <ClCompile Include="keygen.cc" /> - <ClCompile Include="log.cc" /> - <ClCompile Include="main.cc" /> - <ClCompile Include="osal-windows.cc"> - <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">Create</PrecompiledHeader> - <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">Create</PrecompiledHeader> - <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">Create</PrecompiledHeader> - <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|x64'">Create</PrecompiledHeader> - </ClCompile> - <ClCompile Include="test.cc" /> - <ClCompile Include="utils.cc" /> - </ItemGroup> - <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" /> - <ImportGroup Label="ExtensionTargets"> - </ImportGroup> -</Project> diff --git a/plugins/Dbx_mdbx/src/libmdbx/test/try.cc b/plugins/Dbx_mdbx/src/libmdbx/test/try.cc deleted file mode 100644 index 1deae71d31..0000000000 --- a/plugins/Dbx_mdbx/src/libmdbx/test/try.cc +++ /dev/null @@ -1,37 +0,0 @@ -#include "test.h" - -bool testcase_try::setup() { - log_trace(">> setup"); - if (!inherited::setup()) - return false; - - log_trace("<< setup"); - return true; -} - -bool testcase_try::run() { - db_open(); - assert(!txn_guard); - - MDBX_txn *txn = nullptr; - MDBX_txn *txn2 = nullptr; - int rc = mdbx_txn_begin(db_guard.get(), nullptr, 0, &txn); - if (unlikely(rc != MDBX_SUCCESS)) - failure_perror("mdbx_txn_begin(MDBX_TRYTXN)", rc); - else { - rc = mdbx_txn_begin(db_guard.get(), nullptr, MDBX_TRYTXN, &txn2); - if (unlikely(rc != MDBX_BUSY)) - failure_perror("mdbx_txn_begin(MDBX_TRYTXN)", rc); - } - - txn_guard.reset(txn); - return true; -} - -bool testcase_try::teardown() { - log_trace(">> teardown"); - cursor_guard.release(); - txn_guard.release(); - db_guard.release(); - return inherited::teardown(); -} diff --git a/plugins/Dbx_mdbx/src/libmdbx/test/utils.cc b/plugins/Dbx_mdbx/src/libmdbx/test/utils.cc deleted file mode 100644 index 0855c7eef3..0000000000 --- a/plugins/Dbx_mdbx/src/libmdbx/test/utils.cc +++ /dev/null @@ -1,349 +0,0 @@ -/* - * Copyright 2017-2018 Leonid Yuriev <leo@yuriev.ru> - * and other libmdbx authors: please see AUTHORS file. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted only as authorized by the OpenLDAP - * Public License. - * - * A copy of this license is available in the file LICENSE in the - * top-level directory of the distribution or, alternatively, at - * <http://www.OpenLDAP.org/license.html>. - */ - -#include "test.h" -#include <float.h> -#if defined(HAVE_IEEE754_H) || __has_include(<ieee754.h>) -#include <ieee754.h> -#endif - -std::string format(const char *fmt, ...) { - va_list ap, ones; - va_start(ap, fmt); - va_copy(ones, ap); -#ifdef _MSC_VER - int needed = _vscprintf(fmt, ap); -#else - int needed = vsnprintf(nullptr, 0, fmt, ap); -#endif - assert(needed >= 0); - va_end(ap); - std::string result; - result.reserve((size_t)needed + 1); - result.resize((size_t)needed, '\0'); - int actual = vsnprintf((char *)result.data(), result.capacity(), fmt, ones); - assert(actual == needed); - (void)actual; - va_end(ones); - return result; -} - -std::string data2hex(const void *ptr, size_t bytes, simple_checksum &checksum) { - std::string result; - if (bytes > 0) { - const uint8_t *data = (const uint8_t *)ptr; - checksum.push(data, bytes); - result.reserve(bytes * 2); - const uint8_t *const end = data + bytes; - do { - char h = *data >> 4; - char l = *data & 15; - result.push_back((l < 10) ? l + '0' : l - 10 + 'a'); - result.push_back((h < 10) ? h + '0' : h - 10 + 'a'); - } while (++data < end); - } - assert(result.size() == bytes * 2); - return result; -} - -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; - - uint8_t *data = (uint8_t *)ptr; - for (const char *hex = hex_begin; hex != hex_end; hex += 2, ++data) { - unsigned l = hex[0], h = hex[1]; - - if (l >= '0' && l <= '9') - l = l - '0'; - else if (l >= 'A' && l <= 'F') - l = l - 'A' + 10; - else if (l >= 'a' && l <= 'f') - l = l - 'a' + 10; - else - return false; - - if (h >= '0' && h <= '9') - h = h - '0'; - else if (h >= 'A' && h <= 'F') - h = h - 'A' + 10; - else if (h >= 'a' && h <= 'f') - h = h - 'a' + 10; - else - return false; - - uint32_t c = l + (h << 4); - checksum.push(c); - *data = (uint8_t)c; - } - return true; -} - -//----------------------------------------------------------------------------- - -/* TODO: replace my 'libmera' fomr t1ha. */ -uint64_t entropy_ticks(void) { -#if defined(EMSCRIPTEN) - return (uint64_t)emscripten_get_now(); -#endif /* EMSCRIPTEN */ - -#if defined(__APPLE__) || defined(__MACH__) - return mach_absolute_time(); -#endif /* defined(__APPLE__) || defined(__MACH__) */ - -#if defined(__sun__) || defined(__sun) - return gethrtime(); -#endif /* __sun__ */ - -#if defined(__GNUC__) || defined(__clang__) - -#if defined(__ia64__) - uint64_t ticks; - __asm __volatile("mov %0=ar.itc" : "=r"(ticks)); - return ticks; -#elif defined(__hppa__) - uint64_t ticks; - __asm __volatile("mfctl 16, %0" : "=r"(ticks)); - return ticks; -#elif defined(__s390__) - uint64_t ticks; - __asm __volatile("stck 0(%0)" : : "a"(&(ticks)) : "memory", "cc"); - return ticks; -#elif defined(__alpha__) - uint64_t ticks; - __asm __volatile("rpcc %0" : "=r"(ticks)); - return ticks; -#elif defined(__sparc__) || defined(__sparc) || defined(__sparc64__) || \ - defined(__sparc64) || defined(__sparc_v8plus__) || \ - defined(__sparc_v8plus) || defined(__sparc_v8plusa__) || \ - defined(__sparc_v8plusa) || defined(__sparc_v9__) || defined(__sparc_v9) - - union { - uint64_t u64; - struct { -#if __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__ - uint32_t h, l; -#else - uint32_t l, h; -#endif - } u32; - } cycles; - -#if defined(__sparc_v8plus__) || defined(__sparc_v8plusa__) || \ - defined(__sparc_v9__) || defined(__sparc_v8plus) || \ - defined(__sparc_v8plusa) || defined(__sparc_v9) - -#if UINTPTR_MAX > 0xffffFFFFul || ULONG_MAX > 0xffffFFFFul || \ - defined(__sparc64__) || defined(__sparc64) - __asm __volatile("rd %%tick, %0" : "=r"(cycles.u64)); -#else - __asm __volatile("rd %%tick, %1; srlx %1, 32, %0" - : "=r"(cycles.u32.h), "=r"(cycles.u32.l)); -#endif /* __sparc64__ */ - -#else - __asm __volatile(".byte 0x83, 0x41, 0x00, 0x00; mov %%g1, %0" - : "=r"(cycles.u64) - : - : "%g1"); -#endif /* __sparc8plus__ || __sparc_v9__ */ - return cycles.u64; - -#elif (defined(__powerpc64__) || defined(__ppc64__) || defined(__ppc64) || \ - defined(__powerpc64)) - uint64_t ticks; - __asm __volatile("mfspr %0, 268" : "=r"(ticks)); - return ticks; -#elif (defined(__powerpc__) || defined(__ppc__) || defined(__powerpc) || \ - defined(__ppc)) -#if UINTPTR_MAX > 0xffffFFFFul || ULONG_MAX > 0xffffFFFFul - uint64_t ticks; - __asm __volatile("mftb %0" : "=r"(ticks)); - *now = ticks; -#else - uint64_t ticks; - uint32_t low, high_before, high_after; - __asm __volatile("mftbu %0; mftb %1; mftbu %2" - : "=r"(high_before), "=r"(low), "=r"(high_after)); - ticks = (uint64_t)high_after << 32; - ticks |= low & /* zeroes if high part has changed */ - ~(high_before - high_after); -#endif -#elif defined(__aarch64__) || (defined(__ARM_ARCH) && __ARM_ARCH > 7) - uint64_t virtual_timer; - __asm __volatile("mrs %0, cntvct_el0" : "=r"(virtual_timer)); - return virtual_timer; -#elif defined(__ARM_ARCH) && __ARM_ARCH > 5 && __ARM_ARCH < 8 - unsigned long pmccntr; - __asm __volatile("mrc p15, 0, %0, c9, c13, 0" : "=r"(pmccntr)); - return pmccntr; -#elif defined(__mips__) || defined(__mips) || defined(_R4000) - unsigned count; - __asm __volatile("rdhwr %0, $2" : "=r"(count)); - return count; -#endif /* arch selector */ -#endif /* __GNUC__ || __clang__ */ - -#if defined(__e2k__) || defined(__ia32__) - return __rdtsc(); -#elif defined(_M_ARM) - return __rdpmccntr64(); -#elif defined(_WIN32) || defined(_WIN64) || defined(_WINDOWS) - LARGE_INTEGER PerformanceCount; - if (QueryPerformanceCounter(&PerformanceCount)) - return PerformanceCount.QuadPart; - return GetTickCount64(); -#else - struct timespec ts; -#if defined(CLOCK_MONOTONIC_COARSE) - clockid_t clock = CLOCK_MONOTONIC_COARSE; -#elif defined(CLOCK_MONOTONIC_RAW) - clockid_t clock = CLOCK_MONOTONIC_RAW; -#else - clockid_t clock = CLOCK_MONOTONIC; -#endif - int rc = clock_gettime(clock, &ts); - if (unlikely(rc)) - failure_perror("clock_gettime()", rc); - - return (((uint64_t)ts.tv_sec) << 32) + ts.tv_nsec; -#endif -} - -//----------------------------------------------------------------------------- - -static __inline uint64_t bleach64(uint64_t dirty) { - return mul_64x64_high(bswap64(dirty), UINT64_C(17048867929148541611)); -} - -static __inline uint32_t bleach32(uint32_t dirty) { - return (uint32_t)((bswap32(dirty) * UINT64_C(2175734609)) >> 32); -} - -uint64_t prng64_careless(uint64_t &state) { - state = state * UINT64_C(6364136223846793005) + 1; - return state; -} - -uint64_t prng64_white(uint64_t &state) { - state = state * UINT64_C(6364136223846793005) + UINT64_C(1442695040888963407); - return bleach64(state); -} - -uint32_t prng32(uint64_t &state) { - return (uint32_t)(prng64_careless(state) >> 32); -} - -void prng_fill(uint64_t &state, void *ptr, size_t bytes) { - while (bytes >= 4) { - *((uint32_t *)ptr) = prng32(state); - ptr = (uint32_t *)ptr + 1; - bytes -= 4; - } - - switch (bytes & 3) { - case 3: { - uint32_t u32 = prng32(state); - memcpy(ptr, &u32, 3); - } break; - case 2: - *((uint16_t *)ptr) = (uint16_t)prng32(state); - break; - case 1: - *((uint8_t *)ptr) = (uint8_t)prng32(state); - break; - case 0: - break; - } -} - -static __thread uint64_t prng_state; - -void prng_seed(uint64_t seed) { prng_state = bleach64(seed); } - -uint32_t prng32(void) { return prng32(prng_state); } - -uint64_t prng64(void) { return prng64_white(prng_state); } - -void prng_fill(void *ptr, size_t bytes) { prng_fill(prng_state, ptr, bytes); } - -uint64_t entropy_white() { return bleach64(entropy_ticks()); } - -double double_from_lower(uint64_t salt) { -#ifdef IEEE754_DOUBLE_BIAS - ieee754_double r; - r.ieee.negative = 0; - r.ieee.exponent = IEEE754_DOUBLE_BIAS; - r.ieee.mantissa0 = (unsigned)(salt >> 32); - r.ieee.mantissa1 = (unsigned)salt; - return r.d; -#else - const uint64_t top = (UINT64_C(1) << DBL_MANT_DIG) - 1; - const double scale = 1.0 / (double)top; - return (salt & top) * scale; -#endif -} - -double double_from_upper(uint64_t salt) { -#ifdef IEEE754_DOUBLE_BIAS - ieee754_double r; - r.ieee.negative = 0; - r.ieee.exponent = IEEE754_DOUBLE_BIAS; - salt >>= 64 - DBL_MANT_DIG; - r.ieee.mantissa0 = (unsigned)(salt >> 32); - r.ieee.mantissa1 = (unsigned)salt; - return r.d; -#else - const uint64_t top = (UINT64_C(1) << DBL_MANT_DIG) - 1; - const double scale = 1.0 / (double)top; - return (salt >> (64 - DBL_MANT_DIG)) * scale; -#endif -} - -bool flipcoin() { return bleach32((uint32_t)entropy_ticks()) & 1; } - -bool jitter(unsigned probability_percent) { - const uint32_t top = UINT32_MAX - UINT32_MAX % 100; - uint32_t dice, edge = (top) / 100 * probability_percent; - do - dice = bleach32((uint32_t)entropy_ticks()); - while (dice >= top); - return dice < edge; -} - -void jitter_delay(bool extra) { - unsigned dice = entropy_white() & 3; - if (dice == 0) { - log_trace("== jitter.no-delay"); - } else { - log_trace(">> jitter.delay: dice %u", dice); - do { - cpu_relax(); - memory_barrier(); - cpu_relax(); - if (dice > 1) { - osal_yield(); - cpu_relax(); - if (dice > 2) { - unsigned us = entropy_white() & - (extra ? 0xfffff /* 1.05 s */ : 0x3ff /* 1 ms */); - log_trace("== jitter.delay: %0.6f", us / 1000000.0); - osal_udelay(us); - } - } - } while (flipcoin()); - log_trace("<< jitter.delay: dice %u", dice); - } -} diff --git a/plugins/Dbx_mdbx/src/libmdbx/test/utils.h b/plugins/Dbx_mdbx/src/libmdbx/test/utils.h deleted file mode 100644 index 5d62909fd5..0000000000 --- a/plugins/Dbx_mdbx/src/libmdbx/test/utils.h +++ /dev/null @@ -1,337 +0,0 @@ -/* - * Copyright 2017-2018 Leonid Yuriev <leo@yuriev.ru> - * and other libmdbx authors: please see AUTHORS file. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted only as authorized by the OpenLDAP - * Public License. - * - * A copy of this license is available in the file LICENSE in the - * top-level directory of the distribution or, alternatively, at - * <http://www.OpenLDAP.org/license.html>. - */ - -#pragma once -#include "base.h" - -#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__ -#error Unsupported byte order. -#endif - -#if __GNUC_PREREQ(4, 4) || defined(__clang__) -#define bswap64(v) __builtin_bswap64(v) -#define bswap32(v) __builtin_bswap32(v) -#if __GNUC_PREREQ(4, 8) || __has_builtin(__builtin_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.") -#endif - -#define bswap64(v) _byteswap_uint64(v) -#define bswap32(v) _byteswap_ulong(v) -#define bswap16(v) _byteswap_ushort(v) -#define rot64(v, s) _rotr64(v, s) -#define rot32(v, s) _rotr(v, s) - -#if defined(_M_ARM64) || defined(_M_X64) || defined(_M_IA64) -#pragma intrinsic(_umul128) -#define mul_64x64_128(a, b, ph) _umul128(a, b, ph) -#pragma intrinsic(__umulh) -#define mul_64x64_high(a, b) __umulh(a, b) -#endif - -#if defined(_M_IX86) -#pragma intrinsic(__emulu) -#define mul_32x32_64(a, b) __emulu(a, b) -#elif defined(_M_ARM) -#define mul_32x32_64(a, b) _arm_umull(a, b) -#endif - -#endif /* compiler */ - -#ifndef bswap64 -#ifdef __bswap_64 -#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)); -} -#endif -#endif /* bswap64 */ - -#ifndef bswap32 -#ifdef __bswap_32 -#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)); -} -#endif -#endif /* bswap32 */ - -#ifndef bswap16 -#ifdef __bswap_16 -#define bswap16(v) __bswap_16(v) -#else -static __inline uint16_t bswap16(uint16_t v) { return v << 8 | v >> 8; } -#endif -#endif /* bswap16 */ - -#define is_byteorder_le() (__BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__) -#define is_byteorder_be() (__BYTE_ORDER__ == __ORDER_BIG_ENDIAN__) - -#ifndef htole16 -#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ -#define htobe16(v) bswap16(v) -#define htole16(v) (v) -#define be16toh(v) bswap16(v) -#define le16toh(v) (v) -#else -#define htobe16(v) (v) -#define htole16(v) bswap16(v) -#define be16toh(v) (v) -#define le16toh(v) bswap16(v) -#endif -#endif /* htole16 */ - -#ifndef htole32 -#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ -#define htobe32(v) bswap32(v) -#define htole32(v) (v) -#define be32toh(v) bswap32(v) -#define le32toh(v) (v) -#else -#define htobe32(v) (v) -#define htole32(v) bswap32(v) -#define be32toh(v) (v) -#define le32toh(v) bswap32(v) -#endif -#endif /* htole32 */ - -#ifndef htole64 -#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ -#define htobe64(v) bswap64(v) -#define htole64(v) (v) -#define be64toh(v) bswap64(v) -#define le64toh(v) (v) -#else -#define htobe64(v) (v) -#define htole64(v) bswap_64(v) -#define be64toh(v) (v) -#define le64toh(v) bswap_64(v) -#endif -#endif /* htole64 */ - -namespace unaligned { - -template <typename T> static __inline T load(const void *ptr) { -#if defined(_MSC_VER) && \ - (defined(_M_ARM64) || defined(_M_X64) || defined(_M_IA64)) - return *(const T __unaligned *)ptr; -#elif UNALIGNED_OK - return *(const T *)ptr; -#else - T local; -#if defined(__GNUC__) || defined(__clang__) - __builtin_memcpy(&local, (const T *)ptr, sizeof(T)); -#else - memcpy(&local, (const T *)ptr, sizeof(T)); -#endif /* __GNUC__ || __clang__ */ - return local; -#endif /* UNALIGNED_OK */ -} - -template <typename T> static __inline void store(void *ptr, const T &value) { -#if defined(_MSC_VER) && \ - (defined(_M_ARM64) || defined(_M_X64) || defined(_M_IA64)) - *((T __unaligned *)ptr) = value; -#elif UNALIGNED_OK - *(volatile T *)ptr = value; -#else -#if defined(__GNUC__) || defined(__clang__) - __builtin_memcpy(ptr, &value, sizeof(T)); -#else - memcpy(ptr, &value, sizeof(T)); -#endif /* __GNUC__ || __clang__ */ -#endif /* UNALIGNED_OK */ -} - -} /* namespace unaligned */ - -//----------------------------------------------------------------------------- - -#ifndef rot64 -static __inline uint64_t rot64(uint64_t v, unsigned s) { - return (v >> s) | (v << (64 - s)); -} -#endif /* rot64 */ - -#ifndef mul_32x32_64 -static __inline uint64_t mul_32x32_64(uint32_t a, uint32_t b) { - return a * (uint64_t)b; -} -#endif /* mul_32x32_64 */ - -#ifndef mul_64x64_128 - -static __inline unsigned add_with_carry(uint64_t *sum, uint64_t addend) { - *sum += addend; - return (*sum < addend) ? 1u : 0u; -} - -static __inline uint64_t mul_64x64_128(uint64_t a, uint64_t b, uint64_t *h) { -#if defined(__SIZEOF_INT128__) || \ - (defined(_INTEGRAL_MAX_BITS) && _INTEGRAL_MAX_BITS >= 128) - __uint128_t r = (__uint128_t)a * (__uint128_t)b; - /* modern GCC could nicely optimize this */ - *h = r >> 64; - return r; -#elif defined(mul_64x64_high) - *h = mul_64x64_high(a, b); - return a * b; -#else - /* performs 64x64 to 128 bit multiplication */ - uint64_t ll = mul_32x32_64((uint32_t)a, (uint32_t)b); - uint64_t lh = mul_32x32_64(a >> 32, (uint32_t)b); - uint64_t hl = mul_32x32_64((uint32_t)a, b >> 32); - *h = mul_32x32_64(a >> 32, b >> 32) + (lh >> 32) + (hl >> 32) + - add_with_carry(&ll, lh << 32) + add_with_carry(&ll, hl << 32); - return ll; -#endif -} - -#endif /* mul_64x64_128() */ - -#ifndef mul_64x64_high -static __inline uint64_t mul_64x64_high(uint64_t a, uint64_t b) { - uint64_t h; - mul_64x64_128(a, b, &h); - return h; -} -#endif /* mul_64x64_high */ - -static __inline bool is_power2(size_t x) { return (x & (x - 1)) == 0; } - -static __inline size_t roundup2(size_t value, size_t granularity) { - assert(is_power2(granularity)); - return (value + granularity - 1) & ~(granularity - 1); -} - -//----------------------------------------------------------------------------- - -static __inline void memory_barrier(void) { -#if __has_extension(c_atomic) || __has_extension(cxx_atomic) - __c11_atomic_thread_fence(__ATOMIC_SEQ_CST); -#elif defined(__ATOMIC_SEQ_CST) - __atomic_thread_fence(__ATOMIC_SEQ_CST); -#elif defined(__clang__) || defined(__GNUC__) - __sync_synchronize(); -#elif defined(_MSC_VER) - MemoryBarrier(); -#elif defined(__INTEL_COMPILER) /* LY: Intel Compiler may mimic GCC and MSC */ -#if defined(__ia64__) || defined(__ia64) || defined(_M_IA64) - __mf(); -#elif defined(__ia32__) - _mm_mfence(); -#else -#error "Unknown target for Intel Compiler, please report to us." -#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)) - _Asm_mf(); -#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." -#endif -} - -static __inline void cpu_relax() { -#if defined(__ia32__) - _mm_pause(); -#elif defined(_WIN32) || defined(_WIN64) || defined(_WINDOWS) || \ - defined(YieldProcessor) - YieldProcessor(); -#else -/* nope */ -#endif -} - -//----------------------------------------------------------------------------- - -struct simple_checksum { - uint64_t value; - - simple_checksum() : value(0) {} - - void push(uint32_t data) { - value += data * UINT64_C(9386433910765580089) + 1; - value ^= value >> 41; - } - - void push(uint64_t data) { - push((uint32_t)data); - push((uint32_t)(data >> 32)); - } - - void push(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; - for (size_t i = 0; i < bytes; ++i) - push((uint32_t)data[i]); - } - - void push(const double &data) { push(&data, sizeof(double)); } - - void push(const char *cstr) { push(cstr, strlen(cstr)); } - - void push(const std::string &str) { push(str.data(), str.size()); } - -#if defined(_WIN32) || defined(_WIN64) || defined(_WINDOWS) - void push(const HANDLE &handle) { push(&handle, sizeof(handle)); } -#endif /* _WINDOWS */ -}; - -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); - -std::string format(const char *fmt, ...); - -uint64_t entropy_ticks(void); -uint64_t entropy_white(void); -uint64_t prng64_careless(uint64_t &state); -uint64_t prng64_white(uint64_t &state); -uint32_t prng32(uint64_t &state); -void prng_fill(uint64_t &state, void *ptr, size_t bytes); - -void prng_seed(uint64_t seed); -uint32_t prng32(void); -uint64_t prng64(void); -void prng_fill(void *ptr, size_t bytes); - -bool flipcoin(); -bool jitter(unsigned probability_percent); -void jitter_delay(bool extra = false); |
