From 989ce8ba1f3915aa54023784683d50977f198152 Mon Sep 17 00:00:00 2001
From: hinto-janaiyo <hinto.janaiyo@protonmail.com>
Date: Wed, 16 Nov 2022 16:07:49 -0500
Subject: [PATCH] p2pool: use [Arc<Mutex<Ping>>] as intermediary for node
 auto-select

---
 src/main.rs   |  9 ++-------
 src/node.rs   | 25 +++++++++++--------------
 src/p2pool.rs | 41 ++++++++++++++++++++++++++++-------------
 3 files changed, 41 insertions(+), 34 deletions(-)

diff --git a/src/main.rs b/src/main.rs
index 589f0d1..6787cf1 100644
--- a/src/main.rs
+++ b/src/main.rs
@@ -35,7 +35,7 @@ use env_logger::{Builder,WriteStyle};
 
 // Regex
 use regex::Regex;
- 
+
 // std
 use std::io::Write;
 use std::process::exit;
@@ -63,13 +63,13 @@ use {ferris::*,constants::*,node::*,disk::*,status::*,update::*};
 pub struct App {
 	// Misc state
 	tab: Tab, // What tab are we on?
-	ping: Arc<Mutex<Ping>>, // Ping data found in [node.rs]
 	width: f32, // Top-level width
 	height: f32, // Top-level height
 	// State
 	og: Arc<Mutex<State>>, // og = Old state to compare against
 	state: State, // state = Working state (current settings)
 	update: Arc<Mutex<Update>>, // State for update data [update.rs]
+	ping: Arc<Mutex<Ping>>, // Ping data found in [node.rs]
 	og_node_vec: Vec<(String, Node)>, // Manual Node database
 	node_vec: Vec<(String, Node)>, // Manual Node database
 	diff: bool, // This bool indicates state changes
@@ -678,11 +678,6 @@ impl eframe::App for App {
 			return
 		}
 
-		// The [P2Pool Node] selection needs to be the same
-		// for both [State] and [Og] because of [Auto-select]
-		// Wrapping [node] within an [Arc<Mutex>] is a lot more work
-		// so sending it into the [Ping] thread is not viable.
-		self.state.p2pool.node = self.og.lock().unwrap().p2pool.node;
 		// Compare [og == state] and the [node_vec] and enable diff if found.
 		// The struct fields are compared directly because [Version]
 		// contains Arc<Mutex>'s that cannot be compared easily.
diff --git a/src/node.rs b/src/node.rs
index dedec61..5756e4d 100644
--- a/src/node.rs
+++ b/src/node.rs
@@ -96,6 +96,7 @@ pub struct Ping {
 	pub msg: String,
 	pub prog: f32,
 	pub pinged: bool,
+	pub auto_selected: bool,
 }
 
 impl Ping {
@@ -107,16 +108,11 @@ impl Ping {
 			msg: "No ping in progress".to_string(),
 			prog: 0.0,
 			pinged: false,
+			auto_selected: true,
 		}
 	}
 }
 
-#[derive(Debug)]
-pub struct PingResult {
-	pub nodes: Vec<NodeData>,
-	pub fastest: NodeEnum,
-}
-
 //---------------------------------------------------------------------------------------------------- IP <-> Enum functions
 // Function for returning IP/Enum
 pub fn ip_to_enum(ip: &'static str) -> NodeEnum {
@@ -317,15 +313,16 @@ pub fn ping(ping: Arc<Mutex<Ping>>, og: Arc<Mutex<State>>) {
 	}
 	let info = format!("Fastest node: {}ms ... {} @ {}", best_ms, fastest, enum_to_ip(fastest));
 	info!("Ping | {}", info);
-	ping.lock().unwrap().nodes = nodes;
-	ping.lock().unwrap().fastest = fastest;
-	ping.lock().unwrap().prog = 100.0;
-	ping.lock().unwrap().msg = info;
-	ping.lock().unwrap().pinging = false;
-	ping.lock().unwrap().pinged = true;
+	let mut guard = ping.lock().unwrap();
+		guard.nodes = nodes;
+		guard.fastest = fastest;
+		guard.prog = 100.0;
+		guard.msg = info;
+		guard.pinging = false;
+		guard.pinged = true;
+		drop(guard);
 	if og.lock().unwrap().p2pool.auto_select {
-		og.lock().unwrap().p2pool.node = fastest;
-		og.lock().unwrap().save();
+		ping.lock().unwrap().auto_selected = false;
 	}
 	info!("Ping ... OK");
 }
