use mpi::traits::*;
use readcon_core::distrib::Comm;
use readcon_core::distrib_read::{ReadMode, read_block};
use readcon_core::distrib_write::{WriteMode, write_block};
use readcon_core::frame_index::{FrameIndex, read_sidecar};
use readcon_core::writer::ConFrameWriter;
use std::path::Path;
use std::time::Instant;
fn main() {
let a: Vec<String> = std::env::args().collect();
let input = Path::new(&a[1]);
let mode = match a[3].as_str() {
"auto" => WriteMode::Auto,
"mpiio" => WriteMode::MpiIo,
"gather" => WriteMode::Gather,
m => panic!("unknown mode {m}"),
};
let threads = a.get(4).map(|t| t.parse().unwrap());
let universe = mpi::initialize().unwrap();
let world = universe.world();
let comm = Comm::dup_of(&world);
let out_mpi = format!("{}.mpi", a[2]);
let rf = read_block(&comm, input, ReadMode::Auto, threads).unwrap();
if comm.rank() == 0 {
std::fs::write(&out_mpi, vec![b'x'; 4 << 20]).unwrap();
}
world.barrier();
let t0 = Instant::now();
let total = write_block(&comm, Path::new(&out_mpi), &rf.frames, mode, None).unwrap();
let dt = t0.elapsed().as_secs_f64() * 1e3;
if comm.rank() == 0 {
let serial = readcon_core::iterators::read_all_frames(input).unwrap();
let ser_path = format!("{}.serial", a[2]);
let t1 = Instant::now();
{
let mut w = ConFrameWriter::from_path(&ser_path).unwrap();
for f in &serial {
w.write_frame(f).unwrap();
}
w.flush().unwrap();
}
let ds = t1.elapsed().as_secs_f64() * 1e3;
let m = std::fs::read(&out_mpi).unwrap();
let s = std::fs::read(&ser_path).unwrap();
let text = std::str::from_utf8(&m).unwrap();
let side_ok = match read_sidecar(Path::new(&out_mpi)).unwrap() {
Some(idx) => idx == FrameIndex::scan(text).unwrap(),
None => serial.is_empty(),
};
let same = m == s && total as usize == m.len();
println!(
"ranks={} mode={} frames={} bytes={} write_ms={dt:.1} serial_write_ms={ds:.1} identical={same} sidecar_ok={side_ok}",
comm.size(),
a[3],
rf.n_total,
m.len()
);
if !(same && side_ok) {
std::process::exit(1);
}
}
}