serializable-bptree 8.3.5 → 8.4.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/dist/cjs/index.cjs +239 -45
- package/dist/esm/index.mjs +239 -45
- package/dist/types/BPTreeAsync.d.ts +1 -0
- package/dist/types/BPTreeSync.d.ts +1 -0
- package/dist/types/base/BPTreeTransaction.d.ts +12 -0
- package/dist/types/transaction/BPTreeAsyncTransaction.d.ts +1 -0
- package/dist/types/transaction/BPTreeSyncTransaction.d.ts +1 -0
- package/package.json +1 -1
package/dist/cjs/index.cjs
CHANGED
|
@@ -1924,30 +1924,22 @@ var BPTreeTransaction = class _BPTreeTransaction {
|
|
|
1924
1924
|
*/
|
|
1925
1925
|
_insertValueIntoLeaf(leaf, key, value) {
|
|
1926
1926
|
if (leaf.values.length) {
|
|
1927
|
-
|
|
1928
|
-
|
|
1929
|
-
if (
|
|
1930
|
-
|
|
1931
|
-
return false;
|
|
1932
|
-
}
|
|
1933
|
-
leaf.keys[i].push(key);
|
|
1934
|
-
return true;
|
|
1935
|
-
} else if (this.comparator.isLower(value, nValue)) {
|
|
1936
|
-
leaf.values.splice(i, 0, value);
|
|
1937
|
-
leaf.keys.splice(i, 0, [key]);
|
|
1938
|
-
return true;
|
|
1939
|
-
} else if (i + 1 === leaf.values.length) {
|
|
1940
|
-
leaf.values.push(value);
|
|
1941
|
-
leaf.keys.push([key]);
|
|
1942
|
-
return true;
|
|
1927
|
+
const { index, found } = this._binarySearchValues(leaf.values, value);
|
|
1928
|
+
if (found) {
|
|
1929
|
+
if (leaf.keys[index].includes(key)) {
|
|
1930
|
+
return false;
|
|
1943
1931
|
}
|
|
1932
|
+
leaf.keys[index].push(key);
|
|
1933
|
+
return true;
|
|
1944
1934
|
}
|
|
1935
|
+
leaf.values.splice(index, 0, value);
|
|
1936
|
+
leaf.keys.splice(index, 0, [key]);
|
|
1937
|
+
return true;
|
|
1945
1938
|
} else {
|
|
1946
1939
|
leaf.values = [value];
|
|
1947
1940
|
leaf.keys = [[key]];
|
|
1948
1941
|
return true;
|
|
1949
1942
|
}
|
|
1950
|
-
return false;
|
|
1951
1943
|
}
|
|
1952
1944
|
_cloneNode(node) {
|
|
1953
1945
|
return JSON.parse(JSON.stringify(node));
|
|
@@ -2240,12 +2232,8 @@ var BPTreeSyncTransaction = class extends BPTreeTransaction {
|
|
|
2240
2232
|
const midValue = parentNode.values[mid];
|
|
2241
2233
|
parentNode.values = parentNode.values.slice(0, mid);
|
|
2242
2234
|
parentNode.keys = parentNode.keys.slice(0, mid + 1);
|
|
2243
|
-
for (
|
|
2244
|
-
const
|
|
2245
|
-
n.parent = parentNode.id;
|
|
2246
|
-
this._updateNode(n);
|
|
2247
|
-
}
|
|
2248
|
-
for (const k of newSiblingNodeRecursive.keys) {
|
|
2235
|
+
for (let i = 0, len = newSiblingNodeRecursive.keys.length; i < len; i++) {
|
|
2236
|
+
const k = newSiblingNodeRecursive.keys[i];
|
|
2249
2237
|
const n = this._cloneNode(this.getNode(k));
|
|
2250
2238
|
n.parent = newSiblingNodeRecursive.id;
|
|
2251
2239
|
this._updateNode(n);
|
|
@@ -2327,7 +2315,7 @@ var BPTreeSyncTransaction = class extends BPTreeTransaction {
|
|
|
2327
2315
|
for (let i = 0; i < len; i++) {
|
|
2328
2316
|
const nValue = node.values[i];
|
|
2329
2317
|
const keys = node.keys[i];
|
|
2330
|
-
for (let j = 0,
|
|
2318
|
+
for (let j = 0, len2 = keys.length; j < len2; j++) {
|
|
2331
2319
|
yield [keys[j], nValue];
|
|
2332
2320
|
}
|
|
2333
2321
|
}
|
|
@@ -2406,7 +2394,7 @@ var BPTreeSyncTransaction = class extends BPTreeTransaction {
|
|
|
2406
2394
|
while (true) {
|
|
2407
2395
|
for (let i = 0, len = node.values.length; i < len; i++) {
|
|
2408
2396
|
const keys = node.keys[i];
|
|
2409
|
-
for (let j = 0,
|
|
2397
|
+
for (let j = 0, len2 = keys.length; j < len2; j++) {
|
|
2410
2398
|
if (keys[j] === key) {
|
|
2411
2399
|
return node.values[i];
|
|
2412
2400
|
}
|
|
@@ -2515,8 +2503,16 @@ var BPTreeSyncTransaction = class extends BPTreeTransaction {
|
|
|
2515
2503
|
const sorted = [...entries].sort((a, b) => this.comparator.asc(a[1], b[1]));
|
|
2516
2504
|
let currentLeaf = null;
|
|
2517
2505
|
let modified = false;
|
|
2518
|
-
|
|
2519
|
-
|
|
2506
|
+
let cachedLeafId = null;
|
|
2507
|
+
let cachedLeafMaxValue = null;
|
|
2508
|
+
for (let i = 0, len = sorted.length; i < len; i++) {
|
|
2509
|
+
const [key, value] = sorted[i];
|
|
2510
|
+
let targetLeaf;
|
|
2511
|
+
if (cachedLeafId !== null && cachedLeafMaxValue !== null && currentLeaf !== null && (this.comparator.isLower(value, cachedLeafMaxValue) || this.comparator.isSame(value, cachedLeafMaxValue))) {
|
|
2512
|
+
targetLeaf = currentLeaf;
|
|
2513
|
+
} else {
|
|
2514
|
+
targetLeaf = this.locateLeaf(value);
|
|
2515
|
+
}
|
|
2520
2516
|
if (currentLeaf !== null && currentLeaf.id === targetLeaf.id) {
|
|
2521
2517
|
} else {
|
|
2522
2518
|
if (currentLeaf !== null && modified) {
|
|
@@ -2525,8 +2521,10 @@ var BPTreeSyncTransaction = class extends BPTreeTransaction {
|
|
|
2525
2521
|
currentLeaf = this._cloneNode(targetLeaf);
|
|
2526
2522
|
modified = false;
|
|
2527
2523
|
}
|
|
2524
|
+
cachedLeafId = currentLeaf.id;
|
|
2528
2525
|
const changed = this._insertValueIntoLeaf(currentLeaf, key, value);
|
|
2529
2526
|
modified = modified || changed;
|
|
2527
|
+
cachedLeafMaxValue = currentLeaf.values[currentLeaf.values.length - 1];
|
|
2530
2528
|
if (currentLeaf.values.length === this.order) {
|
|
2531
2529
|
this._updateNode(currentLeaf);
|
|
2532
2530
|
let after = this._createNode(
|
|
@@ -2547,6 +2545,8 @@ var BPTreeSyncTransaction = class extends BPTreeTransaction {
|
|
|
2547
2545
|
this._updateNode(after);
|
|
2548
2546
|
this._insertInParent(currentLeaf, after.values[0], after);
|
|
2549
2547
|
currentLeaf = null;
|
|
2548
|
+
cachedLeafId = null;
|
|
2549
|
+
cachedLeafMaxValue = null;
|
|
2550
2550
|
modified = false;
|
|
2551
2551
|
}
|
|
2552
2552
|
}
|
|
@@ -2554,6 +2554,85 @@ var BPTreeSyncTransaction = class extends BPTreeTransaction {
|
|
|
2554
2554
|
this._updateNode(currentLeaf);
|
|
2555
2555
|
}
|
|
2556
2556
|
}
|
|
2557
|
+
bulkLoad(entries) {
|
|
2558
|
+
if (entries.length === 0) return;
|
|
2559
|
+
const root = this.getNode(this.rootId);
|
|
2560
|
+
if (!root.leaf || root.values.length > 0) {
|
|
2561
|
+
throw new Error("bulkLoad can only be called on an empty tree. Use batchInsert for non-empty trees.");
|
|
2562
|
+
}
|
|
2563
|
+
const sorted = [...entries].sort((a, b) => this.comparator.asc(a[1], b[1]));
|
|
2564
|
+
const grouped = [];
|
|
2565
|
+
for (let i = 0, len = sorted.length; i < len; i++) {
|
|
2566
|
+
const [key, value] = sorted[i];
|
|
2567
|
+
const last = grouped[grouped.length - 1];
|
|
2568
|
+
if (last && this.comparator.isSame(last.value, value)) {
|
|
2569
|
+
if (!last.keys.includes(key)) {
|
|
2570
|
+
last.keys.push(key);
|
|
2571
|
+
}
|
|
2572
|
+
} else {
|
|
2573
|
+
grouped.push({ keys: [key], value });
|
|
2574
|
+
}
|
|
2575
|
+
}
|
|
2576
|
+
this._deleteNode(root);
|
|
2577
|
+
const maxLeafSize = this.order - 1;
|
|
2578
|
+
const leaves = [];
|
|
2579
|
+
for (let i = 0, len = grouped.length; i < len; i += maxLeafSize) {
|
|
2580
|
+
const chunk = grouped.slice(i, i + maxLeafSize);
|
|
2581
|
+
const leafKeys = chunk.map((g) => g.keys);
|
|
2582
|
+
const leafValues = chunk.map((g) => g.value);
|
|
2583
|
+
const leaf = this._createNode(
|
|
2584
|
+
true,
|
|
2585
|
+
leafKeys,
|
|
2586
|
+
leafValues,
|
|
2587
|
+
null,
|
|
2588
|
+
null,
|
|
2589
|
+
null
|
|
2590
|
+
);
|
|
2591
|
+
leaves.push(leaf);
|
|
2592
|
+
}
|
|
2593
|
+
for (let i = 0, len = leaves.length; i < len; i++) {
|
|
2594
|
+
if (i > 0) {
|
|
2595
|
+
leaves[i].prev = leaves[i - 1].id;
|
|
2596
|
+
}
|
|
2597
|
+
if (i < len - 1) {
|
|
2598
|
+
leaves[i].next = leaves[i + 1].id;
|
|
2599
|
+
}
|
|
2600
|
+
this._updateNode(leaves[i]);
|
|
2601
|
+
}
|
|
2602
|
+
let currentLevel = leaves;
|
|
2603
|
+
while (currentLevel.length > 1) {
|
|
2604
|
+
const nextLevel = [];
|
|
2605
|
+
for (let i = 0, len = currentLevel.length; i < len; i += this.order) {
|
|
2606
|
+
const children = currentLevel.slice(i, i + this.order);
|
|
2607
|
+
const childIds = children.map((c) => c.id);
|
|
2608
|
+
const separators = [];
|
|
2609
|
+
for (let j = 1, len2 = children.length; j < len2; j++) {
|
|
2610
|
+
separators.push(children[j].values[0]);
|
|
2611
|
+
}
|
|
2612
|
+
const internalNode = this._createNode(
|
|
2613
|
+
false,
|
|
2614
|
+
childIds,
|
|
2615
|
+
separators,
|
|
2616
|
+
null,
|
|
2617
|
+
null,
|
|
2618
|
+
null
|
|
2619
|
+
);
|
|
2620
|
+
for (let j = 0, len2 = children.length; j < len2; j++) {
|
|
2621
|
+
const child = children[j];
|
|
2622
|
+
child.parent = internalNode.id;
|
|
2623
|
+
this._updateNode(child);
|
|
2624
|
+
}
|
|
2625
|
+
nextLevel.push(internalNode);
|
|
2626
|
+
}
|
|
2627
|
+
currentLevel = nextLevel;
|
|
2628
|
+
}
|
|
2629
|
+
const newRoot = currentLevel[0];
|
|
2630
|
+
this._writeHead({
|
|
2631
|
+
root: newRoot.id,
|
|
2632
|
+
order: this.order,
|
|
2633
|
+
data: this.strategy.head.data
|
|
2634
|
+
});
|
|
2635
|
+
}
|
|
2557
2636
|
_deleteEntry(node, key) {
|
|
2558
2637
|
if (!node.leaf) {
|
|
2559
2638
|
let keyIndex = -1;
|
|
@@ -2657,7 +2736,8 @@ var BPTreeSyncTransaction = class extends BPTreeTransaction {
|
|
|
2657
2736
|
siblingNode.values.push(...node.values);
|
|
2658
2737
|
if (!siblingNode.leaf) {
|
|
2659
2738
|
const keys = siblingNode.keys;
|
|
2660
|
-
for (
|
|
2739
|
+
for (let i = 0, len = keys.length; i < len; i++) {
|
|
2740
|
+
const key2 = keys[i];
|
|
2661
2741
|
const node2 = this._cloneNode(this.getNode(key2));
|
|
2662
2742
|
node2.parent = siblingNode.id;
|
|
2663
2743
|
this._updateNode(node2);
|
|
@@ -2725,21 +2805,24 @@ var BPTreeSyncTransaction = class extends BPTreeTransaction {
|
|
|
2725
2805
|
this._updateNode(siblingNode);
|
|
2726
2806
|
}
|
|
2727
2807
|
if (!siblingNode.leaf) {
|
|
2728
|
-
for (
|
|
2808
|
+
for (let i = 0, len = siblingNode.keys.length; i < len; i++) {
|
|
2809
|
+
const key2 = siblingNode.keys[i];
|
|
2729
2810
|
const n = this._cloneNode(this.getNode(key2));
|
|
2730
2811
|
n.parent = siblingNode.id;
|
|
2731
2812
|
this._updateNode(n);
|
|
2732
2813
|
}
|
|
2733
2814
|
}
|
|
2734
2815
|
if (!node.leaf) {
|
|
2735
|
-
for (
|
|
2816
|
+
for (let i = 0, len = node.keys.length; i < len; i++) {
|
|
2817
|
+
const key2 = node.keys[i];
|
|
2736
2818
|
const n = this._cloneNode(this.getNode(key2));
|
|
2737
2819
|
n.parent = node.id;
|
|
2738
2820
|
this._updateNode(n);
|
|
2739
2821
|
}
|
|
2740
2822
|
}
|
|
2741
2823
|
if (!parentNode.leaf) {
|
|
2742
|
-
for (
|
|
2824
|
+
for (let i = 0, len = parentNode.keys.length; i < len; i++) {
|
|
2825
|
+
const key2 = parentNode.keys[i];
|
|
2743
2826
|
const n = this._cloneNode(this.getNode(key2));
|
|
2744
2827
|
n.parent = parentNode.id;
|
|
2745
2828
|
this._updateNode(n);
|
|
@@ -2917,6 +3000,14 @@ var BPTreeSync = class extends BPTreeSyncTransaction {
|
|
|
2917
3000
|
throw new Error(`Transaction failed: ${result.error || "Commit failed due to conflict"}`);
|
|
2918
3001
|
}
|
|
2919
3002
|
}
|
|
3003
|
+
bulkLoad(entries) {
|
|
3004
|
+
const tx = this.createTransaction();
|
|
3005
|
+
tx.bulkLoad(entries);
|
|
3006
|
+
const result = tx.commit();
|
|
3007
|
+
if (!result.success) {
|
|
3008
|
+
throw new Error(`Transaction failed: ${result.error || "Commit failed due to conflict"}`);
|
|
3009
|
+
}
|
|
3010
|
+
}
|
|
2920
3011
|
};
|
|
2921
3012
|
|
|
2922
3013
|
// node_modules/ryoiki/dist/esm/index.mjs
|
|
@@ -3334,12 +3425,8 @@ var BPTreeAsyncTransaction = class extends BPTreeTransaction {
|
|
|
3334
3425
|
const midValue = parentNode.values[mid];
|
|
3335
3426
|
parentNode.values = parentNode.values.slice(0, mid);
|
|
3336
3427
|
parentNode.keys = parentNode.keys.slice(0, mid + 1);
|
|
3337
|
-
for (
|
|
3338
|
-
const
|
|
3339
|
-
n.parent = parentNode.id;
|
|
3340
|
-
await this._updateNode(n);
|
|
3341
|
-
}
|
|
3342
|
-
for (const k of newSiblingNodeRecursive.keys) {
|
|
3428
|
+
for (let i = 0, len = newSiblingNodeRecursive.keys.length; i < len; i++) {
|
|
3429
|
+
const k = newSiblingNodeRecursive.keys[i];
|
|
3343
3430
|
const n = this._cloneNode(await this.getNode(k));
|
|
3344
3431
|
n.parent = newSiblingNodeRecursive.id;
|
|
3345
3432
|
await this._updateNode(n);
|
|
@@ -3431,7 +3518,7 @@ var BPTreeAsyncTransaction = class extends BPTreeTransaction {
|
|
|
3431
3518
|
for (let i = 0; i < len; i++) {
|
|
3432
3519
|
const nValue = node.values[i];
|
|
3433
3520
|
const keys = node.keys[i];
|
|
3434
|
-
for (let j = 0,
|
|
3521
|
+
for (let j = 0, len2 = keys.length; j < len2; j++) {
|
|
3435
3522
|
yield [keys[j], nValue];
|
|
3436
3523
|
}
|
|
3437
3524
|
}
|
|
@@ -3509,7 +3596,7 @@ var BPTreeAsyncTransaction = class extends BPTreeTransaction {
|
|
|
3509
3596
|
while (true) {
|
|
3510
3597
|
for (let i = 0, len = node.values.length; i < len; i++) {
|
|
3511
3598
|
const keys = node.keys[i];
|
|
3512
|
-
for (let j = 0,
|
|
3599
|
+
for (let j = 0, len2 = keys.length; j < len2; j++) {
|
|
3513
3600
|
if (keys[j] === key) {
|
|
3514
3601
|
return node.values[i];
|
|
3515
3602
|
}
|
|
@@ -3621,8 +3708,16 @@ var BPTreeAsyncTransaction = class extends BPTreeTransaction {
|
|
|
3621
3708
|
const sorted = [...entries].sort((a, b) => this.comparator.asc(a[1], b[1]));
|
|
3622
3709
|
let currentLeaf = null;
|
|
3623
3710
|
let modified = false;
|
|
3624
|
-
|
|
3625
|
-
|
|
3711
|
+
let cachedLeafId = null;
|
|
3712
|
+
let cachedLeafMaxValue = null;
|
|
3713
|
+
for (let i = 0, len = sorted.length; i < len; i++) {
|
|
3714
|
+
const [key, value] = sorted[i];
|
|
3715
|
+
let targetLeaf;
|
|
3716
|
+
if (cachedLeafId !== null && cachedLeafMaxValue !== null && currentLeaf !== null && (this.comparator.isLower(value, cachedLeafMaxValue) || this.comparator.isSame(value, cachedLeafMaxValue))) {
|
|
3717
|
+
targetLeaf = currentLeaf;
|
|
3718
|
+
} else {
|
|
3719
|
+
targetLeaf = await this.locateLeaf(value);
|
|
3720
|
+
}
|
|
3626
3721
|
if (currentLeaf !== null && currentLeaf.id === targetLeaf.id) {
|
|
3627
3722
|
} else {
|
|
3628
3723
|
if (currentLeaf !== null && modified) {
|
|
@@ -3631,8 +3726,10 @@ var BPTreeAsyncTransaction = class extends BPTreeTransaction {
|
|
|
3631
3726
|
currentLeaf = this._cloneNode(targetLeaf);
|
|
3632
3727
|
modified = false;
|
|
3633
3728
|
}
|
|
3729
|
+
cachedLeafId = currentLeaf.id;
|
|
3634
3730
|
const changed = this._insertValueIntoLeaf(currentLeaf, key, value);
|
|
3635
3731
|
modified = modified || changed;
|
|
3732
|
+
cachedLeafMaxValue = currentLeaf.values[currentLeaf.values.length - 1];
|
|
3636
3733
|
if (currentLeaf.values.length === this.order) {
|
|
3637
3734
|
await this._updateNode(currentLeaf);
|
|
3638
3735
|
let after = await this._createNode(
|
|
@@ -3653,6 +3750,8 @@ var BPTreeAsyncTransaction = class extends BPTreeTransaction {
|
|
|
3653
3750
|
await this._updateNode(after);
|
|
3654
3751
|
await this._insertInParent(currentLeaf, after.values[0], after);
|
|
3655
3752
|
currentLeaf = null;
|
|
3753
|
+
cachedLeafId = null;
|
|
3754
|
+
cachedLeafMaxValue = null;
|
|
3656
3755
|
modified = false;
|
|
3657
3756
|
}
|
|
3658
3757
|
}
|
|
@@ -3661,6 +3760,87 @@ var BPTreeAsyncTransaction = class extends BPTreeTransaction {
|
|
|
3661
3760
|
}
|
|
3662
3761
|
});
|
|
3663
3762
|
}
|
|
3763
|
+
async bulkLoad(entries) {
|
|
3764
|
+
if (entries.length === 0) return;
|
|
3765
|
+
return this.writeLock(0, async () => {
|
|
3766
|
+
const root = await this.getNode(this.rootId);
|
|
3767
|
+
if (!root.leaf || root.values.length > 0) {
|
|
3768
|
+
throw new Error("bulkLoad can only be called on an empty tree. Use batchInsert for non-empty trees.");
|
|
3769
|
+
}
|
|
3770
|
+
const sorted = [...entries].sort((a, b) => this.comparator.asc(a[1], b[1]));
|
|
3771
|
+
const grouped = [];
|
|
3772
|
+
for (let i = 0, len = sorted.length; i < len; i++) {
|
|
3773
|
+
const [key, value] = sorted[i];
|
|
3774
|
+
const last = grouped[grouped.length - 1];
|
|
3775
|
+
if (last && this.comparator.isSame(last.value, value)) {
|
|
3776
|
+
if (!last.keys.includes(key)) {
|
|
3777
|
+
last.keys.push(key);
|
|
3778
|
+
}
|
|
3779
|
+
} else {
|
|
3780
|
+
grouped.push({ keys: [key], value });
|
|
3781
|
+
}
|
|
3782
|
+
}
|
|
3783
|
+
await this._deleteNode(root);
|
|
3784
|
+
const maxLeafSize = this.order - 1;
|
|
3785
|
+
const leaves = [];
|
|
3786
|
+
for (let i = 0, len = grouped.length; i < len; i += maxLeafSize) {
|
|
3787
|
+
const chunk = grouped.slice(i, i + maxLeafSize);
|
|
3788
|
+
const leafKeys = chunk.map((g) => g.keys);
|
|
3789
|
+
const leafValues = chunk.map((g) => g.value);
|
|
3790
|
+
const leaf = await this._createNode(
|
|
3791
|
+
true,
|
|
3792
|
+
leafKeys,
|
|
3793
|
+
leafValues,
|
|
3794
|
+
null,
|
|
3795
|
+
null,
|
|
3796
|
+
null
|
|
3797
|
+
);
|
|
3798
|
+
leaves.push(leaf);
|
|
3799
|
+
}
|
|
3800
|
+
for (let i = 0, len = leaves.length; i < len; i++) {
|
|
3801
|
+
if (i > 0) {
|
|
3802
|
+
leaves[i].prev = leaves[i - 1].id;
|
|
3803
|
+
}
|
|
3804
|
+
if (i < len - 1) {
|
|
3805
|
+
leaves[i].next = leaves[i + 1].id;
|
|
3806
|
+
}
|
|
3807
|
+
await this._updateNode(leaves[i]);
|
|
3808
|
+
}
|
|
3809
|
+
let currentLevel = leaves;
|
|
3810
|
+
while (currentLevel.length > 1) {
|
|
3811
|
+
const nextLevel = [];
|
|
3812
|
+
for (let i = 0, len = currentLevel.length; i < len; i += this.order) {
|
|
3813
|
+
const children = currentLevel.slice(i, i + this.order);
|
|
3814
|
+
const childIds = children.map((c) => c.id);
|
|
3815
|
+
const separators = [];
|
|
3816
|
+
for (let j = 1, len2 = children.length; j < len2; j++) {
|
|
3817
|
+
separators.push(children[j].values[0]);
|
|
3818
|
+
}
|
|
3819
|
+
const internalNode = await this._createNode(
|
|
3820
|
+
false,
|
|
3821
|
+
childIds,
|
|
3822
|
+
separators,
|
|
3823
|
+
null,
|
|
3824
|
+
null,
|
|
3825
|
+
null
|
|
3826
|
+
);
|
|
3827
|
+
for (let j = 0, len2 = children.length; j < len2; j++) {
|
|
3828
|
+
const child = children[j];
|
|
3829
|
+
child.parent = internalNode.id;
|
|
3830
|
+
await this._updateNode(child);
|
|
3831
|
+
}
|
|
3832
|
+
nextLevel.push(internalNode);
|
|
3833
|
+
}
|
|
3834
|
+
currentLevel = nextLevel;
|
|
3835
|
+
}
|
|
3836
|
+
const newRoot = currentLevel[0];
|
|
3837
|
+
await this._writeHead({
|
|
3838
|
+
root: newRoot.id,
|
|
3839
|
+
order: this.order,
|
|
3840
|
+
data: this.strategy.head.data
|
|
3841
|
+
});
|
|
3842
|
+
});
|
|
3843
|
+
}
|
|
3664
3844
|
async _deleteEntry(node, key) {
|
|
3665
3845
|
if (!node.leaf) {
|
|
3666
3846
|
let keyIndex = -1;
|
|
@@ -3764,7 +3944,8 @@ var BPTreeAsyncTransaction = class extends BPTreeTransaction {
|
|
|
3764
3944
|
siblingNode.values.push(...node.values);
|
|
3765
3945
|
if (!siblingNode.leaf) {
|
|
3766
3946
|
const keys = siblingNode.keys;
|
|
3767
|
-
for (
|
|
3947
|
+
for (let i = 0, len = keys.length; i < len; i++) {
|
|
3948
|
+
const key2 = keys[i];
|
|
3768
3949
|
const node2 = this._cloneNode(await this.getNode(key2));
|
|
3769
3950
|
node2.parent = siblingNode.id;
|
|
3770
3951
|
await this._updateNode(node2);
|
|
@@ -3832,21 +4013,24 @@ var BPTreeAsyncTransaction = class extends BPTreeTransaction {
|
|
|
3832
4013
|
await this._updateNode(siblingNode);
|
|
3833
4014
|
}
|
|
3834
4015
|
if (!siblingNode.leaf) {
|
|
3835
|
-
for (
|
|
4016
|
+
for (let i = 0, len = siblingNode.keys.length; i < len; i++) {
|
|
4017
|
+
const key2 = siblingNode.keys[i];
|
|
3836
4018
|
const n = this._cloneNode(await this.getNode(key2));
|
|
3837
4019
|
n.parent = siblingNode.id;
|
|
3838
4020
|
await this._updateNode(n);
|
|
3839
4021
|
}
|
|
3840
4022
|
}
|
|
3841
4023
|
if (!node.leaf) {
|
|
3842
|
-
for (
|
|
4024
|
+
for (let i = 0, len = node.keys.length; i < len; i++) {
|
|
4025
|
+
const key2 = node.keys[i];
|
|
3843
4026
|
const n = this._cloneNode(await this.getNode(key2));
|
|
3844
4027
|
n.parent = node.id;
|
|
3845
4028
|
await this._updateNode(n);
|
|
3846
4029
|
}
|
|
3847
4030
|
}
|
|
3848
4031
|
if (!parentNode.leaf) {
|
|
3849
|
-
for (
|
|
4032
|
+
for (let i = 0, len = parentNode.keys.length; i < len; i++) {
|
|
4033
|
+
const key2 = parentNode.keys[i];
|
|
3850
4034
|
const n = this._cloneNode(await this.getNode(key2));
|
|
3851
4035
|
n.parent = parentNode.id;
|
|
3852
4036
|
await this._updateNode(n);
|
|
@@ -4032,6 +4216,16 @@ var BPTreeAsync = class extends BPTreeAsyncTransaction {
|
|
|
4032
4216
|
}
|
|
4033
4217
|
});
|
|
4034
4218
|
}
|
|
4219
|
+
async bulkLoad(entries) {
|
|
4220
|
+
return this.writeLock(1, async () => {
|
|
4221
|
+
const tx = await this.createTransaction();
|
|
4222
|
+
await tx.bulkLoad(entries);
|
|
4223
|
+
const result = await tx.commit();
|
|
4224
|
+
if (!result.success) {
|
|
4225
|
+
throw new Error(`Transaction failed: ${result.error || "Commit failed due to conflict"}`);
|
|
4226
|
+
}
|
|
4227
|
+
});
|
|
4228
|
+
}
|
|
4035
4229
|
};
|
|
4036
4230
|
|
|
4037
4231
|
// src/base/SerializeStrategy.ts
|
package/dist/esm/index.mjs
CHANGED
|
@@ -1888,30 +1888,22 @@ var BPTreeTransaction = class _BPTreeTransaction {
|
|
|
1888
1888
|
*/
|
|
1889
1889
|
_insertValueIntoLeaf(leaf, key, value) {
|
|
1890
1890
|
if (leaf.values.length) {
|
|
1891
|
-
|
|
1892
|
-
|
|
1893
|
-
if (
|
|
1894
|
-
|
|
1895
|
-
return false;
|
|
1896
|
-
}
|
|
1897
|
-
leaf.keys[i].push(key);
|
|
1898
|
-
return true;
|
|
1899
|
-
} else if (this.comparator.isLower(value, nValue)) {
|
|
1900
|
-
leaf.values.splice(i, 0, value);
|
|
1901
|
-
leaf.keys.splice(i, 0, [key]);
|
|
1902
|
-
return true;
|
|
1903
|
-
} else if (i + 1 === leaf.values.length) {
|
|
1904
|
-
leaf.values.push(value);
|
|
1905
|
-
leaf.keys.push([key]);
|
|
1906
|
-
return true;
|
|
1891
|
+
const { index, found } = this._binarySearchValues(leaf.values, value);
|
|
1892
|
+
if (found) {
|
|
1893
|
+
if (leaf.keys[index].includes(key)) {
|
|
1894
|
+
return false;
|
|
1907
1895
|
}
|
|
1896
|
+
leaf.keys[index].push(key);
|
|
1897
|
+
return true;
|
|
1908
1898
|
}
|
|
1899
|
+
leaf.values.splice(index, 0, value);
|
|
1900
|
+
leaf.keys.splice(index, 0, [key]);
|
|
1901
|
+
return true;
|
|
1909
1902
|
} else {
|
|
1910
1903
|
leaf.values = [value];
|
|
1911
1904
|
leaf.keys = [[key]];
|
|
1912
1905
|
return true;
|
|
1913
1906
|
}
|
|
1914
|
-
return false;
|
|
1915
1907
|
}
|
|
1916
1908
|
_cloneNode(node) {
|
|
1917
1909
|
return JSON.parse(JSON.stringify(node));
|
|
@@ -2204,12 +2196,8 @@ var BPTreeSyncTransaction = class extends BPTreeTransaction {
|
|
|
2204
2196
|
const midValue = parentNode.values[mid];
|
|
2205
2197
|
parentNode.values = parentNode.values.slice(0, mid);
|
|
2206
2198
|
parentNode.keys = parentNode.keys.slice(0, mid + 1);
|
|
2207
|
-
for (
|
|
2208
|
-
const
|
|
2209
|
-
n.parent = parentNode.id;
|
|
2210
|
-
this._updateNode(n);
|
|
2211
|
-
}
|
|
2212
|
-
for (const k of newSiblingNodeRecursive.keys) {
|
|
2199
|
+
for (let i = 0, len = newSiblingNodeRecursive.keys.length; i < len; i++) {
|
|
2200
|
+
const k = newSiblingNodeRecursive.keys[i];
|
|
2213
2201
|
const n = this._cloneNode(this.getNode(k));
|
|
2214
2202
|
n.parent = newSiblingNodeRecursive.id;
|
|
2215
2203
|
this._updateNode(n);
|
|
@@ -2291,7 +2279,7 @@ var BPTreeSyncTransaction = class extends BPTreeTransaction {
|
|
|
2291
2279
|
for (let i = 0; i < len; i++) {
|
|
2292
2280
|
const nValue = node.values[i];
|
|
2293
2281
|
const keys = node.keys[i];
|
|
2294
|
-
for (let j = 0,
|
|
2282
|
+
for (let j = 0, len2 = keys.length; j < len2; j++) {
|
|
2295
2283
|
yield [keys[j], nValue];
|
|
2296
2284
|
}
|
|
2297
2285
|
}
|
|
@@ -2370,7 +2358,7 @@ var BPTreeSyncTransaction = class extends BPTreeTransaction {
|
|
|
2370
2358
|
while (true) {
|
|
2371
2359
|
for (let i = 0, len = node.values.length; i < len; i++) {
|
|
2372
2360
|
const keys = node.keys[i];
|
|
2373
|
-
for (let j = 0,
|
|
2361
|
+
for (let j = 0, len2 = keys.length; j < len2; j++) {
|
|
2374
2362
|
if (keys[j] === key) {
|
|
2375
2363
|
return node.values[i];
|
|
2376
2364
|
}
|
|
@@ -2479,8 +2467,16 @@ var BPTreeSyncTransaction = class extends BPTreeTransaction {
|
|
|
2479
2467
|
const sorted = [...entries].sort((a, b) => this.comparator.asc(a[1], b[1]));
|
|
2480
2468
|
let currentLeaf = null;
|
|
2481
2469
|
let modified = false;
|
|
2482
|
-
|
|
2483
|
-
|
|
2470
|
+
let cachedLeafId = null;
|
|
2471
|
+
let cachedLeafMaxValue = null;
|
|
2472
|
+
for (let i = 0, len = sorted.length; i < len; i++) {
|
|
2473
|
+
const [key, value] = sorted[i];
|
|
2474
|
+
let targetLeaf;
|
|
2475
|
+
if (cachedLeafId !== null && cachedLeafMaxValue !== null && currentLeaf !== null && (this.comparator.isLower(value, cachedLeafMaxValue) || this.comparator.isSame(value, cachedLeafMaxValue))) {
|
|
2476
|
+
targetLeaf = currentLeaf;
|
|
2477
|
+
} else {
|
|
2478
|
+
targetLeaf = this.locateLeaf(value);
|
|
2479
|
+
}
|
|
2484
2480
|
if (currentLeaf !== null && currentLeaf.id === targetLeaf.id) {
|
|
2485
2481
|
} else {
|
|
2486
2482
|
if (currentLeaf !== null && modified) {
|
|
@@ -2489,8 +2485,10 @@ var BPTreeSyncTransaction = class extends BPTreeTransaction {
|
|
|
2489
2485
|
currentLeaf = this._cloneNode(targetLeaf);
|
|
2490
2486
|
modified = false;
|
|
2491
2487
|
}
|
|
2488
|
+
cachedLeafId = currentLeaf.id;
|
|
2492
2489
|
const changed = this._insertValueIntoLeaf(currentLeaf, key, value);
|
|
2493
2490
|
modified = modified || changed;
|
|
2491
|
+
cachedLeafMaxValue = currentLeaf.values[currentLeaf.values.length - 1];
|
|
2494
2492
|
if (currentLeaf.values.length === this.order) {
|
|
2495
2493
|
this._updateNode(currentLeaf);
|
|
2496
2494
|
let after = this._createNode(
|
|
@@ -2511,6 +2509,8 @@ var BPTreeSyncTransaction = class extends BPTreeTransaction {
|
|
|
2511
2509
|
this._updateNode(after);
|
|
2512
2510
|
this._insertInParent(currentLeaf, after.values[0], after);
|
|
2513
2511
|
currentLeaf = null;
|
|
2512
|
+
cachedLeafId = null;
|
|
2513
|
+
cachedLeafMaxValue = null;
|
|
2514
2514
|
modified = false;
|
|
2515
2515
|
}
|
|
2516
2516
|
}
|
|
@@ -2518,6 +2518,85 @@ var BPTreeSyncTransaction = class extends BPTreeTransaction {
|
|
|
2518
2518
|
this._updateNode(currentLeaf);
|
|
2519
2519
|
}
|
|
2520
2520
|
}
|
|
2521
|
+
bulkLoad(entries) {
|
|
2522
|
+
if (entries.length === 0) return;
|
|
2523
|
+
const root = this.getNode(this.rootId);
|
|
2524
|
+
if (!root.leaf || root.values.length > 0) {
|
|
2525
|
+
throw new Error("bulkLoad can only be called on an empty tree. Use batchInsert for non-empty trees.");
|
|
2526
|
+
}
|
|
2527
|
+
const sorted = [...entries].sort((a, b) => this.comparator.asc(a[1], b[1]));
|
|
2528
|
+
const grouped = [];
|
|
2529
|
+
for (let i = 0, len = sorted.length; i < len; i++) {
|
|
2530
|
+
const [key, value] = sorted[i];
|
|
2531
|
+
const last = grouped[grouped.length - 1];
|
|
2532
|
+
if (last && this.comparator.isSame(last.value, value)) {
|
|
2533
|
+
if (!last.keys.includes(key)) {
|
|
2534
|
+
last.keys.push(key);
|
|
2535
|
+
}
|
|
2536
|
+
} else {
|
|
2537
|
+
grouped.push({ keys: [key], value });
|
|
2538
|
+
}
|
|
2539
|
+
}
|
|
2540
|
+
this._deleteNode(root);
|
|
2541
|
+
const maxLeafSize = this.order - 1;
|
|
2542
|
+
const leaves = [];
|
|
2543
|
+
for (let i = 0, len = grouped.length; i < len; i += maxLeafSize) {
|
|
2544
|
+
const chunk = grouped.slice(i, i + maxLeafSize);
|
|
2545
|
+
const leafKeys = chunk.map((g) => g.keys);
|
|
2546
|
+
const leafValues = chunk.map((g) => g.value);
|
|
2547
|
+
const leaf = this._createNode(
|
|
2548
|
+
true,
|
|
2549
|
+
leafKeys,
|
|
2550
|
+
leafValues,
|
|
2551
|
+
null,
|
|
2552
|
+
null,
|
|
2553
|
+
null
|
|
2554
|
+
);
|
|
2555
|
+
leaves.push(leaf);
|
|
2556
|
+
}
|
|
2557
|
+
for (let i = 0, len = leaves.length; i < len; i++) {
|
|
2558
|
+
if (i > 0) {
|
|
2559
|
+
leaves[i].prev = leaves[i - 1].id;
|
|
2560
|
+
}
|
|
2561
|
+
if (i < len - 1) {
|
|
2562
|
+
leaves[i].next = leaves[i + 1].id;
|
|
2563
|
+
}
|
|
2564
|
+
this._updateNode(leaves[i]);
|
|
2565
|
+
}
|
|
2566
|
+
let currentLevel = leaves;
|
|
2567
|
+
while (currentLevel.length > 1) {
|
|
2568
|
+
const nextLevel = [];
|
|
2569
|
+
for (let i = 0, len = currentLevel.length; i < len; i += this.order) {
|
|
2570
|
+
const children = currentLevel.slice(i, i + this.order);
|
|
2571
|
+
const childIds = children.map((c) => c.id);
|
|
2572
|
+
const separators = [];
|
|
2573
|
+
for (let j = 1, len2 = children.length; j < len2; j++) {
|
|
2574
|
+
separators.push(children[j].values[0]);
|
|
2575
|
+
}
|
|
2576
|
+
const internalNode = this._createNode(
|
|
2577
|
+
false,
|
|
2578
|
+
childIds,
|
|
2579
|
+
separators,
|
|
2580
|
+
null,
|
|
2581
|
+
null,
|
|
2582
|
+
null
|
|
2583
|
+
);
|
|
2584
|
+
for (let j = 0, len2 = children.length; j < len2; j++) {
|
|
2585
|
+
const child = children[j];
|
|
2586
|
+
child.parent = internalNode.id;
|
|
2587
|
+
this._updateNode(child);
|
|
2588
|
+
}
|
|
2589
|
+
nextLevel.push(internalNode);
|
|
2590
|
+
}
|
|
2591
|
+
currentLevel = nextLevel;
|
|
2592
|
+
}
|
|
2593
|
+
const newRoot = currentLevel[0];
|
|
2594
|
+
this._writeHead({
|
|
2595
|
+
root: newRoot.id,
|
|
2596
|
+
order: this.order,
|
|
2597
|
+
data: this.strategy.head.data
|
|
2598
|
+
});
|
|
2599
|
+
}
|
|
2521
2600
|
_deleteEntry(node, key) {
|
|
2522
2601
|
if (!node.leaf) {
|
|
2523
2602
|
let keyIndex = -1;
|
|
@@ -2621,7 +2700,8 @@ var BPTreeSyncTransaction = class extends BPTreeTransaction {
|
|
|
2621
2700
|
siblingNode.values.push(...node.values);
|
|
2622
2701
|
if (!siblingNode.leaf) {
|
|
2623
2702
|
const keys = siblingNode.keys;
|
|
2624
|
-
for (
|
|
2703
|
+
for (let i = 0, len = keys.length; i < len; i++) {
|
|
2704
|
+
const key2 = keys[i];
|
|
2625
2705
|
const node2 = this._cloneNode(this.getNode(key2));
|
|
2626
2706
|
node2.parent = siblingNode.id;
|
|
2627
2707
|
this._updateNode(node2);
|
|
@@ -2689,21 +2769,24 @@ var BPTreeSyncTransaction = class extends BPTreeTransaction {
|
|
|
2689
2769
|
this._updateNode(siblingNode);
|
|
2690
2770
|
}
|
|
2691
2771
|
if (!siblingNode.leaf) {
|
|
2692
|
-
for (
|
|
2772
|
+
for (let i = 0, len = siblingNode.keys.length; i < len; i++) {
|
|
2773
|
+
const key2 = siblingNode.keys[i];
|
|
2693
2774
|
const n = this._cloneNode(this.getNode(key2));
|
|
2694
2775
|
n.parent = siblingNode.id;
|
|
2695
2776
|
this._updateNode(n);
|
|
2696
2777
|
}
|
|
2697
2778
|
}
|
|
2698
2779
|
if (!node.leaf) {
|
|
2699
|
-
for (
|
|
2780
|
+
for (let i = 0, len = node.keys.length; i < len; i++) {
|
|
2781
|
+
const key2 = node.keys[i];
|
|
2700
2782
|
const n = this._cloneNode(this.getNode(key2));
|
|
2701
2783
|
n.parent = node.id;
|
|
2702
2784
|
this._updateNode(n);
|
|
2703
2785
|
}
|
|
2704
2786
|
}
|
|
2705
2787
|
if (!parentNode.leaf) {
|
|
2706
|
-
for (
|
|
2788
|
+
for (let i = 0, len = parentNode.keys.length; i < len; i++) {
|
|
2789
|
+
const key2 = parentNode.keys[i];
|
|
2707
2790
|
const n = this._cloneNode(this.getNode(key2));
|
|
2708
2791
|
n.parent = parentNode.id;
|
|
2709
2792
|
this._updateNode(n);
|
|
@@ -2881,6 +2964,14 @@ var BPTreeSync = class extends BPTreeSyncTransaction {
|
|
|
2881
2964
|
throw new Error(`Transaction failed: ${result.error || "Commit failed due to conflict"}`);
|
|
2882
2965
|
}
|
|
2883
2966
|
}
|
|
2967
|
+
bulkLoad(entries) {
|
|
2968
|
+
const tx = this.createTransaction();
|
|
2969
|
+
tx.bulkLoad(entries);
|
|
2970
|
+
const result = tx.commit();
|
|
2971
|
+
if (!result.success) {
|
|
2972
|
+
throw new Error(`Transaction failed: ${result.error || "Commit failed due to conflict"}`);
|
|
2973
|
+
}
|
|
2974
|
+
}
|
|
2884
2975
|
};
|
|
2885
2976
|
|
|
2886
2977
|
// node_modules/ryoiki/dist/esm/index.mjs
|
|
@@ -3298,12 +3389,8 @@ var BPTreeAsyncTransaction = class extends BPTreeTransaction {
|
|
|
3298
3389
|
const midValue = parentNode.values[mid];
|
|
3299
3390
|
parentNode.values = parentNode.values.slice(0, mid);
|
|
3300
3391
|
parentNode.keys = parentNode.keys.slice(0, mid + 1);
|
|
3301
|
-
for (
|
|
3302
|
-
const
|
|
3303
|
-
n.parent = parentNode.id;
|
|
3304
|
-
await this._updateNode(n);
|
|
3305
|
-
}
|
|
3306
|
-
for (const k of newSiblingNodeRecursive.keys) {
|
|
3392
|
+
for (let i = 0, len = newSiblingNodeRecursive.keys.length; i < len; i++) {
|
|
3393
|
+
const k = newSiblingNodeRecursive.keys[i];
|
|
3307
3394
|
const n = this._cloneNode(await this.getNode(k));
|
|
3308
3395
|
n.parent = newSiblingNodeRecursive.id;
|
|
3309
3396
|
await this._updateNode(n);
|
|
@@ -3395,7 +3482,7 @@ var BPTreeAsyncTransaction = class extends BPTreeTransaction {
|
|
|
3395
3482
|
for (let i = 0; i < len; i++) {
|
|
3396
3483
|
const nValue = node.values[i];
|
|
3397
3484
|
const keys = node.keys[i];
|
|
3398
|
-
for (let j = 0,
|
|
3485
|
+
for (let j = 0, len2 = keys.length; j < len2; j++) {
|
|
3399
3486
|
yield [keys[j], nValue];
|
|
3400
3487
|
}
|
|
3401
3488
|
}
|
|
@@ -3473,7 +3560,7 @@ var BPTreeAsyncTransaction = class extends BPTreeTransaction {
|
|
|
3473
3560
|
while (true) {
|
|
3474
3561
|
for (let i = 0, len = node.values.length; i < len; i++) {
|
|
3475
3562
|
const keys = node.keys[i];
|
|
3476
|
-
for (let j = 0,
|
|
3563
|
+
for (let j = 0, len2 = keys.length; j < len2; j++) {
|
|
3477
3564
|
if (keys[j] === key) {
|
|
3478
3565
|
return node.values[i];
|
|
3479
3566
|
}
|
|
@@ -3585,8 +3672,16 @@ var BPTreeAsyncTransaction = class extends BPTreeTransaction {
|
|
|
3585
3672
|
const sorted = [...entries].sort((a, b) => this.comparator.asc(a[1], b[1]));
|
|
3586
3673
|
let currentLeaf = null;
|
|
3587
3674
|
let modified = false;
|
|
3588
|
-
|
|
3589
|
-
|
|
3675
|
+
let cachedLeafId = null;
|
|
3676
|
+
let cachedLeafMaxValue = null;
|
|
3677
|
+
for (let i = 0, len = sorted.length; i < len; i++) {
|
|
3678
|
+
const [key, value] = sorted[i];
|
|
3679
|
+
let targetLeaf;
|
|
3680
|
+
if (cachedLeafId !== null && cachedLeafMaxValue !== null && currentLeaf !== null && (this.comparator.isLower(value, cachedLeafMaxValue) || this.comparator.isSame(value, cachedLeafMaxValue))) {
|
|
3681
|
+
targetLeaf = currentLeaf;
|
|
3682
|
+
} else {
|
|
3683
|
+
targetLeaf = await this.locateLeaf(value);
|
|
3684
|
+
}
|
|
3590
3685
|
if (currentLeaf !== null && currentLeaf.id === targetLeaf.id) {
|
|
3591
3686
|
} else {
|
|
3592
3687
|
if (currentLeaf !== null && modified) {
|
|
@@ -3595,8 +3690,10 @@ var BPTreeAsyncTransaction = class extends BPTreeTransaction {
|
|
|
3595
3690
|
currentLeaf = this._cloneNode(targetLeaf);
|
|
3596
3691
|
modified = false;
|
|
3597
3692
|
}
|
|
3693
|
+
cachedLeafId = currentLeaf.id;
|
|
3598
3694
|
const changed = this._insertValueIntoLeaf(currentLeaf, key, value);
|
|
3599
3695
|
modified = modified || changed;
|
|
3696
|
+
cachedLeafMaxValue = currentLeaf.values[currentLeaf.values.length - 1];
|
|
3600
3697
|
if (currentLeaf.values.length === this.order) {
|
|
3601
3698
|
await this._updateNode(currentLeaf);
|
|
3602
3699
|
let after = await this._createNode(
|
|
@@ -3617,6 +3714,8 @@ var BPTreeAsyncTransaction = class extends BPTreeTransaction {
|
|
|
3617
3714
|
await this._updateNode(after);
|
|
3618
3715
|
await this._insertInParent(currentLeaf, after.values[0], after);
|
|
3619
3716
|
currentLeaf = null;
|
|
3717
|
+
cachedLeafId = null;
|
|
3718
|
+
cachedLeafMaxValue = null;
|
|
3620
3719
|
modified = false;
|
|
3621
3720
|
}
|
|
3622
3721
|
}
|
|
@@ -3625,6 +3724,87 @@ var BPTreeAsyncTransaction = class extends BPTreeTransaction {
|
|
|
3625
3724
|
}
|
|
3626
3725
|
});
|
|
3627
3726
|
}
|
|
3727
|
+
async bulkLoad(entries) {
|
|
3728
|
+
if (entries.length === 0) return;
|
|
3729
|
+
return this.writeLock(0, async () => {
|
|
3730
|
+
const root = await this.getNode(this.rootId);
|
|
3731
|
+
if (!root.leaf || root.values.length > 0) {
|
|
3732
|
+
throw new Error("bulkLoad can only be called on an empty tree. Use batchInsert for non-empty trees.");
|
|
3733
|
+
}
|
|
3734
|
+
const sorted = [...entries].sort((a, b) => this.comparator.asc(a[1], b[1]));
|
|
3735
|
+
const grouped = [];
|
|
3736
|
+
for (let i = 0, len = sorted.length; i < len; i++) {
|
|
3737
|
+
const [key, value] = sorted[i];
|
|
3738
|
+
const last = grouped[grouped.length - 1];
|
|
3739
|
+
if (last && this.comparator.isSame(last.value, value)) {
|
|
3740
|
+
if (!last.keys.includes(key)) {
|
|
3741
|
+
last.keys.push(key);
|
|
3742
|
+
}
|
|
3743
|
+
} else {
|
|
3744
|
+
grouped.push({ keys: [key], value });
|
|
3745
|
+
}
|
|
3746
|
+
}
|
|
3747
|
+
await this._deleteNode(root);
|
|
3748
|
+
const maxLeafSize = this.order - 1;
|
|
3749
|
+
const leaves = [];
|
|
3750
|
+
for (let i = 0, len = grouped.length; i < len; i += maxLeafSize) {
|
|
3751
|
+
const chunk = grouped.slice(i, i + maxLeafSize);
|
|
3752
|
+
const leafKeys = chunk.map((g) => g.keys);
|
|
3753
|
+
const leafValues = chunk.map((g) => g.value);
|
|
3754
|
+
const leaf = await this._createNode(
|
|
3755
|
+
true,
|
|
3756
|
+
leafKeys,
|
|
3757
|
+
leafValues,
|
|
3758
|
+
null,
|
|
3759
|
+
null,
|
|
3760
|
+
null
|
|
3761
|
+
);
|
|
3762
|
+
leaves.push(leaf);
|
|
3763
|
+
}
|
|
3764
|
+
for (let i = 0, len = leaves.length; i < len; i++) {
|
|
3765
|
+
if (i > 0) {
|
|
3766
|
+
leaves[i].prev = leaves[i - 1].id;
|
|
3767
|
+
}
|
|
3768
|
+
if (i < len - 1) {
|
|
3769
|
+
leaves[i].next = leaves[i + 1].id;
|
|
3770
|
+
}
|
|
3771
|
+
await this._updateNode(leaves[i]);
|
|
3772
|
+
}
|
|
3773
|
+
let currentLevel = leaves;
|
|
3774
|
+
while (currentLevel.length > 1) {
|
|
3775
|
+
const nextLevel = [];
|
|
3776
|
+
for (let i = 0, len = currentLevel.length; i < len; i += this.order) {
|
|
3777
|
+
const children = currentLevel.slice(i, i + this.order);
|
|
3778
|
+
const childIds = children.map((c) => c.id);
|
|
3779
|
+
const separators = [];
|
|
3780
|
+
for (let j = 1, len2 = children.length; j < len2; j++) {
|
|
3781
|
+
separators.push(children[j].values[0]);
|
|
3782
|
+
}
|
|
3783
|
+
const internalNode = await this._createNode(
|
|
3784
|
+
false,
|
|
3785
|
+
childIds,
|
|
3786
|
+
separators,
|
|
3787
|
+
null,
|
|
3788
|
+
null,
|
|
3789
|
+
null
|
|
3790
|
+
);
|
|
3791
|
+
for (let j = 0, len2 = children.length; j < len2; j++) {
|
|
3792
|
+
const child = children[j];
|
|
3793
|
+
child.parent = internalNode.id;
|
|
3794
|
+
await this._updateNode(child);
|
|
3795
|
+
}
|
|
3796
|
+
nextLevel.push(internalNode);
|
|
3797
|
+
}
|
|
3798
|
+
currentLevel = nextLevel;
|
|
3799
|
+
}
|
|
3800
|
+
const newRoot = currentLevel[0];
|
|
3801
|
+
await this._writeHead({
|
|
3802
|
+
root: newRoot.id,
|
|
3803
|
+
order: this.order,
|
|
3804
|
+
data: this.strategy.head.data
|
|
3805
|
+
});
|
|
3806
|
+
});
|
|
3807
|
+
}
|
|
3628
3808
|
async _deleteEntry(node, key) {
|
|
3629
3809
|
if (!node.leaf) {
|
|
3630
3810
|
let keyIndex = -1;
|
|
@@ -3728,7 +3908,8 @@ var BPTreeAsyncTransaction = class extends BPTreeTransaction {
|
|
|
3728
3908
|
siblingNode.values.push(...node.values);
|
|
3729
3909
|
if (!siblingNode.leaf) {
|
|
3730
3910
|
const keys = siblingNode.keys;
|
|
3731
|
-
for (
|
|
3911
|
+
for (let i = 0, len = keys.length; i < len; i++) {
|
|
3912
|
+
const key2 = keys[i];
|
|
3732
3913
|
const node2 = this._cloneNode(await this.getNode(key2));
|
|
3733
3914
|
node2.parent = siblingNode.id;
|
|
3734
3915
|
await this._updateNode(node2);
|
|
@@ -3796,21 +3977,24 @@ var BPTreeAsyncTransaction = class extends BPTreeTransaction {
|
|
|
3796
3977
|
await this._updateNode(siblingNode);
|
|
3797
3978
|
}
|
|
3798
3979
|
if (!siblingNode.leaf) {
|
|
3799
|
-
for (
|
|
3980
|
+
for (let i = 0, len = siblingNode.keys.length; i < len; i++) {
|
|
3981
|
+
const key2 = siblingNode.keys[i];
|
|
3800
3982
|
const n = this._cloneNode(await this.getNode(key2));
|
|
3801
3983
|
n.parent = siblingNode.id;
|
|
3802
3984
|
await this._updateNode(n);
|
|
3803
3985
|
}
|
|
3804
3986
|
}
|
|
3805
3987
|
if (!node.leaf) {
|
|
3806
|
-
for (
|
|
3988
|
+
for (let i = 0, len = node.keys.length; i < len; i++) {
|
|
3989
|
+
const key2 = node.keys[i];
|
|
3807
3990
|
const n = this._cloneNode(await this.getNode(key2));
|
|
3808
3991
|
n.parent = node.id;
|
|
3809
3992
|
await this._updateNode(n);
|
|
3810
3993
|
}
|
|
3811
3994
|
}
|
|
3812
3995
|
if (!parentNode.leaf) {
|
|
3813
|
-
for (
|
|
3996
|
+
for (let i = 0, len = parentNode.keys.length; i < len; i++) {
|
|
3997
|
+
const key2 = parentNode.keys[i];
|
|
3814
3998
|
const n = this._cloneNode(await this.getNode(key2));
|
|
3815
3999
|
n.parent = parentNode.id;
|
|
3816
4000
|
await this._updateNode(n);
|
|
@@ -3996,6 +4180,16 @@ var BPTreeAsync = class extends BPTreeAsyncTransaction {
|
|
|
3996
4180
|
}
|
|
3997
4181
|
});
|
|
3998
4182
|
}
|
|
4183
|
+
async bulkLoad(entries) {
|
|
4184
|
+
return this.writeLock(1, async () => {
|
|
4185
|
+
const tx = await this.createTransaction();
|
|
4186
|
+
await tx.bulkLoad(entries);
|
|
4187
|
+
const result = await tx.commit();
|
|
4188
|
+
if (!result.success) {
|
|
4189
|
+
throw new Error(`Transaction failed: ${result.error || "Commit failed due to conflict"}`);
|
|
4190
|
+
}
|
|
4191
|
+
});
|
|
4192
|
+
}
|
|
3999
4193
|
};
|
|
4000
4194
|
|
|
4001
4195
|
// src/base/SerializeStrategy.ts
|
|
@@ -12,4 +12,5 @@ export declare class BPTreeAsync<K, V> extends BPTreeAsyncTransaction<K, V> {
|
|
|
12
12
|
insert(key: K, value: V): Promise<void>;
|
|
13
13
|
delete(key: K, value?: V): Promise<void>;
|
|
14
14
|
batchInsert(entries: [K, V][]): Promise<void>;
|
|
15
|
+
bulkLoad(entries: [K, V][]): Promise<void>;
|
|
15
16
|
}
|
|
@@ -173,6 +173,18 @@ export declare abstract class BPTreeTransaction<K, V> {
|
|
|
173
173
|
* @param entries Array of [key, value] pairs to insert.
|
|
174
174
|
*/
|
|
175
175
|
abstract batchInsert(entries: [K, V][]): Deferred<void>;
|
|
176
|
+
/**
|
|
177
|
+
* Builds a B+Tree from scratch using bulk loading (bottom-up construction).
|
|
178
|
+
* This is significantly faster than batchInsert for initial tree construction,
|
|
179
|
+
* as it avoids top-down traversal and creates nodes directly.
|
|
180
|
+
*
|
|
181
|
+
* **Precondition**: The tree must be empty. If the tree already contains data,
|
|
182
|
+
* an error will be thrown. Use batchInsert for adding data to an existing tree.
|
|
183
|
+
*
|
|
184
|
+
* @param entries Array of [key, value] pairs to bulk load.
|
|
185
|
+
* @throws Error if the tree is not empty.
|
|
186
|
+
*/
|
|
187
|
+
abstract bulkLoad(entries: [K, V][]): Deferred<void>;
|
|
176
188
|
/**
|
|
177
189
|
* Deletes the pair that matches the key and value.
|
|
178
190
|
* @param key The key of the pair. This key must be unique.
|
|
@@ -42,6 +42,7 @@ export declare class BPTreeAsyncTransaction<K, V> extends BPTreeTransaction<K, V
|
|
|
42
42
|
where(condition: BPTreeCondition<V>, options?: BPTreeSearchOption<K>): Promise<BPTreePair<K, V>>;
|
|
43
43
|
insert(key: K, value: V): Promise<void>;
|
|
44
44
|
batchInsert(entries: [K, V][]): Promise<void>;
|
|
45
|
+
bulkLoad(entries: [K, V][]): Promise<void>;
|
|
45
46
|
protected _deleteEntry(node: BPTreeUnknownNode<K, V>, key: BPTreeNodeKey<K>): Promise<BPTreeUnknownNode<K, V>>;
|
|
46
47
|
delete(key: K, value?: V): Promise<void>;
|
|
47
48
|
getHeadData(): Promise<SerializableData>;
|
|
@@ -39,6 +39,7 @@ export declare class BPTreeSyncTransaction<K, V> extends BPTreeTransaction<K, V>
|
|
|
39
39
|
where(condition: BPTreeCondition<V>, options?: BPTreeSearchOption<K>): BPTreePair<K, V>;
|
|
40
40
|
insert(key: K, value: V): void;
|
|
41
41
|
batchInsert(entries: [K, V][]): void;
|
|
42
|
+
bulkLoad(entries: [K, V][]): void;
|
|
42
43
|
protected _deleteEntry(node: BPTreeUnknownNode<K, V>, key: BPTreeNodeKey<K>): BPTreeUnknownNode<K, V>;
|
|
43
44
|
delete(key: K, value?: V): void;
|
|
44
45
|
getHeadData(): SerializableData;
|