serializable-bptree 2.0.0 → 3.1.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/README.md +186 -10
- package/dist/cjs/index.js +931 -390
- package/dist/esm/index.js +931 -390
- package/dist/typings/BPTreeAsync.d.ts +29 -0
- package/dist/typings/BPTreeSync.d.ts +30 -0
- package/dist/typings/SerializeStrategyAsync.d.ts +21 -0
- package/dist/typings/SerializeStrategySync.d.ts +21 -0
- package/dist/typings/base/BPTree.d.ts +138 -0
- package/dist/typings/{SerializeStrategy.d.ts → base/SerializeStrategy.d.ts} +7 -19
- package/dist/typings/base/ValueComparator.d.ts +56 -0
- package/dist/typings/index.d.ts +7 -3
- package/dist/typings/utils/CacheStorage.d.ts +3 -0
- package/package.json +5 -1
- package/dist/typings/BPTree.d.ts +0 -127
- package/dist/typings/ValueComparator.d.ts +0 -18
- package/dist/typings/utils/BinarySearch.d.ts +0 -9
package/dist/esm/index.js
CHANGED
|
@@ -1,72 +1,55 @@
|
|
|
1
|
-
// src/
|
|
2
|
-
var
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
this.comparator = comparator;
|
|
1
|
+
// src/base/ValueComparator.ts
|
|
2
|
+
var ValueComparator = class {
|
|
3
|
+
isLower(value, than) {
|
|
4
|
+
return this.asc(value, than) < 0;
|
|
6
5
|
}
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
const mid = Math.floor((left + right) / 2);
|
|
10
|
-
const guess = array[mid];
|
|
11
|
-
if (this.comparator.isSame(guess, value)) {
|
|
12
|
-
return mid;
|
|
13
|
-
} else if (this.comparator.isLower(guess, value)) {
|
|
14
|
-
left = mid + 1;
|
|
15
|
-
continue;
|
|
16
|
-
} else {
|
|
17
|
-
right = mid - 1;
|
|
18
|
-
continue;
|
|
19
|
-
}
|
|
20
|
-
}
|
|
21
|
-
return -1;
|
|
6
|
+
isSame(value, than) {
|
|
7
|
+
return this.asc(value, than) === 0;
|
|
22
8
|
}
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
if (i === -1) {
|
|
26
|
-
return -1;
|
|
27
|
-
}
|
|
28
|
-
while (i > 0) {
|
|
29
|
-
if (!this.comparator.isSame(array[i - 1], value)) {
|
|
30
|
-
break;
|
|
31
|
-
}
|
|
32
|
-
i--;
|
|
33
|
-
}
|
|
34
|
-
return i;
|
|
9
|
+
isHigher(value, than) {
|
|
10
|
+
return this.asc(value, than) > 0;
|
|
35
11
|
}
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
}
|
|
41
|
-
const max = array.length - 1;
|
|
42
|
-
while (i < max) {
|
|
43
|
-
if (!this.comparator.isSame(array[i + 1], value)) {
|
|
44
|
-
break;
|
|
45
|
-
}
|
|
46
|
-
i++;
|
|
47
|
-
}
|
|
48
|
-
return i;
|
|
12
|
+
};
|
|
13
|
+
var NumericComparator = class extends ValueComparator {
|
|
14
|
+
asc(a, b) {
|
|
15
|
+
return a - b;
|
|
49
16
|
}
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
17
|
+
match(value) {
|
|
18
|
+
return value.toString();
|
|
19
|
+
}
|
|
20
|
+
};
|
|
21
|
+
var StringComparator = class extends ValueComparator {
|
|
22
|
+
asc(a, b) {
|
|
23
|
+
return a.localeCompare(b);
|
|
24
|
+
}
|
|
25
|
+
match(value) {
|
|
26
|
+
return value;
|
|
27
|
+
}
|
|
28
|
+
};
|
|
29
|
+
|
|
30
|
+
// src/utils/CacheStorage.ts
|
|
31
|
+
var CacheStorage = class extends Map {
|
|
32
|
+
ensure(key, generator) {
|
|
33
|
+
if (!this.has(key)) {
|
|
34
|
+
this.set(key, generator());
|
|
35
|
+
}
|
|
36
|
+
return this.get(key);
|
|
54
37
|
}
|
|
55
38
|
};
|
|
56
39
|
|
|
57
|
-
// src/BPTree.ts
|
|
40
|
+
// src/base/BPTree.ts
|
|
58
41
|
var BPTree = class {
|
|
42
|
+
_regexpCache;
|
|
59
43
|
strategy;
|
|
60
44
|
comparator;
|
|
61
|
-
search;
|
|
62
|
-
order;
|
|
63
45
|
nodes;
|
|
46
|
+
order;
|
|
64
47
|
data;
|
|
65
48
|
root;
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
49
|
+
_nodeCreateBuffer;
|
|
50
|
+
_nodeUpdateBuffer;
|
|
51
|
+
_headBuffer;
|
|
52
|
+
verifierMap = {
|
|
70
53
|
gt: (nv, v) => this.comparator.isHigher(nv, v),
|
|
71
54
|
gte: (nv, v) => this.comparator.isHigher(nv, v) || this.comparator.isSame(nv, v),
|
|
72
55
|
lt: (nv, v) => this.comparator.isLower(nv, v),
|
|
@@ -74,26 +57,25 @@ var BPTree = class {
|
|
|
74
57
|
equal: (nv, v) => this.comparator.isSame(nv, v),
|
|
75
58
|
notEqual: (nv, v) => this.comparator.isSame(nv, v) === false,
|
|
76
59
|
like: (nv, v) => {
|
|
77
|
-
const nodeValue =
|
|
78
|
-
const value =
|
|
79
|
-
const
|
|
80
|
-
|
|
81
|
-
|
|
60
|
+
const nodeValue = this.comparator.match(nv);
|
|
61
|
+
const value = this.comparator.match(v);
|
|
62
|
+
const regexp = this._regexpCache.ensure(value, () => {
|
|
63
|
+
const pattern = value.replace(/%/g, ".*").replace(/_/g, ".");
|
|
64
|
+
return new RegExp(`^${pattern}$`, "i");
|
|
65
|
+
});
|
|
66
|
+
return regexp.test(nodeValue);
|
|
82
67
|
}
|
|
83
68
|
};
|
|
84
|
-
|
|
69
|
+
verifierStartNode = {
|
|
85
70
|
gt: (v) => this.insertableNode(v),
|
|
86
71
|
gte: (v) => this.insertableNode(v),
|
|
87
|
-
// todo
|
|
88
72
|
lt: (v) => this.insertableNode(v),
|
|
89
73
|
lte: (v) => this.insertableNode(v),
|
|
90
|
-
// todo
|
|
91
74
|
equal: (v) => this.insertableNode(v),
|
|
92
75
|
notEqual: (v) => this.leftestNode(),
|
|
93
76
|
like: (v) => this.leftestNode()
|
|
94
|
-
// todo
|
|
95
77
|
};
|
|
96
|
-
|
|
78
|
+
verifierDirection = {
|
|
97
79
|
gt: 1,
|
|
98
80
|
gte: 1,
|
|
99
81
|
lt: -1,
|
|
@@ -102,7 +84,7 @@ var BPTree = class {
|
|
|
102
84
|
notEqual: 1,
|
|
103
85
|
like: 1
|
|
104
86
|
};
|
|
105
|
-
|
|
87
|
+
verifierFullScan = {
|
|
106
88
|
gt: false,
|
|
107
89
|
gte: false,
|
|
108
90
|
lt: false,
|
|
@@ -111,59 +93,7 @@ var BPTree = class {
|
|
|
111
93
|
notEqual: true,
|
|
112
94
|
like: true
|
|
113
95
|
};
|
|
114
|
-
|
|
115
|
-
const id = this.strategy.id();
|
|
116
|
-
if (id === 0) {
|
|
117
|
-
throw new Error(`The node's id should never be 0.`);
|
|
118
|
-
}
|
|
119
|
-
return id;
|
|
120
|
-
}
|
|
121
|
-
_createNode(keys, values, leaf = false, parent = 0, next = 0, prev = 0) {
|
|
122
|
-
const id = this._createNodeId();
|
|
123
|
-
const node = {
|
|
124
|
-
id,
|
|
125
|
-
keys,
|
|
126
|
-
values,
|
|
127
|
-
leaf,
|
|
128
|
-
parent,
|
|
129
|
-
next,
|
|
130
|
-
prev
|
|
131
|
-
};
|
|
132
|
-
this.nodes.set(id, node);
|
|
133
|
-
return node;
|
|
134
|
-
}
|
|
135
|
-
/**
|
|
136
|
-
* @param strategy An instance of a strategy that manages the read/write state of a node.
|
|
137
|
-
* @param comparator An instance of a comparator that compares the size of values.
|
|
138
|
-
*/
|
|
139
|
-
constructor(strategy, comparator) {
|
|
140
|
-
const head = strategy.readHead();
|
|
141
|
-
this._creates = /* @__PURE__ */ new Map();
|
|
142
|
-
this._updates = /* @__PURE__ */ new Map();
|
|
143
|
-
this._updatedHead = null;
|
|
144
|
-
this.nodes = /* @__PURE__ */ new Map();
|
|
145
|
-
this.search = new BinarySearch(comparator);
|
|
146
|
-
this.strategy = strategy;
|
|
147
|
-
this.comparator = comparator;
|
|
148
|
-
if (head === null) {
|
|
149
|
-
this.order = strategy.order;
|
|
150
|
-
this.data = {};
|
|
151
|
-
this.root = this._createNode([], [], true);
|
|
152
|
-
this._setHeadUpdate(this._headState);
|
|
153
|
-
this._setCreates(this.root);
|
|
154
|
-
this._emitHeadUpdates();
|
|
155
|
-
this._emitCreates();
|
|
156
|
-
} else {
|
|
157
|
-
const { root, order, data } = head;
|
|
158
|
-
this.order = order;
|
|
159
|
-
this.data = data ?? {};
|
|
160
|
-
this.root = this.getNode(root);
|
|
161
|
-
}
|
|
162
|
-
if (this.order < 3) {
|
|
163
|
-
throw new Error(`The 'order' parameter must be greater than 2. but got a '${this.order}'.`);
|
|
164
|
-
}
|
|
165
|
-
}
|
|
166
|
-
get _headState() {
|
|
96
|
+
get headState() {
|
|
167
97
|
const root = this.root.id;
|
|
168
98
|
const order = this.order;
|
|
169
99
|
const data = this.data;
|
|
@@ -173,82 +103,14 @@ var BPTree = class {
|
|
|
173
103
|
data
|
|
174
104
|
};
|
|
175
105
|
}
|
|
176
|
-
|
|
177
|
-
this.
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
this.
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
this.
|
|
184
|
-
}
|
|
185
|
-
_emitHeadUpdates() {
|
|
186
|
-
if (this._updatedHead !== null) {
|
|
187
|
-
this.strategy.writeHead(this._updatedHead);
|
|
188
|
-
}
|
|
189
|
-
this._updatedHead = null;
|
|
190
|
-
}
|
|
191
|
-
_emitCreates() {
|
|
192
|
-
for (const node of this._creates.values()) {
|
|
193
|
-
this.strategy.write(node.id, node);
|
|
194
|
-
}
|
|
195
|
-
this._creates.clear();
|
|
196
|
-
}
|
|
197
|
-
_emitUpdates() {
|
|
198
|
-
for (const node of this._updates.values()) {
|
|
199
|
-
this.strategy.write(node.id, node);
|
|
200
|
-
}
|
|
201
|
-
this._updates.clear();
|
|
202
|
-
}
|
|
203
|
-
getNode(id) {
|
|
204
|
-
if (!this.nodes.has(id)) {
|
|
205
|
-
this.nodes.set(id, this.strategy.read(id));
|
|
206
|
-
}
|
|
207
|
-
return this.nodes.get(id);
|
|
208
|
-
}
|
|
209
|
-
leftestNode() {
|
|
210
|
-
let node = this.root;
|
|
211
|
-
while (!node.leaf) {
|
|
212
|
-
const keys = node.keys;
|
|
213
|
-
node = this.getNode(keys[0]);
|
|
214
|
-
}
|
|
215
|
-
return node;
|
|
216
|
-
}
|
|
217
|
-
insertableNode(value) {
|
|
218
|
-
let node = this.root;
|
|
219
|
-
while (!node.leaf) {
|
|
220
|
-
for (let i = 0, len = node.values.length; i < len; i++) {
|
|
221
|
-
const nValue = node.values[i];
|
|
222
|
-
const k = node.keys;
|
|
223
|
-
if (this.comparator.isSame(value, nValue)) {
|
|
224
|
-
node = this.getNode(k[i + 1]);
|
|
225
|
-
break;
|
|
226
|
-
} else if (this.comparator.isLower(value, nValue)) {
|
|
227
|
-
node = this.getNode(k[i]);
|
|
228
|
-
break;
|
|
229
|
-
} else if (i + 1 === node.values.length) {
|
|
230
|
-
node = this.getNode(k[i + 1]);
|
|
231
|
-
break;
|
|
232
|
-
}
|
|
233
|
-
}
|
|
234
|
-
}
|
|
235
|
-
return node;
|
|
236
|
-
}
|
|
237
|
-
/**
|
|
238
|
-
* It returns whether there is a value in the tree.
|
|
239
|
-
* @param key The key value to search for.
|
|
240
|
-
* @param value The value to search for.
|
|
241
|
-
*/
|
|
242
|
-
exists(key, value) {
|
|
243
|
-
const node = this.insertableNode(value);
|
|
244
|
-
for (let i = 0, len = node.values.length; i < len; i++) {
|
|
245
|
-
const nValue = node.values[i];
|
|
246
|
-
if (this.comparator.isSame(value, nValue)) {
|
|
247
|
-
const keys = node.keys[i];
|
|
248
|
-
return keys.includes(key);
|
|
249
|
-
}
|
|
250
|
-
}
|
|
251
|
-
return false;
|
|
106
|
+
constructor(strategy, comparator) {
|
|
107
|
+
this._regexpCache = new CacheStorage();
|
|
108
|
+
this._headBuffer = null;
|
|
109
|
+
this._nodeCreateBuffer = /* @__PURE__ */ new Map();
|
|
110
|
+
this._nodeUpdateBuffer = /* @__PURE__ */ new Map();
|
|
111
|
+
this.nodes = /* @__PURE__ */ new Map();
|
|
112
|
+
this.strategy = strategy;
|
|
113
|
+
this.comparator = comparator;
|
|
252
114
|
}
|
|
253
115
|
_insertAtLeaf(node, key, value) {
|
|
254
116
|
if (node.values.length) {
|
|
@@ -257,74 +119,49 @@ var BPTree = class {
|
|
|
257
119
|
if (this.comparator.isSame(value, nValue)) {
|
|
258
120
|
const keys = node.keys[i];
|
|
259
121
|
keys.push(key);
|
|
260
|
-
this.
|
|
122
|
+
this.bufferForNodeUpdate(node);
|
|
261
123
|
break;
|
|
262
124
|
} else if (this.comparator.isLower(value, nValue)) {
|
|
263
125
|
node.values.splice(i, 0, value);
|
|
264
126
|
node.keys.splice(i, 0, [key]);
|
|
265
|
-
this.
|
|
127
|
+
this.bufferForNodeUpdate(node);
|
|
266
128
|
break;
|
|
267
129
|
} else if (i + 1 === node.values.length) {
|
|
268
130
|
node.values.push(value);
|
|
269
131
|
node.keys.push([key]);
|
|
270
|
-
this.
|
|
132
|
+
this.bufferForNodeUpdate(node);
|
|
271
133
|
break;
|
|
272
134
|
}
|
|
273
135
|
}
|
|
274
136
|
} else {
|
|
275
137
|
node.values = [value];
|
|
276
138
|
node.keys = [[key]];
|
|
277
|
-
this.
|
|
139
|
+
this.bufferForNodeUpdate(node);
|
|
278
140
|
}
|
|
279
141
|
}
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
parentPointer.values = parentNode.values.slice(mid + 1);
|
|
304
|
-
parentPointer.keys = parentNode.keys.slice(mid + 1);
|
|
305
|
-
const midValue = parentNode.values[mid];
|
|
306
|
-
if (mid === 0) {
|
|
307
|
-
parentNode.values = parentNode.values.slice(0, mid + 1);
|
|
308
|
-
} else {
|
|
309
|
-
parentNode.values = parentNode.values.slice(0, mid);
|
|
310
|
-
}
|
|
311
|
-
parentNode.keys = parentNode.keys.slice(0, mid + 1);
|
|
312
|
-
for (const k of parentNode.keys) {
|
|
313
|
-
const node2 = this.getNode(k);
|
|
314
|
-
node2.parent = parentNode.id;
|
|
315
|
-
this._setUpdates(node2);
|
|
316
|
-
}
|
|
317
|
-
for (const k of parentPointer.keys) {
|
|
318
|
-
const node2 = this.getNode(k);
|
|
319
|
-
node2.parent = parentPointer.id;
|
|
320
|
-
this._setUpdates(node2);
|
|
321
|
-
}
|
|
322
|
-
this._insertInParent(parentNode, midValue, parentPointer);
|
|
323
|
-
this._setCreates(parentPointer);
|
|
324
|
-
this._setUpdates(parentNode);
|
|
325
|
-
}
|
|
326
|
-
}
|
|
327
|
-
}
|
|
142
|
+
bufferForHeadUpdate(head) {
|
|
143
|
+
this._headBuffer = head;
|
|
144
|
+
}
|
|
145
|
+
bufferForNodeCreate(node) {
|
|
146
|
+
this._nodeCreateBuffer.set(node.id, node);
|
|
147
|
+
}
|
|
148
|
+
bufferForNodeUpdate(node) {
|
|
149
|
+
this._nodeUpdateBuffer.set(node.id, node);
|
|
150
|
+
}
|
|
151
|
+
/**
|
|
152
|
+
* Returns the user-defined data stored in the head of the tree.
|
|
153
|
+
* This value can be set using the `setHeadData` method. If no data has been previously inserted, the default value is returned, and the default value is `{}`.
|
|
154
|
+
* @returns User-defined data stored in the head of the tree.
|
|
155
|
+
*/
|
|
156
|
+
getHeadData() {
|
|
157
|
+
return this.data;
|
|
158
|
+
}
|
|
159
|
+
};
|
|
160
|
+
|
|
161
|
+
// src/BPTreeSync.ts
|
|
162
|
+
var BPTreeSync = class extends BPTree {
|
|
163
|
+
constructor(strategy, comparator) {
|
|
164
|
+
super(strategy, comparator);
|
|
328
165
|
}
|
|
329
166
|
_getPairsRightToLeft(value, startNode, fullSearch, comparator) {
|
|
330
167
|
const pairs = [];
|
|
@@ -392,63 +229,413 @@ var BPTree = class {
|
|
|
392
229
|
throw new Error(`Direction must be -1 or 1. but got a ${direction}`);
|
|
393
230
|
}
|
|
394
231
|
}
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
* @param condition You can use the `gt`, `lt`, `gte`, `lte`, `equal`, `notEqual`, `like` condition statements.
|
|
400
|
-
*/
|
|
401
|
-
keys(condition) {
|
|
402
|
-
let result = null;
|
|
403
|
-
for (const k in condition) {
|
|
404
|
-
const key = k;
|
|
405
|
-
const value = condition[key];
|
|
406
|
-
const startNode = this._verifierStartNode[key](value);
|
|
407
|
-
const direction = this._verifierDirection[key];
|
|
408
|
-
const fullSearch = this._verifierFullSearch[key];
|
|
409
|
-
const comparator = this._verifierMap[key];
|
|
410
|
-
const pairs = this.getPairs(value, startNode, fullSearch, comparator, direction);
|
|
411
|
-
if (result === null) {
|
|
412
|
-
result = pairs.map((pair) => pair.key);
|
|
413
|
-
} else {
|
|
414
|
-
result = result.filter((key2) => pairs.find((p) => p.key === key2));
|
|
415
|
-
}
|
|
232
|
+
_createNodeId() {
|
|
233
|
+
const id = this.strategy.id();
|
|
234
|
+
if (id === 0) {
|
|
235
|
+
throw new Error(`The node's id should never be 0.`);
|
|
416
236
|
}
|
|
417
|
-
return
|
|
237
|
+
return id;
|
|
418
238
|
}
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
239
|
+
_createNode(keys, values, leaf = false, parent = 0, next = 0, prev = 0) {
|
|
240
|
+
const id = this._createNodeId();
|
|
241
|
+
const node = {
|
|
242
|
+
id,
|
|
243
|
+
keys,
|
|
244
|
+
values,
|
|
245
|
+
leaf,
|
|
246
|
+
parent,
|
|
247
|
+
next,
|
|
248
|
+
prev
|
|
249
|
+
};
|
|
250
|
+
this.nodes.set(id, node);
|
|
251
|
+
return node;
|
|
252
|
+
}
|
|
253
|
+
_deleteEntry(node, key, value) {
|
|
254
|
+
if (!node.leaf) {
|
|
255
|
+
for (let i = 0, len = node.keys.length; i < len; i++) {
|
|
256
|
+
const nKey = node.keys[i];
|
|
257
|
+
if (nKey === key) {
|
|
258
|
+
node.keys.splice(i, 1);
|
|
259
|
+
this.bufferForNodeUpdate(node);
|
|
260
|
+
break;
|
|
261
|
+
}
|
|
262
|
+
}
|
|
263
|
+
for (let i = 0, len = node.values.length; i < len; i++) {
|
|
264
|
+
const nValue = node.values[i];
|
|
265
|
+
if (this.comparator.isSame(value, nValue)) {
|
|
266
|
+
node.values.splice(i, 1);
|
|
267
|
+
this.bufferForNodeUpdate(node);
|
|
268
|
+
break;
|
|
269
|
+
}
|
|
438
270
|
}
|
|
439
271
|
}
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
272
|
+
if (this.root === node && node.keys.length === 1) {
|
|
273
|
+
const keys = node.keys;
|
|
274
|
+
this.root = this.getNode(keys[0]);
|
|
275
|
+
this.root.parent = 0;
|
|
276
|
+
this.bufferForHeadUpdate(this.headState);
|
|
277
|
+
this.bufferForNodeUpdate(this.root);
|
|
278
|
+
return;
|
|
279
|
+
} else if (this.root === node) {
|
|
280
|
+
return;
|
|
281
|
+
} else if (node.keys.length < Math.ceil(this.order / 2) && !node.leaf || node.values.length < Math.ceil((this.order - 1) / 2) && node.leaf) {
|
|
282
|
+
let isPredecessor = false;
|
|
283
|
+
let parentNode = this.getNode(node.parent);
|
|
284
|
+
let prevNode = null;
|
|
285
|
+
let nextNode = null;
|
|
286
|
+
let prevValue = null;
|
|
287
|
+
let postValue = null;
|
|
288
|
+
for (let i = 0, len = parentNode.keys.length; i < len; i++) {
|
|
289
|
+
const nKey = parentNode.keys[i];
|
|
290
|
+
if (nKey === node.id) {
|
|
291
|
+
if (i > 0) {
|
|
292
|
+
prevNode = this.getNode(parentNode.keys[i - 1]);
|
|
293
|
+
prevValue = parentNode.values[i - 1];
|
|
294
|
+
}
|
|
295
|
+
if (i < parentNode.keys.length - 1) {
|
|
296
|
+
nextNode = this.getNode(parentNode.keys[i + 1]);
|
|
297
|
+
postValue = parentNode.values[i];
|
|
298
|
+
}
|
|
299
|
+
}
|
|
300
|
+
}
|
|
301
|
+
let pointer;
|
|
302
|
+
let guess;
|
|
303
|
+
if (prevNode === null) {
|
|
304
|
+
pointer = nextNode;
|
|
305
|
+
guess = postValue;
|
|
306
|
+
} else if (nextNode === null) {
|
|
307
|
+
isPredecessor = true;
|
|
308
|
+
pointer = prevNode;
|
|
309
|
+
guess = prevValue;
|
|
310
|
+
} else {
|
|
311
|
+
if (node.values.length + nextNode.values.length < this.order) {
|
|
312
|
+
pointer = nextNode;
|
|
313
|
+
guess = postValue;
|
|
314
|
+
} else {
|
|
315
|
+
isPredecessor = true;
|
|
316
|
+
pointer = prevNode;
|
|
317
|
+
guess = prevValue;
|
|
318
|
+
}
|
|
319
|
+
}
|
|
320
|
+
if (node.values.length + pointer.values.length < this.order) {
|
|
321
|
+
if (!isPredecessor) {
|
|
322
|
+
const pTemp = pointer;
|
|
323
|
+
pointer = node;
|
|
324
|
+
node = pTemp;
|
|
325
|
+
}
|
|
326
|
+
pointer.keys.push(...node.keys);
|
|
327
|
+
if (!node.leaf) {
|
|
328
|
+
pointer.values.push(guess);
|
|
329
|
+
} else {
|
|
330
|
+
pointer.next = node.next;
|
|
331
|
+
pointer.prev = node.id;
|
|
332
|
+
if (pointer.next) {
|
|
333
|
+
const n = this.getNode(node.next);
|
|
334
|
+
n.prev = pointer.id;
|
|
335
|
+
this.bufferForNodeUpdate(n);
|
|
336
|
+
}
|
|
337
|
+
if (pointer.prev) {
|
|
338
|
+
const n = this.getNode(node.id);
|
|
339
|
+
n.next = pointer.id;
|
|
340
|
+
this.bufferForNodeUpdate(n);
|
|
341
|
+
}
|
|
342
|
+
if (isPredecessor) {
|
|
343
|
+
pointer.prev = 0;
|
|
344
|
+
}
|
|
345
|
+
}
|
|
346
|
+
pointer.values.push(...node.values);
|
|
347
|
+
if (!pointer.leaf) {
|
|
348
|
+
const keys = pointer.keys;
|
|
349
|
+
for (const key2 of keys) {
|
|
350
|
+
const node2 = this.getNode(key2);
|
|
351
|
+
node2.parent = pointer.id;
|
|
352
|
+
this.bufferForNodeUpdate(node2);
|
|
353
|
+
}
|
|
354
|
+
}
|
|
355
|
+
this._deleteEntry(this.getNode(node.parent), node.id, guess);
|
|
356
|
+
this.bufferForNodeUpdate(pointer);
|
|
357
|
+
} else {
|
|
358
|
+
if (isPredecessor) {
|
|
359
|
+
let pointerPm;
|
|
360
|
+
let pointerKm;
|
|
361
|
+
if (!node.leaf) {
|
|
362
|
+
pointerPm = pointer.keys.splice(-1)[0];
|
|
363
|
+
pointerKm = pointer.values.splice(-1)[0];
|
|
364
|
+
node.keys = [pointerPm, ...node.keys];
|
|
365
|
+
node.values = [guess, ...node.values];
|
|
366
|
+
parentNode = this.getNode(node.parent);
|
|
367
|
+
for (let i = 0, len = parentNode.values.length; i < len; i++) {
|
|
368
|
+
const nValue = parentNode.values[i];
|
|
369
|
+
if (this.comparator.isSame(guess, nValue)) {
|
|
370
|
+
parentNode.values[i] = pointerKm;
|
|
371
|
+
this.bufferForNodeUpdate(parentNode);
|
|
372
|
+
break;
|
|
373
|
+
}
|
|
374
|
+
}
|
|
375
|
+
} else {
|
|
376
|
+
pointerPm = pointer.keys.splice(-1)[0];
|
|
377
|
+
pointerKm = pointer.values.splice(-1)[0];
|
|
378
|
+
node.keys = [pointerPm, ...node.keys];
|
|
379
|
+
node.values = [pointerKm, ...node.values];
|
|
380
|
+
parentNode = this.getNode(node.parent);
|
|
381
|
+
for (let i = 0, len = parentNode.values.length; i < len; i++) {
|
|
382
|
+
const nValue = parentNode.values[i];
|
|
383
|
+
if (this.comparator.isSame(guess, nValue)) {
|
|
384
|
+
parentNode.values[i] = pointerKm;
|
|
385
|
+
this.bufferForNodeUpdate(parentNode);
|
|
386
|
+
break;
|
|
387
|
+
}
|
|
388
|
+
}
|
|
389
|
+
}
|
|
390
|
+
this.bufferForNodeUpdate(node);
|
|
391
|
+
this.bufferForNodeUpdate(pointer);
|
|
392
|
+
} else {
|
|
393
|
+
let pointerP0;
|
|
394
|
+
let pointerK0;
|
|
395
|
+
if (!node.leaf) {
|
|
396
|
+
pointerP0 = pointer.keys.splice(0, 1)[0];
|
|
397
|
+
pointerK0 = pointer.values.splice(0, 1)[0];
|
|
398
|
+
node.keys = [...node.keys, pointerP0];
|
|
399
|
+
node.values = [...node.values, guess];
|
|
400
|
+
parentNode = this.getNode(node.parent);
|
|
401
|
+
for (let i = 0, len = parentNode.values.length; i < len; i++) {
|
|
402
|
+
const nValue = parentNode.values[i];
|
|
403
|
+
if (this.comparator.isSame(guess, nValue)) {
|
|
404
|
+
parentNode.values[i] = pointerK0;
|
|
405
|
+
this.bufferForNodeUpdate(parentNode);
|
|
406
|
+
break;
|
|
407
|
+
}
|
|
408
|
+
}
|
|
409
|
+
} else {
|
|
410
|
+
pointerP0 = pointer.keys.splice(0, 1)[0];
|
|
411
|
+
pointerK0 = pointer.values.splice(0, 1)[0];
|
|
412
|
+
node.keys = [...node.keys, pointerP0];
|
|
413
|
+
node.values = [...node.values, pointerK0];
|
|
414
|
+
parentNode = this.getNode(node.parent);
|
|
415
|
+
for (let i = 0, len = parentNode.values.length; i < len; i++) {
|
|
416
|
+
const nValue = parentNode.values[i];
|
|
417
|
+
if (this.comparator.isSame(guess, nValue)) {
|
|
418
|
+
parentNode.values[i] = pointer.values[0];
|
|
419
|
+
this.bufferForNodeUpdate(parentNode);
|
|
420
|
+
break;
|
|
421
|
+
}
|
|
422
|
+
}
|
|
423
|
+
}
|
|
424
|
+
this.bufferForNodeUpdate(node);
|
|
425
|
+
this.bufferForNodeUpdate(pointer);
|
|
426
|
+
}
|
|
427
|
+
if (!pointer.leaf) {
|
|
428
|
+
for (const key2 of pointer.keys) {
|
|
429
|
+
const n = this.getNode(key2);
|
|
430
|
+
n.parent = pointer.id;
|
|
431
|
+
this.bufferForNodeUpdate(n);
|
|
432
|
+
}
|
|
433
|
+
}
|
|
434
|
+
if (!node.leaf) {
|
|
435
|
+
for (const key2 of node.keys) {
|
|
436
|
+
const n = this.getNode(key2);
|
|
437
|
+
n.parent = node.id;
|
|
438
|
+
this.bufferForNodeUpdate(n);
|
|
439
|
+
}
|
|
440
|
+
}
|
|
441
|
+
if (!parentNode.leaf) {
|
|
442
|
+
for (const key2 of parentNode.keys) {
|
|
443
|
+
const n = this.getNode(key2);
|
|
444
|
+
n.parent = parentNode.id;
|
|
445
|
+
this.bufferForNodeUpdate(n);
|
|
446
|
+
}
|
|
447
|
+
}
|
|
448
|
+
}
|
|
449
|
+
}
|
|
450
|
+
}
|
|
451
|
+
_insertAtLeaf(node, key, value) {
|
|
452
|
+
if (node.values.length) {
|
|
453
|
+
for (let i = 0, len = node.values.length; i < len; i++) {
|
|
454
|
+
const nValue = node.values[i];
|
|
455
|
+
if (this.comparator.isSame(value, nValue)) {
|
|
456
|
+
const keys = node.keys[i];
|
|
457
|
+
keys.push(key);
|
|
458
|
+
this.bufferForNodeUpdate(node);
|
|
459
|
+
break;
|
|
460
|
+
} else if (this.comparator.isLower(value, nValue)) {
|
|
461
|
+
node.values.splice(i, 0, value);
|
|
462
|
+
node.keys.splice(i, 0, [key]);
|
|
463
|
+
this.bufferForNodeUpdate(node);
|
|
464
|
+
break;
|
|
465
|
+
} else if (i + 1 === node.values.length) {
|
|
466
|
+
node.values.push(value);
|
|
467
|
+
node.keys.push([key]);
|
|
468
|
+
this.bufferForNodeUpdate(node);
|
|
469
|
+
break;
|
|
470
|
+
}
|
|
471
|
+
}
|
|
472
|
+
} else {
|
|
473
|
+
node.values = [value];
|
|
474
|
+
node.keys = [[key]];
|
|
475
|
+
this.bufferForNodeUpdate(node);
|
|
476
|
+
}
|
|
477
|
+
}
|
|
478
|
+
_insertInParent(node, value, pointer) {
|
|
479
|
+
if (this.root === node) {
|
|
480
|
+
const root = this._createNode([node.id, pointer.id], [value]);
|
|
481
|
+
this.root = root;
|
|
482
|
+
node.parent = root.id;
|
|
483
|
+
pointer.parent = root.id;
|
|
484
|
+
this.bufferForHeadUpdate(this.headState);
|
|
485
|
+
this.bufferForNodeCreate(root);
|
|
486
|
+
this.bufferForNodeUpdate(node);
|
|
487
|
+
this.bufferForNodeUpdate(pointer);
|
|
488
|
+
return;
|
|
489
|
+
}
|
|
490
|
+
const parentNode = this.getNode(node.parent);
|
|
491
|
+
for (let i = 0, len = parentNode.keys.length; i < len; i++) {
|
|
492
|
+
const nKeys = parentNode.keys[i];
|
|
493
|
+
if (nKeys === node.id) {
|
|
494
|
+
parentNode.values.splice(i, 0, value);
|
|
495
|
+
parentNode.keys.splice(i + 1, 0, pointer.id);
|
|
496
|
+
this.bufferForNodeUpdate(parentNode);
|
|
497
|
+
if (parentNode.keys.length > this.order) {
|
|
498
|
+
const parentPointer = this._createNode([], []);
|
|
499
|
+
parentPointer.parent = parentNode.parent;
|
|
500
|
+
const mid = Math.ceil(this.order / 2) - 1;
|
|
501
|
+
parentPointer.values = parentNode.values.slice(mid + 1);
|
|
502
|
+
parentPointer.keys = parentNode.keys.slice(mid + 1);
|
|
503
|
+
const midValue = parentNode.values[mid];
|
|
504
|
+
if (mid === 0) {
|
|
505
|
+
parentNode.values = parentNode.values.slice(0, mid + 1);
|
|
506
|
+
} else {
|
|
507
|
+
parentNode.values = parentNode.values.slice(0, mid);
|
|
508
|
+
}
|
|
509
|
+
parentNode.keys = parentNode.keys.slice(0, mid + 1);
|
|
510
|
+
for (const k of parentNode.keys) {
|
|
511
|
+
const node2 = this.getNode(k);
|
|
512
|
+
node2.parent = parentNode.id;
|
|
513
|
+
this.bufferForNodeUpdate(node2);
|
|
514
|
+
}
|
|
515
|
+
for (const k of parentPointer.keys) {
|
|
516
|
+
const node2 = this.getNode(k);
|
|
517
|
+
node2.parent = parentPointer.id;
|
|
518
|
+
this.bufferForNodeUpdate(node2);
|
|
519
|
+
}
|
|
520
|
+
this._insertInParent(parentNode, midValue, parentPointer);
|
|
521
|
+
this.bufferForNodeCreate(parentPointer);
|
|
522
|
+
this.bufferForNodeUpdate(parentNode);
|
|
523
|
+
}
|
|
524
|
+
}
|
|
525
|
+
}
|
|
526
|
+
}
|
|
527
|
+
init() {
|
|
528
|
+
const head = this.strategy.readHead();
|
|
529
|
+
if (head === null) {
|
|
530
|
+
this.order = this.strategy.order;
|
|
531
|
+
this.data = {};
|
|
532
|
+
this.root = this._createNode([], [], true);
|
|
533
|
+
this.bufferForHeadUpdate(this.headState);
|
|
534
|
+
this.bufferForNodeCreate(this.root);
|
|
535
|
+
this.commitHeadBuffer();
|
|
536
|
+
this.commitNodeCreateBuffer();
|
|
537
|
+
} else {
|
|
538
|
+
const { root, order, data } = head;
|
|
539
|
+
this.order = order;
|
|
540
|
+
this.data = data ?? {};
|
|
541
|
+
this.root = this.getNode(root);
|
|
542
|
+
}
|
|
543
|
+
if (this.order < 3) {
|
|
544
|
+
throw new Error(`The 'order' parameter must be greater than 2. but got a '${this.order}'.`);
|
|
545
|
+
}
|
|
546
|
+
}
|
|
547
|
+
getNode(id) {
|
|
548
|
+
if (!this.nodes.has(id)) {
|
|
549
|
+
this.nodes.set(id, this.strategy.read(id));
|
|
550
|
+
}
|
|
551
|
+
return this.nodes.get(id);
|
|
552
|
+
}
|
|
553
|
+
insertableNode(value) {
|
|
554
|
+
let node = this.root;
|
|
555
|
+
while (!node.leaf) {
|
|
556
|
+
for (let i = 0, len = node.values.length; i < len; i++) {
|
|
557
|
+
const nValue = node.values[i];
|
|
558
|
+
const k = node.keys;
|
|
559
|
+
if (this.comparator.isSame(value, nValue)) {
|
|
560
|
+
node = this.getNode(k[i + 1]);
|
|
561
|
+
break;
|
|
562
|
+
} else if (this.comparator.isLower(value, nValue)) {
|
|
563
|
+
node = this.getNode(k[i]);
|
|
564
|
+
break;
|
|
565
|
+
} else if (i + 1 === node.values.length) {
|
|
566
|
+
node = this.getNode(k[i + 1]);
|
|
567
|
+
break;
|
|
568
|
+
}
|
|
569
|
+
}
|
|
570
|
+
}
|
|
571
|
+
return node;
|
|
572
|
+
}
|
|
573
|
+
leftestNode() {
|
|
574
|
+
let node = this.root;
|
|
575
|
+
while (!node.leaf) {
|
|
576
|
+
const keys = node.keys;
|
|
577
|
+
node = this.getNode(keys[0]);
|
|
578
|
+
}
|
|
579
|
+
return node;
|
|
580
|
+
}
|
|
581
|
+
commitHeadBuffer() {
|
|
582
|
+
if (this._headBuffer !== null) {
|
|
583
|
+
this.strategy.writeHead(this._headBuffer);
|
|
584
|
+
}
|
|
585
|
+
this.bufferForHeadUpdate(null);
|
|
586
|
+
}
|
|
587
|
+
commitNodeCreateBuffer() {
|
|
588
|
+
for (const node of this._nodeCreateBuffer.values()) {
|
|
589
|
+
this.strategy.write(node.id, node);
|
|
590
|
+
}
|
|
591
|
+
this._nodeCreateBuffer.clear();
|
|
592
|
+
}
|
|
593
|
+
commitNodeUpdateBuffer() {
|
|
594
|
+
for (const node of this._nodeUpdateBuffer.values()) {
|
|
595
|
+
this.strategy.write(node.id, node);
|
|
596
|
+
}
|
|
597
|
+
this._nodeUpdateBuffer.clear();
|
|
598
|
+
}
|
|
599
|
+
keys(condition) {
|
|
600
|
+
let result = null;
|
|
601
|
+
for (const k in condition) {
|
|
602
|
+
const key = k;
|
|
603
|
+
const value = condition[key];
|
|
604
|
+
const startNode = this.verifierStartNode[key](value);
|
|
605
|
+
const direction = this.verifierDirection[key];
|
|
606
|
+
const fullScan = this.verifierFullScan[key];
|
|
607
|
+
const comparator = this.verifierMap[key];
|
|
608
|
+
const pairs = this.getPairs(value, startNode, fullScan, comparator, direction);
|
|
609
|
+
if (result === null) {
|
|
610
|
+
result = pairs.map((pair) => pair.key);
|
|
611
|
+
} else {
|
|
612
|
+
result = result.filter((key2) => pairs.find((p) => p.key === key2));
|
|
613
|
+
}
|
|
614
|
+
}
|
|
615
|
+
return new Set(result ?? []);
|
|
616
|
+
}
|
|
617
|
+
where(condition) {
|
|
618
|
+
let result = null;
|
|
619
|
+
for (const k in condition) {
|
|
620
|
+
const key = k;
|
|
621
|
+
const value = condition[key];
|
|
622
|
+
const startNode = this.verifierStartNode[key](value);
|
|
623
|
+
const direction = this.verifierDirection[key];
|
|
624
|
+
const fullScan = this.verifierFullScan[key];
|
|
625
|
+
const comparator = this.verifierMap[key];
|
|
626
|
+
const pairs = this.getPairs(value, startNode, fullScan, comparator, direction);
|
|
627
|
+
if (result === null) {
|
|
628
|
+
result = pairs;
|
|
629
|
+
} else {
|
|
630
|
+
result = result.filter((pair) => pairs.find((p) => p.key === pair.key));
|
|
631
|
+
}
|
|
632
|
+
}
|
|
633
|
+
return result ?? [];
|
|
634
|
+
}
|
|
635
|
+
insert(key, value) {
|
|
636
|
+
const before = this.insertableNode(value);
|
|
637
|
+
this._insertAtLeaf(before, key, value);
|
|
638
|
+
if (before.values.length === this.order) {
|
|
452
639
|
const after = this._createNode(
|
|
453
640
|
[],
|
|
454
641
|
[],
|
|
@@ -467,21 +654,16 @@ var BPTree = class {
|
|
|
467
654
|
if (beforeNext) {
|
|
468
655
|
const node = this.getNode(beforeNext);
|
|
469
656
|
node.prev = after.id;
|
|
470
|
-
this.
|
|
657
|
+
this.bufferForNodeUpdate(node);
|
|
471
658
|
}
|
|
472
659
|
this._insertInParent(before, after.values[0], after);
|
|
473
|
-
this.
|
|
474
|
-
this.
|
|
660
|
+
this.bufferForNodeCreate(after);
|
|
661
|
+
this.bufferForNodeUpdate(before);
|
|
475
662
|
}
|
|
476
|
-
this.
|
|
477
|
-
this.
|
|
478
|
-
this.
|
|
663
|
+
this.commitHeadBuffer();
|
|
664
|
+
this.commitNodeCreateBuffer();
|
|
665
|
+
this.commitNodeUpdateBuffer();
|
|
479
666
|
}
|
|
480
|
-
/**
|
|
481
|
-
* Deletes the pair that matches the key and value.
|
|
482
|
-
* @param key The key of the pair.
|
|
483
|
-
* @param value The value of the pair.
|
|
484
|
-
*/
|
|
485
667
|
delete(key, value) {
|
|
486
668
|
const node = this.insertableNode(value);
|
|
487
669
|
let i = node.values.length;
|
|
@@ -492,32 +674,151 @@ var BPTree = class {
|
|
|
492
674
|
if (keys.includes(key)) {
|
|
493
675
|
if (keys.length > 1) {
|
|
494
676
|
keys.splice(keys.indexOf(key), 1);
|
|
495
|
-
this.
|
|
677
|
+
this.bufferForNodeUpdate(node);
|
|
496
678
|
} else if (node === this.root) {
|
|
497
679
|
node.values.splice(i, 1);
|
|
498
680
|
node.keys.splice(i, 1);
|
|
499
|
-
this.
|
|
681
|
+
this.bufferForNodeUpdate(node);
|
|
500
682
|
} else {
|
|
501
683
|
keys.splice(keys.indexOf(key), 1);
|
|
502
684
|
node.keys.splice(i, 1);
|
|
503
685
|
node.values.splice(node.values.indexOf(value), 1);
|
|
504
686
|
this._deleteEntry(node, key, value);
|
|
505
|
-
this.
|
|
687
|
+
this.bufferForNodeUpdate(node);
|
|
688
|
+
}
|
|
689
|
+
}
|
|
690
|
+
}
|
|
691
|
+
}
|
|
692
|
+
this.commitHeadBuffer();
|
|
693
|
+
this.commitNodeCreateBuffer();
|
|
694
|
+
this.commitNodeUpdateBuffer();
|
|
695
|
+
}
|
|
696
|
+
exists(key, value) {
|
|
697
|
+
const node = this.insertableNode(value);
|
|
698
|
+
for (let i = 0, len = node.values.length; i < len; i++) {
|
|
699
|
+
const nValue = node.values[i];
|
|
700
|
+
if (this.comparator.isSame(value, nValue)) {
|
|
701
|
+
const keys = node.keys[i];
|
|
702
|
+
return keys.includes(key);
|
|
703
|
+
}
|
|
704
|
+
}
|
|
705
|
+
return false;
|
|
706
|
+
}
|
|
707
|
+
setHeadData(data) {
|
|
708
|
+
this.data = data;
|
|
709
|
+
this.bufferForHeadUpdate(this.headState);
|
|
710
|
+
this.commitHeadBuffer();
|
|
711
|
+
}
|
|
712
|
+
forceUpdate() {
|
|
713
|
+
const keys = [...this.nodes.keys()];
|
|
714
|
+
this.nodes.clear();
|
|
715
|
+
this.init();
|
|
716
|
+
for (const key of keys) {
|
|
717
|
+
this.getNode(key);
|
|
718
|
+
}
|
|
719
|
+
return keys.length;
|
|
720
|
+
}
|
|
721
|
+
};
|
|
722
|
+
|
|
723
|
+
// src/BPTreeAsync.ts
|
|
724
|
+
var BPTreeAsync = class extends BPTree {
|
|
725
|
+
constructor(strategy, comparator) {
|
|
726
|
+
super(strategy, comparator);
|
|
727
|
+
}
|
|
728
|
+
async _getPairsRightToLeft(value, startNode, fullSearch, comparator) {
|
|
729
|
+
const pairs = [];
|
|
730
|
+
let node = startNode;
|
|
731
|
+
let done = false;
|
|
732
|
+
let found = false;
|
|
733
|
+
while (!done) {
|
|
734
|
+
let i = node.values.length;
|
|
735
|
+
while (i--) {
|
|
736
|
+
const nValue = node.values[i];
|
|
737
|
+
const keys = node.keys[i];
|
|
738
|
+
if (comparator(nValue, value)) {
|
|
739
|
+
found = true;
|
|
740
|
+
let j = keys.length;
|
|
741
|
+
while (j--) {
|
|
742
|
+
pairs.push({ key: keys[j], value: nValue });
|
|
743
|
+
}
|
|
744
|
+
} else if (found && !fullSearch) {
|
|
745
|
+
done = true;
|
|
746
|
+
break;
|
|
747
|
+
}
|
|
748
|
+
}
|
|
749
|
+
if (!node.prev) {
|
|
750
|
+
done = true;
|
|
751
|
+
break;
|
|
752
|
+
}
|
|
753
|
+
node = await this.getNode(node.prev);
|
|
754
|
+
}
|
|
755
|
+
return pairs.reverse();
|
|
756
|
+
}
|
|
757
|
+
async _getPairsLeftToRight(value, startNode, fullSearch, comparator) {
|
|
758
|
+
const pairs = [];
|
|
759
|
+
let node = startNode;
|
|
760
|
+
let done = false;
|
|
761
|
+
let found = false;
|
|
762
|
+
while (!done) {
|
|
763
|
+
for (let i = 0, len = node.values.length; i < len; i++) {
|
|
764
|
+
const nValue = node.values[i];
|
|
765
|
+
const keys = node.keys[i];
|
|
766
|
+
if (comparator(nValue, value)) {
|
|
767
|
+
found = true;
|
|
768
|
+
for (const key of keys) {
|
|
769
|
+
pairs.push({ key, value: nValue });
|
|
506
770
|
}
|
|
771
|
+
} else if (found && !fullSearch) {
|
|
772
|
+
done = true;
|
|
773
|
+
break;
|
|
507
774
|
}
|
|
508
775
|
}
|
|
776
|
+
if (!node.next) {
|
|
777
|
+
done = true;
|
|
778
|
+
break;
|
|
779
|
+
}
|
|
780
|
+
node = await this.getNode(node.next);
|
|
509
781
|
}
|
|
510
|
-
|
|
511
|
-
this._emitCreates();
|
|
512
|
-
this._emitUpdates();
|
|
782
|
+
return pairs;
|
|
513
783
|
}
|
|
514
|
-
|
|
784
|
+
async getPairs(value, startNode, fullSearch, comparator, direction) {
|
|
785
|
+
switch (direction) {
|
|
786
|
+
case -1:
|
|
787
|
+
return await this._getPairsRightToLeft(value, startNode, fullSearch, comparator);
|
|
788
|
+
case 1:
|
|
789
|
+
return await this._getPairsLeftToRight(value, startNode, fullSearch, comparator);
|
|
790
|
+
default:
|
|
791
|
+
throw new Error(`Direction must be -1 or 1. but got a ${direction}`);
|
|
792
|
+
}
|
|
793
|
+
}
|
|
794
|
+
async _createNodeId() {
|
|
795
|
+
const id = await this.strategy.id();
|
|
796
|
+
if (id === 0) {
|
|
797
|
+
throw new Error(`The node's id should never be 0.`);
|
|
798
|
+
}
|
|
799
|
+
return id;
|
|
800
|
+
}
|
|
801
|
+
async _createNode(keys, values, leaf = false, parent = 0, next = 0, prev = 0) {
|
|
802
|
+
const id = await this._createNodeId();
|
|
803
|
+
const node = {
|
|
804
|
+
id,
|
|
805
|
+
keys,
|
|
806
|
+
values,
|
|
807
|
+
leaf,
|
|
808
|
+
parent,
|
|
809
|
+
next,
|
|
810
|
+
prev
|
|
811
|
+
};
|
|
812
|
+
this.nodes.set(id, node);
|
|
813
|
+
return node;
|
|
814
|
+
}
|
|
815
|
+
async _deleteEntry(node, key, value) {
|
|
515
816
|
if (!node.leaf) {
|
|
516
817
|
for (let i = 0, len = node.keys.length; i < len; i++) {
|
|
517
818
|
const nKey = node.keys[i];
|
|
518
819
|
if (nKey === key) {
|
|
519
820
|
node.keys.splice(i, 1);
|
|
520
|
-
this.
|
|
821
|
+
this.bufferForNodeUpdate(node);
|
|
521
822
|
break;
|
|
522
823
|
}
|
|
523
824
|
}
|
|
@@ -525,23 +826,23 @@ var BPTree = class {
|
|
|
525
826
|
const nValue = node.values[i];
|
|
526
827
|
if (this.comparator.isSame(value, nValue)) {
|
|
527
828
|
node.values.splice(i, 1);
|
|
528
|
-
this.
|
|
829
|
+
this.bufferForNodeUpdate(node);
|
|
529
830
|
break;
|
|
530
831
|
}
|
|
531
832
|
}
|
|
532
833
|
}
|
|
533
834
|
if (this.root === node && node.keys.length === 1) {
|
|
534
835
|
const keys = node.keys;
|
|
535
|
-
this.root = this.getNode(keys[0]);
|
|
836
|
+
this.root = await this.getNode(keys[0]);
|
|
536
837
|
this.root.parent = 0;
|
|
537
|
-
this.
|
|
538
|
-
this.
|
|
838
|
+
this.bufferForHeadUpdate(this.headState);
|
|
839
|
+
this.bufferForNodeUpdate(this.root);
|
|
539
840
|
return;
|
|
540
841
|
} else if (this.root === node) {
|
|
541
842
|
return;
|
|
542
843
|
} else if (node.keys.length < Math.ceil(this.order / 2) && !node.leaf || node.values.length < Math.ceil((this.order - 1) / 2) && node.leaf) {
|
|
543
844
|
let isPredecessor = false;
|
|
544
|
-
let parentNode = this.getNode(node.parent);
|
|
845
|
+
let parentNode = await this.getNode(node.parent);
|
|
545
846
|
let prevNode = null;
|
|
546
847
|
let nextNode = null;
|
|
547
848
|
let prevValue = null;
|
|
@@ -550,11 +851,11 @@ var BPTree = class {
|
|
|
550
851
|
const nKey = parentNode.keys[i];
|
|
551
852
|
if (nKey === node.id) {
|
|
552
853
|
if (i > 0) {
|
|
553
|
-
prevNode = this.getNode(parentNode.keys[i - 1]);
|
|
854
|
+
prevNode = await this.getNode(parentNode.keys[i - 1]);
|
|
554
855
|
prevValue = parentNode.values[i - 1];
|
|
555
856
|
}
|
|
556
857
|
if (i < parentNode.keys.length - 1) {
|
|
557
|
-
nextNode = this.getNode(parentNode.keys[i + 1]);
|
|
858
|
+
nextNode = await this.getNode(parentNode.keys[i + 1]);
|
|
558
859
|
postValue = parentNode.values[i];
|
|
559
860
|
}
|
|
560
861
|
}
|
|
@@ -591,14 +892,14 @@ var BPTree = class {
|
|
|
591
892
|
pointer.next = node.next;
|
|
592
893
|
pointer.prev = node.id;
|
|
593
894
|
if (pointer.next) {
|
|
594
|
-
const n = this.getNode(node.next);
|
|
895
|
+
const n = await this.getNode(node.next);
|
|
595
896
|
n.prev = pointer.id;
|
|
596
|
-
this.
|
|
897
|
+
this.bufferForNodeUpdate(n);
|
|
597
898
|
}
|
|
598
899
|
if (pointer.prev) {
|
|
599
|
-
const n = this.getNode(node.id);
|
|
900
|
+
const n = await this.getNode(node.id);
|
|
600
901
|
n.next = pointer.id;
|
|
601
|
-
this.
|
|
902
|
+
this.bufferForNodeUpdate(n);
|
|
602
903
|
}
|
|
603
904
|
if (isPredecessor) {
|
|
604
905
|
pointer.prev = 0;
|
|
@@ -608,13 +909,13 @@ var BPTree = class {
|
|
|
608
909
|
if (!pointer.leaf) {
|
|
609
910
|
const keys = pointer.keys;
|
|
610
911
|
for (const key2 of keys) {
|
|
611
|
-
const node2 = this.getNode(key2);
|
|
912
|
+
const node2 = await this.getNode(key2);
|
|
612
913
|
node2.parent = pointer.id;
|
|
613
|
-
this.
|
|
914
|
+
this.bufferForNodeUpdate(node2);
|
|
614
915
|
}
|
|
615
916
|
}
|
|
616
|
-
this._deleteEntry(this.getNode(node.parent), node.id, guess);
|
|
617
|
-
this.
|
|
917
|
+
await this._deleteEntry(await this.getNode(node.parent), node.id, guess);
|
|
918
|
+
this.bufferForNodeUpdate(pointer);
|
|
618
919
|
} else {
|
|
619
920
|
if (isPredecessor) {
|
|
620
921
|
let pointerPm;
|
|
@@ -624,12 +925,12 @@ var BPTree = class {
|
|
|
624
925
|
pointerKm = pointer.values.splice(-1)[0];
|
|
625
926
|
node.keys = [pointerPm, ...node.keys];
|
|
626
927
|
node.values = [guess, ...node.values];
|
|
627
|
-
parentNode = this.getNode(node.parent);
|
|
928
|
+
parentNode = await this.getNode(node.parent);
|
|
628
929
|
for (let i = 0, len = parentNode.values.length; i < len; i++) {
|
|
629
930
|
const nValue = parentNode.values[i];
|
|
630
931
|
if (this.comparator.isSame(guess, nValue)) {
|
|
631
932
|
parentNode.values[i] = pointerKm;
|
|
632
|
-
this.
|
|
933
|
+
this.bufferForNodeUpdate(parentNode);
|
|
633
934
|
break;
|
|
634
935
|
}
|
|
635
936
|
}
|
|
@@ -638,18 +939,18 @@ var BPTree = class {
|
|
|
638
939
|
pointerKm = pointer.values.splice(-1)[0];
|
|
639
940
|
node.keys = [pointerPm, ...node.keys];
|
|
640
941
|
node.values = [pointerKm, ...node.values];
|
|
641
|
-
parentNode = this.getNode(node.parent);
|
|
942
|
+
parentNode = await this.getNode(node.parent);
|
|
642
943
|
for (let i = 0, len = parentNode.values.length; i < len; i++) {
|
|
643
944
|
const nValue = parentNode.values[i];
|
|
644
945
|
if (this.comparator.isSame(guess, nValue)) {
|
|
645
946
|
parentNode.values[i] = pointerKm;
|
|
646
|
-
this.
|
|
947
|
+
this.bufferForNodeUpdate(parentNode);
|
|
647
948
|
break;
|
|
648
949
|
}
|
|
649
950
|
}
|
|
650
951
|
}
|
|
651
|
-
this.
|
|
652
|
-
this.
|
|
952
|
+
this.bufferForNodeUpdate(node);
|
|
953
|
+
this.bufferForNodeUpdate(pointer);
|
|
653
954
|
} else {
|
|
654
955
|
let pointerP0;
|
|
655
956
|
let pointerK0;
|
|
@@ -658,12 +959,12 @@ var BPTree = class {
|
|
|
658
959
|
pointerK0 = pointer.values.splice(0, 1)[0];
|
|
659
960
|
node.keys = [...node.keys, pointerP0];
|
|
660
961
|
node.values = [...node.values, guess];
|
|
661
|
-
parentNode = this.getNode(node.parent);
|
|
962
|
+
parentNode = await this.getNode(node.parent);
|
|
662
963
|
for (let i = 0, len = parentNode.values.length; i < len; i++) {
|
|
663
964
|
const nValue = parentNode.values[i];
|
|
664
965
|
if (this.comparator.isSame(guess, nValue)) {
|
|
665
966
|
parentNode.values[i] = pointerK0;
|
|
666
|
-
this.
|
|
967
|
+
this.bufferForNodeUpdate(parentNode);
|
|
667
968
|
break;
|
|
668
969
|
}
|
|
669
970
|
}
|
|
@@ -672,72 +973,300 @@ var BPTree = class {
|
|
|
672
973
|
pointerK0 = pointer.values.splice(0, 1)[0];
|
|
673
974
|
node.keys = [...node.keys, pointerP0];
|
|
674
975
|
node.values = [...node.values, pointerK0];
|
|
675
|
-
parentNode = this.getNode(node.parent);
|
|
976
|
+
parentNode = await this.getNode(node.parent);
|
|
676
977
|
for (let i = 0, len = parentNode.values.length; i < len; i++) {
|
|
677
978
|
const nValue = parentNode.values[i];
|
|
678
979
|
if (this.comparator.isSame(guess, nValue)) {
|
|
679
980
|
parentNode.values[i] = pointer.values[0];
|
|
680
|
-
this.
|
|
981
|
+
this.bufferForNodeUpdate(parentNode);
|
|
681
982
|
break;
|
|
682
983
|
}
|
|
683
984
|
}
|
|
684
985
|
}
|
|
685
|
-
this.
|
|
686
|
-
this.
|
|
986
|
+
this.bufferForNodeUpdate(node);
|
|
987
|
+
this.bufferForNodeUpdate(pointer);
|
|
687
988
|
}
|
|
688
989
|
if (!pointer.leaf) {
|
|
689
990
|
for (const key2 of pointer.keys) {
|
|
690
|
-
const n = this.getNode(key2);
|
|
991
|
+
const n = await this.getNode(key2);
|
|
691
992
|
n.parent = pointer.id;
|
|
692
|
-
this.
|
|
993
|
+
this.bufferForNodeUpdate(n);
|
|
693
994
|
}
|
|
694
995
|
}
|
|
695
996
|
if (!node.leaf) {
|
|
696
997
|
for (const key2 of node.keys) {
|
|
697
|
-
const n = this.getNode(key2);
|
|
998
|
+
const n = await this.getNode(key2);
|
|
698
999
|
n.parent = node.id;
|
|
699
|
-
this.
|
|
1000
|
+
this.bufferForNodeUpdate(n);
|
|
700
1001
|
}
|
|
701
1002
|
}
|
|
702
1003
|
if (!parentNode.leaf) {
|
|
703
1004
|
for (const key2 of parentNode.keys) {
|
|
704
|
-
const n = this.getNode(key2);
|
|
1005
|
+
const n = await this.getNode(key2);
|
|
705
1006
|
n.parent = parentNode.id;
|
|
706
|
-
this.
|
|
1007
|
+
this.bufferForNodeUpdate(n);
|
|
707
1008
|
}
|
|
708
1009
|
}
|
|
709
1010
|
}
|
|
710
1011
|
}
|
|
711
1012
|
}
|
|
712
|
-
|
|
713
|
-
|
|
714
|
-
|
|
715
|
-
|
|
716
|
-
|
|
717
|
-
|
|
718
|
-
|
|
1013
|
+
async _insertInParent(node, value, pointer) {
|
|
1014
|
+
if (this.root === node) {
|
|
1015
|
+
const root = await this._createNode([node.id, pointer.id], [value]);
|
|
1016
|
+
this.root = root;
|
|
1017
|
+
node.parent = root.id;
|
|
1018
|
+
pointer.parent = root.id;
|
|
1019
|
+
this.bufferForHeadUpdate(this.headState);
|
|
1020
|
+
this.bufferForNodeCreate(root);
|
|
1021
|
+
this.bufferForNodeUpdate(node);
|
|
1022
|
+
this.bufferForNodeUpdate(pointer);
|
|
1023
|
+
return;
|
|
1024
|
+
}
|
|
1025
|
+
const parentNode = await this.getNode(node.parent);
|
|
1026
|
+
for (let i = 0, len = parentNode.keys.length; i < len; i++) {
|
|
1027
|
+
const nKeys = parentNode.keys[i];
|
|
1028
|
+
if (nKeys === node.id) {
|
|
1029
|
+
parentNode.values.splice(i, 0, value);
|
|
1030
|
+
parentNode.keys.splice(i + 1, 0, pointer.id);
|
|
1031
|
+
this.bufferForNodeUpdate(parentNode);
|
|
1032
|
+
if (parentNode.keys.length > this.order) {
|
|
1033
|
+
const parentPointer = await this._createNode([], []);
|
|
1034
|
+
parentPointer.parent = parentNode.parent;
|
|
1035
|
+
const mid = Math.ceil(this.order / 2) - 1;
|
|
1036
|
+
parentPointer.values = parentNode.values.slice(mid + 1);
|
|
1037
|
+
parentPointer.keys = parentNode.keys.slice(mid + 1);
|
|
1038
|
+
const midValue = parentNode.values[mid];
|
|
1039
|
+
if (mid === 0) {
|
|
1040
|
+
parentNode.values = parentNode.values.slice(0, mid + 1);
|
|
1041
|
+
} else {
|
|
1042
|
+
parentNode.values = parentNode.values.slice(0, mid);
|
|
1043
|
+
}
|
|
1044
|
+
parentNode.keys = parentNode.keys.slice(0, mid + 1);
|
|
1045
|
+
for (const k of parentNode.keys) {
|
|
1046
|
+
const node2 = await this.getNode(k);
|
|
1047
|
+
node2.parent = parentNode.id;
|
|
1048
|
+
this.bufferForNodeUpdate(node2);
|
|
1049
|
+
}
|
|
1050
|
+
for (const k of parentPointer.keys) {
|
|
1051
|
+
const node2 = await this.getNode(k);
|
|
1052
|
+
node2.parent = parentPointer.id;
|
|
1053
|
+
this.bufferForNodeUpdate(node2);
|
|
1054
|
+
}
|
|
1055
|
+
await this._insertInParent(parentNode, midValue, parentPointer);
|
|
1056
|
+
this.bufferForNodeCreate(parentPointer);
|
|
1057
|
+
this.bufferForNodeUpdate(parentNode);
|
|
1058
|
+
}
|
|
1059
|
+
}
|
|
1060
|
+
}
|
|
719
1061
|
}
|
|
720
|
-
|
|
721
|
-
|
|
722
|
-
|
|
723
|
-
|
|
724
|
-
|
|
725
|
-
|
|
726
|
-
|
|
1062
|
+
async init() {
|
|
1063
|
+
const head = await this.strategy.readHead();
|
|
1064
|
+
if (head === null) {
|
|
1065
|
+
this.order = this.strategy.order;
|
|
1066
|
+
this.data = {};
|
|
1067
|
+
this.root = await this._createNode([], [], true);
|
|
1068
|
+
this.bufferForHeadUpdate(this.headState);
|
|
1069
|
+
this.bufferForNodeCreate(this.root);
|
|
1070
|
+
this.commitHeadBuffer();
|
|
1071
|
+
this.commitNodeCreateBuffer();
|
|
1072
|
+
} else {
|
|
1073
|
+
const { root, order, data } = head;
|
|
1074
|
+
this.order = order;
|
|
1075
|
+
this.data = data ?? {};
|
|
1076
|
+
this.root = await this.getNode(root);
|
|
1077
|
+
}
|
|
1078
|
+
if (this.order < 3) {
|
|
1079
|
+
throw new Error(`The 'order' parameter must be greater than 2. but got a '${this.order}'.`);
|
|
1080
|
+
}
|
|
1081
|
+
}
|
|
1082
|
+
async getNode(id) {
|
|
1083
|
+
if (!this.nodes.has(id)) {
|
|
1084
|
+
this.nodes.set(id, await this.strategy.read(id));
|
|
1085
|
+
}
|
|
1086
|
+
return this.nodes.get(id);
|
|
1087
|
+
}
|
|
1088
|
+
async insertableNode(value) {
|
|
1089
|
+
let node = this.root;
|
|
1090
|
+
while (!node.leaf) {
|
|
1091
|
+
for (let i = 0, len = node.values.length; i < len; i++) {
|
|
1092
|
+
const nValue = node.values[i];
|
|
1093
|
+
const k = node.keys;
|
|
1094
|
+
if (this.comparator.isSame(value, nValue)) {
|
|
1095
|
+
node = await this.getNode(k[i + 1]);
|
|
1096
|
+
break;
|
|
1097
|
+
} else if (this.comparator.isLower(value, nValue)) {
|
|
1098
|
+
node = await this.getNode(k[i]);
|
|
1099
|
+
break;
|
|
1100
|
+
} else if (i + 1 === node.values.length) {
|
|
1101
|
+
node = await this.getNode(k[i + 1]);
|
|
1102
|
+
break;
|
|
1103
|
+
}
|
|
1104
|
+
}
|
|
1105
|
+
}
|
|
1106
|
+
return node;
|
|
1107
|
+
}
|
|
1108
|
+
async leftestNode() {
|
|
1109
|
+
let node = this.root;
|
|
1110
|
+
while (!node.leaf) {
|
|
1111
|
+
const keys = node.keys;
|
|
1112
|
+
node = await this.getNode(keys[0]);
|
|
1113
|
+
}
|
|
1114
|
+
return node;
|
|
1115
|
+
}
|
|
1116
|
+
async commitHeadBuffer() {
|
|
1117
|
+
if (this._headBuffer !== null) {
|
|
1118
|
+
await this.strategy.writeHead(this._headBuffer);
|
|
1119
|
+
}
|
|
1120
|
+
this.bufferForHeadUpdate(null);
|
|
1121
|
+
}
|
|
1122
|
+
async commitNodeCreateBuffer() {
|
|
1123
|
+
for (const node of this._nodeCreateBuffer.values()) {
|
|
1124
|
+
await this.strategy.write(node.id, node);
|
|
1125
|
+
}
|
|
1126
|
+
this._nodeCreateBuffer.clear();
|
|
1127
|
+
}
|
|
1128
|
+
async commitNodeUpdateBuffer() {
|
|
1129
|
+
for (const node of this._nodeUpdateBuffer.values()) {
|
|
1130
|
+
await this.strategy.write(node.id, node);
|
|
1131
|
+
}
|
|
1132
|
+
this._nodeUpdateBuffer.clear();
|
|
1133
|
+
}
|
|
1134
|
+
async keys(condition) {
|
|
1135
|
+
let result = null;
|
|
1136
|
+
for (const k in condition) {
|
|
1137
|
+
const key = k;
|
|
1138
|
+
const value = condition[key];
|
|
1139
|
+
const startNode = await this.verifierStartNode[key](value);
|
|
1140
|
+
const direction = this.verifierDirection[key];
|
|
1141
|
+
const fullScan = this.verifierFullScan[key];
|
|
1142
|
+
const comparator = this.verifierMap[key];
|
|
1143
|
+
const pairs = await this.getPairs(value, startNode, fullScan, comparator, direction);
|
|
1144
|
+
if (result === null) {
|
|
1145
|
+
result = pairs.map((pair) => pair.key);
|
|
1146
|
+
} else {
|
|
1147
|
+
result = result.filter((key2) => pairs.find((p) => p.key === key2));
|
|
1148
|
+
}
|
|
1149
|
+
}
|
|
1150
|
+
return new Set(result ?? []);
|
|
1151
|
+
}
|
|
1152
|
+
async where(condition) {
|
|
1153
|
+
let result = null;
|
|
1154
|
+
for (const k in condition) {
|
|
1155
|
+
const key = k;
|
|
1156
|
+
const value = condition[key];
|
|
1157
|
+
const startNode = await this.verifierStartNode[key](value);
|
|
1158
|
+
const direction = this.verifierDirection[key];
|
|
1159
|
+
const fullScan = this.verifierFullScan[key];
|
|
1160
|
+
const comparator = this.verifierMap[key];
|
|
1161
|
+
const pairs = await this.getPairs(value, startNode, fullScan, comparator, direction);
|
|
1162
|
+
if (result === null) {
|
|
1163
|
+
result = pairs;
|
|
1164
|
+
} else {
|
|
1165
|
+
result = result.filter((pair) => pairs.find((p) => p.key === pair.key));
|
|
1166
|
+
}
|
|
1167
|
+
}
|
|
1168
|
+
return result ?? [];
|
|
1169
|
+
}
|
|
1170
|
+
async insert(key, value) {
|
|
1171
|
+
const before = await this.insertableNode(value);
|
|
1172
|
+
this._insertAtLeaf(before, key, value);
|
|
1173
|
+
if (before.values.length === this.order) {
|
|
1174
|
+
const after = await this._createNode(
|
|
1175
|
+
[],
|
|
1176
|
+
[],
|
|
1177
|
+
true,
|
|
1178
|
+
before.parent,
|
|
1179
|
+
before.next,
|
|
1180
|
+
before.id
|
|
1181
|
+
);
|
|
1182
|
+
const mid = Math.ceil(this.order / 2) - 1;
|
|
1183
|
+
const beforeNext = before.next;
|
|
1184
|
+
after.values = before.values.slice(mid + 1);
|
|
1185
|
+
after.keys = before.keys.slice(mid + 1);
|
|
1186
|
+
before.values = before.values.slice(0, mid + 1);
|
|
1187
|
+
before.keys = before.keys.slice(0, mid + 1);
|
|
1188
|
+
before.next = after.id;
|
|
1189
|
+
if (beforeNext) {
|
|
1190
|
+
const node = await this.getNode(beforeNext);
|
|
1191
|
+
node.prev = after.id;
|
|
1192
|
+
this.bufferForNodeUpdate(node);
|
|
1193
|
+
}
|
|
1194
|
+
await this._insertInParent(before, after.values[0], after);
|
|
1195
|
+
this.bufferForNodeCreate(after);
|
|
1196
|
+
this.bufferForNodeUpdate(before);
|
|
1197
|
+
}
|
|
1198
|
+
await this.commitHeadBuffer();
|
|
1199
|
+
await this.commitNodeCreateBuffer();
|
|
1200
|
+
await this.commitNodeUpdateBuffer();
|
|
1201
|
+
}
|
|
1202
|
+
async delete(key, value) {
|
|
1203
|
+
const node = await this.insertableNode(value);
|
|
1204
|
+
let i = node.values.length;
|
|
1205
|
+
while (i--) {
|
|
1206
|
+
const nValue = node.values[i];
|
|
1207
|
+
if (this.comparator.isSame(value, nValue)) {
|
|
1208
|
+
const keys = node.keys[i];
|
|
1209
|
+
if (keys.includes(key)) {
|
|
1210
|
+
if (keys.length > 1) {
|
|
1211
|
+
keys.splice(keys.indexOf(key), 1);
|
|
1212
|
+
this.bufferForNodeUpdate(node);
|
|
1213
|
+
} else if (node === this.root) {
|
|
1214
|
+
node.values.splice(i, 1);
|
|
1215
|
+
node.keys.splice(i, 1);
|
|
1216
|
+
this.bufferForNodeUpdate(node);
|
|
1217
|
+
} else {
|
|
1218
|
+
keys.splice(keys.indexOf(key), 1);
|
|
1219
|
+
node.keys.splice(i, 1);
|
|
1220
|
+
node.values.splice(node.values.indexOf(value), 1);
|
|
1221
|
+
await this._deleteEntry(node, key, value);
|
|
1222
|
+
this.bufferForNodeUpdate(node);
|
|
1223
|
+
}
|
|
1224
|
+
}
|
|
1225
|
+
}
|
|
1226
|
+
}
|
|
1227
|
+
await this.commitHeadBuffer();
|
|
1228
|
+
await this.commitNodeCreateBuffer();
|
|
1229
|
+
await this.commitNodeUpdateBuffer();
|
|
1230
|
+
}
|
|
1231
|
+
async exists(key, value) {
|
|
1232
|
+
const node = await this.insertableNode(value);
|
|
1233
|
+
for (let i = 0, len = node.values.length; i < len; i++) {
|
|
1234
|
+
const nValue = node.values[i];
|
|
1235
|
+
if (this.comparator.isSame(value, nValue)) {
|
|
1236
|
+
const keys = node.keys[i];
|
|
1237
|
+
return keys.includes(key);
|
|
1238
|
+
}
|
|
1239
|
+
}
|
|
1240
|
+
return false;
|
|
1241
|
+
}
|
|
1242
|
+
async setHeadData(data) {
|
|
727
1243
|
this.data = data;
|
|
728
|
-
this.
|
|
729
|
-
this.
|
|
1244
|
+
this.bufferForHeadUpdate(this.headState);
|
|
1245
|
+
await this.commitHeadBuffer();
|
|
1246
|
+
}
|
|
1247
|
+
async forceUpdate() {
|
|
1248
|
+
const keys = [...this.nodes.keys()];
|
|
1249
|
+
this.nodes.clear();
|
|
1250
|
+
await this.init();
|
|
1251
|
+
for (const key of keys) {
|
|
1252
|
+
await this.getNode(key);
|
|
1253
|
+
}
|
|
1254
|
+
return keys.length;
|
|
730
1255
|
}
|
|
731
1256
|
};
|
|
732
1257
|
|
|
733
|
-
// src/SerializeStrategy.ts
|
|
1258
|
+
// src/base/SerializeStrategy.ts
|
|
734
1259
|
var SerializeStrategy = class {
|
|
735
1260
|
order;
|
|
736
1261
|
constructor(order) {
|
|
737
1262
|
this.order = order;
|
|
738
1263
|
}
|
|
739
1264
|
};
|
|
740
|
-
|
|
1265
|
+
|
|
1266
|
+
// src/SerializeStrategySync.ts
|
|
1267
|
+
var SerializeStrategySync = class extends SerializeStrategy {
|
|
1268
|
+
};
|
|
1269
|
+
var InMemoryStoreStrategySync = class extends SerializeStrategySync {
|
|
741
1270
|
data;
|
|
742
1271
|
constructor(order) {
|
|
743
1272
|
super(order);
|
|
@@ -766,33 +1295,45 @@ var InMemoryStoreStrategy = class extends SerializeStrategy {
|
|
|
766
1295
|
}
|
|
767
1296
|
};
|
|
768
1297
|
|
|
769
|
-
// src/
|
|
770
|
-
var
|
|
771
|
-
|
|
772
|
-
|
|
1298
|
+
// src/SerializeStrategyAsync.ts
|
|
1299
|
+
var SerializeStrategyAsync = class extends SerializeStrategy {
|
|
1300
|
+
};
|
|
1301
|
+
var InMemoryStoreStrategyAsync = class extends SerializeStrategyAsync {
|
|
1302
|
+
data;
|
|
1303
|
+
constructor(order) {
|
|
1304
|
+
super(order);
|
|
1305
|
+
this.data = {
|
|
1306
|
+
head: null,
|
|
1307
|
+
node: {}
|
|
1308
|
+
};
|
|
773
1309
|
}
|
|
774
|
-
|
|
775
|
-
return
|
|
1310
|
+
async id() {
|
|
1311
|
+
return Math.ceil(Math.random() * Number.MAX_SAFE_INTEGER - 1);
|
|
776
1312
|
}
|
|
777
|
-
|
|
778
|
-
|
|
1313
|
+
async read(id) {
|
|
1314
|
+
if (!Object.prototype.hasOwnProperty.call(this.data.node, id)) {
|
|
1315
|
+
throw new Error(`The tree attempted to reference node '${id}', but couldn't find the corresponding node.`);
|
|
1316
|
+
}
|
|
1317
|
+
return this.data.node[id];
|
|
779
1318
|
}
|
|
780
|
-
|
|
781
|
-
|
|
782
|
-
asc(a, b) {
|
|
783
|
-
return a - b;
|
|
1319
|
+
async write(id, node) {
|
|
1320
|
+
this.data.node[id] = node;
|
|
784
1321
|
}
|
|
785
|
-
|
|
786
|
-
|
|
787
|
-
|
|
788
|
-
|
|
1322
|
+
async readHead() {
|
|
1323
|
+
return this.data.head;
|
|
1324
|
+
}
|
|
1325
|
+
async writeHead(head) {
|
|
1326
|
+
this.data.head = head;
|
|
789
1327
|
}
|
|
790
1328
|
};
|
|
791
1329
|
export {
|
|
792
|
-
|
|
793
|
-
|
|
1330
|
+
BPTreeAsync,
|
|
1331
|
+
BPTreeSync,
|
|
1332
|
+
InMemoryStoreStrategyAsync,
|
|
1333
|
+
InMemoryStoreStrategySync,
|
|
794
1334
|
NumericComparator,
|
|
795
|
-
|
|
1335
|
+
SerializeStrategyAsync,
|
|
1336
|
+
SerializeStrategySync,
|
|
796
1337
|
StringComparator,
|
|
797
1338
|
ValueComparator
|
|
798
1339
|
};
|