diff --git a/README.md b/README.md
index b9894d8..6559daf 100644
--- a/README.md
+++ b/README.md
@@ -3,23 +3,18 @@
**Gupax** (*guh-picks*) is a cross-platform GUI for mining [**Monero**](https://github.com/monero-project/monero) on the decentralized [**P2Pool**](https://github.com/SChernykh/p2pool), using the dedicated [**XMRig**](https://github.com/xmrig/xmrig) miner for max hashrate.
## Demo
-*
- Click me to load the demo!
+https://user-images.githubusercontent.com/101352116/194763334-d8e936c9-a71e-474e-ac65-3a339b96a9d2.mp4
- https://user-images.githubusercontent.com/101352116/194763334-d8e936c9-a71e-474e-ac65-3a339b96a9d2.mp4
+
+Click me to load images!
-
+![about.png](https://github.com/hinto-janaiyo/gupax/blob/main/images/tabs/about.png)
+![status.png](https://github.com/hinto-janaiyo/gupax/blob/main/images/tabs/status.png)
+![gupax.png](https://github.com/hinto-janaiyo/gupax/blob/main/images/tabs/gupax.png)
+![p2pool.png](https://github.com/hinto-janaiyo/gupax/blob/main/images/tabs/p2pool.png)
+![xmrig.png](https://github.com/hinto-janaiyo/gupax/blob/main/images/tabs/xmrig.png)
-*
- Click me to load images!
-
- ![about.png](https://github.com/hinto-janaiyo/gupax/blob/main/images/tabs/about.png)
- ![status.png](https://github.com/hinto-janaiyo/gupax/blob/main/images/tabs/status.png)
- ![gupax.png](https://github.com/hinto-janaiyo/gupax/blob/main/images/tabs/gupax.png)
- ![p2pool.png](https://github.com/hinto-janaiyo/gupax/blob/main/images/tabs/p2pool.png)
- ![xmrig.png](https://github.com/hinto-janaiyo/gupax/blob/main/images/tabs/xmrig.png)
-
-
+
## Implementation
diff --git a/src/README.md b/src/README.md
index a9d8e87..7ae5552 100644
--- a/src/README.md
+++ b/src/README.md
@@ -6,15 +6,14 @@
## Structure
| File/Folder | Purpose |
|----------------|---------|
-| `about.rs` | Struct/impl for `About` tab
| `constants.rs` | General constants needed in Gupax
-| `gupax.rs` | Struct/impl for `Gupax` tab
+| `gupax.rs` | Impl for `Gupax` tab
| `main.rs` | Struct/enum/impl for `App/Tab/State`, init functions, main function
| `node.rs` | Struct/impl for Community Nodes
-| `p2pool.rs` | Struct/impl for `P2Pool` tab
-| `state.rs` | Struct/impl for `gupax.toml`, the disk state
+| `p2pool.rs` | Impl for `P2Pool` tab
+| `state.rs` | Struct/impl for `gupax.toml`, the disk state. This holds the structs representing tabs with mutable state (Gupax/P2Pool/XMRig)
| `status.rs` | Struct/impl for `Status` tab
-| `xmrig.rs` | Struct/impl for `XMRig` tab
+| `xmrig.rs` | Impl for `XMRig` tab
## Bootstrap
This is how Gupax works internally when starting up, divided into 3 sections.
diff --git a/src/constants.rs b/src/constants.rs
index 4cda9a6..0d696b1 100644
--- a/src/constants.rs
+++ b/src/constants.rs
@@ -15,9 +15,10 @@
// You should have received a copy of the GNU General Public License
// along with this program. If not, see .
-pub const GUPAX_VERSION: &'static str = "v0.1.0";
+pub const GUPAX_VERSION: &'static str = concat!("v", env!("CARGO_PKG_VERSION"));
pub const P2POOL_VERSION: &'static str = "v2.4";
pub const XMRIG_VERSION: &'static str = "v6.18.0";
+pub const COMMIT: &'static str = include_str!("../.git/refs/heads/main");
pub const BYTES_ICON: &[u8] = include_bytes!("../images/png/icon.png");
pub const BYTES_BANNER: &[u8] = include_bytes!("../images/png/banner.png");
@@ -34,22 +35,26 @@ pub const HUGEPAGES_1GB: bool = false;
#[cfg(target_os = "macos")]
pub const OS: &'static str = " macOS";
#[cfg(target_os = "macos")]
+pub const OS_NAME: &'static str = "macOS";
+#[cfg(target_os = "macos")]
pub const HUGEPAGES_1GB: bool = false;
#[cfg(target_os = "linux")]
pub const OS: &'static str = "🐧 Linux";
#[cfg(target_os = "linux")]
+pub const OS_NAME: &'static str = "Linux";
+#[cfg(target_os = "linux")]
pub const HUGEPAGES_1GB: bool = true;
// Tooltips
// Gupax
-pub const GUPAX_CHECK_FOR_UPDATES: &'static str = "Check for Gupax, P2Pool, and XMRig updates via GitHub's API";
-pub const GUPAX_UPGRADE: &'static str = "Upgrade anything that is out-of-date";
+pub const GUPAX_UPDATE: &'static str = "Update Gupax, P2Pool, and XMRig via GitHub's API";
pub const GUPAX_AUTO_UPDATE: &'static str = "Automatically check for updates at startup";
-pub const GUPAX_ASK_BEFORE_QUIT: &'static str = "Ask before quitting if processes are still alive";
-pub const GUPAX_PATH_CONFIG: &'static str = "The location of the Gupax configuration file";
-pub const GUPAX_PATH_P2POOL: &'static str = "The location of the P2Pool binary";
-pub const GUPAX_PATH_XMRIG: &'static str = "The location of the XMRig binary";
+pub const GUPAX_AUTO_NODE: &'static str = "Automatically ping the community Monero nodes and select the fastest at startup";
+pub const GUPAX_ASK_BEFORE_QUIT: &'static str = "Ask before quitting if processes are still alive, or if an update is in progress";
+pub const GUPAX_SAVE_BEFORE_QUIT: &'static str = "Automatically save any changed settings before quitting";
+pub const GUPAX_PATH_P2POOL: &'static str = "The location of the P2Pool binary, both absolute and relative paths are accepted";
+pub const GUPAX_PATH_XMRIG: &'static str = "The location of the XMRig binary, both absolute and relative paths are accepted";
// P2Pool
pub const P2POOL_MAIN: &'static str = "The P2Pool main-chain. This P2Pool finds shares faster, but has a higher difficulty. Suitable for miners with more than 50kH/s";
pub const P2POOL_MINI: &'static str = "The P2Pool mini-chain. This P2Pool finds shares slower, but has a lower difficulty. Suitable for miners with less than 50kH/s";
@@ -77,9 +82,8 @@ r#"USAGE: gupax [--flags]
-n | --no-startup Disable auto-update/node connections at startup
-r | --reset Reset all Gupax configuration/state"#;
pub const ARG_COPYRIGHT: &'static str =
-r#"For more information:
-https://github.com/hinto-janaiyo/gupax
-https://github.com/SChernykh/p2pool
-https://github.com/xmrig/xmrig
-
-Gupax, P2Pool, and XMRig are licensed under GPLv3."#;
+r#"Gupax, P2Pool, and XMRig are licensed under GPLv3.
+For more information, see here:
+ - https://github.com/hinto-janaiyo/gupax
+ - https://github.com/SChernykh/p2pool
+ - https://github.com/xmrig/xmrig"#;
diff --git a/src/gupax.rs b/src/gupax.rs
index 6b9f01a..581f0e5 100644
--- a/src/gupax.rs
+++ b/src/gupax.rs
@@ -19,32 +19,9 @@ use std::path::Path;
use crate::App;
use egui::WidgetType::Button;
use crate::constants::*;
-
-// Main data structure for the Gupax tab
-#[derive(Clone, Debug, Eq, PartialEq)]
-pub struct Gupax {
- auto_update: bool,
- ask_before_quit: bool,
- updating: bool,
- upgrading: bool,
- config: String,
- p2pool: String,
- xmrig: String,
-}
+use crate::state::Gupax;
impl Gupax {
- pub fn new() -> Self {
- Self {
- auto_update: false,
- ask_before_quit: true,
- updating: false,
- upgrading: false,
- config: String::from("/home/hinto/gupax/gupax.toml"),
- p2pool: String::from("/home/hinto/gupax/p2pool"),
- xmrig: String::from("/home/hinto/gupax/xmrig"),
- }
- }
-
pub fn show(state: &mut Gupax, ctx: &egui::Context, ui: &mut egui::Ui) {
let height = ui.available_height();
let width = ui.available_width();
@@ -54,41 +31,40 @@ impl Gupax {
ui.horizontal(|ui| {
ui.group(|ui| {
ui.vertical(|ui| {
- ui.add_sized([half_width - 8.0, half_height], egui::Button::new("Check for updates")).on_hover_text(GUPAX_CHECK_FOR_UPDATES);
+ ui.add_sized([half_width - 8.0, half_height], egui::Button::new("Check for updates")).on_hover_text(GUPAX_UPDATE);
ui.set_enabled(false);
- ui.add_sized([half_width - 8.0, half_height], egui::Button::new("Upgrade")).on_hover_text(GUPAX_UPGRADE);
+ ui.add_sized([half_width - 8.0, half_height], egui::Button::new("Upgrade")).on_hover_text("asdf");
});
});
ui.group(|ui| {
+ let mut style = (*ctx.style()).clone();
+ style.spacing.icon_width_inner = ui.available_height() / 6.0;
+ style.spacing.icon_width = ui.available_height() / 4.0;
+ style.spacing.icon_spacing = ui.available_width() / 20.0;
+ ctx.set_style(style);
+ let half_width = (half_width/2.0)-15.0;
ui.vertical(|ui| {
- let mut style = (*ctx.style()).clone();
- style.spacing.icon_width_inner = ui.available_height() / 6.0;
- style.spacing.icon_width = ui.available_height() / 4.0;
- style.spacing.icon_spacing = ui.available_width() / 20.0;
- ctx.set_style(style);
ui.add_sized([half_width, half_height], egui::Checkbox::new(&mut state.auto_update, "Auto-update")).on_hover_text(GUPAX_AUTO_UPDATE);
-
ui.add_sized([half_width, half_height], egui::Checkbox::new(&mut state.ask_before_quit, "Ask before quitting")).on_hover_text(GUPAX_ASK_BEFORE_QUIT);
- });
+ });
+ ui.vertical(|ui| {
+ ui.add_sized([half_width, half_height], egui::Checkbox::new(&mut state.auto_node, "Auto-node")).on_hover_text(GUPAX_AUTO_NODE);
+ ui.add_sized([half_width, half_height], egui::Checkbox::new(&mut state.save_before_quit, "Save before quitting")).on_hover_text(GUPAX_SAVE_BEFORE_QUIT);
+ });
});
});
ui.add_space(10.0);
- ui.horizontal(|ui| {
- ui.label("Gupax config path: ");
- ui.spacing_mut().text_edit_width = ui.available_width() - 35.0;
- ui.text_edit_singleline(&mut state.config).on_hover_text(GUPAX_PATH_CONFIG);
- });
ui.horizontal(|ui| {
ui.label("P2Pool binary path:");
ui.spacing_mut().text_edit_width = ui.available_width() - 35.0;
- ui.text_edit_singleline(&mut state.p2pool).on_hover_text(GUPAX_PATH_P2POOL);
+ ui.text_edit_singleline(&mut state.p2pool_path).on_hover_text(GUPAX_PATH_P2POOL);
});
ui.horizontal(|ui| {
ui.label("XMRig binary path: ");
ui.spacing_mut().text_edit_width = ui.available_width() - 35.0;
- ui.text_edit_singleline(&mut state.xmrig).on_hover_text(GUPAX_PATH_XMRIG);
+ ui.text_edit_singleline(&mut state.xmrig_path).on_hover_text(GUPAX_PATH_XMRIG);
});
}
}
diff --git a/src/main.rs b/src/main.rs
index f84a2a7..7075ab4 100644
--- a/src/main.rs
+++ b/src/main.rs
@@ -23,6 +23,7 @@ use egui::TextStyle::*;
use egui::color::Color32;
use egui::FontFamily::Proportional;
use egui::{FontId,Label,RichText,Stroke,Vec2,Pos2};
+use egui::special_emojis::GITHUB;
use egui_extras::RetainedImage;
use eframe::{egui,NativeOptions};
@@ -97,7 +98,7 @@ impl App {
}
}
- fn default() -> Self {
+ fn new() -> Self {
let app = Self {
tab: Tab::default(),
quit: false,
@@ -116,11 +117,30 @@ impl App {
now: Instant::now(),
resolution: Vec2::new(1280.0, 720.0),
os: OS,
- version: "v0.0.1".to_string(),
- name_version: "Gupax v0.0.1".to_string(),
+ version: format!("{}", GUPAX_VERSION),
+ name_version: format!("Gupax {}", GUPAX_VERSION),
banner: RetainedImage::from_image_bytes("banner.png", BYTES_BANNER).expect("oops"),
};
- parse_args(app)
+ // Apply arg state
+ let mut app = parse_args(app);
+ // Read disk state if no [--reset] arg
+ if app.reset == false {
+ app.og = match State::get() {
+ Ok(toml) => toml,
+ Err(err) => {
+ error!("{}", err);
+ let error_msg = err.to_string();
+ let options = Panic::options();
+ eframe::run_native("Gupax", options, Box::new(|cc| Box::new(Panic::new(cc, error_msg))),);
+ exit(1);
+ },
+ };
+ }
+ // Make sure thread count is accurate/doesn't overflow
+ app.og.xmrig.max_threads = num_cpus::get();
+ if app.og.xmrig.current_threads > app.og.xmrig.max_threads { app.og.xmrig.current_threads = app.og.xmrig.max_threads; }
+ app.state = app.og.clone();
+ app
}
}
@@ -238,7 +258,7 @@ fn parse_args(mut app: App) -> App {
match arg.as_str() {
"-h"|"--help" => { println!("{}", ARG_HELP); exit(0); },
"-v"|"--version" => {
- println!("Gupax | {}\nP2Pool | {}\nXMRig | {}\n\n{}", GUPAX_VERSION, P2POOL_VERSION, XMRIG_VERSION, ARG_COPYRIGHT);
+ println!("Gupax | {}\nP2Pool | {}\nXMRig | {}\n\nOS: [{}], Commit: [{}]\n\n{}", GUPAX_VERSION, P2POOL_VERSION, XMRIG_VERSION, OS_NAME, &COMMIT[..40], ARG_COPYRIGHT);
exit(0);
},
_ => (),
@@ -300,30 +320,22 @@ impl eframe::App for Panic {
//---------------------------------------------------------------------------------------------------- Main [App] frame
fn main() {
init_logger();
- let app = App::default();
+ let app = App::new();
let options = init_options();
- let toml = match State::get() {
- Ok(toml) => toml,
- Err(err) => {
- error!("{}", err);
- let error_msg = err.to_string();
- let options = Panic::options();
- eframe::run_native("Gupax", options, Box::new(|cc| Box::new(Panic::new(cc, error_msg))),);
- exit(1);
- },
- };
eframe::run_native("Gupax", options, Box::new(|cc| Box::new(App::cc(cc, app))),);
}
impl eframe::App for App {
fn on_close_event(&mut self) -> bool {
self.quit = true;
- self.quit_confirm
+ if self.og.gupax.ask_before_quit {
+ self.quit_confirm
+ } else {
+ true
+ }
}
fn update(&mut self, ctx: &egui::Context, frame: &mut eframe::Frame) {
-// init_text_styles(ctx, 1280.0);
-
// Close confirmation.
if self.quit {
egui::CentralPanel::default().show(ctx, |ui| {
@@ -332,10 +344,11 @@ impl eframe::App for App {
let width = width - 10.0;
let height = ui.available_height();
// Detect processes or update
- if self.p2pool || self.xmrig {
+ if self.p2pool || self.xmrig || self.updating {
ui.add_sized([width, height/6.0], Label::new("Are you sure you want to quit?"));
- if self.p2pool { ui.add_sized([width, height/6.0], Label::new("P2Pool is online...!")); }
- if self.xmrig { ui.add_sized([width, height/6.0], Label::new("XMRig is online...!")); }
+ if self.updating { ui.add_sized([width, height/9.0], Label::new("Update is in progress...!")); }
+ if self.p2pool { ui.add_sized([width, height/9.0], Label::new("P2Pool is online...!")); }
+ if self.xmrig { ui.add_sized([width, height/9.0], Label::new("XMRig is online...!")); }
// Else, just quit
} else {
if self.state.gupax.save_before_quit {
@@ -383,27 +396,6 @@ impl eframe::App for App {
});
}
- // If ping-ING, display stats
-// if *self.pinging.lock().unwrap() {
-// egui::CentralPanel::default().show(ctx, |ui| {
-// let width = ui.available_width();
-// let width = width - 10.0;
-// let height = ui.available_height();
-// init_text_styles(ctx, width);
-// ui.add_sized([width, height/2.0], Label::new(format!("In progress: {}", *self.pinging.lock().unwrap())));
-// ui.group(|ui| {
-// if ui.add_sized([width, height/10.0], egui::Button::new("Yes")).clicked() {
-// info!("Quit confirmation = yes ... goodbye!");
-// exit(0);
-// } else if ui.add_sized([width, height/10.0], egui::Button::new("No")).clicked() {
-// info!("Quit confirmation = no ... returning!");
-// self.show_confirmation_dialog = false;
-// }
-// });
-// });
-// return
-// }
-
// Top: Tabs
egui::CentralPanel::default().show(ctx, |ui| {
init_text_styles(ctx, ui.available_width());
@@ -439,19 +431,19 @@ impl eframe::App for App {
ui.horizontal(|ui| {
ui.group(|ui| {
let width = width / 2.0;
- ui.add_sized([width, height], Label::new(&self.name_version));
+ ui.add_sized([width, height], Label::new(&*self.name_version));
ui.separator();
ui.add_sized([width, height], Label::new(self.os));
ui.separator();
ui.add_sized([width/1.5, height], Label::new("P2Pool"));
- if self.p2pool == true {
+ if self.p2pool {
ui.add_sized([width/4.0, height], Label::new(RichText::new("⏺").color(Color32::from_rgb(100, 230, 100))));
} else {
ui.add_sized([width/4.0, height], Label::new(RichText::new("⏺").color(Color32::from_rgb(230, 50, 50))));
}
ui.separator();
ui.add_sized([width/1.5, height], Label::new("XMRig"));
- if self.xmrig == true {
+ if self.xmrig {
ui.add_sized([width/4.0, height], Label::new(RichText::new("⏺").color(Color32::from_rgb(100, 230, 100))));
} else {
ui.add_sized([width/4.0, height], Label::new(RichText::new("⏺").color(Color32::from_rgb(230, 50, 50))));
@@ -464,7 +456,7 @@ impl eframe::App for App {
ui.set_enabled(false)
}
let width = width / 2.0;
- if ui.add_sized([width, height], egui::Button::new("Save")).on_hover_text("Save changes").clicked() { self.og = self.state.clone(); }
+ if ui.add_sized([width, height], egui::Button::new("Save")).on_hover_text("Save changes").clicked() { self.og = self.state.clone(); self.state.save(); }
if ui.add_sized([width, height], egui::Button::new("Reset")).on_hover_text("Reset changes").clicked() { self.state = self.og.clone(); }
});
@@ -472,7 +464,7 @@ impl eframe::App for App {
match self.tab {
Tab::P2pool => {
ui.group(|ui| {
- if self.p2pool == true {
+ if self.p2pool {
if ui.add_sized([width, height], egui::Button::new("⟲")).on_hover_text("Restart P2Pool").clicked() { self.p2pool = false; }
if ui.add_sized([width, height], egui::Button::new("⏹")).on_hover_text("Stop P2Pool").clicked() { self.p2pool = false; }
ui.add_enabled_ui(false, |ui| {
@@ -489,7 +481,7 @@ impl eframe::App for App {
}
Tab::Xmrig => {
ui.group(|ui| {
- if self.xmrig == true {
+ if self.xmrig {
if ui.add_sized([width, height], egui::Button::new("⟲")).on_hover_text("Restart XMRig").clicked() { self.xmrig = false; }
if ui.add_sized([width, height], egui::Button::new("⏹")).on_hover_text("Stop XMRig").clicked() { self.xmrig = false; }
ui.add_enabled_ui(false, |ui| {
@@ -513,14 +505,31 @@ impl eframe::App for App {
ui.style_mut().override_text_style = Some(egui::TextStyle::Body);
match self.tab {
Tab::About => {
- About::show(self, ctx, ui);
+ ui.add_space(10.0);
+ ui.vertical_centered(|ui| {
+ let space = ui.available_height()/2.2;
+ self.banner.show(ui);
+ ui.label("Gupax (guh-picks) is a cross-platform GUI for mining");
+ ui.hyperlink_to("[Monero]", "https://www.github.com/monero-project/monero");
+ ui.label("on the decentralized");
+ ui.hyperlink_to("[P2Pool]", "https://www.github.com/SChernykh/p2pool");
+ ui.label("using the dedicated");
+ ui.hyperlink_to("[XMRig]", "https://www.github.com/xmrig/xmrig");
+ ui.label("miner for max hashrate");
+
+ ui.add_space(ui.available_height()/2.4);
+
+ ui.hyperlink_to("Powered by egui", "https://github.com/emilk/egui");
+ ui.hyperlink_to(format!("{} {}", GITHUB, "Gupax made by hinto-janaiyo"), "https://www.github.com/hinto-janaiyo/gupax");
+ ui.label("egui is licensed under MIT & Apache-2.0");
+ ui.label("Gupax, P2Pool, and XMRig are licensed under GPLv3");
+ });
}
Tab::Status => {
Status::show(self, ctx, ui);
}
Tab::Gupax => {
-// Gupax::show(self.state.gupax, ctx, ui);
- exit(0);
+ Gupax::show(&mut self.state.gupax, ctx, ui);
}
Tab::P2pool => {
P2pool::show(&mut self.state.p2pool, ctx, ui);
diff --git a/src/p2pool.rs b/src/p2pool.rs
index 5045249..31b13ad 100644
--- a/src/p2pool.rs
+++ b/src/p2pool.rs
@@ -35,6 +35,29 @@ use crate::node::{RINO,SETH,SELSTA};
impl P2pool {
pub fn show(&mut self, ctx: &egui::Context, ui: &mut egui::Ui) {
+ // TODO:
+ // ping code
+ // If ping-ING, display stats
+// if *self.pinging.lock().unwrap() {
+// egui::CentralPanel::default().show(ctx, |ui| {
+// let width = ui.available_width();
+// let width = width - 10.0;
+// let height = ui.available_height();
+// init_text_styles(ctx, width);
+// ui.add_sized([width, height/2.0], Label::new(format!("In progress: {}", *self.pinging.lock().unwrap())));
+// ui.group(|ui| {
+// if ui.add_sized([width, height/10.0], egui::Button::new("Yes")).clicked() {
+// info!("Quit confirmation = yes ... goodbye!");
+// exit(0);
+// } else if ui.add_sized([width, height/10.0], egui::Button::new("No")).clicked() {
+// info!("Quit confirmation = no ... returning!");
+// self.show_confirmation_dialog = false;
+// }
+// });
+// });
+// return
+// }
+
let height = ui.available_height() / 10.0;
let mut width = ui.available_width() - 50.0;
ui.group(|ui| {
diff --git a/src/state.rs b/src/state.rs
index 4a8366e..4ebbd45 100644
--- a/src/state.rs
+++ b/src/state.rs
@@ -40,9 +40,13 @@ use log::*;
impl State {
pub fn default() -> Self {
use crate::constants::{P2POOL_VERSION,XMRIG_VERSION};
+ let max_threads = num_cpus::get();
+ let current_threads;
+ if max_threads == 1 { current_threads = 1; } else { current_threads = max_threads / 2; }
Self {
gupax: Gupax {
auto_update: true,
+ auto_node: true,
ask_before_quit: true,
save_before_quit: true,
p2pool_path: DEFAULT_P2POOL_PATH.to_string(),
@@ -66,8 +70,8 @@ impl State {
nicehash: false,
keepalive: false,
hugepages_jit: true,
- current_threads: 1,
- max_threads: 1,
+ current_threads,
+ max_threads,
priority: 2,
pool: "localhost:3333".to_string(),
address: "".to_string(),
@@ -224,6 +228,7 @@ pub struct State {
#[derive(Clone,Eq,PartialEq,Debug,Deserialize,Serialize)]
pub struct Gupax {
pub auto_update: bool,
+ pub auto_node: bool,
pub ask_before_quit: bool,
pub save_before_quit: bool,
pub p2pool_path: String,
@@ -253,8 +258,8 @@ pub struct Xmrig {
pub nicehash: bool,
pub keepalive: bool,
pub hugepages_jit: bool,
- pub max_threads: u16,
- pub current_threads: u16,
+ pub max_threads: usize,
+ pub current_threads: usize,
pub priority: u8,
pub pool: String,
pub address: String,