Status Submenu: add macros!()

Writing [a.lock().unwrap().b.lock().unwrap()] sucks, so these are
some macros that are for common situations. This commit also has
a [sed] replace on all previous code that _could_ have been a macro,
which they all are now.

Hopefully nothing breaks :D
This commit is contained in:
hinto-janaiyo 2022-12-28 22:03:45 -05:00
parent 46b528ecbe
commit 19b5a2790b
No known key found for this signature in database
GPG key ID: B1C5A64B80691E45
13 changed files with 438 additions and 306 deletions

View file

@ -482,7 +482,7 @@ You need [`cargo`](https://www.rust-lang.org/learn/get-started), Rust's build to
The `--release` profile in Gupax is set to prefer code performance & small binary sizes over compilation speed (see [`Cargo.toml`](https://github.com/hinto-janaiyo/gupax/blob/main/Cargo.toml)). Gupax itself (with all dependencies already built) takes around 1m30s to build (vs 10s on a normal `--release`) with a Ryzen 5950x. The `--release` profile in Gupax is set to prefer code performance & small binary sizes over compilation speed (see [`Cargo.toml`](https://github.com/hinto-janaiyo/gupax/blob/main/Cargo.toml)). Gupax itself (with all dependencies already built) takes around 1m30s to build (vs 10s on a normal `--release`) with a Ryzen 5950x.
There are `30` unit tests throughout the codebase files, you should probably run: There are `34` unit tests throughout the codebase files, you should probably run:
``` ```
cargo test cargo test
``` ```

View file

@ -23,6 +23,7 @@
| ferris.rs | Cute crab bytes | ferris.rs | Cute crab bytes
| gupax.rs | `Gupax` tab | gupax.rs | `Gupax` tab
| helper.rs | The "helper" thread that runs for the entire duration Gupax is alive. All the processing that needs to be done without blocking the main GUI thread runs here, including everything related to handling P2Pool/XMRig | helper.rs | The "helper" thread that runs for the entire duration Gupax is alive. All the processing that needs to be done without blocking the main GUI thread runs here, including everything related to handling P2Pool/XMRig
| macros.rs | General `macros!()` used in Gupax
| main.rs | The main `App` struct that holds all data + misc data/functions | main.rs | The main `App` struct that holds all data + misc data/functions
| node.rs | Community node ping code for the `P2Pool` simple tab | node.rs | Community node ping code for the `P2Pool` simple tab
| p2pool.rs | `P2Pool` tab | p2pool.rs | `P2Pool` tab

View file

@ -47,6 +47,7 @@ use crate::{
gupax::Ratio, gupax::Ratio,
Tab, Tab,
xmr::*, xmr::*,
macros::*,
}; };
use log::*; use log::*;
@ -213,7 +214,7 @@ impl State {
gupax: Gupax::default(), gupax: Gupax::default(),
p2pool: P2pool::default(), p2pool: P2pool::default(),
xmrig: Xmrig::with_threads(max_threads, current_threads), xmrig: Xmrig::with_threads(max_threads, current_threads),
version: Arc::new(Mutex::new(Version::default())), version: arc_mut!(Version::default()),
} }
} }

View file

@ -32,6 +32,7 @@ use crate::{
ErrorState, ErrorState,
Restart, Restart,
Tab, Tab,
macros::*,
}; };
use std::{ use std::{
thread, thread,
@ -55,13 +56,13 @@ pub struct FileWindow {
impl FileWindow { impl FileWindow {
pub fn new() -> Arc<Mutex<Self>> { pub fn new() -> Arc<Mutex<Self>> {
Arc::new(Mutex::new(Self { arc_mut!(Self {
thread: false, thread: false,
picked_p2pool: false, picked_p2pool: false,
picked_xmrig: false, picked_xmrig: false,
p2pool_path: String::new(), p2pool_path: String::new(),
xmrig_path: String::new(), xmrig_path: String::new(),
})) })
} }
} }
@ -89,7 +90,7 @@ impl crate::disk::Gupax {
let button = if self.simple { height/5.0 } else { height/15.0 }; let button = if self.simple { height/5.0 } else { height/15.0 };
let height = if self.simple { height/5.0 } else { height/10.0 }; let height = if self.simple { height/5.0 } else { height/10.0 };
let width = width - SPACE; let width = width - SPACE;
let updating = *update.lock().unwrap().updating.lock().unwrap(); let updating = *lock2!(update,updating);
ui.vertical(|ui| { ui.vertical(|ui| {
// If [Gupax] is being built for a Linux distro, // If [Gupax] is being built for a Linux distro,
// disable built-in updating completely. // disable built-in updating completely.
@ -106,8 +107,8 @@ impl crate::disk::Gupax {
}); });
ui.vertical(|ui| { ui.vertical(|ui| {
ui.set_enabled(updating); ui.set_enabled(updating);
let prog = *update.lock().unwrap().prog.lock().unwrap(); let prog = *lock2!(update,prog);
let msg = format!("{}\n{}{}", *update.lock().unwrap().msg.lock().unwrap(), prog, "%"); let msg = format!("{}\n{}{}", *lock2!(update,msg), prog, "%");
ui.add_sized([width, height*1.4], Label::new(RichText::text_style(RichText::new(msg), Monospace))); ui.add_sized([width, height*1.4], Label::new(RichText::text_style(RichText::new(msg), Monospace)));
let height = height/2.0; let height = height/2.0;
if updating { if updating {
@ -115,7 +116,7 @@ impl crate::disk::Gupax {
} else { } else {
ui.add_sized([width, height], Label::new("...")); ui.add_sized([width, height], Label::new("..."));
} }
ui.add_sized([width, height], ProgressBar::new(update.lock().unwrap().prog.lock().unwrap().round() / 100.0)); ui.add_sized([width, height], ProgressBar::new(lock2!(update,prog).round() / 100.0));
}); });
}); });
@ -160,7 +161,7 @@ impl crate::disk::Gupax {
ui.add_sized([text_edit, height], Label::new(RichText::new("P2Pool Binary Path ✔").color(GREEN))).on_hover_text(P2POOL_PATH_OK); ui.add_sized([text_edit, height], Label::new(RichText::new("P2Pool Binary Path ✔").color(GREEN))).on_hover_text(P2POOL_PATH_OK);
} }
ui.spacing_mut().text_edit_width = ui.available_width() - SPACE; ui.spacing_mut().text_edit_width = ui.available_width() - SPACE;
ui.set_enabled(!file_window.lock().unwrap().thread); ui.set_enabled(!lock!(file_window).thread);
if ui.button("Open").on_hover_text(GUPAX_SELECT).clicked() { if ui.button("Open").on_hover_text(GUPAX_SELECT).clicked() {
Self::spawn_file_window_thread(file_window, FileType::P2pool); Self::spawn_file_window_thread(file_window, FileType::P2pool);
} }
@ -177,14 +178,14 @@ impl crate::disk::Gupax {
ui.add_sized([text_edit, height], Label::new(RichText::new(" XMRig Binary Path ✔").color(GREEN))).on_hover_text(XMRIG_PATH_OK); ui.add_sized([text_edit, height], Label::new(RichText::new(" XMRig Binary Path ✔").color(GREEN))).on_hover_text(XMRIG_PATH_OK);
} }
ui.spacing_mut().text_edit_width = ui.available_width() - SPACE; ui.spacing_mut().text_edit_width = ui.available_width() - SPACE;
ui.set_enabled(!file_window.lock().unwrap().thread); ui.set_enabled(!lock!(file_window).thread);
if ui.button("Open").on_hover_text(GUPAX_SELECT).clicked() { if ui.button("Open").on_hover_text(GUPAX_SELECT).clicked() {
Self::spawn_file_window_thread(file_window, FileType::Xmrig); Self::spawn_file_window_thread(file_window, FileType::Xmrig);
} }
ui.add_sized([ui.available_width(), height], TextEdit::singleline(&mut self.xmrig_path)).on_hover_text(GUPAX_PATH_XMRIG); ui.add_sized([ui.available_width(), height], TextEdit::singleline(&mut self.xmrig_path)).on_hover_text(GUPAX_PATH_XMRIG);
}); });
}); });
let mut guard = file_window.lock().unwrap(); let mut guard = lock!(file_window);
if guard.picked_p2pool { self.p2pool_path = guard.p2pool_path.clone(); guard.picked_p2pool = false; } if guard.picked_p2pool { self.p2pool_path = guard.p2pool_path.clone(); guard.picked_p2pool = false; }
if guard.picked_xmrig { self.xmrig_path = guard.xmrig_path.clone(); guard.picked_xmrig = false; } if guard.picked_xmrig { self.xmrig_path = guard.xmrig_path.clone(); guard.picked_xmrig = false; }
drop(guard); drop(guard);
@ -276,19 +277,19 @@ impl crate::disk::Gupax {
Xmrig => "XMRig", Xmrig => "XMRig",
}; };
let file_window = file_window.clone(); let file_window = file_window.clone();
file_window.lock().unwrap().thread = true; lock!(file_window).thread = true;
thread::spawn(move|| { thread::spawn(move|| {
match rfd::FileDialog::new().set_title(&format!("Select {} Binary for Gupax", name)).pick_file() { match rfd::FileDialog::new().set_title(&format!("Select {} Binary for Gupax", name)).pick_file() {
Some(path) => { Some(path) => {
info!("Gupax | Path selected for {} ... {}", name, path.display()); info!("Gupax | Path selected for {} ... {}", name, path.display());
match file_type { match file_type {
P2pool => { file_window.lock().unwrap().p2pool_path = path.display().to_string(); file_window.lock().unwrap().picked_p2pool = true; }, P2pool => { lock!(file_window).p2pool_path = path.display().to_string(); lock!(file_window).picked_p2pool = true; },
Xmrig => { file_window.lock().unwrap().xmrig_path = path.display().to_string(); file_window.lock().unwrap().picked_xmrig = true; }, Xmrig => { lock!(file_window).xmrig_path = path.display().to_string(); lock!(file_window).picked_xmrig = true; },
}; };
}, },
None => info!("Gupax | No path selected for {}", name), None => info!("Gupax | No path selected for {}", name),
}; };
file_window.lock().unwrap().thread = false; lock!(file_window).thread = false;
}); });
} }
} }

View file

