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,105 @@
|
|
|
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
|
+
/* Internal prototypes */
|
|
9
|
+
|
|
10
|
+
/* audit.c */
|
|
11
|
+
MDBX_INTERNAL int audit_ex(MDBX_txn *txn, size_t retired_stored, bool dont_filter_gc);
|
|
12
|
+
|
|
13
|
+
/* mvcc-readers.c */
|
|
14
|
+
MDBX_INTERNAL bsr_t mvcc_bind_slot(MDBX_env *env);
|
|
15
|
+
MDBX_MAYBE_UNUSED MDBX_INTERNAL pgno_t mvcc_largest_this(MDBX_env *env, pgno_t largest);
|
|
16
|
+
MDBX_INTERNAL txnid_t mvcc_shapshot_oldest(MDBX_env *const env, const txnid_t steady);
|
|
17
|
+
MDBX_INTERNAL pgno_t mvcc_snapshot_largest(const MDBX_env *env, pgno_t last_used_page);
|
|
18
|
+
MDBX_INTERNAL txnid_t mvcc_kick_laggards(MDBX_env *env, const txnid_t straggler);
|
|
19
|
+
MDBX_INTERNAL int mvcc_cleanup_dead(MDBX_env *env, int rlocked, int *dead);
|
|
20
|
+
MDBX_INTERNAL txnid_t mvcc_kick_laggards(MDBX_env *env, const txnid_t laggard);
|
|
21
|
+
|
|
22
|
+
/* dxb.c */
|
|
23
|
+
MDBX_INTERNAL int dxb_setup(MDBX_env *env, const int lck_rc, const mdbx_mode_t mode_bits);
|
|
24
|
+
MDBX_INTERNAL int __must_check_result dxb_read_header(MDBX_env *env, meta_t *meta, const int lck_exclusive,
|
|
25
|
+
const mdbx_mode_t mode_bits);
|
|
26
|
+
enum resize_mode { implicit_grow, impilict_shrink, explicit_resize };
|
|
27
|
+
MDBX_INTERNAL int __must_check_result dxb_resize(MDBX_env *const env, const pgno_t used_pgno, const pgno_t size_pgno,
|
|
28
|
+
pgno_t limit_pgno, const enum resize_mode mode);
|
|
29
|
+
MDBX_INTERNAL int dxb_set_readahead(const MDBX_env *env, const pgno_t edge, const bool enable, const bool force_whole);
|
|
30
|
+
MDBX_INTERNAL int __must_check_result dxb_sync_locked(MDBX_env *env, unsigned flags, meta_t *const pending,
|
|
31
|
+
troika_t *const troika);
|
|
32
|
+
#if defined(ENABLE_MEMCHECK) || defined(__SANITIZE_ADDRESS__)
|
|
33
|
+
MDBX_INTERNAL void dxb_sanitize_tail(MDBX_env *env, MDBX_txn *txn);
|
|
34
|
+
#else
|
|
35
|
+
static inline void dxb_sanitize_tail(MDBX_env *env, MDBX_txn *txn) {
|
|
36
|
+
(void)env;
|
|
37
|
+
(void)txn;
|
|
38
|
+
}
|
|
39
|
+
#endif /* ENABLE_MEMCHECK || __SANITIZE_ADDRESS__ */
|
|
40
|
+
|
|
41
|
+
/* txn.c */
|
|
42
|
+
MDBX_INTERNAL bool txn_refund(MDBX_txn *txn);
|
|
43
|
+
MDBX_INTERNAL txnid_t txn_snapshot_oldest(const MDBX_txn *const txn);
|
|
44
|
+
MDBX_INTERNAL int txn_abort(MDBX_txn *txn);
|
|
45
|
+
MDBX_INTERNAL int txn_renew(MDBX_txn *txn, unsigned flags);
|
|
46
|
+
MDBX_INTERNAL int txn_park(MDBX_txn *txn, bool autounpark);
|
|
47
|
+
MDBX_INTERNAL int txn_unpark(MDBX_txn *txn);
|
|
48
|
+
MDBX_INTERNAL int txn_check_badbits_parked(const MDBX_txn *txn, int bad_bits);
|
|
49
|
+
MDBX_INTERNAL void txn_done_cursors(MDBX_txn *txn, const bool merge);
|
|
50
|
+
|
|
51
|
+
#define TXN_END_NAMES \
|
|
52
|
+
{"committed", "empty-commit", "abort", "reset", "fail-begin", "fail-beginchild", "ousted", nullptr}
|
|
53
|
+
enum {
|
|
54
|
+
/* txn_end operation number, for logging */
|
|
55
|
+
TXN_END_COMMITTED,
|
|
56
|
+
TXN_END_PURE_COMMIT,
|
|
57
|
+
TXN_END_ABORT,
|
|
58
|
+
TXN_END_RESET,
|
|
59
|
+
TXN_END_FAIL_BEGIN,
|
|
60
|
+
TXN_END_FAIL_BEGINCHILD,
|
|
61
|
+
TXN_END_OUSTED,
|
|
62
|
+
|
|
63
|
+
TXN_END_OPMASK = 0x07 /* mask for txn_end() operation number */,
|
|
64
|
+
TXN_END_UPDATE = 0x10 /* update env state (DBIs) */,
|
|
65
|
+
TXN_END_FREE = 0x20 /* free txn unless it is env.basal_txn */,
|
|
66
|
+
TXN_END_EOTDONE = 0x40 /* txn's cursors already closed */,
|
|
67
|
+
TXN_END_SLOT = 0x80 /* release any reader slot if NOSTICKYTHREADS */
|
|
68
|
+
};
|
|
69
|
+
MDBX_INTERNAL int txn_end(MDBX_txn *txn, unsigned mode);
|
|
70
|
+
MDBX_INTERNAL int txn_write(MDBX_txn *txn, iov_ctx_t *ctx);
|
|
71
|
+
MDBX_INTERNAL void txn_take_gcprof(const MDBX_txn *txn, MDBX_commit_latency *latency);
|
|
72
|
+
MDBX_INTERNAL void txn_merge(MDBX_txn *const parent, MDBX_txn *const txn, const size_t parent_retired_len);
|
|
73
|
+
|
|
74
|
+
/* env.c */
|
|
75
|
+
MDBX_INTERNAL int env_open(MDBX_env *env, mdbx_mode_t mode);
|
|
76
|
+
MDBX_INTERNAL int env_info(const MDBX_env *env, const MDBX_txn *txn, MDBX_envinfo *out, size_t bytes, troika_t *troika);
|
|
77
|
+
MDBX_INTERNAL int env_sync(MDBX_env *env, bool force, bool nonblock);
|
|
78
|
+
MDBX_INTERNAL int env_close(MDBX_env *env, bool resurrect_after_fork);
|
|
79
|
+
MDBX_INTERNAL MDBX_txn *env_owned_wrtxn(const MDBX_env *env);
|
|
80
|
+
MDBX_INTERNAL int __must_check_result env_page_auxbuffer(MDBX_env *env);
|
|
81
|
+
MDBX_INTERNAL unsigned env_setup_pagesize(MDBX_env *env, const size_t pagesize);
|
|
82
|
+
|
|
83
|
+
/* api-opt.c */
|
|
84
|
+
MDBX_INTERNAL void env_options_init(MDBX_env *env);
|
|
85
|
+
MDBX_INTERNAL void env_options_adjust_defaults(MDBX_env *env);
|
|
86
|
+
MDBX_INTERNAL void env_options_adjust_dp_limit(MDBX_env *env);
|
|
87
|
+
MDBX_INTERNAL pgno_t default_dp_limit(const MDBX_env *env);
|
|
88
|
+
|
|
89
|
+
/* tree.c */
|
|
90
|
+
MDBX_INTERNAL int tree_drop(MDBX_cursor *mc, const bool may_have_tables);
|
|
91
|
+
MDBX_INTERNAL int __must_check_result tree_rebalance(MDBX_cursor *mc);
|
|
92
|
+
MDBX_INTERNAL int __must_check_result tree_propagate_key(MDBX_cursor *mc, const MDBX_val *key);
|
|
93
|
+
MDBX_INTERNAL void recalculate_merge_thresholds(MDBX_env *env);
|
|
94
|
+
MDBX_INTERNAL void recalculate_subpage_thresholds(MDBX_env *env);
|
|
95
|
+
|
|
96
|
+
/* table.c */
|
|
97
|
+
MDBX_INTERNAL int __must_check_result tbl_fetch(MDBX_txn *txn, size_t dbi);
|
|
98
|
+
MDBX_INTERNAL int __must_check_result tbl_setup(const MDBX_env *env, volatile kvx_t *const kvx, const tree_t *const db);
|
|
99
|
+
|
|
100
|
+
/* coherency.c */
|
|
101
|
+
MDBX_INTERNAL bool coherency_check_meta(const MDBX_env *env, const volatile meta_t *meta, bool report);
|
|
102
|
+
MDBX_INTERNAL int coherency_fetch_head(MDBX_txn *txn, const meta_ptr_t head, uint64_t *timestamp);
|
|
103
|
+
MDBX_INTERNAL int coherency_check_written(const MDBX_env *env, const txnid_t txnid, const volatile meta_t *meta,
|
|
104
|
+
const intptr_t pgno, uint64_t *timestamp);
|
|
105
|
+
MDBX_INTERNAL int coherency_timeout(uint64_t *timestamp, intptr_t pgno, const MDBX_env *env);
|
|
@@ -0,0 +1,212 @@
|
|
|
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
|
+
#if MDBX_ENABLE_REFUND
|
|
7
|
+
static void refund_reclaimed(MDBX_txn *txn) {
|
|
8
|
+
/* Scanning in descend order */
|
|
9
|
+
pgno_t first_unallocated = txn->geo.first_unallocated;
|
|
10
|
+
const pnl_t pnl = txn->tw.repnl;
|
|
11
|
+
tASSERT(txn, MDBX_PNL_GETSIZE(pnl) && MDBX_PNL_MOST(pnl) == first_unallocated - 1);
|
|
12
|
+
#if MDBX_PNL_ASCENDING
|
|
13
|
+
size_t i = MDBX_PNL_GETSIZE(pnl);
|
|
14
|
+
tASSERT(txn, pnl[i] == first_unallocated - 1);
|
|
15
|
+
while (--first_unallocated, --i > 0 && pnl[i] == first_unallocated - 1)
|
|
16
|
+
;
|
|
17
|
+
MDBX_PNL_SETSIZE(pnl, i);
|
|
18
|
+
#else
|
|
19
|
+
size_t i = 1;
|
|
20
|
+
tASSERT(txn, pnl[i] == first_unallocated - 1);
|
|
21
|
+
size_t len = MDBX_PNL_GETSIZE(pnl);
|
|
22
|
+
while (--first_unallocated, ++i <= len && pnl[i] == first_unallocated - 1)
|
|
23
|
+
;
|
|
24
|
+
MDBX_PNL_SETSIZE(pnl, len -= i - 1);
|
|
25
|
+
for (size_t move = 0; move < len; ++move)
|
|
26
|
+
pnl[1 + move] = pnl[i + move];
|
|
27
|
+
#endif
|
|
28
|
+
VERBOSE("refunded %" PRIaPGNO " pages: %" PRIaPGNO " -> %" PRIaPGNO, txn->geo.first_unallocated - first_unallocated,
|
|
29
|
+
txn->geo.first_unallocated, first_unallocated);
|
|
30
|
+
txn->geo.first_unallocated = first_unallocated;
|
|
31
|
+
tASSERT(txn, pnl_check_allocated(txn->tw.repnl, txn->geo.first_unallocated - 1));
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
static void refund_loose(MDBX_txn *txn) {
|
|
35
|
+
tASSERT(txn, txn->tw.loose_pages != nullptr);
|
|
36
|
+
tASSERT(txn, txn->tw.loose_count > 0);
|
|
37
|
+
|
|
38
|
+
dpl_t *const dl = txn->tw.dirtylist;
|
|
39
|
+
if (dl) {
|
|
40
|
+
tASSERT(txn, dl->length >= txn->tw.loose_count);
|
|
41
|
+
tASSERT(txn, (txn->flags & MDBX_WRITEMAP) == 0 || MDBX_AVOID_MSYNC);
|
|
42
|
+
} else {
|
|
43
|
+
tASSERT(txn, (txn->flags & MDBX_WRITEMAP) != 0 && !MDBX_AVOID_MSYNC);
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
pgno_t onstack[MDBX_CACHELINE_SIZE * 8 / sizeof(pgno_t)];
|
|
47
|
+
pnl_t suitable = onstack;
|
|
48
|
+
|
|
49
|
+
if (!dl || dl->length - dl->sorted > txn->tw.loose_count) {
|
|
50
|
+
/* Dirty list is useless since unsorted. */
|
|
51
|
+
if (pnl_bytes2size(sizeof(onstack)) < txn->tw.loose_count) {
|
|
52
|
+
suitable = pnl_alloc(txn->tw.loose_count);
|
|
53
|
+
if (unlikely(!suitable))
|
|
54
|
+
return /* this is not a reason for transaction fail */;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
/* Collect loose-pages which may be refunded. */
|
|
58
|
+
tASSERT(txn, txn->geo.first_unallocated >= MIN_PAGENO + txn->tw.loose_count);
|
|
59
|
+
pgno_t most = MIN_PAGENO;
|
|
60
|
+
size_t w = 0;
|
|
61
|
+
for (const page_t *lp = txn->tw.loose_pages; lp; lp = page_next(lp)) {
|
|
62
|
+
tASSERT(txn, lp->flags == P_LOOSE);
|
|
63
|
+
tASSERT(txn, txn->geo.first_unallocated > lp->pgno);
|
|
64
|
+
if (likely(txn->geo.first_unallocated - txn->tw.loose_count <= lp->pgno)) {
|
|
65
|
+
tASSERT(txn, w < ((suitable == onstack) ? pnl_bytes2size(sizeof(onstack)) : MDBX_PNL_ALLOCLEN(suitable)));
|
|
66
|
+
suitable[++w] = lp->pgno;
|
|
67
|
+
most = (lp->pgno > most) ? lp->pgno : most;
|
|
68
|
+
}
|
|
69
|
+
MDBX_ASAN_UNPOISON_MEMORY_REGION(&page_next(lp), sizeof(page_t *));
|
|
70
|
+
VALGRIND_MAKE_MEM_DEFINED(&page_next(lp), sizeof(page_t *));
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
if (most + 1 == txn->geo.first_unallocated) {
|
|
74
|
+
/* Sort suitable list and refund pages at the tail. */
|
|
75
|
+
MDBX_PNL_SETSIZE(suitable, w);
|
|
76
|
+
pnl_sort(suitable, MAX_PAGENO + 1);
|
|
77
|
+
|
|
78
|
+
/* Scanning in descend order */
|
|
79
|
+
const intptr_t step = MDBX_PNL_ASCENDING ? -1 : 1;
|
|
80
|
+
const intptr_t begin = MDBX_PNL_ASCENDING ? MDBX_PNL_GETSIZE(suitable) : 1;
|
|
81
|
+
const intptr_t end = MDBX_PNL_ASCENDING ? 0 : MDBX_PNL_GETSIZE(suitable) + 1;
|
|
82
|
+
tASSERT(txn, suitable[begin] >= suitable[end - step]);
|
|
83
|
+
tASSERT(txn, most == suitable[begin]);
|
|
84
|
+
|
|
85
|
+
for (intptr_t i = begin + step; i != end; i += step) {
|
|
86
|
+
if (suitable[i] != most - 1)
|
|
87
|
+
break;
|
|
88
|
+
most -= 1;
|
|
89
|
+
}
|
|
90
|
+
const size_t refunded = txn->geo.first_unallocated - most;
|
|
91
|
+
DEBUG("refund-suitable %zu pages %" PRIaPGNO " -> %" PRIaPGNO, refunded, most, txn->geo.first_unallocated);
|
|
92
|
+
txn->geo.first_unallocated = most;
|
|
93
|
+
txn->tw.loose_count -= refunded;
|
|
94
|
+
if (dl) {
|
|
95
|
+
txn->tw.dirtyroom += refunded;
|
|
96
|
+
dl->pages_including_loose -= refunded;
|
|
97
|
+
assert(txn->tw.dirtyroom <= txn->env->options.dp_limit);
|
|
98
|
+
|
|
99
|
+
/* Filter-out dirty list */
|
|
100
|
+
size_t r = 0;
|
|
101
|
+
w = 0;
|
|
102
|
+
if (dl->sorted) {
|
|
103
|
+
do {
|
|
104
|
+
if (dl->items[++r].pgno < most) {
|
|
105
|
+
if (++w != r)
|
|
106
|
+
dl->items[w] = dl->items[r];
|
|
107
|
+
}
|
|
108
|
+
} while (r < dl->sorted);
|
|
109
|
+
dl->sorted = w;
|
|
110
|
+
}
|
|
111
|
+
while (r < dl->length) {
|
|
112
|
+
if (dl->items[++r].pgno < most) {
|
|
113
|
+
if (++w != r)
|
|
114
|
+
dl->items[w] = dl->items[r];
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
dpl_setlen(dl, w);
|
|
118
|
+
tASSERT(txn, txn->tw.dirtyroom + txn->tw.dirtylist->length ==
|
|
119
|
+
(txn->parent ? txn->parent->tw.dirtyroom : txn->env->options.dp_limit));
|
|
120
|
+
}
|
|
121
|
+
goto unlink_loose;
|
|
122
|
+
}
|
|
123
|
+
} else {
|
|
124
|
+
/* Dirtylist is mostly sorted, just refund loose pages at the end. */
|
|
125
|
+
dpl_sort(txn);
|
|
126
|
+
tASSERT(txn, dl->length < 2 || dl->items[1].pgno < dl->items[dl->length].pgno);
|
|
127
|
+
tASSERT(txn, dl->sorted == dl->length);
|
|
128
|
+
|
|
129
|
+
/* Scan dirtylist tail-forward and cutoff suitable pages. */
|
|
130
|
+
size_t n;
|
|
131
|
+
for (n = dl->length; dl->items[n].pgno == txn->geo.first_unallocated - 1 && dl->items[n].ptr->flags == P_LOOSE;
|
|
132
|
+
--n) {
|
|
133
|
+
tASSERT(txn, n > 0);
|
|
134
|
+
page_t *dp = dl->items[n].ptr;
|
|
135
|
+
DEBUG("refund-sorted page %" PRIaPGNO, dp->pgno);
|
|
136
|
+
tASSERT(txn, dp->pgno == dl->items[n].pgno);
|
|
137
|
+
txn->geo.first_unallocated -= 1;
|
|
138
|
+
}
|
|
139
|
+
dpl_setlen(dl, n);
|
|
140
|
+
|
|
141
|
+
if (dl->sorted != dl->length) {
|
|
142
|
+
const size_t refunded = dl->sorted - dl->length;
|
|
143
|
+
dl->sorted = dl->length;
|
|
144
|
+
txn->tw.loose_count -= refunded;
|
|
145
|
+
txn->tw.dirtyroom += refunded;
|
|
146
|
+
dl->pages_including_loose -= refunded;
|
|
147
|
+
tASSERT(txn, txn->tw.dirtyroom + txn->tw.dirtylist->length ==
|
|
148
|
+
(txn->parent ? txn->parent->tw.dirtyroom : txn->env->options.dp_limit));
|
|
149
|
+
|
|
150
|
+
/* Filter-out loose chain & dispose refunded pages. */
|
|
151
|
+
unlink_loose:
|
|
152
|
+
for (page_t *__restrict *__restrict link = &txn->tw.loose_pages; *link;) {
|
|
153
|
+
page_t *dp = *link;
|
|
154
|
+
tASSERT(txn, dp->flags == P_LOOSE);
|
|
155
|
+
MDBX_ASAN_UNPOISON_MEMORY_REGION(&page_next(dp), sizeof(page_t *));
|
|
156
|
+
VALGRIND_MAKE_MEM_DEFINED(&page_next(dp), sizeof(page_t *));
|
|
157
|
+
if (txn->geo.first_unallocated > dp->pgno) {
|
|
158
|
+
link = &page_next(dp);
|
|
159
|
+
} else {
|
|
160
|
+
*link = page_next(dp);
|
|
161
|
+
if ((txn->flags & MDBX_WRITEMAP) == 0)
|
|
162
|
+
page_shadow_release(txn->env, dp, 1);
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
tASSERT(txn, dpl_check(txn));
|
|
169
|
+
if (suitable != onstack)
|
|
170
|
+
pnl_free(suitable);
|
|
171
|
+
txn->tw.loose_refund_wl = txn->geo.first_unallocated;
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
bool txn_refund(MDBX_txn *txn) {
|
|
175
|
+
const pgno_t before = txn->geo.first_unallocated;
|
|
176
|
+
|
|
177
|
+
if (txn->tw.loose_pages && txn->tw.loose_refund_wl > txn->geo.first_unallocated)
|
|
178
|
+
refund_loose(txn);
|
|
179
|
+
|
|
180
|
+
while (true) {
|
|
181
|
+
if (MDBX_PNL_GETSIZE(txn->tw.repnl) == 0 || MDBX_PNL_MOST(txn->tw.repnl) != txn->geo.first_unallocated - 1)
|
|
182
|
+
break;
|
|
183
|
+
|
|
184
|
+
refund_reclaimed(txn);
|
|
185
|
+
if (!txn->tw.loose_pages || txn->tw.loose_refund_wl <= txn->geo.first_unallocated)
|
|
186
|
+
break;
|
|
187
|
+
|
|
188
|
+
const pgno_t memo = txn->geo.first_unallocated;
|
|
189
|
+
refund_loose(txn);
|
|
190
|
+
if (memo == txn->geo.first_unallocated)
|
|
191
|
+
break;
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
if (before == txn->geo.first_unallocated)
|
|
195
|
+
return false;
|
|
196
|
+
|
|
197
|
+
if (txn->tw.spilled.list)
|
|
198
|
+
/* Squash deleted pagenums if we refunded any */
|
|
199
|
+
spill_purge(txn);
|
|
200
|
+
|
|
201
|
+
return true;
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
#else /* MDBX_ENABLE_REFUND */
|
|
205
|
+
|
|
206
|
+
bool txn_refund(MDBX_txn *txn) {
|
|
207
|
+
(void)txn;
|
|
208
|
+
/* No online auto-compactification. */
|
|
209
|
+
return false;
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
#endif /* MDBX_ENABLE_REFUND */
|