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.
Files changed (220) hide show
  1. package/.github/workflows/ci.yml +32 -0
  2. package/.github/workflows/publish.yml +27 -0
  3. package/.gitmodules +3 -0
  4. package/CMakeLists.txt +53 -0
  5. package/LICENSE +201 -0
  6. package/README.md +639 -0
  7. package/build.js +11 -0
  8. package/deps/libmdbx/.clang-format +3 -0
  9. package/deps/libmdbx/.cmake-format.yaml +3 -0
  10. package/deps/libmdbx/.le.ini +40 -0
  11. package/deps/libmdbx/CMakeLists.txt +1269 -0
  12. package/deps/libmdbx/COPYRIGHT +159 -0
  13. package/deps/libmdbx/ChangeLog.md +2786 -0
  14. package/deps/libmdbx/GNUmakefile +950 -0
  15. package/deps/libmdbx/LICENSE +177 -0
  16. package/deps/libmdbx/Makefile +16 -0
  17. package/deps/libmdbx/NOTICE +39 -0
  18. package/deps/libmdbx/README.md +863 -0
  19. package/deps/libmdbx/TODO.md +43 -0
  20. package/deps/libmdbx/cmake/compiler.cmake +1221 -0
  21. package/deps/libmdbx/cmake/profile.cmake +58 -0
  22. package/deps/libmdbx/cmake/utils.cmake +524 -0
  23. package/deps/libmdbx/conanfile.py +323 -0
  24. package/deps/libmdbx/docs/Doxyfile.in +2734 -0
  25. package/deps/libmdbx/docs/_preface.md +47 -0
  26. package/deps/libmdbx/docs/_restrictions.md +248 -0
  27. package/deps/libmdbx/docs/_starting.md +245 -0
  28. package/deps/libmdbx/docs/_toc.md +34 -0
  29. package/deps/libmdbx/docs/header.html +96 -0
  30. package/deps/libmdbx/example/CMakeLists.txt +6 -0
  31. package/deps/libmdbx/example/README.md +1 -0
  32. package/deps/libmdbx/example/example-mdbx.c +154 -0
  33. package/deps/libmdbx/example/sample-bdb.txt +77 -0
  34. package/deps/libmdbx/mdbx.h +6655 -0
  35. package/deps/libmdbx/mdbx.h++ +6428 -0
  36. package/deps/libmdbx/packages/buildroot/0001-package-libmdbx-new-package-library-database.patch +173 -0
  37. package/deps/libmdbx/src/alloy.c +54 -0
  38. package/deps/libmdbx/src/api-cold.c +543 -0
  39. package/deps/libmdbx/src/api-copy.c +912 -0
  40. package/deps/libmdbx/src/api-cursor.c +754 -0
  41. package/deps/libmdbx/src/api-dbi.c +315 -0
  42. package/deps/libmdbx/src/api-env.c +1434 -0
  43. package/deps/libmdbx/src/api-extra.c +165 -0
  44. package/deps/libmdbx/src/api-key-transform.c +197 -0
  45. package/deps/libmdbx/src/api-misc.c +286 -0
  46. package/deps/libmdbx/src/api-opts.c +575 -0
  47. package/deps/libmdbx/src/api-range-estimate.c +365 -0
  48. package/deps/libmdbx/src/api-txn-data.c +454 -0
  49. package/deps/libmdbx/src/api-txn.c +921 -0
  50. package/deps/libmdbx/src/atomics-ops.h +364 -0
  51. package/deps/libmdbx/src/atomics-types.h +97 -0
  52. package/deps/libmdbx/src/audit.c +109 -0
  53. package/deps/libmdbx/src/bits.md +34 -0
  54. package/deps/libmdbx/src/chk.c +1796 -0
  55. package/deps/libmdbx/src/cogs.c +309 -0
  56. package/deps/libmdbx/src/cogs.h +506 -0
  57. package/deps/libmdbx/src/coherency.c +170 -0
  58. package/deps/libmdbx/src/config.h.in +88 -0
  59. package/deps/libmdbx/src/cursor.c +2396 -0
  60. package/deps/libmdbx/src/cursor.h +391 -0
  61. package/deps/libmdbx/src/dbi.c +717 -0
  62. package/deps/libmdbx/src/dbi.h +142 -0
  63. package/deps/libmdbx/src/debug_begin.h +36 -0
  64. package/deps/libmdbx/src/debug_end.h +15 -0
  65. package/deps/libmdbx/src/dpl.c +486 -0
  66. package/deps/libmdbx/src/dpl.h +134 -0
  67. package/deps/libmdbx/src/dxb.c +1335 -0
  68. package/deps/libmdbx/src/env.c +607 -0
  69. package/deps/libmdbx/src/essentials.h +125 -0
  70. package/deps/libmdbx/src/gc-get.c +1345 -0
  71. package/deps/libmdbx/src/gc-put.c +970 -0
  72. package/deps/libmdbx/src/gc.h +40 -0
  73. package/deps/libmdbx/src/global.c +474 -0
  74. package/deps/libmdbx/src/internals.h +585 -0
  75. package/deps/libmdbx/src/layout-dxb.h +288 -0
  76. package/deps/libmdbx/src/layout-lck.h +289 -0
  77. package/deps/libmdbx/src/lck-posix.c +859 -0
  78. package/deps/libmdbx/src/lck-windows.c +607 -0
  79. package/deps/libmdbx/src/lck.c +174 -0
  80. package/deps/libmdbx/src/lck.h +110 -0
  81. package/deps/libmdbx/src/logging_and_debug.c +250 -0
  82. package/deps/libmdbx/src/logging_and_debug.h +159 -0
  83. package/deps/libmdbx/src/man1/mdbx_chk.1 +106 -0
  84. package/deps/libmdbx/src/man1/mdbx_copy.1 +95 -0
  85. package/deps/libmdbx/src/man1/mdbx_drop.1 +48 -0
  86. package/deps/libmdbx/src/man1/mdbx_dump.1 +101 -0
  87. package/deps/libmdbx/src/man1/mdbx_load.1 +105 -0
  88. package/deps/libmdbx/src/man1/mdbx_stat.1 +86 -0
  89. package/deps/libmdbx/src/mdbx.c++ +1837 -0
  90. package/deps/libmdbx/src/meta.c +656 -0
  91. package/deps/libmdbx/src/meta.h +168 -0
  92. package/deps/libmdbx/src/mvcc-readers.c +414 -0
  93. package/deps/libmdbx/src/node.c +365 -0
  94. package/deps/libmdbx/src/node.h +102 -0
  95. package/deps/libmdbx/src/ntdll.def +1246 -0
  96. package/deps/libmdbx/src/options.h +534 -0
  97. package/deps/libmdbx/src/osal.c +3485 -0
  98. package/deps/libmdbx/src/osal.h +587 -0
  99. package/deps/libmdbx/src/page-get.c +483 -0
  100. package/deps/libmdbx/src/page-iov.c +185 -0
  101. package/deps/libmdbx/src/page-iov.h +34 -0
  102. package/deps/libmdbx/src/page-ops.c +744 -0
  103. package/deps/libmdbx/src/page-ops.h +142 -0
  104. package/deps/libmdbx/src/pnl.c +236 -0
  105. package/deps/libmdbx/src/pnl.h +146 -0
  106. package/deps/libmdbx/src/preface.h +990 -0
  107. package/deps/libmdbx/src/proto.h +105 -0
  108. package/deps/libmdbx/src/refund.c +212 -0
  109. package/deps/libmdbx/src/sort.h +484 -0
  110. package/deps/libmdbx/src/spill.c +431 -0
  111. package/deps/libmdbx/src/spill.h +74 -0
  112. package/deps/libmdbx/src/table.c +107 -0
  113. package/deps/libmdbx/src/tls.c +551 -0
  114. package/deps/libmdbx/src/tls.h +43 -0
  115. package/deps/libmdbx/src/tools/chk.c +673 -0
  116. package/deps/libmdbx/src/tools/copy.c +166 -0
  117. package/deps/libmdbx/src/tools/drop.c +199 -0
  118. package/deps/libmdbx/src/tools/dump.c +515 -0
  119. package/deps/libmdbx/src/tools/load.c +831 -0
  120. package/deps/libmdbx/src/tools/stat.c +516 -0
  121. package/deps/libmdbx/src/tools/wingetopt.c +87 -0
  122. package/deps/libmdbx/src/tools/wingetopt.h +30 -0
  123. package/deps/libmdbx/src/tree-ops.c +1554 -0
  124. package/deps/libmdbx/src/tree-search.c +140 -0
  125. package/deps/libmdbx/src/txl.c +99 -0
  126. package/deps/libmdbx/src/txl.h +26 -0
  127. package/deps/libmdbx/src/txn.c +1083 -0
  128. package/deps/libmdbx/src/unaligned.h +205 -0
  129. package/deps/libmdbx/src/utils.c +32 -0
  130. package/deps/libmdbx/src/utils.h +76 -0
  131. package/deps/libmdbx/src/version.c.in +44 -0
  132. package/deps/libmdbx/src/walk.c +290 -0
  133. package/deps/libmdbx/src/walk.h +20 -0
  134. package/deps/libmdbx/src/windows-import.c +152 -0
  135. package/deps/libmdbx/src/windows-import.h +128 -0
  136. package/deps/libmdbx/test/CMakeLists.txt +317 -0
  137. package/deps/libmdbx/test/append.c++ +237 -0
  138. package/deps/libmdbx/test/base.h++ +92 -0
  139. package/deps/libmdbx/test/battery-tmux.sh +64 -0
  140. package/deps/libmdbx/test/cases.c++ +118 -0
  141. package/deps/libmdbx/test/chrono.c++ +134 -0
  142. package/deps/libmdbx/test/chrono.h++ +85 -0
  143. package/deps/libmdbx/test/config.c++ +643 -0
  144. package/deps/libmdbx/test/config.h++ +334 -0
  145. package/deps/libmdbx/test/copy.c++ +62 -0
  146. package/deps/libmdbx/test/dead.c++ +39 -0
  147. package/deps/libmdbx/test/dump-load.sh +40 -0
  148. package/deps/libmdbx/test/extra/crunched_delete.c++ +409 -0
  149. package/deps/libmdbx/test/extra/cursor_closing.c++ +410 -0
  150. package/deps/libmdbx/test/extra/dbi.c++ +229 -0
  151. package/deps/libmdbx/test/extra/doubtless_positioning.c++ +253 -0
  152. package/deps/libmdbx/test/extra/dupfix_addodd.c +94 -0
  153. package/deps/libmdbx/test/extra/dupfix_multiple.c++ +311 -0
  154. package/deps/libmdbx/test/extra/early_close_dbi.c++ +137 -0
  155. package/deps/libmdbx/test/extra/hex_base64_base58.c++ +118 -0
  156. package/deps/libmdbx/test/extra/maindb_ordinal.c++ +61 -0
  157. package/deps/libmdbx/test/extra/open.c++ +96 -0
  158. package/deps/libmdbx/test/extra/pcrf/README.md +2 -0
  159. package/deps/libmdbx/test/extra/pcrf/pcrf_test.c +380 -0
  160. package/deps/libmdbx/test/extra/probe.c++ +10 -0
  161. package/deps/libmdbx/test/extra/txn.c++ +407 -0
  162. package/deps/libmdbx/test/extra/upsert_alldups.c +193 -0
  163. package/deps/libmdbx/test/fork.c++ +263 -0
  164. package/deps/libmdbx/test/hill.c++ +447 -0
  165. package/deps/libmdbx/test/jitter.c++ +197 -0
  166. package/deps/libmdbx/test/keygen.c++ +393 -0
  167. package/deps/libmdbx/test/keygen.h++ +130 -0
  168. package/deps/libmdbx/test/log.c++ +358 -0
  169. package/deps/libmdbx/test/log.h++ +91 -0
  170. package/deps/libmdbx/test/main.c++ +706 -0
  171. package/deps/libmdbx/test/nested.c++ +318 -0
  172. package/deps/libmdbx/test/osal-unix.c++ +647 -0
  173. package/deps/libmdbx/test/osal-windows.c++ +440 -0
  174. package/deps/libmdbx/test/osal.h++ +41 -0
  175. package/deps/libmdbx/test/stochastic.sh +690 -0
  176. package/deps/libmdbx/test/stub/LICENSE +24 -0
  177. package/deps/libmdbx/test/stub/README.md +8 -0
  178. package/deps/libmdbx/test/stub/pthread_barrier.c +104 -0
  179. package/deps/libmdbx/test/stub/pthread_barrier.h +77 -0
  180. package/deps/libmdbx/test/test.c++ +1551 -0
  181. package/deps/libmdbx/test/test.h++ +298 -0
  182. package/deps/libmdbx/test/tmux.conf +3 -0
  183. package/deps/libmdbx/test/try.c++ +30 -0
  184. package/deps/libmdbx/test/ttl.c++ +240 -0
  185. package/deps/libmdbx/test/utils.c++ +203 -0
  186. package/deps/libmdbx/test/utils.h++ +326 -0
  187. package/deps/libmdbx/test/valgrind_suppress.txt +536 -0
  188. package/lib/mdbx_evn_async.js +211 -0
  189. package/lib/mdbx_worker.js +195 -0
  190. package/lib/nativemou.js +6 -0
  191. package/package.json +38 -0
  192. package/src/async/envmou_close.cpp +34 -0
  193. package/src/async/envmou_close.hpp +32 -0
  194. package/src/async/envmou_copy_to.cpp +29 -0
  195. package/src/async/envmou_copy_to.hpp +38 -0
  196. package/src/async/envmou_keys.cpp +201 -0
  197. package/src/async/envmou_keys.hpp +50 -0
  198. package/src/async/envmou_open.cpp +38 -0
  199. package/src/async/envmou_open.hpp +33 -0
  200. package/src/async/envmou_query.cpp +167 -0
  201. package/src/async/envmou_query.hpp +53 -0
  202. package/src/dbimou.cpp +522 -0
  203. package/src/dbimou.hpp +82 -0
  204. package/src/env_arg0.hpp +24 -0
  205. package/src/envmou.cpp +445 -0
  206. package/src/envmou.hpp +116 -0
  207. package/src/modulemou.cpp +113 -0
  208. package/src/querymou.cpp +177 -0
  209. package/src/querymou.hpp +93 -0
  210. package/src/txnmou.cpp +254 -0
  211. package/src/txnmou.hpp +122 -0
  212. package/src/typemou.hpp +239 -0
  213. package/src/valuemou.hpp +194 -0
  214. package/test/async.js +67 -0
  215. package/test/e3.js +38 -0
  216. package/test/e4.js +89 -0
  217. package/test/e5.js +162 -0
  218. package/test/test-batch-ops.js +243 -0
  219. package/test/test-cursor-mode.js +84 -0
  220. package/test/test-multi-mode.js +87 -0
