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