@aztec/kv-store 0.0.0-test.1 → 0.0.1-commit.017a351
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 +8 -1
- package/dest/bench/shared_map_bench.d.ts +19 -0
- package/dest/bench/shared_map_bench.d.ts.map +1 -0
- package/dest/bench/shared_map_bench.js +91 -0
- package/dest/indexeddb/array.d.ts +3 -2
- package/dest/indexeddb/array.d.ts.map +1 -1
- package/dest/indexeddb/array.js +24 -7
- package/dest/indexeddb/index.d.ts +3 -3
- package/dest/indexeddb/index.d.ts.map +1 -1
- package/dest/indexeddb/index.js +4 -7
- package/dest/indexeddb/map.d.ts +18 -6
- package/dest/indexeddb/map.d.ts.map +1 -1
- package/dest/indexeddb/map.js +51 -63
- package/dest/indexeddb/multi_map.d.ts +14 -0
- package/dest/indexeddb/multi_map.d.ts.map +1 -0
- package/dest/indexeddb/multi_map.js +107 -0
- package/dest/indexeddb/set.d.ts +1 -1
- package/dest/indexeddb/set.d.ts.map +1 -1
- package/dest/indexeddb/singleton.d.ts +3 -2
- package/dest/indexeddb/singleton.d.ts.map +1 -1
- package/dest/indexeddb/singleton.js +6 -2
- package/dest/indexeddb/store.d.ts +15 -16
- package/dest/indexeddb/store.d.ts.map +1 -1
- package/dest/indexeddb/store.js +51 -46
- package/dest/interfaces/array.d.ts +5 -4
- package/dest/interfaces/array.d.ts.map +1 -1
- package/dest/interfaces/array.js +1 -3
- package/dest/interfaces/array_test_suite.d.ts +1 -1
- package/dest/interfaces/array_test_suite.d.ts.map +1 -1
- package/dest/interfaces/array_test_suite.js +33 -34
- package/dest/interfaces/common.d.ts +11 -9
- package/dest/interfaces/common.d.ts.map +1 -1
- package/dest/interfaces/common.js +8 -3
- package/dest/interfaces/counter.d.ts +1 -1
- package/dest/interfaces/index.d.ts +4 -2
- package/dest/interfaces/index.d.ts.map +1 -1
- package/dest/interfaces/index.js +2 -0
- package/dest/interfaces/map.d.ts +21 -49
- package/dest/interfaces/map.d.ts.map +1 -1
- package/dest/interfaces/map.js +1 -1
- package/dest/interfaces/map_test_suite.d.ts +1 -1
- package/dest/interfaces/map_test_suite.d.ts.map +1 -1
- package/dest/interfaces/map_test_suite.js +193 -83
- package/dest/interfaces/multi_map.d.ts +41 -0
- package/dest/interfaces/multi_map.d.ts.map +1 -0
- package/dest/interfaces/multi_map.js +3 -0
- package/dest/interfaces/multi_map_test_suite.d.ts +3 -0
- package/dest/interfaces/multi_map_test_suite.d.ts.map +1 -0
- package/dest/interfaces/multi_map_test_suite.js +363 -0
- package/dest/interfaces/set.d.ts +1 -1
- package/dest/interfaces/set_test_suite.d.ts +1 -1
- package/dest/interfaces/set_test_suite.d.ts.map +1 -1
- package/dest/interfaces/set_test_suite.js +13 -14
- package/dest/interfaces/singleton.d.ts +1 -1
- package/dest/interfaces/singleton_test_suite.d.ts +1 -1
- package/dest/interfaces/singleton_test_suite.d.ts.map +1 -1
- package/dest/interfaces/singleton_test_suite.js +6 -7
- package/dest/interfaces/store.d.ts +18 -43
- package/dest/interfaces/store.d.ts.map +1 -1
- package/dest/interfaces/utils.d.ts +3 -1
- package/dest/interfaces/utils.d.ts.map +1 -1
- package/dest/interfaces/utils.js +3 -1
- package/dest/lmdb/array.d.ts +3 -2
- package/dest/lmdb/array.d.ts.map +1 -1
- package/dest/lmdb/array.js +4 -2
- package/dest/lmdb/counter.d.ts +1 -1
- package/dest/lmdb/counter.d.ts.map +1 -1
- package/dest/lmdb/index.d.ts +3 -3
- package/dest/lmdb/index.d.ts.map +1 -1
- package/dest/lmdb/index.js +6 -6
- package/dest/lmdb/map.d.ts +11 -23
- package/dest/lmdb/map.d.ts.map +1 -1
- package/dest/lmdb/map.js +15 -81
- package/dest/lmdb/multi_map.d.ts +13 -0
- package/dest/lmdb/multi_map.d.ts.map +1 -0
- package/dest/lmdb/multi_map.js +44 -0
- package/dest/lmdb/set.d.ts +1 -1
- package/dest/lmdb/set.d.ts.map +1 -1
- package/dest/lmdb/singleton.d.ts +1 -1
- package/dest/lmdb/singleton.d.ts.map +1 -1
- package/dest/lmdb/store.d.ts +11 -27
- package/dest/lmdb/store.d.ts.map +1 -1
- package/dest/lmdb/store.js +24 -40
- package/dest/lmdb-v2/array.d.ts +4 -3
- package/dest/lmdb-v2/array.d.ts.map +1 -1
- package/dest/lmdb-v2/array.js +4 -2
- package/dest/lmdb-v2/factory.d.ts +32 -10
- package/dest/lmdb-v2/factory.d.ts.map +1 -1
- package/dest/lmdb-v2/factory.js +83 -18
- package/dest/lmdb-v2/index.d.ts +1 -1
- package/dest/lmdb-v2/map.d.ts +12 -45
- package/dest/lmdb-v2/map.d.ts.map +1 -1
- package/dest/lmdb-v2/map.js +17 -104
- package/dest/lmdb-v2/message.d.ts +24 -5
- package/dest/lmdb-v2/message.d.ts.map +1 -1
- package/dest/lmdb-v2/message.js +6 -4
- package/dest/lmdb-v2/multi_map.d.ts +52 -0
- package/dest/lmdb-v2/multi_map.d.ts.map +1 -0
- package/dest/lmdb-v2/multi_map.js +123 -0
- package/dest/lmdb-v2/read_transaction.d.ts +3 -1
- package/dest/lmdb-v2/read_transaction.d.ts.map +1 -1
- package/dest/lmdb-v2/read_transaction.js +47 -11
- package/dest/lmdb-v2/set.d.ts +15 -0
- package/dest/lmdb-v2/set.d.ts.map +1 -0
- package/dest/lmdb-v2/set.js +23 -0
- package/dest/lmdb-v2/singleton.d.ts +2 -2
- package/dest/lmdb-v2/singleton.d.ts.map +1 -1
- package/dest/lmdb-v2/singleton.js +1 -1
- package/dest/lmdb-v2/store.d.ts +13 -13
- package/dest/lmdb-v2/store.d.ts.map +1 -1
- package/dest/lmdb-v2/store.js +22 -32
- package/dest/lmdb-v2/tx-helpers.d.ts +6 -0
- package/dest/lmdb-v2/tx-helpers.d.ts.map +1 -0
- package/dest/lmdb-v2/tx-helpers.js +21 -0
- package/dest/lmdb-v2/utils.d.ts +3 -14
- package/dest/lmdb-v2/utils.d.ts.map +1 -1
- package/dest/lmdb-v2/utils.js +0 -94
- package/dest/lmdb-v2/write_transaction.d.ts +3 -5
- package/dest/lmdb-v2/write_transaction.d.ts.map +1 -1
- package/dest/lmdb-v2/write_transaction.js +9 -5
- package/dest/sqlite-opfs/array.d.ts +21 -0
- package/dest/sqlite-opfs/array.d.ts.map +1 -0
- package/dest/sqlite-opfs/array.js +128 -0
- package/dest/sqlite-opfs/errors.d.ts +27 -0
- package/dest/sqlite-opfs/errors.d.ts.map +1 -0
- package/dest/sqlite-opfs/errors.js +34 -0
- package/dest/sqlite-opfs/index.d.ts +16 -0
- package/dest/sqlite-opfs/index.d.ts.map +1 -0
- package/dest/sqlite-opfs/index.js +22 -0
- package/dest/sqlite-opfs/internal/ordered-binary-browser.d.ts +32 -0
- package/dest/sqlite-opfs/internal/ordered-binary-browser.d.ts.map +1 -0
- package/dest/sqlite-opfs/internal/ordered-binary-browser.js +448 -0
- package/dest/sqlite-opfs/map.d.ts +35 -0
- package/dest/sqlite-opfs/map.d.ts.map +1 -0
- package/dest/sqlite-opfs/map.js +163 -0
- package/dest/sqlite-opfs/messages.d.ts +66 -0
- package/dest/sqlite-opfs/messages.d.ts.map +1 -0
- package/dest/sqlite-opfs/messages.js +5 -0
- package/dest/sqlite-opfs/multi_map.d.ts +16 -0
- package/dest/sqlite-opfs/multi_map.d.ts.map +1 -0
- package/dest/sqlite-opfs/multi_map.js +67 -0
- package/dest/sqlite-opfs/set.d.ts +13 -0
- package/dest/sqlite-opfs/set.d.ts.map +1 -0
- package/dest/sqlite-opfs/set.js +19 -0
- package/dest/sqlite-opfs/singleton.d.ts +13 -0
- package/dest/sqlite-opfs/singleton.d.ts.map +1 -0
- package/dest/sqlite-opfs/singleton.js +48 -0
- package/dest/sqlite-opfs/store.d.ts +79 -0
- package/dest/sqlite-opfs/store.d.ts.map +1 -0
- package/dest/sqlite-opfs/store.js +281 -0
- package/dest/sqlite-opfs/worker.d.ts +2 -0
- package/dest/sqlite-opfs/worker.d.ts.map +1 -0
- package/dest/sqlite-opfs/worker.js +249 -0
- package/dest/stores/index.d.ts +2 -1
- package/dest/stores/index.d.ts.map +1 -1
- package/dest/stores/index.js +1 -0
- package/dest/stores/l2_tips_store.d.ts +25 -9
- package/dest/stores/l2_tips_store.d.ts.map +1 -1
- package/dest/stores/l2_tips_store.js +64 -46
- package/dest/utils.d.ts +9 -6
- package/dest/utils.d.ts.map +1 -1
- package/dest/utils.js +51 -16
- package/package.json +44 -33
- package/src/bench/shared_map_bench.ts +111 -0
- package/src/indexeddb/array.ts +9 -5
- package/src/indexeddb/index.ts +11 -9
- package/src/indexeddb/map.ts +51 -56
- package/src/indexeddb/multi_map.ts +105 -0
- package/src/indexeddb/singleton.ts +5 -2
- package/src/indexeddb/store.ts +77 -60
- package/src/interfaces/array.ts +5 -3
- package/src/interfaces/array_test_suite.ts +33 -35
- package/src/interfaces/common.ts +20 -9
- package/src/interfaces/index.ts +3 -1
- package/src/interfaces/map.ts +19 -53
- package/src/interfaces/map_test_suite.ts +113 -58
- package/src/interfaces/multi_map.ts +45 -0
- package/src/interfaces/multi_map_test_suite.ts +372 -0
- package/src/interfaces/set_test_suite.ts +13 -15
- package/src/interfaces/singleton_test_suite.ts +6 -8
- package/src/interfaces/store.ts +18 -53
- package/src/interfaces/utils.ts +2 -0
- package/src/lmdb/array.ts +2 -1
- package/src/lmdb/index.ts +13 -8
- package/src/lmdb/map.ts +23 -94
- package/src/lmdb/multi_map.ts +51 -0
- package/src/lmdb/store.ts +36 -56
- package/src/lmdb-v2/array.ts +8 -3
- package/src/lmdb-v2/factory.ts +107 -26
- package/src/lmdb-v2/map.ts +30 -127
- package/src/lmdb-v2/message.ts +23 -0
- package/src/lmdb-v2/multi_map.ts +150 -0
- package/src/lmdb-v2/read_transaction.ts +53 -13
- package/src/lmdb-v2/set.ts +33 -0
- package/src/lmdb-v2/singleton.ts +6 -2
- package/src/lmdb-v2/store.ts +28 -44
- package/src/lmdb-v2/tx-helpers.ts +29 -0
- package/src/lmdb-v2/utils.ts +0 -118
- package/src/lmdb-v2/write_transaction.ts +11 -10
- package/src/sqlite-opfs/array.ts +124 -0
- package/src/sqlite-opfs/errors.ts +44 -0
- package/src/sqlite-opfs/index.ts +39 -0
- package/src/sqlite-opfs/internal/ordered-binary-browser.js +465 -0
- package/src/sqlite-opfs/map.ts +163 -0
- package/src/sqlite-opfs/messages.ts +39 -0
- package/src/sqlite-opfs/multi_map.ts +74 -0
- package/src/sqlite-opfs/set.ts +29 -0
- package/src/sqlite-opfs/singleton.ts +48 -0
- package/src/sqlite-opfs/store.ts +296 -0
- package/src/sqlite-opfs/worker.ts +231 -0
- package/src/stores/index.ts +2 -0
- package/src/stores/l2_tips_store.ts +68 -49
- package/src/utils.ts +79 -21
- package/dest/config.d.ts +0 -17
- package/dest/config.d.ts.map +0 -1
- package/dest/config.js +0 -24
- package/dest/interfaces/store_test_suite.d.ts +0 -3
- package/dest/interfaces/store_test_suite.d.ts.map +0 -1
- package/dest/interfaces/store_test_suite.js +0 -37
- package/src/config.ts +0 -34
- package/src/interfaces/store_test_suite.ts +0 -56
package/dest/lmdb/store.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { randomBytes } from '@aztec/foundation/crypto';
|
|
1
|
+
import { randomBytes } from '@aztec/foundation/crypto/random';
|
|
2
2
|
import { createLogger } from '@aztec/foundation/log';
|
|
3
3
|
import { promises as fs, mkdirSync } from 'fs';
|
|
4
4
|
import { open } from 'lmdb';
|
|
@@ -6,7 +6,8 @@ import { tmpdir } from 'os';
|
|
|
6
6
|
import { join } from 'path';
|
|
7
7
|
import { LmdbAztecArray } from './array.js';
|
|
8
8
|
import { LmdbAztecCounter } from './counter.js';
|
|
9
|
-
import { LmdbAztecMap
|
|
9
|
+
import { LmdbAztecMap } from './map.js';
|
|
10
|
+
import { LmdbAztecMultiMap } from './multi_map.js';
|
|
10
11
|
import { LmdbAztecSet } from './set.js';
|
|
11
12
|
import { LmdbAztecSingleton } from './singleton.js';
|
|
12
13
|
/**
|
|
@@ -63,21 +64,6 @@ import { LmdbAztecSingleton } from './singleton.js';
|
|
|
63
64
|
return new AztecLmdbStore(rootDb, ephemeral, dbPath);
|
|
64
65
|
}
|
|
65
66
|
/**
|
|
66
|
-
* Forks the current DB into a new DB by backing it up to a temporary location and opening a new lmdb db.
|
|
67
|
-
* @returns A new AztecLmdbStore.
|
|
68
|
-
*/ async fork() {
|
|
69
|
-
const baseDir = this.path;
|
|
70
|
-
this.#log.debug(`Forking store with basedir ${baseDir}`);
|
|
71
|
-
const forkPath = await fs.mkdtemp(join(baseDir, 'aztec-store-fork-'));
|
|
72
|
-
this.#log.verbose(`Forking store to ${forkPath}`);
|
|
73
|
-
await this.#rootDb.backup(forkPath, false);
|
|
74
|
-
const forkDb = open(forkPath, {
|
|
75
|
-
noSync: this.isEphemeral
|
|
76
|
-
});
|
|
77
|
-
this.#log.debug(`Forked store at ${forkPath} opened successfully`);
|
|
78
|
-
return new AztecLmdbStore(forkDb, this.isEphemeral, forkPath);
|
|
79
|
-
}
|
|
80
|
-
/**
|
|
81
67
|
* Creates a new AztecMap in the store.
|
|
82
68
|
* @param name - Name of the map
|
|
83
69
|
* @returns A new AztecMap
|
|
@@ -96,26 +82,12 @@ import { LmdbAztecSingleton } from './singleton.js';
|
|
|
96
82
|
* @param name - Name of the map
|
|
97
83
|
* @returns A new AztecMultiMap
|
|
98
84
|
*/ openMultiMap(name) {
|
|
99
|
-
return new
|
|
85
|
+
return new LmdbAztecMultiMap(this.#multiMapData, name);
|
|
100
86
|
}
|
|
101
87
|
openCounter(name) {
|
|
102
88
|
return new LmdbAztecCounter(this.#data, name);
|
|
103
89
|
}
|
|
104
90
|
/**
|
|
105
|
-
* Creates a new AztecMultiMapWithSize in the store. A multi-map with size stores multiple values for a single key automatically.
|
|
106
|
-
* @param name - Name of the map
|
|
107
|
-
* @returns A new AztecMultiMapWithSize
|
|
108
|
-
*/ openMultiMapWithSize(name) {
|
|
109
|
-
return new LmdbAztecMapWithSize(this.#multiMapData, name);
|
|
110
|
-
}
|
|
111
|
-
/**
|
|
112
|
-
* Creates a new AztecMapWithSize in the store.
|
|
113
|
-
* @param name - Name of the map
|
|
114
|
-
* @returns A new AztecMapWithSize
|
|
115
|
-
*/ openMapWithSize(name) {
|
|
116
|
-
return new LmdbAztecMapWithSize(this.#data, name);
|
|
117
|
-
}
|
|
118
|
-
/**
|
|
119
91
|
* Creates a new AztecArray in the store.
|
|
120
92
|
* @param name - Name of the array
|
|
121
93
|
* @returns A new AztecArray
|
|
@@ -144,18 +116,22 @@ import { LmdbAztecSingleton } from './singleton.js';
|
|
|
144
116
|
return await this.#rootDb.transaction(callback);
|
|
145
117
|
}
|
|
146
118
|
/**
|
|
147
|
-
* Clears all entries in the store & sub DBs.
|
|
119
|
+
* Clears all entries in the store & sub DBs atomically within a single transaction.
|
|
148
120
|
*/ async clear() {
|
|
149
|
-
await this.#
|
|
150
|
-
|
|
151
|
-
|
|
121
|
+
await this.#rootDb.transaction(async ()=>{
|
|
122
|
+
await this.#data.clearAsync();
|
|
123
|
+
await this.#multiMapData.clearAsync();
|
|
124
|
+
await this.#rootDb.clearAsync();
|
|
125
|
+
});
|
|
152
126
|
}
|
|
153
127
|
/**
|
|
154
|
-
* Drops the database & sub DBs.
|
|
128
|
+
* Drops the database & sub DBs atomically within a single transaction.
|
|
155
129
|
*/ async drop() {
|
|
156
|
-
await this.#
|
|
157
|
-
|
|
158
|
-
|
|
130
|
+
await this.#rootDb.transaction(async ()=>{
|
|
131
|
+
await this.#data.drop();
|
|
132
|
+
await this.#multiMapData.drop();
|
|
133
|
+
await this.#rootDb.drop();
|
|
134
|
+
});
|
|
159
135
|
}
|
|
160
136
|
/**
|
|
161
137
|
* Close the database. Note, once this is closed we can no longer interact with the DB.
|
|
@@ -184,10 +160,15 @@ import { LmdbAztecSingleton } from './singleton.js';
|
|
|
184
160
|
if ('mapSize' in stats && typeof stats.mapSize === 'number') {
|
|
185
161
|
mapSize = stats.mapSize;
|
|
186
162
|
}
|
|
163
|
+
let physicalFileSize = 0;
|
|
164
|
+
if ('physicalFileSize' in stats && typeof stats.physicalFileSize === 'number') {
|
|
165
|
+
physicalFileSize = stats.physicalFileSize;
|
|
166
|
+
}
|
|
187
167
|
const dataResult = this.estimateSubDBSize(this.#data);
|
|
188
168
|
const multiResult = this.estimateSubDBSize(this.#multiMapData);
|
|
189
169
|
return Promise.resolve({
|
|
190
170
|
mappingSize: mapSize,
|
|
171
|
+
physicalFileSize: physicalFileSize,
|
|
191
172
|
actualSize: dataResult.actualSize + multiResult.actualSize,
|
|
192
173
|
numItems: dataResult.numItems + multiResult.numItems
|
|
193
174
|
});
|
|
@@ -213,4 +194,7 @@ import { LmdbAztecSingleton } from './singleton.js';
|
|
|
213
194
|
numItems
|
|
214
195
|
};
|
|
215
196
|
}
|
|
197
|
+
backupTo(_dstPath, _compact) {
|
|
198
|
+
throw new Error('Method not implemented.');
|
|
199
|
+
}
|
|
216
200
|
}
|
package/dest/lmdb-v2/array.d.ts
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import type { AztecAsyncArray } from '../interfaces/array.js';
|
|
2
|
-
import {
|
|
3
|
-
|
|
2
|
+
import type { Value } from '../interfaces/common.js';
|
|
3
|
+
import type { AztecLMDBStoreV2 } from './store.js';
|
|
4
|
+
export declare class LMDBArray<T extends Value> implements AztecAsyncArray<T> {
|
|
4
5
|
private store;
|
|
5
6
|
private length;
|
|
6
7
|
private encoder;
|
|
@@ -15,4 +16,4 @@ export declare class LMDBArray<T> implements AztecAsyncArray<T> {
|
|
|
15
16
|
valuesAsync(): AsyncIterableIterator<T>;
|
|
16
17
|
[Symbol.asyncIterator](): AsyncIterableIterator<T>;
|
|
17
18
|
}
|
|
18
|
-
//# sourceMappingURL=
|
|
19
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiYXJyYXkuZC50cyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy9sbWRiLXYyL2FycmF5LnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUVBLE9BQU8sS0FBSyxFQUFFLGVBQWUsRUFBRSxNQUFNLHdCQUF3QixDQUFDO0FBQzlELE9BQU8sS0FBSyxFQUFFLEtBQUssRUFBRSxNQUFNLHlCQUF5QixDQUFDO0FBR3JELE9BQU8sS0FBSyxFQUFFLGdCQUFnQixFQUFFLE1BQU0sWUFBWSxDQUFDO0FBSW5ELHFCQUFhLFNBQVMsQ0FBQyxDQUFDLFNBQVMsS0FBSyxDQUFFLFlBQVcsZUFBZSxDQUFDLENBQUMsQ0FBQztJQU1qRSxPQUFPLENBQUMsS0FBSztJQUxmLE9BQU8sQ0FBQyxNQUFNLENBQThCO0lBQzVDLE9BQU8sQ0FBQyxPQUFPLENBQWlCO0lBQ2hDLE9BQU8sQ0FBQyxNQUFNLENBQVM7SUFFdkIsWUFDVSxLQUFLLEVBQUUsZ0JBQWdCLEVBQy9CLElBQUksRUFBRSxNQUFNLEVBSWI7SUFFRCxHQUFHLElBQUksT0FBTyxDQUFDLENBQUMsR0FBRyxTQUFTLENBQUMsQ0FjNUI7SUFFRCxJQUFJLENBQUMsR0FBRyxJQUFJLEVBQUUsQ0FBQyxFQUFFLEdBQUcsT0FBTyxDQUFDLE1BQU0sQ0FBQyxDQVNsQztJQUVELEtBQUssQ0FBQyxLQUFLLEVBQUUsTUFBTSxFQUFFLEdBQUcsRUFBRSxDQUFDLEdBQUcsT0FBTyxDQUFDLE9BQU8sQ0FBQyxDQVk3QztJQUVELE9BQU8sQ0FBQyxLQUFLLEVBQUUsTUFBTSxHQUFHLE9BQU8sQ0FBQyxDQUFDLEdBQUcsU0FBUyxDQUFDLENBYTdDO0lBRUssV0FBVyxJQUFJLE9BQU8sQ0FBQyxNQUFNLENBQUMsQ0FFbkM7SUFFTSxZQUFZLElBQUkscUJBQXFCLENBQUMsQ0FBQyxNQUFNLEVBQUUsQ0FBQyxDQUFDLENBQUMsQ0F5QnhEO0lBRU0sV0FBVyxJQUFJLHFCQUFxQixDQUFDLENBQUMsQ0FBQyxDQUk3QztJQUVELENBQUMsTUFBTSxDQUFDLGFBQWEsQ0FBQyxJQUFJLHFCQUFxQixDQUFDLENBQUMsQ0FBQyxDQUVqRDtDQUNGIn0=
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"array.d.ts","sourceRoot":"","sources":["../../src/lmdb-v2/array.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,wBAAwB,CAAC;
|
|
1
|
+
{"version":3,"file":"array.d.ts","sourceRoot":"","sources":["../../src/lmdb-v2/array.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,wBAAwB,CAAC;AAC9D,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,yBAAyB,CAAC;AAGrD,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,YAAY,CAAC;AAInD,qBAAa,SAAS,CAAC,CAAC,SAAS,KAAK,CAAE,YAAW,eAAe,CAAC,CAAC,CAAC;IAMjE,OAAO,CAAC,KAAK;IALf,OAAO,CAAC,MAAM,CAA8B;IAC5C,OAAO,CAAC,OAAO,CAAiB;IAChC,OAAO,CAAC,MAAM,CAAS;IAEvB,YACU,KAAK,EAAE,gBAAgB,EAC/B,IAAI,EAAE,MAAM,EAIb;IAED,GAAG,IAAI,OAAO,CAAC,CAAC,GAAG,SAAS,CAAC,CAc5B;IAED,IAAI,CAAC,GAAG,IAAI,EAAE,CAAC,EAAE,GAAG,OAAO,CAAC,MAAM,CAAC,CASlC;IAED,KAAK,CAAC,KAAK,EAAE,MAAM,EAAE,GAAG,EAAE,CAAC,GAAG,OAAO,CAAC,OAAO,CAAC,CAY7C;IAED,OAAO,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,CAAC,GAAG,SAAS,CAAC,CAa7C;IAEK,WAAW,IAAI,OAAO,CAAC,MAAM,CAAC,CAEnC;IAEM,YAAY,IAAI,qBAAqB,CAAC,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC,CAyBxD;IAEM,WAAW,IAAI,qBAAqB,CAAC,CAAC,CAAC,CAI7C;IAED,CAAC,MAAM,CAAC,aAAa,CAAC,IAAI,qBAAqB,CAAC,CAAC,CAAC,CAEjD;CACF"}
|
package/dest/lmdb-v2/array.js
CHANGED
|
@@ -1,6 +1,8 @@
|
|
|
1
|
+
var _computedKey;
|
|
1
2
|
import { Encoder } from 'msgpackr/pack';
|
|
2
|
-
import { execInReadTx, execInWriteTx } from './
|
|
3
|
+
import { execInReadTx, execInWriteTx } from './tx-helpers.js';
|
|
3
4
|
import { deserializeKey, serializeKey } from './utils.js';
|
|
5
|
+
_computedKey = Symbol.asyncIterator;
|
|
4
6
|
export class LMDBArray {
|
|
5
7
|
store;
|
|
6
8
|
length;
|
|
@@ -95,7 +97,7 @@ export class LMDBArray {
|
|
|
95
97
|
yield value;
|
|
96
98
|
}
|
|
97
99
|
}
|
|
98
|
-
[
|
|
100
|
+
[_computedKey]() {
|
|
99
101
|
return this.valuesAsync();
|
|
100
102
|
}
|
|
101
103
|
}
|
|
@@ -1,12 +1,34 @@
|
|
|
1
1
|
import { EthAddress } from '@aztec/foundation/eth-address';
|
|
2
|
-
import { type
|
|
3
|
-
import type
|
|
2
|
+
import { type LoggerBindings } from '@aztec/foundation/log';
|
|
3
|
+
import { type SchemaVersionMismatchPolicy } from '@aztec/stdlib/database-version/manager';
|
|
4
|
+
import type { DataStoreConfig } from '@aztec/stdlib/kv-store';
|
|
4
5
|
import { AztecLMDBStoreV2 } from './store.js';
|
|
5
|
-
|
|
6
|
-
export
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
export declare function
|
|
11
|
-
|
|
12
|
-
|
|
6
|
+
/** Optional versioning hooks for persistent LMDB stores. */
|
|
7
|
+
export type CreateStoreOptions = {
|
|
8
|
+
onUpgrade?: (dataDir: string, currentVersion: number, latestVersion: number) => Promise<void>;
|
|
9
|
+
schemaVersionMismatchPolicy?: SchemaVersionMismatchPolicy;
|
|
10
|
+
};
|
|
11
|
+
export declare function createStore(name: string, schemaVersion: number, config: DataStoreConfig, bindings?: LoggerBindings, options?: CreateStoreOptions): Promise<AztecLMDBStoreV2>;
|
|
12
|
+
/**
|
|
13
|
+
* Open a persistent on-disk store rooted in OS tmpdir. Caller chooses whether to
|
|
14
|
+
* auto-remove the directory on close. Uses standard durable LMDB flags (fsync on
|
|
15
|
+
* every commit) — for full in-memory / NOSYNC semantics use `openEphemeralStore`.
|
|
16
|
+
*/
|
|
17
|
+
export declare function openTmpStore(name: string, cleanupTmpDir?: boolean, dbMapSizeKb?: number, maxReaders?: number, bindings?: LoggerBindings): Promise<AztecLMDBStoreV2>;
|
|
18
|
+
/**
|
|
19
|
+
* Open a fully-ephemeral store: a fresh tmpdir backing file, LMDB opened with
|
|
20
|
+
* MDB_NOSYNC | MDB_NOMETASYNC (no fsync, kernel-only writeback), and the directory
|
|
21
|
+
* unconditionally removed on close. Intended for tests and worker-local scratch
|
|
22
|
+
* stores where durability is explicitly not desired.
|
|
23
|
+
*/
|
|
24
|
+
export declare function openEphemeralStore(name: string, dbMapSizeKb?: number, maxReaders?: number, bindings?: LoggerBindings): Promise<AztecLMDBStoreV2>;
|
|
25
|
+
export declare function openStoreAt(dataDir: string, dbMapSizeKb?: number, maxReaders?: number, bindings?: LoggerBindings): Promise<AztecLMDBStoreV2>;
|
|
26
|
+
/**
|
|
27
|
+
* Open a fully-ephemeral store seeded from an existing `data.mdb` file. Creates a fresh tmpdir,
|
|
28
|
+
* copies `srcDataMdbPath` into it as `data.mdb`, opens with MDB_NOSYNC | MDB_NOMETASYNC, and
|
|
29
|
+
* removes the tmpdir on close. Intended for worker clones of a main-thread-built store — the
|
|
30
|
+
* source file is never written to.
|
|
31
|
+
*/
|
|
32
|
+
export declare function cloneEphemeralStoreFrom(srcDataMdbPath: string, name: string, dbMapSizeKb?: number, maxReaders?: number, bindings?: LoggerBindings): Promise<AztecLMDBStoreV2>;
|
|
33
|
+
export declare function openVersionedStoreAt(dataDirectory: string, schemaVersion: number, rollupAddress: EthAddress, dbMapSizeKb?: number, maxReaders?: number, bindings?: LoggerBindings): Promise<AztecLMDBStoreV2>;
|
|
34
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZmFjdG9yeS5kLnRzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vc3JjL2xtZGItdjIvZmFjdG9yeS50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEVBQUUsVUFBVSxFQUFFLE1BQU0sK0JBQStCLENBQUM7QUFDM0QsT0FBTyxFQUFFLEtBQUssY0FBYyxFQUFnQixNQUFNLHVCQUF1QixDQUFDO0FBQzFFLE9BQU8sRUFBMEIsS0FBSywyQkFBMkIsRUFBRSxNQUFNLHdDQUF3QyxDQUFDO0FBQ2xILE9BQU8sS0FBSyxFQUFFLGVBQWUsRUFBRSxNQUFNLHdCQUF3QixDQUFDO0FBTTlELE9BQU8sRUFBRSxnQkFBZ0IsRUFBRSxNQUFNLFlBQVksQ0FBQztBQUk5Qyw0REFBNEQ7QUFDNUQsTUFBTSxNQUFNLGtCQUFrQixHQUFHO0lBQy9CLFNBQVMsQ0FBQyxFQUFFLENBQUMsT0FBTyxFQUFFLE1BQU0sRUFBRSxjQUFjLEVBQUUsTUFBTSxFQUFFLGFBQWEsRUFBRSxNQUFNLEtBQUssT0FBTyxDQUFDLElBQUksQ0FBQyxDQUFDO0lBQzlGLDJCQUEyQixDQUFDLEVBQUUsMkJBQTJCLENBQUM7Q0FDM0QsQ0FBQztBQUVGLHdCQUFzQixXQUFXLENBQy9CLElBQUksRUFBRSxNQUFNLEVBQ1osYUFBYSxFQUFFLE1BQU0sRUFDckIsTUFBTSxFQUFFLGVBQWUsRUFDdkIsUUFBUSxDQUFDLEVBQUUsY0FBYyxFQUN6QixPQUFPLEdBQUUsa0JBQXVCLEdBQy9CLE9BQU8sQ0FBQyxnQkFBZ0IsQ0FBQyxDQWdDM0I7QUFFRDs7OztHQUlHO0FBQ0gsd0JBQXNCLFlBQVksQ0FDaEMsSUFBSSxFQUFFLE1BQU0sRUFDWixhQUFhLEdBQUUsT0FBYyxFQUM3QixXQUFXLFNBQXFCLEVBQ2hDLFVBQVUsU0FBYyxFQUN4QixRQUFRLENBQUMsRUFBRSxjQUFjLEdBQ3hCLE9BQU8sQ0FBQyxnQkFBZ0IsQ0FBQyxDQW9CM0I7QUFFRDs7Ozs7R0FLRztBQUNILHdCQUFzQixrQkFBa0IsQ0FDdEMsSUFBSSxFQUFFLE1BQU0sRUFDWixXQUFXLFNBQXFCLEVBQ2hDLFVBQVUsU0FBYyxFQUN4QixRQUFRLENBQUMsRUFBRSxjQUFjLEdBQ3hCLE9BQU8sQ0FBQyxnQkFBZ0IsQ0FBQyxDQWUzQjtBQUVELHdCQUFzQixXQUFXLENBQy9CLE9BQU8sRUFBRSxNQUFNLEVBQ2YsV0FBVyxTQUFxQixFQUNoQyxVQUFVLFNBQWMsRUFDeEIsUUFBUSxDQUFDLEVBQUUsY0FBYyxHQUN4QixPQUFPLENBQUMsZ0JBQWdCLENBQUMsQ0FJM0I7QUFFRDs7Ozs7R0FLRztBQUNILHdCQUFzQix1QkFBdUIsQ0FDM0MsY0FBYyxFQUFFLE1BQU0sRUFDdEIsSUFBSSxFQUFFLE1BQU0sRUFDWixXQUFXLFNBQXFCLEVBQ2hDLFVBQVUsU0FBYyxFQUN4QixRQUFRLENBQUMsRUFBRSxjQUFjLEdBQ3hCLE9BQU8sQ0FBQyxnQkFBZ0IsQ0FBQyxDQWdCM0I7QUFFRCx3QkFBc0Isb0JBQW9CLENBQ3hDLGFBQWEsRUFBRSxNQUFNLEVBQ3JCLGFBQWEsRUFBRSxNQUFNLEVBQ3JCLGFBQWEsRUFBRSxVQUFVLEVBQ3pCLFdBQVcsU0FBcUIsRUFDaEMsVUFBVSxTQUFjLEVBQ3hCLFFBQVEsQ0FBQyxFQUFFLGNBQWMsR0FDeEIsT0FBTyxDQUFDLGdCQUFnQixDQUFDLENBVTNCIn0=
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"factory.d.ts","sourceRoot":"","sources":["../../src/lmdb-v2/factory.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,+BAA+B,CAAC;AAC3D,OAAO,EAAE,KAAK,
|
|
1
|
+
{"version":3,"file":"factory.d.ts","sourceRoot":"","sources":["../../src/lmdb-v2/factory.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,+BAA+B,CAAC;AAC3D,OAAO,EAAE,KAAK,cAAc,EAAgB,MAAM,uBAAuB,CAAC;AAC1E,OAAO,EAA0B,KAAK,2BAA2B,EAAE,MAAM,wCAAwC,CAAC;AAClH,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,wBAAwB,CAAC;AAM9D,OAAO,EAAE,gBAAgB,EAAE,MAAM,YAAY,CAAC;AAI9C,4DAA4D;AAC5D,MAAM,MAAM,kBAAkB,GAAG;IAC/B,SAAS,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,EAAE,cAAc,EAAE,MAAM,EAAE,aAAa,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IAC9F,2BAA2B,CAAC,EAAE,2BAA2B,CAAC;CAC3D,CAAC;AAEF,wBAAsB,WAAW,CAC/B,IAAI,EAAE,MAAM,EACZ,aAAa,EAAE,MAAM,EACrB,MAAM,EAAE,eAAe,EACvB,QAAQ,CAAC,EAAE,cAAc,EACzB,OAAO,GAAE,kBAAuB,GAC/B,OAAO,CAAC,gBAAgB,CAAC,CAgC3B;AAED;;;;GAIG;AACH,wBAAsB,YAAY,CAChC,IAAI,EAAE,MAAM,EACZ,aAAa,GAAE,OAAc,EAC7B,WAAW,SAAqB,EAChC,UAAU,SAAc,EACxB,QAAQ,CAAC,EAAE,cAAc,GACxB,OAAO,CAAC,gBAAgB,CAAC,CAoB3B;AAED;;;;;GAKG;AACH,wBAAsB,kBAAkB,CACtC,IAAI,EAAE,MAAM,EACZ,WAAW,SAAqB,EAChC,UAAU,SAAc,EACxB,QAAQ,CAAC,EAAE,cAAc,GACxB,OAAO,CAAC,gBAAgB,CAAC,CAe3B;AAED,wBAAsB,WAAW,CAC/B,OAAO,EAAE,MAAM,EACf,WAAW,SAAqB,EAChC,UAAU,SAAc,EACxB,QAAQ,CAAC,EAAE,cAAc,GACxB,OAAO,CAAC,gBAAgB,CAAC,CAI3B;AAED;;;;;GAKG;AACH,wBAAsB,uBAAuB,CAC3C,cAAc,EAAE,MAAM,EACtB,IAAI,EAAE,MAAM,EACZ,WAAW,SAAqB,EAChC,UAAU,SAAc,EACxB,QAAQ,CAAC,EAAE,cAAc,GACxB,OAAO,CAAC,gBAAgB,CAAC,CAgB3B;AAED,wBAAsB,oBAAoB,CACxC,aAAa,EAAE,MAAM,EACrB,aAAa,EAAE,MAAM,EACrB,aAAa,EAAE,UAAU,EACzB,WAAW,SAAqB,EAChC,UAAU,SAAc,EACxB,QAAQ,CAAC,EAAE,cAAc,GACxB,OAAO,CAAC,gBAAgB,CAAC,CAU3B"}
|
package/dest/lmdb-v2/factory.js
CHANGED
|
@@ -1,13 +1,14 @@
|
|
|
1
1
|
import { EthAddress } from '@aztec/foundation/eth-address';
|
|
2
2
|
import { createLogger } from '@aztec/foundation/log';
|
|
3
|
-
import { DatabaseVersionManager } from '@aztec/stdlib/database-version';
|
|
4
|
-
import { mkdir, mkdtemp, rm } from 'fs/promises';
|
|
3
|
+
import { DatabaseVersionManager } from '@aztec/stdlib/database-version/manager';
|
|
4
|
+
import { copyFile, mkdir, mkdtemp, rm } from 'fs/promises';
|
|
5
5
|
import { tmpdir } from 'os';
|
|
6
6
|
import { join } from 'path';
|
|
7
7
|
import { AztecLMDBStoreV2 } from './store.js';
|
|
8
8
|
const MAX_READERS = 16;
|
|
9
|
-
export async function createStore(name, schemaVersion, config,
|
|
10
|
-
const
|
|
9
|
+
export async function createStore(name, schemaVersion, config, bindings, options = {}) {
|
|
10
|
+
const log = createLogger('kv-store:lmdb-v2:' + name, bindings);
|
|
11
|
+
const { dataDirectory, rollupAddress: rollupFromConfig } = config;
|
|
11
12
|
let store;
|
|
12
13
|
if (typeof dataDirectory !== 'undefined') {
|
|
13
14
|
// Get rollup address from contracts config, or use zero address
|
|
@@ -15,22 +16,34 @@ export async function createStore(name, schemaVersion, config, log = createLogge
|
|
|
15
16
|
await mkdir(subDir, {
|
|
16
17
|
recursive: true
|
|
17
18
|
});
|
|
18
|
-
const rollupAddress =
|
|
19
|
+
const rollupAddress = rollupFromConfig ?? EthAddress.ZERO;
|
|
19
20
|
// Create a version manager
|
|
20
|
-
const versionManager = new DatabaseVersionManager(
|
|
21
|
-
|
|
21
|
+
const versionManager = new DatabaseVersionManager({
|
|
22
|
+
schemaVersion,
|
|
23
|
+
rollupAddress,
|
|
24
|
+
dataDirectory: subDir,
|
|
25
|
+
onOpen: (dbDirectory)=>AztecLMDBStoreV2.new(dbDirectory, config.dataStoreMapSizeKb, MAX_READERS, ()=>Promise.resolve(), bindings),
|
|
26
|
+
onUpgrade: options.onUpgrade,
|
|
27
|
+
schemaVersionMismatchPolicy: options.schemaVersionMismatchPolicy
|
|
28
|
+
});
|
|
29
|
+
log.info(`Creating ${name} data store at directory ${subDir} with map size ${config.dataStoreMapSizeKb} KB (LMDB v2)`);
|
|
22
30
|
[store] = await versionManager.open();
|
|
23
31
|
} else {
|
|
24
|
-
store = await openTmpStore(name, true, config.
|
|
32
|
+
store = await openTmpStore(name, true, config.dataStoreMapSizeKb, MAX_READERS, bindings);
|
|
25
33
|
}
|
|
26
34
|
return store;
|
|
27
35
|
}
|
|
28
|
-
|
|
36
|
+
/**
|
|
37
|
+
* Open a persistent on-disk store rooted in OS tmpdir. Caller chooses whether to
|
|
38
|
+
* auto-remove the directory on close. Uses standard durable LMDB flags (fsync on
|
|
39
|
+
* every commit) — for full in-memory / NOSYNC semantics use `openEphemeralStore`.
|
|
40
|
+
*/ export async function openTmpStore(name, cleanupTmpDir = true, dbMapSizeKb = 10 * 1_024 * 1_024, maxReaders = MAX_READERS, bindings) {
|
|
41
|
+
const log = createLogger('kv-store:lmdb-v2:' + name, bindings);
|
|
29
42
|
const dataDir = await mkdtemp(join(tmpdir(), name + '-'));
|
|
30
43
|
log.debug(`Created temporary data store at: ${dataDir} with size: ${dbMapSizeKb} KB (LMDB v2)`);
|
|
31
44
|
// pass a cleanup callback because process.on('beforeExit', cleanup) does not work under Jest
|
|
32
45
|
const cleanup = async ()=>{
|
|
33
|
-
if (
|
|
46
|
+
if (cleanupTmpDir) {
|
|
34
47
|
try {
|
|
35
48
|
await rm(dataDir, {
|
|
36
49
|
recursive: true,
|
|
@@ -45,16 +58,68 @@ export async function openTmpStore(name, ephemeral = true, dbMapSizeKb = 10 * 1_
|
|
|
45
58
|
log.debug(`Leaving temporary data store: ${dataDir}`);
|
|
46
59
|
}
|
|
47
60
|
};
|
|
48
|
-
|
|
49
|
-
// as they are ephemeral and get cleaned up after use
|
|
50
|
-
return AztecLMDBStoreV2.new(dataDir, dbMapSizeKb, maxReaders, cleanup, log);
|
|
61
|
+
return AztecLMDBStoreV2.new(dataDir, dbMapSizeKb, maxReaders, cleanup, bindings, false);
|
|
51
62
|
}
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
63
|
+
/**
|
|
64
|
+
* Open a fully-ephemeral store: a fresh tmpdir backing file, LMDB opened with
|
|
65
|
+
* MDB_NOSYNC | MDB_NOMETASYNC (no fsync, kernel-only writeback), and the directory
|
|
66
|
+
* unconditionally removed on close. Intended for tests and worker-local scratch
|
|
67
|
+
* stores where durability is explicitly not desired.
|
|
68
|
+
*/ export async function openEphemeralStore(name, dbMapSizeKb = 10 * 1_024 * 1_024, maxReaders = MAX_READERS, bindings) {
|
|
69
|
+
const log = createLogger('kv-store:lmdb-v2:' + name, bindings);
|
|
70
|
+
const dataDir = await mkdtemp(join(tmpdir(), name + '-'));
|
|
71
|
+
log.debug(`Created ephemeral data store at: ${dataDir} with size: ${dbMapSizeKb} KB (LMDB v2)`);
|
|
72
|
+
const cleanup = async ()=>{
|
|
73
|
+
try {
|
|
74
|
+
await rm(dataDir, {
|
|
75
|
+
recursive: true,
|
|
76
|
+
force: true,
|
|
77
|
+
maxRetries: 3
|
|
78
|
+
});
|
|
79
|
+
log.debug(`Deleted ephemeral data store: ${dataDir}`);
|
|
80
|
+
} catch (err) {
|
|
81
|
+
log.warn(`Failed to delete ephemeral data directory (LMDB v2) ${dataDir}: ${err}`);
|
|
82
|
+
}
|
|
83
|
+
};
|
|
84
|
+
return AztecLMDBStoreV2.new(dataDir, dbMapSizeKb, maxReaders, cleanup, bindings, true);
|
|
55
85
|
}
|
|
56
|
-
export async function
|
|
86
|
+
export async function openStoreAt(dataDir, dbMapSizeKb = 10 * 1_024 * 1_024, maxReaders = MAX_READERS, bindings) {
|
|
87
|
+
const log = createLogger('kv-store:lmdb-v2', bindings);
|
|
57
88
|
log.debug(`Opening data store at: ${dataDir} with size: ${dbMapSizeKb} KB (LMDB v2)`);
|
|
58
|
-
|
|
89
|
+
return await AztecLMDBStoreV2.new(dataDir, dbMapSizeKb, maxReaders, undefined, bindings);
|
|
90
|
+
}
|
|
91
|
+
/**
|
|
92
|
+
* Open a fully-ephemeral store seeded from an existing `data.mdb` file. Creates a fresh tmpdir,
|
|
93
|
+
* copies `srcDataMdbPath` into it as `data.mdb`, opens with MDB_NOSYNC | MDB_NOMETASYNC, and
|
|
94
|
+
* removes the tmpdir on close. Intended for worker clones of a main-thread-built store — the
|
|
95
|
+
* source file is never written to.
|
|
96
|
+
*/ export async function cloneEphemeralStoreFrom(srcDataMdbPath, name, dbMapSizeKb = 10 * 1_024 * 1_024, maxReaders = MAX_READERS, bindings) {
|
|
97
|
+
const log = createLogger('kv-store:lmdb-v2:' + name, bindings);
|
|
98
|
+
const dataDir = await mkdtemp(join(tmpdir(), name + '-'));
|
|
99
|
+
await copyFile(srcDataMdbPath, join(dataDir, 'data.mdb'));
|
|
100
|
+
log.debug(`Cloned ephemeral data store at: ${dataDir} from ${srcDataMdbPath} (LMDB v2)`);
|
|
101
|
+
const cleanup = async ()=>{
|
|
102
|
+
try {
|
|
103
|
+
await rm(dataDir, {
|
|
104
|
+
recursive: true,
|
|
105
|
+
force: true,
|
|
106
|
+
maxRetries: 3
|
|
107
|
+
});
|
|
108
|
+
log.debug(`Deleted ephemeral data store: ${dataDir}`);
|
|
109
|
+
} catch (err) {
|
|
110
|
+
log.warn(`Failed to delete ephemeral data directory (LMDB v2) ${dataDir}: ${err}`);
|
|
111
|
+
}
|
|
112
|
+
};
|
|
113
|
+
return AztecLMDBStoreV2.new(dataDir, dbMapSizeKb, maxReaders, cleanup, bindings, true);
|
|
114
|
+
}
|
|
115
|
+
export async function openVersionedStoreAt(dataDirectory, schemaVersion, rollupAddress, dbMapSizeKb = 10 * 1_024 * 1_024, maxReaders = MAX_READERS, bindings) {
|
|
116
|
+
const log = createLogger('kv-store:lmdb-v2', bindings);
|
|
117
|
+
log.debug(`Opening data store at: ${dataDirectory} with size: ${dbMapSizeKb} KB (LMDB v2)`);
|
|
118
|
+
const [store] = await new DatabaseVersionManager({
|
|
119
|
+
schemaVersion,
|
|
120
|
+
rollupAddress,
|
|
121
|
+
dataDirectory,
|
|
122
|
+
onOpen: (dataDir)=>AztecLMDBStoreV2.new(dataDir, dbMapSizeKb, maxReaders, undefined, bindings)
|
|
123
|
+
}).open();
|
|
59
124
|
return store;
|
|
60
125
|
}
|
package/dest/lmdb-v2/index.d.ts
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
1
|
export * from './store.js';
|
|
2
2
|
export * from './factory.js';
|
|
3
|
-
//# sourceMappingURL=
|
|
3
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5kZXguZC50cyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy9sbWRiLXYyL2luZGV4LnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLGNBQWMsWUFBWSxDQUFDO0FBQzNCLGNBQWMsY0FBYyxDQUFDIn0=
|
package/dest/lmdb-v2/map.d.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import type { Key, Range } from '../interfaces/common.js';
|
|
2
|
-
import type { AztecAsyncMap
|
|
3
|
-
import {
|
|
4
|
-
export declare class LMDBMap<K extends Key, V> implements AztecAsyncMap<K, V> {
|
|
1
|
+
import type { Key, Range, Value } from '../interfaces/common.js';
|
|
2
|
+
import type { AztecAsyncMap } from '../interfaces/map.js';
|
|
3
|
+
import type { AztecLMDBStoreV2 } from './store.js';
|
|
4
|
+
export declare class LMDBMap<K extends Key, V extends Value> implements AztecAsyncMap<K, V> {
|
|
5
5
|
private store;
|
|
6
6
|
private prefix;
|
|
7
7
|
private encoder;
|
|
@@ -13,45 +13,13 @@ export declare class LMDBMap<K extends Key, V> implements AztecAsyncMap<K, V> {
|
|
|
13
13
|
*/
|
|
14
14
|
set(key: K, val: V): Promise<void>;
|
|
15
15
|
/**
|
|
16
|
-
* Sets the
|
|
17
|
-
* @param
|
|
18
|
-
* @param val - The value to set
|
|
19
|
-
*/
|
|
20
|
-
setIfNotExists(key: K, val: V): Promise<boolean>;
|
|
21
|
-
/**
|
|
22
|
-
* Deletes the value at the given key.
|
|
23
|
-
* @param key - The key to delete the value at
|
|
16
|
+
* Sets the values at the given keys.
|
|
17
|
+
* @param entries - The entries to set
|
|
24
18
|
*/
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
* Iterates over the map's key-value entries in the key's natural order
|
|
30
|
-
* @param range - The range of keys to iterate over
|
|
31
|
-
*/
|
|
32
|
-
entriesAsync(range?: Range<K>): AsyncIterableIterator<[K, V]>;
|
|
33
|
-
/**
|
|
34
|
-
* Iterates over the map's values in the key's natural order
|
|
35
|
-
* @param range - The range of keys to iterate over
|
|
36
|
-
*/
|
|
37
|
-
valuesAsync(range?: Range<K>): AsyncIterableIterator<V>;
|
|
38
|
-
/**
|
|
39
|
-
* Iterates over the map's keys in the key's natural order
|
|
40
|
-
* @param range - The range of keys to iterate over
|
|
41
|
-
*/
|
|
42
|
-
keysAsync(range?: Range<K>): AsyncIterableIterator<K>;
|
|
43
|
-
}
|
|
44
|
-
export declare class LMDBMultiMap<K extends Key, V> implements AztecAsyncMultiMap<K, V> {
|
|
45
|
-
private store;
|
|
46
|
-
private prefix;
|
|
47
|
-
private encoder;
|
|
48
|
-
constructor(store: AztecLMDBStoreV2, name: string);
|
|
49
|
-
/**
|
|
50
|
-
* Sets the value at the given key.
|
|
51
|
-
* @param key - The key to set the value at
|
|
52
|
-
* @param val - The value to set
|
|
53
|
-
*/
|
|
54
|
-
set(key: K, val: V): Promise<void>;
|
|
19
|
+
setMany(entries: {
|
|
20
|
+
key: K;
|
|
21
|
+
value: V;
|
|
22
|
+
}[]): Promise<void>;
|
|
55
23
|
/**
|
|
56
24
|
* Sets the value at the given key if it does not already exist.
|
|
57
25
|
* @param key - The key to set the value at
|
|
@@ -65,6 +33,7 @@ export declare class LMDBMultiMap<K extends Key, V> implements AztecAsyncMultiMa
|
|
|
65
33
|
delete(key: K): Promise<void>;
|
|
66
34
|
getAsync(key: K): Promise<V | undefined>;
|
|
67
35
|
hasAsync(key: K): Promise<boolean>;
|
|
36
|
+
sizeAsync(): Promise<number>;
|
|
68
37
|
/**
|
|
69
38
|
* Iterates over the map's key-value entries in the key's natural order
|
|
70
39
|
* @param range - The range of keys to iterate over
|
|
@@ -80,7 +49,5 @@ export declare class LMDBMultiMap<K extends Key, V> implements AztecAsyncMultiMa
|
|
|
80
49
|
* @param range - The range of keys to iterate over
|
|
81
50
|
*/
|
|
82
51
|
keysAsync(range?: Range<K>): AsyncIterableIterator<K>;
|
|
83
|
-
deleteValue(key: K, val: V | undefined): Promise<void>;
|
|
84
|
-
getValuesAsync(key: K): AsyncIterableIterator<V>;
|
|
85
52
|
}
|
|
86
|
-
//# sourceMappingURL=
|
|
53
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibWFwLmQudHMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi9zcmMvbG1kYi12Mi9tYXAudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBRUEsT0FBTyxLQUFLLEVBQUUsR0FBRyxFQUFFLEtBQUssRUFBRSxLQUFLLEVBQUUsTUFBTSx5QkFBeUIsQ0FBQztBQUNqRSxPQUFPLEtBQUssRUFBRSxhQUFhLEVBQUUsTUFBTSxzQkFBc0IsQ0FBQztBQUUxRCxPQUFPLEtBQUssRUFBRSxnQkFBZ0IsRUFBRSxNQUFNLFlBQVksQ0FBQztBQUluRCxxQkFBYSxPQUFPLENBQUMsQ0FBQyxTQUFTLEdBQUcsRUFBRSxDQUFDLFNBQVMsS0FBSyxDQUFFLFlBQVcsYUFBYSxDQUFDLENBQUMsRUFBRSxDQUFDLENBQUM7SUFLL0UsT0FBTyxDQUFDLEtBQUs7SUFKZixPQUFPLENBQUMsTUFBTSxDQUFTO0lBQ3ZCLE9BQU8sQ0FBQyxPQUFPLENBQWlCO0lBRWhDLFlBQ1UsS0FBSyxFQUFFLGdCQUFnQixFQUMvQixJQUFJLEVBQUUsTUFBTSxFQUdiO0lBQ0Q7Ozs7T0FJRztJQUNILEdBQUcsQ0FBQyxHQUFHLEVBQUUsQ0FBQyxFQUFFLEdBQUcsRUFBRSxDQUFDLEdBQUcsT0FBTyxDQUFDLElBQUksQ0FBQyxDQUVqQztJQUVEOzs7T0FHRztJQUNHLE9BQU8sQ0FBQyxPQUFPLEVBQUU7UUFBRSxHQUFHLEVBQUUsQ0FBQyxDQUFDO1FBQUMsS0FBSyxFQUFFLENBQUMsQ0FBQTtLQUFFLEVBQUUsR0FBRyxPQUFPLENBQUMsSUFBSSxDQUFDLENBTTVEO0lBRUQ7Ozs7T0FJRztJQUNILGNBQWMsQ0FBQyxHQUFHLEVBQUUsQ0FBQyxFQUFFLEdBQUcsRUFBRSxDQUFDLEdBQUcsT0FBTyxDQUFDLE9BQU8sQ0FBQyxDQVUvQztJQUVEOzs7T0FHRztJQUNILE1BQU0sQ0FBQyxHQUFHLEVBQUUsQ0FBQyxHQUFHLE9BQU8sQ0FBQyxJQUFJLENBQUMsQ0FFNUI7SUFFRCxRQUFRLENBQUMsR0FBRyxFQUFFLENBQUMsR0FBRyxPQUFPLENBQUMsQ0FBQyxHQUFHLFNBQVMsQ0FBQyxDQUt2QztJQUVELFFBQVEsQ0FBQyxHQUFHLEVBQUUsQ0FBQyxHQUFHLE9BQU8sQ0FBQyxPQUFPLENBQUMsQ0FFakM7SUFFRCxTQUFTLElBQUksT0FBTyxDQUFDLE1BQU0sQ0FBQyxDQUUzQjtJQUVEOzs7T0FHRztJQUNJLFlBQVksQ0FBQyxLQUFLLENBQUMsRUFBRSxLQUFLLENBQUMsQ0FBQyxDQUFDLEdBQUcscUJBQXFCLENBQUMsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxDQUFDLENBQUMsQ0E4Qm5FO0lBRUQ7OztPQUdHO0lBQ0ksV0FBVyxDQUFDLEtBQUssQ0FBQyxFQUFFLEtBQUssQ0FBQyxDQUFDLENBQUMsR0FBRyxxQkFBcUIsQ0FBQyxDQUFDLENBQUMsQ0FJN0Q7SUFFRDs7O09BR0c7SUFDSSxTQUFTLENBQUMsS0FBSyxDQUFDLEVBQUUsS0FBSyxDQUFDLENBQUMsQ0FBQyxHQUFHLHFCQUFxQixDQUFDLENBQUMsQ0FBQyxDQUkzRDtDQUNGIn0=
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"map.d.ts","sourceRoot":"","sources":["../../src/lmdb-v2/map.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,GAAG,EAAE,KAAK,EAAE,MAAM,yBAAyB,CAAC;
|
|
1
|
+
{"version":3,"file":"map.d.ts","sourceRoot":"","sources":["../../src/lmdb-v2/map.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,GAAG,EAAE,KAAK,EAAE,KAAK,EAAE,MAAM,yBAAyB,CAAC;AACjE,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;AAE1D,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,YAAY,CAAC;AAInD,qBAAa,OAAO,CAAC,CAAC,SAAS,GAAG,EAAE,CAAC,SAAS,KAAK,CAAE,YAAW,aAAa,CAAC,CAAC,EAAE,CAAC,CAAC;IAK/E,OAAO,CAAC,KAAK;IAJf,OAAO,CAAC,MAAM,CAAS;IACvB,OAAO,CAAC,OAAO,CAAiB;IAEhC,YACU,KAAK,EAAE,gBAAgB,EAC/B,IAAI,EAAE,MAAM,EAGb;IACD;;;;OAIG;IACH,GAAG,CAAC,GAAG,EAAE,CAAC,EAAE,GAAG,EAAE,CAAC,GAAG,OAAO,CAAC,IAAI,CAAC,CAEjC;IAED;;;OAGG;IACG,OAAO,CAAC,OAAO,EAAE;QAAE,GAAG,EAAE,CAAC,CAAC;QAAC,KAAK,EAAE,CAAC,CAAA;KAAE,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC,CAM5D;IAED;;;;OAIG;IACH,cAAc,CAAC,GAAG,EAAE,CAAC,EAAE,GAAG,EAAE,CAAC,GAAG,OAAO,CAAC,OAAO,CAAC,CAU/C;IAED;;;OAGG;IACH,MAAM,CAAC,GAAG,EAAE,CAAC,GAAG,OAAO,CAAC,IAAI,CAAC,CAE5B;IAED,QAAQ,CAAC,GAAG,EAAE,CAAC,GAAG,OAAO,CAAC,CAAC,GAAG,SAAS,CAAC,CAKvC;IAED,QAAQ,CAAC,GAAG,EAAE,CAAC,GAAG,OAAO,CAAC,OAAO,CAAC,CAEjC;IAED,SAAS,IAAI,OAAO,CAAC,MAAM,CAAC,CAE3B;IAED;;;OAGG;IACI,YAAY,CAAC,KAAK,CAAC,EAAE,KAAK,CAAC,CAAC,CAAC,GAAG,qBAAqB,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CA8BnE;IAED;;;OAGG;IACI,WAAW,CAAC,KAAK,CAAC,EAAE,KAAK,CAAC,CAAC,CAAC,GAAG,qBAAqB,CAAC,CAAC,CAAC,CAI7D;IAED;;;OAGG;IACI,SAAS,CAAC,KAAK,CAAC,EAAE,KAAK,CAAC,CAAC,CAAC,GAAG,qBAAqB,CAAC,CAAC,CAAC,CAI3D;CACF"}
|
package/dest/lmdb-v2/map.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { Encoder } from 'msgpackr';
|
|
2
|
-
import { execInReadTx, execInWriteTx } from './
|
|
2
|
+
import { execInReadTx, execInWriteTx } from './tx-helpers.js';
|
|
3
3
|
import { deserializeKey, maxKey, minKey, serializeKey } from './utils.js';
|
|
4
4
|
export class LMDBMap {
|
|
5
5
|
store;
|
|
@@ -18,6 +18,16 @@ export class LMDBMap {
|
|
|
18
18
|
return execInWriteTx(this.store, (tx)=>tx.set(serializeKey(this.prefix, key), this.encoder.pack(val)));
|
|
19
19
|
}
|
|
20
20
|
/**
|
|
21
|
+
* Sets the values at the given keys.
|
|
22
|
+
* @param entries - The entries to set
|
|
23
|
+
*/ async setMany(entries) {
|
|
24
|
+
await execInWriteTx(this.store, async (tx)=>{
|
|
25
|
+
for (const { key, value } of entries){
|
|
26
|
+
await tx.set(serializeKey(this.prefix, key), this.encoder.pack(value));
|
|
27
|
+
}
|
|
28
|
+
});
|
|
29
|
+
}
|
|
30
|
+
/**
|
|
21
31
|
* Sets the value at the given key if it does not already exist.
|
|
22
32
|
* @param key - The key to set the value at
|
|
23
33
|
* @param val - The value to set
|
|
@@ -47,20 +57,23 @@ export class LMDBMap {
|
|
|
47
57
|
hasAsync(key) {
|
|
48
58
|
return execInReadTx(this.store, async (tx)=>!!await tx.get(serializeKey(this.prefix, key)));
|
|
49
59
|
}
|
|
60
|
+
sizeAsync() {
|
|
61
|
+
return execInReadTx(this.store, (tx)=>tx.countEntries(minKey(this.prefix), maxKey(this.prefix), false));
|
|
62
|
+
}
|
|
50
63
|
/**
|
|
51
64
|
* Iterates over the map's key-value entries in the key's natural order
|
|
52
65
|
* @param range - The range of keys to iterate over
|
|
53
66
|
*/ async *entriesAsync(range) {
|
|
54
67
|
const reverse = range?.reverse ?? false;
|
|
55
|
-
const startKey = range?.start ? serializeKey(this.prefix, range.start) : minKey(this.prefix);
|
|
56
|
-
const endKey = range?.end ? serializeKey(this.prefix, range.end) : reverse ? maxKey(this.prefix) : undefined;
|
|
68
|
+
const startKey = range?.start !== undefined ? serializeKey(this.prefix, range.start) : minKey(this.prefix);
|
|
69
|
+
const endKey = range?.end !== undefined ? serializeKey(this.prefix, range.end) : reverse ? maxKey(this.prefix) : undefined;
|
|
57
70
|
let tx = this.store.getCurrentWriteTx();
|
|
58
71
|
const shouldClose = !tx;
|
|
59
72
|
tx ??= this.store.getReadTx();
|
|
60
73
|
try {
|
|
61
74
|
for await (const [key, val] of tx.iterate(reverse ? endKey : startKey, reverse ? startKey : endKey, reverse, range?.limit)){
|
|
62
75
|
const deserializedKey = deserializeKey(this.prefix, key);
|
|
63
|
-
if (
|
|
76
|
+
if (deserializedKey === false) {
|
|
64
77
|
break;
|
|
65
78
|
}
|
|
66
79
|
yield [
|
|
@@ -91,103 +104,3 @@ export class LMDBMap {
|
|
|
91
104
|
}
|
|
92
105
|
}
|
|
93
106
|
}
|
|
94
|
-
export class LMDBMultiMap {
|
|
95
|
-
store;
|
|
96
|
-
prefix;
|
|
97
|
-
encoder;
|
|
98
|
-
constructor(store, name){
|
|
99
|
-
this.store = store;
|
|
100
|
-
this.encoder = new Encoder();
|
|
101
|
-
this.prefix = `multimap:${name}`;
|
|
102
|
-
}
|
|
103
|
-
/**
|
|
104
|
-
* Sets the value at the given key.
|
|
105
|
-
* @param key - The key to set the value at
|
|
106
|
-
* @param val - The value to set
|
|
107
|
-
*/ set(key, val) {
|
|
108
|
-
return execInWriteTx(this.store, (tx)=>tx.setIndex(serializeKey(this.prefix, key), this.encoder.pack(val)));
|
|
109
|
-
}
|
|
110
|
-
/**
|
|
111
|
-
* Sets the value at the given key if it does not already exist.
|
|
112
|
-
* @param key - The key to set the value at
|
|
113
|
-
* @param val - The value to set
|
|
114
|
-
*/ setIfNotExists(key, val) {
|
|
115
|
-
return execInWriteTx(this.store, async (tx)=>{
|
|
116
|
-
const exists = !!await this.getAsync(key);
|
|
117
|
-
if (!exists) {
|
|
118
|
-
await tx.setIndex(serializeKey(this.prefix, key), this.encoder.pack(val));
|
|
119
|
-
return true;
|
|
120
|
-
}
|
|
121
|
-
return false;
|
|
122
|
-
});
|
|
123
|
-
}
|
|
124
|
-
/**
|
|
125
|
-
* Deletes the value at the given key.
|
|
126
|
-
* @param key - The key to delete the value at
|
|
127
|
-
*/ delete(key) {
|
|
128
|
-
return execInWriteTx(this.store, (tx)=>tx.removeIndex(serializeKey(this.prefix, key)));
|
|
129
|
-
}
|
|
130
|
-
getAsync(key) {
|
|
131
|
-
return execInReadTx(this.store, async (tx)=>{
|
|
132
|
-
const val = await tx.getIndex(serializeKey(this.prefix, key));
|
|
133
|
-
return val.length > 0 ? this.encoder.unpack(val[0]) : undefined;
|
|
134
|
-
});
|
|
135
|
-
}
|
|
136
|
-
hasAsync(key) {
|
|
137
|
-
return execInReadTx(this.store, async (tx)=>(await tx.getIndex(serializeKey(this.prefix, key))).length > 0);
|
|
138
|
-
}
|
|
139
|
-
/**
|
|
140
|
-
* Iterates over the map's key-value entries in the key's natural order
|
|
141
|
-
* @param range - The range of keys to iterate over
|
|
142
|
-
*/ async *entriesAsync(range) {
|
|
143
|
-
const reverse = range?.reverse ?? false;
|
|
144
|
-
const startKey = range?.start ? serializeKey(this.prefix, range.start) : minKey(this.prefix);
|
|
145
|
-
const endKey = range?.end ? serializeKey(this.prefix, range.end) : reverse ? maxKey(this.prefix) : undefined;
|
|
146
|
-
let tx = this.store.getCurrentWriteTx();
|
|
147
|
-
const shouldClose = !tx;
|
|
148
|
-
tx ??= this.store.getReadTx();
|
|
149
|
-
try {
|
|
150
|
-
for await (const [key, vals] of tx.iterateIndex(reverse ? endKey : startKey, reverse ? startKey : endKey, reverse, range?.limit)){
|
|
151
|
-
const deserializedKey = deserializeKey(this.prefix, key);
|
|
152
|
-
if (!deserializedKey) {
|
|
153
|
-
break;
|
|
154
|
-
}
|
|
155
|
-
for (const val of vals){
|
|
156
|
-
yield [
|
|
157
|
-
deserializedKey,
|
|
158
|
-
this.encoder.unpack(val)
|
|
159
|
-
];
|
|
160
|
-
}
|
|
161
|
-
}
|
|
162
|
-
} finally{
|
|
163
|
-
if (shouldClose) {
|
|
164
|
-
tx.close();
|
|
165
|
-
}
|
|
166
|
-
}
|
|
167
|
-
}
|
|
168
|
-
/**
|
|
169
|
-
* Iterates over the map's values in the key's natural order
|
|
170
|
-
* @param range - The range of keys to iterate over
|
|
171
|
-
*/ async *valuesAsync(range) {
|
|
172
|
-
for await (const [_, value] of this.entriesAsync(range)){
|
|
173
|
-
yield value;
|
|
174
|
-
}
|
|
175
|
-
}
|
|
176
|
-
/**
|
|
177
|
-
* Iterates over the map's keys in the key's natural order
|
|
178
|
-
* @param range - The range of keys to iterate over
|
|
179
|
-
*/ async *keysAsync(range) {
|
|
180
|
-
for await (const [key, _] of this.entriesAsync(range)){
|
|
181
|
-
yield key;
|
|
182
|
-
}
|
|
183
|
-
}
|
|
184
|
-
deleteValue(key, val) {
|
|
185
|
-
return execInWriteTx(this.store, (tx)=>tx.removeIndex(serializeKey(this.prefix, key), this.encoder.pack(val)));
|
|
186
|
-
}
|
|
187
|
-
async *getValuesAsync(key) {
|
|
188
|
-
const values = await execInReadTx(this.store, (tx)=>tx.getIndex(serializeKey(this.prefix, key)));
|
|
189
|
-
for (const value of values){
|
|
190
|
-
yield this.encoder.unpack(value);
|
|
191
|
-
}
|
|
192
|
-
}
|
|
193
|
-
}
|