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,140 @@
|
|
|
1
|
+
/// \copyright SPDX-License-Identifier: Apache-2.0
|
|
2
|
+
/// \note Please refer to the COPYRIGHT file for explanations license change,
|
|
3
|
+
/// credits and acknowledgments.
|
|
4
|
+
/// \author Леонид Юрьев aka Leonid Yuriev <leo@yuriev.ru> \date 2015-2025
|
|
5
|
+
|
|
6
|
+
#include "internals.h"
|
|
7
|
+
|
|
8
|
+
/* Search for the lowest key under the current branch page.
|
|
9
|
+
* This just bypasses a numkeys check in the current page
|
|
10
|
+
* before calling tree_search_finalize(), because the callers
|
|
11
|
+
* are all in situations where the current page is known to
|
|
12
|
+
* be underfilled. */
|
|
13
|
+
__hot int tree_search_lowest(MDBX_cursor *mc) {
|
|
14
|
+
cASSERT(mc, mc->top >= 0);
|
|
15
|
+
page_t *mp = mc->pg[mc->top];
|
|
16
|
+
cASSERT(mc, is_branch(mp));
|
|
17
|
+
|
|
18
|
+
node_t *node = page_node(mp, 0);
|
|
19
|
+
int err = page_get(mc, node_pgno(node), &mp, mp->txnid);
|
|
20
|
+
if (unlikely(err != MDBX_SUCCESS))
|
|
21
|
+
return err;
|
|
22
|
+
|
|
23
|
+
mc->ki[mc->top] = 0;
|
|
24
|
+
err = cursor_push(mc, mp, 0);
|
|
25
|
+
if (unlikely(err != MDBX_SUCCESS))
|
|
26
|
+
return err;
|
|
27
|
+
return tree_search_finalize(mc, nullptr, Z_FIRST);
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
__hot int tree_search(MDBX_cursor *mc, const MDBX_val *key, int flags) {
|
|
31
|
+
int err;
|
|
32
|
+
if (unlikely(mc->txn->flags & MDBX_TXN_BLOCKED)) {
|
|
33
|
+
DEBUG("%s", "transaction has failed, must abort");
|
|
34
|
+
err = MDBX_BAD_TXN;
|
|
35
|
+
bailout:
|
|
36
|
+
be_poor(mc);
|
|
37
|
+
return err;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
const size_t dbi = cursor_dbi(mc);
|
|
41
|
+
if (unlikely(*cursor_dbi_state(mc) & DBI_STALE)) {
|
|
42
|
+
err = tbl_fetch(mc->txn, dbi);
|
|
43
|
+
if (unlikely(err != MDBX_SUCCESS))
|
|
44
|
+
goto bailout;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
const pgno_t root = mc->tree->root;
|
|
48
|
+
if (unlikely(root == P_INVALID)) {
|
|
49
|
+
DEBUG("%s", "tree is empty");
|
|
50
|
+
cASSERT(mc, is_poor(mc));
|
|
51
|
+
return MDBX_NOTFOUND;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
cASSERT(mc, root >= NUM_METAS && root < mc->txn->geo.first_unallocated);
|
|
55
|
+
if (mc->top < 0 || mc->pg[0]->pgno != root) {
|
|
56
|
+
txnid_t pp_txnid = mc->tree->mod_txnid;
|
|
57
|
+
pp_txnid = /* tree->mod_txnid maybe zero in a legacy DB */ pp_txnid ? pp_txnid : mc->txn->txnid;
|
|
58
|
+
if ((mc->txn->flags & MDBX_TXN_RDONLY) == 0) {
|
|
59
|
+
MDBX_txn *scan = mc->txn;
|
|
60
|
+
do
|
|
61
|
+
if ((scan->flags & MDBX_TXN_DIRTY) && (dbi == MAIN_DBI || (scan->dbi_state[dbi] & DBI_DIRTY))) {
|
|
62
|
+
/* После коммита вложенных тразакций может быть mod_txnid > front */
|
|
63
|
+
pp_txnid = scan->front_txnid;
|
|
64
|
+
break;
|
|
65
|
+
}
|
|
66
|
+
while (unlikely((scan = scan->parent) != nullptr));
|
|
67
|
+
}
|
|
68
|
+
err = page_get(mc, root, &mc->pg[0], pp_txnid);
|
|
69
|
+
if (unlikely(err != MDBX_SUCCESS))
|
|
70
|
+
goto bailout;
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
mc->top = 0;
|
|
74
|
+
mc->ki[0] = (flags & Z_LAST) ? page_numkeys(mc->pg[0]) - 1 : 0;
|
|
75
|
+
DEBUG("db %d root page %" PRIaPGNO " has flags 0x%X", cursor_dbi_dbg(mc), root, mc->pg[0]->flags);
|
|
76
|
+
|
|
77
|
+
if (flags & Z_MODIFY) {
|
|
78
|
+
err = page_touch(mc);
|
|
79
|
+
if (unlikely(err != MDBX_SUCCESS))
|
|
80
|
+
goto bailout;
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
if (flags & Z_ROOTONLY)
|
|
84
|
+
return MDBX_SUCCESS;
|
|
85
|
+
|
|
86
|
+
return tree_search_finalize(mc, key, flags);
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
__hot __noinline int tree_search_finalize(MDBX_cursor *mc, const MDBX_val *key, int flags) {
|
|
90
|
+
cASSERT(mc, !is_poor(mc));
|
|
91
|
+
DKBUF_DEBUG;
|
|
92
|
+
int err;
|
|
93
|
+
page_t *mp = mc->pg[mc->top];
|
|
94
|
+
intptr_t ki = (flags & Z_FIRST) ? 0 : page_numkeys(mp) - 1;
|
|
95
|
+
while (is_branch(mp)) {
|
|
96
|
+
DEBUG("branch page %" PRIaPGNO " has %zu keys", mp->pgno, page_numkeys(mp));
|
|
97
|
+
cASSERT(mc, page_numkeys(mp) > 1);
|
|
98
|
+
DEBUG("found index 0 to page %" PRIaPGNO, node_pgno(page_node(mp, 0)));
|
|
99
|
+
|
|
100
|
+
if ((flags & (Z_FIRST | Z_LAST)) == 0) {
|
|
101
|
+
const struct node_search_result nsr = node_search(mc, key);
|
|
102
|
+
if (likely(nsr.node))
|
|
103
|
+
ki = mc->ki[mc->top] + (intptr_t)nsr.exact - 1;
|
|
104
|
+
DEBUG("following index %zu for key [%s]", ki, DKEY_DEBUG(key));
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
err = page_get(mc, node_pgno(page_node(mp, ki)), &mp, mp->txnid);
|
|
108
|
+
if (unlikely(err != MDBX_SUCCESS))
|
|
109
|
+
goto bailout;
|
|
110
|
+
|
|
111
|
+
mc->ki[mc->top] = (indx_t)ki;
|
|
112
|
+
ki = (flags & Z_FIRST) ? 0 : page_numkeys(mp) - 1;
|
|
113
|
+
err = cursor_push(mc, mp, ki);
|
|
114
|
+
if (unlikely(err != MDBX_SUCCESS))
|
|
115
|
+
goto bailout;
|
|
116
|
+
|
|
117
|
+
if (flags & Z_MODIFY) {
|
|
118
|
+
err = page_touch(mc);
|
|
119
|
+
if (unlikely(err != MDBX_SUCCESS))
|
|
120
|
+
goto bailout;
|
|
121
|
+
mp = mc->pg[mc->top];
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
if (!MDBX_DISABLE_VALIDATION && unlikely(!check_leaf_type(mc, mp))) {
|
|
126
|
+
ERROR("unexpected leaf-page #%" PRIaPGNO " type 0x%x seen by cursor", mp->pgno, mp->flags);
|
|
127
|
+
err = MDBX_CORRUPTED;
|
|
128
|
+
bailout:
|
|
129
|
+
be_poor(mc);
|
|
130
|
+
return err;
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
DEBUG("found leaf page %" PRIaPGNO " for key [%s]", mp->pgno, DKEY_DEBUG(key));
|
|
134
|
+
/* Логически верно, но (в текущем понимании) нет необходимости.
|
|
135
|
+
Однако, стоит ещё по-проверять/по-тестировать.
|
|
136
|
+
Возможно есть сценарий, в котором очистка флагов всё-таки требуется.
|
|
137
|
+
|
|
138
|
+
be_filled(mc); */
|
|
139
|
+
return MDBX_SUCCESS;
|
|
140
|
+
}
|
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
/// \copyright SPDX-License-Identifier: Apache-2.0
|
|
2
|
+
/// \author Леонид Юрьев aka Leonid Yuriev <leo@yuriev.ru> \date 2015-2025
|
|
3
|
+
|
|
4
|
+
#include "internals.h"
|
|
5
|
+
|
|
6
|
+
static inline size_t txl_size2bytes(const size_t size) {
|
|
7
|
+
assert(size > 0 && size <= txl_max * 2);
|
|
8
|
+
size_t bytes =
|
|
9
|
+
ceil_powerof2(MDBX_ASSUME_MALLOC_OVERHEAD + sizeof(txnid_t) * (size + 2), txl_granulate * sizeof(txnid_t)) -
|
|
10
|
+
MDBX_ASSUME_MALLOC_OVERHEAD;
|
|
11
|
+
return bytes;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
static inline size_t txl_bytes2size(const size_t bytes) {
|
|
15
|
+
size_t size = bytes / sizeof(txnid_t);
|
|
16
|
+
assert(size > 2 && size <= txl_max * 2);
|
|
17
|
+
return size - 2;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
txl_t txl_alloc(void) {
|
|
21
|
+
size_t bytes = txl_size2bytes(txl_initial);
|
|
22
|
+
txl_t txl = osal_malloc(bytes);
|
|
23
|
+
if (likely(txl)) {
|
|
24
|
+
#ifdef osal_malloc_usable_size
|
|
25
|
+
bytes = osal_malloc_usable_size(txl);
|
|
26
|
+
#endif /* osal_malloc_usable_size */
|
|
27
|
+
txl[0] = txl_bytes2size(bytes);
|
|
28
|
+
assert(txl[0] >= txl_initial);
|
|
29
|
+
txl += 1;
|
|
30
|
+
*txl = 0;
|
|
31
|
+
}
|
|
32
|
+
return txl;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
void txl_free(txl_t txl) {
|
|
36
|
+
if (likely(txl))
|
|
37
|
+
osal_free(txl - 1);
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
static int txl_reserve(txl_t __restrict *__restrict ptxl, const size_t wanna) {
|
|
41
|
+
const size_t allocated = (size_t)MDBX_PNL_ALLOCLEN(*ptxl);
|
|
42
|
+
assert(MDBX_PNL_GETSIZE(*ptxl) <= txl_max && MDBX_PNL_ALLOCLEN(*ptxl) >= MDBX_PNL_GETSIZE(*ptxl));
|
|
43
|
+
if (likely(allocated >= wanna))
|
|
44
|
+
return MDBX_SUCCESS;
|
|
45
|
+
|
|
46
|
+
if (unlikely(wanna > /* paranoia */ txl_max)) {
|
|
47
|
+
ERROR("TXL too long (%zu > %zu)", wanna, (size_t)txl_max);
|
|
48
|
+
return MDBX_TXN_FULL;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
const size_t size = (wanna + wanna - allocated < txl_max) ? wanna + wanna - allocated : txl_max;
|
|
52
|
+
size_t bytes = txl_size2bytes(size);
|
|
53
|
+
txl_t txl = osal_realloc(*ptxl - 1, bytes);
|
|
54
|
+
if (likely(txl)) {
|
|
55
|
+
#ifdef osal_malloc_usable_size
|
|
56
|
+
bytes = osal_malloc_usable_size(txl);
|
|
57
|
+
#endif /* osal_malloc_usable_size */
|
|
58
|
+
*txl = txl_bytes2size(bytes);
|
|
59
|
+
assert(*txl >= wanna);
|
|
60
|
+
*ptxl = txl + 1;
|
|
61
|
+
return MDBX_SUCCESS;
|
|
62
|
+
}
|
|
63
|
+
return MDBX_ENOMEM;
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
static __always_inline int __must_check_result txl_need(txl_t __restrict *__restrict ptxl, size_t num) {
|
|
67
|
+
assert(MDBX_PNL_GETSIZE(*ptxl) <= txl_max && MDBX_PNL_ALLOCLEN(*ptxl) >= MDBX_PNL_GETSIZE(*ptxl));
|
|
68
|
+
assert(num <= PAGELIST_LIMIT);
|
|
69
|
+
const size_t wanna = (size_t)MDBX_PNL_GETSIZE(*ptxl) + num;
|
|
70
|
+
return likely(MDBX_PNL_ALLOCLEN(*ptxl) >= wanna) ? MDBX_SUCCESS : txl_reserve(ptxl, wanna);
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
static __always_inline void txl_xappend(txl_t __restrict txl, txnid_t id) {
|
|
74
|
+
assert(MDBX_PNL_GETSIZE(txl) < MDBX_PNL_ALLOCLEN(txl));
|
|
75
|
+
txl[0] += 1;
|
|
76
|
+
MDBX_PNL_LAST(txl) = id;
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
#define TXNID_SORT_CMP(first, last) ((first) > (last))
|
|
80
|
+
SORT_IMPL(txnid_sort, false, txnid_t, TXNID_SORT_CMP)
|
|
81
|
+
void txl_sort(txl_t txl) { txnid_sort(MDBX_PNL_BEGIN(txl), MDBX_PNL_END(txl)); }
|
|
82
|
+
|
|
83
|
+
int __must_check_result txl_append(txl_t __restrict *ptxl, txnid_t id) {
|
|
84
|
+
if (unlikely(MDBX_PNL_GETSIZE(*ptxl) == MDBX_PNL_ALLOCLEN(*ptxl))) {
|
|
85
|
+
int rc = txl_need(ptxl, txl_granulate);
|
|
86
|
+
if (unlikely(rc != MDBX_SUCCESS))
|
|
87
|
+
return rc;
|
|
88
|
+
}
|
|
89
|
+
txl_xappend(*ptxl, id);
|
|
90
|
+
return MDBX_SUCCESS;
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
__hot bool txl_contain(const txl_t txl, txnid_t id) {
|
|
94
|
+
const size_t len = MDBX_PNL_GETSIZE(txl);
|
|
95
|
+
for (size_t i = 1; i <= len; ++i)
|
|
96
|
+
if (txl[i] == id)
|
|
97
|
+
return true;
|
|
98
|
+
return false;
|
|
99
|
+
}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
/// \copyright SPDX-License-Identifier: Apache-2.0
|
|
2
|
+
/// \author Леонид Юрьев aka Leonid Yuriev <leo@yuriev.ru> \date 2015-2025
|
|
3
|
+
|
|
4
|
+
#pragma once
|
|
5
|
+
|
|
6
|
+
#include "essentials.h"
|
|
7
|
+
|
|
8
|
+
/* List of txnid */
|
|
9
|
+
typedef txnid_t *txl_t;
|
|
10
|
+
typedef const txnid_t *const_txl_t;
|
|
11
|
+
|
|
12
|
+
enum txl_rules {
|
|
13
|
+
txl_granulate = 32,
|
|
14
|
+
txl_initial = txl_granulate - 2 - MDBX_ASSUME_MALLOC_OVERHEAD / sizeof(txnid_t),
|
|
15
|
+
txl_max = (1u << 26) - 2 - MDBX_ASSUME_MALLOC_OVERHEAD / sizeof(txnid_t)
|
|
16
|
+
};
|
|
17
|
+
|
|
18
|
+
MDBX_INTERNAL txl_t txl_alloc(void);
|
|
19
|
+
|
|
20
|
+
MDBX_INTERNAL void txl_free(txl_t txl);
|
|
21
|
+
|
|
22
|
+
MDBX_INTERNAL int __must_check_result txl_append(txl_t __restrict *ptxl, txnid_t id);
|
|
23
|
+
|
|
24
|
+
MDBX_INTERNAL void txl_sort(txl_t txl);
|
|
25
|
+
|
|
26
|
+
MDBX_INTERNAL bool txl_contain(const txl_t txl, txnid_t id);
|