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,409 @@
1
+ #include "mdbx.h++"
2
+
3
+ #include <array>
4
+ #include <iostream>
5
+ #include <random>
6
+ #include <vector>
7
+
8
+ #if defined(ENABLE_MEMCHECK) || defined(MDBX_CI)
9
+ #if MDBX_DEBUG || !defined(NDEBUG)
10
+ #define RELIEF_FACTOR 16
11
+ #else
12
+ #define RELIEF_FACTOR 8
13
+ #endif
14
+ #elif MDBX_DEBUG || !defined(NDEBUG) || defined(__APPLE__) || defined(_WIN32)
15
+ #define RELIEF_FACTOR 4
16
+ #elif UINTPTR_MAX > 0xffffFFFFul || ULONG_MAX > 0xffffFFFFul
17
+ #define RELIEF_FACTOR 2
18
+ #else
19
+ #define RELIEF_FACTOR 1
20
+ #endif
21
+
22
+ #define NN (2048 / RELIEF_FACTOR)
23
+
24
+ std::string format_va(const char *fmt, va_list ap) {
25
+ va_list ones;
26
+ va_copy(ones, ap);
27
+ #ifdef _MSC_VER
28
+ int needed = _vscprintf(fmt, ap);
29
+ #else
30
+ int needed = vsnprintf(nullptr, 0, fmt, ap);
31
+ #endif
32
+ assert(needed >= 0);
33
+ std::string result;
34
+ result.reserve(size_t(needed + 1));
35
+ result.resize(size_t(needed), '\0');
36
+ assert(int(result.capacity()) > needed);
37
+ int actual = vsnprintf(const_cast<char *>(result.data()), result.capacity(), fmt, ones);
38
+ assert(actual == needed);
39
+ (void)actual;
40
+ va_end(ones);
41
+ return result;
42
+ }
43
+
44
+ std::string format(const char *fmt, ...) {
45
+ va_list ap;
46
+ va_start(ap, fmt);
47
+ std::string result = format_va(fmt, ap);
48
+ va_end(ap);
49
+ return result;
50
+ }
51
+
52
+ struct acase {
53
+ unsigned klen_min, klen_max;
54
+ unsigned vlen_min, vlen_max;
55
+ unsigned dupmax_log2;
56
+
57
+ acase(unsigned klen_min, unsigned klen_max, unsigned vlen_min, unsigned vlen_max, unsigned dupmax_log2)
58
+ : klen_min(klen_min), klen_max(klen_max), vlen_min(vlen_min), vlen_max(vlen_max), dupmax_log2(dupmax_log2) {}
59
+ };
60
+
61
+ // std::random_device rd;
62
+ std::mt19937_64 rnd;
63
+
64
+ static unsigned prng_fast(uint32_t &seed) {
65
+ seed = seed * 1103515245 + 12345;
66
+ return seed >> 17;
67
+ }
68
+
69
+ static mdbx::slice mk(mdbx::default_buffer &buf, unsigned min, unsigned max) {
70
+ uint32_t seed = rnd() % (NN + NN);
71
+ unsigned len = (min < max) ? min + prng_fast(seed) % (max - min) : min;
72
+ buf.clear_and_reserve(len);
73
+ for (unsigned i = 0; i < len; ++i)
74
+ buf.append_byte(mdbx::byte(prng_fast(seed)));
75
+ return buf.slice();
76
+ }
77
+
78
+ static mdbx::slice mk_key(mdbx::default_buffer &buf, const acase &thecase) {
79
+ return mk(buf, thecase.klen_min, thecase.klen_max);
80
+ }
81
+
82
+ static mdbx::slice mk_val(mdbx::default_buffer &buf, const acase &thecase) {
83
+ return mk(buf, thecase.vlen_min, thecase.vlen_max);
84
+ }
85
+
86
+ static std::string name(unsigned n) { return format("Commitment_%05u", n); }
87
+
88
+ static mdbx::map_handle create_and_fill(mdbx::txn txn, const acase &thecase, const unsigned n) {
89
+ auto map = txn.create_map(name(n),
90
+ (thecase.klen_min == thecase.klen_max && (thecase.klen_min == 4 || thecase.klen_max == 8))
91
+ ? mdbx::key_mode::ordinal
92
+ : mdbx::key_mode::usual,
93
+ (thecase.vlen_min == thecase.vlen_max) ? mdbx::value_mode::multi_samelength
94
+ : mdbx::value_mode::multi);
95
+
96
+ if (txn.get_map_stat(map).ms_entries < NN) {
97
+ mdbx::default_buffer k, v;
98
+ for (auto i = 0u; i < NN; i++) {
99
+ mk_key(k, thecase);
100
+ for (auto ii = thecase.dupmax_log2 ? 1u + (rnd() & ((2u << thecase.dupmax_log2) - 1u)) : 1u; ii > 0; --ii)
101
+ txn.upsert(map, k, mk_val(v, thecase));
102
+ }
103
+ }
104
+ return map;
105
+ }
106
+
107
+ static void chunched_delete(mdbx::txn txn, const acase &thecase, const unsigned n) {
108
+ // printf(">> %s, case #%i\n", __FUNCTION__, n);
109
+ mdbx::default_buffer k, v;
110
+ auto map = txn.open_map_accede(name(n));
111
+
112
+ {
113
+ auto cursor = txn.open_cursor(map);
114
+ while (true) {
115
+ const auto all = cursor.txn().get_map_stat(cursor.map()).ms_entries;
116
+ // printf("== seek random of %u\n", all);
117
+
118
+ const char *last_op;
119
+ bool last_r;
120
+
121
+ if (true == ((last_op = "MDBX_GET_BOTH"),
122
+ (last_r = cursor.find_multivalue(mk_key(k, thecase), mk_val(v, thecase), false))) ||
123
+ rnd() % 3 == 0 ||
124
+ true == ((last_op = "MDBX_SET_RANGE"), (last_r = cursor.lower_bound(mk_key(k, thecase), false)))) {
125
+ int i = int(rnd() % 7) - 3;
126
+ // if (i)
127
+ // printf(" %s -> %s\n", last_op, last_r ? "true" : "false");
128
+ // printf("== shift multi %i\n", i);
129
+ try {
130
+ while (i < 0 && true == ((last_op = "MDBX_PREV_DUP"), (last_r = cursor.to_current_prev_multi(false))))
131
+ ++i;
132
+ while (i > 0 && true == ((last_op = "MDBX_NEXT_DUP"), (last_r = cursor.to_current_next_multi(false))))
133
+ --i;
134
+ } catch (const mdbx::no_data &) {
135
+ printf("cursor_del() -> exception, last %s %s\n", last_op, last_r ? "true" : "false");
136
+ continue;
137
+ }
138
+ }
139
+ // printf(" %s -> %s\n", last_op, last_r ? "true" : "false");
140
+
141
+ if (all < 42) {
142
+ // printf("== erase-tail\n");
143
+ break;
144
+ }
145
+ auto i = all % 17 + 1;
146
+ try {
147
+ last_r = cursor.erase();
148
+ do {
149
+ // printf("== erase-chunk: %u\n", i);
150
+ // printf(" cursor_del() -> %s\n", last_r ? "true" : "false");
151
+ } while (cursor.to_next(false) && --i > 0);
152
+ } catch (const mdbx::no_data &) {
153
+ printf("cursor_del() -> exception, last %s %s\n", last_op, last_r ? "true" : "false");
154
+ }
155
+
156
+ // (void) last_op;
157
+ // (void) last_r;
158
+ }
159
+
160
+ if (cursor.to_first(false))
161
+ do
162
+ cursor.erase();
163
+ while (cursor.to_next(false));
164
+ }
165
+
166
+ // printf("<< %s, case #%i\n", __FUNCTION__, n);
167
+ }
168
+
169
+ static char log_buffer[1024];
170
+
171
+ static void logger_nofmt(MDBX_log_level_t loglevel, const char *function, int line, const char *msg,
172
+ unsigned length) noexcept {
173
+ (void)length;
174
+ (void)loglevel;
175
+ fprintf(stdout, "%s:%u %s", function, line, msg);
176
+ }
177
+
178
+ bool outofrange_prev(mdbx::env env) {
179
+ mdbx::cursor_managed cursor;
180
+ const std::array<mdbx::pair, 4> items = {{{"k1", "v1"}, {"k1", "v2"}, {"k2", "v1"}, {"k2", "v2"}}};
181
+
182
+ auto txn = env.start_write();
183
+ auto multi = txn.create_map("multi", mdbx::key_mode::usual, mdbx::value_mode::multi);
184
+ auto simple = txn.create_map("simple");
185
+ txn.clear_map(multi);
186
+ txn.clear_map(simple);
187
+
188
+ txn.insert(simple, items[0]);
189
+ txn.insert(simple, items[3]);
190
+ cursor.bind(txn, simple);
191
+ const auto simple_oor = cursor.lower_bound("k3");
192
+ if (simple_oor) {
193
+ std::cerr << "simple-outofrange " << simple_oor << "\n";
194
+ return false;
195
+ }
196
+ const auto simple_oor_prevdup = cursor.to_current_prev_multi(false);
197
+ if (simple_oor_prevdup) {
198
+ std::cerr << "simple-outofrange-prevdup " << simple_oor_prevdup << "\n";
199
+ return false;
200
+ }
201
+ const auto simple_oor_prev = cursor.to_previous(false);
202
+ if (!simple_oor_prev || simple_oor_prev != items[3]) {
203
+ std::cerr << "simple-outofrange-prev " << simple_oor_prev << "\n";
204
+ return false;
205
+ }
206
+
207
+ txn.append(multi, items[0]);
208
+ txn.append(multi, items[1]);
209
+ txn.append(multi, items[2]);
210
+ txn.append(multi, items[3]);
211
+ cursor.bind(txn, multi);
212
+ const auto multi_oor = cursor.lower_bound("k3");
213
+ if (multi_oor) {
214
+ std::cerr << "multi-outofrange " << multi_oor << "\n";
215
+ return false;
216
+ }
217
+ const auto multi_oor_prevdup = cursor.to_current_prev_multi(false);
218
+ if (multi_oor_prevdup) {
219
+ std::cerr << "multi-outofrange-prevdup " << multi_oor_prevdup << "\n";
220
+ return false;
221
+ }
222
+ const auto multi_oor_prev = cursor.to_previous(false);
223
+ if (!multi_oor_prev || multi_oor_prev != items[3]) {
224
+ std::cerr << "multi-outofrange-prev " << multi_oor_prev << "\n";
225
+ return false;
226
+ }
227
+
228
+ txn.commit();
229
+ return true;
230
+ }
231
+
232
+ bool next_prev_current(mdbx::env env) {
233
+ const std::array<mdbx::pair, 4> items = {{{"k1", "v1"}, {"k1", "v2"}, {"k2", "v1"}, {"k2", "v2"}}};
234
+
235
+ auto txn = env.start_write();
236
+ auto map = txn.create_map("multi", mdbx::key_mode::usual, mdbx::value_mode::multi);
237
+ txn.clear_map(map);
238
+ for (const auto &i : items)
239
+ txn.upsert(map, i);
240
+
241
+ auto cursor = txn.open_cursor(map);
242
+ const auto first = cursor.to_first(false);
243
+ if (!first || first != items[0]) {
244
+ std::cerr << "bad-first " << first << "\n";
245
+ return false;
246
+ }
247
+ const auto next1 = cursor.to_next(false);
248
+ if (!next1 || next1 != items[1]) {
249
+ std::cerr << "bad-next-1 " << next1 << "\n";
250
+ return false;
251
+ }
252
+ const auto next2 = cursor.to_next(false);
253
+ if (!next2 || next2 != items[2]) {
254
+ std::cerr << "bad-next-2 " << next2 << "\n";
255
+ return false;
256
+ }
257
+ const auto prev1 = cursor.to_previous(false);
258
+ if (!prev1 || prev1 != items[1]) {
259
+ std::cerr << "bad-prev-1 " << prev1 << "\n";
260
+ return false;
261
+ }
262
+ const auto prev2 = cursor.to_previous(false);
263
+ if (!prev2 || prev2 != items[0]) {
264
+ std::cerr << "bad-prev-2 " << prev2 << "\n";
265
+ return false;
266
+ }
267
+
268
+ if (!cursor.erase(false)) {
269
+ std::cerr << "bad-erase\n";
270
+ return false;
271
+ }
272
+
273
+ const auto after_del = cursor.current(false);
274
+ if (!after_del || after_del != items[1]) {
275
+ std::cerr << "bad-after-del, current " << after_del << "\n";
276
+ return false;
277
+ }
278
+ const auto next_after_del1 = cursor.to_next(false);
279
+ if (!next_after_del1 || next_after_del1 != items[2]) {
280
+ std::cerr << "bad-next_after_del1 " << next_after_del1;
281
+ return false;
282
+ }
283
+ const auto next_after_del2 = cursor.to_next(false);
284
+ if (!next_after_del2 || next_after_del2 != items[3]) {
285
+ std::cerr << "bad-next_after_del2 " << next_after_del2;
286
+ return false;
287
+ }
288
+ const auto next_after_del3 = cursor.to_next(false);
289
+ if (next_after_del3) {
290
+ std::cerr << "bad-next_after_del3 " << next_after_del3;
291
+ return false;
292
+ }
293
+ txn.commit();
294
+ return true;
295
+ }
296
+
297
+ bool simple(mdbx::env env) {
298
+ const std::array<mdbx::pair, 3> items = {{{"k0", "v0"}, {"k1", "v1"}, {"k2", "v2"}}};
299
+
300
+ auto txn = env.start_write();
301
+ auto map = txn.create_map("simple");
302
+ txn.clear_map(map);
303
+ for (const auto &i : items)
304
+ txn.insert(map, i);
305
+
306
+ auto cursor = txn.open_cursor(map);
307
+ cursor.seek(items[1].key);
308
+
309
+ const auto seek = cursor.current(false);
310
+ if (seek != items[1]) {
311
+ std::cerr << "bad-seek, current " << seek << "\n";
312
+ return false;
313
+ }
314
+ if (!cursor.erase()) {
315
+ std::cerr << "bad-erase\n";
316
+ return false;
317
+ }
318
+
319
+ const auto next = cursor.to_next(false);
320
+ if (!next || next != items[2]) {
321
+ std::cerr << "bad-next " << next;
322
+ return false;
323
+ }
324
+
325
+ const auto after_del = cursor.current(false);
326
+ if (!after_del || after_del != items[2]) {
327
+ std::cerr << "bad-after-del, current " << after_del << "\n";
328
+ return false;
329
+ }
330
+ txn.commit();
331
+
332
+ txn = env.start_read();
333
+ cursor.bind(txn, map);
334
+
335
+ #define BAD_CODE 1
336
+ #if BAD_CODE
337
+ const auto first = cursor.to_next(false);
338
+ #else
339
+ const auto first = cursor.to_first(false);
340
+ #endif
341
+ const auto second = cursor.to_next(false);
342
+ const auto eof = cursor.to_next(false);
343
+
344
+ if (!first || first != items[0]) {
345
+ std::cerr << "bad-first " << first << "\n";
346
+ return false;
347
+ }
348
+ if (!second || second != items[2]) {
349
+ std::cerr << "bad-second " << second << "\n";
350
+ return false;
351
+ }
352
+ if (eof) {
353
+ std::cerr << "bad-eof " << eof << "\n";
354
+ return false;
355
+ }
356
+
357
+ return true;
358
+ }
359
+
360
+ int doit() {
361
+ mdbx::path db_filename = "test-crunched-del";
362
+ mdbx::env::remove(db_filename);
363
+
364
+ mdbx::env_managed env(db_filename, mdbx::env_managed::create_parameters(), mdbx::env::operate_parameters(42));
365
+ if (!simple(env) || !next_prev_current(env) || !outofrange_prev(env))
366
+ return EXIT_FAILURE;
367
+
368
+ std::vector<acase> testset;
369
+ // Там ключи разной длины - от 1 до 64 байт.
370
+ // Значения разной длины от 100 до 1000 байт.
371
+ testset.emplace_back(/* keylen_min */ 1, /* keylen_max */ 64,
372
+ /* datalen_min */ 100, /* datalen_max */
373
+ mdbx_env_get_valsize4page_max(env, MDBX_db_flags_t(mdbx::value_mode::multi)),
374
+ /* dups_log2 */ 6);
375
+ // В одной таблице DupSort: path -> version_u64+data
376
+ // path - это префикс в дереве. Самые частые длины: 1-5 байт и 32-36 байт.
377
+ testset.emplace_back(1, 5, 100, 1000, 8);
378
+ testset.emplace_back(32, 36, 100, 1000, 7);
379
+ // В другой DupSort: timestamp_u64 -> path
380
+ testset.emplace_back(8, 8, 1, 5, 10);
381
+ testset.emplace_back(8, 8, 32, 36, 9);
382
+
383
+ auto txn = env.start_write();
384
+ for (unsigned i = 0; i < testset.size(); ++i)
385
+ create_and_fill(txn, testset[i], i);
386
+ txn.commit();
387
+
388
+ // mdbx_setup_debug_nofmt(MDBX_LOG_TRACE, MDBX_DBG_AUDIT | MDBX_DBG_ASSERT,
389
+ // logger_nofmt, log_buffer, sizeof(log_buffer));
390
+ txn = env.start_write();
391
+ for (unsigned i = 0; i < testset.size(); ++i)
392
+ chunched_delete(txn, testset[i], i);
393
+ txn.commit();
394
+
395
+ std::cout << "OK\n";
396
+ return EXIT_SUCCESS;
397
+ }
398
+
399
+ int main(int argc, char *argv[]) {
400
+ (void)argc;
401
+ (void)argv;
402
+ mdbx_setup_debug_nofmt(MDBX_LOG_NOTICE, MDBX_DBG_ASSERT, logger_nofmt, log_buffer, sizeof(log_buffer));
403
+ try {
404
+ return doit();
405
+ } catch (const std::exception &ex) {
406
+ std::cerr << "Exception: " << ex.what() << "\n";
407
+ return EXIT_FAILURE;
408
+ }
409
+ }