serializable-bptree 5.2.1 → 6.0.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 +18 -17
- package/dist/cjs/index.cjs +116 -82
- package/dist/esm/index.mjs +116 -82
- package/dist/types/BPTreeAsync.d.ts +2 -2
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -15,7 +15,7 @@ import {
|
|
|
15
15
|
|
|
16
16
|
class FileStoreStrategySync extends SerializeStrategySync<K, V> {
|
|
17
17
|
id(): string {
|
|
18
|
-
return
|
|
18
|
+
return crypto.randomUUID()
|
|
19
19
|
}
|
|
20
20
|
|
|
21
21
|
read(id: string): BPTreeNode<K, V> {
|
|
@@ -105,10 +105,19 @@ import {
|
|
|
105
105
|
ValueComparator,
|
|
106
106
|
NumericComparator,
|
|
107
107
|
StringComparator
|
|
108
|
-
} from 'https://cdn.jsdelivr.
|
|
108
|
+
} from 'https://cdn.jsdelivr.com/npm/serializable-bptree@6/+esm'
|
|
109
109
|
</script>
|
|
110
110
|
```
|
|
111
111
|
|
|
112
|
+
## Migration from v5.x.x to v6.0.0
|
|
113
|
+
|
|
114
|
+
Version 6.0.0 includes a critical fix for how internal nodes are sorted.
|
|
115
|
+
|
|
116
|
+
> [!IMPORTANT]
|
|
117
|
+
> **Breaking Changes & Incompatibility**
|
|
118
|
+
> In previous versions, internal nodes were not strictly sorted by value magnitude, which could lead to incorrect traversals and failed queries (especially for the last nodes in a branch).
|
|
119
|
+
> v6.0.0 enforces strict value sorting. **Data structures created with v5.x.x or earlier may be incompatible** with v6.0.0 if they contain unsorted internal nodes. It is highly recommended to rebuild your tree from scratch when upgrading.
|
|
120
|
+
|
|
112
121
|
## Conceptualization
|
|
113
122
|
|
|
114
123
|
### Value comparator
|
|
@@ -199,21 +208,11 @@ What does this method mean? And why do we need to construct such a method?
|
|
|
199
208
|
|
|
200
209
|
When a node is created in the B+tree, the node needs a unique value to represent itself. This is the **node.id** attribute, and you can specify this attribute yourself.
|
|
201
210
|
|
|
202
|
-
Typically, such an **id** value
|
|
203
|
-
|
|
204
|
-
```typescript
|
|
205
|
-
id(isLeaf: boolean): string {
|
|
206
|
-
const current = this.getHeadData('index', 1) as number
|
|
207
|
-
this.setHeadData('index', current+1)
|
|
208
|
-
return current.toString()
|
|
209
|
-
}
|
|
210
|
-
```
|
|
211
|
-
|
|
212
|
-
Additionally, there is a more dev-friendly usage of this code.
|
|
211
|
+
Typically, such an **id** value can be a unique string like a UUID. Below is an example of usage:
|
|
213
212
|
|
|
214
213
|
```typescript
|
|
215
214
|
id(isLeaf: boolean): string {
|
|
216
|
-
return
|
|
215
|
+
return crypto.randomUUID()
|
|
217
216
|
}
|
|
218
217
|
```
|
|
219
218
|
|
|
@@ -415,7 +414,7 @@ import {
|
|
|
415
414
|
|
|
416
415
|
class FileStoreStrategyAsync extends SerializeStrategyAsync<K, V> {
|
|
417
416
|
async id(isLeaf: boolean): Promise<string> {
|
|
418
|
-
return
|
|
417
|
+
return crypto.randomUUID()
|
|
419
418
|
}
|
|
420
419
|
|
|
421
420
|
async read(id: string): Promise<BPTreeNode<K, V>> {
|
|
@@ -473,9 +472,11 @@ The implementation method for asynchronous operations is not significantly diffe
|
|
|
473
472
|
|
|
474
473
|
### Synchronization Issue
|
|
475
474
|
|
|
476
|
-
The serializable-bptree minimizes file I/O by storing loaded nodes in-memory. This approach works
|
|
475
|
+
The serializable-bptree minimizes file I/O by storing loaded nodes in-memory (caching). This approach works perfectly when a single tree instance is used for a given storage.
|
|
476
|
+
|
|
477
|
+
However, if **multiple BPTree instances** (e.g., across different processes or servers) read from and write to a **single shared storage**, data inconsistency can occur. This is because each instance maintains its own independent in-memory cache, and changes made by one instance are not automatically reflected in the others.
|
|
477
478
|
|
|
478
|
-
To solve this problem,
|
|
479
|
+
To solve this problem, you must synchronize the cached nodes across all instances. The `forceUpdate` method can be used to refresh the nodes cached in a tree instance. When one instance saves data to the shared storage, you should implement a signaling mechanism (e.g., via Pub/Sub or WebSockets) to notify other instances that a node has been updated. Upon receiving this signal, the other instances should call the `forceUpdate` method to ensure they are working with the latest data.
|
|
479
480
|
|
|
480
481
|
### Concurrency Issue in Asynchronous Trees
|
|
481
482
|
|
package/dist/cjs/index.cjs
CHANGED
|
@@ -769,6 +769,9 @@ var BPTreeSync = class extends BPTree {
|
|
|
769
769
|
guess = prevValue;
|
|
770
770
|
}
|
|
771
771
|
}
|
|
772
|
+
if (!pointer) {
|
|
773
|
+
return;
|
|
774
|
+
}
|
|
772
775
|
if (node.values.length + pointer.values.length < this.order) {
|
|
773
776
|
if (!isPredecessor) {
|
|
774
777
|
const pTemp = pointer;
|
|
@@ -908,44 +911,65 @@ var BPTreeSync = class extends BPTree {
|
|
|
908
911
|
this.strategy.head.root = root.id;
|
|
909
912
|
node.parent = root.id;
|
|
910
913
|
pointer.parent = root.id;
|
|
914
|
+
if (pointer.leaf) {
|
|
915
|
+
node.next = pointer.id;
|
|
916
|
+
pointer.prev = node.id;
|
|
917
|
+
}
|
|
911
918
|
this.bufferForNodeUpdate(node);
|
|
912
919
|
this.bufferForNodeUpdate(pointer);
|
|
913
920
|
return;
|
|
914
921
|
}
|
|
915
922
|
const parentNode = this.getNode(node.parent);
|
|
916
|
-
|
|
917
|
-
|
|
918
|
-
if (
|
|
919
|
-
|
|
920
|
-
|
|
921
|
-
|
|
922
|
-
|
|
923
|
-
|
|
924
|
-
|
|
925
|
-
|
|
926
|
-
|
|
927
|
-
|
|
928
|
-
|
|
929
|
-
|
|
930
|
-
|
|
931
|
-
|
|
932
|
-
|
|
933
|
-
|
|
934
|
-
|
|
935
|
-
|
|
936
|
-
|
|
937
|
-
|
|
938
|
-
|
|
939
|
-
|
|
940
|
-
|
|
941
|
-
|
|
942
|
-
|
|
943
|
-
|
|
944
|
-
|
|
945
|
-
|
|
946
|
-
|
|
947
|
-
|
|
923
|
+
let insertIndex = 0;
|
|
924
|
+
for (let i = 0; i < parentNode.values.length; i++) {
|
|
925
|
+
if (this.comparator.asc(value, parentNode.values[i]) > 0) {
|
|
926
|
+
insertIndex = i + 1;
|
|
927
|
+
} else {
|
|
928
|
+
break;
|
|
929
|
+
}
|
|
930
|
+
}
|
|
931
|
+
parentNode.values.splice(insertIndex, 0, value);
|
|
932
|
+
parentNode.keys.splice(insertIndex + 1, 0, pointer.id);
|
|
933
|
+
pointer.parent = parentNode.id;
|
|
934
|
+
if (pointer.leaf) {
|
|
935
|
+
const leftSiblingId = parentNode.keys[insertIndex];
|
|
936
|
+
const rightSiblingId = parentNode.keys[insertIndex + 2];
|
|
937
|
+
if (leftSiblingId) {
|
|
938
|
+
const leftSibling = this.getNode(leftSiblingId);
|
|
939
|
+
pointer.prev = leftSibling.id;
|
|
940
|
+
pointer.next = leftSibling.next;
|
|
941
|
+
leftSibling.next = pointer.id;
|
|
942
|
+
this.bufferForNodeUpdate(leftSibling);
|
|
943
|
+
}
|
|
944
|
+
if (rightSiblingId) {
|
|
945
|
+
const rightSibling = this.getNode(rightSiblingId);
|
|
946
|
+
rightSibling.prev = pointer.id;
|
|
947
|
+
this.bufferForNodeUpdate(rightSibling);
|
|
948
|
+
}
|
|
949
|
+
}
|
|
950
|
+
this.bufferForNodeUpdate(parentNode);
|
|
951
|
+
this.bufferForNodeUpdate(pointer);
|
|
952
|
+
if (parentNode.keys.length > this.order) {
|
|
953
|
+
const parentPointer = this._createNode(false, [], []);
|
|
954
|
+
parentPointer.parent = parentNode.parent;
|
|
955
|
+
const mid = Math.ceil(this.order / 2) - 1;
|
|
956
|
+
parentPointer.values = parentNode.values.slice(mid + 1);
|
|
957
|
+
parentPointer.keys = parentNode.keys.slice(mid + 1);
|
|
958
|
+
const midValue = parentNode.values[mid];
|
|
959
|
+
parentNode.values = parentNode.values.slice(0, mid);
|
|
960
|
+
parentNode.keys = parentNode.keys.slice(0, mid + 1);
|
|
961
|
+
for (const k of parentNode.keys) {
|
|
962
|
+
const node2 = this.getNode(k);
|
|
963
|
+
node2.parent = parentNode.id;
|
|
964
|
+
this.bufferForNodeUpdate(node2);
|
|
965
|
+
}
|
|
966
|
+
for (const k of parentPointer.keys) {
|
|
967
|
+
const node2 = this.getNode(k);
|
|
968
|
+
node2.parent = parentPointer.id;
|
|
969
|
+
this.bufferForNodeUpdate(node2);
|
|
948
970
|
}
|
|
971
|
+
this._insertInParent(parentNode, midValue, parentPointer);
|
|
972
|
+
this.bufferForNodeUpdate(parentNode);
|
|
949
973
|
}
|
|
950
974
|
}
|
|
951
975
|
init() {
|
|
@@ -1111,21 +1135,14 @@ var BPTreeSync = class extends BPTree {
|
|
|
1111
1135
|
[],
|
|
1112
1136
|
true,
|
|
1113
1137
|
before.parent,
|
|
1114
|
-
|
|
1115
|
-
|
|
1138
|
+
null,
|
|
1139
|
+
null
|
|
1116
1140
|
);
|
|
1117
1141
|
const mid = Math.ceil(this.order / 2) - 1;
|
|
1118
|
-
const beforeNext = before.next;
|
|
1119
1142
|
after.values = before.values.slice(mid + 1);
|
|
1120
1143
|
after.keys = before.keys.slice(mid + 1);
|
|
1121
1144
|
before.values = before.values.slice(0, mid + 1);
|
|
1122
1145
|
before.keys = before.keys.slice(0, mid + 1);
|
|
1123
|
-
before.next = after.id;
|
|
1124
|
-
if (beforeNext) {
|
|
1125
|
-
const node = this.getNode(beforeNext);
|
|
1126
|
-
node.prev = after.id;
|
|
1127
|
-
this.bufferForNodeUpdate(node);
|
|
1128
|
-
}
|
|
1129
1146
|
this._insertInParent(before, after.values[0], after);
|
|
1130
1147
|
this.bufferForNodeUpdate(before);
|
|
1131
1148
|
}
|
|
@@ -1639,6 +1656,9 @@ var BPTreeAsync = class extends BPTree {
|
|
|
1639
1656
|
guess = prevValue;
|
|
1640
1657
|
}
|
|
1641
1658
|
}
|
|
1659
|
+
if (!pointer) {
|
|
1660
|
+
return;
|
|
1661
|
+
}
|
|
1642
1662
|
if (node.values.length + pointer.values.length < this.order) {
|
|
1643
1663
|
if (!isPredecessor) {
|
|
1644
1664
|
const pTemp = pointer;
|
|
@@ -1778,44 +1798,65 @@ var BPTreeAsync = class extends BPTree {
|
|
|
1778
1798
|
this.strategy.head.root = root.id;
|
|
1779
1799
|
node.parent = root.id;
|
|
1780
1800
|
pointer.parent = root.id;
|
|
1801
|
+
if (pointer.leaf) {
|
|
1802
|
+
node.next = pointer.id;
|
|
1803
|
+
pointer.prev = node.id;
|
|
1804
|
+
}
|
|
1781
1805
|
this.bufferForNodeUpdate(node);
|
|
1782
1806
|
this.bufferForNodeUpdate(pointer);
|
|
1783
1807
|
return;
|
|
1784
1808
|
}
|
|
1785
1809
|
const parentNode = await this.getNode(node.parent);
|
|
1786
|
-
|
|
1787
|
-
|
|
1788
|
-
if (
|
|
1789
|
-
|
|
1790
|
-
|
|
1791
|
-
|
|
1792
|
-
|
|
1793
|
-
|
|
1794
|
-
|
|
1795
|
-
|
|
1796
|
-
|
|
1797
|
-
|
|
1798
|
-
|
|
1799
|
-
|
|
1800
|
-
|
|
1801
|
-
|
|
1802
|
-
|
|
1803
|
-
|
|
1804
|
-
|
|
1805
|
-
|
|
1806
|
-
|
|
1807
|
-
|
|
1808
|
-
|
|
1809
|
-
|
|
1810
|
-
|
|
1811
|
-
|
|
1812
|
-
|
|
1813
|
-
|
|
1814
|
-
|
|
1815
|
-
|
|
1816
|
-
|
|
1817
|
-
|
|
1810
|
+
let insertIndex = 0;
|
|
1811
|
+
for (let i = 0; i < parentNode.values.length; i++) {
|
|
1812
|
+
if (this.comparator.asc(value, parentNode.values[i]) > 0) {
|
|
1813
|
+
insertIndex = i + 1;
|
|
1814
|
+
} else {
|
|
1815
|
+
break;
|
|
1816
|
+
}
|
|
1817
|
+
}
|
|
1818
|
+
parentNode.values.splice(insertIndex, 0, value);
|
|
1819
|
+
parentNode.keys.splice(insertIndex + 1, 0, pointer.id);
|
|
1820
|
+
pointer.parent = parentNode.id;
|
|
1821
|
+
if (pointer.leaf) {
|
|
1822
|
+
const leftSiblingId = parentNode.keys[insertIndex];
|
|
1823
|
+
const rightSiblingId = parentNode.keys[insertIndex + 2];
|
|
1824
|
+
if (leftSiblingId) {
|
|
1825
|
+
const leftSibling = await this.getNode(leftSiblingId);
|
|
1826
|
+
pointer.prev = leftSibling.id;
|
|
1827
|
+
pointer.next = leftSibling.next;
|
|
1828
|
+
leftSibling.next = pointer.id;
|
|
1829
|
+
this.bufferForNodeUpdate(leftSibling);
|
|
1830
|
+
}
|
|
1831
|
+
if (rightSiblingId) {
|
|
1832
|
+
const rightSibling = await this.getNode(rightSiblingId);
|
|
1833
|
+
rightSibling.prev = pointer.id;
|
|
1834
|
+
this.bufferForNodeUpdate(rightSibling);
|
|
1835
|
+
}
|
|
1836
|
+
}
|
|
1837
|
+
this.bufferForNodeUpdate(parentNode);
|
|
1838
|
+
this.bufferForNodeUpdate(pointer);
|
|
1839
|
+
if (parentNode.keys.length > this.order) {
|
|
1840
|
+
const parentPointer = await this._createNode(false, [], []);
|
|
1841
|
+
parentPointer.parent = parentNode.parent;
|
|
1842
|
+
const mid = Math.ceil(this.order / 2) - 1;
|
|
1843
|
+
parentPointer.values = parentNode.values.slice(mid + 1);
|
|
1844
|
+
parentPointer.keys = parentNode.keys.slice(mid + 1);
|
|
1845
|
+
const midValue = parentNode.values[mid];
|
|
1846
|
+
parentNode.values = parentNode.values.slice(0, mid);
|
|
1847
|
+
parentNode.keys = parentNode.keys.slice(0, mid + 1);
|
|
1848
|
+
for (const k of parentNode.keys) {
|
|
1849
|
+
const node2 = await this.getNode(k);
|
|
1850
|
+
node2.parent = parentNode.id;
|
|
1851
|
+
this.bufferForNodeUpdate(node2);
|
|
1852
|
+
}
|
|
1853
|
+
for (const k of parentPointer.keys) {
|
|
1854
|
+
const node2 = await this.getNode(k);
|
|
1855
|
+
node2.parent = parentPointer.id;
|
|
1856
|
+
this.bufferForNodeUpdate(node2);
|
|
1818
1857
|
}
|
|
1858
|
+
await this._insertInParent(parentNode, midValue, parentPointer);
|
|
1859
|
+
this.bufferForNodeUpdate(parentNode);
|
|
1819
1860
|
}
|
|
1820
1861
|
}
|
|
1821
1862
|
async init() {
|
|
@@ -1986,21 +2027,14 @@ var BPTreeAsync = class extends BPTree {
|
|
|
1986
2027
|
[],
|
|
1987
2028
|
true,
|
|
1988
2029
|
before.parent,
|
|
1989
|
-
|
|
1990
|
-
|
|
2030
|
+
null,
|
|
2031
|
+
null
|
|
1991
2032
|
);
|
|
1992
2033
|
const mid = Math.ceil(this.order / 2) - 1;
|
|
1993
|
-
const beforeNext = before.next;
|
|
1994
2034
|
after.values = before.values.slice(mid + 1);
|
|
1995
2035
|
after.keys = before.keys.slice(mid + 1);
|
|
1996
2036
|
before.values = before.values.slice(0, mid + 1);
|
|
1997
2037
|
before.keys = before.keys.slice(0, mid + 1);
|
|
1998
|
-
before.next = after.id;
|
|
1999
|
-
if (beforeNext) {
|
|
2000
|
-
const node = await this.getNode(beforeNext);
|
|
2001
|
-
node.prev = after.id;
|
|
2002
|
-
this.bufferForNodeUpdate(node);
|
|
2003
|
-
}
|
|
2004
2038
|
await this._insertInParent(before, after.values[0], after);
|
|
2005
2039
|
this.bufferForNodeUpdate(before);
|
|
2006
2040
|
}
|
package/dist/esm/index.mjs
CHANGED
|
@@ -735,6 +735,9 @@ var BPTreeSync = class extends BPTree {
|
|
|
735
735
|
guess = prevValue;
|
|
736
736
|
}
|
|
737
737
|
}
|
|
738
|
+
if (!pointer) {
|
|
739
|
+
return;
|
|
740
|
+
}
|
|
738
741
|
if (node.values.length + pointer.values.length < this.order) {
|
|
739
742
|
if (!isPredecessor) {
|
|
740
743
|
const pTemp = pointer;
|
|
@@ -874,44 +877,65 @@ var BPTreeSync = class extends BPTree {
|
|
|
874
877
|
this.strategy.head.root = root.id;
|
|
875
878
|
node.parent = root.id;
|
|
876
879
|
pointer.parent = root.id;
|
|
880
|
+
if (pointer.leaf) {
|
|
881
|
+
node.next = pointer.id;
|
|
882
|
+
pointer.prev = node.id;
|
|
883
|
+
}
|
|
877
884
|
this.bufferForNodeUpdate(node);
|
|
878
885
|
this.bufferForNodeUpdate(pointer);
|
|
879
886
|
return;
|
|
880
887
|
}
|
|
881
888
|
const parentNode = this.getNode(node.parent);
|
|
882
|
-
|
|
883
|
-
|
|
884
|
-
if (
|
|
885
|
-
|
|
886
|
-
|
|
887
|
-
|
|
888
|
-
|
|
889
|
-
|
|
890
|
-
|
|
891
|
-
|
|
892
|
-
|
|
893
|
-
|
|
894
|
-
|
|
895
|
-
|
|
896
|
-
|
|
897
|
-
|
|
898
|
-
|
|
899
|
-
|
|
900
|
-
|
|
901
|
-
|
|
902
|
-
|
|
903
|
-
|
|
904
|
-
|
|
905
|
-
|
|
906
|
-
|
|
907
|
-
|
|
908
|
-
|
|
909
|
-
|
|
910
|
-
|
|
911
|
-
|
|
912
|
-
|
|
913
|
-
|
|
889
|
+
let insertIndex = 0;
|
|
890
|
+
for (let i = 0; i < parentNode.values.length; i++) {
|
|
891
|
+
if (this.comparator.asc(value, parentNode.values[i]) > 0) {
|
|
892
|
+
insertIndex = i + 1;
|
|
893
|
+
} else {
|
|
894
|
+
break;
|
|
895
|
+
}
|
|
896
|
+
}
|
|
897
|
+
parentNode.values.splice(insertIndex, 0, value);
|
|
898
|
+
parentNode.keys.splice(insertIndex + 1, 0, pointer.id);
|
|
899
|
+
pointer.parent = parentNode.id;
|
|
900
|
+
if (pointer.leaf) {
|
|
901
|
+
const leftSiblingId = parentNode.keys[insertIndex];
|
|
902
|
+
const rightSiblingId = parentNode.keys[insertIndex + 2];
|
|
903
|
+
if (leftSiblingId) {
|
|
904
|
+
const leftSibling = this.getNode(leftSiblingId);
|
|
905
|
+
pointer.prev = leftSibling.id;
|
|
906
|
+
pointer.next = leftSibling.next;
|
|
907
|
+
leftSibling.next = pointer.id;
|
|
908
|
+
this.bufferForNodeUpdate(leftSibling);
|
|
909
|
+
}
|
|
910
|
+
if (rightSiblingId) {
|
|
911
|
+
const rightSibling = this.getNode(rightSiblingId);
|
|
912
|
+
rightSibling.prev = pointer.id;
|
|
913
|
+
this.bufferForNodeUpdate(rightSibling);
|
|
914
|
+
}
|
|
915
|
+
}
|
|
916
|
+
this.bufferForNodeUpdate(parentNode);
|
|
917
|
+
this.bufferForNodeUpdate(pointer);
|
|
918
|
+
if (parentNode.keys.length > this.order) {
|
|
919
|
+
const parentPointer = this._createNode(false, [], []);
|
|
920
|
+
parentPointer.parent = parentNode.parent;
|
|
921
|
+
const mid = Math.ceil(this.order / 2) - 1;
|
|
922
|
+
parentPointer.values = parentNode.values.slice(mid + 1);
|
|
923
|
+
parentPointer.keys = parentNode.keys.slice(mid + 1);
|
|
924
|
+
const midValue = parentNode.values[mid];
|
|
925
|
+
parentNode.values = parentNode.values.slice(0, mid);
|
|
926
|
+
parentNode.keys = parentNode.keys.slice(0, mid + 1);
|
|
927
|
+
for (const k of parentNode.keys) {
|
|
928
|
+
const node2 = this.getNode(k);
|
|
929
|
+
node2.parent = parentNode.id;
|
|
930
|
+
this.bufferForNodeUpdate(node2);
|
|
931
|
+
}
|
|
932
|
+
for (const k of parentPointer.keys) {
|
|
933
|
+
const node2 = this.getNode(k);
|
|
934
|
+
node2.parent = parentPointer.id;
|
|
935
|
+
this.bufferForNodeUpdate(node2);
|
|
914
936
|
}
|
|
937
|
+
this._insertInParent(parentNode, midValue, parentPointer);
|
|
938
|
+
this.bufferForNodeUpdate(parentNode);
|
|
915
939
|
}
|
|
916
940
|
}
|
|
917
941
|
init() {
|
|
@@ -1077,21 +1101,14 @@ var BPTreeSync = class extends BPTree {
|
|
|
1077
1101
|
[],
|
|
1078
1102
|
true,
|
|
1079
1103
|
before.parent,
|
|
1080
|
-
|
|
1081
|
-
|
|
1104
|
+
null,
|
|
1105
|
+
null
|
|
1082
1106
|
);
|
|
1083
1107
|
const mid = Math.ceil(this.order / 2) - 1;
|
|
1084
|
-
const beforeNext = before.next;
|
|
1085
1108
|
after.values = before.values.slice(mid + 1);
|
|
1086
1109
|
after.keys = before.keys.slice(mid + 1);
|
|
1087
1110
|
before.values = before.values.slice(0, mid + 1);
|
|
1088
1111
|
before.keys = before.keys.slice(0, mid + 1);
|
|
1089
|
-
before.next = after.id;
|
|
1090
|
-
if (beforeNext) {
|
|
1091
|
-
const node = this.getNode(beforeNext);
|
|
1092
|
-
node.prev = after.id;
|
|
1093
|
-
this.bufferForNodeUpdate(node);
|
|
1094
|
-
}
|
|
1095
1112
|
this._insertInParent(before, after.values[0], after);
|
|
1096
1113
|
this.bufferForNodeUpdate(before);
|
|
1097
1114
|
}
|
|
@@ -1605,6 +1622,9 @@ var BPTreeAsync = class extends BPTree {
|
|
|
1605
1622
|
guess = prevValue;
|
|
1606
1623
|
}
|
|
1607
1624
|
}
|
|
1625
|
+
if (!pointer) {
|
|
1626
|
+
return;
|
|
1627
|
+
}
|
|
1608
1628
|
if (node.values.length + pointer.values.length < this.order) {
|
|
1609
1629
|
if (!isPredecessor) {
|
|
1610
1630
|
const pTemp = pointer;
|
|
@@ -1744,44 +1764,65 @@ var BPTreeAsync = class extends BPTree {
|
|
|
1744
1764
|
this.strategy.head.root = root.id;
|
|
1745
1765
|
node.parent = root.id;
|
|
1746
1766
|
pointer.parent = root.id;
|
|
1767
|
+
if (pointer.leaf) {
|
|
1768
|
+
node.next = pointer.id;
|
|
1769
|
+
pointer.prev = node.id;
|
|
1770
|
+
}
|
|
1747
1771
|
this.bufferForNodeUpdate(node);
|
|
1748
1772
|
this.bufferForNodeUpdate(pointer);
|
|
1749
1773
|
return;
|
|
1750
1774
|
}
|
|
1751
1775
|
const parentNode = await this.getNode(node.parent);
|
|
1752
|
-
|
|
1753
|
-
|
|
1754
|
-
if (
|
|
1755
|
-
|
|
1756
|
-
|
|
1757
|
-
|
|
1758
|
-
|
|
1759
|
-
|
|
1760
|
-
|
|
1761
|
-
|
|
1762
|
-
|
|
1763
|
-
|
|
1764
|
-
|
|
1765
|
-
|
|
1766
|
-
|
|
1767
|
-
|
|
1768
|
-
|
|
1769
|
-
|
|
1770
|
-
|
|
1771
|
-
|
|
1772
|
-
|
|
1773
|
-
|
|
1774
|
-
|
|
1775
|
-
|
|
1776
|
-
|
|
1777
|
-
|
|
1778
|
-
|
|
1779
|
-
|
|
1780
|
-
|
|
1781
|
-
|
|
1782
|
-
|
|
1783
|
-
|
|
1776
|
+
let insertIndex = 0;
|
|
1777
|
+
for (let i = 0; i < parentNode.values.length; i++) {
|
|
1778
|
+
if (this.comparator.asc(value, parentNode.values[i]) > 0) {
|
|
1779
|
+
insertIndex = i + 1;
|
|
1780
|
+
} else {
|
|
1781
|
+
break;
|
|
1782
|
+
}
|
|
1783
|
+
}
|
|
1784
|
+
parentNode.values.splice(insertIndex, 0, value);
|
|
1785
|
+
parentNode.keys.splice(insertIndex + 1, 0, pointer.id);
|
|
1786
|
+
pointer.parent = parentNode.id;
|
|
1787
|
+
if (pointer.leaf) {
|
|
1788
|
+
const leftSiblingId = parentNode.keys[insertIndex];
|
|
1789
|
+
const rightSiblingId = parentNode.keys[insertIndex + 2];
|
|
1790
|
+
if (leftSiblingId) {
|
|
1791
|
+
const leftSibling = await this.getNode(leftSiblingId);
|
|
1792
|
+
pointer.prev = leftSibling.id;
|
|
1793
|
+
pointer.next = leftSibling.next;
|
|
1794
|
+
leftSibling.next = pointer.id;
|
|
1795
|
+
this.bufferForNodeUpdate(leftSibling);
|
|
1796
|
+
}
|
|
1797
|
+
if (rightSiblingId) {
|
|
1798
|
+
const rightSibling = await this.getNode(rightSiblingId);
|
|
1799
|
+
rightSibling.prev = pointer.id;
|
|
1800
|
+
this.bufferForNodeUpdate(rightSibling);
|
|
1801
|
+
}
|
|
1802
|
+
}
|
|
1803
|
+
this.bufferForNodeUpdate(parentNode);
|
|
1804
|
+
this.bufferForNodeUpdate(pointer);
|
|
1805
|
+
if (parentNode.keys.length > this.order) {
|
|
1806
|
+
const parentPointer = await this._createNode(false, [], []);
|
|
1807
|
+
parentPointer.parent = parentNode.parent;
|
|
1808
|
+
const mid = Math.ceil(this.order / 2) - 1;
|
|
1809
|
+
parentPointer.values = parentNode.values.slice(mid + 1);
|
|
1810
|
+
parentPointer.keys = parentNode.keys.slice(mid + 1);
|
|
1811
|
+
const midValue = parentNode.values[mid];
|
|
1812
|
+
parentNode.values = parentNode.values.slice(0, mid);
|
|
1813
|
+
parentNode.keys = parentNode.keys.slice(0, mid + 1);
|
|
1814
|
+
for (const k of parentNode.keys) {
|
|
1815
|
+
const node2 = await this.getNode(k);
|
|
1816
|
+
node2.parent = parentNode.id;
|
|
1817
|
+
this.bufferForNodeUpdate(node2);
|
|
1818
|
+
}
|
|
1819
|
+
for (const k of parentPointer.keys) {
|
|
1820
|
+
const node2 = await this.getNode(k);
|
|
1821
|
+
node2.parent = parentPointer.id;
|
|
1822
|
+
this.bufferForNodeUpdate(node2);
|
|
1784
1823
|
}
|
|
1824
|
+
await this._insertInParent(parentNode, midValue, parentPointer);
|
|
1825
|
+
this.bufferForNodeUpdate(parentNode);
|
|
1785
1826
|
}
|
|
1786
1827
|
}
|
|
1787
1828
|
async init() {
|
|
@@ -1952,21 +1993,14 @@ var BPTreeAsync = class extends BPTree {
|
|
|
1952
1993
|
[],
|
|
1953
1994
|
true,
|
|
1954
1995
|
before.parent,
|
|
1955
|
-
|
|
1956
|
-
|
|
1996
|
+
null,
|
|
1997
|
+
null
|
|
1957
1998
|
);
|
|
1958
1999
|
const mid = Math.ceil(this.order / 2) - 1;
|
|
1959
|
-
const beforeNext = before.next;
|
|
1960
2000
|
after.values = before.values.slice(mid + 1);
|
|
1961
2001
|
after.keys = before.keys.slice(mid + 1);
|
|
1962
2002
|
before.values = before.values.slice(0, mid + 1);
|
|
1963
2003
|
before.keys = before.keys.slice(0, mid + 1);
|
|
1964
|
-
before.next = after.id;
|
|
1965
|
-
if (beforeNext) {
|
|
1966
|
-
const node = await this.getNode(beforeNext);
|
|
1967
|
-
node.prev = after.id;
|
|
1968
|
-
this.bufferForNodeUpdate(node);
|
|
1969
|
-
}
|
|
1970
2004
|
await this._insertInParent(before, after.values[0], after);
|
|
1971
2005
|
this.bufferForNodeUpdate(before);
|
|
1972
2006
|
}
|
|
@@ -8,8 +8,8 @@ export declare class BPTreeAsync<K, V> extends BPTree<K, V> {
|
|
|
8
8
|
private readonly lock;
|
|
9
9
|
constructor(strategy: SerializeStrategyAsync<K, V>, comparator: ValueComparator<V>, option?: BPTreeConstructorOption);
|
|
10
10
|
private _createCachedNode;
|
|
11
|
-
|
|
12
|
-
|
|
11
|
+
protected readLock<T>(callback: () => Promise<T>): Promise<T>;
|
|
12
|
+
protected writeLock<T>(callback: () => Promise<T>): Promise<T>;
|
|
13
13
|
protected getPairsRightToLeft(value: V, startNode: BPTreeLeafNode<K, V>, endNode: BPTreeLeafNode<K, V> | null, comparator: (nodeValue: V, value: V) => boolean): Promise<BPTreePair<K, V>>;
|
|
14
14
|
protected getPairsLeftToRight(value: V, startNode: BPTreeLeafNode<K, V>, endNode: BPTreeLeafNode<K, V> | null, comparator: (nodeValue: V, value: V) => boolean): Promise<BPTreePair<K, V>>;
|
|
15
15
|
protected getPairs(value: V, startNode: BPTreeLeafNode<K, V>, endNode: BPTreeLeafNode<K, V> | null, comparator: (nodeValue: V, value: V) => boolean, direction: 1 | -1): Promise<BPTreePair<K, V>>;
|