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 <l.wagner@proxmox.com>
This commit is contained in:
Lukas Wagner 2024-08-06 14:59:53 +02:00 committed by Wolfgang Bumiller
parent f01c1e0ce9
commit 7ea63a6fb9
2 changed files with 55 additions and 15 deletions

View File

@ -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<CreateOptions>,
dir_options: Option<CreateOptions>,
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<Database>,
create_rrd_cb: fn(dst: DataSourceType) -> Database,
) -> Result<Self, Error> {
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<u64>,
end: Option<u64>,
) -> Result<Option<Entry>, 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)
}
}
}
}
}

View File

@ -14,18 +14,21 @@ use crate::Entry;
pub struct RRDMap {
config: Arc<CacheConfig>,
map: HashMap<String, Database>,
load_rrd_cb: fn(path: &Path, rel_path: &str, dst: DataSourceType) -> Database,
load_rrd_cb: fn(path: &Path, rel_path: &str) -> Option<Database>,
create_rrd_cb: fn(dst: DataSourceType) -> Database,
}
impl RRDMap {
pub(crate) fn new(
config: Arc<CacheConfig>,
load_rrd_cb: fn(path: &Path, rel_path: &str, dst: DataSourceType) -> Database,
load_rrd_cb: fn(path: &Path, rel_path: &str) -> Option<Database>,
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<bool, Error> {
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);
}
}
}