use std::slice;
use anyhow::Result;
use demikernel::{
demi_sgarray_t,
LibOS,
QDesc,
QToken,
};
pub struct PipeClient {
libos: LibOS,
pipe_name: String,
qds: Vec<QDesc>,
}
impl PipeClient {
pub fn new(libos: LibOS, pipe_name: String) -> Result<Self> {
Ok(Self {
libos,
pipe_name,
qds: Vec::default(),
})
}
pub fn run(&mut self, niterations: usize) -> Result<()> {
for i in 0..niterations {
let pipeqd: QDesc = self.libos.open_pipe(&format!("{}:rx", self.pipe_name))?;
self.qds.push(pipeqd);
self.push_and_wait(pipeqd, 1, i as u8)?;
}
while let Some(qd) = self.qds.pop() {
if let Err(e) = self.libos.close(qd) {
println!("WARN: leaking pipeqd={:?}", qd);
println!("ERROR: close() failed (error={:?})", e);
}
}
Ok(())
}
fn mksga(&mut self, size: usize, value: u8) -> Result<demi_sgarray_t> {
let sga: demi_sgarray_t = match self.libos.sgaalloc(size) {
Ok(sga) => sga,
Err(e) => anyhow::bail!("failed to allocate scatter-gather array: {:?}", e),
};
assert_eq!(sga.sga_segs[0].sgaseg_len as usize, size);
let ptr: *mut u8 = sga.sga_segs[0].sgaseg_buf as *mut u8;
let len: usize = sga.sga_segs[0].sgaseg_len as usize;
let slice: &mut [u8] = unsafe { slice::from_raw_parts_mut(ptr, len) };
slice.fill(value);
Ok(sga)
}
fn push_and_wait(&mut self, pipeqd: QDesc, length: usize, value: u8) -> Result<()> {
let sga: demi_sgarray_t = self.mksga(length, value)?;
let qt: QToken = self.libos.push(pipeqd, &sga)?;
self.libos.wait(qt, None)?;
self.libos.sgafree(sga)?;
Ok(())
}
}
impl Drop for PipeClient {
fn drop(&mut self) {
while let Some(qd) = self.qds.pop() {
if let Err(e) = self.libos.close(qd) {
println!("WARN: leaking pipeqd={:?}", qd);
println!("ERROR: close() failed (error={:?})", e);
}
}
}
}