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 |
|---|---|---|
|
|
|
|
262144 |
Minimum FastCDC chunk size |
|
1048576 |
Power-of-two target, 256 through 4194304 |
|
4194304 |
Maximum chunk size, at most 16777216 |
|
|
|
|
1048576 |
Spool bytes before spilling, at most 16777216 |
|
1099511627776 |
Maximum original payload bytes |
|
65536 |
Maximum chunk count |
|
16777216 |
Sum of EDN-encoded chunk-record lengths |
|
1099511627776 |
Maximum simultaneous staged payload bytes |
|
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 |
Same defaults and resource limits |
Chunking and hashing run during finish, before a write transaction.
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 |
|---|---|---|
|
JVM temporary directory |
Existing directory to inspect |
|
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 |
|---|---|---|
|
65536 |
Maximum manifest entries |
|
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 |
|---|---|---|
|
0 |
Inclusive payload byte offset |
|
Payload size |
Exclusive payload byte offset |
|
65536 |
Maximum manifest entries |
|
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 |
|---|---|
|
Required name, 1–4096 valid UTF-8 bytes, no slash/NUL or dot/double dot |
|
Existing directory ID, default root |
|
One-based position of an earlier directory request, instead of |
|
Published payload ID for a file, absent for a directory |
|
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!.
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 |
|---|---|---|
|
Current parent |
Directory ID or root |
|
Current name |
New name, subject to |
|
|
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 |
|---|---|---|
|
65536 |
Maximum manifest entries |
|
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.