serializable-bptree 1.1.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 +173 -27
- package/dist/cjs/index.js +925 -520
- package/dist/esm/index.js +925 -520
- 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 +6 -1
- package/dist/typings/BPTree.d.ts +0 -126
- package/dist/typings/utils/BinarySearch.d.ts +0 -9
package/dist/cjs/index.js
CHANGED
|
@@ -20,83 +20,206 @@ 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
|
|
35
|
+
// src/base/BPTree.ts
|
|
36
|
+
var BPTree = class {
|
|
37
|
+
strategy;
|
|
34
38
|
comparator;
|
|
35
|
-
|
|
39
|
+
nodes;
|
|
40
|
+
order;
|
|
41
|
+
data;
|
|
42
|
+
root;
|
|
43
|
+
_nodeCreateBuffer;
|
|
44
|
+
_nodeUpdateBuffer;
|
|
45
|
+
_headBuffer;
|
|
46
|
+
verifierMap = {
|
|
47
|
+
gt: (nv, v) => this.comparator.isHigher(nv, v),
|
|
48
|
+
gte: (nv, v) => this.comparator.isHigher(nv, v) || this.comparator.isSame(nv, v),
|
|
49
|
+
lt: (nv, v) => this.comparator.isLower(nv, v),
|
|
50
|
+
lte: (nv, v) => this.comparator.isLower(nv, v) || this.comparator.isSame(nv, v),
|
|
51
|
+
equal: (nv, v) => this.comparator.isSame(nv, v),
|
|
52
|
+
notEqual: (nv, v) => this.comparator.isSame(nv, v) === false,
|
|
53
|
+
like: (nv, v) => {
|
|
54
|
+
const nodeValue = nv.toString();
|
|
55
|
+
const value = v.toString();
|
|
56
|
+
const pattern = value.replace(/%/g, ".*").replace(/_/g, ".");
|
|
57
|
+
const regex = new RegExp(`^${pattern}$`, "i");
|
|
58
|
+
return regex.test(nodeValue);
|
|
59
|
+
}
|
|
60
|
+
};
|
|
61
|
+
verifierStartNode = {
|
|
62
|
+
gt: (v) => this.insertableNode(v),
|
|
63
|
+
gte: (v) => this.insertableNode(v),
|
|
64
|
+
lt: (v) => this.insertableNode(v),
|
|
65
|
+
lte: (v) => this.insertableNode(v),
|
|
66
|
+
equal: (v) => this.insertableNode(v),
|
|
67
|
+
notEqual: (v) => this.leftestNode(),
|
|
68
|
+
like: (v) => this.leftestNode()
|
|
69
|
+
};
|
|
70
|
+
verifierDirection = {
|
|
71
|
+
gt: 1,
|
|
72
|
+
gte: 1,
|
|
73
|
+
lt: -1,
|
|
74
|
+
lte: -1,
|
|
75
|
+
equal: 1,
|
|
76
|
+
notEqual: 1,
|
|
77
|
+
like: 1
|
|
78
|
+
};
|
|
79
|
+
verifierFullSearch = {
|
|
80
|
+
gt: false,
|
|
81
|
+
gte: false,
|
|
82
|
+
lt: false,
|
|
83
|
+
lte: false,
|
|
84
|
+
equal: false,
|
|
85
|
+
notEqual: true,
|
|
86
|
+
like: true
|
|
87
|
+
};
|
|
88
|
+
get headState() {
|
|
89
|
+
const root = this.root.id;
|
|
90
|
+
const order = this.order;
|
|
91
|
+
const data = this.data;
|
|
92
|
+
return {
|
|
93
|
+
root,
|
|
94
|
+
order,
|
|
95
|
+
data
|
|
96
|
+
};
|
|
97
|
+
}
|
|
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;
|
|
36
104
|
this.comparator = comparator;
|
|
37
105
|
}
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
106
|
+
_insertAtLeaf(node, key, value) {
|
|
107
|
+
if (node.values.length) {
|
|
108
|
+
for (let i = 0, len = node.values.length; i < len; i++) {
|
|
109
|
+
const nValue = node.values[i];
|
|
110
|
+
if (this.comparator.isSame(value, nValue)) {
|
|
111
|
+
const keys = node.keys[i];
|
|
112
|
+
keys.push(key);
|
|
113
|
+
this.bufferForNodeUpdate(node);
|
|
114
|
+
break;
|
|
115
|
+
} else if (this.comparator.isLower(value, nValue)) {
|
|
116
|
+
node.values.splice(i, 0, value);
|
|
117
|
+
node.keys.splice(i, 0, [key]);
|
|
118
|
+
this.bufferForNodeUpdate(node);
|
|
119
|
+
break;
|
|
120
|
+
} else if (i + 1 === node.values.length) {
|
|
121
|
+
node.values.push(value);
|
|
122
|
+
node.keys.push([key]);
|
|
123
|
+
this.bufferForNodeUpdate(node);
|
|
124
|
+
break;
|
|
125
|
+
}
|
|
50
126
|
}
|
|
127
|
+
} else {
|
|
128
|
+
node.values = [value];
|
|
129
|
+
node.keys = [[key]];
|
|
130
|
+
this.bufferForNodeUpdate(node);
|
|
51
131
|
}
|
|
52
|
-
return -1;
|
|
53
132
|
}
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
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);
|
|
156
|
+
}
|
|
157
|
+
_getPairsRightToLeft(value, startNode, fullSearch, comparator) {
|
|
158
|
+
const pairs = [];
|
|
159
|
+
let node = startNode;
|
|
160
|
+
let done = false;
|
|
161
|
+
let found = false;
|
|
162
|
+
while (!done) {
|
|
163
|
+
let i = node.values.length;
|
|
164
|
+
while (i--) {
|
|
165
|
+
const nValue = node.values[i];
|
|
166
|
+
const keys = node.keys[i];
|
|
167
|
+
if (comparator(nValue, value)) {
|
|
168
|
+
found = true;
|
|
169
|
+
let j = keys.length;
|
|
170
|
+
while (j--) {
|
|
171
|
+
pairs.push({ key: keys[j], value: nValue });
|
|
172
|
+
}
|
|
173
|
+
} else if (found && !fullSearch) {
|
|
174
|
+
done = true;
|
|
175
|
+
break;
|
|
176
|
+
}
|
|
177
|
+
}
|
|
178
|
+
if (!node.prev) {
|
|
179
|
+
done = true;
|
|
61
180
|
break;
|
|
62
181
|
}
|
|
63
|
-
|
|
182
|
+
node = this.getNode(node.prev);
|
|
64
183
|
}
|
|
65
|
-
return
|
|
184
|
+
return pairs.reverse();
|
|
66
185
|
}
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
186
|
+
_getPairsLeftToRight(value, startNode, fullSearch, comparator) {
|
|
187
|
+
const pairs = [];
|
|
188
|
+
let node = startNode;
|
|
189
|
+
let done = false;
|
|
190
|
+
let found = false;
|
|
191
|
+
while (!done) {
|
|
192
|
+
for (let i = 0, len = node.values.length; i < len; i++) {
|
|
193
|
+
const nValue = node.values[i];
|
|
194
|
+
const keys = node.keys[i];
|
|
195
|
+
if (comparator(nValue, value)) {
|
|
196
|
+
found = true;
|
|
197
|
+
for (const key of keys) {
|
|
198
|
+
pairs.push({ key, value: nValue });
|
|
199
|
+
}
|
|
200
|
+
} else if (found && !fullSearch) {
|
|
201
|
+
done = true;
|
|
202
|
+
break;
|
|
203
|
+
}
|
|
204
|
+
}
|
|
205
|
+
if (!node.next) {
|
|
206
|
+
done = true;
|
|
75
207
|
break;
|
|
76
208
|
}
|
|
77
|
-
|
|
209
|
+
node = this.getNode(node.next);
|
|
78
210
|
}
|
|
79
|
-
return
|
|
211
|
+
return pairs;
|
|
80
212
|
}
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
213
|
+
getPairs(value, startNode, fullSearch, comparator, direction) {
|
|
214
|
+
switch (direction) {
|
|
215
|
+
case -1:
|
|
216
|
+
return this._getPairsRightToLeft(value, startNode, fullSearch, comparator);
|
|
217
|
+
case 1:
|
|
218
|
+
return this._getPairsLeftToRight(value, startNode, fullSearch, comparator);
|
|
219
|
+
default:
|
|
220
|
+
throw new Error(`Direction must be -1 or 1. but got a ${direction}`);
|
|
221
|
+
}
|
|
85
222
|
}
|
|
86
|
-
};
|
|
87
|
-
|
|
88
|
-
// src/BPTree.ts
|
|
89
|
-
var BPTree = class {
|
|
90
|
-
strategy;
|
|
91
|
-
comparator;
|
|
92
|
-
search;
|
|
93
|
-
order;
|
|
94
|
-
nodes;
|
|
95
|
-
data;
|
|
96
|
-
root;
|
|
97
|
-
_creates;
|
|
98
|
-
_updates;
|
|
99
|
-
_updatedHead;
|
|
100
223
|
_createNodeId() {
|
|
101
224
|
const id = this.strategy.id();
|
|
102
225
|
if (id === 0) {
|
|
@@ -104,7 +227,7 @@ var BPTree = class {
|
|
|
104
227
|
}
|
|
105
228
|
return id;
|
|
106
229
|
}
|
|
107
|
-
_createNode(keys, values, leaf = false, parent = 0, next = 0) {
|
|
230
|
+
_createNode(keys, values, leaf = false, parent = 0, next = 0, prev = 0) {
|
|
108
231
|
const id = this._createNodeId();
|
|
109
232
|
const node = {
|
|
110
233
|
id,
|
|
@@ -112,128 +235,209 @@ var BPTree = class {
|
|
|
112
235
|
values,
|
|
113
236
|
leaf,
|
|
114
237
|
parent,
|
|
115
|
-
next
|
|
238
|
+
next,
|
|
239
|
+
prev
|
|
116
240
|
};
|
|
117
241
|
this.nodes.set(id, node);
|
|
118
242
|
return node;
|
|
119
243
|
}
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
this.search = new BinarySearch(comparator);
|
|
131
|
-
this.strategy = strategy;
|
|
132
|
-
this.comparator = comparator;
|
|
133
|
-
if (head === null) {
|
|
134
|
-
this.order = strategy.order;
|
|
135
|
-
this.data = {};
|
|
136
|
-
this.root = this._createNode([], [], true);
|
|
137
|
-
this._setHeadUpdate(this._headState);
|
|
138
|
-
this._setCreates(this.root);
|
|
139
|
-
this._emitHeadUpdates();
|
|
140
|
-
this._emitCreates();
|
|
141
|
-
} else {
|
|
142
|
-
const { root, order, data } = head;
|
|
143
|
-
this.order = order;
|
|
144
|
-
this.data = data ?? {};
|
|
145
|
-
this.root = this.getNode(root);
|
|
146
|
-
}
|
|
147
|
-
if (this.order < 3) {
|
|
148
|
-
throw new Error(`The 'order' parameter must be greater than 2. but got a '${this.order}'.`);
|
|
149
|
-
}
|
|
150
|
-
}
|
|
151
|
-
get _headState() {
|
|
152
|
-
const root = this.root.id;
|
|
153
|
-
const order = this.order;
|
|
154
|
-
const data = this.data;
|
|
155
|
-
return {
|
|
156
|
-
root,
|
|
157
|
-
order,
|
|
158
|
-
data
|
|
159
|
-
};
|
|
160
|
-
}
|
|
161
|
-
_setHeadUpdate(head) {
|
|
162
|
-
this._updatedHead = head;
|
|
163
|
-
}
|
|
164
|
-
_setCreates(node) {
|
|
165
|
-
this._creates.set(node.id, node);
|
|
166
|
-
}
|
|
167
|
-
_setUpdates(node) {
|
|
168
|
-
this._updates.set(node.id, node);
|
|
169
|
-
}
|
|
170
|
-
_emitHeadUpdates() {
|
|
171
|
-
if (this._updatedHead !== null) {
|
|
172
|
-
this.strategy.writeHead(this._updatedHead);
|
|
173
|
-
}
|
|
174
|
-
this._updatedHead = null;
|
|
175
|
-
}
|
|
176
|
-
_emitCreates() {
|
|
177
|
-
for (const node of this._creates.values()) {
|
|
178
|
-
this.strategy.write(node.id, node);
|
|
179
|
-
}
|
|
180
|
-
this._creates.clear();
|
|
181
|
-
}
|
|
182
|
-
_emitUpdates() {
|
|
183
|
-
for (const node of this._updates.values()) {
|
|
184
|
-
this.strategy.write(node.id, node);
|
|
185
|
-
}
|
|
186
|
-
this._updates.clear();
|
|
187
|
-
}
|
|
188
|
-
getNode(id) {
|
|
189
|
-
if (!this.nodes.has(id)) {
|
|
190
|
-
this.nodes.set(id, this.strategy.read(id));
|
|
191
|
-
}
|
|
192
|
-
return this.nodes.get(id);
|
|
193
|
-
}
|
|
194
|
-
leftestNode() {
|
|
195
|
-
let node = this.root;
|
|
196
|
-
while (!node.leaf) {
|
|
197
|
-
const keys = node.keys;
|
|
198
|
-
node = this.getNode(keys[0]);
|
|
199
|
-
}
|
|
200
|
-
return node;
|
|
201
|
-
}
|
|
202
|
-
_insertableNode(value) {
|
|
203
|
-
let node = this.root;
|
|
204
|
-
while (!node.leaf) {
|
|
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
|
+
}
|
|
205
254
|
for (let i = 0, len = node.values.length; i < len; i++) {
|
|
206
255
|
const nValue = node.values[i];
|
|
207
|
-
const k = node.keys;
|
|
208
256
|
if (this.comparator.isSame(value, nValue)) {
|
|
209
|
-
node
|
|
210
|
-
|
|
211
|
-
} else if (this.comparator.isLower(value, nValue)) {
|
|
212
|
-
node = this.getNode(k[i]);
|
|
213
|
-
break;
|
|
214
|
-
} else if (i + 1 === node.values.length) {
|
|
215
|
-
node = this.getNode(k[i + 1]);
|
|
257
|
+
node.values.splice(i, 1);
|
|
258
|
+
this.bufferForNodeUpdate(node);
|
|
216
259
|
break;
|
|
217
260
|
}
|
|
218
261
|
}
|
|
219
262
|
}
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
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
|
+
}
|
|
234
439
|
}
|
|
235
440
|
}
|
|
236
|
-
return false;
|
|
237
441
|
}
|
|
238
442
|
_insertAtLeaf(node, key, value) {
|
|
239
443
|
if (node.values.length) {
|
|
@@ -242,24 +446,24 @@ var BPTree = class {
|
|
|
242
446
|
if (this.comparator.isSame(value, nValue)) {
|
|
243
447
|
const keys = node.keys[i];
|
|
244
448
|
keys.push(key);
|
|
245
|
-
this.
|
|
449
|
+
this.bufferForNodeUpdate(node);
|
|
246
450
|
break;
|
|
247
451
|
} else if (this.comparator.isLower(value, nValue)) {
|
|
248
452
|
node.values.splice(i, 0, value);
|
|
249
453
|
node.keys.splice(i, 0, [key]);
|
|
250
|
-
this.
|
|
454
|
+
this.bufferForNodeUpdate(node);
|
|
251
455
|
break;
|
|
252
456
|
} else if (i + 1 === node.values.length) {
|
|
253
457
|
node.values.push(value);
|
|
254
458
|
node.keys.push([key]);
|
|
255
|
-
this.
|
|
459
|
+
this.bufferForNodeUpdate(node);
|
|
256
460
|
break;
|
|
257
461
|
}
|
|
258
462
|
}
|
|
259
463
|
} else {
|
|
260
464
|
node.values = [value];
|
|
261
465
|
node.keys = [[key]];
|
|
262
|
-
this.
|
|
466
|
+
this.bufferForNodeUpdate(node);
|
|
263
467
|
}
|
|
264
468
|
}
|
|
265
469
|
_insertInParent(node, value, pointer) {
|
|
@@ -268,10 +472,10 @@ var BPTree = class {
|
|
|
268
472
|
this.root = root;
|
|
269
473
|
node.parent = root.id;
|
|
270
474
|
pointer.parent = root.id;
|
|
271
|
-
this.
|
|
272
|
-
this.
|
|
273
|
-
this.
|
|
274
|
-
this.
|
|
475
|
+
this.bufferForHeadUpdate(this.headState);
|
|
476
|
+
this.bufferForNodeCreate(root);
|
|
477
|
+
this.bufferForNodeUpdate(node);
|
|
478
|
+
this.bufferForNodeUpdate(pointer);
|
|
275
479
|
return;
|
|
276
480
|
}
|
|
277
481
|
const parentNode = this.getNode(node.parent);
|
|
@@ -280,7 +484,7 @@ var BPTree = class {
|
|
|
280
484
|
if (nKeys === node.id) {
|
|
281
485
|
parentNode.values.splice(i, 0, value);
|
|
282
486
|
parentNode.keys.splice(i + 1, 0, pointer.id);
|
|
283
|
-
this.
|
|
487
|
+
this.bufferForNodeUpdate(parentNode);
|
|
284
488
|
if (parentNode.keys.length > this.order) {
|
|
285
489
|
const parentPointer = this._createNode([], []);
|
|
286
490
|
parentPointer.parent = parentNode.parent;
|
|
@@ -297,259 +501,264 @@ var BPTree = class {
|
|
|
297
501
|
for (const k of parentNode.keys) {
|
|
298
502
|
const node2 = this.getNode(k);
|
|
299
503
|
node2.parent = parentNode.id;
|
|
300
|
-
this.
|
|
504
|
+
this.bufferForNodeUpdate(node2);
|
|
301
505
|
}
|
|
302
506
|
for (const k of parentPointer.keys) {
|
|
303
507
|
const node2 = this.getNode(k);
|
|
304
508
|
node2.parent = parentPointer.id;
|
|
305
|
-
this.
|
|
509
|
+
this.bufferForNodeUpdate(node2);
|
|
306
510
|
}
|
|
307
511
|
this._insertInParent(parentNode, midValue, parentPointer);
|
|
308
|
-
this.
|
|
309
|
-
this.
|
|
512
|
+
this.bufferForNodeCreate(parentPointer);
|
|
513
|
+
this.bufferForNodeUpdate(parentNode);
|
|
310
514
|
}
|
|
311
515
|
}
|
|
312
516
|
}
|
|
313
517
|
}
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
_getKeysFromValue(value) {
|
|
330
|
-
const keys = /* @__PURE__ */ new Set();
|
|
331
|
-
const node = this._insertableNode(value);
|
|
332
|
-
const [start, end] = this.search.range(node.values, value);
|
|
333
|
-
if (start === -1) {
|
|
334
|
-
return keys;
|
|
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);
|
|
335
533
|
}
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
for (const key of pairKeys) {
|
|
339
|
-
keys.add(key);
|
|
340
|
-
}
|
|
534
|
+
if (this.order < 3) {
|
|
535
|
+
throw new Error(`The 'order' parameter must be greater than 2. but got a '${this.order}'.`);
|
|
341
536
|
}
|
|
342
|
-
return keys;
|
|
343
537
|
}
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
let done = false;
|
|
348
|
-
while (!done) {
|
|
349
|
-
for (let i = 0, len = node.values.length; i < len; i++) {
|
|
350
|
-
const nValue = node.values[i];
|
|
351
|
-
const pairKeys = node.keys[i];
|
|
352
|
-
if (this.comparator.isSame(nValue, value) === false) {
|
|
353
|
-
for (const key of pairKeys) {
|
|
354
|
-
keys.add(key);
|
|
355
|
-
}
|
|
356
|
-
}
|
|
357
|
-
}
|
|
358
|
-
if (!node.next) {
|
|
359
|
-
done = true;
|
|
360
|
-
break;
|
|
361
|
-
}
|
|
362
|
-
node = this.getNode(node.next);
|
|
538
|
+
getNode(id) {
|
|
539
|
+
if (!this.nodes.has(id)) {
|
|
540
|
+
this.nodes.set(id, this.strategy.read(id));
|
|
363
541
|
}
|
|
364
|
-
return
|
|
542
|
+
return this.nodes.get(id);
|
|
365
543
|
}
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
let done = false;
|
|
370
|
-
let found = false;
|
|
371
|
-
while (!done) {
|
|
544
|
+
insertableNode(value) {
|
|
545
|
+
let node = this.root;
|
|
546
|
+
while (!node.leaf) {
|
|
372
547
|
for (let i = 0, len = node.values.length; i < len; i++) {
|
|
373
548
|
const nValue = node.values[i];
|
|
374
|
-
const
|
|
375
|
-
if (this.comparator.
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
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]);
|
|
382
558
|
break;
|
|
383
559
|
}
|
|
384
560
|
}
|
|
385
|
-
if (!node.next) {
|
|
386
|
-
done = true;
|
|
387
|
-
break;
|
|
388
|
-
}
|
|
389
|
-
node = this.getNode(node.next);
|
|
390
561
|
}
|
|
391
|
-
return
|
|
562
|
+
return node;
|
|
392
563
|
}
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
while (!done) {
|
|
399
|
-
for (let i = 0, len = node.values.length; i < len; i++) {
|
|
400
|
-
const nValue = node.values[i];
|
|
401
|
-
const localKeys = node.keys[i];
|
|
402
|
-
if (this.comparator.isHigher(nValue, gt)) {
|
|
403
|
-
found = true;
|
|
404
|
-
for (const key of localKeys) {
|
|
405
|
-
keys.add(key);
|
|
406
|
-
}
|
|
407
|
-
} else if (found) {
|
|
408
|
-
done = true;
|
|
409
|
-
break;
|
|
410
|
-
}
|
|
411
|
-
}
|
|
412
|
-
if (!node.next) {
|
|
413
|
-
done = true;
|
|
414
|
-
break;
|
|
415
|
-
}
|
|
416
|
-
node = this.getNode(node.next);
|
|
564
|
+
leftestNode() {
|
|
565
|
+
let node = this.root;
|
|
566
|
+
while (!node.leaf) {
|
|
567
|
+
const keys = node.keys;
|
|
568
|
+
node = this.getNode(keys[0]);
|
|
417
569
|
}
|
|
418
|
-
return
|
|
570
|
+
return node;
|
|
419
571
|
}
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
let done = false;
|
|
424
|
-
let found = false;
|
|
425
|
-
while (!done) {
|
|
426
|
-
for (let i = 0, len = node.values.length; i < len; i++) {
|
|
427
|
-
const nValue = node.values[i];
|
|
428
|
-
const localKeys = node.keys[i];
|
|
429
|
-
if (this.comparator.isLower(nValue, lt)) {
|
|
430
|
-
found = true;
|
|
431
|
-
for (const key of localKeys) {
|
|
432
|
-
keys.add(key);
|
|
433
|
-
}
|
|
434
|
-
} else if (found) {
|
|
435
|
-
done = true;
|
|
436
|
-
break;
|
|
437
|
-
}
|
|
438
|
-
}
|
|
439
|
-
if (!node.next) {
|
|
440
|
-
done = true;
|
|
441
|
-
break;
|
|
442
|
-
}
|
|
443
|
-
node = this.getNode(node.next);
|
|
572
|
+
commitHeadBuffer() {
|
|
573
|
+
if (this._headBuffer !== null) {
|
|
574
|
+
this.strategy.writeHead(this._headBuffer);
|
|
444
575
|
}
|
|
445
|
-
|
|
576
|
+
this.bufferForHeadUpdate(null);
|
|
446
577
|
}
|
|
447
|
-
|
|
448
|
-
const node
|
|
449
|
-
|
|
450
|
-
if (start === -1) {
|
|
451
|
-
return [];
|
|
578
|
+
commitNodeCreateBuffer() {
|
|
579
|
+
for (const node of this._nodeCreateBuffer.values()) {
|
|
580
|
+
this.strategy.write(node.id, node);
|
|
452
581
|
}
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
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));
|
|
458
604
|
}
|
|
459
605
|
}
|
|
460
|
-
return
|
|
606
|
+
return new Set(result ?? []);
|
|
461
607
|
}
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
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));
|
|
475
622
|
}
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
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);
|
|
479
649
|
}
|
|
480
|
-
|
|
650
|
+
this._insertInParent(before, after.values[0], after);
|
|
651
|
+
this.bufferForNodeCreate(after);
|
|
652
|
+
this.bufferForNodeUpdate(before);
|
|
481
653
|
}
|
|
482
|
-
|
|
654
|
+
this.commitHeadBuffer();
|
|
655
|
+
this.commitNodeCreateBuffer();
|
|
656
|
+
this.commitNodeUpdateBuffer();
|
|
483
657
|
}
|
|
484
|
-
|
|
485
|
-
const
|
|
486
|
-
let
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
for (let i = 0, len = node.values.length; i < len; i++) {
|
|
491
|
-
const nValue = node.values[i];
|
|
658
|
+
delete(key, value) {
|
|
659
|
+
const node = this.insertableNode(value);
|
|
660
|
+
let i = node.values.length;
|
|
661
|
+
while (i--) {
|
|
662
|
+
const nValue = node.values[i];
|
|
663
|
+
if (this.comparator.isSame(value, nValue)) {
|
|
492
664
|
const keys = node.keys[i];
|
|
493
|
-
if (
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
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);
|
|
497
679
|
}
|
|
498
|
-
} else if (found) {
|
|
499
|
-
done = true;
|
|
500
|
-
break;
|
|
501
680
|
}
|
|
502
681
|
}
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
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);
|
|
506
694
|
}
|
|
507
|
-
node = this.getNode(node.next);
|
|
508
695
|
}
|
|
509
|
-
return
|
|
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);
|
|
510
717
|
}
|
|
511
|
-
|
|
718
|
+
async _getPairsRightToLeft(value, startNode, fullSearch, comparator) {
|
|
512
719
|
const pairs = [];
|
|
513
|
-
let node =
|
|
720
|
+
let node = startNode;
|
|
514
721
|
let done = false;
|
|
515
722
|
let found = false;
|
|
516
723
|
while (!done) {
|
|
517
|
-
|
|
724
|
+
let i = node.values.length;
|
|
725
|
+
while (i--) {
|
|
518
726
|
const nValue = node.values[i];
|
|
519
727
|
const keys = node.keys[i];
|
|
520
|
-
if (
|
|
728
|
+
if (comparator(nValue, value)) {
|
|
521
729
|
found = true;
|
|
522
|
-
|
|
523
|
-
|
|
730
|
+
let j = keys.length;
|
|
731
|
+
while (j--) {
|
|
732
|
+
pairs.push({ key: keys[j], value: nValue });
|
|
524
733
|
}
|
|
525
|
-
} else if (found) {
|
|
734
|
+
} else if (found && !fullSearch) {
|
|
526
735
|
done = true;
|
|
527
736
|
break;
|
|
528
737
|
}
|
|
529
738
|
}
|
|
530
|
-
if (!node.
|
|
739
|
+
if (!node.prev) {
|
|
531
740
|
done = true;
|
|
532
741
|
break;
|
|
533
742
|
}
|
|
534
|
-
node = this.getNode(node.
|
|
743
|
+
node = await this.getNode(node.prev);
|
|
535
744
|
}
|
|
536
|
-
return pairs;
|
|
745
|
+
return pairs.reverse();
|
|
537
746
|
}
|
|
538
|
-
|
|
747
|
+
async _getPairsLeftToRight(value, startNode, fullSearch, comparator) {
|
|
539
748
|
const pairs = [];
|
|
540
|
-
let node =
|
|
749
|
+
let node = startNode;
|
|
541
750
|
let done = false;
|
|
542
751
|
let found = false;
|
|
543
752
|
while (!done) {
|
|
544
753
|
for (let i = 0, len = node.values.length; i < len; i++) {
|
|
545
754
|
const nValue = node.values[i];
|
|
546
755
|
const keys = node.keys[i];
|
|
547
|
-
if (
|
|
756
|
+
if (comparator(nValue, value)) {
|
|
548
757
|
found = true;
|
|
549
758
|
for (const key of keys) {
|
|
550
759
|
pairs.push({ key, value: nValue });
|
|
551
760
|
}
|
|
552
|
-
} else if (found) {
|
|
761
|
+
} else if (found && !fullSearch) {
|
|
553
762
|
done = true;
|
|
554
763
|
break;
|
|
555
764
|
}
|
|
@@ -558,125 +767,48 @@ var BPTree = class {
|
|
|
558
767
|
done = true;
|
|
559
768
|
break;
|
|
560
769
|
}
|
|
561
|
-
node = this.getNode(node.next);
|
|
770
|
+
node = await this.getNode(node.next);
|
|
562
771
|
}
|
|
563
772
|
return pairs;
|
|
564
773
|
}
|
|
565
|
-
|
|
566
|
-
|
|
567
|
-
|
|
568
|
-
|
|
569
|
-
|
|
570
|
-
|
|
571
|
-
|
|
572
|
-
|
|
573
|
-
return this._getKeysFromValue(condition.equal);
|
|
574
|
-
} else if (this._notEqualCondition(condition)) {
|
|
575
|
-
return this._getKeysFromNEValue(condition.notEqual);
|
|
576
|
-
} else if (this._rangeCondition(condition)) {
|
|
577
|
-
const { gt, lt } = condition;
|
|
578
|
-
return this._getKeysFromRange(gt, lt);
|
|
579
|
-
} else if (this._onlyGtCondition(condition)) {
|
|
580
|
-
return this._getKeysFromGt(condition.gt);
|
|
581
|
-
} else if (this._onlyLtCondition(condition)) {
|
|
582
|
-
return this._getKeysFromLt(condition.lt);
|
|
583
|
-
} else {
|
|
584
|
-
throw new Error(`The 'condition' parameter is invalid.`);
|
|
585
|
-
}
|
|
586
|
-
}
|
|
587
|
-
/**
|
|
588
|
-
* It searches for a value within the tree. The result is returned as an array sorted in ascending order based on the value.
|
|
589
|
-
* The result includes the key and value attributes, and you can use the `gt`, `lt`, `equal`, `notEqual` condition statements.
|
|
590
|
-
* @param condition You can use the `gt`, `lt`, `equal`, `notEqual` condition statements.
|
|
591
|
-
*/
|
|
592
|
-
where(condition) {
|
|
593
|
-
if (this._equalCondition(condition)) {
|
|
594
|
-
return this._getPairsFromValue(condition.equal);
|
|
595
|
-
} else if (this._notEqualCondition(condition)) {
|
|
596
|
-
return this._getPairsFromNEValue(condition.notEqual);
|
|
597
|
-
} else if (this._rangeCondition(condition)) {
|
|
598
|
-
const { gt, lt } = condition;
|
|
599
|
-
return this._getPairsFromRange(gt, lt);
|
|
600
|
-
} else if (this._onlyGtCondition(condition)) {
|
|
601
|
-
return this._getPairsFromGt(condition.gt);
|
|
602
|
-
} else if (this._onlyLtCondition(condition)) {
|
|
603
|
-
return this._getPairsFromLt(condition.lt);
|
|
604
|
-
} else {
|
|
605
|
-
throw new Error(`The 'condition' parameter is invalid.`);
|
|
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}`);
|
|
606
782
|
}
|
|
607
783
|
}
|
|
608
|
-
|
|
609
|
-
|
|
610
|
-
|
|
611
|
-
|
|
612
|
-
* @param value The value of the pair.
|
|
613
|
-
*/
|
|
614
|
-
insert(key, value) {
|
|
615
|
-
const before = this._insertableNode(value);
|
|
616
|
-
this._insertAtLeaf(before, key, value);
|
|
617
|
-
if (before.values.length === this.order) {
|
|
618
|
-
const after = this._createNode(
|
|
619
|
-
[],
|
|
620
|
-
[],
|
|
621
|
-
true,
|
|
622
|
-
before.parent,
|
|
623
|
-
before.next
|
|
624
|
-
);
|
|
625
|
-
const mid = Math.ceil(this.order / 2) - 1;
|
|
626
|
-
after.values = before.values.slice(mid + 1);
|
|
627
|
-
after.keys = before.keys.slice(mid + 1);
|
|
628
|
-
before.values = before.values.slice(0, mid + 1);
|
|
629
|
-
before.keys = before.keys.slice(0, mid + 1);
|
|
630
|
-
before.next = after.id;
|
|
631
|
-
this._insertInParent(before, after.values[0], after);
|
|
632
|
-
this._setCreates(after);
|
|
633
|
-
this._setUpdates(before);
|
|
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.`);
|
|
634
788
|
}
|
|
635
|
-
|
|
636
|
-
this._emitCreates();
|
|
637
|
-
this._emitUpdates();
|
|
789
|
+
return id;
|
|
638
790
|
}
|
|
639
|
-
|
|
640
|
-
|
|
641
|
-
|
|
642
|
-
|
|
643
|
-
|
|
644
|
-
|
|
645
|
-
|
|
646
|
-
|
|
647
|
-
|
|
648
|
-
|
|
649
|
-
|
|
650
|
-
|
|
651
|
-
|
|
652
|
-
if (keys.length > 1) {
|
|
653
|
-
keys.splice(keys.indexOf(key), 1);
|
|
654
|
-
this._setUpdates(node);
|
|
655
|
-
} else if (node === this.root) {
|
|
656
|
-
node.values.splice(i, 1);
|
|
657
|
-
node.keys.splice(i, 1);
|
|
658
|
-
this._setUpdates(node);
|
|
659
|
-
} else {
|
|
660
|
-
keys.splice(keys.indexOf(key), 1);
|
|
661
|
-
node.keys.splice(i, 1);
|
|
662
|
-
node.values.splice(node.values.indexOf(value), 1);
|
|
663
|
-
this._deleteEntry(node, key, value);
|
|
664
|
-
this._setUpdates(node);
|
|
665
|
-
}
|
|
666
|
-
}
|
|
667
|
-
}
|
|
668
|
-
}
|
|
669
|
-
this._emitHeadUpdates();
|
|
670
|
-
this._emitCreates();
|
|
671
|
-
this._emitUpdates();
|
|
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;
|
|
672
804
|
}
|
|
673
|
-
_deleteEntry(node, key, value) {
|
|
805
|
+
async _deleteEntry(node, key, value) {
|
|
674
806
|
if (!node.leaf) {
|
|
675
807
|
for (let i = 0, len = node.keys.length; i < len; i++) {
|
|
676
808
|
const nKey = node.keys[i];
|
|
677
809
|
if (nKey === key) {
|
|
678
810
|
node.keys.splice(i, 1);
|
|
679
|
-
this.
|
|
811
|
+
this.bufferForNodeUpdate(node);
|
|
680
812
|
break;
|
|
681
813
|
}
|
|
682
814
|
}
|
|
@@ -684,37 +816,37 @@ var BPTree = class {
|
|
|
684
816
|
const nValue = node.values[i];
|
|
685
817
|
if (this.comparator.isSame(value, nValue)) {
|
|
686
818
|
node.values.splice(i, 1);
|
|
687
|
-
this.
|
|
819
|
+
this.bufferForNodeUpdate(node);
|
|
688
820
|
break;
|
|
689
821
|
}
|
|
690
822
|
}
|
|
691
823
|
}
|
|
692
824
|
if (this.root === node && node.keys.length === 1) {
|
|
693
825
|
const keys = node.keys;
|
|
694
|
-
this.root = this.getNode(keys[0]);
|
|
826
|
+
this.root = await this.getNode(keys[0]);
|
|
695
827
|
this.root.parent = 0;
|
|
696
|
-
this.
|
|
697
|
-
this.
|
|
828
|
+
this.bufferForHeadUpdate(this.headState);
|
|
829
|
+
this.bufferForNodeUpdate(this.root);
|
|
698
830
|
return;
|
|
699
831
|
} else if (this.root === node) {
|
|
700
832
|
return;
|
|
701
833
|
} else if (node.keys.length < Math.ceil(this.order / 2) && !node.leaf || node.values.length < Math.ceil((this.order - 1) / 2) && node.leaf) {
|
|
702
834
|
let isPredecessor = false;
|
|
703
|
-
let parentNode = this.getNode(node.parent);
|
|
835
|
+
let parentNode = await this.getNode(node.parent);
|
|
704
836
|
let prevNode = null;
|
|
705
837
|
let nextNode = null;
|
|
706
|
-
let
|
|
707
|
-
let
|
|
838
|
+
let prevValue = null;
|
|
839
|
+
let postValue = null;
|
|
708
840
|
for (let i = 0, len = parentNode.keys.length; i < len; i++) {
|
|
709
841
|
const nKey = parentNode.keys[i];
|
|
710
842
|
if (nKey === node.id) {
|
|
711
843
|
if (i > 0) {
|
|
712
|
-
prevNode = this.getNode(parentNode.keys[i - 1]);
|
|
713
|
-
|
|
844
|
+
prevNode = await this.getNode(parentNode.keys[i - 1]);
|
|
845
|
+
prevValue = parentNode.values[i - 1];
|
|
714
846
|
}
|
|
715
847
|
if (i < parentNode.keys.length - 1) {
|
|
716
|
-
nextNode = this.getNode(parentNode.keys[i + 1]);
|
|
717
|
-
|
|
848
|
+
nextNode = await this.getNode(parentNode.keys[i + 1]);
|
|
849
|
+
postValue = parentNode.values[i];
|
|
718
850
|
}
|
|
719
851
|
}
|
|
720
852
|
}
|
|
@@ -722,19 +854,19 @@ var BPTree = class {
|
|
|
722
854
|
let guess;
|
|
723
855
|
if (prevNode === null) {
|
|
724
856
|
pointer = nextNode;
|
|
725
|
-
guess =
|
|
857
|
+
guess = postValue;
|
|
726
858
|
} else if (nextNode === null) {
|
|
727
859
|
isPredecessor = true;
|
|
728
860
|
pointer = prevNode;
|
|
729
|
-
guess =
|
|
861
|
+
guess = prevValue;
|
|
730
862
|
} else {
|
|
731
863
|
if (node.values.length + nextNode.values.length < this.order) {
|
|
732
864
|
pointer = nextNode;
|
|
733
|
-
guess =
|
|
865
|
+
guess = postValue;
|
|
734
866
|
} else {
|
|
735
867
|
isPredecessor = true;
|
|
736
868
|
pointer = prevNode;
|
|
737
|
-
guess =
|
|
869
|
+
guess = prevValue;
|
|
738
870
|
}
|
|
739
871
|
}
|
|
740
872
|
if (node.values.length + pointer.values.length < this.order) {
|
|
@@ -748,18 +880,32 @@ var BPTree = class {
|
|
|
748
880
|
pointer.values.push(guess);
|
|
749
881
|
} else {
|
|
750
882
|
pointer.next = node.next;
|
|
883
|
+
pointer.prev = node.id;
|
|
884
|
+
if (pointer.next) {
|
|
885
|
+
const n = await this.getNode(node.next);
|
|
886
|
+
n.prev = pointer.id;
|
|
887
|
+
this.bufferForNodeUpdate(n);
|
|
888
|
+
}
|
|
889
|
+
if (pointer.prev) {
|
|
890
|
+
const n = await this.getNode(node.id);
|
|
891
|
+
n.next = pointer.id;
|
|
892
|
+
this.bufferForNodeUpdate(n);
|
|
893
|
+
}
|
|
894
|
+
if (isPredecessor) {
|
|
895
|
+
pointer.prev = 0;
|
|
896
|
+
}
|
|
751
897
|
}
|
|
752
898
|
pointer.values.push(...node.values);
|
|
753
899
|
if (!pointer.leaf) {
|
|
754
900
|
const keys = pointer.keys;
|
|
755
901
|
for (const key2 of keys) {
|
|
756
|
-
const node2 = this.getNode(key2);
|
|
902
|
+
const node2 = await this.getNode(key2);
|
|
757
903
|
node2.parent = pointer.id;
|
|
758
|
-
this.
|
|
904
|
+
this.bufferForNodeUpdate(node2);
|
|
759
905
|
}
|
|
760
906
|
}
|
|
761
|
-
this._deleteEntry(this.getNode(node.parent), node.id, guess);
|
|
762
|
-
this.
|
|
907
|
+
await this._deleteEntry(await this.getNode(node.parent), node.id, guess);
|
|
908
|
+
this.bufferForNodeUpdate(pointer);
|
|
763
909
|
} else {
|
|
764
910
|
if (isPredecessor) {
|
|
765
911
|
let pointerPm;
|
|
@@ -769,12 +915,12 @@ var BPTree = class {
|
|
|
769
915
|
pointerKm = pointer.values.splice(-1)[0];
|
|
770
916
|
node.keys = [pointerPm, ...node.keys];
|
|
771
917
|
node.values = [guess, ...node.values];
|
|
772
|
-
parentNode = this.getNode(node.parent);
|
|
918
|
+
parentNode = await this.getNode(node.parent);
|
|
773
919
|
for (let i = 0, len = parentNode.values.length; i < len; i++) {
|
|
774
920
|
const nValue = parentNode.values[i];
|
|
775
921
|
if (this.comparator.isSame(guess, nValue)) {
|
|
776
922
|
parentNode.values[i] = pointerKm;
|
|
777
|
-
this.
|
|
923
|
+
this.bufferForNodeUpdate(parentNode);
|
|
778
924
|
break;
|
|
779
925
|
}
|
|
780
926
|
}
|
|
@@ -783,18 +929,18 @@ var BPTree = class {
|
|
|
783
929
|
pointerKm = pointer.values.splice(-1)[0];
|
|
784
930
|
node.keys = [pointerPm, ...node.keys];
|
|
785
931
|
node.values = [pointerKm, ...node.values];
|
|
786
|
-
parentNode = this.getNode(node.parent);
|
|
932
|
+
parentNode = await this.getNode(node.parent);
|
|
787
933
|
for (let i = 0, len = parentNode.values.length; i < len; i++) {
|
|
788
934
|
const nValue = parentNode.values[i];
|
|
789
935
|
if (this.comparator.isSame(guess, nValue)) {
|
|
790
936
|
parentNode.values[i] = pointerKm;
|
|
791
|
-
this.
|
|
937
|
+
this.bufferForNodeUpdate(parentNode);
|
|
792
938
|
break;
|
|
793
939
|
}
|
|
794
940
|
}
|
|
795
941
|
}
|
|
796
|
-
this.
|
|
797
|
-
this.
|
|
942
|
+
this.bufferForNodeUpdate(node);
|
|
943
|
+
this.bufferForNodeUpdate(pointer);
|
|
798
944
|
} else {
|
|
799
945
|
let pointerP0;
|
|
800
946
|
let pointerK0;
|
|
@@ -803,12 +949,12 @@ var BPTree = class {
|
|
|
803
949
|
pointerK0 = pointer.values.splice(0, 1)[0];
|
|
804
950
|
node.keys = [...node.keys, pointerP0];
|
|
805
951
|
node.values = [...node.values, guess];
|
|
806
|
-
parentNode = this.getNode(node.parent);
|
|
952
|
+
parentNode = await this.getNode(node.parent);
|
|
807
953
|
for (let i = 0, len = parentNode.values.length; i < len; i++) {
|
|
808
954
|
const nValue = parentNode.values[i];
|
|
809
955
|
if (this.comparator.isSame(guess, nValue)) {
|
|
810
956
|
parentNode.values[i] = pointerK0;
|
|
811
|
-
this.
|
|
957
|
+
this.bufferForNodeUpdate(parentNode);
|
|
812
958
|
break;
|
|
813
959
|
}
|
|
814
960
|
}
|
|
@@ -817,72 +963,299 @@ var BPTree = class {
|
|
|
817
963
|
pointerK0 = pointer.values.splice(0, 1)[0];
|
|
818
964
|
node.keys = [...node.keys, pointerP0];
|
|
819
965
|
node.values = [...node.values, pointerK0];
|
|
820
|
-
parentNode = this.getNode(node.parent);
|
|
966
|
+
parentNode = await this.getNode(node.parent);
|
|
821
967
|
for (let i = 0, len = parentNode.values.length; i < len; i++) {
|
|
822
968
|
const nValue = parentNode.values[i];
|
|
823
969
|
if (this.comparator.isSame(guess, nValue)) {
|
|
824
970
|
parentNode.values[i] = pointer.values[0];
|
|
825
|
-
this.
|
|
971
|
+
this.bufferForNodeUpdate(parentNode);
|
|
826
972
|
break;
|
|
827
973
|
}
|
|
828
974
|
}
|
|
829
975
|
}
|
|
830
|
-
this.
|
|
831
|
-
this.
|
|
976
|
+
this.bufferForNodeUpdate(node);
|
|
977
|
+
this.bufferForNodeUpdate(pointer);
|
|
832
978
|
}
|
|
833
979
|
if (!pointer.leaf) {
|
|
834
980
|
for (const key2 of pointer.keys) {
|
|
835
|
-
const n = this.getNode(key2);
|
|
981
|
+
const n = await this.getNode(key2);
|
|
836
982
|
n.parent = pointer.id;
|
|
837
|
-
this.
|
|
983
|
+
this.bufferForNodeUpdate(n);
|
|
838
984
|
}
|
|
839
985
|
}
|
|
840
986
|
if (!node.leaf) {
|
|
841
987
|
for (const key2 of node.keys) {
|
|
842
|
-
const n = this.getNode(key2);
|
|
988
|
+
const n = await this.getNode(key2);
|
|
843
989
|
n.parent = node.id;
|
|
844
|
-
this.
|
|
990
|
+
this.bufferForNodeUpdate(n);
|
|
845
991
|
}
|
|
846
992
|
}
|
|
847
993
|
if (!parentNode.leaf) {
|
|
848
994
|
for (const key2 of parentNode.keys) {
|
|
849
|
-
const n = this.getNode(key2);
|
|
995
|
+
const n = await this.getNode(key2);
|
|
850
996
|
n.parent = parentNode.id;
|
|
851
|
-
this.
|
|
997
|
+
this.bufferForNodeUpdate(n);
|
|
852
998
|
}
|
|
853
999
|
}
|
|
854
1000
|
}
|
|
855
1001
|
}
|
|
856
1002
|
}
|
|
857
|
-
|
|
858
|
-
|
|
859
|
-
|
|
860
|
-
|
|
861
|
-
|
|
862
|
-
|
|
863
|
-
|
|
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
|
+
}
|
|
864
1051
|
}
|
|
865
|
-
|
|
866
|
-
|
|
867
|
-
|
|
868
|
-
|
|
869
|
-
|
|
870
|
-
|
|
871
|
-
|
|
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) {
|
|
872
1233
|
this.data = data;
|
|
873
|
-
this.
|
|
874
|
-
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;
|
|
875
1244
|
}
|
|
876
1245
|
};
|
|
877
1246
|
|
|
878
|
-
// src/SerializeStrategy.ts
|
|
1247
|
+
// src/base/SerializeStrategy.ts
|
|
879
1248
|
var SerializeStrategy = class {
|
|
880
1249
|
order;
|
|
881
1250
|
constructor(order) {
|
|
882
1251
|
this.order = order;
|
|
883
1252
|
}
|
|
884
1253
|
};
|
|
885
|
-
|
|
1254
|
+
|
|
1255
|
+
// src/SerializeStrategySync.ts
|
|
1256
|
+
var SerializeStrategySync = class extends SerializeStrategy {
|
|
1257
|
+
};
|
|
1258
|
+
var InMemoryStoreStrategySync = class extends SerializeStrategySync {
|
|
886
1259
|
data;
|
|
887
1260
|
constructor(order) {
|
|
888
1261
|
super(order);
|
|
@@ -911,6 +1284,38 @@ var InMemoryStoreStrategy = class extends SerializeStrategy {
|
|
|
911
1284
|
}
|
|
912
1285
|
};
|
|
913
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
|
+
|
|
914
1319
|
// src/ValueComparator.ts
|
|
915
1320
|
var ValueComparator = class {
|
|
916
1321
|
isLower(value, than) {
|