pub struct TypedTree<K: Key, T: Send + Sync, C: Codec<T>, H: TypedWriteHook<K, T> = NoHook> { /* private fields */ }Expand description
A tree with fixed-size keys and typed values T. Values are encoded via
a Codec for disk persistence but stored as T in memory — reads never
touch disk and return TypedRef<T> (guard-protected reference).
Each TypedTree owns its storage engine — one tree = one database directory.
§Clone-free design
Unlike ConstTree which copies [u8; V] values (they are Copy), TypedTree
returns TypedRef<T> — a guard-protected reference. The seize guard
inside TypedRef prevents reclamation of the old data while the reference exists.
This means put(), delete(), and update() can return the old value without
requiring T: Clone.
The only method that requires T: Clone is compact() — compaction
must copy the value into a new TypedData with an updated disk location.
§Write hooks
Uses TypedWriteHook<K, T> instead of WriteHook<K>. The hook receives &T
directly (not encoded bytes). on_write fires on put/insert/delete/cas/update.
Does not fire inside atomic(). Old value is always provided (it lives in
memory) — NEEDS_OLD_VALUE is ignored.
on_init fires once per live entry during migrate() or replay_init()
(enable via NEEDS_INIT = true).
§Usage
let tree = TypedTree::<16, MyValue, RapiraCodec>::open(
"data/users",
Config::default(),
RapiraCodec,
)?;
tree.put(&key, value)?;
if let Some(r) = tree.get(&key) {
println!("{:?}", &*r); // TypedRef<MyValue> derefs to &MyValue
}
tree.close()?;§Iteration
iter(), range(), and prefix_iter() all return TypedIter which
implements Iterator + DoubleEndedIterator with Item = (K, &T).
Lock-free, zero disk I/O.
for (key, value) in tree.iter() { }
let latest = tree.prefix_iter(&user_id).take(20).collect::<Vec<_>>();
let oldest = tree.iter().rev().take(5); // DoubleEndedIterator§Features
Requires the typed-tree feature. Codec implementations:
rapira-codec—RapiraCodecforT: rapira::Rapirabitcode-codec—BitcodeCodecforT: bitcode::Encode + Decode
Implementations§
Source§impl<K: Key, T: Send + Sync, C: Codec<T> + Sync, H: TypedWriteHook<K, T>> TypedTree<K, T, C, H>
impl<K: Key, T: Send + Sync, C: Codec<T> + Sync, H: TypedWriteHook<K, T>> TypedTree<K, T, C, H>
Sourcepub fn open_hooked(
path: impl AsRef<Path>,
config: Config,
codec: C,
hook: H,
) -> DbResult<Self>
pub fn open_hooked( path: impl AsRef<Path>, config: Config, codec: C, hook: H, ) -> DbResult<Self>
Open or create a TypedTree with a write hook for secondary index maintenance.
Sourcepub fn close(self) -> DbResult<()>
pub fn close(self) -> DbResult<()>
Graceful shutdown: write hint files (if enabled), flush write buffers + fsync.
Sourcepub fn flush_buffers(&self) -> DbResult<()>
pub fn flush_buffers(&self) -> DbResult<()>
Flush all shard write buffers to disk (without fsync).
Source§impl<K: Key, T: Send + Sync, C: Codec<T> + Sync, H: TypedWriteHook<K, T>> TypedTree<K, T, C, H>
impl<K: Key, T: Send + Sync, C: Codec<T> + Sync, H: TypedWriteHook<K, T>> TypedTree<K, T, C, H>
Sourcepub fn compact(&self) -> DbResult<usize>where
T: Clone,
pub fn compact(&self) -> DbResult<usize>where
T: Clone,
Trigger a compaction pass across all shards.
Sourcepub fn get(&self, key: &K) -> Option<TypedRef<'_, T>>
pub fn get(&self, key: &K) -> Option<TypedRef<'_, T>>
Get a guard-protected reference to a value by key. Lock-free, zero disk I/O.
Sourcepub fn get_or_err(&self, key: &K) -> DbResult<TypedRef<'_, T>>
pub fn get_or_err(&self, key: &K) -> DbResult<TypedRef<'_, T>>
Get a guard-protected reference to a value by key, returning Err(KeyNotFound) if absent.
Sourcepub fn put(&self, key: &K, value: T) -> DbResult<Option<TypedRef<'_, T>>>
pub fn put(&self, key: &K, value: T) -> DbResult<Option<TypedRef<'_, T>>>
Insert or update a key-value pair. Returns a TypedRef to the old value
if the key existed (valid while the guard lives).
Sourcepub fn insert(&self, key: &K, value: T) -> DbResult<()>
pub fn insert(&self, key: &K, value: T) -> DbResult<()>
Insert a key-value pair only if the key does not exist.
Returns Err(KeyExists) if the key is already present.
Sourcepub fn delete(&self, key: &K) -> DbResult<Option<TypedRef<'_, T>>>
pub fn delete(&self, key: &K) -> DbResult<Option<TypedRef<'_, T>>>
Delete a key. Returns a TypedRef to the old value if the key existed.
Sourcepub fn atomic<R>(
&self,
shard_key: &K,
f: impl FnOnce(&mut TypedShard<'_, K, T, C, H>) -> DbResult<R>,
) -> DbResult<R>
pub fn atomic<R>( &self, shard_key: &K, f: impl FnOnce(&mut TypedShard<'_, K, T, C, H>) -> DbResult<R>, ) -> DbResult<R>
Atomically execute multiple operations on a single shard.
All keys must route to the same shard as shard_key.
The closure must be short — shard lock is held for its duration.
Sourcepub fn cas(&self, key: &K, expected: &T, new_value: T) -> DbResult<()>where
T: PartialEq,
pub fn cas(&self, key: &K, expected: &T, new_value: T) -> DbResult<()>where
T: PartialEq,
Compare-and-swap: if current value == expected, replace with new_value.
Returns Ok(()) on success, Err(CasMismatch) if current != expected,
Err(KeyNotFound) if key doesn’t exist.
Sourcepub fn update(
&self,
key: &K,
f: impl FnOnce(&T) -> T,
) -> DbResult<Option<TypedRef<'_, T>>>
pub fn update( &self, key: &K, f: impl FnOnce(&T) -> T, ) -> DbResult<Option<TypedRef<'_, T>>>
Atomically read-modify-write. Returns Some(TypedRef) to the new value
if key existed, None otherwise.
The closure must not be heavy (shard lock is held).
Sourcepub fn fetch_update(
&self,
key: &K,
f: impl FnOnce(&T) -> T,
) -> DbResult<Option<TypedRef<'_, T>>>
pub fn fetch_update( &self, key: &K, f: impl FnOnce(&T) -> T, ) -> DbResult<Option<TypedRef<'_, T>>>
Like update(), but returns Some(TypedRef) to the old value.
Sourcepub fn first(&self) -> Option<(K, TypedRef<'_, T>)>
pub fn first(&self) -> Option<(K, TypedRef<'_, T>)>
Return the first entry in index order, or None if empty.
With reversed=true (default): the entry with the largest key.
O(1) — follows head’s level-0 pointer, skipping marked nodes.
Sourcepub fn last(&self) -> Option<(K, TypedRef<'_, T>)>
pub fn last(&self) -> Option<(K, TypedRef<'_, T>)>
Return the last entry in index order, or None if empty.
With reversed=true (default): the entry with the smallest key.
Sourcepub fn prefix_iter(&self, prefix: &[u8]) -> TypedIter<'_, K, T> ⓘ
pub fn prefix_iter(&self, prefix: &[u8]) -> TypedIter<'_, K, T> ⓘ
Iterate entries whose keys start with prefix.
reversed=true (default): yields matching keys in DESC order.
next() is O(1), next_back() is O(log n).
Sourcepub fn iter(&self) -> TypedIter<'_, K, T> ⓘ
pub fn iter(&self) -> TypedIter<'_, K, T> ⓘ
Iterate all entries in index order.
reversed=true (default): DESC. reversed=false: ASC.
next() is O(1), next_back() is O(log n).
Sourcepub fn range(&self, start: &K, end: &K) -> TypedIter<'_, K, T> ⓘ
pub fn range(&self, start: &K, end: &K) -> TypedIter<'_, K, T> ⓘ
Iterate entries in [start, end) — start inclusive, end exclusive.
reversed=true (default): DESC within range. reversed=false: ASC.
next() is O(1), next_back() is O(log n).
Sourcepub fn range_bounds(
&self,
start: Bound<&K>,
end: Bound<&K>,
) -> TypedIter<'_, K, T> ⓘ
pub fn range_bounds( &self, start: Bound<&K>, end: Bound<&K>, ) -> TypedIter<'_, K, T> ⓘ
Iterate entries in range defined by start and end bounds.
Unlike range(), allows Included, Excluded, or Unbounded
for each bound independently.
reversed=true (default): DESC within range. reversed=false: ASC.
next() is O(1), next_back() is O(log n).
pub fn len(&self) -> usize
pub fn is_empty(&self) -> bool
Sourcepub fn sync_hints(&self) -> DbResult<()>
pub fn sync_hints(&self) -> DbResult<()>
Write hint files for all active shard files. Call during graceful shutdown.
Sourcepub fn migrate(&self, f: impl Fn(&K, &T) -> MigrateAction<T>) -> DbResult<usize>
pub fn migrate(&self, f: impl Fn(&K, &T) -> MigrateAction<T>) -> DbResult<usize>
Iterate all entries and optionally mutate them. Call once at startup.
The callback receives each (key, &T) and returns MigrateAction:
Keep— no change (fireson_initifNEEDS_INIT)Update(new_value)— replace value (hook-free write, fireson_init)Delete— remove entry (hook-free tombstone)
Returns the number of mutated entries.
pub fn shard_for(&self, key: &K) -> usize
Trait Implementations§
Source§impl<T, C, H> Collection for TypedTree<T::SelfId, T, C, H>
Available on crate feature armour only.
impl<T, C, H> Collection for TypedTree<T::SelfId, T, C, H>
armour only.Source§impl<K: Key, T: Clone + Send + Sync, C: Codec<T> + Sync, H: TypedWriteHook<K, T>> CompactionIndex<K> for TypedTree<K, T, C, H>
impl<K: Key, T: Clone + Send + Sync, C: Codec<T> + Sync, H: TypedWriteHook<K, T>> CompactionIndex<K> for TypedTree<K, T, C, H>
Source§fn update_if_match(&self, key: &K, old_loc: DiskLoc, new_loc: DiskLoc) -> bool
fn update_if_match(&self, key: &K, old_loc: DiskLoc, new_loc: DiskLoc) -> bool
old_loc, it is updated to new_loc and returns true.Source§fn contains_key(&self, key: &K) -> bool
fn contains_key(&self, key: &K) -> bool
Auto Trait Implementations§
impl<K, T, C, H = NoHook> !Freeze for TypedTree<K, T, C, H>
impl<K, T, C, H = NoHook> !RefUnwindSafe for TypedTree<K, T, C, H>
impl<K, T, C, H> Send for TypedTree<K, T, C, H>
impl<K, T, C, H> Sync for TypedTree<K, T, C, H>
impl<K, T, C, H> Unpin for TypedTree<K, T, C, H>
impl<K, T, C, H> UnsafeUnpin for TypedTree<K, T, C, H>where
C: UnsafeUnpin,
H: UnsafeUnpin,
impl<K, T, C, H = NoHook> !UnwindSafe for TypedTree<K, T, C, H>
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> Instrument for T
impl<T> Instrument for T
Source§fn instrument(self, span: Span) -> Instrumented<Self>
fn instrument(self, span: Span) -> Instrumented<Self>
Source§fn in_current_span(self) -> Instrumented<Self>
fn in_current_span(self) -> Instrumented<Self>
Source§impl<T> IntoEither for T
impl<T> IntoEither for T
Source§fn into_either(self, into_left: bool) -> Either<Self, Self>
fn into_either(self, into_left: bool) -> Either<Self, Self>
self into a Left variant of Either<Self, Self>
if into_left is true.
Converts self into a Right variant of Either<Self, Self>
otherwise. Read moreSource§fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
self into a Left variant of Either<Self, Self>
if into_left(&self) returns true.
Converts self into a Right variant of Either<Self, Self>
otherwise. Read more