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§
Sourcefn get(&self, key: &[u8], read_ts: Timestamp) -> Result<Option<Arc<[u8]>>>
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.
Sourcefn try_commit(
&self,
read_ts: Timestamp,
commit_ts: Timestamp,
writes: Vec<WriteEntry>,
reads: &[Arc<[u8]>],
) -> Result<()>
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:
- Validate. For every key in
writesand every key inreads, check that the key has no version with a commit timestamp greater thanread_ts— that is, that nothing the transaction wrote or read has changed since its snapshot.readsis empty for snapshot-isolation transactions and carries the read set for serializable ones. - Apply. If validation passes, install each write in
writesas a new version stampedcommit_ts(Someis a value,Nonea tombstone). The database guaranteescommit_tsis 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§
Sourcefn collect_garbage(&self, low_watermark: Timestamp) -> usize
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".