1use std::time::Duration;
21
22#[derive(Debug, Clone, PartialEq)]
24pub struct IoSchedulerConfig {
25 pub max_concurrent_reads: usize,
27 pub high_priority_size_threshold: usize,
29 pub low_priority_size_threshold: usize,
31 pub queue_high_capacity: usize,
33 pub queue_normal_capacity: usize,
35 pub queue_low_capacity: usize,
37 pub starvation_prevention_interval_ms: u64,
39 pub starvation_threshold_secs: u64,
41 pub load_sample_window: usize,
43 pub load_high_threshold_ms: u64,
45 pub load_low_threshold_ms: u64,
47 pub enable_priority: bool,
49
50 pub storage_detection_enabled: bool,
53 pub sequential_detection_enabled: bool,
55 pub bandwidth_monitoring_enabled: bool,
57 pub adaptive_buffer_enabled: bool,
59 pub base_buffer_size: usize,
61 pub max_buffer_size: usize,
63 pub min_buffer_size: usize,
65}
66
67impl Default for IoSchedulerConfig {
68 fn default() -> Self {
69 Self {
70 max_concurrent_reads: 32,
71 high_priority_size_threshold: 64 * 1024, low_priority_size_threshold: 4 * 1024 * 1024, queue_high_capacity: 100,
74 queue_normal_capacity: 500,
75 queue_low_capacity: 200,
76 starvation_prevention_interval_ms: 100,
77 starvation_threshold_secs: 5,
78 load_sample_window: 10,
79 load_high_threshold_ms: 50,
80 load_low_threshold_ms: 5,
81 enable_priority: true,
82 storage_detection_enabled: true,
83 sequential_detection_enabled: true,
84 bandwidth_monitoring_enabled: true,
85 adaptive_buffer_enabled: true,
86 base_buffer_size: 128 * 1024, max_buffer_size: 1024 * 1024, min_buffer_size: 4 * 1024, }
90 }
91}
92
93impl IoSchedulerConfig {
94 pub fn new() -> Self {
96 Self::default()
97 }
98
99 pub fn validate(&self) -> Result<(), ConfigError> {
105 if self.max_concurrent_reads == 0 {
106 return Err(ConfigError::InvalidValue("max_concurrent_reads must be > 0".to_string()));
107 }
108 if self.high_priority_size_threshold >= self.low_priority_size_threshold {
109 return Err(ConfigError::InvalidValue(
110 "high_priority_size_threshold must be < low_priority_size_threshold".to_string(),
111 ));
112 }
113 if self.min_buffer_size > self.max_buffer_size {
114 return Err(ConfigError::InvalidValue("min_buffer_size must be <= max_buffer_size".to_string()));
115 }
116 if self.base_buffer_size < self.min_buffer_size || self.base_buffer_size > self.max_buffer_size {
117 return Err(ConfigError::InvalidValue(
118 "base_buffer_size must be between min_buffer_size and max_buffer_size".to_string(),
119 ));
120 }
121 Ok(())
122 }
123
124 pub fn starvation_prevention_interval(&self) -> Duration {
126 Duration::from_millis(self.starvation_prevention_interval_ms)
127 }
128
129 pub fn starvation_threshold(&self) -> Duration {
131 Duration::from_secs(self.starvation_threshold_secs)
132 }
133
134 pub fn load_high_threshold(&self) -> Duration {
136 Duration::from_millis(self.load_high_threshold_ms)
137 }
138
139 pub fn load_low_threshold(&self) -> Duration {
141 Duration::from_millis(self.load_low_threshold_ms)
142 }
143
144 pub fn with_max_concurrent_reads(mut self, value: usize) -> Self {
146 self.max_concurrent_reads = value;
147 self
148 }
149
150 pub fn with_priority_thresholds(mut self, high: usize, low: usize) -> Self {
152 self.high_priority_size_threshold = high;
153 self.low_priority_size_threshold = low;
154 self
155 }
156
157 pub fn with_buffer_sizes(mut self, base: usize, min: usize, max: usize) -> Self {
159 self.base_buffer_size = base;
160 self.min_buffer_size = min;
161 self.max_buffer_size = max;
162 self
163 }
164
165 pub fn with_priority_enabled(mut self, enabled: bool) -> Self {
167 self.enable_priority = enabled;
168 self
169 }
170}
171
172#[derive(Debug, Clone, thiserror::Error)]
174pub enum ConfigError {
175 #[error("Invalid configuration: {0}")]
177 InvalidValue(String),
178}
179
180#[derive(Debug, Clone, PartialEq)]
182pub struct IoPriorityQueueConfig {
183 pub high_capacity: usize,
185 pub normal_capacity: usize,
187 pub low_capacity: usize,
189 pub starvation_interval: Duration,
191 pub starvation_threshold: Duration,
193}
194
195impl Default for IoPriorityQueueConfig {
196 fn default() -> Self {
197 Self {
198 high_capacity: 100,
199 normal_capacity: 500,
200 low_capacity: 200,
201 starvation_interval: Duration::from_millis(100),
202 starvation_threshold: Duration::from_secs(5),
203 }
204 }
205}
206
207impl IoPriorityQueueConfig {
208 pub fn from_scheduler_config(config: &IoSchedulerConfig) -> Self {
210 Self {
211 high_capacity: config.queue_high_capacity,
212 normal_capacity: config.queue_normal_capacity,
213 low_capacity: config.queue_low_capacity,
214 starvation_interval: config.starvation_prevention_interval(),
215 starvation_threshold: config.starvation_threshold(),
216 }
217 }
218
219 pub fn total_capacity(&self) -> usize {
221 self.high_capacity + self.normal_capacity + self.low_capacity
222 }
223}
224
225#[cfg(test)]
226mod tests {
227 use super::*;
228
229 #[test]
230 fn test_default_config() {
231 let config = IoSchedulerConfig::default();
232 assert!(config.validate().is_ok());
233 assert!(config.enable_priority);
234 assert!(config.adaptive_buffer_enabled);
235 }
236
237 #[test]
238 fn test_config_validation() {
239 let config = IoSchedulerConfig::new().with_max_concurrent_reads(0);
240 assert!(config.validate().is_err());
241
242 let config = IoSchedulerConfig::new().with_priority_thresholds(1024 * 1024, 1024);
243 assert!(config.validate().is_err());
244
245 let config = IoSchedulerConfig::new().with_buffer_sizes(1024, 4096, 512);
246 assert!(config.validate().is_err());
247 }
248
249 #[test]
250 fn test_builder_pattern() {
251 let config = IoSchedulerConfig::new()
252 .with_max_concurrent_reads(64)
253 .with_priority_thresholds(32 * 1024, 8 * 1024 * 1024)
254 .with_buffer_sizes(256 * 1024, 8 * 1024, 2 * 1024 * 1024)
255 .with_priority_enabled(false);
256
257 assert_eq!(config.max_concurrent_reads, 64);
258 assert_eq!(config.high_priority_size_threshold, 32 * 1024);
259 assert!(!config.enable_priority);
260 assert!(config.validate().is_ok());
261 }
262
263 #[test]
264 fn test_priority_queue_config() {
265 let config = IoSchedulerConfig::default();
266 let pq_config = IoPriorityQueueConfig::from_scheduler_config(&config);
267
268 assert_eq!(pq_config.high_capacity, config.queue_high_capacity);
269 assert_eq!(pq_config.normal_capacity, config.queue_normal_capacity);
270 assert_eq!(pq_config.low_capacity, config.queue_low_capacity);
271 assert!(pq_config.total_capacity() > 0);
272 }
273
274 #[test]
275 fn test_duration_helpers() {
276 let config = IoSchedulerConfig::default();
277
278 assert_eq!(config.starvation_prevention_interval(), Duration::from_millis(100));
279 assert_eq!(config.starvation_threshold(), Duration::from_secs(5));
280 assert_eq!(config.load_high_threshold(), Duration::from_millis(50));
281 assert_eq!(config.load_low_threshold(), Duration::from_millis(5));
282 }
283}