use std::sync::Arc;
use std::sync::mpsc::{Sender, channel};
use dma_libfabric::{
Completion, Direction, FabricService, Operands, Outcome, Pool, TransferRequest,
};
use dma_libfabric_protocol::{DmaError, encode_hex};
mod common;
struct Operation {
payload: Vec<u8>,
done: Sender<Outcome>,
}
impl Operands for Operation {
fn source(&self) -> Option<&[u8]> {
Some(&self.payload)
}
}
fn complete(completions: std::vec::Drain<'_, Completion<Operation>>) {
for completion in completions {
let _ = completion.caller_context.done.send(completion.outcome);
}
}
fn main() -> Result<(), DmaError> {
let common::Arguments {
configuration,
peer,
} = common::parse()?;
let pool = Arc::new(Pool::new(2).map_err(|error| DmaError::Fabric(format!("pool: {error}")))?);
let server = FabricService::start(&configuration, Box::new(complete), pool)?;
println!("local address: {}", encode_hex(server.local_address()));
let peer = match peer {
Some(peer) => peer,
None => {
println!("paste the target's <address-hex> <rkey> <remote-addr>:");
common::peer_from_stdin()?
}
};
let payload = vec![0xab_u8; 4096];
let (done, outcome) = channel();
let request = TransferRequest {
client_id: 1,
peer_address: peer.address,
remote_key: peer.remote_key,
remote_address: peer.remote_address,
direction: Direction::ToPeer,
want_checksum: true,
caller_context: Operation { payload, done },
parent_id: None,
};
if server.submit(request).is_err() {
return Err(DmaError::Fabric("fabric worker is gone".into()));
}
match outcome.recv() {
Ok(Ok(transferred)) => println!(
"wrote {} bytes, crc {:?}",
transferred.bytes, transferred.checksum
),
Ok(Err(error)) => println!("transfer failed: {error}"),
Err(_) => println!("worker exited without completing the transfer"),
}
Ok(())
}