use std::{ collections::HashMap, fs, io::{self, Write}, os::unix::net::UnixListener, path::Path, sync::{Arc, RwLock}, thread, time::Duration, }; use crate::{energy::EnergyLog, Pid}; pub struct LoggingSocketService { path: String, logged_energy: Arc>>, update_interval: Duration, } impl LoggingSocketService { pub fn new( path: &str, logged_energy: Arc>>, update_interval: Duration, ) -> Self { LoggingSocketService { path: path.to_string(), logged_energy, update_interval, } } fn generate_report(&self) -> String { loop { if let Ok(logged_energy) = self.logged_energy.try_read() { let mut result = logged_energy .iter() .map(|(key, value)| { format!( "{key}: {}J", value.energy_of_running_tasks + value.energy_of_exited_tasks ) }) .collect::>() .join(", "); result += "\n"; break result; } thread::sleep(Duration::from_millis(10)); } } pub fn run(self) { thread::spawn(move || { let listener = UnixListener::bind(self.path.clone()).unwrap(); for stream in listener.incoming() { let mut socket = stream.unwrap(); loop { if socket .write_all(format!("{}", self.generate_report()).as_bytes()) .is_err() { break; } thread::sleep(self.update_interval); } //TODO: if we ever want to read too /*let mut reader = BufReader::new(socket.try_clone().unwrap()); let mut line = String::new(); while let Ok(bytes_read) = reader.read_line(&mut line) { if bytes_read == 0 { break; } socket.write_all(format!("got: {line}").as_bytes()); println!("got: {line}"); line.clear(); }*/ } }); } } pub fn start_logging_socket_service( path: &str, logged_energy: Arc>>, update_interval: Duration, ) -> io::Result<()> { if Path::new(path).exists() { fs::remove_file(path)?; } let socket = LoggingSocketService::new(path, logged_energy, update_interval); socket.run(); Ok(()) }