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