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}