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