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,543 @@
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
+ __cold size_t mdbx_default_pagesize(void) {
7
+ size_t pagesize = globals.sys_pagesize;
8
+ ENSURE(nullptr, is_powerof2(pagesize));
9
+ pagesize = (pagesize >= MDBX_MIN_PAGESIZE) ? pagesize : MDBX_MIN_PAGESIZE;
10
+ pagesize = (pagesize <= MDBX_MAX_PAGESIZE) ? pagesize : MDBX_MAX_PAGESIZE;
11
+ return pagesize;
12
+ }
13
+
14
+ __cold intptr_t mdbx_limits_dbsize_min(intptr_t pagesize) {
15
+ if (pagesize < 1)
16
+ pagesize = (intptr_t)mdbx_default_pagesize();
17
+ else if (unlikely(pagesize < (intptr_t)MDBX_MIN_PAGESIZE || pagesize > (intptr_t)MDBX_MAX_PAGESIZE ||
18
+ !is_powerof2((size_t)pagesize)))
19
+ return -1;
20
+
21
+ return MIN_PAGENO * pagesize;
22
+ }
23
+
24
+ __cold intptr_t mdbx_limits_dbsize_max(intptr_t pagesize) {
25
+ if (pagesize < 1)
26
+ pagesize = (intptr_t)mdbx_default_pagesize();
27
+ else if (unlikely(pagesize < (intptr_t)MDBX_MIN_PAGESIZE || pagesize > (intptr_t)MDBX_MAX_PAGESIZE ||
28
+ !is_powerof2((size_t)pagesize)))
29
+ return -1;
30
+
31
+ STATIC_ASSERT(MAX_MAPSIZE < INTPTR_MAX);
32
+ const uint64_t limit = (1 + (uint64_t)MAX_PAGENO) * pagesize;
33
+ return (limit < MAX_MAPSIZE) ? (intptr_t)limit : (intptr_t)MAX_MAPSIZE;
34
+ }
35
+
36
+ __cold intptr_t mdbx_limits_txnsize_max(intptr_t pagesize) {
37
+ if (pagesize < 1)
38
+ pagesize = (intptr_t)mdbx_default_pagesize();
39
+ else if (unlikely(pagesize < (intptr_t)MDBX_MIN_PAGESIZE || pagesize > (intptr_t)MDBX_MAX_PAGESIZE ||
40
+ !is_powerof2((size_t)pagesize)))
41
+ return -1;
42
+
43
+ STATIC_ASSERT(MAX_MAPSIZE < INTPTR_MAX);
44
+ const uint64_t pgl_limit = pagesize * (uint64_t)(PAGELIST_LIMIT / MDBX_GOLD_RATIO_DBL);
45
+ const uint64_t map_limit = (uint64_t)(MAX_MAPSIZE / MDBX_GOLD_RATIO_DBL);
46
+ return (pgl_limit < map_limit) ? (intptr_t)pgl_limit : (intptr_t)map_limit;
47
+ }
48
+
49
+ __cold intptr_t mdbx_limits_keysize_max(intptr_t pagesize, MDBX_db_flags_t flags) {
50
+ if (pagesize < 1)
51
+ pagesize = (intptr_t)mdbx_default_pagesize();
52
+ if (unlikely(pagesize < (intptr_t)MDBX_MIN_PAGESIZE || pagesize > (intptr_t)MDBX_MAX_PAGESIZE ||
53
+ !is_powerof2((size_t)pagesize)))
54
+ return -1;
55
+
56
+ return keysize_max(pagesize, flags);
57
+ }
58
+
59
+ __cold int mdbx_env_get_maxkeysize_ex(const MDBX_env *env, MDBX_db_flags_t flags) {
60
+ if (unlikely(!env || env->signature.weak != env_signature))
61
+ return -1;
62
+
63
+ return (int)mdbx_limits_keysize_max((intptr_t)env->ps, flags);
64
+ }
65
+
66
+ __cold int mdbx_env_get_maxkeysize(const MDBX_env *env) { return mdbx_env_get_maxkeysize_ex(env, MDBX_DUPSORT); }
67
+
68
+ __cold intptr_t mdbx_limits_keysize_min(MDBX_db_flags_t flags) { return keysize_min(flags); }
69
+
70
+ __cold intptr_t mdbx_limits_valsize_max(intptr_t pagesize, MDBX_db_flags_t flags) {
71
+ if (pagesize < 1)
72
+ pagesize = (intptr_t)mdbx_default_pagesize();
73
+ if (unlikely(pagesize < (intptr_t)MDBX_MIN_PAGESIZE || pagesize > (intptr_t)MDBX_MAX_PAGESIZE ||
74
+ !is_powerof2((size_t)pagesize)))
75
+ return -1;
76
+
77
+ return valsize_max(pagesize, flags);
78
+ }
79
+
80
+ __cold int mdbx_env_get_maxvalsize_ex(const MDBX_env *env, MDBX_db_flags_t flags) {
81
+ if (unlikely(!env || env->signature.weak != env_signature))
82
+ return -1;
83
+
84
+ return (int)mdbx_limits_valsize_max((intptr_t)env->ps, flags);
85
+ }
86
+
87
+ __cold intptr_t mdbx_limits_valsize_min(MDBX_db_flags_t flags) { return valsize_min(flags); }
88
+
89
+ __cold intptr_t mdbx_limits_pairsize4page_max(intptr_t pagesize, MDBX_db_flags_t flags) {
90
+ if (pagesize < 1)
91
+ pagesize = (intptr_t)mdbx_default_pagesize();
92
+ if (unlikely(pagesize < (intptr_t)MDBX_MIN_PAGESIZE || pagesize > (intptr_t)MDBX_MAX_PAGESIZE ||
93
+ !is_powerof2((size_t)pagesize)))
94
+ return -1;
95
+
96
+ if (flags & (MDBX_DUPSORT | MDBX_DUPFIXED | MDBX_INTEGERDUP | MDBX_REVERSEDUP))
97
+ return BRANCH_NODE_MAX(pagesize) - NODESIZE;
98
+
99
+ return LEAF_NODE_MAX(pagesize) - NODESIZE;
100
+ }
101
+
102
+ __cold int mdbx_env_get_pairsize4page_max(const MDBX_env *env, MDBX_db_flags_t flags) {
103
+ if (unlikely(!env || env->signature.weak != env_signature))
104
+ return -1;
105
+
106
+ return (int)mdbx_limits_pairsize4page_max((intptr_t)env->ps, flags);
107
+ }
108
+
109
+ __cold intptr_t mdbx_limits_valsize4page_max(intptr_t pagesize, MDBX_db_flags_t flags) {
110
+ if (pagesize < 1)
111
+ pagesize = (intptr_t)mdbx_default_pagesize();
112
+ if (unlikely(pagesize < (intptr_t)MDBX_MIN_PAGESIZE || pagesize > (intptr_t)MDBX_MAX_PAGESIZE ||
113
+ !is_powerof2((size_t)pagesize)))
114
+ return -1;
115
+
116
+ if (flags & (MDBX_DUPSORT | MDBX_DUPFIXED | MDBX_INTEGERDUP | MDBX_REVERSEDUP))
117
+ return valsize_max(pagesize, flags);
118
+
119
+ return PAGESPACE(pagesize);
120
+ }
121
+
122
+ __cold int mdbx_env_get_valsize4page_max(const MDBX_env *env, MDBX_db_flags_t flags) {
123
+ if (unlikely(!env || env->signature.weak != env_signature))
124
+ return -1;
125
+
126
+ return (int)mdbx_limits_valsize4page_max((intptr_t)env->ps, flags);
127
+ }
128
+
129
+ /*----------------------------------------------------------------------------*/
130
+
131
+ static size_t estimate_rss(size_t database_bytes) {
132
+ return database_bytes + database_bytes / 64 + (512 + MDBX_WORDBITS * 16) * MEGABYTE;
133
+ }
134
+
135
+ __cold int mdbx_env_warmup(const MDBX_env *env, const MDBX_txn *txn, MDBX_warmup_flags_t flags,
136
+ unsigned timeout_seconds_16dot16) {
137
+ if (unlikely(env == nullptr && txn == nullptr))
138
+ return LOG_IFERR(MDBX_EINVAL);
139
+ if (unlikely(flags > (MDBX_warmup_force | MDBX_warmup_oomsafe | MDBX_warmup_lock | MDBX_warmup_touchlimit |
140
+ MDBX_warmup_release)))
141
+ return LOG_IFERR(MDBX_EINVAL);
142
+
143
+ if (txn) {
144
+ int err = check_txn(txn, MDBX_TXN_FINISHED | MDBX_TXN_ERROR);
145
+ if (unlikely(err != MDBX_SUCCESS))
146
+ return LOG_IFERR(err);
147
+ }
148
+ if (env) {
149
+ int err = check_env(env, false);
150
+ if (unlikely(err != MDBX_SUCCESS))
151
+ return LOG_IFERR(err);
152
+ if (txn && unlikely(txn->env != env))
153
+ return LOG_IFERR(MDBX_EINVAL);
154
+ } else {
155
+ env = txn->env;
156
+ }
157
+
158
+ const uint64_t timeout_monotime = (timeout_seconds_16dot16 && (flags & MDBX_warmup_force))
159
+ ? osal_monotime() + osal_16dot16_to_monotime(timeout_seconds_16dot16)
160
+ : 0;
161
+
162
+ if (flags & MDBX_warmup_release)
163
+ munlock_all(env);
164
+
165
+ pgno_t used_pgno;
166
+ if (txn) {
167
+ used_pgno = txn->geo.first_unallocated;
168
+ } else {
169
+ const troika_t troika = meta_tap(env);
170
+ used_pgno = meta_recent(env, &troika).ptr_v->geometry.first_unallocated;
171
+ }
172
+ const size_t used_range = pgno_align2os_bytes(env, used_pgno);
173
+ const pgno_t mlock_pgno = bytes2pgno(env, used_range);
174
+
175
+ int rc = MDBX_SUCCESS;
176
+ if (flags & MDBX_warmup_touchlimit) {
177
+ const size_t estimated_rss = estimate_rss(used_range);
178
+ #if defined(_WIN32) || defined(_WIN64)
179
+ SIZE_T current_ws_lower, current_ws_upper;
180
+ if (GetProcessWorkingSetSize(GetCurrentProcess(), &current_ws_lower, &current_ws_upper) &&
181
+ current_ws_lower < estimated_rss) {
182
+ const SIZE_T ws_lower = estimated_rss;
183
+ const SIZE_T ws_upper =
184
+ (MDBX_WORDBITS == 32 && ws_lower > MEGABYTE * 2048) ? ws_lower : ws_lower + MDBX_WORDBITS * MEGABYTE * 32;
185
+ if (!SetProcessWorkingSetSize(GetCurrentProcess(), ws_lower, ws_upper)) {
186
+ rc = (int)GetLastError();
187
+ WARNING("SetProcessWorkingSetSize(%zu, %zu) error %d", ws_lower, ws_upper, rc);
188
+ }
189
+ }
190
+ #endif /* Windows */
191
+ #ifdef RLIMIT_RSS
192
+ struct rlimit rss;
193
+ if (getrlimit(RLIMIT_RSS, &rss) == 0 && rss.rlim_cur < estimated_rss) {
194
+ rss.rlim_cur = estimated_rss;
195
+ if (rss.rlim_max < estimated_rss)
196
+ rss.rlim_max = estimated_rss;
197
+ if (setrlimit(RLIMIT_RSS, &rss)) {
198
+ rc = errno;
199
+ WARNING("setrlimit(%s, {%zu, %zu}) error %d", "RLIMIT_RSS", (size_t)rss.rlim_cur, (size_t)rss.rlim_max, rc);
200
+ }
201
+ }
202
+ #endif /* RLIMIT_RSS */
203
+ #ifdef RLIMIT_MEMLOCK
204
+ if (flags & MDBX_warmup_lock) {
205
+ struct rlimit memlock;
206
+ if (getrlimit(RLIMIT_MEMLOCK, &memlock) == 0 && memlock.rlim_cur < estimated_rss) {
207
+ memlock.rlim_cur = estimated_rss;
208
+ if (memlock.rlim_max < estimated_rss)
209
+ memlock.rlim_max = estimated_rss;
210
+ if (setrlimit(RLIMIT_MEMLOCK, &memlock)) {
211
+ rc = errno;
212
+ WARNING("setrlimit(%s, {%zu, %zu}) error %d", "RLIMIT_MEMLOCK", (size_t)memlock.rlim_cur,
213
+ (size_t)memlock.rlim_max, rc);
214
+ }
215
+ }
216
+ }
217
+ #endif /* RLIMIT_MEMLOCK */
218
+ (void)estimated_rss;
219
+ }
220
+
221
+ #if defined(MLOCK_ONFAULT) && \
222
+ ((defined(_GNU_SOURCE) && __GLIBC_PREREQ(2, 27)) || (defined(__ANDROID_API__) && __ANDROID_API__ >= 30)) && \
223
+ (defined(__linux__) || defined(__gnu_linux__))
224
+ if ((flags & MDBX_warmup_lock) != 0 && globals.linux_kernel_version >= 0x04040000 &&
225
+ atomic_load32(&env->mlocked_pgno, mo_AcquireRelease) < mlock_pgno) {
226
+ if (mlock2(env->dxb_mmap.base, used_range, MLOCK_ONFAULT)) {
227
+ rc = errno;
228
+ WARNING("mlock2(%zu, %s) error %d", used_range, "MLOCK_ONFAULT", rc);
229
+ } else {
230
+ update_mlcnt(env, mlock_pgno, true);
231
+ rc = MDBX_SUCCESS;
232
+ }
233
+ if (rc != EINVAL)
234
+ flags -= MDBX_warmup_lock;
235
+ }
236
+ #endif /* MLOCK_ONFAULT */
237
+
238
+ int err = MDBX_ENOSYS;
239
+ err = dxb_set_readahead(env, used_pgno, true, true);
240
+ if (err != MDBX_SUCCESS && rc == MDBX_SUCCESS)
241
+ rc = err;
242
+
243
+ if ((flags & MDBX_warmup_force) != 0 && (rc == MDBX_SUCCESS || rc == MDBX_ENOSYS)) {
244
+ const volatile uint8_t *ptr = env->dxb_mmap.base;
245
+ size_t offset = 0, unused = 42;
246
+ #if !(defined(_WIN32) || defined(_WIN64))
247
+ if (flags & MDBX_warmup_oomsafe) {
248
+ const int null_fd = open("/dev/null", O_WRONLY);
249
+ if (unlikely(null_fd < 0))
250
+ rc = errno;
251
+ else {
252
+ struct iovec iov[MDBX_AUXILARY_IOV_MAX];
253
+ for (;;) {
254
+ unsigned i;
255
+ for (i = 0; i < MDBX_AUXILARY_IOV_MAX && offset < used_range; ++i) {
256
+ iov[i].iov_base = (void *)(ptr + offset);
257
+ iov[i].iov_len = 1;
258
+ offset += globals.sys_pagesize;
259
+ }
260
+ if (unlikely(writev(null_fd, iov, i) < 0)) {
261
+ rc = errno;
262
+ if (rc == EFAULT)
263
+ rc = ENOMEM;
264
+ break;
265
+ }
266
+ if (offset >= used_range) {
267
+ rc = MDBX_SUCCESS;
268
+ break;
269
+ }
270
+ if (timeout_seconds_16dot16 && osal_monotime() > timeout_monotime) {
271
+ rc = MDBX_RESULT_TRUE;
272
+ break;
273
+ }
274
+ }
275
+ close(null_fd);
276
+ }
277
+ } else
278
+ #endif /* Windows */
279
+ for (;;) {
280
+ unused += ptr[offset];
281
+ offset += globals.sys_pagesize;
282
+ if (offset >= used_range) {
283
+ rc = MDBX_SUCCESS;
284
+ break;
285
+ }
286
+ if (timeout_seconds_16dot16 && osal_monotime() > timeout_monotime) {
287
+ rc = MDBX_RESULT_TRUE;
288
+ break;
289
+ }
290
+ }
291
+ (void)unused;
292
+ }
293
+
294
+ if ((flags & MDBX_warmup_lock) != 0 && (rc == MDBX_SUCCESS || rc == MDBX_ENOSYS) &&
295
+ atomic_load32(&env->mlocked_pgno, mo_AcquireRelease) < mlock_pgno) {
296
+ #if defined(_WIN32) || defined(_WIN64)
297
+ if (VirtualLock(env->dxb_mmap.base, used_range)) {
298
+ update_mlcnt(env, mlock_pgno, true);
299
+ rc = MDBX_SUCCESS;
300
+ } else {
301
+ rc = (int)GetLastError();
302
+ WARNING("%s(%zu) error %d", "VirtualLock", used_range, rc);
303
+ }
304
+ #elif defined(_POSIX_MEMLOCK_RANGE)
305
+ if (mlock(env->dxb_mmap.base, used_range) == 0) {
306
+ update_mlcnt(env, mlock_pgno, true);
307
+ rc = MDBX_SUCCESS;
308
+ } else {
309
+ rc = errno;
310
+ WARNING("%s(%zu) error %d", "mlock", used_range, rc);
311
+ }
312
+ #else
313
+ rc = MDBX_ENOSYS;
314
+ #endif
315
+ }
316
+
317
+ return LOG_IFERR(rc);
318
+ }
319
+
320
+ /*----------------------------------------------------------------------------*/
321
+
322
+ __cold int mdbx_env_get_fd(const MDBX_env *env, mdbx_filehandle_t *arg) {
323
+ int rc = check_env(env, true);
324
+ if (unlikely(rc != MDBX_SUCCESS))
325
+ return LOG_IFERR(rc);
326
+
327
+ if (unlikely(!arg))
328
+ return LOG_IFERR(MDBX_EINVAL);
329
+
330
+ *arg = env->lazy_fd;
331
+ return MDBX_SUCCESS;
332
+ }
333
+
334
+ __cold int mdbx_env_set_flags(MDBX_env *env, MDBX_env_flags_t flags, bool onoff) {
335
+ int rc = check_env(env, false);
336
+ if (unlikely(rc != MDBX_SUCCESS))
337
+ return LOG_IFERR(rc);
338
+
339
+ if (unlikely(flags & ((env->flags & ENV_ACTIVE) ? ~ENV_CHANGEABLE_FLAGS : ~ENV_USABLE_FLAGS)))
340
+ return LOG_IFERR(MDBX_EPERM);
341
+
342
+ if (unlikely(env->flags & MDBX_RDONLY))
343
+ return LOG_IFERR(MDBX_EACCESS);
344
+
345
+ const bool lock_needed = (env->flags & ENV_ACTIVE) && !env_owned_wrtxn(env);
346
+ bool should_unlock = false;
347
+ if (lock_needed) {
348
+ rc = lck_txn_lock(env, false);
349
+ if (unlikely(rc != MDBX_SUCCESS))
350
+ return LOG_IFERR(rc);
351
+ should_unlock = true;
352
+ }
353
+
354
+ if (onoff)
355
+ env->flags = combine_durability_flags(env->flags, flags);
356
+ else
357
+ env->flags &= ~flags;
358
+
359
+ if (should_unlock)
360
+ lck_txn_unlock(env);
361
+ return MDBX_SUCCESS;
362
+ }
363
+
364
+ __cold int mdbx_env_get_flags(const MDBX_env *env, unsigned *flags) {
365
+ int rc = check_env(env, false);
366
+ if (unlikely(rc != MDBX_SUCCESS))
367
+ return LOG_IFERR(rc);
368
+
369
+ if (unlikely(!flags))
370
+ return LOG_IFERR(MDBX_EINVAL);
371
+
372
+ *flags = env->flags & ENV_USABLE_FLAGS;
373
+ return MDBX_SUCCESS;
374
+ }
375
+
376
+ __cold int mdbx_env_set_userctx(MDBX_env *env, void *ctx) {
377
+ int rc = check_env(env, false);
378
+ if (unlikely(rc != MDBX_SUCCESS))
379
+ return LOG_IFERR(rc);
380
+
381
+ env->userctx = ctx;
382
+ return MDBX_SUCCESS;
383
+ }
384
+
385
+ __cold void *mdbx_env_get_userctx(const MDBX_env *env) { return env ? env->userctx : nullptr; }
386
+
387
+ __cold int mdbx_env_set_assert(MDBX_env *env, MDBX_assert_func *func) {
388
+ int rc = check_env(env, false);
389
+ if (unlikely(rc != MDBX_SUCCESS))
390
+ return LOG_IFERR(rc);
391
+
392
+ #if MDBX_DEBUG
393
+ env->assert_func = func;
394
+ return MDBX_SUCCESS;
395
+ #else
396
+ (void)func;
397
+ return LOG_IFERR(MDBX_ENOSYS);
398
+ #endif
399
+ }
400
+
401
+ __cold int mdbx_env_set_hsr(MDBX_env *env, MDBX_hsr_func *hsr) {
402
+ int rc = check_env(env, false);
403
+ if (unlikely(rc != MDBX_SUCCESS))
404
+ return LOG_IFERR(rc);
405
+
406
+ env->hsr_callback = hsr;
407
+ return MDBX_SUCCESS;
408
+ }
409
+
410
+ __cold MDBX_hsr_func *mdbx_env_get_hsr(const MDBX_env *env) {
411
+ return likely(env && env->signature.weak == env_signature) ? env->hsr_callback : nullptr;
412
+ }
413
+
414
+ #if defined(_WIN32) || defined(_WIN64)
415
+ __cold int mdbx_env_get_pathW(const MDBX_env *env, const wchar_t **arg) {
416
+ int rc = check_env(env, true);
417
+ if (unlikely(rc != MDBX_SUCCESS))
418
+ return LOG_IFERR(rc);
419
+
420
+ if (unlikely(!arg))
421
+ return LOG_IFERR(MDBX_EINVAL);
422
+
423
+ *arg = env->pathname.specified;
424
+ return MDBX_SUCCESS;
425
+ }
426
+ #endif /* Windows */
427
+
428
+ __cold int mdbx_env_get_path(const MDBX_env *env, const char **arg) {
429
+ int rc = check_env(env, true);
430
+ if (unlikely(rc != MDBX_SUCCESS))
431
+ return LOG_IFERR(rc);
432
+
433
+ if (unlikely(!arg))
434
+ return LOG_IFERR(MDBX_EINVAL);
435
+
436
+ #if defined(_WIN32) || defined(_WIN64)
437
+ if (!env->pathname_char) {
438
+ *arg = nullptr;
439
+ DWORD flags = /* WC_ERR_INVALID_CHARS */ 0x80;
440
+ size_t mb_len =
441
+ WideCharToMultiByte(CP_THREAD_ACP, flags, env->pathname.specified, -1, nullptr, 0, nullptr, nullptr);
442
+ rc = mb_len ? MDBX_SUCCESS : (int)GetLastError();
443
+ if (rc == ERROR_INVALID_FLAGS) {
444
+ mb_len = WideCharToMultiByte(CP_THREAD_ACP, flags = 0, env->pathname.specified, -1, nullptr, 0, nullptr, nullptr);
445
+ rc = mb_len ? MDBX_SUCCESS : (int)GetLastError();
446
+ }
447
+ if (unlikely(rc != MDBX_SUCCESS))
448
+ return LOG_IFERR(rc);
449
+
450
+ char *const mb_pathname = osal_malloc(mb_len);
451
+ if (!mb_pathname)
452
+ return LOG_IFERR(MDBX_ENOMEM);
453
+ if (mb_len != (size_t)WideCharToMultiByte(CP_THREAD_ACP, flags, env->pathname.specified, -1, mb_pathname,
454
+ (int)mb_len, nullptr, nullptr)) {
455
+ rc = (int)GetLastError();
456
+ osal_free(mb_pathname);
457
+ return LOG_IFERR(rc);
458
+ }
459
+ if (env->pathname_char ||
460
+ InterlockedCompareExchangePointer((PVOID volatile *)&env->pathname_char, mb_pathname, nullptr))
461
+ osal_free(mb_pathname);
462
+ }
463
+ *arg = env->pathname_char;
464
+ #else
465
+ *arg = env->pathname.specified;
466
+ #endif /* Windows */
467
+ return MDBX_SUCCESS;
468
+ }
469
+
470
+ /*------------------------------------------------------------------------------
471
+ * Legacy API */
472
+
473
+ #ifndef LIBMDBX_NO_EXPORTS_LEGACY_API
474
+
475
+ LIBMDBX_API int mdbx_txn_begin(MDBX_env *env, MDBX_txn *parent, MDBX_txn_flags_t flags, MDBX_txn **ret) {
476
+ return __inline_mdbx_txn_begin(env, parent, flags, ret);
477
+ }
478
+
479
+ LIBMDBX_API int mdbx_txn_commit(MDBX_txn *txn) { return __inline_mdbx_txn_commit(txn); }
480
+
481
+ LIBMDBX_API __cold int mdbx_env_stat(const MDBX_env *env, MDBX_stat *stat, size_t bytes) {
482
+ return __inline_mdbx_env_stat(env, stat, bytes);
483
+ }
484
+
485
+ LIBMDBX_API __cold int mdbx_env_info(const MDBX_env *env, MDBX_envinfo *info, size_t bytes) {
486
+ return __inline_mdbx_env_info(env, info, bytes);
487
+ }
488
+
489
+ LIBMDBX_API int mdbx_dbi_flags(const MDBX_txn *txn, MDBX_dbi dbi, unsigned *flags) {
490
+ return __inline_mdbx_dbi_flags(txn, dbi, flags);
491
+ }
492
+
493
+ LIBMDBX_API __cold int mdbx_env_sync(MDBX_env *env) { return __inline_mdbx_env_sync(env); }
494
+
495
+ LIBMDBX_API __cold int mdbx_env_sync_poll(MDBX_env *env) { return __inline_mdbx_env_sync_poll(env); }
496
+
497
+ LIBMDBX_API __cold int mdbx_env_close(MDBX_env *env) { return __inline_mdbx_env_close(env); }
498
+
499
+ LIBMDBX_API __cold int mdbx_env_set_mapsize(MDBX_env *env, size_t size) {
500
+ return __inline_mdbx_env_set_mapsize(env, size);
501
+ }
502
+
503
+ LIBMDBX_API __cold int mdbx_env_set_maxdbs(MDBX_env *env, MDBX_dbi dbs) {
504
+ return __inline_mdbx_env_set_maxdbs(env, dbs);
505
+ }
506
+
507
+ LIBMDBX_API __cold int mdbx_env_get_maxdbs(const MDBX_env *env, MDBX_dbi *dbs) {
508
+ return __inline_mdbx_env_get_maxdbs(env, dbs);
509
+ }
510
+
511
+ LIBMDBX_API __cold int mdbx_env_set_maxreaders(MDBX_env *env, unsigned readers) {
512
+ return __inline_mdbx_env_set_maxreaders(env, readers);
513
+ }
514
+
515
+ LIBMDBX_API __cold int mdbx_env_get_maxreaders(const MDBX_env *env, unsigned *readers) {
516
+ return __inline_mdbx_env_get_maxreaders(env, readers);
517
+ }
518
+
519
+ LIBMDBX_API __cold int mdbx_env_set_syncbytes(MDBX_env *env, size_t threshold) {
520
+ return __inline_mdbx_env_set_syncbytes(env, threshold);
521
+ }
522
+
523
+ LIBMDBX_API __cold int mdbx_env_get_syncbytes(const MDBX_env *env, size_t *threshold) {
524
+ return __inline_mdbx_env_get_syncbytes(env, threshold);
525
+ }
526
+
527
+ LIBMDBX_API __cold int mdbx_env_set_syncperiod(MDBX_env *env, unsigned seconds_16dot16) {
528
+ return __inline_mdbx_env_set_syncperiod(env, seconds_16dot16);
529
+ }
530
+
531
+ LIBMDBX_API __cold int mdbx_env_get_syncperiod(const MDBX_env *env, unsigned *seconds_16dot16) {
532
+ return __inline_mdbx_env_get_syncperiod(env, seconds_16dot16);
533
+ }
534
+
535
+ LIBMDBX_API __cold uint64_t mdbx_key_from_int64(const int64_t i64) { return __inline_mdbx_key_from_int64(i64); }
536
+
537
+ LIBMDBX_API __cold uint32_t mdbx_key_from_int32(const int32_t i32) { return __inline_mdbx_key_from_int32(i32); }
538
+
539
+ LIBMDBX_API __cold intptr_t mdbx_limits_pgsize_min(void) { return __inline_mdbx_limits_pgsize_min(); }
540
+
541
+ LIBMDBX_API __cold intptr_t mdbx_limits_pgsize_max(void) { return __inline_mdbx_limits_pgsize_max(); }
542
+
543
+ #endif /* LIBMDBX_NO_EXPORTS_LEGACY_API */