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}