1pub struct Disk {
2 pub visible: Vec<u8>,
3 pub durable: Vec<u8>,
4 pub operation: usize,
5 pub fail_at: Option<usize>,
6 pub write_limit: usize,
7 pub random: u64,
8}
9
10impl Disk {
11 fn interrupt(&mut self) -> std::io::Result<()> {
12 self.operation += 1;
13 if self.fail_at != Some(self.operation) {
14 return Ok(());
15 }
16 self.durable.resize(self.visible.len(), 0);
17 for (durable, visible) in self.durable.iter_mut().zip(&self.visible) {
18 self.random ^= self.random << 13;
19 self.random ^= self.random >> 7;
20 self.random ^= self.random << 17;
21 if self.random & 1 != 0 {
22 *durable = *visible;
23 }
24 }
25 Err(std::io::Error::other("Injected storage interruption"))
26 }
27}
28
29impl onestore::CommitIo for Disk {
30 fn read_at(&mut self, offset: u64, bytes: &mut [u8]) -> std::io::Result<usize> {
31 self.interrupt()?;
32 let offset = offset as usize;
33 let size = bytes
34 .len()
35 .min(193)
36 .min(self.visible.len().saturating_sub(offset));
37 bytes[..size].copy_from_slice(&self.visible[offset..offset + size]);
38 Ok(size)
39 }
40 fn write_at(&mut self, offset: u64, bytes: &[u8]) -> std::io::Result<usize> {
41 let offset = offset as usize;
42 let size = bytes.len().min(self.write_limit);
43 self.visible
44 .resize(self.visible.len().max(offset + size), 0);
45 self.visible[offset..offset + size].copy_from_slice(&bytes[..size]);
46 self.interrupt()?;
47 Ok(size)
48 }
49 fn flush(&mut self) -> std::io::Result<()> {
50 self.interrupt()?;
51 self.durable.clone_from(&self.visible);
52 Ok(())
53 }
54}