@based/db 0.0.19 → 0.0.21
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/basedDbNative.cjs +6 -2
- package/dist/lib/darwin_aarch64/include/selva/db.h +92 -9
- package/dist/lib/darwin_aarch64/include/selva/fast_memcmp.h +18 -0
- package/dist/lib/darwin_aarch64/include/selva/fields.h +31 -32
- package/dist/lib/darwin_aarch64/include/selva/types.h +0 -10
- package/dist/lib/darwin_aarch64/libdeflate.dylib +0 -0
- package/dist/lib/darwin_aarch64/libjemalloc_selva.2.dylib +0 -0
- package/dist/lib/darwin_aarch64/libnode-v20.node +0 -0
- package/dist/lib/darwin_aarch64/libnode-v21.node +0 -0
- package/dist/lib/darwin_aarch64/libnode-v22.node +0 -0
- package/dist/lib/darwin_aarch64/libnode-v23.node +0 -0
- package/dist/lib/darwin_aarch64/libselva.dylib +0 -0
- package/dist/lib/darwin_aarch64/libxxhash.dylib +0 -0
- package/dist/lib/linux_aarch64/include/selva/db.h +92 -9
- package/dist/lib/linux_aarch64/include/selva/fast_memcmp.h +18 -0
- package/dist/lib/linux_aarch64/include/selva/fields.h +31 -32
- package/dist/lib/linux_aarch64/include/selva/types.h +0 -10
- package/dist/lib/linux_aarch64/libnode-v20.node +0 -0
- package/dist/lib/linux_aarch64/libnode-v21.node +0 -0
- package/dist/lib/linux_aarch64/libnode-v22.node +0 -0
- package/dist/lib/linux_aarch64/libnode-v23.node +0 -0
- package/dist/lib/linux_aarch64/libselva.so +0 -0
- package/dist/lib/linux_x86_64/include/selva/db.h +92 -9
- package/dist/lib/linux_x86_64/include/selva/fast_memcmp.h +18 -0
- package/dist/lib/linux_x86_64/include/selva/fields.h +31 -32
- package/dist/lib/linux_x86_64/include/selva/types.h +0 -10
- package/dist/lib/linux_x86_64/libnode-v20.node +0 -0
- package/dist/lib/linux_x86_64/libnode-v21.node +0 -0
- package/dist/lib/linux_x86_64/libnode-v22.node +0 -0
- package/dist/lib/linux_x86_64/libnode-v23.node +0 -0
- package/dist/lib/linux_x86_64/libselva.so +0 -0
- package/dist/src/client/bitWise.js +0 -1
- package/dist/src/client/crc32.d.ts +1 -1
- package/dist/src/client/modify/alias.js +3 -3
- package/dist/src/client/modify/binary.d.ts +1 -1
- package/dist/src/client/modify/binary.js +7 -6
- package/dist/src/client/modify/cardinality.d.ts +3 -1
- package/dist/src/client/modify/cardinality.js +8 -4
- package/dist/src/client/modify/create.js +41 -5
- package/dist/src/client/modify/delete.js +9 -8
- package/dist/src/client/modify/expire.js +1 -1
- package/dist/src/client/modify/modify.js +3 -3
- package/dist/src/client/modify/references/edge.js +15 -1
- package/dist/src/client/modify/setCursor.js +0 -2
- package/dist/src/client/modify/string.d.ts +1 -1
- package/dist/src/client/modify/string.js +5 -3
- package/dist/src/client/modify/text.d.ts +1 -1
- package/dist/src/client/modify/text.js +52 -9
- package/dist/src/client/modify/types.d.ts +5 -1
- package/dist/src/client/modify/types.js +2 -1
- package/dist/src/client/modify/vector.js +4 -4
- package/dist/src/client/query/filter/convertFilter.js +3 -1
- package/dist/src/client/query/filter/createFixedFilterBuffer.js +1 -1
- package/dist/src/client/query/filter/createVariableFilterBuffer.js +10 -4
- package/dist/src/client/query/filter/parseFilterValue.js +13 -4
- package/dist/src/client/query/filter/primitiveFilter.js +13 -3
- package/dist/src/client/query/filter/toBuffer.js +13 -3
- package/dist/src/client/query/filter/types.d.ts +5 -3
- package/dist/src/client/query/filter/types.js +12 -0
- package/dist/src/client/query/read/read.js +7 -1
- package/dist/src/client/query/search/index.js +25 -19
- package/dist/src/client/query/serialize.d.ts +4 -0
- package/dist/src/client/query/serialize.js +26 -0
- package/dist/src/client/query/sort.d.ts +1 -1
- package/dist/src/client/query/sort.js +5 -5
- package/dist/src/client/query/subscription/run.js +1 -1
- package/dist/src/client/query/types.d.ts +6 -2
- package/dist/src/client/query/validation.js +14 -32
- package/dist/src/client/string.d.ts +2 -2
- package/dist/src/client/string.js +32 -29
- package/dist/src/client/tmpBuffer.d.ts +3 -0
- package/dist/src/client/tmpBuffer.js +20 -0
- package/dist/src/client/xxHash64.d.ts +1 -1
- package/dist/src/client/xxHash64.js +1 -1
- package/dist/src/index.d.ts +2 -0
- package/dist/src/index.js +2 -0
- package/dist/src/native.d.ts +14 -13
- package/dist/src/native.js +41 -25
- package/dist/src/server/csmt/draw-dot.js +2 -1
- package/dist/src/server/csmt/memebership-proof.d.ts +1 -1
- package/dist/src/server/csmt/tree.d.ts +2 -1
- package/dist/src/server/csmt/tree.js +10 -9
- package/dist/src/server/csmt/types.d.ts +4 -3
- package/dist/src/server/index.d.ts +5 -4
- package/dist/src/server/index.js +5 -6
- package/dist/src/server/save.js +4 -3
- package/dist/src/server/start.d.ts +1 -0
- package/dist/src/server/start.js +43 -16
- package/dist/src/server/tree.d.ts +1 -1
- package/dist/src/server/tree.js +17 -2
- package/dist/src/server/worker.js +2 -1
- package/dist/src/utils.d.ts +4 -0
- package/dist/src/utils.js +84 -0
- package/package.json +4 -4
- package/dist/lib/darwin_aarch64/libnode-v20.11.1.node +0 -0
- package/dist/lib/darwin_aarch64/libnode-v20.18.1.node +0 -0
- package/dist/lib/darwin_aarch64/libnode-v22.13.0.node +0 -0
- package/dist/lib/linux_aarch64/libnode-v20.11.1.node +0 -0
- package/dist/lib/linux_aarch64/libnode-v20.18.1.node +0 -0
- package/dist/lib/linux_aarch64/libnode-v22.13.0.node +0 -0
- package/dist/lib/linux_x86_64/libnode-v20.11.1.node +0 -0
- package/dist/lib/linux_x86_64/libnode-v20.18.1.node +0 -0
- package/dist/lib/linux_x86_64/libnode-v22.13.0.node +0 -0
package/dist/src/server/start.js
CHANGED
|
@@ -3,13 +3,14 @@ import { DbWorker } from './index.js';
|
|
|
3
3
|
import native from '../native.js';
|
|
4
4
|
import { rm, mkdir, readFile } from 'node:fs/promises';
|
|
5
5
|
import { join } from 'node:path';
|
|
6
|
-
import { createTree } from './csmt/index.js';
|
|
6
|
+
import { createTree, hashEq } from './csmt/index.js';
|
|
7
7
|
import { foreachBlock } from './tree.js';
|
|
8
8
|
import { availableParallelism } from 'node:os';
|
|
9
9
|
import exitHook from 'exit-hook';
|
|
10
10
|
import './worker.js';
|
|
11
11
|
import { save } from './save.js';
|
|
12
12
|
import { DEFAULT_BLOCK_CAPACITY } from '@based/schema/def';
|
|
13
|
+
import { bufToHex, hexToBuf } from '../utils.js';
|
|
13
14
|
const SCHEMA_FILE = 'schema.json';
|
|
14
15
|
const WRITELOG_FILE = 'writelog.json';
|
|
15
16
|
const makeCsmtKey = (typeId, start) => typeId * 4294967296 + start;
|
|
@@ -28,15 +29,23 @@ export async function start(db, opts) {
|
|
|
28
29
|
try {
|
|
29
30
|
writelog = JSON.parse((await readFile(join(path, WRITELOG_FILE))).toString());
|
|
30
31
|
// Load the common dump
|
|
31
|
-
|
|
32
|
+
try {
|
|
33
|
+
native.loadCommon(join(path, writelog.commonDump), db.dbCtxExternal);
|
|
34
|
+
}
|
|
35
|
+
catch (e) {
|
|
36
|
+
console.log(e.message);
|
|
37
|
+
throw e;
|
|
38
|
+
}
|
|
32
39
|
// Load all range dumps
|
|
33
40
|
for (const typeId in writelog.rangeDumps) {
|
|
34
41
|
const dumps = writelog.rangeDumps[typeId];
|
|
35
42
|
for (const dump of dumps) {
|
|
36
43
|
const fname = dump.file;
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
44
|
+
try {
|
|
45
|
+
native.loadRange(join(path, fname), db.dbCtxExternal);
|
|
46
|
+
}
|
|
47
|
+
catch (e) {
|
|
48
|
+
console.log(e.message);
|
|
40
49
|
}
|
|
41
50
|
}
|
|
42
51
|
}
|
|
@@ -46,13 +55,22 @@ export async function start(db, opts) {
|
|
|
46
55
|
db.putSchema(JSON.parse(schema.toString()), true);
|
|
47
56
|
}
|
|
48
57
|
}
|
|
49
|
-
catch (err) {
|
|
58
|
+
catch (err) {
|
|
59
|
+
// TODO In some cases we really should give up!
|
|
60
|
+
}
|
|
50
61
|
// The merkle tree should be empty at start.
|
|
51
62
|
if (!db.merkleTree || db.merkleTree.getRoot()) {
|
|
52
63
|
db.merkleTree = createTree(db.createCsmtHashFun);
|
|
53
64
|
}
|
|
54
|
-
|
|
55
|
-
|
|
65
|
+
// FDN-791 CSMT is unstable (not history independent)
|
|
66
|
+
// For now we just sort the types to ensure that we always
|
|
67
|
+
// load in the same order.
|
|
68
|
+
const types = Object.keys(db.schemaTypesParsed).sort((a, b) => db.schemaTypesParsed[a].id - db.schemaTypesParsed[b].id).reduce((obj, key) => {
|
|
69
|
+
obj[key] = db.schemaTypesParsed[key];
|
|
70
|
+
return obj;
|
|
71
|
+
}, {});
|
|
72
|
+
for (const key in types) {
|
|
73
|
+
const def = types[key];
|
|
56
74
|
const [total, lastId] = native.getTypeInfo(def.id, db.dbCtxExternal);
|
|
57
75
|
def.total = total;
|
|
58
76
|
def.lastId = writelog?.types[def.id]?.lastId || lastId;
|
|
@@ -71,10 +89,10 @@ export async function start(db, opts) {
|
|
|
71
89
|
});
|
|
72
90
|
}
|
|
73
91
|
if (writelog?.hash) {
|
|
74
|
-
const oldHash =
|
|
92
|
+
const oldHash = hexToBuf(writelog.hash);
|
|
75
93
|
const newHash = db.merkleTree.getRoot()?.hash;
|
|
76
|
-
if (!oldHash
|
|
77
|
-
console.error(`WARN: CSMT hash mismatch: ${writelog.hash} != ${newHash
|
|
94
|
+
if (!hashEq(oldHash, newHash)) {
|
|
95
|
+
console.error(`WARN: CSMT hash mismatch: ${writelog.hash} != ${bufToHex(newHash)}`);
|
|
78
96
|
}
|
|
79
97
|
}
|
|
80
98
|
// start workers
|
|
@@ -84,10 +102,19 @@ export async function start(db, opts) {
|
|
|
84
102
|
while (i--) {
|
|
85
103
|
db.workers[i] = new DbWorker(address, db);
|
|
86
104
|
}
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
105
|
+
if (!opts?.hosted) {
|
|
106
|
+
db.unlistenExit = exitHook(async (signal) => {
|
|
107
|
+
const blockSig = () => { };
|
|
108
|
+
const signals = ['SIGINT', 'SIGTERM', 'SIGHUP'];
|
|
109
|
+
// A really dumb way to block signals temporarily while saving.
|
|
110
|
+
// This is needed because there is no way to set the process signal mask
|
|
111
|
+
// in Node.js.
|
|
112
|
+
signals.forEach((sig) => process.on(sig, blockSig));
|
|
113
|
+
console.log(`Exiting with signal: ${signal}`);
|
|
114
|
+
save(db, true);
|
|
115
|
+
console.log('Successfully saved.');
|
|
116
|
+
signals.forEach((sig) => process.off(sig, blockSig));
|
|
117
|
+
});
|
|
118
|
+
}
|
|
92
119
|
}
|
|
93
120
|
//# sourceMappingURL=start.js.map
|
|
@@ -9,5 +9,5 @@ export type CsmtNodeRange = {
|
|
|
9
9
|
export declare const makeCsmtKey: (typeId: number, start: number) => number;
|
|
10
10
|
export declare const destructureCsmtKey: (key: number) => number[];
|
|
11
11
|
export declare const makeCsmtKeyFromNodeId: (typeId: number, blockCapacity: number, nodeId: number) => number;
|
|
12
|
-
export declare function foreachBlock(db: DbServer, def: SchemaTypeDef, cb: (start: number, end: number, hash:
|
|
12
|
+
export declare function foreachBlock(db: DbServer, def: SchemaTypeDef, cb: (start: number, end: number, hash: Uint8Array) => void): Promise<void>;
|
|
13
13
|
export declare function foreachDirtyBlock(db: DbServer, cb: (mtKey: number, typeId: number, start: number, end: number) => void): Promise<void>;
|
package/dist/src/server/tree.js
CHANGED
|
@@ -12,7 +12,7 @@ export async function foreachBlock(db, def, cb) {
|
|
|
12
12
|
const step = def.blockCapacity;
|
|
13
13
|
for (let start = 1; start <= def.lastId; start += step) {
|
|
14
14
|
const end = start + step - 1;
|
|
15
|
-
const hash =
|
|
15
|
+
const hash = new Uint8Array(16);
|
|
16
16
|
native.getNodeRangeHash(def.id, start, end, hash, db.dbCtxExternal);
|
|
17
17
|
cb(start, end, hash);
|
|
18
18
|
}
|
|
@@ -24,7 +24,22 @@ export async function foreachDirtyBlock(db, cb) {
|
|
|
24
24
|
const typeId = type.id;
|
|
25
25
|
typeIdMap[typeId] = type;
|
|
26
26
|
}
|
|
27
|
-
|
|
27
|
+
// FDN-791 CSMT is unstable (not history independent)
|
|
28
|
+
// For now we just sort the dirty data by type and start
|
|
29
|
+
// to make the insertion order more deterministic.
|
|
30
|
+
// This doesn't solve the issue completely because
|
|
31
|
+
// we might mess the order later with updates.
|
|
32
|
+
const dirty = [...db.dirtyRanges].sort((a, b) => {
|
|
33
|
+
const [aTypeId, aStart] = destructureCsmtKey(a);
|
|
34
|
+
const [bTypeId, bStart] = destructureCsmtKey(b);
|
|
35
|
+
const aId = typeIdMap[aTypeId].id;
|
|
36
|
+
const bId = typeIdMap[bTypeId].id;
|
|
37
|
+
const td = aId - bId;
|
|
38
|
+
if (td != 0)
|
|
39
|
+
return td;
|
|
40
|
+
return aStart - bStart;
|
|
41
|
+
});
|
|
42
|
+
for (const mtKey of dirty) {
|
|
28
43
|
const [typeId, start] = destructureCsmtKey(mtKey);
|
|
29
44
|
const end = start + typeIdMap[typeId].blockCapacity - 1;
|
|
30
45
|
cb(mtKey, typeId, start, end);
|
|
@@ -1,12 +1,13 @@
|
|
|
1
1
|
import { isMainThread, receiveMessageOnPort, workerData, } from 'node:worker_threads';
|
|
2
2
|
import native from '../native.js';
|
|
3
|
+
let workerCtx;
|
|
3
4
|
if (isMainThread) {
|
|
4
5
|
console.warn('running query worker.ts in mainthread');
|
|
5
6
|
}
|
|
6
7
|
else {
|
|
7
8
|
let { address, channel } = workerData;
|
|
8
9
|
let dbCtx = native.externalFromInt(address);
|
|
9
|
-
native.workerCtxInit();
|
|
10
|
+
workerCtx = native.workerCtxInit();
|
|
10
11
|
const transferList = new Array(1);
|
|
11
12
|
const handleMsg = (msg) => {
|
|
12
13
|
try {
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
export declare const equals: (aB: Uint8Array, bB: Uint8Array) => boolean;
|
|
2
|
+
export declare const bufToHex: (a: Uint8Array) => string;
|
|
3
|
+
export declare const hexToBuf: (s: string) => Uint8Array;
|
|
4
|
+
export declare const base64encode: (a: Uint8Array, lineMax?: number) => string;
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
import native from './native.js';
|
|
2
|
+
export const equals = (aB, bB) => {
|
|
3
|
+
const len = aB.byteLength;
|
|
4
|
+
if (len != bB.byteLength) {
|
|
5
|
+
return false;
|
|
6
|
+
}
|
|
7
|
+
let i = 0;
|
|
8
|
+
if (len < 50) {
|
|
9
|
+
while (i < len) {
|
|
10
|
+
if (aB[i] != bB[i]) {
|
|
11
|
+
return false;
|
|
12
|
+
}
|
|
13
|
+
i++;
|
|
14
|
+
}
|
|
15
|
+
return true;
|
|
16
|
+
}
|
|
17
|
+
else {
|
|
18
|
+
while (i < 4) {
|
|
19
|
+
if (aB[i] != bB[i]) {
|
|
20
|
+
return false;
|
|
21
|
+
}
|
|
22
|
+
i++;
|
|
23
|
+
}
|
|
24
|
+
return native.equals(aB, bB);
|
|
25
|
+
}
|
|
26
|
+
};
|
|
27
|
+
const charMap = new TextEncoder().encode("0123456789abcdef");
|
|
28
|
+
const DECODER = new TextDecoder();
|
|
29
|
+
// Uint8Array.fromHex() and Uint8Array.toHex() are not available in V8
|
|
30
|
+
// https://issues.chromium.org/issues/42204568
|
|
31
|
+
export const bufToHex = (a) => {
|
|
32
|
+
const tmp = new Uint8Array(2 * a.byteLength);
|
|
33
|
+
const n = charMap.length;
|
|
34
|
+
let j = 0;
|
|
35
|
+
for (let i = 0; i < a.byteLength; i++) {
|
|
36
|
+
tmp[j++] = charMap[a[i] >>> 4 % n];
|
|
37
|
+
tmp[j++] = charMap[a[i] & 0x0f % n];
|
|
38
|
+
}
|
|
39
|
+
return DECODER.decode(tmp);
|
|
40
|
+
};
|
|
41
|
+
const intMap = {
|
|
42
|
+
'0': 0,
|
|
43
|
+
'1': 0x1,
|
|
44
|
+
'2': 0x2,
|
|
45
|
+
'3': 0x3,
|
|
46
|
+
'4': 0x4,
|
|
47
|
+
'5': 0x5,
|
|
48
|
+
'6': 0x6,
|
|
49
|
+
'7': 0x7,
|
|
50
|
+
'8': 0x8,
|
|
51
|
+
'9': 0x9,
|
|
52
|
+
'a': 0xa,
|
|
53
|
+
'b': 0xb,
|
|
54
|
+
'c': 0xc,
|
|
55
|
+
'd': 0xd,
|
|
56
|
+
'e': 0xe,
|
|
57
|
+
'f': 0xf,
|
|
58
|
+
};
|
|
59
|
+
// Uint8Array.fromHex() and Uint8Array.toHex() are not available in V8
|
|
60
|
+
// https://issues.chromium.org/issues/42204568
|
|
61
|
+
export const hexToBuf = (s) => {
|
|
62
|
+
const len = (s.length >>> 1) << 1;
|
|
63
|
+
const buf = new Uint8Array(len / 2);
|
|
64
|
+
for (let i = 0; i < buf.byteLength; i++) {
|
|
65
|
+
const x = s.charAt(2 * i);
|
|
66
|
+
const y = s.charAt(2 * i + 1);
|
|
67
|
+
buf[i] = (intMap[x] << 4) + intMap[y];
|
|
68
|
+
}
|
|
69
|
+
return buf;
|
|
70
|
+
};
|
|
71
|
+
function base64OutLen(n, lineMax) {
|
|
72
|
+
let olen;
|
|
73
|
+
/* This version would be with padding but we don't pad */
|
|
74
|
+
//olen = n * 4 / 3 + 4; /* 3-byte blocks to 4-byte */
|
|
75
|
+
olen = ((4 * n / 3) + 3) & ~3;
|
|
76
|
+
olen += lineMax > 0 ? olen / lineMax : 0; // line feeds
|
|
77
|
+
return olen;
|
|
78
|
+
}
|
|
79
|
+
export const base64encode = (a, lineMax = 72) => {
|
|
80
|
+
// TODO Could fallback to @saulx/utils if native is not available
|
|
81
|
+
const tmp = new Uint8Array(base64OutLen(a.byteLength, lineMax));
|
|
82
|
+
return DECODER.decode(native.base64encode(tmp, a, lineMax));
|
|
83
|
+
};
|
|
84
|
+
//# sourceMappingURL=utils.js.map
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@based/db",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.21",
|
|
4
4
|
"license": "MIT",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/src/index.js",
|
|
@@ -12,9 +12,9 @@
|
|
|
12
12
|
"clean-selva": "make -C clibs clean",
|
|
13
13
|
"clean": "rimraf {.turbo,dist,node_modules,.zig-cache,.zig-out,tmp} && npm run clean-selva",
|
|
14
14
|
"playground-nodebug": "npm run build && node ./dist/test/shared/playground.js",
|
|
15
|
-
"playground": "npm run build && LOCPATH=../locale/locale-x86_64-gnu/locale lldb
|
|
15
|
+
"playground": "npm run build && LOCPATH=../locale/locale-x86_64-gnu/locale ./scripts/lldb-node ./dist/test/shared/playground.js",
|
|
16
16
|
"playground-fast": "node ./dist/test/shared/playground.js",
|
|
17
|
-
"test": "npm run build && LOCPATH=../locale/locale-x86_64-gnu/locale lldb
|
|
17
|
+
"test": "npm run build && LOCPATH=../locale/locale-x86_64-gnu/locale ./scripts/lldb-node ./scripts/test.js",
|
|
18
18
|
"test-gdb": "npm run build && LOCPATH=../locale/locale-x86_64-gnu/locale gdb -ex run --args node ./scripts/test.js",
|
|
19
19
|
"test-fast": "LOCPATH=../locale/locale-x86_64-gnu/locale node ./scripts/test.js",
|
|
20
20
|
"test-zig": "npm run build-zig -- debug && tsc && npm run test-fast",
|
|
@@ -31,7 +31,7 @@
|
|
|
31
31
|
"basedDbNative.cjs"
|
|
32
32
|
],
|
|
33
33
|
"dependencies": {
|
|
34
|
-
"@based/schema": "5.0.0-alpha.
|
|
34
|
+
"@based/schema": "5.0.0-alpha.5",
|
|
35
35
|
"@saulx/hash": "^3.0.0",
|
|
36
36
|
"@saulx/utils": "^4.3.2",
|
|
37
37
|
"exit-hook": "^4.0.0",
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|