Mounting a fork: freeze a base, compose a private writable overlay over it, and hand back the two stores a KB is built from.
A base is any pair of stores mounted read-only (vaelii.impl.overlay.frozen); a
fork is a fresh writable pair composed over it. Nothing is copied and nothing in
the base is written, so N JVMs mount one frozen base and each evolves its own fork —
the sharing needs no protocol between them, and equally offers no coherence between
them: a base that changes under a mounted fork is outside the contract.
The overlay is a KvBackend decorator, so it forks exactly the index path that is
written over that protocol: KvIndexStore (vaelii.impl.kv) and therefore the
:memory, :dense and :disk index axes. The :columnar index is a native
IndexStore — its trie is int-id nodes in parallel arrays, with no keys and no backend
underneath — so a KvBackend decorator would fork its roots and leave its trie behind.
That is refused here rather than half-done. Forking a columnar index is a different
construction: its compacted CSR mode is already an immutable base, so the natural shape
is a mutable columnar head over a frozen CSR base, not a KV decorator.
The record half keeps tombstones and released premise marks in a small KvBackend
beside the overlay (vaelii.impl.overlay.store). An in-RAM overlay gets an in-RAM one
— the whole fork is ephemeral — and a disk overlay gets a durable one under
<dir>/overlay-meta, so remounting that directory over the same base serves the merged
view it was left in. The index half needs none: its bookkeeping lives in the overlay
index itself, under reserved keys, and so is exactly as durable as the fork is.
Mounting a fork: freeze a base, compose a private writable overlay over it, and hand back the two stores a KB is built from. A **base** is any pair of stores mounted read-only (`vaelii.impl.overlay.frozen`); a **fork** is a fresh writable pair composed over it. Nothing is copied and nothing in the base is written, so N JVMs mount one frozen base and each evolves its own fork — the sharing needs no protocol between them, and equally offers no coherence between them: a base that changes under a mounted fork is outside the contract. ## Which index a fork can be taken over The overlay is a `KvBackend` decorator, so it forks exactly the index path that is written over that protocol: `KvIndexStore` (`vaelii.impl.kv`) and therefore the `:memory`, `:dense` and `:disk` index axes. The `:columnar` index is a **native** `IndexStore` — its trie is int-id nodes in parallel arrays, with no keys and no backend underneath — so a `KvBackend` decorator would fork its roots and leave its trie behind. That is refused here rather than half-done. Forking a columnar index is a different construction: its compacted CSR mode is already an immutable base, so the natural shape is a mutable columnar head over a frozen CSR base, not a KV decorator. ## Bookkeeping The record half keeps tombstones and released premise marks in a small `KvBackend` beside the overlay (`vaelii.impl.overlay.store`). An in-RAM overlay gets an in-RAM one — the whole fork is ephemeral — and a disk overlay gets a durable one under `<dir>/overlay-meta`, so remounting that directory over the same base serves the merged view it was left in. The index half needs none: its bookkeeping lives in the overlay index itself, under reserved keys, and so is exactly as durable as the fork is.
(fresh-overlay-opts)Storage opts for an ephemeral fork: an in-RAM overlay on a space pair nothing else names, so two forks taken with no opts are independent rather than accidentally the same one. Naming the spaces explicitly is how a caller asks for the other behaviour — a remount of a fork it took earlier.
Storage opts for an **ephemeral** fork: an in-RAM overlay on a space pair nothing else names, so two forks taken with no opts are independent rather than accidentally the same one. Naming the spaces explicitly is how a caller asks for the other behaviour — a remount of a fork it took earlier.
(kv-backend-of index-store)The KvBackend an IndexStore is written over, or nil when it is not written over one
at all. A KvIndexStore holds it as :backend; a native index (the columnar one) has
no such seam and answers nil.
The `KvBackend` an `IndexStore` is written over, or nil when it is not written over one at all. A `KvIndexStore` holds it as `:backend`; a native index (the columnar one) has no such seam and answers nil.
(meta-kv kind opts)The bookkeeping KvBackend for a fork whose record overlay is kind (:memory or
:disk) under opts — in RAM for an ephemeral fork, durable beside the records for a
disk one, so the two are exactly as recoverable as each other.
The bookkeeping `KvBackend` for a fork whose *record* overlay is `kind` (`:memory` or `:disk`) under `opts` — in RAM for an ephemeral fork, durable beside the records for a disk one, so the two are exactly as recoverable as each other.
(mount-index overlay base)A KvIndexStore over an OverlayKv: overlay's backend (writable) over base's
(frozen). Both arguments are IndexStores, and both must be KvIndexStores — see the
namespace docstring on why the columnar index is not forkable this way.
A `KvIndexStore` over an `OverlayKv`: `overlay`'s backend (writable) over `base`'s (frozen). Both arguments are `IndexStore`s, and both must be `KvIndexStore`s — see the namespace docstring on why the columnar index is not forkable this way.
(mount-records overlay base meta)An OverlayRecordStore: overlay (writable) over base (frozen), with meta holding
the record-level bookkeeping.
An `OverlayRecordStore`: `overlay` (writable) over `base` (frozen), with `meta` holding the record-level bookkeeping.
cljdoc builds & hosts documentation for Clojure/Script libraries
| Ctrl+k | Jump to recent docs |
| ← | Move to previous article |
| → | Move to next article |
| Ctrl+/ | Jump to the search field |