litter codebase with [debug!()]

The entire codebase is now littered with [debug!()] messages.
Thankfully [log] has 0 cost if you aren't using them, so regular
users won't have a runtime penalty unless they specify RUST_LOG=debug.
This commit is contained in:
hinto-janaiyo 2022-12-12 14:34:17 -05:00
parent bf4e39c3a5
commit 798966d447
No known key found for this signature in database
GPG key ID: B1C5A64B80691E45
8 changed files with 203 additions and 62 deletions

View file

@ -1,6 +1,6 @@
# WORK IN PROGRESS - ETA: December 25th, 2022
![banner.png](https://github.com/hinto-janaiyo/gupax/blob/main/images/banner.png)
Gupax (*guh-picks*) is a (Windows|macOS|Linux) GUI for mining [**Monero**](https://github.com/monero-project/monero) on [**P2Pool**](https://github.com/SChernykh/p2pool), using [**XMRig**](https://github.com/xmrig/xmrig).
Gupax is a (Windows|macOS|Linux) GUI for mining [**Monero**](https://github.com/monero-project/monero) on [**P2Pool**](https://github.com/SChernykh/p2pool), using [**XMRig**](https://github.com/xmrig/xmrig).
**If you just want to see a short 1-minute video on how to download and run Gupax: [click here.](#Video)**

View file

@ -83,6 +83,7 @@ pub enum Ratio {
impl Gupax {
pub fn show(&mut self, og: &Arc<Mutex<State>>, state_path: &Path, update: &Arc<Mutex<Update>>, file_window: &Arc<Mutex<FileWindow>>, error_state: &mut ErrorState, restart: &Arc<Mutex<Restart>>, width: f32, height: f32, frame: &mut eframe::Frame, ctx: &egui::Context, ui: &mut egui::Ui) {
// Update button + Progress bar
debug!("Gupax Tab | Rendering [Update] button + progress bar");
ui.group(|ui| {
// These are in unnecessary [ui.vertical()]'s
// because I need to use [ui.set_enabled]s, but I can't
@ -112,6 +113,7 @@ impl Gupax {
});
});
debug!("Gupax Tab | Rendering bool buttons");
ui.horizontal(|ui| {
ui.group(|ui| {
let width = (width - SPACE*12.0)/6.0;
@ -133,6 +135,7 @@ impl Gupax {
if self.simple { return }
debug!("Gupax Tab | Rendering P2Pool/XMRig path selection");
// P2Pool/XMRig binary path selection
ui.add_space(SPACE);
ui.style_mut().override_text_style = Some(Monospace);
@ -182,6 +185,7 @@ impl Gupax {
drop(guard);
// Gupax App resolution sliders
debug!("Gupax Tab | Rendering resolution sliders");
ui.vertical(|ui| {
let width = width/10.0;
ui.spacing_mut().icon_width = width / 25.0;
@ -229,6 +233,7 @@ impl Gupax {
}
})});
// Saved [Tab]
debug!("Gupax Tab | Rendering [Tab] selector");
ui.group(|ui| {
let height = ui.available_height()/1.85;
let width = (width/5.0)-(SPACE*1.93);

View file

@ -251,6 +251,7 @@ impl Helper {
// The actual [String] holds 56_000_000, but this allows for some leeway so it doesn't allocate more memory.
// This will also append a message showing it was reset.
fn check_reset_output_full(output_full: &Arc<Mutex<String>>, name: ProcessName) {
debug!("{} Watchdog | Resetting [output_full]...", name);
let mut output_full = output_full.lock().unwrap();
if output_full.len() > PROCESS_OUTPUT_LEEWAY {
info!("{} | Output is nearing {} bytes, resetting!", MAX_PROCESS_OUTPUT_BYTES, name);
@ -258,10 +259,12 @@ impl Helper {
output_full.clear();
output_full.push_str(&text);
}
debug!("{} Watchdog | Resetting [output_full] ... OK", name);
}
// For the GUI thread
fn check_reset_gui_p2pool_output(gui_api: &Arc<Mutex<PubP2poolApi>>) {
debug!("P2Pool Watchdog | Resetting GUI output...");
let mut gui_api = gui_api.lock().unwrap();
if gui_api.output.len() > GUI_OUTPUT_LEEWAY {
info!("P2Pool | Output is nearing {} bytes, resetting!", MAX_GUI_OUTPUT_BYTES);
@ -269,9 +272,11 @@ impl Helper {
gui_api.output.clear();
gui_api.output.push_str(&text);
}
debug!("P2Pool Watchdog | Resetting GUI output ... OK");
}
fn check_reset_gui_xmrig_output(gui_api: &Arc<Mutex<PubXmrigApi>>) {
debug!("XMRig Watchdog | Resetting GUI output...");
let mut gui_api = gui_api.lock().unwrap();
if gui_api.output.len() > GUI_OUTPUT_LEEWAY {
info!("XMRig | Output is nearing {} bytes, resetting!", MAX_GUI_OUTPUT_BYTES);
@ -279,6 +284,7 @@ impl Helper {
gui_api.output.clear();
gui_api.output.push_str(&text);
}
debug!("XMRig Watchdog | Resetting GUI output ... OK");
}
//---------------------------------------------------------------------------------------------------- P2Pool specific
@ -306,6 +312,7 @@ impl Helper {
thread::sleep(SECOND);
}
// Ok, process is not alive, start the new one!
info!("P2Pool | Old process seems dead, starting new one!");
Self::start_p2pool(&helper, &state, &path);
});
info!("P2Pool | Restart ... OK");
@ -418,6 +425,7 @@ impl Helper {
// The P2Pool watchdog. Spawns 1 OS thread for reading a PTY (STDOUT+STDERR), and combines the [Child] with a PTY so STDIN actually works.
fn spawn_p2pool_watchdog(process: Arc<Mutex<Process>>, gui_api: Arc<Mutex<PubP2poolApi>>, pub_api: Arc<Mutex<PubP2poolApi>>, priv_api: Arc<Mutex<PrivP2poolApi>>, args: Vec<String>, mut path: std::path::PathBuf) {
// 1a. Create PTY
debug!("P2Pool | Creating PTY...");
let pty = portable_pty::native_pty_system();
let pair = pty.openpty(portable_pty::PtySize {
rows: 100,
@ -426,13 +434,16 @@ impl Helper {
pixel_height: 0,
}).unwrap();
// 1b. Create command
debug!("P2Pool | Creating command...");
let mut cmd = portable_pty::CommandBuilder::new(path.as_path());
cmd.args(args);
cmd.cwd(path.as_path().parent().unwrap());
// 1c. Create child
debug!("P2Pool | Creating child...");
let child_pty = Arc::new(Mutex::new(pair.slave.spawn_command(cmd).unwrap()));
// 2. Set process state
debug!("P2Pool | Setting process state...");
let mut lock = process.lock().unwrap();
lock.state = ProcessState::Alive;
lock.signal = ProcessSignal::None;
@ -443,6 +454,7 @@ impl Helper {
drop(lock);
// 3. Spawn PTY read thread
debug!("P2Pool | Spawning PTY read thread...");
let output_full = Arc::clone(&process.lock().unwrap().output_full);
let output_buf = Arc::clone(&process.lock().unwrap().output_buf);
thread::spawn(move || {
@ -453,6 +465,8 @@ impl Helper {
path.pop();
path.push(P2POOL_API_PATH);
debug!("P2Pool | Cleaning old API files...");
// Attempt to remove stale API file
match std::fs::remove_file(&path) {
Ok(_) => info!("P2Pool | Attempting to remove stale API file ... OK"),
@ -475,9 +489,27 @@ impl Helper {
loop {
// Set timer
let now = Instant::now();
debug!("P2Pool Watchdog | ----------- Start of loop -----------");
// Check if the process is secretly died without us knowing :)
if let Ok(Some(code)) = child_pty.lock().unwrap().try_wait() {
debug!("P2Pool Watchdog | Process secretly died! Getting exit status");
let exit_status = match code.success() {
true => { process.lock().unwrap().state = ProcessState::Dead; "Successful" },
false => { process.lock().unwrap().state = ProcessState::Failed; "Failed" },
};
let uptime = HumanTime::into_human(start.elapsed());
info!("P2Pool Watchdog | Stopped ... Uptime was: [{}], Exit status: [{}]", uptime, exit_status);
// This is written directly into the GUI, because sometimes the 900ms event loop can't catch it.
writeln!(gui_api.lock().unwrap().output, "{}\nP2Pool stopped | Uptime: [{}] | Exit status: [{}]\n{}\n\n\n\n", HORI_CONSOLE, uptime, exit_status, HORI_CONSOLE);
process.lock().unwrap().signal = ProcessSignal::None;
debug!("P2Pool Watchdog | Secret dead process reap OK, breaking");
break
}
// Check SIGNAL
if process.lock().unwrap().signal == ProcessSignal::Stop {
debug!("P2Pool Watchdog | Stop SIGNAL caught");
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 exit_status = match child_pty.lock().unwrap().wait() {
@ -491,13 +523,15 @@ impl Helper {
_ => { process.lock().unwrap().state = ProcessState::Failed; "Unknown Error" },
};
let uptime = HumanTime::into_human(start.elapsed());
info!("P2Pool | Stopped ... Uptime was: [{}], Exit status: [{}]", uptime, exit_status);
info!("P2Pool Watchdog | Stopped ... Uptime was: [{}], Exit status: [{}]", uptime, exit_status);
// This is written directly into the GUI API, because sometimes the 900ms event loop can't catch it.
writeln!(gui_api.lock().unwrap().output, "{}\nP2Pool stopped | Uptime: [{}] | Exit status: [{}]\n{}\n\n\n\n", HORI_CONSOLE, uptime, exit_status, HORI_CONSOLE);
process.lock().unwrap().signal = ProcessSignal::None;
debug!("P2Pool Watchdog | Stop SIGNAL done, breaking");
break
// Check RESTART
} else if process.lock().unwrap().signal == ProcessSignal::Restart {
debug!("P2Pool Watchdog | Restart SIGNAL caught");
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 exit_status = match child_pty.lock().unwrap().wait() {
@ -505,22 +539,11 @@ impl Helper {
_ => "Unknown Error",
};
let uptime = HumanTime::into_human(start.elapsed());
info!("P2Pool | Stopped ... Uptime was: [{}], Exit status: [{}]", uptime, exit_status);
info!("P2Pool Watchdog | Stopped ... Uptime was: [{}], Exit status: [{}]", uptime, exit_status);
// This is written directly into the GUI API, because sometimes the 900ms event loop can't catch it.
writeln!(gui_api.lock().unwrap().output, "{}\nP2Pool stopped | Uptime: [{}] | Exit status: [{}]\n{}\n\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 exit_status = match code.success() {
true => { process.lock().unwrap().state = ProcessState::Dead; "Successful" },
false => { process.lock().unwrap().state = ProcessState::Failed; "Failed" },
};
let uptime = HumanTime::into_human(start.elapsed());
info!("P2Pool | Stopped ... Uptime was: [{}], Exit status: [{}]", uptime, exit_status);
// This is written directly into the GUI, because sometimes the 900ms event loop can't catch it.
writeln!(gui_api.lock().unwrap().output, "{}\nP2Pool stopped | Uptime: [{}] | Exit status: [{}]\n{}\n\n\n\n", HORI_CONSOLE, uptime, exit_status, HORI_CONSOLE);
process.lock().unwrap().signal = ProcessSignal::None;
debug!("P2Pool Watchdog | Restart SIGNAL done, breaking");
break
}
@ -529,15 +552,18 @@ impl Helper {
if !lock.input.is_empty() {
let input = std::mem::take(&mut lock.input);
for line in input {
debug!("P2Pool Watchdog | User input not empty, writing to STDIN: [{}]", line);
writeln!(lock.stdin.as_mut().unwrap(), "{}", line);
}
}
drop(lock);
// Always update from output
debug!("P2Pool Watchdog | Starting [update_from_output()]");
PubP2poolApi::update_from_output(&pub_api, &output_full, &output_buf, start.elapsed(), &regex);
// Read API file into string
debug!("P2Pool Watchdog | Attempting API file read");
if let Ok(string) = PrivP2poolApi::read_p2pool_api(&path) {
// Deserialize
if let Ok(s) = PrivP2poolApi::str_to_priv_p2pool_api(&string) {
@ -547,17 +573,24 @@ impl Helper {
}
// Check if logs need resetting
debug!("P2Pool Watchdog | Attempting log reset check");
Self::check_reset_output_full(&output_full, ProcessName::P2pool);
Self::check_reset_gui_p2pool_output(&gui_api);
// Sleep (only if 900ms hasn't passed)
let elapsed = now.elapsed().as_millis();
// Since logic goes off if less than 1000, casting should be safe
if elapsed < 900 { std::thread::sleep(std::time::Duration::from_millis((900-elapsed) as u64)); }
if elapsed < 900 {
let sleep = (900-elapsed) as u64;
debug!("P2Pool Watchdog | END OF LOOP - Sleeping for [{}]ms...", sleep);
std::thread::sleep(std::time::Duration::from_millis(sleep));
} else {
debug!("P2Pool Watchdog | END OF LOOP - Not sleeping!");
}
}
// 5. If loop broke, we must be done here.
info!("P2Pool | Watchdog thread exiting... Goodbye!");
info!("P2Pool Watchdog | Watchdog thread exiting... Goodbye!");
}
//---------------------------------------------------------------------------------------------------- XMRig specific, most functions are very similar to P2Pool's
@ -620,6 +653,7 @@ impl Helper {
thread::sleep(SECOND);
}
// Ok, process is not alive, start the new one!
info!("XMRig | Old process seems dead, starting new one!");
Self::start_xmrig(&helper, &state, &path, sudo);
});
info!("XMRig | Restart ... OK");
@ -745,6 +779,7 @@ impl Helper {
#[tokio::main]
async fn spawn_xmrig_watchdog(process: Arc<Mutex<Process>>, gui_api: Arc<Mutex<PubXmrigApi>>, pub_api: Arc<Mutex<PubXmrigApi>>, priv_api: Arc<Mutex<PrivXmrigApi>>, args: Vec<String>, mut path: std::path::PathBuf, sudo: Arc<Mutex<SudoState>>, api_ip_port: String) {
// 1a. Create PTY
debug!("XMRig | Creating PTY...");
let pty = portable_pty::native_pty_system();
let mut pair = pty.openpty(portable_pty::PtySize {
rows: 100,
@ -753,15 +788,18 @@ impl Helper {
pixel_height: 0,
}).unwrap();
// 1b. Create command
debug!("XMRig | Creating command...");
#[cfg(target_os = "windows")]
let cmd = Self::create_xmrig_cmd_windows(args, path);
#[cfg(target_family = "unix")]
let cmd = Self::create_xmrig_cmd_unix(args, path);
// 1c. Create child
debug!("XMRig | Creating child...");
let child_pty = Arc::new(Mutex::new(pair.slave.spawn_command(cmd).unwrap()));
// 2. Input [sudo] pass, wipe, then drop.
if cfg!(unix) {
debug!("XMRig | Inputting [sudo] and wiping...");
// 1d. Sleep to wait for [sudo]'s non-echo prompt (on Unix).
// this prevents users pass from showing up in the STDOUT.
std::thread::sleep(std::time::Duration::from_secs(3));
@ -770,6 +808,7 @@ impl Helper {
}
// 3. Set process state
debug!("XMRig | Setting process state...");
let mut lock = process.lock().unwrap();
lock.state = ProcessState::Alive;
lock.signal = ProcessSignal::None;
@ -780,6 +819,7 @@ impl Helper {
drop(lock);
// 4. Spawn PTY read thread
debug!("XMRig | Spawning PTY read thread...");
let output_full = Arc::clone(&process.lock().unwrap().output_full);
let output_buf = Arc::clone(&process.lock().unwrap().output_buf);
thread::spawn(move || {
@ -796,9 +836,11 @@ impl Helper {
loop {
// Set timer
let now = Instant::now();
debug!("XMRig Watchdog | ----------- Start of loop -----------");
// Check if the process secretly died without us knowing :)
if let Ok(Some(code)) = child_pty.lock().unwrap().try_wait() {
debug!("XMRig Watchdog | Process secretly died on us! Getting exit status...");
let exit_status = match code.success() {
true => { process.lock().unwrap().state = ProcessState::Dead; "Successful" },
false => { process.lock().unwrap().state = ProcessState::Failed; "Failed" },
@ -807,12 +849,14 @@ impl Helper {
info!("XMRig | Stopped ... Uptime was: [{}], Exit status: [{}]", uptime, exit_status);
writeln!(gui_api.lock().unwrap().output, "{}\nXMRig stopped | Uptime: [{}] | Exit status: [{}]\n{}\n\n\n\n", HORI_CONSOLE, uptime, exit_status, HORI_CONSOLE);
process.lock().unwrap().signal = ProcessSignal::None;
debug!("XMRig Watchdog | Secret dead process reap OK, breaking");
break
}
// Stop on [Stop/Restart] SIGNAL
let signal = process.lock().unwrap().signal;
if signal == ProcessSignal::Stop || signal == ProcessSignal::Restart {
debug!("XMRig Watchdog | Stop/Restart SIGNAL caught");
// macOS requires [sudo] again to kill [XMRig]
if cfg!(target_os = "macos") {
// If we're at this point, that means the user has
@ -851,6 +895,7 @@ impl Helper {
ProcessSignal::Restart => process.state = ProcessState::Waiting,
_ => (),
}
debug!("XMRig Watchdog | Stop/Restart SIGNAL done, breaking");
break
}
@ -859,33 +904,44 @@ impl Helper {
if !lock.input.is_empty() {
let input = std::mem::take(&mut lock.input);
for line in input {
debug!("XMRig Watchdog | User input not empty, writing to STDIN: [{}]", line);
writeln!(lock.stdin.as_mut().unwrap(), "{}", line);
}
}
drop(lock);
// Always update from output
debug!("XMRig Watchdog | Starting [update_from_output()]");
PubXmrigApi::update_from_output(&pub_api, &output_buf, start.elapsed());
// Send an HTTP API request
debug!("XMRig Watchdog | Attempting HTTP API request...");
if let Ok(priv_api) = PrivXmrigApi::request_xmrig_api(client.clone(), &api_ip_port).await {
debug!("XMRig Watchdog | HTTP API request OK, attempting [update_from_priv()]");
PubXmrigApi::update_from_priv(&pub_api, priv_api);
} else {
warn!("XMRig | Could not send HTTP API request to: {}", api_ip_port);
warn!("XMRig Watchdog | Could not send HTTP API request to: {}", api_ip_port);
}
// Check if logs need resetting
debug!("XMRig Watchdog | Attempting log reset check");
Self::check_reset_output_full(&output_full, ProcessName::Xmrig);
Self::check_reset_gui_xmrig_output(&gui_api);
// Sleep (only if 900ms hasn't passed)
let elapsed = now.elapsed().as_millis();
// Since logic goes off if less than 1000, casting should be safe
if elapsed < 900 { std::thread::sleep(std::time::Duration::from_millis((900-elapsed) as u64)); }
if elapsed < 900 {
let sleep = (900-elapsed) as u64;
debug!("XMRig Watchdog | END OF LOOP - Sleeping for [{}]ms...", sleep);
std::thread::sleep(std::time::Duration::from_millis(sleep));
} else {
debug!("XMRig Watchdog | END OF LOOP - Not sleeping!");
}
}
// 5. If loop broke, we must be done here.
info!("XMRig | Watchdog thread exiting... Goodbye!");
info!("XMRig Watchdog | Watchdog thread exiting... Goodbye!");
}
//---------------------------------------------------------------------------------------------------- The "helper"
@ -933,38 +989,56 @@ impl Helper {
loop {
// 1. Loop init timestamp
let start = Instant::now();
debug!("Helper | ----------- Start of loop -----------");
//
// Ignore the invasive [debug!()] messages on the right side of the code.
// The reason why they are there are so that it's extremely easy to track
// down the culprit of an [Arc<Mutex>] deadlock. I know, they're ugly.
//
// 2. Lock... EVERYTHING!
let mut lock = helper.lock().unwrap();
let mut lock = helper.lock().unwrap(); debug!("Helper | Locking (1/8) ... [helper]");
// Calculate Gupax's uptime always.
lock.uptime = HumanTime::into_human(lock.instant.elapsed());
let mut gui_api_p2pool = lock.gui_api_p2pool.lock().unwrap();
let mut gui_api_xmrig = lock.gui_api_xmrig.lock().unwrap();
let mut pub_api_p2pool = lock.pub_api_p2pool.lock().unwrap();
let mut pub_api_xmrig = lock.pub_api_xmrig.lock().unwrap();
let p2pool = lock.p2pool.lock().unwrap();
let xmrig = lock.xmrig.lock().unwrap();
let mut lock_pub_sys = pub_sys.lock().unwrap();
let mut gui_api_p2pool = lock.gui_api_p2pool.lock().unwrap(); debug!("Helper | Locking (2/8) ... [gui_api_p2pool]");
let mut gui_api_xmrig = lock.gui_api_xmrig.lock().unwrap(); debug!("Helper | Locking (3/8) ... [gui_api_xmrig]");
let mut pub_api_p2pool = lock.pub_api_p2pool.lock().unwrap(); debug!("Helper | Locking (4/8) ... [pub_api_p2pool]");
let mut pub_api_xmrig = lock.pub_api_xmrig.lock().unwrap(); debug!("Helper | Locking (5/8) ... [pub_api_xmrig]");
let p2pool = lock.p2pool.lock().unwrap(); debug!("Helper | Locking (6/8) ... [p2pool]");
let xmrig = lock.xmrig.lock().unwrap(); debug!("Helper | Locking (7/8) ... [xmrig]");
let mut lock_pub_sys = pub_sys.lock().unwrap(); debug!("Helper | Locking (8/8) ... [pub_sys]");
// If [P2Pool] is alive...
if p2pool.is_alive() { PubP2poolApi::combine_gui_pub_api(&mut gui_api_p2pool, &mut pub_api_p2pool); }
if p2pool.is_alive() {
debug!("Helper | P2Pool is alive! Running [combine_gui_pub_api()]");
PubP2poolApi::combine_gui_pub_api(&mut gui_api_p2pool, &mut pub_api_p2pool);
} else {
debug!("Helper | P2Pool is dead! Skipping...");
}
// If [XMRig] is alive...
if xmrig.is_alive() { PubXmrigApi::combine_gui_pub_api(&mut gui_api_xmrig, &mut pub_api_xmrig); }
if xmrig.is_alive() {
debug!("Helper | XMRig is alive! Running [combine_gui_pub_api()]");
PubXmrigApi::combine_gui_pub_api(&mut gui_api_xmrig, &mut pub_api_xmrig);
} else {
debug!("Helper | XMRig is dead! Skipping...");
}
// 2. Selectively refresh [sysinfo] for only what we need (better performance).
sysinfo.refresh_cpu_specifics(sysinfo_cpu);
sysinfo.refresh_processes_specifics(sysinfo_processes);
sysinfo.refresh_memory();
sysinfo.refresh_cpu_specifics(sysinfo_cpu); debug!("Helper | Sysinfo refresh (1/3) ... [cpu]");
sysinfo.refresh_processes_specifics(sysinfo_processes); debug!("Helper | Sysinfo refresh (2/3) ... [processes]");
sysinfo.refresh_memory(); debug!("Helper | Sysinfo refresh (3/3) ... [memory]");
debug!("Helper | Sysinfo OK, running [update_pub_sys_from_sysinfo()]");
Self::update_pub_sys_from_sysinfo(&sysinfo, &mut lock_pub_sys, &pid, &lock, max_threads);
// 3. Drop... (almost) EVERYTHING... IN REVERSE!
drop(lock_pub_sys);
drop(xmrig);
drop(p2pool);
drop(pub_api_xmrig);
drop(pub_api_p2pool);
drop(gui_api_xmrig);
drop(gui_api_p2pool);
drop(lock);
drop(lock_pub_sys); debug!("Helper | Unlocking (1/8) ... [pub_sys]");
drop(xmrig); debug!("Helper | Unlocking (2/8) ... [xmrig]");
drop(p2pool); debug!("Helper | Unlocking (3/8) ... [p2pool]");
drop(pub_api_xmrig); debug!("Helper | Unlocking (4/8) ... [pub_api_xmrig]");
drop(pub_api_p2pool); debug!("Helper | Unlocking (5/8) ... [pub_api_p2pool]");
drop(gui_api_xmrig); debug!("Helper | Unlocking (6/8) ... [gui_api_xmrig]");
drop(gui_api_p2pool); debug!("Helper | Unlocking (7/8) ... [gui_api_p2pool]");
drop(lock); debug!("Helper | Unlocking (8/8) ... [helper]");
// 4. Calculate if we should sleep or not.
// If we should sleep, how long?
@ -972,7 +1046,11 @@ impl Helper {
if elapsed < 1000 {
// Casting from u128 to u64 should be safe here, because [elapsed]
// is less than 1000, meaning it can fit into a u64 easy.
std::thread::sleep(std::time::Duration::from_millis((1000-elapsed) as u64));
let sleep = (1000-elapsed) as u64;
debug!("Helper | END OF LOOP - Sleeping for [{}]ms...", sleep);
std::thread::sleep(std::time::Duration::from_millis(sleep));
} else {
debug!("Helper | END OF LOOP - Not sleeping!");
}
// 5. End loop

View file

@ -166,6 +166,7 @@ impl App {
fn new(now: Instant) -> Self {
info!("Initializing App Struct...");
debug!("App Init | P2Pool & XMRig processes...");
let p2pool = Arc::new(Mutex::new(Process::new(ProcessName::P2pool, String::new(), PathBuf::new())));
let xmrig = Arc::new(Mutex::new(Process::new(ProcessName::Xmrig, String::new(), PathBuf::new())));
let p2pool_api = Arc::new(Mutex::new(PubP2poolApi::new()));
@ -173,6 +174,7 @@ impl App {
let p2pool_img = Arc::new(Mutex::new(ImgP2pool::new()));
let xmrig_img = Arc::new(Mutex::new(ImgXmrig::new()));
debug!("App Init | Sysinfo...");
// We give this to the [Helper] thread.
let mut sysinfo = sysinfo::System::new_with_specifics(
sysinfo::RefreshKind::new()
@ -183,6 +185,7 @@ impl App {
let pid = sysinfo::get_current_pid().unwrap();
let pub_sys = Arc::new(Mutex::new(Sys::new()));
debug!("App Init | The rest of the [App]...");
let mut app = Self {
tab: Tab::default(),
ping: Arc::new(Mutex::new(Ping::new())),
@ -232,6 +235,7 @@ impl App {
regex: Regexes::new(),
};
//---------------------------------------------------------------------------------------------------- App init data that *could* panic
debug!("App Init | Getting EXE path...");
let mut panic = String::new();
// Get exe path
app.exe = match get_exe() {
@ -249,6 +253,7 @@ impl App {
Err(e) => { panic = format!("get_os_data_path(): {}", e); app.error_state.set(panic.clone(), ErrorFerris::Panic, ErrorButtons::Quit); PathBuf::new() },
};
debug!("App Init | Setting TOML path...");
// Set [*.toml] path
app.state_path = app.os_data_path.clone();
app.state_path.push("state.toml");
@ -260,9 +265,11 @@ impl App {
// Apply arg state
// It's not safe to [--reset] if any of the previous variables
// are unset (null path), so make sure we just abort if the [panic] String contains something.
debug!("App Init | Applying argument state...");
let mut app = parse_args(app, panic);
// Read disk state
debug!("App Init | Reading disk state...");
use TomlError::*;
app.state = match State::get(&app.state_path) {
Ok(toml) => toml,
@ -281,6 +288,7 @@ impl App {
};
app.og = Arc::new(Mutex::new(app.state.clone()));
// Read node list
debug!("App Init | Reading node list...");
app.og_node_vec = match Node::get(&app.node_path) {
Ok(toml) => toml,
Err(err) => {
@ -297,6 +305,7 @@ impl App {
},
};
// Read pool list
debug!("App Init | Reading pool list...");
app.og_pool_vec = match Pool::get(&app.pool_path) {
Ok(toml) => toml,
Err(err) => {
@ -317,6 +326,7 @@ impl App {
//----------------------------------------------------------------------------------------------------
let mut og = app.og.lock().unwrap(); // Lock [og]
// Handle max threads
debug!("App Init | Handling max thread overflow...");
og.xmrig.max_threads = app.max_threads;
let current = og.xmrig.current_threads;
let max = og.xmrig.max_threads;
@ -324,6 +334,7 @@ impl App {
og.xmrig.current_threads = max;
}
// Handle [node_vec] overflow
debug!("App Init | Handling [node_vec] overflow");
if og.p2pool.selected_index > app.og_node_vec.len() {
warn!("App | Overflowing manual node index [{} > {}], resetting to 1", og.p2pool.selected_index, app.og_node_vec.len());
let (name, node) = app.og_node_vec[0].clone();
@ -339,6 +350,7 @@ impl App {
app.state.p2pool.selected_zmq = node.zmq;
}
// Handle [pool_vec] overflow
debug!("App Init | Handling [pool_vec] overflow...");
if og.xmrig.selected_index > app.og_pool_vec.len() {
warn!("App | Overflowing manual pool index [{} > {}], resetting to 1", og.xmrig.selected_index, app.og_pool_vec.len());
let (name, pool) = app.og_pool_vec[0].clone();
@ -351,16 +363,24 @@ impl App {
app.state.xmrig.selected_ip = pool.ip;
app.state.xmrig.selected_port = pool.port;
}
// Apply TOML values to [Update]
debug!("App Init | Applying TOML values to [Update]...");
let p2pool_path = og.gupax.absolute_p2pool_path.clone();
let xmrig_path = og.gupax.absolute_xmrig_path.clone();
let tor = og.gupax.update_via_tor;
app.update = Arc::new(Mutex::new(Update::new(app.exe.clone(), p2pool_path, xmrig_path, tor)));
debug!("App Init | Setting state Gupax version...");
// Set state version as compiled in version
og.version.lock().unwrap().gupax = GUPAX_VERSION.to_string();
app.state.version.lock().unwrap().gupax = GUPAX_VERSION.to_string();
debug!("App Init | Setting saved [Tab]...");
// Set saved [Tab]
app.tab = app.state.gupax.tab;
drop(og); // Unlock [og]
info!("App ... OK");
@ -370,6 +390,7 @@ impl App {
info!("Helper ... OK");
// Check for privilege. Should be Admin on [Windows] and NOT root on Unix.
debug!("App Init | Checking for privilege level...");
#[cfg(target_os = "windows")]
if is_elevated::is_elevated() {
app.admin = true;
@ -835,6 +856,7 @@ impl eframe::App for App {
// *-------*
// | DEBUG |
// *-------*
debug!("App | ----------- Start of [update()] -----------");
// If [F11] was pressed, reverse [fullscreen] bool
if ctx.input_mut().consume_key(Modifiers::NONE, Key::F11) {
@ -843,10 +865,12 @@ impl eframe::App for App {
}
// Refresh AT LEAST once a second
debug!("App | Refreshing frame once per second");
ctx.request_repaint_after(SECOND);
// This sets the top level Ui dimensions.
// Used as a reference for other uis.
debug!("App | Setting width/height");
CentralPanel::default().show(ctx, |ui| {
let available_width = ui.available_width();
if self.width != available_width {
@ -863,6 +887,7 @@ impl eframe::App for App {
// while the user was readjusting the frame. It's a pretty heavy operation and looks
// buggy when calling it that many times. Looking for a [must_resize] in addtion to
// checking if the user is hovering over the app means that we only have call it once.
debug!("App | Checking if we need to resize");
if self.must_resize && ctx.is_pointer_over_area() {
self.resizing = true;
self.must_resize = false;
@ -899,6 +924,7 @@ impl eframe::App for App {
}
// If there's an error, display [ErrorState] on the whole screen until user responds
debug!("App | Checking if there is an error in [ErrorState]");
if self.error_state.error {
CentralPanel::default().show(ctx, |ui| {
ui.vertical_centered(|ui| {
@ -1058,6 +1084,7 @@ impl eframe::App for App {
// The struct fields are compared directly because [Version]
// contains Arc<Mutex>'s that cannot be compared easily.
// They don't need to be compared anyway.
debug!("App | Checking diff between [og] & [state]");
let og = self.og.lock().unwrap();
if og.gupax != self.state.gupax || og.p2pool != self.state.p2pool || og.xmrig != self.state.xmrig || self.og_node_vec != self.node_vec {
self.diff = true;
@ -1067,6 +1094,7 @@ impl eframe::App for App {
drop(og);
// Top: Tabs
debug!("App | Rendering TOP tabs");
TopBottomPanel::top("top").show(ctx, |ui| {
let width = (self.width - (SPACE*10.0))/5.0;
let height = self.height/12.0;
@ -1091,6 +1119,7 @@ impl eframe::App for App {
});
// Bottom: app info + state/process buttons
debug!("App | Rendering BOTTOM bar");
TopBottomPanel::bottom("bottom").show(ctx, |ui| {
let height = self.height/20.0;
ui.style_mut().override_text_style = Some(Name("Bottom".into()));
@ -1308,6 +1337,7 @@ impl eframe::App for App {
});
// Middle panel, contents of the [Tab]
debug!("App | Rendering CENTRAL_PANEL (tab contents)");
CentralPanel::default().show(ctx, |ui| {
// This sets the Ui dimensions after Top/Bottom are filled
self.width = ui.available_width();
@ -1315,6 +1345,7 @@ impl eframe::App for App {
ui.style_mut().override_text_style = Some(TextStyle::Body);
match self.tab {
Tab::About => {
debug!("App | Entering [About] Tab");
ui.add_space(10.0);
ui.vertical_centered(|ui| {
// Display [Gupax] banner at max, 1/4 the available length
@ -1336,15 +1367,19 @@ impl eframe::App for App {
});
}
Tab::Status => {
debug!("App | Entering [Status] Tab");
Status::show(&self.pub_sys, &self.p2pool_api, &self.xmrig_api, &self.p2pool_img, &self.xmrig_img, self.p2pool.lock().unwrap().is_alive(), self.xmrig.lock().unwrap().is_alive(), self.width, self.height, ctx, ui);
}
Tab::Gupax => {
debug!("App | Entering [Gupax] Tab");
Gupax::show(&mut self.state.gupax, &self.og, &self.state_path, &self.update, &self.file_window, &mut self.error_state, &self.restart, self.width, self.height, frame, ctx, ui);
}
Tab::P2pool => {
debug!("App | Entering [P2Pool] Tab");
P2pool::show(&mut self.state.p2pool, &mut self.node_vec, &self.og, &self.ping, &self.regex, &self.p2pool, &self.p2pool_api, &mut self.p2pool_console, self.width, self.height, ctx, ui);
}
Tab::Xmrig => {
debug!("App | Entering [XMRig] Tab");
Xmrig::show(&mut self.state.xmrig, &mut self.pool_vec, &self.regex, &self.xmrig, &self.xmrig_api, &mut self.xmrig_console, self.width, self.height, ctx, ui);
}
}

View file

@ -213,12 +213,14 @@ impl Ping {
//---------------------------------------------------------------------------------------------------- Main Ping function
// Intermediate function for spawning thread
pub fn spawn_thread(ping: &Arc<Mutex<Self>>) {
info!("Spawning ping thread...");
let ping = Arc::clone(ping);
std::thread::spawn(move|| {
info!("Spawning ping thread...");
match Self::ping(ping.clone()) {
Ok(_) => {
let now = Instant::now();
match Self::ping(&ping) {
Ok(msg) => {
info!("Ping ... OK");
ping.lock().unwrap().msg = msg;
ping.lock().unwrap().pinged = true;
ping.lock().unwrap().auto_selected = false;
},
@ -228,6 +230,7 @@ impl Ping {
ping.lock().unwrap().msg = err.to_string();
},
}
info!("Ping ... Took [{}] seconds...", now.elapsed().as_secs_f32());
ping.lock().unwrap().pinging = false;
});
}
@ -250,9 +253,10 @@ impl Ping {
// timeout = BLACK
// default = GRAY
#[tokio::main]
pub async fn ping(ping: Arc<Mutex<Self>>) -> Result<(), anyhow::Error> {
pub async fn ping(ping: &Arc<Mutex<Self>>) -> Result<String, anyhow::Error> {
// Timer
let now = Instant::now();
let ping = Arc::clone(ping);
// Start ping
ping.lock().unwrap().pinging = true;
@ -268,8 +272,8 @@ impl Ping {
// Random User Agent
let rand_user_agent = crate::Pkg::get_user_agent();
// Handle vector
let mut handles = vec![];
let node_vec = Arc::new(Mutex::new(Vec::new()));
let mut handles = Vec::with_capacity(NODE_IPS.len());
let node_vec = Arc::new(Mutex::new(Vec::with_capacity(NODE_IPS.len())));
for ip in NODE_IPS {
let client = client.clone();
@ -288,18 +292,19 @@ impl Ping {
for handle in handles {
handle.await?;
}
let node_vec = node_vec.lock().unwrap().clone();
let info = format!("Fastest node: {}ms ... {} @ {}", node_vec[0].ms, node_vec[0].id, node_vec[0].ip);
info!("Ping | {}", info);
info!("Ping | Took [{}] seconds...", now.elapsed().as_secs_f32());
let node_vec = std::mem::take(&mut *node_vec.lock().unwrap());
let fastest_info = format!("Fastest node: {}ms ... {} @ {}", node_vec[0].ms, node_vec[0].id, node_vec[0].ip);
let info = format!("Cleaning up connections");
info!("Ping | {}...", info);
let mut ping = ping.lock().unwrap();
ping.fastest = node_vec[0].id;
ping.nodes = node_vec;
ping.prog = 100.0;
ping.msg = info;
drop(ping);
Ok(())
Ok(fastest_info)
}
async fn response(client: Client<HttpConnector>, request: Request<Body>, ip: &'static str, ping: Arc<Mutex<Self>>, percent: f32, node_vec: Arc<Mutex<Vec<NodeData>>>) {

View file

@ -35,6 +35,7 @@ impl P2pool {
pub fn show(&mut self, node_vec: &mut Vec<(String, Node)>, og: &Arc<Mutex<State>>, ping: &Arc<Mutex<Ping>>, regex: &Regexes, process: &Arc<Mutex<Process>>, api: &Arc<Mutex<PubP2poolApi>>, buffer: &mut String, width: f32, height: f32, ctx: &egui::Context, ui: &mut egui::Ui) {
let text_edit = height / 25.0;
//---------------------------------------------------------------------------------------------------- [Simple] Console
debug!("P2Pool Tab | Rendering [Console]");
ui.group(|ui| {
if self.simple {
let height = height / 2.4;
@ -71,6 +72,7 @@ impl P2pool {
//---------------------------------------------------------------------------------------------------- Args
if !self.simple {
debug!("P2Pool Tab | Rendering [Arguments]");
ui.group(|ui| { ui.horizontal(|ui| {
let width = (width/10.0) - SPACE;
ui.style_mut().override_text_style = Some(Monospace);
@ -82,6 +84,7 @@ impl P2pool {
}
//---------------------------------------------------------------------------------------------------- Address
debug!("P2Pool Tab | Rendering [Address]");
ui.group(|ui| {
let width = width - SPACE;
ui.spacing_mut().text_edit_width = (width)-(SPACE*3.0);
@ -117,6 +120,7 @@ impl P2pool {
// saves me the hassle of wrapping [state: State] completely
// and [.lock().unwrap()]ing it everywhere.
// Two atomic bools = enough to represent this data
debug!("P2Pool Tab | Running [auto-select] check");
if self.auto_select {
let mut ping = ping.lock().unwrap();
// If we haven't auto_selected yet, auto-select and turn it off
@ -129,6 +133,7 @@ impl P2pool {
ui.vertical(|ui| {
ui.horizontal(|ui| {
debug!("P2Pool Tab | Rendering [Ping List]");
// [Ping List]
let id = self.node;
let ip = enum_to_ip(id);
@ -143,6 +148,7 @@ impl P2pool {
}
}
}
debug!("P2Pool Tab | Rendering [ComboBox] of Community Nodes");
let text = RichText::new(format!("{}ms | {} | {}", ms, id, ip)).color(color);
ComboBox::from_id_source("community_nodes").selected_text(RichText::text_style(text, Monospace)).show_ui(ui, |ui| {
for data in ping.lock().unwrap().nodes.iter() {
@ -156,6 +162,7 @@ impl P2pool {
ui.add_space(5.0);
debug!("P2Pool Tab | Rendering [Select fastest ... Ping] buttons");
ui.horizontal(|ui| {
let width = (width/2.0)-4.0;
// [Select fastest node]
@ -189,15 +196,11 @@ impl P2pool {
});
});
debug!("P2Pool Tab | Rendering [Auto-*] buttons");
ui.group(|ui| {
ui.horizontal(|ui| {
let width = (width/2.0)-(SPACE*1.75);
// [Auto-node] + [Auto-select]
// let mut style = (*ctx.style()).clone();
// style.spacing.icon_width_inner = width / 16.0;
// style.spacing.icon_width = width / 6.0;
// style.spacing.icon_spacing = 20.0;
// ctx.set_style(style);
ui.add_sized([width, height], Checkbox::new(&mut self.auto_select, "Auto-select")).on_hover_text(P2POOL_AUTO_SELECT);
ui.separator();
ui.add_sized([width, height], Checkbox::new(&mut self.auto_node, "Auto-node")).on_hover_text(P2POOL_AUTO_NODE);
@ -205,6 +208,7 @@ impl P2pool {
//---------------------------------------------------------------------------------------------------- Advanced
} else {
debug!("P2Pool Tab | Rendering [Node List] elements");
let mut incorrect_input = false; // This will disable [Add/Delete] on bad input
// [Monero node IP/RPC/ZMQ]
ui.horizontal(|ui| {
@ -302,6 +306,7 @@ impl P2pool {
ui.spacing_mut().slider_width = width - 8.0;
ui.spacing_mut().icon_width = width / 25.0;
// [Ping List]
debug!("P2Pool Tab | Rendering [Node List]");
let text = RichText::new(format!("{}. {}", self.selected_index+1, self.selected_name));
ComboBox::from_id_source("manual_nodes").selected_text(RichText::text_style(text, Monospace)).show_ui(ui, |ui| {
let mut n = 0;
@ -416,6 +421,7 @@ impl P2pool {
});
ui.add_space(5.0);
debug!("P2Pool Tab | Rendering [Main/Mini/Peers/Log] elements");
// [Main/Mini]
ui.horizontal(|ui| {
let height = height/4.0;

View file

@ -25,6 +25,7 @@ use crate::{
Sys,
};
use std::sync::{Arc,Mutex};
use log::*;
use egui::{
containers::*,
Label,RichText,TextStyle
@ -42,6 +43,7 @@ pub fn show(sys: &Arc<Mutex<Sys>>, p2pool_api: &Arc<Mutex<PubP2poolApi>>, xmrig_
ui.horizontal(|ui| {
// [Gupax]
ui.group(|ui| { ui.vertical(|ui| {
debug!("Status | Rendering [Gupax]");
ui.set_min_height(min_height);
ui.add_sized([width, height*2.0], Label::new(RichText::new("[Gupax]").color(LIGHT_GRAY).text_style(TextStyle::Name("MonospaceLarge".into())))).on_hover_text("Gupax is online");
let sys = sys.lock().unwrap();
@ -61,6 +63,7 @@ pub fn show(sys: &Arc<Mutex<Sys>>, p2pool_api: &Arc<Mutex<PubP2poolApi>>, xmrig_
})});
// [P2Pool]
ui.group(|ui| { ui.vertical(|ui| {
debug!("Status Tab | Rendering [P2Pool]");
ui.set_enabled(p2pool_online);
ui.set_min_height(min_height);
ui.add_sized([width, height*2.0], Label::new(RichText::new("[P2Pool]").color(LIGHT_GRAY).text_style(TextStyle::Name("MonospaceLarge".into())))).on_hover_text("P2Pool is online").on_disabled_hover_text("P2Pool is offline");
@ -85,6 +88,7 @@ pub fn show(sys: &Arc<Mutex<Sys>>, p2pool_api: &Arc<Mutex<PubP2poolApi>>, xmrig_
})});
// [XMRig]
ui.group(|ui| { ui.vertical(|ui| {
debug!("Status Tab | Rendering [XMRig]");
ui.set_enabled(xmrig_online);
ui.set_min_height(min_height);
ui.add_sized([width, height*2.0], Label::new(RichText::new("[XMRig]").color(LIGHT_GRAY).text_style(TextStyle::Name("MonospaceLarge".into())))).on_hover_text("XMRig is online").on_disabled_hover_text("XMRig is offline");

View file

@ -36,6 +36,7 @@ impl Xmrig {
pub fn show(&mut self, pool_vec: &mut Vec<(String, Pool)>, regex: &Regexes, process: &Arc<Mutex<Process>>, api: &Arc<Mutex<PubXmrigApi>>, buffer: &mut String, width: f32, height: f32, ctx: &egui::Context, ui: &mut egui::Ui) {
let text_edit = height / 25.0;
//---------------------------------------------------------------------------------------------------- [Simple] Console
debug!("XMRig Tab | Rendering [Console]");
ui.group(|ui| {
if self.simple {
let height = height / 1.5;
@ -70,8 +71,9 @@ impl Xmrig {
}
});
//---------------------------------------------------------------------------------------------------- Config
//---------------------------------------------------------------------------------------------------- Arguments
if !self.simple {
debug!("XMRig Tab | Rendering [Arguments]");
ui.group(|ui| { ui.horizontal(|ui| {
let width = (width/10.0) - SPACE;
ui.style_mut().override_text_style = Some(Monospace);
@ -81,6 +83,7 @@ impl Xmrig {
})});
ui.set_enabled(self.arguments.is_empty());
//---------------------------------------------------------------------------------------------------- Address
debug!("XMRig Tab | Rendering [Address]");
ui.group(|ui| {
let width = width - SPACE;
ui.spacing_mut().text_edit_width = (width)-(SPACE*3.0);
@ -106,6 +109,7 @@ impl Xmrig {
//---------------------------------------------------------------------------------------------------- Threads
if self.simple { ui.add_space(SPACE); }
debug!("XMRig Tab | Rendering [Threads]");
ui.vertical(|ui| {
let width = width/10.0;
ui.spacing_mut().icon_width = width / 25.0;
@ -129,7 +133,8 @@ impl Xmrig {
// });
} else {
let _height = height / 10.0;
debug!("XMRig Tab | Rendering [Pool List] elements");
// let _height = height / 10.0;
let width = ui.available_width() - 10.0;
let mut incorrect_input = false; // This will disable [Add/Delete] on bad input
// [Pool IP/Port]
@ -226,7 +231,8 @@ impl Xmrig {
// [Manual node selection]
ui.spacing_mut().slider_width = width - 8.0;
ui.spacing_mut().icon_width = width / 25.0;
// [Ping List]
// [Node List]
debug!("XMRig Tab | Rendering [Node List] ComboBox");
let text = RichText::new(format!("{}. {}", self.selected_index+1, self.selected_name));
ComboBox::from_id_source("manual_pool").selected_text(RichText::text_style(text, Monospace)).show_ui(ui, |ui| {
let mut n = 0;
@ -345,7 +351,8 @@ impl Xmrig {
});
ui.add_space(5.0);
// [HTTP API IP/Port] + [TLS + Keepalive]
debug!("XMRig Tab | Rendering [API] TextEdits");
// [HTTP API IP/Port]
ui.group(|ui| { ui.horizontal(|ui| {
ui.vertical(|ui| {
let width = width/10.0;
@ -396,6 +403,7 @@ impl Xmrig {
ui.separator();
debug!("XMRig Tab | Rendering [TLS/Keepalive] buttons");
ui.vertical(|ui| {
// TLS/Keepalive
ui.horizontal(|ui| {