@@ -0,0 +1,309 @@
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
+ /*------------------------------------------------------------------------------
7
+ * Pack/Unpack 16-bit values for Grow step & Shrink threshold */
8
+
9
+ MDBX_NOTHROW_CONST_FUNCTION static inline pgno_t me2v(size_t m, size_t e) {
10
+ assert(m < 2048 && e < 8);
11
+ return (pgno_t)(32768 + ((m + 1) << (e + 8)));
12
+ }
13
+
14
+ MDBX_NOTHROW_CONST_FUNCTION static inline uint16_t v2me(size_t v, size_t e) {
15
+ assert(v > (e ? me2v(2047, e - 1) : 32768));
16
+ assert(v <= me2v(2047, e));
17
+ size_t m = (v - 32768 + ((size_t)1 << (e + 8)) - 1) >> (e + 8);
18
+ m -= m > 0;
19
+ assert(m < 2048 && e < 8);
20
+ // f e d c b a 9 8 7 6 5 4 3 2 1 0
21
+ // 1 e e e m m m m m m m m m m m 1
22
+ const uint16_t pv = (uint16_t)(0x8001 + (e << 12) + (m << 1));
23
+ assert(pv != 65535);
24
+ return pv;
25
+ }
26
+
27
+ /* Convert 16-bit packed (exponential quantized) value to number of pages */
28
+ pgno_t pv2pages(uint16_t pv) {
29
+ if ((pv & 0x8001) != 0x8001)
30
+ return pv;
31
+ if (pv == 65535)
32
+ return 65536;
33
+ // f e d c b a 9 8 7 6 5 4 3 2 1 0
34
+ // 1 e e e m m m m m m m m m m m 1
35
+ return me2v((pv >> 1) & 2047, (pv >> 12) & 7);
36
+ }
37
+
38
+ /* Convert number of pages to 16-bit packed (exponential quantized) value */
39
+ uint16_t pages2pv(size_t pages) {
40
+ if (pages < 32769 || (pages < 65536 && (pages & 1) == 0))
41
+ return (uint16_t)pages;
42
+ if (pages <= me2v(2047, 0))
43
+ return v2me(pages, 0);
44
+ if (pages <= me2v(2047, 1))
45
+ return v2me(pages, 1);
46
+ if (pages <= me2v(2047, 2))
47
+ return v2me(pages, 2);
48
+ if (pages <= me2v(2047, 3))
49
+ return v2me(pages, 3);
50
+ if (pages <= me2v(2047, 4))
51
+ return v2me(pages, 4);
52
+ if (pages <= me2v(2047, 5))
53
+ return v2me(pages, 5);
54
+ if (pages <= me2v(2047, 6))
55
+ return v2me(pages, 6);
56
+ return (pages < me2v(2046, 7)) ? v2me(pages, 7) : 65533;
57
+ }
58
+
59
+ __cold bool pv2pages_verify(void) {
60
+ bool ok = true, dump_translation = false;
61
+ for (size_t i = 0; i < 65536; ++i) {
62
+ size_t pages = pv2pages(i);
63
+ size_t x = pages2pv(pages);
64
+ size_t xp = pv2pages(x);
65
+ if (pages != xp) {
66
+ ERROR("%zu => %zu => %zu => %zu\n", i, pages, x, xp);
67
+ ok = false;
68
+ } else if (dump_translation && !(x == i || (x % 2 == 0 && x < 65536))) {
69
+ DEBUG("%zu => %zu => %zu => %zu\n", i, pages, x, xp);
70
+ }
71
+ }
72
+ return ok;
73
+ }
74
+
75
+ /*----------------------------------------------------------------------------*/
76
+
77
+ MDBX_NOTHROW_PURE_FUNCTION size_t bytes_align2os_bytes(const MDBX_env *env, size_t bytes) {
78
+ return ceil_powerof2(bytes, (env->ps > globals.sys_pagesize) ? env->ps : globals.sys_pagesize);
79
+ }
80
+
81
+ MDBX_NOTHROW_PURE_FUNCTION size_t pgno_align2os_bytes(const MDBX_env *env, size_t pgno) {
82
+ return ceil_powerof2(pgno2bytes(env, pgno), globals.sys_pagesize);
83
+ }
84
+
85
+ MDBX_NOTHROW_PURE_FUNCTION pgno_t pgno_align2os_pgno(const MDBX_env *env, size_t pgno) {
86
+ return bytes2pgno(env, pgno_align2os_bytes(env, pgno));
87
+ }
88
+
89
+ /*----------------------------------------------------------------------------*/
90
+
91
+ MDBX_NOTHROW_PURE_FUNCTION static __always_inline int cmp_int_inline(const size_t expected_alignment, const MDBX_val *a,
92
+ const MDBX_val *b) {
93
+ if (likely(a->iov_len == b->iov_len)) {
94
+ if (sizeof(size_t) > 7 && likely(a->iov_len == 8))
95
+ return CMP2INT(unaligned_peek_u64(expected_alignment, a->iov_base),
96
+ unaligned_peek_u64(expected_alignment, b->iov_base));
97
+ if (likely(a->iov_len == 4))
98
+ return CMP2INT(unaligned_peek_u32(expected_alignment, a->iov_base),
99
+ unaligned_peek_u32(expected_alignment, b->iov_base));
100
+ if (sizeof(size_t) < 8 && likely(a->iov_len == 8))
101
+ return CMP2INT(unaligned_peek_u64(expected_alignment, a->iov_base),
102
+ unaligned_peek_u64(expected_alignment, b->iov_base));
103
+ }
104
+ ERROR("mismatch and/or invalid size %p.%zu/%p.%zu for INTEGERKEY/INTEGERDUP", a->iov_base, a->iov_len, b->iov_base,
105
+ b->iov_len);
106
+ return 0;
107
+ }
108
+
109
+ MDBX_NOTHROW_PURE_FUNCTION __hot int cmp_int_unaligned(const MDBX_val *a, const MDBX_val *b) {
110
+ return cmp_int_inline(1, a, b);
111
+ }
112
+
113
+ #ifndef cmp_int_align2
114
+ /* Compare two items pointing at 2-byte aligned unsigned int's. */
115
+ MDBX_NOTHROW_PURE_FUNCTION __hot int cmp_int_align2(const MDBX_val *a, const MDBX_val *b) {
116
+ return cmp_int_inline(2, a, b);
117
+ }
118
+ #endif /* cmp_int_align2 */
119
+
120
+ #ifndef cmp_int_align4
121
+ /* Compare two items pointing at 4-byte aligned unsigned int's. */
122
+ MDBX_NOTHROW_PURE_FUNCTION __hot int cmp_int_align4(const MDBX_val *a, const MDBX_val *b) {
123
+ return cmp_int_inline(4, a, b);
124
+ }
125
+ #endif /* cmp_int_align4 */
126
+
127
+ /* Compare two items lexically */
128
+ MDBX_NOTHROW_PURE_FUNCTION __hot int cmp_lexical(const MDBX_val *a, const MDBX_val *b) {
129
+ if (a->iov_len == b->iov_len)
130
+ return a->iov_len ? memcmp(a->iov_base, b->iov_base, a->iov_len) : 0;
131
+
132
+ const int diff_len = (a->iov_len < b->iov_len) ? -1 : 1;
133
+ const size_t shortest = (a->iov_len < b->iov_len) ? a->iov_len : b->iov_len;
134
+ int diff_data = shortest ? memcmp(a->iov_base, b->iov_base, shortest) : 0;
135
+ return likely(diff_data) ? diff_data : diff_len;
136
+ }
137
+
138
+ MDBX_NOTHROW_PURE_FUNCTION static __always_inline unsigned tail3le(const uint8_t *p, size_t l) {
139
+ STATIC_ASSERT(sizeof(unsigned) > 2);
140
+ // 1: 0 0 0
141
+ // 2: 0 1 1
142
+ // 3: 0 1 2
143
+ return p[0] | p[l >> 1] << 8 | p[l - 1] << 16;
144
+ }
145
+
146
+ /* Compare two items in reverse byte order */
147
+ MDBX_NOTHROW_PURE_FUNCTION __hot int cmp_reverse(const MDBX_val *a, const MDBX_val *b) {
148
+ size_t left = (a->iov_len < b->iov_len) ? a->iov_len : b->iov_len;
149
+ if (likely(left)) {
150
+ const uint8_t *pa = ptr_disp(a->iov_base, a->iov_len);
151
+ const uint8_t *pb = ptr_disp(b->iov_base, b->iov_len);
152
+ while (left >= sizeof(size_t)) {
153
+ pa -= sizeof(size_t);
154
+ pb -= sizeof(size_t);
155
+ left -= sizeof(size_t);
156
+ STATIC_ASSERT(sizeof(size_t) == 4 || sizeof(size_t) == 8);
157
+ if (sizeof(size_t) == 4) {
158
+ uint32_t xa = unaligned_peek_u32(1, pa);
159
+ uint32_t xb = unaligned_peek_u32(1, pb);
160
+ #if __BYTE_ORDER__ != __ORDER_LITTLE_ENDIAN__
161
+ xa = osal_bswap32(xa);
162
+ xb = osal_bswap32(xb);
163
+ #endif /* __BYTE_ORDER__ != __ORDER_BIG_ENDIAN__ */
164
+ if (xa != xb)
165
+ return (xa < xb) ? -1 : 1;
166
+ } else {
167
+ uint64_t xa = unaligned_peek_u64(1, pa);
168
+ uint64_t xb = unaligned_peek_u64(1, pb);
169
+ #if __BYTE_ORDER__ != __ORDER_LITTLE_ENDIAN__
170
+ xa = osal_bswap64(xa);
171
+ xb = osal_bswap64(xb);
172
+ #endif /* __BYTE_ORDER__ != __ORDER_BIG_ENDIAN__ */
173
+ if (xa != xb)
174
+ return (xa < xb) ? -1 : 1;
175
+ }
176
+ }
177
+ if (sizeof(size_t) == 8 && left >= 4) {
178
+ pa -= 4;
179
+ pb -= 4;
180
+ left -= 4;
181
+ uint32_t xa = unaligned_peek_u32(1, pa);
182
+ uint32_t xb = unaligned_peek_u32(1, pb);
183
+ #if __BYTE_ORDER__ != __ORDER_LITTLE_ENDIAN__
184
+ xa = osal_bswap32(xa);
185
+ xb = osal_bswap32(xb);
186
+ #endif /* __BYTE_ORDER__ != __ORDER_BIG_ENDIAN__ */
187
+ if (xa != xb)
188
+ return (xa < xb) ? -1 : 1;
189
+ }
190
+ if (left) {
191
+ unsigned xa = tail3le(pa - left, left);
192
+ unsigned xb = tail3le(pb - left, left);
193
+ if (xa != xb)
194
+ return (xa < xb) ? -1 : 1;
195
+ }
196
+ }
197
+ return CMP2INT(a->iov_len, b->iov_len);
198
+ }
199
+
200
+ /* Fast non-lexically comparator */
201
+ MDBX_NOTHROW_PURE_FUNCTION __hot int cmp_lenfast(const MDBX_val *a, const MDBX_val *b) {
202
+ int diff = CMP2INT(a->iov_len, b->iov_len);
203
+ return (likely(diff) || a->iov_len == 0) ? diff : memcmp(a->iov_base, b->iov_base, a->iov_len);
204
+ }
205
+
206
+ MDBX_NOTHROW_PURE_FUNCTION __hot bool eq_fast_slowpath(const uint8_t *a, const uint8_t *b, size_t l) {
207
+ if (likely(l > 3)) {
208
+ if (MDBX_UNALIGNED_OK >= 4 && likely(l < 9))
209
+ return ((unaligned_peek_u32(1, a) - unaligned_peek_u32(1, b)) |
210
+ (unaligned_peek_u32(1, a + l - 4) - unaligned_peek_u32(1, b + l - 4))) == 0;
211
+ if (MDBX_UNALIGNED_OK >= 8 && sizeof(size_t) > 7 && likely(l < 17))
212
+ return ((unaligned_peek_u64(1, a) - unaligned_peek_u64(1, b)) |
213
+ (unaligned_peek_u64(1, a + l - 8) - unaligned_peek_u64(1, b + l - 8))) == 0;
214
+ return memcmp(a, b, l) == 0;
215
+ }
216
+ if (likely(l))
217
+ return tail3le(a, l) == tail3le(b, l);
218
+ return true;
219
+ }
220
+
221
+ int cmp_equal_or_greater(const MDBX_val *a, const MDBX_val *b) { return eq_fast(a, b) ? 0 : 1; }
222
+
223
+ int cmp_equal_or_wrong(const MDBX_val *a, const MDBX_val *b) { return eq_fast(a, b) ? 0 : -1; }
224
+
225
+ /*----------------------------------------------------------------------------*/
226
+
227
+ __cold void update_mlcnt(const MDBX_env *env, const pgno_t new_aligned_mlocked_pgno, const bool lock_not_release) {
228
+ for (;;) {
229
+ const pgno_t mlock_pgno_before = atomic_load32(&env->mlocked_pgno, mo_AcquireRelease);
230
+ eASSERT(env, pgno_align2os_pgno(env, mlock_pgno_before) == mlock_pgno_before);
231
+ eASSERT(env, pgno_align2os_pgno(env, new_aligned_mlocked_pgno) == new_aligned_mlocked_pgno);
232
+ if (lock_not_release ? (mlock_pgno_before >= new_aligned_mlocked_pgno)
233
+ : (mlock_pgno_before <= new_aligned_mlocked_pgno))
234
+ break;
235
+ if (likely(atomic_cas32(&((MDBX_env *)env)->mlocked_pgno, mlock_pgno_before, new_aligned_mlocked_pgno)))
236
+ for (;;) {
237
+ mdbx_atomic_uint32_t *const mlcnt = env->lck->mlcnt;
238
+ const int32_t snap_locked = atomic_load32(mlcnt + 0, mo_Relaxed);
239
+ const int32_t snap_unlocked = atomic_load32(mlcnt + 1, mo_Relaxed);
240
+ if (mlock_pgno_before == 0 && (snap_locked - snap_unlocked) < INT_MAX) {
241
+ eASSERT(env, lock_not_release);
242
+ if (unlikely(!atomic_cas32(mlcnt + 0, snap_locked, snap_locked + 1)))
243
+ continue;
244
+ }
245
+ if (new_aligned_mlocked_pgno == 0 && (snap_locked - snap_unlocked) > 0) {
246
+ eASSERT(env, !lock_not_release);
247
+ if (unlikely(!atomic_cas32(mlcnt + 1, snap_unlocked, snap_unlocked + 1)))
248
+ continue;
249
+ }
250
+ NOTICE("%s-pages %u..%u, mlocked-process(es) %u -> %u", lock_not_release ? "lock" : "unlock",
251
+ lock_not_release ? mlock_pgno_before : new_aligned_mlocked_pgno,
252
+ lock_not_release ? new_aligned_mlocked_pgno : mlock_pgno_before, snap_locked - snap_unlocked,
253
+ atomic_load32(mlcnt + 0, mo_Relaxed) - atomic_load32(mlcnt + 1, mo_Relaxed));
254
+ return;
255
+ }
256
+ }
257
+ }
258
+
259
+ __cold void munlock_after(const MDBX_env *env, const pgno_t aligned_pgno, const size_t end_bytes) {
260
+ if (atomic_load32(&env->mlocked_pgno, mo_AcquireRelease) > aligned_pgno) {
261
+ int err = MDBX_ENOSYS;
262
+ const size_t munlock_begin = pgno2bytes(env, aligned_pgno);
263
+ const size_t munlock_size = end_bytes - munlock_begin;
264
+ eASSERT(env, end_bytes % globals.sys_pagesize == 0 && munlock_begin % globals.sys_pagesize == 0 &&
265
+ munlock_size % globals.sys_pagesize == 0);
266
+ #if defined(_WIN32) || defined(_WIN64)
267
+ err = VirtualUnlock(ptr_disp(env->dxb_mmap.base, munlock_begin), munlock_size) ? MDBX_SUCCESS : (int)GetLastError();
268
+ if (err == ERROR_NOT_LOCKED)
269
+ err = MDBX_SUCCESS;
270
+ #elif defined(_POSIX_MEMLOCK_RANGE)
271
+ err = munlock(ptr_disp(env->dxb_mmap.base, munlock_begin), munlock_size) ? errno : MDBX_SUCCESS;
272
+ #endif
273
+ if (likely(err == MDBX_SUCCESS))
274
+ update_mlcnt(env, aligned_pgno, false);
275
+ else {
276
+ #if defined(_WIN32) || defined(_WIN64)
277
+ WARNING("VirtualUnlock(%zu, %zu) error %d", munlock_begin, munlock_size, err);
278
+ #else
279
+ WARNING("munlock(%zu, %zu) error %d", munlock_begin, munlock_size, err);
280
+ #endif
281
+ }
282
+ }
283
+ }
284
+
285
+ __cold void munlock_all(const MDBX_env *env) {
286
+ munlock_after(env, 0, bytes_align2os_bytes(env, env->dxb_mmap.current));
287
+ }
288
+
289
+ /*----------------------------------------------------------------------------*/
290
+
291
+ uint32_t combine_durability_flags(const uint32_t a, const uint32_t b) {
292
+ uint32_t r = a | b;
293
+
294
+ /* avoid false MDBX_UTTERLY_NOSYNC */
295
+ if (F_ISSET(r, MDBX_UTTERLY_NOSYNC) && !F_ISSET(a, MDBX_UTTERLY_NOSYNC) && !F_ISSET(b, MDBX_UTTERLY_NOSYNC))
296
+ r = (r - MDBX_UTTERLY_NOSYNC) | MDBX_SAFE_NOSYNC;
297
+
298
+ /* convert DEPRECATED_MAPASYNC to MDBX_SAFE_NOSYNC */
299
+ if ((r & (MDBX_WRITEMAP | DEPRECATED_MAPASYNC)) == (MDBX_WRITEMAP | DEPRECATED_MAPASYNC) &&
300
+ !F_ISSET(r, MDBX_UTTERLY_NOSYNC))
301
+ r = (r - DEPRECATED_MAPASYNC) | MDBX_SAFE_NOSYNC;
302
+
303
+ /* force MDBX_NOMETASYNC if NOSYNC enabled */
304
+ if (r & (MDBX_SAFE_NOSYNC | MDBX_UTTERLY_NOSYNC))
305
+ r |= MDBX_NOMETASYNC;
306
+
307
+ assert(!(F_ISSET(r, MDBX_UTTERLY_NOSYNC) && !F_ISSET(a, MDBX_UTTERLY_NOSYNC) && !F_ISSET(b, MDBX_UTTERLY_NOSYNC)));
308
+ return r;
309
+ }