OverlayRecordStore — a composite RecordStore layering a private writable
overlay over a shared read-only base. Reads resolve overlay-first, skipping
tombstoned base handles; writes land only in the overlay; the base is never mutated.
The record half of the :overlay backend (the index half is
vaelii.impl.overlay.kv).
mark-premise materializes an override
before it writes, since the assumption strength lives on the record. The boundary
holds over the base the handles were minted against, so a mount records the base's
watermark and refuses a base that has grown since the fork wrote against it
(check-base-overlap!).clear-records! empties the overlay and marks the base
hidden — one flag rather than a tombstone per base handle — so a fork can be reset
to empty without walking what it inherited.KvBackend under reserved keys, mirrored in atoms for
the read path. Every mutation writes through, and a mount rebuilds the atoms from
it, so remounting a durable overlay over the same base serves the same merged contents:
a deleted base record stays deleted, a released premise stays released. An
ephemeral fork passes an in-RAM bookkeeping backend and pays nothing for the
machinery.Counts need no delta bookkeeping here. A RecordStore exposes handle
sets rather than counts, and everything counted — sentex-count, count-in-context,
count-with-functor — is read off the index, where the merge is the trie's own
copy-on-write counters and the merged root sets (vaelii.impl.overlay.kv). So the
counts a fork reports are exact by construction rather than by a second, parallel
accounting that could drift from the records.
The fork's belief is rebuilt, not overlaid. The JTMS is not storage — it is a
separate protocol (vaelii.impl.jtms) over derived state — and the engine already has the
operation that computes it from records: recover. So a fork gets its own network by
recovering over the merged contents, and nothing here layers one truth-maintenance graph
over another.
`OverlayRecordStore` — a composite `RecordStore` layering a private **writable** overlay over a shared **read-only** base. Reads resolve overlay-first, skipping tombstoned base handles; writes land only in the overlay; the base is never mutated. The record half of the `:overlay` backend (the index half is `vaelii.impl.overlay.kv`). * **The id boundary.** The overlay's handle counter is seeded above every handle the base holds, so a newly minted handle can never collide with a base one. A record written at a handle the base *already* uses is therefore an **override** — the same handle, a different record — and the overlay's copy wins every read. That is how a base record is edited without editing the base: `mark-premise` materializes an override before it writes, since the assumption strength lives on the record. The boundary holds over the base the handles were minted against, so a mount records the base's watermark and refuses a base that has grown since the fork wrote against it (`check-base-overlap!`). * **Tombstones.** Deleting a base handle cannot touch the base, so it is recorded and the read path filters it. They are sticky: a base record cannot come back through fall-through, only by being written again into the overlay (a revival, at the same handle). * **Wholesale clear.** `clear-records!` empties the overlay and marks the base hidden — one flag rather than a tombstone per base handle — so a fork can be reset to empty without walking what it inherited. * **Durable bookkeeping.** The tombstone sets, the released premise marks and the hidden flag live in a small `KvBackend` under reserved keys, mirrored in atoms for the read path. Every mutation writes through, and a mount rebuilds the atoms from it, so remounting a durable overlay over the same base serves the same merged contents: a deleted base record stays deleted, a released premise stays released. An ephemeral fork passes an in-RAM bookkeeping backend and pays nothing for the machinery. **Counts need no delta bookkeeping here.** A `RecordStore` exposes handle *sets* rather than counts, and everything counted — `sentex-count`, `count-in-context`, `count-with-functor` — is read off the index, where the merge is the trie's own copy-on-write counters and the merged root sets (`vaelii.impl.overlay.kv`). So the counts a fork reports are exact by construction rather than by a second, parallel accounting that could drift from the records. **The fork's belief is rebuilt, not overlaid.** The JTMS is not storage — it is a separate protocol (`vaelii.impl.jtms`) over derived state — and the engine already has the operation that computes it from records: `recover`. So a fork gets its own network by recovering over the merged contents, and nothing here layers one truth-maintenance graph over another.
(excluding-readers {:keys [rebase-lock]} f)Call f holding the write side of fork store's rebase lock, and return what f
returns. Every public read holds the read side (kb/reading), so a read on another
thread waits for f to return, and the calling thread's own reads re-enter.
Call `f` holding the write side of fork `store`'s rebase lock, and return what `f` returns. Every public read holds the read side (`kb/reading`), so a read on another thread waits for `f` to return, and the calling thread's own reads re-enter.
(overlay-record-store overlay base meta-kv)(overlay-record-store overlay base meta-kv index-cleared?)(overlay-record-store overlay base meta-kv index-cleared? base-opts)Compose a writable overlay RecordStore over a read-only base one, with meta-kv
holding the overlay's record-level bookkeeping.
The mount reads the bookkeeping back — so a durable overlay remounted over the same
base serves the merged contents it was left in — and seeds the handle counter above both
stores' watermarks, which is what keeps a minted handle out of the base's range even
after a restart. It records the base's watermark in the bookkeeping, and refuses
(:fork-base-overlap) a remount over a base that has changed since, once the fork has
written anything (check-base-overlap!). index-cleared? says the fork's own index
half has been rebuilt (reindex), which is state the record half cannot see.
base-opts are the opts the base was opened from, or nil when it arrived as open
stores; rebase! replaces a base that has them.
Compose a writable `overlay` `RecordStore` over a read-only `base` one, with `meta-kv` holding the overlay's record-level bookkeeping. The mount reads the bookkeeping back — so a durable overlay remounted over the same base serves the merged contents it was left in — and seeds the handle counter above both stores' watermarks, which is what keeps a minted handle out of the base's range even after a restart. It records the base's watermark in the bookkeeping, and refuses (`:fork-base-overlap`) a remount over a base that has changed since, once the fork has written anything (`check-base-overlap!`). `index-cleared?` says the fork's own index half has been rebuilt (`reindex`), which is state the record half cannot see. `base-opts` are the opts the base was opened from, or nil when it arrived as open stores; `rebase!` replaces a base that has them.
(overlay-record-store? store)Is store one of these — i.e. is it already a fork's record half? Asked by
vaelii.impl.overlay.mount, which refuses a base that is itself a fork.
Is `store` one of these — i.e. is it already a fork's record half? Asked by `vaelii.impl.overlay.mount`, which refuses a base that is itself a fork.
(rebase! {:keys [overlay base meta-kv counter base-top hidden? sx-tombstoned
jd-tombstoned pv-tombstoned released]}
refill!)Empty the fork store's own records and bookkeeping, call refill!, which replaces the
contents of the base's stores, and mount the emptied half over the new base, returning
what refill! returns. The handle counter and the watermark are seeded from the
base's next-id, as a mount seeds them. Every record, tombstone, released mark and
base digest the fork held is dropped, so nothing written against the old base is read
against the new one. The base reads as hidden until refill! returns.
Empty the fork `store`'s own records and bookkeeping, call `refill!`, which replaces the contents of the base's stores, and mount the emptied half over the new base, returning what `refill!` returns. The handle counter and the watermark are seeded from the base's `next-id`, as a mount seeds them. Every record, tombstone, released mark and base digest the fork held is dropped, so nothing written against the old base is read against the new one. The base reads as hidden until `refill!` returns.
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 |