Skip to main content

Storage

Trait Storage 

Source
pub trait Storage: Send + Debug {
    // Required methods
    fn get(&self, key: &[u8]) -> Option<Bytes>;
    fn insert(&self, key: &[u8], value: Bytes, origin: Origin) -> Insertion;
    fn replace(&self, key: &[u8], value: Bytes, origin: Origin) -> Insertion;
    fn scan(&self, visit: &mut dyn FnMut(&[u8], &[u8]));
    fn purge(&self);
    fn purge_key(&self, key: &[u8]);
    fn describe(&self) -> String;

    // Provided methods
    fn insert_many(
        &self,
        entries: &mut dyn Iterator<Item = (Bytes, Bytes)>,
        origin: Origin,
    ) -> InsertSummary { ... }
    fn loading(&self) -> bool { ... }
}
Expand description

Where the entries of a single namespace are kept, and written to.

A storage is bound to one namespace at construction (a /-separated name such as autotune/0.11.0/cuda-0/matmul) and addresses entries by their serialized key bytes.

This is the only thing read at runtime. Bundles are an import format: they fill a storage once through crate::bundle::import and are never consulted again.

§Contract

  • insert is insert-only between two Origin::Local values: it leaves the stored value untouched and reports Insertion::Conflict with it.
  • A Origin::Local value replaces an Origin::Imported one, so a stale bundle entry can never wedge the application that imported it. An Origin::Imported value never replaces anything.
  • replace ignores both rules. It exists for one caller: repairing a row whose bytes no longer decode, which no insert could ever agree with.
  • purge and purge_key are the deletions: the whole namespace, or one entry. Everything else is insert-only.
  • The check and the write must be atomic with respect to other processes.
  • A read that fails reports a miss: a cache entry we can’t read is one we recompute. A write that fails reports Insertion::Failed rather than passing for success, so a caller can tell “someone else got there first” from “the write did not happen”. Implementations log failures but never panic on them.
  • scan may run the visitor while holding the backend’s lock, and several namespaces of one environment share that lock. The visitor must therefore not touch any other store of the same environment: doing so deadlocks.

Methods take &self because reads happen behind shared references on the hot path; implementations use interior mutability.

Required Methods§

Source

fn get(&self, key: &[u8]) -> Option<Bytes>

The value stored under key, if any.

Source

fn insert(&self, key: &[u8], value: Bytes, origin: Origin) -> Insertion

Stores value under key. See the trait contract for when the write is declined.

Source

fn replace(&self, key: &[u8], value: Bytes, origin: Origin) -> Insertion

Stores value under key, overwriting whatever is there.

Bypasses the insert-only rule, so it never reports a conflict. Only for repairing an entry that can’t be decoded; ordinary writes go through insert.

Source

fn scan(&self, visit: &mut dyn FnMut(&[u8], &[u8]))

Visits every entry of the namespace.

The visitor must not read or write another store of the same environment; see the trait contract.

Source

fn purge(&self)

Deletes every entry of the namespace, durably.

A failed delete is logged, not reported: the entries were expendable cache content either way, and whatever survives is arbitrated like any other pre-existing entry.

Source

fn purge_key(&self, key: &[u8])

Deletes the entry under key, durably. Same failure contract as purge.

Source

fn describe(&self) -> String

Human-readable location for log messages.

Provided Methods§

Source

fn insert_many( &self, entries: &mut dyn Iterator<Item = (Bytes, Bytes)>, origin: Origin, ) -> InsertSummary

Stores many entries under the same rules as insert.

Backends that can commit a batch atomically override this; the default is one insert per entry.

Source

fn loading(&self) -> bool

Whether the storage is still loading its content asynchronously. Entries become visible through get and scan once the load completes.

Dyn Compatibility§

This trait is dyn compatible.

In older versions of Rust, dyn compatibility was called "object safety".

Implementors§