From 7ea63a6fb93b9a12db90ac60fd2f3b28abe642d7 Mon Sep 17 00:00:00 2001 From: Lukas Wagner Date: Tue, 6 Aug 2024 14:59:53 +0200 Subject: [PATCH] rrd: try to load database if not already present in cache Before, a call to `update` was necessary to load an existing database into the cache. If `update` was never called, `extract_cached_data` would simply return no data. Signed-off-by: Lukas Wagner --- proxmox-rrd/src/cache.rs | 29 ++++++++++++++++------ proxmox-rrd/src/cache/rrd_map.rs | 41 +++++++++++++++++++++++++------- 2 files changed, 55 insertions(+), 15 deletions(-) diff --git a/proxmox-rrd/src/cache.rs b/proxmox-rrd/src/cache.rs index 75a422c0..c8a24d86 100644 --- a/proxmox-rrd/src/cache.rs +++ b/proxmox-rrd/src/cache.rs @@ -12,7 +12,7 @@ use crossbeam_channel::{bounded, TryRecvError}; use proxmox_sys::fs::{create_path, CreateOptions}; -use crate::rrd::{AggregationFn, Archive, DataSourceType, Database}; +use crate::rrd::{AggregationFn, DataSourceType, Database}; use crate::Entry; mod journal; @@ -58,7 +58,8 @@ impl Cache { file_options: Option, dir_options: Option, apply_interval: f64, - load_rrd_cb: fn(path: &Path, rel_path: &str, dst: DataSourceType) -> Database, + load_rrd_cb: fn(path: &Path, rel_path: &str) -> Option, + create_rrd_cb: fn(dst: DataSourceType) -> Database, ) -> Result { let basedir = basedir.as_ref().to_owned(); @@ -80,7 +81,7 @@ impl Cache { }); let state = JournalState::new(Arc::clone(&config))?; - let rrd_map = RRDMap::new(Arc::clone(&config), load_rrd_cb); + let rrd_map = RRDMap::new(Arc::clone(&config), load_rrd_cb, create_rrd_cb); Ok(Self { config: Arc::clone(&config), @@ -248,10 +249,24 @@ impl Cache { start: Option, end: Option, ) -> Result, Error> { - self.rrd_map - .read() - .unwrap() - .extract_cached_data(base, name, cf, resolution, start, end) + let res = { + let map = self.rrd_map.read().unwrap(); + map.extract_cached_data(base, name, cf, resolution, start, end)? + }; + + match res { + Some(entry) => Ok(Some(entry)), + None => { + let mut map = self.rrd_map.write().unwrap(); + let loaded = map.load(&format!("{base}/{name}"))?; + + if loaded { + map.extract_cached_data(base, name, cf, resolution, start, end) + } else { + Ok(None) + } + } + } } } diff --git a/proxmox-rrd/src/cache/rrd_map.rs b/proxmox-rrd/src/cache/rrd_map.rs index 881b3987..fa9eaa1f 100644 --- a/proxmox-rrd/src/cache/rrd_map.rs +++ b/proxmox-rrd/src/cache/rrd_map.rs @@ -14,18 +14,21 @@ use crate::Entry; pub struct RRDMap { config: Arc, map: HashMap, - load_rrd_cb: fn(path: &Path, rel_path: &str, dst: DataSourceType) -> Database, + load_rrd_cb: fn(path: &Path, rel_path: &str) -> Option, + create_rrd_cb: fn(dst: DataSourceType) -> Database, } impl RRDMap { pub(crate) fn new( config: Arc, - load_rrd_cb: fn(path: &Path, rel_path: &str, dst: DataSourceType) -> Database, + load_rrd_cb: fn(path: &Path, rel_path: &str) -> Option, + create_rrd_cb: fn(dst: DataSourceType) -> Database, ) -> Self { Self { config, map: HashMap::new(), load_rrd_cb, + create_rrd_cb, } } @@ -44,13 +47,18 @@ impl RRDMap { } else { let mut path = self.config.basedir.clone(); path.push(rel_path); - create_path( - path.parent().unwrap(), - Some(self.config.dir_options.clone()), - Some(self.config.dir_options.clone()), - )?; + let mut rrd = match (self.load_rrd_cb)(&path, rel_path) { + None => { + create_path( + path.parent().unwrap(), + Some(self.config.dir_options.clone()), + Some(self.config.dir_options.clone()), + )?; - let mut rrd = (self.load_rrd_cb)(&path, rel_path, dst); + (self.create_rrd_cb)(dst) + } + Some(rrd) => rrd, + }; if !new_only || time > rrd.last_update() { rrd.update(time, value); @@ -94,4 +102,21 @@ impl RRDMap { None => Ok(None), } } + + pub fn load(&mut self, rel_path: &str) -> Result { + if self.map.get(rel_path).is_some() { + // Already loaded, do nothing + return Ok(true); + } + + let mut path = self.config.basedir.clone(); + path.push(rel_path); + + if let Some(rrd) = (self.load_rrd_cb)(&path, rel_path) { + self.map.insert(rel_path.to_string(), rrd); + return Ok(true); + } else { + return Ok(false); + } + } }