use std::{
io::{BufRead, Result, Write},
sync::{
atomic::{AtomicBool, Ordering},
Arc, Mutex,
},
};
use log::error;
pub(crate) static STOP_THREADS: AtomicBool = AtomicBool::new(false);
pub(crate) fn monitor_and_buffer(
reader: impl BufRead,
mut io_writer: &mut impl Write,
file_writer: Arc<Mutex<impl Write>>,
) {
let mut buffer = Vec::with_capacity(240);
let mut reader = reader;
loop {
if STOP_THREADS.load(Ordering::Relaxed) {
break;
}
let mut temporary_limiter = reader.take(8192);
let read_result = read_and_double_write(
&mut buffer,
&mut temporary_limiter,
&mut io_writer,
file_writer.clone(),
);
if let Ok(0) = read_result {
break;
}
if let Err(e) = read_result {
error!("Error reading data: {e}");
break;
}
buffer.clear();
reader = temporary_limiter.into_inner();
}
if let Err(e) = file_writer
.lock()
.expect("Failed to lock file writer")
.flush()
{
error!("Error flushing file writer. {e}");
}
}
#[inline(always)]
pub(crate) fn read_and_double_write(
buffer: &mut Vec<u8>,
reader: &mut impl BufRead,
io_writer: &mut impl Write,
file_writer: Arc<Mutex<impl Write>>,
) -> Result<usize> {
match reader.read_until(b'\n', buffer)? {
0 => Ok(0),
bytes_read => {
io_writer.write_all(buffer)?;
io_writer.flush()?;
file_writer
.lock()
.expect("Failed to lock file writer")
.write_all(buffer)?;
Ok(bytes_read)
}
}
}