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
package/src/envmou.cpp ADDED
@@ -0,0 +1,445 @@
1
+ #include "envmou.hpp"
2
+ #include "txnmou.hpp"
3
+ #include "async/envmou_copy_to.hpp"
4
+ #include "async/envmou_query.hpp"
5
+ #include "async/envmou_open.hpp"
6
+ #include "async/envmou_keys.hpp"
7
+ #include "async/envmou_close.hpp"
8
+
9
+ namespace mdbxmou {
10
+
11
+ Napi::FunctionReference envmou::ctor{};
12
+
13
+ void envmou::init(const char *class_name, Napi::Env env, Napi::Object exports)
14
+ {
15
+ auto func = DefineClass(env, class_name, {
16
+ InstanceMethod("open", &envmou::open),
17
+ InstanceMethod("openSync", &envmou::open_sync),
18
+ InstanceMethod("close", &envmou::close),
19
+ InstanceMethod("closeSync", &envmou::close_sync),
20
+ InstanceMethod("copyTo", &envmou::copy_to),
21
+ InstanceMethod("copyToSync", &envmou::copy_to_sync),
22
+ InstanceMethod("version", &envmou::get_version),
23
+ InstanceMethod("startRead", &envmou::start_read),
24
+ InstanceMethod("startWrite", &envmou::start_write),
25
+ InstanceMethod("query", &envmou::query),
26
+ InstanceMethod("keys", &envmou::keys)
27
+ });
28
+ ctor = Napi::Persistent(func);
29
+ ctor.SuppressDestruct();
30
+ exports.Set(class_name, func);
31
+ }
32
+
33
+ mdbx::env::geometry envmou::parse_geometry(const Napi::Value& arg0)
34
+ {
35
+ mdbx::env::geometry geom{};
36
+
37
+ auto obj = arg0.As<Napi::Object>();
38
+
39
+ if (obj.Has("fixedSize")) {
40
+ auto value = obj.Get("fixedSize").As<Napi::Number>();
41
+ auto fixed_size = static_cast<intptr_t>(value.Int64Value());
42
+ return geom.make_fixed(fixed_size);
43
+ } else if (obj.Has("dynamicSize")) {
44
+ auto arr = obj.Get("dynamicSize").As<Napi::Array>();
45
+ if (arr.Length() != 2) {
46
+ throw Napi::TypeError::New(obj.Env(), "dynamicSize must be an array of two numbers");
47
+ }
48
+ auto v1 = arr.Get(0u).As<Napi::Number>();
49
+ auto v2 = arr.Get(1u).As<Napi::Number>();
50
+ auto size_lower = static_cast<intptr_t>(v1.Int64Value());
51
+ auto size_upper = static_cast<intptr_t>(v2.Int64Value());
52
+ return geom.make_dynamic(size_lower, size_upper);
53
+ } else {
54
+ if (obj.Has("sizeNow")) {
55
+ auto value = obj.Get("sizeNow").As<Napi::Number>();
56
+ geom.size_now = static_cast<intptr_t>(value.Int64Value());
57
+ }
58
+ if (obj.Has("sizeUpper")) {
59
+ auto value = obj.Get("sizeUpper").As<Napi::Number>();
60
+ geom.size_upper = static_cast<intptr_t>(value.Int64Value());
61
+ }
62
+ if (obj.Has("growthStep")) {
63
+ auto value = obj.Get("growthStep").As<Napi::Number>();
64
+ geom.growth_step = static_cast<intptr_t>(value.Int64Value());
65
+ }
66
+ if (obj.Has("shrinkThreshold")) {
67
+ auto value = obj.Get("shrinkThreshold").As<Napi::Number>();
68
+ geom.shrink_threshold = static_cast<intptr_t>(value.Int64Value());
69
+ }
70
+ if (obj.Has("pageSize")) {
71
+ auto value = obj.Get("pageSize").As<Napi::Number>();
72
+ geom.pagesize = static_cast<intptr_t>(value.Int64Value());
73
+ }
74
+ }
75
+ return geom;
76
+ }
77
+
78
+ env_arg0 envmou::parse(const Napi::Value& arg0)
79
+ {
80
+ env_arg0 rc;
81
+
82
+ auto obj = arg0.As<Napi::Object>();
83
+
84
+ rc.path = obj.Get("path").As<Napi::String>().Utf8Value();
85
+ if (obj.Has("maxDbi")) {
86
+ auto value = obj.Get("maxDbi").As<Napi::Number>();
87
+ rc.max_dbi = static_cast<MDBX_dbi>(value.Uint32Value());
88
+ }
89
+
90
+ if (obj.Has("geometry")) {
91
+ rc.geom = parse_geometry(obj.Get("geometry"));
92
+ }
93
+
94
+ if (obj.Has("flags")) {
95
+ rc.flag = env_flag::parse(obj.Get("flags"));
96
+ }
97
+
98
+ if (obj.Has("mode")) {
99
+ auto value = obj.Get("mode").As<Napi::Number>();
100
+ rc.file_mode = static_cast<mode_t>(value.Int32Value());
101
+ }
102
+
103
+ if (obj.Has("keyFlag")) {
104
+ rc.key_flag = base_flag::parse_key(obj.Get("keyFlag"));
105
+ }
106
+
107
+ if (obj.Has("valueFlag")) {
108
+ rc.value_flag = base_flag::parse_value(obj.Get("valueFlag"));
109
+ }
110
+
111
+ return rc;
112
+ }
113
+
114
+ Napi::Value envmou::open(const Napi::CallbackInfo& info)
115
+ {
116
+ auto env = info.Env();
117
+ auto arg0 = parse(info[0].As<Napi::Object>());
118
+
119
+ try {
120
+ // асинхронный вызов разлочится внутри worker'a
121
+ if (!try_lock()) {
122
+ throw std::runtime_error("in progress");
123
+ }
124
+
125
+ if (is_open()) {
126
+ throw std::runtime_error("already opened");
127
+ }
128
+
129
+ auto* worker = new async_open(env, *this, arg0);
130
+ Napi::Promise promise = worker->GetPromise();
131
+ worker->Queue();
132
+ return promise;
133
+ } catch (const std::exception& e) {
134
+ unlock();
135
+ throw Napi::Error::New(env, e.what());
136
+ } catch (...) {
137
+ unlock();
138
+ throw;
139
+ }
140
+
141
+ return env.Undefined();
142
+ }
143
+
144
+ Napi::Value envmou::open_sync(const Napi::CallbackInfo& info)
145
+ {
146
+ auto env = info.Env();
147
+ auto arg0 = parse(info[0].As<Napi::Object>());
148
+
149
+ try {
150
+ lock_guard l(*this);
151
+ if (is_open()) {
152
+ throw std::runtime_error("already opened");
153
+ }
154
+ attach(create_and_open(arg0), arg0);
155
+ } catch (const std::exception& e) {
156
+ throw Napi::Error::New(env, e.what());
157
+ }
158
+
159
+ return env.Undefined();
160
+ }
161
+
162
+ MDBX_env* envmou::create_and_open(const env_arg0& arg0)
163
+ {
164
+ MDBX_env *env;
165
+ auto rc = mdbx_env_create(&env);
166
+ if (rc != MDBX_SUCCESS) {
167
+ throw std::runtime_error(mdbx_strerror(rc));
168
+ }
169
+
170
+ rc = mdbx_env_set_maxdbs(env, arg0.max_dbi);
171
+ if (rc != MDBX_SUCCESS) {
172
+ mdbx_env_close(env);
173
+ throw std::runtime_error(mdbx_strerror(rc));
174
+ }
175
+
176
+ rc = mdbx_env_set_maxreaders(env, arg0.max_readers);
177
+ if (rc != MDBX_SUCCESS) {
178
+ mdbx_env_close(env);
179
+ throw std::runtime_error(mdbx_strerror(rc));
180
+ }
181
+
182
+ auto& geom = arg0.geom;
183
+ rc = mdbx_env_set_geometry(env, geom.size_lower, geom.size_now,
184
+ geom.size_upper, geom.growth_step, geom.shrink_threshold, geom.pagesize);
185
+ if (rc != MDBX_SUCCESS) {
186
+ mdbx_env_close(env);
187
+ throw std::runtime_error(mdbx_strerror(rc));
188
+ }
189
+
190
+ auto id = static_cast<std::uint32_t>(pthread_self());
191
+ // выдадим параметры mode, flag и id потока в котором открывается env
192
+ rc = mdbx_env_open(env, arg0.path.c_str(), arg0.flag, arg0.file_mode);
193
+ if (rc != MDBX_SUCCESS) {
194
+ mdbx_env_close(env);
195
+ throw std::runtime_error(mdbx_strerror(rc));
196
+ }
197
+
198
+ return env;
199
+ }
200
+
201
+ void envmou::attach(MDBX_env* env, const env_arg0& arg0)
202
+ {
203
+ arg0_ = arg0;
204
+
205
+ auto rc = mdbx_env_set_userctx(env, &arg0_);
206
+ if (rc != MDBX_SUCCESS) {
207
+ mdbx_env_close(env);
208
+ throw std::runtime_error(mdbx_strerror(rc));
209
+ }
210
+
211
+ env_.reset(env);
212
+ }
213
+
214
+ Napi::Value envmou::close(const Napi::CallbackInfo& info)
215
+ {
216
+ auto env = info.Env();
217
+ try {
218
+ // асинхронный вызов разлочится внутри worker'a
219
+ if (!try_lock()) {
220
+ throw std::runtime_error("in progress");
221
+ }
222
+
223
+ if (!is_open()) {
224
+ return env.Undefined();
225
+ }
226
+
227
+ if (trx_count_.load() > 0) {
228
+ throw std::runtime_error("active transactions");
229
+ }
230
+
231
+ auto* worker = new async_close(env, *this);
232
+ Napi::Promise promise = worker->GetPromise();
233
+ worker->Queue();
234
+ return promise;
235
+ } catch (const std::exception& e) {
236
+ unlock();
237
+ throw Napi::Error::New(env, e.what());
238
+ } catch (...) {
239
+ unlock();
240
+ throw;
241
+ }
242
+
243
+ return env.Undefined();
244
+ }
245
+
246
+ Napi::Value envmou::close_sync(const Napi::CallbackInfo& info)
247
+ {
248
+ auto env = info.Env();
249
+ try {
250
+ lock_guard l(*this);
251
+
252
+ do_close();
253
+
254
+ } catch (const std::exception& e) {
255
+ throw Napi::Error::New(env, e.what());
256
+ }
257
+ return env.Undefined();
258
+ }
259
+
260
+ Napi::Value envmou::copy_to_sync(const Napi::CallbackInfo& info)
261
+ {
262
+ auto env = info.Env();
263
+
264
+ if (info.Length() < 1 || !info[0].IsString()) {
265
+ throw Napi::TypeError::New(env, "expected a string argument for the destination path");
266
+ }
267
+
268
+ MDBX_copy_flags_t flags{MDBX_CP_COMPACT};
269
+ if ((info.Length() > 1) && info[1].IsNumber()) {
270
+ flags = static_cast<MDBX_copy_flags_t>(info[1].As<Napi::Number>().Uint32Value());
271
+ }
272
+
273
+ try {
274
+ auto dest_path = info[0].As<Napi::String>().Utf8Value();
275
+
276
+ lock_guard l(*this);
277
+
278
+ check();
279
+
280
+ auto rc = mdbx_env_copy(*this, dest_path.c_str(), flags);
281
+ if (rc != MDBX_SUCCESS) {
282
+ throw Napi::Error::New(env, mdbx_strerror(rc));
283
+ }
284
+
285
+ } catch (const std::exception& e) {
286
+ throw Napi::Error::New(env, e.what());
287
+ }
288
+
289
+ return env.Undefined();
290
+ }
291
+
292
+ Napi::Value envmou::copy_to(const Napi::CallbackInfo& info)
293
+ {
294
+ Napi::Env env = info.Env();
295
+
296
+ if (info.Length() < 1 || !info[0].IsString()) {
297
+ throw Napi::TypeError::New(env, "copyTo(path: string[, flags?: number]) -> Promise<void>");
298
+ }
299
+
300
+ MDBX_copy_flags_t flags{MDBX_CP_COMPACT};
301
+ if (info.Length() > 1 && info[1].IsNumber()) {
302
+ flags = static_cast<MDBX_copy_flags_t>(info[1].As<Napi::Number>().Uint32Value());
303
+ }
304
+
305
+ try {
306
+ auto dest = info[0].As<Napi::String>().Utf8Value();
307
+
308
+ if (!try_lock()) {
309
+ throw std::runtime_error("in progress");
310
+ }
311
+
312
+ check();
313
+
314
+ auto* worker = new mdbxmou::async_copy(env, *this, std::move(dest), flags);
315
+ Napi::Promise promise = worker->GetPromise();
316
+ worker->Queue();
317
+ return promise;
318
+ } catch (const std::exception& e) {
319
+ throw Napi::Error::New(env, e.what());
320
+ }
321
+
322
+ return env.Undefined();
323
+ }
324
+
325
+ Napi::Value envmou::get_version(const Napi::CallbackInfo& info)
326
+ {
327
+ std::string version = "mdbx v" + std::to_string(MDBX_VERSION_MAJOR);
328
+ version += "." + std::to_string(MDBX_VERSION_MINOR);
329
+ return Napi::Value::From(info.Env(), version);
330
+ }
331
+
332
+ Napi::Value envmou::start_transaction(const Napi::CallbackInfo& info, txn_mode mode)
333
+ {
334
+ auto env = info.Env();
335
+
336
+ try {
337
+ lock_guard l(*this);
338
+
339
+ check();
340
+
341
+ MDBX_txn* txn;
342
+ auto rc = mdbx_txn_begin(*this, nullptr, mode, &txn);
343
+ if (rc != MDBX_SUCCESS) {
344
+ throw Napi::Error::New(env, std::string("Env: ") + mdbx_strerror(rc));
345
+ }
346
+
347
+ // Создаем новый объект txnmou
348
+ auto txn_obj = txnmou::ctor.New({});
349
+ auto txn_wrapper = txnmou::Unwrap(txn_obj);
350
+ txn_wrapper->attach(*this, txn, mode, nullptr);
351
+
352
+ return txn_obj;
353
+ } catch (const std::exception& e) {
354
+ throw Napi::Error::New(env, e.what());
355
+ }
356
+ }
357
+
358
+ Napi::Value envmou::query(const Napi::CallbackInfo& info)
359
+ {
360
+ Napi::Env env = info.Env();
361
+
362
+ txn_mode mode{};
363
+
364
+ if (info.Length() < 1) {
365
+ throw Napi::TypeError::New(env,
366
+ "expected array of requests: [{ db: String, db_mode: Number, key_mode: Number, key_flag: Number, value_mode: Number, value_flag: Number, mode: Number, item: [] }, ...]");
367
+ }
368
+
369
+ if (info.Length() > 1 || info[1].IsNumber()) {
370
+ mode = txn_mode::parse(info[1].As<Napi::Number>());
371
+ }
372
+
373
+ try
374
+ {
375
+ lock_guard lock(*this);
376
+
377
+ check();
378
+
379
+ auto conf = dbimou::get_env_userctx(*this);
380
+
381
+ auto arg0 = info[0];
382
+ query_request query = parse_query(mode,
383
+ conf->key_flag, conf->value_flag, arg0);
384
+ auto* worker = new async_query(env, *this, mode,
385
+ std::move(query), arg0.IsObject());
386
+ auto promise = worker->GetPromise();
387
+ worker->Queue();
388
+
389
+ // Увеличиваем счетчик транзакций после успешного создания
390
+ ++(*this);
391
+
392
+ return promise;
393
+ } catch (const std::exception& e) {
394
+ throw Napi::Error::New(env, e.what());
395
+ } catch (...) {
396
+ throw Napi::Error::New(env, "envmou::query");
397
+ }
398
+ return env.Undefined();
399
+ }
400
+
401
+ Napi::Value envmou::keys(const Napi::CallbackInfo& info)
402
+ {
403
+ Napi::Env env = info.Env();
404
+
405
+ txn_mode mode{};
406
+
407
+ if (info.Length() < 1) {
408
+ throw Napi::TypeError::New(env,
409
+ "expected array of requests: [{ db: String, db_mode: Number, key_mode: Number, key_flag: Number, value_mode: Number, value_flag: Number }, ...]");
410
+ }
411
+
412
+ if (info.Length() > 1 || info[1].IsNumber()) {
413
+ mode = txn_mode::parse(info[1].As<Napi::Number>());
414
+ }
415
+
416
+ try
417
+ {
418
+ lock_guard lock(*this);
419
+
420
+ check();
421
+
422
+ auto conf = dbimou::get_env_userctx(*this);
423
+
424
+ auto arg0 = info[0];
425
+ keys_request query = parse_keys(mode,
426
+ conf->key_flag, conf->value_flag, arg0);
427
+
428
+ auto* worker = new async_keys(env, *this, mode,
429
+ std::move(query), arg0.IsObject());
430
+ auto promise = worker->GetPromise();
431
+ worker->Queue();
432
+
433
+ // Увеличиваем счетчик транзакций после успешного создания
434
+ ++(*this);
435
+
436
+ return promise;
437
+ } catch (const std::exception& e) {
438
+ throw Napi::Error::New(env, e.what());
439
+ } catch (...) {
440
+ throw Napi::Error::New(env, "envmou::keys");
441
+ }
442
+ return env.Undefined();
443
+ }
444
+
445
+ } // namespace mdbxmou
package/src/envmou.hpp ADDED
@@ -0,0 +1,116 @@
1
+ #pragma once
2
+
3
+ #include "txnmou.hpp"
4
+ #include <memory>
5
+ #include <atomic>
6
+ #include <mutex>
7
+
8
+ namespace mdbxmou {
9
+
10
+ // Forward declaration
11
+ class txnmou;
12
+
13
+ class envmou final
14
+ : public Napi::ObjectWrap<envmou>
15
+ {
16
+ static Napi::FunctionReference ctor;
17
+ static mdbx::env::geometry parse_geometry(const Napi::Value& obj);
18
+ static env_arg0 parse(const Napi::Value& obj);
19
+
20
+ struct free_env {
21
+ void operator()(MDBX_env* env) const {
22
+ auto rc = mdbx_env_close(env);
23
+ if (rc != MDBX_SUCCESS) {
24
+ fprintf(stderr, "mdbx_env_close %s\n", mdbx_strerror(rc));
25
+ }
26
+ }
27
+ };
28
+
29
+ std::unique_ptr<MDBX_env, free_env> env_{};
30
+ std::atomic<std::size_t> trx_count_{};
31
+ env_arg0 arg0_{};
32
+ std::mutex lock_{};
33
+
34
+ bool is_open() const {
35
+ return env_ != nullptr;
36
+ }
37
+
38
+ // Inline метод для проверки что база данных открыта
39
+ void check() const {
40
+ if (!is_open()) {
41
+ throw std::runtime_error("closed");
42
+ }
43
+ }
44
+
45
+ // Общий метод для создания транзакций
46
+ Napi::Value start_transaction(const Napi::CallbackInfo& info, txn_mode mode);
47
+
48
+ public:
49
+ envmou(const Napi::CallbackInfo& i)
50
+ : ObjectWrap{i}
51
+ { }
52
+
53
+ static MDBX_env* create_and_open(const env_arg0& arg0);
54
+ void attach(MDBX_env* env, const env_arg0& arg0);
55
+
56
+ operator MDBX_env*() const noexcept {
57
+ return env_.get();
58
+ }
59
+
60
+ static void init(const char *class_name, Napi::Env env, Napi::Object exports);
61
+
62
+ envmou& operator++() noexcept {
63
+ ++trx_count_;
64
+ return *this;
65
+ }
66
+
67
+ envmou& operator--() noexcept {
68
+ --trx_count_;
69
+ return *this;
70
+ }
71
+
72
+ Napi::Value open(const Napi::CallbackInfo&);
73
+ Napi::Value open_sync(const Napi::CallbackInfo&);
74
+ Napi::Value close(const Napi::CallbackInfo&);
75
+ Napi::Value close_sync(const Napi::CallbackInfo&);
76
+ Napi::Value get_version(const Napi::CallbackInfo&);
77
+ Napi::Value copy_to_sync(const Napi::CallbackInfo&);
78
+ Napi::Value copy_to(const Napi::CallbackInfo&);
79
+ // метод для групповых вставок или чтения
80
+ // внутри транзакция, получение db и чтение/запись
81
+ Napi::Value query(const Napi::CallbackInfo&);
82
+ Napi::Value keys(const Napi::CallbackInfo&);
83
+
84
+ // Методы для создания транзакций
85
+ Napi::Value start_read(const Napi::CallbackInfo& info) {
86
+ return start_transaction(info, {txn_mode::ro});
87
+ }
88
+ Napi::Value start_write(const Napi::CallbackInfo& info) {
89
+ return start_transaction(info, {});
90
+ }
91
+
92
+ using lock_guard = std::lock_guard<envmou>;
93
+ // для защиты асинхронных операций
94
+ void lock() {
95
+ auto rc = lock_.try_lock();
96
+ if (!rc) {
97
+ throw std::runtime_error("operation in progress");
98
+ }
99
+ }
100
+ void unlock() {
101
+ lock_.unlock();
102
+ }
103
+ bool try_lock() {
104
+ bool locked = lock_.try_lock();
105
+ return locked;
106
+ }
107
+
108
+ void do_close() {
109
+ if (trx_count_.load() > 0) {
110
+ throw std::runtime_error("transaction in progress");
111
+ }
112
+ env_.reset();
113
+ }
114
+ };
115
+
116
+ } // namespace mdbxmou
@@ -0,0 +1,113 @@
1
+ #include "envmou.hpp"
2
+
3
+ using namespace Napi;
4
+
5
+ Napi::Object Init(Napi::Env env, Napi::Object exports)
6
+ {
7
+ #define MDBXMOU_DECLARE_FLAG_NAME(obj, name, value) \
8
+ obj.Set(name, Napi::Number::New(env, value))
9
+
10
+ Napi::Object mdbx_mou = Napi::Object::New(env);
11
+
12
+ using mdbxmou::env_flag;
13
+ Napi::Object envFlag = Napi::Object::New(env);
14
+ MDBXMOU_DECLARE_FLAG_NAME(envFlag, "validation", env_flag::validation);
15
+ MDBXMOU_DECLARE_FLAG_NAME(envFlag, "rdonly", env_flag::rdonly);
16
+ MDBXMOU_DECLARE_FLAG_NAME(envFlag, "exclusive", env_flag::exclusive);
17
+ MDBXMOU_DECLARE_FLAG_NAME(envFlag, "accede", env_flag::accede);
18
+ MDBXMOU_DECLARE_FLAG_NAME(envFlag, "writemap", env_flag::writemap);
19
+ MDBXMOU_DECLARE_FLAG_NAME(envFlag, "nostickythreads", env_flag::nostickythreads);
20
+ MDBXMOU_DECLARE_FLAG_NAME(envFlag, "nordahead", env_flag::nordahead);
21
+ MDBXMOU_DECLARE_FLAG_NAME(envFlag, "nomeminit", env_flag::nomeminit);
22
+ MDBXMOU_DECLARE_FLAG_NAME(envFlag, "liforeclaim", env_flag::liforeclaim);
23
+ MDBXMOU_DECLARE_FLAG_NAME(envFlag, "nometasync", env_flag::nometasync);
24
+ MDBXMOU_DECLARE_FLAG_NAME(envFlag, "safeNosync", env_flag::safe_nosync);
25
+ MDBXMOU_DECLARE_FLAG_NAME(envFlag, "utterlyNosync", env_flag::utterly_nosync);
26
+ mdbx_mou.Set("envFlag", envFlag);
27
+
28
+ using mdbxmou::txn_mode;
29
+ Napi::Object txn_mode = Napi::Object::New(env);
30
+ MDBXMOU_DECLARE_FLAG_NAME(txn_mode, "ro", txn_mode::ro);
31
+ mdbx_mou.Set("txnMode", txn_mode);
32
+
33
+ using mdbxmou::key_mode;
34
+ Napi::Object key_mode = Napi::Object::New(env);
35
+ MDBXMOU_DECLARE_FLAG_NAME(key_mode, "reverse", key_mode::reverse);
36
+ MDBXMOU_DECLARE_FLAG_NAME(key_mode, "ordinal", key_mode::ordinal);
37
+ mdbx_mou.Set("keyMode", key_mode);
38
+
39
+ using mdbxmou::base_flag;
40
+ Napi::Object key_flag = Napi::Object::New(env);
41
+ MDBXMOU_DECLARE_FLAG_NAME(key_flag, "string", base_flag::string);
42
+ MDBXMOU_DECLARE_FLAG_NAME(key_flag, "number", base_flag::number);
43
+ MDBXMOU_DECLARE_FLAG_NAME(key_flag, "bigint", base_flag::bigint);
44
+ mdbx_mou.Set("keyFlag", key_flag);
45
+
46
+ using mdbxmou::value_mode;
47
+ Napi::Object value_mode = Napi::Object::New(env);
48
+ MDBXMOU_DECLARE_FLAG_NAME(value_mode, "multi", value_mode::multi);
49
+ MDBXMOU_DECLARE_FLAG_NAME(value_mode, "multiReverse", value_mode::multi_reverse);
50
+ MDBXMOU_DECLARE_FLAG_NAME(value_mode, "multiSamelength", value_mode::multi_samelength);
51
+ MDBXMOU_DECLARE_FLAG_NAME(value_mode, "multiOrdinal", value_mode::multi_ordinal);
52
+ MDBXMOU_DECLARE_FLAG_NAME(value_mode, "multiReverseSamelength",
53
+ value_mode::multi_reverse_samelength);
54
+ mdbx_mou.Set("valueMode", value_mode);
55
+
56
+ Napi::Object value_flag = Napi::Object::New(env);
57
+ MDBXMOU_DECLARE_FLAG_NAME(value_flag, "string", base_flag::string);
58
+ mdbx_mou.Set("valueFlag", value_flag);
59
+
60
+ using mdbxmou::db_mode;
61
+ Napi::Object db_mode = Napi::Object::New(env);
62
+ MDBXMOU_DECLARE_FLAG_NAME(db_mode, "create", db_mode::create);
63
+ MDBXMOU_DECLARE_FLAG_NAME(db_mode, "accede", db_mode::accede);
64
+ mdbx_mou.Set("dbMode", db_mode);
65
+
66
+ using mdbxmou::query_mode;
67
+ Napi::Object query_mode = Napi::Object::New(env);
68
+ MDBXMOU_DECLARE_FLAG_NAME(query_mode, "upsert", query_mode::upsert);
69
+ MDBXMOU_DECLARE_FLAG_NAME(query_mode, "update", query_mode::update);
70
+ MDBXMOU_DECLARE_FLAG_NAME(query_mode, "insertUnique", query_mode::insert_unique);
71
+ MDBXMOU_DECLARE_FLAG_NAME(query_mode, "get", query_mode::get);
72
+ MDBXMOU_DECLARE_FLAG_NAME(query_mode, "del", query_mode::del);
73
+ mdbx_mou.Set("queryMode", query_mode);
74
+
75
+ using move_operation = mdbx::cursor::move_operation;
76
+ Napi::Object cursor_mode = Napi::Object::New(env);
77
+ MDBXMOU_DECLARE_FLAG_NAME(cursor_mode, "first", move_operation::first);
78
+ MDBXMOU_DECLARE_FLAG_NAME(cursor_mode, "last", move_operation::last);
79
+ MDBXMOU_DECLARE_FLAG_NAME(cursor_mode, "next", move_operation::next);
80
+ MDBXMOU_DECLARE_FLAG_NAME(cursor_mode, "prev", move_operation::previous);
81
+ MDBXMOU_DECLARE_FLAG_NAME(cursor_mode, "key_lesser_than",
82
+ move_operation::key_lesser_than);
83
+ MDBXMOU_DECLARE_FLAG_NAME(cursor_mode, "key_lesser_or_equal",
84
+ move_operation::key_lesser_or_equal);
85
+ MDBXMOU_DECLARE_FLAG_NAME(cursor_mode, "key_equal", move_operation::key_equal);
86
+ MDBXMOU_DECLARE_FLAG_NAME(cursor_mode, "key_greater_or_equal",
87
+ move_operation::key_greater_or_equal);
88
+ MDBXMOU_DECLARE_FLAG_NAME(cursor_mode, "key_greater_than",
89
+ move_operation::key_greater_than);
90
+ MDBXMOU_DECLARE_FLAG_NAME(cursor_mode, "multi_exactkey_value_lesser_than",
91
+ move_operation::multi_exactkey_value_lesser_than);
92
+ MDBXMOU_DECLARE_FLAG_NAME(cursor_mode, "multi_exactkey_value_lesser_or_equal",
93
+ move_operation::multi_exactkey_value_lesser_or_equal);
94
+ MDBXMOU_DECLARE_FLAG_NAME(cursor_mode, "multi_exactkey_value_equal",
95
+ move_operation::multi_exactkey_value_equal);
96
+ MDBXMOU_DECLARE_FLAG_NAME(cursor_mode, "multi_exactkey_value_greater_or_equal",
97
+ move_operation::multi_exactkey_value_greater_or_equal);
98
+ MDBXMOU_DECLARE_FLAG_NAME(cursor_mode, "multi_exactkey_value_greater",
99
+ move_operation::multi_exactkey_value_greater);
100
+ mdbx_mou.Set("cursorMode", cursor_mode);
101
+
102
+ exports.Set("MDBX_Param", mdbx_mou);
103
+
104
+ #undef MDBXMOU_DECLARE_FLAG_NAME
105
+
106
+ mdbxmou::envmou::init("MDBX_Env", env, exports);
107
+ mdbxmou::txnmou::init("MDBX_Txn", env);
108
+ mdbxmou::dbimou::init("MDBX_Dbi", env);
109
+
110
+ return exports;
111
+ }
112
+
113
+ NODE_API_MODULE(addon, Init)