@cloudbitmaps/core 0.20.0 → 0.21.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 +85 -0
- package/dist/{chunk-YSC7NJWV.js → chunk-IGLIZBR7.js} +740 -137
- package/dist/chunk-IGLIZBR7.js.map +7 -0
- package/dist/core/absent-operands.d.ts +8 -0
- package/dist/core/audit.d.ts +12 -2
- package/dist/core/bit-route.d.ts +2 -1
- package/dist/core/blob.d.ts +12 -1
- package/dist/core/bulk-load.d.ts +148 -0
- package/dist/core/cas-retry.d.ts +27 -0
- package/dist/core/check.d.ts +22 -0
- package/dist/core/chunk-checks.d.ts +6 -1
- package/dist/core/chunk-window.d.ts +11 -4
- package/dist/core/combine-expr.d.ts +1 -3
- package/dist/core/combine-feed.d.ts +2 -16
- package/dist/core/combine-many.d.ts +12 -9
- package/dist/core/concurrency.d.ts +8 -0
- package/dist/core/consistency.d.ts +69 -17
- package/dist/core/crbm/fingerprint.d.ts +5 -0
- package/dist/core/crbm/format.d.ts +0 -1
- package/dist/core/crbm/plan-reads.d.ts +9 -3
- package/dist/core/crbm/reader.d.ts +52 -6
- package/dist/core/crbm/varint.d.ts +2 -1
- package/dist/core/crbm/writer.d.ts +5 -1
- package/dist/core/crbm-open.d.ts +154 -0
- package/dist/core/crbm-storage-source.d.ts +65 -452
- package/dist/core/crbm-write.d.ts +75 -0
- package/dist/core/crypto.d.ts +6 -1
- package/dist/core/engine.d.ts +222 -33
- package/dist/core/erase-id.d.ts +42 -7
- package/dist/core/erasure.d.ts +4 -3
- package/dist/core/errors.d.ts +8 -2
- package/dist/core/generation-gc.d.ts +129 -15
- package/dist/core/generation-list.d.ts +11 -0
- package/dist/core/id-window.d.ts +46 -0
- package/dist/core/invalidation-scope.d.ts +77 -0
- package/dist/core/known-generations-shape.d.ts +13 -0
- package/dist/core/known-generations.d.ts +147 -0
- package/dist/core/leases.d.ts +4 -3
- package/dist/core/ledger-seed.d.ts +17 -0
- package/dist/core/load.d.ts +17 -38
- package/dist/core/lru.d.ts +2 -15
- package/dist/core/metrics.d.ts +4 -2
- package/dist/core/order.d.ts +2 -0
- package/dist/core/pinned-storage-source.d.ts +4 -4
- package/dist/core/ports.d.ts +89 -16
- package/dist/core/publish.d.ts +207 -0
- package/dist/core/registry-scan.d.ts +0 -2
- package/dist/core/retention-sweep.d.ts +69 -65
- package/dist/core/retention.d.ts +1 -1
- package/dist/core/retry.d.ts +12 -19
- package/dist/core/rollback.d.ts +60 -31
- package/dist/core/summary.d.ts +50 -18
- package/dist/core/token.d.ts +2 -2
- package/dist/core/validate.d.ts +2 -0
- package/dist/driver-kit.d.ts +4 -0
- package/dist/driver-kit.js +80 -7
- package/dist/driver-kit.js.map +3 -3
- package/dist/drivers/_shared/bytes.d.ts +6 -0
- package/dist/drivers/_shared/faults.d.ts +15 -0
- package/dist/drivers/_shared/object-keys.d.ts +18 -0
- package/dist/drivers/_shared/object-registry-keys.d.ts +0 -2
- package/dist/drivers/_shared/object-registry.d.ts +2 -0
- package/dist/drivers/_shared/options.d.ts +19 -0
- package/dist/drivers/_shared/registry.d.ts +13 -10
- package/dist/drivers/localfs/exact-case.d.ts +0 -3
- package/dist/drivers/localfs/fs-util.d.ts +22 -0
- package/dist/drivers/localfs/registry.d.ts +10 -4
- package/dist/drivers/localfs/storage.d.ts +9 -2
- package/dist/drivers/memory.d.ts +7 -4
- package/dist/index.d.ts +1 -1
- package/dist/index.js +3647 -2410
- package/dist/index.js.map +4 -4
- package/package.json +1 -1
- package/dist/chunk-YSC7NJWV.js.map +0 -7
- package/dist/core/kept-generations.d.ts +0 -40
|
@@ -37,7 +37,6 @@ export declare const FOOTER: {
|
|
|
37
37
|
export declare const FOOTER_CRC_COVERAGE: 96;
|
|
38
38
|
/** `flags` bit positions. */
|
|
39
39
|
export declare const FLAG_ENCRYPTED: number;
|
|
40
|
-
export declare const FLAG_INDEX_COMPRESSED: number;
|
|
41
40
|
export declare const FLAG_LITTLE_ENDIAN: number;
|
|
42
41
|
/**
|
|
43
42
|
* The object carries an extension block just before its index (a generation's metadata). Set only when there is
|
|
@@ -34,11 +34,17 @@ export interface ChunkRegion {
|
|
|
34
34
|
}
|
|
35
35
|
/**
|
|
36
36
|
* Plan the reads for `extents`: the needed chunks of one object, ascending by offset (the index lists chunks in key
|
|
37
|
-
* order, which is object order), each at least a byte long, none overlapping another. The reads come
|
|
38
|
-
*
|
|
37
|
+
* order, which is object order), each at least a byte long, none overlapping another. The reads come out ascending
|
|
38
|
+
* and disjoint, each covering one or more of the chunks, every chunk in exactly one read.
|
|
39
|
+
*
|
|
40
|
+
* Lazy: the plan is a walk, so a consumer that takes the first reads pulls only the extents those reads cover (and
|
|
41
|
+
* the one after, which closes the last of them), and a plan over a very wide object costs nothing until it is read.
|
|
42
|
+
* Each extent is checked as the walk reaches it, before the read that would carry it is handed out, so no read ever
|
|
43
|
+
* covers an extent that was not checked; a plan taken to its end has checked them all. The reads are exactly the ones
|
|
44
|
+
* a plan made all at once would hold, in the same order.
|
|
39
45
|
*
|
|
40
46
|
* Throws {@link IntegrityError} for an extent that is not a pair of safe integers, or is outside `region`, or out of
|
|
41
47
|
* order, or overlapping the one before it:
|
|
42
48
|
* the index a plan is made from is untrusted bytes, and a read is never planned outside the chunk region.
|
|
43
49
|
*/
|
|
44
|
-
export declare function planChunkReads(extents:
|
|
50
|
+
export declare function planChunkReads(extents: Iterable<ChunkExtent>, region: ChunkRegion): Generator<PlannedRead, void, undefined>;
|
|
@@ -7,7 +7,7 @@ import type { ChunkRead, GenerationMetadata, ReadChunksOptions } from '../ports.
|
|
|
7
7
|
* `cardinalityMinusOne` stores `cardinality - 1` because a chunk's cardinality runs `[1, 65536]` and 65,536 does
|
|
8
8
|
* not fit a `u16`; an offset is a `f64` because an object past 4 GiB puts a payload beyond a `u32`.
|
|
9
9
|
*/
|
|
10
|
-
|
|
10
|
+
interface ParsedIndex {
|
|
11
11
|
readonly keys: Uint16Array;
|
|
12
12
|
readonly cardinalityMinusOne: Uint16Array;
|
|
13
13
|
readonly lengths: Uint32Array;
|
|
@@ -29,7 +29,12 @@ export declare const RETAINED_BYTES_PER_INDEX_ENTRY = 20;
|
|
|
29
29
|
*/
|
|
30
30
|
export declare function indexCapacity(indexLength: number): number;
|
|
31
31
|
export interface CrbmReaderOptions {
|
|
32
|
-
/**
|
|
32
|
+
/**
|
|
33
|
+
* How many bytes the first tail read asks for, a whole number (default 256 KiB; clamped up to at least the footer
|
|
34
|
+
* size). Any value of at least an object's `tailBytes` opens it in that one read. Where an open keeps a small object's
|
|
35
|
+
* chunks (a `CrbmStorageChunkSource`'s does), it keeps them only when this read covers the whole object, so a value
|
|
36
|
+
* below the default can leave them to reads of their own.
|
|
37
|
+
*/
|
|
33
38
|
readonly tailBytes?: number;
|
|
34
39
|
/** Hard cap on a single chunk payload length (default: the 1 MiB decode cap, plus the 28-byte nonce and tag on an encrypted object). The engine decodes under `maxBitmapBytes`; raise this with it. */
|
|
35
40
|
readonly maxPayloadBytes?: number;
|
|
@@ -49,6 +54,20 @@ export interface CrbmReaderOptions {
|
|
|
49
54
|
*/
|
|
50
55
|
readonly lineage?: unknown;
|
|
51
56
|
}
|
|
57
|
+
/**
|
|
58
|
+
* Refuses a `size` that is not a whole byte count its own tail fits in. The size is the tier's word too: one that
|
|
59
|
+
* is not would turn off every bounds check an open makes against it.
|
|
60
|
+
*/
|
|
61
|
+
export declare function checkSize(tail: Uint8Array, size: number): void;
|
|
62
|
+
/**
|
|
63
|
+
* What the footer of the object behind `blob` says with no key and no index, from one tail read of a footer's worth:
|
|
64
|
+
* whether it is encrypted, and its CRC (the one in {@link CrbmReader.fingerprint}). A footer that fails its own checks
|
|
65
|
+
* throws, as an open would.
|
|
66
|
+
*/
|
|
67
|
+
export declare function readFooter(blob: BlobReader): Promise<{
|
|
68
|
+
readonly encrypted: boolean;
|
|
69
|
+
readonly footerCrc: number;
|
|
70
|
+
}>;
|
|
52
71
|
/**
|
|
53
72
|
* Whether the object behind `blob` says it is encrypted, from one tail read of a footer's worth, with no key and no
|
|
54
73
|
* index; a footer that fails its own checks throws, as an open would. For a caller that must not open an object with
|
|
@@ -61,6 +80,14 @@ export declare function footerSaysEncrypted(blob: BlobReader): Promise<boolean>;
|
|
|
61
80
|
* object and that region is at most `keepChunkBytesUpTo` bytes. Not exported from a package entry.
|
|
62
81
|
*/
|
|
63
82
|
export declare function openCrbmReaderKeeping(blob: BlobReader, options: CrbmReaderOptions, keepChunkBytesUpTo: number | undefined): Promise<CrbmReader>;
|
|
83
|
+
/**
|
|
84
|
+
* How many bytes the first tail read of an open asks for: the caller's `tailBytes` or the default, and a footer's worth
|
|
85
|
+
* at least. Not exported from a package entry: {@link CrbmReader.open} and a caller that sends that read ahead of it
|
|
86
|
+
* ask for the same size.
|
|
87
|
+
*/
|
|
88
|
+
export declare function openTailBytes(options: {
|
|
89
|
+
readonly tailBytes?: number;
|
|
90
|
+
}): number;
|
|
64
91
|
export declare class CrbmReader {
|
|
65
92
|
private readonly blob;
|
|
66
93
|
private readonly objectSize;
|
|
@@ -102,6 +129,11 @@ export declare class CrbmReader {
|
|
|
102
129
|
get fingerprint(): string;
|
|
103
130
|
/** Total object bytes (from the one-GET tail read): the `sizeBytes` a segment's `stat()` reports. */
|
|
104
131
|
get sizeBytes(): number;
|
|
132
|
+
/**
|
|
133
|
+
* The bytes of the object after its chunk payloads: any extension block, the index and the footer. A tail read of
|
|
134
|
+
* this many bytes covers all of them.
|
|
135
|
+
*/
|
|
136
|
+
get tailBytes(): number;
|
|
105
137
|
/**
|
|
106
138
|
* Retained JS heap of this reader's parsed index — the weight the storage reader cache bounds on (a wide
|
|
107
139
|
* segment's parsed index, not its payloads, dominates the reader's footprint): the exact byte length of the
|
|
@@ -134,6 +166,16 @@ export declare class CrbmReader {
|
|
|
134
166
|
count(): number;
|
|
135
167
|
/** The slot holding `chunkKey` (binary search over the ascending keys), or -1 when this generation has none. */
|
|
136
168
|
private slotOf;
|
|
169
|
+
/**
|
|
170
|
+
* {@link slotOf} for a key at or after the one that held slot `at`, which a walk over ascending keys has: the slot
|
|
171
|
+
* itself or the next are tried first, so a read of nearly every chunk costs no search.
|
|
172
|
+
*/
|
|
173
|
+
private slotFrom;
|
|
174
|
+
/**
|
|
175
|
+
* The extents of the chunks `chunkKeys` name that this generation holds, in key order, each once (a key given twice
|
|
176
|
+
* is read once). A walk, so nothing is looked up until the plan pulls it.
|
|
177
|
+
*/
|
|
178
|
+
private neededExtents;
|
|
137
179
|
has(chunkKey: number): boolean;
|
|
138
180
|
/**
|
|
139
181
|
* Range-GET one chunk's payload, verifying its CRC32C before returning. Returns `null` if the chunk is
|
|
@@ -168,10 +210,13 @@ export declare class CrbmReader {
|
|
|
168
210
|
* as {@link getChunk} answers for an absent key. A key given twice is read once and answered at both positions with
|
|
169
211
|
* the same view.
|
|
170
212
|
*
|
|
171
|
-
* The
|
|
172
|
-
*
|
|
173
|
-
*
|
|
174
|
-
* it
|
|
213
|
+
* The key list is planned against this one generation's index ({@link planChunkReads}), as a walk the window pulls
|
|
214
|
+
* from only as it opens a range, so a stream that stops early has planned little: the same ranges, in the same
|
|
215
|
+
* order, as a plan of the whole list would make, and each chunk's extent is checked before the range that carries
|
|
216
|
+
* it is requested. The ranges run through a window of `options.concurrency` reads ({@link MAX_RANGES_IN_FLIGHT} by
|
|
217
|
+
* default) that counts a range until the consumer has taken it, so a stream never holds more than that many ranges,
|
|
218
|
+
* in flight or landed, however many keys it was given or how slowly it is read; with `options.ramp` the window opens
|
|
219
|
+
* 1, 2, 4 … wide. A range is at most 1 MiB
|
|
175
220
|
* unless it is one chunk, which is at most the payload cap, so the bound is that many times the per-chunk cap
|
|
176
221
|
* (1 MiB, and 28 bytes more for an encrypted chunk). Nothing is read until the first item is asked for, and a
|
|
177
222
|
* consumer that stops launches no more: ranges already in flight finish and are dropped, and a failure of one of
|
|
@@ -223,3 +268,4 @@ export type ChunkStream = AsyncGenerator<Omit<ChunkRead, 'version'>> & {
|
|
|
223
268
|
*/
|
|
224
269
|
export declare function parseExtension(sections: Uint8Array, crypto: CrbmCrypto | undefined): GenerationMetadata | undefined;
|
|
225
270
|
export declare function parseIndex(indexBytes: Uint8Array, payloadEnd: number, maxPayloadBytes: number, minPayloadBytes?: number): ParsedIndex;
|
|
271
|
+
export {};
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
/** Append the LEB128 encoding of a u32 `value` to `out`. */
|
|
2
2
|
export declare function writeVarint(out: number[], value: number): void;
|
|
3
|
-
|
|
3
|
+
interface VarintRead {
|
|
4
4
|
readonly value: number;
|
|
5
5
|
/** Offset just past the bytes consumed. */
|
|
6
6
|
readonly next: number;
|
|
@@ -11,3 +11,4 @@ export interface VarintRead {
|
|
|
11
11
|
* cleanly, never loop or overflow.
|
|
12
12
|
*/
|
|
13
13
|
export declare function readVarint(bytes: Uint8Array, offset: number): VarintRead;
|
|
14
|
+
export {};
|
|
@@ -35,6 +35,8 @@ export declare class CrbmWriter {
|
|
|
35
35
|
private readonly metadata;
|
|
36
36
|
/** Bytes written so far, the footer included once {@link finish} has run. */
|
|
37
37
|
private written;
|
|
38
|
+
/** Where the chunk payloads end: the extension block's start when there is metadata, else the index's. */
|
|
39
|
+
private payloadEnd;
|
|
38
40
|
private footerCrc32c;
|
|
39
41
|
constructor(sink: BlobSink, options: CrbmWriterOptions);
|
|
40
42
|
/**
|
|
@@ -50,11 +52,13 @@ export declare class CrbmWriter {
|
|
|
50
52
|
/**
|
|
51
53
|
* The finished object's size and its footer's CRC: what names it, as a reader's fingerprint does. A writer that
|
|
52
54
|
* has to tell its own object from another stored later under the same key compares these with the object's
|
|
53
|
-
* footer.
|
|
55
|
+
* footer. `tailBytes` is the bytes after the chunk payloads (any extension block, the index and the footer), which
|
|
56
|
+
* is what {@link CrbmReader.tailBytes} reports for the object. Throws before {@link finish}.
|
|
54
57
|
*/
|
|
55
58
|
get identity(): {
|
|
56
59
|
readonly size: number;
|
|
57
60
|
readonly footerCrc: number;
|
|
61
|
+
readonly tailBytes: number;
|
|
58
62
|
};
|
|
59
63
|
private ensurePreamble;
|
|
60
64
|
/**
|
|
@@ -0,0 +1,154 @@
|
|
|
1
|
+
import type { BlobReader } from './blob.js';
|
|
2
|
+
import type { CrbmCrypto } from './crypto.js';
|
|
3
|
+
import type { GenerationMetadata, GenKey, IStorageDriver, TailRead } from './ports.js';
|
|
4
|
+
import { CrbmReader } from './crbm/reader.js';
|
|
5
|
+
import type { CrbmReaderOptions } from './crbm/reader.js';
|
|
6
|
+
import type { SummaryDescription } from './summary.js';
|
|
7
|
+
/**
|
|
8
|
+
* Adapt one `(driver, key)` pair to the codec's `BlobReader` seam. With `noteTail`, each tail read the reader makes is
|
|
9
|
+
* shown to it with the bytes, `size` and `version` the driver answered, after the copy below when one is made.
|
|
10
|
+
*
|
|
11
|
+
* A tail's bytes reach the reader as a plain `Uint8Array`: the reader keeps a small object's chunk region by slicing
|
|
12
|
+
* the tail, and a subclass's `slice` need not copy. A Node `Buffer`'s is a view, so a driver that answered with one
|
|
13
|
+
* would leave the reader holding the driver's memory, all of it, as the cache weighs only the region. Such an answer
|
|
14
|
+
* is copied here, once ({@link ownedTail}); a plain `Uint8Array` of this realm, which every shipped driver returns, is
|
|
15
|
+
* handed through as it is.
|
|
16
|
+
*/
|
|
17
|
+
export declare function storageBlobReader(driver: IStorageDriver, key: GenKey, noteTail?: (tail: TailRead) => void): BlobReader;
|
|
18
|
+
/**
|
|
19
|
+
* `tail` with its bytes in a plain `Uint8Array` of this realm. Any other `Uint8Array`, a subclass (a Node `Buffer`) or
|
|
20
|
+
* one made in another realm (a `vm` context), is copied once, and the copy is built from the answer's fields by name,
|
|
21
|
+
* so a `size` or `version` the driver serves from a getter on its own class carries over. The brand is read, not
|
|
22
|
+
* `instanceof`, which is false for another realm's arrays. A plain `Uint8Array` of this realm is handed through as it is.
|
|
23
|
+
*/
|
|
24
|
+
export declare function ownedTail(tail: TailRead): TailRead;
|
|
25
|
+
/**
|
|
26
|
+
* The object under `key`, when one read of its footer matches `fingerprint` ({@link CrbmReader.fingerprint}), with the
|
|
27
|
+
* version the driver reported on that read (`undefined` from a driver that reports none). `null` when it is another
|
|
28
|
+
* object, when it is gone, and when the read fails in any way. A fingerprint names the object's bytes, not the writer:
|
|
29
|
+
* an object another writer stored under the number with the same bytes matches too. A caller that deletes what this
|
|
30
|
+
* matches passes the version as the delete's `ifVersion`, so a number taken again between the read and the delete keeps
|
|
31
|
+
* the object put under it since.
|
|
32
|
+
*/
|
|
33
|
+
export declare function provenObject(storage: IStorageDriver, key: GenKey, fingerprint: string): Promise<{
|
|
34
|
+
readonly version: string | undefined;
|
|
35
|
+
} | null>;
|
|
36
|
+
/**
|
|
37
|
+
* Whether the object under `key` is still the one `fingerprint` names ({@link CrbmReader.fingerprint}), from one read
|
|
38
|
+
* of its footer. Unlike {@link provenObject}, a fault is not an answer: `NotFoundError` when the key holds no object,
|
|
39
|
+
* and any other failure of the read, thrown as it is.
|
|
40
|
+
*/
|
|
41
|
+
export declare function sameObjectUnder(storage: IStorageDriver, key: GenKey, fingerprint: string): Promise<boolean>;
|
|
42
|
+
/**
|
|
43
|
+
* Whether the object under `key` says it is encrypted, from one read of its footer, with no key. `noteVersion` is shown
|
|
44
|
+
* the version the driver reported on that read, when it reported one: a caller that deletes the object for what its
|
|
45
|
+
* footer says passes it as the delete's `ifVersion`.
|
|
46
|
+
*/
|
|
47
|
+
export declare function objectIsEncrypted(storage: IStorageDriver, key: GenKey, noteVersion?: (version: string) => void): Promise<boolean>;
|
|
48
|
+
/**
|
|
49
|
+
* What one tail read of a rollback target says about it with no key: whether the footer says it is encrypted and its
|
|
50
|
+
* CRC, and the remembered tail an open from it ({@link openRollbackTargetFrom}) is answered from.
|
|
51
|
+
*/
|
|
52
|
+
interface RollbackTargetFooter {
|
|
53
|
+
readonly encrypted: boolean;
|
|
54
|
+
readonly footerCrc: number;
|
|
55
|
+
readonly blob: BlobReader;
|
|
56
|
+
}
|
|
57
|
+
/**
|
|
58
|
+
* The footer step of a rollback: one tail read of the object under `key`, which is remembered for the open that may
|
|
59
|
+
* follow. A footer that fails its own checks is an {@link IntegrityError}; a missing object is {@link NotFoundError}.
|
|
60
|
+
*/
|
|
61
|
+
export declare function readRollbackTargetFooter(storage: IStorageDriver, key: GenKey): Promise<RollbackTargetFooter>;
|
|
62
|
+
/**
|
|
63
|
+
* The reader {@link RollbackTargetFooter}'s object opens as, from its remembered tail, when the object and the key
|
|
64
|
+
* agree (an encrypted object opened with `crypto`, a cleartext one with none); `undefined` when they disagree, which
|
|
65
|
+
* the caller refuses as a target the row cannot use. An object that is another generation's, and an index or metadata
|
|
66
|
+
* that do not open, are an {@link IntegrityError}.
|
|
67
|
+
*/
|
|
68
|
+
export declare function openRollbackTargetFrom(footer: RollbackTargetFooter, key: GenKey, crypto: CrbmCrypto | undefined): Promise<CrbmReader | undefined>;
|
|
69
|
+
/**
|
|
70
|
+
* The footer CRC of the object under `key` ({@link CrbmReader.fingerprint} carries it), from one read of a footer's
|
|
71
|
+
* worth, so it reads an encrypted object's CRC as it does a cleartext one's, with no key. {@link NotFoundError} when
|
|
72
|
+
* the key holds no object; a footer that fails its own checks is an {@link IntegrityError}.
|
|
73
|
+
*/
|
|
74
|
+
export declare function footerCrcUnder(storage: IStorageDriver, key: GenKey): Promise<number>;
|
|
75
|
+
/**
|
|
76
|
+
* Whether the object under `key` is the one `fingerprint` names, from one read of its footer: false when it is another
|
|
77
|
+
* object or gone. Unlike {@link provenObject}, a read that cannot tell throws, for a caller that must not take "could
|
|
78
|
+
* not look" for "not this object".
|
|
79
|
+
*/
|
|
80
|
+
export declare function provesOwnObject(storage: IStorageDriver, key: GenKey, fingerprint: string): Promise<boolean>;
|
|
81
|
+
/**
|
|
82
|
+
* Open a {@link CrbmReader} on one generation over the storage driver's range/tail reads (decrypting if `crypto`).
|
|
83
|
+
* The reader the write paths use to re-read what they wrote, and the erasure rewrite uses to stream the old
|
|
84
|
+
* generation; the engine's read path goes through {@link CrbmStorageChunkSource} instead, which caches these. With
|
|
85
|
+
* `named`, the fingerprint the row's summary records, the object must be that one: another is {@link NotFoundError}.
|
|
86
|
+
* The version of the object it opened, from the tail read the open made, is what {@link objectVersionOf} answers.
|
|
87
|
+
*/
|
|
88
|
+
export declare function openGenerationReader(storage: IStorageDriver, key: GenKey, crypto: CrbmCrypto | undefined, options?: Omit<CrbmReaderOptions, 'crypto'>, named?: string): Promise<CrbmReader>;
|
|
89
|
+
/**
|
|
90
|
+
* {@link openGenerationReader}, with `noteVersion` shown the version {@link objectVersionOf} would answer as soon as the
|
|
91
|
+
* tail read that carries it returns, before the open goes on: a caller whose open then fails, on an object sealed under
|
|
92
|
+
* another key, say, still knows which object it met, and can condition a delete of it on that read.
|
|
93
|
+
*/
|
|
94
|
+
export declare function openGenerationReaderNoting(storage: IStorageDriver, key: GenKey, crypto: CrbmCrypto | undefined, noteVersion: (version: string) => void): Promise<CrbmReader>;
|
|
95
|
+
/**
|
|
96
|
+
* The version of the object `reader` was opened on, as the driver reported it on the tail read the open made, for a
|
|
97
|
+
* delete conditioned on that object ({@link StorageDeleteOptions.ifVersion}); `undefined` for a reader
|
|
98
|
+
* {@link openGenerationReader} did not open, or a driver that reports none. Held beside the reader rather than on it, so
|
|
99
|
+
* nothing is added to the reader's public surface, and no read the engine makes pays for it.
|
|
100
|
+
*/
|
|
101
|
+
export declare function objectVersionOf(reader: CrbmReader): string | undefined;
|
|
102
|
+
/**
|
|
103
|
+
* {@link openGenerationReader}, of the object `summary.fingerprint` names: `undefined` when the object under the key is
|
|
104
|
+
* another one, found from its footer before its index is opened, so an object sealed under another key is told apart as
|
|
105
|
+
* well. The tail read is sized from the summary's `tailBytes` ({@link sizedTailBytes}), so a wide generation's index
|
|
106
|
+
* comes in that read.
|
|
107
|
+
*/
|
|
108
|
+
export declare function openNamedGeneration(storage: IStorageDriver, key: GenKey, crypto: CrbmCrypto | undefined, summary: Pick<SummaryDescription, 'fingerprint' | 'tailBytes'>, noteTail?: (tail: TailRead) => void): Promise<CrbmReader | undefined>;
|
|
109
|
+
/**
|
|
110
|
+
* Open a reader on `key`, refusing an object whose footer names another generation. Every writer stamps the key's
|
|
111
|
+
* number, and the chunk cache, the load guard and the erasure rewrite all trust it, so an object that disagrees
|
|
112
|
+
* was written under another key or altered. Every open, the live read's, a pin's and the write paths', comes here.
|
|
113
|
+
* With `named`, the object must also be the one that fingerprint names: another one is {@link NotFoundError}, a move.
|
|
114
|
+
* With `early`, the tail read {@link startTailRead} began, the open takes that read as its own instead of making one.
|
|
115
|
+
*/
|
|
116
|
+
export declare function openChecked(storage: IStorageDriver, key: GenKey, options: CrbmReaderOptions, keepChunkBytesUpTo?: number, named?: string, noteTail?: (tail: TailRead) => void, early?: Promise<TailRead>): Promise<CrbmReader>;
|
|
117
|
+
/**
|
|
118
|
+
* The size of the tail read an open makes when its row's summary says how many bytes of the object's end the open
|
|
119
|
+
* needs (`tailBytes`: any extension block, the index and the footer), so that one read reaches the index of a wide
|
|
120
|
+
* generation and no range read follows it. With no summary it is the source's own size ({@link openTailBytes}).
|
|
121
|
+
*
|
|
122
|
+
* The number came from a registry the library may not have written, so it only ever sizes a read: never below the
|
|
123
|
+
* source's own tail, at most the object less its preamble (the size its fingerprint names), and at most the source's
|
|
124
|
+
* `maxIndexBytes` (or the default) plus an extension block, its trailer and the footer, the most any open reads past
|
|
125
|
+
* its own tail. A hint that is not a whole number of bytes above zero is ignored, and so is a result that is not one. A
|
|
126
|
+
* wrong hint is a longer read or one more range read, never a different answer: the reader checks every byte it takes.
|
|
127
|
+
*/
|
|
128
|
+
export declare function sizedTailBytes(summary: Pick<SummaryDescription, 'fingerprint' | 'tailBytes'> | undefined, options: {
|
|
129
|
+
readonly tailBytes?: number;
|
|
130
|
+
readonly maxIndexBytes?: number;
|
|
131
|
+
}): number;
|
|
132
|
+
/**
|
|
133
|
+
* Send the tail read an open of `key` makes, now, and hand back its answer for {@link openChecked}'s `early`: the open
|
|
134
|
+
* then waits on the one request instead of sending its own, so work the open waits on first, such as a keystore call,
|
|
135
|
+
* runs beside the request and not before it. Nothing is parsed here: the bytes are untrusted until the open reads them.
|
|
136
|
+
* The returned promise already has a handler attached, so a caller that never reaches the open (its key failed) leaves
|
|
137
|
+
* no unhandled rejection; the open that does reach it still sees the rejection.
|
|
138
|
+
*/
|
|
139
|
+
export declare function startTailRead(storage: IStorageDriver, key: GenKey, options: CrbmReaderOptions): Promise<TailRead>;
|
|
140
|
+
/**
|
|
141
|
+
* Re-open a freshly written generation and assert it round-trips exactly what was streamed into it: the same
|
|
142
|
+
* per-chunk key set *and* the same total cardinality (on top of the codec's own per-chunk CRC + footer checks), and the
|
|
143
|
+
* metadata it was given. `expected` is the streaming writer's tally (the stream is consumed, so it can't be
|
|
144
|
+
* re-iterated) — the key-set comparison catches a dropped/extra chunk that a cardinality-only check could miss when
|
|
145
|
+
* two errors cancel out. The count and the metadata are what the generation's row summary is about to claim, so the
|
|
146
|
+
* summary is held to the object it describes before it is published.
|
|
147
|
+
* Throws {@link IntegrityError}: the object is on disk but must not be published.
|
|
148
|
+
*/
|
|
149
|
+
export declare function verifyGeneration(storage: IStorageDriver, key: GenKey, expected: {
|
|
150
|
+
readonly chunkKeys: readonly number[];
|
|
151
|
+
readonly cardinality: number;
|
|
152
|
+
readonly metadata?: GenerationMetadata | undefined;
|
|
153
|
+
}, crypto: CrbmCrypto | undefined): Promise<void>;
|
|
154
|
+
export {};
|