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/cjs/index.cjs
CHANGED
|
@@ -475,6 +475,20 @@ var BPTree = class _BPTree {
|
|
|
475
475
|
option;
|
|
476
476
|
order;
|
|
477
477
|
rootId;
|
|
478
|
+
/**
|
|
479
|
+
* Returns the ID of the root node.
|
|
480
|
+
* @returns The root node ID.
|
|
481
|
+
*/
|
|
482
|
+
getRootId() {
|
|
483
|
+
return this.rootId;
|
|
484
|
+
}
|
|
485
|
+
/**
|
|
486
|
+
* Returns the order of the B+Tree.
|
|
487
|
+
* @returns The order of the tree.
|
|
488
|
+
*/
|
|
489
|
+
getOrder() {
|
|
490
|
+
return this.order;
|
|
491
|
+
}
|
|
478
492
|
_strategyDirty;
|
|
479
493
|
_nodeCreateBuffer;
|
|
480
494
|
_nodeUpdateBuffer;
|
|
@@ -707,24 +721,21 @@ var BPTree = class _BPTree {
|
|
|
707
721
|
break;
|
|
708
722
|
}
|
|
709
723
|
keys.push(key);
|
|
710
|
-
this.bufferForNodeUpdate(node);
|
|
711
|
-
break;
|
|
724
|
+
return this.bufferForNodeUpdate(node);
|
|
712
725
|
} else if (this.comparator.isLower(value, nValue)) {
|
|
713
726
|
node.values.splice(i, 0, value);
|
|
714
727
|
node.keys.splice(i, 0, [key]);
|
|
715
|
-
this.bufferForNodeUpdate(node);
|
|
716
|
-
break;
|
|
728
|
+
return this.bufferForNodeUpdate(node);
|
|
717
729
|
} else if (i + 1 === node.values.length) {
|
|
718
730
|
node.values.push(value);
|
|
719
731
|
node.keys.push([key]);
|
|
720
|
-
this.bufferForNodeUpdate(node);
|
|
721
|
-
break;
|
|
732
|
+
return this.bufferForNodeUpdate(node);
|
|
722
733
|
}
|
|
723
734
|
}
|
|
724
735
|
} else {
|
|
725
736
|
node.values = [value];
|
|
726
737
|
node.keys = [[key]];
|
|
727
|
-
this.bufferForNodeUpdate(node);
|
|
738
|
+
return this.bufferForNodeUpdate(node);
|
|
728
739
|
}
|
|
729
740
|
}
|
|
730
741
|
bufferForNodeCreate(node) {
|
|
@@ -840,7 +851,7 @@ var BPTreeSyncBase = class extends BPTree {
|
|
|
840
851
|
}
|
|
841
852
|
return id;
|
|
842
853
|
}
|
|
843
|
-
_createNode(isLeaf, keys, values, leaf =
|
|
854
|
+
_createNode(isLeaf, keys, values, leaf = isLeaf, parent = null, next = null, prev = null) {
|
|
844
855
|
const id = this._createNodeId(isLeaf);
|
|
845
856
|
const node = {
|
|
846
857
|
id,
|
|
@@ -851,26 +862,23 @@ var BPTreeSyncBase = class extends BPTree {
|
|
|
851
862
|
next,
|
|
852
863
|
prev
|
|
853
864
|
};
|
|
854
|
-
this.
|
|
865
|
+
this.bufferForNodeCreate(node);
|
|
855
866
|
return node;
|
|
856
867
|
}
|
|
857
868
|
_deleteEntry(node, key, value) {
|
|
858
869
|
if (!node.leaf) {
|
|
870
|
+
let keyIndex = -1;
|
|
859
871
|
for (let i = 0, len = node.keys.length; i < len; i++) {
|
|
860
|
-
|
|
861
|
-
|
|
862
|
-
node.keys.splice(i, 1);
|
|
863
|
-
this.bufferForNodeUpdate(node);
|
|
872
|
+
if (node.keys[i] === key) {
|
|
873
|
+
keyIndex = i;
|
|
864
874
|
break;
|
|
865
875
|
}
|
|
866
876
|
}
|
|
867
|
-
|
|
868
|
-
|
|
869
|
-
|
|
870
|
-
|
|
871
|
-
|
|
872
|
-
break;
|
|
873
|
-
}
|
|
877
|
+
if (keyIndex !== -1) {
|
|
878
|
+
node.keys.splice(keyIndex, 1);
|
|
879
|
+
const valueIndex = keyIndex > 0 ? keyIndex - 1 : 0;
|
|
880
|
+
node.values.splice(valueIndex, 1);
|
|
881
|
+
this.bufferForNodeUpdate(node);
|
|
874
882
|
}
|
|
875
883
|
}
|
|
876
884
|
if (this.rootId === node.id && node.keys.length === 1 && !node.leaf) {
|
|
@@ -970,13 +978,10 @@ var BPTreeSyncBase = class extends BPTree {
|
|
|
970
978
|
node.keys = [pointerPm, ...node.keys];
|
|
971
979
|
node.values = [guess, ...node.values];
|
|
972
980
|
parentNode = this.getNode(node.parent);
|
|
973
|
-
|
|
974
|
-
|
|
975
|
-
|
|
976
|
-
|
|
977
|
-
this.bufferForNodeUpdate(parentNode);
|
|
978
|
-
break;
|
|
979
|
-
}
|
|
981
|
+
const nodeIndex = parentNode.keys.indexOf(node.id);
|
|
982
|
+
if (nodeIndex > 0) {
|
|
983
|
+
parentNode.values[nodeIndex - 1] = pointerKm;
|
|
984
|
+
this.bufferForNodeUpdate(parentNode);
|
|
980
985
|
}
|
|
981
986
|
} else {
|
|
982
987
|
pointerPm = pointer.keys.splice(-1)[0];
|
|
@@ -984,13 +989,10 @@ var BPTreeSyncBase = class extends BPTree {
|
|
|
984
989
|
node.keys = [pointerPm, ...node.keys];
|
|
985
990
|
node.values = [pointerKm, ...node.values];
|
|
986
991
|
parentNode = this.getNode(node.parent);
|
|
987
|
-
|
|
988
|
-
|
|
989
|
-
|
|
990
|
-
|
|
991
|
-
this.bufferForNodeUpdate(parentNode);
|
|
992
|
-
break;
|
|
993
|
-
}
|
|
992
|
+
const nodeIndex = parentNode.keys.indexOf(node.id);
|
|
993
|
+
if (nodeIndex > 0) {
|
|
994
|
+
parentNode.values[nodeIndex - 1] = pointerKm;
|
|
995
|
+
this.bufferForNodeUpdate(parentNode);
|
|
994
996
|
}
|
|
995
997
|
}
|
|
996
998
|
this.bufferForNodeUpdate(node);
|
|
@@ -1004,13 +1006,10 @@ var BPTreeSyncBase = class extends BPTree {
|
|
|
1004
1006
|
node.keys = [...node.keys, pointerP0];
|
|
1005
1007
|
node.values = [...node.values, guess];
|
|
1006
1008
|
parentNode = this.getNode(node.parent);
|
|
1007
|
-
|
|
1008
|
-
|
|
1009
|
-
|
|
1010
|
-
|
|
1011
|
-
this.bufferForNodeUpdate(parentNode);
|
|
1012
|
-
break;
|
|
1013
|
-
}
|
|
1009
|
+
const pointerIndex = parentNode.keys.indexOf(pointer.id);
|
|
1010
|
+
if (pointerIndex > 0) {
|
|
1011
|
+
parentNode.values[pointerIndex - 1] = pointerK0;
|
|
1012
|
+
this.bufferForNodeUpdate(parentNode);
|
|
1014
1013
|
}
|
|
1015
1014
|
} else {
|
|
1016
1015
|
pointerP0 = pointer.keys.splice(0, 1)[0];
|
|
@@ -1018,13 +1017,10 @@ var BPTreeSyncBase = class extends BPTree {
|
|
|
1018
1017
|
node.keys = [...node.keys, pointerP0];
|
|
1019
1018
|
node.values = [...node.values, pointerK0];
|
|
1020
1019
|
parentNode = this.getNode(node.parent);
|
|
1021
|
-
|
|
1022
|
-
|
|
1023
|
-
|
|
1024
|
-
|
|
1025
|
-
this.bufferForNodeUpdate(parentNode);
|
|
1026
|
-
break;
|
|
1027
|
-
}
|
|
1020
|
+
const pointerIndex = parentNode.keys.indexOf(pointer.id);
|
|
1021
|
+
if (pointerIndex > 0) {
|
|
1022
|
+
parentNode.values[pointerIndex - 1] = pointer.values[0];
|
|
1023
|
+
this.bufferForNodeUpdate(parentNode);
|
|
1028
1024
|
}
|
|
1029
1025
|
}
|
|
1030
1026
|
this.bufferForNodeUpdate(node);
|
|
@@ -1052,6 +1048,8 @@ var BPTreeSyncBase = class extends BPTree {
|
|
|
1052
1048
|
}
|
|
1053
1049
|
}
|
|
1054
1050
|
}
|
|
1051
|
+
} else {
|
|
1052
|
+
this.bufferForNodeUpdate(node);
|
|
1055
1053
|
}
|
|
1056
1054
|
}
|
|
1057
1055
|
_insertInParent(node, value, pointer) {
|
|
@@ -1070,31 +1068,25 @@ var BPTreeSyncBase = class extends BPTree {
|
|
|
1070
1068
|
return;
|
|
1071
1069
|
}
|
|
1072
1070
|
const parentNode = this.getNode(node.parent);
|
|
1073
|
-
|
|
1074
|
-
|
|
1075
|
-
|
|
1076
|
-
insertIndex = i + 1;
|
|
1077
|
-
} else {
|
|
1078
|
-
break;
|
|
1079
|
-
}
|
|
1071
|
+
const nodeIndex = parentNode.keys.indexOf(node.id);
|
|
1072
|
+
if (nodeIndex === -1) {
|
|
1073
|
+
throw new Error(`Node ${node.id} not found in parent ${parentNode.id}`);
|
|
1080
1074
|
}
|
|
1075
|
+
const insertIndex = nodeIndex;
|
|
1081
1076
|
parentNode.values.splice(insertIndex, 0, value);
|
|
1082
1077
|
parentNode.keys.splice(insertIndex + 1, 0, pointer.id);
|
|
1083
1078
|
pointer.parent = parentNode.id;
|
|
1084
1079
|
if (pointer.leaf) {
|
|
1085
|
-
const
|
|
1086
|
-
const
|
|
1087
|
-
|
|
1088
|
-
|
|
1089
|
-
|
|
1090
|
-
|
|
1091
|
-
|
|
1092
|
-
this.
|
|
1093
|
-
|
|
1094
|
-
|
|
1095
|
-
const rightSibling = this.getNode(rightSiblingId);
|
|
1096
|
-
rightSibling.prev = pointer.id;
|
|
1097
|
-
this.bufferForNodeUpdate(rightSibling);
|
|
1080
|
+
const leftSibling = node;
|
|
1081
|
+
const oldNextId = leftSibling.next;
|
|
1082
|
+
pointer.prev = leftSibling.id;
|
|
1083
|
+
pointer.next = oldNextId;
|
|
1084
|
+
leftSibling.next = pointer.id;
|
|
1085
|
+
this.bufferForNodeUpdate(leftSibling);
|
|
1086
|
+
if (oldNextId) {
|
|
1087
|
+
const oldNext = this.getNode(oldNextId);
|
|
1088
|
+
oldNext.prev = pointer.id;
|
|
1089
|
+
this.bufferForNodeUpdate(oldNext);
|
|
1098
1090
|
}
|
|
1099
1091
|
}
|
|
1100
1092
|
this.bufferForNodeUpdate(parentNode);
|
|
@@ -1123,6 +1115,7 @@ var BPTreeSyncBase = class extends BPTree {
|
|
|
1123
1115
|
}
|
|
1124
1116
|
}
|
|
1125
1117
|
init() {
|
|
1118
|
+
this.clear();
|
|
1126
1119
|
const head = this.strategy.readHead();
|
|
1127
1120
|
if (head === null) {
|
|
1128
1121
|
this.order = this.strategy.order;
|
|
@@ -1153,18 +1146,35 @@ var BPTreeSyncBase = class extends BPTree {
|
|
|
1153
1146
|
}
|
|
1154
1147
|
insertableNode(value) {
|
|
1155
1148
|
let node = this.getNode(this.rootId);
|
|
1149
|
+
if (node.parent !== null) {
|
|
1150
|
+
node.parent = null;
|
|
1151
|
+
this.bufferForNodeUpdate(node);
|
|
1152
|
+
}
|
|
1156
1153
|
while (!node.leaf) {
|
|
1154
|
+
const parentId = node.id;
|
|
1157
1155
|
for (let i = 0, len = node.values.length; i < len; i++) {
|
|
1158
1156
|
const nValue = node.values[i];
|
|
1159
1157
|
const k = node.keys;
|
|
1160
1158
|
if (this.comparator.isSame(value, nValue)) {
|
|
1161
1159
|
node = this.getNode(k[i + 1]);
|
|
1160
|
+
if (node.parent !== parentId) {
|
|
1161
|
+
node.parent = parentId;
|
|
1162
|
+
this.bufferForNodeUpdate(node);
|
|
1163
|
+
}
|
|
1162
1164
|
break;
|
|
1163
1165
|
} else if (this.comparator.isLower(value, nValue)) {
|
|
1164
1166
|
node = this.getNode(k[i]);
|
|
1167
|
+
if (node.parent !== parentId) {
|
|
1168
|
+
node.parent = parentId;
|
|
1169
|
+
this.bufferForNodeUpdate(node);
|
|
1170
|
+
}
|
|
1165
1171
|
break;
|
|
1166
1172
|
} else if (i + 1 === node.values.length) {
|
|
1167
1173
|
node = this.getNode(k[i + 1]);
|
|
1174
|
+
if (node.parent !== parentId) {
|
|
1175
|
+
node.parent = parentId;
|
|
1176
|
+
this.bufferForNodeUpdate(node);
|
|
1177
|
+
}
|
|
1168
1178
|
break;
|
|
1169
1179
|
}
|
|
1170
1180
|
}
|
|
@@ -1173,18 +1183,35 @@ var BPTreeSyncBase = class extends BPTree {
|
|
|
1173
1183
|
}
|
|
1174
1184
|
insertableNodeByPrimary(value) {
|
|
1175
1185
|
let node = this.getNode(this.rootId);
|
|
1186
|
+
if (node.parent !== null) {
|
|
1187
|
+
node.parent = null;
|
|
1188
|
+
this.bufferForNodeUpdate(node);
|
|
1189
|
+
}
|
|
1176
1190
|
while (!node.leaf) {
|
|
1191
|
+
const parentId = node.id;
|
|
1177
1192
|
for (let i = 0, len = node.values.length; i < len; i++) {
|
|
1178
1193
|
const nValue = node.values[i];
|
|
1179
1194
|
const k = node.keys;
|
|
1180
1195
|
if (this.comparator.isPrimarySame(value, nValue)) {
|
|
1181
1196
|
node = this.getNode(k[i]);
|
|
1197
|
+
if (node.parent !== parentId) {
|
|
1198
|
+
node.parent = parentId;
|
|
1199
|
+
this.bufferForNodeUpdate(node);
|
|
1200
|
+
}
|
|
1182
1201
|
break;
|
|
1183
1202
|
} else if (this.comparator.isPrimaryLower(value, nValue)) {
|
|
1184
1203
|
node = this.getNode(k[i]);
|
|
1204
|
+
if (node.parent !== parentId) {
|
|
1205
|
+
node.parent = parentId;
|
|
1206
|
+
this.bufferForNodeUpdate(node);
|
|
1207
|
+
}
|
|
1185
1208
|
break;
|
|
1186
1209
|
} else if (i + 1 === node.values.length) {
|
|
1187
1210
|
node = this.getNode(k[i + 1]);
|
|
1211
|
+
if (node.parent !== parentId) {
|
|
1212
|
+
node.parent = parentId;
|
|
1213
|
+
this.bufferForNodeUpdate(node);
|
|
1214
|
+
}
|
|
1188
1215
|
break;
|
|
1189
1216
|
}
|
|
1190
1217
|
}
|
|
@@ -1193,16 +1220,29 @@ var BPTreeSyncBase = class extends BPTree {
|
|
|
1193
1220
|
}
|
|
1194
1221
|
insertableRightestNodeByPrimary(value) {
|
|
1195
1222
|
let node = this.getNode(this.rootId);
|
|
1223
|
+
if (node.parent !== null) {
|
|
1224
|
+
node.parent = null;
|
|
1225
|
+
this.bufferForNodeUpdate(node);
|
|
1226
|
+
}
|
|
1196
1227
|
while (!node.leaf) {
|
|
1228
|
+
const parentId = node.id;
|
|
1197
1229
|
for (let i = 0, len = node.values.length; i < len; i++) {
|
|
1198
1230
|
const nValue = node.values[i];
|
|
1199
1231
|
const k = node.keys;
|
|
1200
1232
|
if (this.comparator.isPrimaryLower(value, nValue)) {
|
|
1201
1233
|
node = this.getNode(k[i]);
|
|
1234
|
+
if (node.parent !== parentId) {
|
|
1235
|
+
node.parent = parentId;
|
|
1236
|
+
this.bufferForNodeUpdate(node);
|
|
1237
|
+
}
|
|
1202
1238
|
break;
|
|
1203
1239
|
}
|
|
1204
1240
|
if (i + 1 === node.values.length) {
|
|
1205
1241
|
node = this.getNode(k[i + 1]);
|
|
1242
|
+
if (node.parent !== parentId) {
|
|
1243
|
+
node.parent = parentId;
|
|
1244
|
+
this.bufferForNodeUpdate(node);
|
|
1245
|
+
}
|
|
1206
1246
|
break;
|
|
1207
1247
|
}
|
|
1208
1248
|
}
|
|
@@ -1237,17 +1277,35 @@ var BPTreeSyncBase = class extends BPTree {
|
|
|
1237
1277
|
}
|
|
1238
1278
|
leftestNode() {
|
|
1239
1279
|
let node = this.getNode(this.rootId);
|
|
1280
|
+
if (node.parent !== null) {
|
|
1281
|
+
node.parent = null;
|
|
1282
|
+
this.bufferForNodeUpdate(node);
|
|
1283
|
+
}
|
|
1240
1284
|
while (!node.leaf) {
|
|
1285
|
+
const parentId = node.id;
|
|
1241
1286
|
const keys = node.keys;
|
|
1242
1287
|
node = this.getNode(keys[0]);
|
|
1288
|
+
if (node.parent !== parentId) {
|
|
1289
|
+
node.parent = parentId;
|
|
1290
|
+
this.bufferForNodeUpdate(node);
|
|
1291
|
+
}
|
|
1243
1292
|
}
|
|
1244
1293
|
return node;
|
|
1245
1294
|
}
|
|
1246
1295
|
rightestNode() {
|
|
1247
1296
|
let node = this.getNode(this.rootId);
|
|
1297
|
+
if (node.parent !== null) {
|
|
1298
|
+
node.parent = null;
|
|
1299
|
+
this.bufferForNodeUpdate(node);
|
|
1300
|
+
}
|
|
1248
1301
|
while (!node.leaf) {
|
|
1302
|
+
const parentId = node.id;
|
|
1249
1303
|
const keys = node.keys;
|
|
1250
1304
|
node = this.getNode(keys[keys.length - 1]);
|
|
1305
|
+
if (node.parent !== parentId) {
|
|
1306
|
+
node.parent = parentId;
|
|
1307
|
+
this.bufferForNodeUpdate(node);
|
|
1308
|
+
}
|
|
1251
1309
|
}
|
|
1252
1310
|
return node;
|
|
1253
1311
|
}
|
|
@@ -1586,23 +1644,37 @@ var BPTreeSyncTransaction = class extends BPTreeSyncBase {
|
|
|
1586
1644
|
realBaseTree;
|
|
1587
1645
|
realBaseStrategy;
|
|
1588
1646
|
txNodes = /* @__PURE__ */ new Map();
|
|
1589
|
-
dirtyIds
|
|
1590
|
-
createdInTx
|
|
1647
|
+
dirtyIds;
|
|
1648
|
+
createdInTx;
|
|
1649
|
+
deletedIds;
|
|
1591
1650
|
initialRootId;
|
|
1592
1651
|
transactionRootId;
|
|
1593
1652
|
constructor(baseTree) {
|
|
1594
1653
|
super(baseTree.strategy, baseTree.comparator, baseTree.option);
|
|
1595
1654
|
this.realBaseTree = baseTree;
|
|
1596
1655
|
this.realBaseStrategy = baseTree.strategy;
|
|
1656
|
+
this.order = baseTree.getOrder();
|
|
1597
1657
|
this.initialRootId = "";
|
|
1598
1658
|
this.transactionRootId = "";
|
|
1659
|
+
this.dirtyIds = /* @__PURE__ */ new Set();
|
|
1660
|
+
this.createdInTx = /* @__PURE__ */ new Set();
|
|
1661
|
+
this.deletedIds = /* @__PURE__ */ new Set();
|
|
1599
1662
|
}
|
|
1600
1663
|
/**
|
|
1601
1664
|
* Initializes the transaction by capturing the current state of the tree.
|
|
1602
1665
|
*/
|
|
1603
1666
|
initTransaction() {
|
|
1604
1667
|
const head = this.realBaseStrategy.readHead();
|
|
1605
|
-
|
|
1668
|
+
if (head) {
|
|
1669
|
+
this.order = head.order;
|
|
1670
|
+
this.initialRootId = head.root;
|
|
1671
|
+
} else {
|
|
1672
|
+
this.initialRootId = this.realBaseTree.getRootId();
|
|
1673
|
+
}
|
|
1674
|
+
if (!this.initialRootId) {
|
|
1675
|
+
const root = this._createNode(true, [], [], true);
|
|
1676
|
+
this.initialRootId = root.id;
|
|
1677
|
+
}
|
|
1606
1678
|
this.transactionRootId = this.initialRootId;
|
|
1607
1679
|
this.rootId = this.transactionRootId;
|
|
1608
1680
|
const snapshotStrategy = new BPTreeSyncSnapshotStrategy(this.realBaseStrategy, this.initialRootId);
|
|
@@ -1610,34 +1682,76 @@ var BPTreeSyncTransaction = class extends BPTreeSyncBase {
|
|
|
1610
1682
|
this.txNodes.clear();
|
|
1611
1683
|
this.dirtyIds.clear();
|
|
1612
1684
|
this.createdInTx.clear();
|
|
1685
|
+
this.deletedIds.clear();
|
|
1613
1686
|
}
|
|
1614
1687
|
getNode(id) {
|
|
1615
1688
|
if (this.txNodes.has(id)) {
|
|
1616
1689
|
return this.txNodes.get(id);
|
|
1617
1690
|
}
|
|
1691
|
+
if (this.deletedIds.has(id)) {
|
|
1692
|
+
throw new Error(`The tree attempted to reference deleted node '${id}'`);
|
|
1693
|
+
}
|
|
1618
1694
|
const baseNode = this.realBaseStrategy.read(id);
|
|
1619
1695
|
const clone = JSON.parse(JSON.stringify(baseNode));
|
|
1620
1696
|
this.txNodes.set(id, clone);
|
|
1621
1697
|
return clone;
|
|
1622
1698
|
}
|
|
1623
1699
|
bufferForNodeUpdate(node) {
|
|
1700
|
+
if (this.dirtyIds.has(node.id) && this.txNodes.has(node.id) && node._p) {
|
|
1701
|
+
this.txNodes.set(node.id, node);
|
|
1702
|
+
return;
|
|
1703
|
+
}
|
|
1704
|
+
node._p = true;
|
|
1624
1705
|
this.txNodes.set(node.id, node);
|
|
1625
1706
|
this.dirtyIds.add(node.id);
|
|
1707
|
+
if (node.leaf) {
|
|
1708
|
+
if (node.next && !this.dirtyIds.has(node.next) && !this.deletedIds.has(node.next)) {
|
|
1709
|
+
try {
|
|
1710
|
+
this.bufferForNodeUpdate(this.getNode(node.next));
|
|
1711
|
+
} catch (e) {
|
|
1712
|
+
}
|
|
1713
|
+
}
|
|
1714
|
+
if (node.prev && !this.dirtyIds.has(node.prev) && !this.deletedIds.has(node.prev)) {
|
|
1715
|
+
try {
|
|
1716
|
+
this.bufferForNodeUpdate(this.getNode(node.prev));
|
|
1717
|
+
} catch (e) {
|
|
1718
|
+
}
|
|
1719
|
+
}
|
|
1720
|
+
}
|
|
1626
1721
|
this.markPathDirty(node);
|
|
1722
|
+
delete node._p;
|
|
1627
1723
|
}
|
|
1628
1724
|
bufferForNodeCreate(node) {
|
|
1629
1725
|
this.txNodes.set(node.id, node);
|
|
1630
1726
|
this.dirtyIds.add(node.id);
|
|
1631
1727
|
this.createdInTx.add(node.id);
|
|
1728
|
+
if (node.leaf) {
|
|
1729
|
+
if (node.next && !this.dirtyIds.has(node.next) && !this.deletedIds.has(node.next)) {
|
|
1730
|
+
try {
|
|
1731
|
+
this.bufferForNodeUpdate(this.getNode(node.next));
|
|
1732
|
+
} catch (e) {
|
|
1733
|
+
}
|
|
1734
|
+
}
|
|
1735
|
+
if (node.prev && !this.dirtyIds.has(node.prev) && !this.deletedIds.has(node.prev)) {
|
|
1736
|
+
try {
|
|
1737
|
+
this.bufferForNodeUpdate(this.getNode(node.prev));
|
|
1738
|
+
} catch (e) {
|
|
1739
|
+
}
|
|
1740
|
+
}
|
|
1741
|
+
}
|
|
1632
1742
|
this.markPathDirty(node);
|
|
1633
1743
|
}
|
|
1634
1744
|
bufferForNodeDelete(node) {
|
|
1635
1745
|
this.txNodes.delete(node.id);
|
|
1636
1746
|
this.dirtyIds.add(node.id);
|
|
1747
|
+
this.deletedIds.add(node.id);
|
|
1637
1748
|
}
|
|
1638
1749
|
markPathDirty(node) {
|
|
1639
1750
|
let curr = node;
|
|
1640
1751
|
while (curr.parent) {
|
|
1752
|
+
if (this.deletedIds.has(curr.parent)) {
|
|
1753
|
+
break;
|
|
1754
|
+
}
|
|
1641
1755
|
if (this.dirtyIds.has(curr.parent) && this.txNodes.has(curr.parent)) {
|
|
1642
1756
|
break;
|
|
1643
1757
|
}
|
|
@@ -1649,13 +1763,13 @@ var BPTreeSyncTransaction = class extends BPTreeSyncBase {
|
|
|
1649
1763
|
this.transactionRootId = curr.id;
|
|
1650
1764
|
}
|
|
1651
1765
|
}
|
|
1652
|
-
_createNode(isLeaf, keys, values, leaf =
|
|
1653
|
-
const id = this.
|
|
1766
|
+
_createNode(isLeaf, keys, values, leaf = isLeaf, parent = null, next = null, prev = null) {
|
|
1767
|
+
const id = this.strategy.id(isLeaf);
|
|
1654
1768
|
const node = {
|
|
1655
1769
|
id,
|
|
1656
1770
|
keys,
|
|
1657
1771
|
values,
|
|
1658
|
-
leaf
|
|
1772
|
+
leaf,
|
|
1659
1773
|
parent,
|
|
1660
1774
|
next,
|
|
1661
1775
|
prev
|
|
@@ -1713,9 +1827,9 @@ var BPTreeSyncTransaction = class extends BPTreeSyncBase {
|
|
|
1713
1827
|
finalNodes.push(node);
|
|
1714
1828
|
newCreatedIds.push(newId);
|
|
1715
1829
|
}
|
|
1716
|
-
let newRootId = this.
|
|
1717
|
-
if (idMapping.has(this.
|
|
1718
|
-
newRootId = idMapping.get(this.
|
|
1830
|
+
let newRootId = this.rootId;
|
|
1831
|
+
if (idMapping.has(this.rootId)) {
|
|
1832
|
+
newRootId = idMapping.get(this.rootId);
|
|
1719
1833
|
}
|
|
1720
1834
|
for (const node of finalNodes) {
|
|
1721
1835
|
this.realBaseStrategy.write(node.id, node);
|
|
@@ -1744,12 +1858,21 @@ var BPTreeSyncTransaction = class extends BPTreeSyncBase {
|
|
|
1744
1858
|
}
|
|
1745
1859
|
/**
|
|
1746
1860
|
* Rolls back the transaction by clearing all buffered changes.
|
|
1747
|
-
*
|
|
1861
|
+
* If cleanup is `true`, it also clears the transaction nodes.
|
|
1862
|
+
* @param cleanup Whether to clear the transaction nodes.
|
|
1863
|
+
* @returns The IDs of nodes that were created in this transaction.
|
|
1748
1864
|
*/
|
|
1749
|
-
rollback() {
|
|
1865
|
+
rollback(cleanup = true) {
|
|
1866
|
+
const createdIds = Array.from(this.createdInTx);
|
|
1750
1867
|
this.txNodes.clear();
|
|
1751
1868
|
this.dirtyIds.clear();
|
|
1752
1869
|
this.createdInTx.clear();
|
|
1870
|
+
if (cleanup) {
|
|
1871
|
+
for (const id of createdIds) {
|
|
1872
|
+
this.realBaseStrategy.delete(id);
|
|
1873
|
+
}
|
|
1874
|
+
}
|
|
1875
|
+
return createdIds;
|
|
1753
1876
|
}
|
|
1754
1877
|
// Override to do nothing, as transaction handles its own commits
|
|
1755
1878
|
commitHeadBuffer() {
|
|
@@ -1766,6 +1889,7 @@ var BPTreeSyncTransaction = class extends BPTreeSyncBase {
|
|
|
1766
1889
|
var BPTreeSync = class extends BPTreeSyncBase {
|
|
1767
1890
|
constructor(strategy, comparator, option) {
|
|
1768
1891
|
super(strategy, comparator, option);
|
|
1892
|
+
this.init();
|
|
1769
1893
|
}
|
|
1770
1894
|
/**
|
|
1771
1895
|
* Creates a new synchronous transaction.
|
|
@@ -1873,7 +1997,7 @@ var BPTreeAsyncBase = class extends BPTree {
|
|
|
1873
1997
|
}
|
|
1874
1998
|
return id;
|
|
1875
1999
|
}
|
|
1876
|
-
async _createNode(isLeaf, keys, values, leaf =
|
|
2000
|
+
async _createNode(isLeaf, keys, values, leaf = isLeaf, parent = null, next = null, prev = null) {
|
|
1877
2001
|
const id = await this._createNodeId(isLeaf);
|
|
1878
2002
|
const node = {
|
|
1879
2003
|
id,
|
|
@@ -1884,40 +2008,37 @@ var BPTreeAsyncBase = class extends BPTree {
|
|
|
1884
2008
|
next,
|
|
1885
2009
|
prev
|
|
1886
2010
|
};
|
|
1887
|
-
this.
|
|
2011
|
+
await this.bufferForNodeCreate(node);
|
|
1888
2012
|
return node;
|
|
1889
2013
|
}
|
|
1890
2014
|
async _deleteEntry(node, key, value) {
|
|
1891
2015
|
if (!node.leaf) {
|
|
2016
|
+
let keyIndex = -1;
|
|
1892
2017
|
for (let i = 0, len = node.keys.length; i < len; i++) {
|
|
1893
|
-
|
|
1894
|
-
|
|
1895
|
-
node.keys.splice(i, 1);
|
|
1896
|
-
this.bufferForNodeUpdate(node);
|
|
2018
|
+
if (node.keys[i] === key) {
|
|
2019
|
+
keyIndex = i;
|
|
1897
2020
|
break;
|
|
1898
2021
|
}
|
|
1899
2022
|
}
|
|
1900
|
-
|
|
1901
|
-
|
|
1902
|
-
|
|
1903
|
-
|
|
1904
|
-
|
|
1905
|
-
break;
|
|
1906
|
-
}
|
|
2023
|
+
if (keyIndex !== -1) {
|
|
2024
|
+
node.keys.splice(keyIndex, 1);
|
|
2025
|
+
const valueIndex = keyIndex > 0 ? keyIndex - 1 : 0;
|
|
2026
|
+
node.values.splice(valueIndex, 1);
|
|
2027
|
+
await this.bufferForNodeUpdate(node);
|
|
1907
2028
|
}
|
|
1908
2029
|
}
|
|
1909
2030
|
if (this.rootId === node.id && node.keys.length === 1 && !node.leaf) {
|
|
1910
2031
|
const keys = node.keys;
|
|
1911
|
-
this.bufferForNodeDelete(node);
|
|
2032
|
+
await this.bufferForNodeDelete(node);
|
|
1912
2033
|
const newRoot = await this.getNode(keys[0]);
|
|
1913
2034
|
this.rootId = newRoot.id;
|
|
1914
2035
|
newRoot.parent = null;
|
|
1915
2036
|
this.strategy.head.root = this.rootId;
|
|
1916
|
-
this.bufferForNodeUpdate(newRoot);
|
|
2037
|
+
await this.bufferForNodeUpdate(newRoot);
|
|
1917
2038
|
return;
|
|
1918
2039
|
} else if (this.rootId === node.id) {
|
|
1919
2040
|
const root = await this.getNode(this.rootId);
|
|
1920
|
-
this.bufferForNodeUpdate(root);
|
|
2041
|
+
await this.bufferForNodeUpdate(root);
|
|
1921
2042
|
return;
|
|
1922
2043
|
} else if (node.keys.length < Math.ceil(this.order / 2) && !node.leaf || node.values.length < Math.ceil((this.order - 1) / 2) && node.leaf) {
|
|
1923
2044
|
if (node.parent === null) {
|
|
@@ -1978,7 +2099,7 @@ var BPTreeAsyncBase = class extends BPTree {
|
|
|
1978
2099
|
if (pointer.next) {
|
|
1979
2100
|
const n = await this.getNode(pointer.next);
|
|
1980
2101
|
n.prev = pointer.id;
|
|
1981
|
-
this.bufferForNodeUpdate(n);
|
|
2102
|
+
await this.bufferForNodeUpdate(n);
|
|
1982
2103
|
}
|
|
1983
2104
|
}
|
|
1984
2105
|
pointer.values.push(...node.values);
|
|
@@ -1987,12 +2108,12 @@ var BPTreeAsyncBase = class extends BPTree {
|
|
|
1987
2108
|
for (const key2 of keys) {
|
|
1988
2109
|
const n = await this.getNode(key2);
|
|
1989
2110
|
n.parent = pointer.id;
|
|
1990
|
-
this.bufferForNodeUpdate(n);
|
|
2111
|
+
await this.bufferForNodeUpdate(n);
|
|
1991
2112
|
}
|
|
1992
2113
|
}
|
|
1993
2114
|
await this._deleteEntry(await this.getNode(node.parent), node.id, guess);
|
|
1994
|
-
this.bufferForNodeUpdate(pointer);
|
|
1995
|
-
this.bufferForNodeDelete(node);
|
|
2115
|
+
await this.bufferForNodeUpdate(pointer);
|
|
2116
|
+
await this.bufferForNodeDelete(node);
|
|
1996
2117
|
} else {
|
|
1997
2118
|
if (isPredecessor) {
|
|
1998
2119
|
let pointerPm;
|
|
@@ -2003,13 +2124,10 @@ var BPTreeAsyncBase = class extends BPTree {
|
|
|
2003
2124
|
node.keys = [pointerPm, ...node.keys];
|
|
2004
2125
|
node.values = [guess, ...node.values];
|
|
2005
2126
|
parentNode = await this.getNode(node.parent);
|
|
2006
|
-
|
|
2007
|
-
|
|
2008
|
-
|
|
2009
|
-
|
|
2010
|
-
this.bufferForNodeUpdate(parentNode);
|
|
2011
|
-
break;
|
|
2012
|
-
}
|
|
2127
|
+
const nodeIndex = parentNode.keys.indexOf(node.id);
|
|
2128
|
+
if (nodeIndex > 0) {
|
|
2129
|
+
parentNode.values[nodeIndex - 1] = pointerKm;
|
|
2130
|
+
await this.bufferForNodeUpdate(parentNode);
|
|
2013
2131
|
}
|
|
2014
2132
|
} else {
|
|
2015
2133
|
pointerPm = pointer.keys.splice(-1)[0];
|
|
@@ -2017,17 +2135,14 @@ var BPTreeAsyncBase = class extends BPTree {
|
|
|
2017
2135
|
node.keys = [pointerPm, ...node.keys];
|
|
2018
2136
|
node.values = [pointerKm, ...node.values];
|
|
2019
2137
|
parentNode = await this.getNode(node.parent);
|
|
2020
|
-
|
|
2021
|
-
|
|
2022
|
-
|
|
2023
|
-
|
|
2024
|
-
this.bufferForNodeUpdate(parentNode);
|
|
2025
|
-
break;
|
|
2026
|
-
}
|
|
2138
|
+
const nodeIndex = parentNode.keys.indexOf(node.id);
|
|
2139
|
+
if (nodeIndex > 0) {
|
|
2140
|
+
parentNode.values[nodeIndex - 1] = pointerKm;
|
|
2141
|
+
await this.bufferForNodeUpdate(parentNode);
|
|
2027
2142
|
}
|
|
2028
2143
|
}
|
|
2029
|
-
this.bufferForNodeUpdate(node);
|
|
2030
|
-
this.bufferForNodeUpdate(pointer);
|
|
2144
|
+
await this.bufferForNodeUpdate(node);
|
|
2145
|
+
await this.bufferForNodeUpdate(pointer);
|
|
2031
2146
|
} else {
|
|
2032
2147
|
let pointerP0;
|
|
2033
2148
|
let pointerK0;
|
|
@@ -2037,13 +2152,10 @@ var BPTreeAsyncBase = class extends BPTree {
|
|
|
2037
2152
|
node.keys = [...node.keys, pointerP0];
|
|
2038
2153
|
node.values = [...node.values, guess];
|
|
2039
2154
|
parentNode = await this.getNode(node.parent);
|
|
2040
|
-
|
|
2041
|
-
|
|
2042
|
-
|
|
2043
|
-
|
|
2044
|
-
this.bufferForNodeUpdate(parentNode);
|
|
2045
|
-
break;
|
|
2046
|
-
}
|
|
2155
|
+
const pointerIndex = parentNode.keys.indexOf(pointer.id);
|
|
2156
|
+
if (pointerIndex > 0) {
|
|
2157
|
+
parentNode.values[pointerIndex - 1] = pointerK0;
|
|
2158
|
+
await this.bufferForNodeUpdate(parentNode);
|
|
2047
2159
|
}
|
|
2048
2160
|
} else {
|
|
2049
2161
|
pointerP0 = pointer.keys.splice(0, 1)[0];
|
|
@@ -2051,24 +2163,21 @@ var BPTreeAsyncBase = class extends BPTree {
|
|
|
2051
2163
|
node.keys = [...node.keys, pointerP0];
|
|
2052
2164
|
node.values = [...node.values, pointerK0];
|
|
2053
2165
|
parentNode = await this.getNode(node.parent);
|
|
2054
|
-
|
|
2055
|
-
|
|
2056
|
-
|
|
2057
|
-
|
|
2058
|
-
this.bufferForNodeUpdate(parentNode);
|
|
2059
|
-
break;
|
|
2060
|
-
}
|
|
2166
|
+
const pointerIndex = parentNode.keys.indexOf(pointer.id);
|
|
2167
|
+
if (pointerIndex > 0) {
|
|
2168
|
+
parentNode.values[pointerIndex - 1] = pointer.values[0];
|
|
2169
|
+
await this.bufferForNodeUpdate(parentNode);
|
|
2061
2170
|
}
|
|
2062
2171
|
}
|
|
2063
|
-
this.bufferForNodeUpdate(node);
|
|
2064
|
-
this.bufferForNodeUpdate(pointer);
|
|
2172
|
+
await this.bufferForNodeUpdate(node);
|
|
2173
|
+
await this.bufferForNodeUpdate(pointer);
|
|
2065
2174
|
}
|
|
2066
2175
|
if (!pointer.leaf) {
|
|
2067
2176
|
const keys = pointer.keys;
|
|
2068
2177
|
for (const key2 of keys) {
|
|
2069
2178
|
const n = await this.getNode(key2);
|
|
2070
2179
|
n.parent = pointer.id;
|
|
2071
|
-
this.bufferForNodeUpdate(n);
|
|
2180
|
+
await this.bufferForNodeUpdate(n);
|
|
2072
2181
|
}
|
|
2073
2182
|
}
|
|
2074
2183
|
if (!node.leaf) {
|
|
@@ -2076,7 +2185,7 @@ var BPTreeAsyncBase = class extends BPTree {
|
|
|
2076
2185
|
for (const key2 of keys) {
|
|
2077
2186
|
const n = await this.getNode(key2);
|
|
2078
2187
|
n.parent = node.id;
|
|
2079
|
-
this.bufferForNodeUpdate(n);
|
|
2188
|
+
await this.bufferForNodeUpdate(n);
|
|
2080
2189
|
}
|
|
2081
2190
|
}
|
|
2082
2191
|
if (!parentNode.leaf) {
|
|
@@ -2084,10 +2193,12 @@ var BPTreeAsyncBase = class extends BPTree {
|
|
|
2084
2193
|
for (const key2 of keys) {
|
|
2085
2194
|
const n = await this.getNode(key2);
|
|
2086
2195
|
n.parent = parentNode.id;
|
|
2087
|
-
this.bufferForNodeUpdate(n);
|
|
2196
|
+
await this.bufferForNodeUpdate(n);
|
|
2088
2197
|
}
|
|
2089
2198
|
}
|
|
2090
2199
|
}
|
|
2200
|
+
} else {
|
|
2201
|
+
await this.bufferForNodeUpdate(node);
|
|
2091
2202
|
}
|
|
2092
2203
|
}
|
|
2093
2204
|
async _insertInParent(node, value, pointer) {
|
|
@@ -2098,43 +2209,39 @@ var BPTreeAsyncBase = class extends BPTree {
|
|
|
2098
2209
|
node.parent = root.id;
|
|
2099
2210
|
pointer.parent = root.id;
|
|
2100
2211
|
if (pointer.leaf) {
|
|
2101
|
-
|
|
2102
|
-
|
|
2212
|
+
const nNode = node;
|
|
2213
|
+
nNode.next = pointer.id;
|
|
2214
|
+
const nPointer = pointer;
|
|
2215
|
+
nPointer.prev = node.id;
|
|
2103
2216
|
}
|
|
2104
|
-
this.bufferForNodeUpdate(node);
|
|
2105
|
-
this.bufferForNodeUpdate(pointer);
|
|
2217
|
+
await this.bufferForNodeUpdate(node);
|
|
2218
|
+
await this.bufferForNodeUpdate(pointer);
|
|
2106
2219
|
return;
|
|
2107
2220
|
}
|
|
2108
2221
|
const parentNode = await this.getNode(node.parent);
|
|
2109
|
-
|
|
2110
|
-
|
|
2111
|
-
|
|
2112
|
-
insertIndex = i + 1;
|
|
2113
|
-
} else {
|
|
2114
|
-
break;
|
|
2115
|
-
}
|
|
2222
|
+
const nodeIndex = parentNode.keys.indexOf(node.id);
|
|
2223
|
+
if (nodeIndex === -1) {
|
|
2224
|
+
throw new Error(`Node ${node.id} not found in parent ${parentNode.id}`);
|
|
2116
2225
|
}
|
|
2226
|
+
const insertIndex = nodeIndex;
|
|
2117
2227
|
parentNode.values.splice(insertIndex, 0, value);
|
|
2118
2228
|
parentNode.keys.splice(insertIndex + 1, 0, pointer.id);
|
|
2119
2229
|
pointer.parent = parentNode.id;
|
|
2120
2230
|
if (pointer.leaf) {
|
|
2121
|
-
const
|
|
2122
|
-
const
|
|
2123
|
-
|
|
2124
|
-
|
|
2125
|
-
|
|
2126
|
-
|
|
2127
|
-
|
|
2128
|
-
this.
|
|
2129
|
-
|
|
2130
|
-
|
|
2131
|
-
|
|
2132
|
-
|
|
2133
|
-
|
|
2134
|
-
|
|
2135
|
-
}
|
|
2136
|
-
this.bufferForNodeUpdate(parentNode);
|
|
2137
|
-
this.bufferForNodeUpdate(pointer);
|
|
2231
|
+
const leftSibling = node;
|
|
2232
|
+
const oldNextId = leftSibling.next;
|
|
2233
|
+
pointer.prev = leftSibling.id;
|
|
2234
|
+
pointer.next = oldNextId;
|
|
2235
|
+
leftSibling.next = pointer.id;
|
|
2236
|
+
await this.bufferForNodeUpdate(leftSibling);
|
|
2237
|
+
if (oldNextId) {
|
|
2238
|
+
const oldNext = await this.getNode(oldNextId);
|
|
2239
|
+
oldNext.prev = pointer.id;
|
|
2240
|
+
await this.bufferForNodeUpdate(oldNext);
|
|
2241
|
+
}
|
|
2242
|
+
}
|
|
2243
|
+
await this.bufferForNodeUpdate(parentNode);
|
|
2244
|
+
await this.bufferForNodeUpdate(pointer);
|
|
2138
2245
|
if (parentNode.keys.length > this.order) {
|
|
2139
2246
|
const parentPointer = await this._createNode(false, [], []);
|
|
2140
2247
|
parentPointer.parent = parentNode.parent;
|
|
@@ -2147,18 +2254,19 @@ var BPTreeAsyncBase = class extends BPTree {
|
|
|
2147
2254
|
for (const k of parentNode.keys) {
|
|
2148
2255
|
const n = await this.getNode(k);
|
|
2149
2256
|
n.parent = parentNode.id;
|
|
2150
|
-
this.bufferForNodeUpdate(n);
|
|
2257
|
+
await this.bufferForNodeUpdate(n);
|
|
2151
2258
|
}
|
|
2152
2259
|
for (const k of parentPointer.keys) {
|
|
2153
2260
|
const n = await this.getNode(k);
|
|
2154
2261
|
n.parent = parentPointer.id;
|
|
2155
|
-
this.bufferForNodeUpdate(n);
|
|
2262
|
+
await this.bufferForNodeUpdate(n);
|
|
2156
2263
|
}
|
|
2157
2264
|
await this._insertInParent(parentNode, midValue, parentPointer);
|
|
2158
|
-
this.bufferForNodeUpdate(parentNode);
|
|
2265
|
+
await this.bufferForNodeUpdate(parentNode);
|
|
2159
2266
|
}
|
|
2160
2267
|
}
|
|
2161
2268
|
async init() {
|
|
2269
|
+
this.clear();
|
|
2162
2270
|
const head = await this.strategy.readHead();
|
|
2163
2271
|
if (head === null) {
|
|
2164
2272
|
this.order = this.strategy.order;
|
|
@@ -2189,18 +2297,35 @@ var BPTreeAsyncBase = class extends BPTree {
|
|
|
2189
2297
|
}
|
|
2190
2298
|
async insertableNode(value) {
|
|
2191
2299
|
let node = await this.getNode(this.rootId);
|
|
2300
|
+
if (node.parent !== null) {
|
|
2301
|
+
node.parent = null;
|
|
2302
|
+
await this.bufferForNodeUpdate(node);
|
|
2303
|
+
}
|
|
2192
2304
|
while (!node.leaf) {
|
|
2305
|
+
const parentId = node.id;
|
|
2193
2306
|
for (let i = 0, len = node.values.length; i < len; i++) {
|
|
2194
2307
|
const nValue = node.values[i];
|
|
2195
2308
|
const k = node.keys;
|
|
2196
2309
|
if (this.comparator.isSame(value, nValue)) {
|
|
2197
2310
|
node = await this.getNode(node.keys[i + 1]);
|
|
2311
|
+
if (node.parent !== parentId) {
|
|
2312
|
+
node.parent = parentId;
|
|
2313
|
+
await this.bufferForNodeUpdate(node);
|
|
2314
|
+
}
|
|
2198
2315
|
break;
|
|
2199
2316
|
} else if (this.comparator.isLower(value, nValue)) {
|
|
2200
2317
|
node = await this.getNode(node.keys[i]);
|
|
2318
|
+
if (node.parent !== parentId) {
|
|
2319
|
+
node.parent = parentId;
|
|
2320
|
+
await this.bufferForNodeUpdate(node);
|
|
2321
|
+
}
|
|
2201
2322
|
break;
|
|
2202
2323
|
} else if (i + 1 === node.values.length) {
|
|
2203
2324
|
node = await this.getNode(node.keys[i + 1]);
|
|
2325
|
+
if (node.parent !== parentId) {
|
|
2326
|
+
node.parent = parentId;
|
|
2327
|
+
await this.bufferForNodeUpdate(node);
|
|
2328
|
+
}
|
|
2204
2329
|
break;
|
|
2205
2330
|
}
|
|
2206
2331
|
}
|
|
@@ -2209,18 +2334,35 @@ var BPTreeAsyncBase = class extends BPTree {
|
|
|
2209
2334
|
}
|
|
2210
2335
|
async insertableNodeByPrimary(value) {
|
|
2211
2336
|
let node = await this.getNode(this.rootId);
|
|
2337
|
+
if (node.parent !== null) {
|
|
2338
|
+
node.parent = null;
|
|
2339
|
+
await this.bufferForNodeUpdate(node);
|
|
2340
|
+
}
|
|
2212
2341
|
while (!node.leaf) {
|
|
2342
|
+
const parentId = node.id;
|
|
2213
2343
|
for (let i = 0, len = node.values.length; i < len; i++) {
|
|
2214
2344
|
const nValue = node.values[i];
|
|
2215
2345
|
const k = node.keys;
|
|
2216
2346
|
if (this.comparator.isPrimarySame(value, nValue)) {
|
|
2217
2347
|
node = await this.getNode(node.keys[i]);
|
|
2348
|
+
if (node.parent !== parentId) {
|
|
2349
|
+
node.parent = parentId;
|
|
2350
|
+
await this.bufferForNodeUpdate(node);
|
|
2351
|
+
}
|
|
2218
2352
|
break;
|
|
2219
2353
|
} else if (this.comparator.isPrimaryLower(value, nValue)) {
|
|
2220
2354
|
node = await this.getNode(node.keys[i]);
|
|
2355
|
+
if (node.parent !== parentId) {
|
|
2356
|
+
node.parent = parentId;
|
|
2357
|
+
await this.bufferForNodeUpdate(node);
|
|
2358
|
+
}
|
|
2221
2359
|
break;
|
|
2222
2360
|
} else if (i + 1 === node.values.length) {
|
|
2223
2361
|
node = await this.getNode(node.keys[i + 1]);
|
|
2362
|
+
if (node.parent !== parentId) {
|
|
2363
|
+
node.parent = parentId;
|
|
2364
|
+
await this.bufferForNodeUpdate(node);
|
|
2365
|
+
}
|
|
2224
2366
|
break;
|
|
2225
2367
|
}
|
|
2226
2368
|
}
|
|
@@ -2229,16 +2371,29 @@ var BPTreeAsyncBase = class extends BPTree {
|
|
|
2229
2371
|
}
|
|
2230
2372
|
async insertableRightestNodeByPrimary(value) {
|
|
2231
2373
|
let node = await this.getNode(this.rootId);
|
|
2374
|
+
if (node.parent !== null) {
|
|
2375
|
+
node.parent = null;
|
|
2376
|
+
await this.bufferForNodeUpdate(node);
|
|
2377
|
+
}
|
|
2232
2378
|
while (!node.leaf) {
|
|
2379
|
+
const parentId = node.id;
|
|
2233
2380
|
for (let i = 0, len = node.values.length; i < len; i++) {
|
|
2234
2381
|
const nValue = node.values[i];
|
|
2235
2382
|
const k = node.keys;
|
|
2236
2383
|
if (this.comparator.isPrimaryLower(value, nValue)) {
|
|
2237
2384
|
node = await this.getNode(node.keys[i]);
|
|
2385
|
+
if (node.parent !== parentId) {
|
|
2386
|
+
node.parent = parentId;
|
|
2387
|
+
await this.bufferForNodeUpdate(node);
|
|
2388
|
+
}
|
|
2238
2389
|
break;
|
|
2239
2390
|
}
|
|
2240
2391
|
if (i + 1 === node.values.length) {
|
|
2241
2392
|
node = await this.getNode(node.keys[i + 1]);
|
|
2393
|
+
if (node.parent !== parentId) {
|
|
2394
|
+
node.parent = parentId;
|
|
2395
|
+
await this.bufferForNodeUpdate(node);
|
|
2396
|
+
}
|
|
2242
2397
|
break;
|
|
2243
2398
|
}
|
|
2244
2399
|
}
|
|
@@ -2273,17 +2428,35 @@ var BPTreeAsyncBase = class extends BPTree {
|
|
|
2273
2428
|
}
|
|
2274
2429
|
async leftestNode() {
|
|
2275
2430
|
let node = await this.getNode(this.rootId);
|
|
2431
|
+
if (node.parent !== null) {
|
|
2432
|
+
node.parent = null;
|
|
2433
|
+
await this.bufferForNodeUpdate(node);
|
|
2434
|
+
}
|
|
2276
2435
|
while (!node.leaf) {
|
|
2436
|
+
const parentId = node.id;
|
|
2277
2437
|
const keys = node.keys;
|
|
2278
2438
|
node = await this.getNode(node.keys[0]);
|
|
2439
|
+
if (node.parent !== parentId) {
|
|
2440
|
+
node.parent = parentId;
|
|
2441
|
+
await this.bufferForNodeUpdate(node);
|
|
2442
|
+
}
|
|
2279
2443
|
}
|
|
2280
2444
|
return node;
|
|
2281
2445
|
}
|
|
2282
2446
|
async rightestNode() {
|
|
2283
2447
|
let node = await this.getNode(this.rootId);
|
|
2448
|
+
if (node.parent !== null) {
|
|
2449
|
+
node.parent = null;
|
|
2450
|
+
await this.bufferForNodeUpdate(node);
|
|
2451
|
+
}
|
|
2284
2452
|
while (!node.leaf) {
|
|
2453
|
+
const parentId = node.id;
|
|
2285
2454
|
const keys = node.keys;
|
|
2286
2455
|
node = await this.getNode(node.keys[node.keys.length - 1]);
|
|
2456
|
+
if (node.parent !== parentId) {
|
|
2457
|
+
node.parent = parentId;
|
|
2458
|
+
await this.bufferForNodeUpdate(node);
|
|
2459
|
+
}
|
|
2287
2460
|
}
|
|
2288
2461
|
return node;
|
|
2289
2462
|
}
|
|
@@ -2443,7 +2616,7 @@ var BPTreeAsyncBase = class extends BPTree {
|
|
|
2443
2616
|
async insert(key, value) {
|
|
2444
2617
|
await this.writeLock(async () => {
|
|
2445
2618
|
const before = await this.insertableNode(value);
|
|
2446
|
-
this._insertAtLeaf(before, key, value);
|
|
2619
|
+
await this._insertAtLeaf(before, key, value);
|
|
2447
2620
|
if (before.values.length === this.order) {
|
|
2448
2621
|
const after = await this._createNode(
|
|
2449
2622
|
true,
|
|
@@ -2460,7 +2633,7 @@ var BPTreeAsyncBase = class extends BPTree {
|
|
|
2460
2633
|
before.values = before.values.slice(0, mid + 1);
|
|
2461
2634
|
before.keys = before.keys.slice(0, mid + 1);
|
|
2462
2635
|
await this._insertInParent(before, after.values[0], after);
|
|
2463
|
-
this.bufferForNodeUpdate(before);
|
|
2636
|
+
await this.bufferForNodeUpdate(before);
|
|
2464
2637
|
}
|
|
2465
2638
|
await this.commitHeadBuffer();
|
|
2466
2639
|
await this.commitNodeCreateBuffer();
|
|
@@ -2483,11 +2656,13 @@ var BPTreeAsyncBase = class extends BPTree {
|
|
|
2483
2656
|
node.values.splice(i, 1);
|
|
2484
2657
|
}
|
|
2485
2658
|
await this._deleteEntry(node, key, value);
|
|
2659
|
+
await this.bufferForNodeUpdate(node);
|
|
2486
2660
|
break;
|
|
2487
2661
|
}
|
|
2488
2662
|
}
|
|
2489
2663
|
}
|
|
2490
2664
|
await this.commitHeadBuffer();
|
|
2665
|
+
await this.commitNodeCreateBuffer();
|
|
2491
2666
|
await this.commitNodeUpdateBuffer();
|
|
2492
2667
|
await this.commitNodeDeleteBuffer();
|
|
2493
2668
|
});
|
|
@@ -2613,23 +2788,37 @@ var BPTreeAsyncTransaction = class extends BPTreeAsyncBase {
|
|
|
2613
2788
|
realBaseTree;
|
|
2614
2789
|
realBaseStrategy;
|
|
2615
2790
|
txNodes = /* @__PURE__ */ new Map();
|
|
2616
|
-
dirtyIds
|
|
2617
|
-
createdInTx
|
|
2791
|
+
dirtyIds;
|
|
2792
|
+
createdInTx;
|
|
2793
|
+
deletedIds;
|
|
2618
2794
|
initialRootId;
|
|
2619
2795
|
transactionRootId;
|
|
2620
2796
|
constructor(baseTree) {
|
|
2621
2797
|
super(baseTree.strategy, baseTree.comparator, baseTree.option);
|
|
2622
2798
|
this.realBaseTree = baseTree;
|
|
2623
2799
|
this.realBaseStrategy = baseTree.strategy;
|
|
2800
|
+
this.order = baseTree.getOrder();
|
|
2624
2801
|
this.initialRootId = "";
|
|
2625
2802
|
this.transactionRootId = "";
|
|
2803
|
+
this.dirtyIds = /* @__PURE__ */ new Set();
|
|
2804
|
+
this.createdInTx = /* @__PURE__ */ new Set();
|
|
2805
|
+
this.deletedIds = /* @__PURE__ */ new Set();
|
|
2626
2806
|
}
|
|
2627
2807
|
/**
|
|
2628
2808
|
* Initializes the transaction by capturing the current state of the tree.
|
|
2629
2809
|
*/
|
|
2630
2810
|
async initTransaction() {
|
|
2631
2811
|
const head = await this.realBaseStrategy.readHead();
|
|
2632
|
-
|
|
2812
|
+
if (head) {
|
|
2813
|
+
this.order = head.order;
|
|
2814
|
+
this.initialRootId = head.root;
|
|
2815
|
+
} else {
|
|
2816
|
+
this.initialRootId = this.realBaseTree.getRootId();
|
|
2817
|
+
}
|
|
2818
|
+
if (!this.initialRootId) {
|
|
2819
|
+
const root = await this._createNode(true, [], [], true);
|
|
2820
|
+
this.initialRootId = root.id;
|
|
2821
|
+
}
|
|
2633
2822
|
this.transactionRootId = this.initialRootId;
|
|
2634
2823
|
this.rootId = this.transactionRootId;
|
|
2635
2824
|
const snapshotStrategy = new BPTreeAsyncSnapshotStrategy(this.realBaseStrategy, this.initialRootId);
|
|
@@ -2637,34 +2826,76 @@ var BPTreeAsyncTransaction = class extends BPTreeAsyncBase {
|
|
|
2637
2826
|
this.txNodes.clear();
|
|
2638
2827
|
this.dirtyIds.clear();
|
|
2639
2828
|
this.createdInTx.clear();
|
|
2829
|
+
this.deletedIds.clear();
|
|
2640
2830
|
}
|
|
2641
2831
|
async getNode(id) {
|
|
2642
2832
|
if (this.txNodes.has(id)) {
|
|
2643
2833
|
return this.txNodes.get(id);
|
|
2644
2834
|
}
|
|
2835
|
+
if (this.deletedIds.has(id)) {
|
|
2836
|
+
throw new Error(`The tree attempted to reference deleted node '${id}'`);
|
|
2837
|
+
}
|
|
2645
2838
|
const baseNode = await this.realBaseStrategy.read(id);
|
|
2646
2839
|
const clone = JSON.parse(JSON.stringify(baseNode));
|
|
2647
2840
|
this.txNodes.set(id, clone);
|
|
2648
2841
|
return clone;
|
|
2649
2842
|
}
|
|
2650
2843
|
async bufferForNodeUpdate(node) {
|
|
2844
|
+
if (this.dirtyIds.has(node.id) && this.txNodes.has(node.id) && node._p) {
|
|
2845
|
+
this.txNodes.set(node.id, node);
|
|
2846
|
+
return;
|
|
2847
|
+
}
|
|
2848
|
+
node._p = true;
|
|
2651
2849
|
this.txNodes.set(node.id, node);
|
|
2652
2850
|
this.dirtyIds.add(node.id);
|
|
2851
|
+
if (node.leaf) {
|
|
2852
|
+
if (node.next && !this.dirtyIds.has(node.next) && !this.deletedIds.has(node.next)) {
|
|
2853
|
+
try {
|
|
2854
|
+
await this.bufferForNodeUpdate(await this.getNode(node.next));
|
|
2855
|
+
} catch (e) {
|
|
2856
|
+
}
|
|
2857
|
+
}
|
|
2858
|
+
if (node.prev && !this.dirtyIds.has(node.prev) && !this.deletedIds.has(node.prev)) {
|
|
2859
|
+
try {
|
|
2860
|
+
await this.bufferForNodeUpdate(await this.getNode(node.prev));
|
|
2861
|
+
} catch (e) {
|
|
2862
|
+
}
|
|
2863
|
+
}
|
|
2864
|
+
}
|
|
2653
2865
|
await this.markPathDirty(node);
|
|
2866
|
+
delete node._p;
|
|
2654
2867
|
}
|
|
2655
2868
|
async bufferForNodeCreate(node) {
|
|
2656
2869
|
this.txNodes.set(node.id, node);
|
|
2657
2870
|
this.dirtyIds.add(node.id);
|
|
2658
2871
|
this.createdInTx.add(node.id);
|
|
2872
|
+
if (node.leaf) {
|
|
2873
|
+
if (node.next && !this.dirtyIds.has(node.next) && !this.deletedIds.has(node.next)) {
|
|
2874
|
+
try {
|
|
2875
|
+
await this.bufferForNodeUpdate(await this.getNode(node.next));
|
|
2876
|
+
} catch (e) {
|
|
2877
|
+
}
|
|
2878
|
+
}
|
|
2879
|
+
if (node.prev && !this.dirtyIds.has(node.prev) && !this.deletedIds.has(node.prev)) {
|
|
2880
|
+
try {
|
|
2881
|
+
await this.bufferForNodeUpdate(await this.getNode(node.prev));
|
|
2882
|
+
} catch (e) {
|
|
2883
|
+
}
|
|
2884
|
+
}
|
|
2885
|
+
}
|
|
2659
2886
|
await this.markPathDirty(node);
|
|
2660
2887
|
}
|
|
2661
2888
|
async bufferForNodeDelete(node) {
|
|
2662
2889
|
this.txNodes.delete(node.id);
|
|
2663
2890
|
this.dirtyIds.add(node.id);
|
|
2891
|
+
this.deletedIds.add(node.id);
|
|
2664
2892
|
}
|
|
2665
2893
|
async markPathDirty(node) {
|
|
2666
2894
|
let curr = node;
|
|
2667
2895
|
while (curr.parent) {
|
|
2896
|
+
if (this.deletedIds.has(curr.parent)) {
|
|
2897
|
+
break;
|
|
2898
|
+
}
|
|
2668
2899
|
if (this.dirtyIds.has(curr.parent) && this.txNodes.has(curr.parent)) {
|
|
2669
2900
|
break;
|
|
2670
2901
|
}
|
|
@@ -2676,13 +2907,13 @@ var BPTreeAsyncTransaction = class extends BPTreeAsyncBase {
|
|
|
2676
2907
|
this.transactionRootId = curr.id;
|
|
2677
2908
|
}
|
|
2678
2909
|
}
|
|
2679
|
-
async _createNode(isLeaf, keys, values, leaf =
|
|
2680
|
-
const id = await this.
|
|
2910
|
+
async _createNode(isLeaf, keys, values, leaf = isLeaf, parent = null, next = null, prev = null) {
|
|
2911
|
+
const id = await this.strategy.id(isLeaf);
|
|
2681
2912
|
const node = {
|
|
2682
2913
|
id,
|
|
2683
2914
|
keys,
|
|
2684
2915
|
values,
|
|
2685
|
-
leaf
|
|
2916
|
+
leaf,
|
|
2686
2917
|
parent,
|
|
2687
2918
|
next,
|
|
2688
2919
|
prev
|
|
@@ -2740,9 +2971,9 @@ var BPTreeAsyncTransaction = class extends BPTreeAsyncBase {
|
|
|
2740
2971
|
finalNodes.push(node);
|
|
2741
2972
|
newCreatedIds.push(newId);
|
|
2742
2973
|
}
|
|
2743
|
-
let newRootId = this.
|
|
2744
|
-
if (idMapping.has(this.
|
|
2745
|
-
newRootId = idMapping.get(this.
|
|
2974
|
+
let newRootId = this.rootId;
|
|
2975
|
+
if (idMapping.has(this.rootId)) {
|
|
2976
|
+
newRootId = idMapping.get(this.rootId);
|
|
2746
2977
|
}
|
|
2747
2978
|
for (const node of finalNodes) {
|
|
2748
2979
|
await this.realBaseStrategy.write(node.id, node);
|
|
@@ -2771,12 +3002,21 @@ var BPTreeAsyncTransaction = class extends BPTreeAsyncBase {
|
|
|
2771
3002
|
}
|
|
2772
3003
|
/**
|
|
2773
3004
|
* Rolls back the transaction by clearing all buffered changes.
|
|
2774
|
-
*
|
|
3005
|
+
* If cleanup is `true`, it also clears the transaction nodes.
|
|
3006
|
+
* @param cleanup Whether to clear the transaction nodes.
|
|
3007
|
+
* @returns The IDs of nodes that were created in this transaction.
|
|
2775
3008
|
*/
|
|
2776
|
-
async rollback() {
|
|
3009
|
+
async rollback(cleanup = true) {
|
|
3010
|
+
const createdIds = Array.from(this.createdInTx);
|
|
2777
3011
|
this.txNodes.clear();
|
|
2778
3012
|
this.dirtyIds.clear();
|
|
2779
3013
|
this.createdInTx.clear();
|
|
3014
|
+
if (cleanup) {
|
|
3015
|
+
for (const id of createdIds) {
|
|
3016
|
+
await this.realBaseStrategy.delete(id);
|
|
3017
|
+
}
|
|
3018
|
+
}
|
|
3019
|
+
return createdIds;
|
|
2780
3020
|
}
|
|
2781
3021
|
async readLock(fn) {
|
|
2782
3022
|
return await fn();
|