UNPKG

@pgxsinkit/pgwasm

Version:
296 lines • 10.2 kB
export type InodeId = bigint; export type ExtentId = bigint; export type MetadataFile = "a" | "b"; export declare function otherMetadataFile(file: MetadataFile): MetadataFile; interface BaseInode { id: InodeId; mode: number; atimeMs: bigint; mtimeMs: bigint; ctimeMs: bigint; } export interface DirectoryInode extends BaseInode { kind: "directory"; children: Map<string, InodeId>; } export interface FileInode extends BaseInode { kind: "file"; size: bigint; extents: ExtentId[]; } /** * A symbolic link. It owns no extents and no children — the whole entry IS its absolute `target`, * which path resolution restarts the walk at. See {@link validateSymlinkTarget} for why relative * targets are refused. */ export interface SymlinkInode extends BaseInode { kind: "symlink"; target: string; } export type Inode = DirectoryInode | FileInode | SymlinkInode; export interface OrphanRecord { inodeId: InodeId; mode: number; atimeMs: bigint; mtimeMs: bigint; ctimeMs: bigint; size: bigint; extents: ExtentId[]; } export declare function makeOrphanRecord(inode: FileInode): OrphanRecord; export declare class IndexedExtentSet { #private; get size(): number; has(extentId: ExtentId): boolean; add(extentId: ExtentId): void; delete(extentId: ExtentId): boolean; values(): readonly ExtentId[]; peekLast(count: number): ExtentId[]; clone(): IndexedExtentSet; } export interface AllocatorState { totalExtents: bigint; ownedBy: Map<ExtentId, InodeId>; available: IndexedExtentSet; quarantine: Map<ExtentId, bigint | null>; } export interface VfsState { generation: bigint; nextInodeId: bigint; rootInodeId: bigint; extentSize: number; activeMetadataFile: MetadataFile; retainedGenerations: Record<MetadataFile, bigint | null>; basePayloadBytes: number; inodes: Map<InodeId, Inode>; parentByInode: Map<InodeId, { parentId: InodeId; name: string; }>; allocator: AllocatorState; } export interface CreateDirectoryChoice { parentId: InodeId; name: string; inodeId: InodeId; mode: number; atimeMs: bigint; mtimeMs: bigint; ctimeMs: bigint; } export interface ExtentRun { start: ExtentId; count: number; } export type TxnRecord = { kind: "createDirectories"; entries: readonly CreateDirectoryChoice[]; } | { kind: "createFile"; parentId: InodeId; name: string; inodeId: InodeId; mode: number; atimeMs: bigint; mtimeMs: bigint; ctimeMs: bigint; size: bigint; extents: readonly ExtentRun[]; } | { kind: "removeFile"; parentId: InodeId; name: string; parentMtimeMs: bigint; parentCtimeMs: bigint; } | { kind: "changeMode"; inodeId: InodeId; mode: number; ctimeMs: bigint; } | { kind: "changeTimes"; inodeId: InodeId; atimeMs: bigint; mtimeMs: bigint; ctimeMs: bigint; } | { kind: "resizeFile"; operation: "truncate" | "write"; inodeId: InodeId; size: bigint; allocated: readonly ExtentRun[]; mtimeMs: bigint; ctimeMs: bigint; } | { kind: "removeDirectory"; parentId: InodeId; name: string; parentMtimeMs: bigint; parentCtimeMs: bigint; } | { kind: "rename"; sourceParentId: InodeId; sourceName: string; destinationParentId: InodeId; destinationName: string; timestampMs: bigint; } | { kind: "createSymlink"; parentId: InodeId; name: string; inodeId: InodeId; mode: number; atimeMs: bigint; mtimeMs: bigint; ctimeMs: bigint; target: string; } | { kind: "reserveQuarantine"; extents: readonly ExtentRun[]; }; export interface TxnPlan<RecordType extends TxnRecord = TxnRecord> { record: RecordType; } export interface PreflightLimits { maxFramePayloadBytes: number; maxBasePayloadBytes: number; } /** The mode a symbolic link carries: `S_IFLNK | 0777`, the only mode POSIX gives a link. */ export declare const SYMLINK_MODE = 41471; export declare function estimateMetadataBasePayloadBytes(state: VfsState): number; export declare function estimateTxnPayloadBytes(record: TxnRecord): number; export declare function preflightTxn(state: VfsState, record: TxnRecord, limits?: PreflightLimits): number; declare const PREPARED_TXN_PROJECTION: unique symbol; export interface PreparedTxnProjection { readonly projectedBasePayloadBytes: number; readonly state: VfsState; readonly record: TxnRecord; readonly [PREPARED_TXN_PROJECTION]: true; } /** @internal Bind one projected size to the exact live state and record it preflighted. */ export declare function prepareTxnProjection(state: VfsState, record: TxnRecord): PreparedTxnProjection; export declare function createInitialState(extentSize: number): VfsState; export declare function toExtentRuns(extents: readonly ExtentId[]): ExtentRun[]; export declare function expandExtentRuns(runs: readonly ExtentRun[], maximum: number): ExtentId[]; export declare function getInodeAtPath(state: VfsState, path: string): Inode; /** * Resolve every symbolic link on `path` and report the link-free absolute path it names. * * `follow` governs the FINAL component only — the POSIX `stat`/`lstat` split. Every INTERMEDIATE * link is always followed, because a path can only continue through the thing a link points at. * * A component that does not exist, or one whose parent turned out not to be a directory, stops the * walk and the remainder is carried through verbatim: resolution answers "which path does this * name", not "does it exist". The operation that follows reports `ENOENT`/`ENOTDIR` itself, or * creates the tail — which is exactly what an `open(O_CREAT)` through a symlinked directory needs. * * Targets are absolute, so a hop restarts the walk at the root. `MAX_SYMLINK_HOPS` hops is `ELOOP`, * and each expansion is re-validated by `parsePath`, so a chain that outgrows the store's depth or * byte limits is rejected here rather than in a planner. */ export declare function resolveLinks(state: VfsState, path: string, follow: boolean): string; export declare function planMkdir(state: VfsState, path: string, options: { recursive?: boolean; mode?: number; nowMs: bigint; }): TxnPlan<Extract<TxnRecord, { kind: "createDirectories"; }>>; export declare function planCreateFile(state: VfsState, path: string, options: { mode?: number; nowMs: bigint; size?: bigint; }): TxnPlan<Extract<TxnRecord, { kind: "createFile"; }>>; /** A symbolic link. Nothing about the TARGET is consulted — the link entry is the whole record. */ export declare function planSymlink(state: VfsState, path: string, target: string, options: { mode?: number; nowMs: bigint; }): TxnPlan<Extract<TxnRecord, { kind: "createSymlink"; }>>; /** Removes a FILE or a SYMBOLIC LINK. A link is unlinked as itself; its target is never touched. */ export declare function planUnlink(state: VfsState, path: string, nowMs: bigint): TxnPlan<Extract<TxnRecord, { kind: "removeFile"; }>>; export declare function planChmod(state: VfsState, path: string, mode: number, nowMs: bigint): TxnPlan<Extract<TxnRecord, { kind: "changeMode"; }>>; export declare function planUtimes(state: VfsState, path: string, atimeMs: bigint, mtimeMs: bigint, ctimeMs: bigint): TxnPlan<Extract<TxnRecord, { kind: "changeTimes"; }>>; export declare function planResizeFile(state: VfsState, path: string, size: bigint, nowMs: bigint, operation: "truncate" | "write"): TxnPlan<Extract<TxnRecord, { kind: "resizeFile"; }>>; /** @internal Inode-first planner for descriptor operations that already resolved the file. */ export declare function planResizeFileForInode(state: VfsState, inode: FileInode, size: bigint, nowMs: bigint, operation: "truncate" | "write"): TxnPlan<Extract<TxnRecord, { kind: "resizeFile"; }>>; export declare function planRmdir(state: VfsState, path: string, nowMs: bigint): TxnPlan<Extract<TxnRecord, { kind: "removeDirectory"; }>>; export declare function planRename(state: VfsState, oldPath: string, newPath: string, nowMs: bigint): TxnPlan<Extract<TxnRecord, { kind: "rename"; }>>; export declare function planReserveQuarantine(state: VfsState, count: number): TxnPlan<Extract<TxnRecord, { kind: "reserveQuarantine"; }>>; export declare function applyTxn(state: VfsState, record: TxnRecord, prepared?: PreparedTxnProjection): void; export declare function projectRepack(state: VfsState, pinnedQuarantine?: ReadonlySet<ExtentId>): VfsState; /** * @internal Activation-only projection. Structures repack never mutates are shared read-only until * durable activation; allocator and generation structures remain isolated from the live state. */ export declare function projectRepackForActivation(state: VfsState, pinnedQuarantine?: ReadonlySet<ExtentId>): VfsState; export declare function validateState(state: VfsState): void; export declare function canonicalStateView(state: VfsState): { generation: bigint; nextInodeId: bigint; rootInodeId: bigint; extentSize: number; activeMetadataFile: MetadataFile; retainedGenerations: { a: bigint | null; b: bigint | null; }; basePayloadBytes: number; inodes: ({ id: InodeId; mode: number; atimeMs: bigint; mtimeMs: bigint; ctimeMs: bigint; kind: "directory"; children: [string, bigint][]; } | { id: InodeId; mode: number; atimeMs: bigint; mtimeMs: bigint; ctimeMs: bigint; kind: "file"; size: bigint; extents: bigint[]; } | { id: InodeId; mode: number; atimeMs: bigint; mtimeMs: bigint; ctimeMs: bigint; kind: "symlink"; target: string; })[]; parentByInode: [bigint, { parentId: InodeId; name: string; }][]; allocator: { totalExtents: bigint; ownedBy: [bigint, bigint][]; available: bigint[]; quarantine: [bigint, bigint | null][]; }; }; export {}; //# sourceMappingURL=state-machine.d.ts.map