From 803ab12ad4cdfca1b434797fa3bd8643fc0131a4 Mon Sep 17 00:00:00 2001 From: Dietmar Maurer Date: Sat, 23 May 2020 15:37:17 +0200 Subject: [PATCH] rrd: simplify code --- src/api2/node/rrd.rs | 2 +- src/rrd/cache.rs | 46 ++++++++++++++------------------ src/rrd/rrd.rs | 63 +++++--------------------------------------- 3 files changed, 27 insertions(+), 84 deletions(-) diff --git a/src/api2/node/rrd.rs b/src/api2/node/rrd.rs index 72534515..de4d279c 100644 --- a/src/api2/node/rrd.rs +++ b/src/api2/node/rrd.rs @@ -27,7 +27,7 @@ fn get_node_stats( _param: Value, ) -> Result { - crate::rrd::extract_data_list( + crate::rrd::extract_data( "host", &["cpu", "iowait", "memtotal", "memused"], timeframe, diff --git a/src/rrd/cache.rs b/src/rrd/cache.rs index c80b9f76..e1209aff 100644 --- a/src/rrd/cache.rs +++ b/src/rrd/cache.rs @@ -5,7 +5,7 @@ use std::sync::{RwLock}; use anyhow::{format_err, Error}; use lazy_static::lazy_static; -use serde_json::Value; +use serde_json::{json, Value}; use proxmox::tools::fs::{create_path, CreateOptions}; @@ -67,24 +67,6 @@ pub fn update_value(rel_path: &str, value: f64) -> Result<(), Error> { } pub fn extract_data( - rel_path: &str, - timeframe: RRDTimeFrameResolution, - mode: RRDMode, -) -> Result { - - let now = now()?; - - let map = RRD_CACHE.read().unwrap(); - - if let Some(rrd) = map.get(rel_path) { - Ok(rrd.extract_data(now, timeframe, mode)) - } else { - Ok(RRD::new().extract_data(now, timeframe, mode)) - } -} - - -pub fn extract_data_list( base: &str, items: &[&str], timeframe: RRDTimeFrameResolution, @@ -95,17 +77,29 @@ pub fn extract_data_list( let map = RRD_CACHE.read().unwrap(); - let mut list: Vec<(&str, &RRD)> = Vec::new(); - let empty_rrd = RRD::new(); + let mut result = Vec::new(); + for name in items.iter() { - if let Some(rrd) = map.get(&format!("{}/{}", base, name)) { - list.push((name, rrd)); - } else { - list.push((name, &empty_rrd)); + let rrd = map.get(&format!("{}/{}", base, name)).unwrap_or(&empty_rrd); + let (start, reso, list) = rrd.extract_data(now, timeframe, mode); + let mut t = start; + for index in 0..RRD_DATA_ENTRIES { + if result.len() <= index { + if let Some(value) = list[index] { + result.push(json!({ "time": t, *name: value })); + } else { + result.push(json!({ "time": t })); + } + } else { + if let Some(value) = list[index] { + result[index][name] = value.into(); + } + } + t += reso; } } - Ok(extract_rrd_data(&list, now, timeframe, mode)) + Ok(result.into()) } diff --git a/src/rrd/rrd.rs b/src/rrd/rrd.rs index 398d48cb..0088e3bb 100644 --- a/src/rrd/rrd.rs +++ b/src/rrd/rrd.rs @@ -45,11 +45,11 @@ impl RRD { epoch: u64, timeframe: RRDTimeFrameResolution, mode: RRDMode, - ) -> Value { + ) -> (u64, u64, Vec>) { let reso = timeframe as u64; - let end = reso*(epoch/reso); + let end = reso*((epoch + reso -1)/reso); let start = end - reso*(RRD_DATA_ENTRIES as u64); let rrd_end = reso*(self.last_update/reso); @@ -69,23 +69,23 @@ impl RRD { let mut index = ((t/reso) % (RRD_DATA_ENTRIES as u64)) as usize; for _ in 0..RRD_DATA_ENTRIES { if t < rrd_start || t > rrd_end { - list.push(json!({ "time": t })); + list.push(None); } else { let entry = data[index]; if entry.count == 0 { - list.push(json!({ "time": t })); + list.push(None); } else { let value = match mode { RRDMode::Max => entry.max, RRDMode::Average => entry.average, }; - list.push(json!({ "time": t, "value": value })); + list.push(Some(value)); } } t += reso; index = (index + 1) % RRD_DATA_ENTRIES; } - list.into() + (start, reso, list.into()) } pub fn from_raw(mut raw: &[u8]) -> Result { @@ -208,54 +208,3 @@ impl RRD { self.last_update = epoch; } } - -pub fn extract_rrd_data( - rrd_list: &[(&str, &RRD)], - epoch: u64, - timeframe: RRDTimeFrameResolution, - mode: RRDMode, -) -> Value { - - let reso = timeframe as u64; - - let end = reso*(epoch/reso); - let start = end - reso*(RRD_DATA_ENTRIES as u64); - - let mut list = Vec::new(); - - let mut t = start; - let mut index = ((t/reso) % (RRD_DATA_ENTRIES as u64)) as usize; - for _ in 0..RRD_DATA_ENTRIES { - let mut item = json!({ "time": t }); - for (name, rrd) in rrd_list.iter() { - let rrd_end = reso*(rrd.last_update/reso); - let rrd_start = rrd_end - reso*(RRD_DATA_ENTRIES as u64); - - if t < rrd_start || t > rrd_end { - continue; - } else { - let data = match timeframe { - RRDTimeFrameResolution::Hour => &rrd.hour, - RRDTimeFrameResolution::Day => &rrd.day, - RRDTimeFrameResolution::Week => &rrd.week, - RRDTimeFrameResolution::Month => &rrd.month, - RRDTimeFrameResolution::Year => &rrd.year, - }; - let entry = data[index]; - if entry.count == 0 { - continue; - } else { - let value = match mode { - RRDMode::Max => entry.max, - RRDMode::Average => entry.average, - }; - item[name] = value.into(); - } - } - } - list.push(item); - t += reso; index = (index + 1) % RRD_DATA_ENTRIES; - } - - list.into() -}