Skip to main content

Tree

Struct Tree 

Source
pub struct Tree(/* private fields */);
Expand description

A log-structured merge tree (LSM-tree/LSMT)

Clones share one tree. Background work of the tree (the table file pool, the file deleter) may still touch its directory after a handle drops; to remove the directory, close the tree and wait for the returned TreeClose: once it fires, the tree writes nothing into its directory any more.

Implementations§

Source§

impl Tree

Source

pub fn columnar_scan<R: RangeBounds<UserKey>>( &self, projection: impl Into<Projection>, predicate: Option<&ColumnRangePredicate>, seqno: SeqNo, range: R, ) -> Result<ColumnarScan>

Runs a projected columnar scan across the whole tree.

Reads every source intersecting range at snapshot seqno: the memtables, the row-oriented tables and the columnar ones. It applies deletions and range tombstones from any source to the keys of every other, resolves merge chains as a read does, applies the optional predicate (zone-map block-skip + row filter, after the newest version of each key is chosen) and yields projected [ColumnBatch]es in ascending key order, one row per key: its newest visible version. A columnar segment no other source overlaps streams without merge overhead.

range bounds the result at row granularity: a segment that only partially overlaps range contributes only the rows whose keys fall inside it (the inclusive / exclusive sense of each bound is honored). A fully unbounded range keeps the zero-copy fast path for an all-visible segment.

projection names the columns each batch carries, in its order: column ids (the intrinsic [COL_USER_KEY] / seqno / value-type columns, or a value column typed by what the tables store), converted from a slice of ids, or a Projection of declared fields, which says what a field a row lacks reads as and carries the projector the fields are read out of whole values through. Every other column of a columnar table is stepped over without decoding.

§Errors

Returns Error::Projection when the projection names one column id twice or the highest id, and, lazily, while iterating, when a row returned stores its value whole and no projector is set to read its declared fields, or when the data does not satisfy the projection. Returns an error on a block read or decode failure, or on a failed point read resolving a merge chain.

§Examples
use lsm_tree::table::columnar::COL_USER_KEY;
use lsm_tree::{AbstractTree, Config, SeqNo};

let folder = tempfile::tempdir()?;
let tree = Config::new(folder, Default::default(), Default::default()).open()?;
// Rows in the memtable are read like any other source.
tree.insert("a", "1", 0);
tree.insert("b", "2", 1);
let rows: u32 = tree
    .columnar_scan(&[COL_USER_KEY], None, SeqNo::MAX, ..)?
    .map(|batch| batch.map(|b| b.row_count))
    .sum::<lsm_tree::Result<u32>>()?;
assert_eq!(rows, 2);
Source§

impl Tree

Source

pub fn downgrade(&self) -> WeakTree

A handle that does not keep the tree open; see WeakTree.

Source

pub fn close(self) -> TreeClose

Gives up this handle and returns the signal of the tree being closed.

The tree is closed once nothing of it owns a file of its directory or works in it any more: other strong handles, iterators, snapshots and pins keep it open until they drop, and the table file pool and the background deleter finish what they started. Once closed, the tree writes nothing into its directory and removing the directory is safe.

From this call on no WeakTree raises the tree again; strong handles already held keep working until dropped.

§Examples
use lsm_tree::{AbstractTree, AnyTree};

let AnyTree::Standard(tree) = lsm_tree::Config::new(
    folder.path(),
    lsm_tree::SequenceNumberCounter::default(),
    lsm_tree::SequenceNumberCounter::default(),
)
.open()?
else {
    unreachable!("no key-value separation configured");
};
let monitor = tree.downgrade();

let closed = tree.close();
assert!(monitor.upgrade().is_none());
closed.wait();
std::fs::remove_dir_all(folder.path())?;
Source§

impl Tree

Source

pub fn register_zstd_dictionary(&self, dict: Arc<ZstdDictionary>) -> Result<()>

Stores dict in the tree and records it in the current version, so it resolves after a reopen with no dictionary supplied in the config.

Additive: tables already written keep resolving to the dictionary they were written against, which is what makes it safe to introduce a dictionary on a tree that already holds data, and to replace one (both are this same operation). Registering an id the tree already holds is a no-op, since the id is derived from the bytes.

