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.
- package/.github/workflows/ci.yml +32 -0
- package/.github/workflows/publish.yml +27 -0
- package/.gitmodules +3 -0
- package/CMakeLists.txt +53 -0
- package/LICENSE +201 -0
- package/README.md +639 -0
- package/build.js +11 -0
- package/deps/libmdbx/.clang-format +3 -0
- package/deps/libmdbx/.cmake-format.yaml +3 -0
- package/deps/libmdbx/.le.ini +40 -0
- package/deps/libmdbx/CMakeLists.txt +1269 -0
- package/deps/libmdbx/COPYRIGHT +159 -0
- package/deps/libmdbx/ChangeLog.md +2786 -0
- package/deps/libmdbx/GNUmakefile +950 -0
- package/deps/libmdbx/LICENSE +177 -0
- package/deps/libmdbx/Makefile +16 -0
- package/deps/libmdbx/NOTICE +39 -0
- package/deps/libmdbx/README.md +863 -0
- package/deps/libmdbx/TODO.md +43 -0
- package/deps/libmdbx/cmake/compiler.cmake +1221 -0
- package/deps/libmdbx/cmake/profile.cmake +58 -0
- package/deps/libmdbx/cmake/utils.cmake +524 -0
- package/deps/libmdbx/conanfile.py +323 -0
- package/deps/libmdbx/docs/Doxyfile.in +2734 -0
- package/deps/libmdbx/docs/_preface.md +47 -0
- package/deps/libmdbx/docs/_restrictions.md +248 -0
- package/deps/libmdbx/docs/_starting.md +245 -0
- package/deps/libmdbx/docs/_toc.md +34 -0
- package/deps/libmdbx/docs/header.html +96 -0
- package/deps/libmdbx/example/CMakeLists.txt +6 -0
- package/deps/libmdbx/example/README.md +1 -0
- package/deps/libmdbx/example/example-mdbx.c +154 -0
- package/deps/libmdbx/example/sample-bdb.txt +77 -0
- package/deps/libmdbx/mdbx.h +6655 -0
- package/deps/libmdbx/mdbx.h++ +6428 -0
- package/deps/libmdbx/packages/buildroot/0001-package-libmdbx-new-package-library-database.patch +173 -0
- package/deps/libmdbx/src/alloy.c +54 -0
- package/deps/libmdbx/src/api-cold.c +543 -0
- package/deps/libmdbx/src/api-copy.c +912 -0
- package/deps/libmdbx/src/api-cursor.c +754 -0
- package/deps/libmdbx/src/api-dbi.c +315 -0
- package/deps/libmdbx/src/api-env.c +1434 -0
- package/deps/libmdbx/src/api-extra.c +165 -0
- package/deps/libmdbx/src/api-key-transform.c +197 -0
- package/deps/libmdbx/src/api-misc.c +286 -0
- package/deps/libmdbx/src/api-opts.c +575 -0
- package/deps/libmdbx/src/api-range-estimate.c +365 -0
- package/deps/libmdbx/src/api-txn-data.c +454 -0
- package/deps/libmdbx/src/api-txn.c +921 -0
- package/deps/libmdbx/src/atomics-ops.h +364 -0
- package/deps/libmdbx/src/atomics-types.h +97 -0
- package/deps/libmdbx/src/audit.c +109 -0
- package/deps/libmdbx/src/bits.md +34 -0
- package/deps/libmdbx/src/chk.c +1796 -0
- package/deps/libmdbx/src/cogs.c +309 -0
- package/deps/libmdbx/src/cogs.h +506 -0
- package/deps/libmdbx/src/coherency.c +170 -0
- package/deps/libmdbx/src/config.h.in +88 -0
- package/deps/libmdbx/src/cursor.c +2396 -0
- package/deps/libmdbx/src/cursor.h +391 -0
- package/deps/libmdbx/src/dbi.c +717 -0
- package/deps/libmdbx/src/dbi.h +142 -0
- package/deps/libmdbx/src/debug_begin.h +36 -0
- package/deps/libmdbx/src/debug_end.h +15 -0
- package/deps/libmdbx/src/dpl.c +486 -0
- package/deps/libmdbx/src/dpl.h +134 -0
- package/deps/libmdbx/src/dxb.c +1335 -0
- package/deps/libmdbx/src/env.c +607 -0
- package/deps/libmdbx/src/essentials.h +125 -0
- package/deps/libmdbx/src/gc-get.c +1345 -0
- package/deps/libmdbx/src/gc-put.c +970 -0
- package/deps/libmdbx/src/gc.h +40 -0
- package/deps/libmdbx/src/global.c +474 -0
- package/deps/libmdbx/src/internals.h +585 -0
- package/deps/libmdbx/src/layout-dxb.h +288 -0
- package/deps/libmdbx/src/layout-lck.h +289 -0
- package/deps/libmdbx/src/lck-posix.c +859 -0
- package/deps/libmdbx/src/lck-windows.c +607 -0
- package/deps/libmdbx/src/lck.c +174 -0
- package/deps/libmdbx/src/lck.h +110 -0
- package/deps/libmdbx/src/logging_and_debug.c +250 -0
- package/deps/libmdbx/src/logging_and_debug.h +159 -0
- package/deps/libmdbx/src/man1/mdbx_chk.1 +106 -0
- package/deps/libmdbx/src/man1/mdbx_copy.1 +95 -0
- package/deps/libmdbx/src/man1/mdbx_drop.1 +48 -0
- package/deps/libmdbx/src/man1/mdbx_dump.1 +101 -0
- package/deps/libmdbx/src/man1/mdbx_load.1 +105 -0
- package/deps/libmdbx/src/man1/mdbx_stat.1 +86 -0
- package/deps/libmdbx/src/mdbx.c++ +1837 -0
- package/deps/libmdbx/src/meta.c +656 -0
- package/deps/libmdbx/src/meta.h +168 -0
- package/deps/libmdbx/src/mvcc-readers.c +414 -0
- package/deps/libmdbx/src/node.c +365 -0
- package/deps/libmdbx/src/node.h +102 -0
- package/deps/libmdbx/src/ntdll.def +1246 -0
- package/deps/libmdbx/src/options.h +534 -0
- package/deps/libmdbx/src/osal.c +3485 -0
- package/deps/libmdbx/src/osal.h +587 -0
- package/deps/libmdbx/src/page-get.c +483 -0
- package/deps/libmdbx/src/page-iov.c +185 -0
- package/deps/libmdbx/src/page-iov.h +34 -0
- package/deps/libmdbx/src/page-ops.c +744 -0
- package/deps/libmdbx/src/page-ops.h +142 -0
- package/deps/libmdbx/src/pnl.c +236 -0
- package/deps/libmdbx/src/pnl.h +146 -0
- package/deps/libmdbx/src/preface.h +990 -0
- package/deps/libmdbx/src/proto.h +105 -0
- package/deps/libmdbx/src/refund.c +212 -0
- package/deps/libmdbx/src/sort.h +484 -0
- package/deps/libmdbx/src/spill.c +431 -0
- package/deps/libmdbx/src/spill.h +74 -0
- package/deps/libmdbx/src/table.c +107 -0
- package/deps/libmdbx/src/tls.c +551 -0
- package/deps/libmdbx/src/tls.h +43 -0
- package/deps/libmdbx/src/tools/chk.c +673 -0
- package/deps/libmdbx/src/tools/copy.c +166 -0
- package/deps/libmdbx/src/tools/drop.c +199 -0
- package/deps/libmdbx/src/tools/dump.c +515 -0
- package/deps/libmdbx/src/tools/load.c +831 -0
- package/deps/libmdbx/src/tools/stat.c +516 -0
- package/deps/libmdbx/src/tools/wingetopt.c +87 -0
- package/deps/libmdbx/src/tools/wingetopt.h +30 -0
- package/deps/libmdbx/src/tree-ops.c +1554 -0
- package/deps/libmdbx/src/tree-search.c +140 -0
- package/deps/libmdbx/src/txl.c +99 -0
- package/deps/libmdbx/src/txl.h +26 -0
- package/deps/libmdbx/src/txn.c +1083 -0
- package/deps/libmdbx/src/unaligned.h +205 -0
- package/deps/libmdbx/src/utils.c +32 -0
- package/deps/libmdbx/src/utils.h +76 -0
- package/deps/libmdbx/src/version.c.in +44 -0
- package/deps/libmdbx/src/walk.c +290 -0
- package/deps/libmdbx/src/walk.h +20 -0
- package/deps/libmdbx/src/windows-import.c +152 -0
- package/deps/libmdbx/src/windows-import.h +128 -0
- package/deps/libmdbx/test/CMakeLists.txt +317 -0
- package/deps/libmdbx/test/append.c++ +237 -0
- package/deps/libmdbx/test/base.h++ +92 -0
- package/deps/libmdbx/test/battery-tmux.sh +64 -0
- package/deps/libmdbx/test/cases.c++ +118 -0
- package/deps/libmdbx/test/chrono.c++ +134 -0
- package/deps/libmdbx/test/chrono.h++ +85 -0
- package/deps/libmdbx/test/config.c++ +643 -0
- package/deps/libmdbx/test/config.h++ +334 -0
- package/deps/libmdbx/test/copy.c++ +62 -0
- package/deps/libmdbx/test/dead.c++ +39 -0
- package/deps/libmdbx/test/dump-load.sh +40 -0
- package/deps/libmdbx/test/extra/crunched_delete.c++ +409 -0
- package/deps/libmdbx/test/extra/cursor_closing.c++ +410 -0
- package/deps/libmdbx/test/extra/dbi.c++ +229 -0
- package/deps/libmdbx/test/extra/doubtless_positioning.c++ +253 -0
- package/deps/libmdbx/test/extra/dupfix_addodd.c +94 -0
- package/deps/libmdbx/test/extra/dupfix_multiple.c++ +311 -0
- package/deps/libmdbx/test/extra/early_close_dbi.c++ +137 -0
- package/deps/libmdbx/test/extra/hex_base64_base58.c++ +118 -0
- package/deps/libmdbx/test/extra/maindb_ordinal.c++ +61 -0
- package/deps/libmdbx/test/extra/open.c++ +96 -0
- package/deps/libmdbx/test/extra/pcrf/README.md +2 -0
- package/deps/libmdbx/test/extra/pcrf/pcrf_test.c +380 -0
- package/deps/libmdbx/test/extra/probe.c++ +10 -0
- package/deps/libmdbx/test/extra/txn.c++ +407 -0
- package/deps/libmdbx/test/extra/upsert_alldups.c +193 -0
- package/deps/libmdbx/test/fork.c++ +263 -0
- package/deps/libmdbx/test/hill.c++ +447 -0
- package/deps/libmdbx/test/jitter.c++ +197 -0
- package/deps/libmdbx/test/keygen.c++ +393 -0
- package/deps/libmdbx/test/keygen.h++ +130 -0
- package/deps/libmdbx/test/log.c++ +358 -0
- package/deps/libmdbx/test/log.h++ +91 -0
- package/deps/libmdbx/test/main.c++ +706 -0
- package/deps/libmdbx/test/nested.c++ +318 -0
- package/deps/libmdbx/test/osal-unix.c++ +647 -0
- package/deps/libmdbx/test/osal-windows.c++ +440 -0
- package/deps/libmdbx/test/osal.h++ +41 -0
- package/deps/libmdbx/test/stochastic.sh +690 -0
- package/deps/libmdbx/test/stub/LICENSE +24 -0
- package/deps/libmdbx/test/stub/README.md +8 -0
- package/deps/libmdbx/test/stub/pthread_barrier.c +104 -0
- package/deps/libmdbx/test/stub/pthread_barrier.h +77 -0
- package/deps/libmdbx/test/test.c++ +1551 -0
- package/deps/libmdbx/test/test.h++ +298 -0
- package/deps/libmdbx/test/tmux.conf +3 -0
- package/deps/libmdbx/test/try.c++ +30 -0
- package/deps/libmdbx/test/ttl.c++ +240 -0
- package/deps/libmdbx/test/utils.c++ +203 -0
- package/deps/libmdbx/test/utils.h++ +326 -0
- package/deps/libmdbx/test/valgrind_suppress.txt +536 -0
- package/lib/mdbx_evn_async.js +211 -0
- package/lib/mdbx_worker.js +195 -0
- package/lib/nativemou.js +6 -0
- package/package.json +38 -0
- package/src/async/envmou_close.cpp +34 -0
- package/src/async/envmou_close.hpp +32 -0
- package/src/async/envmou_copy_to.cpp +29 -0
- package/src/async/envmou_copy_to.hpp +38 -0
- package/src/async/envmou_keys.cpp +201 -0
- package/src/async/envmou_keys.hpp +50 -0
- package/src/async/envmou_open.cpp +38 -0
- package/src/async/envmou_open.hpp +33 -0
- package/src/async/envmou_query.cpp +167 -0
- package/src/async/envmou_query.hpp +53 -0
- package/src/dbimou.cpp +522 -0
- package/src/dbimou.hpp +82 -0
- package/src/env_arg0.hpp +24 -0
- package/src/envmou.cpp +445 -0
- package/src/envmou.hpp +116 -0
- package/src/modulemou.cpp +113 -0
- package/src/querymou.cpp +177 -0
- package/src/querymou.hpp +93 -0
- package/src/txnmou.cpp +254 -0
- package/src/txnmou.hpp +122 -0
- package/src/typemou.hpp +239 -0
- package/src/valuemou.hpp +194 -0
- package/test/async.js +67 -0
- package/test/e3.js +38 -0
- package/test/e4.js +89 -0
- package/test/e5.js +162 -0
- package/test/test-batch-ops.js +243 -0
- package/test/test-cursor-mode.js +84 -0
- package/test/test-multi-mode.js +87 -0
package/src/typemou.hpp
ADDED
|
@@ -0,0 +1,239 @@
|
|
|
1
|
+
#pragma once
|
|
2
|
+
|
|
3
|
+
#include <napi.h>
|
|
4
|
+
#include <mdbx.h++>
|
|
5
|
+
#include <cstdint>
|
|
6
|
+
#include <vector>
|
|
7
|
+
|
|
8
|
+
namespace mdbxmou {
|
|
9
|
+
|
|
10
|
+
using buffer_type = std::vector<char>;
|
|
11
|
+
|
|
12
|
+
struct txnmou_managed final
|
|
13
|
+
: public mdbx::txn_managed
|
|
14
|
+
{
|
|
15
|
+
txnmou_managed(MDBX_txn* txn)
|
|
16
|
+
{
|
|
17
|
+
txn::handle_ = txn;
|
|
18
|
+
}
|
|
19
|
+
};
|
|
20
|
+
|
|
21
|
+
struct cursormou_managed final
|
|
22
|
+
: public mdbx::cursor_managed
|
|
23
|
+
{
|
|
24
|
+
cursormou_managed(MDBX_cursor* cursor) noexcept
|
|
25
|
+
{
|
|
26
|
+
cursor::handle_ = cursor;
|
|
27
|
+
}
|
|
28
|
+
};
|
|
29
|
+
|
|
30
|
+
struct env_flag {
|
|
31
|
+
enum type : int {
|
|
32
|
+
validation = MDBX_VALIDATION,
|
|
33
|
+
rdonly = MDBX_RDONLY,
|
|
34
|
+
exclusive = MDBX_EXCLUSIVE,
|
|
35
|
+
accede = MDBX_ACCEDE,
|
|
36
|
+
writemap = MDBX_WRITEMAP,
|
|
37
|
+
nostickythreads = MDBX_NOSTICKYTHREADS,
|
|
38
|
+
nordahead = MDBX_NORDAHEAD,
|
|
39
|
+
nomeminit = MDBX_NOMEMINIT,
|
|
40
|
+
liforeclaim = MDBX_LIFORECLAIM,
|
|
41
|
+
nometasync = MDBX_NOMETASYNC,
|
|
42
|
+
safe_nosync = MDBX_SAFE_NOSYNC,
|
|
43
|
+
utterly_nosync = MDBX_UTTERLY_NOSYNC,
|
|
44
|
+
mask = MDBX_VALIDATION | MDBX_RDONLY | MDBX_EXCLUSIVE | MDBX_ACCEDE |
|
|
45
|
+
MDBX_WRITEMAP | MDBX_NOSTICKYTHREADS | MDBX_NORDAHEAD |
|
|
46
|
+
MDBX_NOMEMINIT | MDBX_LIFORECLAIM | MDBX_NOMETASYNC |
|
|
47
|
+
MDBX_SAFE_NOSYNC | MDBX_UTTERLY_NOSYNC
|
|
48
|
+
};
|
|
49
|
+
int val{};
|
|
50
|
+
|
|
51
|
+
static inline env_flag parse(const Napi::Value& arg0) {
|
|
52
|
+
return {arg0.As<Napi::Number>().Int32Value() & mask};
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
operator MDBX_env_flags() const noexcept {
|
|
56
|
+
return static_cast<MDBX_env_flags>(val & mask);
|
|
57
|
+
}
|
|
58
|
+
};
|
|
59
|
+
|
|
60
|
+
struct txn_mode {
|
|
61
|
+
enum type : int {
|
|
62
|
+
ro = MDBX_TXN_RDONLY
|
|
63
|
+
};
|
|
64
|
+
int val{};
|
|
65
|
+
|
|
66
|
+
static inline txn_mode parse(const Napi::Value& arg0) {
|
|
67
|
+
return {arg0.As<Napi::Number>().Int32Value() & ro};
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
operator MDBX_txn_flags() const noexcept {
|
|
71
|
+
return static_cast<MDBX_txn_flags>(val & ro);
|
|
72
|
+
}
|
|
73
|
+
};
|
|
74
|
+
|
|
75
|
+
struct query_mode
|
|
76
|
+
{
|
|
77
|
+
enum type : int {
|
|
78
|
+
get = 0x10000000,
|
|
79
|
+
del = 0x20000000,
|
|
80
|
+
upsert = MDBX_UPSERT,
|
|
81
|
+
update = MDBX_CURRENT,
|
|
82
|
+
insert_unique = MDBX_NOOVERWRITE,
|
|
83
|
+
write_mask = upsert | update | insert_unique,
|
|
84
|
+
mask = get | del | upsert | update | insert_unique
|
|
85
|
+
};
|
|
86
|
+
int val{get};
|
|
87
|
+
|
|
88
|
+
static inline query_mode parse(const txn_mode& mode, const Napi::Value& arg0) {
|
|
89
|
+
query_mode rc{arg0.As<Napi::Number>().Int32Value() & mask};
|
|
90
|
+
if ((mode.val & txn_mode::ro) && (rc.val & (del|upsert|update|insert_unique))) {
|
|
91
|
+
throw std::runtime_error("rw query in read-only transaction");
|
|
92
|
+
}
|
|
93
|
+
return rc;
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
operator mdbx::put_mode() const noexcept {
|
|
97
|
+
return static_cast<mdbx::put_mode>(val & write_mask);
|
|
98
|
+
}
|
|
99
|
+
};
|
|
100
|
+
|
|
101
|
+
struct key_mode
|
|
102
|
+
{
|
|
103
|
+
enum type : int {
|
|
104
|
+
reverse = MDBX_REVERSEKEY,
|
|
105
|
+
ordinal = MDBX_INTEGERKEY,
|
|
106
|
+
mask = MDBX_REVERSEKEY | MDBX_INTEGERKEY
|
|
107
|
+
};
|
|
108
|
+
int val{};
|
|
109
|
+
|
|
110
|
+
static inline key_mode parse(const Napi::Value& arg0) {
|
|
111
|
+
return {arg0.As<Napi::Number>().Int32Value() & mask};
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
operator mdbx::key_mode() const noexcept {
|
|
115
|
+
return static_cast<mdbx::key_mode>(val & mask);
|
|
116
|
+
}
|
|
117
|
+
};
|
|
118
|
+
|
|
119
|
+
struct value_mode
|
|
120
|
+
{
|
|
121
|
+
enum type : int {
|
|
122
|
+
multi = MDBX_DUPSORT,
|
|
123
|
+
multi_reverse = MDBX_DUPSORT | MDBX_REVERSEDUP,
|
|
124
|
+
multi_samelength = MDBX_DUPSORT | MDBX_DUPFIXED,
|
|
125
|
+
multi_ordinal = MDBX_DUPSORT | MDBX_DUPFIXED | MDBX_INTEGERDUP,
|
|
126
|
+
multi_reverse_samelength = MDBX_DUPSORT | MDBX_REVERSEDUP | MDBX_DUPFIXED,
|
|
127
|
+
mask = MDBX_DUPSORT | MDBX_REVERSEDUP | MDBX_DUPFIXED | MDBX_INTEGERDUP
|
|
128
|
+
};
|
|
129
|
+
int val{};
|
|
130
|
+
|
|
131
|
+
static inline value_mode parse(const Napi::Value& arg0) {
|
|
132
|
+
return {arg0.As<Napi::Number>().Int32Value() & mask};
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
operator mdbx::value_mode() const noexcept {
|
|
136
|
+
return static_cast<mdbx::value_mode>(val & mask);
|
|
137
|
+
}
|
|
138
|
+
};
|
|
139
|
+
|
|
140
|
+
|
|
141
|
+
struct base_flag
|
|
142
|
+
{
|
|
143
|
+
enum type : int {
|
|
144
|
+
string = 2,
|
|
145
|
+
number = 4,
|
|
146
|
+
bigint = 8,
|
|
147
|
+
mask_key = string | number | bigint,
|
|
148
|
+
mask_val = string
|
|
149
|
+
};
|
|
150
|
+
int val{};
|
|
151
|
+
|
|
152
|
+
static inline base_flag parse_key(const Napi::Value& arg0) {
|
|
153
|
+
return {arg0.As<Napi::Number>().Int32Value() & mask_key};
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
static inline base_flag parse_value(const value_mode& mode,
|
|
157
|
+
const Napi::Value& arg0) {
|
|
158
|
+
return {arg0.As<Napi::Number>().Int32Value() & mask_val};
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
static inline base_flag parse_value(const Napi::Value& arg0) {
|
|
162
|
+
return {arg0.As<Napi::Number>().Int32Value() & mask_val};
|
|
163
|
+
}
|
|
164
|
+
};
|
|
165
|
+
|
|
166
|
+
static inline key_mode parse_key_mode(Napi::Env env, const Napi::Value& arg0, base_flag& key_flag)
|
|
167
|
+
{
|
|
168
|
+
key_mode mode{};
|
|
169
|
+
if (arg0.IsBigInt()) {
|
|
170
|
+
bool lossless;
|
|
171
|
+
auto value = arg0.As<Napi::BigInt>().Int64Value(&lossless);
|
|
172
|
+
if (!lossless) {
|
|
173
|
+
throw Napi::Error::New(env, "BigInt value lossless conversion failed");
|
|
174
|
+
}
|
|
175
|
+
mode.val = static_cast<int>(value);
|
|
176
|
+
if (mode.val & key_mode::ordinal) {
|
|
177
|
+
// только если цифровой key_flag не был задан
|
|
178
|
+
if (key_flag.val <= base_flag::string) {
|
|
179
|
+
key_flag.val = base_flag::bigint;
|
|
180
|
+
}
|
|
181
|
+
}
|
|
182
|
+
} else if (arg0.IsNumber()) {
|
|
183
|
+
mode = key_mode::parse(arg0);
|
|
184
|
+
if (mode.val & key_mode::ordinal) {
|
|
185
|
+
// только если цифровой key_flag не был задан
|
|
186
|
+
if (key_flag.val <= base_flag::string) {
|
|
187
|
+
key_flag.val = base_flag::number;
|
|
188
|
+
}
|
|
189
|
+
}
|
|
190
|
+
} else {
|
|
191
|
+
throw Napi::Error::New(env, "Invalid argument type for key mode");
|
|
192
|
+
}
|
|
193
|
+
return mode;
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
struct db_mode
|
|
197
|
+
{
|
|
198
|
+
enum type : int {
|
|
199
|
+
create = MDBX_CREATE,
|
|
200
|
+
accede = MDBX_ACCEDE,
|
|
201
|
+
mask = MDBX_CREATE | MDBX_ACCEDE
|
|
202
|
+
};
|
|
203
|
+
int val{};
|
|
204
|
+
|
|
205
|
+
static inline db_mode parse(const txn_mode& mode, const Napi::Value& arg0) {
|
|
206
|
+
db_mode rc{arg0.As<Napi::Number>().Int32Value() & mask};
|
|
207
|
+
if ((mode.val & txn_mode::ro) && (rc.val & db_mode::create)) {
|
|
208
|
+
throw std::runtime_error("create DB in read-only transaction");
|
|
209
|
+
}
|
|
210
|
+
return rc;
|
|
211
|
+
}
|
|
212
|
+
};
|
|
213
|
+
|
|
214
|
+
static inline auto parse_cursor_mode(const Napi::Value& arg0) {
|
|
215
|
+
using move_operation = mdbx::cursor::move_operation;
|
|
216
|
+
if (arg0.IsString()) {
|
|
217
|
+
std::string mode = arg0.As<Napi::String>().Utf8Value();
|
|
218
|
+
if (mode == "first") return move_operation::first;
|
|
219
|
+
if (mode == "last") return move_operation::last;
|
|
220
|
+
if (mode == "next") return move_operation::next;
|
|
221
|
+
if (mode == "prev") return move_operation::previous;
|
|
222
|
+
if (mode == "keyLesser" || mode == "key_lesser_than")
|
|
223
|
+
return move_operation::key_lesser_than;
|
|
224
|
+
if (mode == "keyLesserOrEqual" || mode == "key_lesser_or_equal")
|
|
225
|
+
return move_operation::key_lesser_or_equal;
|
|
226
|
+
if (mode == "keyEqual" || mode == "key_equal")
|
|
227
|
+
return move_operation::key_equal;
|
|
228
|
+
if (mode == "keyGreaterOrEqual" || mode == "key_greater_or_equal")
|
|
229
|
+
return move_operation::key_greater_or_equal;
|
|
230
|
+
if (mode == "keyGreater" || mode == "key_greater_than")
|
|
231
|
+
return move_operation::key_greater_than;
|
|
232
|
+
// Если не найдено, используем по умолчанию
|
|
233
|
+
return move_operation::key_greater_or_equal;
|
|
234
|
+
}
|
|
235
|
+
return static_cast<move_operation>(
|
|
236
|
+
arg0.As<Napi::Number>().Int32Value());
|
|
237
|
+
}
|
|
238
|
+
|
|
239
|
+
} // namespace mdbxmou
|
package/src/valuemou.hpp
ADDED
|
@@ -0,0 +1,194 @@
|
|
|
1
|
+
#pragma once
|
|
2
|
+
|
|
3
|
+
#include "typemou.hpp"
|
|
4
|
+
|
|
5
|
+
namespace mdbxmou {
|
|
6
|
+
|
|
7
|
+
class valuemou
|
|
8
|
+
: public mdbx::slice
|
|
9
|
+
{
|
|
10
|
+
public:
|
|
11
|
+
valuemou() = default;
|
|
12
|
+
|
|
13
|
+
valuemou(const mdbx::slice& arg0) noexcept
|
|
14
|
+
: mdbx::slice{arg0}
|
|
15
|
+
{ }
|
|
16
|
+
|
|
17
|
+
valuemou(const Napi::Buffer<char>& arg0) noexcept
|
|
18
|
+
: mdbx::slice{arg0.Data(), arg0.Length()}
|
|
19
|
+
{ }
|
|
20
|
+
|
|
21
|
+
valuemou(const buffer_type& arg0) noexcept
|
|
22
|
+
: mdbx::slice{arg0.data(), arg0.size()}
|
|
23
|
+
{ }
|
|
24
|
+
|
|
25
|
+
valuemou(const Napi::Buffer<char>& arg0, buffer_type& mem)
|
|
26
|
+
{
|
|
27
|
+
auto ptr = arg0.Data();
|
|
28
|
+
mem.assign(ptr, ptr + arg0.Length());
|
|
29
|
+
assign(mem.data(), mem.size());
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
valuemou(const Napi::String& arg0,
|
|
33
|
+
const Napi::Env& env, buffer_type& mem)
|
|
34
|
+
{
|
|
35
|
+
size_t length;
|
|
36
|
+
auto status =
|
|
37
|
+
napi_get_value_string_utf8(env, arg0, nullptr, 0, &length);
|
|
38
|
+
if (status != napi_ok) {
|
|
39
|
+
throw Napi::Error::New(env, "napi_get_value_string_utf8 length");
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
mem.reserve(length + 1);
|
|
43
|
+
mem.resize(length);
|
|
44
|
+
|
|
45
|
+
status = napi_get_value_string_utf8(
|
|
46
|
+
env, arg0, mem.data(), mem.capacity(), nullptr);
|
|
47
|
+
if (status != napi_ok) {
|
|
48
|
+
throw Napi::Error::New(env, "napi_get_value_string_utf8 copyout");
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
assign(mem.data(), mem.size());
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
static inline valuemou from(const Napi::Value& arg0,
|
|
55
|
+
const Napi::Env& env, buffer_type& mem)
|
|
56
|
+
{
|
|
57
|
+
if (arg0.IsBuffer()) {
|
|
58
|
+
return {arg0.As<Napi::Buffer<char>>()};
|
|
59
|
+
} else if (!arg0.IsString()) {
|
|
60
|
+
throw Napi::Error::New(env, "unsupported value");
|
|
61
|
+
}
|
|
62
|
+
return {arg0.As<Napi::String>(), env, mem};
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
Napi::Value to_string(const Napi::Env& env) const
|
|
66
|
+
{
|
|
67
|
+
return Napi::String::New(env,
|
|
68
|
+
char_ptr(), length());
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
Napi::Value to_buffer(const Napi::Env& env) const
|
|
72
|
+
{
|
|
73
|
+
return Napi::Buffer<char>::Copy(env,
|
|
74
|
+
char_ptr(), length());
|
|
75
|
+
}
|
|
76
|
+
};
|
|
77
|
+
|
|
78
|
+
class keymou final
|
|
79
|
+
: public valuemou
|
|
80
|
+
{
|
|
81
|
+
public:
|
|
82
|
+
keymou() = default;
|
|
83
|
+
|
|
84
|
+
keymou(const valuemou& arg0) noexcept
|
|
85
|
+
: valuemou{arg0}
|
|
86
|
+
{ }
|
|
87
|
+
|
|
88
|
+
keymou(const mdbx::slice& arg0) noexcept
|
|
89
|
+
: valuemou{arg0}
|
|
90
|
+
{ }
|
|
91
|
+
|
|
92
|
+
keymou(const Napi::Buffer<char>& arg0)
|
|
93
|
+
: valuemou{arg0}
|
|
94
|
+
{ }
|
|
95
|
+
|
|
96
|
+
keymou(const buffer_type& arg0) noexcept
|
|
97
|
+
: valuemou{arg0}
|
|
98
|
+
{ }
|
|
99
|
+
|
|
100
|
+
keymou(const std::uint64_t& arg0) noexcept
|
|
101
|
+
: valuemou{mdbx::slice{&arg0, sizeof(arg0)}}
|
|
102
|
+
{ }
|
|
103
|
+
|
|
104
|
+
keymou(const Napi::Buffer<char>& arg0, buffer_type& mem)
|
|
105
|
+
: valuemou{arg0, mem}
|
|
106
|
+
{ }
|
|
107
|
+
|
|
108
|
+
keymou(const Napi::String& arg0,
|
|
109
|
+
const Napi::Env& env, buffer_type& mem)
|
|
110
|
+
: valuemou{arg0, env, mem}
|
|
111
|
+
{ }
|
|
112
|
+
|
|
113
|
+
keymou(const Napi::Number& arg0, std::uint64_t& mem)
|
|
114
|
+
{
|
|
115
|
+
auto value = arg0.Int64Value();
|
|
116
|
+
if (value < 0) {
|
|
117
|
+
throw std::runtime_error("Number negative");
|
|
118
|
+
}
|
|
119
|
+
mem = static_cast<std::uint64_t>(value);
|
|
120
|
+
assign(&mem, sizeof(mem));
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
keymou(const Napi::Number& arg0,
|
|
124
|
+
const Napi::Env& env, std::uint64_t& mem)
|
|
125
|
+
{
|
|
126
|
+
auto value = arg0.Int64Value();
|
|
127
|
+
if (value < 0) {
|
|
128
|
+
throw Napi::Error::New(env, "Number negative");
|
|
129
|
+
}
|
|
130
|
+
mem = static_cast<std::uint64_t>(value);
|
|
131
|
+
assign(&mem, sizeof(mem));
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
keymou(const Napi::BigInt& arg0,std::uint64_t& mem)
|
|
135
|
+
{
|
|
136
|
+
bool looseless;
|
|
137
|
+
mem = arg0.Uint64Value(&looseless);
|
|
138
|
+
if (!looseless) {
|
|
139
|
+
throw std::runtime_error("BigInt !looseless");
|
|
140
|
+
}
|
|
141
|
+
assign(&mem, sizeof(mem));
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
keymou(const Napi::BigInt& arg0,
|
|
145
|
+
const Napi::Env& env, std::uint64_t& mem)
|
|
146
|
+
{
|
|
147
|
+
bool looseless;
|
|
148
|
+
mem = arg0.Uint64Value(&looseless);
|
|
149
|
+
if (!looseless) {
|
|
150
|
+
throw Napi::Error::New(env, "BigInt !looseless");
|
|
151
|
+
}
|
|
152
|
+
assign(&mem, sizeof(mem));
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
static inline keymou from(const Napi::Value& arg0,
|
|
156
|
+
const Napi::Env& env, buffer_type& mem)
|
|
157
|
+
{
|
|
158
|
+
return {valuemou::from(arg0, env, mem)};
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
static inline keymou from(const Napi::Value& arg0,
|
|
162
|
+
const Napi::Env& env, std::uint64_t& mem)
|
|
163
|
+
{
|
|
164
|
+
if (arg0.IsBigInt()) {
|
|
165
|
+
return {arg0.As<Napi::BigInt>(), env, mem};
|
|
166
|
+
} else if (!arg0.IsNumber()) {
|
|
167
|
+
throw Napi::Error::New(env, "key must be a Number or BigInt");
|
|
168
|
+
}
|
|
169
|
+
return {arg0.As<Napi::Number>(), env, mem};
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
static inline keymou from(const Napi::Value& arg0,
|
|
173
|
+
const Napi::Env& env, buffer_type& buf, std::uint64_t& num)
|
|
174
|
+
{
|
|
175
|
+
if (arg0.IsBuffer() || arg0.IsString()) {
|
|
176
|
+
return from(arg0, env, buf);
|
|
177
|
+
} else if (!(arg0.IsNumber() || arg0.IsBigInt())) {
|
|
178
|
+
throw Napi::Error::New(env, "key must be a Buffer,String,Number or BigInt");
|
|
179
|
+
}
|
|
180
|
+
return from(arg0, env, num);
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
Napi::Value to_number(const Napi::Env& env) const
|
|
184
|
+
{
|
|
185
|
+
return Napi::Number::New(env, as_int64());
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
Napi::Value to_bigint(const Napi::Env& env) const
|
|
189
|
+
{
|
|
190
|
+
return Napi::BigInt::New(env, as_uint64());
|
|
191
|
+
}
|
|
192
|
+
};
|
|
193
|
+
|
|
194
|
+
} // mdbxmou
|
package/test/async.js
ADDED
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
const fs = require("fs");
|
|
3
|
+
const { MDBX_Async_Env } = require("../lib/mdbx_evn_async.js");
|
|
4
|
+
const MDBX = require("../lib/nativemou.js");
|
|
5
|
+
const { MDBX_Param } = MDBX;
|
|
6
|
+
|
|
7
|
+
(async () => {
|
|
8
|
+
const testPath = "async-test-db";
|
|
9
|
+
await fs.promises.rm(testPath, { recursive: true, force: true }).catch(() => {});
|
|
10
|
+
|
|
11
|
+
// Создаем среду с параметрами и количеством worker'ов
|
|
12
|
+
const envOptions = {
|
|
13
|
+
path: testPath,
|
|
14
|
+
envFlag: MDBX_Param.envFlag.nostickythreads
|
|
15
|
+
};
|
|
16
|
+
const env = new MDBX_Async_Env(1);
|
|
17
|
+
|
|
18
|
+
// Обработка сигналов для корректного завершения
|
|
19
|
+
const cleanup = async () => {
|
|
20
|
+
console.log("\nReceived interrupt signal, cleaning up...");
|
|
21
|
+
try {
|
|
22
|
+
await env.terminate();
|
|
23
|
+
console.log("Cleanup completed");
|
|
24
|
+
} catch (e) {
|
|
25
|
+
console.error("Cleanup error:", e.message);
|
|
26
|
+
}
|
|
27
|
+
process.exit(0);
|
|
28
|
+
};
|
|
29
|
+
|
|
30
|
+
process.on('SIGINT', cleanup);
|
|
31
|
+
process.on('SIGTERM', cleanup);
|
|
32
|
+
|
|
33
|
+
try {
|
|
34
|
+
await env.open({ path: testPath });
|
|
35
|
+
|
|
36
|
+
const { keyMode } = MDBX_Param;
|
|
37
|
+
|
|
38
|
+
// write txn
|
|
39
|
+
const w = await env.startWrite();
|
|
40
|
+
const dbi = await w.openMap({ keyMode: keyMode.ordinal, create: true });
|
|
41
|
+
await dbi.put(1n, "one");
|
|
42
|
+
await dbi.put(2n, "two");
|
|
43
|
+
await w.commit();
|
|
44
|
+
|
|
45
|
+
// read txn – может уйти в другой worker
|
|
46
|
+
const r = await env.startRead();
|
|
47
|
+
const dbi2 = await r.openMap({ keyMode: keyMode.ordinal });
|
|
48
|
+
const v = await dbi2.get(2n);
|
|
49
|
+
console.log("get(2) =", v);
|
|
50
|
+
await r.commit();
|
|
51
|
+
|
|
52
|
+
await env.close();
|
|
53
|
+
console.log("Database closed");
|
|
54
|
+
|
|
55
|
+
// Завершаем все worker'ы
|
|
56
|
+
await env.terminate();
|
|
57
|
+
console.log("Workers terminated");
|
|
58
|
+
} catch (error) {
|
|
59
|
+
console.error("Test failed:", error);
|
|
60
|
+
try {
|
|
61
|
+
await env.terminate();
|
|
62
|
+
} catch (e) {
|
|
63
|
+
console.error("Cleanup error:", e.message);
|
|
64
|
+
}
|
|
65
|
+
process.exit(1);
|
|
66
|
+
}
|
|
67
|
+
})();
|
package/test/e3.js
ADDED
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
const fs = require('fs');
|
|
4
|
+
const MDBX = require('../lib/nativemou.js');
|
|
5
|
+
const { MDBX_Env, MDBX_Param } = MDBX;
|
|
6
|
+
|
|
7
|
+
const test = async () => {
|
|
8
|
+
const db_dir = 'e3';
|
|
9
|
+
|
|
10
|
+
await fs.promises.rm(db_dir, { recursive: true, force: true });
|
|
11
|
+
|
|
12
|
+
console.log("MDBX_Param:", MDBX_Param);
|
|
13
|
+
// получаем константы
|
|
14
|
+
const { keyMode } = MDBX_Param;
|
|
15
|
+
|
|
16
|
+
const db = new MDBX_Env();
|
|
17
|
+
|
|
18
|
+
console.log('Opening database...');
|
|
19
|
+
|
|
20
|
+
await db.open({
|
|
21
|
+
path: db_dir
|
|
22
|
+
});
|
|
23
|
+
|
|
24
|
+
console.log('Start write');
|
|
25
|
+
const count = 100000;
|
|
26
|
+
for (let i = 0; i < count; i++) {
|
|
27
|
+
const txn = db.startWrite();
|
|
28
|
+
const dbi = txn.createMap(keyMode.ordinal);
|
|
29
|
+
dbi.put(i, `value_${i}`);
|
|
30
|
+
txn.commit();
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
console.log('Write finish');
|
|
34
|
+
|
|
35
|
+
await db.close();
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
test().catch(console.error);
|
package/test/e4.js
ADDED
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
const fs = require('fs');
|
|
4
|
+
const MDBX = require('../lib/nativemou.js');
|
|
5
|
+
const { MDBX_Env, MDBX_Param } = MDBX;
|
|
6
|
+
|
|
7
|
+
const test = async () => {
|
|
8
|
+
const path4 = 'e4';
|
|
9
|
+
const path5 = 'e5';
|
|
10
|
+
|
|
11
|
+
console.log("MDBX_Param:", MDBX_Param);
|
|
12
|
+
|
|
13
|
+
await Promise.all([
|
|
14
|
+
fs.promises.rm(path4, { recursive: true, force: true }),
|
|
15
|
+
fs.promises.rm(path5, { recursive: true, force: true })
|
|
16
|
+
]);
|
|
17
|
+
|
|
18
|
+
const db4 = new MDBX_Env();
|
|
19
|
+
const db5 = new MDBX_Env();
|
|
20
|
+
|
|
21
|
+
console.log('Opening database...');
|
|
22
|
+
|
|
23
|
+
const { valueFlag } = MDBX_Param;
|
|
24
|
+
await Promise.all([
|
|
25
|
+
db4.open({
|
|
26
|
+
path: path4,
|
|
27
|
+
valueFlag: valueFlag.string
|
|
28
|
+
}),
|
|
29
|
+
db5.open({
|
|
30
|
+
path: path5,
|
|
31
|
+
})
|
|
32
|
+
]);
|
|
33
|
+
|
|
34
|
+
console.log('Start write test...');
|
|
35
|
+
const count = 10;
|
|
36
|
+
const { keyMode } = MDBX_Param;
|
|
37
|
+
const txn = db4.startWrite();
|
|
38
|
+
// при изменении типа ключей надо указывать MDBX_CREATE если базы еще нет
|
|
39
|
+
const dbi = txn.createMap(keyMode.ordinal);
|
|
40
|
+
for (let i = 0; i < count; i++) {
|
|
41
|
+
dbi.put(i, `value_${i}`);
|
|
42
|
+
}
|
|
43
|
+
txn.commit();
|
|
44
|
+
console.log('Start write finish');
|
|
45
|
+
|
|
46
|
+
await Promise.all([await db4.close(), await db5.close()]);
|
|
47
|
+
|
|
48
|
+
//await db.copyTo('e4_copy_async');
|
|
49
|
+
|
|
50
|
+
await db4.open({
|
|
51
|
+
path: path4,
|
|
52
|
+
valueFlag: valueFlag.string
|
|
53
|
+
});
|
|
54
|
+
|
|
55
|
+
let val = "";
|
|
56
|
+
{
|
|
57
|
+
const txn = db4.startRead();
|
|
58
|
+
// для read транакций не нужно указывать MDBX_CREATE иначе будет Permission denied
|
|
59
|
+
const dbi = txn.openMap(BigInt(keyMode.ordinal));
|
|
60
|
+
const stat = dbi.stat();
|
|
61
|
+
for (let i = 0; i < count; i++) {
|
|
62
|
+
val = dbi.get(i);
|
|
63
|
+
}
|
|
64
|
+
console.log('last value:', val.toString());
|
|
65
|
+
console.log('stat:', JSON.stringify(stat));
|
|
66
|
+
txn.commit();
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
{
|
|
70
|
+
const txn = db4.startRead();
|
|
71
|
+
const dbi = txn.openMap(BigInt(keyMode.ordinal));
|
|
72
|
+
dbi.forEach((key, value) => {
|
|
73
|
+
console.log(key, value);
|
|
74
|
+
});
|
|
75
|
+
txn.commit();
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
|
|
79
|
+
const { queryMode, dbMode, keyFlag } = MDBX_Param;
|
|
80
|
+
const result = await db4.query([
|
|
81
|
+
{ dbMode: dbMode.accede, keyMode: keyMode.ordinal, mode: queryMode.get, item: [{ key: 0 }, { key: 1n }, { key: 2n }] },
|
|
82
|
+
{ dbMode: dbMode.accede, keyMode: keyMode.ordinal, mode: queryMode.get, item: [{ key: 3n }, { key: 4n }, { key: 5n }] }
|
|
83
|
+
]);
|
|
84
|
+
console.log('query', JSON.stringify(result));
|
|
85
|
+
|
|
86
|
+
await db4.close();
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
test().catch(console.error);
|