pub struct ConstTree<K: Key, const V: usize, H: WriteHook<K> = NoHook> { /* private fields */ }Expand description
A tree with fixed-size keys and values. All values are stored inline in SkipList nodes. Reads never touch disk — zero I/O reads.
Each ConstTree owns its storage engine — one tree = one database directory.
§Write hooks
Uses WriteHook<K>. on_write fires on put/insert/delete/cas/update.
Does not fire inside atomic(). on_init fires once per live entry
during migrate() or replay_init(). Old value is always provided in
on_write — NEEDS_OLD_VALUE is ignored (value is inline, zero cost).
§Usage
let tree = ConstTree::<16, 64>::open("data/users", Config::default())?;
tree.put(&key, &value)?;
tree.close()?;§Iteration
iter(), range(), and prefix_iter() all return ConstIter which
implements Iterator + DoubleEndedIterator with Item = (K, [u8; V]).
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); // DoubleEndedIteratorImplementations§
Source§impl<K: Key, const V: usize, H: WriteHook<K>> ConstTree<K, V, H>
impl<K: Key, const V: usize, H: WriteHook<K>> ConstTree<K, V, H>
Sourcepub fn open_hooked(
path: impl AsRef<Path>,
config: Config,
hook: H,
) -> DbResult<Self>
pub fn open_hooked( path: impl AsRef<Path>, config: Config, hook: H, ) -> DbResult<Self>
Open or create a ConstTree 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, const V: usize, H: WriteHook<K>> ConstTree<K, V, H>
impl<K: Key, const V: usize, H: WriteHook<K>> ConstTree<K, V, H>
Sourcepub fn compact(&self) -> DbResult<usize>
pub fn compact(&self) -> DbResult<usize>
Trigger a background compaction pass across all shards.
Sourcepub fn get_or_err(&self, key: &K) -> DbResult<[u8; V]>
pub fn get_or_err(&self, key: &K) -> DbResult<[u8; V]>
Get a value by key, returning Err(KeyNotFound) if absent.
Sourcepub fn put(&self, key: &K, value: &[u8; V]) -> DbResult<Option<[u8; V]>>
pub fn put(&self, key: &K, value: &[u8; V]) -> DbResult<Option<[u8; V]>>
Insert or update a key-value pair. Returns the old value if the key existed.
Sourcepub fn insert(&self, key: &K, value: &[u8; V]) -> DbResult<()>
pub fn insert(&self, key: &K, value: &[u8; V]) -> 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<[u8; V]>>
pub fn delete(&self, key: &K) -> DbResult<Option<[u8; V]>>
Delete a key. Returns the old value if the key existed.
Sourcepub fn atomic<R>(
&self,
shard_key: &K,
f: impl FnOnce(&mut ConstShard<'_, K, V, H>) -> DbResult<R>,
) -> DbResult<R>
pub fn atomic<R>( &self, shard_key: &K, f: impl FnOnce(&mut ConstShard<'_, K, V, 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: &[u8; V],
new_value: &[u8; V],
) -> DbResult<()>
pub fn cas( &self, key: &K, expected: &[u8; V], new_value: &[u8; V], ) -> DbResult<()>
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.
Zero I/O — values are inline in SkipList nodes.
Sourcepub fn update(
&self,
key: &K,
f: impl FnOnce(&[u8; V]) -> [u8; V],
) -> DbResult<Option<[u8; V]>>
pub fn update( &self, key: &K, f: impl FnOnce(&[u8; V]) -> [u8; V], ) -> DbResult<Option<[u8; V]>>
Atomically read-modify-write. Returns Some(new_value) if key existed, None otherwise.
Zero I/O — values are inline in SkipList nodes.
The closure must not be heavy (shard lock is held).
Sourcepub fn fetch_update(
&self,
key: &K,
f: impl FnOnce(&[u8; V]) -> [u8; V],
) -> DbResult<Option<[u8; V]>>
pub fn fetch_update( &self, key: &K, f: impl FnOnce(&[u8; V]) -> [u8; V], ) -> DbResult<Option<[u8; V]>>
Like update(), but returns Some(old_value) instead of the new one.
Sourcepub fn first(&self) -> Option<(K, [u8; V])>
pub fn first(&self) -> Option<(K, [u8; V])>
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, [u8; V])>
pub fn last(&self) -> Option<(K, [u8; V])>
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]) -> ConstIter<'_, K, V> ⓘ
pub fn prefix_iter(&self, prefix: &[u8]) -> ConstIter<'_, K, V> ⓘ
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) -> ConstIter<'_, K, V> ⓘ
pub fn iter(&self) -> ConstIter<'_, K, V> ⓘ
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) -> ConstIter<'_, K, V> ⓘ
pub fn range(&self, start: &K, end: &K) -> ConstIter<'_, K, V> ⓘ
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>,
) -> ConstIter<'_, K, V> ⓘ
pub fn range_bounds( &self, start: Bound<&K>, end: Bound<&K>, ) -> ConstIter<'_, K, V> ⓘ
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, &[u8; V]) -> MigrateAction<[u8; V]>,
) -> DbResult<usize>
pub fn migrate( &self, f: impl Fn(&K, &[u8; V]) -> MigrateAction<[u8; V]>, ) -> DbResult<usize>
Iterate all entries and optionally mutate them. Call once at startup.
The callback receives each (key, value) and returns MigrateAction:
Keep— no change (fireson_initifNEEDS_INIT)Update(new_value)— replace value (fireson_init, hook-free write)Delete— remove entry (hook-free delete, noon_init)
on_write is never fired during migration.
Returns the number of mutated entries.
pub fn shard_for(&self, key: &K) -> usize
Trait Implementations§
Source§impl<K: Key, const V: usize, H: WriteHook<K>> CompactionIndex<K> for ConstTree<K, V, H>
impl<K: Key, const V: usize, H: WriteHook<K>> CompactionIndex<K> for ConstTree<K, V, 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
Source§impl<K: Key, const V: usize, H: WriteHook<K>> ReplicationTarget for ConstTree<K, V, H>
Available on crate feature replication only.
impl<K: Key, const V: usize, H: WriteHook<K>> ReplicationTarget for ConstTree<K, V, H>
replication only.Source§fn apply_entry(
&self,
shard_id: u8,
file_id: u32,
entry_offset: u64,
header: &EntryHeader,
key: &[u8],
value: &[u8],
) -> DbResult<()>
fn apply_entry( &self, shard_id: u8, file_id: u32, entry_offset: u64, header: &EntryHeader, key: &[u8], value: &[u8], ) -> DbResult<()>
Source§fn try_apply_entry(
&self,
shard_id: u8,
file_id: u32,
entry_offset: u64,
header: &EntryHeader,
raw_after_header: &[u8],
) -> DbResult<bool>
fn try_apply_entry( &self, shard_id: u8, file_id: u32, entry_offset: u64, header: &EntryHeader, raw_after_header: &[u8], ) -> DbResult<bool>
Auto Trait Implementations§
impl<K, const V: usize, H = NoHook> !Freeze for ConstTree<K, V, H>
impl<K, const V: usize, H = NoHook> !RefUnwindSafe for ConstTree<K, V, H>
impl<K, const V: usize, H> Send for ConstTree<K, V, H>
impl<K, const V: usize, H> Sync for ConstTree<K, V, H>
impl<K, const V: usize, H> Unpin for ConstTree<K, V, H>where
H: Unpin,
impl<K, const V: usize, H> UnsafeUnpin for ConstTree<K, V, H>where
H: UnsafeUnpin,
impl<K, const V: usize, H = NoHook> !UnwindSafe for ConstTree<K, V, 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