mirror of
https://github.com/Cyrix126/gupaxx.git
synced 2024-11-17 07:47:35 +00:00
helper: p2pool - fix uptime, format with commas and spaces
This commit is contained in:
parent
e1829f967c
commit
9b1a815089
2 changed files with 61 additions and 43 deletions
|
@ -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_ICON: &[u8] = include_bytes!("../images/icons/icon.png");
|
||||||
pub const BYTES_BANNER: &[u8] = include_bytes!("../images/banner.png");
|
pub const BYTES_BANNER: &[u8] = include_bytes!("../images/banner.png");
|
||||||
pub const HORIZONTAL: &str = "--------------------------------------------";
|
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
|
// P2Pool & XMRig default API stuff
|
||||||
#[cfg(target_os = "windows")]
|
#[cfg(target_os = "windows")]
|
||||||
|
@ -73,6 +74,7 @@ pub const DARK_GRAY: egui::Color32 = egui::Color32::from_rgb(18, 18, 18);
|
||||||
|
|
||||||
// [Duration] constants
|
// [Duration] constants
|
||||||
pub const SECOND: std::time::Duration = std::time::Duration::from_secs(1);
|
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 MILLI_900: std::time::Duration = std::time::Duration::from_millis(900);
|
||||||
pub const TOKIO_SECOND: tokio::time::Duration = std::time::Duration::from_secs(1);
|
pub const TOKIO_SECOND: tokio::time::Duration = std::time::Duration::from_secs(1);
|
||||||
|
|
||||||
|
|
|
@ -71,8 +71,6 @@ pub struct Process {
|
||||||
pub name: ProcessName, // P2Pool or XMRig?
|
pub name: ProcessName, // P2Pool or XMRig?
|
||||||
pub state: ProcessState, // The state of the process (alive, dead, etc)
|
pub state: ProcessState, // The state of the process (alive, dead, etc)
|
||||||
pub signal: ProcessSignal, // Did the user click [Start/Stop/Restart]?
|
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:
|
// STDIN Problem:
|
||||||
// - User can input many many commands in 1 second
|
// - User can input many many commands in 1 second
|
||||||
// - The process loop only processes every 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
|
// 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.
|
// so that the data in here is cloned there roughly once a second. GUI thread never touches this.
|
||||||
output: Arc<Mutex<String>>,
|
output: Arc<Mutex<String>>,
|
||||||
|
|
||||||
|
// Start time of process.
|
||||||
|
start: std::time::Instant,
|
||||||
}
|
}
|
||||||
|
|
||||||
//---------------------------------------------------------------------------------------------------- [Process] Impl
|
//---------------------------------------------------------------------------------------------------- [Process] Impl
|
||||||
impl Process {
|
impl Process {
|
||||||
pub fn new(name: ProcessName, args: String, path: PathBuf) -> Self {
|
pub fn new(name: ProcessName, args: String, path: PathBuf) -> Self {
|
||||||
let now = Instant::now();
|
|
||||||
Self {
|
Self {
|
||||||
name,
|
name,
|
||||||
state: ProcessState::Dead,
|
state: ProcessState::Dead,
|
||||||
signal: ProcessSignal::None,
|
signal: ProcessSignal::None,
|
||||||
start: now,
|
start: Instant::now(),
|
||||||
uptime: HumanTime::into_human(now.elapsed()),
|
|
||||||
stdin: Option::None,
|
stdin: Option::None,
|
||||||
child: Option::None,
|
child: Option::None,
|
||||||
// P2Pool log level 1 produces a bit less than 100,000 lines a day.
|
// 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);
|
path.push(P2POOL_API_PATH);
|
||||||
let regex = P2poolRegex::new();
|
let regex = P2poolRegex::new();
|
||||||
let output = Arc::clone(&process.lock().unwrap().output);
|
let output = Arc::clone(&process.lock().unwrap().output);
|
||||||
|
let start = process.lock().unwrap().start;
|
||||||
|
|
||||||
// 4. Loop as watchdog
|
// 4. Loop as watchdog
|
||||||
loop {
|
loop {
|
||||||
|
@ -341,43 +341,46 @@ impl Helper {
|
||||||
if process.lock().unwrap().signal == ProcessSignal::Stop {
|
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)
|
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
|
// Wait to get the exit status
|
||||||
let mut lock = process.lock().unwrap();
|
|
||||||
let exit_status = match child_pty.lock().unwrap().wait() {
|
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" },
|
Ok(e) => {
|
||||||
_ => { lock.state = ProcessState::Failed; "Unknown Error" },
|
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);
|
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.
|
// 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);
|
writeln!(pub_api.lock().unwrap().output, "{}\nP2Pool stopped | Uptime: [{}] | Exit status: [{}]\n{}\n\n", HORI_CONSOLE, uptime, exit_status, HORI_CONSOLE);
|
||||||
lock.signal = ProcessSignal::None;
|
process.lock().unwrap().signal = ProcessSignal::None;
|
||||||
break
|
break
|
||||||
} else if process.lock().unwrap().signal == ProcessSignal::Restart {
|
} 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)
|
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
|
// Wait to get the exit status
|
||||||
let mut lock = process.lock().unwrap();
|
|
||||||
let exit_status = match child_pty.lock().unwrap().wait() {
|
let exit_status = match child_pty.lock().unwrap().wait() {
|
||||||
Ok(e) => if e.success() { "Successful" } else { "Failed" },
|
Ok(e) => if e.success() { "Successful" } else { "Failed" },
|
||||||
_ => "Unknown Error",
|
_ => "Unknown Error",
|
||||||
};
|
};
|
||||||
let uptime = lock.uptime.clone();
|
let uptime = HumanTime::into_human(start.elapsed());
|
||||||
info!("P2Pool | Stopped ... Uptime was: [{}], Exit status: [{}]", uptime, exit_status);
|
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.
|
// 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);
|
writeln!(pub_api.lock().unwrap().output, "{}\nP2Pool stopped | Uptime: [{}] | Exit status: [{}]\n{}\n\n", HORI_CONSOLE, uptime, exit_status, HORI_CONSOLE);
|
||||||
lock.state = ProcessState::Waiting;
|
process.lock().unwrap().state = ProcessState::Waiting;
|
||||||
break
|
break
|
||||||
// Check if the process is secretly died without us knowing :)
|
// Check if the process is secretly died without us knowing :)
|
||||||
} else if let Ok(Some(code)) = child_pty.lock().unwrap().try_wait() {
|
} else if let Ok(Some(code)) = child_pty.lock().unwrap().try_wait() {
|
||||||
let mut lock = process.lock().unwrap();
|
|
||||||
let exit_status = match code.success() {
|
let exit_status = match code.success() {
|
||||||
true => { lock.state = ProcessState::Dead; "Successful" },
|
true => { process.lock().unwrap().state = ProcessState::Dead; "Successful" },
|
||||||
false => { lock.state = ProcessState::Failed; "Failed" },
|
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);
|
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.
|
// 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);
|
writeln!(pub_api.lock().unwrap().output, "{}\nP2Pool stopped | Uptime: [{}] | Exit status: [{}]\n{}\n\n", HORI_CONSOLE, uptime, exit_status, HORI_CONSOLE);
|
||||||
lock.signal = ProcessSignal::None;
|
process.lock().unwrap().signal = ProcessSignal::None;
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -392,7 +395,7 @@ impl Helper {
|
||||||
drop(lock);
|
drop(lock);
|
||||||
|
|
||||||
// Always update from output
|
// Always update from output
|
||||||
PubP2poolApi::update_from_output(&pub_api, &output, process.lock().unwrap().start.elapsed().as_secs_f64(), ®ex);
|
PubP2poolApi::update_from_output(&pub_api, &output, start.elapsed(), ®ex);
|
||||||
|
|
||||||
// Read API file into string
|
// Read API file into string
|
||||||
if let Ok(string) = Self::read_p2pool_api(&path) {
|
if let Ok(string) = Self::read_p2pool_api(&path) {
|
||||||
|
@ -506,19 +509,25 @@ use std::time::Duration;
|
||||||
pub struct HumanTime(Duration);
|
pub struct HumanTime(Duration);
|
||||||
|
|
||||||
impl HumanTime {
|
impl HumanTime {
|
||||||
|
pub fn new() -> HumanTime {
|
||||||
|
HumanTime(ZERO_SECONDS)
|
||||||
|
}
|
||||||
|
|
||||||
pub fn into_human(d: Duration) -> HumanTime {
|
pub fn into_human(d: Duration) -> HumanTime {
|
||||||
HumanTime(d)
|
HumanTime(d)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn plural(f: &mut std::fmt::Formatter, started: &mut bool, name: &str, value: u64) -> std::fmt::Result {
|
fn plural(f: &mut std::fmt::Formatter, started: &mut bool, name: &str, value: u64) -> std::fmt::Result {
|
||||||
if value > 0 {
|
if value > 0 {
|
||||||
if *started { f.write_str(" ")?; }
|
if *started {
|
||||||
|
f.write_str(", ")?;
|
||||||
}
|
}
|
||||||
write!(f, "{} {}", value, name)?;
|
write!(f, "{} {}", value, name)?;
|
||||||
if value > 1 {
|
if value > 1 {
|
||||||
f.write_str("s")?;
|
f.write_str("s")?;
|
||||||
}
|
}
|
||||||
*started = true;
|
*started = true;
|
||||||
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -527,7 +536,7 @@ impl std::fmt::Display for HumanTime {
|
||||||
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
|
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
|
||||||
let secs = self.0.as_secs();
|
let secs = self.0.as_secs();
|
||||||
if secs == 0 {
|
if secs == 0 {
|
||||||
f.write_str("0s")?;
|
f.write_str("0 seconds")?;
|
||||||
return Ok(());
|
return Ok(());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -701,6 +710,8 @@ pub struct PubP2poolApi {
|
||||||
pub mini: bool,
|
pub mini: bool,
|
||||||
// Output
|
// Output
|
||||||
pub output: String,
|
pub output: String,
|
||||||
|
// Uptime
|
||||||
|
pub uptime: HumanTime,
|
||||||
// These are manually parsed from the STDOUT.
|
// These are manually parsed from the STDOUT.
|
||||||
pub payouts: u128,
|
pub payouts: u128,
|
||||||
pub payouts_hour: f64,
|
pub payouts_hour: f64,
|
||||||
|
@ -725,6 +736,7 @@ impl PubP2poolApi {
|
||||||
Self {
|
Self {
|
||||||
mini: true,
|
mini: true,
|
||||||
output: String::with_capacity(56_000_000),
|
output: String::with_capacity(56_000_000),
|
||||||
|
uptime: HumanTime::new(),
|
||||||
payouts: 0,
|
payouts: 0,
|
||||||
payouts_hour: 0.0,
|
payouts_hour: 0.0,
|
||||||
payouts_day: 0.0,
|
payouts_day: 0.0,
|
||||||
|
@ -744,26 +756,30 @@ impl PubP2poolApi {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Mutate [PubP2poolApi] with data the process output.
|
// 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();
|
let output = output.lock().unwrap().clone();
|
||||||
// 1. Parse STDOUT
|
|
||||||
|
// 2. Parse STDOUT
|
||||||
let (payouts, xmr) = Self::calc_payouts_and_xmr(&output, ®ex);
|
let (payouts, xmr) = Self::calc_payouts_and_xmr(&output, ®ex);
|
||||||
|
|
||||||
// 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
|
// 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_hour = (per_sec * 60.0) * 60.0;
|
||||||
let payouts_day = payouts_hour * 24.0;
|
let payouts_day = payouts_hour * 24.0;
|
||||||
let payouts_month = payouts_day * 30.0;
|
let payouts_month = payouts_day * 30.0;
|
||||||
// Total XMR
|
// 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_hour = (per_sec * 60.0) * 60.0;
|
||||||
let xmr_day = payouts_hour * 24.0;
|
let xmr_day = payouts_hour * 24.0;
|
||||||
let xmr_month = payouts_day * 30.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();
|
let mut public = public.lock().unwrap();
|
||||||
*public = Self {
|
*public = Self {
|
||||||
|
uptime: HumanTime::into_human(elapsed),
|
||||||
output,
|
output,
|
||||||
payouts,
|
payouts,
|
||||||
xmr,
|
xmr,
|
||||||
|
@ -779,7 +795,7 @@ impl PubP2poolApi {
|
||||||
|
|
||||||
// Mutate [PubP2poolApi] with data from a [PrivP2poolApi] and the process output.
|
// Mutate [PubP2poolApi] with data from a [PrivP2poolApi] and the process output.
|
||||||
fn update_from_priv(public: &Arc<Mutex<Self>>, private: &Arc<Mutex<PrivP2poolApi>>) {
|
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 private = private.lock().unwrap();
|
||||||
let mut public = public.lock().unwrap();
|
let mut public = public.lock().unwrap();
|
||||||
*public = Self {
|
*public = Self {
|
||||||
|
|
Loading…
Reference in a new issue