@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.
Files changed (124) hide show
  1. package/LICENSE +20 -20
  2. package/README.md +72 -28
  3. package/SECURITY.md +12 -12
  4. package/bin/download-prebuilds.js +15 -0
  5. package/binding.gyp +115 -111
  6. package/build/Release/lmdb.node +0 -0
  7. package/caching.js +212 -156
  8. package/dependencies/lmdb/libraries/liblmdb/COPYRIGHT +20 -20
  9. package/dependencies/lmdb/libraries/liblmdb/Doxyfile +1631 -1631
  10. package/dependencies/lmdb/libraries/liblmdb/LICENSE +47 -47
  11. package/dependencies/lmdb/libraries/liblmdb/Makefile +136 -136
  12. package/dependencies/lmdb/libraries/liblmdb/chacha8.c +183 -183
  13. package/dependencies/lmdb/libraries/liblmdb/chacha8.h +14 -14
  14. package/dependencies/lmdb/libraries/liblmdb/crypto.c +121 -121
  15. package/dependencies/lmdb/libraries/liblmdb/intro.doc +192 -192
  16. package/dependencies/lmdb/libraries/liblmdb/lmdb.h +28 -3
  17. package/dependencies/lmdb/libraries/liblmdb/mdb.c +157 -31
  18. package/dependencies/lmdb/libraries/liblmdb/mdb_copy.1 +74 -74
  19. package/dependencies/lmdb/libraries/liblmdb/mdb_copy.c +106 -106
  20. package/dependencies/lmdb/libraries/liblmdb/mdb_drop.1 +53 -53
  21. package/dependencies/lmdb/libraries/liblmdb/mdb_drop.c +154 -154
  22. package/dependencies/lmdb/libraries/liblmdb/mdb_dump.1 +94 -94
  23. package/dependencies/lmdb/libraries/liblmdb/mdb_dump.c +333 -333
  24. package/dependencies/lmdb/libraries/liblmdb/mdb_load.1 +97 -97
  25. package/dependencies/lmdb/libraries/liblmdb/mdb_load.c +530 -530
  26. package/dependencies/lmdb/libraries/liblmdb/mdb_stat.1 +83 -83
  27. package/dependencies/lmdb/libraries/liblmdb/mdb_stat.c +276 -276
  28. package/dependencies/lmdb/libraries/liblmdb/midl-sparse.c +452 -0
  29. package/dependencies/lmdb/libraries/liblmdb/midl.c +452 -452
  30. package/dependencies/lmdb/libraries/liblmdb/midl.h +208 -208
  31. package/dependencies/lmdb/libraries/liblmdb/module.c +101 -101
  32. package/dependencies/lmdb/libraries/liblmdb/module.h +16 -16
  33. package/dependencies/lmdb/libraries/liblmdb/mtest.c +178 -178
  34. package/dependencies/lmdb/libraries/liblmdb/mtest2.c +124 -124
  35. package/dependencies/lmdb/libraries/liblmdb/mtest3.c +133 -133
  36. package/dependencies/lmdb/libraries/liblmdb/mtest4.c +168 -168
  37. package/dependencies/lmdb/libraries/liblmdb/mtest5.c +135 -135
  38. package/dependencies/lmdb/libraries/liblmdb/mtest6.c +141 -141
  39. package/dependencies/lmdb/libraries/liblmdb/mtest_enc.c +190 -190
  40. package/dependencies/lmdb/libraries/liblmdb/mtest_enc2.c +189 -189
  41. package/dependencies/lmdb/libraries/liblmdb/mtest_remap.c +177 -177
  42. package/dependencies/lmdb/libraries/liblmdb/sample-bdb.txt +73 -73
  43. package/dependencies/lmdb/libraries/liblmdb/sample-mdb.txt +62 -62
  44. package/dependencies/lmdb/libraries/liblmdb/tooltag +27 -27
  45. package/dependencies/lmdb-data-v1/libraries/liblmdb/CHANGES +266 -0
  46. package/dependencies/lmdb-data-v1/libraries/liblmdb/COPYRIGHT +20 -20
  47. package/dependencies/lmdb-data-v1/libraries/liblmdb/Doxyfile +1631 -1631
  48. package/dependencies/lmdb-data-v1/libraries/liblmdb/LICENSE +47 -47
  49. package/dependencies/lmdb-data-v1/libraries/liblmdb/intro.doc +192 -192
  50. package/dependencies/lmdb-data-v1/libraries/liblmdb/lmdb.h +1608 -1653
  51. package/dependencies/lmdb-data-v1/libraries/liblmdb/mdb.c +10320 -11359
  52. package/dependencies/lmdb-data-v1/libraries/liblmdb/mdb_copy.1 +55 -61
  53. package/dependencies/lmdb-data-v1/libraries/liblmdb/mdb_copy.c +82 -84
  54. package/dependencies/lmdb-data-v1/libraries/liblmdb/mdb_dump.1 +75 -81
  55. package/dependencies/lmdb-data-v1/libraries/liblmdb/mdb_dump.c +319 -319
  56. package/dependencies/lmdb-data-v1/libraries/liblmdb/mdb_load.1 +84 -84
  57. package/dependencies/lmdb-data-v1/libraries/liblmdb/mdb_load.c +496 -492
  58. package/dependencies/lmdb-data-v1/libraries/liblmdb/mdb_stat.1 +64 -70
  59. package/dependencies/lmdb-data-v1/libraries/liblmdb/mdb_stat.c +263 -264
  60. package/dependencies/lmdb-data-v1/libraries/liblmdb/midl.c +359 -421
  61. package/dependencies/lmdb-data-v1/libraries/liblmdb/midl.h +186 -200
  62. package/dependencies/lmdb-data-v1/libraries/liblmdb/mtest.c +177 -177
  63. package/dependencies/lmdb-data-v1/libraries/liblmdb/mtest2.c +124 -124
  64. package/dependencies/lmdb-data-v1/libraries/liblmdb/mtest3.c +133 -133
  65. package/dependencies/lmdb-data-v1/libraries/liblmdb/mtest4.c +168 -168
  66. package/dependencies/lmdb-data-v1/libraries/liblmdb/mtest5.c +135 -135
  67. package/dependencies/lmdb-data-v1/libraries/liblmdb/mtest6.c +141 -141
  68. package/dependencies/lmdb-data-v1/libraries/liblmdb/sample-bdb.txt +73 -73
  69. package/dependencies/lmdb-data-v1/libraries/liblmdb/sample-mdb.txt +62 -62
  70. package/dependencies/lmdb-data-v1/libraries/liblmdb/tooltag +22 -27
  71. package/dependencies/lz4/LICENSE +11 -11
  72. package/dependencies/lz4/lib/LICENSE +24 -24
  73. package/dependencies/lz4/lib/Makefile +225 -0
  74. package/dependencies/lz4/lib/README.md +169 -137
  75. package/dependencies/lz4/lib/dll/example/Makefile +63 -0
  76. package/dependencies/lz4/lib/dll/example/README.md +69 -69
  77. package/dependencies/lz4/lib/dll/liblz4.def +62 -62
  78. package/dependencies/lz4/lib/liblz4-dll.rc.in +35 -35
  79. package/dependencies/lz4/lib/liblz4.pc.in +14 -14
  80. package/dependencies/lz4/lib/lz4.c +2722 -2495
  81. package/dependencies/lz4/lib/lz4.h +842 -774
  82. package/dependencies/lz4/lib/lz4file.c +311 -0
  83. package/dependencies/lz4/lib/lz4file.h +93 -0
  84. package/dependencies/lz4/lib/lz4frame.c +2078 -1899
  85. package/dependencies/lz4/lib/lz4frame.h +692 -623
  86. package/dependencies/lz4/lib/lz4frame_static.h +47 -47
  87. package/dependencies/lz4/lib/lz4hc.c +1631 -1615
  88. package/dependencies/lz4/lib/lz4hc.h +413 -413
  89. package/dependencies/lz4/lib/xxhash.c +1030 -1030
  90. package/dependencies/lz4/lib/xxhash.h +328 -328
  91. package/dependencies/v8/v8-fast-api-calls-v16.h +790 -790
  92. package/dependencies/v8/v8-fast-api-calls.h +784 -888
  93. package/dist/index.cjs +1050 -584
  94. package/dist/index.cjs.map +1 -1
  95. package/index.d.cts +420 -0
  96. package/index.d.ts +450 -385
  97. package/index.js +38 -37
  98. package/keys.js +116 -102
  99. package/level.js +26 -26
  100. package/native.js +8 -5
  101. package/node-index.js +21 -17
  102. package/open.js +51 -17
  103. package/package.json +63 -21
  104. package/read.js +338 -95
  105. package/src/compression.cpp +12 -9
  106. package/src/cursor.cpp +82 -31
  107. package/src/dbi.cpp +78 -40
  108. package/src/env.cpp +336 -68
  109. package/src/lmdb-js.cpp +64 -64
  110. package/src/lmdb-js.h +83 -49
  111. package/src/misc.cpp +297 -28
  112. package/src/ordered-binary.cpp +46 -46
  113. package/src/txn.cpp +210 -257
  114. package/src/v8-functions.cpp +170 -166
  115. package/src/windows.c +34 -34
  116. package/src/writer.cpp +169 -84
  117. package/util/RangeIterable.js +112 -17
  118. package/util/set-optional-deps.cjs +14 -10
  119. package/util/when.js +8 -8
  120. package/write.js +145 -121
  121. package/dependencies/lmdb-data-v1/libraries/liblmdb/Makefile +0 -118
  122. package/dependencies/lmdb-data-v1/libraries/liblmdb/mdb_drop.1 +0 -40
  123. package/dependencies/lmdb-data-v1/libraries/liblmdb/mdb_drop.c +0 -135
  124. 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
