What is the most efficient way to write the following code in RUST.
In C, I would have created a large enough thread local buffer once. Assembled the whole message or messages that needs to be sent in that buffer. And done write/linux syscalls operations to write out those blocks.
I am not sure if I could be doing this any more effciently in RUST?
I am writing to a unix pipe, which guarantees that a linux write system call under a certain size 4096 is guaranteed to be atomic.
Most messages written are only a few 100 bytes.
For the very few messages that can be beyond that max 4096 limit, I have a notation of using prefixing the partial message with "*" so that the reciever knows the data is being split across multiple blocks. The example below is splitting one very large data block across 3 entries.
Context: There will be multiple processes and threads within processes writing to the same unix pipe
<uuid> <command> *<patial-message>
<uuid> <command> *<patial-message>
<uuid> <command> <patial-message>
The summary of what I need to be doing is
- to construct json render of the data I want to write
- When writing the rendered json message, split them across multiple messages if it is over the 4096 limit
- print/write that data to file handle
- Preferably not mutex/lock the Tracker/File object to have to write/do 1-3 above. Since 2-3 can be done in its own thread local buffer. and 4 which is a linux syscall if under 4096 doesnt interleave wont require locking.
const SENDLIMIT: usize = 4094;
pub struct Tracker {
pub file: fs::File,
pub fd: i32,
}
impl Tracker {
pub fn new() -> Tracker {
.......
}
pub fn report(self: &Self, op : &str, value: &str) {
let mut minlen: usize = &UUID.as_str().len() + op.len() + 2;
let mut availen: usize = SENDLIMIT - minlen;
let mut lenleft = value.len();
let mut ind = 0;
let mut contin = "";
while lenleft != 0 {
let max = if lenleft > availen {lenleft = lenleft - availen; ind + availen }
else { let x=lenleft; lenleft = 0; ind + x };
contin = if lenleft > availen { "*" } else { " " };
if let Err(e) = (&self.file).write_all(format!("{} {} {}{}\n", &UUID.as_str(), op, contin, &value[ind..max]).as_bytes()) {
}
contin = "*";
ind = max ;
minlen = &UUID.as_str().len() + op.len() + 2 + 1;
availen = SENDLIMIT - minlen;
};
}
pub unsafe fn reportexecvpe(self: &Self, variant: &str, path: *const libc::c_char,
argv: *const *const libc::c_char, envcstr: &Vec<CString>) {
let mut vargv: Vec<&str> = vec![];
let mut venv: Vec<Vec<&str>> = vec![];
for i in 0 .. {
let argptr: *const c_char = *(argv.offset(i));
if argptr != ptr::null() {
vargv.push(utils::ptr2str(argptr))
} else {
break;
}
}
for i in envcstr.iter() {
venv.push(i.to_str().unwrap().splitn(2,"=").collect());
}
let args = (variant, pathgetabs(path,AT_FDCWD), vargv, venv);
self.report("EXECUTES", &serde_json::to_string(&args).unwrap());
}
};