The file is written BEFORE the version edit that references it. The other order would publish an id whose bytes a crash could still lose, and the tables written against it would then fail to open; this order can only leave an unreferenced file, which the next collection removes.

Both steps happen under the version lock, which is what serializes this against Self::collect_unreferenced_dictionaries. Taking the lock only for the edit would leave the file published in the window the collector scans, and it would be unlinked as an orphan before the edit that names it ever landed.

§Errors

Propagates the store’s write failures and the version install’s.

Source

pub fn zstd_dictionaries(&self) -> ZstdDictionaries

The dictionaries this tree can decompress against, as of this call.

Source

pub fn collect_unreferenced_dictionaries(&self) -> Result<usize>

Drops every dictionary nothing references any more, returning how many files were removed.

The current version first stops REGISTERING an id nothing references (a version edit, costing an install and nothing on disk), and the file goes in the same pass once the installed version no longer names it. A reader still holding an older version is unaffected: its tables and blob files pinned their dictionaries when they were opened.

REFERENCED means both directions: the files that already exist (tables and blob files alike), and the ids the compression policies name for what is written next. Counting only the first would unregister a dictionary before its first table is written, and nothing puts the id back afterwards, so a later pass would unlink the file while live tables are compressed against it. What is written next includes the writers already running: a flush or compaction started under a policy Self::update_runtime_config has since replaced still writes against the dictionary that policy named, so it is spared until their files are installed and name it themselves.

The whole pass holds the version lock. Registration takes the same lock before it writes anything, so the two cannot interleave: without that, a registration’s file could land between this scan and its removals and be unlinked as an orphan while the edit naming it was still to come.

§Errors

Propagates the version install and the store’s removal failures.

Source

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).

§Concurrency

The result is a snapshot of the tree as of the call: the active memtable is captured with writers excluded, so a batch committed concurrently is either wholly in the result or wholly absent, never split across it. This holds even for a caller-chosen sequence number at or below the reported watermark, which the seqno bound alone would not exclude. Writers are blocked only while that capture runs — the sealed memtables and SSTs the scan then reads are immutable.

§History retention

The stream carries what the tree still PHYSICALLY HOLDS. A compaction run with a GC watermark (the gc_watermark passed to compact / major_compact) drops shadowed versions and evicted tombstones below that watermark and may fold merge chains and zero bottommost seqnos — history a later scan cannot resurrect. The result is therefore complete only for a target_seqno at or above the highest GC watermark ever applied: a deployment replaying this stream (an external-WAL consumer, a CDC replica) must keep its compaction watermark at or below the lowest cursor it may still rewind to, exactly as docs/external-wal.md section 4’s GC-coordination rules require. The watermark is caller-supplied and not persisted, so this method cannot detect a violation for you.

§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).

Source

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.

Source

pub fn scan_since_seqno_in_range<K: AsRef<[u8]>, R: RangeBounds<K>>( &self, target_seqno: SeqNo, range: R, ) -> Result<impl Iterator<Item = ScanSinceEvent> + use<K, R>>

Range-scoped variant of Self::scan_since_seqno: delivers only events whose key falls within range (in the tree comparator’s order); range-deletion events are delivered when their span OVERLAPS it, since a tombstone reaching into the range affects replay within it. SSTs whose key range cannot intersect the bounds are skipped without a single block read.

This is the presence-check primitive for reconciling an external write-ahead log after a repair: RepairReport::lost_coverage names the affected key ranges, and deciding which retained WAL records to re-apply (in particular, which merge operands SURVIVED and must not be folded twice) only needs the events inside those ranges. See docs/external-wal.md § Replay after repair.

The history-retention caveat of Self::scan_since_seqno applies unchanged: the stream is complete only for a target_seqno at or above the highest compaction GC watermark ever applied.

§Panics

Panics if the internal version-history lock is poisoned.

§Errors

Same as Self::scan_since_seqno.

Source

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.

§Semantics
  • Write paths (flush, compaction, ingestion) take one snapshot when they start and use it throughout, so a change applies to the next one and never splits a single file between two configurations.
  • Existing on-disk data remains in its original format and reads transparently: every block, manifest and blob file is self-describing via its own header or descriptor. That includes the compression policies, so changing one rewrites nothing.
  • 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, and crate::Error::ZstdDictMismatch when a compression policy names a dictionary the tree does not hold (register it first with Self::register_zstd_dictionary). The live snapshot stays at its pre-mutation value on error.