- exports.Set("setGlobalBuffer", Function::New(env, setGlobalBuffer));
26
- exports.Set("lmdbError", Function::New(env, lmdbError));
27
- exports.Set("enableDirectV8", Function::New(env, enableDirectV8));
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", getViewAddress);
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
- // TODO: Provide a direct reference if for really large blocks, but we do that we need to detach that in the next turn
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
- bool getVersionAndUncompress(MDB_val &data, DbiWrap* dw) {
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 true;// successFunc(data);
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
- if (!isValid)
115
- return false;
116
- //return Nan::Null();
121
+ return isValid ? 2 : 0;
117
122
  }
118
- return true;
123
+ return 1;
119
124
  }
120
125
 
121
- Value lmdbError(const CallbackInfo& info) {
122
- return throwLmdbError(info.Env(), info[0].As<Number>().Int32Value());
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
- Value setGlobalBuffer(const CallbackInfo& info) {
126
- napi_get_typedarray_info(info.Env(), info[0], nullptr, &globalUnsafeSize, (void**) &globalUnsafePtr, nullptr, nullptr);
127
- return info.Env().Undefined();
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
- GET_INT64_ARG(0);
140
- void* data = (void*) i64;
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(getViewAddress) {
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
- napi_get_typedarray_info(env, args[0], nullptr, nullptr, &data, nullptr, nullptr);
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
- *((double*) data->mv_data) = version;
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 pthread_cond_init(pthread_cond_t *cond, pthread_condattr_t *attr)
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 += ns % 1000000000;
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
@@ -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
+ }