@ohos-ports/lmdb 2.5.3 → 2.8.5-beta.1
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/LICENSE +20 -20
- package/README.md +72 -28
- package/SECURITY.md +12 -12
- package/bin/download-prebuilds.js +15 -0
- package/binding.gyp +115 -111
- package/build/Release/lmdb.node +0 -0
- package/caching.js +212 -156
- package/dependencies/lmdb/libraries/liblmdb/COPYRIGHT +20 -20
- package/dependencies/lmdb/libraries/liblmdb/Doxyfile +1631 -1631
- package/dependencies/lmdb/libraries/liblmdb/LICENSE +47 -47
- package/dependencies/lmdb/libraries/liblmdb/Makefile +136 -136
- package/dependencies/lmdb/libraries/liblmdb/chacha8.c +183 -183
- package/dependencies/lmdb/libraries/liblmdb/chacha8.h +14 -14
- package/dependencies/lmdb/libraries/liblmdb/crypto.c +121 -121
- package/dependencies/lmdb/libraries/liblmdb/intro.doc +192 -192
- package/dependencies/lmdb/libraries/liblmdb/lmdb.h +28 -3
- package/dependencies/lmdb/libraries/liblmdb/mdb.c +157 -31
- package/dependencies/lmdb/libraries/liblmdb/mdb_copy.1 +74 -74
- package/dependencies/lmdb/libraries/liblmdb/mdb_copy.c +106 -106
- package/dependencies/lmdb/libraries/liblmdb/mdb_drop.1 +53 -53
- package/dependencies/lmdb/libraries/liblmdb/mdb_drop.c +154 -154
- package/dependencies/lmdb/libraries/liblmdb/mdb_dump.1 +94 -94
- package/dependencies/lmdb/libraries/liblmdb/mdb_dump.c +333 -333
- package/dependencies/lmdb/libraries/liblmdb/mdb_load.1 +97 -97
- package/dependencies/lmdb/libraries/liblmdb/mdb_load.c +530 -530
- package/dependencies/lmdb/libraries/liblmdb/mdb_stat.1 +83 -83
- package/dependencies/lmdb/libraries/liblmdb/mdb_stat.c +276 -276
- package/dependencies/lmdb/libraries/liblmdb/midl-sparse.c +452 -0
- package/dependencies/lmdb/libraries/liblmdb/midl.c +452 -452
- package/dependencies/lmdb/libraries/liblmdb/midl.h +208 -208
- package/dependencies/lmdb/libraries/liblmdb/module.c +101 -101
- package/dependencies/lmdb/libraries/liblmdb/module.h +16 -16
- package/dependencies/lmdb/libraries/liblmdb/mtest.c +178 -178
- package/dependencies/lmdb/libraries/liblmdb/mtest2.c +124 -124
- package/dependencies/lmdb/libraries/liblmdb/mtest3.c +133 -133
- package/dependencies/lmdb/libraries/liblmdb/mtest4.c +168 -168
- package/dependencies/lmdb/libraries/liblmdb/mtest5.c +135 -135
- package/dependencies/lmdb/libraries/liblmdb/mtest6.c +141 -141
- package/dependencies/lmdb/libraries/liblmdb/mtest_enc.c +190 -190
- package/dependencies/lmdb/libraries/liblmdb/mtest_enc2.c +189 -189
- package/dependencies/lmdb/libraries/liblmdb/mtest_remap.c +177 -177
- package/dependencies/lmdb/libraries/liblmdb/sample-bdb.txt +73 -73
- package/dependencies/lmdb/libraries/liblmdb/sample-mdb.txt +62 -62
- package/dependencies/lmdb/libraries/liblmdb/tooltag +27 -27
- package/dependencies/lmdb-data-v1/libraries/liblmdb/CHANGES +266 -0
- package/dependencies/lmdb-data-v1/libraries/liblmdb/COPYRIGHT +20 -20
- package/dependencies/lmdb-data-v1/libraries/liblmdb/Doxyfile +1631 -1631
- package/dependencies/lmdb-data-v1/libraries/liblmdb/LICENSE +47 -47
- package/dependencies/lmdb-data-v1/libraries/liblmdb/intro.doc +192 -192
- package/dependencies/lmdb-data-v1/libraries/liblmdb/lmdb.h +1608 -1653
- package/dependencies/lmdb-data-v1/libraries/liblmdb/mdb.c +10320 -11359
- package/dependencies/lmdb-data-v1/libraries/liblmdb/mdb_copy.1 +55 -61
- package/dependencies/lmdb-data-v1/libraries/liblmdb/mdb_copy.c +82 -84
- package/dependencies/lmdb-data-v1/libraries/liblmdb/mdb_dump.1 +75 -81
- package/dependencies/lmdb-data-v1/libraries/liblmdb/mdb_dump.c +319 -319
- package/dependencies/lmdb-data-v1/libraries/liblmdb/mdb_load.1 +84 -84
- package/dependencies/lmdb-data-v1/libraries/liblmdb/mdb_load.c +496 -492
- package/dependencies/lmdb-data-v1/libraries/liblmdb/mdb_stat.1 +64 -70
- package/dependencies/lmdb-data-v1/libraries/liblmdb/mdb_stat.c +263 -264
- package/dependencies/lmdb-data-v1/libraries/liblmdb/midl.c +359 -421
- package/dependencies/lmdb-data-v1/libraries/liblmdb/midl.h +186 -200
- package/dependencies/lmdb-data-v1/libraries/liblmdb/mtest.c +177 -177
- package/dependencies/lmdb-data-v1/libraries/liblmdb/mtest2.c +124 -124
- package/dependencies/lmdb-data-v1/libraries/liblmdb/mtest3.c +133 -133
- package/dependencies/lmdb-data-v1/libraries/liblmdb/mtest4.c +168 -168
- package/dependencies/lmdb-data-v1/libraries/liblmdb/mtest5.c +135 -135
- package/dependencies/lmdb-data-v1/libraries/liblmdb/mtest6.c +141 -141
- package/dependencies/lmdb-data-v1/libraries/liblmdb/sample-bdb.txt +73 -73
- package/dependencies/lmdb-data-v1/libraries/liblmdb/sample-mdb.txt +62 -62
- package/dependencies/lmdb-data-v1/libraries/liblmdb/tooltag +22 -27
- package/dependencies/lz4/LICENSE +11 -11
- package/dependencies/lz4/lib/LICENSE +24 -24
- package/dependencies/lz4/lib/Makefile +225 -0
- package/dependencies/lz4/lib/README.md +169 -137
- package/dependencies/lz4/lib/dll/example/Makefile +63 -0
- package/dependencies/lz4/lib/dll/example/README.md +69 -69
- package/dependencies/lz4/lib/dll/liblz4.def +62 -62
- package/dependencies/lz4/lib/liblz4-dll.rc.in +35 -35
- package/dependencies/lz4/lib/liblz4.pc.in +14 -14
- package/dependencies/lz4/lib/lz4.c +2722 -2495
- package/dependencies/lz4/lib/lz4.h +842 -774
- package/dependencies/lz4/lib/lz4file.c +311 -0
- package/dependencies/lz4/lib/lz4file.h +93 -0
- package/dependencies/lz4/lib/lz4frame.c +2078 -1899
- package/dependencies/lz4/lib/lz4frame.h +692 -623
- package/dependencies/lz4/lib/lz4frame_static.h +47 -47
- package/dependencies/lz4/lib/lz4hc.c +1631 -1615
- package/dependencies/lz4/lib/lz4hc.h +413 -413
- package/dependencies/lz4/lib/xxhash.c +1030 -1030
- package/dependencies/lz4/lib/xxhash.h +328 -328
- package/dependencies/v8/v8-fast-api-calls-v16.h +790 -790
- package/dependencies/v8/v8-fast-api-calls.h +784 -888
- package/dist/index.cjs +1050 -584
- package/dist/index.cjs.map +1 -1
- package/index.d.cts +420 -0
- package/index.d.ts +450 -385
- package/index.js +38 -37
- package/keys.js +116 -102
- package/level.js +26 -26
- package/native.js +8 -5
- package/node-index.js +21 -17
- package/open.js +51 -17
- package/package.json +55 -21
- package/read.js +338 -95
- package/src/compression.cpp +12 -9
- package/src/cursor.cpp +82 -31
- package/src/dbi.cpp +78 -40
- package/src/env.cpp +336 -68
- package/src/lmdb-js.cpp +64 -64
- package/src/lmdb-js.h +83 -49
- package/src/misc.cpp +297 -28
- package/src/ordered-binary.cpp +46 -46
- package/src/txn.cpp +210 -257
- package/src/v8-functions.cpp +170 -166
- package/src/windows.c +34 -34
- package/src/writer.cpp +169 -84
- package/util/RangeIterable.js +112 -17
- package/util/set-optional-deps.cjs +14 -10
- package/util/when.js +8 -8
- package/write.js +145 -121
- package/dependencies/lmdb-data-v1/libraries/liblmdb/Makefile +0 -118
- package/dependencies/lmdb-data-v1/libraries/liblmdb/mdb_drop.1 +0 -40
- package/dependencies/lmdb-data-v1/libraries/liblmdb/mdb_drop.c +0 -135
- package/rollup.config.js +0 -12
package/src/compression.cpp
CHANGED
|
@@ -16,7 +16,7 @@ Compression::Compression(const CallbackInfo& info) : ObjectWrap<Compression>(inf
|
|
|
16
16
|
throwError(info.Env(), "Dictionary must be a buffer");
|
|
17
17
|
return;
|
|
18
18
|
}
|
|
19
|
-
|
|
19
|
+
napi_get_buffer_info(info.Env(), dictionaryOption, (void**) &dictionary, &dictSize);
|
|
20
20
|
dictSize = (dictSize >> 3) << 3; // make sure it is word-aligned
|
|
21
21
|
}
|
|
22
22
|
auto thresholdOption = info[0].As<Object>().Get("threshold");
|
|
@@ -34,10 +34,13 @@ Compression::Compression(const CallbackInfo& info) : ObjectWrap<Compression>(inf
|
|
|
34
34
|
}
|
|
35
35
|
|
|
36
36
|
Napi::Value Compression::setBuffer(const CallbackInfo& info) {
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
this->
|
|
37
|
+
size_t length;
|
|
38
|
+
napi_get_arraybuffer_info(info.Env(), info[0], (void**) &this->decompressTarget, &length);
|
|
39
|
+
unsigned int offset = info[1].As<Number>();
|
|
40
|
+
this->decompressTarget += offset;
|
|
41
|
+
this->decompressSize = info[2].As<Number>();
|
|
42
|
+
this->dictionarySize = info[4].As<Number>();
|
|
43
|
+
napi_get_buffer_info(info.Env(), info[3], (void**) &this->dictionary, &length);
|
|
41
44
|
return info.Env().Undefined();
|
|
42
45
|
}
|
|
43
46
|
void Compression::decompress(MDB_val& data, bool &isValid, bool canAllocate) {
|
|
@@ -180,10 +183,10 @@ class CompressionWorker : public AsyncWorker {
|
|
|
180
183
|
|
|
181
184
|
NAPI_FUNCTION(EnvWrap::compress) {
|
|
182
185
|
ARGS(3)
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
186
|
+
GET_INT64_ARG(0);
|
|
187
|
+
EnvWrap* ew = (EnvWrap*) i64;
|
|
188
|
+
napi_get_value_int64(env, args[1], &i64);
|
|
189
|
+
double* compressionAddress = (double*) i64;
|
|
187
190
|
CompressionWorker* worker = new CompressionWorker(ew, (double*) compressionAddress, Function(env, args[2]));
|
|
188
191
|
worker->Queue();
|
|
189
192
|
RETURN_UNDEFINED;
|
package/src/cursor.cpp
CHANGED
|
@@ -3,6 +3,15 @@
|
|
|
3
3
|
|
|
4
4
|
using namespace Napi;
|
|
5
5
|
|
|
6
|
+
const int INCLUDE_VALUES = 0x100;
|
|
7
|
+
const int REVERSE = 0x400;
|
|
8
|
+
const int VALUES_FOR_KEY = 0x800;
|
|
9
|
+
const int ONLY_COUNT = 0x1000;
|
|
10
|
+
const int RENEW_CURSOR = 0x2000;
|
|
11
|
+
const int EXACT_MATCH = 0x4000;
|
|
12
|
+
const int INCLUSIVE_END = 0x8000;
|
|
13
|
+
const int EXCLUSIVE_START = 0x10000;
|
|
14
|
+
|
|
6
15
|
CursorWrap::CursorWrap(const CallbackInfo& info) : Napi::ObjectWrap<CursorWrap>(info) {
|
|
7
16
|
this->keyType = LmdbKeyType::StringKey;
|
|
8
17
|
this->freeKey = nullptr;
|
|
@@ -14,10 +23,11 @@ CursorWrap::CursorWrap(const CallbackInfo& info) : Napi::ObjectWrap<CursorWrap>(
|
|
|
14
23
|
|
|
15
24
|
DbiWrap *dw;
|
|
16
25
|
napi_unwrap(info.Env(), info[0], (void**)&dw);
|
|
17
|
-
|
|
26
|
+
int64_t tw_address = 0;
|
|
27
|
+
napi_get_value_int64(info.Env(), info[1], &tw_address);
|
|
18
28
|
// Open the cursor
|
|
19
29
|
MDB_cursor *cursor;
|
|
20
|
-
MDB_txn *txn = dw->ew->getReadTxn();
|
|
30
|
+
MDB_txn *txn = dw->ew->getReadTxn(tw_address);
|
|
21
31
|
int rc = mdb_cursor_open(txn, dw->dbi, &cursor);
|
|
22
32
|
if (rc != 0) {
|
|
23
33
|
throwLmdbError(info.Env(), rc);
|
|
@@ -77,22 +87,30 @@ int CursorWrap::returnEntry(int lastRC, MDB_val &key, MDB_val &data) {
|
|
|
77
87
|
}
|
|
78
88
|
if (endKey.mv_size > 0) {
|
|
79
89
|
int comparison;
|
|
80
|
-
if (flags &
|
|
90
|
+
if (flags & VALUES_FOR_KEY)
|
|
81
91
|
comparison = mdb_dcmp(txn, dw->dbi, &endKey, &data);
|
|
82
92
|
else
|
|
83
93
|
comparison = mdb_cmp(txn, dw->dbi, &endKey, &key);
|
|
84
|
-
if ((flags &
|
|
85
|
-
|
|
94
|
+
if ((flags & REVERSE) ? comparison >= 0 : (comparison <= 0)) {
|
|
95
|
+
if (!((flags & INCLUSIVE_END) && comparison == 0))
|
|
96
|
+
return 0;
|
|
86
97
|
}
|
|
87
98
|
}
|
|
88
99
|
char* keyBuffer = dw->ew->keyBuffer;
|
|
89
|
-
if (flags &
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
100
|
+
if (flags & INCLUDE_VALUES) {
|
|
101
|
+
int result = getVersionAndUncompress(data, dw);
|
|
102
|
+
bool fits = true;
|
|
103
|
+
if (result) {
|
|
104
|
+
fits = valToBinaryFast(data, dw); // it fit in the global/compression-target buffer
|
|
105
|
+
}
|
|
106
|
+
if (fits || result == 2 || data.mv_size < SHARED_BUFFER_THRESHOLD) {// if it was decompressed
|
|
107
|
+
*((uint32_t*)keyBuffer) = data.mv_size;
|
|
108
|
+
*((uint32_t*)(keyBuffer + 4)) = 0; // buffer id of 0
|
|
109
|
+
} else {
|
|
110
|
+
EnvWrap::toSharedBuffer(dw->ew->env, (uint32_t*) dw->ew->keyBuffer, data);
|
|
111
|
+
}
|
|
94
112
|
}
|
|
95
|
-
if (!(flags &
|
|
113
|
+
if (!(flags & VALUES_FOR_KEY)) {
|
|
96
114
|
memcpy(keyBuffer + 32, key.mv_data, key.mv_size);
|
|
97
115
|
*(keyBuffer + 32 + key.mv_size) = 0; // make sure it is null terminated for the sake of better ordered-binary performance
|
|
98
116
|
}
|
|
@@ -105,7 +123,10 @@ int32_t CursorWrap::doPosition(uint32_t offset, uint32_t keySize, uint64_t endKe
|
|
|
105
123
|
//char* keyBuffer = dw->ew->keyBuffer;
|
|
106
124
|
MDB_val key, data;
|
|
107
125
|
int rc;
|
|
108
|
-
if (
|
|
126
|
+
if (dw->ew->env == nullptr) {
|
|
127
|
+
return MDB_BAD_TXN;
|
|
128
|
+
}
|
|
129
|
+
if (flags & RENEW_CURSOR) { // TODO: check the txn_id to determine if we need to renew
|
|
109
130
|
rc = mdb_cursor_renew(txn = dw->ew->getReadTxn(), cursor);
|
|
110
131
|
if (rc) {
|
|
111
132
|
if (rc > 0)
|
|
@@ -119,25 +140,28 @@ int32_t CursorWrap::doPosition(uint32_t offset, uint32_t keySize, uint64_t endKe
|
|
|
119
140
|
endKey.mv_data = (char*)(keyBuffer + 1);
|
|
120
141
|
} else
|
|
121
142
|
endKey.mv_size = 0;
|
|
122
|
-
iteratingOp = (flags &
|
|
123
|
-
(flags &
|
|
124
|
-
(flags &
|
|
143
|
+
iteratingOp = (flags & REVERSE) ?
|
|
144
|
+
(flags & INCLUDE_VALUES) ?
|
|
145
|
+
(flags & VALUES_FOR_KEY) ? MDB_PREV_DUP : MDB_PREV :
|
|
125
146
|
MDB_PREV_NODUP :
|
|
126
|
-
(flags &
|
|
127
|
-
(flags &
|
|
147
|
+
(flags & INCLUDE_VALUES) ?
|
|
148
|
+
(flags & VALUES_FOR_KEY) ? MDB_NEXT_DUP : MDB_NEXT :
|
|
128
149
|
MDB_NEXT_NODUP;
|
|
129
150
|
key.mv_size = keySize;
|
|
130
151
|
key.mv_data = dw->ew->keyBuffer;
|
|
131
152
|
if (keySize == 0) {
|
|
132
|
-
rc = mdb_cursor_get(cursor, &key, &data, flags &
|
|
153
|
+
rc = mdb_cursor_get(cursor, &key, &data, flags & REVERSE ? MDB_LAST : MDB_FIRST);
|
|
133
154
|
} else {
|
|
134
|
-
if (flags &
|
|
155
|
+
if (flags & VALUES_FOR_KEY) { // only values for this key
|
|
135
156
|
// take the next part of the key buffer as a pointer to starting data
|
|
136
157
|
uint32_t* startValueBuffer = (uint32_t*)(size_t)(*(double*)(dw->ew->keyBuffer + START_ADDRESS_POSITION));
|
|
137
158
|
data.mv_size = endKeyAddress ? *((uint32_t*)startValueBuffer) : 0;
|
|
138
159
|
data.mv_data = startValueBuffer + 1;
|
|
139
|
-
|
|
140
|
-
|
|
160
|
+
MDB_val startValue;
|
|
161
|
+
if (flags & EXCLUSIVE_START)
|
|
162
|
+
startValue = data; // save it for comparison
|
|
163
|
+
if (flags & REVERSE) {// reverse through values
|
|
164
|
+
startValue = data; // save it for comparison
|
|
141
165
|
rc = mdb_cursor_get(cursor, &key, &data, data.mv_size ? MDB_GET_BOTH_RANGE : MDB_SET_KEY);
|
|
142
166
|
if (rc) {
|
|
143
167
|
if (startValue.mv_size) {
|
|
@@ -154,33 +178,54 @@ int32_t CursorWrap::doPosition(uint32_t offset, uint32_t keySize, uint64_t endKe
|
|
|
154
178
|
}
|
|
155
179
|
} else // forward, just do a get by range
|
|
156
180
|
rc = mdb_cursor_get(cursor, &key, &data, data.mv_size ?
|
|
157
|
-
(flags &
|
|
181
|
+
(flags & EXACT_MATCH) ? MDB_GET_BOTH : MDB_GET_BOTH_RANGE : MDB_SET_KEY);
|
|
158
182
|
|
|
159
183
|
if (rc == MDB_NOTFOUND)
|
|
160
184
|
return 0;
|
|
161
|
-
if (flags &
|
|
185
|
+
if (flags & ONLY_COUNT && (!endKeyAddress || (flags & EXACT_MATCH))) {
|
|
162
186
|
size_t count;
|
|
163
187
|
rc = mdb_cursor_count(cursor, &count);
|
|
164
188
|
if (rc)
|
|
165
189
|
return rc > 0 ? -rc : rc;
|
|
166
190
|
return count;
|
|
167
191
|
}
|
|
192
|
+
if (flags & EXCLUSIVE_START) {
|
|
193
|
+
while(!rc) {
|
|
194
|
+
if (mdb_dcmp(txn, dw->dbi, &startValue, &data))
|
|
195
|
+
break;
|
|
196
|
+
rc = mdb_cursor_get(cursor, &key, &data, iteratingOp);
|
|
197
|
+
}
|
|
198
|
+
}
|
|
168
199
|
} else {
|
|
169
|
-
|
|
170
|
-
|
|
200
|
+
MDB_val firstKey;
|
|
201
|
+
if (flags & EXCLUSIVE_START)
|
|
202
|
+
firstKey = key; // save it for comparison
|
|
203
|
+
if (flags & REVERSE) {// reverse
|
|
204
|
+
firstKey = key; // save it for comparison
|
|
171
205
|
rc = mdb_cursor_get(cursor, &key, &data, MDB_SET_RANGE);
|
|
172
206
|
if (rc)
|
|
173
207
|
rc = mdb_cursor_get(cursor, &key, &data, MDB_LAST);
|
|
174
208
|
else if (mdb_cmp(txn, dw->dbi, &firstKey, &key)) // the range found the next entry *after* the start
|
|
175
209
|
rc = mdb_cursor_get(cursor, &key, &data, MDB_PREV);
|
|
210
|
+
else if (dw->flags & MDB_DUPSORT)
|
|
211
|
+
// we need to go to the last value of this key
|
|
212
|
+
rc = mdb_cursor_get(cursor, &key, &data, MDB_LAST_DUP);
|
|
176
213
|
} else // forward, just do a get by range
|
|
177
|
-
rc = mdb_cursor_get(cursor, &key, &data, (flags &
|
|
214
|
+
rc = mdb_cursor_get(cursor, &key, &data, (flags & EXACT_MATCH) ? MDB_SET_KEY : MDB_SET_RANGE);
|
|
215
|
+
if (flags & EXCLUSIVE_START) {
|
|
216
|
+
while(!rc) {
|
|
217
|
+
if (mdb_cmp(txn, dw->dbi, &firstKey, &key))
|
|
218
|
+
break;
|
|
219
|
+
rc = mdb_cursor_get(cursor, &key, &data, iteratingOp);
|
|
220
|
+
}
|
|
221
|
+
}
|
|
178
222
|
}
|
|
179
223
|
}
|
|
224
|
+
|
|
180
225
|
while (offset-- > 0 && !rc) {
|
|
181
226
|
rc = mdb_cursor_get(cursor, &key, &data, iteratingOp);
|
|
182
227
|
}
|
|
183
|
-
if (flags &
|
|
228
|
+
if (flags & ONLY_COUNT) {
|
|
184
229
|
uint32_t count = 0;
|
|
185
230
|
bool useCursorCount = false;
|
|
186
231
|
// if we are in a dupsort database, and we are iterating over all entries, we can just count all the values for each key
|
|
@@ -198,12 +243,13 @@ int32_t CursorWrap::doPosition(uint32_t offset, uint32_t keySize, uint64_t endKe
|
|
|
198
243
|
while (!rc) {
|
|
199
244
|
if (endKey.mv_size > 0) {
|
|
200
245
|
int comparison;
|
|
201
|
-
if (flags &
|
|
246
|
+
if (flags & VALUES_FOR_KEY)
|
|
202
247
|
comparison = mdb_dcmp(txn, dw->dbi, &endKey, &data);
|
|
203
248
|
else
|
|
204
249
|
comparison = mdb_cmp(txn, dw->dbi, &endKey, &key);
|
|
205
|
-
if ((flags &
|
|
206
|
-
|
|
250
|
+
if ((flags & REVERSE) ? comparison >= 0 : (comparison <=0)) {
|
|
251
|
+
if (!((flags & INCLUSIVE_END) && comparison == 0))
|
|
252
|
+
return count;
|
|
207
253
|
}
|
|
208
254
|
}
|
|
209
255
|
if (useCursorCount) {
|
|
@@ -251,7 +297,10 @@ NAPI_FUNCTION(iterate) {
|
|
|
251
297
|
GET_INT64_ARG(0);
|
|
252
298
|
CursorWrap* cw = (CursorWrap*) i64;
|
|
253
299
|
MDB_val key, data;
|
|
254
|
-
int rc
|
|
300
|
+
int rc;
|
|
301
|
+
if (cw->dw->ew->env == nullptr) rc = MDB_BAD_TXN;
|
|
302
|
+
else
|
|
303
|
+
rc = mdb_cursor_get(cw->cursor, &key, &data, cw->iteratingOp);
|
|
255
304
|
RETURN_INT32(cw->returnEntry(rc, key, data));
|
|
256
305
|
}
|
|
257
306
|
|
|
@@ -260,6 +309,8 @@ int32_t iterateFFI(double cwPointer) {
|
|
|
260
309
|
DbiWrap* dw = cw->dw;
|
|
261
310
|
dw->getFast = true;
|
|
262
311
|
MDB_val key, data;
|
|
312
|
+
if (cw->dw->ew->env == nullptr)
|
|
313
|
+
return MDB_BAD_TXN;
|
|
263
314
|
int rc = mdb_cursor_get(cw->cursor, &key, &data, cw->iteratingOp);
|
|
264
315
|
return cw->returnEntry(rc, key, data);
|
|
265
316
|
}
|
package/src/dbi.cpp
CHANGED
|
@@ -30,7 +30,7 @@ DbiWrap::DbiWrap(const Napi::CallbackInfo& info) : ObjectWrap<DbiWrap>(info) {
|
|
|
30
30
|
napi_unwrap(info.Env(), info[4], (void**) &compression);
|
|
31
31
|
else
|
|
32
32
|
compression = nullptr;
|
|
33
|
-
int rc = this->open(flags
|
|
33
|
+
int rc = this->open(flags, nameBytes, flags & HAS_VERSIONS,
|
|
34
34
|
keyType, compression);
|
|
35
35
|
//if (nameBytes)
|
|
36
36
|
//delete nameBytes;
|
|
@@ -69,8 +69,10 @@ int DbiWrap::open(int flags, char* name, bool hasVersions, LmdbKeyType keyType,
|
|
|
69
69
|
this->hasVersions = hasVersions;
|
|
70
70
|
this->compression = compression;
|
|
71
71
|
this->keyType = keyType;
|
|
72
|
+
#ifndef MDB_RPAGE_CACHE
|
|
73
|
+
flags &= ~0x100; // remove use versions flag for older lmdb
|
|
74
|
+
#endif
|
|
72
75
|
this->flags = flags;
|
|
73
|
-
flags &= ~HAS_VERSIONS;
|
|
74
76
|
int rc = txn ? mdb_dbi_open(txn, name, flags, &this->dbi) : EINVAL;
|
|
75
77
|
if (rc)
|
|
76
78
|
return rc;
|
|
@@ -136,46 +138,58 @@ Value DbiWrap::stat(const Napi::CallbackInfo& info) {
|
|
|
136
138
|
return stats;
|
|
137
139
|
}
|
|
138
140
|
|
|
139
|
-
|
|
140
|
-
int32_t DbiWrap::doGetByBinary(uint32_t keySize) {
|
|
141
|
+
int32_t DbiWrap::doGetByBinary(uint32_t keySize, uint32_t ifNotTxnId, int64_t txnWrapAddress) {
|
|
141
142
|
char* keyBuffer = ew->keyBuffer;
|
|
142
|
-
MDB_txn* txn = ew->getReadTxn();
|
|
143
|
+
MDB_txn* txn = ew->getReadTxn(txnWrapAddress);
|
|
143
144
|
MDB_val key, data;
|
|
144
145
|
key.mv_size = keySize;
|
|
145
146
|
key.mv_data = (void*) keyBuffer;
|
|
146
|
-
|
|
147
|
+
uint32_t* currentTxnId = (uint32_t*) (keyBuffer + 32);
|
|
148
|
+
#ifdef MDB_RPAGE_CACHE
|
|
149
|
+
int result = mdb_get_with_txn(txn, dbi, &key, &data, (mdb_size_t*) currentTxnId);
|
|
150
|
+
#else
|
|
147
151
|
int result = mdb_get(txn, dbi, &key, &data);
|
|
152
|
+
#endif
|
|
148
153
|
if (result) {
|
|
149
|
-
|
|
150
|
-
|
|
154
|
+
if (result > 0)
|
|
155
|
+
return -result;
|
|
151
156
|
return result;
|
|
152
157
|
}
|
|
158
|
+
#ifdef MDB_RPAGE_CACHE
|
|
159
|
+
if (ifNotTxnId && ifNotTxnId == *currentTxnId)
|
|
160
|
+
return -30004;
|
|
161
|
+
#endif
|
|
153
162
|
result = getVersionAndUncompress(data, this);
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
163
|
+
bool fits = true;
|
|
164
|
+
if (result) {
|
|
165
|
+
fits = valToBinaryFast(data, this); // it fits in the global/compression-target buffer
|
|
166
|
+
}
|
|
167
|
+
if (fits || result == 2 || data.mv_size < SHARED_BUFFER_THRESHOLD) {// result = 2 if it was decompressed
|
|
168
|
+
if (data.mv_size < 0x80000000)
|
|
169
|
+
return data.mv_size;
|
|
170
|
+
*((uint32_t*)keyBuffer) = data.mv_size;
|
|
171
|
+
return -30000;
|
|
172
|
+
} else {
|
|
173
|
+
return EnvWrap::toSharedBuffer(ew->env, (uint32_t*) ew->keyBuffer, data);
|
|
174
|
+
}
|
|
165
175
|
}
|
|
166
176
|
|
|
167
177
|
NAPI_FUNCTION(getByBinary) {
|
|
168
|
-
ARGS(
|
|
169
|
-
|
|
170
|
-
|
|
178
|
+
ARGS(4)
|
|
179
|
+
GET_INT64_ARG(0);
|
|
180
|
+
DbiWrap* dw = (DbiWrap*) i64;
|
|
171
181
|
uint32_t keySize;
|
|
172
182
|
GET_UINT32_ARG(keySize, 1);
|
|
173
|
-
|
|
183
|
+
uint32_t ifNotTxnId;
|
|
184
|
+
GET_UINT32_ARG(ifNotTxnId, 2);
|
|
185
|
+
int64_t txnAddress = 0;
|
|
186
|
+
napi_status status = napi_get_value_int64(env, args[3], &txnAddress);
|
|
187
|
+
RETURN_INT32(dw->doGetByBinary(keySize, ifNotTxnId, txnAddress));
|
|
174
188
|
}
|
|
175
189
|
|
|
176
|
-
uint32_t getByBinaryFFI(double dwPointer, uint32_t keySize) {
|
|
177
|
-
|
|
178
|
-
|
|
190
|
+
uint32_t getByBinaryFFI(double dwPointer, uint32_t keySize, uint32_t ifNotTxnId, uint64_t txnAddress) {
|
|
191
|
+
DbiWrap* dw = (DbiWrap*) (size_t) dwPointer;
|
|
192
|
+
return dw->doGetByBinary(keySize, ifNotTxnId, txnAddress);
|
|
179
193
|
}
|
|
180
194
|
|
|
181
195
|
napi_finalize noopDbi = [](napi_env, void *, void *) {
|
|
@@ -183,8 +197,8 @@ napi_finalize noopDbi = [](napi_env, void *, void *) {
|
|
|
183
197
|
};
|
|
184
198
|
NAPI_FUNCTION(getSharedByBinary) {
|
|
185
199
|
ARGS(2)
|
|
186
|
-
|
|
187
|
-
|
|
200
|
+
GET_INT64_ARG(0);
|
|
201
|
+
DbiWrap* dw = (DbiWrap*) i64;
|
|
188
202
|
uint32_t keySize;
|
|
189
203
|
GET_UINT32_ARG(keySize, 1);
|
|
190
204
|
MDB_val key;
|
|
@@ -205,16 +219,18 @@ NAPI_FUNCTION(getSharedByBinary) {
|
|
|
205
219
|
return returnValue;
|
|
206
220
|
}
|
|
207
221
|
NAPI_FUNCTION(getStringByBinary) {
|
|
208
|
-
ARGS(
|
|
209
|
-
|
|
210
|
-
|
|
222
|
+
ARGS(3)
|
|
223
|
+
GET_INT64_ARG(0);
|
|
224
|
+
DbiWrap* dw = (DbiWrap*) i64;
|
|
211
225
|
uint32_t keySize;
|
|
212
226
|
GET_UINT32_ARG(keySize, 1);
|
|
227
|
+
int64_t txnAddress = 0;
|
|
228
|
+
napi_status status = napi_get_value_int64(env, args[2], &txnAddress);
|
|
213
229
|
MDB_val key;
|
|
214
230
|
MDB_val data;
|
|
215
231
|
key.mv_size = keySize;
|
|
216
232
|
key.mv_data = (void*) dw->ew->keyBuffer;
|
|
217
|
-
MDB_txn* txn = dw->ew->getReadTxn();
|
|
233
|
+
MDB_txn* txn = dw->ew->getReadTxn(txnAddress);
|
|
218
234
|
int rc = mdb_get(txn, dw->dbi, &key, &data);
|
|
219
235
|
if (rc) {
|
|
220
236
|
if (rc == MDB_NOTFOUND) {
|
|
@@ -237,12 +253,14 @@ int DbiWrap::prefetch(uint32_t* keys) {
|
|
|
237
253
|
MDB_val data;
|
|
238
254
|
unsigned int flags;
|
|
239
255
|
mdb_dbi_flags(txn, dbi, &flags);
|
|
240
|
-
bool
|
|
256
|
+
bool findAllValues = flags & MDB_DUPSORT;
|
|
241
257
|
int effected = 0;
|
|
258
|
+
bool findDataValue = false;
|
|
242
259
|
MDB_cursor *cursor;
|
|
243
260
|
int rc = mdb_cursor_open(txn, dbi, &cursor);
|
|
244
261
|
if (rc)
|
|
245
262
|
return rc;
|
|
263
|
+
|
|
246
264
|
while((key.mv_size = *keys++) > 0) {
|
|
247
265
|
if (key.mv_size == 0xffffffff) {
|
|
248
266
|
// it is a pointer to a new buffer
|
|
@@ -251,9 +269,20 @@ int DbiWrap::prefetch(uint32_t* keys) {
|
|
|
251
269
|
if (key.mv_size == 0)
|
|
252
270
|
break;
|
|
253
271
|
}
|
|
254
|
-
key.
|
|
272
|
+
if (key.mv_size & 0x80000000) {
|
|
273
|
+
// indicator of using a data value combination (with dupSort), to be followed by the corresponding key
|
|
274
|
+
data.mv_size = key.mv_size & 0x7fffffff;
|
|
275
|
+
data.mv_data = (void *) keys;
|
|
276
|
+
keys += (data.mv_size + 12) >> 2;
|
|
277
|
+
findDataValue = true;
|
|
278
|
+
findAllValues = false;
|
|
279
|
+
continue;
|
|
280
|
+
}
|
|
281
|
+
// else standard key
|
|
282
|
+
key.mv_data = (void *) keys;
|
|
255
283
|
keys += (key.mv_size + 12) >> 2;
|
|
256
|
-
int rc = mdb_cursor_get(cursor, &key, &data, MDB_SET_KEY);
|
|
284
|
+
int rc = mdb_cursor_get(cursor, &key, &data, findDataValue ? MDB_GET_BOTH : MDB_SET_KEY);
|
|
285
|
+
findDataValue = false;
|
|
257
286
|
while (!rc) {
|
|
258
287
|
// access one byte from each of the pages to ensure they are in the OS cache,
|
|
259
288
|
// potentially triggering the hard page fault in this thread
|
|
@@ -262,7 +291,7 @@ int DbiWrap::prefetch(uint32_t* keys) {
|
|
|
262
291
|
for (int i = 0; i < pages; i++) {
|
|
263
292
|
effected += *(((uint8_t*)data.mv_data) + (i << 12));
|
|
264
293
|
}
|
|
265
|
-
if (
|
|
294
|
+
if (findAllValues) // in dupsort databases, access the rest of the values
|
|
266
295
|
rc = mdb_cursor_get(cursor, &key, &data, MDB_NEXT_DUP);
|
|
267
296
|
else
|
|
268
297
|
rc = 1; // done
|
|
@@ -283,7 +312,13 @@ class PrefetchWorker : public AsyncWorker {
|
|
|
283
312
|
}
|
|
284
313
|
|
|
285
314
|
void OnOK() {
|
|
286
|
-
|
|
315
|
+
napi_value result; // we use direct napi call here because node-addon-api interface with throw a fatal error if a worker thread is terminating
|
|
316
|
+
napi_call_function(Env(), Env().Undefined(), Callback().Value(), 0, {}, &result);
|
|
317
|
+
}
|
|
318
|
+
void OnError(const Error& e) {
|
|
319
|
+
napi_value result; // we use direct napi call here because node-addon-api interface with throw a fatal error if a worker thread is terminating
|
|
320
|
+
napi_value arg = e.Value();
|
|
321
|
+
napi_call_function(Env(), Env().Undefined(), Callback().Value(), 1, &arg, &result);
|
|
287
322
|
}
|
|
288
323
|
|
|
289
324
|
private:
|
|
@@ -293,9 +328,9 @@ class PrefetchWorker : public AsyncWorker {
|
|
|
293
328
|
|
|
294
329
|
NAPI_FUNCTION(prefetchNapi) {
|
|
295
330
|
ARGS(3)
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
331
|
+
GET_INT64_ARG(0);
|
|
332
|
+
DbiWrap* dw = (DbiWrap*) i64;
|
|
333
|
+
napi_get_value_int64(env, args[1], &i64);
|
|
299
334
|
uint32_t* keys = (uint32_t*) i64;
|
|
300
335
|
PrefetchWorker* worker = new PrefetchWorker(dw, keys, Function(env, args[2]));
|
|
301
336
|
worker->Queue();
|
|
@@ -319,6 +354,9 @@ void DbiWrap::setupExports(Napi::Env env, Object exports) {
|
|
|
319
354
|
// TODO: wrap mdb_stat too
|
|
320
355
|
}
|
|
321
356
|
|
|
357
|
+
|
|
358
|
+
|
|
359
|
+
|
|
322
360
|
// This file contains code from the node-lmdb project
|
|
323
361
|
// Copyright (c) 2013-2017 Timur Kristóf
|
|
324
362
|
// Copyright (c) 2021 Kristopher Tate
|