pub struct ReadOnlyDatabase { /* private fields */ }Expand description
A read-only database handle backed by a memory-mapped snapshot
See the module docs. Send + Sync — share it across
threads behind a reference or an Arc.
Implementations§
Source§impl ReadOnlyDatabase
impl ReadOnlyDatabase
Sourcepub fn recall(&self, q: RecallQuery<'_>) -> Result<RecallResult, HostError>
pub fn recall(&self, q: RecallQuery<'_>) -> Result<RecallResult, HostError>
Runs a recall. Same semantics as
Database::recall minus the embedder:
a text-only query is not auto-embedded, so pass a vector for the
vector source.
Sourcepub fn get(&self, id: FactId) -> Option<FactSnapshot>
pub fn get(&self, id: FactId) -> Option<FactSnapshot>
An owned copy of one fact, or None for unknown/tombstoned ids.
Sourcepub fn verify(&self) -> Result<(), HostError>
pub fn verify(&self) -> Result<(), HostError>
Runs the on-demand integrity check — the equivalent of
SQLite’s integrity_check. A read-only open validates only the metadata
(the mapped text and vector pools stay non-resident); this sweeps them
and reports any latent corruption. Reads the whole image, so it residents
the pools it checks.
§Errors
HostError::Engine for the first inconsistency found.
Sourcepub fn scrub(&self) -> Result<Scrub, HostError>
pub fn scrub(&self) -> Result<Scrub, HostError>
A resumable byte-level container scrub of the snapshot file, with the
default slice budget (— the ZFS-scrub model). See
Scrub and ReadOnlyDatabase::scrub_with_budget.
§Errors
HostError::Locked/HostError::Io/HostError::Engine if the
file cannot be locked, mapped, or structurally parsed for the scan.
Sourcepub fn scrub_with_budget(&self, budget: usize) -> Result<Scrub, HostError>
pub fn scrub_with_budget(&self, budget: usize) -> Result<Scrub, HostError>
A resumable container scrub hashing at most budget bytes per
Iterator::next.
The returned Scrub owns its own map and its own shared advisory
lock over the same file, so it holds a reader’s lock for its whole
life (a writer is refused with HostError::Locked while any scrub
or read-only handle lives) and can be moved to its own thread — the
caller paces the scan (next, pause, resume, cancel) exactly like
the core ScrubCursor. Dropping it releases the lock.
It is independent of self: the scrub keeps running after this handle
is dropped. A non-empty journal is not an obstacle — the scrub checks
the on-disk snapshot container as-is.
§Errors
Sourcepub fn export(&self) -> Vec<ExportedFact>
pub fn export(&self) -> Vec<ExportedFact>
Dumps the currently-open facts for a human-readable backup
See ExportedFact. Collects the whole
set; for a large database prefer export_each.
Sourcepub fn export_each(&self, f: impl FnMut(ExportedFact))
pub fn export_each(&self, f: impl FnMut(ExportedFact))
Streams the currently-open facts, calling f once per fact under the map
— the whole dump is never materialized (the zero-copy analog of
Database::export_each).
Sourcepub fn generation(&self) -> u64
pub fn generation(&self) -> u64
The snapshot generation this handle is pinned to — the point in time it
reads “as of”. Monotonic: a writer’s checkpoint publishes a strictly
higher number. Compare it against a later call, or drive your own
freshness policy around refresh with it.
Sourcepub fn refresh(&mut self) -> Result<bool, HostError>
pub fn refresh(&mut self) -> Result<bool, HostError>
Advances this handle to the writer’s latest published generation, if
there is a newer one. Returns true when it re-mapped onto a newer
snapshot (subsequent reads now observe it), false when nothing changed.
This is the only way a read-only handle moves forward in time: an
open handle is a point-in-time snapshot and never advances on its own
(see the module docs). It exists for a reader watching another
process’s writer; a single process that reads and writes uses one
Database handle and sees its own writes instantly,
with no refresh at all.
It is cheap to call speculatively — the freshness check is a read of the
tiny fixed-size manifest (a handful of bytes), and the mmap re-map
happens only when the writer has actually published a newer generation.
In steady state (no new checkpoint) it does no mapping and returns false
for the cost of that manifest read, so calling it before each read is a
reasonable “always fresh” policy; batching (refresh every N reads, or on a
timer) trades a bounded staleness for even fewer manifest reads. Re-mapping
borrows the new generation’s pages lazily — no whole-file copy, no journal
replay, no index rebuild — and drops the old map, so RAM does not grow.
The freshness policy is intentionally left to the caller: an autorefresh baked into every read would forfeit snapshot isolation for callers who need a stable view across a series of queries. Keep the reader stable by not calling this; advance it by calling it.
§Errors
HostError::Io if the newer generation cannot be mapped;
HostError::Engine for a corrupt image. On any error the handle is
left untouched on its current generation (the re-map is built before it
replaces the live one).