serializable-bptree 3.1.0 → 3.2.1
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 +21 -5
- package/dist/cjs/index.js +75 -63
- package/dist/esm/index.js +75 -63
- package/dist/typings/BPTreeAsync.d.ts +2 -2
- package/dist/typings/BPTreeSync.d.ts +2 -2
- package/dist/typings/SerializeStrategyAsync.d.ts +5 -4
- package/dist/typings/SerializeStrategySync.d.ts +5 -4
- package/dist/typings/base/BPTree.d.ts +3 -8
- package/dist/typings/base/SerializeStrategy.d.ts +27 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -15,8 +15,7 @@ import {
|
|
|
15
15
|
|
|
16
16
|
class FileStoreStrategySync extends SerializeStrategySync<K, V> {
|
|
17
17
|
id(): number {
|
|
18
|
-
|
|
19
|
-
return random
|
|
18
|
+
return this.autoIncrement('index', 1)
|
|
20
19
|
}
|
|
21
20
|
|
|
22
21
|
read(id: number): BPTreeNode<K, V> {
|
|
@@ -202,7 +201,25 @@ id(): number {
|
|
|
202
201
|
|
|
203
202
|
Or, you could use file input/output to save and load the value of the **before** variable.
|
|
204
203
|
|
|
205
|
-
|
|
204
|
+
Typically, such an **id** value increases sequentially, and it would be beneficial to store such a value separately within the tree. For that purpose, the **setHeadData** and **getHeadData** methods are available. These methods are responsible for storing arbitrary data in the tree's header or retrieving stored data. Below is an example of usage:
|
|
205
|
+
|
|
206
|
+
```typescript
|
|
207
|
+
id(): number {
|
|
208
|
+
const current = this.getHeadData('index', 1) as number
|
|
209
|
+
this.setHeadData('index', current+1)
|
|
210
|
+
return current
|
|
211
|
+
}
|
|
212
|
+
```
|
|
213
|
+
|
|
214
|
+
Additionally, there is a more user-friendly usage of this code.
|
|
215
|
+
|
|
216
|
+
```typescript
|
|
217
|
+
id(): number {
|
|
218
|
+
return this.autoIncrement('index', 1)
|
|
219
|
+
}
|
|
220
|
+
```
|
|
221
|
+
|
|
222
|
+
The **id** method is called before a node is created in the tree. Therefore, it can also be used to allocate space for storing the node.
|
|
206
223
|
|
|
207
224
|
#### read(id: `number`): `BPTreeNode<K, V>`
|
|
208
225
|
|
|
@@ -350,8 +367,7 @@ import {
|
|
|
350
367
|
|
|
351
368
|
class FileStoreStrategyAsync extends SerializeStrategyAsync<K, V> {
|
|
352
369
|
async id(): Promise<number> {
|
|
353
|
-
|
|
354
|
-
return random
|
|
370
|
+
return await this.autoIncrement('index', 1)
|
|
355
371
|
}
|
|
356
372
|
|
|
357
373
|
async read(id: number): Promise<BPTreeNode<K, V>> {
|
package/dist/cjs/index.js
CHANGED
|
@@ -78,11 +78,9 @@ var BPTree = class {
|
|
|
78
78
|
comparator;
|
|
79
79
|
nodes;
|
|
80
80
|
order;
|
|
81
|
-
data;
|
|
82
81
|
root;
|
|
83
82
|
_nodeCreateBuffer;
|
|
84
83
|
_nodeUpdateBuffer;
|
|
85
|
-
_headBuffer;
|
|
86
84
|
verifierMap = {
|
|
87
85
|
gt: (nv, v) => this.comparator.isHigher(nv, v),
|
|
88
86
|
gte: (nv, v) => this.comparator.isHigher(nv, v) || this.comparator.isSame(nv, v),
|
|
@@ -127,19 +125,8 @@ var BPTree = class {
|
|
|
127
125
|
notEqual: true,
|
|
128
126
|
like: true
|
|
129
127
|
};
|
|
130
|
-
get headState() {
|
|
131
|
-
const root = this.root.id;
|
|
132
|
-
const order = this.order;
|
|
133
|
-
const data = this.data;
|
|
134
|
-
return {
|
|
135
|
-
root,
|
|
136
|
-
order,
|
|
137
|
-
data
|
|
138
|
-
};
|
|
139
|
-
}
|
|
140
128
|
constructor(strategy, comparator) {
|
|
141
129
|
this._regexpCache = new CacheStorage();
|
|
142
|
-
this._headBuffer = null;
|
|
143
130
|
this._nodeCreateBuffer = /* @__PURE__ */ new Map();
|
|
144
131
|
this._nodeUpdateBuffer = /* @__PURE__ */ new Map();
|
|
145
132
|
this.nodes = /* @__PURE__ */ new Map();
|
|
@@ -173,9 +160,6 @@ var BPTree = class {
|
|
|
173
160
|
this.bufferForNodeUpdate(node);
|
|
174
161
|
}
|
|
175
162
|
}
|
|
176
|
-
bufferForHeadUpdate(head) {
|
|
177
|
-
this._headBuffer = head;
|
|
178
|
-
}
|
|
179
163
|
bufferForNodeCreate(node) {
|
|
180
164
|
this._nodeCreateBuffer.set(node.id, node);
|
|
181
165
|
}
|
|
@@ -188,7 +172,7 @@ var BPTree = class {
|
|
|
188
172
|
* @returns User-defined data stored in the head of the tree.
|
|
189
173
|
*/
|
|
190
174
|
getHeadData() {
|
|
191
|
-
return this.data;
|
|
175
|
+
return this.strategy.head.data;
|
|
192
176
|
}
|
|
193
177
|
};
|
|
194
178
|
|
|
@@ -307,7 +291,7 @@ var BPTreeSync = class extends BPTree {
|
|
|
307
291
|
const keys = node.keys;
|
|
308
292
|
this.root = this.getNode(keys[0]);
|
|
309
293
|
this.root.parent = 0;
|
|
310
|
-
this.
|
|
294
|
+
this.strategy.head.root = this.root.id;
|
|
311
295
|
this.bufferForNodeUpdate(this.root);
|
|
312
296
|
return;
|
|
313
297
|
} else if (this.root === node) {
|
|
@@ -513,9 +497,9 @@ var BPTreeSync = class extends BPTree {
|
|
|
513
497
|
if (this.root === node) {
|
|
514
498
|
const root = this._createNode([node.id, pointer.id], [value]);
|
|
515
499
|
this.root = root;
|
|
500
|
+
this.strategy.head.root = root.id;
|
|
516
501
|
node.parent = root.id;
|
|
517
502
|
pointer.parent = root.id;
|
|
518
|
-
this.bufferForHeadUpdate(this.headState);
|
|
519
503
|
this.bufferForNodeCreate(root);
|
|
520
504
|
this.bufferForNodeUpdate(node);
|
|
521
505
|
this.bufferForNodeUpdate(pointer);
|
|
@@ -562,16 +546,15 @@ var BPTreeSync = class extends BPTree {
|
|
|
562
546
|
const head = this.strategy.readHead();
|
|
563
547
|
if (head === null) {
|
|
564
548
|
this.order = this.strategy.order;
|
|
565
|
-
this.data = {};
|
|
566
549
|
this.root = this._createNode([], [], true);
|
|
567
|
-
this.
|
|
550
|
+
this.strategy.head.root = this.root.id;
|
|
568
551
|
this.bufferForNodeCreate(this.root);
|
|
569
552
|
this.commitHeadBuffer();
|
|
570
553
|
this.commitNodeCreateBuffer();
|
|
571
554
|
} else {
|
|
572
|
-
const { root, order
|
|
555
|
+
const { root, order } = head;
|
|
556
|
+
this.strategy.head = head;
|
|
573
557
|
this.order = order;
|
|
574
|
-
this.data = data ?? {};
|
|
575
558
|
this.root = this.getNode(root);
|
|
576
559
|
}
|
|
577
560
|
if (this.order < 3) {
|
|
@@ -613,10 +596,7 @@ var BPTreeSync = class extends BPTree {
|
|
|
613
596
|
return node;
|
|
614
597
|
}
|
|
615
598
|
commitHeadBuffer() {
|
|
616
|
-
|
|
617
|
-
this.strategy.writeHead(this._headBuffer);
|
|
618
|
-
}
|
|
619
|
-
this.bufferForHeadUpdate(null);
|
|
599
|
+
this.strategy.writeHead(this.strategy.head);
|
|
620
600
|
}
|
|
621
601
|
commitNodeCreateBuffer() {
|
|
622
602
|
for (const node of this._nodeCreateBuffer.values()) {
|
|
@@ -739,8 +719,7 @@ var BPTreeSync = class extends BPTree {
|
|
|
739
719
|
return false;
|
|
740
720
|
}
|
|
741
721
|
setHeadData(data) {
|
|
742
|
-
this.data = data;
|
|
743
|
-
this.bufferForHeadUpdate(this.headState);
|
|
722
|
+
this.strategy.head.data = data;
|
|
744
723
|
this.commitHeadBuffer();
|
|
745
724
|
}
|
|
746
725
|
forceUpdate() {
|
|
@@ -869,7 +848,7 @@ var BPTreeAsync = class extends BPTree {
|
|
|
869
848
|
const keys = node.keys;
|
|
870
849
|
this.root = await this.getNode(keys[0]);
|
|
871
850
|
this.root.parent = 0;
|
|
872
|
-
this.
|
|
851
|
+
this.strategy.head.root = this.root.id;
|
|
873
852
|
this.bufferForNodeUpdate(this.root);
|
|
874
853
|
return;
|
|
875
854
|
} else if (this.root === node) {
|
|
@@ -1048,9 +1027,9 @@ var BPTreeAsync = class extends BPTree {
|
|
|
1048
1027
|
if (this.root === node) {
|
|
1049
1028
|
const root = await this._createNode([node.id, pointer.id], [value]);
|
|
1050
1029
|
this.root = root;
|
|
1030
|
+
this.strategy.head.root = root.id;
|
|
1051
1031
|
node.parent = root.id;
|
|
1052
1032
|
pointer.parent = root.id;
|
|
1053
|
-
this.bufferForHeadUpdate(this.headState);
|
|
1054
1033
|
this.bufferForNodeCreate(root);
|
|
1055
1034
|
this.bufferForNodeUpdate(node);
|
|
1056
1035
|
this.bufferForNodeUpdate(pointer);
|
|
@@ -1097,16 +1076,15 @@ var BPTreeAsync = class extends BPTree {
|
|
|
1097
1076
|
const head = await this.strategy.readHead();
|
|
1098
1077
|
if (head === null) {
|
|
1099
1078
|
this.order = this.strategy.order;
|
|
1100
|
-
this.data = {};
|
|
1101
1079
|
this.root = await this._createNode([], [], true);
|
|
1102
|
-
this.
|
|
1080
|
+
this.strategy.head.root = this.root.id;
|
|
1103
1081
|
this.bufferForNodeCreate(this.root);
|
|
1104
1082
|
this.commitHeadBuffer();
|
|
1105
1083
|
this.commitNodeCreateBuffer();
|
|
1106
1084
|
} else {
|
|
1107
|
-
const { root, order
|
|
1085
|
+
const { root, order } = head;
|
|
1086
|
+
this.strategy.head = head;
|
|
1108
1087
|
this.order = order;
|
|
1109
|
-
this.data = data ?? {};
|
|
1110
1088
|
this.root = await this.getNode(root);
|
|
1111
1089
|
}
|
|
1112
1090
|
if (this.order < 3) {
|
|
@@ -1148,10 +1126,7 @@ var BPTreeAsync = class extends BPTree {
|
|
|
1148
1126
|
return node;
|
|
1149
1127
|
}
|
|
1150
1128
|
async commitHeadBuffer() {
|
|
1151
|
-
|
|
1152
|
-
await this.strategy.writeHead(this._headBuffer);
|
|
1153
|
-
}
|
|
1154
|
-
this.bufferForHeadUpdate(null);
|
|
1129
|
+
await this.strategy.writeHead(this.strategy.head);
|
|
1155
1130
|
}
|
|
1156
1131
|
async commitNodeCreateBuffer() {
|
|
1157
1132
|
for (const node of this._nodeCreateBuffer.values()) {
|
|
@@ -1274,8 +1249,7 @@ var BPTreeAsync = class extends BPTree {
|
|
|
1274
1249
|
return false;
|
|
1275
1250
|
}
|
|
1276
1251
|
async setHeadData(data) {
|
|
1277
|
-
this.data = data;
|
|
1278
|
-
this.bufferForHeadUpdate(this.headState);
|
|
1252
|
+
this.strategy.head.data = data;
|
|
1279
1253
|
await this.commitHeadBuffer();
|
|
1280
1254
|
}
|
|
1281
1255
|
async forceUpdate() {
|
|
@@ -1292,71 +1266,109 @@ var BPTreeAsync = class extends BPTree {
|
|
|
1292
1266
|
// src/base/SerializeStrategy.ts
|
|
1293
1267
|
var SerializeStrategy = class {
|
|
1294
1268
|
order;
|
|
1269
|
+
head;
|
|
1295
1270
|
constructor(order) {
|
|
1296
1271
|
this.order = order;
|
|
1272
|
+
this.head = {
|
|
1273
|
+
order,
|
|
1274
|
+
root: 0,
|
|
1275
|
+
data: {}
|
|
1276
|
+
};
|
|
1297
1277
|
}
|
|
1298
1278
|
};
|
|
1299
1279
|
|
|
1300
1280
|
// src/SerializeStrategySync.ts
|
|
1301
1281
|
var SerializeStrategySync = class extends SerializeStrategy {
|
|
1282
|
+
getHeadData(key, defaultValue) {
|
|
1283
|
+
if (!Object.hasOwn(this.head.data, key)) {
|
|
1284
|
+
return defaultValue;
|
|
1285
|
+
}
|
|
1286
|
+
return this.head.data[key];
|
|
1287
|
+
}
|
|
1288
|
+
setHeadData(key, data) {
|
|
1289
|
+
this.head.data[key] = data;
|
|
1290
|
+
this.writeHead(this.head);
|
|
1291
|
+
}
|
|
1292
|
+
autoIncrement(key, defaultValue) {
|
|
1293
|
+
const current = this.getHeadData(key, defaultValue);
|
|
1294
|
+
const next = current + 1;
|
|
1295
|
+
this.setHeadData(key, next);
|
|
1296
|
+
return current;
|
|
1297
|
+
}
|
|
1302
1298
|
};
|
|
1303
1299
|
var InMemoryStoreStrategySync = class extends SerializeStrategySync {
|
|
1304
|
-
|
|
1300
|
+
node;
|
|
1305
1301
|
constructor(order) {
|
|
1306
1302
|
super(order);
|
|
1307
|
-
this.
|
|
1308
|
-
head: null,
|
|
1309
|
-
node: {}
|
|
1310
|
-
};
|
|
1303
|
+
this.node = {};
|
|
1311
1304
|
}
|
|
1312
1305
|
id() {
|
|
1313
|
-
return
|
|
1306
|
+
return this.autoIncrement("index", 1);
|
|
1314
1307
|
}
|
|
1315
1308
|
read(id) {
|
|
1316
|
-
if (!Object.
|
|
1309
|
+
if (!Object.hasOwn(this.node, id)) {
|
|
1317
1310
|
throw new Error(`The tree attempted to reference node '${id}', but couldn't find the corresponding node.`);
|
|
1318
1311
|
}
|
|
1319
|
-
return this.
|
|
1312
|
+
return this.node[id];
|
|
1320
1313
|
}
|
|
1321
1314
|
write(id, node) {
|
|
1322
|
-
this.
|
|
1315
|
+
this.node[id] = node;
|
|
1323
1316
|
}
|
|
1324
1317
|
readHead() {
|
|
1325
|
-
|
|
1318
|
+
if (this.head.root === 0) {
|
|
1319
|
+
return null;
|
|
1320
|
+
}
|
|
1321
|
+
return this.head;
|
|
1326
1322
|
}
|
|
1327
1323
|
writeHead(head) {
|
|
1328
|
-
this.
|
|
1324
|
+
this.head = head;
|
|
1329
1325
|
}
|
|
1330
1326
|
};
|
|
1331
1327
|
|
|
1332
1328
|
// src/SerializeStrategyAsync.ts
|
|
1333
1329
|
var SerializeStrategyAsync = class extends SerializeStrategy {
|
|
1330
|
+
async getHeadData(key, defaultValue) {
|
|
1331
|
+
if (!Object.hasOwn(this.head.data, key)) {
|
|
1332
|
+
return defaultValue;
|
|
1333
|
+
}
|
|
1334
|
+
return this.head.data[key];
|
|
1335
|
+
}
|
|
1336
|
+
async setHeadData(key, data) {
|
|
1337
|
+
this.head.data[key] = data;
|
|
1338
|
+
await this.writeHead(this.head);
|
|
1339
|
+
}
|
|
1340
|
+
async autoIncrement(key, defaultValue) {
|
|
1341
|
+
const current = await this.getHeadData(key, defaultValue);
|
|
1342
|
+
const next = current + 1;
|
|
1343
|
+
await this.setHeadData(key, next);
|
|
1344
|
+
return current;
|
|
1345
|
+
}
|
|
1334
1346
|
};
|
|
1335
1347
|
var InMemoryStoreStrategyAsync = class extends SerializeStrategyAsync {
|
|
1336
|
-
|
|
1348
|
+
node;
|
|
1337
1349
|
constructor(order) {
|
|
1338
1350
|
super(order);
|
|
1339
|
-
this.
|
|
1340
|
-
head: null,
|
|
1341
|
-
node: {}
|
|
1342
|
-
};
|
|
1351
|
+
this.node = {};
|
|
1343
1352
|
}
|
|
1344
1353
|
async id() {
|
|
1345
|
-
return
|
|
1354
|
+
return await this.autoIncrement("index", 1);
|
|
1346
1355
|
}
|
|
1347
1356
|
async read(id) {
|
|
1348
|
-
if (!Object.
|
|
1357
|
+
if (!Object.hasOwn(this.node, id)) {
|
|
1349
1358
|
throw new Error(`The tree attempted to reference node '${id}', but couldn't find the corresponding node.`);
|
|
1350
1359
|
}
|
|
1351
|
-
return this.
|
|
1360
|
+
return this.node[id];
|
|
1352
1361
|
}
|
|
1353
1362
|
async write(id, node) {
|
|
1354
|
-
this.
|
|
1363
|
+
this.node[id] = node;
|
|
1355
1364
|
}
|
|
1356
1365
|
async readHead() {
|
|
1357
|
-
|
|
1366
|
+
if (this.head.root === 0) {
|
|
1367
|
+
return null;
|
|
1368
|
+
}
|
|
1369
|
+
return this.head;
|
|
1358
1370
|
}
|
|
1359
1371
|
async writeHead(head) {
|
|
1360
|
-
this.
|
|
1372
|
+
this.head = head;
|
|
1361
1373
|
}
|
|
1362
1374
|
};
|
package/dist/esm/index.js
CHANGED
|
@@ -44,11 +44,9 @@ var BPTree = class {
|
|
|
44
44
|
comparator;
|
|
45
45
|
nodes;
|
|
46
46
|
order;
|
|
47
|
-
data;
|
|
48
47
|
root;
|
|
49
48
|
_nodeCreateBuffer;
|
|
50
49
|
_nodeUpdateBuffer;
|
|
51
|
-
_headBuffer;
|
|
52
50
|
verifierMap = {
|
|
53
51
|
gt: (nv, v) => this.comparator.isHigher(nv, v),
|
|
54
52
|
gte: (nv, v) => this.comparator.isHigher(nv, v) || this.comparator.isSame(nv, v),
|
|
@@ -93,19 +91,8 @@ var BPTree = class {
|
|
|
93
91
|
notEqual: true,
|
|
94
92
|
like: true
|
|
95
93
|
};
|
|
96
|
-
get headState() {
|
|
97
|
-
const root = this.root.id;
|
|
98
|
-
const order = this.order;
|
|
99
|
-
const data = this.data;
|
|
100
|
-
return {
|
|
101
|
-
root,
|
|
102
|
-
order,
|
|
103
|
-
data
|
|
104
|
-
};
|
|
105
|
-
}
|
|
106
94
|
constructor(strategy, comparator) {
|
|
107
95
|
this._regexpCache = new CacheStorage();
|
|
108
|
-
this._headBuffer = null;
|
|
109
96
|
this._nodeCreateBuffer = /* @__PURE__ */ new Map();
|
|
110
97
|
this._nodeUpdateBuffer = /* @__PURE__ */ new Map();
|
|
111
98
|
this.nodes = /* @__PURE__ */ new Map();
|
|
@@ -139,9 +126,6 @@ var BPTree = class {
|
|
|
139
126
|
this.bufferForNodeUpdate(node);
|
|
140
127
|
}
|
|
141
128
|
}
|
|
142
|
-
bufferForHeadUpdate(head) {
|
|
143
|
-
this._headBuffer = head;
|
|
144
|
-
}
|
|
145
129
|
bufferForNodeCreate(node) {
|
|
146
130
|
this._nodeCreateBuffer.set(node.id, node);
|
|
147
131
|
}
|
|
@@ -154,7 +138,7 @@ var BPTree = class {
|
|
|
154
138
|
* @returns User-defined data stored in the head of the tree.
|
|
155
139
|
*/
|
|
156
140
|
getHeadData() {
|
|
157
|
-
return this.data;
|
|
141
|
+
return this.strategy.head.data;
|
|
158
142
|
}
|
|
159
143
|
};
|
|
160
144
|
|
|
@@ -273,7 +257,7 @@ var BPTreeSync = class extends BPTree {
|
|
|
273
257
|
const keys = node.keys;
|
|
274
258
|
this.root = this.getNode(keys[0]);
|
|
275
259
|
this.root.parent = 0;
|
|
276
|
-
this.
|
|
260
|
+
this.strategy.head.root = this.root.id;
|
|
277
261
|
this.bufferForNodeUpdate(this.root);
|
|
278
262
|
return;
|
|
279
263
|
} else if (this.root === node) {
|
|
@@ -479,9 +463,9 @@ var BPTreeSync = class extends BPTree {
|
|
|
479
463
|
if (this.root === node) {
|
|
480
464
|
const root = this._createNode([node.id, pointer.id], [value]);
|
|
481
465
|
this.root = root;
|
|
466
|
+
this.strategy.head.root = root.id;
|
|
482
467
|
node.parent = root.id;
|
|
483
468
|
pointer.parent = root.id;
|
|
484
|
-
this.bufferForHeadUpdate(this.headState);
|
|
485
469
|
this.bufferForNodeCreate(root);
|
|
486
470
|
this.bufferForNodeUpdate(node);
|
|
487
471
|
this.bufferForNodeUpdate(pointer);
|
|
@@ -528,16 +512,15 @@ var BPTreeSync = class extends BPTree {
|
|
|
528
512
|
const head = this.strategy.readHead();
|
|
529
513
|
if (head === null) {
|
|
530
514
|
this.order = this.strategy.order;
|
|
531
|
-
this.data = {};
|
|
532
515
|
this.root = this._createNode([], [], true);
|
|
533
|
-
this.
|
|
516
|
+
this.strategy.head.root = this.root.id;
|
|
534
517
|
this.bufferForNodeCreate(this.root);
|
|
535
518
|
this.commitHeadBuffer();
|
|
536
519
|
this.commitNodeCreateBuffer();
|
|
537
520
|
} else {
|
|
538
|
-
const { root, order
|
|
521
|
+
const { root, order } = head;
|
|
522
|
+
this.strategy.head = head;
|
|
539
523
|
this.order = order;
|
|
540
|
-
this.data = data ?? {};
|
|
541
524
|
this.root = this.getNode(root);
|
|
542
525
|
}
|
|
543
526
|
if (this.order < 3) {
|
|
@@ -579,10 +562,7 @@ var BPTreeSync = class extends BPTree {
|
|
|
579
562
|
return node;
|
|
580
563
|
}
|
|
581
564
|
commitHeadBuffer() {
|
|
582
|
-
|
|
583
|
-
this.strategy.writeHead(this._headBuffer);
|
|
584
|
-
}
|
|
585
|
-
this.bufferForHeadUpdate(null);
|
|
565
|
+
this.strategy.writeHead(this.strategy.head);
|
|
586
566
|
}
|
|
587
567
|
commitNodeCreateBuffer() {
|
|
588
568
|
for (const node of this._nodeCreateBuffer.values()) {
|
|
@@ -705,8 +685,7 @@ var BPTreeSync = class extends BPTree {
|
|
|
705
685
|
return false;
|
|
706
686
|
}
|
|
707
687
|
setHeadData(data) {
|
|
708
|
-
this.data = data;
|
|
709
|
-
this.bufferForHeadUpdate(this.headState);
|
|
688
|
+
this.strategy.head.data = data;
|
|
710
689
|
this.commitHeadBuffer();
|
|
711
690
|
}
|
|
712
691
|
forceUpdate() {
|
|
@@ -835,7 +814,7 @@ var BPTreeAsync = class extends BPTree {
|
|
|
835
814
|
const keys = node.keys;
|
|
836
815
|
this.root = await this.getNode(keys[0]);
|
|
837
816
|
this.root.parent = 0;
|
|
838
|
-
this.
|
|
817
|
+
this.strategy.head.root = this.root.id;
|
|
839
818
|
this.bufferForNodeUpdate(this.root);
|
|
840
819
|
return;
|
|
841
820
|
} else if (this.root === node) {
|
|
@@ -1014,9 +993,9 @@ var BPTreeAsync = class extends BPTree {
|
|
|
1014
993
|
if (this.root === node) {
|
|
1015
994
|
const root = await this._createNode([node.id, pointer.id], [value]);
|
|
1016
995
|
this.root = root;
|
|
996
|
+
this.strategy.head.root = root.id;
|
|
1017
997
|
node.parent = root.id;
|
|
1018
998
|
pointer.parent = root.id;
|
|
1019
|
-
this.bufferForHeadUpdate(this.headState);
|
|
1020
999
|
this.bufferForNodeCreate(root);
|
|
1021
1000
|
this.bufferForNodeUpdate(node);
|
|
1022
1001
|
this.bufferForNodeUpdate(pointer);
|
|
@@ -1063,16 +1042,15 @@ var BPTreeAsync = class extends BPTree {
|
|
|
1063
1042
|
const head = await this.strategy.readHead();
|
|
1064
1043
|
if (head === null) {
|
|
1065
1044
|
this.order = this.strategy.order;
|
|
1066
|
-
this.data = {};
|
|
1067
1045
|
this.root = await this._createNode([], [], true);
|
|
1068
|
-
this.
|
|
1046
|
+
this.strategy.head.root = this.root.id;
|
|
1069
1047
|
this.bufferForNodeCreate(this.root);
|
|
1070
1048
|
this.commitHeadBuffer();
|
|
1071
1049
|
this.commitNodeCreateBuffer();
|
|
1072
1050
|
} else {
|
|
1073
|
-
const { root, order
|
|
1051
|
+
const { root, order } = head;
|
|
1052
|
+
this.strategy.head = head;
|
|
1074
1053
|
this.order = order;
|
|
1075
|
-
this.data = data ?? {};
|
|
1076
1054
|
this.root = await this.getNode(root);
|
|
1077
1055
|
}
|
|
1078
1056
|
if (this.order < 3) {
|
|
@@ -1114,10 +1092,7 @@ var BPTreeAsync = class extends BPTree {
|
|
|
1114
1092
|
return node;
|
|
1115
1093
|
}
|
|
1116
1094
|
async commitHeadBuffer() {
|
|
1117
|
-
|
|
1118
|
-
await this.strategy.writeHead(this._headBuffer);
|
|
1119
|
-
}
|
|
1120
|
-
this.bufferForHeadUpdate(null);
|
|
1095
|
+
await this.strategy.writeHead(this.strategy.head);
|
|
1121
1096
|
}
|
|
1122
1097
|
async commitNodeCreateBuffer() {
|
|
1123
1098
|
for (const node of this._nodeCreateBuffer.values()) {
|
|
@@ -1240,8 +1215,7 @@ var BPTreeAsync = class extends BPTree {
|
|
|
1240
1215
|
return false;
|
|
1241
1216
|
}
|
|
1242
1217
|
async setHeadData(data) {
|
|
1243
|
-
this.data = data;
|
|
1244
|
-
this.bufferForHeadUpdate(this.headState);
|
|
1218
|
+
this.strategy.head.data = data;
|
|
1245
1219
|
await this.commitHeadBuffer();
|
|
1246
1220
|
}
|
|
1247
1221
|
async forceUpdate() {
|
|
@@ -1258,72 +1232,110 @@ var BPTreeAsync = class extends BPTree {
|
|
|
1258
1232
|
// src/base/SerializeStrategy.ts
|
|
1259
1233
|
var SerializeStrategy = class {
|
|
1260
1234
|
order;
|
|
1235
|
+
head;
|
|
1261
1236
|
constructor(order) {
|
|
1262
1237
|
this.order = order;
|
|
1238
|
+
this.head = {
|
|
1239
|
+
order,
|
|
1240
|
+
root: 0,
|
|
1241
|
+
data: {}
|
|
1242
|
+
};
|
|
1263
1243
|
}
|
|
1264
1244
|
};
|
|
1265
1245
|
|
|
1266
1246
|
// src/SerializeStrategySync.ts
|
|
1267
1247
|
var SerializeStrategySync = class extends SerializeStrategy {
|
|
1248
|
+
getHeadData(key, defaultValue) {
|
|
1249
|
+
if (!Object.hasOwn(this.head.data, key)) {
|
|
1250
|
+
return defaultValue;
|
|
1251
|
+
}
|
|
1252
|
+
return this.head.data[key];
|
|
1253
|
+
}
|
|
1254
|
+
setHeadData(key, data) {
|
|
1255
|
+
this.head.data[key] = data;
|
|
1256
|
+
this.writeHead(this.head);
|
|
1257
|
+
}
|
|
1258
|
+
autoIncrement(key, defaultValue) {
|
|
1259
|
+
const current = this.getHeadData(key, defaultValue);
|
|
1260
|
+
const next = current + 1;
|
|
1261
|
+
this.setHeadData(key, next);
|
|
1262
|
+
return current;
|
|
1263
|
+
}
|
|
1268
1264
|
};
|
|
1269
1265
|
var InMemoryStoreStrategySync = class extends SerializeStrategySync {
|
|
1270
|
-
|
|
1266
|
+
node;
|
|
1271
1267
|
constructor(order) {
|
|
1272
1268
|
super(order);
|
|
1273
|
-
this.
|
|
1274
|
-
head: null,
|
|
1275
|
-
node: {}
|
|
1276
|
-
};
|
|
1269
|
+
this.node = {};
|
|
1277
1270
|
}
|
|
1278
1271
|
id() {
|
|
1279
|
-
return
|
|
1272
|
+
return this.autoIncrement("index", 1);
|
|
1280
1273
|
}
|
|
1281
1274
|
read(id) {
|
|
1282
|
-
if (!Object.
|
|
1275
|
+
if (!Object.hasOwn(this.node, id)) {
|
|
1283
1276
|
throw new Error(`The tree attempted to reference node '${id}', but couldn't find the corresponding node.`);
|
|
1284
1277
|
}
|
|
1285
|
-
return this.
|
|
1278
|
+
return this.node[id];
|
|
1286
1279
|
}
|
|
1287
1280
|
write(id, node) {
|
|
1288
|
-
this.
|
|
1281
|
+
this.node[id] = node;
|
|
1289
1282
|
}
|
|
1290
1283
|
readHead() {
|
|
1291
|
-
|
|
1284
|
+
if (this.head.root === 0) {
|
|
1285
|
+
return null;
|
|
1286
|
+
}
|
|
1287
|
+
return this.head;
|
|
1292
1288
|
}
|
|
1293
1289
|
writeHead(head) {
|
|
1294
|
-
this.
|
|
1290
|
+
this.head = head;
|
|
1295
1291
|
}
|
|
1296
1292
|
};
|
|
1297
1293
|
|
|
1298
1294
|
// src/SerializeStrategyAsync.ts
|
|
1299
1295
|
var SerializeStrategyAsync = class extends SerializeStrategy {
|
|
1296
|
+
async getHeadData(key, defaultValue) {
|
|
1297
|
+
if (!Object.hasOwn(this.head.data, key)) {
|
|
1298
|
+
return defaultValue;
|
|
1299
|
+
}
|
|
1300
|
+
return this.head.data[key];
|
|
1301
|
+
}
|
|
1302
|
+
async setHeadData(key, data) {
|
|
1303
|
+
this.head.data[key] = data;
|
|
1304
|
+
await this.writeHead(this.head);
|
|
1305
|
+
}
|
|
1306
|
+
async autoIncrement(key, defaultValue) {
|
|
1307
|
+
const current = await this.getHeadData(key, defaultValue);
|
|
1308
|
+
const next = current + 1;
|
|
1309
|
+
await this.setHeadData(key, next);
|
|
1310
|
+
return current;
|
|
1311
|
+
}
|
|
1300
1312
|
};
|
|
1301
1313
|
var InMemoryStoreStrategyAsync = class extends SerializeStrategyAsync {
|
|
1302
|
-
|
|
1314
|
+
node;
|
|
1303
1315
|
constructor(order) {
|
|
1304
1316
|
super(order);
|
|
1305
|
-
this.
|
|
1306
|
-
head: null,
|
|
1307
|
-
node: {}
|
|
1308
|
-
};
|
|
1317
|
+
this.node = {};
|
|
1309
1318
|
}
|
|
1310
1319
|
async id() {
|
|
1311
|
-
return
|
|
1320
|
+
return await this.autoIncrement("index", 1);
|
|
1312
1321
|
}
|
|
1313
1322
|
async read(id) {
|
|
1314
|
-
if (!Object.
|
|
1323
|
+
if (!Object.hasOwn(this.node, id)) {
|
|
1315
1324
|
throw new Error(`The tree attempted to reference node '${id}', but couldn't find the corresponding node.`);
|
|
1316
1325
|
}
|
|
1317
|
-
return this.
|
|
1326
|
+
return this.node[id];
|
|
1318
1327
|
}
|
|
1319
1328
|
async write(id, node) {
|
|
1320
|
-
this.
|
|
1329
|
+
this.node[id] = node;
|
|
1321
1330
|
}
|
|
1322
1331
|
async readHead() {
|
|
1323
|
-
|
|
1332
|
+
if (this.head.root === 0) {
|
|
1333
|
+
return null;
|
|
1334
|
+
}
|
|
1335
|
+
return this.head;
|
|
1324
1336
|
}
|
|
1325
1337
|
async writeHead(head) {
|
|
1326
|
-
this.
|
|
1338
|
+
this.head = head;
|
|
1327
1339
|
}
|
|
1328
1340
|
};
|
|
1329
1341
|
export {
|
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import type { Json } from './utils/types';
|
|
2
1
|
import { BPTree, BPTreeCondition, BPTreeLeafNode, BPTreePair, BPTreeNodeKey, BPTreeUnknownNode } from './base/BPTree';
|
|
3
2
|
import { SerializeStrategyAsync } from './SerializeStrategyAsync';
|
|
4
3
|
import { ValueComparator } from './base/ValueComparator';
|
|
4
|
+
import { SerializableData } from './base/SerializeStrategy';
|
|
5
5
|
export declare class BPTreeAsync<K, V> extends BPTree<K, V> {
|
|
6
6
|
protected readonly strategy: SerializeStrategyAsync<K, V>;
|
|
7
7
|
constructor(strategy: SerializeStrategyAsync<K, V>, comparator: ValueComparator<V>);
|
|
@@ -24,6 +24,6 @@ export declare class BPTreeAsync<K, V> extends BPTree<K, V> {
|
|
|
24
24
|
insert(key: K, value: V): Promise<void>;
|
|
25
25
|
delete(key: K, value: V): Promise<void>;
|
|
26
26
|
exists(key: K, value: V): Promise<boolean>;
|
|
27
|
-
setHeadData(data:
|
|
27
|
+
setHeadData(data: SerializableData): Promise<void>;
|
|
28
28
|
forceUpdate(): Promise<number>;
|
|
29
29
|
}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import type { Json } from './utils/types';
|
|
2
1
|
import { BPTree, BPTreeCondition, BPTreeLeafNode, BPTreePair, BPTreeNodeKey, BPTreeUnknownNode } from './base/BPTree';
|
|
3
2
|
import { SerializeStrategySync } from './SerializeStrategySync';
|
|
4
3
|
import { ValueComparator } from './base/ValueComparator';
|
|
4
|
+
import { SerializableData } from './base/SerializeStrategy';
|
|
5
5
|
export declare class BPTreeSync<K, V> extends BPTree<K, V> {
|
|
6
6
|
protected readonly strategy: SerializeStrategySync<K, V>;
|
|
7
7
|
constructor(strategy: SerializeStrategySync<K, V>, comparator: ValueComparator<V>);
|
|
@@ -25,6 +25,6 @@ export declare class BPTreeSync<K, V> extends BPTree<K, V> {
|
|
|
25
25
|
insert(key: K, value: V): void;
|
|
26
26
|
delete(key: K, value: V): void;
|
|
27
27
|
exists(key: K, value: V): boolean;
|
|
28
|
-
setHeadData(data:
|
|
28
|
+
setHeadData(data: SerializableData): void;
|
|
29
29
|
forceUpdate(): number;
|
|
30
30
|
}
|
|
@@ -1,17 +1,18 @@
|
|
|
1
1
|
import { BPTreeNode } from './base/BPTree';
|
|
2
2
|
import { SerializeStrategy, SerializeStrategyHead } from './base/SerializeStrategy';
|
|
3
|
+
import { Json } from './utils/types';
|
|
3
4
|
export declare abstract class SerializeStrategyAsync<K, V> extends SerializeStrategy<K, V> {
|
|
4
5
|
abstract id(): Promise<number>;
|
|
5
6
|
abstract read(id: number): Promise<BPTreeNode<K, V>>;
|
|
6
7
|
abstract write(id: number, node: BPTreeNode<K, V>): Promise<void>;
|
|
7
8
|
abstract readHead(): Promise<SerializeStrategyHead | null>;
|
|
8
9
|
abstract writeHead(head: SerializeStrategyHead): Promise<void>;
|
|
10
|
+
getHeadData(key: string, defaultValue: Json): Promise<Json>;
|
|
11
|
+
setHeadData(key: string, data: Json): Promise<void>;
|
|
12
|
+
autoIncrement(key: string, defaultValue: number): Promise<number>;
|
|
9
13
|
}
|
|
10
14
|
export declare class InMemoryStoreStrategyAsync<K, V> extends SerializeStrategyAsync<K, V> {
|
|
11
|
-
protected readonly
|
|
12
|
-
head: SerializeStrategyHead | null;
|
|
13
|
-
node: Record<number, BPTreeNode<K, V>>;
|
|
14
|
-
};
|
|
15
|
+
protected readonly node: Record<number, BPTreeNode<K, V>>;
|
|
15
16
|
constructor(order: number);
|
|
16
17
|
id(): Promise<number>;
|
|
17
18
|
read(id: number): Promise<BPTreeNode<K, V>>;
|
|
@@ -1,17 +1,18 @@
|
|
|
1
1
|
import { BPTreeNode } from './base/BPTree';
|
|
2
2
|
import { SerializeStrategy, SerializeStrategyHead } from './base/SerializeStrategy';
|
|
3
|
+
import { Json } from './utils/types';
|
|
3
4
|
export declare abstract class SerializeStrategySync<K, V> extends SerializeStrategy<K, V> {
|
|
4
5
|
abstract id(): number;
|
|
5
6
|
abstract read(id: number): BPTreeNode<K, V>;
|
|
6
7
|
abstract write(id: number, node: BPTreeNode<K, V>): void;
|
|
7
8
|
abstract readHead(): SerializeStrategyHead | null;
|
|
8
9
|
abstract writeHead(head: SerializeStrategyHead): void;
|
|
10
|
+
getHeadData(key: string, defaultValue: Json): Json;
|
|
11
|
+
setHeadData(key: string, data: Json): void;
|
|
12
|
+
autoIncrement(key: string, defaultValue: number): number;
|
|
9
13
|
}
|
|
10
14
|
export declare class InMemoryStoreStrategySync<K, V> extends SerializeStrategySync<K, V> {
|
|
11
|
-
protected readonly
|
|
12
|
-
head: SerializeStrategyHead | null;
|
|
13
|
-
node: Record<number, BPTreeNode<K, V>>;
|
|
14
|
-
};
|
|
15
|
+
protected readonly node: Record<number, BPTreeNode<K, V>>;
|
|
15
16
|
constructor(order: number);
|
|
16
17
|
id(): number;
|
|
17
18
|
read(id: number): BPTreeNode<K, V>;
|
|
@@ -1,6 +1,5 @@
|
|
|
1
|
-
import type { Json } from '../utils/types';
|
|
2
1
|
import { ValueComparator } from './ValueComparator';
|
|
3
|
-
import {
|
|
2
|
+
import { SerializableData, SerializeStrategy } from './SerializeStrategy';
|
|
4
3
|
type Sync<T> = T;
|
|
5
4
|
type Async<T> = Promise<T>;
|
|
6
5
|
type Deferred<T> = Sync<T> | Async<T>;
|
|
@@ -49,16 +48,13 @@ export declare abstract class BPTree<K, V> {
|
|
|
49
48
|
protected readonly comparator: ValueComparator<V>;
|
|
50
49
|
protected readonly nodes: Map<number, BPTreeUnknownNode<K, V>>;
|
|
51
50
|
protected order: number;
|
|
52
|
-
protected data: Record<string, Json>;
|
|
53
51
|
protected root: BPTreeUnknownNode<K, V>;
|
|
54
52
|
protected readonly _nodeCreateBuffer: Map<number, BPTreeUnknownNode<K, V>>;
|
|
55
53
|
protected readonly _nodeUpdateBuffer: Map<number, BPTreeUnknownNode<K, V>>;
|
|
56
|
-
protected _headBuffer: SerializeStrategyHead | null;
|
|
57
54
|
protected readonly verifierMap: Record<keyof BPTreeCondition<V>, (nodeValue: V, value: V) => boolean>;
|
|
58
55
|
protected readonly verifierStartNode: Record<keyof BPTreeCondition<V>, (value: V) => Deferred<BPTreeLeafNode<K, V>>>;
|
|
59
56
|
protected readonly verifierDirection: Record<keyof BPTreeCondition<V>, -1 | 1>;
|
|
60
57
|
protected readonly verifierFullScan: Record<keyof BPTreeCondition<V>, boolean>;
|
|
61
|
-
protected get headState(): SerializeStrategyHead;
|
|
62
58
|
protected constructor(strategy: SerializeStrategy<K, V>, comparator: ValueComparator<V>);
|
|
63
59
|
protected abstract _getPairsRightToLeft(value: V, startNode: BPTreeLeafNode<K, V>, fullSearch: boolean, comparator: (nodeValue: V, value: V) => boolean): Deferred<BPTreePair<K, V>[]>;
|
|
64
60
|
protected abstract _getPairsLeftToRight(value: V, startNode: BPTreeLeafNode<K, V>, fullSearch: boolean, comparator: (nodeValue: V, value: V) => boolean): Deferred<BPTreePair<K, V>[]>;
|
|
@@ -117,7 +113,7 @@ export declare abstract class BPTree<K, V> {
|
|
|
117
113
|
* For example, you can store information such as the last update time and the number of insertions.
|
|
118
114
|
* @param data User-defined data to be stored in the head of the tree.
|
|
119
115
|
*/
|
|
120
|
-
abstract setHeadData(data:
|
|
116
|
+
abstract setHeadData(data: SerializableData): Deferred<void>;
|
|
121
117
|
/**
|
|
122
118
|
* This method deletes nodes cached in-memory and caches new nodes from the stored nodes.
|
|
123
119
|
* Typically, there's no need to use this method, but it can be used to synchronize data in scenarios where the remote storage and the client are in a 1:n relationship.
|
|
@@ -125,7 +121,6 @@ export declare abstract class BPTree<K, V> {
|
|
|
125
121
|
*/
|
|
126
122
|
abstract forceUpdate(nodeId: number): Deferred<number>;
|
|
127
123
|
protected _insertAtLeaf(node: BPTreeLeafNode<K, V>, key: K, value: V): void;
|
|
128
|
-
protected bufferForHeadUpdate(head: SerializeStrategyHead | null): Deferred<void>;
|
|
129
124
|
protected bufferForNodeCreate(node: BPTreeUnknownNode<K, V>): Deferred<void>;
|
|
130
125
|
protected bufferForNodeUpdate(node: BPTreeUnknownNode<K, V>): Deferred<void>;
|
|
131
126
|
/**
|
|
@@ -133,6 +128,6 @@ export declare abstract class BPTree<K, V> {
|
|
|
133
128
|
* 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 `{}`.
|
|
134
129
|
* @returns User-defined data stored in the head of the tree.
|
|
135
130
|
*/
|
|
136
|
-
getHeadData():
|
|
131
|
+
getHeadData(): SerializableData;
|
|
137
132
|
}
|
|
138
133
|
export {};
|
|
@@ -1,12 +1,14 @@
|
|
|
1
1
|
import { BPTreeNode } from './BPTree';
|
|
2
2
|
import type { Json } from '../utils/types';
|
|
3
|
+
export type SerializableData = Record<string, Json>;
|
|
3
4
|
export interface SerializeStrategyHead {
|
|
4
5
|
root: number;
|
|
5
6
|
order: number;
|
|
6
|
-
data:
|
|
7
|
+
data: SerializableData;
|
|
7
8
|
}
|
|
8
9
|
export declare abstract class SerializeStrategy<K, V> {
|
|
9
10
|
readonly order: number;
|
|
11
|
+
head: SerializeStrategyHead;
|
|
10
12
|
constructor(order: number);
|
|
11
13
|
/**
|
|
12
14
|
* The rule for generating node IDs is set.
|
|
@@ -42,4 +44,28 @@ export declare abstract class SerializeStrategy<K, V> {
|
|
|
42
44
|
* @param head This is the current state of the tree.
|
|
43
45
|
*/
|
|
44
46
|
abstract writeHead(head: SerializeStrategyHead): void | Promise<void>;
|
|
47
|
+
/**
|
|
48
|
+
* Retrieves the data stored in the tree.
|
|
49
|
+
* If there are no values stored in the tree, it returns the `defaultValue`.
|
|
50
|
+
* @param key The key of the data stored in the tree.
|
|
51
|
+
*/
|
|
52
|
+
abstract getHeadData(key: string, defaultValue: Json): Json | Promise<Json>;
|
|
53
|
+
/**
|
|
54
|
+
* Stores data in the tree.
|
|
55
|
+
* This data is permanently stored in the head.
|
|
56
|
+
* The stored data can be retrieved later using the `getHeadData` method.
|
|
57
|
+
* @param key The key of the data to be stored in the tree.
|
|
58
|
+
* @param data The data to be stored in the tree.
|
|
59
|
+
*/
|
|
60
|
+
abstract setHeadData(key: string, data: Json): void | Promise<void>;
|
|
61
|
+
/**
|
|
62
|
+
* This method returns a numeric value and increments it by `1`, storing it in the tree's header.
|
|
63
|
+
* Therefore, when called again, the value incremented by `+1` is returned.
|
|
64
|
+
*
|
|
65
|
+
* This is a syntactic sugar for using the `setHeadData` and `getHeadData` methods.
|
|
66
|
+
* It assists in simplifying the implementation of node ID generation in the `id` method.
|
|
67
|
+
* @param key The key of the data to be stored in the tree.
|
|
68
|
+
* @param defaultValue The data to be stored in the tree.
|
|
69
|
+
*/
|
|
70
|
+
abstract autoIncrement(key: string, defaultValue: number): number | Promise<number>;
|
|
45
71
|
}
|