Skip to main content

VersionStore

Trait VersionStore 

Source
pub trait VersionStore: Send + Sync {
    // Required methods
    fn get(&self, key: &[u8], read_ts: Timestamp) -> Result<Option<Arc<[u8]>>>;
    fn try_commit(
        &self,
        read_ts: Timestamp,
        commit_ts: Timestamp,
        writes: Vec<WriteEntry>,
        reads: &[Arc<[u8]>],
    ) -> Result<()>;

    // Provided method
    fn collect_garbage(&self, low_watermark: Timestamp) -> usize { ... }
}
Expand description

A keeper of timestamped versions, the backend a Db is built on.

This is the extension point for plugging txn-db onto a real storage engine. The transaction layer supplies the snapshot timestamps and the read and write sets; the store stores versions and enforces, atomically, that a commit only lands when nothing it depends on has changed. The two methods below state the precise contract.

Implementations must be Send + Sync: a Db shares one store across every thread that holds a clone of it.

§Examples

Driving the shipped MemoryStore directly through the trait:

use std::sync::Arc;
use txn_db::{MemoryStore, Timestamp, VersionStore};

let store = MemoryStore::new();
let key: Arc<[u8]> = Arc::from(&b"k"[..]);

// Commit one version at timestamp 1 (snapshot 0, no reads to validate).
store.try_commit(
    Timestamp::ZERO,
    Timestamp::from_raw(1),
    vec![(key.clone(), Some(Arc::from(&b"v1"[..])))],
    &[],
)?;

// A reader at timestamp 1 sees it; a reader at timestamp 0 does not.
assert_eq!(store.get(b"k", Timestamp::from_raw(1))?.as_deref(), Some(&b"v1"[..]));
assert_eq!(store.get(b"k", Timestamp::ZERO)?, None);

Required Methods§

Source

fn get(&self, key: &[u8], read_ts: Timestamp) -> Result<Option<Arc<[u8]>>>

Return the value of key visible at read_ts.

The result is the value of the newest version of key whose commit timestamp is <= read_ts, or None if there is no such version or the newest visible version is a tombstone (the key was deleted as of read_ts).

§Errors

Returns TxnError::Store if the backend fails to service the read. MemoryStore never fails.

Source

fn try_commit( &self, read_ts: Timestamp, commit_ts: Timestamp, writes: Vec<WriteEntry>, reads: &[Arc<[u8]>], ) -> Result<()>

Validate a transaction and, if it does not conflict, apply its writes.

The store must perform the following as one step, atomic with respect to any other try_commit that touches an overlapping key:

  1. Validate. For every key in writes and every key in reads, check that the key has no version with a commit timestamp greater than read_ts — that is, that nothing the transaction wrote or read has changed since its snapshot. reads is empty for snapshot-isolation transactions and carries the read set for serializable ones.
  2. Apply. If validation passes, install each write in writes as a new version stamped commit_ts (Some is a value, None a tombstone). The database guarantees commit_ts is unique and that timestamps are handed out in increasing order.

If any key fails validation, the store applies nothing and reports the conflict.

§Errors

Returns TxnError::Conflict if validation fails; no writes are applied. Returns TxnError::Store if the backend fails to apply the batch.

Provided Methods§

Source

fn collect_garbage(&self, low_watermark: Timestamp) -> usize

Reclaim versions that no reader at or after low_watermark can observe, returning how many were removed.

For each key, the newest version with a commit timestamp at or below low_watermark is the oldest one any live snapshot can still see; versions older than it are unreachable and may be dropped. A key whose only surviving version is a tombstone at or below the watermark may be removed entirely.

The default implementation does nothing, so a store that does not retain history — or chooses not to collect — need not implement it. MemoryStore overrides it.

Dyn Compatibility§

This trait is dyn compatible.

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

Implementors§