summaryrefslogtreecommitdiff
path: root/libs/libmdbx/src/test/nested.cc
diff options
context:
space:
mode:
Diffstat (limited to 'libs/libmdbx/src/test/nested.cc')
-rw-r--r--libs/libmdbx/src/test/nested.cc286
1 files changed, 0 insertions, 286 deletions
diff --git a/libs/libmdbx/src/test/nested.cc b/libs/libmdbx/src/test/nested.cc
deleted file mode 100644
index 85df6fa62b..0000000000
--- a/libs/libmdbx/src/test/nested.cc
+++ /dev/null
@@ -1,286 +0,0 @@
-/*
- * Copyright 2017-2020 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 <cmath>
-
-/* LY: тест "эмуляцией time-to-live" с вложенными транзакциями:
- * - организуется "скользящее окно", которое каждую транзакцию сдвигается
- * вперед вдоль числовой оси.
- * - по переднему краю "скользящего окна" записи добавляются в таблицу,
- * а по заднему удаляются.
- * - количество добавляемых/удаляемых записей псевдослучайно зависит
- * от номера транзакции, но с экспоненциальным распределением.
- * - размер "скользящего окна" также псевдослучайно зависит от номера
- * транзакции с "отрицательным" экспоненциальным распределением
- * MAX_WIDTH - exp(rnd(N)), при уменьшении окна сдвигается задний
- * край и удаляются записи позади него.
- * - групповое добавление данных в начало окна и групповое удаление в конце,
- * преимущественно выполняются во вложенных транзакциях.
- * - меньшая часть запускаемых вложенных транзакций отменяется, с последующим
- * продолжением итераций с состояния предыдущиего коммита.
- *
- * Таким образом имитируется поведение таблицы с TTL: записи стохастически
- * добавляются и удаляются, и изредка происходят массивные удаления. */
-
-bool testcase_nested::setup() {
- if (!inherited::setup())
- return false;
- int err = db_open__begin__table_create_open_clean(dbi);
- if (unlikely(err != MDBX_SUCCESS)) {
- log_notice("nested: bailout-prepare due '%s'", mdbx_strerror(err));
- return false;
- }
-
- keyvalue_maker.setup(config.params, config.actor_id, 0 /* thread_number */);
- key = keygen::alloc(config.params.keylen_max);
- data = keygen::alloc(config.params.datalen_max);
- serial = 0;
- fifo.clear();
- speculum.clear();
- assert(stack.empty());
- stack.emplace(nullptr, serial, fifo, speculum);
- return true;
-}
-
-bool testcase_nested::teardown() {
- while (!stack.empty())
- pop_txn(true);
-
- bool ok = true;
- if (dbi) {
- if (config.params.drop_table && !mode_readonly()) {
- txn_begin(false);
- db_table_drop(dbi);
- int err = breakable_commit();
- if (unlikely(err != MDBX_SUCCESS)) {
- log_notice("nested: bailout-clean due '%s'", mdbx_strerror(err));
- ok = false;
- }
- } else
- db_table_close(dbi);
- dbi = 0;
- }
- return inherited::teardown() && ok;
-}
-
-void testcase_nested::push_txn() {
- MDBX_txn *txn;
- unsigned flags =
- prng32() & (MDBX_SAFE_NOSYNC | MDBX_NOMETASYNC | MDBX_MAPASYNC);
- int err = mdbx_txn_begin(db_guard.get(), txn_guard.get(), flags, &txn);
- if (unlikely(err != MDBX_SUCCESS))
- failure_perror("mdbx_txn_begin(nested)", err);
- stack.emplace(scoped_txn_guard(txn), serial, fifo, speculum);
- std::swap(txn_guard, std::get<0>(stack.top()));
- log_verbose("begin level#%zu txn #%" PRIu64 ", flags 0x%x, serial %" PRIu64,
- stack.size(), mdbx_txn_id(txn), flags, serial);
-}
-
-bool testcase_nested::pop_txn(bool abort) {
- assert(txn_guard && !stack.empty());
- bool should_continue = true;
- MDBX_txn *txn = txn_guard.release();
- bool commited = false;
- if (abort) {
- log_verbose(
- "abort level#%zu txn #%" PRIu64 ", undo serial %" PRIu64 " <- %" PRIu64,
- stack.size(), mdbx_txn_id(txn), serial, std::get<1>(stack.top()));
- int err = mdbx_txn_abort(txn);
- if (unlikely(err != MDBX_SUCCESS))
- failure_perror("mdbx_txn_abort()", err);
- } else {
- log_verbose("commit level#%zu txn, nested serial %" PRIu64 " -> %" PRIu64,
- stack.size(), serial, std::get<1>(stack.top()));
- int err = mdbx_txn_commit(txn);
- if (likely(err == MDBX_SUCCESS))
- commited = true;
- else {
- should_continue = false;
- if (err == MDBX_MAP_FULL && config.params.ignore_dbfull) {
- err = mdbx_txn_abort(txn);
- if (unlikely(err != MDBX_SUCCESS && err != MDBX_THREAD_MISMATCH &&
- err != MDBX_BAD_TXN))
- failure_perror("mdbx_txn_abort()", err);
- } else
- failure_perror("mdbx_txn_commit()", err);
- }
- }
-
- std::swap(txn_guard, std::get<0>(stack.top()));
- if (!commited) {
- serial = std::get<1>(stack.top());
- std::swap(fifo, std::get<2>(stack.top()));
- std::swap(speculum, std::get<3>(stack.top()));
- }
- stack.pop();
- return should_continue;
-}
-
-bool testcase_nested::stochastic_breakable_restart_with_nested(
- bool force_restart) {
- log_trace(">> stochastic_breakable_restart_with_nested%s",
- force_restart ? ": force_restart" : "");
-
- if (force_restart)
- while (txn_guard)
- pop_txn(true);
-
- bool should_continue = true;
- while (!stack.empty() &&
- (flipcoin() || txn_underutilization_x256(txn_guard.get()) < 42))
- should_continue &= pop_txn();
-
- if (should_continue)
- while (stack.empty() ||
- (is_nested_txn_available() && flipcoin() && stack.size() < 5))
- push_txn();
-
- log_trace("<< stochastic_breakable_restart_with_nested: should_continue=%s",
- should_continue ? "yes" : "no");
- return should_continue;
-}
-
-bool testcase_nested::trim_tail(unsigned window_width) {
- if (window_width || flipcoin()) {
- clear_stepbystep_passed += window_width == 0;
- while (fifo.size() > window_width) {
- uint64_t tail_serial = fifo.back().first;
- const unsigned tail_count = fifo.back().second;
- log_verbose("nested: pop-tail (serial %" PRIu64 ", count %u)",
- tail_serial, tail_count);
- fifo.pop_back();
- for (unsigned n = 0; n < tail_count; ++n) {
- log_trace("nested: remove-tail %" PRIu64, tail_serial);
- generate_pair(tail_serial);
- int err = remove(key, data);
- if (unlikely(err != MDBX_SUCCESS)) {
- if (err == MDBX_MAP_FULL && config.params.ignore_dbfull) {
- log_notice("nested: tail-bailout due '%s'", mdbx_strerror(err));
- return false;
- }
- failure_perror("mdbx_del(tail)", err);
- }
- if (unlikely(!keyvalue_maker.increment(tail_serial, 1)))
- failure("nested: unexpected key-space overflow on the tail");
- }
- report(tail_count);
- }
- } else if (!fifo.empty()) {
- log_verbose("nested: purge state %" PRIu64 " - %" PRIu64 ", fifo-items %zu",
- fifo.front().first, fifo.back().first + fifo.back().second,
- fifo.size());
- db_table_clear(dbi, txn_guard.get());
- fifo.clear();
- clear_wholetable_passed += 1;
- report(1);
- }
- return true;
-}
-
-bool testcase_nested::grow_head(unsigned head_count) {
- const unsigned insert_flags = (config.params.table_flags & MDBX_DUPSORT)
- ? MDBX_NODUPDATA
- : MDBX_NODUPDATA | MDBX_NOOVERWRITE;
-retry:
- fifo.push_front(std::make_pair(serial, head_count));
- for (unsigned n = 0; n < head_count; ++n) {
- log_trace("nested: insert-head %" PRIu64, serial);
- generate_pair(serial);
- int err = insert(key, data, insert_flags);
- if (unlikely(err != MDBX_SUCCESS)) {
- if (err == MDBX_MAP_FULL && config.params.ignore_dbfull) {
- log_notice("nested: head-insert skip due '%s'", mdbx_strerror(err));
- head_count = n;
- stochastic_breakable_restart_with_nested(true);
- dbfull_passed += 1;
- goto retry;
- }
- failure_perror("mdbx_put(head)", err);
- }
-
- if (unlikely(!keyvalue_maker.increment(serial, 1))) {
- log_notice("nested: unexpected key-space overflow");
- keyspace_overflow = true;
- head_count = n;
- stochastic_breakable_restart_with_nested(true);
- goto retry;
- }
- }
-
- return true;
-}
-
-bool testcase_nested::run() {
- uint64_t seed =
- prng64_map2_white(config.params.keygen.seed) + config.actor_id;
-
- clear_wholetable_passed = 0;
- clear_stepbystep_passed = 0;
- dbfull_passed = 0;
- unsigned loops = 0;
- while (true) {
- const uint64_t salt = prng64_white(seed) /* mdbx_txn_id(txn_guard.get()) */;
- const unsigned window_width =
- (!should_continue() || flipcoin_x4()) ? 0 : edge2window(salt);
- const unsigned head_count = edge2count(salt);
- log_debug("nested: step #%" PRIu64 " (serial %" PRIu64
- ", window %u, count %u) salt %" PRIu64,
- nops_completed, serial, window_width, head_count, salt);
-
- if (!trim_tail(window_width))
- return false;
- if (!stochastic_breakable_restart_with_nested()) {
- log_notice("nested: bailout at commit/restart after tail-trim");
- return false;
- }
- if (!speculum_verify()) {
- log_notice("nested: bailout after tail-trim");
- return false;
- }
-
- if (!keyspace_overflow && (should_continue() || !clear_wholetable_passed ||
- !clear_stepbystep_passed)) {
- unsigned underutilization_x256 =
- txn_underutilization_x256(txn_guard.get());
- if (dbfull_passed > underutilization_x256) {
- log_notice("nested: skip head-grow to avoid one more dbfull (was %u, "
- "underutilization %.2f%%)",
- dbfull_passed, underutilization_x256 / 2.560);
- continue;
- }
- if (!grow_head(head_count))
- return false;
- if (!stochastic_breakable_restart_with_nested())
- log_notice("nested: skip commit/restart after head-grow");
- if (!speculum_verify()) {
- log_notice("nested: bailout after head-grow");
- return false;
- }
- loops += 1;
- } else if (fifo.empty()) {
- log_notice("nested: done %u whole loops, %" PRIu64 " ops, %" PRIu64
- " items",
- loops, nops_completed, serial);
- break;
- } else {
- log_notice("nested: done, wait for empty, skip head-grow");
- }
- }
-
- while (!stack.empty())
- pop_txn(false);
-
- return speculum_verify();
-}