serializable-bptree 7.0.0 → 7.0.2
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/esm/index.mjs
CHANGED
|
@@ -439,6 +439,20 @@ var BPTree = class _BPTree {
|
|
|
439
439
|
option;
|
|
440
440
|
order;
|
|
441
441
|
rootId;
|
|
442
|
+
/**
|
|
443
|
+
* Returns the ID of the root node.
|
|
444
|
+
* @returns The root node ID.
|
|
445
|
+
*/
|
|
446
|
+
getRootId() {
|
|
447
|
+
return this.rootId;
|
|
448
|
+
}
|
|
449
|
+
/**
|
|
450
|
+
* Returns the order of the B+Tree.
|
|
451
|
+
* @returns The order of the tree.
|
|
452
|
+
*/
|
|
453
|
+
getOrder() {
|
|
454
|
+
return this.order;
|
|
455
|
+
}
|
|
442
456
|
_strategyDirty;
|
|
443
457
|
_nodeCreateBuffer;
|
|
444
458
|
_nodeUpdateBuffer;
|
|
@@ -671,24 +685,21 @@ var BPTree = class _BPTree {
|
|
|
671
685
|
break;
|
|
672
686
|
}
|
|
673
687
|
keys.push(key);
|
|
674
|
-
this.bufferForNodeUpdate(node);
|
|
675
|
-
break;
|
|
688
|
+
return this.bufferForNodeUpdate(node);
|
|
676
689
|
} else if (this.comparator.isLower(value, nValue)) {
|
|
677
690
|
node.values.splice(i, 0, value);
|
|
678
691
|
node.keys.splice(i, 0, [key]);
|
|
679
|
-
this.bufferForNodeUpdate(node);
|
|
680
|
-
break;
|
|
692
|
+
return this.bufferForNodeUpdate(node);
|
|
681
693
|
} else if (i + 1 === node.values.length) {
|
|
682
694
|
node.values.push(value);
|
|
683
695
|
node.keys.push([key]);
|
|
684
|
-
this.bufferForNodeUpdate(node);
|
|
685
|
-
break;
|
|
696
|
+
return this.bufferForNodeUpdate(node);
|
|
686
697
|
}
|
|
687
698
|
}
|
|
688
699
|
} else {
|
|
689
700
|
node.values = [value];
|
|
690
701
|
node.keys = [[key]];
|
|
691
|
-
this.bufferForNodeUpdate(node);
|
|
702
|
+
return this.bufferForNodeUpdate(node);
|
|
692
703
|
}
|
|
693
704
|
}
|
|
694
705
|
bufferForNodeCreate(node) {
|
|
@@ -804,7 +815,7 @@ var BPTreeSyncBase = class extends BPTree {
|
|
|
804
815
|
}
|
|
805
816
|
return id;
|
|
806
817
|
}
|
|
807
|
-
_createNode(isLeaf, keys, values, leaf =
|
|
818
|
+
_createNode(isLeaf, keys, values, leaf = isLeaf, parent = null, next = null, prev = null) {
|
|
808
819
|
const id = this._createNodeId(isLeaf);
|
|
809
820
|
const node = {
|
|
810
821
|
id,
|
|
@@ -815,26 +826,23 @@ var BPTreeSyncBase = class extends BPTree {
|
|
|
815
826
|
next,
|
|
816
827
|
prev
|
|
817
828
|
};
|
|
818
|
-
this.
|
|
829
|
+
this.bufferForNodeCreate(node);
|
|
819
830
|
return node;
|
|
820
831
|
}
|
|
821
832
|
_deleteEntry(node, key, value) {
|
|
822
833
|
if (!node.leaf) {
|
|
834
|
+
let keyIndex = -1;
|
|
823
835
|
for (let i = 0, len = node.keys.length; i < len; i++) {
|
|
824
|
-
|
|
825
|
-
|
|
826
|
-
node.keys.splice(i, 1);
|
|
827
|
-
this.bufferForNodeUpdate(node);
|
|
836
|
+
if (node.keys[i] === key) {
|
|
837
|
+
keyIndex = i;
|
|
828
838
|
break;
|
|
829
839
|
}
|
|
830
840
|
}
|
|
831
|
-
|
|
832
|
-
|
|
833
|
-
|
|
834
|
-
|
|
835
|
-
|
|
836
|
-
break;
|
|
837
|
-
}
|
|
841
|
+
if (keyIndex !== -1) {
|
|
842
|
+
node.keys.splice(keyIndex, 1);
|
|
843
|
+
const valueIndex = keyIndex > 0 ? keyIndex - 1 : 0;
|
|
844
|
+
node.values.splice(valueIndex, 1);
|
|
845
|
+
this.bufferForNodeUpdate(node);
|
|
838
846
|
}
|
|
839
847
|
}
|
|
840
848
|
if (this.rootId === node.id && node.keys.length === 1 && !node.leaf) {
|
|
@@ -934,13 +942,10 @@ var BPTreeSyncBase = class extends BPTree {
|
|
|
934
942
|
node.keys = [pointerPm, ...node.keys];
|
|
935
943
|
node.values = [guess, ...node.values];
|
|
936
944
|
parentNode = this.getNode(node.parent);
|
|
937
|
-
|
|
938
|
-
|
|
939
|
-
|
|
940
|
-
|
|
941
|
-
this.bufferForNodeUpdate(parentNode);
|
|
942
|
-
break;
|
|
943
|
-
}
|
|
945
|
+
const nodeIndex = parentNode.keys.indexOf(node.id);
|
|
946
|
+
if (nodeIndex > 0) {
|
|
947
|
+
parentNode.values[nodeIndex - 1] = pointerKm;
|
|
948
|
+
this.bufferForNodeUpdate(parentNode);
|
|
944
949
|
}
|
|
945
950
|
} else {
|
|
946
951
|
pointerPm = pointer.keys.splice(-1)[0];
|
|
@@ -948,13 +953,10 @@ var BPTreeSyncBase = class extends BPTree {
|
|
|
948
953
|
node.keys = [pointerPm, ...node.keys];
|
|
949
954
|
node.values = [pointerKm, ...node.values];
|
|
950
955
|
parentNode = this.getNode(node.parent);
|
|
951
|
-
|
|
952
|
-
|
|
953
|
-
|
|
954
|
-
|
|
955
|
-
this.bufferForNodeUpdate(parentNode);
|
|
956
|
-
break;
|
|
957
|
-
}
|
|
956
|
+
const nodeIndex = parentNode.keys.indexOf(node.id);
|
|
957
|
+
if (nodeIndex > 0) {
|
|
958
|
+
parentNode.values[nodeIndex - 1] = pointerKm;
|
|
959
|
+
this.bufferForNodeUpdate(parentNode);
|
|
958
960
|
}
|
|
959
961
|
}
|
|
960
962
|
this.bufferForNodeUpdate(node);
|
|
@@ -968,13 +970,10 @@ var BPTreeSyncBase = class extends BPTree {
|
|
|
968
970
|
node.keys = [...node.keys, pointerP0];
|
|
969
971
|
node.values = [...node.values, guess];
|
|
970
972
|
parentNode = this.getNode(node.parent);
|
|
971
|
-
|
|
972
|
-
|
|
973
|
-
|
|
974
|
-
|
|
975
|
-
this.bufferForNodeUpdate(parentNode);
|
|
976
|
-
break;
|
|
977
|
-
}
|
|
973
|
+
const pointerIndex = parentNode.keys.indexOf(pointer.id);
|
|
974
|
+
if (pointerIndex > 0) {
|
|
975
|
+
parentNode.values[pointerIndex - 1] = pointerK0;
|
|
976
|
+
this.bufferForNodeUpdate(parentNode);
|
|
978
977
|
}
|
|
979
978
|
} else {
|
|
980
979
|
pointerP0 = pointer.keys.splice(0, 1)[0];
|
|
@@ -982,13 +981,10 @@ var BPTreeSyncBase = class extends BPTree {
|
|
|
982
981
|
node.keys = [...node.keys, pointerP0];
|
|
983
982
|
node.values = [...node.values, pointerK0];
|
|
984
983
|
parentNode = this.getNode(node.parent);
|
|
985
|
-
|
|
986
|
-
|
|
987
|
-
|
|
988
|
-
|
|
989
|
-
this.bufferForNodeUpdate(parentNode);
|
|
990
|
-
break;
|
|
991
|
-
}
|
|
984
|
+
const pointerIndex = parentNode.keys.indexOf(pointer.id);
|
|
985
|
+
if (pointerIndex > 0) {
|
|
986
|
+
parentNode.values[pointerIndex - 1] = pointer.values[0];
|
|
987
|
+
this.bufferForNodeUpdate(parentNode);
|
|
992
988
|
}
|
|
993
989
|
}
|
|
994
990
|
this.bufferForNodeUpdate(node);
|
|
@@ -1016,6 +1012,8 @@ var BPTreeSyncBase = class extends BPTree {
|
|
|
1016
1012
|
}
|
|
1017
1013
|
}
|
|
1018
1014
|
}
|
|
1015
|
+
} else {
|
|
1016
|
+
this.bufferForNodeUpdate(node);
|
|
1019
1017
|
}
|
|
1020
1018
|
}
|
|
1021
1019
|
_insertInParent(node, value, pointer) {
|
|
@@ -1034,31 +1032,25 @@ var BPTreeSyncBase = class extends BPTree {
|
|
|
1034
1032
|
return;
|
|
1035
1033
|
}
|
|
1036
1034
|
const parentNode = this.getNode(node.parent);
|
|
1037
|
-
|
|
1038
|
-
|
|
1039
|
-
|
|
1040
|
-
insertIndex = i + 1;
|
|
1041
|
-
} else {
|
|
1042
|
-
break;
|
|
1043
|
-
}
|
|
1035
|
+
const nodeIndex = parentNode.keys.indexOf(node.id);
|
|
1036
|
+
if (nodeIndex === -1) {
|
|
1037
|
+
throw new Error(`Node ${node.id} not found in parent ${parentNode.id}`);
|
|
1044
1038
|
}
|
|
1039
|
+
const insertIndex = nodeIndex;
|
|
1045
1040
|
parentNode.values.splice(insertIndex, 0, value);
|
|
1046
1041
|
parentNode.keys.splice(insertIndex + 1, 0, pointer.id);
|
|
1047
1042
|
pointer.parent = parentNode.id;
|
|
1048
1043
|
if (pointer.leaf) {
|
|
1049
|
-
const
|
|
1050
|
-
const
|
|
1051
|
-
|
|
1052
|
-
|
|
1053
|
-
|
|
1054
|
-
|
|
1055
|
-
|
|
1056
|
-
this.
|
|
1057
|
-
|
|
1058
|
-
|
|
1059
|
-
const rightSibling = this.getNode(rightSiblingId);
|
|
1060
|
-
rightSibling.prev = pointer.id;
|
|
1061
|
-
this.bufferForNodeUpdate(rightSibling);
|
|
1044
|
+
const leftSibling = node;
|
|
1045
|
+
const oldNextId = leftSibling.next;
|
|
1046
|
+
pointer.prev = leftSibling.id;
|
|
1047
|
+
pointer.next = oldNextId;
|
|
1048
|
+
leftSibling.next = pointer.id;
|
|
1049
|
+
this.bufferForNodeUpdate(leftSibling);
|
|
1050
|
+
if (oldNextId) {
|
|
1051
|
+
const oldNext = this.getNode(oldNextId);
|
|
1052
|
+
oldNext.prev = pointer.id;
|
|
1053
|
+
this.bufferForNodeUpdate(oldNext);
|
|
1062
1054
|
}
|
|
1063
1055
|
}
|
|
1064
1056
|
this.bufferForNodeUpdate(parentNode);
|
|
@@ -1087,6 +1079,7 @@ var BPTreeSyncBase = class extends BPTree {
|
|
|
1087
1079
|
}
|
|
1088
1080
|
}
|
|
1089
1081
|
init() {
|
|
1082
|
+
this.clear();
|
|
1090
1083
|
const head = this.strategy.readHead();
|
|
1091
1084
|
if (head === null) {
|
|
1092
1085
|
this.order = this.strategy.order;
|
|
@@ -1117,18 +1110,35 @@ var BPTreeSyncBase = class extends BPTree {
|
|
|
1117
1110
|
}
|
|
1118
1111
|
insertableNode(value) {
|
|
1119
1112
|
let node = this.getNode(this.rootId);
|
|
1113
|
+
if (node.parent !== null) {
|
|
1114
|
+
node.parent = null;
|
|
1115
|
+
this.bufferForNodeUpdate(node);
|
|
1116
|
+
}
|
|
1120
1117
|
while (!node.leaf) {
|
|
1118
|
+
const parentId = node.id;
|
|
1121
1119
|
for (let i = 0, len = node.values.length; i < len; i++) {
|
|
1122
1120
|
const nValue = node.values[i];
|
|
1123
1121
|
const k = node.keys;
|
|
1124
1122
|
if (this.comparator.isSame(value, nValue)) {
|
|
1125
1123
|
node = this.getNode(k[i + 1]);
|
|
1124
|
+
if (node.parent !== parentId) {
|
|
1125
|
+
node.parent = parentId;
|
|
1126
|
+
this.bufferForNodeUpdate(node);
|
|
1127
|
+
}
|
|
1126
1128
|
break;
|
|
1127
1129
|
} else if (this.comparator.isLower(value, nValue)) {
|
|
1128
1130
|
node = this.getNode(k[i]);
|
|
1131
|
+
if (node.parent !== parentId) {
|
|
1132
|
+
node.parent = parentId;
|
|
1133
|
+
this.bufferForNodeUpdate(node);
|
|
1134
|
+
}
|
|
1129
1135
|
break;
|
|
1130
1136
|
} else if (i + 1 === node.values.length) {
|
|
1131
1137
|
node = this.getNode(k[i + 1]);
|
|
1138
|
+
if (node.parent !== parentId) {
|
|
1139
|
+
node.parent = parentId;
|
|
1140
|
+
this.bufferForNodeUpdate(node);
|
|
1141
|
+
}
|
|
1132
1142
|
break;
|
|
1133
1143
|
}
|
|
1134
1144
|
}
|
|
@@ -1137,18 +1147,35 @@ var BPTreeSyncBase = class extends BPTree {
|
|
|
1137
1147
|
}
|
|
1138
1148
|
insertableNodeByPrimary(value) {
|
|
1139
1149
|
let node = this.getNode(this.rootId);
|
|
1150
|
+
if (node.parent !== null) {
|
|
1151
|
+
node.parent = null;
|
|
1152
|
+
this.bufferForNodeUpdate(node);
|
|
1153
|
+
}
|
|
1140
1154
|
while (!node.leaf) {
|
|
1155
|
+
const parentId = node.id;
|
|
1141
1156
|
for (let i = 0, len = node.values.length; i < len; i++) {
|
|
1142
1157
|
const nValue = node.values[i];
|
|
1143
1158
|
const k = node.keys;
|
|
1144
1159
|
if (this.comparator.isPrimarySame(value, nValue)) {
|
|
1145
1160
|
node = this.getNode(k[i]);
|
|
1161
|
+
if (node.parent !== parentId) {
|
|
1162
|
+
node.parent = parentId;
|
|
1163
|
+
this.bufferForNodeUpdate(node);
|
|
1164
|
+
}
|
|
1146
1165
|
break;
|
|
1147
1166
|
} else if (this.comparator.isPrimaryLower(value, nValue)) {
|
|
1148
1167
|
node = this.getNode(k[i]);
|
|
1168
|
+
if (node.parent !== parentId) {
|
|
1169
|
+
node.parent = parentId;
|
|
1170
|
+
this.bufferForNodeUpdate(node);
|
|
1171
|
+
}
|
|
1149
1172
|
break;
|
|
1150
1173
|
} else if (i + 1 === node.values.length) {
|
|
1151
1174
|
node = this.getNode(k[i + 1]);
|
|
1175
|
+
if (node.parent !== parentId) {
|
|
1176
|
+
node.parent = parentId;
|
|
1177
|
+
this.bufferForNodeUpdate(node);
|
|
1178
|
+
}
|
|
1152
1179
|
break;
|
|
1153
1180
|
}
|
|
1154
1181
|
}
|
|
@@ -1157,16 +1184,29 @@ var BPTreeSyncBase = class extends BPTree {
|
|
|
1157
1184
|
}
|
|
1158
1185
|
insertableRightestNodeByPrimary(value) {
|
|
1159
1186
|
let node = this.getNode(this.rootId);
|
|
1187
|
+
if (node.parent !== null) {
|
|
1188
|
+
node.parent = null;
|
|
1189
|
+
this.bufferForNodeUpdate(node);
|
|
1190
|
+
}
|
|
1160
1191
|
while (!node.leaf) {
|
|
1192
|
+
const parentId = node.id;
|
|
1161
1193
|
for (let i = 0, len = node.values.length; i < len; i++) {
|
|
1162
1194
|
const nValue = node.values[i];
|
|
1163
1195
|
const k = node.keys;
|
|
1164
1196
|
if (this.comparator.isPrimaryLower(value, nValue)) {
|
|
1165
1197
|
node = this.getNode(k[i]);
|
|
1198
|
+
if (node.parent !== parentId) {
|
|
1199
|
+
node.parent = parentId;
|
|
1200
|
+
this.bufferForNodeUpdate(node);
|
|
1201
|
+
}
|
|
1166
1202
|
break;
|
|
1167
1203
|
}
|
|
1168
1204
|
if (i + 1 === node.values.length) {
|
|
1169
1205
|
node = this.getNode(k[i + 1]);
|
|
1206
|
+
if (node.parent !== parentId) {
|
|
1207
|
+
node.parent = parentId;
|
|
1208
|
+
this.bufferForNodeUpdate(node);
|
|
1209
|
+
}
|
|
1170
1210
|
break;
|
|
1171
1211
|
}
|
|
1172
1212
|
}
|
|
@@ -1201,17 +1241,35 @@ var BPTreeSyncBase = class extends BPTree {
|
|
|
1201
1241
|
}
|
|
1202
1242
|
leftestNode() {
|
|
1203
1243
|
let node = this.getNode(this.rootId);
|
|
1244
|
+
if (node.parent !== null) {
|
|
1245
|
+
node.parent = null;
|
|
1246
|
+
this.bufferForNodeUpdate(node);
|
|
1247
|
+
}
|
|
1204
1248
|
while (!node.leaf) {
|
|
1249
|
+
const parentId = node.id;
|
|
1205
1250
|
const keys = node.keys;
|
|
1206
1251
|
node = this.getNode(keys[0]);
|
|
1252
|
+
if (node.parent !== parentId) {
|
|
1253
|
+
node.parent = parentId;
|
|
1254
|
+
this.bufferForNodeUpdate(node);
|
|
1255
|
+
}
|
|
1207
1256
|
}
|
|
1208
1257
|
return node;
|
|
1209
1258
|
}
|
|
1210
1259
|
rightestNode() {
|
|
1211
1260
|
let node = this.getNode(this.rootId);
|
|
1261
|
+
if (node.parent !== null) {
|
|
1262
|
+
node.parent = null;
|
|
1263
|
+
this.bufferForNodeUpdate(node);
|
|
1264
|
+
}
|
|
1212
1265
|
while (!node.leaf) {
|
|
1266
|
+
const parentId = node.id;
|
|
1213
1267
|
const keys = node.keys;
|
|
1214
1268
|
node = this.getNode(keys[keys.length - 1]);
|
|
1269
|
+
if (node.parent !== parentId) {
|
|
1270
|
+
node.parent = parentId;
|
|
1271
|
+
this.bufferForNodeUpdate(node);
|
|
1272
|
+
}
|
|
1215
1273
|
}
|
|
1216
1274
|
return node;
|
|
1217
1275
|
}
|
|
@@ -1550,23 +1608,37 @@ var BPTreeSyncTransaction = class extends BPTreeSyncBase {
|
|
|
1550
1608
|
realBaseTree;
|
|
1551
1609
|
realBaseStrategy;
|
|
1552
1610
|
txNodes = /* @__PURE__ */ new Map();
|
|
1553
|
-
dirtyIds
|
|
1554
|
-
createdInTx
|
|
1611
|
+
dirtyIds;
|
|
1612
|
+
createdInTx;
|
|
1613
|
+
deletedIds;
|
|
1555
1614
|
initialRootId;
|
|
1556
1615
|
transactionRootId;
|
|
1557
1616
|
constructor(baseTree) {
|
|
1558
1617
|
super(baseTree.strategy, baseTree.comparator, baseTree.option);
|
|
1559
1618
|
this.realBaseTree = baseTree;
|
|
1560
1619
|
this.realBaseStrategy = baseTree.strategy;
|
|
1620
|
+
this.order = baseTree.getOrder();
|
|
1561
1621
|
this.initialRootId = "";
|
|
1562
1622
|
this.transactionRootId = "";
|
|
1623
|
+
this.dirtyIds = /* @__PURE__ */ new Set();
|
|
1624
|
+
this.createdInTx = /* @__PURE__ */ new Set();
|
|
1625
|
+
this.deletedIds = /* @__PURE__ */ new Set();
|
|
1563
1626
|
}
|
|
1564
1627
|
/**
|
|
1565
1628
|
* Initializes the transaction by capturing the current state of the tree.
|
|
1566
1629
|
*/
|
|
1567
1630
|
initTransaction() {
|
|
1568
1631
|
const head = this.realBaseStrategy.readHead();
|
|
1569
|
-
|
|
1632
|
+
if (head) {
|
|
1633
|
+
this.order = head.order;
|
|
1634
|
+
this.initialRootId = head.root;
|
|
1635
|
+
} else {
|
|
1636
|
+
this.initialRootId = this.realBaseTree.getRootId();
|
|
1637
|
+
}
|
|
1638
|
+
if (!this.initialRootId) {
|
|
1639
|
+
const root = this._createNode(true, [], [], true);
|
|
1640
|
+
this.initialRootId = root.id;
|
|
1641
|
+
}
|
|
1570
1642
|
this.transactionRootId = this.initialRootId;
|
|
1571
1643
|
this.rootId = this.transactionRootId;
|
|
1572
1644
|
const snapshotStrategy = new BPTreeSyncSnapshotStrategy(this.realBaseStrategy, this.initialRootId);
|
|
@@ -1574,34 +1646,76 @@ var BPTreeSyncTransaction = class extends BPTreeSyncBase {
|
|
|
1574
1646
|
this.txNodes.clear();
|
|
1575
1647
|
this.dirtyIds.clear();
|
|
1576
1648
|
this.createdInTx.clear();
|
|
1649
|
+
this.deletedIds.clear();
|
|
1577
1650
|
}
|
|
1578
1651
|
getNode(id) {
|
|
1579
1652
|
if (this.txNodes.has(id)) {
|
|
1580
1653
|
return this.txNodes.get(id);
|
|
1581
1654
|
}
|
|
1655
|
+
if (this.deletedIds.has(id)) {
|
|
1656
|
+
throw new Error(`The tree attempted to reference deleted node '${id}'`);
|
|
1657
|
+
}
|
|
1582
1658
|
const baseNode = this.realBaseStrategy.read(id);
|
|
1583
1659
|
const clone = JSON.parse(JSON.stringify(baseNode));
|
|
1584
1660
|
this.txNodes.set(id, clone);
|
|
1585
1661
|
return clone;
|
|
1586
1662
|
}
|
|
1587
1663
|
bufferForNodeUpdate(node) {
|
|
1664
|
+
if (this.dirtyIds.has(node.id) && this.txNodes.has(node.id) && node._p) {
|
|
1665
|
+
this.txNodes.set(node.id, node);
|
|
1666
|
+
return;
|
|
1667
|
+
}
|
|
1668
|
+
node._p = true;
|
|
1588
1669
|
this.txNodes.set(node.id, node);
|
|
1589
1670
|
this.dirtyIds.add(node.id);
|
|
1671
|
+
if (node.leaf) {
|
|
1672
|
+
if (node.next && !this.dirtyIds.has(node.next) && !this.deletedIds.has(node.next)) {
|
|
1673
|
+
try {
|
|
1674
|
+
this.bufferForNodeUpdate(this.getNode(node.next));
|
|
1675
|
+
} catch (e) {
|
|
1676
|
+
}
|
|
1677
|
+
}
|
|
1678
|
+
if (node.prev && !this.dirtyIds.has(node.prev) && !this.deletedIds.has(node.prev)) {
|
|
1679
|
+
try {
|
|
1680
|
+
this.bufferForNodeUpdate(this.getNode(node.prev));
|
|
1681
|
+
} catch (e) {
|
|
1682
|
+
}
|
|
1683
|
+
}
|
|
1684
|
+
}
|
|
1590
1685
|
this.markPathDirty(node);
|
|
1686
|
+
delete node._p;
|
|
1591
1687
|
}
|
|
1592
1688
|
bufferForNodeCreate(node) {
|
|
1593
1689
|
this.txNodes.set(node.id, node);
|
|
1594
1690
|
this.dirtyIds.add(node.id);
|
|
1595
1691
|
this.createdInTx.add(node.id);
|
|
1692
|
+
if (node.leaf) {
|
|
1693
|
+
if (node.next && !this.dirtyIds.has(node.next) && !this.deletedIds.has(node.next)) {
|
|
1694
|
+
try {
|
|
1695
|
+
this.bufferForNodeUpdate(this.getNode(node.next));
|
|
1696
|
+
} catch (e) {
|
|
1697
|
+
}
|
|
1698
|
+
}
|
|
1699
|
+
if (node.prev && !this.dirtyIds.has(node.prev) && !this.deletedIds.has(node.prev)) {
|
|
1700
|
+
try {
|
|
1701
|
+
this.bufferForNodeUpdate(this.getNode(node.prev));
|
|
1702
|
+
} catch (e) {
|
|
1703
|
+
}
|
|
1704
|
+
}
|
|
1705
|
+
}
|
|
1596
1706
|
this.markPathDirty(node);
|
|
1597
1707
|
}
|
|
1598
1708
|
bufferForNodeDelete(node) {
|
|
1599
1709
|
this.txNodes.delete(node.id);
|
|
1600
1710
|
this.dirtyIds.add(node.id);
|
|
1711
|
+
this.deletedIds.add(node.id);
|
|
1601
1712
|
}
|
|
1602
1713
|
markPathDirty(node) {
|
|
1603
1714
|
let curr = node;
|
|
1604
1715
|
while (curr.parent) {
|
|
1716
|
+
if (this.deletedIds.has(curr.parent)) {
|
|
1717
|
+
break;
|
|
1718
|
+
}
|
|
1605
1719
|
if (this.dirtyIds.has(curr.parent) && this.txNodes.has(curr.parent)) {
|
|
1606
1720
|
break;
|
|
1607
1721
|
}
|
|
@@ -1613,13 +1727,13 @@ var BPTreeSyncTransaction = class extends BPTreeSyncBase {
|
|
|
1613
1727
|
this.transactionRootId = curr.id;
|
|
1614
1728
|
}
|
|
1615
1729
|
}
|
|
1616
|
-
_createNode(isLeaf, keys, values, leaf =
|
|
1617
|
-
const id = this.
|
|
1730
|
+
_createNode(isLeaf, keys, values, leaf = isLeaf, parent = null, next = null, prev = null) {
|
|
1731
|
+
const id = this.strategy.id(isLeaf);
|
|
1618
1732
|
const node = {
|
|
1619
1733
|
id,
|
|
1620
1734
|
keys,
|
|
1621
1735
|
values,
|
|
1622
|
-
leaf
|
|
1736
|
+
leaf,
|
|
1623
1737
|
parent,
|
|
1624
1738
|
next,
|
|
1625
1739
|
prev
|
|
@@ -1677,9 +1791,9 @@ var BPTreeSyncTransaction = class extends BPTreeSyncBase {
|
|
|
1677
1791
|
finalNodes.push(node);
|
|
1678
1792
|
newCreatedIds.push(newId);
|
|
1679
1793
|
}
|
|
1680
|
-
let newRootId = this.
|
|
1681
|
-
if (idMapping.has(this.
|
|
1682
|
-
newRootId = idMapping.get(this.
|
|
1794
|
+
let newRootId = this.rootId;
|
|
1795
|
+
if (idMapping.has(this.rootId)) {
|
|
1796
|
+
newRootId = idMapping.get(this.rootId);
|
|
1683
1797
|
}
|
|
1684
1798
|
for (const node of finalNodes) {
|
|
1685
1799
|
this.realBaseStrategy.write(node.id, node);
|
|
@@ -1708,12 +1822,21 @@ var BPTreeSyncTransaction = class extends BPTreeSyncBase {
|
|
|
1708
1822
|
}
|
|
1709
1823
|
/**
|
|
1710
1824
|
* Rolls back the transaction by clearing all buffered changes.
|
|
1711
|
-
*
|
|
1825
|
+
* If cleanup is `true`, it also clears the transaction nodes.
|
|
1826
|
+
* @param cleanup Whether to clear the transaction nodes.
|
|
1827
|
+
* @returns The IDs of nodes that were created in this transaction.
|
|
1712
1828
|
*/
|
|
1713
|
-
rollback() {
|
|
1829
|
+
rollback(cleanup = true) {
|
|
1830
|
+
const createdIds = Array.from(this.createdInTx);
|
|
1714
1831
|
this.txNodes.clear();
|
|
1715
1832
|
this.dirtyIds.clear();
|
|
1716
1833
|
this.createdInTx.clear();
|
|
1834
|
+
if (cleanup) {
|
|
1835
|
+
for (const id of createdIds) {
|
|
1836
|
+
this.realBaseStrategy.delete(id);
|
|
1837
|
+
}
|
|
1838
|
+
}
|
|
1839
|
+
return createdIds;
|
|
1717
1840
|
}
|
|
1718
1841
|
// Override to do nothing, as transaction handles its own commits
|
|
1719
1842
|
commitHeadBuffer() {
|
|
@@ -1730,6 +1853,7 @@ var BPTreeSyncTransaction = class extends BPTreeSyncBase {
|
|
|
1730
1853
|
var BPTreeSync = class extends BPTreeSyncBase {
|
|
1731
1854
|
constructor(strategy, comparator, option) {
|
|
1732
1855
|
super(strategy, comparator, option);
|
|
1856
|
+
this.init();
|
|
1733
1857
|
}
|
|
1734
1858
|
/**
|
|
1735
1859
|
* Creates a new synchronous transaction.
|
|
@@ -1837,7 +1961,7 @@ var BPTreeAsyncBase = class extends BPTree {
|
|
|
1837
1961
|
}
|
|
1838
1962
|
return id;
|
|
1839
1963
|
}
|
|
1840
|
-
async _createNode(isLeaf, keys, values, leaf =
|
|
1964
|
+
async _createNode(isLeaf, keys, values, leaf = isLeaf, parent = null, next = null, prev = null) {
|
|
1841
1965
|
const id = await this._createNodeId(isLeaf);
|
|
1842
1966
|
const node = {
|
|
1843
1967
|
id,
|
|
@@ -1848,40 +1972,37 @@ var BPTreeAsyncBase = class extends BPTree {
|
|
|
1848
1972
|
next,
|
|
1849
1973
|
prev
|
|
1850
1974
|
};
|
|
1851
|
-
this.
|
|
1975
|
+
await this.bufferForNodeCreate(node);
|
|
1852
1976
|
return node;
|
|
1853
1977
|
}
|
|
1854
1978
|
async _deleteEntry(node, key, value) {
|
|
1855
1979
|
if (!node.leaf) {
|
|
1980
|
+
let keyIndex = -1;
|
|
1856
1981
|
for (let i = 0, len = node.keys.length; i < len; i++) {
|
|
1857
|
-
|
|
1858
|
-
|
|
1859
|
-
node.keys.splice(i, 1);
|
|
1860
|
-
this.bufferForNodeUpdate(node);
|
|
1982
|
+
if (node.keys[i] === key) {
|
|
1983
|
+
keyIndex = i;
|
|
1861
1984
|
break;
|
|
1862
1985
|
}
|
|
1863
1986
|
}
|
|
1864
|
-
|
|
1865
|
-
|
|
1866
|
-
|
|
1867
|
-
|
|
1868
|
-
|
|
1869
|
-
break;
|
|
1870
|
-
}
|
|
1987
|
+
if (keyIndex !== -1) {
|
|
1988
|
+
node.keys.splice(keyIndex, 1);
|
|
1989
|
+
const valueIndex = keyIndex > 0 ? keyIndex - 1 : 0;
|
|
1990
|
+
node.values.splice(valueIndex, 1);
|
|
1991
|
+
await this.bufferForNodeUpdate(node);
|
|
1871
1992
|
}
|
|
1872
1993
|
}
|
|
1873
1994
|
if (this.rootId === node.id && node.keys.length === 1 && !node.leaf) {
|
|
1874
1995
|
const keys = node.keys;
|
|
1875
|
-
this.bufferForNodeDelete(node);
|
|
1996
|
+
await this.bufferForNodeDelete(node);
|
|
1876
1997
|
const newRoot = await this.getNode(keys[0]);
|
|
1877
1998
|
this.rootId = newRoot.id;
|
|
1878
1999
|
newRoot.parent = null;
|
|
1879
2000
|
this.strategy.head.root = this.rootId;
|
|
1880
|
-
this.bufferForNodeUpdate(newRoot);
|
|
2001
|
+
await this.bufferForNodeUpdate(newRoot);
|
|
1881
2002
|
return;
|
|
1882
2003
|
} else if (this.rootId === node.id) {
|
|
1883
2004
|
const root = await this.getNode(this.rootId);
|
|
1884
|
-
this.bufferForNodeUpdate(root);
|
|
2005
|
+
await this.bufferForNodeUpdate(root);
|
|
1885
2006
|
return;
|
|
1886
2007
|
} else if (node.keys.length < Math.ceil(this.order / 2) && !node.leaf || node.values.length < Math.ceil((this.order - 1) / 2) && node.leaf) {
|
|
1887
2008
|
if (node.parent === null) {
|
|
@@ -1942,7 +2063,7 @@ var BPTreeAsyncBase = class extends BPTree {
|
|
|
1942
2063
|
if (pointer.next) {
|
|
1943
2064
|
const n = await this.getNode(pointer.next);
|
|
1944
2065
|
n.prev = pointer.id;
|
|
1945
|
-
this.bufferForNodeUpdate(n);
|
|
2066
|
+
await this.bufferForNodeUpdate(n);
|
|
1946
2067
|
}
|
|
1947
2068
|
}
|
|
1948
2069
|
pointer.values.push(...node.values);
|
|
@@ -1951,12 +2072,12 @@ var BPTreeAsyncBase = class extends BPTree {
|
|
|
1951
2072
|
for (const key2 of keys) {
|
|
1952
2073
|
const n = await this.getNode(key2);
|
|
1953
2074
|
n.parent = pointer.id;
|
|
1954
|
-
this.bufferForNodeUpdate(n);
|
|
2075
|
+
await this.bufferForNodeUpdate(n);
|
|
1955
2076
|
}
|
|
1956
2077
|
}
|
|
1957
2078
|
await this._deleteEntry(await this.getNode(node.parent), node.id, guess);
|
|
1958
|
-
this.bufferForNodeUpdate(pointer);
|
|
1959
|
-
this.bufferForNodeDelete(node);
|
|
2079
|
+
await this.bufferForNodeUpdate(pointer);
|
|
2080
|
+
await this.bufferForNodeDelete(node);
|
|
1960
2081
|
} else {
|
|
1961
2082
|
if (isPredecessor) {
|
|
1962
2083
|
let pointerPm;
|
|
@@ -1967,13 +2088,10 @@ var BPTreeAsyncBase = class extends BPTree {
|
|
|
1967
2088
|
node.keys = [pointerPm, ...node.keys];
|
|
1968
2089
|
node.values = [guess, ...node.values];
|
|
1969
2090
|
parentNode = await this.getNode(node.parent);
|
|
1970
|
-
|
|
1971
|
-
|
|
1972
|
-
|
|
1973
|
-
|
|
1974
|
-
this.bufferForNodeUpdate(parentNode);
|
|
1975
|
-
break;
|
|
1976
|
-
}
|
|
2091
|
+
const nodeIndex = parentNode.keys.indexOf(node.id);
|
|
2092
|
+
if (nodeIndex > 0) {
|
|
2093
|
+
parentNode.values[nodeIndex - 1] = pointerKm;
|
|
2094
|
+
await this.bufferForNodeUpdate(parentNode);
|
|
1977
2095
|
}
|
|
1978
2096
|
} else {
|
|
1979
2097
|
pointerPm = pointer.keys.splice(-1)[0];
|
|
@@ -1981,17 +2099,14 @@ var BPTreeAsyncBase = class extends BPTree {
|
|
|
1981
2099
|
node.keys = [pointerPm, ...node.keys];
|
|
1982
2100
|
node.values = [pointerKm, ...node.values];
|
|
1983
2101
|
parentNode = await this.getNode(node.parent);
|
|
1984
|
-
|
|
1985
|
-
|
|
1986
|
-
|
|
1987
|
-
|
|
1988
|
-
this.bufferForNodeUpdate(parentNode);
|
|
1989
|
-
break;
|
|
1990
|
-
}
|
|
2102
|
+
const nodeIndex = parentNode.keys.indexOf(node.id);
|
|
2103
|
+
if (nodeIndex > 0) {
|
|
2104
|
+
parentNode.values[nodeIndex - 1] = pointerKm;
|
|
2105
|
+
await this.bufferForNodeUpdate(parentNode);
|
|
1991
2106
|
}
|
|
1992
2107
|
}
|
|
1993
|
-
this.bufferForNodeUpdate(node);
|
|
1994
|
-
this.bufferForNodeUpdate(pointer);
|
|
2108
|
+
await this.bufferForNodeUpdate(node);
|
|
2109
|
+
await this.bufferForNodeUpdate(pointer);
|
|
1995
2110
|
} else {
|
|
1996
2111
|
let pointerP0;
|
|
1997
2112
|
let pointerK0;
|
|
@@ -2001,13 +2116,10 @@ var BPTreeAsyncBase = class extends BPTree {
|
|
|
2001
2116
|
node.keys = [...node.keys, pointerP0];
|
|
2002
2117
|
node.values = [...node.values, guess];
|
|
2003
2118
|
parentNode = await this.getNode(node.parent);
|
|
2004
|
-
|
|
2005
|
-
|
|
2006
|
-
|
|
2007
|
-
|
|
2008
|
-
this.bufferForNodeUpdate(parentNode);
|
|
2009
|
-
break;
|
|
2010
|
-
}
|
|
2119
|
+
const pointerIndex = parentNode.keys.indexOf(pointer.id);
|
|
2120
|
+
if (pointerIndex > 0) {
|
|
2121
|
+
parentNode.values[pointerIndex - 1] = pointerK0;
|
|
2122
|
+
await this.bufferForNodeUpdate(parentNode);
|
|
2011
2123
|
}
|
|
2012
2124
|
} else {
|
|
2013
2125
|
pointerP0 = pointer.keys.splice(0, 1)[0];
|
|
@@ -2015,24 +2127,21 @@ var BPTreeAsyncBase = class extends BPTree {
|
|
|
2015
2127
|
node.keys = [...node.keys, pointerP0];
|
|
2016
2128
|
node.values = [...node.values, pointerK0];
|
|
2017
2129
|
parentNode = await this.getNode(node.parent);
|
|
2018
|
-
|
|
2019
|
-
|
|
2020
|
-
|
|
2021
|
-
|
|
2022
|
-
this.bufferForNodeUpdate(parentNode);
|
|
2023
|
-
break;
|
|
2024
|
-
}
|
|
2130
|
+
const pointerIndex = parentNode.keys.indexOf(pointer.id);
|
|
2131
|
+
if (pointerIndex > 0) {
|
|
2132
|
+
parentNode.values[pointerIndex - 1] = pointer.values[0];
|
|
2133
|
+
await this.bufferForNodeUpdate(parentNode);
|
|
2025
2134
|
}
|
|
2026
2135
|
}
|
|
2027
|
-
this.bufferForNodeUpdate(node);
|
|
2028
|
-
this.bufferForNodeUpdate(pointer);
|
|
2136
|
+
await this.bufferForNodeUpdate(node);
|
|
2137
|
+
await this.bufferForNodeUpdate(pointer);
|
|
2029
2138
|
}
|
|
2030
2139
|
if (!pointer.leaf) {
|
|
2031
2140
|
const keys = pointer.keys;
|
|
2032
2141
|
for (const key2 of keys) {
|
|
2033
2142
|
const n = await this.getNode(key2);
|
|
2034
2143
|
n.parent = pointer.id;
|
|
2035
|
-
this.bufferForNodeUpdate(n);
|
|
2144
|
+
await this.bufferForNodeUpdate(n);
|
|
2036
2145
|
}
|
|
2037
2146
|
}
|
|
2038
2147
|
if (!node.leaf) {
|
|
@@ -2040,7 +2149,7 @@ var BPTreeAsyncBase = class extends BPTree {
|
|
|
2040
2149
|
for (const key2 of keys) {
|
|
2041
2150
|
const n = await this.getNode(key2);
|
|
2042
2151
|
n.parent = node.id;
|
|
2043
|
-
this.bufferForNodeUpdate(n);
|
|
2152
|
+
await this.bufferForNodeUpdate(n);
|
|
2044
2153
|
}
|
|
2045
2154
|
}
|
|
2046
2155
|
if (!parentNode.leaf) {
|
|
@@ -2048,10 +2157,12 @@ var BPTreeAsyncBase = class extends BPTree {
|
|
|
2048
2157
|
for (const key2 of keys) {
|
|
2049
2158
|
const n = await this.getNode(key2);
|
|
2050
2159
|
n.parent = parentNode.id;
|
|
2051
|
-
this.bufferForNodeUpdate(n);
|
|
2160
|
+
await this.bufferForNodeUpdate(n);
|
|
2052
2161
|
}
|
|
2053
2162
|
}
|
|
2054
2163
|
}
|
|
2164
|
+
} else {
|
|
2165
|
+
await this.bufferForNodeUpdate(node);
|
|
2055
2166
|
}
|
|
2056
2167
|
}
|
|
2057
2168
|
async _insertInParent(node, value, pointer) {
|
|
@@ -2062,43 +2173,39 @@ var BPTreeAsyncBase = class extends BPTree {
|
|
|
2062
2173
|
node.parent = root.id;
|
|
2063
2174
|
pointer.parent = root.id;
|
|
2064
2175
|
if (pointer.leaf) {
|
|
2065
|
-
|
|
2066
|
-
|
|
2176
|
+
const nNode = node;
|
|
2177
|
+
nNode.next = pointer.id;
|
|
2178
|
+
const nPointer = pointer;
|
|
2179
|
+
nPointer.prev = node.id;
|
|
2067
2180
|
}
|
|
2068
|
-
this.bufferForNodeUpdate(node);
|
|
2069
|
-
this.bufferForNodeUpdate(pointer);
|
|
2181
|
+
await this.bufferForNodeUpdate(node);
|
|
2182
|
+
await this.bufferForNodeUpdate(pointer);
|
|
2070
2183
|
return;
|
|
2071
2184
|
}
|
|
2072
2185
|
const parentNode = await this.getNode(node.parent);
|
|
2073
|
-
|
|
2074
|
-
|
|
2075
|
-
|
|
2076
|
-
insertIndex = i + 1;
|
|
2077
|
-
} else {
|
|
2078
|
-
break;
|
|
2079
|
-
}
|
|
2186
|
+
const nodeIndex = parentNode.keys.indexOf(node.id);
|
|
2187
|
+
if (nodeIndex === -1) {
|
|
2188
|
+
throw new Error(`Node ${node.id} not found in parent ${parentNode.id}`);
|
|
2080
2189
|
}
|
|
2190
|
+
const insertIndex = nodeIndex;
|
|
2081
2191
|
parentNode.values.splice(insertIndex, 0, value);
|
|
2082
2192
|
parentNode.keys.splice(insertIndex + 1, 0, pointer.id);
|
|
2083
2193
|
pointer.parent = parentNode.id;
|
|
2084
2194
|
if (pointer.leaf) {
|
|
2085
|
-
const
|
|
2086
|
-
const
|
|
2087
|
-
|
|
2088
|
-
|
|
2089
|
-
|
|
2090
|
-
|
|
2091
|
-
|
|
2092
|
-
this.
|
|
2093
|
-
|
|
2094
|
-
|
|
2095
|
-
|
|
2096
|
-
|
|
2097
|
-
|
|
2098
|
-
|
|
2099
|
-
}
|
|
2100
|
-
this.bufferForNodeUpdate(parentNode);
|
|
2101
|
-
this.bufferForNodeUpdate(pointer);
|
|
2195
|
+
const leftSibling = node;
|
|
2196
|
+
const oldNextId = leftSibling.next;
|
|
2197
|
+
pointer.prev = leftSibling.id;
|
|
2198
|
+
pointer.next = oldNextId;
|
|
2199
|
+
leftSibling.next = pointer.id;
|
|
2200
|
+
await this.bufferForNodeUpdate(leftSibling);
|
|
2201
|
+
if (oldNextId) {
|
|
2202
|
+
const oldNext = await this.getNode(oldNextId);
|
|
2203
|
+
oldNext.prev = pointer.id;
|
|
2204
|
+
await this.bufferForNodeUpdate(oldNext);
|
|
2205
|
+
}
|
|
2206
|
+
}
|
|
2207
|
+
await this.bufferForNodeUpdate(parentNode);
|
|
2208
|
+
await this.bufferForNodeUpdate(pointer);
|
|
2102
2209
|
if (parentNode.keys.length > this.order) {
|
|
2103
2210
|
const parentPointer = await this._createNode(false, [], []);
|
|
2104
2211
|
parentPointer.parent = parentNode.parent;
|
|
@@ -2111,18 +2218,19 @@ var BPTreeAsyncBase = class extends BPTree {
|
|
|
2111
2218
|
for (const k of parentNode.keys) {
|
|
2112
2219
|
const n = await this.getNode(k);
|
|
2113
2220
|
n.parent = parentNode.id;
|
|
2114
|
-
this.bufferForNodeUpdate(n);
|
|
2221
|
+
await this.bufferForNodeUpdate(n);
|
|
2115
2222
|
}
|
|
2116
2223
|
for (const k of parentPointer.keys) {
|
|
2117
2224
|
const n = await this.getNode(k);
|
|
2118
2225
|
n.parent = parentPointer.id;
|
|
2119
|
-
this.bufferForNodeUpdate(n);
|
|
2226
|
+
await this.bufferForNodeUpdate(n);
|
|
2120
2227
|
}
|
|
2121
2228
|
await this._insertInParent(parentNode, midValue, parentPointer);
|
|
2122
|
-
this.bufferForNodeUpdate(parentNode);
|
|
2229
|
+
await this.bufferForNodeUpdate(parentNode);
|
|
2123
2230
|
}
|
|
2124
2231
|
}
|
|
2125
2232
|
async init() {
|
|
2233
|
+
this.clear();
|
|
2126
2234
|
const head = await this.strategy.readHead();
|
|
2127
2235
|
if (head === null) {
|
|
2128
2236
|
this.order = this.strategy.order;
|
|
@@ -2153,18 +2261,35 @@ var BPTreeAsyncBase = class extends BPTree {
|
|
|
2153
2261
|
}
|
|
2154
2262
|
async insertableNode(value) {
|
|
2155
2263
|
let node = await this.getNode(this.rootId);
|
|
2264
|
+
if (node.parent !== null) {
|
|
2265
|
+
node.parent = null;
|
|
2266
|
+
await this.bufferForNodeUpdate(node);
|
|
2267
|
+
}
|
|
2156
2268
|
while (!node.leaf) {
|
|
2269
|
+
const parentId = node.id;
|
|
2157
2270
|
for (let i = 0, len = node.values.length; i < len; i++) {
|
|
2158
2271
|
const nValue = node.values[i];
|
|
2159
2272
|
const k = node.keys;
|
|
2160
2273
|
if (this.comparator.isSame(value, nValue)) {
|
|
2161
2274
|
node = await this.getNode(node.keys[i + 1]);
|
|
2275
|
+
if (node.parent !== parentId) {
|
|
2276
|
+
node.parent = parentId;
|
|
2277
|
+
await this.bufferForNodeUpdate(node);
|
|
2278
|
+
}
|
|
2162
2279
|
break;
|
|
2163
2280
|
} else if (this.comparator.isLower(value, nValue)) {
|
|
2164
2281
|
node = await this.getNode(node.keys[i]);
|
|
2282
|
+
if (node.parent !== parentId) {
|
|
2283
|
+
node.parent = parentId;
|
|
2284
|
+
await this.bufferForNodeUpdate(node);
|
|
2285
|
+
}
|
|
2165
2286
|
break;
|
|
2166
2287
|
} else if (i + 1 === node.values.length) {
|
|
2167
2288
|
node = await this.getNode(node.keys[i + 1]);
|
|
2289
|
+
if (node.parent !== parentId) {
|
|
2290
|
+
node.parent = parentId;
|
|
2291
|
+
await this.bufferForNodeUpdate(node);
|
|
2292
|
+
}
|
|
2168
2293
|
break;
|
|
2169
2294
|
}
|
|
2170
2295
|
}
|
|
@@ -2173,18 +2298,35 @@ var BPTreeAsyncBase = class extends BPTree {
|
|
|
2173
2298
|
}
|
|
2174
2299
|
async insertableNodeByPrimary(value) {
|
|
2175
2300
|
let node = await this.getNode(this.rootId);
|
|
2301
|
+
if (node.parent !== null) {
|
|
2302
|
+
node.parent = null;
|
|
2303
|
+
await this.bufferForNodeUpdate(node);
|
|
2304
|
+
}
|
|
2176
2305
|
while (!node.leaf) {
|
|
2306
|
+
const parentId = node.id;
|
|
2177
2307
|
for (let i = 0, len = node.values.length; i < len; i++) {
|
|
2178
2308
|
const nValue = node.values[i];
|
|
2179
2309
|
const k = node.keys;
|
|
2180
2310
|
if (this.comparator.isPrimarySame(value, nValue)) {
|
|
2181
2311
|
node = await this.getNode(node.keys[i]);
|
|
2312
|
+
if (node.parent !== parentId) {
|
|
2313
|
+
node.parent = parentId;
|
|
2314
|
+
await this.bufferForNodeUpdate(node);
|
|
2315
|
+
}
|
|
2182
2316
|
break;
|
|
2183
2317
|
} else if (this.comparator.isPrimaryLower(value, nValue)) {
|
|
2184
2318
|
node = await this.getNode(node.keys[i]);
|
|
2319
|
+
if (node.parent !== parentId) {
|
|
2320
|
+
node.parent = parentId;
|
|
2321
|
+
await this.bufferForNodeUpdate(node);
|
|
2322
|
+
}
|
|
2185
2323
|
break;
|
|
2186
2324
|
} else if (i + 1 === node.values.length) {
|
|
2187
2325
|
node = await this.getNode(node.keys[i + 1]);
|
|
2326
|
+
if (node.parent !== parentId) {
|
|
2327
|
+
node.parent = parentId;
|
|
2328
|
+
await this.bufferForNodeUpdate(node);
|
|
2329
|
+
}
|
|
2188
2330
|
break;
|
|
2189
2331
|
}
|
|
2190
2332
|
}
|
|
@@ -2193,16 +2335,29 @@ var BPTreeAsyncBase = class extends BPTree {
|
|
|
2193
2335
|
}
|
|
2194
2336
|
async insertableRightestNodeByPrimary(value) {
|
|
2195
2337
|
let node = await this.getNode(this.rootId);
|
|
2338
|
+
if (node.parent !== null) {
|
|
2339
|
+
node.parent = null;
|
|
2340
|
+
await this.bufferForNodeUpdate(node);
|
|
2341
|
+
}
|
|
2196
2342
|
while (!node.leaf) {
|
|
2343
|
+
const parentId = node.id;
|
|
2197
2344
|
for (let i = 0, len = node.values.length; i < len; i++) {
|
|
2198
2345
|
const nValue = node.values[i];
|
|
2199
2346
|
const k = node.keys;
|
|
2200
2347
|
if (this.comparator.isPrimaryLower(value, nValue)) {
|
|
2201
2348
|
node = await this.getNode(node.keys[i]);
|
|
2349
|
+
if (node.parent !== parentId) {
|
|
2350
|
+
node.parent = parentId;
|
|
2351
|
+
await this.bufferForNodeUpdate(node);
|
|
2352
|
+
}
|
|
2202
2353
|
break;
|
|
2203
2354
|
}
|
|
2204
2355
|
if (i + 1 === node.values.length) {
|
|
2205
2356
|
node = await this.getNode(node.keys[i + 1]);
|
|
2357
|
+
if (node.parent !== parentId) {
|
|
2358
|
+
node.parent = parentId;
|
|
2359
|
+
await this.bufferForNodeUpdate(node);
|
|
2360
|
+
}
|
|
2206
2361
|
break;
|
|
2207
2362
|
}
|
|
2208
2363
|
}
|
|
@@ -2237,17 +2392,35 @@ var BPTreeAsyncBase = class extends BPTree {
|
|
|
2237
2392
|
}
|
|
2238
2393
|
async leftestNode() {
|
|
2239
2394
|
let node = await this.getNode(this.rootId);
|
|
2395
|
+
if (node.parent !== null) {
|
|
2396
|
+
node.parent = null;
|
|
2397
|
+
await this.bufferForNodeUpdate(node);
|
|
2398
|
+
}
|
|
2240
2399
|
while (!node.leaf) {
|
|
2400
|
+
const parentId = node.id;
|
|
2241
2401
|
const keys = node.keys;
|
|
2242
2402
|
node = await this.getNode(node.keys[0]);
|
|
2403
|
+
if (node.parent !== parentId) {
|
|
2404
|
+
node.parent = parentId;
|
|
2405
|
+
await this.bufferForNodeUpdate(node);
|
|
2406
|
+
}
|
|
2243
2407
|
}
|
|
2244
2408
|
return node;
|
|
2245
2409
|
}
|
|
2246
2410
|
async rightestNode() {
|
|
2247
2411
|
let node = await this.getNode(this.rootId);
|
|
2412
|
+
if (node.parent !== null) {
|
|
2413
|
+
node.parent = null;
|
|
2414
|
+
await this.bufferForNodeUpdate(node);
|
|
2415
|
+
}
|
|
2248
2416
|
while (!node.leaf) {
|
|
2417
|
+
const parentId = node.id;
|
|
2249
2418
|
const keys = node.keys;
|
|
2250
2419
|
node = await this.getNode(node.keys[node.keys.length - 1]);
|
|
2420
|
+
if (node.parent !== parentId) {
|
|
2421
|
+
node.parent = parentId;
|
|
2422
|
+
await this.bufferForNodeUpdate(node);
|
|
2423
|
+
}
|
|
2251
2424
|
}
|
|
2252
2425
|
return node;
|
|
2253
2426
|
}
|
|
@@ -2407,7 +2580,7 @@ var BPTreeAsyncBase = class extends BPTree {
|
|
|
2407
2580
|
async insert(key, value) {
|
|
2408
2581
|
await this.writeLock(async () => {
|
|
2409
2582
|
const before = await this.insertableNode(value);
|
|
2410
|
-
this._insertAtLeaf(before, key, value);
|
|
2583
|
+
await this._insertAtLeaf(before, key, value);
|
|
2411
2584
|
if (before.values.length === this.order) {
|
|
2412
2585
|
const after = await this._createNode(
|
|
2413
2586
|
true,
|
|
@@ -2424,7 +2597,7 @@ var BPTreeAsyncBase = class extends BPTree {
|
|
|
2424
2597
|
before.values = before.values.slice(0, mid + 1);
|
|
2425
2598
|
before.keys = before.keys.slice(0, mid + 1);
|
|
2426
2599
|
await this._insertInParent(before, after.values[0], after);
|
|
2427
|
-
this.bufferForNodeUpdate(before);
|
|
2600
|
+
await this.bufferForNodeUpdate(before);
|
|
2428
2601
|
}
|
|
2429
2602
|
await this.commitHeadBuffer();
|
|
2430
2603
|
await this.commitNodeCreateBuffer();
|
|
@@ -2447,11 +2620,13 @@ var BPTreeAsyncBase = class extends BPTree {
|
|
|
2447
2620
|
node.values.splice(i, 1);
|
|
2448
2621
|
}
|
|
2449
2622
|
await this._deleteEntry(node, key, value);
|
|
2623
|
+
await this.bufferForNodeUpdate(node);
|
|
2450
2624
|
break;
|
|
2451
2625
|
}
|
|
2452
2626
|
}
|
|
2453
2627
|
}
|
|
2454
2628
|
await this.commitHeadBuffer();
|
|
2629
|
+
await this.commitNodeCreateBuffer();
|
|
2455
2630
|
await this.commitNodeUpdateBuffer();
|
|
2456
2631
|
await this.commitNodeDeleteBuffer();
|
|
2457
2632
|
});
|
|
@@ -2577,23 +2752,37 @@ var BPTreeAsyncTransaction = class extends BPTreeAsyncBase {
|
|
|
2577
2752
|
realBaseTree;
|
|
2578
2753
|
realBaseStrategy;
|
|
2579
2754
|
txNodes = /* @__PURE__ */ new Map();
|
|
2580
|
-
dirtyIds
|
|
2581
|
-
createdInTx
|
|
2755
|
+
dirtyIds;
|
|
2756
|
+
createdInTx;
|
|
2757
|
+
deletedIds;
|
|
2582
2758
|
initialRootId;
|
|
2583
2759
|
transactionRootId;
|
|
2584
2760
|
constructor(baseTree) {
|
|
2585
2761
|
super(baseTree.strategy, baseTree.comparator, baseTree.option);
|
|
2586
2762
|
this.realBaseTree = baseTree;
|
|
2587
2763
|
this.realBaseStrategy = baseTree.strategy;
|
|
2764
|
+
this.order = baseTree.getOrder();
|
|
2588
2765
|
this.initialRootId = "";
|
|
2589
2766
|
this.transactionRootId = "";
|
|
2767
|
+
this.dirtyIds = /* @__PURE__ */ new Set();
|
|
2768
|
+
this.createdInTx = /* @__PURE__ */ new Set();
|
|
2769
|
+
this.deletedIds = /* @__PURE__ */ new Set();
|
|
2590
2770
|
}
|
|
2591
2771
|
/**
|
|
2592
2772
|
* Initializes the transaction by capturing the current state of the tree.
|
|
2593
2773
|
*/
|
|
2594
2774
|
async initTransaction() {
|
|
2595
2775
|
const head = await this.realBaseStrategy.readHead();
|
|
2596
|
-
|
|
2776
|
+
if (head) {
|
|
2777
|
+
this.order = head.order;
|
|
2778
|
+
this.initialRootId = head.root;
|
|
2779
|
+
} else {
|
|
2780
|
+
this.initialRootId = this.realBaseTree.getRootId();
|
|
2781
|
+
}
|
|
2782
|
+
if (!this.initialRootId) {
|
|
2783
|
+
const root = await this._createNode(true, [], [], true);
|
|
2784
|
+
this.initialRootId = root.id;
|
|
2785
|
+
}
|
|
2597
2786
|
this.transactionRootId = this.initialRootId;
|
|
2598
2787
|
this.rootId = this.transactionRootId;
|
|
2599
2788
|
const snapshotStrategy = new BPTreeAsyncSnapshotStrategy(this.realBaseStrategy, this.initialRootId);
|
|
@@ -2601,34 +2790,76 @@ var BPTreeAsyncTransaction = class extends BPTreeAsyncBase {
|
|
|
2601
2790
|
this.txNodes.clear();
|
|
2602
2791
|
this.dirtyIds.clear();
|
|
2603
2792
|
this.createdInTx.clear();
|
|
2793
|
+
this.deletedIds.clear();
|
|
2604
2794
|
}
|
|
2605
2795
|
async getNode(id) {
|
|
2606
2796
|
if (this.txNodes.has(id)) {
|
|
2607
2797
|
return this.txNodes.get(id);
|
|
2608
2798
|
}
|
|
2799
|
+
if (this.deletedIds.has(id)) {
|
|
2800
|
+
throw new Error(`The tree attempted to reference deleted node '${id}'`);
|
|
2801
|
+
}
|
|
2609
2802
|
const baseNode = await this.realBaseStrategy.read(id);
|
|
2610
2803
|
const clone = JSON.parse(JSON.stringify(baseNode));
|
|
2611
2804
|
this.txNodes.set(id, clone);
|
|
2612
2805
|
return clone;
|
|
2613
2806
|
}
|
|
2614
2807
|
async bufferForNodeUpdate(node) {
|
|
2808
|
+
if (this.dirtyIds.has(node.id) && this.txNodes.has(node.id) && node._p) {
|
|
2809
|
+
this.txNodes.set(node.id, node);
|
|
2810
|
+
return;
|
|
2811
|
+
}
|
|
2812
|
+
node._p = true;
|
|
2615
2813
|
this.txNodes.set(node.id, node);
|
|
2616
2814
|
this.dirtyIds.add(node.id);
|
|
2815
|
+
if (node.leaf) {
|
|
2816
|
+
if (node.next && !this.dirtyIds.has(node.next) && !this.deletedIds.has(node.next)) {
|
|
2817
|
+
try {
|
|
2818
|
+
await this.bufferForNodeUpdate(await this.getNode(node.next));
|
|
2819
|
+
} catch (e) {
|
|
2820
|
+
}
|
|
2821
|
+
}
|
|
2822
|
+
if (node.prev && !this.dirtyIds.has(node.prev) && !this.deletedIds.has(node.prev)) {
|
|
2823
|
+
try {
|
|
2824
|
+
await this.bufferForNodeUpdate(await this.getNode(node.prev));
|
|
2825
|
+
} catch (e) {
|
|
2826
|
+
}
|
|
2827
|
+
}
|
|
2828
|
+
}
|
|
2617
2829
|
await this.markPathDirty(node);
|
|
2830
|
+
delete node._p;
|
|
2618
2831
|
}
|
|
2619
2832
|
async bufferForNodeCreate(node) {
|
|
2620
2833
|
this.txNodes.set(node.id, node);
|
|
2621
2834
|
this.dirtyIds.add(node.id);
|
|
2622
2835
|
this.createdInTx.add(node.id);
|
|
2836
|
+
if (node.leaf) {
|
|
2837
|
+
if (node.next && !this.dirtyIds.has(node.next) && !this.deletedIds.has(node.next)) {
|
|
2838
|
+
try {
|
|
2839
|
+
await this.bufferForNodeUpdate(await this.getNode(node.next));
|
|
2840
|
+
} catch (e) {
|
|
2841
|
+
}
|
|
2842
|
+
}
|
|
2843
|
+
if (node.prev && !this.dirtyIds.has(node.prev) && !this.deletedIds.has(node.prev)) {
|
|
2844
|
+
try {
|
|
2845
|
+
await this.bufferForNodeUpdate(await this.getNode(node.prev));
|
|
2846
|
+
} catch (e) {
|
|
2847
|
+
}
|
|
2848
|
+
}
|
|
2849
|
+
}
|
|
2623
2850
|
await this.markPathDirty(node);
|
|
2624
2851
|
}
|
|
2625
2852
|
async bufferForNodeDelete(node) {
|
|
2626
2853
|
this.txNodes.delete(node.id);
|
|
2627
2854
|
this.dirtyIds.add(node.id);
|
|
2855
|
+
this.deletedIds.add(node.id);
|
|
2628
2856
|
}
|
|
2629
2857
|
async markPathDirty(node) {
|
|
2630
2858
|
let curr = node;
|
|
2631
2859
|
while (curr.parent) {
|
|
2860
|
+
if (this.deletedIds.has(curr.parent)) {
|
|
2861
|
+
break;
|
|
2862
|
+
}
|
|
2632
2863
|
if (this.dirtyIds.has(curr.parent) && this.txNodes.has(curr.parent)) {
|
|
2633
2864
|
break;
|
|
2634
2865
|
}
|
|
@@ -2640,13 +2871,13 @@ var BPTreeAsyncTransaction = class extends BPTreeAsyncBase {
|
|
|
2640
2871
|
this.transactionRootId = curr.id;
|
|
2641
2872
|
}
|
|
2642
2873
|
}
|
|
2643
|
-
async _createNode(isLeaf, keys, values, leaf =
|
|
2644
|
-
const id = await this.
|
|
2874
|
+
async _createNode(isLeaf, keys, values, leaf = isLeaf, parent = null, next = null, prev = null) {
|
|
2875
|
+
const id = await this.strategy.id(isLeaf);
|
|
2645
2876
|
const node = {
|
|
2646
2877
|
id,
|
|
2647
2878
|
keys,
|
|
2648
2879
|
values,
|
|
2649
|
-
leaf
|
|
2880
|
+
leaf,
|
|
2650
2881
|
parent,
|
|
2651
2882
|
next,
|
|
2652
2883
|
prev
|
|
@@ -2704,9 +2935,9 @@ var BPTreeAsyncTransaction = class extends BPTreeAsyncBase {
|
|
|
2704
2935
|
finalNodes.push(node);
|
|
2705
2936
|
newCreatedIds.push(newId);
|
|
2706
2937
|
}
|
|
2707
|
-
let newRootId = this.
|
|
2708
|
-
if (idMapping.has(this.
|
|
2709
|
-
newRootId = idMapping.get(this.
|
|
2938
|
+
let newRootId = this.rootId;
|
|
2939
|
+
if (idMapping.has(this.rootId)) {
|
|
2940
|
+
newRootId = idMapping.get(this.rootId);
|
|
2710
2941
|
}
|
|
2711
2942
|
for (const node of finalNodes) {
|
|
2712
2943
|
await this.realBaseStrategy.write(node.id, node);
|
|
@@ -2735,12 +2966,21 @@ var BPTreeAsyncTransaction = class extends BPTreeAsyncBase {
|
|
|
2735
2966
|
}
|
|
2736
2967
|
/**
|
|
2737
2968
|
* Rolls back the transaction by clearing all buffered changes.
|
|
2738
|
-
*
|
|
2969
|
+
* If cleanup is `true`, it also clears the transaction nodes.
|
|
2970
|
+
* @param cleanup Whether to clear the transaction nodes.
|
|
2971
|
+
* @returns The IDs of nodes that were created in this transaction.
|
|
2739
2972
|
*/
|
|
2740
|
-
async rollback() {
|
|
2973
|
+
async rollback(cleanup = true) {
|
|
2974
|
+
const createdIds = Array.from(this.createdInTx);
|
|
2741
2975
|
this.txNodes.clear();
|
|
2742
2976
|
this.dirtyIds.clear();
|
|
2743
2977
|
this.createdInTx.clear();
|
|
2978
|
+
if (cleanup) {
|
|
2979
|
+
for (const id of createdIds) {
|
|
2980
|
+
await this.realBaseStrategy.delete(id);
|
|
2981
|
+
}
|
|
2982
|
+
}
|
|
2983
|
+
return createdIds;
|
|
2744
2984
|
}
|
|
2745
2985
|
async readLock(fn) {
|
|
2746
2986
|
return await fn();
|