iroh_blobs/store/fs/
options.rs

1//! Options for configuring the file store.
2use std::path::{Path, PathBuf};
3
4use n0_future::time::Duration;
5
6use super::{meta::raw_outboard_size, temp_name};
7use crate::{store::gc::GcConfig, Hash};
8
9/// Options for directories used by the file store.
10#[derive(Debug, Clone)]
11pub struct PathOptions {
12    /// Path to the directory where data and outboard files are stored.
13    pub data_path: PathBuf,
14    /// Path to the directory where temp files are stored.
15    /// This *must* be on the same device as `data_path`, since we need to
16    /// atomically move temp files into place.
17    pub temp_path: PathBuf,
18}
19
20impl PathOptions {
21    pub fn new(root: &Path) -> Self {
22        Self {
23            data_path: root.join("data"),
24            temp_path: root.join("temp"),
25        }
26    }
27
28    pub fn data_path(&self, hash: &Hash) -> PathBuf {
29        self.data_path.join(format!("{}.data", hash.to_hex()))
30    }
31
32    pub fn outboard_path(&self, hash: &Hash) -> PathBuf {
33        self.data_path.join(format!("{}.obao4", hash.to_hex()))
34    }
35
36    pub fn sizes_path(&self, hash: &Hash) -> PathBuf {
37        self.data_path.join(format!("{}.sizes4", hash.to_hex()))
38    }
39
40    pub fn bitfield_path(&self, hash: &Hash) -> PathBuf {
41        self.data_path.join(format!("{}.bitfield", hash.to_hex()))
42    }
43
44    pub fn temp_file_name(&self) -> PathBuf {
45        self.temp_path.join(temp_name())
46    }
47}
48
49/// Options for inlining small complete data or outboards.
50#[derive(Debug, Clone)]
51pub struct InlineOptions {
52    /// Maximum data size to inline.
53    pub max_data_inlined: u64,
54    /// Maximum outboard size to inline.
55    pub max_outboard_inlined: u64,
56}
57
58impl InlineOptions {
59    /// Do not inline anything, ever.
60    pub const NO_INLINE: Self = Self {
61        max_data_inlined: 0,
62        max_outboard_inlined: 0,
63    };
64    /// Always inline everything
65    pub const ALWAYS_INLINE: Self = Self {
66        max_data_inlined: u64::MAX,
67        max_outboard_inlined: u64::MAX,
68    };
69}
70
71impl Default for InlineOptions {
72    fn default() -> Self {
73        Self {
74            max_data_inlined: 1024 * 16,
75            max_outboard_inlined: 1024 * 16,
76        }
77    }
78}
79
80/// Options for transaction batching.
81#[derive(Debug, Clone)]
82pub struct BatchOptions {
83    /// Maximum number of actor messages to batch before creating a new read transaction.
84    pub max_read_batch: usize,
85    /// Maximum duration to wait before committing a read transaction.
86    pub max_read_duration: Duration,
87    /// Maximum number of actor messages to batch before committing write transaction.
88    pub max_write_batch: usize,
89    /// Maximum duration to wait before committing a write transaction.
90    pub max_write_duration: Duration,
91}
92
93impl Default for BatchOptions {
94    fn default() -> Self {
95        Self {
96            max_read_batch: 10000,
97            max_read_duration: Duration::from_secs(1),
98            max_write_batch: 1000,
99            max_write_duration: Duration::from_millis(500),
100        }
101    }
102}
103
104/// Options for the file store.
105#[derive(Debug, Clone)]
106pub struct Options {
107    /// Path options.
108    pub path: PathOptions,
109    /// Inline storage options.
110    pub inline: InlineOptions,
111    /// Transaction batching options.
112    pub batch: BatchOptions,
113    /// Gc configuration.
114    pub gc: Option<GcConfig>,
115}
116
117impl Options {
118    /// Create new optinos with the given root path and everything else default.
119    pub fn new(root: &Path) -> Self {
120        Self {
121            path: PathOptions::new(root),
122            inline: InlineOptions::default(),
123            batch: BatchOptions::default(),
124            gc: None,
125        }
126    }
127
128    // check if the data will be inlined, based on the size of the data
129    pub fn is_inlined_data(&self, data_size: u64) -> bool {
130        data_size <= self.inline.max_data_inlined
131    }
132
133    // check if the outboard will be inlined, based on the size of the *outboard*
134    pub fn is_inlined_outboard(&self, outboard_size: u64) -> bool {
135        outboard_size <= self.inline.max_outboard_inlined
136    }
137
138    // check if both the data and outboard will be inlined, based on the size of the data
139    pub fn is_inlined_all(&self, data_size: u64) -> bool {
140        let outboard_size = raw_outboard_size(data_size);
141        self.is_inlined_data(data_size) && self.is_inlined_outboard(outboard_size)
142    }
143}