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,407 @@
1
+ #include "mdbx.h++"
2
+ #include MDBX_CONFIG_H
3
+
4
+ #include <iostream>
5
+
6
+ #if defined(ENABLE_MEMCHECK) || defined(MDBX_CI)
7
+ #if MDBX_DEBUG || !defined(NDEBUG)
8
+ #define RELIEF_FACTOR 16
9
+ #else
10
+ #define RELIEF_FACTOR 8
11
+ #endif
12
+ #elif MDBX_DEBUG || !defined(NDEBUG) || defined(__APPLE__) || defined(_WIN32)
13
+ #define RELIEF_FACTOR 4
14
+ #elif UINTPTR_MAX > 0xffffFFFFul || ULONG_MAX > 0xffffFFFFul
15
+ #define RELIEF_FACTOR 2
16
+ #else
17
+ #define RELIEF_FACTOR 1
18
+ #endif
19
+
20
+ #if !defined(__cpp_lib_latch) && __cpp_lib_latch < 201907L
21
+
22
+ int main(int argc, const char *argv[]) {
23
+ (void)argc;
24
+ (void)argv;
25
+ std::cout << "FAKE-OK (since no C++20 std::thread and/or std::latch)\n";
26
+ return EXIT_SUCCESS;
27
+ }
28
+
29
+ #else
30
+
31
+ #include <latch>
32
+ #include <thread>
33
+
34
+ bool case0(const mdbx::path &path) {
35
+ mdbx::env_managed::create_parameters createParameters;
36
+ createParameters.geometry.make_dynamic(21 * mdbx::env::geometry::MiB, 84 * mdbx::env::geometry::MiB);
37
+
38
+ mdbx::env::operate_parameters operateParameters(100, 10);
39
+ operateParameters.options.no_sticky_threads = false;
40
+ mdbx::env_managed env(path, createParameters, operateParameters);
41
+ auto txn = env.start_write(false);
42
+ /* mdbx::map_handle testHandle = */ txn.create_map("xyz", mdbx::key_mode::usual, mdbx::value_mode::single);
43
+ txn.commit();
44
+
45
+ //-------------------------------------
46
+ txn = env.start_write();
47
+ MDBX_txn *c_txn = txn;
48
+ int err = mdbx_txn_reset(txn);
49
+ assert(err == MDBX_EINVAL);
50
+ bool ok = err == MDBX_EINVAL;
51
+
52
+ err = mdbx_txn_break(txn);
53
+ assert(err == MDBX_SUCCESS);
54
+ ok = ok && err == MDBX_SUCCESS;
55
+
56
+ err = mdbx_txn_commit(txn);
57
+ assert(err == MDBX_RESULT_TRUE);
58
+ ok = ok && err == MDBX_RESULT_TRUE;
59
+
60
+ //-------------------------------------
61
+ err = mdbx_txn_begin(env, nullptr, MDBX_TXN_READWRITE, &c_txn);
62
+ assert(err == MDBX_SUCCESS);
63
+ ok = ok && err == MDBX_SUCCESS;
64
+ assert(c_txn == (const MDBX_txn *)txn);
65
+
66
+ err = mdbx_txn_break(txn);
67
+ assert(err == MDBX_SUCCESS);
68
+ ok = ok && err == MDBX_SUCCESS;
69
+
70
+ err = mdbx_txn_reset(txn);
71
+ assert(err == MDBX_EINVAL);
72
+ ok = ok && err == MDBX_EINVAL;
73
+
74
+ err = mdbx_txn_commit(txn);
75
+ assert(err == MDBX_RESULT_TRUE);
76
+ ok = ok && err == MDBX_RESULT_TRUE;
77
+
78
+ err = mdbx_txn_abort(c_txn);
79
+ assert(err == MDBX_BAD_TXN);
80
+ ok = ok && err == MDBX_BAD_TXN;
81
+ //-------------------------------------
82
+ err = mdbx_txn_begin(env, nullptr, MDBX_TXN_READWRITE, &c_txn);
83
+ assert(err == MDBX_SUCCESS);
84
+ ok = ok && err == MDBX_SUCCESS;
85
+ assert(c_txn == (const MDBX_txn *)txn);
86
+ txn.commit();
87
+
88
+ err = mdbx_txn_reset(c_txn);
89
+ assert(err == MDBX_BAD_TXN);
90
+ ok = ok && err == MDBX_BAD_TXN;
91
+ err = mdbx_txn_break(c_txn);
92
+ assert(err == MDBX_BAD_TXN);
93
+ ok = ok && err == MDBX_BAD_TXN;
94
+ err = mdbx_txn_abort(c_txn);
95
+ assert(err == MDBX_BAD_TXN);
96
+ ok = ok && err == MDBX_BAD_TXN;
97
+
98
+ //=====================================
99
+
100
+ txn = env.start_read();
101
+ err = mdbx_txn_begin(env, txn, MDBX_TXN_READWRITE, &c_txn);
102
+ assert(err == MDBX_BAD_TXN);
103
+ ok = ok && err == MDBX_BAD_TXN;
104
+ txn.make_broken();
105
+ err = mdbx_txn_begin(env, txn, MDBX_TXN_READWRITE, &c_txn);
106
+ assert(err == MDBX_BAD_TXN);
107
+ ok = ok && err == MDBX_BAD_TXN;
108
+ txn.reset_reading();
109
+ err = mdbx_txn_begin(env, txn, MDBX_TXN_READWRITE, &c_txn);
110
+ assert(err == MDBX_BAD_TXN);
111
+ ok = ok && err == MDBX_BAD_TXN;
112
+ txn.abort();
113
+
114
+ //-------------------------------------
115
+
116
+ txn = env.start_read();
117
+ txn.reset_reading();
118
+ txn.make_broken();
119
+ txn.abort();
120
+
121
+ //=====================================
122
+
123
+ std::latch s(1);
124
+ txn = env.start_read();
125
+ c_txn = txn;
126
+
127
+ std::thread t([&]() {
128
+ s.wait();
129
+ #if MDBX_TXN_CHECKOWNER
130
+ err = mdbx_txn_reset(c_txn);
131
+ assert(err == MDBX_THREAD_MISMATCH);
132
+ ok = ok && err == MDBX_THREAD_MISMATCH;
133
+ err = mdbx_txn_break(c_txn);
134
+ assert(err == MDBX_THREAD_MISMATCH);
135
+ ok = ok && err == MDBX_THREAD_MISMATCH;
136
+ err = mdbx_txn_commit(c_txn);
137
+ assert(err == MDBX_THREAD_MISMATCH);
138
+ ok = ok && err == MDBX_THREAD_MISMATCH;
139
+ err = mdbx_txn_abort(c_txn);
140
+ assert(err == MDBX_THREAD_MISMATCH);
141
+ ok = ok && err == MDBX_THREAD_MISMATCH;
142
+ #endif /* MDBX_TXN_CHECKOWNER */
143
+
144
+ err = mdbx_txn_begin(env, txn, MDBX_TXN_READWRITE, &c_txn);
145
+ #if MDBX_TXN_CHECKOWNER
146
+ assert(err == MDBX_THREAD_MISMATCH);
147
+ ok = ok && err == MDBX_THREAD_MISMATCH;
148
+ #else
149
+ assert(err == MDBX_BAD_TXN);
150
+ ok = ok && err == MDBX_BAD_TXN;
151
+ #endif /* MDBX_TXN_CHECKOWNER */
152
+ });
153
+
154
+ s.count_down();
155
+ t.join();
156
+
157
+ return ok;
158
+ }
159
+
160
+ bool case1(const mdbx::path &path) {
161
+ mdbx::env::operate_parameters operateParameters(100, 10);
162
+ operateParameters.options.no_sticky_threads = true;
163
+ operateParameters.options.nested_write_transactions = true;
164
+ mdbx::env_managed env(path, operateParameters);
165
+
166
+ //-------------------------------------
167
+ auto txn = env.start_write();
168
+ MDBX_txn *c_txn = txn;
169
+ int err = mdbx_txn_reset(txn);
170
+ assert(err == MDBX_EINVAL);
171
+ bool ok = err == MDBX_EINVAL;
172
+
173
+ err = mdbx_txn_break(txn);
174
+ assert(err == MDBX_SUCCESS);
175
+ ok = ok && err == MDBX_SUCCESS;
176
+
177
+ err = mdbx_txn_commit(txn);
178
+ assert(err == MDBX_RESULT_TRUE);
179
+ ok = ok && err == MDBX_RESULT_TRUE;
180
+
181
+ //-------------------------------------
182
+ err = mdbx_txn_begin(env, nullptr, MDBX_TXN_READWRITE, &c_txn);
183
+ assert(err == MDBX_SUCCESS);
184
+ ok = ok && err == MDBX_SUCCESS;
185
+ assert(c_txn == (const MDBX_txn *)txn);
186
+
187
+ err = mdbx_txn_break(txn);
188
+ assert(err == MDBX_SUCCESS);
189
+ ok = ok && err == MDBX_SUCCESS;
190
+
191
+ err = mdbx_txn_reset(txn);
192
+ assert(err == MDBX_EINVAL);
193
+ ok = ok && err == MDBX_EINVAL;
194
+
195
+ err = mdbx_txn_commit(txn);
196
+ assert(err == MDBX_RESULT_TRUE);
197
+ ok = ok && err == MDBX_RESULT_TRUE;
198
+
199
+ err = mdbx_txn_abort(c_txn);
200
+ assert(err == MDBX_BAD_TXN);
201
+ ok = ok && err == MDBX_BAD_TXN;
202
+ //-------------------------------------
203
+ err = mdbx_txn_begin(env, nullptr, MDBX_TXN_READWRITE, &c_txn);
204
+ assert(err == MDBX_SUCCESS);
205
+ ok = ok && err == MDBX_SUCCESS;
206
+ assert(c_txn == (const MDBX_txn *)txn);
207
+ txn.commit();
208
+
209
+ err = mdbx_txn_reset(c_txn);
210
+ assert(err == MDBX_BAD_TXN);
211
+ ok = ok && err == MDBX_BAD_TXN;
212
+ err = mdbx_txn_break(c_txn);
213
+ assert(err == MDBX_BAD_TXN);
214
+ ok = ok && err == MDBX_BAD_TXN;
215
+ err = mdbx_txn_abort(c_txn);
216
+ assert(err == MDBX_BAD_TXN);
217
+ ok = ok && err == MDBX_BAD_TXN;
218
+
219
+ //=====================================
220
+
221
+ txn = env.start_read();
222
+ err = mdbx_txn_begin(env, txn, MDBX_TXN_READWRITE, &c_txn);
223
+ assert(err == MDBX_BAD_TXN);
224
+ ok = ok && err == MDBX_BAD_TXN;
225
+ txn.make_broken();
226
+ err = mdbx_txn_begin(env, txn, MDBX_TXN_READWRITE, &c_txn);
227
+ assert(err == MDBX_BAD_TXN);
228
+ ok = ok && err == MDBX_BAD_TXN;
229
+ txn.reset_reading();
230
+ err = mdbx_txn_begin(env, txn, MDBX_TXN_READWRITE, &c_txn);
231
+ assert(err == MDBX_BAD_TXN);
232
+ ok = ok && err == MDBX_BAD_TXN;
233
+ txn.abort();
234
+
235
+ //-------------------------------------
236
+
237
+ txn = env.start_read();
238
+ txn.reset_reading();
239
+ txn.make_broken();
240
+ txn.abort();
241
+
242
+ //=====================================
243
+
244
+ std::latch s1(1), s2(1), s3(1);
245
+ txn = env.start_read();
246
+ c_txn = txn;
247
+
248
+ std::thread t([&]() {
249
+ s1.wait();
250
+ err = mdbx_txn_break(c_txn);
251
+ assert(err == MDBX_SUCCESS);
252
+ ok = ok && err == MDBX_SUCCESS;
253
+ err = mdbx_txn_reset(c_txn);
254
+ assert(err == MDBX_SUCCESS);
255
+ ok = ok && err == MDBX_SUCCESS;
256
+ txn.renew_reading();
257
+ s2.count_down();
258
+
259
+ s3.wait();
260
+ err = mdbx_txn_begin(env, txn, MDBX_TXN_READWRITE, &c_txn);
261
+ assert(err == MDBX_SUCCESS);
262
+ ok = ok && err == MDBX_SUCCESS;
263
+ err = mdbx_txn_commit(c_txn);
264
+ assert(err == MDBX_SUCCESS);
265
+ ok = ok && err == MDBX_SUCCESS;
266
+ c_txn = txn;
267
+ err = mdbx_txn_commit(c_txn);
268
+ assert(err == MDBX_THREAD_MISMATCH);
269
+ ok = ok && err == MDBX_THREAD_MISMATCH;
270
+ err = mdbx_txn_abort(c_txn);
271
+ assert(err == MDBX_THREAD_MISMATCH);
272
+ ok = ok && err == MDBX_THREAD_MISMATCH;
273
+ err = mdbx_txn_break(c_txn);
274
+ assert(err == MDBX_SUCCESS);
275
+ ok = ok && err == MDBX_SUCCESS;
276
+ err = mdbx_txn_reset(c_txn);
277
+ assert(err == MDBX_EINVAL);
278
+ ok = ok && err == MDBX_EINVAL;
279
+ });
280
+
281
+ s1.count_down();
282
+ s2.wait();
283
+ txn.commit();
284
+ txn = env.start_write();
285
+ s3.count_down();
286
+
287
+ t.join();
288
+ txn.abort();
289
+
290
+ return ok;
291
+ }
292
+
293
+ bool case2(const mdbx::path &path, bool no_sticky_threads) {
294
+ mdbx::env::operate_parameters operateParameters(100, 10);
295
+ operateParameters.options.no_sticky_threads = no_sticky_threads;
296
+ mdbx::env_managed env(path, operateParameters);
297
+
298
+ std::latch s(1);
299
+ std::vector<std::thread> l;
300
+ for (size_t n = 0; n < 8; ++n)
301
+ l.push_back(std::thread([&]() {
302
+ s.wait();
303
+ for (size_t i = 0; i < 1000000 / RELIEF_FACTOR; ++i) {
304
+ auto txn = env.start_read();
305
+ txn.abort();
306
+ }
307
+ }));
308
+
309
+ s.count_down();
310
+ for (auto &t : l)
311
+ t.join();
312
+
313
+ return true;
314
+ }
315
+
316
+ bool case3(const mdbx::path &path, bool no_sticky_threads) {
317
+ mdbx::env::remove(path);
318
+ mdbx::env_managed::create_parameters createParameters;
319
+ createParameters.geometry.make_dynamic(21 * mdbx::env::geometry::MiB, 84 * mdbx::env::geometry::MiB);
320
+ mdbx::env::operate_parameters operateParameters(100, 10);
321
+ operateParameters.options.no_sticky_threads = no_sticky_threads;
322
+ mdbx::env_managed env(path, createParameters, operateParameters);
323
+
324
+ mdbx::pair pair = {"key", "val"};
325
+ const auto N = std::thread::hardware_concurrency() * 2;
326
+ std::latch s0(N + 1), s1(N + 1), s2(N + 1);
327
+ std::vector<std::thread> l;
328
+
329
+ volatile bool ok = true;
330
+ for (size_t n = 0; n < N; ++n)
331
+ l.push_back(std::thread([&]() {
332
+ try {
333
+ s0.arrive_and_wait();
334
+ {
335
+ auto txn = env.start_read();
336
+ mdbx::slice value;
337
+ int err = mdbx_get(txn, 1, pair.key, &value);
338
+ if (err != MDBX_NOTFOUND) {
339
+ ok = false;
340
+ std::cerr << "Unexpected error " << err << "\n";
341
+ }
342
+ }
343
+
344
+ s1.arrive_and_wait();
345
+ s2.arrive_and_wait();
346
+ {
347
+ auto txn = env.start_read();
348
+ if (txn.get(1, pair.key) != pair.value)
349
+ ok = false;
350
+ }
351
+ } catch (const std::exception &ex) {
352
+ std::cerr << "Exception: " << ex.what() << "\n";
353
+ ok = false;
354
+ }
355
+ }));
356
+
357
+ s0.arrive_and_wait();
358
+ auto txn = env.start_write();
359
+ s1.arrive_and_wait();
360
+ txn.insert(1, pair);
361
+ txn.commit();
362
+ s2.arrive_and_wait();
363
+
364
+ for (auto &t : l)
365
+ t.join();
366
+
367
+ return ok;
368
+ }
369
+
370
+ int doit() {
371
+ mdbx::path path = "test-txn";
372
+ mdbx::env::remove(path);
373
+
374
+ bool ok = true;
375
+ ok = case0(path) && ok;
376
+ ok = case1(path) && ok;
377
+ ok = case2(path, false) && ok;
378
+ ok = case2(path, true) && ok;
379
+ ok = case3(path, false) && ok;
380
+ ok = case3(path, true) && ok;
381
+
382
+ std::cout << (ok ? "OK\n" : "FAIL\n");
383
+ return ok ? EXIT_SUCCESS : EXIT_FAILURE;
384
+ }
385
+
386
+ static char log_buffer[1024];
387
+
388
+ static void logger_nofmt(MDBX_log_level_t loglevel, const char *function, int line, const char *msg,
389
+ unsigned length) noexcept {
390
+ (void)length;
391
+ (void)loglevel;
392
+ fprintf(stdout, "%s:%u %s", function, line, msg);
393
+ }
394
+
395
+ int main(int argc, char *argv[]) {
396
+ (void)argc;
397
+ (void)argv;
398
+ mdbx_setup_debug_nofmt(MDBX_LOG_VERBOSE, MDBX_DBG_ASSERT, logger_nofmt, log_buffer, sizeof(log_buffer));
399
+ try {
400
+ return doit();
401
+ } catch (const std::exception &ex) {
402
+ std::cerr << "Exception: " << ex.what() << "\n";
403
+ return EXIT_FAILURE;
404
+ }
405
+ }
406
+
407
+ #endif /* __cpp_lib_latch */
@@ -0,0 +1,193 @@
1
+ //
2
+ // libmdbx/test/extra/upsert_alldups.c
3
+ //
4
+ // Created by Masatoshi Fukunaga <https://gitflic.ru/user/mah0x211>
5
+ // on 2023-01-31.
6
+ //
7
+
8
+ #include "mdbx.h"
9
+ #include <stdio.h>
10
+ #include <stdlib.h>
11
+ #include <string.h>
12
+ #include <unistd.h>
13
+
14
+ static int dump(MDBX_cursor *cur) {
15
+ MDBX_val key = {NULL, 0};
16
+ MDBX_val data = {NULL, 0};
17
+ int rc = mdbx_cursor_get(cur, &key, &data, MDBX_FIRST);
18
+
19
+ while (rc == 0) {
20
+ printf("(%.*s) = (%.*s)\n", (int)key.iov_len, (const char *)key.iov_base, (int)data.iov_len,
21
+ (const char *)data.iov_base);
22
+ rc = mdbx_cursor_get(cur, &key, &data, MDBX_NEXT);
23
+ }
24
+ return rc;
25
+ }
26
+
27
+ static int clear(MDBX_cursor *cur) {
28
+ MDBX_val key = {NULL, 0};
29
+ MDBX_val data = {NULL, 0};
30
+ int rc = mdbx_cursor_get(cur, &key, &data, MDBX_FIRST);
31
+
32
+ while (rc == 0) {
33
+ rc = mdbx_cursor_del(cur, MDBX_ALLDUPS);
34
+ if (rc)
35
+ return rc;
36
+ rc = mdbx_cursor_get(cur, &key, &data, MDBX_NEXT);
37
+ }
38
+ return (rc == MDBX_NOTFOUND) ? 0 : rc;
39
+ }
40
+
41
+ static int put(MDBX_txn *txn, MDBX_dbi dbi, const char *k, const char *v, MDBX_put_flags_t flags) {
42
+ MDBX_val key = {.iov_base = (void *)k, .iov_len = strlen(k)};
43
+ MDBX_val data = {.iov_base = (void *)v, .iov_len = strlen(v)};
44
+ return mdbx_put(txn, dbi, &key, &data, flags);
45
+ }
46
+
47
+ int main(int argc, const char *argv[]) {
48
+ (void)argc;
49
+ (void)argv;
50
+ char *errmsg = NULL;
51
+ MDBX_env *env = NULL;
52
+ MDBX_txn *txn = NULL;
53
+ MDBX_cursor *cur = NULL;
54
+ MDBX_dbi dbi = 0;
55
+
56
+ unlink("." MDBX_DATANAME);
57
+ unlink("." MDBX_LOCKNAME);
58
+
59
+ int rc = 0;
60
+ if ((rc = mdbx_env_create(&env))) {
61
+ errmsg = "failed to mdbx_env_create: %s\n";
62
+ goto Fail;
63
+ }
64
+ if ((rc = mdbx_env_open(env, ".", MDBX_NOSUBDIR | MDBX_LIFORECLAIM, 0644))) {
65
+ errmsg = "failed to mdbx_env_open: %s\n";
66
+ goto Fail;
67
+ }
68
+ if ((rc = mdbx_txn_begin(env, NULL, 0, &txn))) {
69
+ errmsg = "failed to mdbx_txn_begin: %s\n";
70
+ goto Fail;
71
+ }
72
+ if ((rc = mdbx_dbi_open(txn, NULL, MDBX_DUPSORT | MDBX_CREATE, &dbi))) {
73
+ errmsg = "failed to mdbx_dbi_open: %s\n";
74
+ goto Fail;
75
+ }
76
+ if ((rc = mdbx_cursor_open(txn, dbi, &cur))) {
77
+ errmsg = "failed to mdbx_cursor_open: %s\n";
78
+ goto Fail;
79
+ }
80
+
81
+ #define DUMP() \
82
+ do { \
83
+ if ((rc = dump(cur)) && rc != MDBX_NOTFOUND) { \
84
+ errmsg = "failed to mdbx_cursor_get(FIRST): %s\n"; \
85
+ goto Fail; \
86
+ } \
87
+ puts(""); \
88
+ } while (0)
89
+
90
+ #define PUTVAL(k, v, flags) \
91
+ do { \
92
+ if ((rc = put(txn, dbi, k, v, flags))) { \
93
+ errmsg = "failed to mdbx_put: %s\n"; \
94
+ goto Fail; \
95
+ } \
96
+ } while (0)
97
+
98
+ puts("TEST WITH MULTIPLE KEYS ====================");
99
+ // UPSERTING
100
+ // MDBX_UPSERT:
101
+ // Key is absent → Insertion (Insertion)
102
+ // Key exist → Wanna to add new values (Overwrite by single new value)
103
+ puts("insert multiple keys and values {");
104
+ puts(" foo = bar, baz, qux");
105
+ puts(" hello = world");
106
+ puts("}");
107
+ PUTVAL("foo", "bar", MDBX_UPSERT);
108
+ PUTVAL("foo", "baz", MDBX_UPSERT);
109
+ PUTVAL("foo", "qux", MDBX_UPSERT);
110
+ PUTVAL("hello", "world", MDBX_UPSERT);
111
+ DUMP();
112
+ //
113
+ // above code will output the fllowing;
114
+ //
115
+ // insert multiple values {
116
+ // foo = bar, baz, qux
117
+ // hello = world
118
+ // }
119
+ // (foo) = (bar)
120
+ // (foo) = (baz)
121
+ // (foo) = (qux)
122
+ // (hello) = (world)
123
+ //
124
+
125
+ // UPSERTING
126
+ // MDBX_UPSERT + MDBX_ALLDUPS:
127
+ // Key exist → Replace all values with a new one (Overwrite by single new
128
+ // value)
129
+ puts("overwrite by single new value: MDBX_UPSERT + MDBX_ALLDUPS {");
130
+ puts(" foo = baa");
131
+ puts("}");
132
+ PUTVAL("foo", "baa", MDBX_UPSERT | MDBX_ALLDUPS);
133
+ DUMP();
134
+ // above code will output the fllowing;
135
+ // overwrite by single new value {
136
+ // foo = baa
137
+ // }
138
+ // (foo) = (baa)
139
+ // (hello) = (world)
140
+ if ((rc = clear(cur))) {
141
+ errmsg = "failed to clear: %s\n";
142
+ goto Fail;
143
+ }
144
+ DUMP();
145
+
146
+ puts("TEST WITH A SINGLE KEY ====================");
147
+ // UPSERTING
148
+ // MDBX_UPSERT:
149
+ // Key is absent → Insertion (Insertion)
150
+ // Key exist → Wanna to add new values (Overwrite by single new value)
151
+ puts("insert single key and multiple values {");
152
+ puts(" foo = bar, baz, qux");
153
+ puts("}");
154
+ PUTVAL("foo", "bar", MDBX_UPSERT);
155
+ PUTVAL("foo", "baz", MDBX_UPSERT);
156
+ PUTVAL("foo", "qux", MDBX_UPSERT);
157
+ DUMP();
158
+ //
159
+ // above code will output the fllowing;
160
+ //
161
+ // insert: foo = bar, baz, qux
162
+ // foo = bar
163
+ // foo = baz
164
+ // foo = qux
165
+
166
+ // UPSERTING
167
+ // MDBX_UPSERT + MDBX_ALLDUPS:
168
+ // Key exist → Replace all values with a new one (Overwrite by single new
169
+ // value)
170
+ puts("overwrite by single new value: MDBX_UPSERT + MDBX_ALLDUPS {");
171
+ puts(" foo = baa");
172
+ puts("}");
173
+ PUTVAL("foo", "baa", MDBX_UPSERT | MDBX_ALLDUPS);
174
+ DUMP();
175
+ // above code outputs nothing.
176
+ // all data associated with key has been deleted.
177
+ // Is it a bug? Or, am I misunderstanding how to use it?
178
+
179
+ if ((rc = mdbx_txn_commit(txn))) {
180
+ errmsg = "failed to mdbx_txn_commit: %s\n";
181
+ goto Fail;
182
+ }
183
+ mdbx_cursor_close(cur);
184
+ if ((rc = mdbx_env_close(env))) {
185
+ errmsg = "failed to mdbx_env_close: %s\n";
186
+ goto Fail;
187
+ }
188
+ return 0;
189
+
190
+ Fail:
191
+ printf(errmsg, mdbx_strerror(rc));
192
+ return EXIT_FAILURE;
193
+ }