ol.xitstash

Stores immutable payloads and a file catalog in an application-selected xitdb subtree.

prepare

(prepare source)
(prepare source options)

Chunks and hashes bytes, a File/Path, or an InputStream before insertion.

Returns closeable prepared content with :digest and :size. Byte arrays are copied. Caller-supplied streams are not closed. Uncompressed files are scanned without a temporary copy and must match their prepared chunk hashes when consumed. Closing prepared content releases its temporary storage, not the source file. Prepared content can be consumed repeatedly before close.

Options:

Key Default Meaning

:algorithm

:sha2-256

:sha2-256 or :sha2-512

:min-size

262144

Minimum FastCDC chunk size

:average-size

1048576

Power-of-two target, 256 through 4194304

:max-chunk-size

4194304

Maximum chunk size, at most 16777216

:compression

:none

:none or per-chunk :zlib, only if smaller

:memory-threshold

1048576

Spool bytes before spilling, at most 16777216

:max-size

1099511627776

Maximum original payload bytes

:max-chunks

65536

Maximum chunk count

:max-metadata-bytes

16777216

Sum of EDN-encoded chunk-record lengths

:max-temp-bytes

1099511627776

Maximum simultaneous staged payload bytes

:temp-dir

JVM temporary directory

Existing File/Path or path string

Chunk sizes must be positive and ordered. Resource limits are nonnegative signed 64-bit integers. Spool buffers and chunk buffers are bounded, but total metadata memory grows with chunk count. The metadata limit measures encoded records, not JVM heap usage. Compression may temporarily require both an input spool and an encoded spool within :max-temp-bytes.

Invalid options and exhausted limits throw typed ex-info. Native I/O errors propagate. Use cleanup-staging! for abandoned temporary storage.


upload

(upload)
(upload options)

Creates a closeable OutputStream for content preparation outside a transaction.

Operations on one builder are serialized. Closing an unfinished builder discards its staging data. finish seals the builder and returns separate closeable prepared content. Closing the builder after finish does not close that result. Writes and repeated finish calls after sealing throw typed ex-info. Prefer bulk writes over individual bytes.

Options:

Key Meaning

All prepare options

Same defaults and resource limits

Chunking and hashing run during finish, before a write transaction.


finish

(finish builder)

Seals builder and returns prepared content without publishing it.

Call once on a builder from upload. Hashing and chunking complete before return. A failed finish discards staging data. Close the returned prepared content separately from the builder.


cleanup-staging!

(cleanup-staging!)
(cleanup-staging! options)

Deletes inactive, marked staging directories and returns their paths.

File locks protect active preparations, including those in other processes. A directory with an invalid marker or unexpected files is not removed. No background cleanup starts automatically. Prefer an application-specific temporary directory. Unmarked directories from an interrupted initial directory creation are not removed.

Options:

Key Default Meaning

:temp-dir

JVM temporary directory

Existing directory to inspect

:min-age-ms

86400000

Minimum directory age, nonnegative milliseconds

Unknown options and invalid ages throw typed ex-info. Native I/O errors propagate. Cleanup cannot remove published database content.


initialize!

(initialize! cursor)

Initializes an empty subtree or validates an existing xitstash store.

cursor must be a native write cursor inside an application transaction. Returns {:format string :initialized? boolean}. An empty plain map is accepted. Unrelated nonempty data and unsupported formats are rejected without mutation. Repeated initialization does not write data.


put!

(put! cursor prepared)

Publishes prepared content inside the application’s write transaction.

cursor selects an initialized store. prepared comes from prepare or finish and must be open. Returns :digest, :size, and :deduplicated?. Existing payloads are not rewritten. Prepared bytes are checked again, including on duplicate insertion. Shared chunks are stored once.

Results are provisional until the application commits. Let any exception escape the transaction callback to abort. Close prepared content separately.


payload

(payload cursor digest)

Returns realized {:digest id :size bytes} metadata without reading content.

cursor selects a store. Missing content throws :xitstash/not-found.


manifest

(manifest cursor digest)
(manifest cursor digest options)

Returns realized payload metadata with ordered :chunks digest/size maps.

Validates native references and lengths without decoding chunk bytes. Missing content, corrupt metadata, and exceeded limits throw typed ex-info. The metadata limit counts encoded records, not JVM heap usage.

Option Default Meaning

:max-chunks

65536

Maximum manifest entries

:max-metadata-bytes

16777216

Sum of EDN-encoded chunk-record lengths


open

(open cursor digest)
(open cursor digest options)

Opens a closeable InputStream over a payload or byte range.

Each decoded chunk is checked before its bytes are exposed. One decoded chunk is cached, plus checked metadata and temporary decoding buffers. Closing the stream does not close the database. Close streams before their supplied cursors become invalid, or before database compaction/replacement.

Library native reads use the database monitor. Coordinate other native access, including cursor acquisition and transactions, with that monitor or prevent overlap through application-level synchronization.

Option Default Meaning

:start

0

Inclusive payload byte offset

:end

Payload size

Exclusive payload byte offset

:max-chunks

65536

Maximum manifest entries