Source

pub fn runtime_config(&self) -> Arc<RuntimeConfig> ⓘ

Snapshot of the current runtime config. Cheap atomic load — safe to call on hot paths.

Source

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)?;
}
Source

pub fn start_multi_get<K: Into<UserKey>>( &self, keys: impl IntoIterator<Item = K>, seqno: SeqNo, ) -> Result<Step>

Starts a multi-get of keys at seqno that its caller drives: the read hands out its block reads and jobs instead of carrying them out, so the calling thread is never parked inside it. It answers what AbstractTree::multi_get answers at the moment it starts: what is written while it is suspended is not part of its answer, even at a ceiling such as SeqNo::MAX.

§Errors

Returns crate::Error::SnapshotBelowRetention when seqno is below what the tree retains.

§Examples

Driving the read on the calling thread:

use lsm_tree::resumable::Step;
use lsm_tree::{AbstractTree, Config, SequenceNumberCounter};

let tree = Config::new(&folder, SequenceNumberCounter::default(), SequenceNumberCounter::default()).open()?;
tree.insert("a", "1", 0);
tree.flush_active_memtable(0)?;

let mut step = tree.start_multi_get(["a", "b"], 1)?;
let values = loop {
    let mut read = match step {
        Step::Done(values) => break values?,
        Step::Pending(read) => read,
    };
    for job in read.take_jobs() {
        let outcome = job.run();
        read.complete_job(outcome);
    }
    for mut block in read.take_reads() {
        let result = block.file.read_at(&mut block.buf, block.offset).and_then(|n| {
            if n == block.buf.len() { Ok(()) } else { Err(lsm_tree::io::ErrorKind::UnexpectedEof.into()) }
        });
        read.complete_read(block.tag, result, block.buf);
    }
    step = read.resume();
};
assert_eq!(values, [Some("1".as_bytes().into()), None]);

Trait Implementations§

Source§

impl AbstractTree for Tree

Source§

fn tombstone_count(&self) -> u64

Returns the number of tombstones in the tree.

Source§

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

Returns the number of value entries that become reclaimable once weak tombstones can be GC’d.

Source§

fn table_file_cache_size(&self) -> usize

Returns the number of cached table file descriptors.
Source§

fn persist_flushes(&self) -> Result<()>

Makes every flush installed before this call durable, under FlushDurability::Deferred: the tables and blob files those flushes wrote are synced, then their folders, then the manifest is written. Once it returns Ok a caller may drop its own log up to the writes those flushes held; under SyncMode::Barrier after sync_devices as well. A no-op when nothing is pending, and under FlushDurability::Synced every flush is durable when it returns. Read more
Source§

fn blob_file_count(&self) -> usize

Returns the number of blob files currently in the tree.
Source§

fn create_checkpoint(&self, target_path: &Path) -> Result<CheckpointInfo>

Creates a hard-linked checkpoint of the tree’s on-disk state in target_path for point-in-time recovery (PITR) backup. Read more
Source§

fn pin(&self) -> PinnedVersion

Pins the tree’s current state for a point-in-time copy that costs no file I/O: seals the active memtable and returns a PinnedVersion holding the sealed memtables, tables, blob files and dictionaries as they are now. Read more
Source§

fn acknowledge_repair_report(&self, id: u128) -> Result<bool>

Stops the tree owing the repair report with this RepairReport::id, installing a version that no longer carries it: no later Config::open_or_repair hands it out. Read more
Source§

fn storage_stats(&self) -> Result<StorageStats>

Returns a read-only snapshot of the tree’s on-disk storage footprint: total used bytes, entry count, the average shape of a stored entry (average key / value bytes), and an estimate of how many more average-shaped entries fit in a byte budget (see StorageStats::estimated_remaining_entries). Read more
Source§

fn write_admission(&self) -> Result<()>

Storage admission gate: Ok(()) if a write may proceed, or Error::StorageFull if the tree is over budget and should be treated as read-only. Read more
Source§

fn write_backpressure(&self, strategy: &dyn CompactionStrategy) -> Backpressure

