pub struct Capabilities {
pub atomic_replace: bool,
pub exclusive_create: bool,
pub sync_guarantee: SyncGuarantee,
pub native_transactions: bool,
}Expand description
The durability guarantees a Storage backend can make — declared by the
backend through Storage::capabilities, honored by the crash-safety
machinery in ChangeSet.
The point of naming these explicitly is that a transaction must run correctly over backends that keep very different promises. Rather than assume a guarantee and corrupt data on the backend that cannot keep it, the apply path reads the capabilities and picks the strongest protocol the backend actually supports: a filesystem gets atomic-rename writes and a journal; a transactional store is handed the whole change set to commit itself; a backend that can promise neither still works, it simply cannot claim a write survives a crash.
Fields§
§atomic_replace: boolThe backend can replace an existing file’s contents in one indivisible
step, so no crash exposes a half-written file — an observer sees the whole
old contents or the whole new. On a filesystem this is realized by
Storage::write_atomic’s write-temp-then-rename; a backend may
instead be atomic by nature.
exclusive_create: boolThe backend can create a file only if nothing is at its path yet, as
one operation — Storage::create_new. The create and the
test-for-existence cannot be split: two writers racing to the same name
see exactly one succeed and the other told
AlreadyExists, with no window between
the test and the create for a half-written file to slip through. This is
the primitive an append-only, write-once consumer builds its whole
concurrency story on, which is why it is declared rather than emulated:
a check-then-write emulation has the window in it, and a backend that
cannot close the window must say so instead of pretending.
sync_guarantee: SyncGuaranteeHow strong the backend’s Storage::sync is: whether it can flush at
all, and if so whether a flush merely orders writes or carries them
through a power cut. fsync on std::fs, FileSystemSyncAccessHandle .flush() on OPFS, the implicit durability of a committed IndexedDB
transaction.
native_transactions: boolThe backend commits changes to many objects as one indivisible unit, so this crate’s write-ahead journal would be redundant and a caller should defer to the backend instead. True for IndexedDB; false for a plain filesystem, where multi-file atomicity is the journal’s job to provide.
Implementations§
Source§impl Capabilities
impl Capabilities
Sourcepub const NONE: Capabilities
pub const NONE: Capabilities
Promises nothing — the safe assumption for an unknown backend, and the
Storage::capabilities default. Every field is the pessimistic value,
so code that checks a capability before relying on it takes the most
defensive branch unless a backend has explicitly earned a lighter one.
Sourcepub const LOCAL_FS: Capabilities
pub const LOCAL_FS: Capabilities
A conventional local filesystem: atomic replacement by rename, exclusive
create (O_CREAT|O_EXCL, honored by every OS this crate targets), and
durable fsync — but no native multi-object transaction (that is the
journal’s job). What StdFs reports on every platform this crate
targets.
Sourcepub const IN_MEMORY: Capabilities
pub const IN_MEMORY: Capabilities
An in-process, memory-only store (InMemoryFs): every mutation takes
the backend’s single lock for its whole duration, so one write already
swaps old bytes for new as one indivisible step — no separate
temp-then-rename dance is needed for atomic_replace to be true. But
nothing here is backed by anything other than process memory, so its
sync_guarantee is SyncGuarantee::None: there is nothing to flush,
and the entire store evaporates the instant the process exits — it cannot
even promise ordering against a crash it will not survive.
native_transactions
is false too — the lock makes each single call atomic, not a batch of
several calls committed together, so a multi-file change set still
needs the write-ahead journal over this backend exactly as it would over
a real filesystem. exclusive_create is true on the same grounds as
atomic_replace: one locked call checks and inserts without anything
interleaving.
Trait Implementations§
Source§impl Clone for Capabilities
impl Clone for Capabilities
Source§fn clone(&self) -> Capabilities
fn clone(&self) -> Capabilities
1.0.0 (const: unstable) · Source§fn clone_from(&mut self, source: &Self)
fn clone_from(&mut self, source: &Self)
source. Read moreimpl Copy for Capabilities
Source§impl Debug for Capabilities
impl Debug for Capabilities
impl Eq for Capabilities
Source§impl PartialEq for Capabilities
impl PartialEq for Capabilities
impl StructuralPartialEq for Capabilities
Auto Trait Implementations§
impl Freeze for Capabilities
impl RefUnwindSafe for Capabilities
impl Send for Capabilities
impl Sync for Capabilities
impl Unpin for Capabilities
impl UnsafeUnpin for Capabilities
impl UnwindSafe for Capabilities
Blanket Implementations§
Source§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
Source§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
Source§impl<T> CloneToUninit for Twhere
T: Clone,
impl<T> CloneToUninit for Twhere
T: Clone,
Source§impl<Q, K> Equivalent<K> for Q
impl<Q, K> Equivalent<K> for Q
Source§impl<Q, K> Equivalent<K> for Q
impl<Q, K> Equivalent<K> for Q
Source§fn equivalent(&self, key: &K) -> bool
fn equivalent(&self, key: &K) -> bool
key and return true if they are equal.