#[cfg(test)] mod common; use std::collections::HashMap; use std::rc::Rc; use growthring::wal::{WALLoader, WALWriter, WALStore, WALRingId, WALBytes, WALPos}; use common::{FailGen, SingleFailGen, CountFailGen, Canvas, WALStoreEmulState, WALStoreEmul, PaintStrokes}; fn run(n: usize, m: usize, k: usize, state: &mut WALStoreEmulState, canvas: &mut Canvas, wal: WALLoader, ops: &mut Vec, ringid_map: &mut HashMap, fgen: Rc, rng: &mut R) -> Result<(), ()> { let mut wal = wal.recover(WALStoreEmul::new(state, fgen, |_, _|{}))?; for _ in 0..n { let s = (0..m).map(|_| PaintStrokes::gen_rand(1000, 10, 256, 5, rng)).collect::>(); let recs = s.iter().map(|e| e.to_bytes()).collect::>(); // write ahead let (rids, ok) = wal.grow(recs); for (e, rid) in s.iter().zip(rids.iter()) { ops.push(e.clone()); ringid_map.insert(*rid, ops.len() - 1); } ok?; //for rid in rids.iter() { // println!("got ring id: {:?}", rid); //} // WAL append done // prepare data writes for (e, rid) in s.into_iter().zip(rids.iter()) { canvas.prepaint(&e, &*rid); } // run the scheduler for a bit for _ in 0..k { if let Some((fin_rid, t)) = canvas.rand_paint(rng) { if let Some(rid) = fin_rid { wal.peel(&[rid])? } //trace.push(t); } else { break } } } while let Some((fin_rid, t)) = canvas.rand_paint(rng) { if let Some(rid) = fin_rid { wal.peel(&[rid])? } //trace.push(t); } canvas.print(40); Ok(()) } fn check(state: &mut WALStoreEmulState, canvas: &mut Canvas, wal: WALLoader, ops: &Vec, ringid_map: &HashMap) -> bool { if ops.is_empty() { return true } let mut last_idx = 0; canvas.clear_queued(); wal.recover(WALStoreEmul::new(state, Rc::new(common::ZeroFailGen), |payload, ringid| { let s = PaintStrokes::from_bytes(&payload); canvas.prepaint(&s, &ringid); last_idx = *ringid_map.get(&ringid).unwrap() + 1; })).unwrap(); println!("last = {}/{}", last_idx, ops.len() - 1); canvas.paint_all(); // recover complete let canvas0 = canvas.new_reference(&ops[..last_idx]); let res = canvas.is_same(&canvas0); if !res { canvas.print(40); canvas0.print(40); } res } fn get_nticks(n: usize, m: usize, k: usize, csize: usize) -> usize { let mut rng = ::from_seed([0; 32]); let mut state = WALStoreEmulState::new(); let wal = WALLoader::new(9, 8, 1000); let mut ops: Vec = Vec::new(); let mut ringid_map = HashMap::new(); let mut canvas = Canvas::new(csize); let fgen = Rc::new(CountFailGen::new()); run(n, m, k, &mut state, &mut canvas, wal, &mut ops, &mut ringid_map, fgen.clone(), &mut rng).unwrap(); fgen.get_count() } fn run_(n: usize, m: usize, k: usize, csize: usize) { let nticks = get_nticks(n, m, k, csize); println!("nticks = {}", nticks); for i in 0..nticks { let mut rng = ::from_seed([0; 32]); let mut state = WALStoreEmulState::new(); let wal = WALLoader::new(9, 8, 1000); let mut ops: Vec = Vec::new(); let mut ringid_map = HashMap::new(); let mut canvas = Canvas::new(csize); let fgen = Rc::new(SingleFailGen::new(i)); if run(n, m, k, &mut state, &mut canvas, wal, &mut ops, &mut ringid_map, fgen, &mut rng).is_err() { let wal = WALLoader::new(9, 8, 1000); assert!(check(&mut state, &mut canvas, wal, &ops, &ringid_map)); } } } #[test] fn test_rand_fail() { run_(100, 10, 100, 1000) }