Computed write-backpressure verdict from the live L0 run count, the strategy’s pending-compaction bytes and the unflushed memtable bytes, against the configured RuntimeConfig::backpressure thresholds. Read more
Source§

fn get_flush_lock(&self) -> MutexGuard<'_, ()>

Acquires the flush lock which is required to call Tree::flush.
Source§

fn metrics(&self) -> &Arc<Metrics> ⓘ

Returns the metrics structure.
Source§

fn cache_stats(&self) -> CacheStats

A point-in-time CacheStats snapshot of block-cache effectiveness (cumulative hit / miss counts and rate) and occupancy (current size against capacity). Read more
Source§

fn prefix<K: AsRef<[u8]>>( &self, prefix: K, seqno: SeqNo, index: Option<(Arc<Memtable>, SeqNo)>, ) -> Box<dyn DoubleEndedIterator<Item = IterGuardImpl> + Send + 'static>

Returns an iterator over a prefixed set of items. Read more
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>

Returns an iterator over a range of items. Read more
Source§

fn range_seekable<K: AsRef<[u8]>, R: RangeBounds<K>>( &self, range: R, seqno: SeqNo, index: Option<(Arc<Memtable>, SeqNo)>, ) -> Box<dyn SeekableGuardIter + 'static>

Returns a range iterator that can reposition (seek) in place without reopening its per-SST readers. Read more
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>
where I::IntoIter: Send + 'static,

Scans a sequence of disjoint, ascending key sub-intervals, reusing one set of per-SST readers across all of them. Read more
Source§

fn clear(&self) -> Result<()>

Drops all tables and clears all memtables atomically. Read more
Source§

fn l0_run_count(&self) -> usize

Returns the number of disjoint runs in L0. Read more
Source§

fn size_of<K: AsRef<[u8]>>(&self, key: K, seqno: SeqNo) -> Result<Option<u32>>

Returns the size of a value if it exists. Read more
Source§

fn filter_size(&self) -> u64

Gets the space usage of all filters in the tree. Read more
Source§

fn pinned_filter_size(&self) -> usize

Gets the memory usage of all pinned filters in the tree.
Source§

fn filter_memory(&self) -> FilterMemory

The serialised and the resident bytes of the tree’s filters, and how they stand against a FilterAdvisor budget. Read more
Source§

fn pinned_block_index_size(&self) -> usize

Gets the memory usage of all pinned index blocks in the tree.
Source§

fn sealed_memtable_count(&self) -> usize

Returns the number of sealed memtables.
Source§

fn register_tables( &self, tables: &[Table], blob_files: Option<&[BlobFile]>, frag_map: Option<FragmentationMap>, sealed_memtables_to_delete: &[MemtableId], gc_watermark: SeqNo, collected_below_watermark: bool, ) -> Result<()>

Atomically registers flushed tables into the tree, removing their associated sealed memtables. Read more
Source§

fn clear_active_memtable(&self)

Clears the active memtable atomically.
Source§

fn compact( &self, strategy: Arc<dyn CompactionStrategy>, gc_watermark: SeqNo, ) -> Result<CompactionResult>

Performs compaction on the tree’s levels, blocking the caller until it’s done. Read more
Source§

fn get_next_table_id(&self) -> TableId

Returns the next table’s ID.
Source§

fn tree_config(&self) -> &Config

Returns the tree config.
Source§

fn active_memtable(&self) -> Arc<Memtable> ⓘ

Returns the active memtable.
Source§

fn rotate_memtable(&self) -> Option<Arc<Memtable>>

Seals the active memtable.
Source§

fn table_count(&self) -> usize

Returns the number of tables currently in the tree.
Source§

fn level_table_count(&self, idx: usize) -> Option<usize>

Returns the number of tables in levels[idx]. Read more
Source§

fn approximate_len(&self) -> usize

Approximates the number of items in the tree.
Source§

fn disk_space(&self) -> u64

Returns the disk space usage.
Source§

fn approximate_range_stats<K: AsRef<[u8]>, R: RangeBounds<K>>( &self, range: R, seqno: SeqNo, ) -> Result<ApproximateRangeStats>

Estimates the on-disk bytes and entry count contained in range at seqno, WITHOUT reading any data block. Read more
Source§

fn approximate_range_cardinality<K: AsRef<[u8]>, R: RangeBounds<K>>( &self, range: R, seqno: SeqNo, ) -> Result<RangeCardinality>

