lsm_tree/
ingestion.rs

1// Copyright (c) 2024-present, fjall-rs
2// This source code is licensed under both the Apache 2.0 and MIT License
3// (found in the LICENSE-* files in the repository)
4
5use crate::{
6    blob_tree::ingest::BlobIngestion, tree::ingest::Ingestion, AnyTree, UserKey, UserValue,
7};
8
9/// Unified ingestion builder over `AnyTree`
10// Keep zero allocations and direct dispatch; boxing introduces heap indirection and `dyn` adds virtual dispatch.
11// Ingestion calls use `&mut self` in tight loops; the active variant is stable and branch prediction makes the match cheap.
12// Allowing this lint preserves hot-path performance at the cost of a larger enum size.
13#[expect(clippy::large_enum_variant)]
14pub enum AnyIngestion<'a> {
15    /// Ingestion for a standard LSM-tree
16    Standard(Ingestion<'a>),
17
18    /// Ingestion for a [`BlobTree`] with KV separation
19    Blob(BlobIngestion<'a>),
20}
21
22impl AnyIngestion<'_> {
23    /// Writes a key-value pair.
24    ///
25    /// # Errors
26    ///
27    /// Will return `Err` if an IO error occurs.
28    pub fn write<K: Into<UserKey>, V: Into<UserValue>>(
29        &mut self,
30        key: K,
31        value: V,
32    ) -> crate::Result<()> {
33        match self {
34            Self::Standard(i) => i.write(key.into(), value.into()),
35            Self::Blob(b) => b.write(key.into(), value.into()),
36        }
37    }
38
39    /// Writes a tombstone for a key.
40    ///
41    /// # Errors
42    ///
43    /// Will return `Err` if an IO error occurs.
44    pub fn write_tombstone<K: Into<UserKey>>(&mut self, key: K) -> crate::Result<()> {
45        match self {
46            Self::Standard(i) => i.write_tombstone(key.into()),
47            Self::Blob(b) => b.write_tombstone(key.into()),
48        }
49    }
50
51    /// Writes a weak tombstone for a key.
52    ///
53    /// # Examples
54    ///
55    /// ```
56    /// # use lsm_tree::Config;
57    /// # let folder = tempfile::tempdir()?;
58    /// # let tree = Config::new(folder, Default::default(), Default::default()).open()?;
59    /// #
60    /// let mut ingestion = tree.ingestion()?;
61    /// ingestion.write("a", "abc")?;
62    /// ingestion.write_weak_tombstone("b")?;
63    /// ingestion.finish()?;
64    /// #
65    /// # Ok::<(), lsm_tree::Error>(())
66    /// ```
67    ///
68    /// # Errors
69    ///
70    /// Will return `Err` if an IO error occurs.
71    pub fn write_weak_tombstone<K: Into<UserKey>>(&mut self, key: K) -> crate::Result<()> {
72        match self {
73            Self::Standard(i) => i.write_weak_tombstone(key.into()),
74            Self::Blob(b) => b.write_weak_tombstone(key.into()),
75        }
76    }
77
78    /// Finalizes ingestion and registers created tables (and blob files if present).
79    ///
80    /// # Errors
81    ///
82    /// Will return `Err` if an IO error occurs.
83    pub fn finish(self) -> crate::Result<()> {
84        match self {
85            Self::Standard(i) => i.finish(),
86            Self::Blob(b) => b.finish(),
87        }
88    }
89}
90
91impl AnyTree {
92    /// Starts an ingestion for any tree type (standard or blob).
93    ///
94    /// # Errors
95    ///
96    /// Will return `Err` if an IO error occurs.
97    pub fn ingestion(&self) -> crate::Result<AnyIngestion<'_>> {
98        match self {
99            Self::Standard(t) => Ok(AnyIngestion::Standard(Ingestion::new(t)?)),
100            Self::Blob(b) => Ok(AnyIngestion::Blob(BlobIngestion::new(b)?)),
101        }
102    }
103}