mirror of
https://github.com/Cyrix126/gupaxx.git
synced 2024-12-22 14:49:21 +00:00
feat: fix deadlocks
This commit is contained in:
parent
5230d46d93
commit
387f386573
10 changed files with 538 additions and 540 deletions
|
@ -27,6 +27,12 @@ impl eframe::App for App {
|
||||||
// These values are checked multiple times so
|
// These values are checked multiple times so
|
||||||
// might as well check only once here to save
|
// might as well check only once here to save
|
||||||
// on a bunch of [.lock().unwrap()]s.
|
// on a bunch of [.lock().unwrap()]s.
|
||||||
|
debug!("App | Locking and collecting Node state...");
|
||||||
|
let node = self.node.lock().unwrap();
|
||||||
|
let node_is_alive = node.is_alive();
|
||||||
|
let node_is_waiting = node.is_waiting();
|
||||||
|
let node_state = node.state;
|
||||||
|
drop(node);
|
||||||
debug!("App | Locking and collecting P2Pool state...");
|
debug!("App | Locking and collecting P2Pool state...");
|
||||||
let p2pool = self.p2pool.lock().unwrap();
|
let p2pool = self.p2pool.lock().unwrap();
|
||||||
let p2pool_is_alive = p2pool.is_alive();
|
let p2pool_is_alive = p2pool.is_alive();
|
||||||
|
@ -49,14 +55,9 @@ impl eframe::App for App {
|
||||||
let xvb = self.xvb.lock().unwrap();
|
let xvb = self.xvb.lock().unwrap();
|
||||||
let xvb_is_alive = xvb.is_alive();
|
let xvb_is_alive = xvb.is_alive();
|
||||||
let xvb_is_waiting = xvb.is_waiting();
|
let xvb_is_waiting = xvb.is_waiting();
|
||||||
|
let xvb_is_running = xvb.state == ProcessState::Alive;
|
||||||
let xvb_state = xvb.state;
|
let xvb_state = xvb.state;
|
||||||
drop(xvb);
|
drop(xvb);
|
||||||
debug!("App | Locking and collecting Node state...");
|
|
||||||
let node = self.node.lock().unwrap();
|
|
||||||
let node_is_alive = node.is_alive();
|
|
||||||
let node_is_waiting = node.is_waiting();
|
|
||||||
let node_state = node.state;
|
|
||||||
drop(node);
|
|
||||||
|
|
||||||
// This sets the top level Ui dimensions.
|
// This sets the top level Ui dimensions.
|
||||||
// Used as a reference for other uis.
|
// Used as a reference for other uis.
|
||||||
|
@ -139,6 +140,7 @@ impl eframe::App for App {
|
||||||
xmrig_is_alive,
|
xmrig_is_alive,
|
||||||
xmrig_proxy_is_alive,
|
xmrig_proxy_is_alive,
|
||||||
xvb_is_alive,
|
xvb_is_alive,
|
||||||
|
xvb_is_running,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,5 @@
|
||||||
use crate::app::keys::KeyPressed;
|
use crate::app::keys::KeyPressed;
|
||||||
use crate::app::Tab;
|
use crate::app::Tab;
|
||||||
use crate::helper::ProcessState;
|
|
||||||
use crate::utils::constants::*;
|
use crate::utils::constants::*;
|
||||||
use crate::utils::errors::{ErrorButtons, ErrorFerris};
|
use crate::utils::errors::{ErrorButtons, ErrorFerris};
|
||||||
use egui::*;
|
use egui::*;
|
||||||
|
@ -25,6 +24,7 @@ impl crate::app::App {
|
||||||
xmrig_is_alive: bool,
|
xmrig_is_alive: bool,
|
||||||
xmrig_proxy_is_alive: bool,
|
xmrig_proxy_is_alive: bool,
|
||||||
xvb_is_alive: bool,
|
xvb_is_alive: bool,
|
||||||
|
xvb_is_running: bool,
|
||||||
) {
|
) {
|
||||||
// Middle panel, contents of the [Tab]
|
// Middle panel, contents of the [Tab]
|
||||||
debug!("App | Rendering CENTRAL_PANEL (tab contents)");
|
debug!("App | Rendering CENTRAL_PANEL (tab contents)");
|
||||||
|
@ -43,12 +43,14 @@ impl crate::app::App {
|
||||||
let distro = true;
|
let distro = true;
|
||||||
#[cfg(not(feature = "distro"))]
|
#[cfg(not(feature = "distro"))]
|
||||||
let distro = false;
|
let distro = false;
|
||||||
|
let node_gui_len = self.node_api.lock().unwrap().output.len();
|
||||||
let p2pool_gui_len = self.p2pool_api.lock().unwrap().output.len();
|
let p2pool_gui_len = self.p2pool_api.lock().unwrap().output.len();
|
||||||
let xmrig_gui_len = self.xmrig_api.lock().unwrap().output.len();
|
let xmrig_gui_len = self.xmrig_api.lock().unwrap().output.len();
|
||||||
let xmrig_proxy_gui_len = self.xmrig_proxy_api.lock().unwrap().output.len();
|
let xmrig_proxy_gui_len = self.xmrig_proxy_api.lock().unwrap().output.len();
|
||||||
let gupax_p2pool_api = self.gupax_p2pool_api.lock().unwrap();
|
let gupax_p2pool_api = self.gupax_p2pool_api.lock().unwrap();
|
||||||
let debug_info = format!(
|
let debug_info = format!(
|
||||||
"Gupax version: {}\n
|
"Gupax version: {}\n
|
||||||
|
Bundled Node version: {}\n
|
||||||
Bundled P2Pool version: {}\n
|
Bundled P2Pool version: {}\n
|
||||||
Bundled XMRig version: {}\n
|
Bundled XMRig version: {}\n
|
||||||
Bundled XMRig-Proxy version: {}\n
|
Bundled XMRig-Proxy version: {}\n
|
||||||
|
@ -114,6 +116,7 @@ path_xmr: {:#?}\n
|
||||||
self.state.gupax.absolute_p2pool_path.display(),
|
self.state.gupax.absolute_p2pool_path.display(),
|
||||||
self.state.gupax.absolute_xmrig_path.display(),
|
self.state.gupax.absolute_xmrig_path.display(),
|
||||||
self.state.gupax.absolute_xp_path.display(),
|
self.state.gupax.absolute_xp_path.display(),
|
||||||
|
node_gui_len,
|
||||||
p2pool_gui_len,
|
p2pool_gui_len,
|
||||||
xmrig_gui_len,
|
xmrig_gui_len,
|
||||||
xmrig_proxy_gui_len,
|
xmrig_proxy_gui_len,
|
||||||
|
@ -181,7 +184,7 @@ path_xmr: {:#?}\n
|
||||||
}
|
}
|
||||||
Tab::Xvb => {
|
Tab::Xvb => {
|
||||||
debug!("App | Entering [XvB] Tab");
|
debug!("App | Entering [XvB] Tab");
|
||||||
crate::disk::state::Xvb::show(&mut self.state.xvb, self.size, &self.state.p2pool.address, ctx, ui, &self.xvb_api, &self.xmrig_api, self.xvb.lock().unwrap().state == ProcessState::Alive);
|
crate::disk::state::Xvb::show(&mut self.state.xvb, self.size, &self.state.p2pool.address, ctx, ui, &self.xvb_api, &self.xmrig_api, xvb_is_running);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
|
@ -369,8 +369,12 @@ impl Update {
|
||||||
info!("Update | Saving state...");
|
info!("Update | Saving state...");
|
||||||
let original_version = og.lock().unwrap().version.clone();
|
let original_version = og.lock().unwrap().version.clone();
|
||||||
og.lock().unwrap().version = state_ver;
|
og.lock().unwrap().version = state_ver;
|
||||||
match State::save(&mut og.lock().unwrap(), &state_path) {
|
let mut state = og.lock().unwrap().to_owned();
|
||||||
Ok(_) => info!("Update ... OK"),
|
match State::save(&mut state, &state_path) {
|
||||||
|
Ok(_) => {
|
||||||
|
info!("Update ... OK");
|
||||||
|
*og.lock().unwrap() = state;
|
||||||
|
}
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
warn!("Update | Saving state ... FAIL: {}", e);
|
warn!("Update | Saving state ... FAIL: {}", e);
|
||||||
og.lock().unwrap().version = original_version;
|
og.lock().unwrap().version = original_version;
|
||||||
|
|
|
@ -466,39 +466,39 @@ impl Helper {
|
||||||
|
|
||||||
// 2. Lock... EVERYTHING!
|
// 2. Lock... EVERYTHING!
|
||||||
let mut lock = helper.lock().unwrap();
|
let mut lock = helper.lock().unwrap();
|
||||||
debug!("Helper | Locking (1/15) ... [helper]");
|
debug!("Helper | Locked (1/17) ... [helper]");
|
||||||
let node = node.lock().unwrap();
|
let node = node.lock().unwrap();
|
||||||
debug!("Helper | Locking (2/15) ... [helper]");
|
debug!("Helper | Locked (2/17) ... [node]");
|
||||||
let p2pool = p2pool.lock().unwrap();
|
let p2pool = p2pool.lock().unwrap();
|
||||||
debug!("Helper | Locking (3/15) ... [p2pool]");
|
debug!("Helper | Locked (3/17) ... [p2pool]");
|
||||||
let xmrig = xmrig.lock().unwrap();
|
let xmrig = xmrig.lock().unwrap();
|
||||||
debug!("Helper | Locking (4/15) ... [xmrig]");
|
debug!("Helper | Locked (4/17) ... [xmrig]");
|
||||||
let xmrig_proxy = xmrig_proxy.lock().unwrap();
|
let xmrig_proxy = xmrig_proxy.lock().unwrap();
|
||||||
debug!("Helper | Locking (5/15) ... [xmrig_proxy]");
|
debug!("Helper | Locked (5/17) ... [xmrig_proxy]");
|
||||||
let xvb = xvb.lock().unwrap();
|
let xvb = xvb.lock().unwrap();
|
||||||
debug!("Helper | Locking (6/15) ... [xvb]");
|
debug!("Helper | Locked (6/17) ... [xvb]");
|
||||||
let mut lock_pub_sys = pub_sys.lock().unwrap();
|
let mut lock_pub_sys = pub_sys.lock().unwrap();
|
||||||
debug!("Helper | Locking (8/15) ... [gui_api_node]");
|
debug!("Helper | Locked (8/17) ... [pub_sys]");
|
||||||
let mut gui_api_node = gui_api_node.lock().unwrap();
|
let mut gui_api_node = gui_api_node.lock().unwrap();
|
||||||
debug!("Helper | Locking (7/15) ... [pub_sys]");
|
debug!("Helper | Locked (7/17) ... [gui_api_node]");
|
||||||
let mut gui_api_p2pool = gui_api_p2pool.lock().unwrap();
|
let mut gui_api_p2pool = gui_api_p2pool.lock().unwrap();
|
||||||
debug!("Helper | Locking (8/15) ... [gui_api_p2pool]");
|
debug!("Helper | Locked (9/17) ... [gui_api_p2pool]");
|
||||||
let mut gui_api_xmrig = gui_api_xmrig.lock().unwrap();
|
let mut gui_api_xmrig = gui_api_xmrig.lock().unwrap();
|
||||||
debug!("Helper | Locking (9/15) ... [gui_api_xmrig]");
|
debug!("Helper | Locked (10/17) ... [gui_api_xmrig]");
|
||||||
let mut gui_api_xp = gui_api_xp.lock().unwrap();
|
let mut gui_api_xp = gui_api_xp.lock().unwrap();
|
||||||
debug!("Helper | Locking (10/15) ... [gui_api_xp]");
|
debug!("Helper | Locked (11/17) ... [gui_api_xp]");
|
||||||
let mut gui_api_xvb = gui_api_xvb.lock().unwrap();
|
let mut gui_api_xvb = gui_api_xvb.lock().unwrap();
|
||||||
debug!("Helper | Locking (11/15) ... [gui_api_xvb]");
|
debug!("Helper | Locked (12/17) ... [gui_api_xvb]");
|
||||||
let mut pub_api_node = pub_api_node.lock().unwrap();
|
let mut pub_api_node = pub_api_node.lock().unwrap();
|
||||||
debug!("Helper | Locking (14/15) ... [pub_api_node]");
|
debug!("Helper | Locked (13/17) ... [pub_api_node]");
|
||||||
let mut pub_api_p2pool = pub_api_p2pool.lock().unwrap();
|
let mut pub_api_p2pool = pub_api_p2pool.lock().unwrap();
|
||||||
debug!("Helper | Locking (14/15) ... [pub_api_p2pool]");
|
debug!("Helper | Locked (14/17) ... [pub_api_p2pool]");
|
||||||
let mut pub_api_xmrig = pub_api_xmrig.lock().unwrap();
|
let mut pub_api_xmrig = pub_api_xmrig.lock().unwrap();
|
||||||
debug!("Helper | Locking (13/15) ... [pub_api_xmrig]");
|
debug!("Helper | Locked (15/17) ... [pub_api_xmrig]");
|
||||||
let mut pub_api_xp = pub_api_xp.lock().unwrap();
|
let mut pub_api_xp = pub_api_xp.lock().unwrap();
|
||||||
debug!("Helper | Locking (14/15) ... [pub_api_xp]");
|
debug!("Helper | Locked (16/17) ... [pub_api_xp]");
|
||||||
let mut pub_api_xvb = pub_api_xvb.lock().unwrap();
|
let mut pub_api_xvb = pub_api_xvb.lock().unwrap();
|
||||||
debug!("Helper | Locking (15/15) ... [pub_api_xvb]");
|
debug!("Helper | Locked (17/17) ... [pub_api_xvb]");
|
||||||
// Calculate Gupax's uptime always.
|
// Calculate Gupax's uptime always.
|
||||||
lock.uptime = HumanTime::into_human(lock.instant.elapsed());
|
lock.uptime = HumanTime::into_human(lock.instant.elapsed());
|
||||||
// If [Node] is alive...
|
// If [Node] is alive...
|
||||||
|
@ -558,39 +558,39 @@ impl Helper {
|
||||||
|
|
||||||
// 3. Drop... (almost) EVERYTHING... IN REVERSE!
|
// 3. Drop... (almost) EVERYTHING... IN REVERSE!
|
||||||
drop(lock_pub_sys);
|
drop(lock_pub_sys);
|
||||||
debug!("Helper | Unlocking (1/12) ... [pub_sys]");
|
debug!("Helper | Unlocking (1/17) ... [pub_sys]");
|
||||||
drop(xvb);
|
drop(xvb);
|
||||||
debug!("Helper | Unlocking (2/12) ... [xvb]");
|
debug!("Helper | Unlocking (2/17) ... [xvb]");
|
||||||
drop(xmrig_proxy);
|
drop(xmrig_proxy);
|
||||||
debug!("Helper | Unlocking (3/12) ... [xmrig_proxy]");
|
debug!("Helper | Unlocking (3/17) ... [xmrig_proxy]");
|
||||||
drop(xmrig);
|
drop(xmrig);
|
||||||
debug!("Helper | Unlocking (3/12) ... [xmrig]");
|
debug!("Helper | Unlocking (4/17) ... [xmrig]");
|
||||||
drop(p2pool);
|
drop(p2pool);
|
||||||
debug!("Helper | Unlocking (4/12) ... [p2pool]");
|
debug!("Helper | Unlocking (5/17) ... [p2pool]");
|
||||||
drop(node);
|
drop(node);
|
||||||
debug!("Helper | Unlocking (4/12) ... [node]");
|
debug!("Helper | Unlocking (6/17) ... [node]");
|
||||||
drop(pub_api_xvb);
|
drop(pub_api_xvb);
|
||||||
debug!("Helper | Unlocking (5/12) ... [pub_api_xvb]");
|
debug!("Helper | Unlocking (7/17) ... [pub_api_xvb]");
|
||||||
drop(pub_api_xp);
|
drop(pub_api_xp);
|
||||||
debug!("Helper | Unlocking (6/12) ... [pub_api_xp]");
|
debug!("Helper | Unlocking (8/17) ... [pub_api_xp]");
|
||||||
drop(pub_api_xmrig);
|
drop(pub_api_xmrig);
|
||||||
debug!("Helper | Unlocking (6/12) ... [pub_api_xmrig]");
|
debug!("Helper | Unlocking (9/17) ... [pub_api_xmrig]");
|
||||||
drop(pub_api_p2pool);
|
drop(pub_api_p2pool);
|
||||||
debug!("Helper | Unlocking (7/12) ... [pub_api_p2pool]");
|
debug!("Helper | Unlocking (10/17) ... [pub_api_p2pool]");
|
||||||
drop(pub_api_node);
|
drop(pub_api_node);
|
||||||
debug!("Helper | Unlocking (7/12) ... [node]");
|
debug!("Helper | Unlocking (11/17) ... [pub_api_node]");
|
||||||
drop(gui_api_xvb);
|
drop(gui_api_xvb);
|
||||||
debug!("Helper | Unlocking (8/12) ... [gui_api_xvb]");
|
debug!("Helper | Unlocking (12/17) ... [gui_api_xvb]");
|
||||||
drop(gui_api_xp);
|
drop(gui_api_xp);
|
||||||
debug!("Helper | Unlocking (9/12) ... [gui_api_xp]");
|
debug!("Helper | Unlocking (13/17) ... [gui_api_xp]");
|
||||||
drop(gui_api_xmrig);
|
drop(gui_api_xmrig);
|
||||||
debug!("Helper | Unlocking (10/12) ... [gui_api_xmrig]");
|
debug!("Helper | Unlocking (14/17) ... [gui_api_xmrig]");
|
||||||
drop(gui_api_p2pool);
|
drop(gui_api_p2pool);
|
||||||
debug!("Helper | Unlocking (11/12) ... [gui_api_p2pool]");
|
debug!("Helper | Unlocking (15/17) ... [gui_api_p2pool]");
|
||||||
drop(gui_api_node);
|
drop(gui_api_node);
|
||||||
debug!("Helper | Unlocking (11/12) ... [node]");
|
debug!("Helper | Unlocking (16/17) ... [gui_api_node]");
|
||||||
drop(lock);
|
drop(lock);
|
||||||
debug!("Helper | Unlocking (12/12) ... [helper]");
|
debug!("Helper | Unlocking (17/17) ... [helper]");
|
||||||
|
|
||||||
// 4. Calculate if we should sleep or not.
|
// 4. Calculate if we should sleep or not.
|
||||||
// If we should sleep, how long?
|
// If we should sleep, how long?
|
||||||
|
@ -686,71 +686,63 @@ fn check_user_input(process: &Arc<Mutex<Process>>, stdin: &mut Box<dyn std::io::
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
fn signal_end(
|
fn signal_end(
|
||||||
process: &Arc<Mutex<Process>>,
|
process: &mut Process,
|
||||||
child_pty: &Arc<Mutex<Box<dyn Child + Sync + Send>>>,
|
child_pty: &Arc<Mutex<Box<dyn Child + Sync + Send>>>,
|
||||||
start: &Instant,
|
start: &Instant,
|
||||||
gui_api_output_raw: &mut String,
|
gui_api_output_raw: &mut String,
|
||||||
) -> bool {
|
) -> bool {
|
||||||
if process.lock().unwrap().signal == ProcessSignal::Stop {
|
let mut child_pty_lock = child_pty.lock().unwrap();
|
||||||
debug!("{} Watchdog | Stop SIGNAL caught", process.lock().unwrap().name);
|
if process.signal == ProcessSignal::Stop {
|
||||||
|
debug!("{} Watchdog | Stop SIGNAL caught", process.name);
|
||||||
// This actually sends a SIGHUP to p2pool (closes the PTY, hangs up on p2pool)
|
// This actually sends a SIGHUP to p2pool (closes the PTY, hangs up on p2pool)
|
||||||
if let Err(e) = child_pty.lock().unwrap().kill() {
|
if let Err(e) = child_pty_lock.kill() {
|
||||||
error!("{} Watchdog | Kill error: {}", process.lock().unwrap().name, e);
|
error!("{} Watchdog | Kill error: {}", process.name, e);
|
||||||
}
|
}
|
||||||
// Wait to get the exit status
|
// Wait to get the exit status
|
||||||
let exit_status = match child_pty.lock().unwrap().wait() {
|
let exit_status = match child_pty_lock.wait() {
|
||||||
Ok(e) => {
|
Ok(e) => {
|
||||||
if e.success() {
|
if e.success() {
|
||||||
process.lock().unwrap().state = ProcessState::Dead;
|
process.state = ProcessState::Dead;
|
||||||
"Successful"
|
"Successful"
|
||||||
} else {
|
} else {
|
||||||
process.lock().unwrap().state = ProcessState::Failed;
|
process.state = ProcessState::Failed;
|
||||||
"Failed"
|
"Failed"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
_ => {
|
_ => {
|
||||||
process.lock().unwrap().state = ProcessState::Failed;
|
process.state = ProcessState::Failed;
|
||||||
"Unknown Error"
|
"Unknown Error"
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
let uptime = HumanTime::into_human(start.elapsed());
|
let uptime = HumanTime::into_human(start.elapsed());
|
||||||
info!(
|
info!(
|
||||||
"{} Watchdog | Stopped ... Uptime was: [{}], Exit status: [{}]",
|
"{} Watchdog | Stopped ... Uptime was: [{}], Exit status: [{}]",
|
||||||
process.lock().unwrap().name,
|
process.name, uptime, exit_status
|
||||||
uptime,
|
|
||||||
exit_status
|
|
||||||
);
|
);
|
||||||
// This is written directly into the GUI API, because sometimes the 900ms event loop can't catch it.
|
// This is written directly into the GUI API, because sometimes the 900ms event loop can't catch it.
|
||||||
|
let name = process.name.to_owned();
|
||||||
if let Err(e) = writeln!(
|
if let Err(e) = writeln!(
|
||||||
gui_api_output_raw,
|
gui_api_output_raw,
|
||||||
"{}\n{} stopped | Uptime: [{}] | Exit status: [{}]\n{}\n\n\n\n",
|
"{}\n{} stopped | Uptime: [{}] | Exit status: [{}]\n{}\n\n\n\n",
|
||||||
process.lock().unwrap().name,
|
name, HORI_CONSOLE, uptime, exit_status, HORI_CONSOLE
|
||||||
HORI_CONSOLE,
|
|
||||||
uptime,
|
|
||||||
exit_status,
|
|
||||||
HORI_CONSOLE
|
|
||||||
) {
|
) {
|
||||||
error!(
|
error!(
|
||||||
"{} Watchdog | GUI Uptime/Exit status write failed: {}",
|
"{} Watchdog | GUI Uptime/Exit status write failed: {}",
|
||||||
process.lock().unwrap().name,
|
name, e
|
||||||
e
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
process.lock().unwrap().signal = ProcessSignal::None;
|
process.signal = ProcessSignal::None;
|
||||||
debug!(
|
debug!("{} Watchdog | Stop SIGNAL done, breaking", process.name,);
|
||||||
"{} Watchdog | Stop SIGNAL done, breaking",
|
|
||||||
process.lock().unwrap().name,
|
|
||||||
);
|
|
||||||
return true;
|
return true;
|
||||||
// Check RESTART
|
// Check RESTART
|
||||||
} else if process.lock().unwrap().signal == ProcessSignal::Restart {
|
} else if process.signal == ProcessSignal::Restart {
|
||||||
debug!("{} Watchdog | Restart SIGNAL caught", process.lock().unwrap().name,);
|
debug!("{} Watchdog | Restart SIGNAL caught", process.name,);
|
||||||
// This actually sends a SIGHUP to p2pool (closes the PTY, hangs up on p2pool)
|
// This actually sends a SIGHUP to p2pool (closes the PTY, hangs up on p2pool)
|
||||||
if let Err(e) = child_pty.lock().unwrap().kill() {
|
if let Err(e) = child_pty_lock.kill() {
|
||||||
error!("{} Watchdog | Kill error: {}", process.lock().unwrap().name, e);
|
error!("{} Watchdog | Kill error: {}", process.name, e);
|
||||||
}
|
}
|
||||||
// Wait to get the exit status
|
// Wait to get the exit status
|
||||||
let exit_status = match child_pty.lock().unwrap().wait() {
|
let exit_status = match child_pty_lock.wait() {
|
||||||
Ok(e) => {
|
Ok(e) => {
|
||||||
if e.success() {
|
if e.success() {
|
||||||
"Successful"
|
"Successful"
|
||||||
|
@ -763,31 +755,22 @@ fn signal_end(
|
||||||
let uptime = HumanTime::into_human(start.elapsed());
|
let uptime = HumanTime::into_human(start.elapsed());
|
||||||
info!(
|
info!(
|
||||||
"{} Watchdog | Stopped ... Uptime was: [{}], Exit status: [{}]",
|
"{} Watchdog | Stopped ... Uptime was: [{}], Exit status: [{}]",
|
||||||
process.lock().unwrap().name,
|
process.name, uptime, exit_status
|
||||||
uptime,
|
|
||||||
exit_status
|
|
||||||
);
|
);
|
||||||
// This is written directly into the GUI API, because sometimes the 900ms event loop can't catch it.
|
// This is written directly into the GUI API, because sometimes the 900ms event loop can't catch it.
|
||||||
|
let name = process.name.to_owned();
|
||||||
if let Err(e) = writeln!(
|
if let Err(e) = writeln!(
|
||||||
gui_api_output_raw,
|
gui_api_output_raw,
|
||||||
"{}\n{} stopped | Uptime: [{}] | Exit status: [{}]\n{}\n\n\n\n",
|
"{}\n{} stopped | Uptime: [{}] | Exit status: [{}]\n{}\n\n\n\n",
|
||||||
process.lock().unwrap().name,
|
name, HORI_CONSOLE, uptime, exit_status, HORI_CONSOLE
|
||||||
HORI_CONSOLE,
|
|
||||||
uptime,
|
|
||||||
exit_status,
|
|
||||||
HORI_CONSOLE
|
|
||||||
) {
|
) {
|
||||||
error!(
|
error!(
|
||||||
"{} Watchdog | GUI Uptime/Exit status write failed: {}",
|
"{} Watchdog | GUI Uptime/Exit status write failed: {}",
|
||||||
process.lock().unwrap().name,
|
name, e
|
||||||
e
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
process.lock().unwrap().state = ProcessState::Waiting;
|
process.state = ProcessState::Waiting;
|
||||||
debug!(
|
debug!("{} Watchdog | Restart SIGNAL done, breaking", process.name,);
|
||||||
"{} Watchdog | Restart SIGNAL done, breaking",
|
|
||||||
process.lock().unwrap().name,
|
|
||||||
);
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
false
|
false
|
||||||
|
@ -796,8 +779,8 @@ async fn sleep_end_loop(now: Instant, name: ProcessName) {
|
||||||
// Sleep (only if 999ms hasn't passed)
|
// Sleep (only if 999ms hasn't passed)
|
||||||
let elapsed = now.elapsed().as_millis();
|
let elapsed = now.elapsed().as_millis();
|
||||||
// Since logic goes off if less than 1000, casting should be safe
|
// Since logic goes off if less than 1000, casting should be safe
|
||||||
if elapsed < 999 {
|
if elapsed < 1000 {
|
||||||
let sleep = (999 - elapsed) as u64;
|
let sleep = (1000 - elapsed) as u64;
|
||||||
debug!(
|
debug!(
|
||||||
"{} Watchdog | END OF LOOP - Sleeping for [{}]ms...",
|
"{} Watchdog | END OF LOOP - Sleeping for [{}]ms...",
|
||||||
name, sleep
|
name, sleep
|
||||||
|
|
|
@ -227,56 +227,62 @@ impl Helper {
|
||||||
loop {
|
loop {
|
||||||
let now = Instant::now();
|
let now = Instant::now();
|
||||||
debug!("Node Watchdog | ----------- Start of loop -----------");
|
debug!("Node Watchdog | ----------- Start of loop -----------");
|
||||||
|
|
||||||
// check state
|
|
||||||
if check_died(
|
|
||||||
&child_pty,
|
|
||||||
&mut process.lock().unwrap(),
|
|
||||||
&start,
|
|
||||||
&mut gui_api.lock().unwrap().output,
|
|
||||||
) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
// check signal
|
|
||||||
if signal_end(
|
|
||||||
process,
|
|
||||||
&child_pty,
|
|
||||||
&start,
|
|
||||||
&mut gui_api.lock().unwrap().output,
|
|
||||||
) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
// check user input
|
|
||||||
check_user_input(process, &mut stdin);
|
|
||||||
// get data output/api
|
|
||||||
|
|
||||||
// Check if logs need resetting
|
|
||||||
debug!("Node Watchdog | Attempting GUI log reset check");
|
|
||||||
{
|
{
|
||||||
let mut lock = gui_api.lock().unwrap();
|
// scope to drop locked mutex before the sleep
|
||||||
Self::check_reset_gui_output(&mut lock.output, ProcessName::Node);
|
// check state
|
||||||
}
|
if check_died(
|
||||||
// No need to check output since monerod has a sufficient API
|
&child_pty,
|
||||||
// Always update from output
|
&mut process.lock().unwrap(),
|
||||||
debug!("Node Watchdog | Starting [update_from_output()]");
|
&start,
|
||||||
PubNodeApi::update_from_output(pub_api, &output_pub, start.elapsed());
|
&mut gui_api.lock().unwrap().output,
|
||||||
// update data from api
|
) {
|
||||||
debug!("Node Watchdog | Attempting HTTP API request...");
|
break;
|
||||||
match PrivNodeApi::request_api(&client, &state).await {
|
|
||||||
Ok(priv_api) => {
|
|
||||||
debug!("Node Watchdog | HTTP API request OK, attempting [update_from_priv()]");
|
|
||||||
if priv_api.result.synchronized && priv_api.result.status == "OK" {
|
|
||||||
process.lock().unwrap().state = ProcessState::Alive
|
|
||||||
}
|
|
||||||
PubNodeApi::update_from_priv(pub_api, priv_api);
|
|
||||||
}
|
}
|
||||||
Err(err) => {
|
// check signal
|
||||||
// if node is just starting, do not throw an error
|
if signal_end(
|
||||||
if start.elapsed() > Duration::from_secs(10) {
|
&mut process.lock().unwrap(),
|
||||||
warn!(
|
&child_pty,
|
||||||
"Node Watchdog | Could not send HTTP API request to node\n{}",
|
&start,
|
||||||
err
|
&mut gui_api.lock().unwrap().output,
|
||||||
|
) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
// check user input
|
||||||
|
check_user_input(process, &mut stdin);
|
||||||
|
// get data output/api
|
||||||
|
|
||||||
|
// Check if logs need resetting
|
||||||
|
debug!("Node Watchdog | Attempting GUI log reset check");
|
||||||
|
{
|
||||||
|
Self::check_reset_gui_output(
|
||||||
|
&mut gui_api.lock().unwrap().output,
|
||||||
|
ProcessName::Node,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
// No need to check output since monerod has a sufficient API
|
||||||
|
// Always update from output
|
||||||
|
debug!("Node Watchdog | Starting [update_from_output()]");
|
||||||
|
PubNodeApi::update_from_output(pub_api, &output_pub, start.elapsed());
|
||||||
|
// update data from api
|
||||||
|
debug!("Node Watchdog | Attempting HTTP API request...");
|
||||||
|
match PrivNodeApi::request_api(&client, &state).await {
|
||||||
|
Ok(priv_api) => {
|
||||||
|
debug!(
|
||||||
|
"Node Watchdog | HTTP API request OK, attempting [update_from_priv()]"
|
||||||
);
|
);
|
||||||
|
if priv_api.result.synchronized && priv_api.result.status == "OK" {
|
||||||
|
process.lock().unwrap().state = ProcessState::Alive
|
||||||
|
}
|
||||||
|
PubNodeApi::update_from_priv(pub_api, priv_api);
|
||||||
|
}
|
||||||
|
Err(err) => {
|
||||||
|
// if node is just starting, do not throw an error
|
||||||
|
if start.elapsed() > Duration::from_secs(10) {
|
||||||
|
warn!(
|
||||||
|
"Node Watchdog | Could not send HTTP API request to node\n{}",
|
||||||
|
err
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -527,109 +527,111 @@ impl Helper {
|
||||||
// Set timer
|
// Set timer
|
||||||
let now = Instant::now();
|
let now = Instant::now();
|
||||||
debug!("P2Pool Watchdog | ----------- Start of loop -----------");
|
debug!("P2Pool Watchdog | ----------- Start of loop -----------");
|
||||||
gui_api.lock().unwrap().tick = (last_p2pool_request.elapsed().as_secs() % 60) as u8;
|
|
||||||
|
|
||||||
// Check if the process is secretly died without us knowing :)
|
|
||||||
if check_died(
|
|
||||||
&child_pty,
|
|
||||||
&mut process.lock().unwrap(),
|
|
||||||
&start,
|
|
||||||
&mut gui_api.lock().unwrap().output,
|
|
||||||
) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Check SIGNAL
|
|
||||||
if signal_end(
|
|
||||||
&process,
|
|
||||||
&child_pty,
|
|
||||||
&start,
|
|
||||||
&mut gui_api.lock().unwrap().output,
|
|
||||||
) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
// Check vector of user input
|
|
||||||
check_user_input(&process, &mut stdin);
|
|
||||||
// Check if logs need resetting
|
|
||||||
debug!("P2Pool Watchdog | Attempting GUI log reset check");
|
|
||||||
let mut lock = gui_api.lock().unwrap();
|
|
||||||
Self::check_reset_gui_output(&mut lock.output, ProcessName::P2pool);
|
|
||||||
drop(lock);
|
|
||||||
|
|
||||||
// Always update from output
|
|
||||||
debug!("P2Pool Watchdog | Starting [update_from_output()]");
|
|
||||||
PubP2poolApi::update_from_output(
|
|
||||||
&pub_api,
|
|
||||||
&output_parse,
|
|
||||||
&output_pub,
|
|
||||||
start.elapsed(),
|
|
||||||
&process,
|
|
||||||
);
|
|
||||||
|
|
||||||
// Read [local] API
|
|
||||||
debug!("P2Pool Watchdog | Attempting [local] API file read");
|
|
||||||
if let Ok(string) = Self::path_to_string(&api_path_local, ProcessName::P2pool) {
|
|
||||||
// Deserialize
|
|
||||||
if let Ok(local_api) = PrivP2poolLocalApi::from_str(&string) {
|
|
||||||
// Update the structs.
|
|
||||||
PubP2poolApi::update_from_local(&pub_api, local_api);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// If more than 1 minute has passed, read the other API files.
|
|
||||||
let last_p2pool_request_expired =
|
|
||||||
last_p2pool_request.elapsed() >= Duration::from_secs(60);
|
|
||||||
// need to reload fast to get the first right values after syncing.
|
|
||||||
// check if value is 100k or under and request immediately if that's the case. fixed in release of p2pool including commit https://github.com/SChernykh/p2pool/commit/64a199be6dec7924b41f857a401086f25e1ec9be
|
|
||||||
if (last_p2pool_request_expired
|
|
||||||
|| pub_api.lock().unwrap().p2pool_difficulty_u64 <= 100000)
|
|
||||||
&& process.lock().unwrap().state == ProcessState::Alive
|
|
||||||
{
|
{
|
||||||
debug!("P2Pool Watchdog | Attempting [network] & [pool] API file read");
|
gui_api.lock().unwrap().tick = (last_p2pool_request.elapsed().as_secs() % 60) as u8;
|
||||||
if let (Ok(network_api), Ok(pool_api)) = (
|
// Check if the process is secretly died without us knowing :)
|
||||||
Self::path_to_string(&api_path_network, ProcessName::P2pool),
|
if check_died(
|
||||||
Self::path_to_string(&api_path_pool, ProcessName::P2pool),
|
&child_pty,
|
||||||
|
&mut process.lock().unwrap(),
|
||||||
|
&start,
|
||||||
|
&mut gui_api.lock().unwrap().output,
|
||||||
) {
|
) {
|
||||||
if let (Ok(network_api), Ok(pool_api)) = (
|
break;
|
||||||
PrivP2poolNetworkApi::from_str(&network_api),
|
}
|
||||||
PrivP2poolPoolApi::from_str(&pool_api),
|
|
||||||
) {
|
// Check SIGNAL
|
||||||
PubP2poolApi::update_from_network_pool(&pub_api, network_api, pool_api);
|
if signal_end(
|
||||||
last_p2pool_request = tokio::time::Instant::now();
|
&mut process.lock().unwrap(),
|
||||||
|
&child_pty,
|
||||||
|
&start,
|
||||||
|
&mut gui_api.lock().unwrap().output,
|
||||||
|
) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
// Check vector of user input
|
||||||
|
check_user_input(&process, &mut stdin);
|
||||||
|
// Check if logs need resetting
|
||||||
|
debug!("P2Pool Watchdog | Attempting GUI log reset check");
|
||||||
|
let mut lock = gui_api.lock().unwrap();
|
||||||
|
Self::check_reset_gui_output(&mut lock.output, ProcessName::P2pool);
|
||||||
|
drop(lock);
|
||||||
|
|
||||||
|
// Always update from output
|
||||||
|
debug!("P2Pool Watchdog | Starting [update_from_output()]");
|
||||||
|
let mut process_lock = process.lock().unwrap();
|
||||||
|
let mut pub_api_lock = pub_api.lock().unwrap();
|
||||||
|
PubP2poolApi::update_from_output(
|
||||||
|
&mut pub_api_lock,
|
||||||
|
&output_parse,
|
||||||
|
&output_pub,
|
||||||
|
start.elapsed(),
|
||||||
|
&mut process_lock,
|
||||||
|
);
|
||||||
|
|
||||||
|
// Read [local] API
|
||||||
|
debug!("P2Pool Watchdog | Attempting [local] API file read");
|
||||||
|
if let Ok(string) = Self::path_to_string(&api_path_local, ProcessName::P2pool) {
|
||||||
|
// Deserialize
|
||||||
|
if let Ok(local_api) = PrivP2poolLocalApi::from_str(&string) {
|
||||||
|
// Update the structs.
|
||||||
|
PubP2poolApi::update_from_local(&mut pub_api_lock, local_api);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
// If more than 1 minute has passed, read the other API files.
|
||||||
|
let last_p2pool_request_expired =
|
||||||
let last_status_request_expired =
|
last_p2pool_request.elapsed() >= Duration::from_secs(60);
|
||||||
last_status_request.elapsed() >= Duration::from_secs(60);
|
// need to reload fast to get the first right values after syncing.
|
||||||
|
// check if value is 100k or under and request immediately if that's the case. fixed in release of p2pool including commit https://github.com/SChernykh/p2pool/commit/64a199be6dec7924b41f857a401086f25e1ec9be
|
||||||
if (last_status_request_expired || first_loop)
|
if (last_p2pool_request_expired
|
||||||
&& process.lock().unwrap().state == ProcessState::Alive
|
|| pub_api.lock().unwrap().p2pool_difficulty_u64 <= 100000)
|
||||||
{
|
&& process_lock.state == ProcessState::Alive
|
||||||
debug!("P2Pool Watchdog | Reading status output of p2pool node");
|
{
|
||||||
#[cfg(target_os = "windows")]
|
debug!("P2Pool Watchdog | Attempting [network] & [pool] API file read");
|
||||||
if let Err(e) = write!(stdin, "statusfromgupaxx\r\n") {
|
if let (Ok(network_api), Ok(pool_api)) = (
|
||||||
error!("P2Pool Watchdog | STDIN error: {}", e);
|
Self::path_to_string(&api_path_network, ProcessName::P2pool),
|
||||||
|
Self::path_to_string(&api_path_pool, ProcessName::P2pool),
|
||||||
|
) {
|
||||||
|
if let (Ok(network_api), Ok(pool_api)) = (
|
||||||
|
PrivP2poolNetworkApi::from_str(&network_api),
|
||||||
|
PrivP2poolPoolApi::from_str(&pool_api),
|
||||||
|
) {
|
||||||
|
PubP2poolApi::update_from_network_pool(
|
||||||
|
&mut pub_api_lock,
|
||||||
|
network_api,
|
||||||
|
pool_api,
|
||||||
|
);
|
||||||
|
last_p2pool_request = tokio::time::Instant::now();
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
#[cfg(target_family = "unix")]
|
|
||||||
if let Err(e) = writeln!(stdin, "statusfromgupaxx") {
|
|
||||||
error!("P2Pool Watchdog | STDIN error: {}", e);
|
|
||||||
}
|
|
||||||
// Flush.
|
|
||||||
if let Err(e) = stdin.flush() {
|
|
||||||
error!("P2Pool Watchdog | STDIN flush error: {}", e);
|
|
||||||
}
|
|
||||||
last_status_request = tokio::time::Instant::now();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Sleep (only if 900ms hasn't passed)
|
let last_status_request_expired =
|
||||||
if first_loop {
|
last_status_request.elapsed() >= Duration::from_secs(60);
|
||||||
first_loop = false;
|
if (last_status_request_expired || first_loop)
|
||||||
}
|
&& process_lock.state == ProcessState::Alive
|
||||||
|
{
|
||||||
|
debug!("P2Pool Watchdog | Reading status output of p2pool node");
|
||||||
|
#[cfg(target_os = "windows")]
|
||||||
|
if let Err(e) = write!(stdin, "statusfromgupaxx\r\n") {
|
||||||
|
error!("P2Pool Watchdog | STDIN error: {}", e);
|
||||||
|
}
|
||||||
|
#[cfg(target_family = "unix")]
|
||||||
|
if let Err(e) = writeln!(stdin, "statusfromgupaxx") {
|
||||||
|
error!("P2Pool Watchdog | STDIN error: {}", e);
|
||||||
|
}
|
||||||
|
// Flush.
|
||||||
|
if let Err(e) = stdin.flush() {
|
||||||
|
error!("P2Pool Watchdog | STDIN flush error: {}", e);
|
||||||
|
}
|
||||||
|
last_status_request = tokio::time::Instant::now();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Sleep (only if 900ms hasn't passed)
|
||||||
|
if first_loop {
|
||||||
|
first_loop = false;
|
||||||
|
}
|
||||||
|
} // end of scope to drop lock
|
||||||
sleep_end_loop(now, ProcessName::P2pool).await;
|
sleep_end_loop(now, ProcessName::P2pool).await;
|
||||||
debug!(
|
|
||||||
"P2Pool Watchdog | END OF LOOP - Tick: [{}/60]",
|
|
||||||
gui_api.lock().unwrap().tick,
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// 5. If loop broke, we must be done here.
|
// 5. If loop broke, we must be done here.
|
||||||
|
@ -826,46 +828,39 @@ impl PubP2poolApi {
|
||||||
|
|
||||||
// Mutate "watchdog"'s [PubP2poolApi] with data the process output.
|
// Mutate "watchdog"'s [PubP2poolApi] with data the process output.
|
||||||
pub(super) fn update_from_output(
|
pub(super) fn update_from_output(
|
||||||
public: &Arc<Mutex<Self>>,
|
public: &mut Self,
|
||||||
output_parse: &Arc<Mutex<String>>,
|
output_parse: &Arc<Mutex<String>>,
|
||||||
output_pub: &Arc<Mutex<String>>,
|
output_pub: &Arc<Mutex<String>>,
|
||||||
elapsed: std::time::Duration,
|
elapsed: std::time::Duration,
|
||||||
process: &Arc<Mutex<Process>>,
|
process: &mut Process,
|
||||||
) {
|
) {
|
||||||
// 1. Take the process's current output buffer and combine it with Pub (if not empty)
|
// 1. Take the process's current output buffer and combine it with Pub (if not empty)
|
||||||
let mut output_pub = output_pub.lock().unwrap();
|
let mut output_pub = output_pub.lock().unwrap();
|
||||||
if !output_pub.is_empty() {
|
if !output_pub.is_empty() {
|
||||||
public
|
public.output.push_str(&std::mem::take(&mut *output_pub));
|
||||||
.lock()
|
|
||||||
.unwrap()
|
|
||||||
.output
|
|
||||||
.push_str(&std::mem::take(&mut *output_pub));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// 2. Parse the full STDOUT
|
// 2. Parse the full STDOUT
|
||||||
let mut output_parse = output_parse.lock().unwrap();
|
let mut output_parse = output_parse.lock().unwrap();
|
||||||
let (payouts_new, xmr_new) = Self::calc_payouts_and_xmr(&output_parse);
|
let (payouts_new, xmr_new) = Self::calc_payouts_and_xmr(&output_parse);
|
||||||
// Check for "SYNCHRONIZED" only if we aren't already.
|
// Check for "SYNCHRONIZED" only if we aren't already.
|
||||||
if process.lock().unwrap().state == ProcessState::Syncing {
|
if process.state == ProcessState::Syncing {
|
||||||
// look for depth 0
|
// look for depth 0
|
||||||
|
|
||||||
if P2POOL_REGEX.depth_0.is_match(&output_parse) {
|
if P2POOL_REGEX.depth_0.is_match(&output_parse) {
|
||||||
process.lock().unwrap().state = ProcessState::Alive;
|
process.state = ProcessState::Alive;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// check if zmq server still alive
|
// check if zmq server still alive
|
||||||
if process.lock().unwrap().state == ProcessState::Alive
|
if process.state == ProcessState::Alive && contains_zmq_connection_lost(&output_parse) {
|
||||||
&& contains_zmq_connection_lost(&output_parse)
|
|
||||||
{
|
|
||||||
// node zmq is not responding, p2pool is not ready
|
// node zmq is not responding, p2pool is not ready
|
||||||
process.lock().unwrap().state = ProcessState::Syncing;
|
process.state = ProcessState::Syncing;
|
||||||
}
|
}
|
||||||
|
|
||||||
// 3. Throw away [output_parse]
|
// 3. Throw away [output_parse]
|
||||||
output_parse.clear();
|
output_parse.clear();
|
||||||
drop(output_parse);
|
drop(output_parse);
|
||||||
// 4. Add to current values
|
// 4. Add to current values
|
||||||
let mut public = public.lock().unwrap();
|
|
||||||
let (payouts, xmr) = (public.payouts + payouts_new, public.xmr + xmr_new);
|
let (payouts, xmr) = (public.payouts + payouts_new, public.xmr + xmr_new);
|
||||||
|
|
||||||
// 5. Calculate hour/day/month given elapsed time
|
// 5. Calculate hour/day/month given elapsed time
|
||||||
|
@ -912,13 +907,12 @@ impl PubP2poolApi {
|
||||||
xmr_hour,
|
xmr_hour,
|
||||||
xmr_day,
|
xmr_day,
|
||||||
xmr_month,
|
xmr_month,
|
||||||
..std::mem::take(&mut *public)
|
..std::mem::take(public)
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
// Mutate [PubP2poolApi] with data from a [PrivP2poolLocalApi] and the process output.
|
// Mutate [PubP2poolApi] with data from a [PrivP2poolLocalApi] and the process output.
|
||||||
pub(super) fn update_from_local(public: &Arc<Mutex<Self>>, local: PrivP2poolLocalApi) {
|
pub(super) fn update_from_local(public: &mut Self, local: PrivP2poolLocalApi) {
|
||||||
let mut public = public.lock().unwrap();
|
|
||||||
*public = Self {
|
*public = Self {
|
||||||
hashrate_15m: HumanNumber::from_u64(local.hashrate_15m),
|
hashrate_15m: HumanNumber::from_u64(local.hashrate_15m),
|
||||||
hashrate_1h: HumanNumber::from_u64(local.hashrate_1h),
|
hashrate_1h: HumanNumber::from_u64(local.hashrate_1h),
|
||||||
|
@ -934,11 +928,11 @@ impl PubP2poolApi {
|
||||||
|
|
||||||
// Mutate [PubP2poolApi] with data from a [PrivP2pool(Network|Pool)Api].
|
// Mutate [PubP2poolApi] with data from a [PrivP2pool(Network|Pool)Api].
|
||||||
pub(super) fn update_from_network_pool(
|
pub(super) fn update_from_network_pool(
|
||||||
public: &Arc<Mutex<Self>>,
|
public: &mut Self,
|
||||||
net: PrivP2poolNetworkApi,
|
net: PrivP2poolNetworkApi,
|
||||||
pool: PrivP2poolPoolApi,
|
pool: PrivP2poolPoolApi,
|
||||||
) {
|
) {
|
||||||
let user_hashrate = public.lock().unwrap().user_p2pool_hashrate_u64; // The user's total P2Pool hashrate
|
let user_hashrate = public.user_p2pool_hashrate_u64; // The user's total P2Pool hashrate
|
||||||
let monero_difficulty = net.difficulty;
|
let monero_difficulty = net.difficulty;
|
||||||
let monero_hashrate = monero_difficulty / MONERO_BLOCK_TIME_IN_SECONDS;
|
let monero_hashrate = monero_difficulty / MONERO_BLOCK_TIME_IN_SECONDS;
|
||||||
let p2pool_hashrate = pool.pool_statistics.hashRate;
|
let p2pool_hashrate = pool.pool_statistics.hashRate;
|
||||||
|
@ -980,7 +974,6 @@ impl PubP2poolApi {
|
||||||
p2pool_difficulty / user_hashrate,
|
p2pool_difficulty / user_hashrate,
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
let mut public = public.lock().unwrap();
|
|
||||||
*public = Self {
|
*public = Self {
|
||||||
p2pool_difficulty_u64: p2pool_difficulty,
|
p2pool_difficulty_u64: p2pool_difficulty,
|
||||||
monero_difficulty_u64: monero_difficulty,
|
monero_difficulty_u64: monero_difficulty,
|
||||||
|
|
|
@ -116,8 +116,14 @@ Uptime = 0h 2m 4s
|
||||||
"".to_string(),
|
"".to_string(),
|
||||||
PathBuf::new(),
|
PathBuf::new(),
|
||||||
)));
|
)));
|
||||||
PubP2poolApi::update_from_output(&public, &output_parse, &output_pub, elapsed, &process);
|
let mut public = public.lock().unwrap();
|
||||||
let public = public.lock().unwrap();
|
PubP2poolApi::update_from_output(
|
||||||
|
&mut public,
|
||||||
|
&output_parse,
|
||||||
|
&output_pub,
|
||||||
|
elapsed,
|
||||||
|
&mut process.lock().unwrap(),
|
||||||
|
);
|
||||||
println!("{:#?}", public);
|
println!("{:#?}", public);
|
||||||
assert_eq!(public.payouts, 3);
|
assert_eq!(public.payouts, 3);
|
||||||
assert_eq!(public.payouts_hour, 180.0);
|
assert_eq!(public.payouts_hour, 180.0);
|
||||||
|
@ -161,8 +167,8 @@ Uptime = 0h 2m 4s
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
// Update Local
|
// Update Local
|
||||||
PubP2poolApi::update_from_local(&public, local);
|
let mut p = public.lock().unwrap();
|
||||||
let p = public.lock().unwrap();
|
PubP2poolApi::update_from_local(&mut p, local);
|
||||||
println!("AFTER LOCAL: {:#?}", p);
|
println!("AFTER LOCAL: {:#?}", p);
|
||||||
assert_eq!(p.hashrate_15m.to_string(), "10,000");
|
assert_eq!(p.hashrate_15m.to_string(), "10,000");
|
||||||
assert_eq!(p.hashrate_1h.to_string(), "20,000");
|
assert_eq!(p.hashrate_1h.to_string(), "20,000");
|
||||||
|
@ -175,10 +181,8 @@ Uptime = 0h 2m 4s
|
||||||
assert_eq!(p.current_effort.to_string(), "200.00%");
|
assert_eq!(p.current_effort.to_string(), "200.00%");
|
||||||
assert_eq!(p.connections.to_string(), "1,234");
|
assert_eq!(p.connections.to_string(), "1,234");
|
||||||
assert_eq!(p.user_p2pool_hashrate_u64, 20000);
|
assert_eq!(p.user_p2pool_hashrate_u64, 20000);
|
||||||
drop(p);
|
|
||||||
// Update Network + Pool
|
// Update Network + Pool
|
||||||
PubP2poolApi::update_from_network_pool(&public, network, pool);
|
PubP2poolApi::update_from_network_pool(&mut p, network, pool);
|
||||||
let p = public.lock().unwrap();
|
|
||||||
println!("AFTER NETWORK+POOL: {:#?}", p);
|
println!("AFTER NETWORK+POOL: {:#?}", p);
|
||||||
assert_eq!(p.monero_difficulty.to_string(), "300,000,000,000");
|
assert_eq!(p.monero_difficulty.to_string(), "300,000,000,000");
|
||||||
assert_eq!(p.monero_hashrate.to_string(), "2.500 GH/s");
|
assert_eq!(p.monero_hashrate.to_string(), "2.500 GH/s");
|
||||||
|
|
|
@ -1,12 +1,12 @@
|
||||||
|
use crate::constants::*;
|
||||||
use crate::helper::xrig::update_xmrig_config;
|
use crate::helper::xrig::update_xmrig_config;
|
||||||
use crate::helper::{check_died, check_user_input, sleep_end_loop, Process};
|
use crate::helper::{arc_mut, check_died, check_user_input, sleep, sleep_end_loop, Process};
|
||||||
use crate::helper::{Helper, ProcessName, ProcessSignal, ProcessState};
|
use crate::helper::{Helper, ProcessName, ProcessSignal, ProcessState};
|
||||||
use crate::helper::{PubXvbApi, XvbNode};
|
use crate::helper::{PubXvbApi, XvbNode};
|
||||||
use crate::miscs::output_console;
|
use crate::miscs::output_console;
|
||||||
use crate::regex::{contains_error, contains_usepool, detect_new_node_xmrig, XMRIG_REGEX};
|
use crate::regex::{contains_error, contains_usepool, detect_new_node_xmrig, XMRIG_REGEX};
|
||||||
use crate::utils::human::HumanNumber;
|
use crate::utils::human::HumanNumber;
|
||||||
use crate::utils::sudo::SudoState;
|
use crate::utils::sudo::SudoState;
|
||||||
use crate::{constants::*, macros::*};
|
|
||||||
use enclose::enclose;
|
use enclose::enclose;
|
||||||
use log::*;
|
use log::*;
|
||||||
use portable_pty::Child;
|
use portable_pty::Child;
|
||||||
|
@ -514,7 +514,7 @@ impl Helper {
|
||||||
}
|
}
|
||||||
// Stop on [Stop/Restart] SIGNAL
|
// Stop on [Stop/Restart] SIGNAL
|
||||||
if Self::xmrig_signal_end(
|
if Self::xmrig_signal_end(
|
||||||
&process,
|
&mut process.lock().unwrap(),
|
||||||
&child_pty,
|
&child_pty,
|
||||||
&start,
|
&start,
|
||||||
&mut gui_api.lock().unwrap().output,
|
&mut gui_api.lock().unwrap().output,
|
||||||
|
@ -591,13 +591,13 @@ impl Helper {
|
||||||
info!("XMRig Watchdog | Watchdog thread exiting... Goodbye!");
|
info!("XMRig Watchdog | Watchdog thread exiting... Goodbye!");
|
||||||
}
|
}
|
||||||
fn xmrig_signal_end(
|
fn xmrig_signal_end(
|
||||||
process: &Arc<Mutex<Process>>,
|
process: &mut Process,
|
||||||
child_pty: &Arc<Mutex<Box<dyn Child + Sync + Send>>>,
|
child_pty: &Arc<Mutex<Box<dyn Child + Sync + Send>>>,
|
||||||
start: &Instant,
|
start: &Instant,
|
||||||
gui_api_output_raw: &mut String,
|
gui_api_output_raw: &mut String,
|
||||||
sudo: &Arc<Mutex<SudoState>>,
|
sudo: &Arc<Mutex<SudoState>>,
|
||||||
) -> bool {
|
) -> bool {
|
||||||
let signal = process.lock().unwrap().signal;
|
let signal = process.signal;
|
||||||
if signal == ProcessSignal::Stop || signal == ProcessSignal::Restart {
|
if signal == ProcessSignal::Stop || signal == ProcessSignal::Restart {
|
||||||
debug!("XMRig Watchdog | Stop/Restart SIGNAL caught");
|
debug!("XMRig Watchdog | Stop/Restart SIGNAL caught");
|
||||||
// macOS requires [sudo] again to kill [XMRig]
|
// macOS requires [sudo] again to kill [XMRig]
|
||||||
|
@ -616,7 +616,6 @@ impl Helper {
|
||||||
}
|
}
|
||||||
let exit_status = match child_pty.lock().unwrap().wait() {
|
let exit_status = match child_pty.lock().unwrap().wait() {
|
||||||
Ok(e) => {
|
Ok(e) => {
|
||||||
let mut process = process.lock().unwrap();
|
|
||||||
if e.success() {
|
if e.success() {
|
||||||
if process.signal == ProcessSignal::Stop {
|
if process.signal == ProcessSignal::Stop {
|
||||||
process.state = ProcessState::Dead;
|
process.state = ProcessState::Dead;
|
||||||
|
@ -630,7 +629,6 @@ impl Helper {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
_ => {
|
_ => {
|
||||||
let mut process = process.lock().unwrap();
|
|
||||||
if process.signal == ProcessSignal::Stop {
|
if process.signal == ProcessSignal::Stop {
|
||||||
process.state = ProcessState::Failed;
|
process.state = ProcessState::Failed;
|
||||||
}
|
}
|
||||||
|
@ -652,7 +650,6 @@ impl Helper {
|
||||||
e
|
e
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
let mut process = process.lock().unwrap();
|
|
||||||
match process.signal {
|
match process.signal {
|
||||||
ProcessSignal::Stop => process.signal = ProcessSignal::None,
|
ProcessSignal::Stop => process.signal = ProcessSignal::None,
|
||||||
ProcessSignal::Restart => process.state = ProcessState::Waiting,
|
ProcessSignal::Restart => process.state = ProcessState::Waiting,
|
||||||
|
|
|
@ -371,91 +371,93 @@ impl Helper {
|
||||||
loop {
|
loop {
|
||||||
let now = Instant::now();
|
let now = Instant::now();
|
||||||
debug!("XMRig-Proxy Watchdog | ----------- Start of loop -----------");
|
debug!("XMRig-Proxy Watchdog | ----------- Start of loop -----------");
|
||||||
// check state
|
{
|
||||||
if check_died(
|
if check_died(
|
||||||
&child_pty,
|
&child_pty,
|
||||||
&mut process.lock().unwrap(),
|
&mut process.lock().unwrap(),
|
||||||
&start,
|
&start,
|
||||||
&mut gui_api.lock().unwrap().output,
|
&mut gui_api.lock().unwrap().output,
|
||||||
) {
|
) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
// check signal
|
// check signal
|
||||||
if signal_end(
|
if signal_end(
|
||||||
process,
|
&mut process.lock().unwrap(),
|
||||||
&child_pty,
|
&child_pty,
|
||||||
&start,
|
&start,
|
||||||
&mut gui_api.lock().unwrap().output,
|
&mut gui_api.lock().unwrap().output,
|
||||||
) {
|
) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
// check user input
|
// check user input
|
||||||
check_user_input(process, &mut stdin);
|
check_user_input(process, &mut stdin);
|
||||||
// get data output/api
|
// get data output/api
|
||||||
|
|
||||||
// Check if logs need resetting
|
// Check if logs need resetting
|
||||||
debug!("XMRig-Proxy Watchdog | Attempting GUI log reset check");
|
debug!("XMRig-Proxy Watchdog | Attempting GUI log reset check");
|
||||||
{
|
Self::check_reset_gui_output(
|
||||||
let mut lock = gui_api.lock().unwrap();
|
&mut gui_api.lock().unwrap().output,
|
||||||
Self::check_reset_gui_output(&mut lock.output, ProcessName::XmrigProxy);
|
ProcessName::XmrigProxy,
|
||||||
}
|
);
|
||||||
// Always update from output
|
// Always update from output
|
||||||
// todo: check difference with xmrig
|
// todo: check difference with xmrig
|
||||||
debug!("XMRig-Proxy Watchdog | Starting [update_from_output()]");
|
debug!("XMRig-Proxy Watchdog | Starting [update_from_output()]");
|
||||||
PubXmrigProxyApi::update_from_output(
|
PubXmrigProxyApi::update_from_output(
|
||||||
pub_api,
|
pub_api,
|
||||||
&output_pub,
|
&output_pub,
|
||||||
&output_parse,
|
&output_parse,
|
||||||
start.elapsed(),
|
start.elapsed(),
|
||||||
process,
|
process,
|
||||||
);
|
);
|
||||||
// update data from api
|
// update data from api
|
||||||
debug!("XMRig-Proxy Watchdog | Attempting HTTP API request...");
|
debug!("XMRig-Proxy Watchdog | Attempting HTTP API request...");
|
||||||
match PrivXmrigProxyApi::request_xp_api(&client, api_summary_xp, token_proxy).await {
|
match PrivXmrigProxyApi::request_xp_api(&client, api_summary_xp, token_proxy).await
|
||||||
Ok(priv_api) => {
|
|
||||||
debug!("XMRig-Proxy Watchdog | HTTP API request OK, attempting [update_from_priv()]");
|
|
||||||
PubXmrigProxyApi::update_from_priv(pub_api, priv_api);
|
|
||||||
}
|
|
||||||
Err(err) => {
|
|
||||||
warn!(
|
|
||||||
"XMRig-Proxy Watchdog | Could not send HTTP API request to: {}\n{}",
|
|
||||||
api_summary_xp, err
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// update xmrig to use xmrig-proxy if option enabled and local xmrig alive
|
|
||||||
if xmrig_redirect
|
|
||||||
&& gui_api_xmrig.lock().unwrap().node != XvbNode::XmrigProxy.to_string()
|
|
||||||
&& (process_xmrig.lock().unwrap().state == ProcessState::Alive
|
|
||||||
|| process_xmrig.lock().unwrap().state == ProcessState::NotMining)
|
|
||||||
{
|
|
||||||
info!("redirect local xmrig instance to xmrig-proxy");
|
|
||||||
if let Err(err) = update_xmrig_config(
|
|
||||||
&client,
|
|
||||||
api_config_xmrig,
|
|
||||||
&state_xmrig.token,
|
|
||||||
&XvbNode::XmrigProxy,
|
|
||||||
"",
|
|
||||||
GUPAX_VERSION_UNDERSCORE,
|
|
||||||
)
|
|
||||||
.await
|
|
||||||
{
|
{
|
||||||
// show to console error about updating xmrig config
|
Ok(priv_api) => {
|
||||||
warn!("XMRig-Proxy Process | Failed request HTTP API Xmrig");
|
debug!("XMRig-Proxy Watchdog | HTTP API request OK, attempting [update_from_priv()]");
|
||||||
output_console(
|
PubXmrigProxyApi::update_from_priv(pub_api, priv_api);
|
||||||
&mut gui_api.lock().unwrap().output,
|
}
|
||||||
&format!(
|
Err(err) => {
|
||||||
"Failure to update xmrig config with HTTP API.\nError: {}",
|
warn!(
|
||||||
err
|
"XMRig-Proxy Watchdog | Could not send HTTP API request to: {}\n{}",
|
||||||
),
|
api_summary_xp, err
|
||||||
ProcessName::XmrigProxy,
|
);
|
||||||
);
|
}
|
||||||
} else {
|
|
||||||
gui_api_xmrig.lock().unwrap().node = XvbNode::XmrigProxy.to_string();
|
|
||||||
debug!("XMRig-Proxy Process | mining on Xmrig-Proxy pool");
|
|
||||||
}
|
}
|
||||||
}
|
// update xmrig to use xmrig-proxy if option enabled and local xmrig alive
|
||||||
// do not use more than 1 second for the loop
|
if xmrig_redirect
|
||||||
|
&& gui_api_xmrig.lock().unwrap().node != XvbNode::XmrigProxy.to_string()
|
||||||
|
&& (process_xmrig.lock().unwrap().state == ProcessState::Alive
|
||||||
|
|| process_xmrig.lock().unwrap().state == ProcessState::NotMining)
|
||||||
|
{
|
||||||
|
info!("redirect local xmrig instance to xmrig-proxy");
|
||||||
|
if let Err(err) = update_xmrig_config(
|
||||||
|
&client,
|
||||||
|
api_config_xmrig,
|
||||||
|
&state_xmrig.token,
|
||||||
|
&XvbNode::XmrigProxy,
|
||||||
|
"",
|
||||||
|
GUPAX_VERSION_UNDERSCORE,
|
||||||
|
)
|
||||||
|
.await
|
||||||
|
{
|
||||||
|
// show to console error about updating xmrig config
|
||||||
|
warn!("XMRig-Proxy Process | Failed request HTTP API Xmrig");
|
||||||
|
output_console(
|
||||||
|
&mut gui_api.lock().unwrap().output,
|
||||||
|
&format!(
|
||||||
|
"Failure to update xmrig config with HTTP API.\nError: {}",
|
||||||
|
err
|
||||||
|
),
|
||||||
|
ProcessName::XmrigProxy,
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
gui_api_xmrig.lock().unwrap().node = XvbNode::XmrigProxy.to_string();
|
||||||
|
debug!("XMRig-Proxy Process | mining on Xmrig-Proxy pool");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} // locked are dropped here
|
||||||
|
// do not use more than 1 second for the loop
|
||||||
sleep_end_loop(now, ProcessName::XmrigProxy).await;
|
sleep_end_loop(now, ProcessName::XmrigProxy).await;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -208,203 +208,207 @@ impl Helper {
|
||||||
debug!("XvB Watchdog | ----------- Start of loop -----------");
|
debug!("XvB Watchdog | ----------- Start of loop -----------");
|
||||||
// Set timer of loop
|
// Set timer of loop
|
||||||
let start_loop = std::time::Instant::now();
|
let start_loop = std::time::Instant::now();
|
||||||
// check if first loop the state of Xmrig-Proxy
|
|
||||||
if first_loop {
|
|
||||||
xp_alive = process_xp.lock().unwrap().state == ProcessState::Alive;
|
|
||||||
msg_retry_done = false;
|
|
||||||
*retry.lock().unwrap() = false;
|
|
||||||
}
|
|
||||||
// verify if p2pool and xmrig are running, else XvB must be reloaded with another token/address to start verifying the other process.
|
|
||||||
if check_state_outcauses_xvb(
|
|
||||||
&client,
|
|
||||||
gui_api,
|
|
||||||
pub_api,
|
|
||||||
process,
|
|
||||||
process_xmrig,
|
|
||||||
process_xp,
|
|
||||||
process_p2pool,
|
|
||||||
&mut first_loop,
|
|
||||||
&handle_algo,
|
|
||||||
pub_api_xmrig,
|
|
||||||
pub_api_xp,
|
|
||||||
state_p2pool,
|
|
||||||
state_xmrig,
|
|
||||||
state_xp,
|
|
||||||
xp_alive,
|
|
||||||
)
|
|
||||||
.await
|
|
||||||
{
|
{
|
||||||
continue;
|
// check if first loop the state of Xmrig-Proxy
|
||||||
}
|
if first_loop {
|
||||||
// check signal
|
xp_alive = process_xp.lock().unwrap().state == ProcessState::Alive;
|
||||||
debug!("XvB | check signal");
|
msg_retry_done = false;
|
||||||
if signal_interrupt(
|
*retry.lock().unwrap() = false;
|
||||||
process,
|
}
|
||||||
if xp_alive { process_xp } else { process_xmrig },
|
// verify if p2pool and xmrig are running, else XvB must be reloaded with another token/address to start verifying the other process.
|
||||||
start.into(),
|
if check_state_outcauses_xvb(
|
||||||
&client,
|
&client,
|
||||||
pub_api,
|
gui_api,
|
||||||
gui_api,
|
pub_api,
|
||||||
gui_api_xmrig,
|
process,
|
||||||
gui_api_xp,
|
process_xmrig,
|
||||||
state_p2pool,
|
process_xp,
|
||||||
state_xmrig,
|
process_p2pool,
|
||||||
state_xp,
|
&mut first_loop,
|
||||||
xp_alive,
|
&handle_algo,
|
||||||
) {
|
pub_api_xmrig,
|
||||||
info!("XvB Watchdog | Signal has stopped the loop");
|
pub_api_xp,
|
||||||
break;
|
state_p2pool,
|
||||||
}
|
state_xmrig,
|
||||||
// let handle_algo_c = handle_algo.lock().unwrap();
|
state_xp,
|
||||||
let is_algo_started_once = handle_algo.lock().unwrap().is_some();
|
xp_alive,
|
||||||
let is_algo_finished = handle_algo
|
)
|
||||||
.lock()
|
.await
|
||||||
.unwrap()
|
{
|
||||||
.as_ref()
|
continue;
|
||||||
.is_some_and(|algo| algo.is_finished());
|
}
|
||||||
let is_request_finished = handle_request
|
// check signal
|
||||||
.lock()
|
debug!("XvB | check signal");
|
||||||
.unwrap()
|
if signal_interrupt(
|
||||||
.as_ref()
|
process,
|
||||||
.is_some_and(|request: &JoinHandle<()>| request.is_finished())
|
if xp_alive { process_xp } else { process_xmrig },
|
||||||
|| handle_request.lock().unwrap().is_none();
|
start.into(),
|
||||||
// Send an HTTP API request only if one minute is passed since the last request or if first loop or if algorithm need to retry or if request is finished and algo is finished or almost finished (only public and private stats). We make sure public and private stats are refreshed before doing another run of the algo.
|
&client,
|
||||||
// We make sure algo or request are not rerun when they are not over.
|
pub_api,
|
||||||
// in the case of quick refresh before new run of algo, make sure it doesn't happen multiple times.
|
gui_api,
|
||||||
let last_request_expired =
|
gui_api_xmrig,
|
||||||
last_request.lock().unwrap().elapsed() >= Duration::from_secs(60);
|
gui_api_xp,
|
||||||
let should_refresh_before_next_algo = is_algo_started_once
|
state_p2pool,
|
||||||
&& last_algorithm.lock().unwrap().elapsed()
|
state_xmrig,
|
||||||
>= Duration::from_secs((XVB_TIME_ALGO as f32 * 0.95) as u64)
|
state_xp,
|
||||||
&& last_request.lock().unwrap().elapsed() >= Duration::from_secs(25);
|
xp_alive,
|
||||||
let process_alive = process.lock().unwrap().state == ProcessState::Alive;
|
) {
|
||||||
if ((last_request_expired || first_loop)
|
info!("XvB Watchdog | Signal has stopped the loop");
|
||||||
|| (*retry.lock().unwrap() || is_algo_finished || should_refresh_before_next_algo)
|
break;
|
||||||
&& process_alive)
|
}
|
||||||
&& is_request_finished
|
// let handle_algo_c = handle_algo.lock().unwrap();
|
||||||
{
|
let is_algo_started_once = handle_algo.lock().unwrap().is_some();
|
||||||
// do not wait for the request to finish so that they are retrieved at exactly one minute interval and not block the thread.
|
let is_algo_finished = handle_algo
|
||||||
// Private API will also use this instant if XvB is Alive.
|
.lock()
|
||||||
// first_loop is false here but could be changed to true under some conditions.
|
.unwrap()
|
||||||
// will send a stop signal if public stats failed or update data with new one.
|
.as_ref()
|
||||||
*handle_request.lock().unwrap() = Some(spawn(
|
.is_some_and(|algo| algo.is_finished());
|
||||||
enc!((client, pub_api, gui_api, gui_api_p2pool, gui_api_xmrig, gui_api_xp, state_xvb, state_p2pool, state_xmrig, state_xp, process, last_algorithm, retry, handle_algo, time_donated, last_request) async move {
|
let is_request_finished = handle_request
|
||||||
// needs to wait here for public stats to get private stats.
|
.lock()
|
||||||
if last_request_expired || first_loop || should_refresh_before_next_algo {
|
.unwrap()
|
||||||
XvbPubStats::update_stats(&client, &gui_api, &pub_api, &process).await;
|
.as_ref()
|
||||||
*last_request.lock().unwrap() = Instant::now();
|
.is_some_and(|request: &JoinHandle<()>| request.is_finished())
|
||||||
}
|
|| handle_request.lock().unwrap().is_none();
|
||||||
// private stats needs valid token and address.
|
// Send an HTTP API request only if one minute is passed since the last request or if first loop or if algorithm need to retry or if request is finished and algo is finished or almost finished (only public and private stats). We make sure public and private stats are refreshed before doing another run of the algo.
|
||||||
// other stats needs everything to be alive, so just require alive here for now.
|
// We make sure algo or request are not rerun when they are not over.
|
||||||
// maybe later differentiate to add a way to get private stats without running the algo ?
|
// in the case of quick refresh before new run of algo, make sure it doesn't happen multiple times.
|
||||||
if process.lock().unwrap().state == ProcessState::Alive {
|
let last_request_expired =
|
||||||
// get current share to know if we are in a round and this is a required data for algo.
|
last_request.lock().unwrap().elapsed() >= Duration::from_secs(60);
|
||||||
let share = gui_api_p2pool.lock().unwrap().sidechain_shares;
|
let should_refresh_before_next_algo = is_algo_started_once
|
||||||
debug!("XvB | Number of current shares: {}", share);
|
&& last_algorithm.lock().unwrap().elapsed()
|
||||||
// private stats can be requested every minute or first loop or if the have almost finished.
|
>= Duration::from_secs((XVB_TIME_ALGO as f32 * 0.95) as u64)
|
||||||
if last_request_expired || first_loop || should_refresh_before_next_algo {
|
&& last_request.lock().unwrap().elapsed() >= Duration::from_secs(25);
|
||||||
debug!("XvB Watchdog | Attempting HTTP private API request...");
|
let process_alive = process.lock().unwrap().state == ProcessState::Alive;
|
||||||
// reload private stats, it send a signal if error that will be captured on the upper thread.
|
if ((last_request_expired || first_loop)
|
||||||
XvbPrivStats::update_stats(
|
|| (*retry.lock().unwrap()
|
||||||
&client, &state_p2pool.address, &state_xvb.token, &pub_api, &gui_api, &process,
|
|| is_algo_finished
|
||||||
)
|
|| should_refresh_before_next_algo)
|
||||||
.await;
|
&& process_alive)
|
||||||
*last_request.lock().unwrap() = Instant::now();
|
&& is_request_finished
|
||||||
|
{
|
||||||
// verify in which round type we are
|
// do not wait for the request to finish so that they are retrieved at exactly one minute interval and not block the thread.
|
||||||
let round = round_type(share, &pub_api);
|
// Private API will also use this instant if XvB is Alive.
|
||||||
// refresh the round we participate in.
|
// first_loop is false here but could be changed to true under some conditions.
|
||||||
debug!("XvB | Round type: {:#?}", round);
|
// will send a stop signal if public stats failed or update data with new one.
|
||||||
pub_api.lock().unwrap().stats_priv.round_participate = round;
|
*handle_request.lock().unwrap() = Some(spawn(
|
||||||
// verify if we are the winner of the current round
|
enc!((client, pub_api, gui_api, gui_api_p2pool, gui_api_xmrig, gui_api_xp, state_xvb, state_p2pool, state_xmrig, state_xp, process, last_algorithm, retry, handle_algo, time_donated, last_request) async move {
|
||||||
if pub_api.lock().unwrap().stats_pub.winner
|
// needs to wait here for public stats to get private stats.
|
||||||
== Helper::head_tail_of_monero_address(&state_p2pool.address).as_str()
|
if last_request_expired || first_loop || should_refresh_before_next_algo {
|
||||||
{
|
XvbPubStats::update_stats(&client, &gui_api, &pub_api, &process).await;
|
||||||
pub_api.lock().unwrap().stats_priv.win_current = true
|
*last_request.lock().unwrap() = Instant::now();
|
||||||
}
|
}
|
||||||
}
|
// private stats needs valid token and address.
|
||||||
let hashrate = current_controllable_hr(xp_alive, &gui_api_xp, &gui_api_xmrig);
|
// other stats needs everything to be alive, so just require alive here for now.
|
||||||
let difficulty_data_is_ready = gui_api_p2pool.lock().unwrap().p2pool_difficulty_u64 > 100_000;
|
// maybe later differentiate to add a way to get private stats without running the algo ?
|
||||||
if (first_loop || *retry.lock().unwrap()|| is_algo_finished) && hashrate > 0.0 && process.lock().unwrap().state == ProcessState::Alive && difficulty_data_is_ready
|
if process.lock().unwrap().state == ProcessState::Alive {
|
||||||
{
|
// get current share to know if we are in a round and this is a required data for algo.
|
||||||
// if algo was started, it must not retry next loop.
|
let share = gui_api_p2pool.lock().unwrap().sidechain_shares;
|
||||||
*retry.lock().unwrap() = false;
|
debug!("XvB | Number of current shares: {}", share);
|
||||||
// reset instant because algo will start.
|
// private stats can be requested every minute or first loop or if the have almost finished.
|
||||||
*last_algorithm.lock().unwrap() = Instant::now();
|
if last_request_expired || first_loop || should_refresh_before_next_algo {
|
||||||
*handle_algo.lock().unwrap() = Some(spawn(enc!((client, gui_api, gui_api_xmrig, gui_api_xp, state_xmrig, state_xp, time_donated, state_xvb) async move {
|
debug!("XvB Watchdog | Attempting HTTP private API request...");
|
||||||
let token_xmrig = if xp_alive {
|
// reload private stats, it send a signal if error that will be captured on the upper thread.
|
||||||
&state_xp.token
|
XvbPrivStats::update_stats(
|
||||||
} else {
|
&client, &state_p2pool.address, &state_xvb.token, &pub_api, &gui_api, &process,
|
||||||
&state_xmrig.token
|
)
|
||||||
};
|
.await;
|
||||||
let rig = if xp_alive {
|
*last_request.lock().unwrap() = Instant::now();
|
||||||
""
|
|
||||||
} else {
|
|
||||||
&state_xmrig.rig
|
|
||||||
};
|
|
||||||
algorithm(
|
|
||||||
&client,
|
|
||||||
&pub_api,
|
|
||||||
&gui_api,
|
|
||||||
&gui_api_xmrig,
|
|
||||||
&gui_api_xp,
|
|
||||||
&gui_api_p2pool,
|
|
||||||
token_xmrig,
|
|
||||||
&state_p2pool,
|
|
||||||
share,
|
|
||||||
&time_donated,
|
|
||||||
rig,
|
|
||||||
xp_alive,
|
|
||||||
state_xvb.p2pool_buffer
|
|
||||||
).await;
|
|
||||||
})));
|
|
||||||
} else {
|
|
||||||
// if xmrig is still at 0 HR but is alive and algorithm is skipped, recheck first 10s of xmrig inside algorithm next time (in one minute). Don't check if algo failed to start because state was not alive after getting private stats.
|
|
||||||
|
|
||||||
if (hashrate == 0.0 || !difficulty_data_is_ready) && process.lock().unwrap().state == ProcessState::Alive {
|
// verify in which round type we are
|
||||||
*retry.lock().unwrap() = true
|
let round = round_type(share, &pub_api);
|
||||||
|
// refresh the round we participate in.
|
||||||
|
debug!("XvB | Round type: {:#?}", round);
|
||||||
|
pub_api.lock().unwrap().stats_priv.round_participate = round;
|
||||||
|
// verify if we are the winner of the current round
|
||||||
|
if pub_api.lock().unwrap().stats_pub.winner
|
||||||
|
== Helper::head_tail_of_monero_address(&state_p2pool.address).as_str()
|
||||||
|
{
|
||||||
|
pub_api.lock().unwrap().stats_priv.win_current = true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
let hashrate = current_controllable_hr(xp_alive, &gui_api_xp, &gui_api_xmrig);
|
||||||
|
let difficulty_data_is_ready = gui_api_p2pool.lock().unwrap().p2pool_difficulty_u64 > 100_000;
|
||||||
|
if (first_loop || *retry.lock().unwrap()|| is_algo_finished) && hashrate > 0.0 && process.lock().unwrap().state == ProcessState::Alive && difficulty_data_is_ready
|
||||||
|
{
|
||||||
|
// if algo was started, it must not retry next loop.
|
||||||
|
*retry.lock().unwrap() = false;
|
||||||
|
// reset instant because algo will start.
|
||||||
|
*last_algorithm.lock().unwrap() = Instant::now();
|
||||||
|
*handle_algo.lock().unwrap() = Some(spawn(enc!((client, gui_api, gui_api_xmrig, gui_api_xp, state_xmrig, state_xp, time_donated, state_xvb) async move {
|
||||||
|
let token_xmrig = if xp_alive {
|
||||||
|
&state_xp.token
|
||||||
|
} else {
|
||||||
|
&state_xmrig.token
|
||||||
|
};
|
||||||
|
let rig = if xp_alive {
|
||||||
|
""
|
||||||
|
} else {
|
||||||
|
&state_xmrig.rig
|
||||||
|
};
|
||||||
|
algorithm(
|
||||||
|
&client,
|
||||||
|
&pub_api,
|
||||||
|
&gui_api,
|
||||||
|
&gui_api_xmrig,
|
||||||
|
&gui_api_xp,
|
||||||
|
&gui_api_p2pool,
|
||||||
|
token_xmrig,
|
||||||
|
&state_p2pool,
|
||||||
|
share,
|
||||||
|
&time_donated,
|
||||||
|
rig,
|
||||||
|
xp_alive,
|
||||||
|
state_xvb.p2pool_buffer
|
||||||
|
).await;
|
||||||
|
})));
|
||||||
|
} else {
|
||||||
|
// if xmrig is still at 0 HR but is alive and algorithm is skipped, recheck first 10s of xmrig inside algorithm next time (in one minute). Don't check if algo failed to start because state was not alive after getting private stats.
|
||||||
|
|
||||||
}
|
if (hashrate == 0.0 || !difficulty_data_is_ready) && process.lock().unwrap().state == ProcessState::Alive {
|
||||||
}),
|
*retry.lock().unwrap() = true
|
||||||
));
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}),
|
||||||
|
));
|
||||||
|
}
|
||||||
|
// if retry is false, next time the message about waiting for xmrig HR can be shown.
|
||||||
|
if !*retry.lock().unwrap() {
|
||||||
|
msg_retry_done = false;
|
||||||
|
}
|
||||||
|
// inform user that algorithm has not yet started because it is waiting for xmrig HR.
|
||||||
|
// show this message only once before the start of algo
|
||||||
|
if *retry.lock().unwrap() && !msg_retry_done {
|
||||||
|
let msg = if xp_alive {
|
||||||
|
"Algorithm is waiting for 1 minute average HR of XMRig-Proxy or p2pool data"
|
||||||
|
} else {
|
||||||
|
"Algorithm is waiting for 10 seconds average HR of XMRig or p2pool data"
|
||||||
|
};
|
||||||
|
output_console(&mut gui_api.lock().unwrap().output, msg, ProcessName::Xvb);
|
||||||
|
msg_retry_done = true;
|
||||||
|
}
|
||||||
|
// update indicator (time before switch and mining location) in private stats
|
||||||
|
// if algo not running, second message.
|
||||||
|
// will update countdown every second.
|
||||||
|
// verify current node which is set by algo or circonstances (failed node).
|
||||||
|
// verify given time set by algo and start time of current algo.
|
||||||
|
// will run only if XvB is alive.
|
||||||
|
// let algo time to start, so no countdown is shown.
|
||||||
|
update_indicator_algo(
|
||||||
|
is_algo_started_once,
|
||||||
|
is_algo_finished,
|
||||||
|
process,
|
||||||
|
pub_api,
|
||||||
|
*time_donated.lock().unwrap(),
|
||||||
|
&last_algorithm,
|
||||||
|
);
|
||||||
|
// first_loop is done, but maybe retry will allow the algorithm to retry again.
|
||||||
|
if first_loop {
|
||||||
|
first_loop = false;
|
||||||
|
}
|
||||||
|
// Sleep (only if 900ms hasn't passed)
|
||||||
}
|
}
|
||||||
// if retry is false, next time the message about waiting for xmrig HR can be shown.
|
|
||||||
if !*retry.lock().unwrap() {
|
|
||||||
msg_retry_done = false;
|
|
||||||
}
|
|
||||||
// inform user that algorithm has not yet started because it is waiting for xmrig HR.
|
|
||||||
// show this message only once before the start of algo
|
|
||||||
if *retry.lock().unwrap() && !msg_retry_done {
|
|
||||||
let msg = if xp_alive {
|
|
||||||
"Algorithm is waiting for 1 minute average HR of XMRig-Proxy or p2pool data"
|
|
||||||
} else {
|
|
||||||
"Algorithm is waiting for 10 seconds average HR of XMRig or p2pool data"
|
|
||||||
};
|
|
||||||
output_console(&mut gui_api.lock().unwrap().output, msg, ProcessName::Xvb);
|
|
||||||
msg_retry_done = true;
|
|
||||||
}
|
|
||||||
// update indicator (time before switch and mining location) in private stats
|
|
||||||
// if algo not running, second message.
|
|
||||||
// will update countdown every second.
|
|
||||||
// verify current node which is set by algo or circonstances (failed node).
|
|
||||||
// verify given time set by algo and start time of current algo.
|
|
||||||
// will run only if XvB is alive.
|
|
||||||
// let algo time to start, so no countdown is shown.
|
|
||||||
update_indicator_algo(
|
|
||||||
is_algo_started_once,
|
|
||||||
is_algo_finished,
|
|
||||||
process,
|
|
||||||
pub_api,
|
|
||||||
*time_donated.lock().unwrap(),
|
|
||||||
&last_algorithm,
|
|
||||||
);
|
|
||||||
// first_loop is done, but maybe retry will allow the algorithm to retry again.
|
|
||||||
if first_loop {
|
|
||||||
first_loop = false;
|
|
||||||
}
|
|
||||||
// Sleep (only if 900ms hasn't passed)
|
|
||||||
sleep_end_loop(start_loop, ProcessName::Xvb).await;
|
sleep_end_loop(start_loop, ProcessName::Xvb).await;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue