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 tree_type(&self) -> crate::TreeType {
500        forward!(self.tree_type())
501    }
502
503    #[inline]
504    fn rotate_memtable(&self) -> Option<Arc<Memtable>> {
505        forward!(self.rotate_memtable())
506    }
507
508    #[inline]
509    fn table_count(&self) -> usize {
510        forward!(self.table_count())
511    }
512
513    #[inline]
514    fn level_table_count(&self, idx: usize) -> Option<usize> {
515        forward!(self.level_table_count(idx))
516    }
517
518    #[inline]
519    fn l0_run_count(&self) -> usize {
520        forward!(self.l0_run_count())
521    }
522
523    #[inline]
524    fn blob_file_count(&self) -> usize {
525        forward!(self.blob_file_count())
526    }
527
528    #[inline]
529    fn approximate_len(&self) -> usize {
530        forward!(self.approximate_len())
531    }
532
533    #[inline]
534    fn disk_space(&self) -> u64 {
535        forward!(self.disk_space())
536    }
537
538    #[inline]
539    fn approximate_range_stats<K: AsRef<[u8]>, R: RangeBounds<K>>(
540        &self,
541        range: R,
542        seqno: SeqNo,
543    ) -> crate::Result<crate::ApproximateRangeStats> {
544        forward!(self.approximate_range_stats(range, seqno))
545    }
546
547    #[inline]
548    fn approximate_range_cardinality<K: AsRef<[u8]>, R: RangeBounds<K>>(
549        &self,
550        range: R,
551        seqno: SeqNo,
552    ) -> crate::Result<crate::RangeCardinality> {
553        forward!(self.approximate_range_cardinality(range, seqno))
554    }
555
556    #[inline]
557    fn get_highest_memtable_seqno(&self) -> Option<SeqNo> {
558        forward!(self.get_highest_memtable_seqno())
559    }
560
561    #[inline]
562    fn get_highest_persisted_seqno(&self) -> Option<SeqNo> {
563        forward!(self.get_highest_persisted_seqno())
564    }
565
566    #[inline]
567    fn oldest_retained_seqno(&self) -> SeqNo {
568        forward!(self.oldest_retained_seqno())
569    }
570
571    #[inline]
572    fn retention_floor(&self) -> SeqNo {
573        forward!(self.retention_floor())
574    }
575
576    fn lower_retention_floor(&self, floor: SeqNo) -> crate::Result<()> {
577        forward!(self.lower_retention_floor(floor))
578    }
579
580    #[inline]
581    fn compaction_rate_limiter(&self) -> Arc<crate::rate_limiter::RateLimiter> {
582        forward!(self.compaction_rate_limiter())
583    }
584
585    #[inline]
586    fn len(&self, seqno: SeqNo, index: Option<(Arc<Memtable>, SeqNo)>) -> crate::Result<usize> {
587        forward!(self.len(seqno, index))
588    }
589
590    #[inline]
591    fn is_empty(&self, seqno: SeqNo, index: Option<(Arc<Memtable>, SeqNo)>) -> crate::Result<bool> {
592        forward!(self.is_empty(seqno, index))
593    }
594
595    #[inline]
596    fn first_key_value(
597        &self,
598        seqno: SeqNo,
599        index: Option<(Arc<Memtable>, SeqNo)>,
600    ) -> Option<IterGuardImpl> {
601        forward!(self.first_key_value(seqno, index))
602    }
603
604    #[inline]
605    fn last_key_value(
606        &self,
607        seqno: SeqNo,
608        index: Option<(Arc<Memtable>, SeqNo)>,
609    ) -> Option<IterGuardImpl> {
610        forward!(self.last_key_value(seqno, index))
611    }
612
613    #[inline]
614    fn size_of<K: AsRef<[u8]>>(&self, key: K, seqno: SeqNo) -> crate::Result<Option<u32>> {
615        forward!(self.size_of(key, seqno))
616    }
617
618    #[inline]
619    fn get<K: AsRef<[u8]>>(&self, key: K, seqno: SeqNo) -> crate::Result<Option<UserValue>> {
620        forward!(self.get(key, seqno))
621    }
622
623    #[inline]
624    fn get_pinned<K: AsRef<[u8]>>(
625        &self,
626        key: K,
627        seqno: SeqNo,
628    ) -> crate::Result<Option<crate::PinnableSlice>> {
629        forward!(self.get_pinned(key, seqno))
630    }
631
632    #[inline]
633    fn contains_key<K: AsRef<[u8]>>(&self, key: K, seqno: SeqNo) -> crate::Result<bool> {
634        forward!(self.contains_key(key, seqno))
635    }
636
637    #[inline]
638    fn contains_prefix<K: AsRef<[u8]>>(
639        &self,
640        prefix: K,
641        seqno: SeqNo,
642        index: Option<(Arc<Memtable>, SeqNo)>,
643    ) -> crate::Result<bool> {
644        forward!(self.contains_prefix(prefix, seqno, index))
645    }
646
647    #[inline]
648    fn multi_get<K: AsRef<[u8]>>(
649        &self,
650        keys: impl IntoIterator<Item = K>,
651        seqno: SeqNo,
652    ) -> crate::Result<Vec<Option<UserValue>>> {
653        forward!(self.multi_get(keys, seqno))
654    }
655
656    #[inline]
657    fn apply_batch(&self, batch: crate::WriteBatch, seqno: SeqNo) -> crate::Result<(u64, u64)> {
658        forward!(self.apply_batch(batch, seqno))
659    }
660
661    #[inline]
662    fn insert<K: Into<UserKey>, V: Into<UserValue>>(
663        &self,
664        key: K,
665        value: V,
666        seqno: SeqNo,
667    ) -> (u64, u64) {
668        forward!(self.insert(key, value, seqno))
669    }
670
671    #[inline]
672    fn try_insert<K: Into<UserKey>, V: Into<UserValue>>(
673        &self,
674        key: K,
675        value: V,
676        seqno: SeqNo,
677    ) -> crate::Result<(u64, u64)> {
678        forward!(self.try_insert(key, value, seqno))
679    }
680
681    #[inline]
682    fn try_merge<K: Into<UserKey>, V: Into<UserValue>>(
683        &self,
684        key: K,
685        operand: V,
686        seqno: SeqNo,
687    ) -> crate::Result<(u64, u64)> {
688        forward!(self.try_merge(key, operand, seqno))
689    }
690
691    #[inline]
692    fn try_remove<K: Into<UserKey>>(&self, key: K, seqno: SeqNo) -> crate::Result<(u64, u64)> {
693        forward!(self.try_remove(key, seqno))
694    }
695
696    #[inline]
697    fn try_remove_weak<K: Into<UserKey>>(&self, key: K, seqno: SeqNo) -> crate::Result<(u64, u64)> {
698        forward!(self.try_remove_weak(key, seqno))
699    }
700
701    #[inline]
702    fn try_remove_range<K: Into<UserKey>>(
703        &self,
704        start: K,
705        end: K,
706        seqno: SeqNo,
707    ) -> crate::Result<u64> {
708        forward!(self.try_remove_range(start, end, seqno))
709    }
710
711    #[inline]
712    fn remove<K: Into<UserKey>>(&self, key: K, seqno: SeqNo) -> (u64, u64) {
713        forward!(self.remove(key, seqno))
714    }
715
716    #[inline]
717    fn merge<K: Into<UserKey>, V: Into<UserValue>>(
718        &self,
719        key: K,
720        operand: V,
721        seqno: SeqNo,
722    ) -> (u64, u64) {
723        forward!(self.merge(key, operand, seqno))
724    }
725
726    #[inline]
727    fn remove_weak<K: Into<UserKey>>(&self, key: K, seqno: SeqNo) -> (u64, u64) {
728        forward!(self.remove_weak(key, seqno))
729    }
730
731    #[inline]
732    fn remove_range<K: Into<UserKey>>(&self, start: K, end: K, seqno: SeqNo) -> u64 {
733        forward!(self.remove_range(start, end, seqno))
734    }
735
736    #[inline]
737    fn remove_prefix<K: AsRef<[u8]>>(&self, prefix: K, seqno: SeqNo) -> u64 {
738        forward!(self.remove_prefix(prefix, seqno))
739    }
740}