serializable-bptree 5.2.0 → 6.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +27 -18
- package/dist/cjs/index.cjs +508 -185
- package/dist/esm/index.mjs +508 -185
- package/dist/types/BPTreeAsync.d.ts +3 -0
- package/package.json +3 -2
package/dist/cjs/index.cjs
CHANGED
|
@@ -67,16 +67,26 @@ var LRUMap = class {
|
|
|
67
67
|
map;
|
|
68
68
|
head = null;
|
|
69
69
|
tail = null;
|
|
70
|
+
/**
|
|
71
|
+
* Creates an instance of LRUMap.
|
|
72
|
+
* @param capacity The maximum number of items the cache can hold.
|
|
73
|
+
*/
|
|
70
74
|
constructor(capacity) {
|
|
71
75
|
this.capacity = capacity;
|
|
72
76
|
this.map = /* @__PURE__ */ new Map();
|
|
73
77
|
}
|
|
74
|
-
|
|
78
|
+
/**
|
|
79
|
+
* Promotes a node to the head of the linked list (marks as most recently used).
|
|
80
|
+
* @param node The node to promote.
|
|
81
|
+
*/
|
|
75
82
|
promote(node) {
|
|
76
83
|
this.extract(node);
|
|
77
84
|
this.prepend(node);
|
|
78
85
|
}
|
|
79
|
-
|
|
86
|
+
/**
|
|
87
|
+
* Disconnects a node from the doubly linked list.
|
|
88
|
+
* @param node The node to extract.
|
|
89
|
+
*/
|
|
80
90
|
extract(node) {
|
|
81
91
|
if (node.prev) node.prev.next = node.next;
|
|
82
92
|
else this.head = node.next;
|
|
@@ -85,7 +95,10 @@ var LRUMap = class {
|
|
|
85
95
|
node.prev = null;
|
|
86
96
|
node.next = null;
|
|
87
97
|
}
|
|
88
|
-
|
|
98
|
+
/**
|
|
99
|
+
* Inserts a node at the head of the doubly linked list.
|
|
100
|
+
* @param node The node to prepend.
|
|
101
|
+
*/
|
|
89
102
|
prepend(node) {
|
|
90
103
|
node.next = this.head;
|
|
91
104
|
if (this.head) this.head.prev = node;
|
|
@@ -93,8 +106,10 @@ var LRUMap = class {
|
|
|
93
106
|
if (!this.tail) this.tail = node;
|
|
94
107
|
}
|
|
95
108
|
/**
|
|
96
|
-
*
|
|
97
|
-
*
|
|
109
|
+
* Stores or updates a value by key.
|
|
110
|
+
* If the capacity is exceeded, the least recently used item (tail) is removed.
|
|
111
|
+
* @param key The key to store.
|
|
112
|
+
* @param value The value to store.
|
|
98
113
|
*/
|
|
99
114
|
set(key, value) {
|
|
100
115
|
const existing = this.map.get(key);
|
|
@@ -112,7 +127,10 @@ var LRUMap = class {
|
|
|
112
127
|
}
|
|
113
128
|
}
|
|
114
129
|
/**
|
|
115
|
-
*
|
|
130
|
+
* Retrieves a value by key.
|
|
131
|
+
* Accessing the item moves it to the "most recently used" position.
|
|
132
|
+
* @param key The key to look for.
|
|
133
|
+
* @returns The value associated with the key, or undefined if not found.
|
|
116
134
|
*/
|
|
117
135
|
get(key) {
|
|
118
136
|
const node = this.map.get(key);
|
|
@@ -121,13 +139,17 @@ var LRUMap = class {
|
|
|
121
139
|
return node.value;
|
|
122
140
|
}
|
|
123
141
|
/**
|
|
124
|
-
*
|
|
142
|
+
* Checks if a key exists in the cache without changing its access order.
|
|
143
|
+
* @param key The key to check.
|
|
144
|
+
* @returns True if the key exists, false otherwise.
|
|
125
145
|
*/
|
|
126
146
|
has(key) {
|
|
127
147
|
return this.map.has(key);
|
|
128
148
|
}
|
|
129
149
|
/**
|
|
130
|
-
*
|
|
150
|
+
* Removes a key and its associated value from the cache.
|
|
151
|
+
* @param key The key to remove.
|
|
152
|
+
* @returns True if the key was found and removed, false otherwise.
|
|
131
153
|
*/
|
|
132
154
|
delete(key) {
|
|
133
155
|
const node = this.map.get(key);
|
|
@@ -137,7 +159,8 @@ var LRUMap = class {
|
|
|
137
159
|
return true;
|
|
138
160
|
}
|
|
139
161
|
/**
|
|
140
|
-
*
|
|
162
|
+
* Returns an iterator of keys in the order of most recently used to least recently used.
|
|
163
|
+
* @returns An iterable iterator of keys.
|
|
141
164
|
*/
|
|
142
165
|
*keys() {
|
|
143
166
|
let current = this.head;
|
|
@@ -147,13 +170,13 @@ var LRUMap = class {
|
|
|
147
170
|
}
|
|
148
171
|
}
|
|
149
172
|
/**
|
|
150
|
-
*
|
|
173
|
+
* Returns the current number of items in the cache.
|
|
151
174
|
*/
|
|
152
175
|
get size() {
|
|
153
176
|
return this.map.size;
|
|
154
177
|
}
|
|
155
178
|
/**
|
|
156
|
-
*
|
|
179
|
+
* Clears all items from the cache.
|
|
157
180
|
*/
|
|
158
181
|
clear() {
|
|
159
182
|
this.map.clear();
|
|
@@ -746,6 +769,9 @@ var BPTreeSync = class extends BPTree {
|
|
|
746
769
|
guess = prevValue;
|
|
747
770
|
}
|
|
748
771
|
}
|
|
772
|
+
if (!pointer) {
|
|
773
|
+
return;
|
|
774
|
+
}
|
|
749
775
|
if (node.values.length + pointer.values.length < this.order) {
|
|
750
776
|
if (!isPredecessor) {
|
|
751
777
|
const pTemp = pointer;
|
|
@@ -890,39 +916,40 @@ var BPTreeSync = class extends BPTree {
|
|
|
890
916
|
return;
|
|
891
917
|
}
|
|
892
918
|
const parentNode = this.getNode(node.parent);
|
|
893
|
-
|
|
894
|
-
|
|
895
|
-
if (
|
|
896
|
-
|
|
897
|
-
|
|
898
|
-
|
|
899
|
-
|
|
900
|
-
|
|
901
|
-
|
|
902
|
-
|
|
903
|
-
|
|
904
|
-
|
|
905
|
-
|
|
906
|
-
|
|
907
|
-
|
|
908
|
-
|
|
909
|
-
|
|
910
|
-
|
|
911
|
-
|
|
912
|
-
|
|
913
|
-
|
|
914
|
-
|
|
915
|
-
|
|
916
|
-
|
|
917
|
-
|
|
918
|
-
|
|
919
|
-
|
|
920
|
-
|
|
921
|
-
|
|
922
|
-
|
|
923
|
-
|
|
924
|
-
}
|
|
919
|
+
let insertIndex = 0;
|
|
920
|
+
for (let i = 0; i < parentNode.values.length; i++) {
|
|
921
|
+
if (this.comparator.asc(value, parentNode.values[i]) > 0) {
|
|
922
|
+
insertIndex = i + 1;
|
|
923
|
+
} else {
|
|
924
|
+
break;
|
|
925
|
+
}
|
|
926
|
+
}
|
|
927
|
+
parentNode.values.splice(insertIndex, 0, value);
|
|
928
|
+
parentNode.keys.splice(insertIndex + 1, 0, pointer.id);
|
|
929
|
+
pointer.parent = parentNode.id;
|
|
930
|
+
this.bufferForNodeUpdate(parentNode);
|
|
931
|
+
this.bufferForNodeUpdate(pointer);
|
|
932
|
+
if (parentNode.keys.length > this.order) {
|
|
933
|
+
const parentPointer = this._createNode(false, [], []);
|
|
934
|
+
parentPointer.parent = parentNode.parent;
|
|
935
|
+
const mid = Math.ceil(this.order / 2) - 1;
|
|
936
|
+
parentPointer.values = parentNode.values.slice(mid + 1);
|
|
937
|
+
parentPointer.keys = parentNode.keys.slice(mid + 1);
|
|
938
|
+
const midValue = parentNode.values[mid];
|
|
939
|
+
parentNode.values = parentNode.values.slice(0, mid);
|
|
940
|
+
parentNode.keys = parentNode.keys.slice(0, mid + 1);
|
|
941
|
+
for (const k of parentNode.keys) {
|
|
942
|
+
const node2 = this.getNode(k);
|
|
943
|
+
node2.parent = parentNode.id;
|
|
944
|
+
this.bufferForNodeUpdate(node2);
|
|
945
|
+
}
|
|
946
|
+
for (const k of parentPointer.keys) {
|
|
947
|
+
const node2 = this.getNode(k);
|
|
948
|
+
node2.parent = parentPointer.id;
|
|
949
|
+
this.bufferForNodeUpdate(node2);
|
|
925
950
|
}
|
|
951
|
+
this._insertInParent(parentNode, midValue, parentPointer);
|
|
952
|
+
this.bufferForNodeUpdate(parentNode);
|
|
926
953
|
}
|
|
927
954
|
}
|
|
928
955
|
init() {
|
|
@@ -1167,11 +1194,271 @@ var BPTreeSync = class extends BPTree {
|
|
|
1167
1194
|
}
|
|
1168
1195
|
};
|
|
1169
1196
|
|
|
1197
|
+
// node_modules/ryoiki/dist/esm/index.mjs
|
|
1198
|
+
var Ryoiki = class _Ryoiki {
|
|
1199
|
+
readings;
|
|
1200
|
+
writings;
|
|
1201
|
+
readQueue;
|
|
1202
|
+
writeQueue;
|
|
1203
|
+
static async CatchError(promise) {
|
|
1204
|
+
return await promise.then((v) => [void 0, v]).catch((err) => [err]);
|
|
1205
|
+
}
|
|
1206
|
+
static IsRangeOverlap(a, b) {
|
|
1207
|
+
const [start1, end1] = a;
|
|
1208
|
+
const [start2, end2] = b;
|
|
1209
|
+
if (end1 <= start2 || end2 <= start1) {
|
|
1210
|
+
return false;
|
|
1211
|
+
}
|
|
1212
|
+
return true;
|
|
1213
|
+
}
|
|
1214
|
+
static ERR_ALREADY_EXISTS(lockId) {
|
|
1215
|
+
return new Error(`The '${lockId}' task already existing in queue or running.`);
|
|
1216
|
+
}
|
|
1217
|
+
static ERR_NOT_EXISTS(lockId) {
|
|
1218
|
+
return new Error(`The '${lockId}' task not existing in task queue.`);
|
|
1219
|
+
}
|
|
1220
|
+
static ERR_TIMEOUT(lockId, timeout) {
|
|
1221
|
+
return new Error(`The task with ID '${lockId}' failed to acquire the lock within the timeout(${timeout}ms).`);
|
|
1222
|
+
}
|
|
1223
|
+
/**
|
|
1224
|
+
* Constructs a new instance of the Ryoiki class.
|
|
1225
|
+
*/
|
|
1226
|
+
constructor() {
|
|
1227
|
+
this.readings = /* @__PURE__ */ new Map();
|
|
1228
|
+
this.writings = /* @__PURE__ */ new Map();
|
|
1229
|
+
this.readQueue = /* @__PURE__ */ new Map();
|
|
1230
|
+
this.writeQueue = /* @__PURE__ */ new Map();
|
|
1231
|
+
}
|
|
1232
|
+
/**
|
|
1233
|
+
* Creates a range based on a start value and length.
|
|
1234
|
+
* @param start - The starting value of the range.
|
|
1235
|
+
* @param length - The length of the range.
|
|
1236
|
+
* @returns A range tuple [start, start + length].
|
|
1237
|
+
*/
|
|
1238
|
+
range(start, length) {
|
|
1239
|
+
return [start, start + length];
|
|
1240
|
+
}
|
|
1241
|
+
rangeOverlapping(tasks, range) {
|
|
1242
|
+
return Array.from(tasks.values()).some((t) => _Ryoiki.IsRangeOverlap(t.range, range));
|
|
1243
|
+
}
|
|
1244
|
+
isSameRange(a, b) {
|
|
1245
|
+
const [a1, a2] = a;
|
|
1246
|
+
const [b1, b2] = b;
|
|
1247
|
+
return a1 === b1 && a2 === b2;
|
|
1248
|
+
}
|
|
1249
|
+
fetchUnitAndRun(queue, workspaces) {
|
|
1250
|
+
for (const [id, unit] of queue) {
|
|
1251
|
+
if (!unit.condition()) {
|
|
1252
|
+
continue;
|
|
1253
|
+
}
|
|
1254
|
+
this._alloc(queue, workspaces, id);
|
|
1255
|
+
}
|
|
1256
|
+
}
|
|
1257
|
+
_handleOverload(args, handlers, argPatterns) {
|
|
1258
|
+
for (const [key, pattern] of Object.entries(argPatterns)) {
|
|
1259
|
+
if (this._matchArgs(args, pattern)) {
|
|
1260
|
+
return handlers[key](...args);
|
|
1261
|
+
}
|
|
1262
|
+
}
|
|
1263
|
+
throw new Error("Invalid arguments");
|
|
1264
|
+
}
|
|
1265
|
+
_matchArgs(args, pattern) {
|
|
1266
|
+
return args.every((arg, index) => {
|
|
1267
|
+
const expectedType = pattern[index];
|
|
1268
|
+
if (expectedType === void 0) return typeof arg === "undefined";
|
|
1269
|
+
if (expectedType === Function) return typeof arg === "function";
|
|
1270
|
+
if (expectedType === Number) return typeof arg === "number";
|
|
1271
|
+
if (expectedType === Array) return Array.isArray(arg);
|
|
1272
|
+
return false;
|
|
1273
|
+
});
|
|
1274
|
+
}
|
|
1275
|
+
_createRandomId() {
|
|
1276
|
+
const timestamp = Date.now().toString(36);
|
|
1277
|
+
const random = Math.random().toString(36).substring(2);
|
|
1278
|
+
return `${timestamp}${random}`;
|
|
1279
|
+
}
|
|
1280
|
+
_alloc(queue, workspaces, lockId) {
|
|
1281
|
+
const unit = queue.get(lockId);
|
|
1282
|
+
if (!unit) {
|
|
1283
|
+
throw _Ryoiki.ERR_NOT_EXISTS(lockId);
|
|
1284
|
+
}
|
|
1285
|
+
workspaces.set(lockId, unit);
|
|
1286
|
+
queue.delete(lockId);
|
|
1287
|
+
unit.alloc();
|
|
1288
|
+
}
|
|
1289
|
+
_free(workspaces, lockId) {
|
|
1290
|
+
const unit = workspaces.get(lockId);
|
|
1291
|
+
if (!unit) {
|
|
1292
|
+
throw _Ryoiki.ERR_NOT_EXISTS(lockId);
|
|
1293
|
+
}
|
|
1294
|
+
workspaces.delete(lockId);
|
|
1295
|
+
unit.free();
|
|
1296
|
+
}
|
|
1297
|
+
_lock(queue, range, timeout, task, condition) {
|
|
1298
|
+
return new Promise((resolve, reject) => {
|
|
1299
|
+
let timeoutId = null;
|
|
1300
|
+
if (timeout >= 0) {
|
|
1301
|
+
timeoutId = setTimeout(() => {
|
|
1302
|
+
reject(_Ryoiki.ERR_TIMEOUT(id, timeout));
|
|
1303
|
+
}, timeout);
|
|
1304
|
+
}
|
|
1305
|
+
const id = this._createRandomId();
|
|
1306
|
+
const alloc = async () => {
|
|
1307
|
+
if (timeoutId !== null) {
|
|
1308
|
+
clearTimeout(timeoutId);
|
|
1309
|
+
}
|
|
1310
|
+
const [err, v] = await _Ryoiki.CatchError(task(id));
|
|
1311
|
+
if (err) reject(err);
|
|
1312
|
+
else resolve(v);
|
|
1313
|
+
};
|
|
1314
|
+
const fetch = () => {
|
|
1315
|
+
this.fetchUnitAndRun(this.readQueue, this.readings);
|
|
1316
|
+
this.fetchUnitAndRun(this.writeQueue, this.writings);
|
|
1317
|
+
};
|
|
1318
|
+
queue.set(id, { id, range, condition, alloc, free: fetch });
|
|
1319
|
+
fetch();
|
|
1320
|
+
});
|
|
1321
|
+
}
|
|
1322
|
+
_checkWorking(range, workspaces) {
|
|
1323
|
+
let isLocked = false;
|
|
1324
|
+
for (const lock of workspaces.values()) {
|
|
1325
|
+
if (_Ryoiki.IsRangeOverlap(range, lock.range)) {
|
|
1326
|
+
isLocked = true;
|
|
1327
|
+
break;
|
|
1328
|
+
}
|
|
1329
|
+
}
|
|
1330
|
+
return isLocked;
|
|
1331
|
+
}
|
|
1332
|
+
/**
|
|
1333
|
+
* Checks if there is any active read lock within the specified range.
|
|
1334
|
+
* @param range The range to check for active read locks.
|
|
1335
|
+
* @returns `true` if there is an active read lock within the range, `false` otherwise.
|
|
1336
|
+
*/
|
|
1337
|
+
isReading(range) {
|
|
1338
|
+
return this._checkWorking(range, this.readings);
|
|
1339
|
+
}
|
|
1340
|
+
/**
|
|
1341
|
+
* Checks if there is any active write lock within the specified range.
|
|
1342
|
+
* @param range The range to check for active write locks.
|
|
1343
|
+
* @returns `true` if there is an active write lock within the range, `false` otherwise.
|
|
1344
|
+
*/
|
|
1345
|
+
isWriting(range) {
|
|
1346
|
+
return this._checkWorking(range, this.writings);
|
|
1347
|
+
}
|
|
1348
|
+
/**
|
|
1349
|
+
* Checks if a read lock can be acquired within the specified range.
|
|
1350
|
+
* @param range The range to check for read lock availability.
|
|
1351
|
+
* @returns `true` if a read lock can be acquired, `false` otherwise.
|
|
1352
|
+
*/
|
|
1353
|
+
canRead(range) {
|
|
1354
|
+
const writing = this.isWriting(range);
|
|
1355
|
+
return !writing;
|
|
1356
|
+
}
|
|
1357
|
+
/**
|
|
1358
|
+
* Checks if a write lock can be acquired within the specified range.
|
|
1359
|
+
* @param range The range to check for write lock availability.
|
|
1360
|
+
* @returns `true` if a write lock can be acquired, `false` otherwise.
|
|
1361
|
+
*/
|
|
1362
|
+
canWrite(range) {
|
|
1363
|
+
const reading = this.isReading(range);
|
|
1364
|
+
const writing = this.isWriting(range);
|
|
1365
|
+
return !reading && !writing;
|
|
1366
|
+
}
|
|
1367
|
+
/**
|
|
1368
|
+
* Internal implementation of the read lock. Handles both overloads.
|
|
1369
|
+
* @template T - The return type of the task.
|
|
1370
|
+
* @param arg0 - Either a range or a task callback.
|
|
1371
|
+
* If a range is provided, the task is the second argument.
|
|
1372
|
+
* @param arg1 - The task to execute, required if a range is provided.
|
|
1373
|
+
* @param arg2 - The timeout for acquiring the lock.
|
|
1374
|
+
* If the lock cannot be acquired within this period, an error will be thrown.
|
|
1375
|
+
* If this value is not provided, no timeout will be set.
|
|
1376
|
+
* @returns A promise resolving to the result of the task execution.
|
|
1377
|
+
*/
|
|
1378
|
+
readLock(arg0, arg1, arg2) {
|
|
1379
|
+
const [range, task, timeout] = this._handleOverload(
|
|
1380
|
+
[arg0, arg1, arg2],
|
|
1381
|
+
{
|
|
1382
|
+
rangeTask: (range2, task2) => [range2, task2, -1],
|
|
1383
|
+
rangeTaskTimeout: (range2, task2, timeout2) => [range2, task2, timeout2],
|
|
1384
|
+
task: (task2) => [[-Infinity, Infinity], task2, -1],
|
|
1385
|
+
taskTimeout: (task2, timeout2) => [[-Infinity, Infinity], task2, timeout2]
|
|
1386
|
+
},
|
|
1387
|
+
{
|
|
1388
|
+
task: [Function],
|
|
1389
|
+
taskTimeout: [Function, Number],
|
|
1390
|
+
rangeTask: [Array, Function],
|
|
1391
|
+
rangeTaskTimeout: [Array, Function, Number]
|
|
1392
|
+
}
|
|
1393
|
+
);
|
|
1394
|
+
return this._lock(
|
|
1395
|
+
this.readQueue,
|
|
1396
|
+
range,
|
|
1397
|
+
timeout,
|
|
1398
|
+
task,
|
|
1399
|
+
() => !this.rangeOverlapping(this.writings, range)
|
|
1400
|
+
);
|
|
1401
|
+
}
|
|
1402
|
+
/**
|
|
1403
|
+
* Internal implementation of the write lock. Handles both overloads.
|
|
1404
|
+
* @template T - The return type of the task.
|
|
1405
|
+
* @param arg0 - Either a range or a task callback.
|
|
1406
|
+
* If a range is provided, the task is the second argument.
|
|
1407
|
+
* @param arg1 - The task to execute, required if a range is provided.
|
|
1408
|
+
* @param arg2 - The timeout for acquiring the lock.
|
|
1409
|
+
* If the lock cannot be acquired within this period, an error will be thrown.
|
|
1410
|
+
* If this value is not provided, no timeout will be set.
|
|
1411
|
+
* @returns A promise resolving to the result of the task execution.
|
|
1412
|
+
*/
|
|
1413
|
+
writeLock(arg0, arg1, arg2) {
|
|
1414
|
+
const [range, task, timeout] = this._handleOverload(
|
|
1415
|
+
[arg0, arg1, arg2],
|
|
1416
|
+
{
|
|
1417
|
+
rangeTask: (range2, task2) => [range2, task2, -1],
|
|
1418
|
+
rangeTaskTimeout: (range2, task2, timeout2) => [range2, task2, timeout2],
|
|
1419
|
+
task: (task2) => [[-Infinity, Infinity], task2, -1],
|
|
1420
|
+
taskTimeout: (task2, timeout2) => [[-Infinity, Infinity], task2, timeout2]
|
|
1421
|
+
},
|
|
1422
|
+
{
|
|
1423
|
+
task: [Function],
|
|
1424
|
+
taskTimeout: [Function, Number],
|
|
1425
|
+
rangeTask: [Array, Function],
|
|
1426
|
+
rangeTaskTimeout: [Array, Function, Number]
|
|
1427
|
+
}
|
|
1428
|
+
);
|
|
1429
|
+
return this._lock(
|
|
1430
|
+
this.writeQueue,
|
|
1431
|
+
range,
|
|
1432
|
+
timeout,
|
|
1433
|
+
task,
|
|
1434
|
+
() => {
|
|
1435
|
+
return !this.rangeOverlapping(this.writings, range) && !this.rangeOverlapping(this.readings, range);
|
|
1436
|
+
}
|
|
1437
|
+
);
|
|
1438
|
+
}
|
|
1439
|
+
/**
|
|
1440
|
+
* Releases a read lock by its lock ID.
|
|
1441
|
+
* @param lockId - The unique identifier for the lock to release.
|
|
1442
|
+
*/
|
|
1443
|
+
readUnlock(lockId) {
|
|
1444
|
+
this._free(this.readings, lockId);
|
|
1445
|
+
}
|
|
1446
|
+
/**
|
|
1447
|
+
* Releases a write lock by its lock ID.
|
|
1448
|
+
* @param lockId - The unique identifier for the lock to release.
|
|
1449
|
+
*/
|
|
1450
|
+
writeUnlock(lockId) {
|
|
1451
|
+
this._free(this.writings, lockId);
|
|
1452
|
+
}
|
|
1453
|
+
};
|
|
1454
|
+
|
|
1170
1455
|
// src/BPTreeAsync.ts
|
|
1171
1456
|
var BPTreeAsync = class extends BPTree {
|
|
1457
|
+
lock;
|
|
1172
1458
|
constructor(strategy, comparator, option) {
|
|
1173
1459
|
super(strategy, comparator, option);
|
|
1174
1460
|
this.nodes = this._createCachedNode();
|
|
1461
|
+
this.lock = new Ryoiki();
|
|
1175
1462
|
}
|
|
1176
1463
|
_createCachedNode() {
|
|
1177
1464
|
return new CacheEntanglementAsync(async (key) => {
|
|
@@ -1180,6 +1467,24 @@ var BPTreeAsync = class extends BPTree {
|
|
|
1180
1467
|
capacity: this.option.capacity ?? 1e3
|
|
1181
1468
|
});
|
|
1182
1469
|
}
|
|
1470
|
+
async readLock(callback) {
|
|
1471
|
+
let lockId;
|
|
1472
|
+
return await this.lock.readLock(async (_lockId) => {
|
|
1473
|
+
lockId = _lockId;
|
|
1474
|
+
return await callback();
|
|
1475
|
+
}).finally(() => {
|
|
1476
|
+
this.lock.readUnlock(lockId);
|
|
1477
|
+
});
|
|
1478
|
+
}
|
|
1479
|
+
async writeLock(callback) {
|
|
1480
|
+
let lockId;
|
|
1481
|
+
return await this.lock.writeLock(async (_lockId) => {
|
|
1482
|
+
lockId = _lockId;
|
|
1483
|
+
return await callback();
|
|
1484
|
+
}).finally(() => {
|
|
1485
|
+
this.lock.writeUnlock(lockId);
|
|
1486
|
+
});
|
|
1487
|
+
}
|
|
1183
1488
|
async getPairsRightToLeft(value, startNode, endNode, comparator) {
|
|
1184
1489
|
const pairs = [];
|
|
1185
1490
|
let node = startNode;
|
|
@@ -1338,6 +1643,9 @@ var BPTreeAsync = class extends BPTree {
|
|
|
1338
1643
|
guess = prevValue;
|
|
1339
1644
|
}
|
|
1340
1645
|
}
|
|
1646
|
+
if (!pointer) {
|
|
1647
|
+
return;
|
|
1648
|
+
}
|
|
1341
1649
|
if (node.values.length + pointer.values.length < this.order) {
|
|
1342
1650
|
if (!isPredecessor) {
|
|
1343
1651
|
const pTemp = pointer;
|
|
@@ -1482,40 +1790,41 @@ var BPTreeAsync = class extends BPTree {
|
|
|
1482
1790
|
return;
|
|
1483
1791
|
}
|
|
1484
1792
|
const parentNode = await this.getNode(node.parent);
|
|
1485
|
-
|
|
1486
|
-
|
|
1487
|
-
if (
|
|
1488
|
-
|
|
1489
|
-
|
|
1490
|
-
|
|
1491
|
-
if (parentNode.keys.length > this.order) {
|
|
1492
|
-
const parentPointer = await this._createNode(false, [], []);
|
|
1493
|
-
parentPointer.parent = parentNode.parent;
|
|
1494
|
-
const mid = Math.ceil(this.order / 2) - 1;
|
|
1495
|
-
parentPointer.values = parentNode.values.slice(mid + 1);
|
|
1496
|
-
parentPointer.keys = parentNode.keys.slice(mid + 1);
|
|
1497
|
-
const midValue = parentNode.values[mid];
|
|
1498
|
-
if (mid === 0) {
|
|
1499
|
-
parentNode.values = parentNode.values.slice(0, mid + 1);
|
|
1500
|
-
} else {
|
|
1501
|
-
parentNode.values = parentNode.values.slice(0, mid);
|
|
1502
|
-
}
|
|
1503
|
-
parentNode.keys = parentNode.keys.slice(0, mid + 1);
|
|
1504
|
-
for (const k of parentNode.keys) {
|
|
1505
|
-
const node2 = await this.getNode(k);
|
|
1506
|
-
node2.parent = parentNode.id;
|
|
1507
|
-
this.bufferForNodeUpdate(node2);
|
|
1508
|
-
}
|
|
1509
|
-
for (const k of parentPointer.keys) {
|
|
1510
|
-
const node2 = await this.getNode(k);
|
|
1511
|
-
node2.parent = parentPointer.id;
|
|
1512
|
-
this.bufferForNodeUpdate(node2);
|
|
1513
|
-
}
|
|
1514
|
-
await this._insertInParent(parentNode, midValue, parentPointer);
|
|
1515
|
-
this.bufferForNodeUpdate(parentNode);
|
|
1516
|
-
}
|
|
1793
|
+
let insertIndex = 0;
|
|
1794
|
+
for (let i = 0; i < parentNode.values.length; i++) {
|
|
1795
|
+
if (this.comparator.asc(value, parentNode.values[i]) > 0) {
|
|
1796
|
+
insertIndex = i + 1;
|
|
1797
|
+
} else {
|
|
1798
|
+
break;
|
|
1517
1799
|
}
|
|
1518
1800
|
}
|
|
1801
|
+
parentNode.values.splice(insertIndex, 0, value);
|
|
1802
|
+
parentNode.keys.splice(insertIndex + 1, 0, pointer.id);
|
|
1803
|
+
pointer.parent = parentNode.id;
|
|
1804
|
+
this.bufferForNodeUpdate(parentNode);
|
|
1805
|
+
this.bufferForNodeUpdate(pointer);
|
|
1806
|
+
if (parentNode.keys.length > this.order) {
|
|
1807
|
+
const parentPointer = await this._createNode(false, [], []);
|
|
1808
|
+
parentPointer.parent = parentNode.parent;
|
|
1809
|
+
const mid = Math.ceil(this.order / 2) - 1;
|
|
1810
|
+
parentPointer.values = parentNode.values.slice(mid + 1);
|
|
1811
|
+
parentPointer.keys = parentNode.keys.slice(mid + 1);
|
|
1812
|
+
const midValue = parentNode.values[mid];
|
|
1813
|
+
parentNode.values = parentNode.values.slice(0, mid);
|
|
1814
|
+
parentNode.keys = parentNode.keys.slice(0, mid + 1);
|
|
1815
|
+
for (const k of parentNode.keys) {
|
|
1816
|
+
const node2 = await this.getNode(k);
|
|
1817
|
+
node2.parent = parentNode.id;
|
|
1818
|
+
this.bufferForNodeUpdate(node2);
|
|
1819
|
+
}
|
|
1820
|
+
for (const k of parentPointer.keys) {
|
|
1821
|
+
const node2 = await this.getNode(k);
|
|
1822
|
+
node2.parent = parentPointer.id;
|
|
1823
|
+
this.bufferForNodeUpdate(node2);
|
|
1824
|
+
}
|
|
1825
|
+
await this._insertInParent(parentNode, midValue, parentPointer);
|
|
1826
|
+
this.bufferForNodeUpdate(parentNode);
|
|
1827
|
+
}
|
|
1519
1828
|
}
|
|
1520
1829
|
async init() {
|
|
1521
1830
|
const head = await this.strategy.readHead();
|
|
@@ -1623,139 +1932,153 @@ var BPTreeAsync = class extends BPTree {
|
|
|
1623
1932
|
this._nodeDeleteBuffer.clear();
|
|
1624
1933
|
}
|
|
1625
1934
|
async keys(condition, filterValues) {
|
|
1626
|
-
|
|
1627
|
-
const
|
|
1628
|
-
|
|
1629
|
-
|
|
1630
|
-
|
|
1631
|
-
|
|
1632
|
-
|
|
1633
|
-
|
|
1634
|
-
|
|
1635
|
-
|
|
1636
|
-
|
|
1637
|
-
|
|
1638
|
-
|
|
1639
|
-
const
|
|
1640
|
-
|
|
1641
|
-
|
|
1935
|
+
return this.readLock(async () => {
|
|
1936
|
+
for (const k in condition) {
|
|
1937
|
+
const key = k;
|
|
1938
|
+
const value = condition[key];
|
|
1939
|
+
const startNode = await this.verifierStartNode[key](value);
|
|
1940
|
+
const endNode = await this.verifierEndNode[key](value);
|
|
1941
|
+
const direction = this.verifierDirection[key];
|
|
1942
|
+
const comparator = this.verifierMap[key];
|
|
1943
|
+
const pairs = await this.getPairs(value, startNode, endNode, comparator, direction);
|
|
1944
|
+
if (!filterValues) {
|
|
1945
|
+
filterValues = new Set(pairs.keys());
|
|
1946
|
+
} else {
|
|
1947
|
+
const intersections = /* @__PURE__ */ new Set();
|
|
1948
|
+
for (const key2 of filterValues) {
|
|
1949
|
+
const has = pairs.has(key2);
|
|
1950
|
+
if (has) {
|
|
1951
|
+
intersections.add(key2);
|
|
1952
|
+
}
|
|
1642
1953
|
}
|
|
1954
|
+
filterValues = intersections;
|
|
1643
1955
|
}
|
|
1644
|
-
filterValues = intersections;
|
|
1645
1956
|
}
|
|
1646
|
-
|
|
1647
|
-
|
|
1957
|
+
return filterValues ?? /* @__PURE__ */ new Set([]);
|
|
1958
|
+
});
|
|
1648
1959
|
}
|
|
1649
1960
|
async where(condition) {
|
|
1650
|
-
|
|
1651
|
-
|
|
1652
|
-
const
|
|
1653
|
-
|
|
1654
|
-
|
|
1655
|
-
|
|
1656
|
-
|
|
1657
|
-
|
|
1658
|
-
|
|
1659
|
-
|
|
1660
|
-
result
|
|
1661
|
-
|
|
1662
|
-
|
|
1663
|
-
|
|
1664
|
-
|
|
1665
|
-
|
|
1961
|
+
return this.readLock(async () => {
|
|
1962
|
+
let result = null;
|
|
1963
|
+
for (const k in condition) {
|
|
1964
|
+
const key = k;
|
|
1965
|
+
const value = condition[key];
|
|
1966
|
+
const startNode = await this.verifierStartNode[key](value);
|
|
1967
|
+
const endNode = await this.verifierEndNode[key](value);
|
|
1968
|
+
const direction = this.verifierDirection[key];
|
|
1969
|
+
const comparator = this.verifierMap[key];
|
|
1970
|
+
const pairs = await this.getPairs(value, startNode, endNode, comparator, direction);
|
|
1971
|
+
if (result === null) {
|
|
1972
|
+
result = pairs;
|
|
1973
|
+
} else {
|
|
1974
|
+
const intersection = /* @__PURE__ */ new Map();
|
|
1975
|
+
for (const [k2, v] of pairs) {
|
|
1976
|
+
if (result.has(k2)) {
|
|
1977
|
+
intersection.set(k2, v);
|
|
1978
|
+
}
|
|
1666
1979
|
}
|
|
1980
|
+
result = intersection;
|
|
1667
1981
|
}
|
|
1668
|
-
result = intersection;
|
|
1669
1982
|
}
|
|
1670
|
-
|
|
1671
|
-
|
|
1983
|
+
return result ?? /* @__PURE__ */ new Map();
|
|
1984
|
+
});
|
|
1672
1985
|
}
|
|
1673
1986
|
async insert(key, value) {
|
|
1674
|
-
|
|
1675
|
-
|
|
1676
|
-
|
|
1677
|
-
|
|
1678
|
-
|
|
1679
|
-
|
|
1680
|
-
|
|
1681
|
-
|
|
1682
|
-
|
|
1683
|
-
|
|
1684
|
-
|
|
1685
|
-
|
|
1686
|
-
|
|
1687
|
-
|
|
1688
|
-
|
|
1689
|
-
|
|
1690
|
-
|
|
1691
|
-
|
|
1692
|
-
|
|
1693
|
-
|
|
1694
|
-
|
|
1695
|
-
|
|
1696
|
-
|
|
1987
|
+
return this.writeLock(async () => {
|
|
1988
|
+
const before = await this.insertableNode(value);
|
|
1989
|
+
this._insertAtLeaf(before, key, value);
|
|
1990
|
+
if (before.values.length === this.order) {
|
|
1991
|
+
const after = await this._createNode(
|
|
1992
|
+
true,
|
|
1993
|
+
[],
|
|
1994
|
+
[],
|
|
1995
|
+
true,
|
|
1996
|
+
before.parent,
|
|
1997
|
+
before.next,
|
|
1998
|
+
before.id
|
|
1999
|
+
);
|
|
2000
|
+
const mid = Math.ceil(this.order / 2) - 1;
|
|
2001
|
+
const beforeNext = before.next;
|
|
2002
|
+
after.values = before.values.slice(mid + 1);
|
|
2003
|
+
after.keys = before.keys.slice(mid + 1);
|
|
2004
|
+
before.values = before.values.slice(0, mid + 1);
|
|
2005
|
+
before.keys = before.keys.slice(0, mid + 1);
|
|
2006
|
+
before.next = after.id;
|
|
2007
|
+
if (beforeNext) {
|
|
2008
|
+
const node = await this.getNode(beforeNext);
|
|
2009
|
+
node.prev = after.id;
|
|
2010
|
+
this.bufferForNodeUpdate(node);
|
|
2011
|
+
}
|
|
2012
|
+
await this._insertInParent(before, after.values[0], after);
|
|
2013
|
+
this.bufferForNodeUpdate(before);
|
|
1697
2014
|
}
|
|
1698
|
-
await this.
|
|
1699
|
-
this.
|
|
1700
|
-
|
|
1701
|
-
|
|
1702
|
-
await this.commitNodeCreateBuffer();
|
|
1703
|
-
await this.commitNodeUpdateBuffer();
|
|
2015
|
+
await this.commitHeadBuffer();
|
|
2016
|
+
await this.commitNodeCreateBuffer();
|
|
2017
|
+
await this.commitNodeUpdateBuffer();
|
|
2018
|
+
});
|
|
1704
2019
|
}
|
|
1705
2020
|
async delete(key, value) {
|
|
1706
|
-
|
|
1707
|
-
|
|
1708
|
-
|
|
1709
|
-
|
|
1710
|
-
|
|
1711
|
-
|
|
1712
|
-
|
|
1713
|
-
if (keys.
|
|
1714
|
-
|
|
1715
|
-
|
|
1716
|
-
|
|
1717
|
-
node.
|
|
1718
|
-
|
|
1719
|
-
|
|
1720
|
-
|
|
1721
|
-
|
|
1722
|
-
|
|
1723
|
-
|
|
1724
|
-
|
|
1725
|
-
|
|
2021
|
+
return this.writeLock(async () => {
|
|
2022
|
+
const node = await this.insertableNode(value);
|
|
2023
|
+
let i = node.values.length;
|
|
2024
|
+
while (i--) {
|
|
2025
|
+
const nValue = node.values[i];
|
|
2026
|
+
if (this.comparator.isSame(value, nValue)) {
|
|
2027
|
+
const keys = node.keys[i];
|
|
2028
|
+
if (keys.includes(key)) {
|
|
2029
|
+
if (keys.length > 1) {
|
|
2030
|
+
keys.splice(keys.indexOf(key), 1);
|
|
2031
|
+
this.bufferForNodeUpdate(node);
|
|
2032
|
+
} else if (node.id === this.root.id) {
|
|
2033
|
+
node.values.splice(i, 1);
|
|
2034
|
+
node.keys.splice(i, 1);
|
|
2035
|
+
this.bufferForNodeUpdate(node);
|
|
2036
|
+
} else {
|
|
2037
|
+
keys.splice(keys.indexOf(key), 1);
|
|
2038
|
+
node.keys.splice(i, 1);
|
|
2039
|
+
node.values.splice(node.values.indexOf(value), 1);
|
|
2040
|
+
await this._deleteEntry(node, key, value);
|
|
2041
|
+
this.bufferForNodeUpdate(node);
|
|
2042
|
+
}
|
|
1726
2043
|
}
|
|
1727
2044
|
}
|
|
1728
2045
|
}
|
|
1729
|
-
|
|
1730
|
-
|
|
1731
|
-
|
|
1732
|
-
|
|
1733
|
-
|
|
2046
|
+
await this.commitHeadBuffer();
|
|
2047
|
+
await this.commitNodeCreateBuffer();
|
|
2048
|
+
await this.commitNodeUpdateBuffer();
|
|
2049
|
+
await this.commitNodeDeleteBuffer();
|
|
2050
|
+
});
|
|
1734
2051
|
}
|
|
1735
2052
|
async exists(key, value) {
|
|
1736
|
-
|
|
1737
|
-
|
|
1738
|
-
|
|
1739
|
-
|
|
1740
|
-
|
|
1741
|
-
|
|
2053
|
+
return this.readLock(async () => {
|
|
2054
|
+
const node = await this.insertableNode(value);
|
|
2055
|
+
for (let i = 0, len = node.values.length; i < len; i++) {
|
|
2056
|
+
const nValue = node.values[i];
|
|
2057
|
+
if (this.comparator.isSame(value, nValue)) {
|
|
2058
|
+
const keys = node.keys[i];
|
|
2059
|
+
return keys.includes(key);
|
|
2060
|
+
}
|
|
1742
2061
|
}
|
|
1743
|
-
|
|
1744
|
-
|
|
2062
|
+
return false;
|
|
2063
|
+
});
|
|
1745
2064
|
}
|
|
1746
2065
|
async setHeadData(data) {
|
|
1747
|
-
this.
|
|
1748
|
-
|
|
1749
|
-
|
|
2066
|
+
return this.writeLock(async () => {
|
|
2067
|
+
this.strategy.head.data = data;
|
|
2068
|
+
this._strategyDirty = true;
|
|
2069
|
+
await this.commitHeadBuffer();
|
|
2070
|
+
});
|
|
1750
2071
|
}
|
|
1751
2072
|
async forceUpdate() {
|
|
1752
|
-
|
|
1753
|
-
|
|
1754
|
-
|
|
1755
|
-
|
|
1756
|
-
|
|
1757
|
-
|
|
1758
|
-
|
|
2073
|
+
return this.readLock(async () => {
|
|
2074
|
+
const keys = [...this.nodes.keys()];
|
|
2075
|
+
this.nodes.clear();
|
|
2076
|
+
await this.init();
|
|
2077
|
+
for (const key of keys) {
|
|
2078
|
+
await this.getNode(key);
|
|
2079
|
+
}
|
|
2080
|
+
return keys.length;
|
|
2081
|
+
});
|
|
1759
2082
|
}
|
|
1760
2083
|
};
|
|
1761
2084
|
|