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,142 @@
|
|
|
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
|
+
MDBX_INTERNAL int __must_check_result tree_search_finalize(MDBX_cursor *mc, const MDBX_val *key, int flags);
|
|
9
|
+
MDBX_INTERNAL int tree_search_lowest(MDBX_cursor *mc);
|
|
10
|
+
|
|
11
|
+
enum page_search_flags {
|
|
12
|
+
Z_MODIFY = 1,
|
|
13
|
+
Z_ROOTONLY = 2,
|
|
14
|
+
Z_FIRST = 4,
|
|
15
|
+
Z_LAST = 8,
|
|
16
|
+
};
|
|
17
|
+
MDBX_INTERNAL int __must_check_result tree_search(MDBX_cursor *mc, const MDBX_val *key, int flags);
|
|
18
|
+
|
|
19
|
+
#define MDBX_SPLIT_REPLACE MDBX_APPENDDUP /* newkey is not new */
|
|
20
|
+
MDBX_INTERNAL int __must_check_result page_split(MDBX_cursor *mc, const MDBX_val *const newkey, MDBX_val *const newdata,
|
|
21
|
+
pgno_t newpgno, const unsigned naf);
|
|
22
|
+
|
|
23
|
+
/*----------------------------------------------------------------------------*/
|
|
24
|
+
|
|
25
|
+
MDBX_INTERNAL int MDBX_PRINTF_ARGS(2, 3) bad_page(const page_t *mp, const char *fmt, ...);
|
|
26
|
+
|
|
27
|
+
MDBX_INTERNAL void MDBX_PRINTF_ARGS(2, 3) poor_page(const page_t *mp, const char *fmt, ...);
|
|
28
|
+
|
|
29
|
+
MDBX_NOTHROW_PURE_FUNCTION static inline bool is_frozen(const MDBX_txn *txn, const page_t *mp) {
|
|
30
|
+
return mp->txnid < txn->txnid;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
MDBX_NOTHROW_PURE_FUNCTION static inline bool is_spilled(const MDBX_txn *txn, const page_t *mp) {
|
|
34
|
+
return mp->txnid == txn->txnid;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
MDBX_NOTHROW_PURE_FUNCTION static inline bool is_shadowed(const MDBX_txn *txn, const page_t *mp) {
|
|
38
|
+
return mp->txnid > txn->txnid;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
MDBX_MAYBE_UNUSED MDBX_NOTHROW_PURE_FUNCTION static inline bool is_correct(const MDBX_txn *txn, const page_t *mp) {
|
|
42
|
+
return mp->txnid <= txn->front_txnid;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
MDBX_NOTHROW_PURE_FUNCTION static inline bool is_modifable(const MDBX_txn *txn, const page_t *mp) {
|
|
46
|
+
return mp->txnid == txn->front_txnid;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
MDBX_INTERNAL int __must_check_result page_check(const MDBX_cursor *const mc, const page_t *const mp);
|
|
50
|
+
|
|
51
|
+
MDBX_INTERNAL pgr_t page_get_any(const MDBX_cursor *const mc, const pgno_t pgno, const txnid_t front);
|
|
52
|
+
|
|
53
|
+
MDBX_INTERNAL pgr_t page_get_three(const MDBX_cursor *const mc, const pgno_t pgno, const txnid_t front);
|
|
54
|
+
|
|
55
|
+
MDBX_INTERNAL pgr_t page_get_large(const MDBX_cursor *const mc, const pgno_t pgno, const txnid_t front);
|
|
56
|
+
|
|
57
|
+
static inline int __must_check_result page_get(const MDBX_cursor *mc, const pgno_t pgno, page_t **mp,
|
|
58
|
+
const txnid_t front) {
|
|
59
|
+
pgr_t ret = page_get_three(mc, pgno, front);
|
|
60
|
+
*mp = ret.page;
|
|
61
|
+
return ret.err;
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
/*----------------------------------------------------------------------------*/
|
|
65
|
+
|
|
66
|
+
MDBX_INTERNAL int __must_check_result page_dirty(MDBX_txn *txn, page_t *mp, size_t npages);
|
|
67
|
+
MDBX_INTERNAL pgr_t page_new(MDBX_cursor *mc, const unsigned flags);
|
|
68
|
+
MDBX_INTERNAL pgr_t page_new_large(MDBX_cursor *mc, const size_t npages);
|
|
69
|
+
MDBX_INTERNAL int page_touch_modifable(MDBX_txn *txn, const page_t *const mp);
|
|
70
|
+
MDBX_INTERNAL int page_touch_unmodifable(MDBX_txn *txn, MDBX_cursor *mc, const page_t *const mp);
|
|
71
|
+
|
|
72
|
+
static inline int page_touch(MDBX_cursor *mc) {
|
|
73
|
+
page_t *const mp = mc->pg[mc->top];
|
|
74
|
+
MDBX_txn *txn = mc->txn;
|
|
75
|
+
|
|
76
|
+
tASSERT(txn, mc->txn->flags & MDBX_TXN_DIRTY);
|
|
77
|
+
tASSERT(txn, F_ISSET(*cursor_dbi_state(mc), DBI_LINDO | DBI_VALID | DBI_DIRTY));
|
|
78
|
+
tASSERT(txn, !is_largepage(mp));
|
|
79
|
+
if (ASSERT_ENABLED()) {
|
|
80
|
+
if (mc->flags & z_inner) {
|
|
81
|
+
subcur_t *mx = container_of(mc->tree, subcur_t, nested_tree);
|
|
82
|
+
cursor_couple_t *couple = container_of(mx, cursor_couple_t, inner);
|
|
83
|
+
tASSERT(txn, mc->tree == &couple->outer.subcur->nested_tree);
|
|
84
|
+
tASSERT(txn, &mc->clc->k == &couple->outer.clc->v);
|
|
85
|
+
tASSERT(txn, *couple->outer.dbi_state & DBI_DIRTY);
|
|
86
|
+
}
|
|
87
|
+
tASSERT(txn, dpl_check(txn));
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
if (is_modifable(txn, mp)) {
|
|
91
|
+
if (!txn->tw.dirtylist) {
|
|
92
|
+
tASSERT(txn, (txn->flags & MDBX_WRITEMAP) && !MDBX_AVOID_MSYNC);
|
|
93
|
+
return MDBX_SUCCESS;
|
|
94
|
+
}
|
|
95
|
+
return is_subpage(mp) ? MDBX_SUCCESS : page_touch_modifable(txn, mp);
|
|
96
|
+
}
|
|
97
|
+
return page_touch_unmodifable(txn, mc, mp);
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
MDBX_INTERNAL void page_copy(page_t *const dst, const page_t *const src, const size_t size);
|
|
101
|
+
MDBX_INTERNAL pgr_t __must_check_result page_unspill(MDBX_txn *const txn, const page_t *const mp);
|
|
102
|
+
|
|
103
|
+
MDBX_INTERNAL page_t *page_shadow_alloc(MDBX_txn *txn, size_t num);
|
|
104
|
+
|
|
105
|
+
MDBX_INTERNAL void page_shadow_release(MDBX_env *env, page_t *dp, size_t npages);
|
|
106
|
+
|
|
107
|
+
MDBX_INTERNAL int page_retire_ex(MDBX_cursor *mc, const pgno_t pgno, page_t *mp /* maybe null */,
|
|
108
|
+
unsigned pageflags /* maybe unknown/zero */);
|
|
109
|
+
|
|
110
|
+
static inline int page_retire(MDBX_cursor *mc, page_t *mp) { return page_retire_ex(mc, mp->pgno, mp, mp->flags); }
|
|
111
|
+
|
|
112
|
+
static inline void page_wash(MDBX_txn *txn, size_t di, page_t *const mp, const size_t npages) {
|
|
113
|
+
tASSERT(txn, (txn->flags & MDBX_TXN_RDONLY) == 0);
|
|
114
|
+
mp->txnid = INVALID_TXNID;
|
|
115
|
+
mp->flags = P_BAD;
|
|
116
|
+
|
|
117
|
+
if (txn->tw.dirtylist) {
|
|
118
|
+
tASSERT(txn, (txn->flags & MDBX_WRITEMAP) == 0 || MDBX_AVOID_MSYNC);
|
|
119
|
+
tASSERT(txn, MDBX_AVOID_MSYNC || (di && txn->tw.dirtylist->items[di].ptr == mp));
|
|
120
|
+
if (!MDBX_AVOID_MSYNC || di) {
|
|
121
|
+
dpl_remove_ex(txn, di, npages);
|
|
122
|
+
txn->tw.dirtyroom++;
|
|
123
|
+
tASSERT(txn, txn->tw.dirtyroom + txn->tw.dirtylist->length ==
|
|
124
|
+
(txn->parent ? txn->parent->tw.dirtyroom : txn->env->options.dp_limit));
|
|
125
|
+
if (!MDBX_AVOID_MSYNC || !(txn->flags & MDBX_WRITEMAP)) {
|
|
126
|
+
page_shadow_release(txn->env, mp, npages);
|
|
127
|
+
return;
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
} else {
|
|
131
|
+
tASSERT(txn, (txn->flags & MDBX_WRITEMAP) && !MDBX_AVOID_MSYNC && !di);
|
|
132
|
+
txn->tw.writemap_dirty_npages -= (txn->tw.writemap_dirty_npages > npages) ? npages : txn->tw.writemap_dirty_npages;
|
|
133
|
+
}
|
|
134
|
+
VALGRIND_MAKE_MEM_UNDEFINED(mp, PAGEHDRSZ);
|
|
135
|
+
VALGRIND_MAKE_MEM_NOACCESS(page_data(mp), pgno2bytes(txn->env, npages) - PAGEHDRSZ);
|
|
136
|
+
MDBX_ASAN_POISON_MEMORY_REGION(page_data(mp), pgno2bytes(txn->env, npages) - PAGEHDRSZ);
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
MDBX_INTERNAL size_t page_subleaf2_reserve(const MDBX_env *env, size_t host_page_room, size_t subpage_len,
|
|
140
|
+
size_t item_len);
|
|
141
|
+
|
|
142
|
+
#define page_next(mp) (*(page_t **)ptr_disp((mp)->entries, sizeof(void *) - sizeof(uint32_t)))
|
|
@@ -0,0 +1,236 @@
|
|
|
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
|
+
pnl_t pnl_alloc(size_t size) {
|
|
7
|
+
size_t bytes = pnl_size2bytes(size);
|
|
8
|
+
pnl_t pnl = osal_malloc(bytes);
|
|
9
|
+
if (likely(pnl)) {
|
|
10
|
+
#ifdef osal_malloc_usable_size
|
|
11
|
+
bytes = osal_malloc_usable_size(pnl);
|
|
12
|
+
#endif /* osal_malloc_usable_size */
|
|
13
|
+
pnl[0] = pnl_bytes2size(bytes);
|
|
14
|
+
assert(pnl[0] >= size);
|
|
15
|
+
pnl += 1;
|
|
16
|
+
*pnl = 0;
|
|
17
|
+
}
|
|
18
|
+
return pnl;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
void pnl_free(pnl_t pnl) {
|
|
22
|
+
if (likely(pnl))
|
|
23
|
+
osal_free(pnl - 1);
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
void pnl_shrink(pnl_t __restrict *__restrict ppnl) {
|
|
27
|
+
assert(pnl_bytes2size(pnl_size2bytes(MDBX_PNL_INITIAL)) >= MDBX_PNL_INITIAL &&
|
|
28
|
+
pnl_bytes2size(pnl_size2bytes(MDBX_PNL_INITIAL)) < MDBX_PNL_INITIAL * 3 / 2);
|
|
29
|
+
assert(MDBX_PNL_GETSIZE(*ppnl) <= PAGELIST_LIMIT && MDBX_PNL_ALLOCLEN(*ppnl) >= MDBX_PNL_GETSIZE(*ppnl));
|
|
30
|
+
MDBX_PNL_SETSIZE(*ppnl, 0);
|
|
31
|
+
if (unlikely(MDBX_PNL_ALLOCLEN(*ppnl) >
|
|
32
|
+
MDBX_PNL_INITIAL * (MDBX_PNL_PREALLOC_FOR_RADIXSORT ? 8 : 4) - MDBX_CACHELINE_SIZE / sizeof(pgno_t))) {
|
|
33
|
+
size_t bytes = pnl_size2bytes(MDBX_PNL_INITIAL * 2);
|
|
34
|
+
pnl_t pnl = osal_realloc(*ppnl - 1, bytes);
|
|
35
|
+
if (likely(pnl)) {
|
|
36
|
+
#ifdef osal_malloc_usable_size
|
|
37
|
+
bytes = osal_malloc_usable_size(pnl);
|
|
38
|
+
#endif /* osal_malloc_usable_size */
|
|
39
|
+
*pnl = pnl_bytes2size(bytes);
|
|
40
|
+
*ppnl = pnl + 1;
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
int pnl_reserve(pnl_t __restrict *__restrict ppnl, const size_t wanna) {
|
|
46
|
+
const size_t allocated = MDBX_PNL_ALLOCLEN(*ppnl);
|
|
47
|
+
assert(MDBX_PNL_GETSIZE(*ppnl) <= PAGELIST_LIMIT && MDBX_PNL_ALLOCLEN(*ppnl) >= MDBX_PNL_GETSIZE(*ppnl));
|
|
48
|
+
if (likely(allocated >= wanna))
|
|
49
|
+
return MDBX_SUCCESS;
|
|
50
|
+
|
|
51
|
+
if (unlikely(wanna > /* paranoia */ PAGELIST_LIMIT)) {
|
|
52
|
+
ERROR("PNL too long (%zu > %zu)", wanna, (size_t)PAGELIST_LIMIT);
|
|
53
|
+
return MDBX_TXN_FULL;
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
const size_t size = (wanna + wanna - allocated < PAGELIST_LIMIT) ? wanna + wanna - allocated : PAGELIST_LIMIT;
|
|
57
|
+
size_t bytes = pnl_size2bytes(size);
|
|
58
|
+
pnl_t pnl = osal_realloc(*ppnl - 1, bytes);
|
|
59
|
+
if (likely(pnl)) {
|
|
60
|
+
#ifdef osal_malloc_usable_size
|
|
61
|
+
bytes = osal_malloc_usable_size(pnl);
|
|
62
|
+
#endif /* osal_malloc_usable_size */
|
|
63
|
+
*pnl = pnl_bytes2size(bytes);
|
|
64
|
+
assert(*pnl >= wanna);
|
|
65
|
+
*ppnl = pnl + 1;
|
|
66
|
+
return MDBX_SUCCESS;
|
|
67
|
+
}
|
|
68
|
+
return MDBX_ENOMEM;
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
static __always_inline int __must_check_result pnl_append_stepped(unsigned step, __restrict pnl_t *ppnl, pgno_t pgno,
|
|
72
|
+
size_t n) {
|
|
73
|
+
assert(n > 0);
|
|
74
|
+
int rc = pnl_need(ppnl, n);
|
|
75
|
+
if (unlikely(rc != MDBX_SUCCESS))
|
|
76
|
+
return rc;
|
|
77
|
+
|
|
78
|
+
const pnl_t pnl = *ppnl;
|
|
79
|
+
if (likely(n == 1)) {
|
|
80
|
+
pnl_append_prereserved(pnl, pgno);
|
|
81
|
+
return MDBX_SUCCESS;
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
#if MDBX_PNL_ASCENDING
|
|
85
|
+
size_t w = MDBX_PNL_GETSIZE(pnl);
|
|
86
|
+
do {
|
|
87
|
+
pnl[++w] = pgno;
|
|
88
|
+
pgno += step;
|
|
89
|
+
} while (--n);
|
|
90
|
+
MDBX_PNL_SETSIZE(pnl, w);
|
|
91
|
+
#else
|
|
92
|
+
size_t w = MDBX_PNL_GETSIZE(pnl) + n;
|
|
93
|
+
MDBX_PNL_SETSIZE(pnl, w);
|
|
94
|
+
do {
|
|
95
|
+
pnl[w--] = pgno;
|
|
96
|
+
pgno += step;
|
|
97
|
+
} while (--n);
|
|
98
|
+
#endif
|
|
99
|
+
return MDBX_SUCCESS;
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
__hot int __must_check_result spill_append_span(__restrict pnl_t *ppnl, pgno_t pgno, size_t n) {
|
|
103
|
+
return pnl_append_stepped(2, ppnl, pgno << 1, n);
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
__hot int __must_check_result pnl_append_span(__restrict pnl_t *ppnl, pgno_t pgno, size_t n) {
|
|
107
|
+
return pnl_append_stepped(1, ppnl, pgno, n);
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
__hot int __must_check_result pnl_insert_span(__restrict pnl_t *ppnl, pgno_t pgno, size_t n) {
|
|
111
|
+
assert(n > 0);
|
|
112
|
+
int rc = pnl_need(ppnl, n);
|
|
113
|
+
if (unlikely(rc != MDBX_SUCCESS))
|
|
114
|
+
return rc;
|
|
115
|
+
|
|
116
|
+
const pnl_t pnl = *ppnl;
|
|
117
|
+
size_t r = MDBX_PNL_GETSIZE(pnl), w = r + n;
|
|
118
|
+
MDBX_PNL_SETSIZE(pnl, w);
|
|
119
|
+
while (r && MDBX_PNL_DISORDERED(pnl[r], pgno))
|
|
120
|
+
pnl[w--] = pnl[r--];
|
|
121
|
+
|
|
122
|
+
for (pgno_t fill = MDBX_PNL_ASCENDING ? pgno + n : pgno; w > r; --w)
|
|
123
|
+
pnl[w] = MDBX_PNL_ASCENDING ? --fill : fill++;
|
|
124
|
+
|
|
125
|
+
return MDBX_SUCCESS;
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
__hot __noinline bool pnl_check(const const_pnl_t pnl, const size_t limit) {
|
|
129
|
+
assert(limit >= MIN_PAGENO - MDBX_ENABLE_REFUND);
|
|
130
|
+
if (likely(MDBX_PNL_GETSIZE(pnl))) {
|
|
131
|
+
if (unlikely(MDBX_PNL_GETSIZE(pnl) > PAGELIST_LIMIT))
|
|
132
|
+
return false;
|
|
133
|
+
if (unlikely(MDBX_PNL_LEAST(pnl) < MIN_PAGENO))
|
|
134
|
+
return false;
|
|
135
|
+
if (unlikely(MDBX_PNL_MOST(pnl) >= limit))
|
|
136
|
+
return false;
|
|
137
|
+
|
|
138
|
+
if ((!MDBX_DISABLE_VALIDATION || AUDIT_ENABLED()) && likely(MDBX_PNL_GETSIZE(pnl) > 1)) {
|
|
139
|
+
const pgno_t *scan = MDBX_PNL_BEGIN(pnl);
|
|
140
|
+
const pgno_t *const end = MDBX_PNL_END(pnl);
|
|
141
|
+
pgno_t prev = *scan++;
|
|
142
|
+
do {
|
|
143
|
+
if (unlikely(!MDBX_PNL_ORDERED(prev, *scan)))
|
|
144
|
+
return false;
|
|
145
|
+
prev = *scan;
|
|
146
|
+
} while (likely(++scan != end));
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
return true;
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
static __always_inline void pnl_merge_inner(pgno_t *__restrict dst, const pgno_t *__restrict src_a,
|
|
153
|
+
const pgno_t *__restrict src_b,
|
|
154
|
+
const pgno_t *__restrict const src_b_detent) {
|
|
155
|
+
do {
|
|
156
|
+
#if MDBX_HAVE_CMOV
|
|
157
|
+
const bool flag = MDBX_PNL_ORDERED(*src_b, *src_a);
|
|
158
|
+
#if defined(__LCC__) || __CLANG_PREREQ(13, 0)
|
|
159
|
+
// lcc 1.26: 13ШК (подготовка и первая итерация) + 7ШК (цикл), БЕЗ loop-mode
|
|
160
|
+
// gcc>=7: cmp+jmp с возвратом в тело цикла (WTF?)
|
|
161
|
+
// gcc<=6: cmov×3
|
|
162
|
+
// clang<=12: cmov×3
|
|
163
|
+
// clang>=13: cmov, set+add/sub
|
|
164
|
+
*dst = flag ? *src_a-- : *src_b--;
|
|
165
|
+
#else
|
|
166
|
+
// gcc: cmov, cmp+set+add/sub
|
|
167
|
+
// clang<=5: cmov×2, set+add/sub
|
|
168
|
+
// clang>=6: cmov, set+add/sub
|
|
169
|
+
*dst = flag ? *src_a : *src_b;
|
|
170
|
+
src_b += (ptrdiff_t)flag - 1;
|
|
171
|
+
src_a -= flag;
|
|
172
|
+
#endif
|
|
173
|
+
--dst;
|
|
174
|
+
#else /* MDBX_HAVE_CMOV */
|
|
175
|
+
while (MDBX_PNL_ORDERED(*src_b, *src_a))
|
|
176
|
+
*dst-- = *src_a--;
|
|
177
|
+
*dst-- = *src_b--;
|
|
178
|
+
#endif /* !MDBX_HAVE_CMOV */
|
|
179
|
+
} while (likely(src_b > src_b_detent));
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
__hot size_t pnl_merge(pnl_t dst, const pnl_t src) {
|
|
183
|
+
assert(pnl_check_allocated(dst, MAX_PAGENO + 1));
|
|
184
|
+
assert(pnl_check(src, MAX_PAGENO + 1));
|
|
185
|
+
const size_t src_len = MDBX_PNL_GETSIZE(src);
|
|
186
|
+
const size_t dst_len = MDBX_PNL_GETSIZE(dst);
|
|
187
|
+
size_t total = dst_len;
|
|
188
|
+
assert(MDBX_PNL_ALLOCLEN(dst) >= total);
|
|
189
|
+
if (likely(src_len > 0)) {
|
|
190
|
+
total += src_len;
|
|
191
|
+
if (!MDBX_DEBUG && total < (MDBX_HAVE_CMOV ? 21 : 12))
|
|
192
|
+
goto avoid_call_libc_for_short_cases;
|
|
193
|
+
if (dst_len == 0 || MDBX_PNL_ORDERED(MDBX_PNL_LAST(dst), MDBX_PNL_FIRST(src)))
|
|
194
|
+
memcpy(MDBX_PNL_END(dst), MDBX_PNL_BEGIN(src), src_len * sizeof(pgno_t));
|
|
195
|
+
else if (MDBX_PNL_ORDERED(MDBX_PNL_LAST(src), MDBX_PNL_FIRST(dst))) {
|
|
196
|
+
memmove(MDBX_PNL_BEGIN(dst) + src_len, MDBX_PNL_BEGIN(dst), dst_len * sizeof(pgno_t));
|
|
197
|
+
memcpy(MDBX_PNL_BEGIN(dst), MDBX_PNL_BEGIN(src), src_len * sizeof(pgno_t));
|
|
198
|
+
} else {
|
|
199
|
+
avoid_call_libc_for_short_cases:
|
|
200
|
+
dst[0] = /* the detent */ (MDBX_PNL_ASCENDING ? 0 : P_INVALID);
|
|
201
|
+
pnl_merge_inner(dst + total, dst + dst_len, src + src_len, src);
|
|
202
|
+
}
|
|
203
|
+
MDBX_PNL_SETSIZE(dst, total);
|
|
204
|
+
}
|
|
205
|
+
assert(pnl_check_allocated(dst, MAX_PAGENO + 1));
|
|
206
|
+
return total;
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
#if MDBX_PNL_ASCENDING
|
|
210
|
+
#define MDBX_PNL_EXTRACT_KEY(ptr) (*(ptr))
|
|
211
|
+
#else
|
|
212
|
+
#define MDBX_PNL_EXTRACT_KEY(ptr) (P_INVALID - *(ptr))
|
|
213
|
+
#endif
|
|
214
|
+
RADIXSORT_IMPL(pgno, pgno_t, MDBX_PNL_EXTRACT_KEY, MDBX_PNL_PREALLOC_FOR_RADIXSORT, 0)
|
|
215
|
+
|
|
216
|
+
SORT_IMPL(pgno_sort, false, pgno_t, MDBX_PNL_ORDERED)
|
|
217
|
+
|
|
218
|
+
__hot __noinline void pnl_sort_nochk(pnl_t pnl) {
|
|
219
|
+
if (likely(MDBX_PNL_GETSIZE(pnl) < MDBX_RADIXSORT_THRESHOLD) ||
|
|
220
|
+
unlikely(!pgno_radixsort(&MDBX_PNL_FIRST(pnl), MDBX_PNL_GETSIZE(pnl))))
|
|
221
|
+
pgno_sort(MDBX_PNL_BEGIN(pnl), MDBX_PNL_END(pnl));
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
SEARCH_IMPL(pgno_bsearch, pgno_t, pgno_t, MDBX_PNL_ORDERED)
|
|
225
|
+
|
|
226
|
+
__hot __noinline size_t pnl_search_nochk(const pnl_t pnl, pgno_t pgno) {
|
|
227
|
+
const pgno_t *begin = MDBX_PNL_BEGIN(pnl);
|
|
228
|
+
const pgno_t *it = pgno_bsearch(begin, MDBX_PNL_GETSIZE(pnl), pgno);
|
|
229
|
+
const pgno_t *end = begin + MDBX_PNL_GETSIZE(pnl);
|
|
230
|
+
assert(it >= begin && it <= end);
|
|
231
|
+
if (it != begin)
|
|
232
|
+
assert(MDBX_PNL_ORDERED(it[-1], pgno));
|
|
233
|
+
if (it != end)
|
|
234
|
+
assert(!MDBX_PNL_ORDERED(it[0], pgno));
|
|
235
|
+
return it - begin + 1;
|
|
236
|
+
}
|
|
@@ -0,0 +1,146 @@
|
|
|
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
|
+
#pragma once
|
|
7
|
+
|
|
8
|
+
#include "essentials.h"
|
|
9
|
+
|
|
10
|
+
/* An PNL is an Page Number List, a sorted array of IDs.
|
|
11
|
+
*
|
|
12
|
+
* The first element of the array is a counter for how many actual page-numbers
|
|
13
|
+
* are in the list. By default PNLs are sorted in descending order, this allow
|
|
14
|
+
* cut off a page with lowest pgno (at the tail) just truncating the list. The
|
|
15
|
+
* sort order of PNLs is controlled by the MDBX_PNL_ASCENDING build option. */
|
|
16
|
+
typedef pgno_t *pnl_t;
|
|
17
|
+
typedef const pgno_t *const_pnl_t;
|
|
18
|
+
|
|
19
|
+
#if MDBX_PNL_ASCENDING
|
|
20
|
+
#define MDBX_PNL_ORDERED(first, last) ((first) < (last))
|
|
21
|
+
#define MDBX_PNL_DISORDERED(first, last) ((first) >= (last))
|
|
22
|
+
#else
|
|
23
|
+
#define MDBX_PNL_ORDERED(first, last) ((first) > (last))
|
|
24
|
+
#define MDBX_PNL_DISORDERED(first, last) ((first) <= (last))
|
|
25
|
+
#endif
|
|
26
|
+
|
|
27
|
+
#define MDBX_PNL_GRANULATE_LOG2 10
|
|
28
|
+
#define MDBX_PNL_GRANULATE (1 << MDBX_PNL_GRANULATE_LOG2)
|
|
29
|
+
#define MDBX_PNL_INITIAL (MDBX_PNL_GRANULATE - 2 - MDBX_ASSUME_MALLOC_OVERHEAD / sizeof(pgno_t))
|
|
30
|
+
|
|
31
|
+
#define MDBX_PNL_ALLOCLEN(pl) ((pl)[-1])
|
|
32
|
+
#define MDBX_PNL_GETSIZE(pl) ((size_t)((pl)[0]))
|
|
33
|
+
#define MDBX_PNL_SETSIZE(pl, size) \
|
|
34
|
+
do { \
|
|
35
|
+
const size_t __size = size; \
|
|
36
|
+
assert(__size < INT_MAX); \
|
|
37
|
+
(pl)[0] = (pgno_t)__size; \
|
|
38
|
+
} while (0)
|
|
39
|
+
#define MDBX_PNL_FIRST(pl) ((pl)[1])
|
|
40
|
+
#define MDBX_PNL_LAST(pl) ((pl)[MDBX_PNL_GETSIZE(pl)])
|
|
41
|
+
#define MDBX_PNL_BEGIN(pl) (&(pl)[1])
|
|
42
|
+
#define MDBX_PNL_END(pl) (&(pl)[MDBX_PNL_GETSIZE(pl) + 1])
|
|
43
|
+
|
|
44
|
+
#if MDBX_PNL_ASCENDING
|
|
45
|
+
#define MDBX_PNL_EDGE(pl) ((pl) + 1)
|
|
46
|
+
#define MDBX_PNL_LEAST(pl) MDBX_PNL_FIRST(pl)
|
|
47
|
+
#define MDBX_PNL_MOST(pl) MDBX_PNL_LAST(pl)
|
|
48
|
+
#else
|
|
49
|
+
#define MDBX_PNL_EDGE(pl) ((pl) + MDBX_PNL_GETSIZE(pl))
|
|
50
|
+
#define MDBX_PNL_LEAST(pl) MDBX_PNL_LAST(pl)
|
|
51
|
+
#define MDBX_PNL_MOST(pl) MDBX_PNL_FIRST(pl)
|
|
52
|
+
#endif
|
|
53
|
+
|
|
54
|
+
#define MDBX_PNL_SIZEOF(pl) ((MDBX_PNL_GETSIZE(pl) + 1) * sizeof(pgno_t))
|
|
55
|
+
#define MDBX_PNL_IS_EMPTY(pl) (MDBX_PNL_GETSIZE(pl) == 0)
|
|
56
|
+
|
|
57
|
+
MDBX_MAYBE_UNUSED static inline size_t pnl_size2bytes(size_t size) {
|
|
58
|
+
assert(size > 0 && size <= PAGELIST_LIMIT);
|
|
59
|
+
#if MDBX_PNL_PREALLOC_FOR_RADIXSORT
|
|
60
|
+
|
|
61
|
+
size += size;
|
|
62
|
+
#endif /* MDBX_PNL_PREALLOC_FOR_RADIXSORT */
|
|
63
|
+
STATIC_ASSERT(MDBX_ASSUME_MALLOC_OVERHEAD +
|
|
64
|
+
(PAGELIST_LIMIT * (MDBX_PNL_PREALLOC_FOR_RADIXSORT + 1) + MDBX_PNL_GRANULATE + 3) * sizeof(pgno_t) <
|
|
65
|
+
SIZE_MAX / 4 * 3);
|
|
66
|
+
size_t bytes =
|
|
67
|
+
ceil_powerof2(MDBX_ASSUME_MALLOC_OVERHEAD + sizeof(pgno_t) * (size + 3), MDBX_PNL_GRANULATE * sizeof(pgno_t)) -
|
|
68
|
+
MDBX_ASSUME_MALLOC_OVERHEAD;
|
|
69
|
+
return bytes;
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
MDBX_MAYBE_UNUSED static inline pgno_t pnl_bytes2size(const size_t bytes) {
|
|
73
|
+
size_t size = bytes / sizeof(pgno_t);
|
|
74
|
+
assert(size > 3 && size <= PAGELIST_LIMIT + /* alignment gap */ 65536);
|
|
75
|
+
size -= 3;
|
|
76
|
+
#if MDBX_PNL_PREALLOC_FOR_RADIXSORT
|
|
77
|
+
size >>= 1;
|
|
78
|
+
#endif /* MDBX_PNL_PREALLOC_FOR_RADIXSORT */
|
|
79
|
+
return (pgno_t)size;
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
MDBX_INTERNAL pnl_t pnl_alloc(size_t size);
|
|
83
|
+
|
|
84
|
+
MDBX_INTERNAL void pnl_free(pnl_t pnl);
|
|
85
|
+
|
|
86
|
+
MDBX_INTERNAL int pnl_reserve(pnl_t __restrict *__restrict ppnl, const size_t wanna);
|
|
87
|
+
|
|
88
|
+
MDBX_MAYBE_UNUSED static inline int __must_check_result pnl_need(pnl_t __restrict *__restrict ppnl, size_t num) {
|
|
89
|
+
assert(MDBX_PNL_GETSIZE(*ppnl) <= PAGELIST_LIMIT && MDBX_PNL_ALLOCLEN(*ppnl) >= MDBX_PNL_GETSIZE(*ppnl));
|
|
90
|
+
assert(num <= PAGELIST_LIMIT);
|
|
91
|
+
const size_t wanna = MDBX_PNL_GETSIZE(*ppnl) + num;
|
|
92
|
+
return likely(MDBX_PNL_ALLOCLEN(*ppnl) >= wanna) ? MDBX_SUCCESS : pnl_reserve(ppnl, wanna);
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
MDBX_MAYBE_UNUSED static inline void pnl_append_prereserved(__restrict pnl_t pnl, pgno_t pgno) {
|
|
96
|
+
assert(MDBX_PNL_GETSIZE(pnl) < MDBX_PNL_ALLOCLEN(pnl));
|
|
97
|
+
if (AUDIT_ENABLED()) {
|
|
98
|
+
for (size_t i = MDBX_PNL_GETSIZE(pnl); i > 0; --i)
|
|
99
|
+
assert(pgno != pnl[i]);
|
|
100
|
+
}
|
|
101
|
+
*pnl += 1;
|
|
102
|
+
MDBX_PNL_LAST(pnl) = pgno;
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
MDBX_INTERNAL void pnl_shrink(pnl_t __restrict *__restrict ppnl);
|
|
106
|
+
|
|
107
|
+
MDBX_INTERNAL int __must_check_result spill_append_span(__restrict pnl_t *ppnl, pgno_t pgno, size_t n);
|
|
108
|
+
|
|
109
|
+
MDBX_INTERNAL int __must_check_result pnl_append_span(__restrict pnl_t *ppnl, pgno_t pgno, size_t n);
|
|
110
|
+
|
|
111
|
+
MDBX_INTERNAL int __must_check_result pnl_insert_span(__restrict pnl_t *ppnl, pgno_t pgno, size_t n);
|
|
112
|
+
|
|
113
|
+
MDBX_INTERNAL size_t pnl_search_nochk(const pnl_t pnl, pgno_t pgno);
|
|
114
|
+
|
|
115
|
+
MDBX_INTERNAL void pnl_sort_nochk(pnl_t pnl);
|
|
116
|
+
|
|
117
|
+
MDBX_INTERNAL bool pnl_check(const const_pnl_t pnl, const size_t limit);
|
|
118
|
+
|
|
119
|
+
MDBX_MAYBE_UNUSED static inline bool pnl_check_allocated(const const_pnl_t pnl, const size_t limit) {
|
|
120
|
+
return pnl == nullptr || (MDBX_PNL_ALLOCLEN(pnl) >= MDBX_PNL_GETSIZE(pnl) && pnl_check(pnl, limit));
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
MDBX_MAYBE_UNUSED static inline void pnl_sort(pnl_t pnl, size_t limit4check) {
|
|
124
|
+
pnl_sort_nochk(pnl);
|
|
125
|
+
assert(pnl_check(pnl, limit4check));
|
|
126
|
+
(void)limit4check;
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
MDBX_MAYBE_UNUSED static inline size_t pnl_search(const pnl_t pnl, pgno_t pgno, size_t limit) {
|
|
130
|
+
assert(pnl_check_allocated(pnl, limit));
|
|
131
|
+
if (MDBX_HAVE_CMOV) {
|
|
132
|
+
/* cmov-ускоренный бинарный поиск может читать (но не использовать) один
|
|
133
|
+
* элемент за концом данных, этот элемент в пределах выделенного участка
|
|
134
|
+
* памяти, но не инициализирован. */
|
|
135
|
+
VALGRIND_MAKE_MEM_DEFINED(MDBX_PNL_END(pnl), sizeof(pgno_t));
|
|
136
|
+
}
|
|
137
|
+
assert(pgno < limit);
|
|
138
|
+
(void)limit;
|
|
139
|
+
size_t n = pnl_search_nochk(pnl, pgno);
|
|
140
|
+
if (MDBX_HAVE_CMOV) {
|
|
141
|
+
VALGRIND_MAKE_MEM_UNDEFINED(MDBX_PNL_END(pnl), sizeof(pgno_t));
|
|
142
|
+
}
|
|
143
|
+
return n;
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
MDBX_INTERNAL size_t pnl_merge(pnl_t dst, const pnl_t src);
|