dataply 0.0.16-alpha.2 → 0.0.16-alpha.4
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.js
CHANGED
|
@@ -31,7 +31,9 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
|
|
|
31
31
|
var src_exports = {};
|
|
32
32
|
__export(src_exports, {
|
|
33
33
|
BPTreeAsync: () => BPTreeAsync,
|
|
34
|
+
BPTreeAsyncTransaction: () => BPTreeAsyncTransaction,
|
|
34
35
|
BPTreeSync: () => BPTreeSync,
|
|
36
|
+
BPTreeSyncTransaction: () => BPTreeSyncTransaction,
|
|
35
37
|
BitmapPageManager: () => BitmapPageManager,
|
|
36
38
|
CacheEntanglementAsync: () => CacheEntanglementAsync2,
|
|
37
39
|
CacheEntanglementSync: () => CacheEntanglementSync2,
|
|
@@ -50,7 +52,7 @@ __export(src_exports, {
|
|
|
50
52
|
OverflowPageManager: () => OverflowPageManager,
|
|
51
53
|
PageManager: () => PageManager,
|
|
52
54
|
PageManagerFactory: () => PageManagerFactory,
|
|
53
|
-
Ryoiki: () =>
|
|
55
|
+
Ryoiki: () => Ryoiki,
|
|
54
56
|
SerializeStrategyAsync: () => SerializeStrategyAsync,
|
|
55
57
|
SerializeStrategySync: () => SerializeStrategySync,
|
|
56
58
|
StringComparator: () => StringComparator,
|
|
@@ -496,7 +498,21 @@ var BPTree = class _BPTree {
|
|
|
496
498
|
comparator;
|
|
497
499
|
option;
|
|
498
500
|
order;
|
|
499
|
-
|
|
501
|
+
rootId;
|
|
502
|
+
/**
|
|
503
|
+
* Returns the ID of the root node.
|
|
504
|
+
* @returns The root node ID.
|
|
505
|
+
*/
|
|
506
|
+
getRootId() {
|
|
507
|
+
return this.rootId;
|
|
508
|
+
}
|
|
509
|
+
/**
|
|
510
|
+
* Returns the order of the B+Tree.
|
|
511
|
+
* @returns The order of the tree.
|
|
512
|
+
*/
|
|
513
|
+
getOrder() {
|
|
514
|
+
return this.order;
|
|
515
|
+
}
|
|
500
516
|
_strategyDirty;
|
|
501
517
|
_nodeCreateBuffer;
|
|
502
518
|
_nodeUpdateBuffer;
|
|
@@ -729,40 +745,37 @@ var BPTree = class _BPTree {
|
|
|
729
745
|
break;
|
|
730
746
|
}
|
|
731
747
|
keys.push(key);
|
|
732
|
-
this.bufferForNodeUpdate(node);
|
|
733
|
-
break;
|
|
748
|
+
return this.bufferForNodeUpdate(node);
|
|
734
749
|
} else if (this.comparator.isLower(value, nValue)) {
|
|
735
750
|
node.values.splice(i, 0, value);
|
|
736
751
|
node.keys.splice(i, 0, [key]);
|
|
737
|
-
this.bufferForNodeUpdate(node);
|
|
738
|
-
break;
|
|
752
|
+
return this.bufferForNodeUpdate(node);
|
|
739
753
|
} else if (i + 1 === node.values.length) {
|
|
740
754
|
node.values.push(value);
|
|
741
755
|
node.keys.push([key]);
|
|
742
|
-
this.bufferForNodeUpdate(node);
|
|
743
|
-
break;
|
|
756
|
+
return this.bufferForNodeUpdate(node);
|
|
744
757
|
}
|
|
745
758
|
}
|
|
746
759
|
} else {
|
|
747
760
|
node.values = [value];
|
|
748
761
|
node.keys = [[key]];
|
|
749
|
-
this.bufferForNodeUpdate(node);
|
|
762
|
+
return this.bufferForNodeUpdate(node);
|
|
750
763
|
}
|
|
751
764
|
}
|
|
752
765
|
bufferForNodeCreate(node) {
|
|
753
|
-
if (node.id === this.
|
|
766
|
+
if (node.id === this.rootId) {
|
|
754
767
|
this._strategyDirty = true;
|
|
755
768
|
}
|
|
756
769
|
this._nodeCreateBuffer.set(node.id, node);
|
|
757
770
|
}
|
|
758
771
|
bufferForNodeUpdate(node) {
|
|
759
|
-
if (node.id === this.
|
|
772
|
+
if (node.id === this.rootId) {
|
|
760
773
|
this._strategyDirty = true;
|
|
761
774
|
}
|
|
762
775
|
this._nodeUpdateBuffer.set(node.id, node);
|
|
763
776
|
}
|
|
764
777
|
bufferForNodeDelete(node) {
|
|
765
|
-
if (node.id === this.
|
|
778
|
+
if (node.id === this.rootId) {
|
|
766
779
|
this._strategyDirty = true;
|
|
767
780
|
}
|
|
768
781
|
this._nodeDeleteBuffer.set(node.id, node);
|
|
@@ -784,7 +797,7 @@ var BPTree = class _BPTree {
|
|
|
784
797
|
this.nodes.clear();
|
|
785
798
|
}
|
|
786
799
|
};
|
|
787
|
-
var
|
|
800
|
+
var BPTreeSyncBase = class extends BPTree {
|
|
788
801
|
constructor(strategy, comparator, option) {
|
|
789
802
|
super(strategy, comparator, option);
|
|
790
803
|
this.nodes = this._createCachedNode();
|
|
@@ -860,7 +873,7 @@ var BPTreeSync = class extends BPTree {
|
|
|
860
873
|
}
|
|
861
874
|
return id;
|
|
862
875
|
}
|
|
863
|
-
_createNode(isLeaf, keys, values, leaf =
|
|
876
|
+
_createNode(isLeaf, keys, values, leaf = isLeaf, parent = null, next = null, prev = null) {
|
|
864
877
|
const id = this._createNodeId(isLeaf);
|
|
865
878
|
const node = {
|
|
866
879
|
id,
|
|
@@ -871,38 +884,37 @@ var BPTreeSync = class extends BPTree {
|
|
|
871
884
|
next,
|
|
872
885
|
prev
|
|
873
886
|
};
|
|
874
|
-
this.
|
|
887
|
+
this.bufferForNodeCreate(node);
|
|
875
888
|
return node;
|
|
876
889
|
}
|
|
877
890
|
_deleteEntry(node, key, value) {
|
|
878
891
|
if (!node.leaf) {
|
|
892
|
+
let keyIndex = -1;
|
|
879
893
|
for (let i = 0, len = node.keys.length; i < len; i++) {
|
|
880
|
-
|
|
881
|
-
|
|
882
|
-
node.keys.splice(i, 1);
|
|
883
|
-
this.bufferForNodeUpdate(node);
|
|
894
|
+
if (node.keys[i] === key) {
|
|
895
|
+
keyIndex = i;
|
|
884
896
|
break;
|
|
885
897
|
}
|
|
886
898
|
}
|
|
887
|
-
|
|
888
|
-
|
|
889
|
-
|
|
890
|
-
|
|
891
|
-
|
|
892
|
-
break;
|
|
893
|
-
}
|
|
899
|
+
if (keyIndex !== -1) {
|
|
900
|
+
node.keys.splice(keyIndex, 1);
|
|
901
|
+
const valueIndex = keyIndex > 0 ? keyIndex - 1 : 0;
|
|
902
|
+
node.values.splice(valueIndex, 1);
|
|
903
|
+
this.bufferForNodeUpdate(node);
|
|
894
904
|
}
|
|
895
905
|
}
|
|
896
|
-
if (this.
|
|
906
|
+
if (this.rootId === node.id && node.keys.length === 1 && !node.leaf) {
|
|
897
907
|
const keys = node.keys;
|
|
898
|
-
this.bufferForNodeDelete(
|
|
899
|
-
|
|
900
|
-
this.
|
|
901
|
-
|
|
902
|
-
this.
|
|
908
|
+
this.bufferForNodeDelete(node);
|
|
909
|
+
const newRoot = this.getNode(keys[0]);
|
|
910
|
+
this.rootId = newRoot.id;
|
|
911
|
+
newRoot.parent = null;
|
|
912
|
+
this.strategy.head.root = this.rootId;
|
|
913
|
+
this.bufferForNodeUpdate(newRoot);
|
|
903
914
|
return;
|
|
904
|
-
} else if (this.
|
|
905
|
-
this.
|
|
915
|
+
} else if (this.rootId === node.id) {
|
|
916
|
+
const root = this.getNode(this.rootId);
|
|
917
|
+
this.bufferForNodeUpdate(root);
|
|
906
918
|
return;
|
|
907
919
|
} else if (node.keys.length < Math.ceil(this.order / 2) && !node.leaf || node.values.length < Math.ceil((this.order - 1) / 2) && node.leaf) {
|
|
908
920
|
if (node.parent === null) {
|
|
@@ -960,20 +972,11 @@ var BPTreeSync = class extends BPTree {
|
|
|
960
972
|
pointer.values.push(guess);
|
|
961
973
|
} else {
|
|
962
974
|
pointer.next = node.next;
|
|
963
|
-
pointer.prev = node.id;
|
|
964
975
|
if (pointer.next) {
|
|
965
|
-
const n = this.getNode(
|
|
976
|
+
const n = this.getNode(pointer.next);
|
|
966
977
|
n.prev = pointer.id;
|
|
967
978
|
this.bufferForNodeUpdate(n);
|
|
968
979
|
}
|
|
969
|
-
if (pointer.prev) {
|
|
970
|
-
const n = this.getNode(node.id);
|
|
971
|
-
n.next = pointer.id;
|
|
972
|
-
this.bufferForNodeUpdate(n);
|
|
973
|
-
}
|
|
974
|
-
if (isPredecessor) {
|
|
975
|
-
pointer.prev = null;
|
|
976
|
-
}
|
|
977
980
|
}
|
|
978
981
|
pointer.values.push(...node.values);
|
|
979
982
|
if (!pointer.leaf) {
|
|
@@ -997,13 +1000,10 @@ var BPTreeSync = class extends BPTree {
|
|
|
997
1000
|
node.keys = [pointerPm, ...node.keys];
|
|
998
1001
|
node.values = [guess, ...node.values];
|
|
999
1002
|
parentNode = this.getNode(node.parent);
|
|
1000
|
-
|
|
1001
|
-
|
|
1002
|
-
|
|
1003
|
-
|
|
1004
|
-
this.bufferForNodeUpdate(parentNode);
|
|
1005
|
-
break;
|
|
1006
|
-
}
|
|
1003
|
+
const nodeIndex = parentNode.keys.indexOf(node.id);
|
|
1004
|
+
if (nodeIndex > 0) {
|
|
1005
|
+
parentNode.values[nodeIndex - 1] = pointerKm;
|
|
1006
|
+
this.bufferForNodeUpdate(parentNode);
|
|
1007
1007
|
}
|
|
1008
1008
|
} else {
|
|
1009
1009
|
pointerPm = pointer.keys.splice(-1)[0];
|
|
@@ -1011,13 +1011,10 @@ var BPTreeSync = class extends BPTree {
|
|
|
1011
1011
|
node.keys = [pointerPm, ...node.keys];
|
|
1012
1012
|
node.values = [pointerKm, ...node.values];
|
|
1013
1013
|
parentNode = this.getNode(node.parent);
|
|
1014
|
-
|
|
1015
|
-
|
|
1016
|
-
|
|
1017
|
-
|
|
1018
|
-
this.bufferForNodeUpdate(parentNode);
|
|
1019
|
-
break;
|
|
1020
|
-
}
|
|
1014
|
+
const nodeIndex = parentNode.keys.indexOf(node.id);
|
|
1015
|
+
if (nodeIndex > 0) {
|
|
1016
|
+
parentNode.values[nodeIndex - 1] = pointerKm;
|
|
1017
|
+
this.bufferForNodeUpdate(parentNode);
|
|
1021
1018
|
}
|
|
1022
1019
|
}
|
|
1023
1020
|
this.bufferForNodeUpdate(node);
|
|
@@ -1031,13 +1028,10 @@ var BPTreeSync = class extends BPTree {
|
|
|
1031
1028
|
node.keys = [...node.keys, pointerP0];
|
|
1032
1029
|
node.values = [...node.values, guess];
|
|
1033
1030
|
parentNode = this.getNode(node.parent);
|
|
1034
|
-
|
|
1035
|
-
|
|
1036
|
-
|
|
1037
|
-
|
|
1038
|
-
this.bufferForNodeUpdate(parentNode);
|
|
1039
|
-
break;
|
|
1040
|
-
}
|
|
1031
|
+
const pointerIndex = parentNode.keys.indexOf(pointer.id);
|
|
1032
|
+
if (pointerIndex > 0) {
|
|
1033
|
+
parentNode.values[pointerIndex - 1] = pointerK0;
|
|
1034
|
+
this.bufferForNodeUpdate(parentNode);
|
|
1041
1035
|
}
|
|
1042
1036
|
} else {
|
|
1043
1037
|
pointerP0 = pointer.keys.splice(0, 1)[0];
|
|
@@ -1045,13 +1039,10 @@ var BPTreeSync = class extends BPTree {
|
|
|
1045
1039
|
node.keys = [...node.keys, pointerP0];
|
|
1046
1040
|
node.values = [...node.values, pointerK0];
|
|
1047
1041
|
parentNode = this.getNode(node.parent);
|
|
1048
|
-
|
|
1049
|
-
|
|
1050
|
-
|
|
1051
|
-
|
|
1052
|
-
this.bufferForNodeUpdate(parentNode);
|
|
1053
|
-
break;
|
|
1054
|
-
}
|
|
1042
|
+
const pointerIndex = parentNode.keys.indexOf(pointer.id);
|
|
1043
|
+
if (pointerIndex > 0) {
|
|
1044
|
+
parentNode.values[pointerIndex - 1] = pointer.values[0];
|
|
1045
|
+
this.bufferForNodeUpdate(parentNode);
|
|
1055
1046
|
}
|
|
1056
1047
|
}
|
|
1057
1048
|
this.bufferForNodeUpdate(node);
|
|
@@ -1079,12 +1070,14 @@ var BPTreeSync = class extends BPTree {
|
|
|
1079
1070
|
}
|
|
1080
1071
|
}
|
|
1081
1072
|
}
|
|
1073
|
+
} else {
|
|
1074
|
+
this.bufferForNodeUpdate(node);
|
|
1082
1075
|
}
|
|
1083
1076
|
}
|
|
1084
1077
|
_insertInParent(node, value, pointer) {
|
|
1085
|
-
if (this.
|
|
1078
|
+
if (this.rootId === node.id) {
|
|
1086
1079
|
const root = this._createNode(false, [node.id, pointer.id], [value]);
|
|
1087
|
-
this.
|
|
1080
|
+
this.rootId = root.id;
|
|
1088
1081
|
this.strategy.head.root = root.id;
|
|
1089
1082
|
node.parent = root.id;
|
|
1090
1083
|
pointer.parent = root.id;
|
|
@@ -1097,31 +1090,25 @@ var BPTreeSync = class extends BPTree {
|
|
|
1097
1090
|
return;
|
|
1098
1091
|
}
|
|
1099
1092
|
const parentNode = this.getNode(node.parent);
|
|
1100
|
-
|
|
1101
|
-
|
|
1102
|
-
|
|
1103
|
-
insertIndex = i + 1;
|
|
1104
|
-
} else {
|
|
1105
|
-
break;
|
|
1106
|
-
}
|
|
1093
|
+
const nodeIndex = parentNode.keys.indexOf(node.id);
|
|
1094
|
+
if (nodeIndex === -1) {
|
|
1095
|
+
throw new Error(`Node ${node.id} not found in parent ${parentNode.id}`);
|
|
1107
1096
|
}
|
|
1097
|
+
const insertIndex = nodeIndex;
|
|
1108
1098
|
parentNode.values.splice(insertIndex, 0, value);
|
|
1109
1099
|
parentNode.keys.splice(insertIndex + 1, 0, pointer.id);
|
|
1110
1100
|
pointer.parent = parentNode.id;
|
|
1111
1101
|
if (pointer.leaf) {
|
|
1112
|
-
const
|
|
1113
|
-
const
|
|
1114
|
-
|
|
1115
|
-
|
|
1116
|
-
|
|
1117
|
-
|
|
1118
|
-
|
|
1119
|
-
this.
|
|
1120
|
-
|
|
1121
|
-
|
|
1122
|
-
const rightSibling = this.getNode(rightSiblingId);
|
|
1123
|
-
rightSibling.prev = pointer.id;
|
|
1124
|
-
this.bufferForNodeUpdate(rightSibling);
|
|
1102
|
+
const leftSibling = node;
|
|
1103
|
+
const oldNextId = leftSibling.next;
|
|
1104
|
+
pointer.prev = leftSibling.id;
|
|
1105
|
+
pointer.next = oldNextId;
|
|
1106
|
+
leftSibling.next = pointer.id;
|
|
1107
|
+
this.bufferForNodeUpdate(leftSibling);
|
|
1108
|
+
if (oldNextId) {
|
|
1109
|
+
const oldNext = this.getNode(oldNextId);
|
|
1110
|
+
oldNext.prev = pointer.id;
|
|
1111
|
+
this.bufferForNodeUpdate(oldNext);
|
|
1125
1112
|
}
|
|
1126
1113
|
}
|
|
1127
1114
|
this.bufferForNodeUpdate(parentNode);
|
|
@@ -1150,18 +1137,20 @@ var BPTreeSync = class extends BPTree {
|
|
|
1150
1137
|
}
|
|
1151
1138
|
}
|
|
1152
1139
|
init() {
|
|
1140
|
+
this.clear();
|
|
1153
1141
|
const head = this.strategy.readHead();
|
|
1154
1142
|
if (head === null) {
|
|
1155
1143
|
this.order = this.strategy.order;
|
|
1156
|
-
|
|
1157
|
-
this.
|
|
1144
|
+
const root = this._createNode(true, [], [], true);
|
|
1145
|
+
this.rootId = root.id;
|
|
1146
|
+
this.strategy.head.root = this.rootId;
|
|
1158
1147
|
this.commitHeadBuffer();
|
|
1159
1148
|
this.commitNodeCreateBuffer();
|
|
1160
1149
|
} else {
|
|
1161
1150
|
const { root, order } = head;
|
|
1162
1151
|
this.strategy.head = head;
|
|
1163
1152
|
this.order = order;
|
|
1164
|
-
this.
|
|
1153
|
+
this.rootId = root;
|
|
1165
1154
|
}
|
|
1166
1155
|
if (this.order < 3) {
|
|
1167
1156
|
throw new Error(`The 'order' parameter must be greater than 2. but got a '${this.order}'.`);
|
|
@@ -1178,43 +1167,73 @@ var BPTreeSync = class extends BPTree {
|
|
|
1178
1167
|
return cache.raw;
|
|
1179
1168
|
}
|
|
1180
1169
|
insertableNode(value) {
|
|
1181
|
-
let node = this.getNode(this.
|
|
1170
|
+
let node = this.getNode(this.rootId);
|
|
1171
|
+
if (node.parent !== null) {
|
|
1172
|
+
node.parent = null;
|
|
1173
|
+
this.bufferForNodeUpdate(node);
|
|
1174
|
+
}
|
|
1182
1175
|
while (!node.leaf) {
|
|
1176
|
+
const parentId = node.id;
|
|
1183
1177
|
for (let i = 0, len = node.values.length; i < len; i++) {
|
|
1184
1178
|
const nValue = node.values[i];
|
|
1185
1179
|
const k = node.keys;
|
|
1186
1180
|
if (this.comparator.isSame(value, nValue)) {
|
|
1187
1181
|
node = this.getNode(k[i + 1]);
|
|
1182
|
+
if (node.parent !== parentId) {
|
|
1183
|
+
node.parent = parentId;
|
|
1184
|
+
this.bufferForNodeUpdate(node);
|
|
1185
|
+
}
|
|
1188
1186
|
break;
|
|
1189
1187
|
} else if (this.comparator.isLower(value, nValue)) {
|
|
1190
1188
|
node = this.getNode(k[i]);
|
|
1189
|
+
if (node.parent !== parentId) {
|
|
1190
|
+
node.parent = parentId;
|
|
1191
|
+
this.bufferForNodeUpdate(node);
|
|
1192
|
+
}
|
|
1191
1193
|
break;
|
|
1192
1194
|
} else if (i + 1 === node.values.length) {
|
|
1193
1195
|
node = this.getNode(k[i + 1]);
|
|
1196
|
+
if (node.parent !== parentId) {
|
|
1197
|
+
node.parent = parentId;
|
|
1198
|
+
this.bufferForNodeUpdate(node);
|
|
1199
|
+
}
|
|
1194
1200
|
break;
|
|
1195
1201
|
}
|
|
1196
1202
|
}
|
|
1197
1203
|
}
|
|
1198
1204
|
return node;
|
|
1199
1205
|
}
|
|
1200
|
-
/**
|
|
1201
|
-
* Find the insertable node using primaryAsc comparison.
|
|
1202
|
-
* This allows finding nodes by primary value only, ignoring unique identifiers.
|
|
1203
|
-
*/
|
|
1204
1206
|
insertableNodeByPrimary(value) {
|
|
1205
|
-
let node = this.getNode(this.
|
|
1207
|
+
let node = this.getNode(this.rootId);
|
|
1208
|
+
if (node.parent !== null) {
|
|
1209
|
+
node.parent = null;
|
|
1210
|
+
this.bufferForNodeUpdate(node);
|
|
1211
|
+
}
|
|
1206
1212
|
while (!node.leaf) {
|
|
1213
|
+
const parentId = node.id;
|
|
1207
1214
|
for (let i = 0, len = node.values.length; i < len; i++) {
|
|
1208
1215
|
const nValue = node.values[i];
|
|
1209
1216
|
const k = node.keys;
|
|
1210
1217
|
if (this.comparator.isPrimarySame(value, nValue)) {
|
|
1211
1218
|
node = this.getNode(k[i]);
|
|
1219
|
+
if (node.parent !== parentId) {
|
|
1220
|
+
node.parent = parentId;
|
|
1221
|
+
this.bufferForNodeUpdate(node);
|
|
1222
|
+
}
|
|
1212
1223
|
break;
|
|
1213
1224
|
} else if (this.comparator.isPrimaryLower(value, nValue)) {
|
|
1214
1225
|
node = this.getNode(k[i]);
|
|
1226
|
+
if (node.parent !== parentId) {
|
|
1227
|
+
node.parent = parentId;
|
|
1228
|
+
this.bufferForNodeUpdate(node);
|
|
1229
|
+
}
|
|
1215
1230
|
break;
|
|
1216
1231
|
} else if (i + 1 === node.values.length) {
|
|
1217
1232
|
node = this.getNode(k[i + 1]);
|
|
1233
|
+
if (node.parent !== parentId) {
|
|
1234
|
+
node.parent = parentId;
|
|
1235
|
+
this.bufferForNodeUpdate(node);
|
|
1236
|
+
}
|
|
1218
1237
|
break;
|
|
1219
1238
|
}
|
|
1220
1239
|
}
|
|
@@ -1222,17 +1241,30 @@ var BPTreeSync = class extends BPTree {
|
|
|
1222
1241
|
return node;
|
|
1223
1242
|
}
|
|
1224
1243
|
insertableRightestNodeByPrimary(value) {
|
|
1225
|
-
let node = this.getNode(this.
|
|
1244
|
+
let node = this.getNode(this.rootId);
|
|
1245
|
+
if (node.parent !== null) {
|
|
1246
|
+
node.parent = null;
|
|
1247
|
+
this.bufferForNodeUpdate(node);
|
|
1248
|
+
}
|
|
1226
1249
|
while (!node.leaf) {
|
|
1250
|
+
const parentId = node.id;
|
|
1227
1251
|
for (let i = 0, len = node.values.length; i < len; i++) {
|
|
1228
1252
|
const nValue = node.values[i];
|
|
1229
1253
|
const k = node.keys;
|
|
1230
1254
|
if (this.comparator.isPrimaryLower(value, nValue)) {
|
|
1231
1255
|
node = this.getNode(k[i]);
|
|
1256
|
+
if (node.parent !== parentId) {
|
|
1257
|
+
node.parent = parentId;
|
|
1258
|
+
this.bufferForNodeUpdate(node);
|
|
1259
|
+
}
|
|
1232
1260
|
break;
|
|
1233
1261
|
}
|
|
1234
1262
|
if (i + 1 === node.values.length) {
|
|
1235
1263
|
node = this.getNode(k[i + 1]);
|
|
1264
|
+
if (node.parent !== parentId) {
|
|
1265
|
+
node.parent = parentId;
|
|
1266
|
+
this.bufferForNodeUpdate(node);
|
|
1267
|
+
}
|
|
1236
1268
|
break;
|
|
1237
1269
|
}
|
|
1238
1270
|
}
|
|
@@ -1266,27 +1298,75 @@ var BPTreeSync = class extends BPTree {
|
|
|
1266
1298
|
return this.getNode(guessNode);
|
|
1267
1299
|
}
|
|
1268
1300
|
leftestNode() {
|
|
1269
|
-
let node = this.
|
|
1301
|
+
let node = this.getNode(this.rootId);
|
|
1302
|
+
if (node.parent !== null) {
|
|
1303
|
+
node.parent = null;
|
|
1304
|
+
this.bufferForNodeUpdate(node);
|
|
1305
|
+
}
|
|
1270
1306
|
while (!node.leaf) {
|
|
1307
|
+
const parentId = node.id;
|
|
1271
1308
|
const keys = node.keys;
|
|
1272
1309
|
node = this.getNode(keys[0]);
|
|
1310
|
+
if (node.parent !== parentId) {
|
|
1311
|
+
node.parent = parentId;
|
|
1312
|
+
this.bufferForNodeUpdate(node);
|
|
1313
|
+
}
|
|
1273
1314
|
}
|
|
1274
1315
|
return node;
|
|
1275
1316
|
}
|
|
1276
1317
|
rightestNode() {
|
|
1277
|
-
let node = this.
|
|
1318
|
+
let node = this.getNode(this.rootId);
|
|
1319
|
+
if (node.parent !== null) {
|
|
1320
|
+
node.parent = null;
|
|
1321
|
+
this.bufferForNodeUpdate(node);
|
|
1322
|
+
}
|
|
1278
1323
|
while (!node.leaf) {
|
|
1324
|
+
const parentId = node.id;
|
|
1279
1325
|
const keys = node.keys;
|
|
1280
1326
|
node = this.getNode(keys[keys.length - 1]);
|
|
1327
|
+
if (node.parent !== parentId) {
|
|
1328
|
+
node.parent = parentId;
|
|
1329
|
+
this.bufferForNodeUpdate(node);
|
|
1330
|
+
}
|
|
1281
1331
|
}
|
|
1282
1332
|
return node;
|
|
1283
1333
|
}
|
|
1334
|
+
exists(key, value) {
|
|
1335
|
+
const node = this.insertableNode(value);
|
|
1336
|
+
for (let i = 0, len = node.values.length; i < len; i++) {
|
|
1337
|
+
if (this.comparator.isSame(value, node.values[i])) {
|
|
1338
|
+
const keys = node.keys[i];
|
|
1339
|
+
if (keys.includes(key)) {
|
|
1340
|
+
return true;
|
|
1341
|
+
}
|
|
1342
|
+
}
|
|
1343
|
+
}
|
|
1344
|
+
return false;
|
|
1345
|
+
}
|
|
1346
|
+
forceUpdate(id) {
|
|
1347
|
+
if (id) {
|
|
1348
|
+
this.nodes.delete(id);
|
|
1349
|
+
this.getNode(id);
|
|
1350
|
+
return 1;
|
|
1351
|
+
}
|
|
1352
|
+
const keys = Array.from(this.nodes.keys());
|
|
1353
|
+
for (const key of keys) {
|
|
1354
|
+
this.nodes.delete(key);
|
|
1355
|
+
}
|
|
1356
|
+
for (const key of keys) {
|
|
1357
|
+
this.getNode(key);
|
|
1358
|
+
}
|
|
1359
|
+
return keys.length;
|
|
1360
|
+
}
|
|
1284
1361
|
commitHeadBuffer() {
|
|
1285
1362
|
if (!this._strategyDirty) {
|
|
1286
1363
|
return;
|
|
1287
1364
|
}
|
|
1288
1365
|
this._strategyDirty = false;
|
|
1289
1366
|
this.strategy.writeHead(this.strategy.head);
|
|
1367
|
+
if (this.strategy.head.root) {
|
|
1368
|
+
this.nodes.delete(this.strategy.head.root);
|
|
1369
|
+
}
|
|
1290
1370
|
}
|
|
1291
1371
|
commitNodeCreateBuffer() {
|
|
1292
1372
|
for (const node of this._nodeCreateBuffer.values()) {
|
|
@@ -1297,33 +1377,25 @@ var BPTreeSync = class extends BPTree {
|
|
|
1297
1377
|
commitNodeUpdateBuffer() {
|
|
1298
1378
|
for (const node of this._nodeUpdateBuffer.values()) {
|
|
1299
1379
|
this.strategy.write(node.id, node);
|
|
1380
|
+
this.nodes.delete(node.id);
|
|
1300
1381
|
}
|
|
1301
1382
|
this._nodeUpdateBuffer.clear();
|
|
1302
1383
|
}
|
|
1303
1384
|
commitNodeDeleteBuffer() {
|
|
1304
1385
|
for (const node of this._nodeDeleteBuffer.values()) {
|
|
1305
1386
|
this.strategy.delete(node.id);
|
|
1387
|
+
this.nodes.delete(node.id);
|
|
1306
1388
|
}
|
|
1307
1389
|
this._nodeDeleteBuffer.clear();
|
|
1308
1390
|
}
|
|
1309
|
-
/**
|
|
1310
|
-
* Retrieves the value associated with the given key (PK).
|
|
1311
|
-
* Note: This method performs a full scan of leaf nodes as the tree is ordered by Value, not Key.
|
|
1312
|
-
*
|
|
1313
|
-
* @param key The key to search for.
|
|
1314
|
-
* @returns The value associated with the key, or undefined if not found.
|
|
1315
|
-
*/
|
|
1316
1391
|
get(key) {
|
|
1317
1392
|
let node = this.leftestNode();
|
|
1318
1393
|
while (true) {
|
|
1319
|
-
|
|
1320
|
-
const
|
|
1321
|
-
for (let
|
|
1322
|
-
|
|
1323
|
-
|
|
1324
|
-
if (keys[j] === key) {
|
|
1325
|
-
return node.values[i];
|
|
1326
|
-
}
|
|
1394
|
+
for (let i = 0, len = node.values.length; i < len; i++) {
|
|
1395
|
+
const keys = node.keys[i];
|
|
1396
|
+
for (let j = 0, kLen = keys.length; j < kLen; j++) {
|
|
1397
|
+
if (keys[j] === key) {
|
|
1398
|
+
return node.values[i];
|
|
1327
1399
|
}
|
|
1328
1400
|
}
|
|
1329
1401
|
}
|
|
@@ -1442,21 +1514,15 @@ var BPTreeSync = class extends BPTree {
|
|
|
1442
1514
|
const nValue = node.values[i];
|
|
1443
1515
|
if (this.comparator.isSame(value, nValue)) {
|
|
1444
1516
|
const keys = node.keys[i];
|
|
1445
|
-
|
|
1446
|
-
|
|
1447
|
-
|
|
1448
|
-
|
|
1449
|
-
} else if (node.id === this.root.id) {
|
|
1450
|
-
node.values.splice(i, 1);
|
|
1517
|
+
const keyIndex = keys.indexOf(key);
|
|
1518
|
+
if (keyIndex !== -1) {
|
|
1519
|
+
keys.splice(keyIndex, 1);
|
|
1520
|
+
if (keys.length === 0) {
|
|
1451
1521
|
node.keys.splice(i, 1);
|
|
1452
|
-
|
|
1453
|
-
} else {
|
|
1454
|
-
keys.splice(keys.indexOf(key), 1);
|
|
1455
|
-
node.keys.splice(i, 1);
|
|
1456
|
-
node.values.splice(node.values.indexOf(value), 1);
|
|
1457
|
-
this._deleteEntry(node, key, value);
|
|
1458
|
-
this.bufferForNodeUpdate(node);
|
|
1522
|
+
node.values.splice(i, 1);
|
|
1459
1523
|
}
|
|
1524
|
+
this._deleteEntry(node, key, value);
|
|
1525
|
+
break;
|
|
1460
1526
|
}
|
|
1461
1527
|
}
|
|
1462
1528
|
}
|
|
@@ -1465,294 +1531,410 @@ var BPTreeSync = class extends BPTree {
|
|
|
1465
1531
|
this.commitNodeUpdateBuffer();
|
|
1466
1532
|
this.commitNodeDeleteBuffer();
|
|
1467
1533
|
}
|
|
1468
|
-
|
|
1469
|
-
|
|
1470
|
-
for (let i = 0, len = node.values.length; i < len; i++) {
|
|
1471
|
-
const nValue = node.values[i];
|
|
1472
|
-
if (this.comparator.isSame(value, nValue)) {
|
|
1473
|
-
const keys = node.keys[i];
|
|
1474
|
-
return keys.includes(key);
|
|
1475
|
-
}
|
|
1476
|
-
}
|
|
1477
|
-
return false;
|
|
1534
|
+
getHeadData() {
|
|
1535
|
+
return this.strategy.head.data;
|
|
1478
1536
|
}
|
|
1479
1537
|
setHeadData(data) {
|
|
1480
1538
|
this.strategy.head.data = data;
|
|
1481
|
-
this.
|
|
1482
|
-
this.commitHeadBuffer();
|
|
1539
|
+
this.strategy.writeHead(this.strategy.head);
|
|
1483
1540
|
}
|
|
1484
|
-
|
|
1485
|
-
|
|
1486
|
-
|
|
1487
|
-
|
|
1488
|
-
|
|
1489
|
-
|
|
1490
|
-
|
|
1491
|
-
|
|
1541
|
+
};
|
|
1542
|
+
var SerializeStrategy = class {
|
|
1543
|
+
order;
|
|
1544
|
+
head;
|
|
1545
|
+
constructor(order) {
|
|
1546
|
+
this.order = order;
|
|
1547
|
+
this.head = {
|
|
1548
|
+
order,
|
|
1549
|
+
root: null,
|
|
1550
|
+
data: {}
|
|
1551
|
+
};
|
|
1492
1552
|
}
|
|
1493
1553
|
};
|
|
1494
|
-
var
|
|
1495
|
-
|
|
1496
|
-
|
|
1497
|
-
|
|
1498
|
-
|
|
1499
|
-
|
|
1500
|
-
return await promise.then((v) => [void 0, v]).catch((err) => [err]);
|
|
1554
|
+
var SerializeStrategySync = class extends SerializeStrategy {
|
|
1555
|
+
getHeadData(key, defaultValue) {
|
|
1556
|
+
if (!Object.hasOwn(this.head.data, key)) {
|
|
1557
|
+
this.setHeadData(key, defaultValue);
|
|
1558
|
+
}
|
|
1559
|
+
return this.head.data[key];
|
|
1501
1560
|
}
|
|
1502
|
-
|
|
1503
|
-
|
|
1504
|
-
|
|
1505
|
-
|
|
1561
|
+
setHeadData(key, data) {
|
|
1562
|
+
this.head.data[key] = data;
|
|
1563
|
+
this.writeHead(this.head);
|
|
1564
|
+
}
|
|
1565
|
+
autoIncrement(key, defaultValue) {
|
|
1566
|
+
const current = this.getHeadData(key, defaultValue);
|
|
1567
|
+
const next = current + 1;
|
|
1568
|
+
this.setHeadData(key, next);
|
|
1569
|
+
return current;
|
|
1570
|
+
}
|
|
1571
|
+
compareAndSwapHead(oldRoot, newRoot) {
|
|
1572
|
+
if (this.head.root !== oldRoot) {
|
|
1506
1573
|
return false;
|
|
1507
1574
|
}
|
|
1575
|
+
this.head.root = newRoot;
|
|
1576
|
+
this.writeHead(this.head);
|
|
1508
1577
|
return true;
|
|
1509
1578
|
}
|
|
1510
|
-
|
|
1511
|
-
|
|
1579
|
+
};
|
|
1580
|
+
var InMemoryStoreStrategySync = class extends SerializeStrategySync {
|
|
1581
|
+
node;
|
|
1582
|
+
constructor(order) {
|
|
1583
|
+
super(order);
|
|
1584
|
+
this.node = {};
|
|
1512
1585
|
}
|
|
1513
|
-
|
|
1514
|
-
return
|
|
1586
|
+
id(isLeaf) {
|
|
1587
|
+
return this.autoIncrement("index", 1).toString();
|
|
1515
1588
|
}
|
|
1516
|
-
|
|
1517
|
-
|
|
1589
|
+
read(id) {
|
|
1590
|
+
if (!Object.hasOwn(this.node, id)) {
|
|
1591
|
+
throw new Error(`The tree attempted to reference node '${id}', but couldn't find the corresponding node.`);
|
|
1592
|
+
}
|
|
1593
|
+
const node = this.node[id];
|
|
1594
|
+
return JSON.parse(JSON.stringify(node));
|
|
1518
1595
|
}
|
|
1519
|
-
|
|
1520
|
-
|
|
1521
|
-
*/
|
|
1522
|
-
constructor() {
|
|
1523
|
-
this.readings = /* @__PURE__ */ new Map();
|
|
1524
|
-
this.writings = /* @__PURE__ */ new Map();
|
|
1525
|
-
this.readQueue = /* @__PURE__ */ new Map();
|
|
1526
|
-
this.writeQueue = /* @__PURE__ */ new Map();
|
|
1596
|
+
write(id, node) {
|
|
1597
|
+
this.node[id] = node;
|
|
1527
1598
|
}
|
|
1528
|
-
|
|
1529
|
-
|
|
1530
|
-
* @param start - The starting value of the range.
|
|
1531
|
-
* @param length - The length of the range.
|
|
1532
|
-
* @returns A range tuple [start, start + length].
|
|
1533
|
-
*/
|
|
1534
|
-
range(start, length) {
|
|
1535
|
-
return [start, start + length];
|
|
1599
|
+
delete(id) {
|
|
1600
|
+
delete this.node[id];
|
|
1536
1601
|
}
|
|
1537
|
-
|
|
1538
|
-
|
|
1602
|
+
readHead() {
|
|
1603
|
+
if (this.head.root === null) {
|
|
1604
|
+
return null;
|
|
1605
|
+
}
|
|
1606
|
+
return this.head;
|
|
1539
1607
|
}
|
|
1540
|
-
|
|
1541
|
-
|
|
1542
|
-
const [b1, b2] = b;
|
|
1543
|
-
return a1 === b1 && a2 === b2;
|
|
1608
|
+
writeHead(head) {
|
|
1609
|
+
this.head = head;
|
|
1544
1610
|
}
|
|
1545
|
-
|
|
1546
|
-
|
|
1547
|
-
|
|
1548
|
-
|
|
1549
|
-
|
|
1550
|
-
|
|
1551
|
-
|
|
1611
|
+
};
|
|
1612
|
+
var BPTreeSyncSnapshotStrategy = class extends SerializeStrategySync {
|
|
1613
|
+
baseStrategy;
|
|
1614
|
+
snapshotHead;
|
|
1615
|
+
constructor(baseStrategy, root) {
|
|
1616
|
+
super(baseStrategy.order);
|
|
1617
|
+
this.baseStrategy = baseStrategy;
|
|
1618
|
+
this.snapshotHead = {
|
|
1619
|
+
...baseStrategy.head,
|
|
1620
|
+
root,
|
|
1621
|
+
data: { ...baseStrategy.head.data }
|
|
1622
|
+
};
|
|
1623
|
+
this.head = this.snapshotHead;
|
|
1552
1624
|
}
|
|
1553
|
-
|
|
1554
|
-
|
|
1555
|
-
if (this._matchArgs(args, pattern)) {
|
|
1556
|
-
return handlers[key](...args);
|
|
1557
|
-
}
|
|
1558
|
-
}
|
|
1559
|
-
throw new Error("Invalid arguments");
|
|
1625
|
+
id(isLeaf) {
|
|
1626
|
+
return this.baseStrategy.id(isLeaf);
|
|
1560
1627
|
}
|
|
1561
|
-
|
|
1562
|
-
return
|
|
1563
|
-
const expectedType = pattern[index];
|
|
1564
|
-
if (expectedType === void 0) return typeof arg === "undefined";
|
|
1565
|
-
if (expectedType === Function) return typeof arg === "function";
|
|
1566
|
-
if (expectedType === Number) return typeof arg === "number";
|
|
1567
|
-
if (expectedType === Array) return Array.isArray(arg);
|
|
1568
|
-
return false;
|
|
1569
|
-
});
|
|
1628
|
+
read(id) {
|
|
1629
|
+
return this.baseStrategy.read(id);
|
|
1570
1630
|
}
|
|
1571
|
-
|
|
1572
|
-
|
|
1573
|
-
const random = Math.random().toString(36).substring(2);
|
|
1574
|
-
return `${timestamp}${random}`;
|
|
1631
|
+
write(id, node) {
|
|
1632
|
+
this.baseStrategy.write(id, node);
|
|
1575
1633
|
}
|
|
1576
|
-
|
|
1577
|
-
|
|
1578
|
-
if (!unit) {
|
|
1579
|
-
throw _Ryoiki.ERR_NOT_EXISTS(lockId);
|
|
1580
|
-
}
|
|
1581
|
-
workspaces.set(lockId, unit);
|
|
1582
|
-
queue.delete(lockId);
|
|
1583
|
-
unit.alloc();
|
|
1634
|
+
delete(id) {
|
|
1635
|
+
this.baseStrategy.delete(id);
|
|
1584
1636
|
}
|
|
1585
|
-
|
|
1586
|
-
|
|
1587
|
-
if (!unit) {
|
|
1588
|
-
throw _Ryoiki.ERR_NOT_EXISTS(lockId);
|
|
1589
|
-
}
|
|
1590
|
-
workspaces.delete(lockId);
|
|
1591
|
-
unit.free();
|
|
1637
|
+
readHead() {
|
|
1638
|
+
return this.snapshotHead;
|
|
1592
1639
|
}
|
|
1593
|
-
|
|
1594
|
-
|
|
1595
|
-
|
|
1596
|
-
|
|
1597
|
-
|
|
1598
|
-
|
|
1599
|
-
|
|
1640
|
+
writeHead(head) {
|
|
1641
|
+
this.snapshotHead.root = head.root;
|
|
1642
|
+
this.snapshotHead.data = { ...head.data };
|
|
1643
|
+
}
|
|
1644
|
+
compareAndSwapHead(oldRoot, newRoot) {
|
|
1645
|
+
return this.baseStrategy.compareAndSwapHead(oldRoot, newRoot);
|
|
1646
|
+
}
|
|
1647
|
+
getHeadData(key, defaultValue) {
|
|
1648
|
+
return this.snapshotHead.data[key] ?? defaultValue;
|
|
1649
|
+
}
|
|
1650
|
+
setHeadData(key, data) {
|
|
1651
|
+
this.snapshotHead.data[key] = data;
|
|
1652
|
+
}
|
|
1653
|
+
autoIncrement(key, defaultValue) {
|
|
1654
|
+
return this.snapshotHead.data[key] ?? defaultValue;
|
|
1655
|
+
}
|
|
1656
|
+
};
|
|
1657
|
+
var BPTreeSyncTransaction = class extends BPTreeSyncBase {
|
|
1658
|
+
realBaseTree;
|
|
1659
|
+
realBaseStrategy;
|
|
1660
|
+
txNodes = /* @__PURE__ */ new Map();
|
|
1661
|
+
dirtyIds;
|
|
1662
|
+
createdInTx;
|
|
1663
|
+
deletedIds;
|
|
1664
|
+
initialRootId;
|
|
1665
|
+
transactionRootId;
|
|
1666
|
+
constructor(baseTree) {
|
|
1667
|
+
super(baseTree.strategy, baseTree.comparator, baseTree.option);
|
|
1668
|
+
this.realBaseTree = baseTree;
|
|
1669
|
+
this.realBaseStrategy = baseTree.strategy;
|
|
1670
|
+
this.order = baseTree.getOrder();
|
|
1671
|
+
this.initialRootId = "";
|
|
1672
|
+
this.transactionRootId = "";
|
|
1673
|
+
this.dirtyIds = /* @__PURE__ */ new Set();
|
|
1674
|
+
this.createdInTx = /* @__PURE__ */ new Set();
|
|
1675
|
+
this.deletedIds = /* @__PURE__ */ new Set();
|
|
1676
|
+
}
|
|
1677
|
+
/**
|
|
1678
|
+
* Initializes the transaction by capturing the current state of the tree.
|
|
1679
|
+
*/
|
|
1680
|
+
initTransaction() {
|
|
1681
|
+
const head = this.realBaseStrategy.readHead();
|
|
1682
|
+
if (head) {
|
|
1683
|
+
this.order = head.order;
|
|
1684
|
+
this.initialRootId = head.root;
|
|
1685
|
+
} else {
|
|
1686
|
+
this.initialRootId = this.realBaseTree.getRootId();
|
|
1687
|
+
}
|
|
1688
|
+
if (!this.initialRootId) {
|
|
1689
|
+
const root = this._createNode(true, [], [], true);
|
|
1690
|
+
this.initialRootId = root.id;
|
|
1691
|
+
}
|
|
1692
|
+
this.transactionRootId = this.initialRootId;
|
|
1693
|
+
this.rootId = this.transactionRootId;
|
|
1694
|
+
const snapshotStrategy = new BPTreeSyncSnapshotStrategy(this.realBaseStrategy, this.initialRootId);
|
|
1695
|
+
this.strategy = snapshotStrategy;
|
|
1696
|
+
this.txNodes.clear();
|
|
1697
|
+
this.dirtyIds.clear();
|
|
1698
|
+
this.createdInTx.clear();
|
|
1699
|
+
this.deletedIds.clear();
|
|
1700
|
+
}
|
|
1701
|
+
getNode(id) {
|
|
1702
|
+
if (this.txNodes.has(id)) {
|
|
1703
|
+
return this.txNodes.get(id);
|
|
1704
|
+
}
|
|
1705
|
+
if (this.deletedIds.has(id)) {
|
|
1706
|
+
throw new Error(`The tree attempted to reference deleted node '${id}'`);
|
|
1707
|
+
}
|
|
1708
|
+
const baseNode = this.realBaseStrategy.read(id);
|
|
1709
|
+
const clone = JSON.parse(JSON.stringify(baseNode));
|
|
1710
|
+
this.txNodes.set(id, clone);
|
|
1711
|
+
return clone;
|
|
1712
|
+
}
|
|
1713
|
+
bufferForNodeUpdate(node) {
|
|
1714
|
+
if (this.dirtyIds.has(node.id) && this.txNodes.has(node.id) && node._p) {
|
|
1715
|
+
this.txNodes.set(node.id, node);
|
|
1716
|
+
return;
|
|
1717
|
+
}
|
|
1718
|
+
node._p = true;
|
|
1719
|
+
this.txNodes.set(node.id, node);
|
|
1720
|
+
this.dirtyIds.add(node.id);
|
|
1721
|
+
if (node.leaf) {
|
|
1722
|
+
if (node.next && !this.dirtyIds.has(node.next) && !this.deletedIds.has(node.next)) {
|
|
1723
|
+
try {
|
|
1724
|
+
this.bufferForNodeUpdate(this.getNode(node.next));
|
|
1725
|
+
} catch (e) {
|
|
1726
|
+
}
|
|
1600
1727
|
}
|
|
1601
|
-
|
|
1602
|
-
|
|
1603
|
-
|
|
1604
|
-
|
|
1728
|
+
if (node.prev && !this.dirtyIds.has(node.prev) && !this.deletedIds.has(node.prev)) {
|
|
1729
|
+
try {
|
|
1730
|
+
this.bufferForNodeUpdate(this.getNode(node.prev));
|
|
1731
|
+
} catch (e) {
|
|
1605
1732
|
}
|
|
1606
|
-
|
|
1607
|
-
|
|
1608
|
-
|
|
1609
|
-
|
|
1610
|
-
const fetch = () => {
|
|
1611
|
-
this.fetchUnitAndRun(this.readQueue, this.readings);
|
|
1612
|
-
this.fetchUnitAndRun(this.writeQueue, this.writings);
|
|
1613
|
-
};
|
|
1614
|
-
queue.set(id, { id, range, condition, alloc, free: fetch });
|
|
1615
|
-
fetch();
|
|
1616
|
-
});
|
|
1733
|
+
}
|
|
1734
|
+
}
|
|
1735
|
+
this.markPathDirty(node);
|
|
1736
|
+
delete node._p;
|
|
1617
1737
|
}
|
|
1618
|
-
|
|
1619
|
-
|
|
1620
|
-
|
|
1621
|
-
|
|
1622
|
-
|
|
1738
|
+
bufferForNodeCreate(node) {
|
|
1739
|
+
this.txNodes.set(node.id, node);
|
|
1740
|
+
this.dirtyIds.add(node.id);
|
|
1741
|
+
this.createdInTx.add(node.id);
|
|
1742
|
+
if (node.leaf) {
|
|
1743
|
+
if (node.next && !this.dirtyIds.has(node.next) && !this.deletedIds.has(node.next)) {
|
|
1744
|
+
try {
|
|
1745
|
+
this.bufferForNodeUpdate(this.getNode(node.next));
|
|
1746
|
+
} catch (e) {
|
|
1747
|
+
}
|
|
1748
|
+
}
|
|
1749
|
+
if (node.prev && !this.dirtyIds.has(node.prev) && !this.deletedIds.has(node.prev)) {
|
|
1750
|
+
try {
|
|
1751
|
+
this.bufferForNodeUpdate(this.getNode(node.prev));
|
|
1752
|
+
} catch (e) {
|
|
1753
|
+
}
|
|
1754
|
+
}
|
|
1755
|
+
}
|
|
1756
|
+
this.markPathDirty(node);
|
|
1757
|
+
}
|
|
1758
|
+
bufferForNodeDelete(node) {
|
|
1759
|
+
this.txNodes.delete(node.id);
|
|
1760
|
+
this.dirtyIds.add(node.id);
|
|
1761
|
+
this.deletedIds.add(node.id);
|
|
1762
|
+
}
|
|
1763
|
+
markPathDirty(node) {
|
|
1764
|
+
let curr = node;
|
|
1765
|
+
while (curr.parent) {
|
|
1766
|
+
if (this.deletedIds.has(curr.parent)) {
|
|
1623
1767
|
break;
|
|
1624
1768
|
}
|
|
1769
|
+
if (this.dirtyIds.has(curr.parent) && this.txNodes.has(curr.parent)) {
|
|
1770
|
+
break;
|
|
1771
|
+
}
|
|
1772
|
+
const parent = this.getNode(curr.parent);
|
|
1773
|
+
this.dirtyIds.add(parent.id);
|
|
1774
|
+
curr = parent;
|
|
1775
|
+
}
|
|
1776
|
+
if (!curr.parent) {
|
|
1777
|
+
this.transactionRootId = curr.id;
|
|
1625
1778
|
}
|
|
1626
|
-
return isLocked;
|
|
1627
1779
|
}
|
|
1628
|
-
|
|
1629
|
-
|
|
1630
|
-
|
|
1631
|
-
|
|
1632
|
-
|
|
1633
|
-
|
|
1634
|
-
|
|
1780
|
+
_createNode(isLeaf, keys, values, leaf = isLeaf, parent = null, next = null, prev = null) {
|
|
1781
|
+
const id = this.strategy.id(isLeaf);
|
|
1782
|
+
const node = {
|
|
1783
|
+
id,
|
|
1784
|
+
keys,
|
|
1785
|
+
values,
|
|
1786
|
+
leaf,
|
|
1787
|
+
parent,
|
|
1788
|
+
next,
|
|
1789
|
+
prev
|
|
1790
|
+
};
|
|
1791
|
+
this.bufferForNodeCreate(node);
|
|
1792
|
+
return node;
|
|
1635
1793
|
}
|
|
1636
1794
|
/**
|
|
1637
|
-
*
|
|
1638
|
-
*
|
|
1639
|
-
*
|
|
1640
|
-
|
|
1641
|
-
|
|
1642
|
-
|
|
1795
|
+
* Attempts to commit the transaction.
|
|
1796
|
+
* Uses Optimistic Locking (Compare-And-Swap) on the root node ID to detect conflicts.
|
|
1797
|
+
*
|
|
1798
|
+
* @returns The transaction result.
|
|
1799
|
+
*/
|
|
1800
|
+
commit() {
|
|
1801
|
+
const idMapping = /* @__PURE__ */ new Map();
|
|
1802
|
+
const finalNodes = [];
|
|
1803
|
+
for (const oldId of this.dirtyIds) {
|
|
1804
|
+
if (this.createdInTx.has(oldId)) {
|
|
1805
|
+
idMapping.set(oldId, oldId);
|
|
1806
|
+
} else {
|
|
1807
|
+
const node = this.txNodes.get(oldId);
|
|
1808
|
+
if (node) {
|
|
1809
|
+
const newId = this.realBaseStrategy.id(node.leaf);
|
|
1810
|
+
idMapping.set(oldId, newId);
|
|
1811
|
+
}
|
|
1812
|
+
}
|
|
1813
|
+
}
|
|
1814
|
+
const newCreatedIds = [];
|
|
1815
|
+
for (const oldId of this.dirtyIds) {
|
|
1816
|
+
const node = this.txNodes.get(oldId);
|
|
1817
|
+
if (!node) continue;
|
|
1818
|
+
const newId = idMapping.get(oldId);
|
|
1819
|
+
node.id = newId;
|
|
1820
|
+
if (node.parent && idMapping.has(node.parent)) {
|
|
1821
|
+
node.parent = idMapping.get(node.parent);
|
|
1822
|
+
}
|
|
1823
|
+
if (!node.leaf) {
|
|
1824
|
+
const internal = node;
|
|
1825
|
+
for (let i = 0; i < internal.keys.length; i++) {
|
|
1826
|
+
const childId = internal.keys[i];
|
|
1827
|
+
if (idMapping.has(childId)) {
|
|
1828
|
+
internal.keys[i] = idMapping.get(childId);
|
|
1829
|
+
}
|
|
1830
|
+
}
|
|
1831
|
+
}
|
|
1832
|
+
if (node.leaf) {
|
|
1833
|
+
const leaf = node;
|
|
1834
|
+
if (leaf.next && idMapping.has(leaf.next)) {
|
|
1835
|
+
leaf.next = idMapping.get(leaf.next);
|
|
1836
|
+
}
|
|
1837
|
+
if (leaf.prev && idMapping.has(leaf.prev)) {
|
|
1838
|
+
leaf.prev = idMapping.get(leaf.prev);
|
|
1839
|
+
}
|
|
1840
|
+
}
|
|
1841
|
+
finalNodes.push(node);
|
|
1842
|
+
newCreatedIds.push(newId);
|
|
1843
|
+
}
|
|
1844
|
+
let newRootId = this.rootId;
|
|
1845
|
+
if (idMapping.has(this.rootId)) {
|
|
1846
|
+
newRootId = idMapping.get(this.rootId);
|
|
1847
|
+
}
|
|
1848
|
+
for (const node of finalNodes) {
|
|
1849
|
+
this.realBaseStrategy.write(node.id, node);
|
|
1850
|
+
}
|
|
1851
|
+
const success = this.realBaseStrategy.compareAndSwapHead(this.initialRootId, newRootId);
|
|
1852
|
+
if (success) {
|
|
1853
|
+
const distinctObsolete = /* @__PURE__ */ new Set();
|
|
1854
|
+
for (const oldId of this.dirtyIds) {
|
|
1855
|
+
if (!this.createdInTx.has(oldId) && this.txNodes.has(oldId)) {
|
|
1856
|
+
distinctObsolete.add(oldId);
|
|
1857
|
+
}
|
|
1858
|
+
}
|
|
1859
|
+
return {
|
|
1860
|
+
success: true,
|
|
1861
|
+
createdIds: newCreatedIds,
|
|
1862
|
+
obsoleteIds: Array.from(distinctObsolete)
|
|
1863
|
+
};
|
|
1864
|
+
} else {
|
|
1865
|
+
this.rollback();
|
|
1866
|
+
return {
|
|
1867
|
+
success: false,
|
|
1868
|
+
createdIds: newCreatedIds,
|
|
1869
|
+
obsoleteIds: []
|
|
1870
|
+
};
|
|
1871
|
+
}
|
|
1643
1872
|
}
|
|
1644
1873
|
/**
|
|
1645
|
-
*
|
|
1646
|
-
*
|
|
1647
|
-
* @
|
|
1874
|
+
* Rolls back the transaction by clearing all buffered changes.
|
|
1875
|
+
* If cleanup is `true`, it also clears the transaction nodes.
|
|
1876
|
+
* @param cleanup Whether to clear the transaction nodes.
|
|
1877
|
+
* @returns The IDs of nodes that were created in this transaction.
|
|
1648
1878
|
*/
|
|
1649
|
-
|
|
1650
|
-
const
|
|
1651
|
-
|
|
1879
|
+
rollback(cleanup = true) {
|
|
1880
|
+
const createdIds = Array.from(this.createdInTx);
|
|
1881
|
+
this.txNodes.clear();
|
|
1882
|
+
this.dirtyIds.clear();
|
|
1883
|
+
this.createdInTx.clear();
|
|
1884
|
+
if (cleanup) {
|
|
1885
|
+
for (const id of createdIds) {
|
|
1886
|
+
this.realBaseStrategy.delete(id);
|
|
1887
|
+
}
|
|
1888
|
+
}
|
|
1889
|
+
return createdIds;
|
|
1652
1890
|
}
|
|
1653
|
-
|
|
1654
|
-
|
|
1655
|
-
* @param range The range to check for write lock availability.
|
|
1656
|
-
* @returns `true` if a write lock can be acquired, `false` otherwise.
|
|
1657
|
-
*/
|
|
1658
|
-
canWrite(range) {
|
|
1659
|
-
const reading = this.isReading(range);
|
|
1660
|
-
const writing = this.isWriting(range);
|
|
1661
|
-
return !reading && !writing;
|
|
1891
|
+
// Override to do nothing, as transaction handles its own commits
|
|
1892
|
+
commitHeadBuffer() {
|
|
1662
1893
|
}
|
|
1663
|
-
|
|
1664
|
-
* Internal implementation of the read lock. Handles both overloads.
|
|
1665
|
-
* @template T - The return type of the task.
|
|
1666
|
-
* @param arg0 - Either a range or a task callback.
|
|
1667
|
-
* If a range is provided, the task is the second argument.
|
|
1668
|
-
* @param arg1 - The task to execute, required if a range is provided.
|
|
1669
|
-
* @param arg2 - The timeout for acquiring the lock.
|
|
1670
|
-
* If the lock cannot be acquired within this period, an error will be thrown.
|
|
1671
|
-
* If this value is not provided, no timeout will be set.
|
|
1672
|
-
* @returns A promise resolving to the result of the task execution.
|
|
1673
|
-
*/
|
|
1674
|
-
readLock(arg0, arg1, arg2) {
|
|
1675
|
-
const [range, task, timeout] = this._handleOverload(
|
|
1676
|
-
[arg0, arg1, arg2],
|
|
1677
|
-
{
|
|
1678
|
-
rangeTask: (range2, task2) => [range2, task2, -1],
|
|
1679
|
-
rangeTaskTimeout: (range2, task2, timeout2) => [range2, task2, timeout2],
|
|
1680
|
-
task: (task2) => [[-Infinity, Infinity], task2, -1],
|
|
1681
|
-
taskTimeout: (task2, timeout2) => [[-Infinity, Infinity], task2, timeout2]
|
|
1682
|
-
},
|
|
1683
|
-
{
|
|
1684
|
-
task: [Function],
|
|
1685
|
-
taskTimeout: [Function, Number],
|
|
1686
|
-
rangeTask: [Array, Function],
|
|
1687
|
-
rangeTaskTimeout: [Array, Function, Number]
|
|
1688
|
-
}
|
|
1689
|
-
);
|
|
1690
|
-
return this._lock(
|
|
1691
|
-
this.readQueue,
|
|
1692
|
-
range,
|
|
1693
|
-
timeout,
|
|
1694
|
-
task,
|
|
1695
|
-
() => !this.rangeOverlapping(this.writings, range)
|
|
1696
|
-
);
|
|
1894
|
+
commitNodeCreateBuffer() {
|
|
1697
1895
|
}
|
|
1698
|
-
|
|
1699
|
-
* Internal implementation of the write lock. Handles both overloads.
|
|
1700
|
-
* @template T - The return type of the task.
|
|
1701
|
-
* @param arg0 - Either a range or a task callback.
|
|
1702
|
-
* If a range is provided, the task is the second argument.
|
|
1703
|
-
* @param arg1 - The task to execute, required if a range is provided.
|
|
1704
|
-
* @param arg2 - The timeout for acquiring the lock.
|
|
1705
|
-
* If the lock cannot be acquired within this period, an error will be thrown.
|
|
1706
|
-
* If this value is not provided, no timeout will be set.
|
|
1707
|
-
* @returns A promise resolving to the result of the task execution.
|
|
1708
|
-
*/
|
|
1709
|
-
writeLock(arg0, arg1, arg2) {
|
|
1710
|
-
const [range, task, timeout] = this._handleOverload(
|
|
1711
|
-
[arg0, arg1, arg2],
|
|
1712
|
-
{
|
|
1713
|
-
rangeTask: (range2, task2) => [range2, task2, -1],
|
|
1714
|
-
rangeTaskTimeout: (range2, task2, timeout2) => [range2, task2, timeout2],
|
|
1715
|
-
task: (task2) => [[-Infinity, Infinity], task2, -1],
|
|
1716
|
-
taskTimeout: (task2, timeout2) => [[-Infinity, Infinity], task2, timeout2]
|
|
1717
|
-
},
|
|
1718
|
-
{
|
|
1719
|
-
task: [Function],
|
|
1720
|
-
taskTimeout: [Function, Number],
|
|
1721
|
-
rangeTask: [Array, Function],
|
|
1722
|
-
rangeTaskTimeout: [Array, Function, Number]
|
|
1723
|
-
}
|
|
1724
|
-
);
|
|
1725
|
-
return this._lock(
|
|
1726
|
-
this.writeQueue,
|
|
1727
|
-
range,
|
|
1728
|
-
timeout,
|
|
1729
|
-
task,
|
|
1730
|
-
() => {
|
|
1731
|
-
return !this.rangeOverlapping(this.writings, range) && !this.rangeOverlapping(this.readings, range);
|
|
1732
|
-
}
|
|
1733
|
-
);
|
|
1896
|
+
commitNodeUpdateBuffer() {
|
|
1734
1897
|
}
|
|
1735
|
-
|
|
1736
|
-
|
|
1737
|
-
|
|
1738
|
-
|
|
1739
|
-
|
|
1740
|
-
|
|
1898
|
+
commitNodeDeleteBuffer() {
|
|
1899
|
+
}
|
|
1900
|
+
};
|
|
1901
|
+
var BPTreeSync = class extends BPTreeSyncBase {
|
|
1902
|
+
constructor(strategy, comparator, option) {
|
|
1903
|
+
super(strategy, comparator, option);
|
|
1904
|
+
this.init();
|
|
1741
1905
|
}
|
|
1742
1906
|
/**
|
|
1743
|
-
*
|
|
1744
|
-
* @
|
|
1907
|
+
* Creates a new synchronous transaction.
|
|
1908
|
+
* @returns A new BPTreeSyncTransaction.
|
|
1745
1909
|
*/
|
|
1746
|
-
|
|
1747
|
-
|
|
1910
|
+
createTransaction() {
|
|
1911
|
+
const tx = new BPTreeSyncTransaction(this);
|
|
1912
|
+
tx.initTransaction();
|
|
1913
|
+
return tx;
|
|
1914
|
+
}
|
|
1915
|
+
insert(key, value) {
|
|
1916
|
+
const tx = this.createTransaction();
|
|
1917
|
+
tx.insert(key, value);
|
|
1918
|
+
const { success } = tx.commit();
|
|
1919
|
+
this.init();
|
|
1920
|
+
if (!success) {
|
|
1921
|
+
throw new Error("Transaction failed: Commit failed due to conflict");
|
|
1922
|
+
}
|
|
1923
|
+
}
|
|
1924
|
+
delete(key, value) {
|
|
1925
|
+
const tx = this.createTransaction();
|
|
1926
|
+
tx.delete(key, value);
|
|
1927
|
+
const { success } = tx.commit();
|
|
1928
|
+
this.init();
|
|
1929
|
+
if (!success) {
|
|
1930
|
+
throw new Error("Transaction failed: Commit failed due to conflict");
|
|
1931
|
+
}
|
|
1748
1932
|
}
|
|
1749
1933
|
};
|
|
1750
|
-
var
|
|
1751
|
-
lock;
|
|
1934
|
+
var BPTreeAsyncBase = class extends BPTree {
|
|
1752
1935
|
constructor(strategy, comparator, option) {
|
|
1753
1936
|
super(strategy, comparator, option);
|
|
1754
1937
|
this.nodes = this._createCachedNode();
|
|
1755
|
-
this.lock = new Ryoiki();
|
|
1756
1938
|
}
|
|
1757
1939
|
_createCachedNode() {
|
|
1758
1940
|
return new CacheEntanglementAsync(async (key) => {
|
|
@@ -1761,24 +1943,6 @@ var BPTreeAsync = class extends BPTree {
|
|
|
1761
1943
|
capacity: this.option.capacity ?? 1e3
|
|
1762
1944
|
});
|
|
1763
1945
|
}
|
|
1764
|
-
async readLock(callback) {
|
|
1765
|
-
let lockId;
|
|
1766
|
-
return await this.lock.readLock(async (_lockId) => {
|
|
1767
|
-
lockId = _lockId;
|
|
1768
|
-
return await callback();
|
|
1769
|
-
}).finally(() => {
|
|
1770
|
-
this.lock.readUnlock(lockId);
|
|
1771
|
-
});
|
|
1772
|
-
}
|
|
1773
|
-
async writeLock(callback) {
|
|
1774
|
-
let lockId;
|
|
1775
|
-
return await this.lock.writeLock(async (_lockId) => {
|
|
1776
|
-
lockId = _lockId;
|
|
1777
|
-
return await callback();
|
|
1778
|
-
}).finally(() => {
|
|
1779
|
-
this.lock.writeUnlock(lockId);
|
|
1780
|
-
});
|
|
1781
|
-
}
|
|
1782
1946
|
async *getPairsGenerator(value, startNode, endNode, comparator, direction, earlyTerminate) {
|
|
1783
1947
|
let node = startNode;
|
|
1784
1948
|
let done = false;
|
|
@@ -1843,7 +2007,7 @@ var BPTreeAsync = class extends BPTree {
|
|
|
1843
2007
|
}
|
|
1844
2008
|
return id;
|
|
1845
2009
|
}
|
|
1846
|
-
async _createNode(isLeaf, keys, values, leaf =
|
|
2010
|
+
async _createNode(isLeaf, keys, values, leaf = isLeaf, parent = null, next = null, prev = null) {
|
|
1847
2011
|
const id = await this._createNodeId(isLeaf);
|
|
1848
2012
|
const node = {
|
|
1849
2013
|
id,
|
|
@@ -1854,38 +2018,37 @@ var BPTreeAsync = class extends BPTree {
|
|
|
1854
2018
|
next,
|
|
1855
2019
|
prev
|
|
1856
2020
|
};
|
|
1857
|
-
this.
|
|
2021
|
+
await this.bufferForNodeCreate(node);
|
|
1858
2022
|
return node;
|
|
1859
2023
|
}
|
|
1860
2024
|
async _deleteEntry(node, key, value) {
|
|
1861
2025
|
if (!node.leaf) {
|
|
2026
|
+
let keyIndex = -1;
|
|
1862
2027
|
for (let i = 0, len = node.keys.length; i < len; i++) {
|
|
1863
|
-
|
|
1864
|
-
|
|
1865
|
-
node.keys.splice(i, 1);
|
|
1866
|
-
this.bufferForNodeUpdate(node);
|
|
2028
|
+
if (node.keys[i] === key) {
|
|
2029
|
+
keyIndex = i;
|
|
1867
2030
|
break;
|
|
1868
2031
|
}
|
|
1869
2032
|
}
|
|
1870
|
-
|
|
1871
|
-
|
|
1872
|
-
|
|
1873
|
-
|
|
1874
|
-
|
|
1875
|
-
break;
|
|
1876
|
-
}
|
|
2033
|
+
if (keyIndex !== -1) {
|
|
2034
|
+
node.keys.splice(keyIndex, 1);
|
|
2035
|
+
const valueIndex = keyIndex > 0 ? keyIndex - 1 : 0;
|
|
2036
|
+
node.values.splice(valueIndex, 1);
|
|
2037
|
+
await this.bufferForNodeUpdate(node);
|
|
1877
2038
|
}
|
|
1878
2039
|
}
|
|
1879
|
-
if (this.
|
|
2040
|
+
if (this.rootId === node.id && node.keys.length === 1 && !node.leaf) {
|
|
1880
2041
|
const keys = node.keys;
|
|
1881
|
-
this.bufferForNodeDelete(
|
|
1882
|
-
|
|
1883
|
-
this.
|
|
1884
|
-
|
|
1885
|
-
this.
|
|
2042
|
+
await this.bufferForNodeDelete(node);
|
|
2043
|
+
const newRoot = await this.getNode(keys[0]);
|
|
2044
|
+
this.rootId = newRoot.id;
|
|
2045
|
+
newRoot.parent = null;
|
|
2046
|
+
this.strategy.head.root = this.rootId;
|
|
2047
|
+
await this.bufferForNodeUpdate(newRoot);
|
|
1886
2048
|
return;
|
|
1887
|
-
} else if (this.
|
|
1888
|
-
this.
|
|
2049
|
+
} else if (this.rootId === node.id) {
|
|
2050
|
+
const root = await this.getNode(this.rootId);
|
|
2051
|
+
await this.bufferForNodeUpdate(root);
|
|
1889
2052
|
return;
|
|
1890
2053
|
} else if (node.keys.length < Math.ceil(this.order / 2) && !node.leaf || node.values.length < Math.ceil((this.order - 1) / 2) && node.leaf) {
|
|
1891
2054
|
if (node.parent === null) {
|
|
@@ -1943,33 +2106,24 @@ var BPTreeAsync = class extends BPTree {
|
|
|
1943
2106
|
pointer.values.push(guess);
|
|
1944
2107
|
} else {
|
|
1945
2108
|
pointer.next = node.next;
|
|
1946
|
-
pointer.prev = node.id;
|
|
1947
2109
|
if (pointer.next) {
|
|
1948
|
-
const n = await this.getNode(
|
|
2110
|
+
const n = await this.getNode(pointer.next);
|
|
1949
2111
|
n.prev = pointer.id;
|
|
1950
|
-
this.bufferForNodeUpdate(n);
|
|
1951
|
-
}
|
|
1952
|
-
if (pointer.prev) {
|
|
1953
|
-
const n = await this.getNode(node.id);
|
|
1954
|
-
n.next = pointer.id;
|
|
1955
|
-
this.bufferForNodeUpdate(n);
|
|
1956
|
-
}
|
|
1957
|
-
if (isPredecessor) {
|
|
1958
|
-
pointer.prev = null;
|
|
2112
|
+
await this.bufferForNodeUpdate(n);
|
|
1959
2113
|
}
|
|
1960
2114
|
}
|
|
1961
2115
|
pointer.values.push(...node.values);
|
|
1962
2116
|
if (!pointer.leaf) {
|
|
1963
2117
|
const keys = pointer.keys;
|
|
1964
2118
|
for (const key2 of keys) {
|
|
1965
|
-
const
|
|
1966
|
-
|
|
1967
|
-
this.bufferForNodeUpdate(
|
|
2119
|
+
const n = await this.getNode(key2);
|
|
2120
|
+
n.parent = pointer.id;
|
|
2121
|
+
await this.bufferForNodeUpdate(n);
|
|
1968
2122
|
}
|
|
1969
2123
|
}
|
|
1970
2124
|
await this._deleteEntry(await this.getNode(node.parent), node.id, guess);
|
|
1971
|
-
this.bufferForNodeUpdate(pointer);
|
|
1972
|
-
this.bufferForNodeDelete(node);
|
|
2125
|
+
await this.bufferForNodeUpdate(pointer);
|
|
2126
|
+
await this.bufferForNodeDelete(node);
|
|
1973
2127
|
} else {
|
|
1974
2128
|
if (isPredecessor) {
|
|
1975
2129
|
let pointerPm;
|
|
@@ -1980,13 +2134,10 @@ var BPTreeAsync = class extends BPTree {
|
|
|
1980
2134
|
node.keys = [pointerPm, ...node.keys];
|
|
1981
2135
|
node.values = [guess, ...node.values];
|
|
1982
2136
|
parentNode = await this.getNode(node.parent);
|
|
1983
|
-
|
|
1984
|
-
|
|
1985
|
-
|
|
1986
|
-
|
|
1987
|
-
this.bufferForNodeUpdate(parentNode);
|
|
1988
|
-
break;
|
|
1989
|
-
}
|
|
2137
|
+
const nodeIndex = parentNode.keys.indexOf(node.id);
|
|
2138
|
+
if (nodeIndex > 0) {
|
|
2139
|
+
parentNode.values[nodeIndex - 1] = pointerKm;
|
|
2140
|
+
await this.bufferForNodeUpdate(parentNode);
|
|
1990
2141
|
}
|
|
1991
2142
|
} else {
|
|
1992
2143
|
pointerPm = pointer.keys.splice(-1)[0];
|
|
@@ -1994,17 +2145,14 @@ var BPTreeAsync = class extends BPTree {
|
|
|
1994
2145
|
node.keys = [pointerPm, ...node.keys];
|
|
1995
2146
|
node.values = [pointerKm, ...node.values];
|
|
1996
2147
|
parentNode = await this.getNode(node.parent);
|
|
1997
|
-
|
|
1998
|
-
|
|
1999
|
-
|
|
2000
|
-
|
|
2001
|
-
this.bufferForNodeUpdate(parentNode);
|
|
2002
|
-
break;
|
|
2003
|
-
}
|
|
2148
|
+
const nodeIndex = parentNode.keys.indexOf(node.id);
|
|
2149
|
+
if (nodeIndex > 0) {
|
|
2150
|
+
parentNode.values[nodeIndex - 1] = pointerKm;
|
|
2151
|
+
await this.bufferForNodeUpdate(parentNode);
|
|
2004
2152
|
}
|
|
2005
2153
|
}
|
|
2006
|
-
this.bufferForNodeUpdate(node);
|
|
2007
|
-
this.bufferForNodeUpdate(pointer);
|
|
2154
|
+
await this.bufferForNodeUpdate(node);
|
|
2155
|
+
await this.bufferForNodeUpdate(pointer);
|
|
2008
2156
|
} else {
|
|
2009
2157
|
let pointerP0;
|
|
2010
2158
|
let pointerK0;
|
|
@@ -2014,13 +2162,10 @@ var BPTreeAsync = class extends BPTree {
|
|
|
2014
2162
|
node.keys = [...node.keys, pointerP0];
|
|
2015
2163
|
node.values = [...node.values, guess];
|
|
2016
2164
|
parentNode = await this.getNode(node.parent);
|
|
2017
|
-
|
|
2018
|
-
|
|
2019
|
-
|
|
2020
|
-
|
|
2021
|
-
this.bufferForNodeUpdate(parentNode);
|
|
2022
|
-
break;
|
|
2023
|
-
}
|
|
2165
|
+
const pointerIndex = parentNode.keys.indexOf(pointer.id);
|
|
2166
|
+
if (pointerIndex > 0) {
|
|
2167
|
+
parentNode.values[pointerIndex - 1] = pointerK0;
|
|
2168
|
+
await this.bufferForNodeUpdate(parentNode);
|
|
2024
2169
|
}
|
|
2025
2170
|
} else {
|
|
2026
2171
|
pointerP0 = pointer.keys.splice(0, 1)[0];
|
|
@@ -2028,87 +2173,85 @@ var BPTreeAsync = class extends BPTree {
|
|
|
2028
2173
|
node.keys = [...node.keys, pointerP0];
|
|
2029
2174
|
node.values = [...node.values, pointerK0];
|
|
2030
2175
|
parentNode = await this.getNode(node.parent);
|
|
2031
|
-
|
|
2032
|
-
|
|
2033
|
-
|
|
2034
|
-
|
|
2035
|
-
this.bufferForNodeUpdate(parentNode);
|
|
2036
|
-
break;
|
|
2037
|
-
}
|
|
2176
|
+
const pointerIndex = parentNode.keys.indexOf(pointer.id);
|
|
2177
|
+
if (pointerIndex > 0) {
|
|
2178
|
+
parentNode.values[pointerIndex - 1] = pointer.values[0];
|
|
2179
|
+
await this.bufferForNodeUpdate(parentNode);
|
|
2038
2180
|
}
|
|
2039
2181
|
}
|
|
2040
|
-
this.bufferForNodeUpdate(node);
|
|
2041
|
-
this.bufferForNodeUpdate(pointer);
|
|
2182
|
+
await this.bufferForNodeUpdate(node);
|
|
2183
|
+
await this.bufferForNodeUpdate(pointer);
|
|
2042
2184
|
}
|
|
2043
2185
|
if (!pointer.leaf) {
|
|
2044
|
-
|
|
2186
|
+
const keys = pointer.keys;
|
|
2187
|
+
for (const key2 of keys) {
|
|
2045
2188
|
const n = await this.getNode(key2);
|
|
2046
2189
|
n.parent = pointer.id;
|
|
2047
|
-
this.bufferForNodeUpdate(n);
|
|
2190
|
+
await this.bufferForNodeUpdate(n);
|
|
2048
2191
|
}
|
|
2049
2192
|
}
|
|
2050
2193
|
if (!node.leaf) {
|
|
2051
|
-
|
|
2194
|
+
const keys = node.keys;
|
|
2195
|
+
for (const key2 of keys) {
|
|
2052
2196
|
const n = await this.getNode(key2);
|
|
2053
2197
|
n.parent = node.id;
|
|
2054
|
-
this.bufferForNodeUpdate(n);
|
|
2198
|
+
await this.bufferForNodeUpdate(n);
|
|
2055
2199
|
}
|
|
2056
2200
|
}
|
|
2057
2201
|
if (!parentNode.leaf) {
|
|
2058
|
-
|
|
2202
|
+
const keys = parentNode.keys;
|
|
2203
|
+
for (const key2 of keys) {
|
|
2059
2204
|
const n = await this.getNode(key2);
|
|
2060
2205
|
n.parent = parentNode.id;
|
|
2061
|
-
this.bufferForNodeUpdate(n);
|
|
2206
|
+
await this.bufferForNodeUpdate(n);
|
|
2062
2207
|
}
|
|
2063
2208
|
}
|
|
2064
2209
|
}
|
|
2210
|
+
} else {
|
|
2211
|
+
await this.bufferForNodeUpdate(node);
|
|
2065
2212
|
}
|
|
2066
2213
|
}
|
|
2067
2214
|
async _insertInParent(node, value, pointer) {
|
|
2068
|
-
if (this.
|
|
2215
|
+
if (this.rootId === node.id) {
|
|
2069
2216
|
const root = await this._createNode(false, [node.id, pointer.id], [value]);
|
|
2070
|
-
this.
|
|
2217
|
+
this.rootId = root.id;
|
|
2071
2218
|
this.strategy.head.root = root.id;
|
|
2072
2219
|
node.parent = root.id;
|
|
2073
2220
|
pointer.parent = root.id;
|
|
2074
2221
|
if (pointer.leaf) {
|
|
2075
|
-
|
|
2076
|
-
|
|
2222
|
+
const nNode = node;
|
|
2223
|
+
nNode.next = pointer.id;
|
|
2224
|
+
const nPointer = pointer;
|
|
2225
|
+
nPointer.prev = node.id;
|
|
2077
2226
|
}
|
|
2078
|
-
this.bufferForNodeUpdate(node);
|
|
2079
|
-
this.bufferForNodeUpdate(pointer);
|
|
2227
|
+
await this.bufferForNodeUpdate(node);
|
|
2228
|
+
await this.bufferForNodeUpdate(pointer);
|
|
2080
2229
|
return;
|
|
2081
2230
|
}
|
|
2082
2231
|
const parentNode = await this.getNode(node.parent);
|
|
2083
|
-
|
|
2084
|
-
|
|
2085
|
-
|
|
2086
|
-
insertIndex = i + 1;
|
|
2087
|
-
} else {
|
|
2088
|
-
break;
|
|
2089
|
-
}
|
|
2232
|
+
const nodeIndex = parentNode.keys.indexOf(node.id);
|
|
2233
|
+
if (nodeIndex === -1) {
|
|
2234
|
+
throw new Error(`Node ${node.id} not found in parent ${parentNode.id}`);
|
|
2090
2235
|
}
|
|
2236
|
+
const insertIndex = nodeIndex;
|
|
2091
2237
|
parentNode.values.splice(insertIndex, 0, value);
|
|
2092
2238
|
parentNode.keys.splice(insertIndex + 1, 0, pointer.id);
|
|
2093
2239
|
pointer.parent = parentNode.id;
|
|
2094
2240
|
if (pointer.leaf) {
|
|
2095
|
-
const
|
|
2096
|
-
const
|
|
2097
|
-
|
|
2098
|
-
|
|
2099
|
-
|
|
2100
|
-
|
|
2101
|
-
|
|
2102
|
-
this.
|
|
2103
|
-
|
|
2104
|
-
|
|
2105
|
-
const rightSibling = await this.getNode(rightSiblingId);
|
|
2106
|
-
rightSibling.prev = pointer.id;
|
|
2107
|
-
this.bufferForNodeUpdate(rightSibling);
|
|
2241
|
+
const leftSibling = node;
|
|
2242
|
+
const oldNextId = leftSibling.next;
|
|
2243
|
+
pointer.prev = leftSibling.id;
|
|
2244
|
+
pointer.next = oldNextId;
|
|
2245
|
+
leftSibling.next = pointer.id;
|
|
2246
|
+
await this.bufferForNodeUpdate(leftSibling);
|
|
2247
|
+
if (oldNextId) {
|
|
2248
|
+
const oldNext = await this.getNode(oldNextId);
|
|
2249
|
+
oldNext.prev = pointer.id;
|
|
2250
|
+
await this.bufferForNodeUpdate(oldNext);
|
|
2108
2251
|
}
|
|
2109
2252
|
}
|
|
2110
|
-
this.bufferForNodeUpdate(parentNode);
|
|
2111
|
-
this.bufferForNodeUpdate(pointer);
|
|
2253
|
+
await this.bufferForNodeUpdate(parentNode);
|
|
2254
|
+
await this.bufferForNodeUpdate(pointer);
|
|
2112
2255
|
if (parentNode.keys.length > this.order) {
|
|
2113
2256
|
const parentPointer = await this._createNode(false, [], []);
|
|
2114
2257
|
parentPointer.parent = parentNode.parent;
|
|
@@ -2119,32 +2262,34 @@ var BPTreeAsync = class extends BPTree {
|
|
|
2119
2262
|
parentNode.values = parentNode.values.slice(0, mid);
|
|
2120
2263
|
parentNode.keys = parentNode.keys.slice(0, mid + 1);
|
|
2121
2264
|
for (const k of parentNode.keys) {
|
|
2122
|
-
const
|
|
2123
|
-
|
|
2124
|
-
this.bufferForNodeUpdate(
|
|
2265
|
+
const n = await this.getNode(k);
|
|
2266
|
+
n.parent = parentNode.id;
|
|
2267
|
+
await this.bufferForNodeUpdate(n);
|
|
2125
2268
|
}
|
|
2126
2269
|
for (const k of parentPointer.keys) {
|
|
2127
|
-
const
|
|
2128
|
-
|
|
2129
|
-
this.bufferForNodeUpdate(
|
|
2270
|
+
const n = await this.getNode(k);
|
|
2271
|
+
n.parent = parentPointer.id;
|
|
2272
|
+
await this.bufferForNodeUpdate(n);
|
|
2130
2273
|
}
|
|
2131
2274
|
await this._insertInParent(parentNode, midValue, parentPointer);
|
|
2132
|
-
this.bufferForNodeUpdate(parentNode);
|
|
2275
|
+
await this.bufferForNodeUpdate(parentNode);
|
|
2133
2276
|
}
|
|
2134
2277
|
}
|
|
2135
2278
|
async init() {
|
|
2279
|
+
this.clear();
|
|
2136
2280
|
const head = await this.strategy.readHead();
|
|
2137
2281
|
if (head === null) {
|
|
2138
2282
|
this.order = this.strategy.order;
|
|
2139
|
-
|
|
2140
|
-
this.
|
|
2283
|
+
const root = await this._createNode(true, [], [], true);
|
|
2284
|
+
this.rootId = root.id;
|
|
2285
|
+
this.strategy.head.root = this.rootId;
|
|
2141
2286
|
await this.commitHeadBuffer();
|
|
2142
2287
|
await this.commitNodeCreateBuffer();
|
|
2143
2288
|
} else {
|
|
2144
2289
|
const { root, order } = head;
|
|
2145
2290
|
this.strategy.head = head;
|
|
2146
2291
|
this.order = order;
|
|
2147
|
-
this.
|
|
2292
|
+
this.rootId = root;
|
|
2148
2293
|
}
|
|
2149
2294
|
if (this.order < 3) {
|
|
2150
2295
|
throw new Error(`The 'order' parameter must be greater than 2. but got a '${this.order}'.`);
|
|
@@ -2161,43 +2306,73 @@ var BPTreeAsync = class extends BPTree {
|
|
|
2161
2306
|
return cache.raw;
|
|
2162
2307
|
}
|
|
2163
2308
|
async insertableNode(value) {
|
|
2164
|
-
let node = await this.getNode(this.
|
|
2309
|
+
let node = await this.getNode(this.rootId);
|
|
2310
|
+
if (node.parent !== null) {
|
|
2311
|
+
node.parent = null;
|
|
2312
|
+
await this.bufferForNodeUpdate(node);
|
|
2313
|
+
}
|
|
2165
2314
|
while (!node.leaf) {
|
|
2315
|
+
const parentId = node.id;
|
|
2166
2316
|
for (let i = 0, len = node.values.length; i < len; i++) {
|
|
2167
2317
|
const nValue = node.values[i];
|
|
2168
2318
|
const k = node.keys;
|
|
2169
2319
|
if (this.comparator.isSame(value, nValue)) {
|
|
2170
|
-
node = await this.getNode(
|
|
2320
|
+
node = await this.getNode(node.keys[i + 1]);
|
|
2321
|
+
if (node.parent !== parentId) {
|
|
2322
|
+
node.parent = parentId;
|
|
2323
|
+
await this.bufferForNodeUpdate(node);
|
|
2324
|
+
}
|
|
2171
2325
|
break;
|
|
2172
2326
|
} else if (this.comparator.isLower(value, nValue)) {
|
|
2173
|
-
node = await this.getNode(
|
|
2327
|
+
node = await this.getNode(node.keys[i]);
|
|
2328
|
+
if (node.parent !== parentId) {
|
|
2329
|
+
node.parent = parentId;
|
|
2330
|
+
await this.bufferForNodeUpdate(node);
|
|
2331
|
+
}
|
|
2174
2332
|
break;
|
|
2175
2333
|
} else if (i + 1 === node.values.length) {
|
|
2176
|
-
node = await this.getNode(
|
|
2334
|
+
node = await this.getNode(node.keys[i + 1]);
|
|
2335
|
+
if (node.parent !== parentId) {
|
|
2336
|
+
node.parent = parentId;
|
|
2337
|
+
await this.bufferForNodeUpdate(node);
|
|
2338
|
+
}
|
|
2177
2339
|
break;
|
|
2178
2340
|
}
|
|
2179
2341
|
}
|
|
2180
2342
|
}
|
|
2181
2343
|
return node;
|
|
2182
2344
|
}
|
|
2183
|
-
/**
|
|
2184
|
-
* Find the insertable node using primaryAsc comparison.
|
|
2185
|
-
* This allows finding nodes by primary value only, ignoring unique identifiers.
|
|
2186
|
-
*/
|
|
2187
2345
|
async insertableNodeByPrimary(value) {
|
|
2188
|
-
let node = await this.getNode(this.
|
|
2346
|
+
let node = await this.getNode(this.rootId);
|
|
2347
|
+
if (node.parent !== null) {
|
|
2348
|
+
node.parent = null;
|
|
2349
|
+
await this.bufferForNodeUpdate(node);
|
|
2350
|
+
}
|
|
2189
2351
|
while (!node.leaf) {
|
|
2352
|
+
const parentId = node.id;
|
|
2190
2353
|
for (let i = 0, len = node.values.length; i < len; i++) {
|
|
2191
2354
|
const nValue = node.values[i];
|
|
2192
2355
|
const k = node.keys;
|
|
2193
2356
|
if (this.comparator.isPrimarySame(value, nValue)) {
|
|
2194
|
-
node = await this.getNode(
|
|
2357
|
+
node = await this.getNode(node.keys[i]);
|
|
2358
|
+
if (node.parent !== parentId) {
|
|
2359
|
+
node.parent = parentId;
|
|
2360
|
+
await this.bufferForNodeUpdate(node);
|
|
2361
|
+
}
|
|
2195
2362
|
break;
|
|
2196
2363
|
} else if (this.comparator.isPrimaryLower(value, nValue)) {
|
|
2197
|
-
node = await this.getNode(
|
|
2364
|
+
node = await this.getNode(node.keys[i]);
|
|
2365
|
+
if (node.parent !== parentId) {
|
|
2366
|
+
node.parent = parentId;
|
|
2367
|
+
await this.bufferForNodeUpdate(node);
|
|
2368
|
+
}
|
|
2198
2369
|
break;
|
|
2199
2370
|
} else if (i + 1 === node.values.length) {
|
|
2200
|
-
node = await this.getNode(
|
|
2371
|
+
node = await this.getNode(node.keys[i + 1]);
|
|
2372
|
+
if (node.parent !== parentId) {
|
|
2373
|
+
node.parent = parentId;
|
|
2374
|
+
await this.bufferForNodeUpdate(node);
|
|
2375
|
+
}
|
|
2201
2376
|
break;
|
|
2202
2377
|
}
|
|
2203
2378
|
}
|
|
@@ -2205,17 +2380,30 @@ var BPTreeAsync = class extends BPTree {
|
|
|
2205
2380
|
return node;
|
|
2206
2381
|
}
|
|
2207
2382
|
async insertableRightestNodeByPrimary(value) {
|
|
2208
|
-
let node = await this.getNode(this.
|
|
2383
|
+
let node = await this.getNode(this.rootId);
|
|
2384
|
+
if (node.parent !== null) {
|
|
2385
|
+
node.parent = null;
|
|
2386
|
+
await this.bufferForNodeUpdate(node);
|
|
2387
|
+
}
|
|
2209
2388
|
while (!node.leaf) {
|
|
2389
|
+
const parentId = node.id;
|
|
2210
2390
|
for (let i = 0, len = node.values.length; i < len; i++) {
|
|
2211
2391
|
const nValue = node.values[i];
|
|
2212
2392
|
const k = node.keys;
|
|
2213
2393
|
if (this.comparator.isPrimaryLower(value, nValue)) {
|
|
2214
|
-
node = await this.getNode(
|
|
2394
|
+
node = await this.getNode(node.keys[i]);
|
|
2395
|
+
if (node.parent !== parentId) {
|
|
2396
|
+
node.parent = parentId;
|
|
2397
|
+
await this.bufferForNodeUpdate(node);
|
|
2398
|
+
}
|
|
2215
2399
|
break;
|
|
2216
2400
|
}
|
|
2217
2401
|
if (i + 1 === node.values.length) {
|
|
2218
|
-
node = await this.getNode(
|
|
2402
|
+
node = await this.getNode(node.keys[i + 1]);
|
|
2403
|
+
if (node.parent !== parentId) {
|
|
2404
|
+
node.parent = parentId;
|
|
2405
|
+
await this.bufferForNodeUpdate(node);
|
|
2406
|
+
}
|
|
2219
2407
|
break;
|
|
2220
2408
|
}
|
|
2221
2409
|
}
|
|
@@ -2249,27 +2437,75 @@ var BPTreeAsync = class extends BPTree {
|
|
|
2249
2437
|
return await this.getNode(guessNode);
|
|
2250
2438
|
}
|
|
2251
2439
|
async leftestNode() {
|
|
2252
|
-
let node = this.
|
|
2440
|
+
let node = await this.getNode(this.rootId);
|
|
2441
|
+
if (node.parent !== null) {
|
|
2442
|
+
node.parent = null;
|
|
2443
|
+
await this.bufferForNodeUpdate(node);
|
|
2444
|
+
}
|
|
2253
2445
|
while (!node.leaf) {
|
|
2446
|
+
const parentId = node.id;
|
|
2254
2447
|
const keys = node.keys;
|
|
2255
|
-
node = await this.getNode(keys[0]);
|
|
2448
|
+
node = await this.getNode(node.keys[0]);
|
|
2449
|
+
if (node.parent !== parentId) {
|
|
2450
|
+
node.parent = parentId;
|
|
2451
|
+
await this.bufferForNodeUpdate(node);
|
|
2452
|
+
}
|
|
2256
2453
|
}
|
|
2257
2454
|
return node;
|
|
2258
2455
|
}
|
|
2259
2456
|
async rightestNode() {
|
|
2260
|
-
let node = this.
|
|
2457
|
+
let node = await this.getNode(this.rootId);
|
|
2458
|
+
if (node.parent !== null) {
|
|
2459
|
+
node.parent = null;
|
|
2460
|
+
await this.bufferForNodeUpdate(node);
|
|
2461
|
+
}
|
|
2261
2462
|
while (!node.leaf) {
|
|
2463
|
+
const parentId = node.id;
|
|
2262
2464
|
const keys = node.keys;
|
|
2263
|
-
node = await this.getNode(keys[keys.length - 1]);
|
|
2465
|
+
node = await this.getNode(node.keys[node.keys.length - 1]);
|
|
2466
|
+
if (node.parent !== parentId) {
|
|
2467
|
+
node.parent = parentId;
|
|
2468
|
+
await this.bufferForNodeUpdate(node);
|
|
2469
|
+
}
|
|
2264
2470
|
}
|
|
2265
2471
|
return node;
|
|
2266
2472
|
}
|
|
2473
|
+
async exists(key, value) {
|
|
2474
|
+
const node = await this.insertableNode(value);
|
|
2475
|
+
for (let i = 0, len = node.values.length; i < len; i++) {
|
|
2476
|
+
if (this.comparator.isSame(value, node.values[i])) {
|
|
2477
|
+
const keys = node.keys[i];
|
|
2478
|
+
if (keys.includes(key)) {
|
|
2479
|
+
return true;
|
|
2480
|
+
}
|
|
2481
|
+
}
|
|
2482
|
+
}
|
|
2483
|
+
return false;
|
|
2484
|
+
}
|
|
2485
|
+
async forceUpdate(id) {
|
|
2486
|
+
if (id) {
|
|
2487
|
+
this.nodes.delete(id);
|
|
2488
|
+
await this.getNode(id);
|
|
2489
|
+
return 1;
|
|
2490
|
+
}
|
|
2491
|
+
const keys = Array.from(this.nodes.keys());
|
|
2492
|
+
for (const key of keys) {
|
|
2493
|
+
this.nodes.delete(key);
|
|
2494
|
+
}
|
|
2495
|
+
for (const key of keys) {
|
|
2496
|
+
await this.getNode(key);
|
|
2497
|
+
}
|
|
2498
|
+
return keys.length;
|
|
2499
|
+
}
|
|
2267
2500
|
async commitHeadBuffer() {
|
|
2268
2501
|
if (!this._strategyDirty) {
|
|
2269
2502
|
return;
|
|
2270
2503
|
}
|
|
2271
2504
|
this._strategyDirty = false;
|
|
2272
2505
|
await this.strategy.writeHead(this.strategy.head);
|
|
2506
|
+
if (this.strategy.head.root) {
|
|
2507
|
+
this.nodes.delete(this.strategy.head.root);
|
|
2508
|
+
}
|
|
2273
2509
|
}
|
|
2274
2510
|
async commitNodeCreateBuffer() {
|
|
2275
2511
|
for (const node of this._nodeCreateBuffer.values()) {
|
|
@@ -2280,34 +2516,26 @@ var BPTreeAsync = class extends BPTree {
|
|
|
2280
2516
|
async commitNodeUpdateBuffer() {
|
|
2281
2517
|
for (const node of this._nodeUpdateBuffer.values()) {
|
|
2282
2518
|
await this.strategy.write(node.id, node);
|
|
2519
|
+
this.nodes.delete(node.id);
|
|
2283
2520
|
}
|
|
2284
2521
|
this._nodeUpdateBuffer.clear();
|
|
2285
2522
|
}
|
|
2286
2523
|
async commitNodeDeleteBuffer() {
|
|
2287
2524
|
for (const node of this._nodeDeleteBuffer.values()) {
|
|
2288
2525
|
await this.strategy.delete(node.id);
|
|
2526
|
+
this.nodes.delete(node.id);
|
|
2289
2527
|
}
|
|
2290
2528
|
this._nodeDeleteBuffer.clear();
|
|
2291
2529
|
}
|
|
2292
|
-
/**
|
|
2293
|
-
* Retrieves the value associated with the given key (PK).
|
|
2294
|
-
* Note: This method performs a full scan of leaf nodes as the tree is ordered by Value, not Key.
|
|
2295
|
-
*
|
|
2296
|
-
* @param key The key to search for.
|
|
2297
|
-
* @returns The value associated with the key, or undefined if not found.
|
|
2298
|
-
*/
|
|
2299
2530
|
async get(key) {
|
|
2300
|
-
return this.readLock(async () => {
|
|
2531
|
+
return await this.readLock(async () => {
|
|
2301
2532
|
let node = await this.leftestNode();
|
|
2302
2533
|
while (true) {
|
|
2303
|
-
|
|
2304
|
-
const
|
|
2305
|
-
for (let
|
|
2306
|
-
|
|
2307
|
-
|
|
2308
|
-
if (keys[j] === key) {
|
|
2309
|
-
return node.values[i];
|
|
2310
|
-
}
|
|
2534
|
+
for (let i = 0, len = node.values.length; i < len; i++) {
|
|
2535
|
+
const keys = node.keys[i];
|
|
2536
|
+
for (let j = 0, kLen = keys.length; j < kLen; j++) {
|
|
2537
|
+
if (keys[j] === key) {
|
|
2538
|
+
return node.values[i];
|
|
2311
2539
|
}
|
|
2312
2540
|
}
|
|
2313
2541
|
}
|
|
@@ -2379,176 +2607,82 @@ var BPTreeAsync = class extends BPTree {
|
|
|
2379
2607
|
break;
|
|
2380
2608
|
}
|
|
2381
2609
|
}
|
|
2382
|
-
}
|
|
2383
|
-
}
|
|
2384
|
-
async keys(condition, filterValues) {
|
|
2385
|
-
return this.readLock(async () => {
|
|
2386
|
-
const set = /* @__PURE__ */ new Set();
|
|
2387
|
-
for await (const key of this.keysStream(condition, filterValues)) {
|
|
2388
|
-
set.add(key);
|
|
2389
|
-
}
|
|
2390
|
-
return set;
|
|
2391
|
-
});
|
|
2392
|
-
}
|
|
2393
|
-
async where(condition) {
|
|
2394
|
-
return this.readLock(async () => {
|
|
2395
|
-
const map = /* @__PURE__ */ new Map();
|
|
2396
|
-
for await (const [key, value] of this.whereStream(condition)) {
|
|
2397
|
-
map.set(key, value);
|
|
2398
|
-
}
|
|
2399
|
-
return map;
|
|
2400
|
-
});
|
|
2401
|
-
}
|
|
2402
|
-
async insert(key, value) {
|
|
2403
|
-
return this.writeLock(async () => {
|
|
2404
|
-
const before = await this.insertableNode(value);
|
|
2405
|
-
this._insertAtLeaf(before, key, value);
|
|
2406
|
-
if (before.values.length === this.order) {
|
|
2407
|
-
const after = await this._createNode(
|
|
2408
|
-
true,
|
|
2409
|
-
[],
|
|
2410
|
-
[],
|
|
2411
|
-
true,
|
|
2412
|
-
before.parent,
|
|
2413
|
-
null,
|
|
2414
|
-
null
|
|
2415
|
-
);
|
|
2416
|
-
const mid = Math.ceil(this.order / 2) - 1;
|
|
2417
|
-
after.values = before.values.slice(mid + 1);
|
|
2418
|
-
after.keys = before.keys.slice(mid + 1);
|
|
2419
|
-
before.values = before.values.slice(0, mid + 1);
|
|
2420
|
-
before.keys = before.keys.slice(0, mid + 1);
|
|
2421
|
-
await this._insertInParent(before, after.values[0], after);
|
|
2422
|
-
this.bufferForNodeUpdate(before);
|
|
2423
|
-
}
|
|
2424
|
-
await this.commitHeadBuffer();
|
|
2425
|
-
await this.commitNodeCreateBuffer();
|
|
2426
|
-
await this.commitNodeUpdateBuffer();
|
|
2427
|
-
});
|
|
2428
|
-
}
|
|
2429
|
-
async delete(key, value) {
|
|
2430
|
-
return this.writeLock(async () => {
|
|
2431
|
-
const node = await this.insertableNode(value);
|
|
2432
|
-
let i = node.values.length;
|
|
2433
|
-
while (i--) {
|
|
2434
|
-
const nValue = node.values[i];
|
|
2435
|
-
if (this.comparator.isSame(value, nValue)) {
|
|
2436
|
-
const keys = node.keys[i];
|
|
2437
|
-
if (keys.includes(key)) {
|
|
2438
|
-
if (keys.length > 1) {
|
|
2439
|
-
keys.splice(keys.indexOf(key), 1);
|
|
2440
|
-
this.bufferForNodeUpdate(node);
|
|
2441
|
-
} else if (node.id === this.root.id) {
|
|
2442
|
-
node.values.splice(i, 1);
|
|
2443
|
-
node.keys.splice(i, 1);
|
|
2444
|
-
this.bufferForNodeUpdate(node);
|
|
2445
|
-
} else {
|
|
2446
|
-
keys.splice(keys.indexOf(key), 1);
|
|
2447
|
-
node.keys.splice(i, 1);
|
|
2448
|
-
node.values.splice(node.values.indexOf(value), 1);
|
|
2449
|
-
await this._deleteEntry(node, key, value);
|
|
2450
|
-
this.bufferForNodeUpdate(node);
|
|
2451
|
-
}
|
|
2452
|
-
}
|
|
2453
|
-
}
|
|
2454
|
-
}
|
|
2455
|
-
await this.commitHeadBuffer();
|
|
2456
|
-
await this.commitNodeCreateBuffer();
|
|
2457
|
-
await this.commitNodeUpdateBuffer();
|
|
2458
|
-
await this.commitNodeDeleteBuffer();
|
|
2459
|
-
});
|
|
2460
|
-
}
|
|
2461
|
-
async exists(key, value) {
|
|
2462
|
-
return this.readLock(async () => {
|
|
2463
|
-
const node = await this.insertableNode(value);
|
|
2464
|
-
for (let i = 0, len = node.values.length; i < len; i++) {
|
|
2465
|
-
const nValue = node.values[i];
|
|
2466
|
-
if (this.comparator.isSame(value, nValue)) {
|
|
2467
|
-
const keys = node.keys[i];
|
|
2468
|
-
return keys.includes(key);
|
|
2469
|
-
}
|
|
2470
|
-
}
|
|
2471
|
-
return false;
|
|
2472
|
-
});
|
|
2473
|
-
}
|
|
2474
|
-
async setHeadData(data) {
|
|
2475
|
-
return this.writeLock(async () => {
|
|
2476
|
-
this.strategy.head.data = data;
|
|
2477
|
-
this._strategyDirty = true;
|
|
2478
|
-
await this.commitHeadBuffer();
|
|
2479
|
-
});
|
|
2480
|
-
}
|
|
2481
|
-
async forceUpdate() {
|
|
2482
|
-
return this.readLock(async () => {
|
|
2483
|
-
const keys = [...this.nodes.keys()];
|
|
2484
|
-
this.nodes.clear();
|
|
2485
|
-
await this.init();
|
|
2486
|
-
for (const key of keys) {
|
|
2487
|
-
await this.getNode(key);
|
|
2488
|
-
}
|
|
2489
|
-
return keys.length;
|
|
2490
|
-
});
|
|
2491
|
-
}
|
|
2492
|
-
};
|
|
2493
|
-
var SerializeStrategy = class {
|
|
2494
|
-
order;
|
|
2495
|
-
head;
|
|
2496
|
-
constructor(order) {
|
|
2497
|
-
this.order = order;
|
|
2498
|
-
this.head = {
|
|
2499
|
-
order,
|
|
2500
|
-
root: null,
|
|
2501
|
-
data: {}
|
|
2502
|
-
};
|
|
2503
|
-
}
|
|
2504
|
-
};
|
|
2505
|
-
var SerializeStrategySync = class extends SerializeStrategy {
|
|
2506
|
-
getHeadData(key, defaultValue) {
|
|
2507
|
-
if (!Object.hasOwn(this.head.data, key)) {
|
|
2508
|
-
this.setHeadData(key, defaultValue);
|
|
2509
|
-
}
|
|
2510
|
-
return this.head.data[key];
|
|
2511
|
-
}
|
|
2512
|
-
setHeadData(key, data) {
|
|
2513
|
-
this.head.data[key] = data;
|
|
2514
|
-
this.writeHead(this.head);
|
|
2515
|
-
}
|
|
2516
|
-
autoIncrement(key, defaultValue) {
|
|
2517
|
-
const current = this.getHeadData(key, defaultValue);
|
|
2518
|
-
const next = current + 1;
|
|
2519
|
-
this.setHeadData(key, next);
|
|
2520
|
-
return current;
|
|
2521
|
-
}
|
|
2522
|
-
};
|
|
2523
|
-
var InMemoryStoreStrategySync = class extends SerializeStrategySync {
|
|
2524
|
-
node;
|
|
2525
|
-
constructor(order) {
|
|
2526
|
-
super(order);
|
|
2527
|
-
this.node = {};
|
|
2610
|
+
}
|
|
2528
2611
|
}
|
|
2529
|
-
|
|
2530
|
-
|
|
2612
|
+
async keys(condition, filterValues) {
|
|
2613
|
+
const set = /* @__PURE__ */ new Set();
|
|
2614
|
+
for await (const key of this.keysStream(condition, filterValues)) {
|
|
2615
|
+
set.add(key);
|
|
2616
|
+
}
|
|
2617
|
+
return set;
|
|
2531
2618
|
}
|
|
2532
|
-
|
|
2533
|
-
|
|
2534
|
-
|
|
2619
|
+
async where(condition) {
|
|
2620
|
+
const map = /* @__PURE__ */ new Map();
|
|
2621
|
+
for await (const [key, value] of this.whereStream(condition)) {
|
|
2622
|
+
map.set(key, value);
|
|
2535
2623
|
}
|
|
2536
|
-
return
|
|
2624
|
+
return map;
|
|
2537
2625
|
}
|
|
2538
|
-
|
|
2539
|
-
this.
|
|
2626
|
+
async insert(key, value) {
|
|
2627
|
+
await this.writeLock(async () => {
|
|
2628
|
+
const before = await this.insertableNode(value);
|
|
2629
|
+
await this._insertAtLeaf(before, key, value);
|
|
2630
|
+
if (before.values.length === this.order) {
|
|
2631
|
+
const after = await this._createNode(
|
|
2632
|
+
true,
|
|
2633
|
+
[],
|
|
2634
|
+
[],
|
|
2635
|
+
true,
|
|
2636
|
+
before.parent,
|
|
2637
|
+
null,
|
|
2638
|
+
null
|
|
2639
|
+
);
|
|
2640
|
+
const mid = Math.ceil(this.order / 2) - 1;
|
|
2641
|
+
after.values = before.values.slice(mid + 1);
|
|
2642
|
+
after.keys = before.keys.slice(mid + 1);
|
|
2643
|
+
before.values = before.values.slice(0, mid + 1);
|
|
2644
|
+
before.keys = before.keys.slice(0, mid + 1);
|
|
2645
|
+
await this._insertInParent(before, after.values[0], after);
|
|
2646
|
+
await this.bufferForNodeUpdate(before);
|
|
2647
|
+
}
|
|
2648
|
+
await this.commitHeadBuffer();
|
|
2649
|
+
await this.commitNodeCreateBuffer();
|
|
2650
|
+
await this.commitNodeUpdateBuffer();
|
|
2651
|
+
});
|
|
2540
2652
|
}
|
|
2541
|
-
delete(
|
|
2542
|
-
|
|
2653
|
+
async delete(key, value) {
|
|
2654
|
+
await this.writeLock(async () => {
|
|
2655
|
+
const node = await this.insertableNode(value);
|
|
2656
|
+
let i = node.values.length;
|
|
2657
|
+
while (i--) {
|
|
2658
|
+
const nValue = node.values[i];
|
|
2659
|
+
if (this.comparator.isSame(value, nValue)) {
|
|
2660
|
+
const keys = node.keys[i];
|
|
2661
|
+
const keyIndex = keys.indexOf(key);
|
|
2662
|
+
if (keyIndex !== -1) {
|
|
2663
|
+
keys.splice(keyIndex, 1);
|
|
2664
|
+
if (keys.length === 0) {
|
|
2665
|
+
node.keys.splice(i, 1);
|
|
2666
|
+
node.values.splice(i, 1);
|
|
2667
|
+
}
|
|
2668
|
+
await this._deleteEntry(node, key, value);
|
|
2669
|
+
await this.bufferForNodeUpdate(node);
|
|
2670
|
+
break;
|
|
2671
|
+
}
|
|
2672
|
+
}
|
|
2673
|
+
}
|
|
2674
|
+
await this.commitHeadBuffer();
|
|
2675
|
+
await this.commitNodeCreateBuffer();
|
|
2676
|
+
await this.commitNodeUpdateBuffer();
|
|
2677
|
+
await this.commitNodeDeleteBuffer();
|
|
2678
|
+
});
|
|
2543
2679
|
}
|
|
2544
|
-
|
|
2545
|
-
|
|
2546
|
-
return null;
|
|
2547
|
-
}
|
|
2548
|
-
return this.head;
|
|
2680
|
+
getHeadData() {
|
|
2681
|
+
return this.strategy.head.data;
|
|
2549
2682
|
}
|
|
2550
|
-
|
|
2551
|
-
this.head =
|
|
2683
|
+
async setHeadData(data) {
|
|
2684
|
+
this.strategy.head.data = data;
|
|
2685
|
+
await this.strategy.writeHead(this.strategy.head);
|
|
2552
2686
|
}
|
|
2553
2687
|
};
|
|
2554
2688
|
var SerializeStrategyAsync = class extends SerializeStrategy {
|
|
@@ -2568,6 +2702,14 @@ var SerializeStrategyAsync = class extends SerializeStrategy {
|
|
|
2568
2702
|
await this.setHeadData(key, next);
|
|
2569
2703
|
return current;
|
|
2570
2704
|
}
|
|
2705
|
+
async compareAndSwapHead(oldRoot, newRoot) {
|
|
2706
|
+
if (this.head.root !== oldRoot) {
|
|
2707
|
+
return false;
|
|
2708
|
+
}
|
|
2709
|
+
this.head.root = newRoot;
|
|
2710
|
+
await this.writeHead(this.head);
|
|
2711
|
+
return true;
|
|
2712
|
+
}
|
|
2571
2713
|
};
|
|
2572
2714
|
var InMemoryStoreStrategyAsync = class extends SerializeStrategyAsync {
|
|
2573
2715
|
node;
|
|
@@ -2582,7 +2724,8 @@ var InMemoryStoreStrategyAsync = class extends SerializeStrategyAsync {
|
|
|
2582
2724
|
if (!Object.hasOwn(this.node, id)) {
|
|
2583
2725
|
throw new Error(`The tree attempted to reference node '${id}', but couldn't find the corresponding node.`);
|
|
2584
2726
|
}
|
|
2585
|
-
|
|
2727
|
+
const node = this.node[id];
|
|
2728
|
+
return JSON.parse(JSON.stringify(node));
|
|
2586
2729
|
}
|
|
2587
2730
|
async write(id, node) {
|
|
2588
2731
|
this.node[id] = node;
|
|
@@ -2600,9 +2743,341 @@ var InMemoryStoreStrategyAsync = class extends SerializeStrategyAsync {
|
|
|
2600
2743
|
this.head = head;
|
|
2601
2744
|
}
|
|
2602
2745
|
};
|
|
2746
|
+
var BPTreeAsyncSnapshotStrategy = class extends SerializeStrategyAsync {
|
|
2747
|
+
baseStrategy;
|
|
2748
|
+
snapshotHead;
|
|
2749
|
+
constructor(baseStrategy, root) {
|
|
2750
|
+
super(baseStrategy.order);
|
|
2751
|
+
this.baseStrategy = baseStrategy;
|
|
2752
|
+
this.snapshotHead = {
|
|
2753
|
+
...baseStrategy.head,
|
|
2754
|
+
root,
|
|
2755
|
+
data: { ...baseStrategy.head.data }
|
|
2756
|
+
};
|
|
2757
|
+
this.head = this.snapshotHead;
|
|
2758
|
+
}
|
|
2759
|
+
async id(isLeaf) {
|
|
2760
|
+
return await this.baseStrategy.id(isLeaf);
|
|
2761
|
+
}
|
|
2762
|
+
async read(id) {
|
|
2763
|
+
return await this.baseStrategy.read(id);
|
|
2764
|
+
}
|
|
2765
|
+
async write(id, node) {
|
|
2766
|
+
await this.baseStrategy.write(id, node);
|
|
2767
|
+
}
|
|
2768
|
+
async delete(id) {
|
|
2769
|
+
await this.baseStrategy.delete(id);
|
|
2770
|
+
}
|
|
2771
|
+
async readHead() {
|
|
2772
|
+
return this.snapshotHead;
|
|
2773
|
+
}
|
|
2774
|
+
async writeHead(head) {
|
|
2775
|
+
this.snapshotHead.root = head.root;
|
|
2776
|
+
this.snapshotHead.data = { ...head.data };
|
|
2777
|
+
}
|
|
2778
|
+
async compareAndSwapHead(oldRoot, newRoot) {
|
|
2779
|
+
return await this.baseStrategy.compareAndSwapHead(oldRoot, newRoot);
|
|
2780
|
+
}
|
|
2781
|
+
async getHeadData(key, defaultValue) {
|
|
2782
|
+
return this.snapshotHead.data[key] ?? defaultValue;
|
|
2783
|
+
}
|
|
2784
|
+
async setHeadData(key, data) {
|
|
2785
|
+
this.snapshotHead.data[key] = data;
|
|
2786
|
+
}
|
|
2787
|
+
async autoIncrement(key, defaultValue) {
|
|
2788
|
+
return this.snapshotHead.data[key] ?? defaultValue;
|
|
2789
|
+
}
|
|
2790
|
+
};
|
|
2791
|
+
var BPTreeAsyncTransaction = class extends BPTreeAsyncBase {
|
|
2792
|
+
realBaseTree;
|
|
2793
|
+
realBaseStrategy;
|
|
2794
|
+
txNodes = /* @__PURE__ */ new Map();
|
|
2795
|
+
dirtyIds;
|
|
2796
|
+
createdInTx;
|
|
2797
|
+
deletedIds;
|
|
2798
|
+
initialRootId;
|
|
2799
|
+
transactionRootId;
|
|
2800
|
+
constructor(baseTree) {
|
|
2801
|
+
super(baseTree.strategy, baseTree.comparator, baseTree.option);
|
|
2802
|
+
this.realBaseTree = baseTree;
|
|
2803
|
+
this.realBaseStrategy = baseTree.strategy;
|
|
2804
|
+
this.order = baseTree.getOrder();
|
|
2805
|
+
this.initialRootId = "";
|
|
2806
|
+
this.transactionRootId = "";
|
|
2807
|
+
this.dirtyIds = /* @__PURE__ */ new Set();
|
|
2808
|
+
this.createdInTx = /* @__PURE__ */ new Set();
|
|
2809
|
+
this.deletedIds = /* @__PURE__ */ new Set();
|
|
2810
|
+
}
|
|
2811
|
+
/**
|
|
2812
|
+
* Initializes the transaction by capturing the current state of the tree.
|
|
2813
|
+
*/
|
|
2814
|
+
async initTransaction() {
|
|
2815
|
+
const head = await this.realBaseStrategy.readHead();
|
|
2816
|
+
if (head) {
|
|
2817
|
+
this.order = head.order;
|
|
2818
|
+
this.initialRootId = head.root;
|
|
2819
|
+
} else {
|
|
2820
|
+
this.initialRootId = this.realBaseTree.getRootId();
|
|
2821
|
+
}
|
|
2822
|
+
if (!this.initialRootId) {
|
|
2823
|
+
const root = await this._createNode(true, [], [], true);
|
|
2824
|
+
this.initialRootId = root.id;
|
|
2825
|
+
}
|
|
2826
|
+
this.transactionRootId = this.initialRootId;
|
|
2827
|
+
this.rootId = this.transactionRootId;
|
|
2828
|
+
const snapshotStrategy = new BPTreeAsyncSnapshotStrategy(this.realBaseStrategy, this.initialRootId);
|
|
2829
|
+
this.strategy = snapshotStrategy;
|
|
2830
|
+
this.txNodes.clear();
|
|
2831
|
+
this.dirtyIds.clear();
|
|
2832
|
+
this.createdInTx.clear();
|
|
2833
|
+
this.deletedIds.clear();
|
|
2834
|
+
}
|
|
2835
|
+
async getNode(id) {
|
|
2836
|
+
if (this.txNodes.has(id)) {
|
|
2837
|
+
return this.txNodes.get(id);
|
|
2838
|
+
}
|
|
2839
|
+
if (this.deletedIds.has(id)) {
|
|
2840
|
+
throw new Error(`The tree attempted to reference deleted node '${id}'`);
|
|
2841
|
+
}
|
|
2842
|
+
const baseNode = await this.realBaseStrategy.read(id);
|
|
2843
|
+
const clone = JSON.parse(JSON.stringify(baseNode));
|
|
2844
|
+
this.txNodes.set(id, clone);
|
|
2845
|
+
return clone;
|
|
2846
|
+
}
|
|
2847
|
+
async bufferForNodeUpdate(node) {
|
|
2848
|
+
if (this.dirtyIds.has(node.id) && this.txNodes.has(node.id) && node._p) {
|
|
2849
|
+
this.txNodes.set(node.id, node);
|
|
2850
|
+
return;
|
|
2851
|
+
}
|
|
2852
|
+
node._p = true;
|
|
2853
|
+
this.txNodes.set(node.id, node);
|
|
2854
|
+
this.dirtyIds.add(node.id);
|
|
2855
|
+
if (node.leaf) {
|
|
2856
|
+
if (node.next && !this.dirtyIds.has(node.next) && !this.deletedIds.has(node.next)) {
|
|
2857
|
+
try {
|
|
2858
|
+
await this.bufferForNodeUpdate(await this.getNode(node.next));
|
|
2859
|
+
} catch (e) {
|
|
2860
|
+
}
|
|
2861
|
+
}
|
|
2862
|
+
if (node.prev && !this.dirtyIds.has(node.prev) && !this.deletedIds.has(node.prev)) {
|
|
2863
|
+
try {
|
|
2864
|
+
await this.bufferForNodeUpdate(await this.getNode(node.prev));
|
|
2865
|
+
} catch (e) {
|
|
2866
|
+
}
|
|
2867
|
+
}
|
|
2868
|
+
}
|
|
2869
|
+
await this.markPathDirty(node);
|
|
2870
|
+
delete node._p;
|
|
2871
|
+
}
|
|
2872
|
+
async bufferForNodeCreate(node) {
|
|
2873
|
+
this.txNodes.set(node.id, node);
|
|
2874
|
+
this.dirtyIds.add(node.id);
|
|
2875
|
+
this.createdInTx.add(node.id);
|
|
2876
|
+
if (node.leaf) {
|
|
2877
|
+
if (node.next && !this.dirtyIds.has(node.next) && !this.deletedIds.has(node.next)) {
|
|
2878
|
+
try {
|
|
2879
|
+
await this.bufferForNodeUpdate(await this.getNode(node.next));
|
|
2880
|
+
} catch (e) {
|
|
2881
|
+
}
|
|
2882
|
+
}
|
|
2883
|
+
if (node.prev && !this.dirtyIds.has(node.prev) && !this.deletedIds.has(node.prev)) {
|
|
2884
|
+
try {
|
|
2885
|
+
await this.bufferForNodeUpdate(await this.getNode(node.prev));
|
|
2886
|
+
} catch (e) {
|
|
2887
|
+
}
|
|
2888
|
+
}
|
|
2889
|
+
}
|
|
2890
|
+
await this.markPathDirty(node);
|
|
2891
|
+
}
|
|
2892
|
+
async bufferForNodeDelete(node) {
|
|
2893
|
+
this.txNodes.delete(node.id);
|
|
2894
|
+
this.dirtyIds.add(node.id);
|
|
2895
|
+
this.deletedIds.add(node.id);
|
|
2896
|
+
}
|
|
2897
|
+
async markPathDirty(node) {
|
|
2898
|
+
let curr = node;
|
|
2899
|
+
while (curr.parent) {
|
|
2900
|
+
if (this.deletedIds.has(curr.parent)) {
|
|
2901
|
+
break;
|
|
2902
|
+
}
|
|
2903
|
+
if (this.dirtyIds.has(curr.parent) && this.txNodes.has(curr.parent)) {
|
|
2904
|
+
break;
|
|
2905
|
+
}
|
|
2906
|
+
const parent = await this.getNode(curr.parent);
|
|
2907
|
+
this.dirtyIds.add(parent.id);
|
|
2908
|
+
curr = parent;
|
|
2909
|
+
}
|
|
2910
|
+
if (!curr.parent) {
|
|
2911
|
+
this.transactionRootId = curr.id;
|
|
2912
|
+
}
|
|
2913
|
+
}
|
|
2914
|
+
async _createNode(isLeaf, keys, values, leaf = isLeaf, parent = null, next = null, prev = null) {
|
|
2915
|
+
const id = await this.strategy.id(isLeaf);
|
|
2916
|
+
const node = {
|
|
2917
|
+
id,
|
|
2918
|
+
keys,
|
|
2919
|
+
values,
|
|
2920
|
+
leaf,
|
|
2921
|
+
parent,
|
|
2922
|
+
next,
|
|
2923
|
+
prev
|
|
2924
|
+
};
|
|
2925
|
+
await this.bufferForNodeCreate(node);
|
|
2926
|
+
return node;
|
|
2927
|
+
}
|
|
2928
|
+
/**
|
|
2929
|
+
* Attempts to commit the transaction.
|
|
2930
|
+
* Uses Optimistic Locking (Compare-And-Swap) on the root node ID to detect conflicts.
|
|
2931
|
+
*
|
|
2932
|
+
* @returns A promise that resolves to the transaction result.
|
|
2933
|
+
*/
|
|
2934
|
+
async commit() {
|
|
2935
|
+
const idMapping = /* @__PURE__ */ new Map();
|
|
2936
|
+
const finalNodes = [];
|
|
2937
|
+
for (const oldId of this.dirtyIds) {
|
|
2938
|
+
if (this.createdInTx.has(oldId)) {
|
|
2939
|
+
idMapping.set(oldId, oldId);
|
|
2940
|
+
} else {
|
|
2941
|
+
const node = this.txNodes.get(oldId);
|
|
2942
|
+
if (node) {
|
|
2943
|
+
const newId = await this.realBaseStrategy.id(node.leaf);
|
|
2944
|
+
idMapping.set(oldId, newId);
|
|
2945
|
+
}
|
|
2946
|
+
}
|
|
2947
|
+
}
|
|
2948
|
+
const newCreatedIds = [];
|
|
2949
|
+
for (const oldId of this.dirtyIds) {
|
|
2950
|
+
const node = this.txNodes.get(oldId);
|
|
2951
|
+
if (!node) continue;
|
|
2952
|
+
const newId = idMapping.get(oldId);
|
|
2953
|
+
node.id = newId;
|
|
2954
|
+
if (node.parent && idMapping.has(node.parent)) {
|
|
2955
|
+
node.parent = idMapping.get(node.parent);
|
|
2956
|
+
}
|
|
2957
|
+
if (!node.leaf) {
|
|
2958
|
+
const internal = node;
|
|
2959
|
+
for (let i = 0; i < internal.keys.length; i++) {
|
|
2960
|
+
const childId = internal.keys[i];
|
|
2961
|
+
if (idMapping.has(childId)) {
|
|
2962
|
+
internal.keys[i] = idMapping.get(childId);
|
|
2963
|
+
}
|
|
2964
|
+
}
|
|
2965
|
+
}
|
|
2966
|
+
if (node.leaf) {
|
|
2967
|
+
const leaf = node;
|
|
2968
|
+
if (leaf.next && idMapping.has(leaf.next)) {
|
|
2969
|
+
leaf.next = idMapping.get(leaf.next);
|
|
2970
|
+
}
|
|
2971
|
+
if (leaf.prev && idMapping.has(leaf.prev)) {
|
|
2972
|
+
leaf.prev = idMapping.get(leaf.prev);
|
|
2973
|
+
}
|
|
2974
|
+
}
|
|
2975
|
+
finalNodes.push(node);
|
|
2976
|
+
newCreatedIds.push(newId);
|
|
2977
|
+
}
|
|
2978
|
+
let newRootId = this.rootId;
|
|
2979
|
+
if (idMapping.has(this.rootId)) {
|
|
2980
|
+
newRootId = idMapping.get(this.rootId);
|
|
2981
|
+
}
|
|
2982
|
+
for (const node of finalNodes) {
|
|
2983
|
+
await this.realBaseStrategy.write(node.id, node);
|
|
2984
|
+
}
|
|
2985
|
+
const success = await this.realBaseStrategy.compareAndSwapHead(this.initialRootId, newRootId);
|
|
2986
|
+
if (success) {
|
|
2987
|
+
const distinctObsolete = /* @__PURE__ */ new Set();
|
|
2988
|
+
for (const oldId of this.dirtyIds) {
|
|
2989
|
+
if (!this.createdInTx.has(oldId) && this.txNodes.has(oldId)) {
|
|
2990
|
+
distinctObsolete.add(oldId);
|
|
2991
|
+
}
|
|
2992
|
+
}
|
|
2993
|
+
return {
|
|
2994
|
+
success: true,
|
|
2995
|
+
createdIds: newCreatedIds,
|
|
2996
|
+
obsoleteIds: Array.from(distinctObsolete)
|
|
2997
|
+
};
|
|
2998
|
+
} else {
|
|
2999
|
+
await this.rollback();
|
|
3000
|
+
return {
|
|
3001
|
+
success: false,
|
|
3002
|
+
createdIds: newCreatedIds,
|
|
3003
|
+
obsoleteIds: []
|
|
3004
|
+
};
|
|
3005
|
+
}
|
|
3006
|
+
}
|
|
3007
|
+
/**
|
|
3008
|
+
* Rolls back the transaction by clearing all buffered changes.
|
|
3009
|
+
* If cleanup is `true`, it also clears the transaction nodes.
|
|
3010
|
+
* @param cleanup Whether to clear the transaction nodes.
|
|
3011
|
+
* @returns The IDs of nodes that were created in this transaction.
|
|
3012
|
+
*/
|
|
3013
|
+
async rollback(cleanup = true) {
|
|
3014
|
+
const createdIds = Array.from(this.createdInTx);
|
|
3015
|
+
this.txNodes.clear();
|
|
3016
|
+
this.dirtyIds.clear();
|
|
3017
|
+
this.createdInTx.clear();
|
|
3018
|
+
if (cleanup) {
|
|
3019
|
+
for (const id of createdIds) {
|
|
3020
|
+
await this.realBaseStrategy.delete(id);
|
|
3021
|
+
}
|
|
3022
|
+
}
|
|
3023
|
+
return createdIds;
|
|
3024
|
+
}
|
|
3025
|
+
async readLock(fn) {
|
|
3026
|
+
return await fn();
|
|
3027
|
+
}
|
|
3028
|
+
async writeLock(fn) {
|
|
3029
|
+
return await fn();
|
|
3030
|
+
}
|
|
3031
|
+
async commitHeadBuffer() {
|
|
3032
|
+
}
|
|
3033
|
+
async commitNodeCreateBuffer() {
|
|
3034
|
+
}
|
|
3035
|
+
async commitNodeUpdateBuffer() {
|
|
3036
|
+
}
|
|
3037
|
+
async commitNodeDeleteBuffer() {
|
|
3038
|
+
}
|
|
3039
|
+
};
|
|
3040
|
+
var BPTreeAsync = class extends BPTreeAsyncBase {
|
|
3041
|
+
constructor(strategy, comparator, option) {
|
|
3042
|
+
super(strategy, comparator, option);
|
|
3043
|
+
}
|
|
3044
|
+
/**
|
|
3045
|
+
* Creates a new asynchronous transaction.
|
|
3046
|
+
* @returns A promise that resolves to a new BPTreeAsyncTransaction.
|
|
3047
|
+
*/
|
|
3048
|
+
async createTransaction() {
|
|
3049
|
+
const tx = new BPTreeAsyncTransaction(this);
|
|
3050
|
+
await tx.initTransaction();
|
|
3051
|
+
return tx;
|
|
3052
|
+
}
|
|
3053
|
+
async insert(key, value) {
|
|
3054
|
+
const tx = await this.createTransaction();
|
|
3055
|
+
await tx.insert(key, value);
|
|
3056
|
+
const { success } = await tx.commit();
|
|
3057
|
+
await this.init();
|
|
3058
|
+
if (!success) {
|
|
3059
|
+
throw new Error("Transaction failed: Commit failed due to conflict");
|
|
3060
|
+
}
|
|
3061
|
+
}
|
|
3062
|
+
async delete(key, value) {
|
|
3063
|
+
const tx = await this.createTransaction();
|
|
3064
|
+
await tx.delete(key, value);
|
|
3065
|
+
const { success } = await tx.commit();
|
|
3066
|
+
await this.init();
|
|
3067
|
+
if (!success) {
|
|
3068
|
+
throw new Error("Transaction failed: Commit failed due to conflict");
|
|
3069
|
+
}
|
|
3070
|
+
}
|
|
3071
|
+
async readLock(fn) {
|
|
3072
|
+
return await fn();
|
|
3073
|
+
}
|
|
3074
|
+
async writeLock(fn) {
|
|
3075
|
+
return await fn();
|
|
3076
|
+
}
|
|
3077
|
+
};
|
|
2603
3078
|
|
|
2604
3079
|
// node_modules/ryoiki/dist/esm/index.mjs
|
|
2605
|
-
var
|
|
3080
|
+
var Ryoiki = class _Ryoiki {
|
|
2606
3081
|
readings;
|
|
2607
3082
|
writings;
|
|
2608
3083
|
readQueue;
|
|
@@ -2646,7 +3121,7 @@ var Ryoiki2 = class _Ryoiki2 {
|
|
|
2646
3121
|
return [start, start + length];
|
|
2647
3122
|
}
|
|
2648
3123
|
rangeOverlapping(tasks, range) {
|
|
2649
|
-
return Array.from(tasks.values()).some((t) =>
|
|
3124
|
+
return Array.from(tasks.values()).some((t) => _Ryoiki.IsRangeOverlap(t.range, range));
|
|
2650
3125
|
}
|
|
2651
3126
|
isSameRange(a, b) {
|
|
2652
3127
|
const [a1, a2] = a;
|
|
@@ -2687,7 +3162,7 @@ var Ryoiki2 = class _Ryoiki2 {
|
|
|
2687
3162
|
_alloc(queue, workspaces, lockId) {
|
|
2688
3163
|
const unit = queue.get(lockId);
|
|
2689
3164
|
if (!unit) {
|
|
2690
|
-
throw
|
|
3165
|
+
throw _Ryoiki.ERR_NOT_EXISTS(lockId);
|
|
2691
3166
|
}
|
|
2692
3167
|
workspaces.set(lockId, unit);
|
|
2693
3168
|
queue.delete(lockId);
|
|
@@ -2696,7 +3171,7 @@ var Ryoiki2 = class _Ryoiki2 {
|
|
|
2696
3171
|
_free(workspaces, lockId) {
|
|
2697
3172
|
const unit = workspaces.get(lockId);
|
|
2698
3173
|
if (!unit) {
|
|
2699
|
-
throw
|
|
3174
|
+
throw _Ryoiki.ERR_NOT_EXISTS(lockId);
|
|
2700
3175
|
}
|
|
2701
3176
|
workspaces.delete(lockId);
|
|
2702
3177
|
unit.free();
|
|
@@ -2706,7 +3181,7 @@ var Ryoiki2 = class _Ryoiki2 {
|
|
|
2706
3181
|
let timeoutId = null;
|
|
2707
3182
|
if (timeout >= 0) {
|
|
2708
3183
|
timeoutId = setTimeout(() => {
|
|
2709
|
-
reject(
|
|
3184
|
+
reject(_Ryoiki.ERR_TIMEOUT(id, timeout));
|
|
2710
3185
|
}, timeout);
|
|
2711
3186
|
}
|
|
2712
3187
|
const id = this._createRandomId();
|
|
@@ -2714,7 +3189,7 @@ var Ryoiki2 = class _Ryoiki2 {
|
|
|
2714
3189
|
if (timeoutId !== null) {
|
|
2715
3190
|
clearTimeout(timeoutId);
|
|
2716
3191
|
}
|
|
2717
|
-
const [err, v] = await
|
|
3192
|
+
const [err, v] = await _Ryoiki.CatchError(task(id));
|
|
2718
3193
|
if (err) reject(err);
|
|
2719
3194
|
else resolve(v);
|
|
2720
3195
|
};
|
|
@@ -2729,7 +3204,7 @@ var Ryoiki2 = class _Ryoiki2 {
|
|
|
2729
3204
|
_checkWorking(range, workspaces) {
|
|
2730
3205
|
let isLocked = false;
|
|
2731
3206
|
for (const lock of workspaces.values()) {
|
|
2732
|
-
if (
|
|
3207
|
+
if (_Ryoiki.IsRangeOverlap(range, lock.range)) {
|
|
2733
3208
|
isLocked = true;
|
|
2734
3209
|
break;
|
|
2735
3210
|
}
|
|
@@ -5840,8 +6315,11 @@ var RowIdentifierStrategy = class extends SerializeStrategyAsync {
|
|
|
5840
6315
|
if (node.leaf) {
|
|
5841
6316
|
const n = node;
|
|
5842
6317
|
const keys = new Array(n.keys.length);
|
|
5843
|
-
|
|
6318
|
+
let i = 0;
|
|
6319
|
+
const len = keys.length;
|
|
6320
|
+
while (i < len) {
|
|
5844
6321
|
keys[i] = +n.keys[i][0];
|
|
6322
|
+
i++;
|
|
5845
6323
|
}
|
|
5846
6324
|
this.indexPageManger.setIndexId(page, +n.id);
|
|
5847
6325
|
this.indexPageManger.setParentIndexId(page, +n.parent);
|
|
@@ -5854,8 +6332,11 @@ var RowIdentifierStrategy = class extends SerializeStrategyAsync {
|
|
|
5854
6332
|
} else {
|
|
5855
6333
|
const n = node;
|
|
5856
6334
|
const keys = new Array(n.keys.length);
|
|
5857
|
-
|
|
6335
|
+
let i = 0;
|
|
6336
|
+
const len = keys.length;
|
|
6337
|
+
while (i < len) {
|
|
5858
6338
|
keys[i] = +n.keys[i];
|
|
6339
|
+
i++;
|
|
5859
6340
|
}
|
|
5860
6341
|
this.indexPageManger.setIndexId(page, +n.id);
|
|
5861
6342
|
this.indexPageManger.setParentIndexId(page, +n.parent);
|
|
@@ -5890,9 +6371,11 @@ var RowIdentifierStrategy = class extends SerializeStrategyAsync {
|
|
|
5890
6371
|
if (rootIndexPageId === -1) {
|
|
5891
6372
|
return null;
|
|
5892
6373
|
}
|
|
6374
|
+
const metaOrder = manager.getRootIndexOrder(metadataPage);
|
|
6375
|
+
const order = metaOrder || this.order;
|
|
5893
6376
|
return {
|
|
5894
|
-
root:
|
|
5895
|
-
order
|
|
6377
|
+
root: rootIndexPageId.toString(),
|
|
6378
|
+
order,
|
|
5896
6379
|
data: {}
|
|
5897
6380
|
};
|
|
5898
6381
|
}
|
|
@@ -5979,8 +6462,9 @@ var RowTableEngine = class {
|
|
|
5979
6462
|
this.pageIdBuffer = new Uint8Array(DataPageManager.CONSTANT.SIZE_PAGE_ID);
|
|
5980
6463
|
this.maxBodySize = this.pfs.pageSize - DataPageManager.CONSTANT.SIZE_PAGE_HEADER;
|
|
5981
6464
|
this.order = this.getOptimalOrder(pfs.pageSize, IndexPageManager.CONSTANT.SIZE_KEY, IndexPageManager.CONSTANT.SIZE_VALUE);
|
|
6465
|
+
this.strategy = new RowIdentifierStrategy(this.order, pfs, txContext);
|
|
5982
6466
|
this.bptree = new BPTreeAsync(
|
|
5983
|
-
|
|
6467
|
+
this.strategy,
|
|
5984
6468
|
new NumericComparator(),
|
|
5985
6469
|
{
|
|
5986
6470
|
capacity: this.options.pageCacheCapacity
|
|
@@ -5988,6 +6472,7 @@ var RowTableEngine = class {
|
|
|
5988
6472
|
);
|
|
5989
6473
|
}
|
|
5990
6474
|
bptree;
|
|
6475
|
+
strategy;
|
|
5991
6476
|
order;
|
|
5992
6477
|
factory;
|
|
5993
6478
|
metadataPageManager;
|
|
@@ -5999,6 +6484,35 @@ var RowTableEngine = class {
|
|
|
5999
6484
|
ridBuffer;
|
|
6000
6485
|
pageIdBuffer;
|
|
6001
6486
|
initialized = false;
|
|
6487
|
+
/**
|
|
6488
|
+
* Retrieves the BPTree transaction associated with the given transaction.
|
|
6489
|
+
* If it doesn't exist, it creates a new one and registers commit/rollback hooks.
|
|
6490
|
+
* @param tx Dataply transaction
|
|
6491
|
+
* @returns BPTree transaction
|
|
6492
|
+
*/
|
|
6493
|
+
async getBPTreeTransaction(tx) {
|
|
6494
|
+
let btx = tx.__getBPTreeTransaction();
|
|
6495
|
+
if (!btx) {
|
|
6496
|
+
btx = await this.bptree.createTransaction();
|
|
6497
|
+
tx.__setBPTreeTransaction(btx);
|
|
6498
|
+
tx.onCommit(async () => {
|
|
6499
|
+
if (!tx.__isBPTreeDirty()) {
|
|
6500
|
+
return;
|
|
6501
|
+
}
|
|
6502
|
+
if (!btx) return;
|
|
6503
|
+
const result = await btx.commit();
|
|
6504
|
+
if (result.success) {
|
|
6505
|
+
await this.bptree.init();
|
|
6506
|
+
for (const id of result.obsoleteIds) {
|
|
6507
|
+
await this.strategy.delete(id);
|
|
6508
|
+
}
|
|
6509
|
+
} else {
|
|
6510
|
+
throw new Error(`BPTree transaction commit failed. Current Root: ${this.bptree.getRootId()}`);
|
|
6511
|
+
}
|
|
6512
|
+
});
|
|
6513
|
+
}
|
|
6514
|
+
return btx;
|
|
6515
|
+
}
|
|
6002
6516
|
/**
|
|
6003
6517
|
* Initializes the B+ Tree.
|
|
6004
6518
|
*/
|
|
@@ -6128,7 +6642,9 @@ var RowTableEngine = class {
|
|
|
6128
6642
|
this.metadataPageManager.setRowCount(freshMetadataPage, currentRowCount + 1);
|
|
6129
6643
|
}
|
|
6130
6644
|
await this.pfs.setMetadata(freshMetadataPage, tx);
|
|
6131
|
-
await this.
|
|
6645
|
+
const btx = await this.getBPTreeTransaction(tx);
|
|
6646
|
+
await btx.insert(this.getRID(), pk);
|
|
6647
|
+
tx.__markBPTreeDirty();
|
|
6132
6648
|
return pk;
|
|
6133
6649
|
}
|
|
6134
6650
|
/**
|
|
@@ -6139,11 +6655,8 @@ var RowTableEngine = class {
|
|
|
6139
6655
|
* @returns RID or null (if not found)
|
|
6140
6656
|
*/
|
|
6141
6657
|
async getRidByPK(pk, tx) {
|
|
6142
|
-
const
|
|
6143
|
-
|
|
6144
|
-
return pendingUpdate.newRid;
|
|
6145
|
-
}
|
|
6146
|
-
const keys = await this.bptree.keys({ equal: pk });
|
|
6658
|
+
const btx = await this.getBPTreeTransaction(tx);
|
|
6659
|
+
const keys = await btx.keys({ equal: pk });
|
|
6147
6660
|
if (keys.size === 0) {
|
|
6148
6661
|
return null;
|
|
6149
6662
|
}
|
|
@@ -6162,6 +6675,7 @@ var RowTableEngine = class {
|
|
|
6162
6675
|
* @param tx Transaction
|
|
6163
6676
|
*/
|
|
6164
6677
|
async update(pk, data, tx) {
|
|
6678
|
+
await tx.__acquireWriteLock(0);
|
|
6165
6679
|
const rid = await this.getRidByPK(pk, tx);
|
|
6166
6680
|
if (rid === null) {
|
|
6167
6681
|
return;
|
|
@@ -6231,16 +6745,10 @@ var RowTableEngine = class {
|
|
|
6231
6745
|
const oldRidNumeric = this.getRID();
|
|
6232
6746
|
this.setRID(lastInsertDataPageId, newSlotIndex);
|
|
6233
6747
|
const newRidNumeric = this.getRID();
|
|
6234
|
-
|
|
6235
|
-
|
|
6236
|
-
|
|
6237
|
-
|
|
6238
|
-
await this.bptree.delete(oldRid, key);
|
|
6239
|
-
await this.bptree.insert(newRid, key);
|
|
6240
|
-
}
|
|
6241
|
-
});
|
|
6242
|
-
}
|
|
6243
|
-
tx.__addPendingIndexUpdate(pk, newRidNumeric, oldRidNumeric);
|
|
6748
|
+
const btx = await this.getBPTreeTransaction(tx);
|
|
6749
|
+
await btx.delete(oldRidNumeric, pk);
|
|
6750
|
+
await btx.insert(newRidNumeric, pk);
|
|
6751
|
+
tx.__markBPTreeDirty();
|
|
6244
6752
|
const freshMetadataPage = await this.pfs.getMetadata(tx);
|
|
6245
6753
|
this.metadataPageManager.setLastInsertPageId(freshMetadataPage, lastInsertDataPageId);
|
|
6246
6754
|
await this.pfs.setMetadata(freshMetadataPage, tx);
|
|
@@ -6280,6 +6788,9 @@ var RowTableEngine = class {
|
|
|
6280
6788
|
}
|
|
6281
6789
|
this.rowManager.setDeletedFlag(row, true);
|
|
6282
6790
|
await this.pfs.setPage(pageId, page, tx);
|
|
6791
|
+
const btx = await this.getBPTreeTransaction(tx);
|
|
6792
|
+
await btx.delete(rid, pk);
|
|
6793
|
+
tx.__markBPTreeDirty();
|
|
6283
6794
|
if (decrementRowCount) {
|
|
6284
6795
|
const metadataPage2 = await this.pfs.getMetadata(tx);
|
|
6285
6796
|
const currentRowCount = this.metadataPageManager.getRowCount(metadataPage2);
|
|
@@ -6293,12 +6804,14 @@ var RowTableEngine = class {
|
|
|
6293
6804
|
if (pageId === lastInsertPageId) {
|
|
6294
6805
|
allDeleted = false;
|
|
6295
6806
|
} else {
|
|
6296
|
-
|
|
6807
|
+
let i = 0;
|
|
6808
|
+
while (i < insertedRowCount) {
|
|
6297
6809
|
const slotRow = this.dataPageManager.getRow(page, i);
|
|
6298
6810
|
if (!this.rowManager.getDeletedFlag(slotRow)) {
|
|
6299
6811
|
allDeleted = false;
|
|
6300
6812
|
break;
|
|
6301
6813
|
}
|
|
6814
|
+
i++;
|
|
6302
6815
|
}
|
|
6303
6816
|
}
|
|
6304
6817
|
if (allDeleted) {
|
|
@@ -6361,7 +6874,7 @@ var LockManager = class {
|
|
|
6361
6874
|
lock;
|
|
6362
6875
|
unlockMap = /* @__PURE__ */ new Map();
|
|
6363
6876
|
constructor() {
|
|
6364
|
-
this.lock = new
|
|
6877
|
+
this.lock = new Ryoiki();
|
|
6365
6878
|
}
|
|
6366
6879
|
/**
|
|
6367
6880
|
* Requests a read (Shared) lock for a page.
|
|
@@ -6424,12 +6937,41 @@ var Transaction = class {
|
|
|
6424
6937
|
pageLocks = /* @__PURE__ */ new Map();
|
|
6425
6938
|
/** Undo Logs: PageID -> Original Page Buffer (Snapshot) */
|
|
6426
6939
|
undoPages = /* @__PURE__ */ new Map();
|
|
6427
|
-
/**
|
|
6940
|
+
/** Dirty Pages modified by the transaction */
|
|
6428
6941
|
dirtyPages = /* @__PURE__ */ new Set();
|
|
6429
|
-
/**
|
|
6430
|
-
|
|
6942
|
+
/** BPTree Transaction instance */
|
|
6943
|
+
bptreeTx;
|
|
6944
|
+
/** Whether the BPTree transaction is dirty */
|
|
6945
|
+
bptreeDirty = false;
|
|
6431
6946
|
/** List of callbacks to execute on commit */
|
|
6432
6947
|
commitHooks = [];
|
|
6948
|
+
/**
|
|
6949
|
+
* Sets the BPTree transaction.
|
|
6950
|
+
* @param tx BPTree transaction
|
|
6951
|
+
*/
|
|
6952
|
+
__setBPTreeTransaction(tx) {
|
|
6953
|
+
this.bptreeTx = tx;
|
|
6954
|
+
}
|
|
6955
|
+
/**
|
|
6956
|
+
* Returns the BPTree transaction.
|
|
6957
|
+
* @returns BPTree transaction
|
|
6958
|
+
*/
|
|
6959
|
+
__getBPTreeTransaction() {
|
|
6960
|
+
return this.bptreeTx;
|
|
6961
|
+
}
|
|
6962
|
+
/**
|
|
6963
|
+
* Marks the BPTree transaction as dirty.
|
|
6964
|
+
*/
|
|
6965
|
+
__markBPTreeDirty() {
|
|
6966
|
+
this.bptreeDirty = true;
|
|
6967
|
+
}
|
|
6968
|
+
/**
|
|
6969
|
+
* Returns whether the BPTree transaction is dirty.
|
|
6970
|
+
* @returns True if dirty
|
|
6971
|
+
*/
|
|
6972
|
+
__isBPTreeDirty() {
|
|
6973
|
+
return this.bptreeDirty;
|
|
6974
|
+
}
|
|
6433
6975
|
/**
|
|
6434
6976
|
* Registers a commit hook.
|
|
6435
6977
|
* @param hook Function to execute
|
|
@@ -6465,32 +7007,6 @@ var Transaction = class {
|
|
|
6465
7007
|
__hasUndoPage(pageId) {
|
|
6466
7008
|
return this.undoPages.has(pageId);
|
|
6467
7009
|
}
|
|
6468
|
-
/**
|
|
6469
|
-
* Adds a Pending Index Update.
|
|
6470
|
-
* Does not call this method directly. It is called by the `VirtualFileSystem` instance.
|
|
6471
|
-
* @param pk PK
|
|
6472
|
-
* @param newRid New RID
|
|
6473
|
-
* @param oldRid Old RID
|
|
6474
|
-
*/
|
|
6475
|
-
__addPendingIndexUpdate(pk, newRid, oldRid) {
|
|
6476
|
-
this.pendingIndexUpdates.set(pk, { newRid, oldRid });
|
|
6477
|
-
}
|
|
6478
|
-
/**
|
|
6479
|
-
* Returns a Pending Index Update.
|
|
6480
|
-
* Does not call this method directly. It is called by the `VirtualFileSystem` instance.
|
|
6481
|
-
* @param pk PK
|
|
6482
|
-
* @returns Pending Index Update
|
|
6483
|
-
*/
|
|
6484
|
-
__getPendingIndexUpdate(pk) {
|
|
6485
|
-
return this.pendingIndexUpdates.get(pk);
|
|
6486
|
-
}
|
|
6487
|
-
/**
|
|
6488
|
-
* Returns all Pending Index Updates.
|
|
6489
|
-
* Does not call this method directly. It is called by the `VirtualFileSystem` instance.
|
|
6490
|
-
*/
|
|
6491
|
-
__getPendingIndexUpdates() {
|
|
6492
|
-
return this.pendingIndexUpdates;
|
|
6493
|
-
}
|
|
6494
7010
|
/**
|
|
6495
7011
|
* Acquires a write lock.
|
|
6496
7012
|
* Does not call this method directly. It is called by the `VirtualFileSystem` instance.
|
|
@@ -6518,19 +7034,22 @@ var Transaction = class {
|
|
|
6518
7034
|
* Commits the transaction.
|
|
6519
7035
|
*/
|
|
6520
7036
|
async commit() {
|
|
6521
|
-
await this.vfs.prepareCommit(this);
|
|
6522
|
-
await this.vfs.finalizeCommit(this);
|
|
6523
7037
|
await this.context.run(this, async () => {
|
|
6524
7038
|
for (const hook of this.commitHooks) {
|
|
6525
7039
|
await hook();
|
|
6526
7040
|
}
|
|
6527
7041
|
});
|
|
7042
|
+
await this.vfs.prepareCommit(this);
|
|
7043
|
+
await this.vfs.finalizeCommit(this);
|
|
6528
7044
|
this.releaseAllLocks();
|
|
6529
7045
|
}
|
|
6530
7046
|
/**
|
|
6531
7047
|
* Rolls back the transaction.
|
|
6532
7048
|
*/
|
|
6533
|
-
async rollback() {
|
|
7049
|
+
async rollback(cleanup = true) {
|
|
7050
|
+
if (this.bptreeTx) {
|
|
7051
|
+
await this.bptreeTx.rollback(cleanup);
|
|
7052
|
+
}
|
|
6534
7053
|
await this.vfs.rollback(this);
|
|
6535
7054
|
this.releaseAllLocks();
|
|
6536
7055
|
}
|
|
@@ -6669,6 +7188,8 @@ var DataplyAPI = class {
|
|
|
6669
7188
|
metadataPageManager.setMagicString(metadataPage);
|
|
6670
7189
|
metadataPageManager.setPageSize(metadataPage, options.pageSize);
|
|
6671
7190
|
metadataPageManager.setRootIndexPageId(metadataPage, -1);
|
|
7191
|
+
const order = Math.floor((options.pageSize - IndexPageManager.CONSTANT.OFFSET_KEYS_AND_VALUES + IndexPageManager.CONSTANT.SIZE_KEY) / (IndexPageManager.CONSTANT.SIZE_KEY + IndexPageManager.CONSTANT.SIZE_VALUE));
|
|
7192
|
+
metadataPageManager.setRootIndexOrder(metadataPage, order);
|
|
6672
7193
|
metadataPageManager.setBitmapPageId(metadataPage, 1);
|
|
6673
7194
|
metadataPageManager.setLastInsertPageId(metadataPage, 2);
|
|
6674
7195
|
metadataPageManager.setPageCount(metadataPage, 3);
|
|
@@ -7047,7 +7568,9 @@ var GlobalTransaction = class {
|
|
|
7047
7568
|
// Annotate the CommonJS export names for ESM import in node:
|
|
7048
7569
|
0 && (module.exports = {
|
|
7049
7570
|
BPTreeAsync,
|
|
7571
|
+
BPTreeAsyncTransaction,
|
|
7050
7572
|
BPTreeSync,
|
|
7573
|
+
BPTreeSyncTransaction,
|
|
7051
7574
|
BitmapPageManager,
|
|
7052
7575
|
CacheEntanglementAsync,
|
|
7053
7576
|
CacheEntanglementSync,
|