lsm_tree/runtime_config/pin.rs
1// SPDX-License-Identifier: Apache-2.0
2// Copyright (c) 2026-present, Dmitry Prudnikov
3
4//! The hold a write keeps on the policy it resolved its dictionaries from.
5
6use super::RuntimeConfig;
7use alloc::sync::Arc;
8
9/// Keeps the dictionaries a write's files name out of a dictionary collection
10/// until those files are installed.
11///
12/// A write resolves its dictionary from the policy snapshot it started under,
13/// and a collection spares every dictionary a still-held snapshot names, however
14/// the policy has changed since. The pin is that hold, owned by the operation
15/// rather than its writers, since finishing a writer comes before the install:
16/// drop it only once the files it covers are part of the tree, from which point
17/// the files name the dictionary themselves. A flush and an ingestion carry it
18/// from where their files are finished to where they are installed; a
19/// compaction, which does both in one call, holds its snapshot directly. Always
20/// empty in builds without zstd, which have no dictionaries to collect.
21///
22/// It also holds the filter bytes the write took in the tree's filter budget,
23/// when the tree sizes its filters by probe load: dropped before the install,
24/// the budget would hand that room to another rewrite while the files that
25/// take it are about to join the tree.
26#[derive(Default)]
27#[must_use = "dropping the pin before the files are installed lets a collection take their dictionary"]
28pub struct WritePin {
29 snapshot: Option<Arc<RuntimeConfig>>,
30 filter_sizing: Option<crate::filter_budget::FilterPlan>,
31}
32
33impl WritePin {
34 /// A pin on the snapshot a write resolves its dictionaries from. Empty when
35 /// the snapshot names no dictionary: its files name none either, and an
36 /// update never records such a snapshot for a collection to consult.
37 #[cfg(zstd_any)]
38 pub(crate) fn new(snapshot: &Arc<RuntimeConfig>) -> Self {
39 Self {
40 snapshot: snapshot
41 .write_dict_ids(true)
42 .next()
43 .map(|_| Arc::clone(snapshot)),
44 filter_sizing: None,
45 }
46 }
47
48 /// A pin on the snapshot a write resolves its dictionaries from: empty, as
49 /// a build without zstd resolves none.
50 #[cfg(not(zstd_any))]
51 pub(crate) fn new(_snapshot: &Arc<RuntimeConfig>) -> Self {
52 Self::default()
53 }
54
55 /// Also holds the filter budget `sizing` reserved until the install.
56 pub(crate) fn with_filter_sizing(
57 mut self,
58 sizing: Option<crate::filter_budget::FilterPlan>,
59 ) -> Self {
60 self.filter_sizing = sizing;
61 self
62 }
63}
64
65impl core::fmt::Debug for WritePin {
66 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
67 f.debug_struct("WritePin")
68 .field("holds", &self.snapshot.is_some())
69 .field("filter_budget", &self.filter_sizing.is_some())
70 .finish()
71 }
72}