diff --git a/Cargo.lock b/Cargo.lock index a9bb987..fa42541 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -449,9 +449,9 @@ dependencies = [ [[package]] name = "calloop" -version = "0.10.4" +version = "0.10.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "19457a0da465234abd76134a5c2a910c14bd3c5558463e4396ab9a37a328e465" +checksum = "1a59225be45a478d772ce015d9743e49e92798ece9e34eda9a6aa2a6a7f40192" dependencies = [ "log", "nix 0.25.1", @@ -1841,9 +1841,9 @@ dependencies = [ [[package]] name = "half" -version = "2.1.0" +version = "2.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ad6a9459c9c30b177b925162351f97e7d967c7ea8bab3b8352805327daf45554" +checksum = "6c467d36af040b7b2681f5fddd27427f6da8d3d072f575a265e181d2f8e8d157" dependencies = [ "crunchy", ] @@ -2665,9 +2665,9 @@ dependencies = [ [[package]] name = "once_cell" -version = "1.16.0" +version = "1.17.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "86f0b0d4bf799edbc74508c1e8bf170ff5f41238e5f8225603ca7caaae2b7860" +checksum = "6f61fba1741ea2b3d6a1e3178721804bb716a68a6aeba1149b5d52e3d464ea66" [[package]] name = "opaque-debug" @@ -3420,18 +3420,18 @@ checksum = "58bc9567378fc7690d6b2addae4e60ac2eeea07becb2c64b9f218b53865cba2a" [[package]] name = "serde" -version = "1.0.151" +version = "1.0.152" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "97fed41fc1a24994d044e6db6935e69511a1153b52c15eb42493b26fa87feba0" +checksum = "bb7d1f0d3021d347a83e556fc4683dea2ea09d87bccdf88ff5c12545d89d5efb" dependencies = [ "serde_derive", ] [[package]] name = "serde_derive" -version = "1.0.151" +version = "1.0.152" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "255abe9a125a985c05190d687b320c12f9b1f0b99445e608c21ba0782c719ad8" +checksum = "af487d118eecd09402d70a5d72551860e788df87b464af30e5ea6a38c75c541e" dependencies = [ "proc-macro2", "quote", @@ -3832,9 +3832,9 @@ dependencies = [ [[package]] name = "sysinfo" -version = "0.27.1" +version = "0.27.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ccb297c0afb439440834b4bcf02c5c9da8ec2e808e70f36b0d8e815ff403bd24" +checksum = "17351d0e9eb8841897b14e9669378f3c69fb57779cc04f8ca9a9d512edfb2563" dependencies = [ "cfg-if", "core-foundation-sys", diff --git a/src/disk.rs b/src/disk.rs index 4613b1f..bd245ac 100644 --- a/src/disk.rs +++ b/src/disk.rs @@ -605,6 +605,7 @@ pub struct GupaxP2poolApi { impl Default for GupaxP2poolApi { fn default() -> Self { Self::new() } } impl GupaxP2poolApi { + //---------------------------------------------------------------------------------------------------- Init, these pretty much only get called once pub fn new() -> Self { Self { log: String::new(), @@ -659,34 +660,6 @@ impl GupaxP2poolApi { Ok(()) } - pub fn update_log_rev(&mut self) { - let mut log_rev = String::with_capacity(self.log.len()); - for line in self.log.lines().rev() { - log_rev.push_str(line); - log_rev.push_str("\n"); - } - self.log_rev = log_rev; - } - - pub fn append_head_log_rev(&mut self, line: &str) { - self.log_rev = format!("{}\n{}", line, self.log_rev); - } - - pub fn update_payout_low(&mut self) { - self.payout_ord.sort_payout_low_to_high(); - self.payout_low = self.payout_ord.to_string(); - } - - pub fn update_payout_high(&mut self) { - self.payout_ord.sort_payout_high_to_low(); - self.payout_high = self.payout_ord.to_string(); - } - - pub fn update_payout_strings(&mut self) { - self.update_payout_low(); - self.update_payout_high(); - } - pub fn read_all_files_and_update(&mut self) -> Result<(), TomlError> { let payout_u64 = match read_to_string(File::Payout, &self.path_payout)?.trim().parse::() { Ok(o) => o, @@ -711,10 +684,48 @@ impl GupaxP2poolApi { Ok(()) } - // Takes the log line and (date, atomic_unit, block) and updates [self] and the [PayoutOrd] - pub fn add_payout(&mut self, log_payout_line: &str, date: String, atomic_unit: AtomicUnit, block: HumanNumber) { - self.log.push_str(log_payout_line); - self.append_head_log_rev(log_payout_line); + //---------------------------------------------------------------------------------------------------- Live, functions that actually update/write live stats + pub fn update_log_rev(&mut self) { + let mut log_rev = String::with_capacity(self.log.len()); + for line in self.log.lines().rev() { + log_rev.push_str(line); + log_rev.push_str("\n"); + } + self.log_rev = log_rev; + } + + pub fn format_payout(date: &str, atomic_unit: &AtomicUnit, block: &HumanNumber) -> String { + format!("{} | {} XMR | Block {}", date, atomic_unit, block) + } + + pub fn append_log(&mut self, formatted_log_line: &str) { + self.log.push_str(formatted_log_line); + self.log.push_str("\n"); + } + + pub fn append_head_log_rev(&mut self, formatted_log_line: &str) { + self.log_rev = format!("{}\n{}", formatted_log_line, self.log_rev); + } + + pub fn update_payout_low(&mut self) { + self.payout_ord.sort_payout_low_to_high(); + self.payout_low = self.payout_ord.to_string(); + } + + pub fn update_payout_high(&mut self) { + self.payout_ord.sort_payout_high_to_low(); + self.payout_high = self.payout_ord.to_string(); + } + + pub fn update_payout_strings(&mut self) { + self.update_payout_low(); + self.update_payout_high(); + } + + // Takes the (date, atomic_unit, block) and updates [self] and the [PayoutOrd] + pub fn add_payout(&mut self, formatted_log_line: &str, date: String, atomic_unit: AtomicUnit, block: HumanNumber) { + self.append_log(formatted_log_line); + self.append_head_log_rev(formatted_log_line); self.payout_u64 += 1; self.payout = HumanNumber::from_u64(self.payout_u64); self.xmr = self.xmr.add_self(atomic_unit); @@ -722,20 +733,20 @@ impl GupaxP2poolApi { self.update_payout_strings(); } - pub fn write_to_all_files(&self) -> Result<(), TomlError> { + pub fn write_to_all_files(&self, formatted_log_line: &str) -> Result<(), TomlError> { Self::disk_overwrite(&self.payout_u64.to_string(), &self.path_payout)?; Self::disk_overwrite(&self.xmr.to_string(), &self.path_xmr)?; - Self::disk_append(&self.log, &self.path_log)?; + Self::disk_append(formatted_log_line, &self.path_log)?; Ok(()) } - pub fn disk_append(string: &str, path: &PathBuf) -> Result<(), TomlError> { + pub fn disk_append(formatted_log_line: &str, path: &PathBuf) -> Result<(), TomlError> { use std::io::Write; let mut file = match fs::OpenOptions::new().append(true).create(true).open(path) { Ok(f) => f, Err(e) => { error!("GupaxP2poolApi | Append [{}] ... FAIL: {}", path.display(), e); return Err(TomlError::Io(e)) }, }; - match writeln!(file, "{}", string) { + match writeln!(file, "{}", formatted_log_line) { Ok(_) => { debug!("GupaxP2poolApi | Append [{}] ... OK", path.display()); Ok(()) }, Err(e) => { error!("GupaxP2poolApi | Append [{}] ... FAIL: {}", path.display(), e); Err(TomlError::Io(e)) }, } @@ -1384,6 +1395,8 @@ mod test { #[test] fn create_and_serde_gupax_p2pool_api() { use crate::disk::GupaxP2poolApi; + use crate::regex::P2poolRegex; + use crate::xmr::PayoutOrd; use crate::xmr::AtomicUnit; // Get API dir, fill paths. @@ -1398,7 +1411,9 @@ mod test { api.log = "NOTICE 2022-01-27 01:30:23.1377 P2Pool You received a payout of 0.000000000001 XMR in block 2642816".to_string(); api.payout_u64 = 1; api.xmr = AtomicUnit::from_u64(2); - GupaxP2poolApi::write_to_all_files(&api).unwrap(); + let (date, atomic_unit, block) = PayoutOrd::parse_raw_payout_line(&api.log, &P2poolRegex::new()); + let formatted_log_line = GupaxP2poolApi::format_payout(&date, &atomic_unit, &block); + GupaxP2poolApi::write_to_all_files(&api, &formatted_log_line).unwrap(); println!("AFTER WRITE: {:#?}", api); // Read @@ -1409,7 +1424,7 @@ mod test { assert_eq!(api.payout_u64, 1); assert_eq!(api.xmr.to_u64(), 2); assert!(!api.payout_ord.is_empty()); - assert!(api.log.contains("2022-01-27 01:30:23.1377 P2Pool You received a payout of 0.000000000001 XMR in block 2642816\n")); + assert!(api.log.contains("2022-01-27 01:30:23.1377 | 0.000000000001 XMR | Block 2,642,816")); } #[test] diff --git a/src/helper.rs b/src/helper.rs index c5c79d6..ec2dd2f 100644 --- a/src/helper.rs +++ b/src/helper.rs @@ -267,9 +267,10 @@ impl Helper { // println!("{}", line); // For debugging. if regex.payout.is_match(&line) { debug!("P2Pool PTY | Found payout, attempting write: {}", line); - let (date, atomic_unit, block) = PayoutOrd::parse_line(&line, ®ex); - GupaxP2poolApi::add_payout(&mut lock!(gupax_p2pool_api), &line, date, atomic_unit, block); - if let Err(e) = GupaxP2poolApi::write_to_all_files(&lock!(gupax_p2pool_api)) { error!("P2Pool PTY GupaxP2poolApi | Write error: {}", e); } + let (date, atomic_unit, block) = PayoutOrd::parse_raw_payout_line(&line, ®ex); + let formatted_log_line = GupaxP2poolApi::format_payout(&date, &atomic_unit, &block); + GupaxP2poolApi::add_payout(&mut lock!(gupax_p2pool_api), &formatted_log_line, date, atomic_unit, block); + if let Err(e) = GupaxP2poolApi::write_to_all_files(&lock!(gupax_p2pool_api), &formatted_log_line) { error!("P2Pool PTY GupaxP2poolApi | Write error: {}", e); } } if let Err(e) = writeln!(lock!(output_parse), "{}", line) { error!("P2Pool PTY Parse | Output error: {}", e); } if let Err(e) = writeln!(lock!(output_pub), "{}", line) { error!("P2Pool PTY Pub | Output error: {}", e); } diff --git a/src/human.rs b/src/human.rs index e62356d..4bf267a 100644 --- a/src/human.rs +++ b/src/human.rs @@ -113,6 +113,9 @@ impl HumanNumber { pub fn unknown() -> Self { Self("???".to_string()) } + pub fn from_str(s: &str) -> Self { + Self(s.to_string()) + } pub fn to_percent(f: f32) -> Self { if f < 0.01 { Self("0%".to_string()) diff --git a/src/regex.rs b/src/regex.rs index 8bb802c..ca2e60f 100644 --- a/src/regex.rs +++ b/src/regex.rs @@ -74,6 +74,7 @@ pub struct P2poolRegex { pub payout_float: regex::Regex, pub block: regex::Regex, pub block_int: regex::Regex, + pub block_comma: regex::Regex, } impl P2poolRegex { @@ -84,6 +85,7 @@ impl P2poolRegex { payout_float: regex::Regex::new("[0-9].[0-9]{12}").unwrap(), // Assumes 12 digits after the dot. block: regex::Regex::new("block [0-9]{7}").unwrap(), // Monero blocks will be 7 digits for... the next 10,379 years block_int: regex::Regex::new("[0-9]{7}").unwrap(), + block_comma: regex::Regex::new("[0-9],[0-9]{3},[0-9]{3}").unwrap(), } } } @@ -115,10 +117,12 @@ mod test { use regex::Regex; let r = crate::P2poolRegex::new(); let text = "NOTICE 2022-11-11 11:11:11.1111 P2Pool You received a payout of 0.111111111111 XMR in block 1111111"; + let text2 = "2022-11-11 11:11:11.1111 | 0.111111111111 XMR | Block 1,111,111"; assert_eq!(r.payout.find(text).unwrap().as_str(), "payout of 0.111111111111 XMR"); assert_eq!(r.payout_float.find(text).unwrap().as_str(), "0.111111111111"); assert_eq!(r.date.find(text).unwrap().as_str(), "2022-11-11 11:11:11.1111"); assert_eq!(r.block.find(text).unwrap().as_str(), "block 1111111"); assert_eq!(r.block_int.find(text).unwrap().as_str(), "1111111"); + assert_eq!(r.block_comma.find(text2).unwrap().as_str(), "1,111,111"); } } diff --git a/src/status.rs b/src/status.rs index 150792c..6a59de8 100644 --- a/src/status.rs +++ b/src/status.rs @@ -165,8 +165,8 @@ pub fn show(&mut self, sys: &Arc>, p2pool_api: &Arc ui.add_sized([width, log], TextEdit::multiline(&mut api.log.as_str())), - PayoutView::Oldest => ui.add_sized([width, log], TextEdit::multiline(&mut api.log_rev.as_str())), + PayoutView::Latest => ui.add_sized([width, log], TextEdit::multiline(&mut api.log_rev.as_str())), + PayoutView::Oldest => ui.add_sized([width, log], TextEdit::multiline(&mut api.log.as_str())), PayoutView::Biggest => ui.add_sized([width, log], TextEdit::multiline(&mut api.payout_high.as_str())), PayoutView::Smallest => ui.add_sized([width, log], TextEdit::multiline(&mut api.payout_low.as_str())), }; @@ -191,14 +191,15 @@ pub fn show(&mut self, sys: &Arc>, p2pool_api: &Arc>, p2pool_api: &Arc (String, AtomicUnit, HumanNumber) { + // Expected input: "NOTICE 2022-01-27 01:30:23.1377 P2Pool You received a payout of 0.000000000001 XMR in block 2642816" + pub fn parse_raw_payout_line(line: &str, regex: &P2poolRegex) -> (String, AtomicUnit, HumanNumber) { // Date let date = match regex.date.find(line) { Some(date) => date.as_str().to_string(), @@ -154,9 +155,11 @@ impl PayoutOrd { Err(e) => { error!("P2Pool | AtomicUnit parse error: [{}] on [{}]", e, line); AtomicUnit::new() }, } } else { + error!("P2Pool | AtomicUnit parse error: [{}]", line); AtomicUnit::new() } } else { + error!("P2Pool | AtomicUnit parse error: [{}]", line); AtomicUnit::new() }; // Block @@ -167,31 +170,57 @@ impl PayoutOrd { Err(e) => { error!("P2Pool | Block parse error: [{}] on [{}]", e, line); HumanNumber::unknown() }, } } else { + error!("P2Pool | Block parse error: [{}]", line); HumanNumber::unknown() } } else { + error!("P2Pool | Block parse error: [{}]", line); HumanNumber::unknown() }; (date, atomic_unit, block) } - // Takes in input of ONLY P2Pool payout logs and - // converts it into a usable [PayoutOrd] - // It expects log lines like this: - // "NOTICE 2022-04-11 00:20:17.2571 P2Pool You received a payout of 0.001371623621 XMR in block 2562511" + // Expected input: "2022-01-27 01:30:23.1377 | 0.000000000001 XMR | Block 2,642,816" + pub fn parse_formatted_payout_line(line: &str, regex: &P2poolRegex) -> (String, AtomicUnit, HumanNumber) { + // Date + let date = match regex.date.find(line) { + Some(date) => date.as_str().to_string(), + None => { error!("P2Pool | Date parse error: [{}]", line); "????-??-?? ??:??:??.????".to_string() }, + }; + // AtomicUnit + let atomic_unit = if let Some(word) = regex.payout_float.find(line) { + match word.as_str().parse::() { + Ok(au) => AtomicUnit::from_f64(au), + Err(e) => { error!("P2Pool | AtomicUnit parse error: [{}] on [{}]", e, line); AtomicUnit::new() }, + } + } else { + error!("P2Pool | AtomicUnit parse error: [{}]", line); + AtomicUnit::new() + }; + // Block + let block = match regex.block_comma.find(line) { + Some(b) => HumanNumber::from_str(b.as_str()), + None => { error!("P2Pool | Block parse error: [{}]", line); HumanNumber::unknown() }, + }; + (date, atomic_unit, block) + } + + // Takes in input of ONLY P2Pool payout logs and converts it into a usable [PayoutOrd] + // It expects formatted log lines like this: "2022-04-11 00:20:17.2571 | 0.001371623621 XMR | Block 2,562,511" // For efficiency reasons, I'd like to know the byte size // we should allocate for the vector so we aren't adding every loop. // Given a log [str], the equation for how many bytes the final vec will be is: - // (BYTES_OF_DATE + BYTES OF XMR + BYTES OF BLOCK) * amount_of_lines + // (BYTES_OF_DATE + BYTES OF XMR + BYTES OF BLOCK) + (SPACES, PIPES, MISC WORDS) * amount_of_lines // The first three are more or less constants (monero block 10m is in 10,379 years...): [23, 14, 7] (sum: 44) - // Add 16 more bytes for wrapper type overhead and it's an even [60] bytes per line. + // Spaces, pipes, commas and words (XMR, Block): [19] + // Add 7 more bytes for wrapper type overhead and it's an even [70] bytes per line. pub fn update_from_payout_log(&mut self, log: &str) { let regex = P2poolRegex::new(); let amount_of_lines = log.lines().count(); - let mut vec: Vec<(String, AtomicUnit, HumanNumber)> = Vec::with_capacity(60 * amount_of_lines); + let mut vec: Vec<(String, AtomicUnit, HumanNumber)> = Vec::with_capacity(70 * amount_of_lines); for line in log.lines() { debug!("PayoutOrg | Parsing line: [{}]", line); - vec.push(Self::parse_line(line, ®ex)); + vec.push(Self::parse_formatted_payout_line(line, ®ex)); } *self = Self(vec); } @@ -259,20 +288,15 @@ mod test { fn update_p2pool_payout_log() { use crate::xmr::PayoutOrd; let log = -r#"NOTICE 2021-12-21 01:01:01.1111 P2Pool You received a payout of 0.001000000000 XMR in block 1234567 -NOTICE 2021-12-21 02:01:01.1111 P2Pool You received a payout of 0.002000000000 XMR in block 2345678 -NOTICE 2021-12-21 03:01:01.1111 P2Pool You received a payout of 0.003000000000 XMR in block 3456789 +r#"2021-12-21 01:01:01.1111 | 0.001000000000 XMR | Block 1,234,567 +2021-12-21 02:01:01.1111 | 0.002000000000 XMR | Block 2,345,678 +2021-12-21 03:01:01.1111 | 0.003000000000 XMR | Block 3,456,789 "#; let mut payout_ord = PayoutOrd::new(); println!("BEFORE: {}", payout_ord); PayoutOrd::update_from_payout_log(&mut payout_ord, log); println!("AFTER: {}", payout_ord); - let should_be = -r#"2021-12-21 01:01:01.1111 | 0.001000000000 XMR | Block 1,234,567 -2021-12-21 02:01:01.1111 | 0.002000000000 XMR | Block 2,345,678 -2021-12-21 03:01:01.1111 | 0.003000000000 XMR | Block 3,456,789 -"#; - assert_eq!(payout_ord.to_string(), should_be) + assert_eq!(payout_ord.to_string(), log); } #[test]