1mod block_size;
6mod compression;
7mod filter;
8mod hash_ratio;
9mod pinning;
10mod restart_interval;
11
12pub use block_size::BlockSizePolicy;
13pub use compression::CompressionPolicy;
14pub use filter::{BloomConstructionPolicy, FilterPolicy, FilterPolicyEntry};
15pub use hash_ratio::HashRatioPolicy;
16pub use pinning::PinningPolicy;
17pub use restart_interval::RestartIntervalPolicy;
18
19use crate::{
20 path::absolute_path, version::DEFAULT_LEVEL_COUNT, AnyTree, BlobTree, Cache, CompressionType,
21 DescriptorTable, Tree,
22};
23use std::{
24 path::{Path, PathBuf},
25 sync::Arc,
26};
27
28#[derive(Copy, Clone, Debug, PartialEq, Eq)]
30pub enum TreeType {
31 Standard,
33
34 Blob,
36}
37
38impl From<TreeType> for u8 {
39 fn from(val: TreeType) -> Self {
40 match val {
41 TreeType::Standard => 0,
42 TreeType::Blob => 1,
43 }
44 }
45}
46
47impl TryFrom<u8> for TreeType {
48 type Error = ();
49
50 fn try_from(value: u8) -> Result<Self, Self::Error> {
51 match value {
52 0 => Ok(Self::Standard),
53 1 => Ok(Self::Blob),
54 _ => Err(()),
55 }
56 }
57}
58
59const DEFAULT_FILE_FOLDER: &str = ".lsm.data";
60
61#[derive(Clone, Debug, PartialEq)]
63pub struct KvSeparationOptions {
64 pub compression: CompressionType,
66
67 #[doc(hidden)]
69 pub file_target_size: u64,
70
71 #[doc(hidden)]
73 pub separation_threshold: u32,
74
75 pub(crate) staleness_threshold: f32,
76
77 pub(crate) age_cutoff: f32,
78}
79
80impl Default for KvSeparationOptions {
81 fn default() -> Self {
82 Self {
83 #[cfg(feature="lz4")]
84 compression: CompressionType::Lz4,
85
86 #[cfg(not(feature="lz4"))]
87 compression: CompressionType::None,
88
89 file_target_size: 64 * 1_024 * 1_024,
90 separation_threshold: 1_024,
91
92 staleness_threshold: 0.33,
93 age_cutoff: 0.20,
94 }
95 }
96}
97
98impl KvSeparationOptions {
99 #[must_use]
101 pub fn compression(mut self, compression: CompressionType) -> Self {
102 self.compression = compression;
103 self
104 }
105
106 #[must_use]
116 pub fn file_target_size(mut self, bytes: u64) -> Self {
117 self.file_target_size = bytes;
118 self
119 }
120
121 #[must_use]
128 pub fn separation_threshold(mut self, bytes: u32) -> Self {
129 self.separation_threshold = bytes;
130 self
131 }
132
133 #[must_use]
140 pub fn staleness_threshold(mut self, ratio: f32) -> Self {
141 self.staleness_threshold = ratio;
142 self
143 }
144
145 #[must_use]
149 pub fn age_cutoff(mut self, ratio: f32) -> Self {
150 self.age_cutoff = ratio;
151 self
152 }
153}
154
155#[derive(Clone)]
156pub struct Config {
158 #[doc(hidden)]
160 pub path: PathBuf,
161
162 #[doc(hidden)]
164 pub cache: Arc<Cache>,
165
166 #[doc(hidden)]
168 pub descriptor_table: Arc<DescriptorTable>,
169
170 pub level_count: u8,
174
175 pub data_block_compression_policy: CompressionPolicy,
177
178 pub index_block_compression_policy: CompressionPolicy,
180
181 pub data_block_restart_interval_policy: RestartIntervalPolicy,
183
184 pub index_block_restart_interval_policy: RestartIntervalPolicy,
186
187 pub data_block_size_policy: BlockSizePolicy,
189
190 pub index_block_size_policy: BlockSizePolicy,
192
193 pub index_block_pinning_policy: PinningPolicy,
195
196 pub filter_block_pinning_policy: PinningPolicy,
198
199 pub data_block_hash_ratio_policy: HashRatioPolicy,
201
202 pub(crate) expect_point_read_hits: bool,
205
206 pub filter_policy: FilterPolicy,
208
209 #[doc(hidden)]
210 pub kv_separation_opts: Option<KvSeparationOptions>,
211}
212
213impl Default for Config {
214 fn default() -> Self {
215 Self {
216 path: absolute_path(Path::new(DEFAULT_FILE_FOLDER)),
217 descriptor_table: Arc::new(DescriptorTable::new(256)),
218
219 cache: Arc::new(Cache::with_capacity_bytes(
220 16 * 1_024 * 1_024,
221 )),
222
223 data_block_restart_interval_policy: RestartIntervalPolicy::all(16),
224 index_block_restart_interval_policy: RestartIntervalPolicy::all(1),
225
226 level_count: DEFAULT_LEVEL_COUNT,
227
228 data_block_size_policy: BlockSizePolicy::default(),
229 index_block_size_policy: BlockSizePolicy::default(),
230
231 index_block_pinning_policy: PinningPolicy::new(&[true, true, false]),
232 filter_block_pinning_policy: PinningPolicy::new(&[true, false]),
233
234 data_block_compression_policy: CompressionPolicy::default(),
235 index_block_compression_policy: CompressionPolicy::all(CompressionType::None),
236
237 data_block_hash_ratio_policy: HashRatioPolicy::all(0.0),
238
239 filter_policy: FilterPolicy::default(),
240
241 expect_point_read_hits: false,
242
243 kv_separation_opts: None,
244 }
245 }
246}
247
248impl Config {
249 pub fn new<P: AsRef<Path>>(path: P) -> Self {
251 Self {
252 path: absolute_path(path.as_ref()),
253 ..Default::default()
254 }
255 }
256
257 #[must_use]
264 pub fn use_cache(mut self, cache: Arc<Cache>) -> Self {
265 self.cache = cache;
266 self
267 }
268
269 #[must_use]
270 #[doc(hidden)]
271 pub fn use_descriptor_table(mut self, descriptor_table: Arc<DescriptorTable>) -> Self {
272 self.descriptor_table = descriptor_table;
273 self
274 }
275
276 #[must_use]
281 pub fn expect_point_read_hits(mut self, b: bool) -> Self {
282 self.expect_point_read_hits = b;
283 self
284 }
285
286 #[must_use]
288 pub fn filter_block_pinning_policy(mut self, policy: PinningPolicy) -> Self {
289 self.filter_block_pinning_policy = policy;
290 self
291 }
292
293 #[must_use]
295 pub fn index_block_pinning_policy(mut self, policy: PinningPolicy) -> Self {
296 self.index_block_pinning_policy = policy;
297 self
298 }
299
300 #[must_use]
307 pub fn data_block_restart_interval_policy(mut self, policy: RestartIntervalPolicy) -> Self {
308 self.data_block_restart_interval_policy = policy;
309 self
310 }
311
312 #[must_use]
327 pub fn filter_policy(mut self, policy: FilterPolicy) -> Self {
328 self.filter_policy = policy;
329 self
330 }
331
332 #[must_use]
334 pub fn data_block_compression_policy(mut self, policy: CompressionPolicy) -> Self {
335 self.data_block_compression_policy = policy;
336 self
337 }
338
339 #[must_use]
341 pub fn index_block_compression_policy(mut self, policy: CompressionPolicy) -> Self {
342 self.index_block_compression_policy = policy;
343 self
344 }
345
346 #[must_use]
366 pub fn data_block_size_policy(mut self, policy: BlockSizePolicy) -> Self {
367 self.data_block_size_policy = policy;
368 self
369 }
370
371 #[must_use]
384 pub fn data_block_hash_ratio_policy(mut self, policy: HashRatioPolicy) -> Self {
385 self.data_block_hash_ratio_policy = policy;
386 self
387 }
388
389 #[must_use]
391 pub fn with_kv_separation(mut self, opts: Option<KvSeparationOptions>) -> Self {
392 self.kv_separation_opts = opts;
393 self
394 }
395
396 pub fn open(self) -> crate::Result<AnyTree> {
402 Ok(if self.kv_separation_opts.is_some() {
403 AnyTree::Blob(BlobTree::open(self)?)
404 } else {
405 AnyTree::Standard(Tree::open(self)?)
406 })
407 }
408}