dataply 0.0.16-alpha.1 → 0.0.16-alpha.3
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;
|
|
@@ -525,13 +541,13 @@ var BPTree = class _BPTree {
|
|
|
525
541
|
}
|
|
526
542
|
};
|
|
527
543
|
verifierStartNode = {
|
|
528
|
-
gt: (v) => this.
|
|
529
|
-
gte: (v) => this.
|
|
530
|
-
lt: (v) => this.
|
|
531
|
-
lte: (v) => this.
|
|
532
|
-
equal: (v) => this.
|
|
544
|
+
gt: (v) => this.insertableNodeByPrimary(v),
|
|
545
|
+
gte: (v) => this.insertableNodeByPrimary(v),
|
|
546
|
+
lt: (v) => this.insertableNodeByPrimary(v),
|
|
547
|
+
lte: (v) => this.insertableRightestNodeByPrimary(v),
|
|
548
|
+
equal: (v) => this.insertableNodeByPrimary(v),
|
|
533
549
|
notEqual: (v) => this.leftestNode(),
|
|
534
|
-
or: (v) => this.
|
|
550
|
+
or: (v) => this.insertableNodeByPrimary(this.lowestPrimaryValue(this.ensureValues(v))),
|
|
535
551
|
primaryGt: (v) => this.insertableNodeByPrimary(v),
|
|
536
552
|
primaryGte: (v) => this.insertableNodeByPrimary(v),
|
|
537
553
|
primaryLt: (v) => this.insertableNodeByPrimary(v),
|
|
@@ -556,7 +572,7 @@ var BPTree = class _BPTree {
|
|
|
556
572
|
primaryGte: (v) => null,
|
|
557
573
|
primaryLt: (v) => null,
|
|
558
574
|
primaryLte: (v) => null,
|
|
559
|
-
primaryEqual: (v) =>
|
|
575
|
+
primaryEqual: (v) => this.insertableRightestEndNodeByPrimary(v),
|
|
560
576
|
primaryNotEqual: (v) => null,
|
|
561
577
|
primaryOr: (v) => this.insertableRightestEndNodeByPrimary(
|
|
562
578
|
this.highestPrimaryValue(this.ensureValues(v))
|
|
@@ -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,401 @@ 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
|
-
* @returns `true` if a read lock can be acquired, `false` otherwise.
|
|
1874
|
+
* Rolls back the transaction by clearing all buffered changes.
|
|
1875
|
+
* Internal use only.
|
|
1648
1876
|
*/
|
|
1649
|
-
|
|
1650
|
-
|
|
1651
|
-
|
|
1877
|
+
rollback() {
|
|
1878
|
+
this.txNodes.clear();
|
|
1879
|
+
this.dirtyIds.clear();
|
|
1880
|
+
this.createdInTx.clear();
|
|
1652
1881
|
}
|
|
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;
|
|
1882
|
+
// Override to do nothing, as transaction handles its own commits
|
|
1883
|
+
commitHeadBuffer() {
|
|
1662
1884
|
}
|
|
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
|
-
);
|
|
1885
|
+
commitNodeCreateBuffer() {
|
|
1697
1886
|
}
|
|
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
|
-
);
|
|
1887
|
+
commitNodeUpdateBuffer() {
|
|
1734
1888
|
}
|
|
1735
|
-
|
|
1736
|
-
|
|
1737
|
-
|
|
1738
|
-
|
|
1739
|
-
|
|
1740
|
-
|
|
1889
|
+
commitNodeDeleteBuffer() {
|
|
1890
|
+
}
|
|
1891
|
+
};
|
|
1892
|
+
var BPTreeSync = class extends BPTreeSyncBase {
|
|
1893
|
+
constructor(strategy, comparator, option) {
|
|
1894
|
+
super(strategy, comparator, option);
|
|
1895
|
+
this.init();
|
|
1741
1896
|
}
|
|
1742
1897
|
/**
|
|
1743
|
-
*
|
|
1744
|
-
* @
|
|
1898
|
+
* Creates a new synchronous transaction.
|
|
1899
|
+
* @returns A new BPTreeSyncTransaction.
|
|
1745
1900
|
*/
|
|
1746
|
-
|
|
1747
|
-
|
|
1901
|
+
createTransaction() {
|
|
1902
|
+
const tx = new BPTreeSyncTransaction(this);
|
|
1903
|
+
tx.initTransaction();
|
|
1904
|
+
return tx;
|
|
1905
|
+
}
|
|
1906
|
+
insert(key, value) {
|
|
1907
|
+
const tx = this.createTransaction();
|
|
1908
|
+
tx.insert(key, value);
|
|
1909
|
+
const { success } = tx.commit();
|
|
1910
|
+
this.init();
|
|
1911
|
+
if (!success) {
|
|
1912
|
+
throw new Error("Transaction failed: Commit failed due to conflict");
|
|
1913
|
+
}
|
|
1914
|
+
}
|
|
1915
|
+
delete(key, value) {
|
|
1916
|
+
const tx = this.createTransaction();
|
|
1917
|
+
tx.delete(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
|
+
}
|
|
1748
1923
|
}
|
|
1749
1924
|
};
|
|
1750
|
-
var
|
|
1751
|
-
lock;
|
|
1925
|
+
var BPTreeAsyncBase = class extends BPTree {
|
|
1752
1926
|
constructor(strategy, comparator, option) {
|
|
1753
1927
|
super(strategy, comparator, option);
|
|
1754
1928
|
this.nodes = this._createCachedNode();
|
|
1755
|
-
this.lock = new Ryoiki();
|
|
1756
1929
|
}
|
|
1757
1930
|
_createCachedNode() {
|
|
1758
1931
|
return new CacheEntanglementAsync(async (key) => {
|
|
@@ -1761,24 +1934,6 @@ var BPTreeAsync = class extends BPTree {
|
|
|
1761
1934
|
capacity: this.option.capacity ?? 1e3
|
|
1762
1935
|
});
|
|
1763
1936
|
}
|
|
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
1937
|
async *getPairsGenerator(value, startNode, endNode, comparator, direction, earlyTerminate) {
|
|
1783
1938
|
let node = startNode;
|
|
1784
1939
|
let done = false;
|
|
@@ -1843,7 +1998,7 @@ var BPTreeAsync = class extends BPTree {
|
|
|
1843
1998
|
}
|
|
1844
1999
|
return id;
|
|
1845
2000
|
}
|
|
1846
|
-
async _createNode(isLeaf, keys, values, leaf =
|
|
2001
|
+
async _createNode(isLeaf, keys, values, leaf = isLeaf, parent = null, next = null, prev = null) {
|
|
1847
2002
|
const id = await this._createNodeId(isLeaf);
|
|
1848
2003
|
const node = {
|
|
1849
2004
|
id,
|
|
@@ -1854,38 +2009,37 @@ var BPTreeAsync = class extends BPTree {
|
|
|
1854
2009
|
next,
|
|
1855
2010
|
prev
|
|
1856
2011
|
};
|
|
1857
|
-
this.
|
|
2012
|
+
await this.bufferForNodeCreate(node);
|
|
1858
2013
|
return node;
|
|
1859
2014
|
}
|
|
1860
2015
|
async _deleteEntry(node, key, value) {
|
|
1861
2016
|
if (!node.leaf) {
|
|
2017
|
+
let keyIndex = -1;
|
|
1862
2018
|
for (let i = 0, len = node.keys.length; i < len; i++) {
|
|
1863
|
-
|
|
1864
|
-
|
|
1865
|
-
node.keys.splice(i, 1);
|
|
1866
|
-
this.bufferForNodeUpdate(node);
|
|
2019
|
+
if (node.keys[i] === key) {
|
|
2020
|
+
keyIndex = i;
|
|
1867
2021
|
break;
|
|
1868
2022
|
}
|
|
1869
2023
|
}
|
|
1870
|
-
|
|
1871
|
-
|
|
1872
|
-
|
|
1873
|
-
|
|
1874
|
-
|
|
1875
|
-
break;
|
|
1876
|
-
}
|
|
2024
|
+
if (keyIndex !== -1) {
|
|
2025
|
+
node.keys.splice(keyIndex, 1);
|
|
2026
|
+
const valueIndex = keyIndex > 0 ? keyIndex - 1 : 0;
|
|
2027
|
+
node.values.splice(valueIndex, 1);
|
|
2028
|
+
await this.bufferForNodeUpdate(node);
|
|
1877
2029
|
}
|
|
1878
2030
|
}
|
|
1879
|
-
if (this.
|
|
2031
|
+
if (this.rootId === node.id && node.keys.length === 1 && !node.leaf) {
|
|
1880
2032
|
const keys = node.keys;
|
|
1881
|
-
this.bufferForNodeDelete(
|
|
1882
|
-
|
|
1883
|
-
this.
|
|
1884
|
-
|
|
1885
|
-
this.
|
|
2033
|
+
await this.bufferForNodeDelete(node);
|
|
2034
|
+
const newRoot = await this.getNode(keys[0]);
|
|
2035
|
+
this.rootId = newRoot.id;
|
|
2036
|
+
newRoot.parent = null;
|
|
2037
|
+
this.strategy.head.root = this.rootId;
|
|
2038
|
+
await this.bufferForNodeUpdate(newRoot);
|
|
1886
2039
|
return;
|
|
1887
|
-
} else if (this.
|
|
1888
|
-
this.
|
|
2040
|
+
} else if (this.rootId === node.id) {
|
|
2041
|
+
const root = await this.getNode(this.rootId);
|
|
2042
|
+
await this.bufferForNodeUpdate(root);
|
|
1889
2043
|
return;
|
|
1890
2044
|
} else if (node.keys.length < Math.ceil(this.order / 2) && !node.leaf || node.values.length < Math.ceil((this.order - 1) / 2) && node.leaf) {
|
|
1891
2045
|
if (node.parent === null) {
|
|
@@ -1943,33 +2097,24 @@ var BPTreeAsync = class extends BPTree {
|
|
|
1943
2097
|
pointer.values.push(guess);
|
|
1944
2098
|
} else {
|
|
1945
2099
|
pointer.next = node.next;
|
|
1946
|
-
pointer.prev = node.id;
|
|
1947
2100
|
if (pointer.next) {
|
|
1948
|
-
const n = await this.getNode(
|
|
2101
|
+
const n = await this.getNode(pointer.next);
|
|
1949
2102
|
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;
|
|
2103
|
+
await this.bufferForNodeUpdate(n);
|
|
1959
2104
|
}
|
|
1960
2105
|
}
|
|
1961
2106
|
pointer.values.push(...node.values);
|
|
1962
2107
|
if (!pointer.leaf) {
|
|
1963
2108
|
const keys = pointer.keys;
|
|
1964
2109
|
for (const key2 of keys) {
|
|
1965
|
-
const
|
|
1966
|
-
|
|
1967
|
-
this.bufferForNodeUpdate(
|
|
2110
|
+
const n = await this.getNode(key2);
|
|
2111
|
+
n.parent = pointer.id;
|
|
2112
|
+
await this.bufferForNodeUpdate(n);
|
|
1968
2113
|
}
|
|
1969
2114
|
}
|
|
1970
2115
|
await this._deleteEntry(await this.getNode(node.parent), node.id, guess);
|
|
1971
|
-
this.bufferForNodeUpdate(pointer);
|
|
1972
|
-
this.bufferForNodeDelete(node);
|
|
2116
|
+
await this.bufferForNodeUpdate(pointer);
|
|
2117
|
+
await this.bufferForNodeDelete(node);
|
|
1973
2118
|
} else {
|
|
1974
2119
|
if (isPredecessor) {
|
|
1975
2120
|
let pointerPm;
|
|
@@ -1980,13 +2125,10 @@ var BPTreeAsync = class extends BPTree {
|
|
|
1980
2125
|
node.keys = [pointerPm, ...node.keys];
|
|
1981
2126
|
node.values = [guess, ...node.values];
|
|
1982
2127
|
parentNode = await this.getNode(node.parent);
|
|
1983
|
-
|
|
1984
|
-
|
|
1985
|
-
|
|
1986
|
-
|
|
1987
|
-
this.bufferForNodeUpdate(parentNode);
|
|
1988
|
-
break;
|
|
1989
|
-
}
|
|
2128
|
+
const nodeIndex = parentNode.keys.indexOf(node.id);
|
|
2129
|
+
if (nodeIndex > 0) {
|
|
2130
|
+
parentNode.values[nodeIndex - 1] = pointerKm;
|
|
2131
|
+
await this.bufferForNodeUpdate(parentNode);
|
|
1990
2132
|
}
|
|
1991
2133
|
} else {
|
|
1992
2134
|
pointerPm = pointer.keys.splice(-1)[0];
|
|
@@ -1994,17 +2136,14 @@ var BPTreeAsync = class extends BPTree {
|
|
|
1994
2136
|
node.keys = [pointerPm, ...node.keys];
|
|
1995
2137
|
node.values = [pointerKm, ...node.values];
|
|
1996
2138
|
parentNode = await this.getNode(node.parent);
|
|
1997
|
-
|
|
1998
|
-
|
|
1999
|
-
|
|
2000
|
-
|
|
2001
|
-
this.bufferForNodeUpdate(parentNode);
|
|
2002
|
-
break;
|
|
2003
|
-
}
|
|
2139
|
+
const nodeIndex = parentNode.keys.indexOf(node.id);
|
|
2140
|
+
if (nodeIndex > 0) {
|
|
2141
|
+
parentNode.values[nodeIndex - 1] = pointerKm;
|
|
2142
|
+
await this.bufferForNodeUpdate(parentNode);
|
|
2004
2143
|
}
|
|
2005
2144
|
}
|
|
2006
|
-
this.bufferForNodeUpdate(node);
|
|
2007
|
-
this.bufferForNodeUpdate(pointer);
|
|
2145
|
+
await this.bufferForNodeUpdate(node);
|
|
2146
|
+
await this.bufferForNodeUpdate(pointer);
|
|
2008
2147
|
} else {
|
|
2009
2148
|
let pointerP0;
|
|
2010
2149
|
let pointerK0;
|
|
@@ -2014,13 +2153,10 @@ var BPTreeAsync = class extends BPTree {
|
|
|
2014
2153
|
node.keys = [...node.keys, pointerP0];
|
|
2015
2154
|
node.values = [...node.values, guess];
|
|
2016
2155
|
parentNode = await this.getNode(node.parent);
|
|
2017
|
-
|
|
2018
|
-
|
|
2019
|
-
|
|
2020
|
-
|
|
2021
|
-
this.bufferForNodeUpdate(parentNode);
|
|
2022
|
-
break;
|
|
2023
|
-
}
|
|
2156
|
+
const pointerIndex = parentNode.keys.indexOf(pointer.id);
|
|
2157
|
+
if (pointerIndex > 0) {
|
|
2158
|
+
parentNode.values[pointerIndex - 1] = pointerK0;
|
|
2159
|
+
await this.bufferForNodeUpdate(parentNode);
|
|
2024
2160
|
}
|
|
2025
2161
|
} else {
|
|
2026
2162
|
pointerP0 = pointer.keys.splice(0, 1)[0];
|
|
@@ -2028,87 +2164,85 @@ var BPTreeAsync = class extends BPTree {
|
|
|
2028
2164
|
node.keys = [...node.keys, pointerP0];
|
|
2029
2165
|
node.values = [...node.values, pointerK0];
|
|
2030
2166
|
parentNode = await this.getNode(node.parent);
|
|
2031
|
-
|
|
2032
|
-
|
|
2033
|
-
|
|
2034
|
-
|
|
2035
|
-
this.bufferForNodeUpdate(parentNode);
|
|
2036
|
-
break;
|
|
2037
|
-
}
|
|
2167
|
+
const pointerIndex = parentNode.keys.indexOf(pointer.id);
|
|
2168
|
+
if (pointerIndex > 0) {
|
|
2169
|
+
parentNode.values[pointerIndex - 1] = pointer.values[0];
|
|
2170
|
+
await this.bufferForNodeUpdate(parentNode);
|
|
2038
2171
|
}
|
|
2039
2172
|
}
|
|
2040
|
-
this.bufferForNodeUpdate(node);
|
|
2041
|
-
this.bufferForNodeUpdate(pointer);
|
|
2173
|
+
await this.bufferForNodeUpdate(node);
|
|
2174
|
+
await this.bufferForNodeUpdate(pointer);
|
|
2042
2175
|
}
|
|
2043
2176
|
if (!pointer.leaf) {
|
|
2044
|
-
|
|
2177
|
+
const keys = pointer.keys;
|
|
2178
|
+
for (const key2 of keys) {
|
|
2045
2179
|
const n = await this.getNode(key2);
|
|
2046
2180
|
n.parent = pointer.id;
|
|
2047
|
-
this.bufferForNodeUpdate(n);
|
|
2181
|
+
await this.bufferForNodeUpdate(n);
|
|
2048
2182
|
}
|
|
2049
2183
|
}
|
|
2050
2184
|
if (!node.leaf) {
|
|
2051
|
-
|
|
2185
|
+
const keys = node.keys;
|
|
2186
|
+
for (const key2 of keys) {
|
|
2052
2187
|
const n = await this.getNode(key2);
|
|
2053
2188
|
n.parent = node.id;
|
|
2054
|
-
this.bufferForNodeUpdate(n);
|
|
2189
|
+
await this.bufferForNodeUpdate(n);
|
|
2055
2190
|
}
|
|
2056
2191
|
}
|
|
2057
2192
|
if (!parentNode.leaf) {
|
|
2058
|
-
|
|
2193
|
+
const keys = parentNode.keys;
|
|
2194
|
+
for (const key2 of keys) {
|
|
2059
2195
|
const n = await this.getNode(key2);
|
|
2060
2196
|
n.parent = parentNode.id;
|
|
2061
|
-
this.bufferForNodeUpdate(n);
|
|
2197
|
+
await this.bufferForNodeUpdate(n);
|
|
2062
2198
|
}
|
|
2063
2199
|
}
|
|
2064
2200
|
}
|
|
2201
|
+
} else {
|
|
2202
|
+
await this.bufferForNodeUpdate(node);
|
|
2065
2203
|
}
|
|
2066
2204
|
}
|
|
2067
2205
|
async _insertInParent(node, value, pointer) {
|
|
2068
|
-
if (this.
|
|
2206
|
+
if (this.rootId === node.id) {
|
|
2069
2207
|
const root = await this._createNode(false, [node.id, pointer.id], [value]);
|
|
2070
|
-
this.
|
|
2208
|
+
this.rootId = root.id;
|
|
2071
2209
|
this.strategy.head.root = root.id;
|
|
2072
2210
|
node.parent = root.id;
|
|
2073
2211
|
pointer.parent = root.id;
|
|
2074
2212
|
if (pointer.leaf) {
|
|
2075
|
-
|
|
2076
|
-
|
|
2213
|
+
const nNode = node;
|
|
2214
|
+
nNode.next = pointer.id;
|
|
2215
|
+
const nPointer = pointer;
|
|
2216
|
+
nPointer.prev = node.id;
|
|
2077
2217
|
}
|
|
2078
|
-
this.bufferForNodeUpdate(node);
|
|
2079
|
-
this.bufferForNodeUpdate(pointer);
|
|
2218
|
+
await this.bufferForNodeUpdate(node);
|
|
2219
|
+
await this.bufferForNodeUpdate(pointer);
|
|
2080
2220
|
return;
|
|
2081
2221
|
}
|
|
2082
2222
|
const parentNode = await this.getNode(node.parent);
|
|
2083
|
-
|
|
2084
|
-
|
|
2085
|
-
|
|
2086
|
-
insertIndex = i + 1;
|
|
2087
|
-
} else {
|
|
2088
|
-
break;
|
|
2089
|
-
}
|
|
2223
|
+
const nodeIndex = parentNode.keys.indexOf(node.id);
|
|
2224
|
+
if (nodeIndex === -1) {
|
|
2225
|
+
throw new Error(`Node ${node.id} not found in parent ${parentNode.id}`);
|
|
2090
2226
|
}
|
|
2227
|
+
const insertIndex = nodeIndex;
|
|
2091
2228
|
parentNode.values.splice(insertIndex, 0, value);
|
|
2092
2229
|
parentNode.keys.splice(insertIndex + 1, 0, pointer.id);
|
|
2093
2230
|
pointer.parent = parentNode.id;
|
|
2094
2231
|
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);
|
|
2232
|
+
const leftSibling = node;
|
|
2233
|
+
const oldNextId = leftSibling.next;
|
|
2234
|
+
pointer.prev = leftSibling.id;
|
|
2235
|
+
pointer.next = oldNextId;
|
|
2236
|
+
leftSibling.next = pointer.id;
|
|
2237
|
+
await this.bufferForNodeUpdate(leftSibling);
|
|
2238
|
+
if (oldNextId) {
|
|
2239
|
+
const oldNext = await this.getNode(oldNextId);
|
|
2240
|
+
oldNext.prev = pointer.id;
|
|
2241
|
+
await this.bufferForNodeUpdate(oldNext);
|
|
2108
2242
|
}
|
|
2109
2243
|
}
|
|
2110
|
-
this.bufferForNodeUpdate(parentNode);
|
|
2111
|
-
this.bufferForNodeUpdate(pointer);
|
|
2244
|
+
await this.bufferForNodeUpdate(parentNode);
|
|
2245
|
+
await this.bufferForNodeUpdate(pointer);
|
|
2112
2246
|
if (parentNode.keys.length > this.order) {
|
|
2113
2247
|
const parentPointer = await this._createNode(false, [], []);
|
|
2114
2248
|
parentPointer.parent = parentNode.parent;
|
|
@@ -2119,32 +2253,34 @@ var BPTreeAsync = class extends BPTree {
|
|
|
2119
2253
|
parentNode.values = parentNode.values.slice(0, mid);
|
|
2120
2254
|
parentNode.keys = parentNode.keys.slice(0, mid + 1);
|
|
2121
2255
|
for (const k of parentNode.keys) {
|
|
2122
|
-
const
|
|
2123
|
-
|
|
2124
|
-
this.bufferForNodeUpdate(
|
|
2256
|
+
const n = await this.getNode(k);
|
|
2257
|
+
n.parent = parentNode.id;
|
|
2258
|
+
await this.bufferForNodeUpdate(n);
|
|
2125
2259
|
}
|
|
2126
2260
|
for (const k of parentPointer.keys) {
|
|
2127
|
-
const
|
|
2128
|
-
|
|
2129
|
-
this.bufferForNodeUpdate(
|
|
2261
|
+
const n = await this.getNode(k);
|
|
2262
|
+
n.parent = parentPointer.id;
|
|
2263
|
+
await this.bufferForNodeUpdate(n);
|
|
2130
2264
|
}
|
|
2131
2265
|
await this._insertInParent(parentNode, midValue, parentPointer);
|
|
2132
|
-
this.bufferForNodeUpdate(parentNode);
|
|
2266
|
+
await this.bufferForNodeUpdate(parentNode);
|
|
2133
2267
|
}
|
|
2134
2268
|
}
|
|
2135
2269
|
async init() {
|
|
2270
|
+
this.clear();
|
|
2136
2271
|
const head = await this.strategy.readHead();
|
|
2137
2272
|
if (head === null) {
|
|
2138
2273
|
this.order = this.strategy.order;
|
|
2139
|
-
|
|
2140
|
-
this.
|
|
2274
|
+
const root = await this._createNode(true, [], [], true);
|
|
2275
|
+
this.rootId = root.id;
|
|
2276
|
+
this.strategy.head.root = this.rootId;
|
|
2141
2277
|
await this.commitHeadBuffer();
|
|
2142
2278
|
await this.commitNodeCreateBuffer();
|
|
2143
2279
|
} else {
|
|
2144
2280
|
const { root, order } = head;
|
|
2145
2281
|
this.strategy.head = head;
|
|
2146
2282
|
this.order = order;
|
|
2147
|
-
this.
|
|
2283
|
+
this.rootId = root;
|
|
2148
2284
|
}
|
|
2149
2285
|
if (this.order < 3) {
|
|
2150
2286
|
throw new Error(`The 'order' parameter must be greater than 2. but got a '${this.order}'.`);
|
|
@@ -2161,43 +2297,73 @@ var BPTreeAsync = class extends BPTree {
|
|
|
2161
2297
|
return cache.raw;
|
|
2162
2298
|
}
|
|
2163
2299
|
async insertableNode(value) {
|
|
2164
|
-
let node = await this.getNode(this.
|
|
2300
|
+
let node = await this.getNode(this.rootId);
|
|
2301
|
+
if (node.parent !== null) {
|
|
2302
|
+
node.parent = null;
|
|
2303
|
+
await this.bufferForNodeUpdate(node);
|
|
2304
|
+
}
|
|
2165
2305
|
while (!node.leaf) {
|
|
2306
|
+
const parentId = node.id;
|
|
2166
2307
|
for (let i = 0, len = node.values.length; i < len; i++) {
|
|
2167
2308
|
const nValue = node.values[i];
|
|
2168
2309
|
const k = node.keys;
|
|
2169
2310
|
if (this.comparator.isSame(value, nValue)) {
|
|
2170
|
-
node = await this.getNode(
|
|
2311
|
+
node = await this.getNode(node.keys[i + 1]);
|
|
2312
|
+
if (node.parent !== parentId) {
|
|
2313
|
+
node.parent = parentId;
|
|
2314
|
+
await this.bufferForNodeUpdate(node);
|
|
2315
|
+
}
|
|
2171
2316
|
break;
|
|
2172
2317
|
} else if (this.comparator.isLower(value, nValue)) {
|
|
2173
|
-
node = await this.getNode(
|
|
2318
|
+
node = await this.getNode(node.keys[i]);
|
|
2319
|
+
if (node.parent !== parentId) {
|
|
2320
|
+
node.parent = parentId;
|
|
2321
|
+
await this.bufferForNodeUpdate(node);
|
|
2322
|
+
}
|
|
2174
2323
|
break;
|
|
2175
2324
|
} else if (i + 1 === node.values.length) {
|
|
2176
|
-
node = await this.getNode(
|
|
2325
|
+
node = await this.getNode(node.keys[i + 1]);
|
|
2326
|
+
if (node.parent !== parentId) {
|
|
2327
|
+
node.parent = parentId;
|
|
2328
|
+
await this.bufferForNodeUpdate(node);
|
|
2329
|
+
}
|
|
2177
2330
|
break;
|
|
2178
2331
|
}
|
|
2179
2332
|
}
|
|
2180
2333
|
}
|
|
2181
2334
|
return node;
|
|
2182
2335
|
}
|
|
2183
|
-
/**
|
|
2184
|
-
* Find the insertable node using primaryAsc comparison.
|
|
2185
|
-
* This allows finding nodes by primary value only, ignoring unique identifiers.
|
|
2186
|
-
*/
|
|
2187
2336
|
async insertableNodeByPrimary(value) {
|
|
2188
|
-
let node = await this.getNode(this.
|
|
2337
|
+
let node = await this.getNode(this.rootId);
|
|
2338
|
+
if (node.parent !== null) {
|
|
2339
|
+
node.parent = null;
|
|
2340
|
+
await this.bufferForNodeUpdate(node);
|
|
2341
|
+
}
|
|
2189
2342
|
while (!node.leaf) {
|
|
2343
|
+
const parentId = node.id;
|
|
2190
2344
|
for (let i = 0, len = node.values.length; i < len; i++) {
|
|
2191
2345
|
const nValue = node.values[i];
|
|
2192
2346
|
const k = node.keys;
|
|
2193
2347
|
if (this.comparator.isPrimarySame(value, nValue)) {
|
|
2194
|
-
node = await this.getNode(
|
|
2348
|
+
node = await this.getNode(node.keys[i]);
|
|
2349
|
+
if (node.parent !== parentId) {
|
|
2350
|
+
node.parent = parentId;
|
|
2351
|
+
await this.bufferForNodeUpdate(node);
|
|
2352
|
+
}
|
|
2195
2353
|
break;
|
|
2196
2354
|
} else if (this.comparator.isPrimaryLower(value, nValue)) {
|
|
2197
|
-
node = await this.getNode(
|
|
2355
|
+
node = await this.getNode(node.keys[i]);
|
|
2356
|
+
if (node.parent !== parentId) {
|
|
2357
|
+
node.parent = parentId;
|
|
2358
|
+
await this.bufferForNodeUpdate(node);
|
|
2359
|
+
}
|
|
2198
2360
|
break;
|
|
2199
2361
|
} else if (i + 1 === node.values.length) {
|
|
2200
|
-
node = await this.getNode(
|
|
2362
|
+
node = await this.getNode(node.keys[i + 1]);
|
|
2363
|
+
if (node.parent !== parentId) {
|
|
2364
|
+
node.parent = parentId;
|
|
2365
|
+
await this.bufferForNodeUpdate(node);
|
|
2366
|
+
}
|
|
2201
2367
|
break;
|
|
2202
2368
|
}
|
|
2203
2369
|
}
|
|
@@ -2205,17 +2371,30 @@ var BPTreeAsync = class extends BPTree {
|
|
|
2205
2371
|
return node;
|
|
2206
2372
|
}
|
|
2207
2373
|
async insertableRightestNodeByPrimary(value) {
|
|
2208
|
-
let node = await this.getNode(this.
|
|
2374
|
+
let node = await this.getNode(this.rootId);
|
|
2375
|
+
if (node.parent !== null) {
|
|
2376
|
+
node.parent = null;
|
|
2377
|
+
await this.bufferForNodeUpdate(node);
|
|
2378
|
+
}
|
|
2209
2379
|
while (!node.leaf) {
|
|
2380
|
+
const parentId = node.id;
|
|
2210
2381
|
for (let i = 0, len = node.values.length; i < len; i++) {
|
|
2211
2382
|
const nValue = node.values[i];
|
|
2212
2383
|
const k = node.keys;
|
|
2213
2384
|
if (this.comparator.isPrimaryLower(value, nValue)) {
|
|
2214
|
-
node = await this.getNode(
|
|
2385
|
+
node = await this.getNode(node.keys[i]);
|
|
2386
|
+
if (node.parent !== parentId) {
|
|
2387
|
+
node.parent = parentId;
|
|
2388
|
+
await this.bufferForNodeUpdate(node);
|
|
2389
|
+
}
|
|
2215
2390
|
break;
|
|
2216
2391
|
}
|
|
2217
2392
|
if (i + 1 === node.values.length) {
|
|
2218
|
-
node = await this.getNode(
|
|
2393
|
+
node = await this.getNode(node.keys[i + 1]);
|
|
2394
|
+
if (node.parent !== parentId) {
|
|
2395
|
+
node.parent = parentId;
|
|
2396
|
+
await this.bufferForNodeUpdate(node);
|
|
2397
|
+
}
|
|
2219
2398
|
break;
|
|
2220
2399
|
}
|
|
2221
2400
|
}
|
|
@@ -2249,27 +2428,75 @@ var BPTreeAsync = class extends BPTree {
|
|
|
2249
2428
|
return await this.getNode(guessNode);
|
|
2250
2429
|
}
|
|
2251
2430
|
async leftestNode() {
|
|
2252
|
-
let node = this.
|
|
2431
|
+
let node = await this.getNode(this.rootId);
|
|
2432
|
+
if (node.parent !== null) {
|
|
2433
|
+
node.parent = null;
|
|
2434
|
+
await this.bufferForNodeUpdate(node);
|
|
2435
|
+
}
|
|
2253
2436
|
while (!node.leaf) {
|
|
2437
|
+
const parentId = node.id;
|
|
2254
2438
|
const keys = node.keys;
|
|
2255
|
-
node = await this.getNode(keys[0]);
|
|
2439
|
+
node = await this.getNode(node.keys[0]);
|
|
2440
|
+
if (node.parent !== parentId) {
|
|
2441
|
+
node.parent = parentId;
|
|
2442
|
+
await this.bufferForNodeUpdate(node);
|
|
2443
|
+
}
|
|
2256
2444
|
}
|
|
2257
2445
|
return node;
|
|
2258
2446
|
}
|
|
2259
2447
|
async rightestNode() {
|
|
2260
|
-
let node = this.
|
|
2448
|
+
let node = await this.getNode(this.rootId);
|
|
2449
|
+
if (node.parent !== null) {
|
|
2450
|
+
node.parent = null;
|
|
2451
|
+
await this.bufferForNodeUpdate(node);
|
|
2452
|
+
}
|
|
2261
2453
|
while (!node.leaf) {
|
|
2454
|
+
const parentId = node.id;
|
|
2262
2455
|
const keys = node.keys;
|
|
2263
|
-
node = await this.getNode(keys[keys.length - 1]);
|
|
2456
|
+
node = await this.getNode(node.keys[node.keys.length - 1]);
|
|
2457
|
+
if (node.parent !== parentId) {
|
|
2458
|
+
node.parent = parentId;
|
|
2459
|
+
await this.bufferForNodeUpdate(node);
|
|
2460
|
+
}
|
|
2264
2461
|
}
|
|
2265
2462
|
return node;
|
|
2266
2463
|
}
|
|
2464
|
+
async exists(key, value) {
|
|
2465
|
+
const node = await this.insertableNode(value);
|
|
2466
|
+
for (let i = 0, len = node.values.length; i < len; i++) {
|
|
2467
|
+
if (this.comparator.isSame(value, node.values[i])) {
|
|
2468
|
+
const keys = node.keys[i];
|
|
2469
|
+
if (keys.includes(key)) {
|
|
2470
|
+
return true;
|
|
2471
|
+
}
|
|
2472
|
+
}
|
|
2473
|
+
}
|
|
2474
|
+
return false;
|
|
2475
|
+
}
|
|
2476
|
+
async forceUpdate(id) {
|
|
2477
|
+
if (id) {
|
|
2478
|
+
this.nodes.delete(id);
|
|
2479
|
+
await this.getNode(id);
|
|
2480
|
+
return 1;
|
|
2481
|
+
}
|
|
2482
|
+
const keys = Array.from(this.nodes.keys());
|
|
2483
|
+
for (const key of keys) {
|
|
2484
|
+
this.nodes.delete(key);
|
|
2485
|
+
}
|
|
2486
|
+
for (const key of keys) {
|
|
2487
|
+
await this.getNode(key);
|
|
2488
|
+
}
|
|
2489
|
+
return keys.length;
|
|
2490
|
+
}
|
|
2267
2491
|
async commitHeadBuffer() {
|
|
2268
2492
|
if (!this._strategyDirty) {
|
|
2269
2493
|
return;
|
|
2270
2494
|
}
|
|
2271
2495
|
this._strategyDirty = false;
|
|
2272
2496
|
await this.strategy.writeHead(this.strategy.head);
|
|
2497
|
+
if (this.strategy.head.root) {
|
|
2498
|
+
this.nodes.delete(this.strategy.head.root);
|
|
2499
|
+
}
|
|
2273
2500
|
}
|
|
2274
2501
|
async commitNodeCreateBuffer() {
|
|
2275
2502
|
for (const node of this._nodeCreateBuffer.values()) {
|
|
@@ -2280,34 +2507,26 @@ var BPTreeAsync = class extends BPTree {
|
|
|
2280
2507
|
async commitNodeUpdateBuffer() {
|
|
2281
2508
|
for (const node of this._nodeUpdateBuffer.values()) {
|
|
2282
2509
|
await this.strategy.write(node.id, node);
|
|
2510
|
+
this.nodes.delete(node.id);
|
|
2283
2511
|
}
|
|
2284
2512
|
this._nodeUpdateBuffer.clear();
|
|
2285
2513
|
}
|
|
2286
2514
|
async commitNodeDeleteBuffer() {
|
|
2287
2515
|
for (const node of this._nodeDeleteBuffer.values()) {
|
|
2288
2516
|
await this.strategy.delete(node.id);
|
|
2517
|
+
this.nodes.delete(node.id);
|
|
2289
2518
|
}
|
|
2290
2519
|
this._nodeDeleteBuffer.clear();
|
|
2291
2520
|
}
|
|
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
2521
|
async get(key) {
|
|
2300
|
-
return this.readLock(async () => {
|
|
2522
|
+
return await this.readLock(async () => {
|
|
2301
2523
|
let node = await this.leftestNode();
|
|
2302
2524
|
while (true) {
|
|
2303
|
-
|
|
2304
|
-
const
|
|
2305
|
-
for (let
|
|
2306
|
-
|
|
2307
|
-
|
|
2308
|
-
if (keys[j] === key) {
|
|
2309
|
-
return node.values[i];
|
|
2310
|
-
}
|
|
2525
|
+
for (let i = 0, len = node.values.length; i < len; i++) {
|
|
2526
|
+
const keys = node.keys[i];
|
|
2527
|
+
for (let j = 0, kLen = keys.length; j < kLen; j++) {
|
|
2528
|
+
if (keys[j] === key) {
|
|
2529
|
+
return node.values[i];
|
|
2311
2530
|
}
|
|
2312
2531
|
}
|
|
2313
2532
|
}
|
|
@@ -2376,179 +2595,85 @@ var BPTreeAsync = class extends BPTree {
|
|
|
2376
2595
|
yield pair;
|
|
2377
2596
|
count++;
|
|
2378
2597
|
if (limit !== void 0 && count >= limit) {
|
|
2379
|
-
break;
|
|
2380
|
-
}
|
|
2381
|
-
}
|
|
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 = {};
|
|
2598
|
+
break;
|
|
2599
|
+
}
|
|
2600
|
+
}
|
|
2601
|
+
}
|
|
2528
2602
|
}
|
|
2529
|
-
|
|
2530
|
-
|
|
2603
|
+
async keys(condition, filterValues) {
|
|
2604
|
+
const set = /* @__PURE__ */ new Set();
|
|
2605
|
+
for await (const key of this.keysStream(condition, filterValues)) {
|
|
2606
|
+
set.add(key);
|
|
2607
|
+
}
|
|
2608
|
+
return set;
|
|
2531
2609
|
}
|
|
2532
|
-
|
|
2533
|
-
|
|
2534
|
-
|
|
2610
|
+
async where(condition) {
|
|
2611
|
+
const map = /* @__PURE__ */ new Map();
|
|
2612
|
+
for await (const [key, value] of this.whereStream(condition)) {
|
|
2613
|
+
map.set(key, value);
|
|
2535
2614
|
}
|
|
2536
|
-
return
|
|
2615
|
+
return map;
|
|
2537
2616
|
}
|
|
2538
|
-
|
|
2539
|
-
this.
|
|
2617
|
+
async insert(key, value) {
|
|
2618
|
+
await this.writeLock(async () => {
|
|
2619
|
+
const before = await this.insertableNode(value);
|
|
2620
|
+
await this._insertAtLeaf(before, key, value);
|
|
2621
|
+
if (before.values.length === this.order) {
|
|
2622
|
+
const after = await this._createNode(
|
|
2623
|
+
true,
|
|
2624
|
+
[],
|
|
2625
|
+
[],
|
|
2626
|
+
true,
|
|
2627
|
+
before.parent,
|
|
2628
|
+
null,
|
|
2629
|
+
null
|
|
2630
|
+
);
|
|
2631
|
+
const mid = Math.ceil(this.order / 2) - 1;
|
|
2632
|
+
after.values = before.values.slice(mid + 1);
|
|
2633
|
+
after.keys = before.keys.slice(mid + 1);
|
|
2634
|
+
before.values = before.values.slice(0, mid + 1);
|
|
2635
|
+
before.keys = before.keys.slice(0, mid + 1);
|
|
2636
|
+
await this._insertInParent(before, after.values[0], after);
|
|
2637
|
+
await this.bufferForNodeUpdate(before);
|
|
2638
|
+
}
|
|
2639
|
+
await this.commitHeadBuffer();
|
|
2640
|
+
await this.commitNodeCreateBuffer();
|
|
2641
|
+
await this.commitNodeUpdateBuffer();
|
|
2642
|
+
});
|
|
2540
2643
|
}
|
|
2541
|
-
delete(
|
|
2542
|
-
|
|
2644
|
+
async delete(key, value) {
|
|
2645
|
+
await this.writeLock(async () => {
|
|
2646
|
+
const node = await this.insertableNode(value);
|
|
2647
|
+
let i = node.values.length;
|
|
2648
|
+
while (i--) {
|
|
2649
|
+
const nValue = node.values[i];
|
|
2650
|
+
if (this.comparator.isSame(value, nValue)) {
|
|
2651
|
+
const keys = node.keys[i];
|
|
2652
|
+
const keyIndex = keys.indexOf(key);
|
|
2653
|
+
if (keyIndex !== -1) {
|
|
2654
|
+
keys.splice(keyIndex, 1);
|
|
2655
|
+
if (keys.length === 0) {
|
|
2656
|
+
node.keys.splice(i, 1);
|
|
2657
|
+
node.values.splice(i, 1);
|
|
2658
|
+
}
|
|
2659
|
+
await this._deleteEntry(node, key, value);
|
|
2660
|
+
await this.bufferForNodeUpdate(node);
|
|
2661
|
+
break;
|
|
2662
|
+
}
|
|
2663
|
+
}
|
|
2664
|
+
}
|
|
2665
|
+
await this.commitHeadBuffer();
|
|
2666
|
+
await this.commitNodeCreateBuffer();
|
|
2667
|
+
await this.commitNodeUpdateBuffer();
|
|
2668
|
+
await this.commitNodeDeleteBuffer();
|
|
2669
|
+
});
|
|
2543
2670
|
}
|
|
2544
|
-
|
|
2545
|
-
|
|
2546
|
-
return null;
|
|
2547
|
-
}
|
|
2548
|
-
return this.head;
|
|
2671
|
+
getHeadData() {
|
|
2672
|
+
return this.strategy.head.data;
|
|
2549
2673
|
}
|
|
2550
|
-
|
|
2551
|
-
this.head =
|
|
2674
|
+
async setHeadData(data) {
|
|
2675
|
+
this.strategy.head.data = data;
|
|
2676
|
+
await this.strategy.writeHead(this.strategy.head);
|
|
2552
2677
|
}
|
|
2553
2678
|
};
|
|
2554
2679
|
var SerializeStrategyAsync = class extends SerializeStrategy {
|
|
@@ -2568,6 +2693,14 @@ var SerializeStrategyAsync = class extends SerializeStrategy {
|
|
|
2568
2693
|
await this.setHeadData(key, next);
|
|
2569
2694
|
return current;
|
|
2570
2695
|
}
|
|
2696
|
+
async compareAndSwapHead(oldRoot, newRoot) {
|
|
2697
|
+
if (this.head.root !== oldRoot) {
|
|
2698
|
+
return false;
|
|
2699
|
+
}
|
|
2700
|
+
this.head.root = newRoot;
|
|
2701
|
+
await this.writeHead(this.head);
|
|
2702
|
+
return true;
|
|
2703
|
+
}
|
|
2571
2704
|
};
|
|
2572
2705
|
var InMemoryStoreStrategyAsync = class extends SerializeStrategyAsync {
|
|
2573
2706
|
node;
|
|
@@ -2582,7 +2715,8 @@ var InMemoryStoreStrategyAsync = class extends SerializeStrategyAsync {
|
|
|
2582
2715
|
if (!Object.hasOwn(this.node, id)) {
|
|
2583
2716
|
throw new Error(`The tree attempted to reference node '${id}', but couldn't find the corresponding node.`);
|
|
2584
2717
|
}
|
|
2585
|
-
|
|
2718
|
+
const node = this.node[id];
|
|
2719
|
+
return JSON.parse(JSON.stringify(node));
|
|
2586
2720
|
}
|
|
2587
2721
|
async write(id, node) {
|
|
2588
2722
|
this.node[id] = node;
|
|
@@ -2600,9 +2734,332 @@ var InMemoryStoreStrategyAsync = class extends SerializeStrategyAsync {
|
|
|
2600
2734
|
this.head = head;
|
|
2601
2735
|
}
|
|
2602
2736
|
};
|
|
2737
|
+
var BPTreeAsyncSnapshotStrategy = class extends SerializeStrategyAsync {
|
|
2738
|
+
baseStrategy;
|
|
2739
|
+
snapshotHead;
|
|
2740
|
+
constructor(baseStrategy, root) {
|
|
2741
|
+
super(baseStrategy.order);
|
|
2742
|
+
this.baseStrategy = baseStrategy;
|
|
2743
|
+
this.snapshotHead = {
|
|
2744
|
+
...baseStrategy.head,
|
|
2745
|
+
root,
|
|
2746
|
+
data: { ...baseStrategy.head.data }
|
|
2747
|
+
};
|
|
2748
|
+
this.head = this.snapshotHead;
|
|
2749
|
+
}
|
|
2750
|
+
async id(isLeaf) {
|
|
2751
|
+
return await this.baseStrategy.id(isLeaf);
|
|
2752
|
+
}
|
|
2753
|
+
async read(id) {
|
|
2754
|
+
return await this.baseStrategy.read(id);
|
|
2755
|
+
}
|
|
2756
|
+
async write(id, node) {
|
|
2757
|
+
await this.baseStrategy.write(id, node);
|
|
2758
|
+
}
|
|
2759
|
+
async delete(id) {
|
|
2760
|
+
await this.baseStrategy.delete(id);
|
|
2761
|
+
}
|
|
2762
|
+
async readHead() {
|
|
2763
|
+
return this.snapshotHead;
|
|
2764
|
+
}
|
|
2765
|
+
async writeHead(head) {
|
|
2766
|
+
this.snapshotHead.root = head.root;
|
|
2767
|
+
this.snapshotHead.data = { ...head.data };
|
|
2768
|
+
}
|
|
2769
|
+
async compareAndSwapHead(oldRoot, newRoot) {
|
|
2770
|
+
return await this.baseStrategy.compareAndSwapHead(oldRoot, newRoot);
|
|
2771
|
+
}
|
|
2772
|
+
async getHeadData(key, defaultValue) {
|
|
2773
|
+
return this.snapshotHead.data[key] ?? defaultValue;
|
|
2774
|
+
}
|
|
2775
|
+
async setHeadData(key, data) {
|
|
2776
|
+
this.snapshotHead.data[key] = data;
|
|
2777
|
+
}
|
|
2778
|
+
async autoIncrement(key, defaultValue) {
|
|
2779
|
+
return this.snapshotHead.data[key] ?? defaultValue;
|
|
2780
|
+
}
|
|
2781
|
+
};
|
|
2782
|
+
var BPTreeAsyncTransaction = class extends BPTreeAsyncBase {
|
|
2783
|
+
realBaseTree;
|
|
2784
|
+
realBaseStrategy;
|
|
2785
|
+
txNodes = /* @__PURE__ */ new Map();
|
|
2786
|
+
dirtyIds;
|
|
2787
|
+
createdInTx;
|
|
2788
|
+
deletedIds;
|
|
2789
|
+
initialRootId;
|
|
2790
|
+
transactionRootId;
|
|
2791
|
+
constructor(baseTree) {
|
|
2792
|
+
super(baseTree.strategy, baseTree.comparator, baseTree.option);
|
|
2793
|
+
this.realBaseTree = baseTree;
|
|
2794
|
+
this.realBaseStrategy = baseTree.strategy;
|
|
2795
|
+
this.order = baseTree.getOrder();
|
|
2796
|
+
this.initialRootId = "";
|
|
2797
|
+
this.transactionRootId = "";
|
|
2798
|
+
this.dirtyIds = /* @__PURE__ */ new Set();
|
|
2799
|
+
this.createdInTx = /* @__PURE__ */ new Set();
|
|
2800
|
+
this.deletedIds = /* @__PURE__ */ new Set();
|
|
2801
|
+
}
|
|
2802
|
+
/**
|
|
2803
|
+
* Initializes the transaction by capturing the current state of the tree.
|
|
2804
|
+
*/
|
|
2805
|
+
async initTransaction() {
|
|
2806
|
+
const head = await this.realBaseStrategy.readHead();
|
|
2807
|
+
if (head) {
|
|
2808
|
+
this.order = head.order;
|
|
2809
|
+
this.initialRootId = head.root;
|
|
2810
|
+
} else {
|
|
2811
|
+
this.initialRootId = this.realBaseTree.getRootId();
|
|
2812
|
+
}
|
|
2813
|
+
if (!this.initialRootId) {
|
|
2814
|
+
const root = await this._createNode(true, [], [], true);
|
|
2815
|
+
this.initialRootId = root.id;
|
|
2816
|
+
}
|
|
2817
|
+
this.transactionRootId = this.initialRootId;
|
|
2818
|
+
this.rootId = this.transactionRootId;
|
|
2819
|
+
const snapshotStrategy = new BPTreeAsyncSnapshotStrategy(this.realBaseStrategy, this.initialRootId);
|
|
2820
|
+
this.strategy = snapshotStrategy;
|
|
2821
|
+
this.txNodes.clear();
|
|
2822
|
+
this.dirtyIds.clear();
|
|
2823
|
+
this.createdInTx.clear();
|
|
2824
|
+
this.deletedIds.clear();
|
|
2825
|
+
}
|
|
2826
|
+
async getNode(id) {
|
|
2827
|
+
if (this.txNodes.has(id)) {
|
|
2828
|
+
return this.txNodes.get(id);
|
|
2829
|
+
}
|
|
2830
|
+
if (this.deletedIds.has(id)) {
|
|
2831
|
+
throw new Error(`The tree attempted to reference deleted node '${id}'`);
|
|
2832
|
+
}
|
|
2833
|
+
const baseNode = await this.realBaseStrategy.read(id);
|
|
2834
|
+
const clone = JSON.parse(JSON.stringify(baseNode));
|
|
2835
|
+
this.txNodes.set(id, clone);
|
|
2836
|
+
return clone;
|
|
2837
|
+
}
|
|
2838
|
+
async bufferForNodeUpdate(node) {
|
|
2839
|
+
if (this.dirtyIds.has(node.id) && this.txNodes.has(node.id) && node._p) {
|
|
2840
|
+
this.txNodes.set(node.id, node);
|
|
2841
|
+
return;
|
|
2842
|
+
}
|
|
2843
|
+
node._p = true;
|
|
2844
|
+
this.txNodes.set(node.id, node);
|
|
2845
|
+
this.dirtyIds.add(node.id);
|
|
2846
|
+
if (node.leaf) {
|
|
2847
|
+
if (node.next && !this.dirtyIds.has(node.next) && !this.deletedIds.has(node.next)) {
|
|
2848
|
+
try {
|
|
2849
|
+
await this.bufferForNodeUpdate(await this.getNode(node.next));
|
|
2850
|
+
} catch (e) {
|
|
2851
|
+
}
|
|
2852
|
+
}
|
|
2853
|
+
if (node.prev && !this.dirtyIds.has(node.prev) && !this.deletedIds.has(node.prev)) {
|
|
2854
|
+
try {
|
|
2855
|
+
await this.bufferForNodeUpdate(await this.getNode(node.prev));
|
|
2856
|
+
} catch (e) {
|
|
2857
|
+
}
|
|
2858
|
+
}
|
|
2859
|
+
}
|
|
2860
|
+
await this.markPathDirty(node);
|
|
2861
|
+
delete node._p;
|
|
2862
|
+
}
|
|
2863
|
+
async bufferForNodeCreate(node) {
|
|
2864
|
+
this.txNodes.set(node.id, node);
|
|
2865
|
+
this.dirtyIds.add(node.id);
|
|
2866
|
+
this.createdInTx.add(node.id);
|
|
2867
|
+
if (node.leaf) {
|
|
2868
|
+
if (node.next && !this.dirtyIds.has(node.next) && !this.deletedIds.has(node.next)) {
|
|
2869
|
+
try {
|
|
2870
|
+
await this.bufferForNodeUpdate(await this.getNode(node.next));
|
|
2871
|
+
} catch (e) {
|
|
2872
|
+
}
|
|
2873
|
+
}
|
|
2874
|
+
if (node.prev && !this.dirtyIds.has(node.prev) && !this.deletedIds.has(node.prev)) {
|
|
2875
|
+
try {
|
|
2876
|
+
await this.bufferForNodeUpdate(await this.getNode(node.prev));
|
|
2877
|
+
} catch (e) {
|
|
2878
|
+
}
|
|
2879
|
+
}
|
|
2880
|
+
}
|
|
2881
|
+
await this.markPathDirty(node);
|
|
2882
|
+
}
|
|
2883
|
+
async bufferForNodeDelete(node) {
|
|
2884
|
+
this.txNodes.delete(node.id);
|
|
2885
|
+
this.dirtyIds.add(node.id);
|
|
2886
|
+
this.deletedIds.add(node.id);
|
|
2887
|
+
}
|
|
2888
|
+
async markPathDirty(node) {
|
|
2889
|
+
let curr = node;
|
|
2890
|
+
while (curr.parent) {
|
|
2891
|
+
if (this.deletedIds.has(curr.parent)) {
|
|
2892
|
+
break;
|
|
2893
|
+
}
|
|
2894
|
+
if (this.dirtyIds.has(curr.parent) && this.txNodes.has(curr.parent)) {
|
|
2895
|
+
break;
|
|
2896
|
+
}
|
|
2897
|
+
const parent = await this.getNode(curr.parent);
|
|
2898
|
+
this.dirtyIds.add(parent.id);
|
|
2899
|
+
curr = parent;
|
|
2900
|
+
}
|
|
2901
|
+
if (!curr.parent) {
|
|
2902
|
+
this.transactionRootId = curr.id;
|
|
2903
|
+
}
|
|
2904
|
+
}
|
|
2905
|
+
async _createNode(isLeaf, keys, values, leaf = isLeaf, parent = null, next = null, prev = null) {
|
|
2906
|
+
const id = await this.strategy.id(isLeaf);
|
|
2907
|
+
const node = {
|
|
2908
|
+
id,
|
|
2909
|
+
keys,
|
|
2910
|
+
values,
|
|
2911
|
+
leaf,
|
|
2912
|
+
parent,
|
|
2913
|
+
next,
|
|
2914
|
+
prev
|
|
2915
|
+
};
|
|
2916
|
+
await this.bufferForNodeCreate(node);
|
|
2917
|
+
return node;
|
|
2918
|
+
}
|
|
2919
|
+
/**
|
|
2920
|
+
* Attempts to commit the transaction.
|
|
2921
|
+
* Uses Optimistic Locking (Compare-And-Swap) on the root node ID to detect conflicts.
|
|
2922
|
+
*
|
|
2923
|
+
* @returns A promise that resolves to the transaction result.
|
|
2924
|
+
*/
|
|
2925
|
+
async commit() {
|
|
2926
|
+
const idMapping = /* @__PURE__ */ new Map();
|
|
2927
|
+
const finalNodes = [];
|
|
2928
|
+
for (const oldId of this.dirtyIds) {
|
|
2929
|
+
if (this.createdInTx.has(oldId)) {
|
|
2930
|
+
idMapping.set(oldId, oldId);
|
|
2931
|
+
} else {
|
|
2932
|
+
const node = this.txNodes.get(oldId);
|
|
2933
|
+
if (node) {
|
|
2934
|
+
const newId = await this.realBaseStrategy.id(node.leaf);
|
|
2935
|
+
idMapping.set(oldId, newId);
|
|
2936
|
+
}
|
|
2937
|
+
}
|
|
2938
|
+
}
|
|
2939
|
+
const newCreatedIds = [];
|
|
2940
|
+
for (const oldId of this.dirtyIds) {
|
|
2941
|
+
const node = this.txNodes.get(oldId);
|
|
2942
|
+
if (!node) continue;
|
|
2943
|
+
const newId = idMapping.get(oldId);
|
|
2944
|
+
node.id = newId;
|
|
2945
|
+
if (node.parent && idMapping.has(node.parent)) {
|
|
2946
|
+
node.parent = idMapping.get(node.parent);
|
|
2947
|
+
}
|
|
2948
|
+
if (!node.leaf) {
|
|
2949
|
+
const internal = node;
|
|
2950
|
+
for (let i = 0; i < internal.keys.length; i++) {
|
|
2951
|
+
const childId = internal.keys[i];
|
|
2952
|
+
if (idMapping.has(childId)) {
|
|
2953
|
+
internal.keys[i] = idMapping.get(childId);
|
|
2954
|
+
}
|
|
2955
|
+
}
|
|
2956
|
+
}
|
|
2957
|
+
if (node.leaf) {
|
|
2958
|
+
const leaf = node;
|
|
2959
|
+
if (leaf.next && idMapping.has(leaf.next)) {
|
|
2960
|
+
leaf.next = idMapping.get(leaf.next);
|
|
2961
|
+
}
|
|
2962
|
+
if (leaf.prev && idMapping.has(leaf.prev)) {
|
|
2963
|
+
leaf.prev = idMapping.get(leaf.prev);
|
|
2964
|
+
}
|
|
2965
|
+
}
|
|
2966
|
+
finalNodes.push(node);
|
|
2967
|
+
newCreatedIds.push(newId);
|
|
2968
|
+
}
|
|
2969
|
+
let newRootId = this.rootId;
|
|
2970
|
+
if (idMapping.has(this.rootId)) {
|
|
2971
|
+
newRootId = idMapping.get(this.rootId);
|
|
2972
|
+
}
|
|
2973
|
+
for (const node of finalNodes) {
|
|
2974
|
+
await this.realBaseStrategy.write(node.id, node);
|
|
2975
|
+
}
|
|
2976
|
+
const success = await this.realBaseStrategy.compareAndSwapHead(this.initialRootId, newRootId);
|
|
2977
|
+
if (success) {
|
|
2978
|
+
const distinctObsolete = /* @__PURE__ */ new Set();
|
|
2979
|
+
for (const oldId of this.dirtyIds) {
|
|
2980
|
+
if (!this.createdInTx.has(oldId) && this.txNodes.has(oldId)) {
|
|
2981
|
+
distinctObsolete.add(oldId);
|
|
2982
|
+
}
|
|
2983
|
+
}
|
|
2984
|
+
return {
|
|
2985
|
+
success: true,
|
|
2986
|
+
createdIds: newCreatedIds,
|
|
2987
|
+
obsoleteIds: Array.from(distinctObsolete)
|
|
2988
|
+
};
|
|
2989
|
+
} else {
|
|
2990
|
+
await this.rollback();
|
|
2991
|
+
return {
|
|
2992
|
+
success: false,
|
|
2993
|
+
createdIds: newCreatedIds,
|
|
2994
|
+
obsoleteIds: []
|
|
2995
|
+
};
|
|
2996
|
+
}
|
|
2997
|
+
}
|
|
2998
|
+
/**
|
|
2999
|
+
* Rolls back the transaction by clearing all buffered changes.
|
|
3000
|
+
* Internal use only.
|
|
3001
|
+
*/
|
|
3002
|
+
async rollback() {
|
|
3003
|
+
this.txNodes.clear();
|
|
3004
|
+
this.dirtyIds.clear();
|
|
3005
|
+
this.createdInTx.clear();
|
|
3006
|
+
}
|
|
3007
|
+
async readLock(fn) {
|
|
3008
|
+
return await fn();
|
|
3009
|
+
}
|
|
3010
|
+
async writeLock(fn) {
|
|
3011
|
+
return await fn();
|
|
3012
|
+
}
|
|
3013
|
+
async commitHeadBuffer() {
|
|
3014
|
+
}
|
|
3015
|
+
async commitNodeCreateBuffer() {
|
|
3016
|
+
}
|
|
3017
|
+
async commitNodeUpdateBuffer() {
|
|
3018
|
+
}
|
|
3019
|
+
async commitNodeDeleteBuffer() {
|
|
3020
|
+
}
|
|
3021
|
+
};
|
|
3022
|
+
var BPTreeAsync = class extends BPTreeAsyncBase {
|
|
3023
|
+
constructor(strategy, comparator, option) {
|
|
3024
|
+
super(strategy, comparator, option);
|
|
3025
|
+
}
|
|
3026
|
+
/**
|
|
3027
|
+
* Creates a new asynchronous transaction.
|
|
3028
|
+
* @returns A promise that resolves to a new BPTreeAsyncTransaction.
|
|
3029
|
+
*/
|
|
3030
|
+
async createTransaction() {
|
|
3031
|
+
const tx = new BPTreeAsyncTransaction(this);
|
|
3032
|
+
await tx.initTransaction();
|
|
3033
|
+
return tx;
|
|
3034
|
+
}
|
|
3035
|
+
async insert(key, value) {
|
|
3036
|
+
const tx = await this.createTransaction();
|
|
3037
|
+
await tx.insert(key, value);
|
|
3038
|
+
const { success } = await tx.commit();
|
|
3039
|
+
await this.init();
|
|
3040
|
+
if (!success) {
|
|
3041
|
+
throw new Error("Transaction failed: Commit failed due to conflict");
|
|
3042
|
+
}
|
|
3043
|
+
}
|
|
3044
|
+
async delete(key, value) {
|
|
3045
|
+
const tx = await this.createTransaction();
|
|
3046
|
+
await tx.delete(key, value);
|
|
3047
|
+
const { success } = await tx.commit();
|
|
3048
|
+
await this.init();
|
|
3049
|
+
if (!success) {
|
|
3050
|
+
throw new Error("Transaction failed: Commit failed due to conflict");
|
|
3051
|
+
}
|
|
3052
|
+
}
|
|
3053
|
+
async readLock(fn) {
|
|
3054
|
+
return await fn();
|
|
3055
|
+
}
|
|
3056
|
+
async writeLock(fn) {
|
|
3057
|
+
return await fn();
|
|
3058
|
+
}
|
|
3059
|
+
};
|
|
2603
3060
|
|
|
2604
3061
|
// node_modules/ryoiki/dist/esm/index.mjs
|
|
2605
|
-
var
|
|
3062
|
+
var Ryoiki = class _Ryoiki {
|
|
2606
3063
|
readings;
|
|
2607
3064
|
writings;
|
|
2608
3065
|
readQueue;
|
|
@@ -2646,7 +3103,7 @@ var Ryoiki2 = class _Ryoiki2 {
|
|
|
2646
3103
|
return [start, start + length];
|
|
2647
3104
|
}
|
|
2648
3105
|
rangeOverlapping(tasks, range) {
|
|
2649
|
-
return Array.from(tasks.values()).some((t) =>
|
|
3106
|
+
return Array.from(tasks.values()).some((t) => _Ryoiki.IsRangeOverlap(t.range, range));
|
|
2650
3107
|
}
|
|
2651
3108
|
isSameRange(a, b) {
|
|
2652
3109
|
const [a1, a2] = a;
|
|
@@ -2687,7 +3144,7 @@ var Ryoiki2 = class _Ryoiki2 {
|
|
|
2687
3144
|
_alloc(queue, workspaces, lockId) {
|
|
2688
3145
|
const unit = queue.get(lockId);
|
|
2689
3146
|
if (!unit) {
|
|
2690
|
-
throw
|
|
3147
|
+
throw _Ryoiki.ERR_NOT_EXISTS(lockId);
|
|
2691
3148
|
}
|
|
2692
3149
|
workspaces.set(lockId, unit);
|
|
2693
3150
|
queue.delete(lockId);
|
|
@@ -2696,7 +3153,7 @@ var Ryoiki2 = class _Ryoiki2 {
|
|
|
2696
3153
|
_free(workspaces, lockId) {
|
|
2697
3154
|
const unit = workspaces.get(lockId);
|
|
2698
3155
|
if (!unit) {
|
|
2699
|
-
throw
|
|
3156
|
+
throw _Ryoiki.ERR_NOT_EXISTS(lockId);
|
|
2700
3157
|
}
|
|
2701
3158
|
workspaces.delete(lockId);
|
|
2702
3159
|
unit.free();
|
|
@@ -2706,7 +3163,7 @@ var Ryoiki2 = class _Ryoiki2 {
|
|
|
2706
3163
|
let timeoutId = null;
|
|
2707
3164
|
if (timeout >= 0) {
|
|
2708
3165
|
timeoutId = setTimeout(() => {
|
|
2709
|
-
reject(
|
|
3166
|
+
reject(_Ryoiki.ERR_TIMEOUT(id, timeout));
|
|
2710
3167
|
}, timeout);
|
|
2711
3168
|
}
|
|
2712
3169
|
const id = this._createRandomId();
|
|
@@ -2714,7 +3171,7 @@ var Ryoiki2 = class _Ryoiki2 {
|
|
|
2714
3171
|
if (timeoutId !== null) {
|
|
2715
3172
|
clearTimeout(timeoutId);
|
|
2716
3173
|
}
|
|
2717
|
-
const [err, v] = await
|
|
3174
|
+
const [err, v] = await _Ryoiki.CatchError(task(id));
|
|
2718
3175
|
if (err) reject(err);
|
|
2719
3176
|
else resolve(v);
|
|
2720
3177
|
};
|
|
@@ -2729,7 +3186,7 @@ var Ryoiki2 = class _Ryoiki2 {
|
|
|
2729
3186
|
_checkWorking(range, workspaces) {
|
|
2730
3187
|
let isLocked = false;
|
|
2731
3188
|
for (const lock of workspaces.values()) {
|
|
2732
|
-
if (
|
|
3189
|
+
if (_Ryoiki.IsRangeOverlap(range, lock.range)) {
|
|
2733
3190
|
isLocked = true;
|
|
2734
3191
|
break;
|
|
2735
3192
|
}
|
|
@@ -5840,8 +6297,11 @@ var RowIdentifierStrategy = class extends SerializeStrategyAsync {
|
|
|
5840
6297
|
if (node.leaf) {
|
|
5841
6298
|
const n = node;
|
|
5842
6299
|
const keys = new Array(n.keys.length);
|
|
5843
|
-
|
|
6300
|
+
let i = 0;
|
|
6301
|
+
const len = keys.length;
|
|
6302
|
+
while (i < len) {
|
|
5844
6303
|
keys[i] = +n.keys[i][0];
|
|
6304
|
+
i++;
|
|
5845
6305
|
}
|
|
5846
6306
|
this.indexPageManger.setIndexId(page, +n.id);
|
|
5847
6307
|
this.indexPageManger.setParentIndexId(page, +n.parent);
|
|
@@ -5854,8 +6314,11 @@ var RowIdentifierStrategy = class extends SerializeStrategyAsync {
|
|
|
5854
6314
|
} else {
|
|
5855
6315
|
const n = node;
|
|
5856
6316
|
const keys = new Array(n.keys.length);
|
|
5857
|
-
|
|
6317
|
+
let i = 0;
|
|
6318
|
+
const len = keys.length;
|
|
6319
|
+
while (i < len) {
|
|
5858
6320
|
keys[i] = +n.keys[i];
|
|
6321
|
+
i++;
|
|
5859
6322
|
}
|
|
5860
6323
|
this.indexPageManger.setIndexId(page, +n.id);
|
|
5861
6324
|
this.indexPageManger.setParentIndexId(page, +n.parent);
|
|
@@ -5890,9 +6353,11 @@ var RowIdentifierStrategy = class extends SerializeStrategyAsync {
|
|
|
5890
6353
|
if (rootIndexPageId === -1) {
|
|
5891
6354
|
return null;
|
|
5892
6355
|
}
|
|
6356
|
+
const metaOrder = manager.getRootIndexOrder(metadataPage);
|
|
6357
|
+
const order = metaOrder || this.order;
|
|
5893
6358
|
return {
|
|
5894
|
-
root:
|
|
5895
|
-
order
|
|
6359
|
+
root: rootIndexPageId.toString(),
|
|
6360
|
+
order,
|
|
5896
6361
|
data: {}
|
|
5897
6362
|
};
|
|
5898
6363
|
}
|
|
@@ -5979,8 +6444,9 @@ var RowTableEngine = class {
|
|
|
5979
6444
|
this.pageIdBuffer = new Uint8Array(DataPageManager.CONSTANT.SIZE_PAGE_ID);
|
|
5980
6445
|
this.maxBodySize = this.pfs.pageSize - DataPageManager.CONSTANT.SIZE_PAGE_HEADER;
|
|
5981
6446
|
this.order = this.getOptimalOrder(pfs.pageSize, IndexPageManager.CONSTANT.SIZE_KEY, IndexPageManager.CONSTANT.SIZE_VALUE);
|
|
6447
|
+
this.strategy = new RowIdentifierStrategy(this.order, pfs, txContext);
|
|
5982
6448
|
this.bptree = new BPTreeAsync(
|
|
5983
|
-
|
|
6449
|
+
this.strategy,
|
|
5984
6450
|
new NumericComparator(),
|
|
5985
6451
|
{
|
|
5986
6452
|
capacity: this.options.pageCacheCapacity
|
|
@@ -5988,6 +6454,7 @@ var RowTableEngine = class {
|
|
|
5988
6454
|
);
|
|
5989
6455
|
}
|
|
5990
6456
|
bptree;
|
|
6457
|
+
strategy;
|
|
5991
6458
|
order;
|
|
5992
6459
|
factory;
|
|
5993
6460
|
metadataPageManager;
|
|
@@ -5999,6 +6466,35 @@ var RowTableEngine = class {
|
|
|
5999
6466
|
ridBuffer;
|
|
6000
6467
|
pageIdBuffer;
|
|
6001
6468
|
initialized = false;
|
|
6469
|
+
/**
|
|
6470
|
+
* Retrieves the BPTree transaction associated with the given transaction.
|
|
6471
|
+
* If it doesn't exist, it creates a new one and registers commit/rollback hooks.
|
|
6472
|
+
* @param tx Dataply transaction
|
|
6473
|
+
* @returns BPTree transaction
|
|
6474
|
+
*/
|
|
6475
|
+
async getBPTreeTransaction(tx) {
|
|
6476
|
+
let btx = tx.__getBPTreeTransaction();
|
|
6477
|
+
if (!btx) {
|
|
6478
|
+
btx = await this.bptree.createTransaction();
|
|
6479
|
+
tx.__setBPTreeTransaction(btx);
|
|
6480
|
+
tx.onCommit(async () => {
|
|
6481
|
+
if (!tx.__isBPTreeDirty()) {
|
|
6482
|
+
return;
|
|
6483
|
+
}
|
|
6484
|
+
if (!btx) return;
|
|
6485
|
+
const result = await btx.commit();
|
|
6486
|
+
if (result.success) {
|
|
6487
|
+
await this.bptree.init();
|
|
6488
|
+
for (const id of result.obsoleteIds) {
|
|
6489
|
+
await this.strategy.delete(id);
|
|
6490
|
+
}
|
|
6491
|
+
} else {
|
|
6492
|
+
throw new Error(`BPTree transaction commit failed. Current Root: ${this.bptree.getRootId()}`);
|
|
6493
|
+
}
|
|
6494
|
+
});
|
|
6495
|
+
}
|
|
6496
|
+
return btx;
|
|
6497
|
+
}
|
|
6002
6498
|
/**
|
|
6003
6499
|
* Initializes the B+ Tree.
|
|
6004
6500
|
*/
|
|
@@ -6128,7 +6624,9 @@ var RowTableEngine = class {
|
|
|
6128
6624
|
this.metadataPageManager.setRowCount(freshMetadataPage, currentRowCount + 1);
|
|
6129
6625
|
}
|
|
6130
6626
|
await this.pfs.setMetadata(freshMetadataPage, tx);
|
|
6131
|
-
await this.
|
|
6627
|
+
const btx = await this.getBPTreeTransaction(tx);
|
|
6628
|
+
await btx.insert(this.getRID(), pk);
|
|
6629
|
+
tx.__markBPTreeDirty();
|
|
6132
6630
|
return pk;
|
|
6133
6631
|
}
|
|
6134
6632
|
/**
|
|
@@ -6139,11 +6637,8 @@ var RowTableEngine = class {
|
|
|
6139
6637
|
* @returns RID or null (if not found)
|
|
6140
6638
|
*/
|
|
6141
6639
|
async getRidByPK(pk, tx) {
|
|
6142
|
-
const
|
|
6143
|
-
|
|
6144
|
-
return pendingUpdate.newRid;
|
|
6145
|
-
}
|
|
6146
|
-
const keys = await this.bptree.keys({ equal: pk });
|
|
6640
|
+
const btx = await this.getBPTreeTransaction(tx);
|
|
6641
|
+
const keys = await btx.keys({ equal: pk });
|
|
6147
6642
|
if (keys.size === 0) {
|
|
6148
6643
|
return null;
|
|
6149
6644
|
}
|
|
@@ -6162,6 +6657,7 @@ var RowTableEngine = class {
|
|
|
6162
6657
|
* @param tx Transaction
|
|
6163
6658
|
*/
|
|
6164
6659
|
async update(pk, data, tx) {
|
|
6660
|
+
await tx.__acquireWriteLock(0);
|
|
6165
6661
|
const rid = await this.getRidByPK(pk, tx);
|
|
6166
6662
|
if (rid === null) {
|
|
6167
6663
|
return;
|
|
@@ -6231,16 +6727,10 @@ var RowTableEngine = class {
|
|
|
6231
6727
|
const oldRidNumeric = this.getRID();
|
|
6232
6728
|
this.setRID(lastInsertDataPageId, newSlotIndex);
|
|
6233
6729
|
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);
|
|
6730
|
+
const btx = await this.getBPTreeTransaction(tx);
|
|
6731
|
+
await btx.delete(oldRidNumeric, pk);
|
|
6732
|
+
await btx.insert(newRidNumeric, pk);
|
|
6733
|
+
tx.__markBPTreeDirty();
|
|
6244
6734
|
const freshMetadataPage = await this.pfs.getMetadata(tx);
|
|
6245
6735
|
this.metadataPageManager.setLastInsertPageId(freshMetadataPage, lastInsertDataPageId);
|
|
6246
6736
|
await this.pfs.setMetadata(freshMetadataPage, tx);
|
|
@@ -6280,6 +6770,9 @@ var RowTableEngine = class {
|
|
|
6280
6770
|
}
|
|
6281
6771
|
this.rowManager.setDeletedFlag(row, true);
|
|
6282
6772
|
await this.pfs.setPage(pageId, page, tx);
|
|
6773
|
+
const btx = await this.getBPTreeTransaction(tx);
|
|
6774
|
+
await btx.delete(rid, pk);
|
|
6775
|
+
tx.__markBPTreeDirty();
|
|
6283
6776
|
if (decrementRowCount) {
|
|
6284
6777
|
const metadataPage2 = await this.pfs.getMetadata(tx);
|
|
6285
6778
|
const currentRowCount = this.metadataPageManager.getRowCount(metadataPage2);
|
|
@@ -6293,12 +6786,14 @@ var RowTableEngine = class {
|
|
|
6293
6786
|
if (pageId === lastInsertPageId) {
|
|
6294
6787
|
allDeleted = false;
|
|
6295
6788
|
} else {
|
|
6296
|
-
|
|
6789
|
+
let i = 0;
|
|
6790
|
+
while (i < insertedRowCount) {
|
|
6297
6791
|
const slotRow = this.dataPageManager.getRow(page, i);
|
|
6298
6792
|
if (!this.rowManager.getDeletedFlag(slotRow)) {
|
|
6299
6793
|
allDeleted = false;
|
|
6300
6794
|
break;
|
|
6301
6795
|
}
|
|
6796
|
+
i++;
|
|
6302
6797
|
}
|
|
6303
6798
|
}
|
|
6304
6799
|
if (allDeleted) {
|
|
@@ -6361,7 +6856,7 @@ var LockManager = class {
|
|
|
6361
6856
|
lock;
|
|
6362
6857
|
unlockMap = /* @__PURE__ */ new Map();
|
|
6363
6858
|
constructor() {
|
|
6364
|
-
this.lock = new
|
|
6859
|
+
this.lock = new Ryoiki();
|
|
6365
6860
|
}
|
|
6366
6861
|
/**
|
|
6367
6862
|
* Requests a read (Shared) lock for a page.
|
|
@@ -6424,12 +6919,41 @@ var Transaction = class {
|
|
|
6424
6919
|
pageLocks = /* @__PURE__ */ new Map();
|
|
6425
6920
|
/** Undo Logs: PageID -> Original Page Buffer (Snapshot) */
|
|
6426
6921
|
undoPages = /* @__PURE__ */ new Map();
|
|
6427
|
-
/**
|
|
6922
|
+
/** Dirty Pages modified by the transaction */
|
|
6428
6923
|
dirtyPages = /* @__PURE__ */ new Set();
|
|
6429
|
-
/**
|
|
6430
|
-
|
|
6924
|
+
/** BPTree Transaction instance */
|
|
6925
|
+
bptreeTx;
|
|
6926
|
+
/** Whether the BPTree transaction is dirty */
|
|
6927
|
+
bptreeDirty = false;
|
|
6431
6928
|
/** List of callbacks to execute on commit */
|
|
6432
6929
|
commitHooks = [];
|
|
6930
|
+
/**
|
|
6931
|
+
* Sets the BPTree transaction.
|
|
6932
|
+
* @param tx BPTree transaction
|
|
6933
|
+
*/
|
|
6934
|
+
__setBPTreeTransaction(tx) {
|
|
6935
|
+
this.bptreeTx = tx;
|
|
6936
|
+
}
|
|
6937
|
+
/**
|
|
6938
|
+
* Returns the BPTree transaction.
|
|
6939
|
+
* @returns BPTree transaction
|
|
6940
|
+
*/
|
|
6941
|
+
__getBPTreeTransaction() {
|
|
6942
|
+
return this.bptreeTx;
|
|
6943
|
+
}
|
|
6944
|
+
/**
|
|
6945
|
+
* Marks the BPTree transaction as dirty.
|
|
6946
|
+
*/
|
|
6947
|
+
__markBPTreeDirty() {
|
|
6948
|
+
this.bptreeDirty = true;
|
|
6949
|
+
}
|
|
6950
|
+
/**
|
|
6951
|
+
* Returns whether the BPTree transaction is dirty.
|
|
6952
|
+
* @returns True if dirty
|
|
6953
|
+
*/
|
|
6954
|
+
__isBPTreeDirty() {
|
|
6955
|
+
return this.bptreeDirty;
|
|
6956
|
+
}
|
|
6433
6957
|
/**
|
|
6434
6958
|
* Registers a commit hook.
|
|
6435
6959
|
* @param hook Function to execute
|
|
@@ -6465,32 +6989,6 @@ var Transaction = class {
|
|
|
6465
6989
|
__hasUndoPage(pageId) {
|
|
6466
6990
|
return this.undoPages.has(pageId);
|
|
6467
6991
|
}
|
|
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
6992
|
/**
|
|
6495
6993
|
* Acquires a write lock.
|
|
6496
6994
|
* Does not call this method directly. It is called by the `VirtualFileSystem` instance.
|
|
@@ -6518,13 +7016,13 @@ var Transaction = class {
|
|
|
6518
7016
|
* Commits the transaction.
|
|
6519
7017
|
*/
|
|
6520
7018
|
async commit() {
|
|
6521
|
-
await this.vfs.prepareCommit(this);
|
|
6522
|
-
await this.vfs.finalizeCommit(this);
|
|
6523
7019
|
await this.context.run(this, async () => {
|
|
6524
7020
|
for (const hook of this.commitHooks) {
|
|
6525
7021
|
await hook();
|
|
6526
7022
|
}
|
|
6527
7023
|
});
|
|
7024
|
+
await this.vfs.prepareCommit(this);
|
|
7025
|
+
await this.vfs.finalizeCommit(this);
|
|
6528
7026
|
this.releaseAllLocks();
|
|
6529
7027
|
}
|
|
6530
7028
|
/**
|
|
@@ -6669,6 +7167,8 @@ var DataplyAPI = class {
|
|
|
6669
7167
|
metadataPageManager.setMagicString(metadataPage);
|
|
6670
7168
|
metadataPageManager.setPageSize(metadataPage, options.pageSize);
|
|
6671
7169
|
metadataPageManager.setRootIndexPageId(metadataPage, -1);
|
|
7170
|
+
const order = Math.floor((options.pageSize - IndexPageManager.CONSTANT.OFFSET_KEYS_AND_VALUES + IndexPageManager.CONSTANT.SIZE_KEY) / (IndexPageManager.CONSTANT.SIZE_KEY + IndexPageManager.CONSTANT.SIZE_VALUE));
|
|
7171
|
+
metadataPageManager.setRootIndexOrder(metadataPage, order);
|
|
6672
7172
|
metadataPageManager.setBitmapPageId(metadataPage, 1);
|
|
6673
7173
|
metadataPageManager.setLastInsertPageId(metadataPage, 2);
|
|
6674
7174
|
metadataPageManager.setPageCount(metadataPage, 3);
|
|
@@ -7047,7 +7547,9 @@ var GlobalTransaction = class {
|
|
|
7047
7547
|
// Annotate the CommonJS export names for ESM import in node:
|
|
7048
7548
|
0 && (module.exports = {
|
|
7049
7549
|
BPTreeAsync,
|
|
7550
|
+
BPTreeAsyncTransaction,
|
|
7050
7551
|
BPTreeSync,
|
|
7552
|
+
BPTreeSyncTransaction,
|
|
7051
7553
|
BitmapPageManager,
|
|
7052
7554
|
CacheEntanglementAsync,
|
|
7053
7555
|
CacheEntanglementSync,
|