helper: p2pool - fix uptime, format with commas and spaces

This commit is contained in:
hinto-janaiyo 2022-12-06 15:17:37 -05:00
parent e1829f967c
commit 9b1a815089
No known key found for this signature in database
GPG key ID: B1C5A64B80691E45
2 changed files with 61 additions and 43 deletions

View file

@ -36,7 +36,8 @@ pub const BYTES_ICON: &[u8] = include_bytes!("../images/icons/icon@2x.png");
pub const BYTES_ICON: &[u8] = include_bytes!("../images/icons/icon.png");
pub const BYTES_BANNER: &[u8] = include_bytes!("../images/banner.png");
pub const HORIZONTAL: &str = "--------------------------------------------";
pub const HORI_DOUBLE: &str = "----------------------------------------------------------------------------------------";
// The text to separate my "process stopped, here's stats" text from the process output in the console.
pub const HORI_CONSOLE: &str = "---------------------------------------------------------------------------------------------------------------------------";
// P2Pool & XMRig default API stuff
#[cfg(target_os = "windows")]
@ -73,6 +74,7 @@ pub const DARK_GRAY: egui::Color32 = egui::Color32::from_rgb(18, 18, 18);
// [Duration] constants
pub const SECOND: std::time::Duration = std::time::Duration::from_secs(1);
pub const ZERO_SECONDS: std::time::Duration = std::time::Duration::from_secs(0);
pub const MILLI_900: std::time::Duration = std::time::Duration::from_millis(900);
pub const TOKIO_SECOND: tokio::time::Duration = std::time::Duration::from_secs(1);

View file

