@ohos-ports/lmdb 2.5.3 → 2.8.5-beta.0
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 +63 -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/misc.cpp
CHANGED
|
@@ -1,7 +1,9 @@
|
|
|
1
1
|
#include "lmdb-js.h"
|
|
2
|
+
#include <atomic>
|
|
2
3
|
#include <string.h>
|
|
3
4
|
#include <stdio.h>
|
|
4
5
|
#include <node_version.h>
|
|
6
|
+
#include <time.h>
|
|
5
7
|
|
|
6
8
|
using namespace Napi;
|
|
7
9
|
|
|
@@ -22,12 +24,20 @@ void setupExportMisc(Napi::Env env, Object exports) {
|
|
|
22
24
|
#endif
|
|
23
25
|
|
|
24
26
|
exports.Set("version", versionObj);
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
27
|
+
EXPORT_NAPI_FUNCTION("setGlobalBuffer", setGlobalBuffer)
|
|
28
|
+
EXPORT_NAPI_FUNCTION("lmdbError", lmdbError)
|
|
29
|
+
EXPORT_NAPI_FUNCTION("enableDirectV8", enableDirectV8)
|
|
28
30
|
EXPORT_NAPI_FUNCTION("createBufferForAddress", createBufferForAddress);
|
|
29
|
-
EXPORT_NAPI_FUNCTION("getAddress",
|
|
31
|
+
EXPORT_NAPI_FUNCTION("getAddress", getAddress);
|
|
32
|
+
EXPORT_NAPI_FUNCTION("getBufferAddress", getBufferAddress);
|
|
30
33
|
EXPORT_NAPI_FUNCTION("detachBuffer", detachBuffer);
|
|
34
|
+
EXPORT_NAPI_FUNCTION("startRead", startRead);
|
|
35
|
+
EXPORT_NAPI_FUNCTION("setReadCallback", setReadCallback);
|
|
36
|
+
EXPORT_NAPI_FUNCTION("enableThreadSafeCalls", enableThreadSafeCalls);
|
|
37
|
+
napi_value globalBuffer;
|
|
38
|
+
napi_create_buffer(env, SHARED_BUFFER_THRESHOLD, (void**) &globalUnsafePtr, &globalBuffer);
|
|
39
|
+
globalUnsafeSize = SHARED_BUFFER_THRESHOLD;
|
|
40
|
+
exports.Set("globalBuffer", Object(env, globalBuffer));
|
|
31
41
|
}
|
|
32
42
|
|
|
33
43
|
void setFlagFromValue(int *flags, int flag, const char *name, bool defaultValue, Object options) {
|
|
@@ -69,6 +79,7 @@ bool valToBinaryFast(MDB_val &data, DbiWrap* dw) {
|
|
|
69
79
|
// already decompressed to the target, nothing more to do
|
|
70
80
|
} else {
|
|
71
81
|
if (data.mv_size > compression->decompressSize) {
|
|
82
|
+
// indicates we could not copy, won't fit
|
|
72
83
|
return false;
|
|
73
84
|
}
|
|
74
85
|
// copy into the buffer target
|
|
@@ -76,11 +87,7 @@ bool valToBinaryFast(MDB_val &data, DbiWrap* dw) {
|
|
|
76
87
|
}
|
|
77
88
|
} else {
|
|
78
89
|
if (data.mv_size > globalUnsafeSize) {
|
|
79
|
-
//
|
|
80
|
-
/* if(data.mv_size > 64000) {
|
|
81
|
-
dw->SetUnsafeBuffer(data.mv_data, data.mv_size);
|
|
82
|
-
return Nan::New<Number>(data.mv_size);
|
|
83
|
-
}*/
|
|
90
|
+
// indicates we could not copy, won't fit
|
|
84
91
|
return false;
|
|
85
92
|
}
|
|
86
93
|
memcpy(globalUnsafePtr, data.mv_data, data.mv_size);
|
|
@@ -93,7 +100,7 @@ Value valToBinaryUnsafe(MDB_val &data, DbiWrap* dw, Env env) {
|
|
|
93
100
|
}
|
|
94
101
|
|
|
95
102
|
|
|
96
|
-
|
|
103
|
+
int getVersionAndUncompress(MDB_val &data, DbiWrap* dw) {
|
|
97
104
|
//fprintf(stdout, "uncompressing %u\n", compressionThreshold);
|
|
98
105
|
unsigned char* charData = (unsigned char*) data.mv_data;
|
|
99
106
|
if (dw->hasVersions) {
|
|
@@ -104,27 +111,29 @@ bool getVersionAndUncompress(MDB_val &data, DbiWrap* dw) {
|
|
|
104
111
|
data.mv_size -= 8;
|
|
105
112
|
}
|
|
106
113
|
if (data.mv_size == 0) {
|
|
107
|
-
return
|
|
114
|
+
return 1;// successFunc(data);
|
|
108
115
|
}
|
|
109
116
|
unsigned char statusByte = dw->compression ? charData[0] : 0;
|
|
110
117
|
//fprintf(stdout, "uncompressing status %X\n", statusByte);
|
|
111
118
|
if (statusByte >= 250) {
|
|
112
119
|
bool isValid;
|
|
113
120
|
dw->compression->decompress(data, isValid, !dw->getFast);
|
|
114
|
-
|
|
115
|
-
return false;
|
|
116
|
-
//return Nan::Null();
|
|
121
|
+
return isValid ? 2 : 0;
|
|
117
122
|
}
|
|
118
|
-
return
|
|
123
|
+
return 1;
|
|
119
124
|
}
|
|
120
125
|
|
|
121
|
-
|
|
122
|
-
|
|
126
|
+
NAPI_FUNCTION(lmdbError) {
|
|
127
|
+
ARGS(1)
|
|
128
|
+
int32_t error_code;
|
|
129
|
+
GET_INT32_ARG(error_code, 0);
|
|
130
|
+
return throwLmdbError(env, error_code);
|
|
123
131
|
}
|
|
124
132
|
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
133
|
+
NAPI_FUNCTION(setGlobalBuffer) {
|
|
134
|
+
ARGS(1)
|
|
135
|
+
napi_get_buffer_info(env, args[0], (void**) &globalUnsafePtr, &globalUnsafeSize);
|
|
136
|
+
RETURN_UNDEFINED
|
|
128
137
|
}
|
|
129
138
|
|
|
130
139
|
/*Value getBufferForAddress) {
|
|
@@ -136,18 +145,28 @@ Value setGlobalBuffer(const CallbackInfo& info) {
|
|
|
136
145
|
}*/
|
|
137
146
|
NAPI_FUNCTION(createBufferForAddress) {
|
|
138
147
|
ARGS(2)
|
|
139
|
-
|
|
140
|
-
|
|
148
|
+
GET_INT64_ARG(0)
|
|
149
|
+
void* data = (void*) i64;
|
|
141
150
|
uint32_t length;
|
|
142
151
|
GET_UINT32_ARG(length, 1);
|
|
143
152
|
napi_create_external_buffer(env, length, data, nullptr, nullptr, &returnValue);
|
|
144
153
|
return returnValue;
|
|
145
154
|
}
|
|
146
155
|
|
|
147
|
-
NAPI_FUNCTION(
|
|
156
|
+
NAPI_FUNCTION(getAddress) {
|
|
157
|
+
ARGS(1)
|
|
158
|
+
void* data;
|
|
159
|
+
size_t length;
|
|
160
|
+
napi_get_arraybuffer_info(env, args[0], &data, &length);
|
|
161
|
+
napi_create_double(env, (double) (size_t) data, &returnValue);
|
|
162
|
+
return returnValue;
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
NAPI_FUNCTION(getBufferAddress) {
|
|
148
166
|
ARGS(1)
|
|
149
167
|
void* data;
|
|
150
|
-
|
|
168
|
+
size_t length;
|
|
169
|
+
napi_get_buffer_info(env, args[0], &data, &length);
|
|
151
170
|
napi_create_double(env, (double) (size_t) data, &returnValue);
|
|
152
171
|
return returnValue;
|
|
153
172
|
}
|
|
@@ -160,6 +179,232 @@ NAPI_FUNCTION(detachBuffer) {
|
|
|
160
179
|
RETURN_UNDEFINED;
|
|
161
180
|
}
|
|
162
181
|
|
|
182
|
+
class ReadWorker : public AsyncWorker {
|
|
183
|
+
public:
|
|
184
|
+
ReadWorker(uint32_t* start, const Function& callback)
|
|
185
|
+
: AsyncWorker(callback), start(start) {}
|
|
186
|
+
|
|
187
|
+
void Execute() {
|
|
188
|
+
uint32_t instruction;
|
|
189
|
+
uint32_t* gets = start;
|
|
190
|
+
while((instruction = std::atomic_exchange((std::atomic<uint32_t>*)(gets + 2), (uint32_t)0xf0000000))) {
|
|
191
|
+
|
|
192
|
+
MDB_val key;
|
|
193
|
+
key.mv_size = *(gets + 3);
|
|
194
|
+
MDB_dbi dbi = (MDB_dbi) (instruction & 0xffff);
|
|
195
|
+
MDB_val data;
|
|
196
|
+
MDB_txn* txn = (MDB_txn*) (size_t) *((double*)gets);
|
|
197
|
+
|
|
198
|
+
unsigned int flags;
|
|
199
|
+
mdb_dbi_flags(txn, dbi, &flags);
|
|
200
|
+
bool dupSort = flags & MDB_DUPSORT;
|
|
201
|
+
int effected = 0;
|
|
202
|
+
MDB_cursor *cursor;
|
|
203
|
+
int rc = mdb_cursor_open(txn, dbi, &cursor);
|
|
204
|
+
if (rc)
|
|
205
|
+
return SetError(mdb_strerror(rc));
|
|
206
|
+
|
|
207
|
+
key.mv_data = (void*) gets;
|
|
208
|
+
rc = mdb_cursor_get(cursor, &key, &data, MDB_SET_KEY);
|
|
209
|
+
MDB_env* env = mdb_txn_env(txn);
|
|
210
|
+
*(gets + 3) = data.mv_size;
|
|
211
|
+
*((double*)gets) = (double) (size_t) data.mv_data;
|
|
212
|
+
gets += (key.mv_size + 28) >> 2;
|
|
213
|
+
while (!rc) {
|
|
214
|
+
// access one byte from each of the pages to ensure they are in the OS cache,
|
|
215
|
+
// potentially triggering the hard page fault in this thread
|
|
216
|
+
int pages = (data.mv_size + 0xfff) >> 12;
|
|
217
|
+
// TODO: Adjust this for the page headers, I believe that makes the first page slightly less 4KB.
|
|
218
|
+
for (int i = 0; i < pages; i++) {
|
|
219
|
+
effected += *(((uint8_t*)data.mv_data) + (i << 12));
|
|
220
|
+
}
|
|
221
|
+
if (dupSort) // in dupsort databases, access the rest of the values
|
|
222
|
+
rc = mdb_cursor_get(cursor, &key, &data, MDB_NEXT_DUP);
|
|
223
|
+
else
|
|
224
|
+
rc = 1; // done
|
|
225
|
+
|
|
226
|
+
}
|
|
227
|
+
mdb_cursor_close(cursor);
|
|
228
|
+
}
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
void OnOK() {
|
|
232
|
+
// TODO: For each entry, find the shared buffer
|
|
233
|
+
uint32_t* gets = start;
|
|
234
|
+
// EnvWrap::toSharedBuffer();
|
|
235
|
+
Callback().Call({Env().Null()});
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
private:
|
|
239
|
+
uint32_t* start;
|
|
240
|
+
};
|
|
241
|
+
typedef struct { // this is read results data buffer that is actively being used by a JS thread (read results are written to it)
|
|
242
|
+
int id;
|
|
243
|
+
char* data;
|
|
244
|
+
uint32_t offset;
|
|
245
|
+
uint32_t size;
|
|
246
|
+
} read_results_buffer_t;
|
|
247
|
+
|
|
248
|
+
static thread_local std::unordered_map<void*, read_results_buffer_t*>* buffersByWorker;
|
|
249
|
+
|
|
250
|
+
typedef struct {
|
|
251
|
+
napi_ref callback;
|
|
252
|
+
napi_ref resource;
|
|
253
|
+
} read_callback_t;
|
|
254
|
+
static int next_buffer_id = -1;
|
|
255
|
+
typedef struct {
|
|
256
|
+
uint32_t* instructionAddress;
|
|
257
|
+
uint32_t callback_id;
|
|
258
|
+
napi_async_work work;
|
|
259
|
+
//napi_deferred deferred;
|
|
260
|
+
js_buffers_t* buffers;
|
|
261
|
+
} read_instruction_t;
|
|
262
|
+
const uint32_t ZERO = 0;
|
|
263
|
+
void do_read(napi_env nenv, void* instruction_pointer) {
|
|
264
|
+
read_instruction_t* readInstruction = (read_instruction_t*) instruction_pointer;
|
|
265
|
+
//fprintf(stderr, "lock %p\n", &readInstruction->buffers->modification_lock);
|
|
266
|
+
uint32_t* instruction = readInstruction->instructionAddress;
|
|
267
|
+
MDB_val key;
|
|
268
|
+
key.mv_size = *(instruction + 3);
|
|
269
|
+
MDB_dbi dbi = (MDB_dbi) (*(instruction + 2) & 0xffff) ;
|
|
270
|
+
MDB_val data;
|
|
271
|
+
TxnWrap* tw = (TxnWrap*) (size_t) *((double*)instruction);
|
|
272
|
+
MDB_txn* txn = tw->txn;
|
|
273
|
+
mdb_txn_renew(txn);
|
|
274
|
+
unsigned int flags;
|
|
275
|
+
mdb_dbi_flags(txn, dbi, &flags);
|
|
276
|
+
bool dupSort = flags & MDB_DUPSORT;
|
|
277
|
+
int effected = 0;
|
|
278
|
+
MDB_cursor *cursor;
|
|
279
|
+
MDB_env* env = mdb_txn_env(txn);
|
|
280
|
+
int rc = mdb_cursor_open(txn, dbi, &cursor);
|
|
281
|
+
if (rc) {
|
|
282
|
+
*instruction = rc;
|
|
283
|
+
return;
|
|
284
|
+
}
|
|
285
|
+
key.mv_data = (void*) (instruction + 4);
|
|
286
|
+
rc = mdb_cursor_get(cursor, &key, &data, MDB_SET_KEY);
|
|
287
|
+
*(instruction + 3) = data.mv_size;
|
|
288
|
+
|
|
289
|
+
//instruction += (key.mv_size + 28) >> 2;
|
|
290
|
+
while (!rc) {
|
|
291
|
+
// access one byte from each of the pages to ensure they are in the OS cache,
|
|
292
|
+
// potentially triggering the hard page fault in this thread
|
|
293
|
+
int pages = (data.mv_size + 0xfff) >> 12;
|
|
294
|
+
// TODO: Adjust this for the page headers, I believe that makes the first page slightly less than 4KB.
|
|
295
|
+
for (int i = 0; i < pages; i++) {
|
|
296
|
+
effected += *(((uint8_t*)data.mv_data) + (i << 12));
|
|
297
|
+
}
|
|
298
|
+
if (dupSort) // in dupsort databases, access the rest of the values
|
|
299
|
+
rc = mdb_cursor_get(cursor, &key, &data, MDB_NEXT_DUP);
|
|
300
|
+
else
|
|
301
|
+
rc = 1; // done
|
|
302
|
+
|
|
303
|
+
}
|
|
304
|
+
*instruction = rc;
|
|
305
|
+
unsigned int env_flags = 0;
|
|
306
|
+
mdb_env_get_flags(env, &env_flags);
|
|
307
|
+
if (data.mv_size > 4096 && !(env_flags & MDB_REMAP_CHUNKS)) {
|
|
308
|
+
EnvWrap::toSharedBuffer(env, instruction, data);
|
|
309
|
+
*((double*)instruction) = (double) (size_t) data.mv_data;
|
|
310
|
+
} else {
|
|
311
|
+
if (!buffersByWorker)
|
|
312
|
+
buffersByWorker = new std::unordered_map<void*, read_results_buffer_t*>;
|
|
313
|
+
read_results_buffer_t* read_buffer;
|
|
314
|
+
auto buffer_search = buffersByWorker->find(readInstruction->buffers);
|
|
315
|
+
if (buffer_search == buffersByWorker->end()) {
|
|
316
|
+
// create new one
|
|
317
|
+
buffersByWorker->emplace(readInstruction->buffers, read_buffer = new read_results_buffer_t);
|
|
318
|
+
read_buffer->size = 0;
|
|
319
|
+
read_buffer->offset = 0; // force it re-malloc
|
|
320
|
+
} else
|
|
321
|
+
read_buffer = buffer_search->second;
|
|
322
|
+
if ((int) read_buffer->size - (int) read_buffer->offset - 4 < (int) data.mv_size) {
|
|
323
|
+
size_t size = 0x40000;// 256KB
|
|
324
|
+
read_buffer->data = (char*) malloc(size);
|
|
325
|
+
read_buffer->size = size;
|
|
326
|
+
read_buffer->offset = 0;
|
|
327
|
+
buffer_info_t buffer_info;
|
|
328
|
+
buffer_info.end = read_buffer->data + size;
|
|
329
|
+
buffer_info.env = nullptr;
|
|
330
|
+
buffer_info.isSharedMap = false;
|
|
331
|
+
pthread_mutex_lock(&readInstruction->buffers->modification_lock);
|
|
332
|
+
buffer_info.id = read_buffer->id = readInstruction->buffers->nextId++;
|
|
333
|
+
readInstruction->buffers->buffers.emplace(read_buffer->data, buffer_info);
|
|
334
|
+
pthread_mutex_unlock(&readInstruction->buffers->modification_lock);
|
|
335
|
+
|
|
336
|
+
}
|
|
337
|
+
auto position = (uint32_t*) (read_buffer->data + read_buffer->offset);
|
|
338
|
+
memcpy(position, data.mv_data, data.mv_size);
|
|
339
|
+
position += (data.mv_size + 7) >> 2;
|
|
340
|
+
*(instruction + 1) = read_buffer->id;
|
|
341
|
+
*(instruction + 2) = read_buffer->offset;
|
|
342
|
+
read_buffer->offset = (char*)position - read_buffer->data;
|
|
343
|
+
}
|
|
344
|
+
mdb_cursor_close(cursor);
|
|
345
|
+
//fprintf(stderr, "unlock %p\n", &readInstruction->buffers->modification_lock);
|
|
346
|
+
}
|
|
347
|
+
static thread_local napi_ref* read_callback;
|
|
348
|
+
void read_complete(napi_env env, napi_status status, void* data) {
|
|
349
|
+
read_instruction_t* readInstruction = (read_instruction_t*) data;
|
|
350
|
+
napi_value callback;
|
|
351
|
+
napi_get_reference_value(env, *read_callback, &callback);
|
|
352
|
+
//uint32_t count;
|
|
353
|
+
napi_value result;
|
|
354
|
+
napi_value callback_id;
|
|
355
|
+
napi_create_int32(env, readInstruction->callback_id, &callback_id);
|
|
356
|
+
status = napi_call_function(env, callback, callback, 1, &callback_id, &result);
|
|
357
|
+
napi_delete_async_work(env, readInstruction->work);
|
|
358
|
+
delete readInstruction;
|
|
359
|
+
//napi_resolve_deferred(env, readInstruction->deferred, resolution);
|
|
360
|
+
}
|
|
361
|
+
NAPI_FUNCTION(enableThreadSafeCalls) {
|
|
362
|
+
WriteWorker::threadSafeCallsEnabled = true;
|
|
363
|
+
napi_value returnValue;
|
|
364
|
+
RETURN_UNDEFINED;
|
|
365
|
+
}
|
|
366
|
+
|
|
367
|
+
NAPI_FUNCTION(setReadCallback) {
|
|
368
|
+
ARGS(1)
|
|
369
|
+
read_callback = new napi_ref;
|
|
370
|
+
napi_create_reference(env, args[0], 1, read_callback);
|
|
371
|
+
RETURN_UNDEFINED;
|
|
372
|
+
}
|
|
373
|
+
NAPI_FUNCTION(startRead) {
|
|
374
|
+
ARGS(4)
|
|
375
|
+
GET_INT64_ARG(0);
|
|
376
|
+
uint32_t* instructionAddress = (uint32_t*) i64;
|
|
377
|
+
read_instruction_t* readInstruction = new read_instruction_t;
|
|
378
|
+
readInstruction->instructionAddress = instructionAddress;
|
|
379
|
+
uint32_t callback_id;
|
|
380
|
+
GET_UINT32_ARG(callback_id, 1);
|
|
381
|
+
//napi_create_reference(env, args[1], 1, &readInstruction->callback);
|
|
382
|
+
readInstruction->callback_id = callback_id;
|
|
383
|
+
readInstruction->buffers = EnvWrap::sharedBuffers;
|
|
384
|
+
napi_status status;
|
|
385
|
+
status = napi_create_async_work(env, args[2], args[3], do_read, read_complete, readInstruction, &readInstruction->work);
|
|
386
|
+
status = napi_queue_async_work(env, readInstruction->work);
|
|
387
|
+
RETURN_UNDEFINED;
|
|
388
|
+
}/*
|
|
389
|
+
NAPI_FUNCTION(nextRead) {
|
|
390
|
+
ARGS(1)
|
|
391
|
+
uint32_t offset;
|
|
392
|
+
GET_UINT32_ARG(offset, 0);
|
|
393
|
+
uint32_t* instructionAddress = (uint32_t*) currentReadAddress + offset;
|
|
394
|
+
read_callback_t* callback = lastCallback;
|
|
395
|
+
uint32_t count;
|
|
396
|
+
napi_reference_ref(callback->env, callback->callback, &count);
|
|
397
|
+
read_instruction_t* readInstruction = new read_instruction_t;
|
|
398
|
+
readInstruction->instructionAddress = instructionAddress;
|
|
399
|
+
readInstruction->callback = callback;
|
|
400
|
+
napi_async_work work;
|
|
401
|
+
napi_create_async_work(callback->env, nullptr, readInstruction, &work);
|
|
402
|
+
napi_queue_async_work(env, work);
|
|
403
|
+
ReadWorker* worker = new ReadWorker(instructionAddress, Function(env, args[1]));
|
|
404
|
+
worker->Queue();
|
|
405
|
+
RETURN_UNDEFINED;
|
|
406
|
+
}*/
|
|
407
|
+
|
|
163
408
|
Value lmdbNativeFunctions(const CallbackInfo& info) {
|
|
164
409
|
// no-op, just doing this to give a label to the native functions
|
|
165
410
|
return info.Env().Undefined();
|
|
@@ -192,7 +437,8 @@ int putWithVersion(MDB_txn * txn,
|
|
|
192
437
|
if (rc == 0) {
|
|
193
438
|
// if put is successful, data->mv_data will point into the database where we copy the data to
|
|
194
439
|
memcpy((char*) data->mv_data + 8, sourceData, size);
|
|
195
|
-
|
|
440
|
+
memcpy(data->mv_data, &version, 8);
|
|
441
|
+
//*((double*) data->mv_data) = version; // this doesn't work on ARM v7 because it is not (guaranteed) memory-aligned
|
|
196
442
|
}
|
|
197
443
|
data->mv_data = sourceData; // restore this so that if it points to data that needs to be freed, it points to the right place
|
|
198
444
|
return rc;
|
|
@@ -236,9 +482,8 @@ int pthread_mutex_unlock(pthread_mutex_t *mutex)
|
|
|
236
482
|
return 0;
|
|
237
483
|
}
|
|
238
484
|
|
|
239
|
-
int
|
|
485
|
+
int cond_init(pthread_cond_t *cond)
|
|
240
486
|
{
|
|
241
|
-
(void)attr;
|
|
242
487
|
if (cond == NULL)
|
|
243
488
|
return 1;
|
|
244
489
|
InitializeConditionVariable(cond);
|
|
@@ -286,17 +531,41 @@ int pthread_cond_broadcast(pthread_cond_t *cond)
|
|
|
286
531
|
return 0;
|
|
287
532
|
}
|
|
288
533
|
|
|
534
|
+
uint64_t get_time64() {
|
|
535
|
+
return GetTickCount64();
|
|
536
|
+
}
|
|
537
|
+
|
|
289
538
|
#else
|
|
539
|
+
int cond_init(pthread_cond_t *cond) {
|
|
540
|
+
pthread_condattr_t attr;
|
|
541
|
+
pthread_condattr_init( &attr);
|
|
542
|
+
#if defined(__linux)
|
|
543
|
+
// only tested in linux, not available on macos
|
|
544
|
+
pthread_condattr_setclock( &attr, CLOCK_MONOTONIC);
|
|
545
|
+
#endif
|
|
546
|
+
return pthread_cond_init(cond, &attr);
|
|
547
|
+
}
|
|
548
|
+
|
|
290
549
|
int cond_timedwait(pthread_cond_t *cond, pthread_mutex_t *mutex, uint64_t cms)
|
|
291
550
|
{
|
|
292
551
|
struct timespec ts;
|
|
552
|
+
#if defined(__linux)
|
|
553
|
+
clock_gettime(CLOCK_MONOTONIC, &ts);
|
|
554
|
+
#else
|
|
555
|
+
// without being able to set the clock for condition/mutexes, need to use default realtime clock on macos
|
|
293
556
|
clock_gettime(CLOCK_REALTIME, &ts);
|
|
557
|
+
#endif
|
|
294
558
|
uint64_t ns = ts.tv_nsec + cms * 10000;
|
|
295
559
|
ts.tv_sec += ns / 1000000000;
|
|
296
|
-
ts.tv_nsec
|
|
560
|
+
ts.tv_nsec = ns % 1000000000;
|
|
297
561
|
return pthread_cond_timedwait(cond, mutex, &ts);
|
|
298
562
|
}
|
|
299
563
|
|
|
564
|
+
uint64_t get_time64() {
|
|
565
|
+
struct timespec time;
|
|
566
|
+
clock_gettime(CLOCK_MONOTONIC, &time);
|
|
567
|
+
return time.tv_sec * 1000000000ll + time.tv_nsec;
|
|
568
|
+
}
|
|
300
569
|
#endif
|
|
301
570
|
|
|
302
571
|
// This file contains code from the node-lmdb project
|
package/src/ordered-binary.cpp
CHANGED
|
@@ -1,46 +1,46 @@
|
|
|
1
|
-
#include "lmdb-js.h"
|
|
2
|
-
|
|
3
|
-
#ifdef _WIN32
|
|
4
|
-
#define ntohl _byteswap_ulong
|
|
5
|
-
#define htonl _byteswap_ulong
|
|
6
|
-
#else
|
|
7
|
-
#include <arpa/inet.h>
|
|
8
|
-
#endif
|
|
9
|
-
|
|
10
|
-
// compare items by 32-bit comparison, a is user provided and assumed to be zero terminated/padded
|
|
11
|
-
// which allows us to do the full 32-bit comparisons safely
|
|
12
|
-
int compareFast(const MDB_val *a, const MDB_val *b) {
|
|
13
|
-
uint32_t* dataA = (uint32_t*) a->mv_data;
|
|
14
|
-
uint32_t* dataB = (uint32_t*) b->mv_data;
|
|
15
|
-
size_t remaining = b->mv_size;
|
|
16
|
-
uint32_t aVal, bVal;
|
|
17
|
-
while(remaining >= 4) {
|
|
18
|
-
aVal = ntohl(*dataA);
|
|
19
|
-
bVal = ntohl(*dataB);
|
|
20
|
-
if (aVal > bVal)
|
|
21
|
-
return 1;
|
|
22
|
-
if (aVal < bVal)
|
|
23
|
-
return -1;
|
|
24
|
-
/*diff = (int64_t) ntohl(*dataA) - (int64_t) ntohl(*dataB);
|
|
25
|
-
if (diff)
|
|
26
|
-
return diff;*/
|
|
27
|
-
dataA++;
|
|
28
|
-
dataB++;
|
|
29
|
-
remaining -= 4;
|
|
30
|
-
}
|
|
31
|
-
if (remaining) {
|
|
32
|
-
if (remaining == 1) {
|
|
33
|
-
aVal = *((uint8_t*) dataA);
|
|
34
|
-
bVal = *((uint8_t*) dataB);
|
|
35
|
-
} else {
|
|
36
|
-
aVal = ntohl(*dataA);
|
|
37
|
-
bVal = remaining == 2 ? (*((uint8_t*) dataB) << 24) + (*((uint8_t*) dataB + 1) << 16) :
|
|
38
|
-
ntohl(*dataB & 0x00ffffff);
|
|
39
|
-
}
|
|
40
|
-
if (aVal > bVal)
|
|
41
|
-
return 1;
|
|
42
|
-
if (aVal < bVal)
|
|
43
|
-
return -1;
|
|
44
|
-
}
|
|
45
|
-
return a->mv_size - b->mv_size;
|
|
46
|
-
}
|
|
1
|
+
#include "lmdb-js.h"
|
|
2
|
+
|
|
3
|
+
#ifdef _WIN32
|
|
4
|
+
#define ntohl _byteswap_ulong
|
|
5
|
+
#define htonl _byteswap_ulong
|
|
6
|
+
#else
|
|
7
|
+
#include <arpa/inet.h>
|
|
8
|
+
#endif
|
|
9
|
+
|
|
10
|
+
// compare items by 32-bit comparison, a is user provided and assumed to be zero terminated/padded
|
|
11
|
+
// which allows us to do the full 32-bit comparisons safely
|
|
12
|
+
int compareFast(const MDB_val *a, const MDB_val *b) {
|
|
13
|
+
uint32_t* dataA = (uint32_t*) a->mv_data;
|
|
14
|
+
uint32_t* dataB = (uint32_t*) b->mv_data;
|
|
15
|
+
size_t remaining = b->mv_size;
|
|
16
|
+
uint32_t aVal, bVal;
|
|
17
|
+
while(remaining >= 4) {
|
|
18
|
+
aVal = ntohl(*dataA);
|
|
19
|
+
bVal = ntohl(*dataB);
|
|
20
|
+
if (aVal > bVal)
|
|
21
|
+
return 1;
|
|
22
|
+
if (aVal < bVal)
|
|
23
|
+
return -1;
|
|
24
|
+
/*diff = (int64_t) ntohl(*dataA) - (int64_t) ntohl(*dataB);
|
|
25
|
+
if (diff)
|
|
26
|
+
return diff;*/
|
|
27
|
+
dataA++;
|
|
28
|
+
dataB++;
|
|
29
|
+
remaining -= 4;
|
|
30
|
+
}
|
|
31
|
+
if (remaining) {
|
|
32
|
+
if (remaining == 1) {
|
|
33
|
+
aVal = *((uint8_t*) dataA);
|
|
34
|
+
bVal = *((uint8_t*) dataB);
|
|
35
|
+
} else {
|
|
36
|
+
aVal = ntohl(*dataA);
|
|
37
|
+
bVal = remaining == 2 ? (*((uint8_t*) dataB) << 24) + (*((uint8_t*) dataB + 1) << 16) :
|
|
38
|
+
ntohl(*dataB & 0x00ffffff);
|
|
39
|
+
}
|
|
40
|
+
if (aVal > bVal)
|
|
41
|
+
return 1;
|
|
42
|
+
if (aVal < bVal)
|
|
43
|
+
return -1;
|
|
44
|
+
}
|
|
45
|
+
return a->mv_size - b->mv_size;
|
|
46
|
+
}
|