Estimates the row cardinality and selectivity of range at seqno, WITHOUT reading any data block. Read more
Source§

fn get_highest_memtable_seqno(&self) -> Option<SeqNo>

Returns the highest sequence number of the active memtable.
Source§

fn get_highest_seqno(&self) -> Option<SeqNo>

Returns the highest sequence number.
Source§

fn get_highest_persisted_seqno(&self) -> Option<SeqNo>

Returns the highest sequence number that is flushed to disk. Read more
Source§

fn oldest_retained_seqno(&self) -> SeqNo

Returns the retention floor: the lower bound of the readable snapshot window. Read more
Source§

fn retention_floor(&self) -> SeqNo

Returns the persisted retention floor: the highest snapshot seqno the tree refuses, now and after a reopen. It always equals oldest_retained_seqno. Read more
Source§

fn lower_retention_floor(&self, floor: SeqNo) -> Result<()>

Lowers the persisted retention floor to floor, so snapshots above it are served again, now and after a reopen. Read more
Source§

fn compaction_rate_limiter(&self) -> Arc<RateLimiter> ⓘ

Returns the limiter that throttles this tree’s compactions: the one supplied through Config::compaction_rate_limiter, which other trees may share, or the tree’s own built from Config::compaction_rate_limit. Read more
Source§

fn write_rate_limiter(&self) -> Arc<RateLimiter> ⓘ

The limiter writes are paced with under backpressure slowdown: shared with other trees if one was supplied through Config::write_rate_limiter, else the tree’s own. Retune it live with RateLimiter::set_rate; 0 turns byte pacing off.
Source§

fn get<K: AsRef<[u8]>>(&self, key: K, seqno: SeqNo) -> Result<Option<UserValue>>

Retrieves an item from the tree. Read more
Source§

fn contains_key<K: AsRef<[u8]>>(&self, key: K, seqno: SeqNo) -> Result<bool>

Returns true if the tree contains the specified key. Read more
Source§

fn contains_prefix<K: AsRef<[u8]>>( &self, prefix: K, seqno: SeqNo, index: Option<(Arc<Memtable>, SeqNo)>, ) -> Result<bool>

Returns true if the tree contains any key with the given prefix. Read more
Source§

fn is_empty( &self, seqno: SeqNo, index: Option<(Arc<Memtable>, SeqNo)>, ) -> Result<bool>

Returns true if the tree is empty. Read more
Source§

fn len( &self, seqno: SeqNo, index: Option<(Arc<Memtable>, SeqNo)>, ) -> Result<usize>

Scans the entire tree, returning the number of items. Read more
Source§

fn get_pinned<K: AsRef<[u8]>>( &self, key: K, seqno: SeqNo, ) -> Result<Option<PinnableSlice>>

Retrieves an item from the tree as a PinnableSlice. Read more
Source§

fn multi_get<K: AsRef<[u8]>>( &self, keys: impl IntoIterator<Item = K>, seqno: SeqNo, ) -> Result<Vec<Option<UserValue>>>

Reads multiple keys from the tree. Read more
Source§

fn apply_batch(&self, batch: WriteBatch, seqno: SeqNo) -> Result<(u64, u64)>

Applies a WriteBatch with the given sequence number. Read more
Source§

fn insert<K: Into<UserKey>, V: Into<UserValue>>( &self, key: K, value: V, seqno: SeqNo, ) -> (u64, u64)

Inserts a key-value pair into the tree. Read more
Source§

fn merge<K: Into<UserKey>, V: Into<UserValue>>( &self, key: K, operand: V, seqno: SeqNo, ) -> (u64, u64)

Writes a merge operand for a key. Read more
Source§

fn remove<K: Into<UserKey>>(&self, key: K, seqno: SeqNo) -> (u64, u64)

Removes an item from the tree. Read more
Source§

fn remove_range<K: Into<UserKey>>(&self, start: K, end: K, seqno: SeqNo) -> u64

Deletes all keys in the range [start, end) by inserting a range tombstone. Read more
Source§

fn level_segment_stats(&self) -> Result<Vec<LevelStats>>

Per-LSM-level and per-segment size + entry-count stats, for tiering and erasure-coding placement decisions (which level / segment is large enough to demote, EC-encode, or migrate). Read more
Source§

