proxmox-rrd: make rrd load callback configurable

This commit is contained in:
Dietmar Maurer 2021-10-14 11:41:26 +02:00
parent d531c7ae61
commit 2e3f94e12f
2 changed files with 56 additions and 16 deletions

View File

@ -25,6 +25,7 @@ pub struct RRDCache {
file_options: CreateOptions,
dir_options: CreateOptions,
state: RwLock<RRDCacheState>,
load_rrd_cb: fn(cache: &RRDCache, path: &Path, rel_path: &str, dst: DST) -> RRD,
}
// shared state behind RwLock
@ -44,11 +45,25 @@ struct JournalEntry {
impl RRDCache {
/// Creates a new instance
///
/// `basedir`: All files are stored relative to this path.
///
/// `file_options`: Files are created with this options.
///
/// `dir_options`: Directories are created with this options.
///
/// `apply_interval`: Commit journal after `apply_interval` seconds.
///
/// `load_rrd_cb`; The callback function is use to load RRD files,
/// and should return a newly generated RRD if the file does not
/// exists (or is unreadable). This may generate RRDs with
/// different configurations (dependent on `rel_path`).
pub fn new<P: AsRef<Path>>(
basedir: P,
file_options: Option<CreateOptions>,
dir_options: Option<CreateOptions>,
apply_interval: f64,
load_rrd_cb: fn(cache: &RRDCache, path: &Path, rel_path: &str, dst: DST) -> RRD,
) -> Result<Self, Error> {
let basedir = basedir.as_ref().to_owned();
@ -75,11 +90,26 @@ impl RRDCache {
file_options,
dir_options,
apply_interval,
load_rrd_cb,
state: RwLock::new(state),
})
}
fn create_default_rrd(dst: DST) -> RRD {
/// Create a new RRD as used by the proxmox backup server
///
/// It contains the following RRAs:
///
/// * cf=average,r=60,n=1440 => 1day
/// * cf=maximum,r=60,n=1440 => 1day
/// * cf=average,r=30*60,n=1440 => 1month
/// * cf=maximum,r=30*60,n=1440 => 1month
/// * cf=average,r=6*3600,n=1440 => 1year
/// * cf=maximum,r=6*3600,n=1440 => 1year
/// * cf=average,r=7*86400,n=570 => 10years
/// * cf=maximum,r=7*86400,n=570 => 10year
///
/// The resultion data file size is about 80KB.
pub fn create_proxmox_backup_default_rrd(dst: DST) -> RRD {
let mut rra_list = Vec::new();
@ -194,7 +224,7 @@ impl RRDCache {
path.push(&entry.rel_path);
create_path(path.parent().unwrap(), Some(self.dir_options.clone()), Some(self.dir_options.clone()))?;
let mut rrd = Self::load_rrd(&path, entry.dst);
let mut rrd = (self.load_rrd_cb)(&self, &path, &entry.rel_path, entry.dst);
if entry.time > get_last_update(&entry.rel_path, &rrd) {
rrd.update(entry.time, entry.value);
@ -228,18 +258,6 @@ impl RRDCache {
Ok(())
}
fn load_rrd(path: &Path, dst: DST) -> RRD {
match RRD::load(path) {
Ok(rrd) => rrd,
Err(err) => {
if err.kind() != std::io::ErrorKind::NotFound {
log::warn!("overwriting RRD file {:?}, because of load error: {}", path, err);
}
Self::create_default_rrd(dst)
},
}
}
/// Update data in RAM and write file back to disk (journal)
pub fn update_value(
&self,
@ -266,7 +284,7 @@ impl RRDCache {
path.push(rel_path);
create_path(path.parent().unwrap(), Some(self.dir_options.clone()), Some(self.dir_options.clone()))?;
let mut rrd = Self::load_rrd(&path, dst);
let mut rrd = (self.load_rrd_cb)(&self, &path, rel_path, dst);
rrd.update(time, value);
state.rrd_map.insert(rel_path.into(), rrd);

View File

@ -1,9 +1,11 @@
use std::path::Path;
use anyhow::{format_err, Error};
use once_cell::sync::OnceCell;
use proxmox::tools::fs::CreateOptions;
use proxmox_rrd::RRDCache;
use proxmox_rrd::rrd::{DST, CF};
use proxmox_rrd::rrd::{RRD, DST, CF};
use pbs_api_types::{RRDMode, RRDTimeFrame};
@ -36,6 +38,7 @@ pub fn initialize_rrd_cache() -> Result<&'static RRDCache, Error> {
Some(file_options),
Some(dir_options),
apply_interval,
load_callback,
)?;
RRD_CACHE.set(cache)
@ -44,6 +47,25 @@ pub fn initialize_rrd_cache() -> Result<&'static RRDCache, Error> {
Ok(RRD_CACHE.get().unwrap())
}
fn load_callback(
_cache: &RRDCache,
path: &Path,
_rel_path: &str,
dst: DST,
) -> RRD {
match RRD::load(path) {
Ok(rrd) => rrd,
Err(err) => {
if err.kind() != std::io::ErrorKind::NotFound {
log::warn!("overwriting RRD file {:?}, because of load error: {}", path, err);
}
RRDCache::create_proxmox_backup_default_rrd(dst)
},
}
}
/// Extracts data for the specified time frame from from RRD cache
pub fn extract_rrd_data(
basedir: &str,