flatsql 3.11.0 → 3.12.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 +61 -795
- package/bin/flatsql.mjs +76 -0
- package/cpp/README.md +18 -0
- package/cpp/include/flatsql/flatsql.h +162 -0
- package/cpp/include/flatsql/flatsql_io.h +159 -0
- package/docs/API-3.12.md +114 -0
- package/package.json +28 -123
- package/wasm/flatsql.wasm +0 -0
- package/wasm/index.d.ts +61 -548
- package/wasm/index.js +280 -1281
- package/wasm/integrity.json +6 -26
- package/wasm/runtime/LICENSE.sdk.txt +190 -0
- package/wasm/runtime/NOTICE.txt +2 -0
- package/wasm/runtime/browser-guest.mjs +1 -0
- package/wasm/runtime/browser-host.mjs +1 -0
- package/wasm/runtime/node-guest.mjs +2 -0
- package/wasm/runtime/node-host.mjs +5 -0
- package/wasm/runtime/opfsIoWorker.mjs +1 -0
- package/wasm/runtime/wasiThreadBrowserWorker.mjs +1 -0
- package/dist/artifacts/index.d.ts +0 -3
- package/dist/artifacts/index.d.ts.map +0 -1
- package/dist/artifacts/index.js +0 -3
- package/dist/artifacts/index.js.map +0 -1
- package/dist/artifacts/transport.d.ts +0 -5
- package/dist/artifacts/transport.d.ts.map +0 -1
- package/dist/artifacts/transport.js +0 -45
- package/dist/artifacts/transport.js.map +0 -1
- package/dist/artifacts/types.d.ts +0 -34
- package/dist/artifacts/types.d.ts.map +0 -1
- package/dist/artifacts/types.js +0 -2
- package/dist/artifacts/types.js.map +0 -1
- package/dist/btree/btree.d.ts +0 -34
- package/dist/btree/btree.d.ts.map +0 -1
- package/dist/btree/btree.js +0 -234
- package/dist/btree/btree.js.map +0 -1
- package/dist/btree/index.d.ts +0 -3
- package/dist/btree/index.d.ts.map +0 -1
- package/dist/btree/index.js +0 -3
- package/dist/btree/index.js.map +0 -1
- package/dist/btree/types.d.ts +0 -36
- package/dist/btree/types.d.ts.map +0 -1
- package/dist/btree/types.js +0 -55
- package/dist/btree/types.js.map +0 -1
- package/dist/cluster/index.d.ts +0 -11
- package/dist/cluster/index.d.ts.map +0 -1
- package/dist/cluster/index.js +0 -59
- package/dist/cluster/index.js.map +0 -1
- package/dist/response/artifact.d.ts +0 -4
- package/dist/response/artifact.d.ts.map +0 -1
- package/dist/response/artifact.js +0 -102
- package/dist/response/artifact.js.map +0 -1
- package/dist/response/cache-key.d.ts +0 -6
- package/dist/response/cache-key.d.ts.map +0 -1
- package/dist/response/cache-key.js +0 -114
- package/dist/response/cache-key.js.map +0 -1
- package/dist/response/index.d.ts +0 -5
- package/dist/response/index.d.ts.map +0 -1
- package/dist/response/index.js +0 -5
- package/dist/response/index.js.map +0 -1
- package/dist/response/memory-cache.d.ts +0 -17
- package/dist/response/memory-cache.d.ts.map +0 -1
- package/dist/response/memory-cache.js +0 -76
- package/dist/response/memory-cache.js.map +0 -1
- package/dist/response/types.d.ts +0 -57
- package/dist/response/types.d.ts.map +0 -1
- package/dist/response/types.js +0 -2
- package/dist/response/types.js.map +0 -1
- package/dist/schema/index.d.ts +0 -3
- package/dist/schema/index.d.ts.map +0 -1
- package/dist/schema/index.js +0 -3
- package/dist/schema/index.js.map +0 -1
- package/dist/schema/parser.d.ts +0 -25
- package/dist/schema/parser.d.ts.map +0 -1
- package/dist/schema/parser.js +0 -474
- package/dist/schema/parser.js.map +0 -1
- package/dist/schema/types.d.ts +0 -33
- package/dist/schema/types.d.ts.map +0 -1
- package/dist/schema/types.js +0 -29
- package/dist/schema/types.js.map +0 -1
- package/dist/standalone/index.d.ts +0 -3
- package/dist/standalone/index.d.ts.map +0 -1
- package/dist/standalone/index.js +0 -3
- package/dist/standalone/index.js.map +0 -1
- package/dist/standalone/process-client.d.ts +0 -85
- package/dist/standalone/process-client.d.ts.map +0 -1
- package/dist/standalone/process-client.js +0 -537
- package/dist/standalone/process-client.js.map +0 -1
- package/dist/standalone/wasmedge-runner.d.ts +0 -19
- package/dist/standalone/wasmedge-runner.d.ts.map +0 -1
- package/dist/standalone/wasmedge-runner.js +0 -108
- package/dist/standalone/wasmedge-runner.js.map +0 -1
- package/dist/storage/index.d.ts +0 -3
- package/dist/storage/index.d.ts.map +0 -1
- package/dist/storage/index.js +0 -3
- package/dist/storage/index.js.map +0 -1
- package/dist/storage/stacked-flatbuffers.d.ts +0 -38
- package/dist/storage/stacked-flatbuffers.d.ts.map +0 -1
- package/dist/storage/stacked-flatbuffers.js +0 -253
- package/dist/storage/stacked-flatbuffers.js.map +0 -1
- package/dist/storage/types.d.ts +0 -23
- package/dist/storage/types.d.ts.map +0 -1
- package/dist/storage/types.js +0 -27
- package/dist/storage/types.js.map +0 -1
- package/dist/stress/aggregate.d.ts +0 -3
- package/dist/stress/aggregate.d.ts.map +0 -1
- package/dist/stress/aggregate.js +0 -61
- package/dist/stress/aggregate.js.map +0 -1
- package/dist/stress/docker-compose.d.ts +0 -17
- package/dist/stress/docker-compose.d.ts.map +0 -1
- package/dist/stress/docker-compose.js +0 -156
- package/dist/stress/docker-compose.js.map +0 -1
- package/dist/stress/index.d.ts +0 -10
- package/dist/stress/index.d.ts.map +0 -1
- package/dist/stress/index.js +0 -10
- package/dist/stress/index.js.map +0 -1
- package/dist/stress/metrics.d.ts +0 -3
- package/dist/stress/metrics.d.ts.map +0 -1
- package/dist/stress/metrics.js +0 -83
- package/dist/stress/metrics.js.map +0 -1
- package/dist/stress/native-publish-event-workload.d.ts +0 -3
- package/dist/stress/native-publish-event-workload.d.ts.map +0 -1
- package/dist/stress/native-publish-event-workload.js +0 -465
- package/dist/stress/native-publish-event-workload.js.map +0 -1
- package/dist/stress/production-gate.d.ts +0 -4
- package/dist/stress/production-gate.d.ts.map +0 -1
- package/dist/stress/production-gate.js +0 -12
- package/dist/stress/production-gate.js.map +0 -1
- package/dist/stress/report.d.ts +0 -3
- package/dist/stress/report.d.ts.map +0 -1
- package/dist/stress/report.js +0 -174
- package/dist/stress/report.js.map +0 -1
- package/dist/stress/sds-discovery.d.ts +0 -4
- package/dist/stress/sds-discovery.d.ts.map +0 -1
- package/dist/stress/sds-discovery.js +0 -40
- package/dist/stress/sds-discovery.js.map +0 -1
- package/dist/stress/smoke-runner.d.ts +0 -3
- package/dist/stress/smoke-runner.d.ts.map +0 -1
- package/dist/stress/smoke-runner.js +0 -64
- package/dist/stress/smoke-runner.js.map +0 -1
- package/dist/stress/types.d.ts +0 -219
- package/dist/stress/types.d.ts.map +0 -1
- package/dist/stress/types.js +0 -2
- package/dist/stress/types.js.map +0 -1
- package/dist/stress/workload.d.ts +0 -6
- package/dist/stress/workload.d.ts.map +0 -1
- package/dist/stress/workload.js +0 -144
- package/dist/stress/workload.js.map +0 -1
- package/docs/PARTITION-STORE-WASM.md +0 -338
- package/docs/PARTITION-STORE.md +0 -2380
- package/docs/agents/response-artifacts.md +0 -65
- package/docs/response-artifacts.md +0 -86
- package/scripts/stress-docker.sh +0 -279
- package/sdm/flatsql-spatial.wasm +0 -0
- package/sdm/index.d.ts +0 -88
- package/sdm/index.js +0 -253
- package/sdm/manifest.json +0 -402
- package/stress/docker/Dockerfile +0 -11
- package/stress/docker/docker-compose.yml +0 -51
- package/stress/sds/aggregate.mjs +0 -97
- package/stress/sds/run.mjs +0 -105
- package/stress/sds/write-compose.mjs +0 -96
- package/wasm/flatsql-client.js +0 -280
- package/wasm/flatsql-io.d.ts +0 -97
- package/wasm/flatsql-io.js +0 -621
- package/wasm/flatsql-p4-threads.wasm +0 -0
- package/wasm/flatsql-ps-threads.wasm +0 -0
- package/wasm/flatsql-wasi-noeh.wasm +0 -0
- package/wasm/flatsql-wasi.wasm +0 -0
- package/wasm/flatsql.js +0 -2
- package/wasm/flatsql.worker.js +0 -209
- package/wasm/native/flatsql_wasmedge_runner.cpp +0 -858
- package/wasm/ps-node-fault.d.mts +0 -23
- package/wasm/ps-node-fault.mjs +0 -381
- package/wasm/ps-node-guest.mjs +0 -173
- package/wasm/ps-node-host.d.mts +0 -95
- package/wasm/ps-node-host.mjs +0 -476
- package/wasm/ps-node-imports.mjs +0 -847
- package/wasm/ps.d.ts +0 -21
- package/wasm/ps.js +0 -75
- package/wasm/wasi.d.ts +0 -11
- package/wasm/wasi.js +0 -51
package/wasm/flatsql-io.d.ts
DELETED
|
@@ -1,97 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Types for the FlatSQL host I/O contract (cpp/include/flatsql/flatsql_io.h).
|
|
3
|
-
*
|
|
4
|
-
* These live in the flatsql package on purpose: the seven-call shape is an ABI,
|
|
5
|
-
* and an ABI that each consumer re-declares locally is an ABI that drifts.
|
|
6
|
-
*/
|
|
7
|
-
|
|
8
|
-
export declare const FLATSQL_IO_READ: number;
|
|
9
|
-
export declare const FLATSQL_IO_WRITE: number;
|
|
10
|
-
export declare const FLATSQL_IO_CREATE: number;
|
|
11
|
-
export declare const FLATSQL_IO_EXCL: number;
|
|
12
|
-
export declare const FLATSQL_IO_TRUNC: number;
|
|
13
|
-
export declare const FLATSQL_IO_DELETE_ON_CLOSE: number;
|
|
14
|
-
/** Namespace op: does the path exist? Returns a status, allocates no handle. */
|
|
15
|
-
export declare const FLATSQL_IO_PROBE: number;
|
|
16
|
-
/** Namespace op: remove the path. Returns a status, allocates no handle. */
|
|
17
|
-
export declare const FLATSQL_IO_UNLINK: number;
|
|
18
|
-
|
|
19
|
-
export declare const FLATSQL_IO_ERR_GENERIC: number;
|
|
20
|
-
export declare const FLATSQL_IO_ERR_NOENT: number;
|
|
21
|
-
export declare const FLATSQL_IO_ERR_ACCESS: number;
|
|
22
|
-
export declare const FLATSQL_IO_ERR_IO: number;
|
|
23
|
-
export declare const FLATSQL_IO_ERR_NOSPACE: number;
|
|
24
|
-
export declare const FLATSQL_IO_ERR_BADHANDLE: number;
|
|
25
|
-
|
|
26
|
-
export declare const DEFAULT_CHUNK_BYTES: number;
|
|
27
|
-
|
|
28
|
-
/**
|
|
29
|
-
* A backend answers the seven imports SYNCHRONOUSLY, because a wasm import is
|
|
30
|
-
* synchronous. Offsets and sizes are plain numbers (f64 on the wire — never
|
|
31
|
-
* i64, which emscripten legalizes differently in the two lanes).
|
|
32
|
-
*/
|
|
33
|
-
export interface FlatSqlIoBackend {
|
|
34
|
-
/** Returns a handle, or a negative status. PROBE/UNLINK return a status. */
|
|
35
|
-
open(path: string, flags: number): number;
|
|
36
|
-
/** Bytes read; may be short at EOF. Never moves an implicit cursor. */
|
|
37
|
-
read(handle: number, dst: Uint8Array, offset: number): number;
|
|
38
|
-
/** Bytes written. Writing past EOF extends; the gap reads as zeroes. */
|
|
39
|
-
write(handle: number, src: Uint8Array, offset: number): number;
|
|
40
|
-
truncate(handle: number, size: number): number;
|
|
41
|
-
/**
|
|
42
|
-
* Durability barrier. On a synchronous backend bytes are durable at return;
|
|
43
|
-
* on an async store they become durable when the caller awaits flush().
|
|
44
|
-
*/
|
|
45
|
-
sync(handle: number): number;
|
|
46
|
-
size(handle: number): number;
|
|
47
|
-
close(handle: number): number;
|
|
48
|
-
|
|
49
|
-
/** Pull a file into the synchronous cache BEFORE the engine opens it. */
|
|
50
|
-
hydrate(path: string): Promise<unknown>;
|
|
51
|
-
/** Persist dirty state. No-op on synchronous backends. */
|
|
52
|
-
flush(): Promise<void>;
|
|
53
|
-
/** Remove a file and every key backing it. */
|
|
54
|
-
drop(path: string): Promise<void>;
|
|
55
|
-
|
|
56
|
-
readonly kind?: string;
|
|
57
|
-
}
|
|
58
|
-
|
|
59
|
-
export interface FlatSqlIoChunkOptions {
|
|
60
|
-
/** Page-group size in bytes. */
|
|
61
|
-
chunkBytes?: number;
|
|
62
|
-
/** Key namespace inside the store. */
|
|
63
|
-
prefix?: string;
|
|
64
|
-
/** Paths already known to exist. */
|
|
65
|
-
knownPaths?: string[];
|
|
66
|
-
}
|
|
67
|
-
|
|
68
|
-
/** Flat key -> bytes store: the shape every browser persistence store has. */
|
|
69
|
-
export interface FlatSqlKeyValueStore {
|
|
70
|
-
readBytes(key: string): Promise<Uint8Array | null>;
|
|
71
|
-
writeBytes(key: string, bytes: Uint8Array): Promise<void>;
|
|
72
|
-
deleteKey(key: string): Promise<void>;
|
|
73
|
-
}
|
|
74
|
-
|
|
75
|
-
export declare function createMemoryBackend(
|
|
76
|
-
options?: { chunkBytes?: number },
|
|
77
|
-
): FlatSqlIoBackend;
|
|
78
|
-
|
|
79
|
-
export declare function createNodeFsBackend(
|
|
80
|
-
fs: unknown,
|
|
81
|
-
options?: { root?: string },
|
|
82
|
-
): FlatSqlIoBackend;
|
|
83
|
-
|
|
84
|
-
/**
|
|
85
|
-
* Give a flat key -> bytes store real pread/pwrite semantics by addressing
|
|
86
|
-
* fixed-size page groups. A flush costs O(dirty chunks), not O(file).
|
|
87
|
-
*/
|
|
88
|
-
export declare function createChunkedStoreBackend(
|
|
89
|
-
store: FlatSqlKeyValueStore,
|
|
90
|
-
options?: FlatSqlIoChunkOptions,
|
|
91
|
-
): FlatSqlIoBackend & { knownPaths(): string[]; chunkBytes: number };
|
|
92
|
-
|
|
93
|
-
/** Build the `env` import object for a directly-instantiated (WASI) module. */
|
|
94
|
-
export declare function createFlatSqlIoImports(
|
|
95
|
-
backend: FlatSqlIoBackend,
|
|
96
|
-
memoryRef: () => WebAssembly.Memory,
|
|
97
|
-
): Record<string, (...args: number[]) => number>;
|
package/wasm/flatsql-io.js
DELETED
|
@@ -1,621 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* FlatSQL host I/O backends — the JavaScript half of the seven-import contract
|
|
3
|
-
* (cpp/include/flatsql/flatsql_io.h).
|
|
4
|
-
*
|
|
5
|
-
* ONE backend interface, used by BOTH JavaScript loaders:
|
|
6
|
-
* - the emscripten browser bundle, via cpp/js/flatsql_io_library.js
|
|
7
|
-
* - the standalone/WASI shim, via wasm/standalone.js
|
|
8
|
-
* ...and matched call-for-call by the Go host and by cpp/src/flatsql_io_native.cpp.
|
|
9
|
-
*
|
|
10
|
-
* A backend is SYNCHRONOUS, because a wasm import is. Its methods are:
|
|
11
|
-
*
|
|
12
|
-
* open(path: string, flags: number): number // handle, or negative status
|
|
13
|
-
* read(handle, dst: Uint8Array, offset: number): number
|
|
14
|
-
* write(handle, src: Uint8Array, offset: number): number
|
|
15
|
-
* truncate(handle, size: number): number
|
|
16
|
-
* sync(handle): number
|
|
17
|
-
* size(handle): number
|
|
18
|
-
* close(handle): number
|
|
19
|
-
*
|
|
20
|
-
* The pointer->subarray translation is done by the loader; a backend never sees
|
|
21
|
-
* wasm memory. That is the entire reason two very different hosts can satisfy
|
|
22
|
-
* the same seven calls without one line of runtime detection inside the module.
|
|
23
|
-
*
|
|
24
|
-
* ASYNC STORES (the one honest asymmetry, and it is in the shim where it
|
|
25
|
-
* belongs): IndexedDB and an HTTP desktop store cannot answer synchronously.
|
|
26
|
-
* createChunkedStoreBackend() therefore keeps a synchronous page cache and
|
|
27
|
-
* makes durability an explicit, awaited JavaScript step:
|
|
28
|
-
*
|
|
29
|
-
* await backend.hydrate(path); // BEFORE opening the database
|
|
30
|
-
* ... engine runs entirely synchronously ...
|
|
31
|
-
* await backend.flush(); // AFTER flatsql_flush_index()
|
|
32
|
-
*
|
|
33
|
-
* Results are identical to the native lane in every case; only the moment at
|
|
34
|
-
* which bytes become durable differs, and it is observable and awaited rather
|
|
35
|
-
* than assumed. Nothing about the wasm-side contract changes.
|
|
36
|
-
*/
|
|
37
|
-
|
|
38
|
-
export const FLATSQL_IO_READ = 0x0001;
|
|
39
|
-
export const FLATSQL_IO_WRITE = 0x0002;
|
|
40
|
-
export const FLATSQL_IO_CREATE = 0x0004;
|
|
41
|
-
export const FLATSQL_IO_EXCL = 0x0008;
|
|
42
|
-
export const FLATSQL_IO_TRUNC = 0x0010;
|
|
43
|
-
export const FLATSQL_IO_DELETE_ON_CLOSE = 0x0020;
|
|
44
|
-
export const FLATSQL_IO_PROBE = 0x0040;
|
|
45
|
-
export const FLATSQL_IO_UNLINK = 0x0080;
|
|
46
|
-
|
|
47
|
-
export const FLATSQL_IO_ERR_GENERIC = -1;
|
|
48
|
-
export const FLATSQL_IO_ERR_NOENT = -2;
|
|
49
|
-
export const FLATSQL_IO_ERR_ACCESS = -3;
|
|
50
|
-
export const FLATSQL_IO_ERR_IO = -4;
|
|
51
|
-
export const FLATSQL_IO_ERR_NOSPACE = -5;
|
|
52
|
-
export const FLATSQL_IO_ERR_BADHANDLE = -6;
|
|
53
|
-
|
|
54
|
-
/** Default page-group size. One IndexedDB value per group. */
|
|
55
|
-
export const DEFAULT_CHUNK_BYTES = 64 * 1024;
|
|
56
|
-
|
|
57
|
-
/**
|
|
58
|
-
* A file living in RAM as a set of fixed-size chunks. Shared by every backend
|
|
59
|
-
* so that chunk boundaries, growth and zero-fill behave identically no matter
|
|
60
|
-
* what the bytes are eventually persisted into.
|
|
61
|
-
*/
|
|
62
|
-
class ChunkedFile {
|
|
63
|
-
constructor(path, chunkBytes) {
|
|
64
|
-
this.path = path;
|
|
65
|
-
this.chunkBytes = chunkBytes;
|
|
66
|
-
this.chunks = new Map(); // index -> Uint8Array(chunkBytes)
|
|
67
|
-
this.dirty = new Set();
|
|
68
|
-
this.length = 0;
|
|
69
|
-
this.metaDirty = false;
|
|
70
|
-
}
|
|
71
|
-
|
|
72
|
-
chunk(index, create) {
|
|
73
|
-
let buf = this.chunks.get(index);
|
|
74
|
-
if (!buf && create) {
|
|
75
|
-
buf = new Uint8Array(this.chunkBytes);
|
|
76
|
-
this.chunks.set(index, buf);
|
|
77
|
-
}
|
|
78
|
-
return buf || null;
|
|
79
|
-
}
|
|
80
|
-
|
|
81
|
-
read(dst, offset) {
|
|
82
|
-
// A read past EOF is a SHORT read, never an error — the C side zero-fills
|
|
83
|
-
// the remainder and reports SQLITE_IOERR_SHORT_READ, exactly as POSIX
|
|
84
|
-
// pread does. Getting this wrong silently corrupts pager reads.
|
|
85
|
-
const available = Math.max(0, this.length - offset);
|
|
86
|
-
const want = Math.min(dst.length, available);
|
|
87
|
-
let done = 0;
|
|
88
|
-
while (done < want) {
|
|
89
|
-
const at = offset + done;
|
|
90
|
-
const index = Math.floor(at / this.chunkBytes);
|
|
91
|
-
const within = at % this.chunkBytes;
|
|
92
|
-
const n = Math.min(this.chunkBytes - within, want - done);
|
|
93
|
-
const buf = this.chunk(index, false);
|
|
94
|
-
if (buf) {
|
|
95
|
-
dst.set(buf.subarray(within, within + n), done);
|
|
96
|
-
} else {
|
|
97
|
-
dst.fill(0, done, done + n); // sparse hole
|
|
98
|
-
}
|
|
99
|
-
done += n;
|
|
100
|
-
}
|
|
101
|
-
return want;
|
|
102
|
-
}
|
|
103
|
-
|
|
104
|
-
write(src, offset) {
|
|
105
|
-
let done = 0;
|
|
106
|
-
while (done < src.length) {
|
|
107
|
-
const at = offset + done;
|
|
108
|
-
const index = Math.floor(at / this.chunkBytes);
|
|
109
|
-
const within = at % this.chunkBytes;
|
|
110
|
-
const n = Math.min(this.chunkBytes - within, src.length - done);
|
|
111
|
-
const buf = this.chunk(index, true);
|
|
112
|
-
buf.set(src.subarray(done, done + n), within);
|
|
113
|
-
this.dirty.add(index);
|
|
114
|
-
done += n;
|
|
115
|
-
}
|
|
116
|
-
if (offset + src.length > this.length) {
|
|
117
|
-
this.length = offset + src.length;
|
|
118
|
-
this.metaDirty = true;
|
|
119
|
-
}
|
|
120
|
-
return src.length;
|
|
121
|
-
}
|
|
122
|
-
|
|
123
|
-
truncate(size) {
|
|
124
|
-
if (size < this.length) {
|
|
125
|
-
const lastIndex = Math.floor(size / this.chunkBytes);
|
|
126
|
-
for (const index of Array.from(this.chunks.keys())) {
|
|
127
|
-
if (index > lastIndex) {
|
|
128
|
-
this.chunks.delete(index);
|
|
129
|
-
this.dirty.add(index); // removal must be persisted too
|
|
130
|
-
}
|
|
131
|
-
}
|
|
132
|
-
const tail = this.chunk(lastIndex, false);
|
|
133
|
-
if (tail) {
|
|
134
|
-
tail.fill(0, size % this.chunkBytes);
|
|
135
|
-
this.dirty.add(lastIndex);
|
|
136
|
-
}
|
|
137
|
-
}
|
|
138
|
-
this.length = size;
|
|
139
|
-
this.metaDirty = true;
|
|
140
|
-
return 0;
|
|
141
|
-
}
|
|
142
|
-
}
|
|
143
|
-
|
|
144
|
-
/** Handle table shared by every backend: small, dense, reused after close. */
|
|
145
|
-
class HandleTable {
|
|
146
|
-
constructor() {
|
|
147
|
-
this.slots = [];
|
|
148
|
-
}
|
|
149
|
-
|
|
150
|
-
add(entry) {
|
|
151
|
-
for (let i = 0; i < this.slots.length; i++) {
|
|
152
|
-
if (!this.slots[i]) {
|
|
153
|
-
this.slots[i] = entry;
|
|
154
|
-
return i;
|
|
155
|
-
}
|
|
156
|
-
}
|
|
157
|
-
this.slots.push(entry);
|
|
158
|
-
return this.slots.length - 1;
|
|
159
|
-
}
|
|
160
|
-
|
|
161
|
-
get(handle) {
|
|
162
|
-
return this.slots[handle] || null;
|
|
163
|
-
}
|
|
164
|
-
|
|
165
|
-
remove(handle) {
|
|
166
|
-
const entry = this.slots[handle];
|
|
167
|
-
this.slots[handle] = null;
|
|
168
|
-
return entry;
|
|
169
|
-
}
|
|
170
|
-
}
|
|
171
|
-
|
|
172
|
-
/**
|
|
173
|
-
* Pure in-memory backend. Durable for exactly as long as the process lives —
|
|
174
|
-
* which is the DOCUMENTED behaviour asserted by the Memory-store lane of the
|
|
175
|
-
* test matrix, not a skipped case.
|
|
176
|
-
*/
|
|
177
|
-
export function createMemoryBackend(options = {}) {
|
|
178
|
-
const chunkBytes = options.chunkBytes || DEFAULT_CHUNK_BYTES;
|
|
179
|
-
const files = new Map();
|
|
180
|
-
const handles = new HandleTable();
|
|
181
|
-
|
|
182
|
-
return {
|
|
183
|
-
kind: 'memory',
|
|
184
|
-
files,
|
|
185
|
-
|
|
186
|
-
open(path, flags) {
|
|
187
|
-
if (flags & FLATSQL_IO_PROBE) {
|
|
188
|
-
return files.has(path) ? 0 : FLATSQL_IO_ERR_NOENT;
|
|
189
|
-
}
|
|
190
|
-
if (flags & FLATSQL_IO_UNLINK) {
|
|
191
|
-
return files.delete(path) ? 0 : FLATSQL_IO_ERR_NOENT;
|
|
192
|
-
}
|
|
193
|
-
let file = files.get(path);
|
|
194
|
-
if (!file) {
|
|
195
|
-
if (!(flags & FLATSQL_IO_CREATE)) return FLATSQL_IO_ERR_NOENT;
|
|
196
|
-
file = new ChunkedFile(path, chunkBytes);
|
|
197
|
-
files.set(path, file);
|
|
198
|
-
} else if (flags & FLATSQL_IO_EXCL) {
|
|
199
|
-
return FLATSQL_IO_ERR_ACCESS;
|
|
200
|
-
}
|
|
201
|
-
if (flags & FLATSQL_IO_TRUNC) file.truncate(0);
|
|
202
|
-
return handles.add({ file, deleteOnClose: !!(flags & FLATSQL_IO_DELETE_ON_CLOSE) });
|
|
203
|
-
},
|
|
204
|
-
|
|
205
|
-
read(handle, dst, offset) {
|
|
206
|
-
const entry = handles.get(handle);
|
|
207
|
-
if (!entry) return FLATSQL_IO_ERR_BADHANDLE;
|
|
208
|
-
return entry.file.read(dst, offset);
|
|
209
|
-
},
|
|
210
|
-
|
|
211
|
-
write(handle, src, offset) {
|
|
212
|
-
const entry = handles.get(handle);
|
|
213
|
-
if (!entry) return FLATSQL_IO_ERR_BADHANDLE;
|
|
214
|
-
return entry.file.write(src, offset);
|
|
215
|
-
},
|
|
216
|
-
|
|
217
|
-
truncate(handle, size) {
|
|
218
|
-
const entry = handles.get(handle);
|
|
219
|
-
if (!entry) return FLATSQL_IO_ERR_BADHANDLE;
|
|
220
|
-
return entry.file.truncate(size);
|
|
221
|
-
},
|
|
222
|
-
|
|
223
|
-
sync() {
|
|
224
|
-
return 0; // RAM is already as durable as it will ever be
|
|
225
|
-
},
|
|
226
|
-
|
|
227
|
-
size(handle) {
|
|
228
|
-
const entry = handles.get(handle);
|
|
229
|
-
if (!entry) return FLATSQL_IO_ERR_BADHANDLE;
|
|
230
|
-
return entry.file.length;
|
|
231
|
-
},
|
|
232
|
-
|
|
233
|
-
close(handle) {
|
|
234
|
-
const entry = handles.remove(handle);
|
|
235
|
-
if (!entry) return FLATSQL_IO_ERR_BADHANDLE;
|
|
236
|
-
if (entry.deleteOnClose) files.delete(entry.file.path);
|
|
237
|
-
return 0;
|
|
238
|
-
},
|
|
239
|
-
|
|
240
|
-
async hydrate() {},
|
|
241
|
-
async flush() {},
|
|
242
|
-
async drop(path) {
|
|
243
|
-
files.delete(path);
|
|
244
|
-
},
|
|
245
|
-
};
|
|
246
|
-
}
|
|
247
|
-
|
|
248
|
-
/**
|
|
249
|
-
* Node/desktop backend over real files. Fully synchronous, so sync() really is
|
|
250
|
-
* durable at return — this lane has no asymmetry at all.
|
|
251
|
-
*
|
|
252
|
-
* `fs` is injected rather than imported so the module stays loadable in a
|
|
253
|
-
* browser bundle that will never call this.
|
|
254
|
-
*/
|
|
255
|
-
export function createNodeFsBackend(fs, options = {}) {
|
|
256
|
-
const root = options.root || '';
|
|
257
|
-
const handles = new HandleTable();
|
|
258
|
-
const resolve = (p) => (root ? `${root}/${p.replace(/^\/+/, '')}` : p);
|
|
259
|
-
|
|
260
|
-
const statusFor = (err) => {
|
|
261
|
-
if (!err || !err.code) return FLATSQL_IO_ERR_GENERIC;
|
|
262
|
-
if (err.code === 'ENOENT') return FLATSQL_IO_ERR_NOENT;
|
|
263
|
-
if (err.code === 'EACCES' || err.code === 'EPERM') return FLATSQL_IO_ERR_ACCESS;
|
|
264
|
-
if (err.code === 'ENOSPC') return FLATSQL_IO_ERR_NOSPACE;
|
|
265
|
-
return FLATSQL_IO_ERR_IO;
|
|
266
|
-
};
|
|
267
|
-
|
|
268
|
-
return {
|
|
269
|
-
kind: 'node-fs',
|
|
270
|
-
|
|
271
|
-
open(path, flags) {
|
|
272
|
-
const full = resolve(path);
|
|
273
|
-
try {
|
|
274
|
-
if (flags & FLATSQL_IO_PROBE) {
|
|
275
|
-
fs.statSync(full);
|
|
276
|
-
return 0;
|
|
277
|
-
}
|
|
278
|
-
if (flags & FLATSQL_IO_UNLINK) {
|
|
279
|
-
fs.unlinkSync(full);
|
|
280
|
-
return 0;
|
|
281
|
-
}
|
|
282
|
-
let mode = 'r';
|
|
283
|
-
if (flags & FLATSQL_IO_WRITE) {
|
|
284
|
-
mode = flags & FLATSQL_IO_EXCL ? 'wx+' : flags & FLATSQL_IO_CREATE ? 'a+' : 'r+';
|
|
285
|
-
}
|
|
286
|
-
const fd = fs.openSync(full, mode);
|
|
287
|
-
return handles.add({
|
|
288
|
-
fd,
|
|
289
|
-
path: full,
|
|
290
|
-
deleteOnClose: !!(flags & FLATSQL_IO_DELETE_ON_CLOSE),
|
|
291
|
-
});
|
|
292
|
-
} catch (err) {
|
|
293
|
-
return statusFor(err);
|
|
294
|
-
}
|
|
295
|
-
},
|
|
296
|
-
|
|
297
|
-
read(handle, dst, offset) {
|
|
298
|
-
const entry = handles.get(handle);
|
|
299
|
-
if (!entry) return FLATSQL_IO_ERR_BADHANDLE;
|
|
300
|
-
try {
|
|
301
|
-
return fs.readSync(entry.fd, dst, 0, dst.length, offset);
|
|
302
|
-
} catch (err) {
|
|
303
|
-
return statusFor(err);
|
|
304
|
-
}
|
|
305
|
-
},
|
|
306
|
-
|
|
307
|
-
write(handle, src, offset) {
|
|
308
|
-
const entry = handles.get(handle);
|
|
309
|
-
if (!entry) return FLATSQL_IO_ERR_BADHANDLE;
|
|
310
|
-
try {
|
|
311
|
-
return fs.writeSync(entry.fd, src, 0, src.length, offset);
|
|
312
|
-
} catch (err) {
|
|
313
|
-
return statusFor(err);
|
|
314
|
-
}
|
|
315
|
-
},
|
|
316
|
-
|
|
317
|
-
truncate(handle, size) {
|
|
318
|
-
const entry = handles.get(handle);
|
|
319
|
-
if (!entry) return FLATSQL_IO_ERR_BADHANDLE;
|
|
320
|
-
try {
|
|
321
|
-
fs.ftruncateSync(entry.fd, size);
|
|
322
|
-
return 0;
|
|
323
|
-
} catch (err) {
|
|
324
|
-
return statusFor(err);
|
|
325
|
-
}
|
|
326
|
-
},
|
|
327
|
-
|
|
328
|
-
sync(handle) {
|
|
329
|
-
const entry = handles.get(handle);
|
|
330
|
-
if (!entry) return FLATSQL_IO_ERR_BADHANDLE;
|
|
331
|
-
try {
|
|
332
|
-
fs.fsyncSync(entry.fd);
|
|
333
|
-
return 0;
|
|
334
|
-
} catch (err) {
|
|
335
|
-
return statusFor(err);
|
|
336
|
-
}
|
|
337
|
-
},
|
|
338
|
-
|
|
339
|
-
size(handle) {
|
|
340
|
-
const entry = handles.get(handle);
|
|
341
|
-
if (!entry) return FLATSQL_IO_ERR_BADHANDLE;
|
|
342
|
-
try {
|
|
343
|
-
return fs.fstatSync(entry.fd).size;
|
|
344
|
-
} catch (err) {
|
|
345
|
-
return statusFor(err);
|
|
346
|
-
}
|
|
347
|
-
},
|
|
348
|
-
|
|
349
|
-
close(handle) {
|
|
350
|
-
const entry = handles.remove(handle);
|
|
351
|
-
if (!entry) return FLATSQL_IO_ERR_BADHANDLE;
|
|
352
|
-
try {
|
|
353
|
-
fs.closeSync(entry.fd);
|
|
354
|
-
if (entry.deleteOnClose) {
|
|
355
|
-
try {
|
|
356
|
-
fs.unlinkSync(entry.path);
|
|
357
|
-
} catch (_) {
|
|
358
|
-
/* already gone */
|
|
359
|
-
}
|
|
360
|
-
}
|
|
361
|
-
return 0;
|
|
362
|
-
} catch (err) {
|
|
363
|
-
return statusFor(err);
|
|
364
|
-
}
|
|
365
|
-
},
|
|
366
|
-
|
|
367
|
-
async hydrate() {},
|
|
368
|
-
async flush() {},
|
|
369
|
-
async drop(path) {
|
|
370
|
-
try {
|
|
371
|
-
fs.unlinkSync(resolve(path));
|
|
372
|
-
} catch (_) {
|
|
373
|
-
/* already gone */
|
|
374
|
-
}
|
|
375
|
-
},
|
|
376
|
-
};
|
|
377
|
-
}
|
|
378
|
-
|
|
379
|
-
/**
|
|
380
|
-
* Backend over ANY flat key->bytes store — the shape every sdn-js persistence
|
|
381
|
-
* store already has (readBytes/writeBytes/deleteKey). This is what gives a
|
|
382
|
-
* store with no seek and no partial write real pread/pwrite semantics:
|
|
383
|
-
*
|
|
384
|
-
* <prefix><path>#<pageGroup> fixed-size chunk of file bytes
|
|
385
|
-
* <prefix><path>#meta JSON { length }
|
|
386
|
-
*
|
|
387
|
-
* Because addressing is by chunk index, a flush costs O(dirty chunks) rather
|
|
388
|
-
* than O(file), and the browser lane reads and writes the same byte ranges the
|
|
389
|
-
* POSIX lane does. It is not "the browser rewrites everything" — the two lanes
|
|
390
|
-
* are the same algorithm over a different transport.
|
|
391
|
-
*
|
|
392
|
-
* `store` must provide:
|
|
393
|
-
* readBytes(key): Promise<Uint8Array|null>
|
|
394
|
-
* writeBytes(key, bytes): Promise<void>
|
|
395
|
-
* deleteKey(key): Promise<void>
|
|
396
|
-
*/
|
|
397
|
-
export function createChunkedStoreBackend(store, options = {}) {
|
|
398
|
-
const chunkBytes = options.chunkBytes || DEFAULT_CHUNK_BYTES;
|
|
399
|
-
const prefix = options.prefix || 'flatsql-io/';
|
|
400
|
-
const files = new Map();
|
|
401
|
-
const handles = new HandleTable();
|
|
402
|
-
const known = new Set(options.knownPaths || []);
|
|
403
|
-
|
|
404
|
-
const metaKey = (path) => `${prefix}${path}#meta`;
|
|
405
|
-
const chunkKey = (path, index) => `${prefix}${path}#${index}`;
|
|
406
|
-
|
|
407
|
-
/**
|
|
408
|
-
* Pull a file's chunks into the synchronous cache. MUST be awaited before
|
|
409
|
-
* the engine opens the database: after that point every call is synchronous
|
|
410
|
-
* because a wasm import cannot await.
|
|
411
|
-
*/
|
|
412
|
-
async function hydrate(path) {
|
|
413
|
-
if (files.has(path)) return files.get(path);
|
|
414
|
-
const file = new ChunkedFile(path, chunkBytes);
|
|
415
|
-
let meta = null;
|
|
416
|
-
const raw = await store.readBytes(metaKey(path));
|
|
417
|
-
if (raw) {
|
|
418
|
-
try {
|
|
419
|
-
meta = JSON.parse(new TextDecoder().decode(raw));
|
|
420
|
-
} catch (_) {
|
|
421
|
-
meta = null;
|
|
422
|
-
}
|
|
423
|
-
}
|
|
424
|
-
if (meta && Number.isFinite(meta.length)) {
|
|
425
|
-
file.length = meta.length;
|
|
426
|
-
if (meta.chunkBytes && meta.chunkBytes !== chunkBytes) {
|
|
427
|
-
// A different page-group size means the persisted keys do not line up
|
|
428
|
-
// with the ones we would read. Treat it as absent: derived state is
|
|
429
|
-
// always rebuildable, so this costs a re-derivation and never a wrong
|
|
430
|
-
// answer.
|
|
431
|
-
file.length = 0;
|
|
432
|
-
} else {
|
|
433
|
-
const count = Math.ceil(file.length / chunkBytes);
|
|
434
|
-
for (let i = 0; i < count; i++) {
|
|
435
|
-
const bytes = await store.readBytes(chunkKey(path, i));
|
|
436
|
-
if (bytes) {
|
|
437
|
-
const buf = new Uint8Array(chunkBytes);
|
|
438
|
-
buf.set(bytes.subarray(0, Math.min(bytes.length, chunkBytes)));
|
|
439
|
-
file.chunks.set(i, buf);
|
|
440
|
-
}
|
|
441
|
-
}
|
|
442
|
-
}
|
|
443
|
-
known.add(path);
|
|
444
|
-
}
|
|
445
|
-
files.set(path, file);
|
|
446
|
-
return file;
|
|
447
|
-
}
|
|
448
|
-
|
|
449
|
-
/** Persist every dirty chunk plus the length. Await this after a flush. */
|
|
450
|
-
async function flush() {
|
|
451
|
-
for (const [path, file] of files) {
|
|
452
|
-
if (!file.dirty.size && !file.metaDirty) continue;
|
|
453
|
-
for (const index of file.dirty) {
|
|
454
|
-
const buf = file.chunks.get(index);
|
|
455
|
-
if (buf) {
|
|
456
|
-
const start = index * chunkBytes;
|
|
457
|
-
const end = Math.min(chunkBytes, Math.max(0, file.length - start));
|
|
458
|
-
await store.writeBytes(chunkKey(path, index), buf.subarray(0, end));
|
|
459
|
-
} else {
|
|
460
|
-
await store.deleteKey(chunkKey(path, index));
|
|
461
|
-
}
|
|
462
|
-
}
|
|
463
|
-
file.dirty.clear();
|
|
464
|
-
if (file.metaDirty || file.length >= 0) {
|
|
465
|
-
await store.writeBytes(
|
|
466
|
-
metaKey(path),
|
|
467
|
-
new TextEncoder().encode(JSON.stringify({ length: file.length, chunkBytes })),
|
|
468
|
-
);
|
|
469
|
-
file.metaDirty = false;
|
|
470
|
-
}
|
|
471
|
-
known.add(path);
|
|
472
|
-
}
|
|
473
|
-
}
|
|
474
|
-
|
|
475
|
-
async function drop(path) {
|
|
476
|
-
const file = files.get(path);
|
|
477
|
-
const count = file
|
|
478
|
-
? Math.max(Math.ceil(file.length / chunkBytes), ...[...file.chunks.keys()].map((i) => i + 1), 0)
|
|
479
|
-
: 0;
|
|
480
|
-
for (let i = 0; i < count; i++) await store.deleteKey(chunkKey(path, i));
|
|
481
|
-
await store.deleteKey(metaKey(path));
|
|
482
|
-
files.delete(path);
|
|
483
|
-
known.delete(path);
|
|
484
|
-
}
|
|
485
|
-
|
|
486
|
-
return {
|
|
487
|
-
kind: 'chunked-store',
|
|
488
|
-
chunkBytes,
|
|
489
|
-
hydrate,
|
|
490
|
-
flush,
|
|
491
|
-
drop,
|
|
492
|
-
/** Paths this backend believes exist — used to hydrate before an open. */
|
|
493
|
-
knownPaths: () => Array.from(known),
|
|
494
|
-
|
|
495
|
-
open(path, flags) {
|
|
496
|
-
if (flags & FLATSQL_IO_PROBE) {
|
|
497
|
-
const file = files.get(path);
|
|
498
|
-
if (file) return file.length > 0 || file.chunks.size > 0 ? 0 : FLATSQL_IO_ERR_NOENT;
|
|
499
|
-
return known.has(path) ? 0 : FLATSQL_IO_ERR_NOENT;
|
|
500
|
-
}
|
|
501
|
-
if (flags & FLATSQL_IO_UNLINK) {
|
|
502
|
-
const file = files.get(path);
|
|
503
|
-
if (file) file.truncate(0);
|
|
504
|
-
known.delete(path);
|
|
505
|
-
return 0;
|
|
506
|
-
}
|
|
507
|
-
let file = files.get(path);
|
|
508
|
-
if (!file) {
|
|
509
|
-
// Not hydrated. Creating is fine (it is genuinely new); opening an
|
|
510
|
-
// existing file that was never hydrated is a caller error we refuse
|
|
511
|
-
// rather than answer with an empty file — an empty answer here is
|
|
512
|
-
// indistinguishable from data loss.
|
|
513
|
-
if (!(flags & FLATSQL_IO_CREATE)) return FLATSQL_IO_ERR_NOENT;
|
|
514
|
-
file = new ChunkedFile(path, chunkBytes);
|
|
515
|
-
file.metaDirty = true;
|
|
516
|
-
files.set(path, file);
|
|
517
|
-
} else if (flags & FLATSQL_IO_EXCL && file.length > 0) {
|
|
518
|
-
return FLATSQL_IO_ERR_ACCESS;
|
|
519
|
-
}
|
|
520
|
-
if (flags & FLATSQL_IO_TRUNC) file.truncate(0);
|
|
521
|
-
return handles.add({
|
|
522
|
-
file,
|
|
523
|
-
deleteOnClose: !!(flags & FLATSQL_IO_DELETE_ON_CLOSE),
|
|
524
|
-
});
|
|
525
|
-
},
|
|
526
|
-
|
|
527
|
-
read(handle, dst, offset) {
|
|
528
|
-
const entry = handles.get(handle);
|
|
529
|
-
if (!entry) return FLATSQL_IO_ERR_BADHANDLE;
|
|
530
|
-
return entry.file.read(dst, offset);
|
|
531
|
-
},
|
|
532
|
-
|
|
533
|
-
write(handle, src, offset) {
|
|
534
|
-
const entry = handles.get(handle);
|
|
535
|
-
if (!entry) return FLATSQL_IO_ERR_BADHANDLE;
|
|
536
|
-
return entry.file.write(src, offset);
|
|
537
|
-
},
|
|
538
|
-
|
|
539
|
-
truncate(handle, size) {
|
|
540
|
-
const entry = handles.get(handle);
|
|
541
|
-
if (!entry) return FLATSQL_IO_ERR_BADHANDLE;
|
|
542
|
-
return entry.file.truncate(size);
|
|
543
|
-
},
|
|
544
|
-
|
|
545
|
-
/**
|
|
546
|
-
* A durability BARRIER, not a durability guarantee — the underlying store
|
|
547
|
-
* is asynchronous and a wasm import cannot await. Bytes become durable when
|
|
548
|
-
* the caller awaits flush(). Stated plainly because the alternative is a
|
|
549
|
-
* shim that claims fsync semantics it cannot deliver, which is precisely
|
|
550
|
-
* the class of lie this whole task exists to remove.
|
|
551
|
-
*/
|
|
552
|
-
sync(handle) {
|
|
553
|
-
const entry = handles.get(handle);
|
|
554
|
-
if (!entry) return FLATSQL_IO_ERR_BADHANDLE;
|
|
555
|
-
return 0;
|
|
556
|
-
},
|
|
557
|
-
|
|
558
|
-
size(handle) {
|
|
559
|
-
const entry = handles.get(handle);
|
|
560
|
-
if (!entry) return FLATSQL_IO_ERR_BADHANDLE;
|
|
561
|
-
return entry.file.length;
|
|
562
|
-
},
|
|
563
|
-
|
|
564
|
-
close(handle) {
|
|
565
|
-
const entry = handles.remove(handle);
|
|
566
|
-
if (!entry) return FLATSQL_IO_ERR_BADHANDLE;
|
|
567
|
-
if (entry.deleteOnClose) {
|
|
568
|
-
entry.file.truncate(0);
|
|
569
|
-
known.delete(entry.file.path);
|
|
570
|
-
}
|
|
571
|
-
return 0;
|
|
572
|
-
},
|
|
573
|
-
};
|
|
574
|
-
}
|
|
575
|
-
|
|
576
|
-
/**
|
|
577
|
-
* Build the `env` import object for a directly-instantiated (WASI) module.
|
|
578
|
-
* The pointer->subarray translation here is the mirror image of the one in
|
|
579
|
-
* cpp/js/flatsql_io_library.js; keeping them in one file each, both feeding the
|
|
580
|
-
* same backend, is what stops the lanes drifting apart.
|
|
581
|
-
*/
|
|
582
|
-
export function createFlatSqlIoImports(backend, memoryRef) {
|
|
583
|
-
const heap = () => new Uint8Array(memoryRef().buffer);
|
|
584
|
-
const guard = (fn) => {
|
|
585
|
-
try {
|
|
586
|
-
return fn();
|
|
587
|
-
} catch (_) {
|
|
588
|
-
return FLATSQL_IO_ERR_GENERIC;
|
|
589
|
-
}
|
|
590
|
-
};
|
|
591
|
-
|
|
592
|
-
return {
|
|
593
|
-
flatsql_io_open(pathPtr, pathLen, flags) {
|
|
594
|
-
return guard(() => {
|
|
595
|
-
// Copy out of guest memory before decoding: TextDecoder rejects views
|
|
596
|
-
// of a SharedArrayBuffer (a wasi-threads memory), and a shared view
|
|
597
|
-
// could change under the decoder.
|
|
598
|
-
const bytes = heap().slice(pathPtr, pathPtr + pathLen);
|
|
599
|
-
return backend.open(new TextDecoder().decode(bytes), flags) | 0;
|
|
600
|
-
});
|
|
601
|
-
},
|
|
602
|
-
flatsql_io_read(handle, dstPtr, len, offset) {
|
|
603
|
-
return guard(() => backend.read(handle, heap().subarray(dstPtr, dstPtr + len), offset) | 0);
|
|
604
|
-
},
|
|
605
|
-
flatsql_io_write(handle, srcPtr, len, offset) {
|
|
606
|
-
return guard(() => backend.write(handle, heap().subarray(srcPtr, srcPtr + len), offset) | 0);
|
|
607
|
-
},
|
|
608
|
-
flatsql_io_truncate(handle, size) {
|
|
609
|
-
return guard(() => backend.truncate(handle, size) | 0);
|
|
610
|
-
},
|
|
611
|
-
flatsql_io_sync(handle) {
|
|
612
|
-
return guard(() => backend.sync(handle) | 0);
|
|
613
|
-
},
|
|
614
|
-
flatsql_io_size(handle) {
|
|
615
|
-
return guard(() => backend.size(handle));
|
|
616
|
-
},
|
|
617
|
-
flatsql_io_close(handle) {
|
|
618
|
-
return guard(() => backend.close(handle) | 0);
|
|
619
|
-
},
|
|
620
|
-
};
|
|
621
|
-
}
|