diff --git a/src/p2pool.rs b/src/p2pool.rs
index fa7ed02..3fdeba2 100644
--- a/src/p2pool.rs
+++ b/src/p2pool.rs
@@ -84,6 +84,22 @@ impl P2pool {
 		let height = height / 6.0;
 		ui.spacing_mut().slider_width = width - 8.0;
 		ui.spacing_mut().icon_width = width / 25.0;
+
+		// [Auto-select] if we haven't already.
+		// Using [Arc<Mutex<Ping>>] as an intermediary here
+		// saves me the hassle of wrapping [state: State] completely
+		// and [.lock().unwrap()]ing it everywhere.
+		// Two atomic bools = enough to represent this data
+		if self.auto_select {
+			let mut ping = ping.lock().unwrap();
+			// If we haven't auto_selected yet, auto-select and turn it off
+			if ping.auto_selected == false {
+				self.node = ping.fastest;
+				ping.auto_selected = true;
+			}
+			drop(ping);
+		}
+
 		ui.vertical(|ui| {
 		ui.horizontal(|ui| {
 			// [Ping List]
@@ -91,15 +107,17 @@ impl P2pool {
 			let ip = enum_to_ip(id);
 			let mut ms = 0;
 			let mut color = Color32::LIGHT_GRAY;
-			for data in ping.lock().unwrap().nodes.iter() {
-				if data.id == id {
-					ms = data.ms;
-					color = data.color;
-					break
+			if ping.lock().unwrap().pinged {
+				for data in ping.lock().unwrap().nodes.iter() {
+					if data.id == id {
+						ms = data.ms;
+						color = data.color;
+						break
+					}
 				}
 			}
 			let text = RichText::new(format!(" ⏺ {}ms | {} | {}", ms, id, ip)).color(color);
-			ComboBox::from_id_source("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() {
 					let ms = crate::node::format_ms(data.ms);
 					let id = crate::node::format_enum(data.id);
@@ -115,13 +133,11 @@ impl P2pool {
 		let width = (width/2.0)-4.0;
 		// [Select fastest node]
 		if ui.add_sized([width, height], Button::new("Select fastest node")).on_hover_text(P2POOL_SELECT_FASTEST).clicked() {
-			let pinged = ping.lock().unwrap().pinged;
-			let fastest = ping.lock().unwrap().fastest;
-			if pinged && og.lock().unwrap().p2pool.node != fastest {
-				og.lock().unwrap().p2pool.node = ping.lock().unwrap().fastest;
-				og.lock().unwrap().save();
+			if ping.lock().unwrap().pinged {
+				self.node = ping.lock().unwrap().fastest;
 			}
 		}
+
 		// [Ping Button]
 		ui.set_enabled(!ping.lock().unwrap().pinging);
 		if ui.add_sized([width, height], Button::new("Ping community nodes")).on_hover_text(P2POOL_PING).clicked() {
@@ -267,7 +283,7 @@ impl P2pool {
 			ui.spacing_mut().icon_width = width / 25.0;
 			// [Ping List]
 			let text = RichText::new(format!("{}. {} | {}", self.selected_index, self.selected_name, self.selected_ip));
-			ComboBox::from_id_source("nodes").selected_text(RichText::text_style(text, Monospace)).show_ui(ui, |ui| {
+			ComboBox::from_id_source("manual_nodes").selected_text(RichText::text_style(text, Monospace)).show_ui(ui, |ui| {
 				let mut n = 1;
 				for (name, node) in node_vec.iter() {
 					let text = RichText::text_style(RichText::new(format!("{}. {}\n     IP: {}\n    RPC: {}\n    ZMQ: {}", n, name, node.ip, node.rpc, node.zmq)), Monospace);
@@ -275,7 +291,6 @@ impl P2pool {
 						self.selected_index = n;
 						self.selected_name = name.clone();
 					}
-//					ui.selectable_value(&mut self.selected_name, name.clone(), text);
 					n += 1;
 				}
 			});