rustfs_config/constants/scanner.rs
1// Copyright 2024 RustFS Team
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7// http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
15use std::time::Duration;
16
17/// Scanner admin config subsystem name.
18pub const SCANNER_SUB_SYS: &str = "scanner";
19
20/// Scanner config key selecting the speed preset.
21pub const SCANNER_SPEED: &str = "speed";
22
23/// Scanner config key overriding the scanner sleep multiplier.
24pub const SCANNER_DELAY: &str = "delay";
25
26/// Scanner config key overriding the maximum scanner sleep in seconds.
27pub const SCANNER_MAX_WAIT: &str = "max_wait";
28
29/// Scanner config key overriding the cycle interval in seconds.
30pub const SCANNER_CYCLE: &str = "cycle";
31
32/// Scanner config key setting the startup delay in seconds.
33///
34/// For compatibility, this also acts as the scanner cycle interval when
35/// `cycle` is unset.
36pub const SCANNER_START_DELAY: &str = "start_delay";
37
38/// Scanner config key capping one cycle's runtime in seconds.
39pub const SCANNER_CYCLE_MAX_DURATION: &str = "cycle_max_duration";
40
41/// Scanner config key capping objects processed by one cycle.
42pub const SCANNER_CYCLE_MAX_OBJECTS: &str = "cycle_max_objects";
43
44/// Scanner config key capping directories entered by one cycle.
45pub const SCANNER_CYCLE_MAX_DIRECTORIES: &str = "cycle_max_directories";
46
47/// Scanner config key setting the periodic bitrot scan cycle in seconds.
48pub const SCANNER_BITROT_CYCLE: &str = "bitrot_cycle";
49
50/// Scanner config key controlling whether scanner throttling is enabled.
51pub const SCANNER_IDLE_MODE: &str = "idle_mode";
52
53/// Scanner config key controlling scanner cache save timeout in seconds.
54pub const SCANNER_CACHE_SAVE_TIMEOUT: &str = "cache_save_timeout";
55
56/// Scanner config key capping concurrent scanner set tasks.
57pub const SCANNER_MAX_CONCURRENT_SET_SCANS: &str = "max_concurrent_set_scans";
58
59/// Scanner config key capping concurrent scanner disk bucket walks per set.
60pub const SCANNER_MAX_CONCURRENT_DISK_SCANS: &str = "max_concurrent_disk_scans";
61
62/// Scanner config key controlling how often object loops yield.
63pub const SCANNER_YIELD_EVERY_N_OBJECTS: &str = "yield_every_n_objects";
64
65/// Scanner config key controlling object version count alerts.
66pub const SCANNER_ALERT_EXCESS_VERSIONS: &str = "alert_excess_versions";
67
68/// Scanner config key controlling retained version size alerts.
69pub const SCANNER_ALERT_EXCESS_VERSION_SIZE: &str = "alert_excess_version_size";
70
71/// Scanner config key controlling direct subfolder count alerts.
72pub const SCANNER_ALERT_EXCESS_FOLDERS: &str = "alert_excess_folders";
73
74/// Scanner config keys supported by the admin config subsystem.
75pub const SCANNER_KEYS: &[&str] = &[
76 SCANNER_SPEED,
77 SCANNER_DELAY,
78 SCANNER_MAX_WAIT,
79 SCANNER_CYCLE,
80 SCANNER_START_DELAY,
81 SCANNER_CYCLE_MAX_DURATION,
82 SCANNER_CYCLE_MAX_OBJECTS,
83 SCANNER_CYCLE_MAX_DIRECTORIES,
84 SCANNER_BITROT_CYCLE,
85 SCANNER_IDLE_MODE,
86 SCANNER_CACHE_SAVE_TIMEOUT,
87 SCANNER_MAX_CONCURRENT_SET_SCANS,
88 SCANNER_MAX_CONCURRENT_DISK_SCANS,
89 SCANNER_YIELD_EVERY_N_OBJECTS,
90 SCANNER_ALERT_EXCESS_VERSIONS,
91 SCANNER_ALERT_EXCESS_VERSION_SIZE,
92 SCANNER_ALERT_EXCESS_FOLDERS,
93];
94
95/// Canonical environment variable name that specifies the scanner start delay in seconds.
96/// If set, this overrides the cycle interval derived from `RUSTFS_SCANNER_SPEED`.
97/// - Unit: seconds (u64).
98/// - Example: `export RUSTFS_SCANNER_START_DELAY_SECS=10`
99pub const ENV_SCANNER_START_DELAY_SECS: &str = "RUSTFS_SCANNER_START_DELAY_SECS";
100
101/// Deprecated compatibility alias for scanner start delay.
102/// Prefer `RUSTFS_SCANNER_START_DELAY_SECS`.
103#[deprecated(note = "Use RUSTFS_SCANNER_START_DELAY_SECS instead")]
104pub const ENV_DATA_SCANNER_START_DELAY_SECS: &str = "RUSTFS_DATA_SCANNER_START_DELAY_SECS";
105
106/// Environment variable that specifies the scanner cycle interval in seconds.
107/// If set, this overrides the cycle interval derived from `RUSTFS_SCANNER_SPEED`.
108/// - Unit: seconds (u64).
109/// - Example: `export RUSTFS_SCANNER_CYCLE=3600` (1 hour)
110pub const ENV_SCANNER_CYCLE: &str = "RUSTFS_SCANNER_CYCLE";
111
112/// Environment variable that caps one scanner cycle's runtime in seconds.
113/// A value of `0` disables the cycle runtime budget.
114/// - Unit: seconds (u64).
115/// - Example: `export RUSTFS_SCANNER_CYCLE_MAX_DURATION_SECS=1800`
116pub const ENV_SCANNER_CYCLE_MAX_DURATION_SECS: &str = "RUSTFS_SCANNER_CYCLE_MAX_DURATION_SECS";
117
118/// Environment variable that caps objects processed by one scanner cycle.
119/// A value of `0` disables the per-cycle object budget.
120/// - Example: `export RUSTFS_SCANNER_CYCLE_MAX_OBJECTS=1000000`
121pub const ENV_SCANNER_CYCLE_MAX_OBJECTS: &str = "RUSTFS_SCANNER_CYCLE_MAX_OBJECTS";
122
123/// Environment variable that caps directories entered by one scanner cycle.
124/// A value of `0` disables the per-cycle directory budget.
125/// - Example: `export RUSTFS_SCANNER_CYCLE_MAX_DIRECTORIES=100000`
126pub const ENV_SCANNER_CYCLE_MAX_DIRECTORIES: &str = "RUSTFS_SCANNER_CYCLE_MAX_DIRECTORIES";
127
128/// Environment variable that selects the scanner speed preset.
129/// Valid values: `fastest`, `fast`, `default`, `slow`, `slowest`.
130/// Controls the sleep factor, maximum sleep duration, and cycle interval.
131/// - Example: `export RUSTFS_SCANNER_SPEED=slow`
132pub const ENV_SCANNER_SPEED: &str = "RUSTFS_SCANNER_SPEED";
133
134/// Environment variable that overrides the scanner sleep multiplier.
135/// - Example: `export RUSTFS_SCANNER_DELAY=30.0`
136pub const ENV_SCANNER_DELAY: &str = "RUSTFS_SCANNER_DELAY";
137
138/// Environment variable that overrides the maximum scanner sleep in seconds.
139/// - Unit: seconds (u64).
140/// - Example: `export RUSTFS_SCANNER_MAX_WAIT_SECS=15`
141pub const ENV_SCANNER_MAX_WAIT_SECS: &str = "RUSTFS_SCANNER_MAX_WAIT_SECS";
142
143/// Default scanner speed preset.
144pub const DEFAULT_SCANNER_SPEED: &str = "default";
145
146/// Default scanner cycle runtime budget when no override is configured.
147///
148/// An explicit `0` remains the compatibility escape hatch for an unbounded
149/// cycle. Keeping the unset default finite prevents a stalled scanner I/O
150/// operation from holding the leader lease forever.
151pub const DEFAULT_SCANNER_CYCLE_MAX_DURATION_SECS: u64 = 30 * 60;
152
153/// Default scanner per-cycle object budget.
154/// `0` keeps the existing unbounded per-cycle behavior.
155pub const DEFAULT_SCANNER_CYCLE_MAX_OBJECTS: u64 = 0;
156
157/// Default scanner per-cycle directory budget.
158/// `0` keeps the existing unbounded per-cycle behavior.
159pub const DEFAULT_SCANNER_CYCLE_MAX_DIRECTORIES: u64 = 0;
160
161/// Environment variable that specifies the periodic bitrot scan cycle in seconds.
162/// When set to `0`, `true`, `on`, or `yes`, every scanner cycle runs in deep mode.
163/// When set to `false`, `off`, `no`, or `disabled`, periodic deep scans are disabled.
164/// - Unit: seconds (u64).
165/// - Example: `export RUSTFS_SCANNER_BITROT_CYCLE_SECS=2592000` (30 days)
166pub const ENV_SCANNER_BITROT_CYCLE_SECS: &str = "RUSTFS_SCANNER_BITROT_CYCLE_SECS";
167
168/// Default bitrot scan cycle used by the scanner.
169pub const DEFAULT_SCANNER_BITROT_CYCLE_SECS: u64 = 30 * 24 * 60 * 60;
170
171/// Environment variable that controls how many object versions trigger scanner alerts.
172/// - Example: `export RUSTFS_SCANNER_ALERT_EXCESS_VERSIONS=100`
173pub const ENV_SCANNER_ALERT_EXCESS_VERSIONS: &str = "RUSTFS_SCANNER_ALERT_EXCESS_VERSIONS";
174
175/// Default object version count that triggers scanner alerts.
176pub const DEFAULT_SCANNER_ALERT_EXCESS_VERSIONS: u64 = 100;
177
178/// Environment variable that controls how many cumulative bytes across object versions trigger scanner alerts.
179/// - Example: `export RUSTFS_SCANNER_ALERT_EXCESS_VERSION_SIZE=1099511627776`
180pub const ENV_SCANNER_ALERT_EXCESS_VERSION_SIZE: &str = "RUSTFS_SCANNER_ALERT_EXCESS_VERSION_SIZE";
181
182/// Default cumulative object version bytes that trigger scanner alerts.
183pub const DEFAULT_SCANNER_ALERT_EXCESS_VERSION_SIZE: u64 = 1024 * 1024 * 1024 * 1024;
184
185/// Environment variable that controls how many subfolders trigger scanner alerts.
186/// - Example: `export RUSTFS_SCANNER_ALERT_EXCESS_FOLDERS=65538`
187pub const ENV_SCANNER_ALERT_EXCESS_FOLDERS: &str = "RUSTFS_SCANNER_ALERT_EXCESS_FOLDERS";
188
189/// Default subfolder count that triggers scanner alerts.
190/// Allows Proxmox Backup Server's chunk namespace layout.
191pub const DEFAULT_SCANNER_ALERT_EXCESS_FOLDERS: u64 = 65_538;
192
193/// Environment variable that controls whether the scanner sleeps between operations.
194/// When `true` (default), the scanner throttles itself. When `false`, it runs at full speed.
195/// - Example: `export RUSTFS_SCANNER_IDLE_MODE=false`
196pub const ENV_SCANNER_IDLE_MODE: &str = "RUSTFS_SCANNER_IDLE_MODE";
197
198/// Environment variable that controls scanner cache save timeout in seconds.
199/// The scanner enforces a minimum value of `1`.
200/// - Unit: seconds (u64).
201/// - Example: `export RUSTFS_SCANNER_CACHE_SAVE_TIMEOUT_SECS=14`
202pub const ENV_SCANNER_CACHE_SAVE_TIMEOUT_SECS: &str = "RUSTFS_SCANNER_CACHE_SAVE_TIMEOUT_SECS";
203
204/// Default scanner cache save timeout in seconds.
205pub const DEFAULT_SCANNER_CACHE_SAVE_TIMEOUT_SECS: u64 = 14;
206
207/// Environment variable that caps concurrent scanner set tasks.
208/// A value of `0` keeps the existing topology-based concurrency.
209/// - Example: `export RUSTFS_SCANNER_MAX_CONCURRENT_SET_SCANS=2`
210pub const ENV_SCANNER_MAX_CONCURRENT_SET_SCANS: &str = "RUSTFS_SCANNER_MAX_CONCURRENT_SET_SCANS";
211
212/// Environment variable that caps concurrent scanner disk bucket walks per set.
213/// A value of `0` keeps the existing disk-count-based concurrency.
214/// - Example: `export RUSTFS_SCANNER_MAX_CONCURRENT_DISK_SCANS=1`
215pub const ENV_SCANNER_MAX_CONCURRENT_DISK_SCANS: &str = "RUSTFS_SCANNER_MAX_CONCURRENT_DISK_SCANS";
216
217/// Environment variable that controls how often scanner object loops yield to the async runtime.
218/// A value of `0` disables this extra object-count yield.
219/// - Example: `export RUSTFS_SCANNER_YIELD_EVERY_N_OBJECTS=32`
220pub const ENV_SCANNER_YIELD_EVERY_N_OBJECTS: &str = "RUSTFS_SCANNER_YIELD_EVERY_N_OBJECTS";
221
222/// Default scanner idle mode.
223pub const DEFAULT_SCANNER_IDLE_MODE: bool = true;
224
225/// Default set scan concurrency budget.
226pub const DEFAULT_SCANNER_MAX_CONCURRENT_SET_SCANS: usize = 4;
227
228/// Default disk scan concurrency budget.
229pub const DEFAULT_SCANNER_MAX_CONCURRENT_DISK_SCANS: usize = 4;
230
231/// Default object interval for cooperative scanner yields.
232pub const DEFAULT_SCANNER_YIELD_EVERY_N_OBJECTS: u64 = 128;
233
234/// Scanner speed preset controlling throttling behavior.
235///
236/// Each preset defines three parameters:
237/// - **sleep_factor**: Multiplier applied to elapsed work time to compute inter-object sleep.
238/// - **max_sleep**: Upper bound on any single throttle sleep.
239/// - **cycle_interval**: Base delay between scan cycles.
240///
241/// | Preset | Factor | Max Sleep | Cycle Interval |
242/// |-----------|--------|-----------|----------------|
243/// | `fastest` | 0 | 0 | 1 second |
244/// | `fast` | 1x | 100ms | 1 minute |
245/// | `default` | 2x | 1 second | 1 minute |
246/// | `slow` | 10x | 15 seconds| 1 minute |
247/// | `slowest` | 100x | 15 seconds| 30 minutes |
248///
249/// The sleep factor, max sleep, and cycle interval can be overridden by
250/// `RUSTFS_SCANNER_DELAY`, `RUSTFS_SCANNER_MAX_WAIT_SECS`, and
251/// `RUSTFS_SCANNER_CYCLE`.
252#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
253pub enum ScannerSpeed {
254 Fastest,
255 Fast,
256 #[default]
257 Default,
258 Slow,
259 Slowest,
260}
261
262impl ScannerSpeed {
263 pub fn sleep_factor(self) -> f64 {
264 match self {
265 Self::Fastest => 0.0,
266 Self::Fast => 1.0,
267 Self::Default => 2.0,
268 Self::Slow => 10.0,
269 Self::Slowest => 100.0,
270 }
271 }
272
273 pub fn max_sleep(self) -> Duration {
274 match self {
275 Self::Fastest => Duration::ZERO,
276 Self::Fast => Duration::from_millis(100),
277 Self::Default => Duration::from_secs(1),
278 Self::Slow | Self::Slowest => Duration::from_secs(15),
279 }
280 }
281
282 pub fn cycle_interval(self) -> Duration {
283 match self {
284 Self::Fastest => Duration::from_secs(1),
285 Self::Fast | Self::Default | Self::Slow => Duration::from_secs(60),
286 Self::Slowest => Duration::from_secs(30 * 60),
287 }
288 }
289
290 pub fn parse_str(s: &str) -> Option<Self> {
291 match s.trim().to_ascii_lowercase().as_str() {
292 "fastest" => Some(Self::Fastest),
293 "fast" => Some(Self::Fast),
294 "default" => Some(Self::Default),
295 "slow" => Some(Self::Slow),
296 "slowest" => Some(Self::Slowest),
297 _ => None,
298 }
299 }
300
301 pub fn from_env_str(s: &str) -> Self {
302 Self::parse_str(s).unwrap_or_default()
303 }
304}
305
306impl std::fmt::Display for ScannerSpeed {
307 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
308 match self {
309 Self::Fastest => write!(f, "fastest"),
310 Self::Fast => write!(f, "fast"),
311 Self::Default => write!(f, "default"),
312 Self::Slow => write!(f, "slow"),
313 Self::Slowest => write!(f, "slowest"),
314 }
315 }
316}