:max-metadata-bytes

16777216

Sum of EDN-encoded chunk-record lengths

Requires 0 ⇐ start ⇐ end ⇐ size. Missing content, corrupt chunks, invalid ranges, and exceeded limits throw typed ex-info. Native I/O errors propagate. Use seek! to move within the selected range.


seek!

(seek! stream offset origin)

Moves a stream from open and returns its range-relative byte position.

origin is :start/0, :current/1, or :end/2. offset is a signed 64-bit integer. Negative results and overflow throw typed ex-info without changing position. Positions after the range end are allowed and read EOF. Seeking a closed stream throws :xitstash/closed.


create!

(create! cursor requests)

Creates 1–4096 catalog nodes inside the application’s write transaction.

Returns a vector of records in request order. Each record has :id, :parent, :name, :kind (:directory or :file), and :revision. Files also have :digest and :size. All records in one batch use the same revision token.

Request key Meaning

:name

Required name, 1–4096 valid UTF-8 bytes, no slash/NUL or dot/double dot

:parent

Existing directory ID, default root 0

:under

One-based position of an earlier directory request, instead of :parent

:digest

Published payload ID for a file, absent for a directory

:id

Optional positive signed 64-bit ID, otherwise allocated automatically

Requests are processed in order. Explicit IDs advance the automatic counter. Existing IDs and sibling names conflict. Automatic IDs are not recycled, but independent branches can allocate the same ID. Applications must handle that when merging. Unknown request keys are invalid.

Results are provisional until commit. Let any exception escape the transaction callback to abort all changes. Files can reference payloads published earlier in the same transaction with put!.


node

(node cursor id)

Returns a realized catalog record for a positive id.

Root 0 has no record. Missing nodes throw :xitstash/not-found. See create! for record fields.


lookup

(lookup cursor parent name)

Returns the child record at parent and name.

parent is a directory ID or root 0. Invalid names and non-directory parents throw :xitstash/invalid-argument. Missing parents or children throw :xitstash/not-found.


children

(children cursor parent)

Returns a realized vector of child records in UTF-8 byte name order.

parent is a directory ID or root 0. Empty directories return []. Missing parents throw :xitstash/not-found, files are invalid parents. Result memory grows with the directory’s child count.


path

(path cursor id)

Returns a realized vector of names from root to id.

Root 0 returns []. Missing nodes or ancestors throw :xitstash/not-found. Corrupt parent chains throw :xitstash/corrupt-data.


files

(files cursor digest)

Returns a realized vector of ascending file IDs that reference digest.

No references return [], including for an unpublished valid payload ID. Invalid identifiers throw typed ex-info. Result memory grows with the number of referencing files.


update!

(update! cursor id digest expected-revision)

Changes a file’s payload inside the application’s write transaction.

digest must identify a published payload. Returns the updated record. Directories and root 0 cannot be updated. An unchanged digest performs no writes and preserves the record’s revision.

expected-revision is a nonnegative signed 64-bit integer. Zero skips the check. A stale positive value throws :xitstash/conflict, even for a no-op. Negative values are invalid. Changed records get a new per-store revision. Results are provisional, as described by create!.


move!

(move! cursor id destination expected-revision)

Renames or reparents a catalog node inside the application’s transaction.

Returns the source record with its unchanged ID and new revision. Moving to its current parent/name performs no writes and preserves its revision. Root 0 cannot move. A directory cannot move into itself or its descendants. Revision checks and provisional results follow update!.

Destination key Default Meaning

:parent

Current parent

Directory ID or root 0

:name

Current name

New name, subject to create! name rules

:replace?

false

Remove an occupied destination of the same kind

Replacement directories must be empty. Replacement removes the destination record, not its payload. Without replacement, occupied destinations conflict. Unknown keys are invalid. Let any exception escape to abort the transaction.


remove!

(remove! cursor id expected-revision)

Removes a file or empty directory inside the application’s transaction.

Returns the removed record, with its revision from before removal. Root 0 cannot be removed. Nonempty directories throw :xitstash/conflict. Removal updates catalog indexes but never deletes payload content. Automatic IDs are not recycled. Revision checks and provisional results follow update!.


delete-payload!

(delete-payload! cursor digest)
(delete-payload! cursor digest options)

Deletes a published payload inside the application’s write transaction.

Current catalog file references cause :xitstash/conflict. The application must check references outside the catalog. Missing payloads throw :xitstash/not-found. Shared chunks stay available to other payloads.

Returns {:digest id :removed-chunks n :shared-chunks n}. Counts refer to distinct chunk IDs, not repeated manifest occurrences. Metadata and reference counts are checked without reading chunk content. Results are provisional until commit. Let any exception escape the transaction callback to abort.

Option Default Meaning

:max-chunks

65536

Maximum manifest entries

:max-metadata-bytes

16777216

Sum of EDN-encoded chunk-record lengths

This is logical deletion from the selected current store. It does not compact or replace database files, revoke open streams, or erase snapshots, backups, or replicas. Physical reclamation needs application-controlled compaction with no reachable old native references. No secure-overwrite guarantee is made.