fn compaction_debt(&self, strategy: &dyn CompactionStrategy) -> u64

Estimated bytes pending compaction under 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 more
Source§

fn write_backpressure_for( &self, strategy: &dyn CompactionStrategy, bytes: u64, ) -> Backpressure

The verdict for one write of bytes: write_backpressure, except that a slowdown on a tree with a write rate limit (see Config::write_rate_limit) debits bytes from the tree’s write limiter and suggests waiting until they, and every byte debited before them, are paid off at its rate. Writes honouring it are then bounded by the rate in bytes per second, large and small alike, however many writers share the limiter. Outside the slowdown tier nothing is debited. Read more
Source§

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 more
Source§

fn verify_checksum(&self) -> BlockVerifyReport
where Self: Sized,

Proactively verifies every block’s XXH3 checksum across every SST in the tree’s current version — a scrubber for catching bit rot before it surfaces as a user-visible read failure (cron / scrub jobs). Read more
Source§

fn verify_checksum_with(&self, options: &VerifyOptions) -> BlockVerifyReport
where Self: Sized,

Like Self::verify_checksum but with configurable parallelism and I/O throttle (see VerifyOptions).
Source§

fn flush_active_memtable(&self, gc_watermark: SeqNo) -> Result<()>

Seals the active memtable and flushes it, with every memtable sealed before it, to tables: the durability barrier for a caller that keeps its own journal of the writes. Read more
Source§

fn sync_devices(&self) -> Result<()>

Makes durable everything this tree synced on each device it lies on: the tree folder’s, that of every level’s tables, that of the dictionaries folder and, with KV separation, that of the blobs folder. Read more
Source§

