lsm_tree/vlog/gc/mod.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
5pub mod report;
6
7use crate::vlog::{BlobFileId, ValueLog};
8
9/// GC strategy
10#[allow(clippy::module_name_repetitions)]
11pub trait GcStrategy {
12 /// Picks blob files based on a predicate.
13 fn pick(&self, value_log: &ValueLog) -> Vec<BlobFileId>;
14}
15
16/// Picks blob files that have a certain percentage of stale blobs
17pub struct StaleThresholdStrategy(f32);
18
19impl StaleThresholdStrategy {
20 /// Creates a new strategy with the given threshold.
21 ///
22 /// # Panics
23 ///
24 /// Panics if the ratio is invalid.
25 #[must_use]
26 pub fn new(ratio: f32) -> Self {
27 assert!(
28 ratio.is_finite() && ratio.is_sign_positive(),
29 "invalid stale ratio"
30 );
31 Self(ratio.min(1.0))
32 }
33}
34
35impl GcStrategy for StaleThresholdStrategy {
36 fn pick(&self, value_log: &ValueLog) -> Vec<BlobFileId> {
37 unimplemented!()
38
39 // value_log
40 // .manifest
41 // .blob_files
42 // .read()
43 // .expect("lock is poisoned")
44 // .values()
45 // .filter(|x| x.stale_ratio() > self.0)
46 // .map(|x| x.id)
47 // .collect::<Vec<_>>()
48 }
49}
50
51/// Tries to find a least-effort-selection of blob files to merge to reach a certain space amplification
52pub struct SpaceAmpStrategy(f32);
53
54impl SpaceAmpStrategy {
55 /// Creates a new strategy with the given space amp factor.
56 ///
57 /// # Panics
58 ///
59 /// Panics if the space amp factor is < 1.0.
60 #[must_use]
61 pub fn new(ratio: f32) -> Self {
62 assert!(ratio >= 1.0, "invalid space amp ratio");
63 Self(ratio)
64 }
65}
66
67impl GcStrategy for SpaceAmpStrategy {
68 #[allow(clippy::cast_precision_loss, clippy::significant_drop_tightening)]
69 fn pick(&self, value_log: &ValueLog) -> Vec<BlobFileId> {
70 unimplemented!()
71
72 // let space_amp_target = self.0;
73 // let current_space_amp = value_log.space_amp();
74
75 // if current_space_amp < space_amp_target {
76 // log::trace!("Space amp is <= target {space_amp_target}, nothing to do");
77 // vec![]
78 // } else {
79 // log::debug!("Selecting blob files to GC, space_amp_target={space_amp_target}");
80
81 // let lock = value_log
82 // .manifest
83 // .blob_files
84 // .read()
85 // .expect("lock is poisoned");
86
87 // let mut blob_files = lock
88 // .values()
89 // .filter(|x| x.stale_ratio() > 0.0)
90 // .collect::<Vec<_>>();
91
92 // // Sort by stale ratio descending
93 // blob_files.sort_by(|a, b| {
94 // b.stale_ratio()
95 // .partial_cmp(&a.stale_ratio())
96 // .unwrap_or(std::cmp::Ordering::Equal)
97 // });
98
99 // let mut selection = vec![];
100
101 // let mut total_bytes = value_log.manifest.total_bytes();
102 // let mut stale_bytes = value_log.manifest.stale_bytes();
103
104 // for blob_file in blob_files {
105 // let blob_file_stale_bytes = blob_file.gc_stats.stale_bytes();
106 // stale_bytes -= blob_file_stale_bytes;
107 // total_bytes -= blob_file_stale_bytes;
108
109 // selection.push(blob_file.id);
110
111 // let space_amp_after_gc =
112 // total_bytes as f32 / (total_bytes as f32 - stale_bytes as f32);
113
114 // log::debug!(
115 // "Selected blob file #{} for GC: will reduce space amp to {space_amp_after_gc}",
116 // blob_file.id,
117 // );
118
119 // if space_amp_after_gc <= space_amp_target {
120 // break;
121 // }
122 // }
123
124 // selection
125 // }
126 }
127}