proxmox-backup/proxmox-rrd/src/cache/rrd_map.rs
Dietmar Maurer 7f381a6246 proxmox-rrd: use fine grained locking in commit_journal_impl
Aquire the rrd_map lock for each file (else we block access for a long time)
2021-10-18 14:55:47 +02:00

98 lines
2.5 KiB
Rust

use std::path::Path;
use std::sync::Arc;
use std::collections::HashMap;
use anyhow::{bail, Error};
use proxmox::tools::fs::create_path;
use crate::rrd::{CF, DST, RRD};
use super::CacheConfig;
pub struct RRDMap {
config: Arc<CacheConfig>,
map: HashMap<String, RRD>,
load_rrd_cb: fn(path: &Path, rel_path: &str, dst: DST) -> RRD,
}
impl RRDMap {
pub(crate) fn new(
config: Arc<CacheConfig>,
load_rrd_cb: fn(path: &Path, rel_path: &str, dst: DST) -> RRD,
) -> Self {
Self {
config,
map: HashMap::new(),
load_rrd_cb,
}
}
pub fn update(
&mut self,
rel_path: &str,
time: f64,
value: f64,
dst: DST,
new_only: bool,
) -> Result<(), Error> {
if let Some(rrd) = self.map.get_mut(rel_path) {
if !new_only || time > rrd.last_update() {
rrd.update(time, value);
}
} 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 = (self.load_rrd_cb)(&path, rel_path, dst);
if !new_only || time > rrd.last_update() {
rrd.update(time, value);
}
self.map.insert(rel_path.to_string(), rrd);
}
Ok(())
}
pub fn file_list(&self) -> Vec<String> {
let mut list = Vec::new();
for rel_path in self.map.keys() {
list.push(rel_path.clone());
}
list
}
pub fn flush_rrd_file(&self, rel_path: &str) -> Result<(), Error> {
if let Some(rrd) = self.map.get(rel_path) {
let mut path = self.config.basedir.clone();
path.push(rel_path);
rrd.save(&path, self.config.file_options.clone())
} else {
bail!("rrd file {} not loaded", rel_path);
}
}
pub fn extract_cached_data(
&self,
base: &str,
name: &str,
cf: CF,
resolution: u64,
start: Option<u64>,
end: Option<u64>,
) -> Result<Option<(u64, u64, Vec<Option<f64>>)>, Error> {
match self.map.get(&format!("{}/{}", base, name)) {
Some(rrd) => Ok(Some(rrd.extract_data(cf, resolution, start, end)?)),
None => Ok(None),
}
}
}