fn flush( &self, _lock: &MutexGuard<'_, ()>, gc_watermark: SeqNo, ) -> Result<Option<u64>>

Synchronously flushes pending sealed memtables to tables. Read more
Source§

fn iter( &self, seqno: SeqNo, index: Option<(Arc<Memtable>, SeqNo)>, ) -> Box<dyn DoubleEndedIterator<Item = IterGuardImpl> + Send + 'static>

Returns an iterator that scans through the entire tree. Read more
Source§

fn major_compact( &self, target_size: u64, gc_watermark: SeqNo, ) -> Result<CompactionResult>

Performs major compaction, blocking the caller until it’s done. Read more
Source§

fn stale_blob_bytes(&self) -> u64

Returns the disk space used by stale blobs.
Source§

fn flush_to_tables( &self, stream: impl Iterator<Item = Result<InternalValue>>, ) -> Result<Option<(Vec<Table>, Option<Vec<BlobFile>>, WritePin)>>

Synchronously flushes a memtable to a table. Read more
Source§

fn tree_type(&self) -> TreeType

Returns the tree type.
Source§

fn first_key_value( &self, seqno: SeqNo, index: Option<(Arc<Memtable>, SeqNo)>, ) -> Option<IterGuardImpl>

Returns the first key-value pair in the tree. The key in this pair is the minimum key in the tree. Read more
Source§

fn last_key_value( &self, seqno: SeqNo, index: Option<(Arc<Memtable>, SeqNo)>, ) -> Option<IterGuardImpl>

Returns the last key-value pair in the tree. The key in this pair is the maximum key in the tree. Read more
Source§

fn try_insert<K: Into<UserKey>, V: Into<UserValue>>( &self, key: K, value: V, seqno: SeqNo, ) -> Result<(u64, u64)>

Admission-gated 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 more
Source§

fn try_merge<K: Into<UserKey>, V: Into<UserValue>>( &self, key: K, operand: V, seqno: SeqNo, ) -> Result<(u64, u64)>

Admission-gated merge. See try_insert. Read more
Source§

fn try_remove<K: Into<UserKey>>( &self, key: K, seqno: SeqNo, ) -> Result<(u64, u64)>

Admission-gated remove. See try_insert. Read more
Source§

fn try_remove_weak<K: Into<UserKey>>( &self, key: K, seqno: SeqNo, ) -> Result<(u64, u64)>

Admission-gated remove_weak. See try_insert. Read more
Source§

fn try_remove_range<K: Into<UserKey>>( &self, start: K, end: K, seqno: SeqNo, ) -> Result<u64>

Admission-gated remove_range. See try_insert. Read more
Source§

fn remove_prefix<K: AsRef<[u8]>>(&self, prefix: K, seqno: SeqNo) -> u64

Deletes all keys with the given prefix by inserting a range tombstone. Read more
Source§

impl Clone for Tree

Source§

fn clone(&self) -> Self

Returns a duplicate of the value. Read more
1.0.0 (const: unstable) · Source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
Source§

impl Deref for Tree

Source§

type Target = TreeInner

The resulting type after dereferencing.
Source§

fn deref(&self) -> &Self::Target

Dereferences the value.
Source§

impl From<Tree> for AnyTree

Source§

fn from(tree: Tree) -> Self

Converts to this type from the input type.
Source§

impl TryInto<Tree> for AnyTree

Source§

type Error = &'static str

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<Tree, Self::Error>

Performs the conversion.

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> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<ST, DT> CastableFrom<ST, Initialized, Initialized> for DT
where ST: ?Sized, DT: ?Sized,

Source§

impl<ST, DT> CastableFrom<ST, Uninit, Uninit> for DT
where ST: ?Sized, DT: ?Sized,

Source§

impl<T> CloneToUninit for T
where T: Clone,

Source§

unsafe fn clone_to_uninit(&self, dest: *mut u8)

🔬This is a nightly-only experimental API. (clone_to_uninit)
Performs copy-assignment from self to dest. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T> IntoEither for T

Source§

fn into_either(self, into_left: bool) -> Either<Self, Self> ⓘ

Converts 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 more
Source§

fn into_either_with<F>(self, into_left: F) -> Either<Self, Self> ⓘ
where F: FnOnce(&Self) -> bool,

Converts 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
Source§

impl<T> Pointable for T

Source§

const ALIGN: usize

The alignment of pointer.
Source§

type Init = T

The type for initializers.
Source§

unsafe fn init(init: <T as Pointable>::Init) -> usize

Initializes a with the given initializer. Read more
Source§

unsafe fn deref<'a>(ptr: usize) -> &'a T

Dereferences the given pointer. Read more
Source§

unsafe fn deref_mut<'a>(ptr: usize) -> &'a mut T

Mutably dereferences the given pointer. Read more
Source§

unsafe fn drop(ptr: usize)

Drops the object pointed to by the given pointer. Read more
Source§

impl<T> Read<Exclusive, BecauseExclusive> for T
where T: ?Sized,

Source§

impl<P, T> Receiver for P
where P: Deref<Target = T> + ?Sized, T: ?Sized,

Source§

type Target = T

🔬This is a nightly-only experimental API. (arbitrary_self_types)
The target type on which the method may be called.
Source§

impl<T> Same for T

Source§

type Output = T

Should always be Self
Source§

impl<T> StorageStatistics for T
where T: AbstractTree + ?Sized,

Source§

fn storage_stats(&self) -> Result<StorageStats, Error>

On-disk footprint and average entry shape: used / capacity / available bytes, item & table counts, average entry size, reclaimable-bytes estimate, and a coarse StorageStatus. See StorageStats::estimated_remaining_entries for a budget projection. Read more
Source§

fn level_segment_stats(&self) -> Result<Vec<LevelStats>, Error>

Per-LSM-level and per-segment size + entry-count stats, for tiering and erasure-coding placement decisions (which level / segment is large enough to demote, EC-encode, or migrate). Read more
Source§

fn compaction_debt(&self, strategy: &dyn CompactionStrategy) -> u64

Estimated bytes pending compaction under 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 more
Source§

fn cache_stats(&self) -> CacheStats

A point-in-time CacheStats snapshot of block-cache effectiveness (cumulative hit / miss counts and rate) and occupancy (current size against capacity). Read more
Source§

impl<T> ToOwned for T
where T: Clone,

Source§

type Owned = T

The resulting type after obtaining ownership.
Source§

fn to_owned(&self) -> T

Creates owned data from borrowed data, usually by cloning. Read more
Source§

fn clone_into(&self, target: &mut T)

Uses borrowed data to replace owned data, usually by cloning. Read more
Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = !

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, !>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
Source§

impl<V, T> VZip<V> for T
where V: MultiLane<T>,

Source§

fn vzip(self) -> V