@ -71,8 +71,6 @@ pub struct Process {
pub name: ProcessName, // P2Pool or XMRig?
pub state: ProcessState, // The state of the process (alive, dead, etc)
pub signal: ProcessSignal, // Did the user click [Start/Stop/Restart]?
pub start: Instant, // Start time of process
pub uptime: HumanTime, // Human readable process uptime
// STDIN Problem:
// - User can input many many commands in 1 second
// - The process loop only processes every 1 second
@ -96,18 +94,19 @@ pub struct Process {
// The "watchdog" threads mutate this, the "helper" thread synchronizes the [Pub*Api] structs
// so that the data in here is cloned there roughly once a second. GUI thread never touches this.
output: Arc<Mutex<String>>,
// Start time of process.
start: std::time::Instant,
}
//---------------------------------------------------------------------------------------------------- [Process] Impl
impl Process {
pub fn new(name: ProcessName, args: String, path: PathBuf) -> Self {
let now = Instant::now();
Self {
name,
state: ProcessState::Dead,
signal: ProcessSignal::None,
start: now,
uptime: HumanTime::into_human(now.elapsed()),
start: Instant::now(),
stdin: Option::None,
child: Option::None,
// P2Pool log level 1 produces a bit less than 100,000 lines a day.
@ -331,6 +330,7 @@ impl Helper {
path.push(P2POOL_API_PATH);
let regex = P2poolRegex::new();
let output = Arc::clone(&process.lock().unwrap().output);
let start = process.lock().unwrap().start;
// 4. Loop as watchdog
loop {
@ -341,43 +341,46 @@ impl Helper {
if process.lock().unwrap().signal == ProcessSignal::Stop {
child_pty.lock().unwrap().kill(); // This actually sends a SIGHUP to p2pool (closes the PTY, hangs up on p2pool)
// Wait to get the exit status
let mut lock = process.lock().unwrap();
let exit_status = match child_pty.lock().unwrap().wait() {
Ok(e) => if e.success() { lock.state = ProcessState::Dead; "Successful" } else { lock.state = ProcessState::Failed; "Failed" },
_ => { lock.state = ProcessState::Failed; "Unknown Error" },
Ok(e) => {
if e.success() {
process.lock().unwrap().state = ProcessState::Dead; "Successful"
} else {
process.lock().unwrap().state = ProcessState::Failed; "Failed"
}
},
_ => { process.lock().unwrap().state = ProcessState::Failed; "Unknown Error" },
};
let uptime = lock.uptime.clone();
let uptime = HumanTime::into_human(start.elapsed());
info!("P2Pool | Stopped ... Uptime was: [{}], Exit status: [{}]", uptime, exit_status);
// This is written directly into the public API, because sometimes the 900ms event loop can't catch it.
writeln!(pub_api.lock().unwrap().output, "{}\nP2Pool stopped | Uptime: [{}] | Exit status: [{}]\n{}\n\n", HORI_DOUBLE, uptime, exit_status, HORI_DOUBLE);
lock.signal = ProcessSignal::None;
writeln!(pub_api.lock().unwrap().output, "{}\nP2Pool stopped | Uptime: [{}] | Exit status: [{}]\n{}\n\n", HORI_CONSOLE, uptime, exit_status, HORI_CONSOLE);
process.lock().unwrap().signal = ProcessSignal::None;
break
} else if process.lock().unwrap().signal == ProcessSignal::Restart {
child_pty.lock().unwrap().kill(); // This actually sends a SIGHUP to p2pool (closes the PTY, hangs up on p2pool)
// Wait to get the exit status
let mut lock = process.lock().unwrap();
let exit_status = match child_pty.lock().unwrap().wait() {
Ok(e) => if e.success() { "Successful" } else { "Failed" },
_ => "Unknown Error",
};
let uptime = lock.uptime.clone();
let uptime = HumanTime::into_human(start.elapsed());
info!("P2Pool | Stopped ... Uptime was: [{}], Exit status: [{}]", uptime, exit_status);
// This is written directly into the public API, because sometimes the 900ms event loop can't catch it.
writeln!(pub_api.lock().unwrap().output, "{}\nP2Pool stopped | Uptime: [{}] | Exit status: [{}]\n{}\n\n", HORI_DOUBLE, uptime, exit_status, HORI_DOUBLE);
lock.state = ProcessState::Waiting;
writeln!(pub_api.lock().unwrap().output, "{}\nP2Pool stopped | Uptime: [{}] | Exit status: [{}]\n{}\n\n", HORI_CONSOLE, uptime, exit_status, HORI_CONSOLE);
process.lock().unwrap().state = ProcessState::Waiting;
break
// Check if the process is secretly died without us knowing :)
} else if let Ok(Some(code)) = child_pty.lock().unwrap().try_wait() {
let mut lock = process.lock().unwrap();
let exit_status = match code.success() {
true => { lock.state = ProcessState::Dead; "Successful" },
false => { lock.state = ProcessState::Failed; "Failed" },
true => { process.lock().unwrap().state = ProcessState::Dead; "Successful" },
false => { process.lock().unwrap().state = ProcessState::Failed; "Failed" },
};
let uptime = lock.uptime.clone();
let uptime = HumanTime::into_human(start.elapsed());
info!("P2Pool | Stopped ... Uptime was: [{}], Exit status: [{}]", uptime, exit_status);
// This is written directly into the public API, because sometimes the 900ms event loop can't catch it.
writeln!(pub_api.lock().unwrap().output, "{}\nP2Pool stopped | Uptime: [{}] | Exit status: [{}]\n{}\n\n", HORI_DOUBLE, uptime, exit_status, HORI_DOUBLE);
lock.signal = ProcessSignal::None;
writeln!(pub_api.lock().unwrap().output, "{}\nP2Pool stopped | Uptime: [{}] | Exit status: [{}]\n{}\n\n", HORI_CONSOLE, uptime, exit_status, HORI_CONSOLE);
process.lock().unwrap().signal = ProcessSignal::None;
break
}
@ -392,7 +395,7 @@ impl Helper {
drop(lock);
// Always update from output
PubP2poolApi::update_from_output(&pub_api, &output, process.lock().unwrap().start.elapsed().as_secs_f64(), &regex);
PubP2poolApi::update_from_output(&pub_api, &output, start.elapsed(), &regex);
// Read API file into string
if let Ok(string) = Self::read_p2pool_api(&path) {
@ -506,19 +509,25 @@ use std::time::Duration;
pub struct HumanTime(Duration);
impl HumanTime {
pub fn new() -> HumanTime {
HumanTime(ZERO_SECONDS)
}
pub fn into_human(d: Duration) -> HumanTime {
HumanTime(d)
}
fn plural(f: &mut std::fmt::Formatter, started: &mut bool, name: &str, value: u64) -> std::fmt::Result {
if value > 0 {
if *started { f.write_str(" ")?; }
if *started {
f.write_str(", ")?;
}
write!(f, "{} {}", value, name)?;
if value > 1 {
f.write_str("s")?;
}
*started = true;
}
Ok(())
}
}
@ -527,7 +536,7 @@ impl std::fmt::Display for HumanTime {
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
let secs = self.0.as_secs();
if secs == 0 {
f.write_str("0s")?;
f.write_str("0 seconds")?;
return Ok(());
}
@ -701,6 +710,8 @@ pub struct PubP2poolApi {
pub mini: bool,
// Output
pub output: String,
// Uptime
pub uptime: HumanTime,
// These are manually parsed from the STDOUT.
pub payouts: u128,
pub payouts_hour: f64,
@ -725,6 +736,7 @@ impl PubP2poolApi {
Self {
mini: true,
output: String::with_capacity(56_000_000),
uptime: HumanTime::new(),
payouts: 0,
payouts_hour: 0.0,
payouts_day: 0.0,
@ -744,26 +756,30 @@ impl PubP2poolApi {
}
// Mutate [PubP2poolApi] with data the process output.
fn update_from_output(public: &Arc<Mutex<Self>>, output: &Arc<Mutex<String>>, elapsed: f64, regex: &P2poolRegex) {
fn update_from_output(public: &Arc<Mutex<Self>>, output: &Arc<Mutex<String>>, elapsed: std::time::Duration, regex: &P2poolRegex) {
// 1. Clone output
let output = output.lock().unwrap().clone();
// 1. Parse STDOUT
// 2. Parse STDOUT
let (payouts, xmr) = Self::calc_payouts_and_xmr(&output, &regex);
// 2. Calculate hour/day/month given elapsed time
// 3. Calculate hour/day/month given elapsed time
let elapsed_as_secs_f64 = elapsed.as_secs_f64();
// Payouts
let per_sec = (payouts as f64) / elapsed;
let per_sec = (payouts as f64) / elapsed_as_secs_f64;
let payouts_hour = (per_sec * 60.0) * 60.0;
let payouts_day = payouts_hour * 24.0;
let payouts_month = payouts_day * 30.0;
// Total XMR
let per_sec = xmr / elapsed;
let per_sec = xmr / elapsed_as_secs_f64;
let xmr_hour = (per_sec * 60.0) * 60.0;
let xmr_day = payouts_hour * 24.0;
let xmr_month = payouts_day * 30.0;
// 3. Mutate the struct with the new info
// 4. Mutate the struct with the new info
let mut public = public.lock().unwrap();
*public = Self {
uptime: HumanTime::into_human(elapsed),
output,
payouts,
xmr,
@ -779,7 +795,7 @@ impl PubP2poolApi {
// Mutate [PubP2poolApi] with data from a [PrivP2poolApi] and the process output.
fn update_from_priv(public: &Arc<Mutex<Self>>, private: &Arc<Mutex<PrivP2poolApi>>) {
// 3. Final priv -> pub conversion
// priv -> pub conversion
let private = private.lock().unwrap();
let mut public = public.lock().unwrap();
*public = Self {