Skip to main content

moonpool_sim/storage/
config.rs

1//! # Storage Simulation Configuration
2//!
3//! This module provides configuration for storage simulation, following
4//! FoundationDB's battle-tested simulation approach and TigerBeetle's deterministic
5//! testing patterns.
6//!
7//! ## Performance Parameters
8//!
9//! | Parameter | Config Field | Default | Description |
10//! |-----------|--------------|---------|-------------|
11//! | IOPS | `iops` | 25,000 | I/O operations per second limit |
12//! | Bandwidth | `bandwidth` | 150 MB/s | Maximum throughput in bytes/sec |
13//! | Read latency | `read_latency` | 50-200µs | Time for read operations |
14//! | Write latency | `write_latency` | 100-500µs | Time for write operations |
15//! | Sync latency | `sync_latency` | 1-5ms | Time for sync operations |
16//!
17//! ## Fault Injection
18//!
19//! | Fault | Config Field | Default | Real-World Scenario |
20//! |-------|--------------|---------|---------------------|
21//! | Read fault | `read_fault_probability` | 0% | Disk read errors, ECC failures |
22//! | Write fault | `write_fault_probability` | 0% | Write failures, disk full |
23//! | Crash fault | `crash_fault_probability` | 0% | Sudden power loss simulation |
24//! | Misdirected write | `misdirect_write_probability` | 0% | Write lands at wrong location |
25//! | Misdirected read | `misdirect_read_probability` | 0% | Read returns wrong data |
26//! | Phantom write | `phantom_write_probability` | 0% | Write appears to succeed but doesn't persist |
27//! | Sync failure | `sync_failure_probability` | 0% | fsync fails |
28//!
29//! ## Configuration Examples
30//!
31//! ### Fast Local Testing (No Chaos)
32//! ```rust
33//! use moonpool_sim::storage::StorageConfiguration;
34//!
35//! let config = StorageConfiguration::fast_local();
36//! // All faults disabled, minimal latencies
37//! ```
38//!
39//! ### Full Chaos Testing
40//! ```rust
41//! use moonpool_sim::storage::StorageConfiguration;
42//!
43//! let config = StorageConfiguration::random_for_seed();
44//! // Randomized fault parameters for comprehensive testing
45//! ```
46//!
47//! ## FDB/TigerBeetle References
48//!
49//! - Simulated file operations: FDB sim2.actor.cpp
50//! - Storage faults: TigerBeetle storage simulation
51//! - Crash consistency: FDB AsyncFileKAIO, TigerBeetle deterministic testing
52
53use crate::sim::rng::sim_random_range;
54use std::ops::Range;
55use std::time::Duration;
56
57/// Configuration for storage simulation parameters.
58///
59/// This struct contains all settings related to storage simulation including
60/// performance characteristics and fault injection probabilities.
61#[derive(Debug, Clone)]
62pub struct StorageConfiguration {
63    // =========================================================================
64    // Performance Parameters
65    // =========================================================================
66    /// I/O operations per second limit.
67    ///
68    /// Typical values:
69    /// - NVMe SSD: 100,000-500,000 IOPS
70    /// - SATA SSD: 25,000-100,000 IOPS
71    /// - HDD: 100-200 IOPS
72    pub iops: u64,
73
74    /// Maximum bandwidth in bytes per second.
75    ///
76    /// Typical values:
77    /// - NVMe SSD: 3,000-7,000 MB/s
78    /// - SATA SSD: 500-600 MB/s
79    /// - HDD: 100-200 MB/s
80    pub bandwidth: u64,
81
82    /// Latency range for read operations.
83    ///
84    /// Typical values:
85    /// - NVMe SSD: 20-100µs
86    /// - SATA SSD: 50-200µs
87    /// - HDD: 2-10ms
88    pub read_latency: Range<Duration>,
89
90    /// Latency range for write operations.
91    ///
92    /// Typical values:
93    /// - NVMe SSD: 20-100µs
94    /// - SATA SSD: 100-500µs
95    /// - HDD: 2-10ms
96    pub write_latency: Range<Duration>,
97
98    /// Latency range for sync/flush operations.
99    ///
100    /// Sync operations ensure data durability and typically take
101    /// longer than regular read/write operations.
102    pub sync_latency: Range<Duration>,
103
104    // =========================================================================
105    // Fault Injection Probabilities
106    // =========================================================================
107    /// Probability of read operation failing (0.0 - 1.0).
108    ///
109    /// # Real-World Scenario
110    /// Simulates disk read errors, ECC failures, or media degradation.
111    pub read_fault_probability: f64,
112
113    /// Probability of write operation failing (0.0 - 1.0).
114    ///
115    /// # Real-World Scenario
116    /// Simulates write failures due to disk full, bad sectors, or media errors.
117    pub write_fault_probability: f64,
118
119    /// Probability of crash fault during operation (0.0 - 1.0).
120    ///
121    /// # Real-World Scenario
122    /// Simulates sudden power loss or system crash during I/O.
123    /// Tests crash consistency and recovery logic.
124    pub crash_fault_probability: f64,
125
126    /// Probability of write landing at wrong location (0.0 - 1.0).
127    ///
128    /// # Real-World Scenario
129    /// Simulates misdirected writes where data is written to a different
130    /// block than intended. Tests checksum validation and corruption detection.
131    /// TigerBeetle ref: storage fault injection
132    pub misdirect_write_probability: f64,
133
134    /// Probability of read returning data from wrong location (0.0 - 1.0).
135    ///
136    /// # Real-World Scenario
137    /// Simulates misdirected reads where data is read from a different
138    /// block than intended. Tests checksum validation.
139    /// TigerBeetle ref: storage fault injection
140    pub misdirect_read_probability: f64,
141
142    /// Probability of write appearing to succeed but not persisting (0.0 - 1.0).
143    ///
144    /// # Real-World Scenario
145    /// Simulates phantom writes where the write reports success but data
146    /// is lost before reaching stable storage. Tests durability guarantees.
147    pub phantom_write_probability: f64,
148
149    /// Probability of sync/flush operation failing (0.0 - 1.0).
150    ///
151    /// # Real-World Scenario
152    /// Simulates fsync failures which can indicate serious storage issues.
153    /// Tests error handling in durability-critical code paths.
154    pub sync_failure_probability: f64,
155}
156
157impl Default for StorageConfiguration {
158    fn default() -> Self {
159        Self {
160            // Performance parameters matching a typical SATA SSD
161            iops: 25_000,
162            bandwidth: 150_000_000, // 150 MB/s
163            read_latency: Duration::from_micros(50)..Duration::from_micros(200),
164            write_latency: Duration::from_micros(100)..Duration::from_micros(500),
165            sync_latency: Duration::from_millis(1)..Duration::from_millis(5),
166
167            // Fault probabilities - disabled by default for predictable behavior
168            read_fault_probability: 0.0,
169            write_fault_probability: 0.0,
170            crash_fault_probability: 0.0,
171            misdirect_write_probability: 0.0,
172            misdirect_read_probability: 0.0,
173            phantom_write_probability: 0.0,
174            sync_failure_probability: 0.0,
175        }
176    }
177}
178
179impl StorageConfiguration {
180    /// Create a new storage configuration with default settings.
181    pub fn new() -> Self {
182        Self::default()
183    }
184
185    /// Create a randomized storage configuration for chaos testing.
186    ///
187    /// Uses deterministic random values based on the simulation seed
188    /// to create varied configurations across test runs.
189    pub fn random_for_seed() -> Self {
190        Self {
191            // Randomize IOPS between 10,000 and 100,000
192            iops: sim_random_range(10_000..100_000),
193
194            // Randomize bandwidth between 50 MB/s and 500 MB/s
195            bandwidth: sim_random_range(50_000_000..500_000_000),
196
197            // Randomize latencies
198            read_latency: Duration::from_micros(sim_random_range(20..100))
199                ..Duration::from_micros(sim_random_range(100..500)),
200            write_latency: Duration::from_micros(sim_random_range(50..200))
201                ..Duration::from_micros(sim_random_range(200..1000)),
202            sync_latency: Duration::from_micros(sim_random_range(500..2000))
203                ..Duration::from_micros(sim_random_range(2000..10000)),
204
205            // Low fault probabilities for chaos testing (0.001% to 0.1%)
206            read_fault_probability: sim_random_range(0..100) as f64 / 100_000.0,
207            write_fault_probability: sim_random_range(0..100) as f64 / 100_000.0,
208            crash_fault_probability: sim_random_range(0..50) as f64 / 100_000.0,
209            misdirect_write_probability: sim_random_range(0..10) as f64 / 100_000.0,
210            misdirect_read_probability: sim_random_range(0..10) as f64 / 100_000.0,
211            phantom_write_probability: sim_random_range(0..20) as f64 / 100_000.0,
212            sync_failure_probability: sim_random_range(0..50) as f64 / 100_000.0,
213        }
214    }
215
216    /// Create a configuration optimized for fast local testing.
217    ///
218    /// Minimal latencies and no fault injection for predictable,
219    /// fast test execution.
220    pub fn fast_local() -> Self {
221        let one_us = Duration::from_micros(1);
222        Self {
223            iops: 1_000_000,          // Very high IOPS
224            bandwidth: 1_000_000_000, // 1 GB/s
225            read_latency: one_us..one_us,
226            write_latency: one_us..one_us,
227            sync_latency: one_us..one_us,
228
229            // All faults disabled
230            read_fault_probability: 0.0,
231            write_fault_probability: 0.0,
232            crash_fault_probability: 0.0,
233            misdirect_write_probability: 0.0,
234            misdirect_read_probability: 0.0,
235            phantom_write_probability: 0.0,
236            sync_failure_probability: 0.0,
237        }
238    }
239}