Skip to main content

lsm_tree/
any_tree.rs

1// SPDX-License-Identifier: Apache-2.0
2// Copyright (c) 2024-present, fjall-rs
3// Copyright (c) 2026-present, Dmitry Prudnikov
4
5use crate::{
6    AbstractTree, BlobTree, Config, InternalValue, Memtable, SeqNo, TableId, Tree, UserKey,
7    UserValue,
8    abstract_tree::FlushToTablesResult,
9    iter_guard::{IterGuardImpl, SeekableGuardIter},
10    table::Table,
11    tree::inner::{FlushGuard, VersionsWriteGuard},
12    version::Version,
13    vlog::BlobFile,
14};
15use alloc::sync::Arc;
16#[cfg(not(feature = "std"))]
17use alloc::{boxed::Box, vec::Vec};
18use core::ops::RangeBounds;
19
20#[cfg(test)]
21#[expect(clippy::expect_used, reason = "test code")]
22mod tests;
23
24/// May be a standard [`Tree`] or a [`BlobTree`]
25///
26/// Closed like either: once the [`TreeClose`](crate::TreeClose) of
27/// [`close`](Self::close) fires, the tree writes nothing into its directory.
28#[derive(Clone)]
29pub enum AnyTree {
30    /// Standard LSM-tree, see [`Tree`]
31    Standard(Tree),
32
33    /// Key-value separated LSM-tree, see [`BlobTree`]
34    Blob(BlobTree),
35}
36
37impl crate::abstract_tree::sealed::Sealed for AnyTree {}
38
39impl AnyTree {
40    /// A handle that does not keep the tree open; see [`WeakTree`](crate::WeakTree).
41    #[must_use]
42    pub fn downgrade(&self) -> crate::WeakTree {
43        match self {
44            Self::Standard(tree) => tree.downgrade(),
45            Self::Blob(tree) => tree.downgrade(),
46        }
47    }
48
49    /// Gives up this handle and returns the signal of the tree being closed;
50    /// see [`Tree::close`](crate::Tree::close).
51    pub fn close(self) -> crate::TreeClose {
52        match self {
53            Self::Standard(tree) => tree.close(),
54            Self::Blob(tree) => tree.close(),
55        }
56    }
57
58    /// Starts a multi-get of `keys` at `seqno` that its caller drives: see
59    /// [`Tree::start_multi_get`].
60    ///
61    /// # Errors
62    ///
63    /// Returns [`crate::Error::SnapshotBelowRetention`] when `seqno` is below
64    /// what the tree retains.
65    pub fn start_multi_get<K: Into<crate::UserKey>>(
66        &self,
67        keys: impl IntoIterator<Item = K>,
68        seqno: crate::SeqNo,
69    ) -> crate::Result<crate::resumable::Step> {
70        match self {
71            Self::Standard(tree) => tree.start_multi_get(keys, seqno),
72            Self::Blob(tree) => tree.start_multi_get(keys, seqno),
73        }
74    }
75}
76
77impl From<Tree> for AnyTree {
78    fn from(tree: Tree) -> Self {
79        Self::Standard(tree)
80    }
81}
82
83impl From<BlobTree> for AnyTree {
84    fn from(tree: BlobTree) -> Self {
85        Self::Blob(tree)
86    }
87}
88
89impl TryInto<Tree> for AnyTree {
90    type Error = &'static str;
91
92    fn try_into(self) -> Result<Tree, Self::Error> {
93        match self {
94            Self::Standard(tree) => Ok(tree),
95            Self::Blob(_) => Err("Tried to convert variant Blob to Standard"),
96        }
97    }
98}
99
100impl TryInto<BlobTree> for AnyTree {
101    type Error = &'static str;
102
103    fn try_into(self) -> Result<BlobTree, Self::Error> {
104        match self {
105            Self::Blob(tree) => Ok(tree),
106            Self::Standard(_) => Err("Tried to convert variant Standard to Blob"),
107        }
108    }
109}
110
111/// Calls the [`AbstractTree`] method on the tree inside either variant. The
112/// trait path keeps a same-named inherent method of [`Tree`] or [`BlobTree`]
113/// from being picked instead.
114macro_rules! forward {
115    ($self:ident.$method:ident($($arg:expr),*)) => {
116        match $self {
117            AnyTree::Standard(tree) => AbstractTree::$method(tree, $($arg),*),
118            AnyTree::Blob(tree) => AbstractTree::$method(tree, $($arg),*),
119        }
120    };
121}
122
123// Every method is forwarded, defaulted ones included, so an override in `Tree`
124// or `BlobTree` is the one that runs.
125impl AbstractTree for AnyTree {
126    #[inline]
127    fn print_trace(&self, key: &[u8]) -> crate::Result<()> {
128        forward!(self.print_trace(key))
129    }
130
131    #[inline]
132    fn table_file_cache_size(&self) -> usize {
133        forward!(self.table_file_cache_size())
134    }
135
136    #[inline]
137    fn next_table_id(&self) -> TableId {
138        forward!(self.next_table_id())
139    }
140
141    #[inline]
142    fn id(&self) -> crate::TreeId {
143        forward!(self.id())
144    }
145
146    #[inline]
147    fn get_internal_entry(&self, key: &[u8], seqno: SeqNo) -> crate::Result<Option<InternalValue>> {
148        forward!(self.get_internal_entry(key, seqno))
149    }
150
151    #[inline]
152    fn current_version(&self) -> Version {
153        forward!(self.current_version())
154    }
155
156    #[cfg(feature = "std")]
157    #[inline]
158    fn refresh_table_checksum(
159        &self,
160        table_id: TableId,
161        checksum: crate::checksum::Checksum,
162        expected_restriction: Option<&UserKey>,
163    ) -> crate::Result<crate::abstract_tree::ChecksumRefreshOutcome> {
164        forward!(self.refresh_table_checksum(table_id, checksum, expected_restriction))
165    }
166
167    #[inline]
168    fn sync_mode(&self) -> crate::fs::SyncMode {
169        forward!(self.sync_mode())
170    }
171
172    #[inline]
173    fn wait_for_table_file_refills(&self) {
174        forward!(self.wait_for_table_file_refills());
175    }
176
177    #[inline]
178    fn prefix_extractor(&self) -> Option<Arc<dyn crate::prefix::PrefixExtractor>> {
179        forward!(self.prefix_extractor())
180    }
181
182    #[inline]
183    fn storage_stats(&self) -> crate::Result<crate::StorageStats> {
184        forward!(self.storage_stats())
185    }
186
187    #[inline]
188    fn level_segment_stats(&self) -> crate::Result<Vec<crate::LevelStats>> {
189        forward!(self.level_segment_stats())
190    }
191
192    #[inline]
193    fn compaction_debt(&self, strategy: &dyn crate::compaction::CompactionStrategy) -> u64 {
194        forward!(self.compaction_debt(strategy))
195    }
196
197    #[inline]
198    fn write_backpressure(
199        &self,
200        strategy: &dyn crate::compaction::CompactionStrategy,
201    ) -> crate::Backpressure {
202        forward!(self.write_backpressure(strategy))
203    }
204
205    #[inline]
206    fn write_backpressure_for(
207        &self,
208        strategy: &dyn crate::compaction::CompactionStrategy,
209        bytes: u64,
210    ) -> crate::Backpressure {
211        forward!(self.write_backpressure_for(strategy, bytes))
212    }
213
214    #[inline]
215    fn write_rate_limiter(&self) -> Arc<crate::rate_limiter::RateLimiter> {
216        forward!(self.write_rate_limiter())
217    }
218
219    #[inline]
220    fn write_admission(&self) -> crate::Result<()> {
221        forward!(self.write_admission())
222    }
223
224    #[inline]
225    fn is_read_only(&self) -> bool {
226        forward!(self.is_read_only())
227    }
228
229    #[cfg(feature = "std")]
230    #[inline]
231    fn verify_checksum(&self) -> crate::verify::BlockVerifyReport
232    where
233        Self: Sized,
234    {
235        forward!(self.verify_checksum())
236    }
237
238    #[cfg(feature = "std")]
239    #[inline]
240    fn verify_checksum_with(
241        &self,
242        options: &crate::verify::VerifyOptions,
243    ) -> crate::verify::BlockVerifyReport
244    where
245        Self: Sized,
246    {
247        forward!(self.verify_checksum_with(options))
248    }
249
250    #[inline]
251    fn get_version_history_lock(&self) -> VersionsWriteGuard<'_> {
252        forward!(self.get_version_history_lock())
253    }
254
255    #[cfg(feature = "std")]
256    #[inline]
257    fn create_checkpoint(
258        &self,
259        target_path: &crate::path::Path,
260    ) -> crate::Result<crate::CheckpointInfo> {
261        forward!(self.create_checkpoint(target_path))
262    }
263
264    #[cfg(feature = "std")]
265    #[inline]
266    fn pin(&self) -> crate::PinnedVersion {
267        forward!(self.pin())
268    }
269
270    #[cfg(feature = "std")]
271    #[inline]
272    fn acknowledge_repair_report(&self, id: u128) -> crate::Result<bool> {
273        forward!(self.acknowledge_repair_report(id))
274    }
275
276    #[inline]
277    fn flush_active_memtable(&self, gc_watermark: SeqNo) -> crate::Result<()> {
278        forward!(self.flush_active_memtable(gc_watermark))
279    }
280
281    #[inline]
282    fn persist_flushes(&self) -> crate::Result<()> {
283        forward!(self.persist_flushes())
284    }
285
286    #[inline]
287    fn sync_devices(&self) -> crate::Result<()> {
288        forward!(self.sync_devices())
289    }
290
291    #[inline]
292    fn flush(&self, lock: &FlushGuard<'_>, gc_watermark: SeqNo) -> crate::Result<Option<u64>> {
293        forward!(self.flush(lock, gc_watermark))
294    }
295
296    #[inline]
297    fn iter(
298        &self,
299        seqno: SeqNo,
300        index: Option<(Arc<Memtable>, SeqNo)>,
301    ) -> Box<dyn DoubleEndedIterator<Item = IterGuardImpl> + Send + 'static> {
302        forward!(self.iter(seqno, index))
303    }
304
305    #[inline]
306    fn prefix<K: AsRef<[u8]>>(
307        &self,
308        prefix: K,
309        seqno: SeqNo,
310        index: Option<(Arc<Memtable>, SeqNo)>,
311    ) -> Box<dyn DoubleEndedIterator<Item = IterGuardImpl> + Send + 'static> {
312        forward!(self.prefix(prefix, seqno, index))
313    }
314
315    #[inline]
316    fn range<K: AsRef<[u8]>, R: RangeBounds<K>>(
317        &self,
318        range: R,
319        seqno: SeqNo,
320        index: Option<(Arc<Memtable>, SeqNo)>,
321    ) -> Box<dyn DoubleEndedIterator<Item = IterGuardImpl> + Send + 'static> {
322        forward!(self.range(range, seqno, index))
323    }
324
325    #[inline]
326    fn range_seekable<K: AsRef<[u8]>, R: RangeBounds<K>>(
327        &self,
328        range: R,
329        seqno: SeqNo,
330        index: Option<(Arc<Memtable>, SeqNo)>,
331    ) -> Box<dyn SeekableGuardIter + 'static> {
332        forward!(self.range_seekable(range, seqno, index))
333    }
334
335    #[inline]
336    fn batch_range_scan<K: AsRef<[u8]>, R: RangeBounds<K> + 'static, I: IntoIterator<Item = R>>(
337        &self,
338        intervals: I,
339        seqno: SeqNo,
340        index: Option<(Arc<Memtable>, SeqNo)>,
341    ) -> Box<dyn Iterator<Item = IterGuardImpl> + Send + 'static>
342    where
343        I::IntoIter: Send + 'static,
344    {
345        forward!(self.batch_range_scan(intervals, seqno, index))
346    }
347
348    #[inline]
349    fn tombstone_count(&self) -> u64 {
350        forward!(self.tombstone_count())
351    }
352
353    #[inline]
354    fn weak_tombstone_count(&self) -> u64 {
355        forward!(self.weak_tombstone_count())
356    }
357
358    #[inline]
359    fn weak_tombstone_reclaimable_count(&self) -> u64 {
360        forward!(self.weak_tombstone_reclaimable_count())
361    }
362
363    #[inline]
364    fn clear(&self) -> crate::Result<()> {
365        forward!(self.clear())
366    }
367
368    #[inline]
369    fn major_compact(
370        &self,
371        target_size: u64,
372        gc_watermark: SeqNo,
373    ) -> crate::Result<crate::compaction::CompactionResult> {
374        forward!(self.major_compact(target_size, gc_watermark))
375    }
376
377    #[inline]
378    fn stale_blob_bytes(&self) -> u64 {
379        forward!(self.stale_blob_bytes())
380    }
381
382    #[inline]
383    fn filter_size(&self) -> u64 {
384        forward!(self.filter_size())
385    }
386
387    #[inline]
388    fn pinned_filter_size(&self) -> usize {
389        forward!(self.pinned_filter_size())
390    }
391
392    #[inline]
393    fn filter_memory(&self) -> crate::FilterMemory {
394        forward!(self.filter_memory())
395    }
396
397    #[inline]
398    fn pinned_block_index_size(&self) -> usize {
399        forward!(self.pinned_block_index_size())
400    }
401
402    #[cfg(feature = "metrics")]
403    #[inline]
404    fn metrics(&self) -> &Arc<crate::Metrics> {
405        forward!(self.metrics())
406    }
407
408    #[cfg(feature = "metrics")]
409    #[inline]
410    fn cache_stats(&self) -> crate::CacheStats {
411        forward!(self.cache_stats())
412    }
413
414    #[inline]
415    fn get_flush_lock(&self) -> FlushGuard<'_> {
416        forward!(self.get_flush_lock())
417    }
418
419    #[inline]
420    fn flush_to_tables(
421        &self,
422        stream: impl Iterator<Item = crate::Result<InternalValue>>,
423    ) -> crate::Result<Option<FlushToTablesResult>> {
424        forward!(self.flush_to_tables(stream))
425    }
426
427    #[inline]
428    fn flush_to_tables_with_rt(
429        &self,
430        stream: impl Iterator<Item = crate::Result<InternalValue>>,
431        range_tombstones: Vec<crate::range_tombstone::RangeTombstone>,
432        keys: u64,
433        hashes: u64,
434        overwritten: Option<&crate::blob_tree::overwritten::OverwrittenKeys>,
435    ) -> crate::Result<Option<FlushToTablesResult>> {
436        forward!(self.flush_to_tables_with_rt(stream, range_tombstones, keys, hashes, overwritten))
437    }
438
439    #[inline]
440    fn register_tables(
441        &self,
442        tables: &[Table],
443        blob_files: Option<&[BlobFile]>,
444        frag_map: Option<crate::blob_tree::FragmentationMap>,
445        sealed_memtables_to_delete: &[crate::tree::inner::MemtableId],
446        gc_watermark: SeqNo,
447        collected_below_watermark: bool,
448    ) -> crate::Result<()> {
449        forward!(self.register_tables(
450            tables,
451            blob_files,
452            frag_map,
453            sealed_memtables_to_delete,
454            gc_watermark,
455            collected_below_watermark
456        ))
457    }
458
459    #[inline]
460    fn clear_active_memtable(&self) {
461        forward!(self.clear_active_memtable());
462    }
463
464    #[inline]
465    fn sealed_memtable_count(&self) -> usize {
466        forward!(self.sealed_memtable_count())
467    }
468
469    #[inline]
470    fn compact(
471        &self,
472        strategy: Arc<dyn crate::compaction::CompactionStrategy>,
473        gc_watermark: SeqNo,
474    ) -> crate::Result<crate::compaction::CompactionResult> {
475        forward!(self.compact(strategy, gc_watermark))
476    }
477
478    #[inline]
479    fn get_next_table_id(&self) -> TableId {
480        forward!(self.get_next_table_id())
481    }
482
483    #[inline]
484    fn tree_config(&self) -> &Config {
485        forward!(self.tree_config())
486    }
487
488    #[inline]
489    fn get_highest_seqno(&self) -> Option<SeqNo> {
490        forward!(self.get_highest_seqno())
491    }
492
493    #[inline]
494    fn active_memtable(&self) -> Arc<Memtable> {
495        forward!(self.active_memtable())
496    }
497
498    #[inline]
499    fn active_memtable_is_empty(&self) -> bool {
500        forward!(self.active_memtable_is_empty())
501    }
502
503    #[inline]
504    fn tree_type(&self) -> crate::TreeType {
505        forward!(self.tree_type())
506    }
507
508    #[inline]
509    fn rotate_memtable(&self) -> Option<Arc<Memtable>> {
510        forward!(self.rotate_memtable())
511    }
512
513    #[inline]
514    fn table_count(&self) -> usize {
515        forward!(self.table_count())
516    }
517
518    #[inline]
519    fn level_table_count(&self, idx: usize) -> Option<usize> {
520        forward!(self.level_table_count(idx))
521    }
522
523    #[inline]
524    fn l0_run_count(&self) -> usize {
525        forward!(self.l0_run_count())
526    }
527
528    #[inline]
529    fn blob_file_count(&self) -> usize {
530        forward!(self.blob_file_count())
531    }
532
533    #[inline]
534    fn approximate_len(&self) -> usize {
535        forward!(self.approximate_len())
536    }
537
538    #[inline]
539    fn disk_space(&self) -> u64 {
540        forward!(self.disk_space())
541    }
542
543    #[inline]
544    fn approximate_range_stats<K: AsRef<[u8]>, R: RangeBounds<K>>(
545        &self,
546        range: R,
547        seqno: SeqNo,
548    ) -> crate::Result<crate::ApproximateRangeStats> {
549        forward!(self.approximate_range_stats(range, seqno))
550    }
551
552    #[inline]
553    fn approximate_range_cardinality<K: AsRef<[u8]>, R: RangeBounds<K>>(
554        &self,
555        range: R,
556        seqno: SeqNo,
557    ) -> crate::Result<crate::RangeCardinality> {
558        forward!(self.approximate_range_cardinality(range, seqno))
559    }
560
561    #[inline]
562    fn get_highest_memtable_seqno(&self) -> Option<SeqNo> {
563        forward!(self.get_highest_memtable_seqno())
564    }
565
566    #[inline]
567    fn get_highest_persisted_seqno(&self) -> Option<SeqNo> {
568        forward!(self.get_highest_persisted_seqno())
569    }
570
571    #[inline]
572    fn oldest_retained_seqno(&self) -> SeqNo {
573        forward!(self.oldest_retained_seqno())
574    }
575
576    #[inline]
577    fn retention_floor(&self) -> SeqNo {
578        forward!(self.retention_floor())
579    }
580
581    fn lower_retention_floor(&self, floor: SeqNo) -> crate::Result<()> {
582        forward!(self.lower_retention_floor(floor))
583    }
584
585    #[inline]
586    fn compaction_rate_limiter(&self) -> Arc<crate::rate_limiter::RateLimiter> {
587        forward!(self.compaction_rate_limiter())
588    }
589
590    #[inline]
591    fn len(&self, seqno: SeqNo, index: Option<(Arc<Memtable>, SeqNo)>) -> crate::Result<usize> {
592        forward!(self.len(seqno, index))
593    }
594
595    #[inline]
596    fn is_empty(&self, seqno: SeqNo, index: Option<(Arc<Memtable>, SeqNo)>) -> crate::Result<bool> {
597        forward!(self.is_empty(seqno, index))
598    }
599
600    #[inline]
601    fn first_key_value(
602        &self,
603        seqno: SeqNo,
604        index: Option<(Arc<Memtable>, SeqNo)>,
605    ) -> Option<IterGuardImpl> {
606        forward!(self.first_key_value(seqno, index))
607    }
608
609    #[inline]
610    fn last_key_value(
611        &self,
612        seqno: SeqNo,
613        index: Option<(Arc<Memtable>, SeqNo)>,
614    ) -> Option<IterGuardImpl> {
615        forward!(self.last_key_value(seqno, index))
616    }
617
618    #[inline]
619    fn size_of<K: AsRef<[u8]>>(&self, key: K, seqno: SeqNo) -> crate::Result<Option<u32>> {
620        forward!(self.size_of(key, seqno))
621    }
622
623    #[inline]
624    fn get<K: AsRef<[u8]>>(&self, key: K, seqno: SeqNo) -> crate::Result<Option<UserValue>> {
625        forward!(self.get(key, seqno))
626    }
627
628    #[inline]
629    fn get_pinned<K: AsRef<[u8]>>(
630        &self,
631        key: K,
632        seqno: SeqNo,
633    ) -> crate::Result<Option<crate::PinnableSlice>> {
634        forward!(self.get_pinned(key, seqno))
635    }
636
637    #[inline]
638    fn contains_key<K: AsRef<[u8]>>(&self, key: K, seqno: SeqNo) -> crate::Result<bool> {
639        forward!(self.contains_key(key, seqno))
640    }
641
642    #[inline]
643    fn contains_prefix<K: AsRef<[u8]>>(
644        &self,
645        prefix: K,
646        seqno: SeqNo,
647        index: Option<(Arc<Memtable>, SeqNo)>,
648    ) -> crate::Result<bool> {
649        forward!(self.contains_prefix(prefix, seqno, index))
650    }
651
652    #[inline]
653    fn multi_get<K: AsRef<[u8]>>(
654        &self,
655        keys: impl IntoIterator<Item = K>,
656        seqno: SeqNo,
657    ) -> crate::Result<Vec<Option<UserValue>>> {
658        forward!(self.multi_get(keys, seqno))
659    }
660
661    #[inline]
662    fn apply_batch(&self, batch: crate::WriteBatch, seqno: SeqNo) -> crate::Result<(u64, u64)> {
663        forward!(self.apply_batch(batch, seqno))
664    }
665
666    #[inline]
667    fn insert<K: Into<UserKey>, V: Into<UserValue>>(
668        &self,
669        key: K,
670        value: V,
671        seqno: SeqNo,
672    ) -> (u64, u64) {
673        forward!(self.insert(key, value, seqno))
674    }
675
676    #[inline]
677    fn try_insert<K: Into<UserKey>, V: Into<UserValue>>(
678        &self,
679        key: K,
680        value: V,
681        seqno: SeqNo,
682    ) -> crate::Result<(u64, u64)> {
683        forward!(self.try_insert(key, value, seqno))
684    }
685
686    #[inline]
687    fn try_merge<K: Into<UserKey>, V: Into<UserValue>>(
688        &self,
689        key: K,
690        operand: V,
691        seqno: SeqNo,
692    ) -> crate::Result<(u64, u64)> {
693        forward!(self.try_merge(key, operand, seqno))
694    }
695
696    #[inline]
697    fn try_remove<K: Into<UserKey>>(&self, key: K, seqno: SeqNo) -> crate::Result<(u64, u64)> {
698        forward!(self.try_remove(key, seqno))
699    }
700
701    #[inline]
702    fn try_remove_weak<K: Into<UserKey>>(&self, key: K, seqno: SeqNo) -> crate::Result<(u64, u64)> {
703        forward!(self.try_remove_weak(key, seqno))
704    }
705
706    #[inline]
707    fn try_remove_range<K: Into<UserKey>>(
708        &self,
709        start: K,
710        end: K,
711        seqno: SeqNo,
712    ) -> crate::Result<u64> {
713        forward!(self.try_remove_range(start, end, seqno))
714    }
715
716    #[inline]
717    fn remove<K: Into<UserKey>>(&self, key: K, seqno: SeqNo) -> (u64, u64) {
718        forward!(self.remove(key, seqno))
719    }
720
721    #[inline]
722    fn merge<K: Into<UserKey>, V: Into<UserValue>>(
723        &self,
724        key: K,
725        operand: V,
726        seqno: SeqNo,
727    ) -> (u64, u64) {
728        forward!(self.merge(key, operand, seqno))
729    }
730
731    #[inline]
732    fn remove_weak<K: Into<UserKey>>(&self, key: K, seqno: SeqNo) -> (u64, u64) {
733        forward!(self.remove_weak(key, seqno))
734    }
735
736    #[inline]
737    fn remove_range<K: Into<UserKey>>(&self, start: K, end: K, seqno: SeqNo) -> u64 {
738        forward!(self.remove_range(start, end, seqno))
739    }
740
741    #[inline]
742    fn remove_prefix<K: AsRef<[u8]>>(&self, prefix: K, seqno: SeqNo) -> u64 {
743        forward!(self.remove_prefix(prefix, seqno))
744    }
745}