@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/index.js
CHANGED
|
@@ -1,37 +1,38 @@
|
|
|
1
|
-
import { EventEmitter } from 'events';
|
|
2
|
-
import { setExternals, setNativeFunctions, Dbi } from './native.js';
|
|
3
|
-
import { arch, tmpdir, platform } from 'os';
|
|
4
|
-
import fs from 'fs';
|
|
5
|
-
import { Encoder as MsgpackrEncoder } from 'msgpackr';
|
|
6
|
-
import { WeakLRUCache } from 'weak-lru-cache';
|
|
7
|
-
import * as orderedBinary from 'ordered-binary';
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
orderedBinary.enableNullTermination();
|
|
11
|
-
setExternals({
|
|
12
|
-
arch, fs, tmpdir, MsgpackrEncoder, WeakLRUCache, orderedBinary,
|
|
13
|
-
EventEmitter, os: platform(), onExit(callback) {
|
|
14
|
-
if (process.getMaxListeners() < process.listenerCount('exit') + 8)
|
|
15
|
-
process.setMaxListeners(process.listenerCount('exit') + 8);
|
|
16
|
-
process.on('exit', callback);
|
|
17
|
-
},
|
|
18
|
-
});
|
|
19
|
-
export { toBufferKey as keyValueToBuffer, compareKeys, compareKeys as compareKey, fromBufferKey as bufferToKeyValue } from 'ordered-binary';
|
|
20
|
-
export { ABORT, IF_EXISTS, asBinary } from './write.js';
|
|
21
|
-
import { ABORT, IF_EXISTS, asBinary } from './write.js';
|
|
22
|
-
export { levelup } from './level.js';
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
export {
|
|
28
|
-
|
|
29
|
-
import {
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
1
|
+
import { EventEmitter } from 'events';
|
|
2
|
+
import { setExternals, setNativeFunctions, Dbi } from './native.js';
|
|
3
|
+
import { arch, tmpdir, platform } from 'os';
|
|
4
|
+
import fs from 'fs';
|
|
5
|
+
import { Encoder as MsgpackrEncoder } from 'msgpackr';
|
|
6
|
+
import { WeakLRUCache } from 'weak-lru-cache';
|
|
7
|
+
import * as orderedBinary from 'ordered-binary';
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
orderedBinary.enableNullTermination();
|
|
11
|
+
setExternals({
|
|
12
|
+
arch, fs, tmpdir, MsgpackrEncoder, WeakLRUCache, orderedBinary,
|
|
13
|
+
EventEmitter, os: platform(), onExit(callback) {
|
|
14
|
+
if (process.getMaxListeners() < process.listenerCount('exit') + 8)
|
|
15
|
+
process.setMaxListeners(process.listenerCount('exit') + 8);
|
|
16
|
+
process.on('exit', callback);
|
|
17
|
+
},
|
|
18
|
+
});
|
|
19
|
+
export { toBufferKey as keyValueToBuffer, compareKeys, compareKeys as compareKey, fromBufferKey as bufferToKeyValue } from 'ordered-binary';
|
|
20
|
+
export { ABORT, IF_EXISTS, asBinary } from './write.js';
|
|
21
|
+
import { ABORT, IF_EXISTS, asBinary } from './write.js';
|
|
22
|
+
export { levelup } from './level.js';
|
|
23
|
+
export { SKIP } from './util/RangeIterable.js';
|
|
24
|
+
import { levelup } from './level.js';
|
|
25
|
+
export { clearKeptObjects } from './native.js';
|
|
26
|
+
import { nativeAddon } from './native.js';
|
|
27
|
+
export let { noop } = nativeAddon;
|
|
28
|
+
export { open, openAsClass, getLastVersion, allDbs, getLastTxnId } from './open.js';
|
|
29
|
+
import { toBufferKey as keyValueToBuffer, compareKeys as compareKey, fromBufferKey as bufferToKeyValue } from 'ordered-binary';
|
|
30
|
+
import { open, openAsClass, getLastVersion } from './open.js';
|
|
31
|
+
export const TransactionFlags = {
|
|
32
|
+
ABORTABLE: 1,
|
|
33
|
+
SYNCHRONOUS_COMMIT: 2,
|
|
34
|
+
NO_SYNC_FLUSH: 0x10000,
|
|
35
|
+
};
|
|
36
|
+
export default {
|
|
37
|
+
open, openAsClass, getLastVersion, compareKey, keyValueToBuffer, bufferToKeyValue, ABORT, IF_EXISTS, asBinary, levelup, TransactionFlags
|
|
38
|
+
};
|
package/keys.js
CHANGED
|
@@ -1,102 +1,116 @@
|
|
|
1
|
-
import { getAddress, orderedBinary } from './native.js';
|
|
2
|
-
|
|
3
|
-
const
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
const
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
store.
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
store.
|
|
46
|
-
store.
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
}
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
1
|
+
import { getAddress, orderedBinary } from './native.js';
|
|
2
|
+
|
|
3
|
+
const REUSE_BUFFER_MODE = 512;
|
|
4
|
+
const writeUint32Key = (key, target, start) => {
|
|
5
|
+
(target.dataView || (target.dataView = new DataView(target.buffer, 0, target.length))).setUint32(start, key, true);
|
|
6
|
+
return start + 4;
|
|
7
|
+
};
|
|
8
|
+
const readUint32Key = (target, start) => {
|
|
9
|
+
return (target.dataView || (target.dataView = new DataView(target.buffer, 0, target.length))).getUint32(start, true);
|
|
10
|
+
};
|
|
11
|
+
const writeBufferKey = (key, target, start) => {
|
|
12
|
+
target.set(key, start);
|
|
13
|
+
return key.length + start;
|
|
14
|
+
};
|
|
15
|
+
const Uint8ArraySlice = Uint8Array.prototype.slice;
|
|
16
|
+
const readBufferKey = (target, start, end) => {
|
|
17
|
+
return Uint8ArraySlice.call(target, start, end);
|
|
18
|
+
};
|
|
19
|
+
|
|
20
|
+
let lastEncodedValue, bytes;
|
|
21
|
+
export function applyKeyHandling(store) {
|
|
22
|
+
if (store.encoding == 'ordered-binary') {
|
|
23
|
+
store.encoder = store.decoder = {
|
|
24
|
+
writeKey: orderedBinary.writeKey,
|
|
25
|
+
readKey: orderedBinary.readKey,
|
|
26
|
+
};
|
|
27
|
+
}
|
|
28
|
+
if (store.encoder && store.encoder.writeKey && !store.encoder.encode) {
|
|
29
|
+
store.encoder.encode = function(value, mode) {
|
|
30
|
+
if (typeof value !== 'object' && value && value === lastEncodedValue) {
|
|
31
|
+
// reuse the last serialized bytes
|
|
32
|
+
// NOTE that it is very important that nothing else calls saveKey with saveTo: false
|
|
33
|
+
} else {
|
|
34
|
+
lastEncodedValue = value;
|
|
35
|
+
bytes = saveKey(value, this.writeKey, false, store.maxKeySize);
|
|
36
|
+
}
|
|
37
|
+
if (bytes.end > 0 && !(REUSE_BUFFER_MODE & mode)) {
|
|
38
|
+
return bytes.subarray(bytes.start, bytes.end);
|
|
39
|
+
}
|
|
40
|
+
return bytes;
|
|
41
|
+
};
|
|
42
|
+
store.encoder.copyBuffers = true; // just an indicator for the buffer reuse in write.js
|
|
43
|
+
}
|
|
44
|
+
if (store.decoder && store.decoder.readKey && !store.decoder.decode) {
|
|
45
|
+
store.decoder.decode = function(buffer) { return this.readKey(buffer, 0, buffer.length); };
|
|
46
|
+
store.decoderCopies = true;
|
|
47
|
+
}
|
|
48
|
+
if (store.keyIsUint32 || store.keyEncoding == 'uint32') {
|
|
49
|
+
store.writeKey = writeUint32Key;
|
|
50
|
+
store.readKey = readUint32Key;
|
|
51
|
+
} else if (store.keyIsBuffer || store.keyEncoding == 'binary') {
|
|
52
|
+
store.writeKey = writeBufferKey;
|
|
53
|
+
store.readKey = readBufferKey;
|
|
54
|
+
} else if (store.keyEncoder) {
|
|
55
|
+
store.writeKey = store.keyEncoder.writeKey;
|
|
56
|
+
store.readKey = store.keyEncoder.readKey;
|
|
57
|
+
} else {
|
|
58
|
+
store.writeKey = orderedBinary.writeKey;
|
|
59
|
+
store.readKey = orderedBinary.readKey;
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
let saveBuffer, uint32, saveDataView = { setFloat64() {}, setUint32() {} }, saveDataAddress;
|
|
64
|
+
let savePosition = 8000;
|
|
65
|
+
let DYNAMIC_KEY_BUFFER_SIZE = 8192;
|
|
66
|
+
function allocateSaveBuffer() {
|
|
67
|
+
saveBuffer = typeof Buffer != 'undefined' ? Buffer.alloc(DYNAMIC_KEY_BUFFER_SIZE) : new Uint8Array(DYNAMIC_KEY_BUFFER_SIZE);
|
|
68
|
+
uint32 = null;
|
|
69
|
+
saveBuffer.buffer.address = getAddress(saveBuffer.buffer);
|
|
70
|
+
saveDataAddress = saveBuffer.buffer.address;
|
|
71
|
+
// TODO: Conditionally only do this for key sequences?
|
|
72
|
+
saveDataView.setUint32(savePosition, 0xffffffff);
|
|
73
|
+
saveDataView.setFloat64(savePosition + 4, saveDataAddress, true); // save a pointer from the old buffer to the new address for the sake of the prefetch sequences
|
|
74
|
+
saveDataView = saveBuffer.dataView || (saveBuffer.dataView = new DataView(saveBuffer.buffer, saveBuffer.byteOffset, saveBuffer.byteLength));
|
|
75
|
+
savePosition = 0;
|
|
76
|
+
}
|
|
77
|
+
export function saveKey(key, writeKey, saveTo, maxKeySize, flags) {
|
|
78
|
+
if (savePosition > 7800) {
|
|
79
|
+
allocateSaveBuffer();
|
|
80
|
+
}
|
|
81
|
+
let start = savePosition;
|
|
82
|
+
try {
|
|
83
|
+
savePosition = key === undefined ? start + 4 :
|
|
84
|
+
writeKey(key, saveBuffer, start + 4);
|
|
85
|
+
} catch (error) {
|
|
86
|
+
saveBuffer.fill(0, start + 4); // restore zeros
|
|
87
|
+
if (error.name == 'RangeError') {
|
|
88
|
+
if (8180 - start < maxKeySize) {
|
|
89
|
+
allocateSaveBuffer(); // try again:
|
|
90
|
+
return saveKey(key, writeKey, saveTo, maxKeySize);
|
|
91
|
+
}
|
|
92
|
+
throw new Error('Key was too large, max key size is ' + maxKeySize);
|
|
93
|
+
} else
|
|
94
|
+
throw error;
|
|
95
|
+
}
|
|
96
|
+
let length = savePosition - start - 4;
|
|
97
|
+
if (length > maxKeySize) {
|
|
98
|
+
throw new Error('Key of size ' + length + ' was too large, max key size is ' + maxKeySize);
|
|
99
|
+
}
|
|
100
|
+
if (savePosition >= 8160) { // need to reserve enough room at the end for pointers
|
|
101
|
+
savePosition = start // reset position
|
|
102
|
+
allocateSaveBuffer(); // try again:
|
|
103
|
+
return saveKey(key, writeKey, saveTo, maxKeySize);
|
|
104
|
+
}
|
|
105
|
+
if (saveTo) {
|
|
106
|
+
saveDataView.setUint32(start, flags ? length | flags : length, true); // save the length
|
|
107
|
+
saveTo.saveBuffer = saveBuffer;
|
|
108
|
+
savePosition = (savePosition + 12) & 0xfffffc;
|
|
109
|
+
return start + saveDataAddress;
|
|
110
|
+
} else {
|
|
111
|
+
saveBuffer.start = start + 4;
|
|
112
|
+
saveBuffer.end = savePosition;
|
|
113
|
+
savePosition = (savePosition + 7) & 0xfffff8; // full 64-bit word alignment since these are usually copied
|
|
114
|
+
return saveBuffer;
|
|
115
|
+
}
|
|
116
|
+
}
|
package/level.js
CHANGED
|
@@ -1,27 +1,27 @@
|
|
|
1
|
-
export function levelup(store) {
|
|
2
|
-
return Object.assign(Object.create(store), {
|
|
3
|
-
get(key, options, callback) {
|
|
4
|
-
let result = store.get(key);
|
|
5
|
-
if (typeof options == 'function')
|
|
6
|
-
callback = options;
|
|
7
|
-
if (callback) {
|
|
8
|
-
if (result === undefined)
|
|
9
|
-
callback(new NotFoundError());
|
|
10
|
-
else
|
|
11
|
-
callback(null, result);
|
|
12
|
-
} else {
|
|
13
|
-
if (result === undefined)
|
|
14
|
-
return Promise.reject(new NotFoundError());
|
|
15
|
-
else
|
|
16
|
-
return Promise.resolve(result);
|
|
17
|
-
}
|
|
18
|
-
},
|
|
19
|
-
});
|
|
20
|
-
}
|
|
21
|
-
class NotFoundError extends Error {
|
|
22
|
-
constructor(message) {
|
|
23
|
-
super(message);
|
|
24
|
-
this.name = 'NotFoundError';
|
|
25
|
-
this.notFound = true;
|
|
26
|
-
}
|
|
1
|
+
export function levelup(store) {
|
|
2
|
+
return Object.assign(Object.create(store), {
|
|
3
|
+
get(key, options, callback) {
|
|
4
|
+
let result = store.get(key);
|
|
5
|
+
if (typeof options == 'function')
|
|
6
|
+
callback = options;
|
|
7
|
+
if (callback) {
|
|
8
|
+
if (result === undefined)
|
|
9
|
+
callback(new NotFoundError());
|
|
10
|
+
else
|
|
11
|
+
callback(null, result);
|
|
12
|
+
} else {
|
|
13
|
+
if (result === undefined)
|
|
14
|
+
return Promise.reject(new NotFoundError());
|
|
15
|
+
else
|
|
16
|
+
return Promise.resolve(result);
|
|
17
|
+
}
|
|
18
|
+
},
|
|
19
|
+
});
|
|
20
|
+
}
|
|
21
|
+
class NotFoundError extends Error {
|
|
22
|
+
constructor(message) {
|
|
23
|
+
super(message);
|
|
24
|
+
this.name = 'NotFoundError';
|
|
25
|
+
this.notFound = true;
|
|
26
|
+
}
|
|
27
27
|
}
|
package/native.js
CHANGED
|
@@ -1,14 +1,12 @@
|
|
|
1
1
|
import { dirname, join, default as pathModule } from 'path';
|
|
2
2
|
import { fileURLToPath } from 'url';
|
|
3
3
|
import loadNAPI from 'node-gyp-build-optional-packages';
|
|
4
|
-
export let Env, Txn, Dbi, Compression, Cursor, getAddress, createBufferForAddress, clearKeptObjects, setGlobalBuffer, arch, fs, os, onExit, tmpdir, lmdbError, path, EventEmitter, orderedBinary, MsgpackrEncoder, WeakLRUCache, setEnvMap, getEnvMap, getByBinary, detachBuffer, write, position, iterate, prefetch, resetTxn, getCurrentValue, getCurrentShared, getStringByBinary, getSharedByBinary, compress;
|
|
5
|
-
|
|
4
|
+
export let Env, Txn, Dbi, Compression, Cursor, getAddress, getBufferAddress, createBufferForAddress, clearKeptObjects, globalBuffer, setGlobalBuffer, arch, fs, os, onExit, tmpdir, lmdbError, path, EventEmitter, orderedBinary, MsgpackrEncoder, WeakLRUCache, setEnvMap, getEnvMap, getByBinary, detachBuffer, startRead, setReadCallback, write, position, iterate, prefetch, resetTxn, getCurrentValue, getCurrentShared, getStringByBinary, getSharedByBinary, getSharedBuffer, compress;
|
|
6
5
|
path = pathModule;
|
|
7
|
-
let dirName = (
|
|
8
|
-
dirname(fileURLToPath(import.meta.url))).replace(/dist$/, ''); // for node, which doesn't have __dirname in ESM
|
|
6
|
+
let dirName = dirname(fileURLToPath(import.meta.url)).replace(/dist$/, '');
|
|
9
7
|
export let nativeAddon = loadNAPI(dirName);
|
|
10
8
|
|
|
11
|
-
if (process.isBun) {
|
|
9
|
+
if (process.isBun && false) {
|
|
12
10
|
const { linkSymbols, FFIType } = require('bun:ffi');
|
|
13
11
|
let lmdbLib = linkSymbols({
|
|
14
12
|
getByBinary: {
|
|
@@ -49,11 +47,16 @@ export function setNativeFunctions(externals) {
|
|
|
49
47
|
Dbi = externals.Dbi;
|
|
50
48
|
Compression = externals.Compression;
|
|
51
49
|
getAddress = externals.getAddress;
|
|
50
|
+
getBufferAddress = externals.getBufferAddress;
|
|
52
51
|
createBufferForAddress = externals.createBufferForAddress;
|
|
53
52
|
clearKeptObjects = externals.clearKeptObjects || function() {};
|
|
54
53
|
getByBinary = externals.getByBinary;
|
|
55
54
|
detachBuffer = externals.detachBuffer;
|
|
55
|
+
startRead = externals.startRead;
|
|
56
|
+
setReadCallback = externals.setReadCallback;
|
|
56
57
|
setGlobalBuffer = externals.setGlobalBuffer;
|
|
58
|
+
globalBuffer = externals.globalBuffer;
|
|
59
|
+
getSharedBuffer = externals.getSharedBuffer;
|
|
57
60
|
prefetch = externals.prefetch;
|
|
58
61
|
iterate = externals.iterate;
|
|
59
62
|
position = externals.position;
|
package/node-index.js
CHANGED
|
@@ -1,26 +1,30 @@
|
|
|
1
1
|
import { createRequire } from 'module';
|
|
2
2
|
import { setRequire } from './open.js';
|
|
3
3
|
import { nativeAddon, setNativeFunctions } from './native.js';
|
|
4
|
-
|
|
5
|
-
|
|
4
|
+
export { nativeAddon } from './native.js'
|
|
5
|
+
let require = createRequire(import.meta.url);
|
|
6
|
+
setRequire(require);
|
|
6
7
|
export let v8AccelerationEnabled = false
|
|
7
8
|
|
|
8
9
|
let versions = process.versions;
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
if (versions.v8 && +majorVersion == nativeAddon.version.nodeCompiledVersion) {
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
10
|
+
if (!versions.deno && !process.isBun) {
|
|
11
|
+
let [ majorVersion, minorVersion ] = versions.node.split('.');
|
|
12
|
+
if (versions.v8 && +majorVersion == nativeAddon.version.nodeCompiledVersion) {
|
|
13
|
+
let v8Funcs = {};
|
|
14
|
+
let fastApiCalls = (majorVersion == 17 || majorVersion == 18 || majorVersion == 16 && minorVersion > 8) && !process.env.DISABLE_TURBO_CALLS;
|
|
15
|
+
if (fastApiCalls) {
|
|
16
|
+
require('v8').setFlagsFromString('--turbo-fast-api-calls');
|
|
17
|
+
}
|
|
18
|
+
nativeAddon.enableDirectV8(v8Funcs, fastApiCalls);
|
|
19
|
+
Object.assign(nativeAddon, v8Funcs);
|
|
20
|
+
v8AccelerationEnabled = true;
|
|
21
|
+
} else if (majorVersion == 14) {
|
|
22
|
+
// node v14 only has ABI compatibility with node v16 for zero-arg clearKeptObjects
|
|
23
|
+
let v8Funcs = {};
|
|
24
|
+
nativeAddon.enableDirectV8(v8Funcs, false);
|
|
25
|
+
nativeAddon.clearKeptObjects = v8Funcs.clearKeptObjects;
|
|
26
|
+
}
|
|
27
|
+
nativeAddon.enableThreadSafeCalls();
|
|
24
28
|
}
|
|
25
29
|
setNativeFunctions(nativeAddon);
|
|
26
30
|
|
package/open.js
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
import { Compression, getAddress, arch, fs, path as pathModule, lmdbError, EventEmitter, MsgpackrEncoder, Env,
|
|
1
|
+
import { Compression, getAddress, arch, fs, path as pathModule, lmdbError, EventEmitter, MsgpackrEncoder, Env,
|
|
2
|
+
Dbi, tmpdir, os, nativeAddon } from './native.js';
|
|
2
3
|
import { CachingStore, setGetLastVersion } from './caching.js';
|
|
3
4
|
import { addReadMethods, makeReusableBuffer } from './read.js';
|
|
4
5
|
import { addWriteMethods } from './write.js';
|
|
@@ -8,7 +9,7 @@ export function setRequire(require) {
|
|
|
8
9
|
moduleRequire = require;
|
|
9
10
|
}
|
|
10
11
|
|
|
11
|
-
setGetLastVersion(getLastVersion);
|
|
12
|
+
setGetLastVersion(getLastVersion, getLastTxnId);
|
|
12
13
|
let keyBytes, keyBytesView;
|
|
13
14
|
const buffers = [];
|
|
14
15
|
const { onExit, getEnvsPointer, setEnvsPointer, getEnvFlags, setJSFlags } = nativeAddon;
|
|
@@ -20,6 +21,9 @@ else
|
|
|
20
21
|
// this is hard coded as an upper limit because it is important assumption of the fixed buffers in writing instructions
|
|
21
22
|
// this corresponds to the max key size for 8KB pages
|
|
22
23
|
const MAX_KEY_SIZE = 4026;
|
|
24
|
+
// this is used as the key size by default because default page size is OS page size, which is usually
|
|
25
|
+
// 4KB (but is 16KB on M-series MacOS), and this keeps a consistent max key size when no page size specified.
|
|
26
|
+
const DEFAULT_MAX_KEY_SIZE = 1978;
|
|
23
27
|
const DEFAULT_COMMIT_DELAY = 0;
|
|
24
28
|
|
|
25
29
|
export const allDbs = new Map();
|
|
@@ -27,6 +31,20 @@ let defaultCompression;
|
|
|
27
31
|
let lastSize;
|
|
28
32
|
let hasRegisteredOnExit;
|
|
29
33
|
export function open(path, options) {
|
|
34
|
+
if (nativeAddon.open) {
|
|
35
|
+
if (nativeAddon.open !== open) {
|
|
36
|
+
// this is the case when lmdb-js has been opened in both ESM and CJS mode, which means that there are two
|
|
37
|
+
// separate JS modules, but they are both using the same native module.
|
|
38
|
+
getLastVersion = nativeAddon.getLastVersion;
|
|
39
|
+
getLastTxnId = nativeAddon.getLastTxnId;
|
|
40
|
+
setGetLastVersion(getLastVersion, getLastTxnId);
|
|
41
|
+
return nativeAddon.open(path, options);
|
|
42
|
+
}
|
|
43
|
+
} else {
|
|
44
|
+
nativeAddon.open = open;
|
|
45
|
+
nativeAddon.getLastVersion = getLastVersion;
|
|
46
|
+
nativeAddon.getLastTxnId = getLastTxnId;
|
|
47
|
+
}
|
|
30
48
|
if (!keyBytes) // TODO: Consolidate get buffer and key buffer (don't think we need both)
|
|
31
49
|
allocateFixedBuffer();
|
|
32
50
|
if (typeof path == 'object' && !options) {
|
|
@@ -34,8 +52,9 @@ export function open(path, options) {
|
|
|
34
52
|
path = options.path;
|
|
35
53
|
}
|
|
36
54
|
options = options || {};
|
|
55
|
+
let noFSAccess = options.noFSAccess; // this can only be configured on open, can't let users change it
|
|
37
56
|
let userOptions = options;
|
|
38
|
-
if (
|
|
57
|
+
if (path == null) {
|
|
39
58
|
options = Object.assign({
|
|
40
59
|
deleteOnClose: true,
|
|
41
60
|
noSync: true,
|
|
@@ -46,17 +65,16 @@ export function open(path, options) {
|
|
|
46
65
|
let extension = pathModule.extname(path);
|
|
47
66
|
let name = pathModule.basename(path, extension);
|
|
48
67
|
let is32Bit = arch().endsWith('32');
|
|
49
|
-
let remapChunks = options.remapChunks || (options.mapSize ?
|
|
68
|
+
let remapChunks = options.remapChunks || options.encryptionKey || (options.mapSize ?
|
|
50
69
|
(is32Bit && options.mapSize > 0x100000000) : // larger than fits in address space, must use dynamic maps
|
|
51
70
|
is32Bit); // without a known map size, we default to being able to handle large data correctly/well*/
|
|
71
|
+
let userMapSize = options.mapSize;
|
|
52
72
|
options = Object.assign({
|
|
53
|
-
path,
|
|
54
73
|
noSubdir: Boolean(extension),
|
|
55
74
|
isRoot: true,
|
|
56
75
|
maxDbs: 12,
|
|
57
76
|
remapChunks,
|
|
58
77
|
keyBytes,
|
|
59
|
-
pageSize: 4096,
|
|
60
78
|
overlappingSync: (options.noSync || options.readOnly) ? false : (os != 'win32'),
|
|
61
79
|
// default map size limit of 4 exabytes when using remapChunks, since it is not preallocated and we can
|
|
62
80
|
// make it super huge.
|
|
@@ -64,9 +82,18 @@ export function open(path, options) {
|
|
|
64
82
|
0x20000, // Otherwise we start small with 128KB
|
|
65
83
|
safeRestore: process.env.LMDB_RESTORE == 'safe',
|
|
66
84
|
}, options);
|
|
85
|
+
options.path = path;
|
|
67
86
|
if (options.asyncTransactionOrder == 'strict') {
|
|
68
87
|
options.strictAsyncOrder = true;
|
|
69
88
|
}
|
|
89
|
+
if (nativeAddon.version.major + nativeAddon.version.minor / 100 + nativeAddon.version.patch / 10000 < 0.0980) {
|
|
90
|
+
options.overlappingSync = false; // not support on older versions
|
|
91
|
+
options.trackMetrics = false;
|
|
92
|
+
options.usePreviousSnapshot = false;
|
|
93
|
+
options.safeRestore = false;
|
|
94
|
+
options.remapChunks = false;
|
|
95
|
+
if (!userMapSize) options.mapSize = 0x40000000; // 1 GB
|
|
96
|
+
}
|
|
70
97
|
|
|
71
98
|
if (!exists(options.noSubdir ? pathModule.dirname(path) : path))
|
|
72
99
|
fs.mkdirSync(options.noSubdir ? pathModule.dirname(path) : path, { recursive: true }
|
|
@@ -102,17 +129,20 @@ export function open(path, options) {
|
|
|
102
129
|
(options.noMemInit ? 0x1000000 : 0) |
|
|
103
130
|
(options.usePreviousSnapshot ? 0x2000000 : 0) |
|
|
104
131
|
(options.remapChunks ? 0x4000000 : 0) |
|
|
105
|
-
(options.safeRestore ?
|
|
132
|
+
(options.safeRestore ? 0x800 : 0) |
|
|
133
|
+
(options.trackMetrics ? 0x400 : 0);
|
|
106
134
|
|
|
107
135
|
let env = new Env();
|
|
108
136
|
let jsFlags = (options.overlappingSync ? 0x1000 : 0) |
|
|
109
137
|
(options.separateFlushed ? 1 : 0) |
|
|
110
|
-
(options.deleteOnClose ? 2 : 0)
|
|
138
|
+
(options.deleteOnClose ? 2 : 0);
|
|
111
139
|
let rc = env.open(options, flags, jsFlags);
|
|
140
|
+
env.path = path;
|
|
112
141
|
if (rc)
|
|
113
142
|
lmdbError(rc);
|
|
143
|
+
delete options.keyBytes // no longer needed, don't copy to stores
|
|
114
144
|
let maxKeySize = env.getMaxKeySize();
|
|
115
|
-
maxKeySize = Math.min(maxKeySize, MAX_KEY_SIZE);
|
|
145
|
+
maxKeySize = Math.min(maxKeySize, options.pageSize ? MAX_KEY_SIZE : DEFAULT_MAX_KEY_SIZE);
|
|
116
146
|
flags = getEnvFlags(env.address); // re-retrieve them, they are not necessarily the same if we are connecting to an existing env
|
|
117
147
|
if (flags & 0x1000) {
|
|
118
148
|
if (userOptions.noSync) {
|
|
@@ -130,7 +160,6 @@ export function open(path, options) {
|
|
|
130
160
|
}
|
|
131
161
|
|
|
132
162
|
env.readerCheck(); // clear out any stale entries
|
|
133
|
-
let stores = [];
|
|
134
163
|
if ((options.overlappingSync || options.deleteOnClose) && !hasRegisteredOnExit && process.on) {
|
|
135
164
|
hasRegisteredOnExit = true;
|
|
136
165
|
process.on('exit', onExit);
|
|
@@ -167,14 +196,14 @@ export function open(path, options) {
|
|
|
167
196
|
(dbOptions.integerDup ? 0x20 : 0) |
|
|
168
197
|
(dbOptions.reverseDup ? 0x40 : 0) |
|
|
169
198
|
(!options.readOnly && dbOptions.create !== false ? 0x40000 : 0) |
|
|
170
|
-
(dbOptions.useVersions ?
|
|
199
|
+
(dbOptions.useVersions ? 0x100 : 0);
|
|
171
200
|
let keyType = (dbOptions.keyIsUint32 || dbOptions.keyEncoding == 'uint32') ? 2 : keyIsBuffer ? 3 : 0;
|
|
172
201
|
if (keyType == 2)
|
|
173
202
|
flags |= 0x08; // integer key
|
|
174
203
|
|
|
175
204
|
if (options.readOnly) {
|
|
176
205
|
// in read-only mode we use a read-only txn to open the database
|
|
177
|
-
// TODO: LMDB is actually not
|
|
206
|
+
// TODO: LMDB is actually not entirely thread-safe when it comes to opening databases with
|
|
178
207
|
// read-only transactions since there is a race condition on setting the update dbis that
|
|
179
208
|
// occurs outside the lock
|
|
180
209
|
// make sure we are using a fresh read txn, so we don't want to share with a cursor txn
|
|
@@ -219,7 +248,7 @@ export function open(path, options) {
|
|
|
219
248
|
}
|
|
220
249
|
if (Encoder) {
|
|
221
250
|
this.encoder = new Encoder(Object.assign(
|
|
222
|
-
assignConstrainedProperties(['copyBuffers', 'getStructures', 'saveStructures', 'useFloat32', 'useRecords', 'structuredClone', 'variableMapSize', 'useTimestamp32', 'largeBigIntToFloat', 'encodeUndefinedAsNil', 'int64AsNumber', 'onInvalidDate', 'mapsAsObjects', 'useTag259ForMaps', 'pack', 'maxSharedStructures', 'shouldShareStructure'],
|
|
251
|
+
assignConstrainedProperties(['copyBuffers', 'getStructures', 'saveStructures', 'useFloat32', 'useRecords', 'structuredClone', 'variableMapSize', 'useTimestamp32', 'largeBigIntToFloat', 'encodeUndefinedAsNil', 'int64AsNumber', 'onInvalidDate', 'mapsAsObjects', 'useTag259ForMaps', 'pack', 'maxSharedStructures', 'shouldShareStructure', 'randomAccessStructure', 'freezeData'],
|
|
223
252
|
this.sharedStructuresKey ? this.setupSharedStructures() : {
|
|
224
253
|
copyBuffers: true, // need to copy any embedded buffers that are found since we use unsafe buffers
|
|
225
254
|
}, options, dbOptions), this.encoder));
|
|
@@ -235,7 +264,6 @@ export function open(path, options) {
|
|
|
235
264
|
this.maxKeySize = maxKeySize;
|
|
236
265
|
applyKeyHandling(this);
|
|
237
266
|
allDbs.set(dbName ? name + '-' + dbName : name, this);
|
|
238
|
-
stores.push(this);
|
|
239
267
|
}
|
|
240
268
|
openDB(dbName, dbOptions) {
|
|
241
269
|
if (this.dupSort && this.name == null)
|
|
@@ -264,7 +292,10 @@ export function open(path, options) {
|
|
|
264
292
|
callback(null, db);
|
|
265
293
|
return db;
|
|
266
294
|
}
|
|
267
|
-
backup(path) {
|
|
295
|
+
backup(path, compact) {
|
|
296
|
+
if (noFSAccess)
|
|
297
|
+
return;
|
|
298
|
+
fs.mkdirSync(pathModule.dirname(path), { recursive: true });
|
|
268
299
|
return new Promise((resolve, reject) => env.copy(path, false, (error) => {
|
|
269
300
|
if (error) {
|
|
270
301
|
reject(error);
|
|
@@ -377,11 +408,14 @@ export function openAsClass(path, options) {
|
|
|
377
408
|
export function getLastVersion() {
|
|
378
409
|
return keyBytesView.getFloat64(16, true);
|
|
379
410
|
}
|
|
380
|
-
|
|
381
411
|
export function setLastVersion(version) {
|
|
382
412
|
return keyBytesView.setFloat64(16, version, true);
|
|
383
413
|
}
|
|
384
414
|
|
|
415
|
+
export function getLastTxnId() {
|
|
416
|
+
return keyBytesView.getUint32(32, true);
|
|
417
|
+
}
|
|
418
|
+
|
|
385
419
|
const KEY_BUFFER_SIZE = 4096;
|
|
386
420
|
function allocateFixedBuffer() {
|
|
387
421
|
keyBytes = typeof Buffer != 'undefined' ? Buffer.allocUnsafeSlow(KEY_BUFFER_SIZE) : new Uint8Array(KEY_BUFFER_SIZE);
|
|
@@ -389,7 +423,7 @@ function allocateFixedBuffer() {
|
|
|
389
423
|
keyBytesView = keyBytes.dataView || (keyBytes.dataView = new DataView(keyBytes.buffer, 0, KEY_BUFFER_SIZE)); // max key size is actually 4026
|
|
390
424
|
keyBytes.uint32 = new Uint32Array(keyBuffer, 0, KEY_BUFFER_SIZE >> 2);
|
|
391
425
|
keyBytes.float64 = new Float64Array(keyBuffer, 0, KEY_BUFFER_SIZE >> 3);
|
|
392
|
-
keyBytes.uint32.address = keyBytes.address = keyBuffer.address = getAddress(
|
|
426
|
+
keyBytes.uint32.address = keyBytes.address = keyBuffer.address = getAddress(keyBuffer);
|
|
393
427
|
}
|
|
394
428
|
|
|
395
429
|
function exists(path) {
|