pub struct Tree(/* private fields */);Expand description
A log-structured merge tree (LSM-tree/LSMT)
Implementations§
Source§impl Tree
impl Tree
Sourcepub fn scan_since_seqno(
&self,
target_seqno: SeqNo,
) -> Result<impl Iterator<Item = ScanSinceEvent> + use<>>
pub fn scan_since_seqno( &self, target_seqno: SeqNo, ) -> Result<impl Iterator<Item = ScanSinceEvent> + use<>>
Iterate change events with seqno >= target_seqno.
Returns every change committed at or after target_seqno as a stream
of ScanSinceEvents in increasing seqno order. This is the canonical
change-data-capture primitive: a downstream consumer (replica, Kafka
connector, Debezium-style pipeline) replays the events in order to
reconstruct the source’s history. Superseded versions are not collapsed
(a key written three times after the target yields three events).
§Block-skip
On SSTs written with the seqno_bounds section (seqno_in_index), data
blocks whose bounds cannot overlap the target window are skipped without
being read; SSTs without the section are read and filtered per entry, so
mixed trees are handled transparently.
§KV-separation
Standard trees never store blob-indirected values. On the inner tree of
a KV-separated (blob) tree this returns an Err for indirected entries:
blob resolution into ScanSinceEvent::Insert is provided by the
blob-tree scan path, which owns the blob files.
§Corruption resilience
The per-block seqno-bounds used for skipping live in the optional
seqno_bounds SST section, a Block covered by XXH3-128 (+ optional Page
ECC) and verified when it is loaded at open, plus a decode that rejects
non-ascending offsets and inverted bounds, so a corrupted bound is caught
rather than trusted. Even in the impossible case of a fault bypassing
those checks, a bad bound can only cause a missed record, never a wrong
one. Callers who want defense against that hypothetical can use
Self::scan_since_seqno_full_scan, which reads every block (slower, no
skip).
§Panics
Panics if the internal version-history lock is poisoned.
§Errors
Returns Err if reading the index or a data block fails, or if an entry
is a KV-separated value (see above).
Sourcepub fn scan_since_seqno_full_scan(
&self,
target_seqno: SeqNo,
) -> Result<impl Iterator<Item = ScanSinceEvent> + use<>>
pub fn scan_since_seqno_full_scan( &self, target_seqno: SeqNo, ) -> Result<impl Iterator<Item = ScanSinceEvent> + use<>>
Paranoid variant of Self::scan_since_seqno that disables the
per-block seqno-bounds skip: every data block is read and filtered per
entry, even on seqno-indexed SSTs.
§When to use
The fast Self::scan_since_seqno trusts each block’s recorded
[seqno_min, seqno_max] to skip blocks that cannot hold a qualifying
record. Those bounds live in the seqno_bounds SST section, a Block
covered by XXH3-128 (and optional Page ECC) and verified at open, so
on-disk corruption is caught, not silently trusted. This method exists
for callers who
want defense even against a fault that somehow bypassed those checks: a
corrupted seqno_max can only ever cause a missed record (never a
wrong one), and a full scan cannot miss. It is slower (no skip), so
prefer Self::scan_since_seqno unless you specifically need this
guarantee.
§Panics
Panics if the internal version-history lock is poisoned.
§Errors
Same as Self::scan_since_seqno.
Sourcepub fn update_runtime_config<F>(&self, mutator: F) -> Result<()>where
F: FnOnce(&mut RuntimeConfig),
pub fn update_runtime_config<F>(&self, mutator: F) -> Result<()>where
F: FnOnce(&mut RuntimeConfig),
Update the live crate::runtime_config::RuntimeConfig.
Mutator runs on a clone of the current snapshot; the new snapshot
is then atomically swapped in. Subsequent calls to
Self::runtime_config observe the new snapshot.
§Current scope
This API ships the snapshot + atomic-swap mechanism. No write
path in the current tree consults runtime_config yet — that
wiring lands with the V5-batch format features (manifest
hardening, per-KV protection, scan-since-seqno) which extend
RuntimeConfig with
their own fields and read it at block write / manifest commit /
compaction boundaries.
§Designed semantics (effective once wired by V5 features)
- Subsequent write paths load the new snapshot lockless on their next operation.
- Existing on-disk data remains in its original format and reads transparently — every block / manifest is self-describing via its own header.
- Compaction acts as the live-migration mechanism: source blocks are rewritten per the current snapshot over subsequent cycles, so all data converges to the current settings without stop-the-world coordination.
§Concurrency
Reader atomicity: concurrent readers observe either the old or the new snapshot, never a torn intermediate state.
Writer semantics: last-writer-wins. Two update calls racing
from the same starting snapshot will have the second store
overwrite the first — the first writer’s mutation is lost. There
is no CAS / RCU merge. Callers that need lost-update avoidance
(e.g. two threads concurrently toggling different fields) MUST
serialize their update_runtime_config calls, typically via a
Mutex around the call site.
§Errors
Returns crate::Error::PageEccUnsupported when the mutator
leaves page_ecc = true on a binary built without the
page_ecc cargo feature. The live snapshot stays at its
pre-mutation value on error.
Sourcepub fn runtime_config(&self) -> Arc<RuntimeConfig> ⓘ
pub fn runtime_config(&self) -> Arc<RuntimeConfig> ⓘ
Snapshot of the current runtime config. Cheap atomic load — safe to call on hot paths.
Sourcepub fn heal_hints(&self) -> Arc<HealHints> ⓘ
pub fn heal_hints(&self) -> Arc<HealHints> ⓘ
Shared handle to this tree’s ECC heal-hint queue.
A read that recovers a block from Page-ECC parity records the owning SST
here (when the on-disk fault is confirmed persistent). Pass the handle to
compaction::EccHeal and run that strategy
via Tree::compact — leader-only in a
clustered deployment — to rewrite the flagged SSTs clean. Check
HealHints::is_empty to skip
the pass when nothing is queued.
§Examples
use lsm_tree::{AbstractTree, AnyTree, Config, SequenceNumberCounter, compaction::EccHeal};
use std::sync::Arc;
let AnyTree::Standard(tree) = Config::new(
"/tmp/db",
SequenceNumberCounter::default(),
SequenceNumberCounter::default(),
)
.open()?
else {
return Ok(());
};
// Opt into rewrite scheduling; reads that recover a block from parity now
// flag its SST for healing.
tree.update_runtime_config(|c| c.auto_heal = true)?;
// Drain the queue, rewriting each flagged SST clean (leader-only in a
// clustered deployment).
let hints = tree.heal_hints();
while !hints.is_empty() {
tree.compact(Arc::new(EccHeal::new(tree.heal_hints(), u64::MAX)), 0)?;
}Trait Implementations§
Source§impl AbstractTree for Tree
impl AbstractTree for Tree
Source§fn tombstone_count(&self) -> u64
fn tombstone_count(&self) -> u64
Returns the number of tombstones in the tree.
Source§fn weak_tombstone_count(&self) -> u64
fn weak_tombstone_count(&self) -> u64
Returns the number of weak tombstones (single deletes) in the tree.
Source§fn weak_tombstone_reclaimable_count(&self) -> u64
fn weak_tombstone_reclaimable_count(&self) -> u64
Returns the number of value entries that become reclaimable once weak tombstones can be GC’d.
Source§fn table_file_cache_size(&self) -> usize
fn table_file_cache_size(&self) -> usize
Source§fn blob_file_count(&self) -> usize
fn blob_file_count(&self) -> usize
Source§fn create_checkpoint(&self, target_path: &Path) -> Result<CheckpointInfo>
fn create_checkpoint(&self, target_path: &Path) -> Result<CheckpointInfo>
target_path for point-in-time recovery (PITR) backup. Read moreSource§fn storage_stats(&self) -> Result<StorageStats>
fn storage_stats(&self) -> Result<StorageStats>
StorageStats::estimated_remaining_entries). Read moreSource§fn write_admission(&self) -> Result<()>
fn write_admission(&self) -> Result<()>
Ok(()) if a write may proceed, or
Error::StorageFull if the tree is
over budget and should be treated as read-only. Read moreSource§fn write_backpressure(&self, strategy: &dyn CompactionStrategy) -> Backpressure
fn write_backpressure(&self, strategy: &dyn CompactionStrategy) -> Backpressure
RuntimeConfig::backpressure
thresholds. Read moreSource§fn get_flush_lock(&self) -> MutexGuard<'_, ()>
fn get_flush_lock(&self) -> MutexGuard<'_, ()>
Tree::flush.Source§fn cache_stats(&self) -> CacheStats
fn cache_stats(&self) -> CacheStats
CacheStats snapshot of block-cache
effectiveness (cumulative hit / miss counts and rate) and occupancy
(current size against capacity). Read moreSource§fn version_free_list_len(&self) -> usize
fn version_free_list_len(&self) -> usize
Source§fn prefix<K: AsRef<[u8]>>(
&self,
prefix: K,
seqno: SeqNo,
index: Option<(Arc<Memtable>, SeqNo)>,
) -> Box<dyn DoubleEndedIterator<Item = IterGuardImpl> + Send + 'static>
fn prefix<K: AsRef<[u8]>>( &self, prefix: K, seqno: SeqNo, index: Option<(Arc<Memtable>, SeqNo)>, ) -> Box<dyn DoubleEndedIterator<Item = IterGuardImpl> + Send + 'static>
Source§fn range<K: AsRef<[u8]>, R: RangeBounds<K>>(
&self,
range: R,
seqno: SeqNo,
index: Option<(Arc<Memtable>, SeqNo)>,
) -> Box<dyn DoubleEndedIterator<Item = IterGuardImpl> + Send + 'static>
fn range<K: AsRef<[u8]>, R: RangeBounds<K>>( &self, range: R, seqno: SeqNo, index: Option<(Arc<Memtable>, SeqNo)>, ) -> Box<dyn DoubleEndedIterator<Item = IterGuardImpl> + Send + 'static>
Source§fn range_seekable<K: AsRef<[u8]>, R: RangeBounds<K>>(
&self,
range: R,
seqno: SeqNo,
index: Option<(Arc<Memtable>, SeqNo)>,
) -> Box<dyn SeekableGuardIter + 'static>
fn range_seekable<K: AsRef<[u8]>, R: RangeBounds<K>>( &self, range: R, seqno: SeqNo, index: Option<(Arc<Memtable>, SeqNo)>, ) -> Box<dyn SeekableGuardIter + 'static>
Source§fn batch_range_scan<K: AsRef<[u8]>, R: RangeBounds<K> + 'static, I: IntoIterator<Item = R>>(
&self,
intervals: I,
seqno: SeqNo,
index: Option<(Arc<Memtable>, SeqNo)>,
) -> Box<dyn Iterator<Item = IterGuardImpl> + Send + 'static>
fn batch_range_scan<K: AsRef<[u8]>, R: RangeBounds<K> + 'static, I: IntoIterator<Item = R>>( &self, intervals: I, seqno: SeqNo, index: Option<(Arc<Memtable>, SeqNo)>, ) -> Box<dyn Iterator<Item = IterGuardImpl> + Send + 'static>
Source§fn drop_range<K: AsRef<[u8]>, R: RangeBounds<K>>(&self, range: R) -> Result<()>
fn drop_range<K: AsRef<[u8]>, R: RangeBounds<K>>(&self, range: R) -> Result<()>
Source§fn l0_run_count(&self) -> usize
fn l0_run_count(&self) -> usize
Source§fn size_of<K: AsRef<[u8]>>(&self, key: K, seqno: SeqNo) -> Result<Option<u32>>
fn size_of<K: AsRef<[u8]>>(&self, key: K, seqno: SeqNo) -> Result<Option<u32>>
Source§fn filter_size(&self) -> u64
fn filter_size(&self) -> u64
Source§fn pinned_filter_size(&self) -> usize
fn pinned_filter_size(&self) -> usize
Source§fn pinned_block_index_size(&self) -> usize
fn pinned_block_index_size(&self) -> usize
Source§fn sealed_memtable_count(&self) -> usize
fn sealed_memtable_count(&self) -> usize
Source§fn register_tables(
&self,
tables: &[Table],
blob_files: Option<&[BlobFile]>,
frag_map: Option<FragmentationMap>,
sealed_memtables_to_delete: &[MemtableId],
gc_watermark: SeqNo,
) -> Result<()>
fn register_tables( &self, tables: &[Table], blob_files: Option<&[BlobFile]>, frag_map: Option<FragmentationMap>, sealed_memtables_to_delete: &[MemtableId], gc_watermark: SeqNo, ) -> Result<()>
Source§fn clear_active_memtable(&self)
fn clear_active_memtable(&self)
Source§fn compact(
&self,
strategy: Arc<dyn CompactionStrategy>,
seqno_threshold: SeqNo,
) -> Result<CompactionResult>
fn compact( &self, strategy: Arc<dyn CompactionStrategy>, seqno_threshold: SeqNo, ) -> Result<CompactionResult>
Source§fn get_next_table_id(&self) -> TableId
fn get_next_table_id(&self) -> TableId
Source§fn tree_config(&self) -> &Config
fn tree_config(&self) -> &Config
Source§fn table_count(&self) -> usize
fn table_count(&self) -> usize
Source§fn level_table_count(&self, idx: usize) -> Option<usize>
fn level_table_count(&self, idx: usize) -> Option<usize>
levels[idx]. Read moreSource§fn approximate_len(&self) -> usize
fn approximate_len(&self) -> usize
Source§fn disk_space(&self) -> u64
fn disk_space(&self) -> u64
Source§fn approximate_range_stats<K: AsRef<[u8]>, R: RangeBounds<K>>(
&self,
range: R,
seqno: SeqNo,
) -> Result<ApproximateRangeStats>
fn approximate_range_stats<K: AsRef<[u8]>, R: RangeBounds<K>>( &self, range: R, seqno: SeqNo, ) -> Result<ApproximateRangeStats>
range at
seqno, WITHOUT reading any data block. Read moreSource§fn approximate_range_cardinality<K: AsRef<[u8]>, R: RangeBounds<K>>(
&self,
range: R,
seqno: SeqNo,
) -> Result<RangeCardinality>
fn approximate_range_cardinality<K: AsRef<[u8]>, R: RangeBounds<K>>( &self, range: R, seqno: SeqNo, ) -> Result<RangeCardinality>
range at seqno,
WITHOUT reading any data block. Read moreSource§fn get_highest_memtable_seqno(&self) -> Option<SeqNo>
fn get_highest_memtable_seqno(&self) -> Option<SeqNo>
Source§fn get_highest_persisted_seqno(&self) -> Option<SeqNo>
fn get_highest_persisted_seqno(&self) -> Option<SeqNo>
Source§fn get<K: AsRef<[u8]>>(&self, key: K, seqno: SeqNo) -> Result<Option<UserValue>>
fn get<K: AsRef<[u8]>>(&self, key: K, seqno: SeqNo) -> Result<Option<UserValue>>
Source§fn get_pinned<K: AsRef<[u8]>>(
&self,
key: K,
seqno: SeqNo,
) -> Result<Option<PinnableSlice>>
fn get_pinned<K: AsRef<[u8]>>( &self, key: K, seqno: SeqNo, ) -> Result<Option<PinnableSlice>>
PinnableSlice. Read moreSource§fn multi_get<K: AsRef<[u8]>>(
&self,
keys: impl IntoIterator<Item = K>,
seqno: SeqNo,
) -> Result<Vec<Option<UserValue>>>
fn multi_get<K: AsRef<[u8]>>( &self, keys: impl IntoIterator<Item = K>, seqno: SeqNo, ) -> Result<Vec<Option<UserValue>>>
Source§fn apply_batch(&self, batch: WriteBatch, seqno: SeqNo) -> Result<(u64, u64)>
fn apply_batch(&self, batch: WriteBatch, seqno: SeqNo) -> Result<(u64, u64)>
WriteBatch with the given sequence number. Read moreSource§fn insert<K: Into<UserKey>, V: Into<UserValue>>(
&self,
key: K,
value: V,
seqno: SeqNo,
) -> (u64, u64)
fn insert<K: Into<UserKey>, V: Into<UserValue>>( &self, key: K, value: V, seqno: SeqNo, ) -> (u64, u64)
Source§fn merge<K: Into<UserKey>, V: Into<UserValue>>(
&self,
key: K,
operand: V,
seqno: SeqNo,
) -> (u64, u64)
fn merge<K: Into<UserKey>, V: Into<UserValue>>( &self, key: K, operand: V, seqno: SeqNo, ) -> (u64, u64)
Source§fn remove<K: Into<UserKey>>(&self, key: K, seqno: SeqNo) -> (u64, u64)
fn remove<K: Into<UserKey>>(&self, key: K, seqno: SeqNo) -> (u64, u64)
Source§fn remove_range<K: Into<UserKey>>(&self, start: K, end: K, seqno: SeqNo) -> u64
fn remove_range<K: Into<UserKey>>(&self, start: K, end: K, seqno: SeqNo) -> u64
[start, end) by inserting a range tombstone. Read moreSource§fn level_segment_stats(&self) -> Result<Vec<LevelStats>>
fn level_segment_stats(&self) -> Result<Vec<LevelStats>>
Source§fn compaction_debt(&self, strategy: &dyn CompactionStrategy) -> u64
fn compaction_debt(&self, strategy: &dyn CompactionStrategy) -> u64
strategy: on-disk data above
its level’s target that must eventually be rewritten downward (a RocksDB
estimate-pending-compaction-bytes analog), a compaction-debt signal for a
scheduler / tiering consumer. Read moreSource§fn is_read_only(&self) -> bool
fn is_read_only(&self) -> bool
true when the admission gate is currently closed (see
write_admission). Convenience for callers that
want a boolean rather than a Result. Always false unless admission
control is enabled and the tree is over budget. Read moreSource§fn verify_checksum(&self) -> BlockVerifyReportwhere
Self: Sized,
fn verify_checksum(&self) -> BlockVerifyReportwhere
Self: Sized,
Source§fn verify_checksum_with(&self, options: &VerifyOptions) -> BlockVerifyReportwhere
Self: Sized,
fn verify_checksum_with(&self, options: &VerifyOptions) -> BlockVerifyReportwhere
Self: Sized,
Self::verify_checksum but with configurable parallelism and
I/O throttle (see VerifyOptions).Source§fn flush(
&self,
_lock: &MutexGuard<'_, ()>,
seqno_threshold: SeqNo,
) -> Result<Option<u64>>
fn flush( &self, _lock: &MutexGuard<'_, ()>, seqno_threshold: SeqNo, ) -> Result<Option<u64>>
Source§fn iter(
&self,
seqno: SeqNo,
index: Option<(Arc<Memtable>, SeqNo)>,
) -> Box<dyn DoubleEndedIterator<Item = IterGuardImpl> + Send + 'static>
fn iter( &self, seqno: SeqNo, index: Option<(Arc<Memtable>, SeqNo)>, ) -> Box<dyn DoubleEndedIterator<Item = IterGuardImpl> + Send + 'static>
Source§fn major_compact(
&self,
target_size: u64,
seqno_threshold: SeqNo,
) -> Result<CompactionResult>
fn major_compact( &self, target_size: u64, seqno_threshold: SeqNo, ) -> Result<CompactionResult>
Source§fn stale_blob_bytes(&self) -> u64
fn stale_blob_bytes(&self) -> u64
Source§fn flush_to_tables(
&self,
stream: impl Iterator<Item = Result<InternalValue>>,
) -> Result<Option<(Vec<Table>, Option<Vec<BlobFile>>)>>
fn flush_to_tables( &self, stream: impl Iterator<Item = Result<InternalValue>>, ) -> Result<Option<(Vec<Table>, Option<Vec<BlobFile>>)>>
Source§fn get_highest_seqno(&self) -> Option<SeqNo>
fn get_highest_seqno(&self) -> Option<SeqNo>
Source§fn len(
&self,
seqno: SeqNo,
index: Option<(Arc<Memtable>, SeqNo)>,
) -> Result<usize>
fn len( &self, seqno: SeqNo, index: Option<(Arc<Memtable>, SeqNo)>, ) -> Result<usize>
Source§fn is_empty(
&self,
seqno: SeqNo,
index: Option<(Arc<Memtable>, SeqNo)>,
) -> Result<bool>
fn is_empty( &self, seqno: SeqNo, index: Option<(Arc<Memtable>, SeqNo)>, ) -> Result<bool>
true if the tree is empty. Read moreSource§fn first_key_value(
&self,
seqno: SeqNo,
index: Option<(Arc<Memtable>, SeqNo)>,
) -> Option<IterGuardImpl>
fn first_key_value( &self, seqno: SeqNo, index: Option<(Arc<Memtable>, SeqNo)>, ) -> Option<IterGuardImpl>
Source§fn last_key_value(
&self,
seqno: SeqNo,
index: Option<(Arc<Memtable>, SeqNo)>,
) -> Option<IterGuardImpl>
fn last_key_value( &self, seqno: SeqNo, index: Option<(Arc<Memtable>, SeqNo)>, ) -> Option<IterGuardImpl>
Source§fn contains_key<K: AsRef<[u8]>>(&self, key: K, seqno: SeqNo) -> Result<bool>
fn contains_key<K: AsRef<[u8]>>(&self, key: K, seqno: SeqNo) -> Result<bool>
true if the tree contains the specified key. Read moreSource§fn contains_prefix<K: AsRef<[u8]>>(
&self,
prefix: K,
seqno: SeqNo,
index: Option<(Arc<Memtable>, SeqNo)>,
) -> Result<bool>
fn contains_prefix<K: AsRef<[u8]>>( &self, prefix: K, seqno: SeqNo, index: Option<(Arc<Memtable>, SeqNo)>, ) -> Result<bool>
true if the tree contains any key with the given prefix. Read moreSource§fn try_insert<K: Into<UserKey>, V: Into<UserValue>>(
&self,
key: K,
value: V,
seqno: SeqNo,
) -> Result<(u64, u64)>
fn try_insert<K: Into<UserKey>, V: Into<UserValue>>( &self, key: K, value: V, seqno: SeqNo, ) -> Result<(u64, u64)>
insert: consults
write_admission first and declines with
Error::StorageFull when the tree is over
budget, otherwise inserts and returns the same (added_bytes, memtable_size) tuple. This is the write entry a space-aware caller uses
so over-budget writes are refused up front rather than failing a flush
later; bare insert stays infallible for callers that
do not opt into admission control. Read moreSource§fn try_merge<K: Into<UserKey>, V: Into<UserValue>>(
&self,
key: K,
operand: V,
seqno: SeqNo,
) -> Result<(u64, u64)>
fn try_merge<K: Into<UserKey>, V: Into<UserValue>>( &self, key: K, operand: V, seqno: SeqNo, ) -> Result<(u64, u64)>
Auto Trait Implementations§
impl !RefUnwindSafe for Tree
impl !UnwindSafe for Tree
impl Freeze for Tree
impl Send for Tree
impl Sync for Tree
impl Unpin for Tree
impl UnsafeUnpin for Tree
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
impl<ST, DT> CastableFrom<ST, Initialized, Initialized> for DT
impl<ST, DT> CastableFrom<ST, Uninit, Uninit> for DT
Source§impl<T> CloneToUninit for Twhere
T: Clone,
impl<T> CloneToUninit for Twhere
T: Clone,
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 moreSource§impl<T> Pointable for T
impl<T> Pointable for T
impl<T> Read<Exclusive, BecauseExclusive> for Twhere
T: ?Sized,
Source§impl<T> StorageStatistics for Twhere
T: AbstractTree + ?Sized,
impl<T> StorageStatistics for Twhere
T: AbstractTree + ?Sized,
Source§fn storage_stats(&self) -> Result<StorageStats, Error>
fn storage_stats(&self) -> Result<StorageStats, Error>
StorageStatus. See
StorageStats::estimated_remaining_entries for a budget projection. Read moreSource§fn level_segment_stats(&self) -> Result<Vec<LevelStats>, Error>
fn level_segment_stats(&self) -> Result<Vec<LevelStats>, Error>
Source§fn compaction_debt(&self, strategy: &dyn CompactionStrategy) -> u64
fn compaction_debt(&self, strategy: &dyn CompactionStrategy) -> u64
strategy: on-disk data above
its level’s target that must eventually be rewritten downward (a RocksDB
estimate-pending-compaction-bytes analog), a compaction-debt signal for a
scheduler / tiering consumer. Read moreSource§fn cache_stats(&self) -> CacheStats
fn cache_stats(&self) -> CacheStats
CacheStats snapshot of block-cache
effectiveness (cumulative hit / miss counts and rate) and occupancy
(current size against capacity). Read more