use std::io;
use crate::ring::IoUring;
#[derive(Clone, Copy, Debug)]
pub struct FileRead {
pub fd: i32,
pub offset: u64,
pub len: u32,
}
impl IoUring {
pub fn read_file_batch(&mut self, reads: &[FileRead]) -> io::Result<(Vec<Vec<u8>>, u64)> {
let mut bufs: Vec<Vec<u8>> = reads.iter().map(|r| vec![0u8; r.len as usize]).collect();
let mut submissions = 0u64;
let mut done = 0usize;
while done < reads.len() {
let mut in_chunk = 0u32;
for i in done..reads.len() {
let (r, buf) = (&reads[i], &mut bufs[i]);
let ok = unsafe {
self.prep_read_at(r.fd, buf.as_mut_ptr(), r.len, r.offset, i as u64)
};
if !ok {
break; }
in_chunk += 1;
}
debug_assert!(in_chunk > 0, "an empty SQ accepts at least one SQE");
if let Err(e) = self.submit_and_wait(in_chunk) {
std::mem::forget(bufs);
return Err(e);
}
submissions += 1;
let mut bad: Option<(usize, i32)> = None;
self.for_each_completion(|c| {
let i = c.user_data as usize;
if c.res != reads[i].len as i32 && bad.is_none() {
bad = Some((i, c.res));
}
});
if let Some((i, res)) = bad {
return Err(io::Error::other(format!(
"batched file read {i} returned {res}, want {}",
reads[i].len
)));
}
done += in_chunk as usize;
}
Ok((bufs, submissions))
}
}