pub mod ringmaster_client;
use clap::{command, value_parser, Arg};
use proctitle;
use std::fs;
use std::io;
use std::io::Write;
use std::path;
use std::process;
use std::time::Duration;
#[derive(Debug)]
struct ProgramArguments {
directory: String,
ring_name: String,
portman: u16,
comment: String,
}
impl ProgramArguments {
fn new() -> ProgramArguments {
ProgramArguments {
directory: String::from("/dev/shm"),
ring_name: String::from(""), portman: 30000,
comment: String::from(""),
}
}
}
fn main() {
let args = process_args();
eprintln!("{:#?}", args);
let mut path_buf = path::PathBuf::from(args.directory);
path_buf.push(args.ring_name);
match ringmaster_client::attach_consumer(path_buf.to_str().expect("BUG")) {
Err(e) => {
eprintln!("Failed to attach ring buffer : {}", e);
process::exit(-1);
}
Ok(consumer_info) => {
match consumer_info.client {
ringmaster_client::ClientType::Consumer(mut c) => {
if args.comment != "" {
let title = format!("ring2stdout - {}", args.comment);
proctitle::set_title(title);
}
output_data(&mut c);
}
ringmaster_client::ClientType::Producer(_p) => {
eprintln!("ERROR - a producer was returned not a consumer");
process::exit(-1);
}
}
}
};
process::exit(-1); }
fn output_data(ring: &mut nscldaq_ringbuffer::ringbuffer::consumer::Consumer) {
let mut data = Vec::<u8>::new();
data.reserve(1024 * 1024);
data.resize(1024 * 1024, 0);
loop {
match ring.timed_get(&mut data, Duration::from_millis(1)) {
Ok(n) => {
io::stdout()
.write_all(&data[0..n])
.expect("Failed to write to stdout");
io::stdout().flush().expect("Failed to flush output");
}
Err(e) => {
match e {
nscldaq_ringbuffer::ringbuffer::consumer::Error::Timeout => {}
_ => {
eprintln!(
"Error reading from ring buffer: {}",
nscldaq_ringbuffer::ringbuffer::consumer::error_string(&e)
);
break;
}
}
}
}
}
}
fn process_args() -> ProgramArguments {
let mut result = ProgramArguments::new();
let parser = command!()
.version(env!("CARGO_PKG_VERSION"))
.author("Ron Fox")
.about(env!("CARGO_PKG_DESCRIPTION"))
.arg(Arg::new("directory")
.short('d')
.long("directory")
.help("Directory of ring buffer shared memory files managed by the ringmaster")
.default_value("/dev/shm")
.value_parser(value_parser!(String))
)
.arg(Arg::new("ring_name")
.short('r')
.long("ring")
.help("Name of the ring buffer we should take data from")
.required(true)
.value_parser(value_parser!(String))
)
.arg(
Arg::new("portman")
.short('p')
.long("port")
.help("TCP/IP port on which the port manager is listening")
.default_value("30000")
.value_parser(value_parser!(u16))
)
.arg(
Arg::new("comment")
.short('c')
.long("comment")
.default_value("")
.value_parser(value_parser!(String))
)
.get_matches();
if let Some(directory) = parser.get_one::<String>("directory") {
if fs::read_dir(directory).is_err() {
eprintln!("{} Must be a readable directory", directory);
process::exit(-1);
} else {
result.directory = directory.clone();
}
}
if let Some(ring) = parser.get_one::<String>("ring_name") {
result.ring_name = ring.clone();
} else {
eprintln!("The --ring option is required");
process::exit(-1);
}
if let Some(port) = parser.get_one::<u16>("portman") {
result.portman = *port;
}
if let Some(comment) = parser.get_one::<String>("comment") {
result.comment = comment.clone();
}
result
}