1use 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#[derive(Clone)]
29pub enum AnyTree {
30 Standard(Tree),
32
33 Blob(BlobTree),
35}
36
37impl crate::abstract_tree::sealed::Sealed for AnyTree {}
38
39impl AnyTree {
40 #[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 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 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
111macro_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
123impl 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}