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,515 @@
1
+ /// \copyright SPDX-License-Identifier: Apache-2.0
2
+ /// \note Please refer to the COPYRIGHT file for explanations license change,
3
+ /// credits and acknowledgments.
4
+ /// \author Леонид Юрьев aka Leonid Yuriev <leo@yuriev.ru> \date 2015-2025
5
+ ///
6
+ /// mdbx_dump.c - memory-mapped database dump tool
7
+ ///
8
+
9
+ #ifdef _MSC_VER
10
+ #if _MSC_VER > 1800
11
+ #pragma warning(disable : 4464) /* relative include path contains '..' */
12
+ #endif
13
+ #pragma warning(disable : 4996) /* The POSIX name is deprecated... */
14
+ #endif /* _MSC_VER (warnings) */
15
+
16
+ #define xMDBX_TOOLS /* Avoid using internal eASSERT() */
17
+ #include "essentials.h"
18
+
19
+ #include <ctype.h>
20
+
21
+ #define PRINT 1
22
+ #define GLOBAL 2
23
+ static int mode = GLOBAL;
24
+
25
+ typedef struct flagbit {
26
+ int bit;
27
+ char *name;
28
+ } flagbit;
29
+
30
+ flagbit dbflags[] = {{MDBX_REVERSEKEY, "reversekey"},
31
+ {MDBX_DUPSORT, "dupsort"},
32
+ {MDBX_INTEGERKEY, "integerkey"},
33
+ {MDBX_DUPFIXED, "dupfix"},
34
+ {MDBX_INTEGERDUP, "integerdup"},
35
+ {MDBX_REVERSEDUP, "reversedup"},
36
+ {0, nullptr}};
37
+
38
+ #if defined(_WIN32) || defined(_WIN64)
39
+ #include "wingetopt.h"
40
+
41
+ static volatile BOOL user_break;
42
+ static BOOL WINAPI ConsoleBreakHandlerRoutine(DWORD dwCtrlType) {
43
+ (void)dwCtrlType;
44
+ user_break = true;
45
+ return true;
46
+ }
47
+
48
+ #else /* WINDOWS */
49
+
50
+ static volatile sig_atomic_t user_break;
51
+ static void signal_handler(int sig) {
52
+ (void)sig;
53
+ user_break = 1;
54
+ }
55
+
56
+ #endif /* !WINDOWS */
57
+
58
+ static const char hexc[] = "0123456789abcdef";
59
+
60
+ static void dumpbyte(unsigned char c) {
61
+ putchar(hexc[c >> 4]);
62
+ putchar(hexc[c & 15]);
63
+ }
64
+
65
+ static void text(MDBX_val *v) {
66
+ unsigned char *c, *end;
67
+
68
+ putchar(' ');
69
+ c = v->iov_base;
70
+ end = c + v->iov_len;
71
+ while (c < end) {
72
+ if (isprint(*c) && *c != '\\') {
73
+ putchar(*c);
74
+ } else {
75
+ putchar('\\');
76
+ dumpbyte(*c);
77
+ }
78
+ c++;
79
+ }
80
+ putchar('\n');
81
+ }
82
+
83
+ static void dumpval(MDBX_val *v) {
84
+ unsigned char *c, *end;
85
+
86
+ putchar(' ');
87
+ c = v->iov_base;
88
+ end = c + v->iov_len;
89
+ while (c < end)
90
+ dumpbyte(*c++);
91
+ putchar('\n');
92
+ }
93
+
94
+ bool quiet = false, rescue = false;
95
+ const char *prog;
96
+ static void error(const char *func, int rc) {
97
+ if (!quiet)
98
+ fprintf(stderr, "%s: %s() error %d %s\n", prog, func, rc, mdbx_strerror(rc));
99
+ }
100
+
101
+ /* Dump in BDB-compatible format */
102
+ static int dump_tbl(MDBX_txn *txn, MDBX_dbi dbi, char *name) {
103
+ unsigned flags;
104
+ int rc = mdbx_dbi_flags(txn, dbi, &flags);
105
+ if (unlikely(rc != MDBX_SUCCESS)) {
106
+ error("mdbx_dbi_flags", rc);
107
+ return rc;
108
+ }
109
+
110
+ MDBX_stat ms;
111
+ rc = mdbx_dbi_stat(txn, dbi, &ms, sizeof(ms));
112
+ if (unlikely(rc != MDBX_SUCCESS)) {
113
+ error("mdbx_dbi_stat", rc);
114
+ return rc;
115
+ }
116
+
117
+ MDBX_envinfo info;
118
+ rc = mdbx_env_info_ex(mdbx_txn_env(txn), txn, &info, sizeof(info));
119
+ if (unlikely(rc != MDBX_SUCCESS)) {
120
+ error("mdbx_env_info_ex", rc);
121
+ return rc;
122
+ }
123
+
124
+ printf("VERSION=3\n");
125
+ if (mode & GLOBAL) {
126
+ mode -= GLOBAL;
127
+ if (info.mi_geo.upper != info.mi_geo.lower)
128
+ printf("geometry=l%" PRIu64 ",c%" PRIu64 ",u%" PRIu64 ",s%" PRIu64 ",g%" PRIu64 "\n", info.mi_geo.lower,
129
+ info.mi_geo.current, info.mi_geo.upper, info.mi_geo.shrink, info.mi_geo.grow);
130
+ printf("mapsize=%" PRIu64 "\n", info.mi_geo.upper);
131
+ printf("maxreaders=%u\n", info.mi_maxreaders);
132
+
133
+ MDBX_canary canary;
134
+ rc = mdbx_canary_get(txn, &canary);
135
+ if (unlikely(rc != MDBX_SUCCESS)) {
136
+ error("mdbx_canary_get", rc);
137
+ return rc;
138
+ }
139
+ if (canary.v)
140
+ printf("canary=v%" PRIu64 ",x%" PRIu64 ",y%" PRIu64 ",z%" PRIu64 "\n", canary.v, canary.x, canary.y, canary.z);
141
+ }
142
+ printf("format=%s\n", mode & PRINT ? "print" : "bytevalue");
143
+ if (name)
144
+ printf("database=%s\n", name);
145
+ printf("type=btree\n");
146
+ printf("db_pagesize=%u\n", ms.ms_psize);
147
+ /* if (ms.ms_mod_txnid)
148
+ printf("txnid=%" PRIaTXN "\n", ms.ms_mod_txnid);
149
+ else if (!name)
150
+ printf("txnid=%" PRIaTXN "\n", mdbx_txn_id(txn)); */
151
+
152
+ printf("duplicates=%d\n", (flags & (MDBX_DUPSORT | MDBX_DUPFIXED | MDBX_INTEGERDUP | MDBX_REVERSEDUP)) ? 1 : 0);
153
+ for (int i = 0; dbflags[i].bit; i++)
154
+ if (flags & dbflags[i].bit)
155
+ printf("%s=1\n", dbflags[i].name);
156
+
157
+ uint64_t sequence;
158
+ rc = mdbx_dbi_sequence(txn, dbi, &sequence, 0);
159
+ if (unlikely(rc != MDBX_SUCCESS)) {
160
+ error("mdbx_dbi_sequence", rc);
161
+ return rc;
162
+ }
163
+ if (sequence)
164
+ printf("sequence=%" PRIu64 "\n", sequence);
165
+
166
+ printf("HEADER=END\n"); /*-------------------------------------------------*/
167
+
168
+ MDBX_cursor *cursor;
169
+ MDBX_val key, data;
170
+ rc = mdbx_cursor_open(txn, dbi, &cursor);
171
+ if (unlikely(rc != MDBX_SUCCESS)) {
172
+ error("mdbx_cursor_open", rc);
173
+ return rc;
174
+ }
175
+ if (rescue) {
176
+ rc = mdbx_cursor_ignord(cursor);
177
+ if (unlikely(rc != MDBX_SUCCESS)) {
178
+ error("mdbx_cursor_ignord", rc);
179
+ return rc;
180
+ }
181
+ }
182
+
183
+ while ((rc = mdbx_cursor_get(cursor, &key, &data, MDBX_NEXT)) == MDBX_SUCCESS) {
184
+ if (user_break) {
185
+ rc = MDBX_EINTR;
186
+ break;
187
+ }
188
+ if (mode & PRINT) {
189
+ text(&key);
190
+ text(&data);
191
+ } else {
192
+ dumpval(&key);
193
+ dumpval(&data);
194
+ }
195
+ }
196
+ printf("DATA=END\n");
197
+ if (rc == MDBX_NOTFOUND)
198
+ rc = MDBX_SUCCESS;
199
+ if (unlikely(rc != MDBX_SUCCESS))
200
+ error("mdbx_cursor_get", rc);
201
+
202
+ mdbx_cursor_close(cursor);
203
+ return rc;
204
+ }
205
+
206
+ static void usage(void) {
207
+ fprintf(stderr,
208
+ "usage: %s "
209
+ "[-V] [-q] [-f file] [-l] [-p] [-r] [-a|-s table] [-u|U] "
210
+ "dbpath\n"
211
+ " -V\t\tprint version and exit\n"
212
+ " -q\t\tbe quiet\n"
213
+ " -f\t\twrite to file instead of stdout\n"
214
+ " -l\t\tlist tables and exit\n"
215
+ " -p\t\tuse printable characters\n"
216
+ " -r\t\trescue mode (ignore errors to dump corrupted DB)\n"
217
+ " -a\t\tdump main DB and all tables\n"
218
+ " -s name\tdump only the specified named table\n"
219
+ " -u\t\twarmup database before dumping\n"
220
+ " -U\t\twarmup and try lock database pages in memory before dumping\n"
221
+ " \t\tby default dump only the main DB\n",
222
+ prog);
223
+ exit(EXIT_FAILURE);
224
+ }
225
+
226
+ static void logger(MDBX_log_level_t level, const char *function, int line, const char *fmt, va_list args) {
227
+ static const char *const prefixes[] = {
228
+ "!!!fatal: ", // 0 fatal
229
+ " ! ", // 1 error
230
+ " ~ ", // 2 warning
231
+ " ", // 3 notice
232
+ " //", // 4 verbose
233
+ };
234
+ if (level < MDBX_LOG_DEBUG) {
235
+ if (function && line)
236
+ fprintf(stderr, "%s", prefixes[level]);
237
+ vfprintf(stderr, fmt, args);
238
+ }
239
+ }
240
+
241
+ static int equal_or_greater(const MDBX_val *a, const MDBX_val *b) {
242
+ return (a->iov_len == b->iov_len && memcmp(a->iov_base, b->iov_base, a->iov_len) == 0) ? 0 : 1;
243
+ }
244
+
245
+ int main(int argc, char *argv[]) {
246
+ int i, err;
247
+ MDBX_env *env;
248
+ MDBX_txn *txn;
249
+ MDBX_dbi dbi;
250
+ prog = argv[0];
251
+ char *envname;
252
+ char *subname = nullptr, *buf4free = nullptr;
253
+ unsigned envflags = 0;
254
+ bool alldbs = false, list = false;
255
+ bool warmup = false;
256
+ MDBX_warmup_flags_t warmup_flags = MDBX_warmup_default;
257
+
258
+ if (argc < 2)
259
+ usage();
260
+
261
+ while ((i = getopt(argc, argv,
262
+ "uU"
263
+ "a"
264
+ "f:"
265
+ "l"
266
+ "n"
267
+ "p"
268
+ "s:"
269
+ "V"
270
+ "r"
271
+ "q")) != EOF) {
272
+ switch (i) {
273
+ case 'V':
274
+ printf("mdbx_dump version %d.%d.%d.%d\n"
275
+ " - source: %s %s, commit %s, tree %s\n"
276
+ " - anchor: %s\n"
277
+ " - build: %s for %s by %s\n"
278
+ " - flags: %s\n"
279
+ " - options: %s\n",
280
+ mdbx_version.major, mdbx_version.minor, mdbx_version.patch, mdbx_version.tweak, mdbx_version.git.describe,
281
+ mdbx_version.git.datetime, mdbx_version.git.commit, mdbx_version.git.tree, mdbx_sourcery_anchor,
282
+ mdbx_build.datetime, mdbx_build.target, mdbx_build.compiler, mdbx_build.flags, mdbx_build.options);
283
+ return EXIT_SUCCESS;
284
+ case 'l':
285
+ list = true;
286
+ /*FALLTHROUGH*/;
287
+ __fallthrough;
288
+ case 'a':
289
+ if (subname)
290
+ usage();
291
+ alldbs = true;
292
+ break;
293
+ case 'f':
294
+ if (freopen(optarg, "w", stdout) == nullptr) {
295
+ fprintf(stderr, "%s: %s: reopen: %s\n", prog, optarg, mdbx_strerror(errno));
296
+ exit(EXIT_FAILURE);
297
+ }
298
+ break;
299
+ case 'n':
300
+ break;
301
+ case 'p':
302
+ mode |= PRINT;
303
+ break;
304
+ case 's':
305
+ if (alldbs)
306
+ usage();
307
+ subname = optarg;
308
+ break;
309
+ case 'q':
310
+ quiet = true;
311
+ break;
312
+ case 'r':
313
+ rescue = true;
314
+ break;
315
+ case 'u':
316
+ warmup = true;
317
+ break;
318
+ case 'U':
319
+ warmup = true;
320
+ warmup_flags = MDBX_warmup_force | MDBX_warmup_touchlimit | MDBX_warmup_lock;
321
+ break;
322
+ default:
323
+ usage();
324
+ }
325
+ }
326
+
327
+ if (optind != argc - 1)
328
+ usage();
329
+
330
+ #if defined(_WIN32) || defined(_WIN64)
331
+ SetConsoleCtrlHandler(ConsoleBreakHandlerRoutine, true);
332
+ #else
333
+ #ifdef SIGPIPE
334
+ signal(SIGPIPE, signal_handler);
335
+ #endif
336
+ #ifdef SIGHUP
337
+ signal(SIGHUP, signal_handler);
338
+ #endif
339
+ signal(SIGINT, signal_handler);
340
+ signal(SIGTERM, signal_handler);
341
+ #endif /* !WINDOWS */
342
+
343
+ envname = argv[optind];
344
+ if (!quiet) {
345
+ fprintf(stderr, "mdbx_dump %s (%s, T-%s)\nRunning for %s...\n", mdbx_version.git.describe,
346
+ mdbx_version.git.datetime, mdbx_version.git.tree, envname);
347
+ fflush(nullptr);
348
+ mdbx_setup_debug(MDBX_LOG_NOTICE, MDBX_DBG_DONTCHANGE, logger);
349
+ }
350
+
351
+ err = mdbx_env_create(&env);
352
+ if (unlikely(err != MDBX_SUCCESS)) {
353
+ error("mdbx_env_create", err);
354
+ return EXIT_FAILURE;
355
+ }
356
+
357
+ if (alldbs || subname) {
358
+ err = mdbx_env_set_maxdbs(env, 2);
359
+ if (unlikely(err != MDBX_SUCCESS)) {
360
+ error("mdbx_env_set_maxdbs", err);
361
+ goto env_close;
362
+ }
363
+ }
364
+
365
+ err = mdbx_env_open(env, envname, envflags | (rescue ? MDBX_RDONLY | MDBX_EXCLUSIVE | MDBX_VALIDATION : MDBX_RDONLY),
366
+ 0);
367
+ if (unlikely(err != MDBX_SUCCESS)) {
368
+ error("mdbx_env_open", err);
369
+ goto env_close;
370
+ }
371
+
372
+ if (warmup) {
373
+ err = mdbx_env_warmup(env, nullptr, warmup_flags, 3600 * 65536);
374
+ if (MDBX_IS_ERROR(err)) {
375
+ error("mdbx_env_warmup", err);
376
+ goto env_close;
377
+ }
378
+ }
379
+
380
+ err = mdbx_txn_begin(env, nullptr, MDBX_TXN_RDONLY, &txn);
381
+ if (unlikely(err != MDBX_SUCCESS)) {
382
+ error("mdbx_txn_begin", err);
383
+ goto env_close;
384
+ }
385
+
386
+ err = mdbx_dbi_open(txn, subname, MDBX_DB_ACCEDE, &dbi);
387
+ if (unlikely(err != MDBX_SUCCESS)) {
388
+ error("mdbx_dbi_open", err);
389
+ goto txn_abort;
390
+ }
391
+
392
+ if (alldbs) {
393
+ assert(dbi == MAIN_DBI);
394
+
395
+ MDBX_cursor *cursor;
396
+ err = mdbx_cursor_open(txn, MAIN_DBI, &cursor);
397
+ if (unlikely(err != MDBX_SUCCESS)) {
398
+ error("mdbx_cursor_open", err);
399
+ goto txn_abort;
400
+ }
401
+ if (rescue) {
402
+ err = mdbx_cursor_ignord(cursor);
403
+ if (unlikely(err != MDBX_SUCCESS)) {
404
+ error("mdbx_cursor_ignord", err);
405
+ return err;
406
+ }
407
+ }
408
+
409
+ bool have_raw = false;
410
+ int count = 0;
411
+ MDBX_val key;
412
+ while (MDBX_SUCCESS == (err = mdbx_cursor_get(cursor, &key, nullptr, MDBX_NEXT_NODUP))) {
413
+ if (user_break) {
414
+ err = MDBX_EINTR;
415
+ break;
416
+ }
417
+
418
+ if (memchr(key.iov_base, '\0', key.iov_len))
419
+ continue;
420
+ subname = osal_realloc(buf4free, key.iov_len + 1);
421
+ if (!subname) {
422
+ err = MDBX_ENOMEM;
423
+ break;
424
+ }
425
+
426
+ buf4free = subname;
427
+ memcpy(subname, key.iov_base, key.iov_len);
428
+ subname[key.iov_len] = '\0';
429
+
430
+ MDBX_dbi sub_dbi;
431
+ err = mdbx_dbi_open_ex(txn, subname, MDBX_DB_ACCEDE, &sub_dbi, rescue ? equal_or_greater : nullptr,
432
+ rescue ? equal_or_greater : nullptr);
433
+ if (unlikely(err != MDBX_SUCCESS)) {
434
+ if (err == MDBX_INCOMPATIBLE) {
435
+ have_raw = true;
436
+ continue;
437
+ }
438
+ error("mdbx_dbi_open", err);
439
+ if (!rescue)
440
+ break;
441
+ } else {
442
+ count++;
443
+ if (list) {
444
+ printf("%s\n", subname);
445
+ } else {
446
+ err = dump_tbl(txn, sub_dbi, subname);
447
+ if (unlikely(err != MDBX_SUCCESS)) {
448
+ if (!rescue)
449
+ break;
450
+ if (!quiet)
451
+ fprintf(stderr, "%s: %s: ignore %s for `%s` and continue\n", prog, envname, mdbx_strerror(err), subname);
452
+ /* Here is a hack for rescue mode, don't do that:
453
+ * - we should restart transaction in case error due
454
+ * database corruption;
455
+ * - but we won't close cursor, reopen and re-positioning it
456
+ * for new a transaction;
457
+ * - this is possible since DB is opened in read-only exclusive
458
+ * mode and transaction is the same, i.e. has the same address
459
+ * and so on. */
460
+ err = mdbx_txn_reset(txn);
461
+ if (unlikely(err != MDBX_SUCCESS)) {
462
+ error("mdbx_txn_reset", err);
463
+ goto env_close;
464
+ }
465
+ err = mdbx_txn_renew(txn);
466
+ if (unlikely(err != MDBX_SUCCESS)) {
467
+ error("mdbx_txn_renew", err);
468
+ goto env_close;
469
+ }
470
+ }
471
+ }
472
+ err = mdbx_dbi_close(env, sub_dbi);
473
+ if (unlikely(err != MDBX_SUCCESS)) {
474
+ error("mdbx_dbi_close", err);
475
+ break;
476
+ }
477
+ }
478
+ }
479
+ mdbx_cursor_close(cursor);
480
+ cursor = nullptr;
481
+
482
+ if (have_raw && (!count /* || rescue */))
483
+ err = dump_tbl(txn, MAIN_DBI, nullptr);
484
+ else if (!count) {
485
+ if (!quiet)
486
+ fprintf(stderr, "%s: %s does not contain multiple databases\n", prog, envname);
487
+ err = MDBX_NOTFOUND;
488
+ }
489
+ } else {
490
+ err = dump_tbl(txn, dbi, subname);
491
+ }
492
+
493
+ switch (err) {
494
+ case MDBX_NOTFOUND:
495
+ err = MDBX_SUCCESS;
496
+ case MDBX_SUCCESS:
497
+ break;
498
+ case MDBX_EINTR:
499
+ if (!quiet)
500
+ fprintf(stderr, "Interrupted by signal/user\n");
501
+ break;
502
+ default:
503
+ if (unlikely(err != MDBX_SUCCESS))
504
+ error("mdbx_cursor_get", err);
505
+ }
506
+
507
+ mdbx_dbi_close(env, dbi);
508
+ txn_abort:
509
+ mdbx_txn_abort(txn);
510
+ env_close:
511
+ mdbx_env_close(env);
512
+ free(buf4free);
513
+
514
+ return err ? EXIT_FAILURE : EXIT_SUCCESS;
515
+ }