iroh_blobs/store/fs/
options.rs

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