@ -26,7 +26,7 @@
// found here, e.g: User clicks [Stop P2Pool] -> Arc<Mutex<ProcessSignal> is set // found here, e.g: User clicks [Stop P2Pool] -> Arc<Mutex<ProcessSignal> is set
// indicating to this thread during its loop: "I should stop P2Pool!", e.g: // indicating to this thread during its loop: "I should stop P2Pool!", e.g:
// //
// if p2pool.lock().unwrap().signal == ProcessSignal::Stop { // if lock!(p2pool).signal == ProcessSignal::Stop {
// stop_p2pool(), // stop_p2pool(),
// } // }
// //
@ -49,6 +49,7 @@ use crate::{
GupaxP2poolApi, GupaxP2poolApi,
P2poolRegex, P2poolRegex,
xmr::*, xmr::*,
macros::*,
}; };
use sysinfo::SystemExt; use sysinfo::SystemExt;
use serde::{Serialize,Deserialize}; use serde::{Serialize,Deserialize};
@ -168,8 +169,8 @@ impl Process {
start: Instant::now(), start: Instant::now(),
stdin: Option::None, stdin: Option::None,
child: Option::None, child: Option::None,
output_parse: Arc::new(Mutex::new(String::with_capacity(500))), output_parse: arc_mut!(String::with_capacity(500)),
output_pub: Arc::new(Mutex::new(String::with_capacity(500))), output_pub: arc_mut!(String::with_capacity(500)),
input: vec![String::new()], input: vec![String::new()],
} }
} }
@ -232,12 +233,12 @@ impl Helper {
instant, instant,
pub_sys, pub_sys,
uptime: HumanTime::into_human(instant.elapsed()), uptime: HumanTime::into_human(instant.elapsed()),
priv_api_p2pool_local: Arc::new(Mutex::new(PrivP2poolLocalApi::new())), priv_api_p2pool_local: arc_mut!(PrivP2poolLocalApi::new()),
priv_api_p2pool_network: Arc::new(Mutex::new(PrivP2poolNetworkApi::new())), priv_api_p2pool_network: arc_mut!(PrivP2poolNetworkApi::new()),
priv_api_p2pool_pool: Arc::new(Mutex::new(PrivP2poolPoolApi::new())), priv_api_p2pool_pool: arc_mut!(PrivP2poolPoolApi::new()),
priv_api_xmrig: Arc::new(Mutex::new(PrivXmrigApi::new())), priv_api_xmrig: arc_mut!(PrivXmrigApi::new()),
pub_api_p2pool: Arc::new(Mutex::new(PubP2poolApi::new())), pub_api_p2pool: arc_mut!(PubP2poolApi::new()),
pub_api_xmrig: Arc::new(Mutex::new(PubXmrigApi::new())), pub_api_xmrig: arc_mut!(PubXmrigApi::new()),
// These are created when initializing [App], since it needs a handle to it as well // These are created when initializing [App], since it needs a handle to it as well
p2pool, p2pool,
xmrig, xmrig,
@ -255,7 +256,7 @@ impl Helper {
// We don't need to write twice for XMRig, since we dont parse it... yet. // We don't need to write twice for XMRig, since we dont parse it... yet.
while let Some(Ok(line)) = stdout.next() { while let Some(Ok(line)) = stdout.next() {
// println!("{}", line); // For debugging. // println!("{}", line); // For debugging.
if let Err(e) = writeln!(output_pub.lock().unwrap(), "{}", line) { error!("XMRig PTY | Output error: {}", e); } if let Err(e) = writeln!(lock!(output_pub), "{}", line) { error!("XMRig PTY | Output error: {}", e); }
} }
} }
@ -267,11 +268,11 @@ impl Helper {
if regex.payout.is_match(&line) { if regex.payout.is_match(&line) {
debug!("P2Pool PTY | Found payout, attempting write: {}", line); debug!("P2Pool PTY | Found payout, attempting write: {}", line);
let (date, atomic_unit, block) = PayoutOrd::parse_line(&line, &regex); let (date, atomic_unit, block) = PayoutOrd::parse_line(&line, &regex);
GupaxP2poolApi::add_payout(&mut gupax_p2pool_api.lock().unwrap(), atomic_unit.to_u128(), &line); GupaxP2poolApi::add_payout(&mut lock!(gupax_p2pool_api), atomic_unit.to_u128(), &line);
if let Err(e) = GupaxP2poolApi::write_to_all_files(&gupax_p2pool_api.lock().unwrap()) { error!("P2Pool PTY GupaxP2poolApi | Write error: {}", e); } if let Err(e) = GupaxP2poolApi::write_to_all_files(&lock!(gupax_p2pool_api)) { error!("P2Pool PTY GupaxP2poolApi | Write error: {}", e); }
} }
if let Err(e) = writeln!(output_parse.lock().unwrap(), "{}", line) { error!("P2Pool PTY Parse | Output error: {}", e); } if let Err(e) = writeln!(lock!(output_parse), "{}", line) { error!("P2Pool PTY Parse | Output error: {}", e); }
if let Err(e) = writeln!(output_pub.lock().unwrap(), "{}", line) { error!("P2Pool PTY Pub | Output error: {}", e); } if let Err(e) = writeln!(lock!(output_pub), "{}", line) { error!("P2Pool PTY Pub | Output error: {}", e); }
} }
} }
@ -302,25 +303,25 @@ impl Helper {
// Just sets some signals for the watchdog thread to pick up on. // Just sets some signals for the watchdog thread to pick up on.
pub fn stop_p2pool(helper: &Arc<Mutex<Self>>) { pub fn stop_p2pool(helper: &Arc<Mutex<Self>>) {
info!("P2Pool | Attempting to stop..."); info!("P2Pool | Attempting to stop...");
helper.lock().unwrap().p2pool.lock().unwrap().signal = ProcessSignal::Stop; lock2!(helper,p2pool).signal = ProcessSignal::Stop;
helper.lock().unwrap().p2pool.lock().unwrap().state = ProcessState::Middle; lock2!(helper,p2pool).state = ProcessState::Middle;
} }
// The "restart frontend" to a "frontend" function. // The "restart frontend" to a "frontend" function.
// Basically calls to kill the current p2pool, waits a little, then starts the below function in a a new thread, then exit. // Basically calls to kill the current p2pool, waits a little, then starts the below function in a a new thread, then exit.
pub fn restart_p2pool(helper: &Arc<Mutex<Self>>, state: &crate::disk::P2pool, path: &std::path::PathBuf) { pub fn restart_p2pool(helper: &Arc<Mutex<Self>>, state: &crate::disk::P2pool, path: &std::path::PathBuf) {
info!("P2Pool | Attempting to restart..."); info!("P2Pool | Attempting to restart...");
helper.lock().unwrap().p2pool.lock().unwrap().signal = ProcessSignal::Restart; lock2!(helper,p2pool).signal = ProcessSignal::Restart;
helper.lock().unwrap().p2pool.lock().unwrap().state = ProcessState::Middle; lock2!(helper,p2pool).state = ProcessState::Middle;
let helper = Arc::clone(helper); let helper = Arc::clone(helper);
let state = state.clone(); let state = state.clone();
let path = path.clone(); let path = path.clone();
// This thread lives to wait, start p2pool then die. // This thread lives to wait, start p2pool then die.
thread::spawn(move || { thread::spawn(move || {
while helper.lock().unwrap().p2pool.lock().unwrap().is_alive() { while lock2!(helper,p2pool).is_alive() {
warn!("P2Pool | Want to restart but process is still alive, waiting..."); warn!("P2Pool | Want to restart but process is still alive, waiting...");
thread::sleep(SECOND); sleep!(1000);
} }
// Ok, process is not alive, start the new one! // Ok, process is not alive, start the new one!
info!("P2Pool | Old process seems dead, starting new one!"); info!("P2Pool | Old process seems dead, starting new one!");
@ -331,7 +332,7 @@ impl Helper {
// The "frontend" function that parses the arguments, and spawns either the [Simple] or [Advanced] P2Pool watchdog thread. // The "frontend" function that parses the arguments, and spawns either the [Simple] or [Advanced] P2Pool watchdog thread.
pub fn start_p2pool(helper: &Arc<Mutex<Self>>, state: &crate::disk::P2pool, path: &std::path::PathBuf) { pub fn start_p2pool(helper: &Arc<Mutex<Self>>, state: &crate::disk::P2pool, path: &std::path::PathBuf) {
helper.lock().unwrap().p2pool.lock().unwrap().state = ProcessState::Middle; lock2!(helper,p2pool).state = ProcessState::Middle;
let (args, api_path_local, api_path_network, api_path_pool) = Self::build_p2pool_args_and_mutate_img(helper, state, path); let (args, api_path_local, api_path_network, api_path_pool) = Self::build_p2pool_args_and_mutate_img(helper, state, path);
@ -345,10 +346,10 @@ impl Helper {
)); ));
// Spawn watchdog thread // Spawn watchdog thread
let process = Arc::clone(&helper.lock().unwrap().p2pool); let process = Arc::clone(&lock!(helper).p2pool);
let gui_api = Arc::clone(&helper.lock().unwrap().gui_api_p2pool); let gui_api = Arc::clone(&lock!(helper).gui_api_p2pool);
let pub_api = Arc::clone(&helper.lock().unwrap().pub_api_p2pool); let pub_api = Arc::clone(&lock!(helper).pub_api_p2pool);
let gupax_p2pool_api = Arc::clone(&helper.lock().unwrap().gupax_p2pool_api); let gupax_p2pool_api = Arc::clone(&lock!(helper).gupax_p2pool_api);
let path = path.clone(); let path = path.clone();
thread::spawn(move || { thread::spawn(move || {
Self::spawn_p2pool_watchdog(process, gui_api, pub_api, args, path, api_path_local, api_path_network, api_path_pool, gupax_p2pool_api); Self::spawn_p2pool_watchdog(process, gui_api, pub_api, args, path, api_path_local, api_path_network, api_path_pool, gupax_p2pool_api);
@ -385,7 +386,7 @@ impl Helper {
args.push("--local-api".to_string()); // Enable API args.push("--local-api".to_string()); // Enable API
args.push("--no-color".to_string()); // Remove color escape sequences, Gupax terminal can't parse it :( args.push("--no-color".to_string()); // Remove color escape sequences, Gupax terminal can't parse it :(
args.push("--mini".to_string()); // P2Pool Mini args.push("--mini".to_string()); // P2Pool Mini
*helper.lock().unwrap().img_p2pool.lock().unwrap() = ImgP2pool { *lock2!(helper,img_p2pool) = ImgP2pool {
mini: "P2Pool Mini".to_string(), mini: "P2Pool Mini".to_string(),
address: Self::head_tail_of_monero_address(&state.address), address: Self::head_tail_of_monero_address(&state.address),
host: ip.to_string(), host: ip.to_string(),
@ -402,8 +403,8 @@ impl Helper {
// This parses the input and attemps to fill out // This parses the input and attemps to fill out
// the [ImgP2pool]... This is pretty bad code... // the [ImgP2pool]... This is pretty bad code...
let mut last = ""; let mut last = "";
let lock = helper.lock().unwrap(); let lock = lock!(helper);
let mut p2pool_image = lock.img_p2pool.lock().unwrap(); let mut p2pool_image = lock!(lock.img_p2pool);
let mut mini = false; let mut mini = false;
for arg in state.arguments.split_whitespace() { for arg in state.arguments.split_whitespace() {
match last { match last {
@ -434,7 +435,7 @@ impl Helper {
args.push("--local-api".to_string()); // Enable API args.push("--local-api".to_string()); // Enable API
args.push("--no-color".to_string()); // Remove color escape sequences args.push("--no-color".to_string()); // Remove color escape sequences
if state.mini { args.push("--mini".to_string()); }; // Mini if state.mini { args.push("--mini".to_string()); }; // Mini
*helper.lock().unwrap().img_p2pool.lock().unwrap() = ImgP2pool { *lock2!(helper,img_p2pool) = ImgP2pool {
mini: if state.mini { "P2Pool Mini".to_string() } else { "P2Pool Main".to_string() }, mini: if state.mini { "P2Pool Mini".to_string() } else { "P2Pool Main".to_string() },
address: Self::head_tail_of_monero_address(&state.address), address: Self::head_tail_of_monero_address(&state.address),
host: state.selected_ip.to_string(), host: state.selected_ip.to_string(),
@ -472,11 +473,11 @@ impl Helper {
cmd.cwd(path.as_path().parent().unwrap()); cmd.cwd(path.as_path().parent().unwrap());
// 1c. Create child // 1c. Create child
debug!("P2Pool | Creating child..."); debug!("P2Pool | Creating child...");
let child_pty = Arc::new(Mutex::new(pair.slave.spawn_command(cmd).unwrap())); let child_pty = arc_mut!(pair.slave.spawn_command(cmd).unwrap());
// 2. Set process state // 2. Set process state
debug!("P2Pool | Setting process state..."); debug!("P2Pool | Setting process state...");
let mut lock = process.lock().unwrap(); let mut lock = lock!(process);
lock.state = ProcessState::Alive; lock.state = ProcessState::Alive;
lock.signal = ProcessSignal::None; lock.signal = ProcessSignal::None;
lock.start = Instant::now(); lock.start = Instant::now();
@ -489,15 +490,15 @@ impl Helper {
// 3. Spawn PTY read thread // 3. Spawn PTY read thread
debug!("P2Pool | Spawning PTY read thread..."); debug!("P2Pool | Spawning PTY read thread...");
let output_parse = Arc::clone(&process.lock().unwrap().output_parse); let output_parse = Arc::clone(&lock!(process).output_parse);
let output_pub = Arc::clone(&process.lock().unwrap().output_pub); let output_pub = Arc::clone(&lock!(process).output_pub);
let gupax_p2pool_api = Arc::clone(&gupax_p2pool_api); let gupax_p2pool_api = Arc::clone(&gupax_p2pool_api);
let regex_clone = regex.clone(); let regex_clone = regex.clone();
thread::spawn(move || { thread::spawn(move || {
Self::read_pty_p2pool(output_parse, output_pub, reader, regex_clone, gupax_p2pool_api); Self::read_pty_p2pool(output_parse, output_pub, reader, regex_clone, gupax_p2pool_api);
}); });
let output_parse = Arc::clone(&process.lock().unwrap().output_parse); let output_parse = Arc::clone(&lock!(process).output_parse);
let output_pub = Arc::clone(&process.lock().unwrap().output_pub); let output_pub = Arc::clone(&lock!(process).output_pub);
debug!("P2Pool | Cleaning old [local] API files..."); debug!("P2Pool | Cleaning old [local] API files...");
// Attempt to remove stale API file // Attempt to remove stale API file
@ -514,11 +515,11 @@ impl Helper {
Err(e) => warn!("P2Pool | Creating default empty API file ... FAIL ... {}", e), Err(e) => warn!("P2Pool | Creating default empty API file ... FAIL ... {}", e),
} }
} }
let start = process.lock().unwrap().start; let start = lock!(process).start;
// Reset stats before loop // Reset stats before loop
*pub_api.lock().unwrap() = PubP2poolApi::new(); *lock!(pub_api) = PubP2poolApi::new();
*gui_api.lock().unwrap() = PubP2poolApi::new(); *lock!(gui_api) = PubP2poolApi::new();
// 4. Loop as watchdog // 4. Loop as watchdog
info!("P2Pool | Entering watchdog mode... woof!"); info!("P2Pool | Entering watchdog mode... woof!");
@ -530,17 +531,17 @@ impl Helper {
tick += 1; tick += 1;
// Check if the process is secretly died without us knowing :) // Check if the process is secretly died without us knowing :)
if let Ok(Some(code)) = child_pty.lock().unwrap().try_wait() { if let Ok(Some(code)) = lock!(child_pty).try_wait() {
debug!("P2Pool Watchdog | Process secretly died! Getting exit status"); debug!("P2Pool Watchdog | Process secretly died! Getting exit status");
let exit_status = match code.success() { let exit_status = match code.success() {
true => { process.lock().unwrap().state = ProcessState::Dead; "Successful" }, true => { lock!(process).state = ProcessState::Dead; "Successful" },
false => { process.lock().unwrap().state = ProcessState::Failed; "Failed" }, false => { lock!(process).state = ProcessState::Failed; "Failed" },
}; };
let uptime = HumanTime::into_human(start.elapsed()); let uptime = HumanTime::into_human(start.elapsed());
info!("P2Pool Watchdog | 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, because sometimes the 900ms event loop can't catch it. // This is written directly into the GUI, because sometimes the 900ms event loop can't catch it.
if let Err(e) = writeln!( if let Err(e) = writeln!(
gui_api.lock().unwrap().output, lock!(gui_api).output,
"{}\nP2Pool stopped | Uptime: [{}] | Exit status: [{}]\n{}\n\n\n\n", "{}\nP2Pool stopped | Uptime: [{}] | Exit status: [{}]\n{}\n\n\n\n",
HORI_CONSOLE, HORI_CONSOLE,
uptime, uptime,
@ -549,32 +550,32 @@ impl Helper {
) { ) {
error!("P2Pool Watchdog | GUI Uptime/Exit status write failed: {}", e); error!("P2Pool Watchdog | GUI Uptime/Exit status write failed: {}", e);
} }
process.lock().unwrap().signal = ProcessSignal::None; lock!(process).signal = ProcessSignal::None;
debug!("P2Pool Watchdog | Secret dead process reap OK, breaking"); debug!("P2Pool Watchdog | Secret dead process reap OK, breaking");
break break
} }
// Check SIGNAL // Check SIGNAL
if process.lock().unwrap().signal == ProcessSignal::Stop { if lock!(process).signal == ProcessSignal::Stop {
debug!("P2Pool Watchdog | Stop SIGNAL caught"); debug!("P2Pool Watchdog | Stop SIGNAL caught");
// 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() { error!("P2Pool Watchdog | Kill error: {}", e); } if let Err(e) = lock!(child_pty).kill() { error!("P2Pool Watchdog | Kill error: {}", 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 lock!(child_pty).wait() {
Ok(e) => { Ok(e) => {
if e.success() { if e.success() {
process.lock().unwrap().state = ProcessState::Dead; "Successful" lock!(process).state = ProcessState::Dead; "Successful"
} else { } else {
process.lock().unwrap().state = ProcessState::Failed; "Failed" lock!(process).state = ProcessState::Failed; "Failed"
} }
}, },
_ => { process.lock().unwrap().state = ProcessState::Failed; "Unknown Error" }, _ => { lock!(process).state = ProcessState::Failed; "Unknown Error" },
}; };
let uptime = HumanTime::into_human(start.elapsed()); let uptime = HumanTime::into_human(start.elapsed());
info!("P2Pool Watchdog | 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. // This is written directly into the GUI API, because sometimes the 900ms event loop can't catch it.
if let Err(e) = writeln!( if let Err(e) = writeln!(
gui_api.lock().unwrap().output, lock!(gui_api).output,
"{}\nP2Pool stopped | Uptime: [{}] | Exit status: [{}]\n{}\n\n\n\n", "{}\nP2Pool stopped | Uptime: [{}] | Exit status: [{}]\n{}\n\n\n\n",
HORI_CONSOLE, HORI_CONSOLE,
uptime, uptime,
@ -583,16 +584,16 @@ impl Helper {
) { ) {
error!("P2Pool Watchdog | GUI Uptime/Exit status write failed: {}", e); error!("P2Pool Watchdog | GUI Uptime/Exit status write failed: {}", e);
} }
process.lock().unwrap().signal = ProcessSignal::None; lock!(process).signal = ProcessSignal::None;
debug!("P2Pool Watchdog | Stop SIGNAL done, breaking"); debug!("P2Pool Watchdog | Stop SIGNAL done, breaking");
break break
// Check RESTART // Check RESTART
} else if process.lock().unwrap().signal == ProcessSignal::Restart { } else if lock!(process).signal == ProcessSignal::Restart {
debug!("P2Pool Watchdog | Restart SIGNAL caught"); debug!("P2Pool Watchdog | Restart SIGNAL caught");
// 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() { error!("P2Pool Watchdog | Kill error: {}", e); } if let Err(e) = lock!(child_pty).kill() { error!("P2Pool Watchdog | Kill error: {}", 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 lock!(child_pty).wait() {
Ok(e) => if e.success() { "Successful" } else { "Failed" }, Ok(e) => if e.success() { "Successful" } else { "Failed" },
_ => "Unknown Error", _ => "Unknown Error",
}; };
@ -600,7 +601,7 @@ impl Helper {
info!("P2Pool Watchdog | 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. // This is written directly into the GUI API, because sometimes the 900ms event loop can't catch it.
if let Err(e) = writeln!( if let Err(e) = writeln!(
gui_api.lock().unwrap().output, lock!(gui_api).output,
"{}\nP2Pool stopped | Uptime: [{}] | Exit status: [{}]\n{}\n\n\n\n", "{}\nP2Pool stopped | Uptime: [{}] | Exit status: [{}]\n{}\n\n\n\n",
HORI_CONSOLE, HORI_CONSOLE,
uptime, uptime,
@ -609,13 +610,13 @@ impl Helper {
) { ) {
error!("P2Pool Watchdog | GUI Uptime/Exit status write failed: {}", e); error!("P2Pool Watchdog | GUI Uptime/Exit status write failed: {}", e);
} }
process.lock().unwrap().state = ProcessState::Waiting; lock!(process).state = ProcessState::Waiting;
debug!("P2Pool Watchdog | Restart SIGNAL done, breaking"); debug!("P2Pool Watchdog | Restart SIGNAL done, breaking");
break break
} }
// Check vector of user input // Check vector of user input
let mut lock = process.lock().unwrap(); let mut lock = lock!(process);
if !lock.input.is_empty() { if !lock.input.is_empty() {
let input = std::mem::take(&mut lock.input); let input = std::mem::take(&mut lock.input);
for line in input { for line in input {
@ -628,7 +629,7 @@ impl Helper {
// Check if logs need resetting // Check if logs need resetting
debug!("P2Pool Watchdog | Attempting GUI log reset check"); debug!("P2Pool Watchdog | Attempting GUI log reset check");
let mut lock = gui_api.lock().unwrap(); let mut lock = lock!(gui_api);
Self::check_reset_gui_output(&mut lock.output, ProcessName::P2pool); Self::check_reset_gui_output(&mut lock.output, ProcessName::P2pool);
drop(lock); drop(lock);
@ -662,7 +663,7 @@ impl Helper {
if elapsed < 900 { if elapsed < 900 {
let sleep = (900-elapsed) as u64; let sleep = (900-elapsed) as u64;
debug!("P2Pool Watchdog | END OF LOOP - Tick: [{}/60] - Sleeping for [{}]ms...", tick, sleep); debug!("P2Pool Watchdog | END OF LOOP - Tick: [{}/60] - Sleeping for [{}]ms...", tick, sleep);
std::thread::sleep(std::time::Duration::from_millis(sleep)); sleep!(sleep);
} else { } else {
debug!("P2Pool Watchdog | END OF LOOP - Tick: [{}/60] Not sleeping!", tick); debug!("P2Pool Watchdog | END OF LOOP - Tick: [{}/60] Not sleeping!", tick);
} }
@ -686,7 +687,7 @@ impl Helper {
// Write the [sudo] password to STDIN. // Write the [sudo] password to STDIN.
let mut stdin = child.stdin.take().unwrap(); let mut stdin = child.stdin.take().unwrap();
use std::io::Write; use std::io::Write;
if let Err(e) = writeln!(stdin, "{}\n", sudo.lock().unwrap().pass) { error!("Sudo Kill | STDIN error: {}", e); } if let Err(e) = writeln!(stdin, "{}\n", lock!(sudo).pass) { error!("Sudo Kill | STDIN error: {}", e); }
// Return exit code of [sudo/kill]. // Return exit code of [sudo/kill].
child.wait().unwrap().success() child.wait().unwrap().success()
@ -695,25 +696,25 @@ impl Helper {
// Just sets some signals for the watchdog thread to pick up on. // Just sets some signals for the watchdog thread to pick up on.
pub fn stop_xmrig(helper: &Arc<Mutex<Self>>) { pub fn stop_xmrig(helper: &Arc<Mutex<Self>>) {
info!("XMRig | Attempting to stop..."); info!("XMRig | Attempting to stop...");
helper.lock().unwrap().xmrig.lock().unwrap().signal = ProcessSignal::Stop; lock2!(helper,xmrig).signal = ProcessSignal::Stop;
helper.lock().unwrap().xmrig.lock().unwrap().state = ProcessState::Middle; lock2!(helper,xmrig).state = ProcessState::Middle;
} }
// The "restart frontend" to a "frontend" function. // The "restart frontend" to a "frontend" function.
// Basically calls to kill the current xmrig, waits a little, then starts the below function in a a new thread, then exit. // Basically calls to kill the current xmrig, waits a little, then starts the below function in a a new thread, then exit.
pub fn restart_xmrig(helper: &Arc<Mutex<Self>>, state: &crate::disk::Xmrig, path: &std::path::PathBuf, sudo: Arc<Mutex<SudoState>>) { pub fn restart_xmrig(helper: &Arc<Mutex<Self>>, state: &crate::disk::Xmrig, path: &std::path::PathBuf, sudo: Arc<Mutex<SudoState>>) {
info!("XMRig | Attempting to restart..."); info!("XMRig | Attempting to restart...");
helper.lock().unwrap().xmrig.lock().unwrap().signal = ProcessSignal::Restart; lock2!(helper,xmrig).signal = ProcessSignal::Restart;
helper.lock().unwrap().xmrig.lock().unwrap().state = ProcessState::Middle; lock2!(helper,xmrig).state = ProcessState::Middle;
let helper = Arc::clone(helper); let helper = Arc::clone(helper);
let state = state.clone(); let state = state.clone();
let path = path.clone(); let path = path.clone();
// This thread lives to wait, start xmrig then die. // This thread lives to wait, start xmrig then die.
thread::spawn(move || { thread::spawn(move || {
while helper.lock().unwrap().xmrig.lock().unwrap().state != ProcessState::Waiting { while lock2!(helper,xmrig).state != ProcessState::Waiting {
warn!("XMRig | Want to restart but process is still alive, waiting..."); warn!("XMRig | Want to restart but process is still alive, waiting...");
thread::sleep(SECOND); sleep!(1000);
} }
// Ok, process is not alive, start the new one! // Ok, process is not alive, start the new one!
info!("XMRig | Old process seems dead, starting new one!"); info!("XMRig | Old process seems dead, starting new one!");
@ -723,7 +724,7 @@ impl Helper {
} }
pub fn start_xmrig(helper: &Arc<Mutex<Self>>, state: &crate::disk::Xmrig, path: &std::path::PathBuf, sudo: Arc<Mutex<SudoState>>) { pub fn start_xmrig(helper: &Arc<Mutex<Self>>, state: &crate::disk::Xmrig, path: &std::path::PathBuf, sudo: Arc<Mutex<SudoState>>) {
helper.lock().unwrap().xmrig.lock().unwrap().state = ProcessState::Middle; lock2!(helper,xmrig).state = ProcessState::Middle;
let (args, api_ip_port) = Self::build_xmrig_args_and_mutate_img(helper, state, path); let (args, api_ip_port) = Self::build_xmrig_args_and_mutate_img(helper, state, path);
@ -732,10 +733,10 @@ impl Helper {
info!("XMRig | Using path: [{}]", path.display()); info!("XMRig | Using path: [{}]", path.display());
// Spawn watchdog thread // Spawn watchdog thread
let process = Arc::clone(&helper.lock().unwrap().xmrig); let process = Arc::clone(&lock!(helper).xmrig);
let gui_api = Arc::clone(&helper.lock().unwrap().gui_api_xmrig); let gui_api = Arc::clone(&lock!(helper).gui_api_xmrig);
let pub_api = Arc::clone(&helper.lock().unwrap().pub_api_xmrig); let pub_api = Arc::clone(&lock!(helper).pub_api_xmrig);
let priv_api = Arc::clone(&helper.lock().unwrap().priv_api_xmrig); let priv_api = Arc::clone(&lock!(helper).priv_api_xmrig);
let path = path.clone(); let path = path.clone();
thread::spawn(move || { thread::spawn(move || {
Self::spawn_xmrig_watchdog(process, gui_api, pub_api, priv_api, args, path, sudo, api_ip_port); Self::spawn_xmrig_watchdog(process, gui_api, pub_api, priv_api, args, path, sudo, api_ip_port);
@ -771,7 +772,7 @@ impl Helper {
args.push("--http-host".to_string()); args.push("127.0.0.1".to_string()); // HTTP API IP args.push("--http-host".to_string()); args.push("127.0.0.1".to_string()); // HTTP API IP
args.push("--http-port".to_string()); args.push("18088".to_string()); // HTTP API Port args.push("--http-port".to_string()); args.push("18088".to_string()); // HTTP API Port
if state.pause != 0 { args.push("--pause-on-active".to_string()); args.push(state.pause.to_string()); } // Pause on active if state.pause != 0 { args.push("--pause-on-active".to_string()); args.push(state.pause.to_string()); } // Pause on active
*helper.lock().unwrap().img_xmrig.lock().unwrap() = ImgXmrig { *lock2!(helper,img_xmrig) = ImgXmrig {
threads: state.current_threads.to_string(), threads: state.current_threads.to_string(),
url: "127.0.0.1:3333 (Local P2Pool)".to_string(), url: "127.0.0.1:3333 (Local P2Pool)".to_string(),
}; };
@ -785,8 +786,8 @@ impl Helper {
// This parses the input and attemps to fill out // This parses the input and attemps to fill out
// the [ImgXmrig]... This is pretty bad code... // the [ImgXmrig]... This is pretty bad code...
let mut last = ""; let mut last = "";
let lock = helper.lock().unwrap(); let lock = lock!(helper);
let mut xmrig_image = lock.img_xmrig.lock().unwrap(); let mut xmrig_image = lock!(lock.img_xmrig);
for arg in state.arguments.split_whitespace() { for arg in state.arguments.split_whitespace() {
match last { match last {
"--threads" => xmrig_image.threads = arg.to_string(), "--threads" => xmrig_image.threads = arg.to_string(),
@ -814,7 +815,7 @@ impl Helper {
if state.tls { args.push("--tls".to_string()); } // TLS if state.tls { args.push("--tls".to_string()); } // TLS
if state.keepalive { args.push("--keepalive".to_string()); } // Keepalive if state.keepalive { args.push("--keepalive".to_string()); } // Keepalive
if state.pause != 0 { args.push("--pause-on-active".to_string()); args.push(state.pause.to_string()); } // Pause on active if state.pause != 0 { args.push("--pause-on-active".to_string()); args.push(state.pause.to_string()); } // Pause on active
*helper.lock().unwrap().img_xmrig.lock().unwrap() = ImgXmrig { *lock2!(helper,img_xmrig) = ImgXmrig {
url, url,
threads: state.current_threads.to_string(), threads: state.current_threads.to_string(),
}; };
@ -862,21 +863,21 @@ impl Helper {
let cmd = Self::create_xmrig_cmd_unix(args, path); let cmd = Self::create_xmrig_cmd_unix(args, path);
// 1c. Create child // 1c. Create child
debug!("XMRig | Creating child..."); debug!("XMRig | Creating child...");
let child_pty = Arc::new(Mutex::new(pair.slave.spawn_command(cmd).unwrap())); let child_pty = arc_mut!(pair.slave.spawn_command(cmd).unwrap());
// 2. Input [sudo] pass, wipe, then drop. // 2. Input [sudo] pass, wipe, then drop.
if cfg!(unix) { if cfg!(unix) {
debug!("XMRig | Inputting [sudo] and wiping..."); debug!("XMRig | Inputting [sudo] and wiping...");
// 1d. Sleep to wait for [sudo]'s non-echo prompt (on Unix). // 1d. Sleep to wait for [sudo]'s non-echo prompt (on Unix).
// this prevents users pass from showing up in the STDOUT. // this prevents users pass from showing up in the STDOUT.
std::thread::sleep(std::time::Duration::from_secs(3)); sleep!(3000);
if let Err(e) = writeln!(pair.master, "{}", sudo.lock().unwrap().pass) { error!("XMRig | Sudo STDIN error: {}", e); }; if let Err(e) = writeln!(pair.master, "{}", lock!(sudo).pass) { error!("XMRig | Sudo STDIN error: {}", e); };
SudoState::wipe(&sudo); SudoState::wipe(&sudo);
} }
// 3. Set process state // 3. Set process state
debug!("XMRig | Setting process state..."); debug!("XMRig | Setting process state...");
let mut lock = process.lock().unwrap(); let mut lock = lock!(process);
lock.state = ProcessState::Alive; lock.state = ProcessState::Alive;
lock.signal = ProcessSignal::None; lock.signal = ProcessSignal::None;
lock.start = Instant::now(); lock.start = Instant::now();
@ -887,17 +888,17 @@ impl Helper {
// 4. Spawn PTY read thread // 4. Spawn PTY read thread
debug!("XMRig | Spawning PTY read thread..."); debug!("XMRig | Spawning PTY read thread...");
let output_parse = Arc::clone(&process.lock().unwrap().output_parse); let output_parse = Arc::clone(&lock!(process).output_parse);
let output_pub = Arc::clone(&process.lock().unwrap().output_pub); let output_pub = Arc::clone(&lock!(process).output_pub);
thread::spawn(move || { thread::spawn(move || {
Self::read_pty_xmrig(output_parse, output_pub, reader); Self::read_pty_xmrig(output_parse, output_pub, reader);
}); });
// We don't parse anything in XMRigs output... yet. // We don't parse anything in XMRigs output... yet.
// let output_parse = Arc::clone(&process.lock().unwrap().output_parse); // let output_parse = Arc::clone(&lock!(process).output_parse);
let output_pub = Arc::clone(&process.lock().unwrap().output_pub); let output_pub = Arc::clone(&lock!(process).output_pub);
let client: hyper::Client<hyper::client::HttpConnector> = hyper::Client::builder().build(hyper::client::HttpConnector::new()); let client: hyper::Client<hyper::client::HttpConnector> = hyper::Client::builder().build(hyper::client::HttpConnector::new());
let start = process.lock().unwrap().start; let start = lock!(process).start;
let api_uri = { let api_uri = {
if !api_ip_port.ends_with('/') { api_ip_port.push('/'); } if !api_ip_port.ends_with('/') { api_ip_port.push('/'); }
"http://".to_owned() + &api_ip_port + XMRIG_API_URI "http://".to_owned() + &api_ip_port + XMRIG_API_URI
@ -905,8 +906,8 @@ impl Helper {
info!("XMRig | Final API URI: {}", api_uri); info!("XMRig | Final API URI: {}", api_uri);
// Reset stats before loop // Reset stats before loop
*pub_api.lock().unwrap() = PubXmrigApi::new(); *lock!(pub_api) = PubXmrigApi::new();
*gui_api.lock().unwrap() = PubXmrigApi::new(); *lock!(gui_api) = PubXmrigApi::new();
// 5. Loop as watchdog // 5. Loop as watchdog
info!("XMRig | Entering watchdog mode... woof!"); info!("XMRig | Entering watchdog mode... woof!");
@ -916,16 +917,16 @@ impl Helper {
debug!("XMRig Watchdog | ----------- Start of loop -----------"); debug!("XMRig Watchdog | ----------- Start of loop -----------");
// Check if the process secretly died without us knowing :) // Check if the process secretly died without us knowing :)
if let Ok(Some(code)) = child_pty.lock().unwrap().try_wait() { if let Ok(Some(code)) = lock!(child_pty).try_wait() {
debug!("XMRig Watchdog | Process secretly died on us! Getting exit status..."); debug!("XMRig Watchdog | Process secretly died on us! Getting exit status...");
let exit_status = match code.success() { let exit_status = match code.success() {
true => { process.lock().unwrap().state = ProcessState::Dead; "Successful" }, true => { lock!(process).state = ProcessState::Dead; "Successful" },
false => { process.lock().unwrap().state = ProcessState::Failed; "Failed" }, false => { lock!(process).state = ProcessState::Failed; "Failed" },
}; };
let uptime = HumanTime::into_human(start.elapsed()); let uptime = HumanTime::into_human(start.elapsed());
info!("XMRig | Stopped ... Uptime was: [{}], Exit status: [{}]", uptime, exit_status); info!("XMRig | Stopped ... Uptime was: [{}], Exit status: [{}]", uptime, exit_status);
if let Err(e) = writeln!( if let Err(e) = writeln!(
gui_api.lock().unwrap().output, lock!(gui_api).output,
"{}\nXMRig stopped | Uptime: [{}] | Exit status: [{}]\n{}\n\n\n\n", "{}\nXMRig stopped | Uptime: [{}] | Exit status: [{}]\n{}\n\n\n\n",
HORI_CONSOLE, HORI_CONSOLE,
uptime, uptime,
@ -934,13 +935,13 @@ impl Helper {
) { ) {
error!("XMRig Watchdog | GUI Uptime/Exit status write failed: {}", e); error!("XMRig Watchdog | GUI Uptime/Exit status write failed: {}", e);
} }
process.lock().unwrap().signal = ProcessSignal::None; lock!(process).signal = ProcessSignal::None;
debug!("XMRig Watchdog | Secret dead process reap OK, breaking"); debug!("XMRig Watchdog | Secret dead process reap OK, breaking");
break break
} }
// Stop on [Stop/Restart] SIGNAL // Stop on [Stop/Restart] SIGNAL
let signal = process.lock().unwrap().signal; let signal = lock!(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]
@ -948,16 +949,16 @@ impl Helper {
// If we're at this point, that means the user has // If we're at this point, that means the user has
// entered their [sudo] pass again, after we wiped it. // entered their [sudo] pass again, after we wiped it.
// So, we should be able to find it in our [Arc<Mutex<SudoState>>]. // So, we should be able to find it in our [Arc<Mutex<SudoState>>].
Self::sudo_kill(child_pty.lock().unwrap().process_id().unwrap(), &sudo); Self::sudo_kill(lock!(child_pty).process_id().unwrap(), &sudo);
// And... wipe it again (only if we're stopping full). // And... wipe it again (only if we're stopping full).
// If we're restarting, the next start will wipe it for us. // If we're restarting, the next start will wipe it for us.
if signal != ProcessSignal::Restart { SudoState::wipe(&sudo); } if signal != ProcessSignal::Restart { SudoState::wipe(&sudo); }
} else if let Err(e) = child_pty.lock().unwrap().kill() { } else if let Err(e) = lock!(child_pty).kill() {
error!("XMRig Watchdog | Kill error: {}", e); error!("XMRig Watchdog | Kill error: {}", e);
} }
let exit_status = match child_pty.lock().unwrap().wait() { let exit_status = match lock!(child_pty).wait() {
Ok(e) => { Ok(e) => {
let mut process = process.lock().unwrap(); let mut process = lock!(process);
if e.success() { if e.success() {
if process.signal == ProcessSignal::Stop { process.state = ProcessState::Dead; } if process.signal == ProcessSignal::Stop { process.state = ProcessState::Dead; }
"Successful" "Successful"
@ -967,7 +968,7 @@ impl Helper {
} }
}, },
_ => { _ => {
let mut process = process.lock().unwrap(); let mut process = lock!(process);
if process.signal == ProcessSignal::Stop { process.state = ProcessState::Failed; } if process.signal == ProcessSignal::Stop { process.state = ProcessState::Failed; }
"Unknown Error" "Unknown Error"
}, },
@ -975,7 +976,7 @@ impl Helper {
let uptime = HumanTime::into_human(start.elapsed()); let uptime = HumanTime::into_human(start.elapsed());
info!("XMRig | Stopped ... Uptime was: [{}], Exit status: [{}]", uptime, exit_status); info!("XMRig | Stopped ... Uptime was: [{}], Exit status: [{}]", uptime, exit_status);
if let Err(e) = writeln!( if let Err(e) = writeln!(
gui_api.lock().unwrap().output, lock!(gui_api).output,
"{}\nXMRig stopped | Uptime: [{}] | Exit status: [{}]\n{}\n\n\n\n", "{}\nXMRig stopped | Uptime: [{}] | Exit status: [{}]\n{}\n\n\n\n",
HORI_CONSOLE, HORI_CONSOLE,
uptime, uptime,
@ -984,7 +985,7 @@ impl Helper {
) { ) {
error!("XMRig Watchdog | GUI Uptime/Exit status write failed: {}", e); error!("XMRig Watchdog | GUI Uptime/Exit status write failed: {}", e);
} }
let mut process = process.lock().unwrap(); let mut process = lock!(process);
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,
@ -995,7 +996,7 @@ impl Helper {
} }
// Check vector of user input // Check vector of user input
let mut lock = process.lock().unwrap(); let mut lock = lock!(process);
if !lock.input.is_empty() { if !lock.input.is_empty() {
let input = std::mem::take(&mut lock.input); let input = std::mem::take(&mut lock.input);
for line in input { for line in input {
@ -1007,7 +1008,7 @@ impl Helper {
// Check if logs need resetting // Check if logs need resetting
debug!("XMRig Watchdog | Attempting GUI log reset check"); debug!("XMRig Watchdog | Attempting GUI log reset check");
let mut lock = gui_api.lock().unwrap(); let mut lock = lock!(gui_api);
Self::check_reset_gui_output(&mut lock.output, ProcessName::Xmrig); Self::check_reset_gui_output(&mut lock.output, ProcessName::Xmrig);
drop(lock); drop(lock);
@ -1030,7 +1031,7 @@ impl Helper {
if elapsed < 900 { if elapsed < 900 {
let sleep = (900-elapsed) as u64; let sleep = (900-elapsed) as u64;
debug!("XMRig Watchdog | END OF LOOP - Sleeping for [{}]ms...", sleep); debug!("XMRig Watchdog | END OF LOOP - Sleeping for [{}]ms...", sleep);
std::thread::sleep(std::time::Duration::from_millis(sleep)); sleep!(sleep);
} else { } else {
debug!("XMRig Watchdog | END OF LOOP - Not sleeping!"); debug!("XMRig Watchdog | END OF LOOP - Not sleeping!");
} }
@ -1089,7 +1090,7 @@ impl Helper {
// order as the main GUI thread (top to bottom). // order as the main GUI thread (top to bottom).
let helper = Arc::clone(helper); let helper = Arc::clone(helper);
let lock = helper.lock().unwrap(); let lock = lock!(helper);
let p2pool = Arc::clone(&lock.p2pool); let p2pool = Arc::clone(&lock.p2pool);
let xmrig = Arc::clone(&lock.xmrig); let xmrig = Arc::clone(&lock.xmrig);
let pub_sys = Arc::clone(&lock.pub_sys); let pub_sys = Arc::clone(&lock.pub_sys);
@ -1115,14 +1116,14 @@ impl Helper {
// down the culprit of an [Arc<Mutex>] deadlock. I know, they're ugly. // down the culprit of an [Arc<Mutex>] deadlock. I know, they're ugly.
// 2. Lock... EVERYTHING! // 2. Lock... EVERYTHING!
let mut lock = helper.lock().unwrap(); debug!("Helper | Locking (1/8) ... [helper]"); let mut lock = lock!(helper); debug!("Helper | Locking (1/8) ... [helper]");
let p2pool = p2pool.lock().unwrap(); debug!("Helper | Locking (2/8) ... [p2pool]"); let p2pool = lock!(p2pool); debug!("Helper | Locking (2/8) ... [p2pool]");
let xmrig = xmrig.lock().unwrap(); debug!("Helper | Locking (3/8) ... [xmrig]"); let xmrig = lock!(xmrig); debug!("Helper | Locking (3/8) ... [xmrig]");
let mut lock_pub_sys = pub_sys.lock().unwrap(); debug!("Helper | Locking (4/8) ... [pub_sys]"); let mut lock_pub_sys = lock!(pub_sys); debug!("Helper | Locking (4/8) ... [pub_sys]");
let mut gui_api_p2pool = gui_api_p2pool.lock().unwrap(); debug!("Helper | Locking (5/8) ... [gui_api_p2pool]"); let mut gui_api_p2pool = lock!(gui_api_p2pool); debug!("Helper | Locking (5/8) ... [gui_api_p2pool]");
let mut gui_api_xmrig = gui_api_xmrig.lock().unwrap(); debug!("Helper | Locking (6/8) ... [gui_api_xmrig]"); let mut gui_api_xmrig = lock!(gui_api_xmrig); debug!("Helper | Locking (6/8) ... [gui_api_xmrig]");
let mut pub_api_p2pool = pub_api_p2pool.lock().unwrap(); debug!("Helper | Locking (7/8) ... [pub_api_p2pool]"); let mut pub_api_p2pool = lock!(pub_api_p2pool); debug!("Helper | Locking (7/8) ... [pub_api_p2pool]");
let mut pub_api_xmrig = pub_api_xmrig.lock().unwrap(); debug!("Helper | Locking (8/8) ... [pub_api_xmrig]"); let mut pub_api_xmrig = lock!(pub_api_xmrig); debug!("Helper | Locking (8/8) ... [pub_api_xmrig]");
// 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 [P2Pool] is alive... // If [P2Pool] is alive...
@ -1165,7 +1166,7 @@ impl Helper {
// is less than 1000, meaning it can fit into a u64 easy. // is less than 1000, meaning it can fit into a u64 easy.
let sleep = (1000-elapsed) as u64; let sleep = (1000-elapsed) as u64;
debug!("Helper | END OF LOOP - Sleeping for [{}]ms...", sleep); debug!("Helper | END OF LOOP - Sleeping for [{}]ms...", sleep);
std::thread::sleep(std::time::Duration::from_millis(sleep)); sleep!(sleep);
} else { } else {
debug!("Helper | END OF LOOP - Not sleeping!"); debug!("Helper | END OF LOOP - Not sleeping!");
} }
@ -1341,19 +1342,19 @@ impl PubP2poolApi {
// Mutate "watchdog"'s [PubP2poolApi] with data the process output. // Mutate "watchdog"'s [PubP2poolApi] with data the process output.
fn update_from_output(public: &Arc<Mutex<Self>>, output_parse: &Arc<Mutex<String>>, output_pub: &Arc<Mutex<String>>, elapsed: std::time::Duration, regex: &P2poolRegex) { fn update_from_output(public: &Arc<Mutex<Self>>, output_parse: &Arc<Mutex<String>>, output_pub: &Arc<Mutex<String>>, elapsed: std::time::Duration, regex: &P2poolRegex) {
// 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 = lock!(output_pub);
if !output_pub.is_empty() { if !output_pub.is_empty() {
public.lock().unwrap().output.push_str(&std::mem::take(&mut *output_pub)); lock!(public).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 = lock!(output_parse);
let (payouts_new, xmr_new) = Self::calc_payouts_and_xmr(&output_parse, regex); let (payouts_new, xmr_new) = Self::calc_payouts_and_xmr(&output_parse, regex);
// 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 mut public = lock!(public);
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
@ -1397,7 +1398,7 @@ impl PubP2poolApi {
// Mutate [PubP2poolApi] with data from a [PrivP2poolLocalApi] and the process output. // Mutate [PubP2poolApi] with data from a [PrivP2poolLocalApi] and the process output.
fn update_from_local(public: &Arc<Mutex<Self>>, local: PrivP2poolLocalApi) { fn update_from_local(public: &Arc<Mutex<Self>>, local: PrivP2poolLocalApi) {
let mut public = public.lock().unwrap(); let mut public = lock!(public);
*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),
@ -1413,7 +1414,7 @@ impl PubP2poolApi {
// Mutate [PubP2poolApi] with data from a [PrivP2pool(Network|Pool)Api]. // Mutate [PubP2poolApi] with data from a [PrivP2pool(Network|Pool)Api].
fn update_from_network_pool(public: &Arc<Mutex<Self>>, net: PrivP2poolNetworkApi, pool: PrivP2poolPoolApi) { fn update_from_network_pool(public: &Arc<Mutex<Self>>, net: PrivP2poolNetworkApi, pool: PrivP2poolPoolApi) {
let user_hashrate = public.lock().unwrap().hashrate; // The user's total P2Pool hashrate let user_hashrate = lock!(public).hashrate; // 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;
@ -1449,7 +1450,7 @@ impl PubP2poolApi {
solo_block_mean = HumanTime::into_human(std::time::Duration::from_secs(monero_difficulty / user_hashrate)); solo_block_mean = HumanTime::into_human(std::time::Duration::from_secs(monero_difficulty / user_hashrate));
p2pool_share_mean = HumanTime::into_human(std::time::Duration::from_secs(p2pool_difficulty / user_hashrate)); p2pool_share_mean = HumanTime::into_human(std::time::Duration::from_secs(p2pool_difficulty / user_hashrate));
} }
let mut public = public.lock().unwrap(); let mut public = lock!(public);
*public = Self { *public = Self {
monero_difficulty: HumanNumber::from_u64(monero_difficulty), monero_difficulty: HumanNumber::from_u64(monero_difficulty),
monero_hashrate: HumanNumber::from_u64_to_gigahash_3_point(monero_hashrate), monero_hashrate: HumanNumber::from_u64_to_gigahash_3_point(monero_hashrate),
@ -1642,8 +1643,8 @@ impl PubXmrigApi {
// with the actual [PubApiXmrig] output field. // with the actual [PubApiXmrig] output field.
fn update_from_output(public: &Arc<Mutex<Self>>, output_pub: &Arc<Mutex<String>>, elapsed: std::time::Duration) { fn update_from_output(public: &Arc<Mutex<Self>>, output_pub: &Arc<Mutex<String>>, elapsed: std::time::Duration) {
// 1. Take process output buffer if not empty // 1. Take process output buffer if not empty
let mut output_pub = output_pub.lock().unwrap(); let mut output_pub = lock!(output_pub);
let mut public = public.lock().unwrap(); let mut public = lock!(public);
// 2. Append // 2. Append
if !output_pub.is_empty() { if !output_pub.is_empty() {
public.output.push_str(&std::mem::take(&mut *output_pub)); public.output.push_str(&std::mem::take(&mut *output_pub));
@ -1654,7 +1655,7 @@ impl PubXmrigApi {
// Formats raw private data into ready-to-print human readable version. // Formats raw private data into ready-to-print human readable version.
fn update_from_priv(public: &Arc<Mutex<Self>>, private: PrivXmrigApi) { fn update_from_priv(public: &Arc<Mutex<Self>>, private: PrivXmrigApi) {
let mut public = public.lock().unwrap(); let mut public = lock!(public);
*public = Self { *public = Self {
worker_id: private.worker_id, worker_id: private.worker_id,
resources: HumanNumber::from_load(private.resources.load_average), resources: HumanNumber::from_load(private.resources.load_average),

121
src/macros.rs Normal file
View file

@ -0,0 +1,121 @@
// Gupax - GUI Uniting P2Pool And XMRig
//
// Copyright (c) 2022 hinto-janaiyo
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <https://www.gnu.org/licenses/>.
// These are general QoL macros, nothing too scary, I promise.
//
// | MACRO | PURPOSE | EQUIVALENT CODE |
// |---------|----------------------------------------------|------------------------------------------------------------|
// | lock | Lock an [Arc<Mutex>] | a.lock().unwrap() |
// | lock2 | Lock a field inside a struct, both Arc<Mutex | a.lock().unwrap().b.lock().unwrap() |
// | arc_mut | Create a new [Arc<Mutex>] | std::sync::Arc::new(std::sync::Mutex::new(my_value)) |
// | sleep | Sleep the current thread for x milliseconds | std::thread::sleep(std::time::Duration::from_millis(1000)) |
// | flip | Flip a bool in place | my_bool = !my_bool |
//
// Hopefully the long ass code on the right justifies usage of macros :D
//
// [lock2!()] works like this: "lock2!(my_first, my_second)"
// and expects it be a [Struct]-[field] relationship, e.g:
//
// let my_first = Struct {
// my_second: Arc::new(Mutex::new(true)),
// };
// lock2!(my_first, my_second);
//
// The equivalent code is: "my_first.lock().unwrap().my_second.lock().unwrap()" (see? this is long as hell)
// Locks and unwraps an [Arc<Mutex<T>]
macro_rules! lock {
($arc_mutex:expr) => {
$arc_mutex.lock().unwrap()
};
}
pub(crate) use lock;
// Creates a new [Arc<Mutex<T>]
macro_rules! arc_mut {
($arc_mutex:expr) => {
std::sync::Arc::new(std::sync::Mutex::new($arc_mutex))
};
}
pub(crate) use arc_mut;
// Locks and unwraps a field of a struct, both of them being [Arc<Mutex>]
// Yes, I know this is bad code.
macro_rules! lock2 {
($arc_mutex:expr, $arc_mutex_two:ident) => {
$arc_mutex.lock().unwrap().$arc_mutex_two.lock().unwrap()
};
}
pub(crate) use lock2;
// Sleeps a [std::thread] using milliseconds
macro_rules! sleep {
($millis:expr) => {
std::thread::sleep(std::time::Duration::from_millis($millis))
};
}
pub(crate) use sleep;
// Flips a [bool] in place
macro_rules! flip {
($b:expr) => {
match $b {
true|false => $b = !$b,
};
};
}
pub(crate) use flip;
//---------------------------------------------------------------------------------------------------- TESTS
#[cfg(test)]
mod test {
#[test]
fn lock() {
use std::sync::{Arc,Mutex};
let arc_mutex = Arc::new(Mutex::new(false));
*lock!(arc_mutex) = true;
assert!(*lock!(arc_mutex) == true);
}
#[test]
fn lock2() {
struct Ab {
a: Arc<Mutex<bool>>,
}
use std::sync::{Arc,Mutex};
let arc_mutex = Arc::new(Mutex::new(
Ab {
a: Arc::new(Mutex::new(false)),
}
));
*lock2!(arc_mutex,a) = true;
assert!(*lock2!(arc_mutex,a) == true);
}
#[test]
fn arc_mut() {
let a = arc_mut!(false);
assert!(*lock!(a) == false);
}
#[test]
fn flip() {
let mut b = true;
flip!(b);
assert!(b == false);
}
}

View file

@ -65,7 +65,8 @@ mod helper;
mod human; mod human;
mod regex; mod regex;
mod xmr; mod xmr;
use {crate::regex::*,ferris::*,constants::*,node::*,disk::*,update::*,gupax::*,helper::*}; mod macros;
use {macros::*,crate::regex::*,ferris::*,constants::*,node::*,disk::*,update::*,gupax::*,helper::*};
// Sudo (dummy values for Windows) // Sudo (dummy values for Windows)
mod sudo; mod sudo;
@ -176,12 +177,12 @@ impl App {
fn new(now: Instant) -> Self { fn new(now: Instant) -> Self {
info!("Initializing App Struct..."); info!("Initializing App Struct...");
debug!("App Init | P2Pool & XMRig processes..."); debug!("App Init | P2Pool & XMRig processes...");
let p2pool = Arc::new(Mutex::new(Process::new(ProcessName::P2pool, String::new(), PathBuf::new()))); let p2pool = arc_mut!(Process::new(ProcessName::P2pool, String::new(), PathBuf::new()));
let xmrig = Arc::new(Mutex::new(Process::new(ProcessName::Xmrig, String::new(), PathBuf::new()))); let xmrig = arc_mut!(Process::new(ProcessName::Xmrig, String::new(), PathBuf::new()));
let p2pool_api = Arc::new(Mutex::new(PubP2poolApi::new())); let p2pool_api = arc_mut!(PubP2poolApi::new());
let xmrig_api = Arc::new(Mutex::new(PubXmrigApi::new())); let xmrig_api = arc_mut!(PubXmrigApi::new());
let p2pool_img = Arc::new(Mutex::new(ImgP2pool::new())); let p2pool_img = arc_mut!(ImgP2pool::new());
let xmrig_img = Arc::new(Mutex::new(ImgXmrig::new())); let xmrig_img = arc_mut!(ImgXmrig::new());
debug!("App Init | Sysinfo..."); debug!("App Init | Sysinfo...");
// We give this to the [Helper] thread. // We give this to the [Helper] thread.
@ -195,27 +196,27 @@ impl App {
Ok(pid) => pid, Ok(pid) => pid,
Err(e) => { error!("App Init | Failed to get sysinfo PID: {}", e); exit(1) } Err(e) => { error!("App Init | Failed to get sysinfo PID: {}", e); exit(1) }
}; };
let pub_sys = Arc::new(Mutex::new(Sys::new())); let pub_sys = arc_mut!(Sys::new());
debug!("App Init | The rest of the [App]..."); debug!("App Init | The rest of the [App]...");
let mut app = Self { let mut app = Self {
tab: Tab::default(), tab: Tab::default(),
ping: Arc::new(Mutex::new(Ping::new())), ping: arc_mut!(Ping::new()),
width: APP_DEFAULT_WIDTH, width: APP_DEFAULT_WIDTH,
height: APP_DEFAULT_HEIGHT, height: APP_DEFAULT_HEIGHT,
must_resize: false, must_resize: false,
og: Arc::new(Mutex::new(State::new())), og: arc_mut!(State::new()),
state: State::new(), state: State::new(),
update: Arc::new(Mutex::new(Update::new(String::new(), PathBuf::new(), PathBuf::new(), true))), update: arc_mut!(Update::new(String::new(), PathBuf::new(), PathBuf::new(), true)),
file_window: FileWindow::new(), file_window: FileWindow::new(),
og_node_vec: Node::new_vec(), og_node_vec: Node::new_vec(),
node_vec: Node::new_vec(), node_vec: Node::new_vec(),
og_pool_vec: Pool::new_vec(), og_pool_vec: Pool::new_vec(),
pool_vec: Pool::new_vec(), pool_vec: Pool::new_vec(),
restart: Arc::new(Mutex::new(Restart::No)), restart: arc_mut!(Restart::No),
diff: false, diff: false,
error_state: ErrorState::new(), error_state: ErrorState::new(),
helper: Arc::new(Mutex::new(Helper::new(now, pub_sys.clone(), p2pool.clone(), xmrig.clone(), p2pool_api.clone(), xmrig_api.clone(), p2pool_img.clone(), xmrig_img.clone(), Arc::new(Mutex::new(GupaxP2poolApi::new()))))), helper: arc_mut!(Helper::new(now, pub_sys.clone(), p2pool.clone(), xmrig.clone(), p2pool_api.clone(), xmrig_api.clone(), p2pool_img.clone(), xmrig_img.clone(), arc_mut!(GupaxP2poolApi::new()))),
p2pool, p2pool,
xmrig, xmrig,
p2pool_api, p2pool_api,
@ -224,11 +225,11 @@ impl App {
xmrig_img, xmrig_img,
p2pool_stdin: String::with_capacity(10), p2pool_stdin: String::with_capacity(10),
xmrig_stdin: String::with_capacity(10), xmrig_stdin: String::with_capacity(10),
sudo: Arc::new(Mutex::new(SudoState::new())), sudo: arc_mut!(SudoState::new()),
resizing: false, resizing: false,
alpha: 0, alpha: 0,
no_startup: false, no_startup: false,
gupax_p2pool_api: Arc::new(Mutex::new(GupaxP2poolApi::new())), gupax_p2pool_api: arc_mut!(GupaxP2poolApi::new()),
pub_sys, pub_sys,
pid, pid,
max_threads: num_cpus::get(), max_threads: num_cpus::get(),
@ -301,7 +302,7 @@ impl App {
State::new() State::new()
}, },
}; };
app.og = Arc::new(Mutex::new(app.state.clone())); app.og = arc_mut!(app.state.clone());
// Read node list // Read node list
debug!("App Init | Reading node list..."); debug!("App Init | Reading node list...");
app.node_vec = match Node::get(&app.node_path) { app.node_vec = match Node::get(&app.node_path) {
@ -348,7 +349,7 @@ impl App {
//---------------------------------------------------------------------------------------------------- //----------------------------------------------------------------------------------------------------
// Read [GupaxP2poolApi] disk files // Read [GupaxP2poolApi] disk files
app.gupax_p2pool_api_path = crate::disk::get_gupax_p2pool_path(&app.os_data_path); app.gupax_p2pool_api_path = crate::disk::get_gupax_p2pool_path(&app.os_data_path);
let mut gupax_p2pool_api = app.gupax_p2pool_api.lock().unwrap(); let mut gupax_p2pool_api = lock!(app.gupax_p2pool_api);
gupax_p2pool_api.fill_paths(&app.gupax_p2pool_api_path); gupax_p2pool_api.fill_paths(&app.gupax_p2pool_api_path);
match GupaxP2poolApi::create_all_files(&app.gupax_p2pool_api_path) { match GupaxP2poolApi::create_all_files(&app.gupax_p2pool_api_path) {
Ok(_) => debug!("App Init | Creating Gupax-P2Pool API files ... OK"), Ok(_) => debug!("App Init | Creating Gupax-P2Pool API files ... OK"),
@ -388,10 +389,10 @@ impl App {
}, },
}; };
drop(gupax_p2pool_api); drop(gupax_p2pool_api);
app.helper.lock().unwrap().gupax_p2pool_api = Arc::clone(&app.gupax_p2pool_api); lock!(app.helper).gupax_p2pool_api = Arc::clone(&app.gupax_p2pool_api);
//---------------------------------------------------------------------------------------------------- //----------------------------------------------------------------------------------------------------
let mut og = app.og.lock().unwrap(); // Lock [og] let mut og = lock!(app.og); // Lock [og]
// Handle max threads // Handle max threads
debug!("App Init | Handling max thread overflow..."); debug!("App Init | Handling max thread overflow...");
og.xmrig.max_threads = app.max_threads; og.xmrig.max_threads = app.max_threads;
@ -436,13 +437,13 @@ impl App {
let p2pool_path = og.gupax.absolute_p2pool_path.clone(); let p2pool_path = og.gupax.absolute_p2pool_path.clone();
let xmrig_path = og.gupax.absolute_xmrig_path.clone(); let xmrig_path = og.gupax.absolute_xmrig_path.clone();
let tor = og.gupax.update_via_tor; let tor = og.gupax.update_via_tor;
app.update = Arc::new(Mutex::new(Update::new(app.exe.clone(), p2pool_path, xmrig_path, tor))); app.update = arc_mut!(Update::new(app.exe.clone(), p2pool_path, xmrig_path, tor));
debug!("App Init | Setting state Gupax version..."); debug!("App Init | Setting state Gupax version...");
// Set state version as compiled in version // Set state version as compiled in version
og.version.lock().unwrap().gupax = GUPAX_VERSION.to_string(); lock!(og.version).gupax = GUPAX_VERSION.to_string();
app.state.version.lock().unwrap().gupax = GUPAX_VERSION.to_string(); lock!(app.state.version).gupax = GUPAX_VERSION.to_string();
debug!("App Init | Setting saved [Tab]..."); debug!("App Init | Setting saved [Tab]...");
// Set saved [Tab] // Set saved [Tab]
@ -804,7 +805,7 @@ fn init_auto(app: &mut App) {
} else if cfg!(windows) { } else if cfg!(windows) {
Helper::start_xmrig(&app.helper, &app.state.xmrig, &app.state.gupax.absolute_xmrig_path, Arc::clone(&app.sudo)); Helper::start_xmrig(&app.helper, &app.state.xmrig, &app.state.gupax.absolute_xmrig_path, Arc::clone(&app.sudo));
} else { } else {
app.sudo.lock().unwrap().signal = ProcessSignal::Start; lock!(app.sudo).signal = ProcessSignal::Start;
app.error_state.ask_sudo(&app.sudo); app.error_state.ask_sudo(&app.sudo);
} }
} else { } else {
@ -1062,9 +1063,9 @@ impl eframe::App for App {
Submenu::Monero => self.state.status.submenu = Submenu::P2pool, Submenu::Monero => self.state.status.submenu = Submenu::P2pool,
} }
}, },
Tab::Gupax => self.state.gupax.simple = !self.state.gupax.simple, Tab::Gupax => flip!(self.state.gupax.simple),
Tab::P2pool => self.state.p2pool.simple = !self.state.p2pool.simple, Tab::P2pool => flip!(self.state.p2pool.simple),
Tab::Xmrig => self.state.xmrig.simple = !self.state.xmrig.simple, Tab::Xmrig => flip!(self.state.xmrig.simple),
_ => (), _ => (),
}; };
// Change Submenu RIGHT // Change Submenu RIGHT
@ -1077,9 +1078,9 @@ impl eframe::App for App {
Submenu::Monero => self.state.status.submenu = Submenu::Processes, Submenu::Monero => self.state.status.submenu = Submenu::Processes,
} }
}, },
Tab::Gupax => self.state.gupax.simple = !self.state.gupax.simple, Tab::Gupax => flip!(self.state.gupax.simple),
Tab::P2pool => self.state.p2pool.simple = !self.state.p2pool.simple, Tab::P2pool => flip!(self.state.p2pool.simple),
Tab::Xmrig => self.state.xmrig.simple = !self.state.xmrig.simple, Tab::Xmrig => flip!(self.state.xmrig.simple),
_ => (), _ => (),
}; };
} }
@ -1093,13 +1094,13 @@ impl eframe::App for App {
// 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 P2Pool state..."); debug!("App | Locking and collecting P2Pool state...");
let p2pool = self.p2pool.lock().unwrap(); let p2pool = lock!(self.p2pool);
let p2pool_is_alive = p2pool.is_alive(); let p2pool_is_alive = p2pool.is_alive();
let p2pool_is_waiting = p2pool.is_waiting(); let p2pool_is_waiting = p2pool.is_waiting();
let p2pool_state = p2pool.state; let p2pool_state = p2pool.state;
drop(p2pool); drop(p2pool);
debug!("App | Locking and collecting XMRig state..."); debug!("App | Locking and collecting XMRig state...");
let xmrig = self.xmrig.lock().unwrap(); let xmrig = lock!(self.xmrig);
let xmrig_is_alive = xmrig.is_alive(); let xmrig_is_alive = xmrig.is_alive();
let xmrig_is_waiting = xmrig.is_waiting(); let xmrig_is_waiting = xmrig.is_waiting();
let xmrig_state = xmrig.state; let xmrig_state = xmrig.state;
@ -1190,7 +1191,7 @@ impl eframe::App for App {
match self.error_state.buttons { match self.error_state.buttons {
StayQuit => { StayQuit => {
let mut text = "".to_string(); let mut text = "".to_string();
if *self.update.lock().unwrap().updating.lock().unwrap() { text = format!("{}\nUpdate is in progress...! Quitting may cause file corruption!", text); } if *lock2!(self.update,updating) { text = format!("{}\nUpdate is in progress...! Quitting may cause file corruption!", text); }
if p2pool_is_alive { text = format!("{}\nP2Pool is online...!", text); } if p2pool_is_alive { text = format!("{}\nP2Pool is online...!", text); }
if xmrig_is_alive { text = format!("{}\nXMRig is online...!", text); } if xmrig_is_alive { text = format!("{}\nXMRig is online...!", text); }
ui.add_sized([width, height], Label::new("--- Are you sure you want to quit? ---")); ui.add_sized([width, height], Label::new("--- Are you sure you want to quit? ---"));
@ -1270,7 +1271,7 @@ impl eframe::App for App {
match State::get(&self.state_path) { match State::get(&self.state_path) {
Ok(s) => { Ok(s) => {
self.state = s; self.state = s;
self.og = Arc::new(Mutex::new(self.state.clone())); self.og = arc_mut!(self.state.clone());
self.error_state.set("State read OK", ErrorFerris::Happy, ErrorButtons::Okay); self.error_state.set("State read OK", ErrorFerris::Happy, ErrorButtons::Okay);
}, },
Err(e) => self.error_state.set(format!("State read fail: {}", e), ErrorFerris::Panic, ErrorButtons::Quit), Err(e) => self.error_state.set(format!("State read fail: {}", e), ErrorFerris::Panic, ErrorButtons::Quit),
@ -1302,7 +1303,7 @@ impl eframe::App for App {
ErrorButtons::Sudo => { ErrorButtons::Sudo => {
let sudo_width = width/10.0; let sudo_width = width/10.0;
let height = ui.available_height()/4.0; let height = ui.available_height()/4.0;
let mut sudo = self.sudo.lock().unwrap(); let mut sudo = lock!(self.sudo);
let hide = sudo.hide; let hide = sudo.hide;
ui.style_mut().override_text_style = Some(Monospace); ui.style_mut().override_text_style = Some(Monospace);
if sudo.testing { if sudo.testing {
@ -1325,7 +1326,7 @@ impl eframe::App for App {
} }
} }
let color = if hide { BLACK } else { BRIGHT_YELLOW }; let color = if hide { BLACK } else { BRIGHT_YELLOW };
if ui.add_sized([box_width, height], Button::new(RichText::new("👁").color(color))).on_hover_text(PASSWORD_HIDE).clicked() { sudo.hide = !sudo.hide; } if ui.add_sized([box_width, height], Button::new(RichText::new("👁").color(color))).on_hover_text(PASSWORD_HIDE).clicked() { flip!(sudo.hide) }
}); });
if (key.is_esc() && !sudo.testing) || ui.add_sized([width, height*4.0], Button::new("Leave")).on_hover_text(PASSWORD_LEAVE).clicked() { self.error_state.reset(); }; if (key.is_esc() && !sudo.testing) || ui.add_sized([width, height*4.0], Button::new("Leave")).on_hover_text(PASSWORD_LEAVE).clicked() { self.error_state.reset(); };
// If [test_sudo()] finished, reset error state. // If [test_sudo()] finished, reset error state.
@ -1346,7 +1347,7 @@ impl eframe::App for App {
// contains Arc<Mutex>'s that cannot be compared easily. // contains Arc<Mutex>'s that cannot be compared easily.
// They don't need to be compared anyway. // They don't need to be compared anyway.
debug!("App | Checking diff between [og] & [state]"); debug!("App | Checking diff between [og] & [state]");
let og = self.og.lock().unwrap(); let og = lock!(self.og);
if og.status != self.state.status || if og.status != self.state.status ||
og.gupax != self.state.gupax || og.gupax != self.state.gupax ||
og.p2pool != self.state.p2pool || og.p2pool != self.state.p2pool ||
@ -1394,7 +1395,7 @@ impl eframe::App for App {
let width = ((self.width/2.0)/4.0)-(SPACE*2.0); let width = ((self.width/2.0)/4.0)-(SPACE*2.0);
// [Gupax Version] // [Gupax Version]
// Is yellow if the user updated and should (but isn't required to) restart. // Is yellow if the user updated and should (but isn't required to) restart.
match *self.restart.lock().unwrap() { match *lock!(self.restart) {
Restart::Yes => ui.add_sized([width, height], Label::new(RichText::new(&self.name_version).color(YELLOW))).on_hover_text(GUPAX_SHOULD_RESTART), Restart::Yes => ui.add_sized([width, height], Label::new(RichText::new(&self.name_version).color(YELLOW))).on_hover_text(GUPAX_SHOULD_RESTART),
_ => ui.add_sized([width, height], Label::new(&self.name_version)).on_hover_text(GUPAX_UP_TO_DATE), _ => ui.add_sized([width, height], Label::new(&self.name_version)).on_hover_text(GUPAX_UP_TO_DATE),
}; };
@ -1436,7 +1437,7 @@ impl eframe::App for App {
ui.set_enabled(self.diff); ui.set_enabled(self.diff);
let width = width / 2.0; let width = width / 2.0;
if key.is_r() && !wants_input && self.diff || ui.add_sized([width, height], Button::new("Reset")).on_hover_text("Reset changes").clicked() { if key.is_r() && !wants_input && self.diff || ui.add_sized([width, height], Button::new("Reset")).on_hover_text("Reset changes").clicked() {
let og = self.og.lock().unwrap().clone(); let og = lock!(self.og).clone();
self.state.status = og.status; self.state.status = og.status;
self.state.gupax = og.gupax; self.state.gupax = og.gupax;
self.state.p2pool = og.p2pool; self.state.p2pool = og.p2pool;
@ -1447,7 +1448,7 @@ impl eframe::App for App {
if key.is_s() && !wants_input && self.diff || ui.add_sized([width, height], Button::new("Save")).on_hover_text("Save changes").clicked() { if key.is_s() && !wants_input && self.diff || ui.add_sized([width, height], Button::new("Save")).on_hover_text("Save changes").clicked() {
match State::save(&mut self.state, &self.state_path) { match State::save(&mut self.state, &self.state_path) {
Ok(_) => { Ok(_) => {
let mut og = self.og.lock().unwrap(); let mut og = lock!(self.og);
og.status = self.state.status.clone(); og.status = self.state.status.clone();
og.gupax = self.state.gupax.clone(); og.gupax = self.state.gupax.clone();
og.p2pool = self.state.p2pool.clone(); og.p2pool = self.state.p2pool.clone();
@ -1577,13 +1578,13 @@ impl eframe::App for App {
if cfg!(windows) { if cfg!(windows) {
Helper::restart_xmrig(&self.helper, &self.state.xmrig, &self.state.gupax.absolute_xmrig_path, Arc::clone(&self.sudo)); Helper::restart_xmrig(&self.helper, &self.state.xmrig, &self.state.gupax.absolute_xmrig_path, Arc::clone(&self.sudo));
} else { } else {
self.sudo.lock().unwrap().signal = ProcessSignal::Restart; lock!(self.sudo).signal = ProcessSignal::Restart;
self.error_state.ask_sudo(&self.sudo); self.error_state.ask_sudo(&self.sudo);
} }
} }
if key.is_down() && !wants_input || ui.add_sized([width, height], Button::new("")).on_hover_text("Stop XMRig").clicked() { if key.is_down() && !wants_input || ui.add_sized([width, height], Button::new("")).on_hover_text("Stop XMRig").clicked() {
if cfg!(target_os = "macos") { if cfg!(target_os = "macos") {
self.sudo.lock().unwrap().signal = ProcessSignal::Stop; lock!(self.sudo).signal = ProcessSignal::Stop;
self.error_state.ask_sudo(&self.sudo); self.error_state.ask_sudo(&self.sudo);
} else { } else {
Helper::stop_xmrig(&self.helper); Helper::stop_xmrig(&self.helper);
@ -1614,7 +1615,7 @@ impl eframe::App for App {
} }
#[cfg(target_family = "unix")] #[cfg(target_family = "unix")]
if (ui_enabled && key.is_up() && !wants_input) || ui.add_sized([width, height], Button::new(RichText::new("").color(color))).on_hover_text("Start XMRig").on_disabled_hover_text(text).clicked() { if (ui_enabled && key.is_up() && !wants_input) || ui.add_sized([width, height], Button::new(RichText::new("").color(color))).on_hover_text("Start XMRig").on_disabled_hover_text(text).clicked() {
self.sudo.lock().unwrap().signal = ProcessSignal::Start; lock!(self.sudo).signal = ProcessSignal::Start;
self.error_state.ask_sudo(&self.sudo); self.error_state.ask_sudo(&self.sudo);
} }
} }
@ -1643,8 +1644,8 @@ impl eframe::App for App {
let distro = true; let distro = true;
#[cfg(not(feature = "distro"))] #[cfg(not(feature = "distro"))]
let distro = false; let distro = false;
let p2pool_gui_len = self.p2pool_api.lock().unwrap().output.len(); let p2pool_gui_len = lock!(self.p2pool_api).output.len();
let xmrig_gui_len = self.xmrig_api.lock().unwrap().output.len(); let xmrig_gui_len = lock!(self.xmrig_api).output.len();
let debug_info = format!( let debug_info = format!(
"Gupax version: {}\n "Gupax version: {}\n
Bundled P2Pool version: {}\n Bundled P2Pool version: {}\n
@ -1704,11 +1705,11 @@ XMRig console byte length: {}\n
self.state.gupax.absolute_xmrig_path.display(), self.state.gupax.absolute_xmrig_path.display(),
p2pool_gui_len, p2pool_gui_len,
xmrig_gui_len, xmrig_gui_len,
self.p2pool_img.lock().unwrap(), lock!(self.p2pool_img),
self.xmrig_img.lock().unwrap(), lock!(self.xmrig_img),
self.gupax_p2pool_api.lock().unwrap(), lock!(self.gupax_p2pool_api),
self.state, self.state,
self.og.lock().unwrap(), lock!(self.og),
); );
self.error_state.set(debug_info, ErrorFerris::Cute, ErrorButtons::Debug); self.error_state.set(debug_info, ErrorFerris::Cute, ErrorButtons::Debug);
} }

View file

@ -17,6 +17,7 @@
use crate::{ use crate::{
constants::*, constants::*,
macros::*,
}; };
use serde::{Serialize,Deserialize}; use serde::{Serialize,Deserialize};
use rand::{thread_rng, Rng}; use rand::{thread_rng, Rng};
@ -310,19 +311,19 @@ impl Ping {
match Self::ping(&ping) { match Self::ping(&ping) {
Ok(msg) => { Ok(msg) => {
info!("Ping ... OK"); info!("Ping ... OK");
ping.lock().unwrap().msg = msg; lock!(ping).msg = msg;
ping.lock().unwrap().pinged = true; lock!(ping).pinged = true;
ping.lock().unwrap().auto_selected = false; lock!(ping).auto_selected = false;
ping.lock().unwrap().prog = 100.0; lock!(ping).prog = 100.0;
}, },
Err(err) => { Err(err) => {
error!("Ping ... FAIL ... {}", err); error!("Ping ... FAIL ... {}", err);
ping.lock().unwrap().pinged = false; lock!(ping).pinged = false;
ping.lock().unwrap().msg = err.to_string(); lock!(ping).msg = err.to_string();
}, },
} }
info!("Ping ... Took [{}] seconds...", now.elapsed().as_secs_f32()); info!("Ping ... Took [{}] seconds...", now.elapsed().as_secs_f32());
ping.lock().unwrap().pinging = false; lock!(ping).pinging = false;
}); });
} }
@ -347,13 +348,13 @@ impl Ping {
pub async fn ping(ping: &Arc<Mutex<Self>>) -> Result<String, anyhow::Error> { pub async fn ping(ping: &Arc<Mutex<Self>>) -> Result<String, anyhow::Error> {
// Start ping // Start ping
let ping = Arc::clone(ping); let ping = Arc::clone(ping);
ping.lock().unwrap().pinging = true; lock!(ping).pinging = true;
ping.lock().unwrap().prog = 0.0; lock!(ping).prog = 0.0;
let percent = (100.0 / (COMMUNITY_NODE_LENGTH as f32)).floor(); let percent = (100.0 / (COMMUNITY_NODE_LENGTH as f32)).floor();
// Create HTTP client // Create HTTP client
let info = "Creating HTTP Client".to_string(); let info = "Creating HTTP Client".to_string();
ping.lock().unwrap().msg = info; lock!(ping).msg = info;
let client: Client<HttpConnector> = Client::builder() let client: Client<HttpConnector> = Client::builder()
.build(HttpConnector::new()); .build(HttpConnector::new());
@ -361,7 +362,7 @@ impl Ping {
let rand_user_agent = crate::Pkg::get_user_agent(); let rand_user_agent = crate::Pkg::get_user_agent();
// Handle vector // Handle vector
let mut handles = Vec::with_capacity(COMMUNITY_NODE_LENGTH); let mut handles = Vec::with_capacity(COMMUNITY_NODE_LENGTH);
let node_vec = Arc::new(Mutex::new(Vec::with_capacity(COMMUNITY_NODE_LENGTH))); let node_vec = arc_mut!(Vec::with_capacity(COMMUNITY_NODE_LENGTH));
for ip in NODE_IPS { for ip in NODE_IPS {
let client = client.clone(); let client = client.clone();
@ -381,12 +382,12 @@ impl Ping {
handle.await?; handle.await?;
} }
let node_vec = std::mem::take(&mut *node_vec.lock().unwrap()); let node_vec = std::mem::take(&mut *lock!(node_vec));
let fastest_info = format!("Fastest node: {}ms ... {} @ {}", node_vec[0].ms, node_vec[0].id, node_vec[0].ip); let fastest_info = format!("Fastest node: {}ms ... {} @ {}", node_vec[0].ms, node_vec[0].id, node_vec[0].ip);
let info = "Cleaning up connections".to_string(); let info = "Cleaning up connections".to_string();
info!("Ping | {}...", info); info!("Ping | {}...", info);
let mut ping = ping.lock().unwrap(); let mut ping = lock!(ping);
ping.fastest = node_vec[0].id; ping.fastest = node_vec[0].id;
ping.nodes = node_vec; ping.nodes = node_vec;
ping.msg = info; ping.msg = info;
@ -421,11 +422,11 @@ impl Ping {
} else { } else {
color = BLACK; color = BLACK;
} }
let mut ping = ping.lock().unwrap(); let mut ping = lock!(ping);
ping.msg = info; ping.msg = info;
ping.prog += percent; ping.prog += percent;
drop(ping); drop(ping);
node_vec.lock().unwrap().push(NodeData { id: ip_to_enum(ip), ip, ms, color, }); lock!(node_vec).push(NodeData { id: ip_to_enum(ip), ip, ms, color, });
} }
} }

View file

@ -21,6 +21,7 @@ use crate::{
disk::*, disk::*,
node::*, node::*,
helper::*, helper::*,
macros::*,
}; };
use egui::{ use egui::{
TextEdit,SelectableLabel,ComboBox,Label,Button, TextEdit,SelectableLabel,ComboBox,Label,Button,
@ -44,7 +45,7 @@ impl crate::disk::P2pool {
egui::Frame::none().fill(DARK_GRAY).show(ui, |ui| { egui::Frame::none().fill(DARK_GRAY).show(ui, |ui| {
ui.style_mut().override_text_style = Some(Name("MonospaceSmall".into())); ui.style_mut().override_text_style = Some(Name("MonospaceSmall".into()));
egui::ScrollArea::vertical().stick_to_bottom(true).max_width(width).max_height(height).auto_shrink([false; 2]).show_viewport(ui, |ui, _| { egui::ScrollArea::vertical().stick_to_bottom(true).max_width(width).max_height(height).auto_shrink([false; 2]).show_viewport(ui, |ui, _| {
ui.add_sized([width, height], TextEdit::multiline(&mut api.lock().unwrap().output.as_str())); ui.add_sized([width, height], TextEdit::multiline(&mut lock!(api).output.as_str()));
}); });
}); });
//---------------------------------------------------------------------------------------------------- [Advanced] Console //---------------------------------------------------------------------------------------------------- [Advanced] Console
@ -55,7 +56,7 @@ impl crate::disk::P2pool {
egui::Frame::none().fill(DARK_GRAY).show(ui, |ui| { egui::Frame::none().fill(DARK_GRAY).show(ui, |ui| {
ui.style_mut().override_text_style = Some(Name("MonospaceSmall".into())); ui.style_mut().override_text_style = Some(Name("MonospaceSmall".into()));
egui::ScrollArea::vertical().stick_to_bottom(true).max_width(width).max_height(height).auto_shrink([false; 2]).show_viewport(ui, |ui, _| { egui::ScrollArea::vertical().stick_to_bottom(true).max_width(width).max_height(height).auto_shrink([false; 2]).show_viewport(ui, |ui, _| {
ui.add_sized([width, height], TextEdit::multiline(&mut api.lock().unwrap().output.as_str())); ui.add_sized([width, height], TextEdit::multiline(&mut lock!(api).output.as_str()));
}); });
}); });
ui.separator(); ui.separator();
@ -64,7 +65,7 @@ impl crate::disk::P2pool {
if response.lost_focus() && ui.input().key_pressed(egui::Key::Enter) { if response.lost_focus() && ui.input().key_pressed(egui::Key::Enter) {
response.request_focus(); // Get focus back response.request_focus(); // Get focus back
let buffer = std::mem::take(buffer); // Take buffer let buffer = std::mem::take(buffer); // Take buffer
let mut process = process.lock().unwrap(); // Lock let mut process = lock!(process); // Lock
if process.is_alive() { process.input.push(buffer); } // Push only if alive if process.is_alive() { process.input.push(buffer); } // Push only if alive
} }
} }
@ -122,7 +123,7 @@ impl crate::disk::P2pool {
// Two atomic bools = enough to represent this data // Two atomic bools = enough to represent this data
debug!("P2Pool Tab | Running [auto-select] check"); debug!("P2Pool Tab | Running [auto-select] check");
if self.auto_select { if self.auto_select {
let mut ping = ping.lock().unwrap(); let mut ping = lock!(ping);
// If we haven't auto_selected yet, auto-select and turn it off // If we haven't auto_selected yet, auto-select and turn it off
if ping.pinged && !ping.auto_selected { if ping.pinged && !ping.auto_selected {
self.node = ping.fastest; self.node = ping.fastest;
@ -139,8 +140,8 @@ impl crate::disk::P2pool {
let ip = enum_to_ip(id); let ip = enum_to_ip(id);
let mut ms = 0; let mut ms = 0;
let mut color = Color32::LIGHT_GRAY; let mut color = Color32::LIGHT_GRAY;
if ping.lock().unwrap().pinged { if lock!(ping).pinged {
for data in ping.lock().unwrap().nodes.iter() { for data in lock!(ping).nodes.iter() {
if data.id == id { if data.id == id {
ms = data.ms; ms = data.ms;
color = data.color; color = data.color;
@ -151,7 +152,7 @@ impl crate::disk::P2pool {
debug!("P2Pool Tab | Rendering [ComboBox] of Community Nodes"); debug!("P2Pool Tab | Rendering [ComboBox] of Community Nodes");
let text = RichText::new(format!("{}ms | {} | {}", ms, id, ip)).color(color); 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| { 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() { for data in lock!(ping).nodes.iter() {
let ms = crate::node::format_ms(data.ms); let ms = crate::node::format_ms(data.ms);
let id = crate::node::format_enum(data.id); let id = crate::node::format_enum(data.id);
let text = RichText::text_style(RichText::new(format!("{} | {} | {}", ms, id, data.ip)).color(data.color), Monospace); let text = RichText::text_style(RichText::new(format!("{} | {} | {}", ms, id, data.ip)).color(data.color), Monospace);
@ -170,18 +171,18 @@ impl crate::disk::P2pool {
self.node = NodeEnum::get_random(&self.node); self.node = NodeEnum::get_random(&self.node);
} }
// [Select fastest node] // [Select fastest node]
if ui.add_sized([width, height], Button::new("Select fastest node")).on_hover_text(P2POOL_SELECT_FASTEST).clicked() && ping.lock().unwrap().pinged { if ui.add_sized([width, height], Button::new("Select fastest node")).on_hover_text(P2POOL_SELECT_FASTEST).clicked() && lock!(ping).pinged {
self.node = ping.lock().unwrap().fastest; self.node = lock!(ping).fastest;
} }
// [Ping Button] // [Ping Button]
ui.add_enabled_ui(!ping.lock().unwrap().pinging, |ui| { ui.add_enabled_ui(!lock!(ping).pinging, |ui| {
if ui.add_sized([width, height], Button::new("Ping community nodes")).on_hover_text(P2POOL_PING).clicked() { if ui.add_sized([width, height], Button::new("Ping community nodes")).on_hover_text(P2POOL_PING).clicked() {
Ping::spawn_thread(ping); Ping::spawn_thread(ping);
} }
}); });
// [Last <-] // [Last <-]
if ui.add_sized([width, height], Button::new("⬅ Last")).on_hover_text(P2POOL_SELECT_LAST).clicked() { if ui.add_sized([width, height], Button::new("⬅ Last")).on_hover_text(P2POOL_SELECT_LAST).clicked() {
let ping = ping.lock().unwrap(); let ping = lock!(ping);
match ping.pinged { match ping.pinged {
true => self.node = NodeEnum::get_last_from_ping(&self.node, &ping.nodes), true => self.node = NodeEnum::get_last_from_ping(&self.node, &ping.nodes),
false => self.node = NodeEnum::get_last(&self.node), false => self.node = NodeEnum::get_last(&self.node),
@ -190,7 +191,7 @@ impl crate::disk::P2pool {
} }
// [Next ->] // [Next ->]
if ui.add_sized([width, height], Button::new("Next ➡")).on_hover_text(P2POOL_SELECT_NEXT).clicked() { if ui.add_sized([width, height], Button::new("Next ➡")).on_hover_text(P2POOL_SELECT_NEXT).clicked() {
let ping = ping.lock().unwrap(); let ping = lock!(ping);
match ping.pinged { match ping.pinged {
true => self.node = NodeEnum::get_next_from_ping(&self.node, &ping.nodes), true => self.node = NodeEnum::get_next_from_ping(&self.node, &ping.nodes),
false => self.node = NodeEnum::get_next(&self.node), false => self.node = NodeEnum::get_next(&self.node),
@ -201,10 +202,10 @@ impl crate::disk::P2pool {
ui.vertical(|ui| { ui.vertical(|ui| {
let height = height / 2.0; let height = height / 2.0;
let pinging = ping.lock().unwrap().pinging; let pinging = lock!(ping).pinging;
ui.set_enabled(pinging); ui.set_enabled(pinging);
let prog = ping.lock().unwrap().prog.round(); let prog = lock!(ping).prog.round();
let msg = RichText::text_style(RichText::new(format!("{} ... {}%", ping.lock().unwrap().msg, prog)), Monospace); let msg = RichText::text_style(RichText::new(format!("{} ... {}%", lock!(ping).msg, prog)), Monospace);
let height = height / 1.25; let height = height / 1.25;
ui.add_space(5.0); ui.add_space(5.0);
ui.add_sized([width, height], Label::new(msg)); ui.add_sized([width, height], Label::new(msg));

View file

@ -24,6 +24,7 @@ use crate::{
Sys, Sys,
Hash, Hash,
Submenu, Submenu,
macros::*,
}; };
use std::sync::{Arc,Mutex}; use std::sync::{Arc,Mutex};
use log::*; use log::*;
@ -47,7 +48,7 @@ pub fn show(&mut self, sys: &Arc<Mutex<Sys>>, p2pool_api: &Arc<Mutex<PubP2poolAp
ui.set_min_height(min_height); ui.set_min_height(min_height);
ui.add_sized([width, height], Label::new(RichText::new("[Gupax]").color(LIGHT_GRAY).text_style(TextStyle::Name("MonospaceLarge".into())))).on_hover_text("Gupax is online"); ui.add_sized([width, height], Label::new(RichText::new("[Gupax]").color(LIGHT_GRAY).text_style(TextStyle::Name("MonospaceLarge".into())))).on_hover_text("Gupax is online");
ui.style_mut().override_text_style = Some(Monospace); ui.style_mut().override_text_style = Some(Monospace);
let sys = sys.lock().unwrap(); let sys = lock!(sys);
ui.add_sized([width, height], Label::new(RichText::new("Uptime").underline().color(BONE))).on_hover_text(STATUS_GUPAX_UPTIME); ui.add_sized([width, height], Label::new(RichText::new("Uptime").underline().color(BONE))).on_hover_text(STATUS_GUPAX_UPTIME);
ui.add_sized([width, height], Label::new(sys.gupax_uptime.to_string())); ui.add_sized([width, height], Label::new(sys.gupax_uptime.to_string()));
ui.add_sized([width, height], Label::new(RichText::new("Gupax CPU").underline().color(BONE))).on_hover_text(STATUS_GUPAX_CPU_USAGE); ui.add_sized([width, height], Label::new(RichText::new("Gupax CPU").underline().color(BONE))).on_hover_text(STATUS_GUPAX_CPU_USAGE);
@ -70,7 +71,7 @@ pub fn show(&mut self, sys: &Arc<Mutex<Sys>>, p2pool_api: &Arc<Mutex<PubP2poolAp
ui.add_sized([width, height], 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"); ui.add_sized([width, height], 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");
let height = height/1.4; let height = height/1.4;
ui.style_mut().override_text_style = Some(Name("MonospaceSmall".into())); ui.style_mut().override_text_style = Some(Name("MonospaceSmall".into()));
let api = p2pool_api.lock().unwrap(); let api = lock!(p2pool_api);
ui.add_sized([width, height], Label::new(RichText::new("Uptime").underline().color(BONE))).on_hover_text(STATUS_P2POOL_UPTIME); ui.add_sized([width, height], Label::new(RichText::new("Uptime").underline().color(BONE))).on_hover_text(STATUS_P2POOL_UPTIME);
ui.add_sized([width, height], Label::new(format!("{}", api.uptime))); ui.add_sized([width, height], Label::new(format!("{}", api.uptime)));
ui.add_sized([width, height], Label::new(RichText::new("Shares Found").underline().color(BONE))).on_hover_text(STATUS_P2POOL_SHARES); ui.add_sized([width, height], Label::new(RichText::new("Shares Found").underline().color(BONE))).on_hover_text(STATUS_P2POOL_SHARES);
@ -87,7 +88,7 @@ pub fn show(&mut self, sys: &Arc<Mutex<Sys>>, p2pool_api: &Arc<Mutex<PubP2poolAp
ui.add_sized([width, height], Label::new(format!("{}", api.connections))); ui.add_sized([width, height], Label::new(format!("{}", api.connections)));
ui.add_sized([width, height], Label::new(RichText::new("Effort").underline().color(BONE))).on_hover_text(STATUS_P2POOL_EFFORT); ui.add_sized([width, height], Label::new(RichText::new("Effort").underline().color(BONE))).on_hover_text(STATUS_P2POOL_EFFORT);
ui.add_sized([width, height], Label::new(format!("[Average: {}] [Current: {}]", api.average_effort, api.current_effort))); ui.add_sized([width, height], Label::new(format!("[Average: {}] [Current: {}]", api.average_effort, api.current_effort)));
let img = p2pool_img.lock().unwrap(); let img = lock!(p2pool_img);
ui.add_sized([width, height], Label::new(RichText::new("Monero Node").underline().color(BONE))).on_hover_text(STATUS_P2POOL_MONERO_NODE); ui.add_sized([width, height], Label::new(RichText::new("Monero Node").underline().color(BONE))).on_hover_text(STATUS_P2POOL_MONERO_NODE);
ui.add_sized([width, height], Label::new(format!("[IP: {}]\n[RPC: {}] [ZMQ: {}]", &img.host, &img.rpc, &img.zmq))); ui.add_sized([width, height], Label::new(format!("[IP: {}]\n[RPC: {}] [ZMQ: {}]", &img.host, &img.rpc, &img.zmq)));
ui.add_sized([width, height], Label::new(RichText::new("Sidechain").underline().color(BONE))).on_hover_text(STATUS_P2POOL_POOL); ui.add_sized([width, height], Label::new(RichText::new("Sidechain").underline().color(BONE))).on_hover_text(STATUS_P2POOL_POOL);
@ -104,7 +105,7 @@ pub fn show(&mut self, sys: &Arc<Mutex<Sys>>, p2pool_api: &Arc<Mutex<PubP2poolAp
ui.set_min_height(min_height); ui.set_min_height(min_height);
ui.add_sized([width, height], 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"); ui.add_sized([width, height], 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");
ui.style_mut().override_text_style = Some(Monospace); ui.style_mut().override_text_style = Some(Monospace);
let api = xmrig_api.lock().unwrap(); let api = lock!(xmrig_api);
ui.add_sized([width, height], Label::new(RichText::new("Uptime").underline().color(BONE))).on_hover_text(STATUS_XMRIG_UPTIME); ui.add_sized([width, height], Label::new(RichText::new("Uptime").underline().color(BONE))).on_hover_text(STATUS_XMRIG_UPTIME);
ui.add_sized([width, height], Label::new(format!("{}", api.uptime))); ui.add_sized([width, height], Label::new(format!("{}", api.uptime)));
ui.add_sized([width, height], Label::new(RichText::new("CPU Load Averages").underline().color(BONE))).on_hover_text(STATUS_XMRIG_CPU); ui.add_sized([width, height], Label::new(RichText::new("CPU Load Averages").underline().color(BONE))).on_hover_text(STATUS_XMRIG_CPU);
@ -116,9 +117,9 @@ pub fn show(&mut self, sys: &Arc<Mutex<Sys>>, p2pool_api: &Arc<Mutex<PubP2poolAp
ui.add_sized([width, height], Label::new(RichText::new("Shares").underline().color(BONE))).on_hover_text(STATUS_XMRIG_SHARES); ui.add_sized([width, height], Label::new(RichText::new("Shares").underline().color(BONE))).on_hover_text(STATUS_XMRIG_SHARES);
ui.add_sized([width, height], Label::new(format!("[Accepted: {}] [Rejected: {}]", api.accepted, api.rejected))); ui.add_sized([width, height], Label::new(format!("[Accepted: {}] [Rejected: {}]", api.accepted, api.rejected)));
ui.add_sized([width, height], Label::new(RichText::new("Pool").underline().color(BONE))).on_hover_text(STATUS_XMRIG_POOL); ui.add_sized([width, height], Label::new(RichText::new("Pool").underline().color(BONE))).on_hover_text(STATUS_XMRIG_POOL);
ui.add_sized([width, height], Label::new(&xmrig_img.lock().unwrap().url)); ui.add_sized([width, height], Label::new(&lock!(xmrig_img).url));
ui.add_sized([width, height], Label::new(RichText::new("Threads").underline().color(BONE))).on_hover_text(STATUS_XMRIG_THREADS); ui.add_sized([width, height], Label::new(RichText::new("Threads").underline().color(BONE))).on_hover_text(STATUS_XMRIG_THREADS);
ui.add_sized([width, height], Label::new(format!("{}/{}", &xmrig_img.lock().unwrap().threads, max_threads))); ui.add_sized([width, height], Label::new(format!("{}/{}", &lock!(xmrig_img).threads, max_threads)));
drop(api); drop(api);
})}); })});
}); });

View file

@ -32,6 +32,7 @@ use crate::{
disk::Xmrig, disk::Xmrig,
ProcessSignal, ProcessSignal,
constants::*, constants::*,
macros::*,
}; };
use log::*; use log::*;
@ -81,7 +82,7 @@ impl SudoState {
// Resets the state. // Resets the state.
pub fn reset(state: &Arc<Mutex<Self>>) { pub fn reset(state: &Arc<Mutex<Self>>) {
Self::wipe(state); Self::wipe(state);
let mut state = state.lock().unwrap(); let mut state = lock!(state);
state.testing = false; state.testing = false;
state.success = false; state.success = false;
// state.signal = ProcessSignal::None; // state.signal = ProcessSignal::None;
@ -92,7 +93,7 @@ impl SudoState {
pub fn wipe(state: &Arc<Mutex<Self>>) { pub fn wipe(state: &Arc<Mutex<Self>>) {
let mut new = String::with_capacity(256); let mut new = String::with_capacity(256);
// new is now == old, and vice-versa. // new is now == old, and vice-versa.
std::mem::swap(&mut new, &mut state.lock().unwrap().pass); std::mem::swap(&mut new, &mut lock!(state).pass);
// we're wiping & dropping the old pass here. // we're wiping & dropping the old pass here.
new.zeroize(); new.zeroize();
std::mem::drop(new); std::mem::drop(new);
@ -108,7 +109,7 @@ impl SudoState {
let path = path.clone(); let path = path.clone();
thread::spawn(move || { thread::spawn(move || {
// Set to testing // Set to testing
state.lock().unwrap().testing = true; lock!(state).testing = true;
// Make sure sudo timestamp is reset // Make sure sudo timestamp is reset
let reset = Command::new("sudo") let reset = Command::new("sudo")
@ -122,8 +123,8 @@ impl SudoState {
Err(e) => { Err(e) => {
error!("Sudo | Couldn't reset timestamp: {}", e); error!("Sudo | Couldn't reset timestamp: {}", e);
Self::wipe(&state); Self::wipe(&state);
state.lock().unwrap().msg = format!("Sudo error: {}", e); lock!(state).msg = format!("Sudo error: {}", e);
state.lock().unwrap().testing = false; lock!(state).testing = false;
return return
}, },
} }
@ -139,7 +140,7 @@ impl SudoState {
// Write pass to STDIN // Write pass to STDIN
let mut stdin = sudo.stdin.take().unwrap(); let mut stdin = sudo.stdin.take().unwrap();
stdin.write_all(state.lock().unwrap().pass.as_bytes()).unwrap(); stdin.write_all(lock!(state).pass.as_bytes()).unwrap();
drop(stdin); drop(stdin);
// Sudo re-prompts and will hang. // Sudo re-prompts and will hang.
@ -149,7 +150,7 @@ impl SudoState {
match sudo.try_wait() { match sudo.try_wait() {
Ok(Some(code)) => if code.success() { Ok(Some(code)) => if code.success() {
info!("Sudo | Password ... OK!"); info!("Sudo | Password ... OK!");
state.lock().unwrap().success = true; lock!(state).success = true;
break break
}, },
Ok(None) => { Ok(None) => {
@ -159,25 +160,25 @@ impl SudoState {
Err(e) => { Err(e) => {
error!("Sudo | Couldn't reset timestamp: {}", e); error!("Sudo | Couldn't reset timestamp: {}", e);
Self::wipe(&state); Self::wipe(&state);
state.lock().unwrap().msg = format!("Sudo error: {}", e); lock!(state).msg = format!("Sudo error: {}", e);
state.lock().unwrap().testing = false; lock!(state).testing = false;
return return
}, },
} }
} }
if let Err(e) = sudo.kill() { warn!("Sudo | Kill error (it probably already exited): {}", e); } if let Err(e) = sudo.kill() { warn!("Sudo | Kill error (it probably already exited): {}", e); }
if state.lock().unwrap().success { if lock!(state).success {
match state.lock().unwrap().signal { match lock!(state).signal {
ProcessSignal::Restart => crate::helper::Helper::restart_xmrig(&helper, &xmrig, &path, Arc::clone(&state)), ProcessSignal::Restart => crate::helper::Helper::restart_xmrig(&helper, &xmrig, &path, Arc::clone(&state)),
ProcessSignal::Stop => crate::helper::Helper::stop_xmrig(&helper), ProcessSignal::Stop => crate::helper::Helper::stop_xmrig(&helper),
_ => crate::helper::Helper::start_xmrig(&helper, &xmrig, &path, Arc::clone(&state)), _ => crate::helper::Helper::start_xmrig(&helper, &xmrig, &path, Arc::clone(&state)),
} }
} else { } else {
state.lock().unwrap().msg = "Incorrect password! (or sudo timeout)".to_string(); lock!(state).msg = "Incorrect password! (or sudo timeout)".to_string();
Self::wipe(&state); Self::wipe(&state);
} }
state.lock().unwrap().signal = ProcessSignal::None; lock!(state).signal = ProcessSignal::None;
state.lock().unwrap().testing = false; lock!(state).testing = false;
}); });
} }
} }

View file

@ -33,6 +33,7 @@ use crate::{
update::Name::*, update::Name::*,
ErrorState,ErrorFerris,ErrorButtons, ErrorState,ErrorFerris,ErrorButtons,
Restart, Restart,
macros::*,
}; };
use hyper::{ use hyper::{
Client,Body,Request, Client,Body,Request,
@ -265,9 +266,9 @@ impl Update {
path_p2pool: path_p2pool.display().to_string(), path_p2pool: path_p2pool.display().to_string(),
path_xmrig: path_xmrig.display().to_string(), path_xmrig: path_xmrig.display().to_string(),
tmp_dir: "".to_string(), tmp_dir: "".to_string(),
updating: Arc::new(Mutex::new(false)), updating: arc_mut!(false),
prog: Arc::new(Mutex::new(0.0)), prog: arc_mut!(0.0),
msg: Arc::new(Mutex::new(MSG_NONE.to_string())), msg: arc_mut!(MSG_NONE.to_string()),
tor, tor,
} }
} }
@ -392,13 +393,13 @@ impl Update {
return; return;
} }
update.lock().unwrap().path_p2pool = p2pool_path.display().to_string(); lock!(update).path_p2pool = p2pool_path.display().to_string();
update.lock().unwrap().path_xmrig = xmrig_path.display().to_string(); lock!(update).path_xmrig = xmrig_path.display().to_string();
update.lock().unwrap().tor = gupax.update_via_tor; lock!(update).tor = gupax.update_via_tor;
// Clone before thread spawn // Clone before thread spawn
let og = Arc::clone(og); let og = Arc::clone(og);
let state_ver = Arc::clone(&og.lock().unwrap().version); let state_ver = Arc::clone(&lock!(og).version);
let state_path = state_path.to_path_buf(); let state_path = state_path.to_path_buf();
let update = Arc::clone(update); let update = Arc::clone(update);
let restart = Arc::clone(restart); let restart = Arc::clone(restart);
@ -407,23 +408,23 @@ impl Update {
match Update::start(update.clone(), og.clone(), state_ver.clone(), restart) { match Update::start(update.clone(), og.clone(), state_ver.clone(), restart) {
Ok(_) => { Ok(_) => {
info!("Update | Saving state..."); info!("Update | Saving state...");
let original_version = og.lock().unwrap().version.clone(); let original_version = lock!(og).version.clone();
og.lock().unwrap().version = state_ver; lock!(og).version = state_ver;
match State::save(&mut og.lock().unwrap(), &state_path) { match State::save(&mut lock!(og), &state_path) {
Ok(_) => info!("Update ... OK"), Ok(_) => info!("Update ... OK"),
Err(e) => { Err(e) => {
warn!("Update | Saving state ... FAIL: {}", e); warn!("Update | Saving state ... FAIL: {}", e);
og.lock().unwrap().version = original_version; lock!(og).version = original_version;
*update.lock().unwrap().msg.lock().unwrap() = "Saving new versions into state failed".to_string(); *lock2!(update,msg) = "Saving new versions into state failed".to_string();
}, },
}; };
} }
Err(e) => { Err(e) => {
info!("Update ... FAIL: {}", e); info!("Update ... FAIL: {}", e);
*update.lock().unwrap().msg.lock().unwrap() = format!("{} | {}", MSG_FAILED, e); *lock2!(update,msg) = format!("{} | {}", MSG_FAILED, e);
}, },
}; };
*update.lock().unwrap().updating.lock().unwrap() = false; *lock2!(update,updating) = false;
}); });
} }
@ -442,19 +443,19 @@ impl Update {
return Err(anyhow!("This is the [Linux distro] version of Gupax, updates are disabled")); return Err(anyhow!("This is the [Linux distro] version of Gupax, updates are disabled"));
//---------------------------------------------------------------------------------------------------- Init //---------------------------------------------------------------------------------------------------- Init
*update.lock().unwrap().updating.lock().unwrap() = true; *lock2!(update,updating) = true;
// Set timer // Set timer
let now = std::time::Instant::now(); let now = std::time::Instant::now();
// Set progress bar // Set progress bar
*update.lock().unwrap().msg.lock().unwrap() = MSG_START.to_string(); *lock2!(update,msg) = MSG_START.to_string();
*update.lock().unwrap().prog.lock().unwrap() = 0.0; *lock2!(update,prog) = 0.0;
info!("Update | {}", INIT); info!("Update | {}", INIT);
// Get temporary directory // Get temporary directory
let msg = MSG_TMP.to_string(); let msg = MSG_TMP.to_string();
info!("Update | {}", msg); info!("Update | {}", msg);
*update.lock().unwrap().msg.lock().unwrap() = msg; *lock2!(update,msg) = msg;
let tmp_dir = Self::get_tmp_dir()?; let tmp_dir = Self::get_tmp_dir()?;
std::fs::create_dir(&tmp_dir)?; std::fs::create_dir(&tmp_dir)?;
@ -467,27 +468,27 @@ impl Update {
// Generate fake user-agent // Generate fake user-agent
let user_agent = Pkg::get_user_agent(); let user_agent = Pkg::get_user_agent();
*update.lock().unwrap().prog.lock().unwrap() = 5.0; *lock2!(update,prog) = 5.0;
// Create Tor/HTTPS client // Create Tor/HTTPS client
let lock = update.lock().unwrap(); let lock = lock!(update);
let tor = lock.tor; let tor = lock.tor;
if tor { if tor {
let msg = MSG_TOR.to_string(); let msg = MSG_TOR.to_string();
info!("Update | {}", msg); info!("Update | {}", msg);
*lock.msg.lock().unwrap() = msg; *lock!(lock.msg) = msg;
} else { } else {
let msg = MSG_HTTPS.to_string(); let msg = MSG_HTTPS.to_string();
info!("Update | {}", msg); info!("Update | {}", msg);
*lock.msg.lock().unwrap() = msg; *lock!(lock.msg) = msg;
} }
drop(lock); drop(lock);
let mut client = Self::get_client(tor)?; let mut client = Self::get_client(tor)?;
*update.lock().unwrap().prog.lock().unwrap() += 5.0; *lock2!(update,prog) += 5.0;
info!("Update | Init ... OK ... {}%", update.lock().unwrap().prog.lock().unwrap()); info!("Update | Init ... OK ... {}%", lock2!(update,prog));
//---------------------------------------------------------------------------------------------------- Metadata //---------------------------------------------------------------------------------------------------- Metadata
*update.lock().unwrap().msg.lock().unwrap() = MSG_METADATA.to_string(); *lock2!(update,msg) = MSG_METADATA.to_string();
info!("Update | {}", METADATA); info!("Update | {}", METADATA);
let mut vec2 = vec![]; let mut vec2 = vec![];
// Loop process: // Loop process:
@ -502,7 +503,7 @@ impl Update {
// function itself but for some reason, it was getting skipped over, // function itself but for some reason, it was getting skipped over,
// so the [new_ver] check is now here, in the outer scope. // so the [new_ver] check is now here, in the outer scope.
for i in 1..=3 { for i in 1..=3 {
if i > 1 { *update.lock().unwrap().msg.lock().unwrap() = format!("{} [{}/3]", MSG_METADATA_RETRY, i); } if i > 1 { *lock2!(update,msg) = format!("{} [{}/3]", MSG_METADATA_RETRY, i); }
let mut handles: Vec<JoinHandle<Result<(), anyhow::Error>>> = vec![]; let mut handles: Vec<JoinHandle<Result<(), anyhow::Error>>> = vec![];
for pkg in vec.iter() { for pkg in vec.iter() {
// Clone data before sending to async // Clone data before sending to async
@ -528,13 +529,13 @@ impl Update {
// Check for empty version // Check for empty version
let mut indexes = vec![]; let mut indexes = vec![];
for (index, pkg) in vec.iter().enumerate() { for (index, pkg) in vec.iter().enumerate() {
if pkg.new_ver.lock().unwrap().is_empty() { if lock!(pkg.new_ver).is_empty() {
warn!("Update | {} failed, attempt [{}/3]...", pkg.name, i+1); warn!("Update | {} failed, attempt [{}/3]...", pkg.name, i+1);
} else { } else {
indexes.push(index); indexes.push(index);
vec2.push(pkg.clone()); vec2.push(pkg.clone());
*update.lock().unwrap().prog.lock().unwrap() += 10.0; *lock2!(update,prog) += 10.0;
info!("Update | {} {} ... OK", pkg.name, pkg.new_ver.lock().unwrap()); info!("Update | {} {} ... OK", pkg.name, lock!(pkg.new_ver));
} }
} }
// Order indexes from biggest to smallest // Order indexes from biggest to smallest
@ -553,19 +554,19 @@ impl Update {
} }
} }
if vec.is_empty() { if vec.is_empty() {
info!("Update | Metadata ... OK ... {}%", update.lock().unwrap().prog.lock().unwrap()); info!("Update | Metadata ... OK ... {}%", lock2!(update,prog));
} else { } else {
error!("Update | Metadata ... FAIL"); error!("Update | Metadata ... FAIL");
return Err(anyhow!("Metadata fetch failed")) return Err(anyhow!("Metadata fetch failed"))
} }
//---------------------------------------------------------------------------------------------------- Compare //---------------------------------------------------------------------------------------------------- Compare
*update.lock().unwrap().msg.lock().unwrap() = MSG_COMPARE.to_string(); *lock2!(update,msg) = MSG_COMPARE.to_string();
info!("Update | {}", COMPARE); info!("Update | {}", COMPARE);
let mut vec3 = vec![]; let mut vec3 = vec![];
let mut new_pkgs = vec![]; let mut new_pkgs = vec![];
for pkg in vec2.iter() { for pkg in vec2.iter() {
let new_ver = pkg.new_ver.lock().unwrap().clone(); let new_ver = lock!(pkg.new_ver).clone();
let diff; let diff;
let old_ver; let old_ver;
let name; let name;
@ -575,17 +576,17 @@ impl Update {
// that gets updated during an update. This prevents the updater always thinking // that gets updated during an update. This prevents the updater always thinking
// there's a new Gupax update since the user didnt restart and is still technically // there's a new Gupax update since the user didnt restart and is still technically
// using the old version (even though the underlying binary was updated). // using the old version (even though the underlying binary was updated).
old_ver = state_ver.lock().unwrap().gupax.clone(); old_ver = lock!(state_ver).gupax.clone();
diff = old_ver != new_ver && GUPAX_VERSION != new_ver; diff = old_ver != new_ver && GUPAX_VERSION != new_ver;
name = "Gupax"; name = "Gupax";
} }
P2pool => { P2pool => {
old_ver = state_ver.lock().unwrap().p2pool.clone(); old_ver = lock!(state_ver).p2pool.clone();
diff = old_ver != new_ver; diff = old_ver != new_ver;
name = "P2Pool"; name = "P2Pool";
} }
Xmrig => { Xmrig => {
old_ver = state_ver.lock().unwrap().xmrig.clone(); old_ver = lock!(state_ver).xmrig.clone();
diff = old_ver != new_ver; diff = old_ver != new_ver;
name = "XMRig"; name = "XMRig";
} }
@ -598,32 +599,32 @@ impl Update {
info!("Update | {} {} == {} ... SKIPPING", pkg.name, old_ver, new_ver); info!("Update | {} {} == {} ... SKIPPING", pkg.name, old_ver, new_ver);
} }
} }
*update.lock().unwrap().prog.lock().unwrap() += 5.0; *lock2!(update,prog) += 5.0;
info!("Update | Compare ... OK ... {}%", update.lock().unwrap().prog.lock().unwrap()); info!("Update | Compare ... OK ... {}%", lock2!(update,prog));
// Return if 0 (all packages up-to-date) // Return if 0 (all packages up-to-date)
// Get amount of packages to divide up the percentage increases // Get amount of packages to divide up the percentage increases
let pkg_amount = vec3.len() as f32; let pkg_amount = vec3.len() as f32;
if pkg_amount == 0.0 { if pkg_amount == 0.0 {
info!("Update | All packages up-to-date ... RETURNING"); info!("Update | All packages up-to-date ... RETURNING");
*update.lock().unwrap().prog.lock().unwrap() = 100.0; *lock2!(update,prog) = 100.0;
*update.lock().unwrap().msg.lock().unwrap() = MSG_UP_TO_DATE.to_string(); *lock2!(update,msg) = MSG_UP_TO_DATE.to_string();
return Ok(()) return Ok(())
} }
let new_pkgs: String = new_pkgs.concat(); let new_pkgs: String = new_pkgs.concat();
//---------------------------------------------------------------------------------------------------- Download //---------------------------------------------------------------------------------------------------- Download
*update.lock().unwrap().msg.lock().unwrap() = format!("{}{}", MSG_DOWNLOAD, new_pkgs); *lock2!(update,msg) = format!("{}{}", MSG_DOWNLOAD, new_pkgs);
info!("Update | {}", DOWNLOAD); info!("Update | {}", DOWNLOAD);
let mut vec4 = vec![]; let mut vec4 = vec![];
for i in 1..=3 { for i in 1..=3 {
if i > 1 { *update.lock().unwrap().msg.lock().unwrap() = format!("{} [{}/3]{}", MSG_DOWNLOAD_RETRY, i, new_pkgs); } if i > 1 { *lock2!(update,msg) = format!("{} [{}/3]{}", MSG_DOWNLOAD_RETRY, i, new_pkgs); }
let mut handles: Vec<JoinHandle<Result<(), anyhow::Error>>> = vec![]; let mut handles: Vec<JoinHandle<Result<(), anyhow::Error>>> = vec![];
for pkg in vec3.iter() { for pkg in vec3.iter() {
// Clone data before async // Clone data before async
let bytes = Arc::clone(&pkg.bytes); let bytes = Arc::clone(&pkg.bytes);
let client = client.clone(); let client = client.clone();
let version = pkg.new_ver.lock().unwrap(); let version = lock!(pkg.new_ver);
// Download link = PREFIX + Version (found at runtime) + SUFFIX + Version + EXT // Download link = PREFIX + Version (found at runtime) + SUFFIX + Version + EXT
// Example: https://github.com/hinto-janaiyo/gupax/releases/download/v0.0.1/gupax-v0.0.1-linux-x64-standalone // Example: https://github.com/hinto-janaiyo/gupax/releases/download/v0.0.1/gupax-v0.0.1-linux-x64-standalone
// XMRig doesn't have a [v], so slice it out // XMRig doesn't have a [v], so slice it out
@ -647,12 +648,12 @@ impl Update {
// Check for empty bytes // Check for empty bytes
let mut indexes = vec![]; let mut indexes = vec![];
for (index, pkg) in vec3.iter().enumerate() { for (index, pkg) in vec3.iter().enumerate() {
if pkg.bytes.lock().unwrap().is_empty() { if lock!(pkg.bytes).is_empty() {
warn!("Update | {} failed, attempt [{}/3]...", pkg.name, i); warn!("Update | {} failed, attempt [{}/3]...", pkg.name, i);
} else { } else {
indexes.push(index); indexes.push(index);
vec4.push(pkg.clone()); vec4.push(pkg.clone());
*update.lock().unwrap().prog.lock().unwrap() += (30.0 / pkg_amount).round(); *lock2!(update,prog) += (30.0 / pkg_amount).round();
info!("Update | {} ... OK", pkg.name); info!("Update | {} ... OK", pkg.name);
} }
} }
@ -666,14 +667,14 @@ impl Update {
if vec3.is_empty() { break } if vec3.is_empty() { break }
} }
if vec3.is_empty() { if vec3.is_empty() {
info!("Update | Download ... OK ... {}%", *update.lock().unwrap().prog.lock().unwrap()); info!("Update | Download ... OK ... {}%", *lock2!(update,prog));
} else { } else {
error!("Update | Download ... FAIL"); error!("Update | Download ... FAIL");
return Err(anyhow!("Download failed")) return Err(anyhow!("Download failed"))
} }
//---------------------------------------------------------------------------------------------------- Extract //---------------------------------------------------------------------------------------------------- Extract
*update.lock().unwrap().msg.lock().unwrap() = format!("{}{}", MSG_EXTRACT, new_pkgs); *lock2!(update,msg) = format!("{}{}", MSG_EXTRACT, new_pkgs);
info!("Update | {}", EXTRACT); info!("Update | {}", EXTRACT);
for pkg in vec4.iter() { for pkg in vec4.iter() {
let tmp = match pkg.name { let tmp = match pkg.name {
@ -681,20 +682,20 @@ impl Update {
_ => tmp_dir.to_owned() + &pkg.name.to_string(), _ => tmp_dir.to_owned() + &pkg.name.to_string(),
}; };
#[cfg(target_os = "windows")] #[cfg(target_os = "windows")]
ZipArchive::extract(&mut ZipArchive::new(std::io::Cursor::new(pkg.bytes.lock().unwrap().as_ref()))?, tmp)?; ZipArchive::extract(&mut ZipArchive::new(std::io::Cursor::new(lock!(pkg.bytes).as_ref()))?, tmp)?;
#[cfg(target_family = "unix")] #[cfg(target_family = "unix")]
tar::Archive::new(flate2::read::GzDecoder::new(pkg.bytes.lock().unwrap().as_ref())).unpack(tmp)?; tar::Archive::new(flate2::read::GzDecoder::new(lock!(pkg.bytes).as_ref())).unpack(tmp)?;
*update.lock().unwrap().prog.lock().unwrap() += (5.0 / pkg_amount).round(); *lock2!(update,prog) += (5.0 / pkg_amount).round();
info!("Update | {} ... OK", pkg.name); info!("Update | {} ... OK", pkg.name);
} }
info!("Update | Extract ... OK ... {}%", *update.lock().unwrap().prog.lock().unwrap()); info!("Update | Extract ... OK ... {}%", *lock2!(update,prog));
//---------------------------------------------------------------------------------------------------- Upgrade //---------------------------------------------------------------------------------------------------- Upgrade
// 1. Walk directories // 1. Walk directories
// 2. If basename matches known binary name, start // 2. If basename matches known binary name, start
// 3. Rename tmp path into current path // 3. Rename tmp path into current path
// 4. Update [State/Version] // 4. Update [State/Version]
*update.lock().unwrap().msg.lock().unwrap() = format!("{}{}", MSG_UPGRADE, new_pkgs); *lock2!(update,msg) = format!("{}{}", MSG_UPGRADE, new_pkgs);
info!("Update | {}", UPGRADE); info!("Update | {}", UPGRADE);
// If this bool doesn't get set, something has gone wrong because // If this bool doesn't get set, something has gone wrong because
// we _didn't_ find a binary even though we downloaded it. // we _didn't_ find a binary even though we downloaded it.
@ -715,9 +716,9 @@ impl Update {
_ => Xmrig, _ => Xmrig,
}; };
let path = match name { let path = match name {
Gupax => update.lock().unwrap().path_gupax.clone(), Gupax => lock!(update).path_gupax.clone(),
P2pool => update.lock().unwrap().path_p2pool.clone(), P2pool => lock!(update).path_p2pool.clone(),
Xmrig => update.lock().unwrap().path_xmrig.clone(), Xmrig => lock!(update).path_xmrig.clone(),
}; };
let path = Path::new(&path); let path = Path::new(&path);
// Unix can replace running binaries no problem (they're loaded into memory) // Unix can replace running binaries no problem (they're loaded into memory)
@ -745,14 +746,14 @@ impl Update {
// Update [State] version // Update [State] version
match name { match name {
Gupax => { Gupax => {
state_ver.lock().unwrap().gupax = Pkg::get_new_pkg_version(Gupax, &vec4)?; lock!(state_ver).gupax = Pkg::get_new_pkg_version(Gupax, &vec4)?;
// If we're updating Gupax, set the [Restart] state so that the user knows to restart // If we're updating Gupax, set the [Restart] state so that the user knows to restart
*restart.lock().unwrap() = Restart::Yes; *lock!(restart) = Restart::Yes;
}, },
P2pool => state_ver.lock().unwrap().p2pool = Pkg::get_new_pkg_version(P2pool, &vec4)?, P2pool => lock!(state_ver).p2pool = Pkg::get_new_pkg_version(P2pool, &vec4)?,
Xmrig => state_ver.lock().unwrap().xmrig = Pkg::get_new_pkg_version(Xmrig, &vec4)?, Xmrig => lock!(state_ver).xmrig = Pkg::get_new_pkg_version(Xmrig, &vec4)?,
}; };
*update.lock().unwrap().prog.lock().unwrap() += (5.0 / pkg_amount).round(); *lock2!(update,prog) += (5.0 / pkg_amount).round();
}, },
_ => (), _ => (),
} }
@ -768,11 +769,11 @@ impl Update {
let seconds = now.elapsed().as_secs(); let seconds = now.elapsed().as_secs();
info!("Update | Seconds elapsed ... [{}s]", seconds); info!("Update | Seconds elapsed ... [{}s]", seconds);
match seconds { match seconds {
0 => *update.lock().unwrap().msg.lock().unwrap() = format!("{}! Took 0 seconds... What...?!{}", MSG_SUCCESS, new_pkgs), 0 => *lock2!(update,msg) = format!("{}! Took 0 seconds... What...?!{}", MSG_SUCCESS, new_pkgs),
1 => *update.lock().unwrap().msg.lock().unwrap() = format!("{}! Took 1 second... Wow!{}", MSG_SUCCESS, new_pkgs), 1 => *lock2!(update,msg) = format!("{}! Took 1 second... Wow!{}", MSG_SUCCESS, new_pkgs),
_ => *update.lock().unwrap().msg.lock().unwrap() = format!("{}! Took {} seconds.{}", MSG_SUCCESS, seconds, new_pkgs), _ => *lock2!(update,msg) = format!("{}! Took {} seconds.{}", MSG_SUCCESS, seconds, new_pkgs),
} }
*update.lock().unwrap().prog.lock().unwrap() = 100.0; *lock2!(update,prog) = 100.0;
Ok(()) Ok(())
} }
} }
@ -823,8 +824,8 @@ impl Pkg {
link_prefix, link_prefix,
link_suffix, link_suffix,
link_extension, link_extension,
bytes: Arc::new(Mutex::new(bytes::Bytes::new())), bytes: arc_mut!(bytes::Bytes::new()),
new_ver: Arc::new(Mutex::new(String::new())), new_ver: arc_mut!(String::new()),
} }
} }
@ -855,7 +856,7 @@ impl Pkg {
let mut response = client.request(request).await?; let mut response = client.request(request).await?;
let body = hyper::body::to_bytes(response.body_mut()).await?; let body = hyper::body::to_bytes(response.body_mut()).await?;
let body: TagName = serde_json::from_slice(&body)?; let body: TagName = serde_json::from_slice(&body)?;
*new_ver.lock().unwrap() = body.tag_name; *lock!(new_ver) = body.tag_name;
Ok(()) Ok(())
} }
@ -873,7 +874,7 @@ impl Pkg {
response = client.request(request).await?; response = client.request(request).await?;
} }
let body = hyper::body::to_bytes(response.into_body()).await?; let body = hyper::body::to_bytes(response.into_body()).await?;
*bytes.lock().unwrap() = body; *lock!(bytes) = body;
Ok(()) Ok(())
} }
@ -882,7 +883,7 @@ impl Pkg {
fn get_new_pkg_version(name: Name, vec: &[&Pkg]) -> Result<String, Error> { fn get_new_pkg_version(name: Name, vec: &[&Pkg]) -> Result<String, Error> {
for pkg in vec.iter() { for pkg in vec.iter() {
if pkg.name == name { if pkg.name == name {
return Ok(pkg.new_ver.lock().unwrap().to_string()) return Ok(lock!(pkg.new_ver).to_string())
} }
} }
Err(anyhow!("Couldn't find new_pkg_version")) Err(anyhow!("Couldn't find new_pkg_version"))

View file

@ -21,6 +21,7 @@ use crate::{
disk::*, disk::*,
Process, Process,
PubXmrigApi, PubXmrigApi,
macros::*,
}; };
use egui::{ use egui::{
TextEdit,SelectableLabel,ComboBox,Label,Button,RichText,Slider,Checkbox, TextEdit,SelectableLabel,ComboBox,Label,Button,RichText,Slider,Checkbox,
@ -45,7 +46,7 @@ impl crate::disk::Xmrig {
egui::Frame::none().fill(DARK_GRAY).show(ui, |ui| { egui::Frame::none().fill(DARK_GRAY).show(ui, |ui| {
ui.style_mut().override_text_style = Some(Name("MonospaceSmall".into())); ui.style_mut().override_text_style = Some(Name("MonospaceSmall".into()));
egui::ScrollArea::vertical().stick_to_bottom(true).max_width(width).max_height(height).auto_shrink([false; 2]).show_viewport(ui, |ui, _| { egui::ScrollArea::vertical().stick_to_bottom(true).max_width(width).max_height(height).auto_shrink([false; 2]).show_viewport(ui, |ui, _| {
ui.add_sized([width, height], TextEdit::multiline(&mut api.lock().unwrap().output.as_str())); ui.add_sized([width, height], TextEdit::multiline(&mut lock!(api).output.as_str()));
}); });
}); });
//---------------------------------------------------------------------------------------------------- [Advanced] Console //---------------------------------------------------------------------------------------------------- [Advanced] Console
@ -56,7 +57,7 @@ impl crate::disk::Xmrig {
egui::Frame::none().fill(DARK_GRAY).show(ui, |ui| { egui::Frame::none().fill(DARK_GRAY).show(ui, |ui| {
ui.style_mut().override_text_style = Some(Name("MonospaceSmall".into())); ui.style_mut().override_text_style = Some(Name("MonospaceSmall".into()));
egui::ScrollArea::vertical().stick_to_bottom(true).max_width(width).max_height(height).auto_shrink([false; 2]).show_viewport(ui, |ui, _| { egui::ScrollArea::vertical().stick_to_bottom(true).max_width(width).max_height(height).auto_shrink([false; 2]).show_viewport(ui, |ui, _| {
ui.add_sized([width, height], TextEdit::multiline(&mut api.lock().unwrap().output.as_str())); ui.add_sized([width, height], TextEdit::multiline(&mut lock!(api).output.as_str()));
}); });
}); });
ui.separator(); ui.separator();
@ -65,7 +66,7 @@ impl crate::disk::Xmrig {
if response.lost_focus() && ui.input().key_pressed(egui::Key::Enter) { if response.lost_focus() && ui.input().key_pressed(egui::Key::Enter) {
response.request_focus(); // Get focus back response.request_focus(); // Get focus back
let buffer = std::mem::take(buffer); // Take buffer let buffer = std::mem::take(buffer); // Take buffer
let mut process = process.lock().unwrap(); // Lock let mut process = lock!(process); // Lock
if process.is_alive() { process.input.push(buffer); } // Push only if alive if process.is_alive() { process.input.push(buffer); } // Push only if alive
} }
} }