iroh_blobs/store/fs/
options.rs

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