mdbxmou 0.1.26
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.github/workflows/ci.yml +32 -0
- package/.github/workflows/publish.yml +27 -0
- package/.gitmodules +3 -0
- package/CMakeLists.txt +53 -0
- package/LICENSE +201 -0
- package/README.md +639 -0
- package/build.js +11 -0
- package/deps/libmdbx/.clang-format +3 -0
- package/deps/libmdbx/.cmake-format.yaml +3 -0
- package/deps/libmdbx/.le.ini +40 -0
- package/deps/libmdbx/CMakeLists.txt +1269 -0
- package/deps/libmdbx/COPYRIGHT +159 -0
- package/deps/libmdbx/ChangeLog.md +2786 -0
- package/deps/libmdbx/GNUmakefile +950 -0
- package/deps/libmdbx/LICENSE +177 -0
- package/deps/libmdbx/Makefile +16 -0
- package/deps/libmdbx/NOTICE +39 -0
- package/deps/libmdbx/README.md +863 -0
- package/deps/libmdbx/TODO.md +43 -0
- package/deps/libmdbx/cmake/compiler.cmake +1221 -0
- package/deps/libmdbx/cmake/profile.cmake +58 -0
- package/deps/libmdbx/cmake/utils.cmake +524 -0
- package/deps/libmdbx/conanfile.py +323 -0
- package/deps/libmdbx/docs/Doxyfile.in +2734 -0
- package/deps/libmdbx/docs/_preface.md +47 -0
- package/deps/libmdbx/docs/_restrictions.md +248 -0
- package/deps/libmdbx/docs/_starting.md +245 -0
- package/deps/libmdbx/docs/_toc.md +34 -0
- package/deps/libmdbx/docs/header.html +96 -0
- package/deps/libmdbx/example/CMakeLists.txt +6 -0
- package/deps/libmdbx/example/README.md +1 -0
- package/deps/libmdbx/example/example-mdbx.c +154 -0
- package/deps/libmdbx/example/sample-bdb.txt +77 -0
- package/deps/libmdbx/mdbx.h +6655 -0
- package/deps/libmdbx/mdbx.h++ +6428 -0
- package/deps/libmdbx/packages/buildroot/0001-package-libmdbx-new-package-library-database.patch +173 -0
- package/deps/libmdbx/src/alloy.c +54 -0
- package/deps/libmdbx/src/api-cold.c +543 -0
- package/deps/libmdbx/src/api-copy.c +912 -0
- package/deps/libmdbx/src/api-cursor.c +754 -0
- package/deps/libmdbx/src/api-dbi.c +315 -0
- package/deps/libmdbx/src/api-env.c +1434 -0
- package/deps/libmdbx/src/api-extra.c +165 -0
- package/deps/libmdbx/src/api-key-transform.c +197 -0
- package/deps/libmdbx/src/api-misc.c +286 -0
- package/deps/libmdbx/src/api-opts.c +575 -0
- package/deps/libmdbx/src/api-range-estimate.c +365 -0
- package/deps/libmdbx/src/api-txn-data.c +454 -0
- package/deps/libmdbx/src/api-txn.c +921 -0
- package/deps/libmdbx/src/atomics-ops.h +364 -0
- package/deps/libmdbx/src/atomics-types.h +97 -0
- package/deps/libmdbx/src/audit.c +109 -0
- package/deps/libmdbx/src/bits.md +34 -0
- package/deps/libmdbx/src/chk.c +1796 -0
- package/deps/libmdbx/src/cogs.c +309 -0
- package/deps/libmdbx/src/cogs.h +506 -0
- package/deps/libmdbx/src/coherency.c +170 -0
- package/deps/libmdbx/src/config.h.in +88 -0
- package/deps/libmdbx/src/cursor.c +2396 -0
- package/deps/libmdbx/src/cursor.h +391 -0
- package/deps/libmdbx/src/dbi.c +717 -0
- package/deps/libmdbx/src/dbi.h +142 -0
- package/deps/libmdbx/src/debug_begin.h +36 -0
- package/deps/libmdbx/src/debug_end.h +15 -0
- package/deps/libmdbx/src/dpl.c +486 -0
- package/deps/libmdbx/src/dpl.h +134 -0
- package/deps/libmdbx/src/dxb.c +1335 -0
- package/deps/libmdbx/src/env.c +607 -0
- package/deps/libmdbx/src/essentials.h +125 -0
- package/deps/libmdbx/src/gc-get.c +1345 -0
- package/deps/libmdbx/src/gc-put.c +970 -0
- package/deps/libmdbx/src/gc.h +40 -0
- package/deps/libmdbx/src/global.c +474 -0
- package/deps/libmdbx/src/internals.h +585 -0
- package/deps/libmdbx/src/layout-dxb.h +288 -0
- package/deps/libmdbx/src/layout-lck.h +289 -0
- package/deps/libmdbx/src/lck-posix.c +859 -0
- package/deps/libmdbx/src/lck-windows.c +607 -0
- package/deps/libmdbx/src/lck.c +174 -0
- package/deps/libmdbx/src/lck.h +110 -0
- package/deps/libmdbx/src/logging_and_debug.c +250 -0
- package/deps/libmdbx/src/logging_and_debug.h +159 -0
- package/deps/libmdbx/src/man1/mdbx_chk.1 +106 -0
- package/deps/libmdbx/src/man1/mdbx_copy.1 +95 -0
- package/deps/libmdbx/src/man1/mdbx_drop.1 +48 -0
- package/deps/libmdbx/src/man1/mdbx_dump.1 +101 -0
- package/deps/libmdbx/src/man1/mdbx_load.1 +105 -0
- package/deps/libmdbx/src/man1/mdbx_stat.1 +86 -0
- package/deps/libmdbx/src/mdbx.c++ +1837 -0
- package/deps/libmdbx/src/meta.c +656 -0
- package/deps/libmdbx/src/meta.h +168 -0
- package/deps/libmdbx/src/mvcc-readers.c +414 -0
- package/deps/libmdbx/src/node.c +365 -0
- package/deps/libmdbx/src/node.h +102 -0
- package/deps/libmdbx/src/ntdll.def +1246 -0
- package/deps/libmdbx/src/options.h +534 -0
- package/deps/libmdbx/src/osal.c +3485 -0
- package/deps/libmdbx/src/osal.h +587 -0
- package/deps/libmdbx/src/page-get.c +483 -0
- package/deps/libmdbx/src/page-iov.c +185 -0
- package/deps/libmdbx/src/page-iov.h +34 -0
- package/deps/libmdbx/src/page-ops.c +744 -0
- package/deps/libmdbx/src/page-ops.h +142 -0
- package/deps/libmdbx/src/pnl.c +236 -0
- package/deps/libmdbx/src/pnl.h +146 -0
- package/deps/libmdbx/src/preface.h +990 -0
- package/deps/libmdbx/src/proto.h +105 -0
- package/deps/libmdbx/src/refund.c +212 -0
- package/deps/libmdbx/src/sort.h +484 -0
- package/deps/libmdbx/src/spill.c +431 -0
- package/deps/libmdbx/src/spill.h +74 -0
- package/deps/libmdbx/src/table.c +107 -0
- package/deps/libmdbx/src/tls.c +551 -0
- package/deps/libmdbx/src/tls.h +43 -0
- package/deps/libmdbx/src/tools/chk.c +673 -0
- package/deps/libmdbx/src/tools/copy.c +166 -0
- package/deps/libmdbx/src/tools/drop.c +199 -0
- package/deps/libmdbx/src/tools/dump.c +515 -0
- package/deps/libmdbx/src/tools/load.c +831 -0
- package/deps/libmdbx/src/tools/stat.c +516 -0
- package/deps/libmdbx/src/tools/wingetopt.c +87 -0
- package/deps/libmdbx/src/tools/wingetopt.h +30 -0
- package/deps/libmdbx/src/tree-ops.c +1554 -0
- package/deps/libmdbx/src/tree-search.c +140 -0
- package/deps/libmdbx/src/txl.c +99 -0
- package/deps/libmdbx/src/txl.h +26 -0
- package/deps/libmdbx/src/txn.c +1083 -0
- package/deps/libmdbx/src/unaligned.h +205 -0
- package/deps/libmdbx/src/utils.c +32 -0
- package/deps/libmdbx/src/utils.h +76 -0
- package/deps/libmdbx/src/version.c.in +44 -0
- package/deps/libmdbx/src/walk.c +290 -0
- package/deps/libmdbx/src/walk.h +20 -0
- package/deps/libmdbx/src/windows-import.c +152 -0
- package/deps/libmdbx/src/windows-import.h +128 -0
- package/deps/libmdbx/test/CMakeLists.txt +317 -0
- package/deps/libmdbx/test/append.c++ +237 -0
- package/deps/libmdbx/test/base.h++ +92 -0
- package/deps/libmdbx/test/battery-tmux.sh +64 -0
- package/deps/libmdbx/test/cases.c++ +118 -0
- package/deps/libmdbx/test/chrono.c++ +134 -0
- package/deps/libmdbx/test/chrono.h++ +85 -0
- package/deps/libmdbx/test/config.c++ +643 -0
- package/deps/libmdbx/test/config.h++ +334 -0
- package/deps/libmdbx/test/copy.c++ +62 -0
- package/deps/libmdbx/test/dead.c++ +39 -0
- package/deps/libmdbx/test/dump-load.sh +40 -0
- package/deps/libmdbx/test/extra/crunched_delete.c++ +409 -0
- package/deps/libmdbx/test/extra/cursor_closing.c++ +410 -0
- package/deps/libmdbx/test/extra/dbi.c++ +229 -0
- package/deps/libmdbx/test/extra/doubtless_positioning.c++ +253 -0
- package/deps/libmdbx/test/extra/dupfix_addodd.c +94 -0
- package/deps/libmdbx/test/extra/dupfix_multiple.c++ +311 -0
- package/deps/libmdbx/test/extra/early_close_dbi.c++ +137 -0
- package/deps/libmdbx/test/extra/hex_base64_base58.c++ +118 -0
- package/deps/libmdbx/test/extra/maindb_ordinal.c++ +61 -0
- package/deps/libmdbx/test/extra/open.c++ +96 -0
- package/deps/libmdbx/test/extra/pcrf/README.md +2 -0
- package/deps/libmdbx/test/extra/pcrf/pcrf_test.c +380 -0
- package/deps/libmdbx/test/extra/probe.c++ +10 -0
- package/deps/libmdbx/test/extra/txn.c++ +407 -0
- package/deps/libmdbx/test/extra/upsert_alldups.c +193 -0
- package/deps/libmdbx/test/fork.c++ +263 -0
- package/deps/libmdbx/test/hill.c++ +447 -0
- package/deps/libmdbx/test/jitter.c++ +197 -0
- package/deps/libmdbx/test/keygen.c++ +393 -0
- package/deps/libmdbx/test/keygen.h++ +130 -0
- package/deps/libmdbx/test/log.c++ +358 -0
- package/deps/libmdbx/test/log.h++ +91 -0
- package/deps/libmdbx/test/main.c++ +706 -0
- package/deps/libmdbx/test/nested.c++ +318 -0
- package/deps/libmdbx/test/osal-unix.c++ +647 -0
- package/deps/libmdbx/test/osal-windows.c++ +440 -0
- package/deps/libmdbx/test/osal.h++ +41 -0
- package/deps/libmdbx/test/stochastic.sh +690 -0
- package/deps/libmdbx/test/stub/LICENSE +24 -0
- package/deps/libmdbx/test/stub/README.md +8 -0
- package/deps/libmdbx/test/stub/pthread_barrier.c +104 -0
- package/deps/libmdbx/test/stub/pthread_barrier.h +77 -0
- package/deps/libmdbx/test/test.c++ +1551 -0
- package/deps/libmdbx/test/test.h++ +298 -0
- package/deps/libmdbx/test/tmux.conf +3 -0
- package/deps/libmdbx/test/try.c++ +30 -0
- package/deps/libmdbx/test/ttl.c++ +240 -0
- package/deps/libmdbx/test/utils.c++ +203 -0
- package/deps/libmdbx/test/utils.h++ +326 -0
- package/deps/libmdbx/test/valgrind_suppress.txt +536 -0
- package/lib/mdbx_evn_async.js +211 -0
- package/lib/mdbx_worker.js +195 -0
- package/lib/nativemou.js +6 -0
- package/package.json +38 -0
- package/src/async/envmou_close.cpp +34 -0
- package/src/async/envmou_close.hpp +32 -0
- package/src/async/envmou_copy_to.cpp +29 -0
- package/src/async/envmou_copy_to.hpp +38 -0
- package/src/async/envmou_keys.cpp +201 -0
- package/src/async/envmou_keys.hpp +50 -0
- package/src/async/envmou_open.cpp +38 -0
- package/src/async/envmou_open.hpp +33 -0
- package/src/async/envmou_query.cpp +167 -0
- package/src/async/envmou_query.hpp +53 -0
- package/src/dbimou.cpp +522 -0
- package/src/dbimou.hpp +82 -0
- package/src/env_arg0.hpp +24 -0
- package/src/envmou.cpp +445 -0
- package/src/envmou.hpp +116 -0
- package/src/modulemou.cpp +113 -0
- package/src/querymou.cpp +177 -0
- package/src/querymou.hpp +93 -0
- package/src/txnmou.cpp +254 -0
- package/src/txnmou.hpp +122 -0
- package/src/typemou.hpp +239 -0
- package/src/valuemou.hpp +194 -0
- package/test/async.js +67 -0
- package/test/e3.js +38 -0
- package/test/e4.js +89 -0
- package/test/e5.js +162 -0
- package/test/test-batch-ops.js +243 -0
- package/test/test-cursor-mode.js +84 -0
- package/test/test-multi-mode.js +87 -0
|
@@ -0,0 +1,197 @@
|
|
|
1
|
+
/// \author Леонид Юрьев aka Leonid Yuriev <leo@yuriev.ru> \date 2015-2025
|
|
2
|
+
/// \copyright SPDX-License-Identifier: Apache-2.0
|
|
3
|
+
|
|
4
|
+
#include "test.h++"
|
|
5
|
+
|
|
6
|
+
class testcase_jitter : public testcase {
|
|
7
|
+
protected:
|
|
8
|
+
void check_dbi_error(int expect, const char *stage);
|
|
9
|
+
|
|
10
|
+
public:
|
|
11
|
+
testcase_jitter(const actor_config &config, const mdbx_pid_t pid) : testcase(config, pid) {}
|
|
12
|
+
bool run() override;
|
|
13
|
+
};
|
|
14
|
+
REGISTER_TESTCASE(jitter);
|
|
15
|
+
|
|
16
|
+
void testcase_jitter::check_dbi_error(int expect, const char *stage) {
|
|
17
|
+
MDBX_stat stat;
|
|
18
|
+
int err = mdbx_dbi_stat(txn_guard.get(), dbi, &stat, sizeof(stat));
|
|
19
|
+
if (err != expect)
|
|
20
|
+
failure("unexpected result for %s dbi-handle: expect %d, got %d", stage, expect, err);
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
bool testcase_jitter::run() {
|
|
24
|
+
int err;
|
|
25
|
+
size_t upper_limit = config.params.size_upper;
|
|
26
|
+
if (upper_limit < 1)
|
|
27
|
+
upper_limit = config.params.size_now * 2;
|
|
28
|
+
|
|
29
|
+
tablename_buf buffer;
|
|
30
|
+
const char *const tablename = db_tablename(buffer);
|
|
31
|
+
tablename_buf buffer_renamed;
|
|
32
|
+
const char *const tablename_renamed = db_tablename(buffer_renamed, ".renamed");
|
|
33
|
+
|
|
34
|
+
while (should_continue()) {
|
|
35
|
+
jitter_delay();
|
|
36
|
+
db_open();
|
|
37
|
+
|
|
38
|
+
if (!dbi && !mode_readonly()) {
|
|
39
|
+
// create table
|
|
40
|
+
txn_begin(false);
|
|
41
|
+
dbi = db_table_open(true);
|
|
42
|
+
check_dbi_error(MDBX_SUCCESS, "created-uncommitted");
|
|
43
|
+
|
|
44
|
+
bool renamed = false;
|
|
45
|
+
if (flipcoin()) {
|
|
46
|
+
err = mdbx_dbi_rename(txn_guard.get(), dbi, tablename_renamed);
|
|
47
|
+
if (err != MDBX_SUCCESS)
|
|
48
|
+
failure_perror("jitter.rename-1", err);
|
|
49
|
+
renamed = true;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
// note: here and below the 4-byte length keys and value are used
|
|
53
|
+
// to be compatible with any Db-flags given from command line.
|
|
54
|
+
MDBX_val k = {(void *)"k000", 4}, v = {(void *)"v001", 4};
|
|
55
|
+
err = mdbx_put(txn_guard.get(), dbi, &k, &v, MDBX_UPSERT);
|
|
56
|
+
if (err != MDBX_SUCCESS)
|
|
57
|
+
failure_perror("jitter.put-1", err);
|
|
58
|
+
txn_end(false);
|
|
59
|
+
|
|
60
|
+
// drop & re-create table, but abort txn
|
|
61
|
+
txn_begin(false);
|
|
62
|
+
check_dbi_error(MDBX_SUCCESS, "created-committed");
|
|
63
|
+
err = mdbx_drop(txn_guard.get(), dbi, true);
|
|
64
|
+
if (unlikely(err != MDBX_SUCCESS))
|
|
65
|
+
failure_perror("mdbx_drop(delete=true)", err);
|
|
66
|
+
check_dbi_error(MDBX_BAD_DBI, "dropped-uncommitted");
|
|
67
|
+
dbi = db_table_open(true);
|
|
68
|
+
check_dbi_error(MDBX_SUCCESS, "recreated-uncommitted");
|
|
69
|
+
txn_end(true);
|
|
70
|
+
|
|
71
|
+
// check after aborted txn
|
|
72
|
+
txn_begin(false);
|
|
73
|
+
v = {(void *)"v002", 4};
|
|
74
|
+
err = mdbx_put(txn_guard.get(), dbi, &k, &v, MDBX_UPSERT);
|
|
75
|
+
if (err != MDBX_BAD_DBI)
|
|
76
|
+
failure_perror("jitter.put-2", err);
|
|
77
|
+
check_dbi_error(MDBX_BAD_DBI, "dropped-recreated-aborted");
|
|
78
|
+
// restore DBI
|
|
79
|
+
dbi = db_table_open(false, renamed);
|
|
80
|
+
if (renamed) {
|
|
81
|
+
err = mdbx_dbi_open(txn_guard.get(), tablename_renamed, flipcoin() ? MDBX_DB_ACCEDE : config.params.table_flags,
|
|
82
|
+
&dbi);
|
|
83
|
+
if (unlikely(err != MDBX_SUCCESS))
|
|
84
|
+
failure_perror("open-renamed", err);
|
|
85
|
+
err = mdbx_dbi_rename(txn_guard.get(), dbi, tablename);
|
|
86
|
+
if (err != MDBX_SUCCESS)
|
|
87
|
+
failure_perror("jitter.rename-2", err);
|
|
88
|
+
}
|
|
89
|
+
check_dbi_error(MDBX_SUCCESS, "dropped-recreated-aborted+reopened");
|
|
90
|
+
v = {(void *)"v003", 4};
|
|
91
|
+
err = mdbx_put(txn_guard.get(), dbi, &k, &v, MDBX_UPSERT);
|
|
92
|
+
if (err != MDBX_SUCCESS)
|
|
93
|
+
failure_perror("jitter.put-3", err);
|
|
94
|
+
txn_end(false);
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
if (upper_limit < 1) {
|
|
98
|
+
MDBX_envinfo info;
|
|
99
|
+
err = mdbx_env_info_ex(db_guard.get(), txn_guard.get(), &info, sizeof(info));
|
|
100
|
+
if (err)
|
|
101
|
+
failure_perror("mdbx_env_info_ex()", err);
|
|
102
|
+
upper_limit = (info.mi_geo.upper < INTPTR_MAX) ? (intptr_t)info.mi_geo.upper : INTPTR_MAX;
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
if (flipcoin()) {
|
|
106
|
+
jitter_delay();
|
|
107
|
+
txn_begin(true);
|
|
108
|
+
fetch_canary();
|
|
109
|
+
if (flipcoin()) {
|
|
110
|
+
MDBX_txn_info info;
|
|
111
|
+
err = mdbx_txn_reset(txn_guard.get());
|
|
112
|
+
if (err)
|
|
113
|
+
failure_perror("mdbx_txn_reset()", err);
|
|
114
|
+
err = mdbx_txn_info(txn_guard.get(), &info, false);
|
|
115
|
+
if (err != MDBX_BAD_TXN)
|
|
116
|
+
failure_perror("mdbx_txn_info(MDBX_BAD_TXN)", err);
|
|
117
|
+
err = mdbx_txn_reset(txn_guard.get());
|
|
118
|
+
if (err)
|
|
119
|
+
failure_perror("mdbx_txn_reset(again)", err);
|
|
120
|
+
err = mdbx_txn_break(txn_guard.get());
|
|
121
|
+
if (err)
|
|
122
|
+
failure_perror("mdbx_txn_break()", err);
|
|
123
|
+
|
|
124
|
+
err = mdbx_txn_abort(txn_guard.get());
|
|
125
|
+
if (err)
|
|
126
|
+
failure_perror("mdbx_txn_abort()", err);
|
|
127
|
+
txn_guard.release();
|
|
128
|
+
txn_begin(true);
|
|
129
|
+
err = mdbx_txn_reset(txn_guard.get());
|
|
130
|
+
if (err)
|
|
131
|
+
failure_perror("mdbx_txn_reset()", err);
|
|
132
|
+
|
|
133
|
+
err = mdbx_txn_renew(txn_guard.get());
|
|
134
|
+
if (err)
|
|
135
|
+
failure_perror("mdbx_txn_renew()", err);
|
|
136
|
+
err = mdbx_txn_info(txn_guard.get(), &info, false);
|
|
137
|
+
if (err)
|
|
138
|
+
failure_perror("mdbx_txn_info()", err);
|
|
139
|
+
}
|
|
140
|
+
jitter_delay();
|
|
141
|
+
txn_end(flipcoin());
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
const bool coin4size = flipcoin();
|
|
145
|
+
jitter_delay();
|
|
146
|
+
txn_begin(mode_readonly());
|
|
147
|
+
jitter_delay();
|
|
148
|
+
if (!mode_readonly()) {
|
|
149
|
+
fetch_canary();
|
|
150
|
+
update_canary(1);
|
|
151
|
+
if (global::config::geometry_jitter) {
|
|
152
|
+
err = mdbx_env_set_geometry(db_guard.get(), -1, -1, coin4size ? upper_limit * 2 / 3 : upper_limit * 3 / 2, -1,
|
|
153
|
+
-1, -1);
|
|
154
|
+
if (err != MDBX_SUCCESS && err != MDBX_UNABLE_EXTEND_MAPSIZE && err != MDBX_MAP_FULL && err != MDBX_TOO_LARGE &&
|
|
155
|
+
err != MDBX_EPERM)
|
|
156
|
+
failure_perror("mdbx_env_set_geometry-1", err);
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
if (flipcoin()) {
|
|
160
|
+
uint64_t unused;
|
|
161
|
+
err = mdbx_dbi_sequence(txn_guard.get(), MAIN_DBI, &unused, mode_readonly() ? 0 : 1);
|
|
162
|
+
if (err)
|
|
163
|
+
failure_perror("mdbx_dbi_sequence()", err);
|
|
164
|
+
}
|
|
165
|
+
txn_end(flipcoin());
|
|
166
|
+
|
|
167
|
+
if (global::config::geometry_jitter) {
|
|
168
|
+
err = mdbx_env_set_geometry(db_guard.get(), -1, -1, !coin4size ? upper_limit * 2 / 3 : upper_limit * 3 / 2, -1,
|
|
169
|
+
-1, -1);
|
|
170
|
+
if (err != MDBX_SUCCESS && err != MDBX_UNABLE_EXTEND_MAPSIZE && err != MDBX_MAP_FULL && err != MDBX_TOO_LARGE &&
|
|
171
|
+
err != MDBX_EPERM)
|
|
172
|
+
failure_perror("mdbx_env_set_geometry-2", err);
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
if (flipcoin()) {
|
|
176
|
+
jitter_delay();
|
|
177
|
+
txn_begin(true);
|
|
178
|
+
jitter_delay();
|
|
179
|
+
txn_end(flipcoin());
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
if (global::config::geometry_jitter) {
|
|
183
|
+
jitter_delay();
|
|
184
|
+
err = mdbx_env_set_geometry(db_guard.get(), -1, -1, upper_limit, -1, -1, -1);
|
|
185
|
+
if (err != MDBX_SUCCESS && err != MDBX_UNABLE_EXTEND_MAPSIZE && err != MDBX_MAP_FULL && err != MDBX_TOO_LARGE &&
|
|
186
|
+
err != MDBX_EPERM)
|
|
187
|
+
failure_perror("mdbx_env_set_geometry-3", err);
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
db_close();
|
|
191
|
+
|
|
192
|
+
/* just 'align' nops with other tests with batching */
|
|
193
|
+
const auto batching = std::max(config.params.batch_read, config.params.batch_write);
|
|
194
|
+
report(std::max(1u, batching / 2));
|
|
195
|
+
}
|
|
196
|
+
return true;
|
|
197
|
+
}
|
|
@@ -0,0 +1,393 @@
|
|
|
1
|
+
/// \author Леонид Юрьев aka Leonid Yuriev <leo@yuriev.ru> \date 2015-2025
|
|
2
|
+
/// \copyright SPDX-License-Identifier: Apache-2.0
|
|
3
|
+
|
|
4
|
+
#include "test.h++"
|
|
5
|
+
|
|
6
|
+
static const uint64_t primes[64] = {
|
|
7
|
+
/* */
|
|
8
|
+
0, 1, 3, 7, 13, 31, 61, 127, 251, 509, 1021, 2039, 4093, 8191, 16381,
|
|
9
|
+
/* */
|
|
10
|
+
UINT64_C(32749), UINT64_C(65521), UINT64_C(131071), UINT64_C(262139), UINT64_C(524287), UINT64_C(1048573),
|
|
11
|
+
UINT64_C(2097143), UINT64_C(4194301), UINT64_C(8388593), UINT64_C(16777213), UINT64_C(33554393), UINT64_C(67108859),
|
|
12
|
+
UINT64_C(134217689), UINT64_C(268435399), UINT64_C(536870909), UINT64_C(1073741789), UINT64_C(2147483647),
|
|
13
|
+
UINT64_C(4294967291), UINT64_C(8589934583), UINT64_C(17179869143), UINT64_C(34359738337), UINT64_C(68719476731),
|
|
14
|
+
UINT64_C(137438953447), UINT64_C(274877906899), UINT64_C(549755813881), UINT64_C(1099511627689),
|
|
15
|
+
UINT64_C(2199023255531), UINT64_C(4398046511093), UINT64_C(8796093022151), UINT64_C(17592186044399),
|
|
16
|
+
UINT64_C(35184372088777), UINT64_C(70368744177643), UINT64_C(140737488355213), UINT64_C(281474976710597),
|
|
17
|
+
UINT64_C(562949953421231), UINT64_C(1125899906842597), UINT64_C(2251799813685119), UINT64_C(4503599627370449),
|
|
18
|
+
UINT64_C(9007199254740881), UINT64_C(18014398509481951), UINT64_C(36028797018963913), UINT64_C(72057594037927931),
|
|
19
|
+
UINT64_C(144115188075855859), UINT64_C(288230376151711717), UINT64_C(576460752303423433),
|
|
20
|
+
UINT64_C(1152921504606846883), UINT64_C(2305843009213693951), UINT64_C(4611686018427387847),
|
|
21
|
+
UINT64_C(9223372036854775783)};
|
|
22
|
+
|
|
23
|
+
/* static unsigned supid_log2(uint64_t v) {
|
|
24
|
+
unsigned r = 0;
|
|
25
|
+
while (v > 1) {
|
|
26
|
+
v >>= 1;
|
|
27
|
+
r += 1;
|
|
28
|
+
}
|
|
29
|
+
return r;
|
|
30
|
+
} */
|
|
31
|
+
|
|
32
|
+
namespace keygen {
|
|
33
|
+
|
|
34
|
+
/* LY: https://en.wikipedia.org/wiki/Injective_function */
|
|
35
|
+
serial_t injective(const serial_t serial, const unsigned bits /* at least serial_minwith (8) */, const serial_t salt) {
|
|
36
|
+
assert(bits >= serial_minwith && bits <= serial_maxwith);
|
|
37
|
+
|
|
38
|
+
/* LY: All these "magic" prime numbers were found
|
|
39
|
+
* and verified with a bit of brute force. */
|
|
40
|
+
|
|
41
|
+
static const uint64_t m[64 - serial_minwith + 1] = {
|
|
42
|
+
/* 8 - 24 */
|
|
43
|
+
113, 157, 397, 653, 1753, 5641, 9697, 23873, 25693, 80833, 105953, 316937, 309277, 834497, 1499933, 4373441,
|
|
44
|
+
10184137,
|
|
45
|
+
/* 25 - 64 */
|
|
46
|
+
10184137, 17279209, 33990377, 67295161, 284404553, 1075238767, 6346721573, 6924051577, 19204053433, 45840188887,
|
|
47
|
+
53625693977, 73447827913, 141638870249, 745683604649, 1283334050489, 1100828289853, 2201656586197, 5871903036137,
|
|
48
|
+
11238507001417, 45264020802263, 105008404482889, 81921776907059, 199987980256399, 307207457507641,
|
|
49
|
+
946769023178273, 2420886491930041, 3601632139991929, 11984491914483833, 21805846439714153, 23171543400565993,
|
|
50
|
+
53353226456762893, 155627817337932409, 227827205384840249, 816509268558278821, 576933057762605689,
|
|
51
|
+
2623957345935638441, 5048241705479929949, 4634245581946485653, 4613509448041658233, 4952535426879925961};
|
|
52
|
+
static const uint8_t s[64 - serial_minwith + 1] = {/* 8 - 24 */
|
|
53
|
+
2, 3, 4, 4, 2, 4, 3, 3, 7, 3, 3, 4, 8, 3, 10, 3, 11,
|
|
54
|
+
/* 25 - 64 */
|
|
55
|
+
11, 9, 9, 9, 11, 10, 5, 14, 11, 16, 14, 12, 13, 16, 19, 10, 10, 21,
|
|
56
|
+
7, 20, 10, 14, 22, 19, 3, 21, 18, 19, 26, 24, 2, 21, 25, 29, 24,
|
|
57
|
+
10, 11, 14, 20, 19};
|
|
58
|
+
|
|
59
|
+
const auto mask = actor_params::serial_mask(bits);
|
|
60
|
+
const auto mult = m[bits - 8];
|
|
61
|
+
const auto shift = s[bits - 8];
|
|
62
|
+
serial_t result = serial * mult;
|
|
63
|
+
if (salt) {
|
|
64
|
+
const unsigned left = bits / 2;
|
|
65
|
+
const unsigned right = bits - left;
|
|
66
|
+
result = (result << left) | ((result & mask) >> right);
|
|
67
|
+
result = (result ^ salt) * mult;
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
result ^= (result & mask) >> shift;
|
|
71
|
+
result &= mask;
|
|
72
|
+
log_trace("keygen-injective: serial %" PRIu64 "/%u @%" PRIx64 ",%u,%" PRIu64 " => %" PRIu64 "/%u", serial, bits, mult,
|
|
73
|
+
shift, salt, result, bits);
|
|
74
|
+
return result;
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
void __hot maker::pair(serial_t serial, const buffer &key, buffer &value, serial_t value_age,
|
|
78
|
+
const bool keylen_changeable) {
|
|
79
|
+
assert(mapping.width >= serial_minwith && mapping.width <= serial_maxwith);
|
|
80
|
+
assert(mapping.split <= mapping.width);
|
|
81
|
+
assert(mapping.mesh <= mapping.width);
|
|
82
|
+
assert(mapping.rotate <= mapping.width);
|
|
83
|
+
assert(mapping.offset <= actor_params::serial_mask(mapping.width));
|
|
84
|
+
assert(!(key_essentials.flags &
|
|
85
|
+
~(essentials::prng_fill_flag | unsigned(MDBX_INTEGERKEY | MDBX_REVERSEKEY | MDBX_DUPSORT))));
|
|
86
|
+
assert(!(value_essentials.flags &
|
|
87
|
+
~(essentials::prng_fill_flag | unsigned(MDBX_INTEGERDUP | MDBX_REVERSEDUP | MDBX_DUPFIXED))));
|
|
88
|
+
|
|
89
|
+
log_trace("keygen-pair: serial %" PRIu64 ", data-age %" PRIu64, serial, value_age);
|
|
90
|
+
|
|
91
|
+
if (mapping.mesh >= serial_minwith) {
|
|
92
|
+
serial = (serial & ~actor_params::serial_mask(mapping.mesh)) | injective(serial, mapping.mesh, salt);
|
|
93
|
+
log_trace("keygen-pair: mesh@%u => %" PRIu64, mapping.mesh, serial);
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
if (mapping.rotate) {
|
|
97
|
+
const unsigned right = mapping.rotate;
|
|
98
|
+
const unsigned left = mapping.width - right;
|
|
99
|
+
serial = (serial << left) | ((serial & actor_params::serial_mask(mapping.width)) >> right);
|
|
100
|
+
log_trace("keygen-pair: rotate@%u => %" PRIu64 ", 0x%" PRIx64, mapping.rotate, serial, serial);
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
if (mapping.offset) {
|
|
104
|
+
serial = (serial + mapping.offset) & actor_params::serial_mask(mapping.width);
|
|
105
|
+
log_trace("keygen-pair: offset@%" PRIu64 " => %" PRIu64, mapping.offset, serial);
|
|
106
|
+
}
|
|
107
|
+
if (base) {
|
|
108
|
+
serial += base;
|
|
109
|
+
log_trace("keygen-pair: base@%" PRIu64 " => %" PRIu64, base, serial);
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
serial_t key_serial = serial;
|
|
113
|
+
serial_t value_serial = (value_age & value_age_mask) << mapping.split;
|
|
114
|
+
if (mapping.split) {
|
|
115
|
+
if (MDBX_db_flags_t(key_essentials.flags) & MDBX_DUPSORT) {
|
|
116
|
+
key_serial >>= mapping.split;
|
|
117
|
+
value_serial += serial & actor_params::serial_mask(mapping.split);
|
|
118
|
+
} else {
|
|
119
|
+
/* Без MDBX_DUPSORT требуется уникальность ключей, а для этого нельзя
|
|
120
|
+
* отбрасывать какие-либо биты serial после инъективного преобразования.
|
|
121
|
+
* Поэтому key_serial не трогаем, а в value_serial нелинейно вмешиваем
|
|
122
|
+
* запрошенное количество бит из serial */
|
|
123
|
+
value_serial +=
|
|
124
|
+
(serial ^ (serial >> mapping.split) * UINT64_C(57035339200100753)) & actor_params::serial_mask(mapping.split);
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
log_trace("keygen-pair: split@%u => k%" PRIu64 ", v%" PRIu64, mapping.split, key_serial, value_serial);
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
log_trace("keygen-pair: key %" PRIu64 ", value %" PRIu64, key_serial, value_serial);
|
|
131
|
+
key_serial = mk_begin(key_serial, key_essentials, *key);
|
|
132
|
+
value_serial = mk_begin(value_serial, value_essentials, *value);
|
|
133
|
+
|
|
134
|
+
#if 0 /* unused for now */
|
|
135
|
+
if (key->value.iov_len + value->value.iov_len > pair_maxlen) {
|
|
136
|
+
unsigned extra = key->value.iov_len + value->value.iov_len - pair_maxlen;
|
|
137
|
+
if (keylen_changeable &&
|
|
138
|
+
key->value.iov_len > std::max(8u, (unsigned)key_essentials.minlen)) {
|
|
139
|
+
#if defined(__GNUC__) || defined(__clang__)
|
|
140
|
+
const bool coin = __builtin_parityll(serial) != 0;
|
|
141
|
+
#else
|
|
142
|
+
const bool coin = INT64_C(0xF2CEECA9989BD96A) * int64_t(serial) < 0;
|
|
143
|
+
#endif
|
|
144
|
+
if (coin) {
|
|
145
|
+
const unsigned gap =
|
|
146
|
+
key->value.iov_len - std::max(8u, (unsigned)key_essentials.minlen);
|
|
147
|
+
const unsigned chop = std::min(gap, extra);
|
|
148
|
+
log_trace("keygen-pair: chop %u key-len %u -> %u", chop,
|
|
149
|
+
(unsigned)key->value.iov_len,
|
|
150
|
+
(unsigned)key->value.iov_len - chop);
|
|
151
|
+
key->value.iov_len -= chop;
|
|
152
|
+
extra -= chop;
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
if (extra && value->value.iov_len >
|
|
156
|
+
std::max(8u, (unsigned)value_essentials.minlen)) {
|
|
157
|
+
const unsigned gap = value->value.iov_len -
|
|
158
|
+
std::max(8u, (unsigned)value_essentials.minlen);
|
|
159
|
+
const unsigned chop = std::min(gap, extra);
|
|
160
|
+
log_trace("keygen-pair: chop %u value-len %u -> %u", chop,
|
|
161
|
+
(unsigned)value->value.iov_len,
|
|
162
|
+
(unsigned)value->value.iov_len - chop);
|
|
163
|
+
value->value.iov_len -= chop;
|
|
164
|
+
extra -= chop;
|
|
165
|
+
}
|
|
166
|
+
if (keylen_changeable && extra &&
|
|
167
|
+
key->value.iov_len > std::max(8u, (unsigned)key_essentials.minlen)) {
|
|
168
|
+
const unsigned gap =
|
|
169
|
+
key->value.iov_len - std::max(8u, (unsigned)key_essentials.minlen);
|
|
170
|
+
const unsigned chop = std::min(gap, extra);
|
|
171
|
+
log_trace("keygen-pair: chop %u key-len %u -> %u", chop,
|
|
172
|
+
(unsigned)key->value.iov_len,
|
|
173
|
+
(unsigned)key->value.iov_len - chop);
|
|
174
|
+
key->value.iov_len -= chop;
|
|
175
|
+
extra -= chop;
|
|
176
|
+
}
|
|
177
|
+
}
|
|
178
|
+
#else
|
|
179
|
+
(void)keylen_changeable;
|
|
180
|
+
#endif /* unused for now */
|
|
181
|
+
|
|
182
|
+
mk_continue(key_serial, key_essentials, *key);
|
|
183
|
+
mk_continue(value_serial, value_essentials, *value);
|
|
184
|
+
log_pair(logging::trace, "kv", key, value);
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
void maker::setup(const config::actor_params_pod &actor, unsigned thread_number) {
|
|
188
|
+
#if CONSTEXPR_ENUM_FLAGS_OPERATIONS
|
|
189
|
+
static_assert(unsigned(MDBX_INTEGERKEY | MDBX_REVERSEKEY | MDBX_DUPSORT | MDBX_DUPFIXED | MDBX_INTEGERDUP |
|
|
190
|
+
MDBX_REVERSEDUP) < UINT16_MAX,
|
|
191
|
+
"WTF?");
|
|
192
|
+
#else
|
|
193
|
+
assert(unsigned(MDBX_INTEGERKEY | MDBX_REVERSEKEY | MDBX_DUPSORT | MDBX_DUPFIXED | MDBX_INTEGERDUP |
|
|
194
|
+
MDBX_REVERSEDUP) < UINT16_MAX);
|
|
195
|
+
#endif
|
|
196
|
+
|
|
197
|
+
key_essentials.flags =
|
|
198
|
+
uint16_t(actor.table_flags & MDBX_db_flags_t(MDBX_INTEGERKEY | MDBX_REVERSEKEY | MDBX_DUPSORT));
|
|
199
|
+
assert(actor.keylen_min <= UINT16_MAX);
|
|
200
|
+
key_essentials.minlen = uint16_t(actor.keylen_min);
|
|
201
|
+
assert(actor.keylen_max <= UINT32_MAX);
|
|
202
|
+
key_essentials.maxlen =
|
|
203
|
+
std::min(uint32_t(actor.keylen_max), uint32_t(mdbx_limits_keysize_max(actor.pagesize, actor.table_flags)));
|
|
204
|
+
key_essentials.bits =
|
|
205
|
+
(key_essentials.maxlen < sizeof(serial_t)) ? key_essentials.maxlen * CHAR_BIT : sizeof(serial_t) * CHAR_BIT;
|
|
206
|
+
key_essentials.mask = actor_params::serial_mask(key_essentials.bits);
|
|
207
|
+
assert(key_essentials.bits > 63 || key_essentials.mask > primes[key_essentials.bits]);
|
|
208
|
+
|
|
209
|
+
value_essentials.flags =
|
|
210
|
+
uint16_t(actor.table_flags & MDBX_db_flags_t(MDBX_INTEGERDUP | MDBX_REVERSEDUP | MDBX_DUPFIXED));
|
|
211
|
+
assert(actor.datalen_min <= UINT16_MAX);
|
|
212
|
+
value_essentials.minlen = uint16_t(actor.datalen_min);
|
|
213
|
+
assert(actor.datalen_max <= UINT32_MAX);
|
|
214
|
+
value_essentials.maxlen =
|
|
215
|
+
std::min(uint32_t(actor.datalen_max), uint32_t(mdbx_limits_valsize_max(actor.pagesize, actor.table_flags)));
|
|
216
|
+
value_essentials.bits =
|
|
217
|
+
(value_essentials.maxlen < sizeof(serial_t)) ? value_essentials.maxlen * CHAR_BIT : sizeof(serial_t) * CHAR_BIT;
|
|
218
|
+
value_essentials.mask = actor_params::serial_mask(value_essentials.bits);
|
|
219
|
+
assert(value_essentials.bits > 63 || value_essentials.mask > primes[value_essentials.bits]);
|
|
220
|
+
|
|
221
|
+
if (!actor.keygen.zero_fill) {
|
|
222
|
+
key_essentials.flags |= essentials::prng_fill_flag;
|
|
223
|
+
value_essentials.flags |= essentials::prng_fill_flag;
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
mapping = actor.keygen;
|
|
227
|
+
const auto split = mapping.split;
|
|
228
|
+
while (mapping.split > value_essentials.bits - essentials::value_age_minwidth || mapping.split >= mapping.width)
|
|
229
|
+
mapping.split -= 1;
|
|
230
|
+
if (split != mapping.split)
|
|
231
|
+
log_notice("keygen: reduce mapping-split from %u to %u", split, mapping.split);
|
|
232
|
+
|
|
233
|
+
const auto width = mapping.width;
|
|
234
|
+
while (unsigned((actor.table_flags & MDBX_DUPSORT) ? mapping.width - mapping.split : mapping.width) >
|
|
235
|
+
key_essentials.bits)
|
|
236
|
+
mapping.width -= 1;
|
|
237
|
+
if (width != mapping.width)
|
|
238
|
+
log_notice("keygen: reduce mapping-width from %u to %u", width, mapping.width);
|
|
239
|
+
|
|
240
|
+
value_age_bits = value_essentials.bits - mapping.split;
|
|
241
|
+
value_age_mask = actor_params::serial_mask(value_age_bits);
|
|
242
|
+
assert(value_age_bits >= essentials::value_age_minwidth);
|
|
243
|
+
|
|
244
|
+
salt = (prng_state ^ (thread_number * 1575554837) * UINT64_C(59386707711075671)) * UINT64_C(14653293970879851569);
|
|
245
|
+
base = actor.serial_base();
|
|
246
|
+
}
|
|
247
|
+
|
|
248
|
+
bool maker::is_unordered() const {
|
|
249
|
+
return mapping.rotate || mapping.mesh > ((MDBX_db_flags_t(key_essentials.flags) & MDBX_DUPSORT) ? 0 : mapping.split);
|
|
250
|
+
}
|
|
251
|
+
|
|
252
|
+
void maker::seek2end(serial_t &serial) const { serial = actor_params::serial_mask(mapping.width) - 1; }
|
|
253
|
+
|
|
254
|
+
bool maker::increment(serial_t &serial, int64_t delta) const {
|
|
255
|
+
if (serial > actor_params::serial_mask(mapping.width)) {
|
|
256
|
+
log_extra("keygen-increment: %" PRIu64 " > %" PRIu64 ", overflow", serial,
|
|
257
|
+
actor_params::serial_mask(mapping.width));
|
|
258
|
+
return false;
|
|
259
|
+
}
|
|
260
|
+
|
|
261
|
+
serial_t target = serial + delta;
|
|
262
|
+
if (target > actor_params::serial_mask(mapping.width) || ((delta > 0) ? target < serial : target > serial)) {
|
|
263
|
+
log_extra("keygen-increment: %" PRIu64 "%-" PRId64 " => %" PRIu64 ", overflow", serial, delta, target);
|
|
264
|
+
return false;
|
|
265
|
+
}
|
|
266
|
+
|
|
267
|
+
log_extra("keygen-increment: %" PRIu64 "%-" PRId64 " => %" PRIu64 ", continue", serial, delta, target);
|
|
268
|
+
serial = target;
|
|
269
|
+
return true;
|
|
270
|
+
}
|
|
271
|
+
|
|
272
|
+
//-----------------------------------------------------------------------------
|
|
273
|
+
|
|
274
|
+
MDBX_NOTHROW_PURE_FUNCTION static inline unsigned length(serial_t serial) {
|
|
275
|
+
#if defined(__clang__) && __clang__ > 8
|
|
276
|
+
unsigned n = 0;
|
|
277
|
+
if (serial > UINT32_MAX) {
|
|
278
|
+
n = 4;
|
|
279
|
+
serial >>= 32;
|
|
280
|
+
}
|
|
281
|
+
if (serial > UINT16_MAX) {
|
|
282
|
+
n += 2;
|
|
283
|
+
serial >>= 16;
|
|
284
|
+
}
|
|
285
|
+
if (serial > UINT8_MAX) {
|
|
286
|
+
n += 1;
|
|
287
|
+
serial >>= 8;
|
|
288
|
+
}
|
|
289
|
+
#else
|
|
290
|
+
unsigned n = (serial > UINT32_MAX) ? 4 : 0;
|
|
291
|
+
serial = (serial > UINT32_MAX) ? serial >> 32 : serial;
|
|
292
|
+
|
|
293
|
+
n += (serial > UINT16_MAX) ? 2 : 0;
|
|
294
|
+
serial = (serial > UINT16_MAX) ? serial >> 16 : serial;
|
|
295
|
+
|
|
296
|
+
n += (serial > UINT8_MAX);
|
|
297
|
+
serial = (serial > UINT8_MAX) ? serial >> 8 : serial;
|
|
298
|
+
#endif
|
|
299
|
+
return n + (serial > 0);
|
|
300
|
+
}
|
|
301
|
+
|
|
302
|
+
buffer alloc(size_t limit) {
|
|
303
|
+
result *ptr = (result *)malloc(sizeof(result) + limit + 8);
|
|
304
|
+
if (unlikely(ptr == nullptr))
|
|
305
|
+
failure_perror("malloc(keyvalue_buffer)", errno);
|
|
306
|
+
ptr->value.iov_base = ptr->bytes;
|
|
307
|
+
ptr->value.iov_len = 0;
|
|
308
|
+
ptr->limit = limit + 8;
|
|
309
|
+
return buffer(ptr);
|
|
310
|
+
}
|
|
311
|
+
|
|
312
|
+
serial_t __hot maker::mk_begin(serial_t serial, const essentials ¶ms, result &out) {
|
|
313
|
+
assert(out.limit >= params.maxlen);
|
|
314
|
+
assert(params.maxlen >= params.minlen);
|
|
315
|
+
assert(serial <= params.mask);
|
|
316
|
+
if (unlikely(serial > params.mask)) {
|
|
317
|
+
#if 1
|
|
318
|
+
serial %= primes[params.bits];
|
|
319
|
+
assert(params.mask > primes[params.bits]);
|
|
320
|
+
#else
|
|
321
|
+
const serial_t maxbits = params.maxlen * CHAR_BIT;
|
|
322
|
+
serial ^=
|
|
323
|
+
(serial >> maxbits / 2) * serial_t((sizeof(serial_t) > 4) ? UINT64_C(40719303417517073) : UINT32_C(3708688457));
|
|
324
|
+
serial &= params.mask;
|
|
325
|
+
#endif
|
|
326
|
+
assert(params.maxlen >= length(serial));
|
|
327
|
+
}
|
|
328
|
+
|
|
329
|
+
out.value.iov_len = std::max(unsigned(params.minlen), length(serial));
|
|
330
|
+
const auto variation = params.maxlen - params.minlen;
|
|
331
|
+
if (variation) {
|
|
332
|
+
if (serial % (variation + serial_t(1))) {
|
|
333
|
+
auto refix = serial * UINT64_C(48835288005252737);
|
|
334
|
+
refix ^= refix >> 32;
|
|
335
|
+
out.value.iov_len = std::max(out.value.iov_len, params.minlen + size_t(1) + size_t(refix) % variation);
|
|
336
|
+
}
|
|
337
|
+
}
|
|
338
|
+
|
|
339
|
+
assert(length(serial) <= out.value.iov_len);
|
|
340
|
+
assert(out.value.iov_len >= params.minlen);
|
|
341
|
+
assert(out.value.iov_len <= params.maxlen);
|
|
342
|
+
return serial;
|
|
343
|
+
}
|
|
344
|
+
|
|
345
|
+
void __hot maker::mk_continue(const serial_t serial, const essentials ¶ms, result &out) {
|
|
346
|
+
#if CONSTEXPR_ENUM_FLAGS_OPERATIONS
|
|
347
|
+
static_assert((essentials::prng_fill_flag & unsigned(MDBX_DUPSORT | MDBX_DUPFIXED | MDBX_INTEGERKEY |
|
|
348
|
+
MDBX_INTEGERDUP | MDBX_REVERSEKEY | MDBX_REVERSEDUP)) == 0,
|
|
349
|
+
"WTF?");
|
|
350
|
+
#else
|
|
351
|
+
assert((essentials::prng_fill_flag & unsigned(MDBX_DUPSORT | MDBX_DUPFIXED | MDBX_INTEGERKEY | MDBX_INTEGERDUP |
|
|
352
|
+
MDBX_REVERSEKEY | MDBX_REVERSEDUP)) == 0);
|
|
353
|
+
#endif
|
|
354
|
+
assert(length(serial) <= out.value.iov_len);
|
|
355
|
+
out.value.iov_base = out.bytes;
|
|
356
|
+
if (MDBX_db_flags_t(params.flags) & (MDBX_INTEGERKEY | MDBX_INTEGERDUP)) {
|
|
357
|
+
assert(params.maxlen == params.minlen);
|
|
358
|
+
if (MDBX_db_flags_t(params.flags) & (MDBX_INTEGERKEY | MDBX_INTEGERDUP))
|
|
359
|
+
assert(params.minlen == 4 || params.minlen == 8);
|
|
360
|
+
out.u64 = serial;
|
|
361
|
+
if (!is_byteorder_le() && out.value.iov_len != 8)
|
|
362
|
+
out.u32 = uint32_t(serial);
|
|
363
|
+
} else {
|
|
364
|
+
const auto prefix = std::max(std::min(unsigned(params.minlen), 8u), length(serial));
|
|
365
|
+
out.u64 = htobe64(serial);
|
|
366
|
+
out.value.iov_base = out.bytes + 8 - prefix;
|
|
367
|
+
if (out.value.iov_len > prefix) {
|
|
368
|
+
if (params.flags & essentials::prng_fill_flag) {
|
|
369
|
+
uint64_t state = serial ^ UINT64_C(0x923ab47b7ee6f6e4);
|
|
370
|
+
prng_fill(state, out.bytes + 8, out.value.iov_len - prefix);
|
|
371
|
+
} else
|
|
372
|
+
memset(out.bytes + 8, '\0', out.value.iov_len - prefix);
|
|
373
|
+
}
|
|
374
|
+
if (unlikely(MDBX_db_flags_t(params.flags) & (MDBX_REVERSEKEY | MDBX_REVERSEDUP)))
|
|
375
|
+
std::reverse((char *)out.value.iov_base, (char *)out.value.iov_base + out.value.iov_len);
|
|
376
|
+
}
|
|
377
|
+
|
|
378
|
+
assert(out.value.iov_len >= params.minlen);
|
|
379
|
+
assert(out.value.iov_len <= params.maxlen);
|
|
380
|
+
assert(out.value.iov_len >= length(serial));
|
|
381
|
+
assert(out.value.iov_base >= out.bytes);
|
|
382
|
+
assert((char *)out.value.iov_base + out.value.iov_len <= (char *)&out.bytes + out.limit);
|
|
383
|
+
}
|
|
384
|
+
|
|
385
|
+
void log_pair(logging::loglevel level, const char *prefix, const buffer &key, buffer &value) {
|
|
386
|
+
if (log_enabled(level)) {
|
|
387
|
+
char dump_key[4096], dump_value[4096];
|
|
388
|
+
logging::output(level, "%s-pair: key %s, value %s", prefix, mdbx_dump_val(&key->value, dump_key, sizeof(dump_key)),
|
|
389
|
+
mdbx_dump_val(&value->value, dump_value, sizeof(dump_value)));
|
|
390
|
+
}
|
|
391
|
+
}
|
|
392
|
+
|
|
393
|
+
} /* namespace keygen */
|