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,364 @@
|
|
|
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
|
+
#ifndef __cplusplus
|
|
9
|
+
|
|
10
|
+
#ifdef MDBX_HAVE_C11ATOMICS
|
|
11
|
+
#define osal_memory_fence(order, write) atomic_thread_fence((write) ? mo_c11_store(order) : mo_c11_load(order))
|
|
12
|
+
#else /* MDBX_HAVE_C11ATOMICS */
|
|
13
|
+
#define osal_memory_fence(order, write) \
|
|
14
|
+
do { \
|
|
15
|
+
osal_compiler_barrier(); \
|
|
16
|
+
if (write && order > (MDBX_CPU_WRITEBACK_INCOHERENT ? mo_Relaxed : mo_AcquireRelease)) \
|
|
17
|
+
osal_memory_barrier(); \
|
|
18
|
+
} while (0)
|
|
19
|
+
#endif /* MDBX_HAVE_C11ATOMICS */
|
|
20
|
+
|
|
21
|
+
#if defined(MDBX_HAVE_C11ATOMICS) && defined(__LCC__)
|
|
22
|
+
#define atomic_store32(p, value, order) \
|
|
23
|
+
({ \
|
|
24
|
+
const uint32_t value_to_store = (value); \
|
|
25
|
+
atomic_store_explicit(MDBX_c11a_rw(uint32_t, p), value_to_store, mo_c11_store(order)); \
|
|
26
|
+
value_to_store; \
|
|
27
|
+
})
|
|
28
|
+
#define atomic_load32(p, order) atomic_load_explicit(MDBX_c11a_ro(uint32_t, p), mo_c11_load(order))
|
|
29
|
+
#define atomic_store64(p, value, order) \
|
|
30
|
+
({ \
|
|
31
|
+
const uint64_t value_to_store = (value); \
|
|
32
|
+
atomic_store_explicit(MDBX_c11a_rw(uint64_t, p), value_to_store, mo_c11_store(order)); \
|
|
33
|
+
value_to_store; \
|
|
34
|
+
})
|
|
35
|
+
#define atomic_load64(p, order) atomic_load_explicit(MDBX_c11a_ro(uint64_t, p), mo_c11_load(order))
|
|
36
|
+
#endif /* LCC && MDBX_HAVE_C11ATOMICS */
|
|
37
|
+
|
|
38
|
+
#ifndef atomic_store32
|
|
39
|
+
MDBX_MAYBE_UNUSED static __always_inline uint32_t atomic_store32(mdbx_atomic_uint32_t *p, const uint32_t value,
|
|
40
|
+
enum mdbx_memory_order order) {
|
|
41
|
+
STATIC_ASSERT(sizeof(mdbx_atomic_uint32_t) == 4);
|
|
42
|
+
#ifdef MDBX_HAVE_C11ATOMICS
|
|
43
|
+
assert(atomic_is_lock_free(MDBX_c11a_rw(uint32_t, p)));
|
|
44
|
+
atomic_store_explicit(MDBX_c11a_rw(uint32_t, p), value, mo_c11_store(order));
|
|
45
|
+
#else /* MDBX_HAVE_C11ATOMICS */
|
|
46
|
+
if (order != mo_Relaxed)
|
|
47
|
+
osal_compiler_barrier();
|
|
48
|
+
p->weak = value;
|
|
49
|
+
osal_memory_fence(order, true);
|
|
50
|
+
#endif /* MDBX_HAVE_C11ATOMICS */
|
|
51
|
+
return value;
|
|
52
|
+
}
|
|
53
|
+
#endif /* atomic_store32 */
|
|
54
|
+
|
|
55
|
+
#ifndef atomic_load32
|
|
56
|
+
MDBX_MAYBE_UNUSED static __always_inline uint32_t atomic_load32(const volatile mdbx_atomic_uint32_t *p,
|
|
57
|
+
enum mdbx_memory_order order) {
|
|
58
|
+
STATIC_ASSERT(sizeof(mdbx_atomic_uint32_t) == 4);
|
|
59
|
+
#ifdef MDBX_HAVE_C11ATOMICS
|
|
60
|
+
assert(atomic_is_lock_free(MDBX_c11a_ro(uint32_t, p)));
|
|
61
|
+
return atomic_load_explicit(MDBX_c11a_ro(uint32_t, p), mo_c11_load(order));
|
|
62
|
+
#else /* MDBX_HAVE_C11ATOMICS */
|
|
63
|
+
osal_memory_fence(order, false);
|
|
64
|
+
const uint32_t value = p->weak;
|
|
65
|
+
if (order != mo_Relaxed)
|
|
66
|
+
osal_compiler_barrier();
|
|
67
|
+
return value;
|
|
68
|
+
#endif /* MDBX_HAVE_C11ATOMICS */
|
|
69
|
+
}
|
|
70
|
+
#endif /* atomic_load32 */
|
|
71
|
+
|
|
72
|
+
/*------------------------------------------------------------------------------
|
|
73
|
+
* safe read/write volatile 64-bit fields on 32-bit architectures. */
|
|
74
|
+
|
|
75
|
+
/* LY: for testing non-atomic 64-bit txnid on 32-bit arches.
|
|
76
|
+
* #define xMDBX_TXNID_STEP (UINT32_MAX / 3) */
|
|
77
|
+
#ifndef xMDBX_TXNID_STEP
|
|
78
|
+
#if MDBX_64BIT_CAS
|
|
79
|
+
#define xMDBX_TXNID_STEP 1u
|
|
80
|
+
#else
|
|
81
|
+
#define xMDBX_TXNID_STEP 2u
|
|
82
|
+
#endif
|
|
83
|
+
#endif /* xMDBX_TXNID_STEP */
|
|
84
|
+
|
|
85
|
+
#ifndef atomic_store64
|
|
86
|
+
MDBX_MAYBE_UNUSED static __always_inline uint64_t atomic_store64(mdbx_atomic_uint64_t *p, const uint64_t value,
|
|
87
|
+
enum mdbx_memory_order order) {
|
|
88
|
+
STATIC_ASSERT(sizeof(mdbx_atomic_uint64_t) == 8);
|
|
89
|
+
#if MDBX_64BIT_ATOMIC
|
|
90
|
+
#if __GNUC_PREREQ(11, 0)
|
|
91
|
+
STATIC_ASSERT(__alignof__(mdbx_atomic_uint64_t) >= sizeof(uint64_t));
|
|
92
|
+
#endif /* GNU C >= 11 */
|
|
93
|
+
#ifdef MDBX_HAVE_C11ATOMICS
|
|
94
|
+
assert(atomic_is_lock_free(MDBX_c11a_rw(uint64_t, p)));
|
|
95
|
+
atomic_store_explicit(MDBX_c11a_rw(uint64_t, p), value, mo_c11_store(order));
|
|
96
|
+
#else /* MDBX_HAVE_C11ATOMICS */
|
|
97
|
+
if (order != mo_Relaxed)
|
|
98
|
+
osal_compiler_barrier();
|
|
99
|
+
p->weak = value;
|
|
100
|
+
osal_memory_fence(order, true);
|
|
101
|
+
#endif /* MDBX_HAVE_C11ATOMICS */
|
|
102
|
+
#else /* !MDBX_64BIT_ATOMIC */
|
|
103
|
+
osal_compiler_barrier();
|
|
104
|
+
atomic_store32(&p->low, (uint32_t)value, mo_Relaxed);
|
|
105
|
+
jitter4testing(true);
|
|
106
|
+
atomic_store32(&p->high, (uint32_t)(value >> 32), order);
|
|
107
|
+
jitter4testing(true);
|
|
108
|
+
#endif /* !MDBX_64BIT_ATOMIC */
|
|
109
|
+
return value;
|
|
110
|
+
}
|
|
111
|
+
#endif /* atomic_store64 */
|
|
112
|
+
|
|
113
|
+
#ifndef atomic_load64
|
|
114
|
+
MDBX_MAYBE_UNUSED static
|
|
115
|
+
#if MDBX_64BIT_ATOMIC
|
|
116
|
+
__always_inline
|
|
117
|
+
#endif /* MDBX_64BIT_ATOMIC */
|
|
118
|
+
uint64_t
|
|
119
|
+
atomic_load64(const volatile mdbx_atomic_uint64_t *p, enum mdbx_memory_order order) {
|
|
120
|
+
STATIC_ASSERT(sizeof(mdbx_atomic_uint64_t) == 8);
|
|
121
|
+
#if MDBX_64BIT_ATOMIC
|
|
122
|
+
#ifdef MDBX_HAVE_C11ATOMICS
|
|
123
|
+
assert(atomic_is_lock_free(MDBX_c11a_ro(uint64_t, p)));
|
|
124
|
+
return atomic_load_explicit(MDBX_c11a_ro(uint64_t, p), mo_c11_load(order));
|
|
125
|
+
#else /* MDBX_HAVE_C11ATOMICS */
|
|
126
|
+
osal_memory_fence(order, false);
|
|
127
|
+
const uint64_t value = p->weak;
|
|
128
|
+
if (order != mo_Relaxed)
|
|
129
|
+
osal_compiler_barrier();
|
|
130
|
+
return value;
|
|
131
|
+
#endif /* MDBX_HAVE_C11ATOMICS */
|
|
132
|
+
#else /* !MDBX_64BIT_ATOMIC */
|
|
133
|
+
osal_compiler_barrier();
|
|
134
|
+
uint64_t value = (uint64_t)atomic_load32(&p->high, order) << 32;
|
|
135
|
+
jitter4testing(true);
|
|
136
|
+
value |= atomic_load32(&p->low, (order == mo_Relaxed) ? mo_Relaxed : mo_AcquireRelease);
|
|
137
|
+
jitter4testing(true);
|
|
138
|
+
for (;;) {
|
|
139
|
+
osal_compiler_barrier();
|
|
140
|
+
uint64_t again = (uint64_t)atomic_load32(&p->high, order) << 32;
|
|
141
|
+
jitter4testing(true);
|
|
142
|
+
again |= atomic_load32(&p->low, (order == mo_Relaxed) ? mo_Relaxed : mo_AcquireRelease);
|
|
143
|
+
jitter4testing(true);
|
|
144
|
+
if (likely(value == again))
|
|
145
|
+
return value;
|
|
146
|
+
value = again;
|
|
147
|
+
}
|
|
148
|
+
#endif /* !MDBX_64BIT_ATOMIC */
|
|
149
|
+
}
|
|
150
|
+
#endif /* atomic_load64 */
|
|
151
|
+
|
|
152
|
+
MDBX_MAYBE_UNUSED static __always_inline void atomic_yield(void) {
|
|
153
|
+
#if defined(_WIN32) || defined(_WIN64)
|
|
154
|
+
YieldProcessor();
|
|
155
|
+
#elif defined(__ia32__) || defined(__e2k__)
|
|
156
|
+
__builtin_ia32_pause();
|
|
157
|
+
#elif defined(__ia64__)
|
|
158
|
+
#if defined(__HP_cc__) || defined(__HP_aCC__)
|
|
159
|
+
_Asm_hint(_HINT_PAUSE);
|
|
160
|
+
#else
|
|
161
|
+
__asm__ __volatile__("hint @pause");
|
|
162
|
+
#endif
|
|
163
|
+
#elif defined(__aarch64__) || (defined(__ARM_ARCH) && __ARM_ARCH > 6) || defined(__ARM_ARCH_6K__)
|
|
164
|
+
#ifdef __CC_ARM
|
|
165
|
+
__yield();
|
|
166
|
+
#else
|
|
167
|
+
__asm__ __volatile__("yield");
|
|
168
|
+
#endif
|
|
169
|
+
#elif (defined(__mips64) || defined(__mips64__)) && defined(__mips_isa_rev) && __mips_isa_rev >= 2
|
|
170
|
+
__asm__ __volatile__("pause");
|
|
171
|
+
#elif defined(__mips) || defined(__mips__) || defined(__mips64) || defined(__mips64__) || defined(_M_MRX000) || \
|
|
172
|
+
defined(_MIPS_) || defined(__MWERKS__) || defined(__sgi)
|
|
173
|
+
__asm__ __volatile__(".word 0x00000140");
|
|
174
|
+
#elif defined(__linux__) || defined(__gnu_linux__) || defined(_UNIX03_SOURCE)
|
|
175
|
+
sched_yield();
|
|
176
|
+
#elif (defined(_GNU_SOURCE) && __GLIBC_PREREQ(2, 1)) || defined(_OPEN_THREADS)
|
|
177
|
+
pthread_yield();
|
|
178
|
+
#endif
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
#if MDBX_64BIT_CAS
|
|
182
|
+
MDBX_MAYBE_UNUSED static __always_inline bool atomic_cas64(mdbx_atomic_uint64_t *p, uint64_t c, uint64_t v) {
|
|
183
|
+
#ifdef MDBX_HAVE_C11ATOMICS
|
|
184
|
+
STATIC_ASSERT(sizeof(long long) >= sizeof(uint64_t));
|
|
185
|
+
assert(atomic_is_lock_free(MDBX_c11a_rw(uint64_t, p)));
|
|
186
|
+
return atomic_compare_exchange_strong(MDBX_c11a_rw(uint64_t, p), &c, v);
|
|
187
|
+
#elif defined(__GNUC__) || defined(__clang__)
|
|
188
|
+
return __sync_bool_compare_and_swap(&p->weak, c, v);
|
|
189
|
+
#elif defined(_MSC_VER)
|
|
190
|
+
return c == (uint64_t)_InterlockedCompareExchange64((volatile __int64 *)&p->weak, v, c);
|
|
191
|
+
#elif defined(__APPLE__)
|
|
192
|
+
return OSAtomicCompareAndSwap64Barrier(c, v, &p->weak);
|
|
193
|
+
#else
|
|
194
|
+
#error FIXME: Unsupported compiler
|
|
195
|
+
#endif
|
|
196
|
+
}
|
|
197
|
+
#endif /* MDBX_64BIT_CAS */
|
|
198
|
+
|
|
199
|
+
MDBX_MAYBE_UNUSED static __always_inline bool atomic_cas32(mdbx_atomic_uint32_t *p, uint32_t c, uint32_t v) {
|
|
200
|
+
#ifdef MDBX_HAVE_C11ATOMICS
|
|
201
|
+
STATIC_ASSERT(sizeof(int) >= sizeof(uint32_t));
|
|
202
|
+
assert(atomic_is_lock_free(MDBX_c11a_rw(uint32_t, p)));
|
|
203
|
+
return atomic_compare_exchange_strong(MDBX_c11a_rw(uint32_t, p), &c, v);
|
|
204
|
+
#elif defined(__GNUC__) || defined(__clang__)
|
|
205
|
+
return __sync_bool_compare_and_swap(&p->weak, c, v);
|
|
206
|
+
#elif defined(_MSC_VER)
|
|
207
|
+
STATIC_ASSERT(sizeof(volatile long) == sizeof(volatile uint32_t));
|
|
208
|
+
return c == (uint32_t)_InterlockedCompareExchange((volatile long *)&p->weak, v, c);
|
|
209
|
+
#elif defined(__APPLE__)
|
|
210
|
+
return OSAtomicCompareAndSwap32Barrier(c, v, &p->weak);
|
|
211
|
+
#else
|
|
212
|
+
#error FIXME: Unsupported compiler
|
|
213
|
+
#endif
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
MDBX_MAYBE_UNUSED static __always_inline uint32_t atomic_add32(mdbx_atomic_uint32_t *p, uint32_t v) {
|
|
217
|
+
#ifdef MDBX_HAVE_C11ATOMICS
|
|
218
|
+
STATIC_ASSERT(sizeof(int) >= sizeof(uint32_t));
|
|
219
|
+
assert(atomic_is_lock_free(MDBX_c11a_rw(uint32_t, p)));
|
|
220
|
+
return atomic_fetch_add(MDBX_c11a_rw(uint32_t, p), v);
|
|
221
|
+
#elif defined(__GNUC__) || defined(__clang__)
|
|
222
|
+
return __sync_fetch_and_add(&p->weak, v);
|
|
223
|
+
#elif defined(_MSC_VER)
|
|
224
|
+
STATIC_ASSERT(sizeof(volatile long) == sizeof(volatile uint32_t));
|
|
225
|
+
return (uint32_t)_InterlockedExchangeAdd((volatile long *)&p->weak, v);
|
|
226
|
+
#elif defined(__APPLE__)
|
|
227
|
+
return OSAtomicAdd32Barrier(v, &p->weak);
|
|
228
|
+
#else
|
|
229
|
+
#error FIXME: Unsupported compiler
|
|
230
|
+
#endif
|
|
231
|
+
}
|
|
232
|
+
|
|
233
|
+
#define atomic_sub32(p, v) atomic_add32(p, 0 - (v))
|
|
234
|
+
|
|
235
|
+
MDBX_MAYBE_UNUSED static __always_inline uint64_t safe64_txnid_next(uint64_t txnid) {
|
|
236
|
+
txnid += xMDBX_TXNID_STEP;
|
|
237
|
+
#if !MDBX_64BIT_CAS
|
|
238
|
+
/* avoid overflow of low-part in safe64_reset() */
|
|
239
|
+
txnid += (UINT32_MAX == (uint32_t)txnid);
|
|
240
|
+
#endif
|
|
241
|
+
return txnid;
|
|
242
|
+
}
|
|
243
|
+
|
|
244
|
+
/* Atomically make target value >= SAFE64_INVALID_THRESHOLD */
|
|
245
|
+
MDBX_MAYBE_UNUSED static __always_inline void safe64_reset(mdbx_atomic_uint64_t *p, bool single_writer) {
|
|
246
|
+
if (single_writer) {
|
|
247
|
+
#if MDBX_64BIT_ATOMIC && MDBX_WORDBITS >= 64
|
|
248
|
+
atomic_store64(p, UINT64_MAX, mo_AcquireRelease);
|
|
249
|
+
#else
|
|
250
|
+
atomic_store32(&p->high, UINT32_MAX, mo_AcquireRelease);
|
|
251
|
+
#endif /* MDBX_64BIT_ATOMIC && MDBX_WORDBITS >= 64 */
|
|
252
|
+
} else {
|
|
253
|
+
#if MDBX_64BIT_CAS && MDBX_64BIT_ATOMIC
|
|
254
|
+
/* atomically make value >= SAFE64_INVALID_THRESHOLD by 64-bit operation */
|
|
255
|
+
atomic_store64(p, UINT64_MAX, mo_AcquireRelease);
|
|
256
|
+
#elif MDBX_64BIT_CAS
|
|
257
|
+
/* atomically make value >= SAFE64_INVALID_THRESHOLD by 32-bit operation */
|
|
258
|
+
atomic_store32(&p->high, UINT32_MAX, mo_AcquireRelease);
|
|
259
|
+
#else
|
|
260
|
+
/* it is safe to increment low-part to avoid ABA, since xMDBX_TXNID_STEP > 1
|
|
261
|
+
* and overflow was preserved in safe64_txnid_next() */
|
|
262
|
+
STATIC_ASSERT(xMDBX_TXNID_STEP > 1);
|
|
263
|
+
atomic_add32(&p->low, 1) /* avoid ABA in safe64_reset_compare() */;
|
|
264
|
+
atomic_store32(&p->high, UINT32_MAX, mo_AcquireRelease);
|
|
265
|
+
atomic_add32(&p->low, 1) /* avoid ABA in safe64_reset_compare() */;
|
|
266
|
+
#endif /* MDBX_64BIT_CAS && MDBX_64BIT_ATOMIC */
|
|
267
|
+
}
|
|
268
|
+
assert(p->weak >= SAFE64_INVALID_THRESHOLD);
|
|
269
|
+
jitter4testing(true);
|
|
270
|
+
}
|
|
271
|
+
|
|
272
|
+
MDBX_MAYBE_UNUSED static __always_inline bool safe64_reset_compare(mdbx_atomic_uint64_t *p, uint64_t compare) {
|
|
273
|
+
/* LY: This function is used to reset `txnid` from hsr-handler in case
|
|
274
|
+
* the asynchronously cancellation of read transaction. Therefore,
|
|
275
|
+
* there may be a collision between the cleanup performed here and
|
|
276
|
+
* asynchronous termination and restarting of the read transaction
|
|
277
|
+
* in another process/thread. In general we MUST NOT reset the `txnid`
|
|
278
|
+
* if a new transaction was started (i.e. if `txnid` was changed). */
|
|
279
|
+
#if MDBX_64BIT_CAS
|
|
280
|
+
bool rc = atomic_cas64(p, compare, UINT64_MAX);
|
|
281
|
+
#else
|
|
282
|
+
/* LY: There is no gold ratio here since shared mutex is too costly,
|
|
283
|
+
* in such way we must acquire/release it for every update of txnid,
|
|
284
|
+
* i.e. twice for each read transaction). */
|
|
285
|
+
bool rc = false;
|
|
286
|
+
if (likely(atomic_load32(&p->low, mo_AcquireRelease) == (uint32_t)compare &&
|
|
287
|
+
atomic_cas32(&p->high, (uint32_t)(compare >> 32), UINT32_MAX))) {
|
|
288
|
+
if (unlikely(atomic_load32(&p->low, mo_AcquireRelease) != (uint32_t)compare))
|
|
289
|
+
atomic_cas32(&p->high, UINT32_MAX, (uint32_t)(compare >> 32));
|
|
290
|
+
else
|
|
291
|
+
rc = true;
|
|
292
|
+
}
|
|
293
|
+
#endif /* MDBX_64BIT_CAS */
|
|
294
|
+
jitter4testing(true);
|
|
295
|
+
return rc;
|
|
296
|
+
}
|
|
297
|
+
|
|
298
|
+
MDBX_MAYBE_UNUSED static __always_inline void safe64_write(mdbx_atomic_uint64_t *p, const uint64_t v) {
|
|
299
|
+
assert(p->weak >= SAFE64_INVALID_THRESHOLD);
|
|
300
|
+
#if MDBX_64BIT_ATOMIC && MDBX_64BIT_CAS
|
|
301
|
+
atomic_store64(p, v, mo_AcquireRelease);
|
|
302
|
+
#else /* MDBX_64BIT_ATOMIC */
|
|
303
|
+
osal_compiler_barrier();
|
|
304
|
+
/* update low-part but still value >= SAFE64_INVALID_THRESHOLD */
|
|
305
|
+
atomic_store32(&p->low, (uint32_t)v, mo_Relaxed);
|
|
306
|
+
assert(p->weak >= SAFE64_INVALID_THRESHOLD);
|
|
307
|
+
jitter4testing(true);
|
|
308
|
+
/* update high-part from SAFE64_INVALID_THRESHOLD to actual value */
|
|
309
|
+
atomic_store32(&p->high, (uint32_t)(v >> 32), mo_AcquireRelease);
|
|
310
|
+
#endif /* MDBX_64BIT_ATOMIC */
|
|
311
|
+
assert(p->weak == v);
|
|
312
|
+
jitter4testing(true);
|
|
313
|
+
}
|
|
314
|
+
|
|
315
|
+
MDBX_MAYBE_UNUSED static __always_inline uint64_t safe64_read(const mdbx_atomic_uint64_t *p) {
|
|
316
|
+
jitter4testing(true);
|
|
317
|
+
uint64_t v;
|
|
318
|
+
do
|
|
319
|
+
v = atomic_load64(p, mo_AcquireRelease);
|
|
320
|
+
while (!MDBX_64BIT_ATOMIC && unlikely(v != p->weak));
|
|
321
|
+
return v;
|
|
322
|
+
}
|
|
323
|
+
|
|
324
|
+
#if 0 /* unused for now */
|
|
325
|
+
MDBX_MAYBE_UNUSED static __always_inline bool safe64_is_valid(uint64_t v) {
|
|
326
|
+
#if MDBX_WORDBITS >= 64
|
|
327
|
+
return v < SAFE64_INVALID_THRESHOLD;
|
|
328
|
+
#else
|
|
329
|
+
return (v >> 32) != UINT32_MAX;
|
|
330
|
+
#endif /* MDBX_WORDBITS */
|
|
331
|
+
}
|
|
332
|
+
|
|
333
|
+
MDBX_MAYBE_UNUSED static __always_inline bool
|
|
334
|
+
safe64_is_valid_ptr(const mdbx_atomic_uint64_t *p) {
|
|
335
|
+
#if MDBX_64BIT_ATOMIC
|
|
336
|
+
return atomic_load64(p, mo_AcquireRelease) < SAFE64_INVALID_THRESHOLD;
|
|
337
|
+
#else
|
|
338
|
+
return atomic_load32(&p->high, mo_AcquireRelease) != UINT32_MAX;
|
|
339
|
+
#endif /* MDBX_64BIT_ATOMIC */
|
|
340
|
+
}
|
|
341
|
+
#endif /* unused for now */
|
|
342
|
+
|
|
343
|
+
/* non-atomic write with safety for reading a half-updated value */
|
|
344
|
+
MDBX_MAYBE_UNUSED static __always_inline void safe64_update(mdbx_atomic_uint64_t *p, const uint64_t v) {
|
|
345
|
+
#if MDBX_64BIT_ATOMIC
|
|
346
|
+
atomic_store64(p, v, mo_Relaxed);
|
|
347
|
+
#else
|
|
348
|
+
safe64_reset(p, true);
|
|
349
|
+
safe64_write(p, v);
|
|
350
|
+
#endif /* MDBX_64BIT_ATOMIC */
|
|
351
|
+
}
|
|
352
|
+
|
|
353
|
+
/* non-atomic increment with safety for reading a half-updated value */
|
|
354
|
+
MDBX_MAYBE_UNUSED static
|
|
355
|
+
#if MDBX_64BIT_ATOMIC
|
|
356
|
+
__always_inline
|
|
357
|
+
#endif /* MDBX_64BIT_ATOMIC */
|
|
358
|
+
void
|
|
359
|
+
safe64_inc(mdbx_atomic_uint64_t *p, const uint64_t v) {
|
|
360
|
+
assert(v > 0);
|
|
361
|
+
safe64_update(p, safe64_read(p) + v);
|
|
362
|
+
}
|
|
363
|
+
|
|
364
|
+
#endif /* !__cplusplus */
|
|
@@ -0,0 +1,97 @@
|
|
|
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
|
+
#ifndef MDBX_64BIT_ATOMIC
|
|
9
|
+
#error "The MDBX_64BIT_ATOMIC must be defined before"
|
|
10
|
+
#endif /* MDBX_64BIT_ATOMIC */
|
|
11
|
+
|
|
12
|
+
#ifndef MDBX_64BIT_CAS
|
|
13
|
+
#error "The MDBX_64BIT_CAS must be defined before"
|
|
14
|
+
#endif /* MDBX_64BIT_CAS */
|
|
15
|
+
|
|
16
|
+
#if defined(__cplusplus) && !defined(__STDC_NO_ATOMICS__) && __has_include(<cstdatomic>)
|
|
17
|
+
#include <cstdatomic>
|
|
18
|
+
#define MDBX_HAVE_C11ATOMICS
|
|
19
|
+
#elif !defined(__cplusplus) && (__STDC_VERSION__ >= 201112L || __has_extension(c_atomic)) && \
|
|
20
|
+
!defined(__STDC_NO_ATOMICS__) && \
|
|
21
|
+
(__GNUC_PREREQ(4, 9) || __CLANG_PREREQ(3, 8) || !(defined(__GNUC__) || defined(__clang__)))
|
|
22
|
+
#include <stdatomic.h>
|
|
23
|
+
#define MDBX_HAVE_C11ATOMICS
|
|
24
|
+
#elif defined(__GNUC__) || defined(__clang__)
|
|
25
|
+
#elif defined(_MSC_VER)
|
|
26
|
+
#pragma warning(disable : 4163) /* 'xyz': not available as an intrinsic */
|
|
27
|
+
#pragma warning(disable : 4133) /* 'function': incompatible types - from \
|
|
28
|
+
'size_t' to 'LONGLONG' */
|
|
29
|
+
#pragma warning(disable : 4244) /* 'return': conversion from 'LONGLONG' to \
|
|
30
|
+
'std::size_t', possible loss of data */
|
|
31
|
+
#pragma warning(disable : 4267) /* 'function': conversion from 'size_t' to \
|
|
32
|
+
'long', possible loss of data */
|
|
33
|
+
#pragma intrinsic(_InterlockedExchangeAdd, _InterlockedCompareExchange)
|
|
34
|
+
#pragma intrinsic(_InterlockedExchangeAdd64, _InterlockedCompareExchange64)
|
|
35
|
+
#elif defined(__APPLE__)
|
|
36
|
+
#include <libkern/OSAtomic.h>
|
|
37
|
+
#else
|
|
38
|
+
#error FIXME atomic-ops
|
|
39
|
+
#endif
|
|
40
|
+
|
|
41
|
+
typedef enum mdbx_memory_order {
|
|
42
|
+
mo_Relaxed,
|
|
43
|
+
mo_AcquireRelease
|
|
44
|
+
/* , mo_SequentialConsistency */
|
|
45
|
+
} mdbx_memory_order_t;
|
|
46
|
+
|
|
47
|
+
typedef union {
|
|
48
|
+
volatile uint32_t weak;
|
|
49
|
+
#ifdef MDBX_HAVE_C11ATOMICS
|
|
50
|
+
volatile _Atomic uint32_t c11a;
|
|
51
|
+
#endif /* MDBX_HAVE_C11ATOMICS */
|
|
52
|
+
} mdbx_atomic_uint32_t;
|
|
53
|
+
|
|
54
|
+
typedef union {
|
|
55
|
+
volatile uint64_t weak;
|
|
56
|
+
#if defined(MDBX_HAVE_C11ATOMICS) && (MDBX_64BIT_CAS || MDBX_64BIT_ATOMIC)
|
|
57
|
+
volatile _Atomic uint64_t c11a;
|
|
58
|
+
#endif
|
|
59
|
+
#if !defined(MDBX_HAVE_C11ATOMICS) || !MDBX_64BIT_CAS || !MDBX_64BIT_ATOMIC
|
|
60
|
+
__anonymous_struct_extension__ struct {
|
|
61
|
+
#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
|
|
62
|
+
mdbx_atomic_uint32_t low, high;
|
|
63
|
+
#elif __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
|
|
64
|
+
mdbx_atomic_uint32_t high, low;
|
|
65
|
+
#else
|
|
66
|
+
#error "FIXME: Unsupported byte order"
|
|
67
|
+
#endif /* __BYTE_ORDER__ */
|
|
68
|
+
};
|
|
69
|
+
#endif
|
|
70
|
+
} mdbx_atomic_uint64_t;
|
|
71
|
+
|
|
72
|
+
#ifdef MDBX_HAVE_C11ATOMICS
|
|
73
|
+
|
|
74
|
+
/* Crutches for C11 atomic compiler's bugs */
|
|
75
|
+
#if defined(__e2k__) && defined(__LCC__) && __LCC__ < /* FIXME */ 127
|
|
76
|
+
#define MDBX_c11a_ro(type, ptr) (&(ptr)->weak)
|
|
77
|
+
#define MDBX_c11a_rw(type, ptr) (&(ptr)->weak)
|
|
78
|
+
#elif defined(__clang__) && __clang__ < 8
|
|
79
|
+
#define MDBX_c11a_ro(type, ptr) ((volatile _Atomic(type) *)&(ptr)->c11a)
|
|
80
|
+
#define MDBX_c11a_rw(type, ptr) (&(ptr)->c11a)
|
|
81
|
+
#else
|
|
82
|
+
#define MDBX_c11a_ro(type, ptr) (&(ptr)->c11a)
|
|
83
|
+
#define MDBX_c11a_rw(type, ptr) (&(ptr)->c11a)
|
|
84
|
+
#endif /* Crutches for C11 atomic compiler's bugs */
|
|
85
|
+
|
|
86
|
+
#define mo_c11_store(fence) \
|
|
87
|
+
(((fence) == mo_Relaxed) ? memory_order_relaxed \
|
|
88
|
+
: ((fence) == mo_AcquireRelease) ? memory_order_release \
|
|
89
|
+
: memory_order_seq_cst)
|
|
90
|
+
#define mo_c11_load(fence) \
|
|
91
|
+
(((fence) == mo_Relaxed) ? memory_order_relaxed \
|
|
92
|
+
: ((fence) == mo_AcquireRelease) ? memory_order_acquire \
|
|
93
|
+
: memory_order_seq_cst)
|
|
94
|
+
|
|
95
|
+
#endif /* MDBX_HAVE_C11ATOMICS */
|
|
96
|
+
|
|
97
|
+
#define SAFE64_INVALID_THRESHOLD UINT64_C(0xffffFFFF00000000)
|
|
@@ -0,0 +1,109 @@
|
|
|
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
|
+
struct audit_ctx {
|
|
7
|
+
size_t used;
|
|
8
|
+
uint8_t *const done_bitmap;
|
|
9
|
+
};
|
|
10
|
+
|
|
11
|
+
static int audit_dbi(void *ctx, const MDBX_txn *txn, const MDBX_val *name, MDBX_db_flags_t flags,
|
|
12
|
+
const struct MDBX_stat *stat, MDBX_dbi dbi) {
|
|
13
|
+
struct audit_ctx *audit_ctx = ctx;
|
|
14
|
+
(void)name;
|
|
15
|
+
(void)txn;
|
|
16
|
+
(void)flags;
|
|
17
|
+
audit_ctx->used += (size_t)stat->ms_branch_pages + (size_t)stat->ms_leaf_pages + (size_t)stat->ms_overflow_pages;
|
|
18
|
+
if (dbi)
|
|
19
|
+
audit_ctx->done_bitmap[dbi / CHAR_BIT] |= 1 << dbi % CHAR_BIT;
|
|
20
|
+
return MDBX_SUCCESS;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
static size_t audit_db_used(const tree_t *db) {
|
|
24
|
+
return db ? (size_t)db->branch_pages + (size_t)db->leaf_pages + (size_t)db->large_pages : 0;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
__cold static int audit_ex_locked(MDBX_txn *txn, size_t retired_stored, bool dont_filter_gc) {
|
|
28
|
+
const MDBX_env *const env = txn->env;
|
|
29
|
+
size_t pending = 0;
|
|
30
|
+
if ((txn->flags & MDBX_TXN_RDONLY) == 0)
|
|
31
|
+
pending = txn->tw.loose_count + MDBX_PNL_GETSIZE(txn->tw.repnl) +
|
|
32
|
+
(MDBX_PNL_GETSIZE(txn->tw.retired_pages) - retired_stored);
|
|
33
|
+
|
|
34
|
+
cursor_couple_t cx;
|
|
35
|
+
int rc = cursor_init(&cx.outer, txn, FREE_DBI);
|
|
36
|
+
if (unlikely(rc != MDBX_SUCCESS))
|
|
37
|
+
return rc;
|
|
38
|
+
|
|
39
|
+
size_t gc = 0;
|
|
40
|
+
MDBX_val key, data;
|
|
41
|
+
rc = outer_first(&cx.outer, &key, &data);
|
|
42
|
+
while (rc == MDBX_SUCCESS) {
|
|
43
|
+
if (!dont_filter_gc) {
|
|
44
|
+
if (unlikely(key.iov_len != sizeof(txnid_t))) {
|
|
45
|
+
ERROR("%s/%d: %s %u", "MDBX_CORRUPTED", MDBX_CORRUPTED, "invalid GC-key size", (unsigned)key.iov_len);
|
|
46
|
+
return MDBX_CORRUPTED;
|
|
47
|
+
}
|
|
48
|
+
txnid_t id = unaligned_peek_u64(4, key.iov_base);
|
|
49
|
+
if (txn->tw.gc.retxl ? txl_contain(txn->tw.gc.retxl, id) : (id <= txn->tw.gc.last_reclaimed))
|
|
50
|
+
goto skip;
|
|
51
|
+
}
|
|
52
|
+
gc += *(pgno_t *)data.iov_base;
|
|
53
|
+
skip:
|
|
54
|
+
rc = outer_next(&cx.outer, &key, &data, MDBX_NEXT);
|
|
55
|
+
}
|
|
56
|
+
tASSERT(txn, rc == MDBX_NOTFOUND);
|
|
57
|
+
|
|
58
|
+
const size_t done_bitmap_size = (txn->n_dbi + CHAR_BIT - 1) / CHAR_BIT;
|
|
59
|
+
if (txn->parent) {
|
|
60
|
+
tASSERT(txn, txn->n_dbi == txn->parent->n_dbi && txn->n_dbi == txn->env->txn->n_dbi);
|
|
61
|
+
#if MDBX_ENABLE_DBI_SPARSE
|
|
62
|
+
tASSERT(txn, txn->dbi_sparse == txn->parent->dbi_sparse && txn->dbi_sparse == txn->env->txn->dbi_sparse);
|
|
63
|
+
#endif /* MDBX_ENABLE_DBI_SPARSE */
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
struct audit_ctx ctx = {0, alloca(done_bitmap_size)};
|
|
67
|
+
memset(ctx.done_bitmap, 0, done_bitmap_size);
|
|
68
|
+
ctx.used =
|
|
69
|
+
NUM_METAS + audit_db_used(dbi_dig(txn, FREE_DBI, nullptr)) + audit_db_used(dbi_dig(txn, MAIN_DBI, nullptr));
|
|
70
|
+
|
|
71
|
+
rc = mdbx_enumerate_tables(txn, audit_dbi, &ctx);
|
|
72
|
+
tASSERT(txn, rc == MDBX_SUCCESS);
|
|
73
|
+
|
|
74
|
+
for (size_t dbi = CORE_DBS; dbi < txn->n_dbi; ++dbi) {
|
|
75
|
+
if (ctx.done_bitmap[dbi / CHAR_BIT] & (1 << dbi % CHAR_BIT))
|
|
76
|
+
continue;
|
|
77
|
+
const tree_t *db = dbi_dig(txn, dbi, nullptr);
|
|
78
|
+
if (db)
|
|
79
|
+
ctx.used += audit_db_used(db);
|
|
80
|
+
else if (dbi_state(txn, dbi))
|
|
81
|
+
WARNING("audit %s@%" PRIaTXN ": unable account dbi %zd / \"%.*s\", state 0x%02x", txn->parent ? "nested-" : "",
|
|
82
|
+
txn->txnid, dbi, (int)env->kvs[dbi].name.iov_len, (const char *)env->kvs[dbi].name.iov_base,
|
|
83
|
+
dbi_state(txn, dbi));
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
if (pending + gc + ctx.used == txn->geo.first_unallocated)
|
|
87
|
+
return MDBX_SUCCESS;
|
|
88
|
+
|
|
89
|
+
if ((txn->flags & MDBX_TXN_RDONLY) == 0)
|
|
90
|
+
ERROR("audit @%" PRIaTXN ": %zu(pending) = %zu(loose) + "
|
|
91
|
+
"%zu(reclaimed) + %zu(retired-pending) - %zu(retired-stored)",
|
|
92
|
+
txn->txnid, pending, txn->tw.loose_count, MDBX_PNL_GETSIZE(txn->tw.repnl),
|
|
93
|
+
txn->tw.retired_pages ? MDBX_PNL_GETSIZE(txn->tw.retired_pages) : 0, retired_stored);
|
|
94
|
+
ERROR("audit @%" PRIaTXN ": %zu(pending) + %zu"
|
|
95
|
+
"(gc) + %zu(count) = %zu(total) <> %zu"
|
|
96
|
+
"(allocated)",
|
|
97
|
+
txn->txnid, pending, gc, ctx.used, pending + gc + ctx.used, (size_t)txn->geo.first_unallocated);
|
|
98
|
+
return MDBX_PROBLEM;
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
__cold int audit_ex(MDBX_txn *txn, size_t retired_stored, bool dont_filter_gc) {
|
|
102
|
+
MDBX_env *const env = txn->env;
|
|
103
|
+
int rc = osal_fastmutex_acquire(&env->dbi_lock);
|
|
104
|
+
if (likely(rc == MDBX_SUCCESS)) {
|
|
105
|
+
rc = audit_ex_locked(txn, retired_stored, dont_filter_gc);
|
|
106
|
+
ENSURE(txn->env, osal_fastmutex_release(&env->dbi_lock) == MDBX_SUCCESS);
|
|
107
|
+
}
|
|
108
|
+
return rc;
|
|
109
|
+
}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
N | MASK | ENV | TXN | DB | PUT | DBI | NODE | PAGE | MRESIZE |
|
|
2
|
+
--|---------|-----------|--------------|----------|-----------|------------|---------|----------|---------|
|
|
3
|
+
0 |0000 0001|ALLOC_RSRV |TXN_FINISHED | | |DBI_DIRTY |N_BIG |P_BRANCH | |
|
|
4
|
+
1 |0000 0002|ALLOC_UNIMP|TXN_ERROR |REVERSEKEY|N_TREE |DBI_STALE |N_TREE |P_LEAF | |
|
|
5
|
+
2 |0000 0004|ALLOC_COLSC|TXN_DIRTY |DUPSORT | |DBI_FRESH |N_DUP |P_LARGE | |
|
|
6
|
+
3 |0000 0008|ALLOC_SSCAN|TXN_SPILLS |INTEGERKEY| |DBI_CREAT | |P_META | |
|
|
7
|
+
4 |0000 0010|ALLOC_FIFO |TXN_HAS_CHILD |DUPFIXED |NOOVERWRITE|DBI_VALID | |P_BAD | |
|
|
8
|
+
5 |0000 0020| |TXN_PARKED |INTEGERDUP|NODUPDATA | | |P_DUPFIX | |
|
|
9
|
+
6 |0000 0040| |TXN_AUTOUNPARK|REVERSEDUP|CURRENT |DBI_OLDEN | |P_SUBP | |
|
|
10
|
+
7 |0000 0080| |TXN_DRAINED_GC|DB_VALID |ALLDUPS |DBI_LINDO | | | |
|
|
11
|
+
8 |0000 0100| _MAY_MOVE | | | | | | | <= |
|
|
12
|
+
9 |0000 0200| _MAY_UNMAP| | | | | | | <= |
|
|
13
|
+
10|0000 0400| | | | | | | | |
|
|
14
|
+
11|0000 0800| | | | | | | | |
|
|
15
|
+
12|0000 1000| | | | | | | | |
|
|
16
|
+
13|0000 2000|VALIDATION | | | | | |P_SPILLED | |
|
|
17
|
+
14|0000 4000|NOSUBDIR | | | | | |P_LOOSE | |
|
|
18
|
+
15|0000 8000| | | | | | |P_FROZEN | |
|
|
19
|
+
16|0001 0000|SAFE_NOSYNC|TXN_NOSYNC | |RESERVE | |RESERVE | | |
|
|
20
|
+
17|0002 0000|RDONLY |TXN_RDONLY | |APPEND | |APPEND | | <= |
|
|
21
|
+
18|0004 0000|NOMETASYNC |TXN_NOMETASYNC|CREATE |APPENDDUP | | | | |
|
|
22
|
+
19|0008 0000|WRITEMAP |<= | |MULTIPLE | | | | <= |
|
|
23
|
+
20|0010 0000|UTTERLY | | | | | | | <= |
|
|
24
|
+
21|0020 0000|NOSTICKYTHR|<= | | | | | | |
|
|
25
|
+
22|0040 0000|EXCLUSIVE | | | | | | | |
|
|
26
|
+
23|0080 0000|NORDAHEAD | | | | | | | |
|
|
27
|
+
24|0100 0000|NOMEMINIT |TXN_PREPARE | | | | | | |
|
|
28
|
+
25|0200 0000|COALESCE | | | | | | | |
|
|
29
|
+
26|0400 0000|LIFORECLAIM| | | | | | | |
|
|
30
|
+
27|0800 0000|PAGEPERTURB| | | | | | | |
|
|
31
|
+
28|1000 0000|ENV_TXKEY |TXN_TRY | | | | | | |
|
|
32
|
+
29|2000 0000|ENV_ACTIVE | | | | | | | |
|
|
33
|
+
30|4000 0000|ACCEDE |SHRINK_ALLOWED|DB_ACCEDE | | | | | |
|
|
34
|
+
31|8000 0000|FATAL_ERROR| | | | | | | |
|