use std::error::Error;
use subetha_cxc::adaptive_ring::AdaptiveRing;
type BoxErr = Box<dyn Error + Send + Sync>;
const CAPACITY: usize = 1024;
const N_ITEMS: u64 = 500;
fn main() -> Result<(), BoxErr> {
let argv: Vec<String> = std::env::args().collect();
if let Some(pos) = argv.iter().position(|a| a == "worker") {
let name = argv.get(pos + 1).cloned().unwrap_or_default();
let buggy = argv.iter().any(|a| a == "--buggy");
return worker(&name, buggy);
}
let buggy = argv.iter().any(|a| a == "--buggy");
let name = format!("subetha_open_shmfs_e2e_{}", std::process::id());
let ring = AdaptiveRing::create_shmfs(&name, 1, 1, CAPACITY)
.map_err(|e| format!("create_shmfs: {e:?}"))?;
{
let pin = ring.pin_current_shape();
for seq in 0..N_ITEMS {
pin.spsc_try_push(&seq.to_le_bytes())
.map_err(|e| format!("parent push {seq}: {e:?}"))?;
}
}
println!("parent: enqueued {N_ITEMS} items into shmfs region '{name}'");
let self_exe = std::env::current_exe()?;
let mut cmd = std::process::Command::new(&self_exe);
cmd.arg("worker").arg(&name);
if buggy {
cmd.arg("--buggy");
}
let status = cmd.status()?;
drop(ring);
let ok = status.success();
println!(
"\nRESULT open_shmfs_attach: worker_exit={} mode={} -> {}",
status.code().unwrap_or(-1),
if buggy { "buggy(create_shmfs)" } else { "open_shmfs" },
if buggy {
if ok { "UNEXPECTED PASS (buggy worker saw data?!)" } else { "PASS: create_shmfs wiped the snapshot, as the fix documents" }
} else if ok {
"PASS: open_shmfs attached and recovered every item"
} else {
"FAIL: open_shmfs lost data"
}
);
if !buggy && !ok {
std::process::exit(1);
}
Ok(())
}
fn worker(name: &str, buggy: bool) -> Result<(), BoxErr> {
let ring = if buggy {
AdaptiveRing::create_shmfs(name, 1, 1, CAPACITY)
.map_err(|e| format!("worker create_shmfs: {e:?}"))?
} else {
AdaptiveRing::open_shmfs(name, 1, 1, CAPACITY)
.map_err(|e| format!("worker open_shmfs: {e:?}"))?
};
let pin = ring.pin_current_shape();
let mut got = 0u64;
let mut buf = [0u8; 64];
for expect in 0..N_ITEMS {
match pin.spsc_try_pop(&mut buf) {
Ok(n) if n >= 8 => {
let seq = u64::from_le_bytes(buf[..8].try_into().unwrap());
if seq != expect {
eprintln!("worker: order/value mismatch at {expect}: got {seq}");
std::process::exit(1);
}
got += 1;
}
_ => break, }
}
if got == N_ITEMS {
println!("worker: recovered all {got} items in order (attach preserved the snapshot)");
Ok(())
} else {
eprintln!("worker: recovered only {got}/{N_ITEMS} items (region was re-initialised / wiped)");
std::process::exit(1);
}
}