]> git.proxmox.com Git - proxmox-backup.git/blame - src/rrd_cache.rs
bump proxmox-rrd to 0.2 and proxmox-time to 2.0
[proxmox-backup.git] / src / rrd_cache.rs
CommitLineData
192ece47
DM
1//! Round Robin Database cache
2//!
3//! RRD files are stored under `/var/lib/proxmox-backup/rrdb/`. Only a
4//! single process may access and update those files, so we initialize
5//! and update RRD data inside `proxmox-backup-proxy`.
6
2e3f94e1
DM
7use std::path::Path;
8
fae4f6c5
DM
9use anyhow::{format_err, Error};
10use once_cell::sync::OnceCell;
11
f0c26122
LW
12use proxmox_rrd::rrd::{AggregationFn, DataSourceType, Database};
13use proxmox_rrd::Cache;
9531d2c5 14use proxmox_sys::fs::CreateOptions;
fae4f6c5
DM
15
16use pbs_api_types::{RRDMode, RRDTimeFrame};
9531d2c5 17use pbs_buildcfg::PROXMOX_BACKUP_STATE_DIR_M;
fae4f6c5 18
b9352095
DM
19const RRD_CACHE_BASEDIR: &str = concat!(PROXMOX_BACKUP_STATE_DIR_M!(), "/rrdb");
20
f0c26122 21static RRD_CACHE: OnceCell<Cache> = OnceCell::new();
fae4f6c5
DM
22
23/// Get the RRD cache instance
f0c26122 24pub fn get_rrd_cache() -> Result<&'static Cache, Error> {
9531d2c5
TL
25 RRD_CACHE
26 .get()
27 .ok_or_else(|| format_err!("RRD cache not initialized!"))
fae4f6c5
DM
28}
29
30/// Initialize the RRD cache instance
31///
32/// Note: Only a single process must do this (proxmox-backup-proxy)
f0c26122 33pub fn initialize_rrd_cache() -> Result<&'static Cache, Error> {
fae4f6c5
DM
34 let backup_user = pbs_config::backup_user()?;
35
36 let file_options = CreateOptions::new()
37 .owner(backup_user.uid)
38 .group(backup_user.gid);
39
40 let dir_options = CreateOptions::new()
41 .owner(backup_user.uid)
42 .group(backup_user.gid);
43
9531d2c5 44 let apply_interval = 30.0 * 60.0; // 30 minutes
fae4f6c5 45
f0c26122 46 let cache = Cache::new(
b9352095 47 RRD_CACHE_BASEDIR,
fae4f6c5
DM
48 Some(file_options),
49 Some(dir_options),
50 apply_interval,
2e3f94e1 51 load_callback,
fae4f6c5
DM
52 )?;
53
9531d2c5
TL
54 RRD_CACHE
55 .set(cache)
fae4f6c5
DM
56 .map_err(|_| format_err!("RRD cache already initialized!"))?;
57
58 Ok(RRD_CACHE.get().unwrap())
59}
60
f0c26122
LW
61fn load_callback(path: &Path, _rel_path: &str, dst: DataSourceType) -> Database {
62 match Database::load(path, true) {
2e3f94e1
DM
63 Ok(rrd) => rrd,
64 Err(err) => {
65 if err.kind() != std::io::ErrorKind::NotFound {
9531d2c5
TL
66 log::warn!(
67 "overwriting RRD file {:?}, because of load error: {}",
68 path,
69 err
70 );
2e3f94e1 71 }
f0c26122 72 Cache::create_proxmox_backup_default_rrd(dst)
9531d2c5 73 }
2e3f94e1
DM
74 }
75}
76
fae4f6c5
DM
77/// Extracts data for the specified time frame from from RRD cache
78pub fn extract_rrd_data(
79 basedir: &str,
80 name: &str,
81 timeframe: RRDTimeFrame,
82 mode: RRDMode,
92ead5d3 83) -> Result<Option<proxmox_rrd::Entry>, Error> {
fae4f6c5
DM
84 let end = proxmox_time::epoch_f64() as u64;
85
86 let (start, resolution) = match timeframe {
87 RRDTimeFrame::Hour => (end - 3600, 60),
9531d2c5
TL
88 RRDTimeFrame::Day => (end - 3600 * 24, 60),
89 RRDTimeFrame::Week => (end - 3600 * 24 * 7, 30 * 60),
90 RRDTimeFrame::Month => (end - 3600 * 24 * 30, 30 * 60),
91 RRDTimeFrame::Year => (end - 3600 * 24 * 365, 6 * 60 * 60),
92 RRDTimeFrame::Decade => (end - 10 * 3600 * 24 * 366, 7 * 86400),
fae4f6c5
DM
93 };
94
95 let cf = match mode {
f0c26122
LW
96 RRDMode::Max => AggregationFn::Maximum,
97 RRDMode::Average => AggregationFn::Average,
fae4f6c5
DM
98 };
99
100 let rrd_cache = get_rrd_cache()?;
101
102 rrd_cache.extract_cached_data(basedir, name, cf, resolution, Some(start), Some(end))
103}
104
98eb435d
DM
105/// Sync/Flush the RRD journal
106pub fn rrd_sync_journal() {
107 if let Ok(rrd_cache) = get_rrd_cache() {
108 if let Err(err) = rrd_cache.sync_journal() {
109 log::error!("rrd_sync_journal failed - {}", err);
110 }
111 }
112}
fae4f6c5
DM
113/// Update RRD Gauge values
114pub fn rrd_update_gauge(name: &str, value: f64) {
115 if let Ok(rrd_cache) = get_rrd_cache() {
58f70bcc 116 let now = proxmox_time::epoch_f64();
f0c26122 117 if let Err(err) = rrd_cache.update_value(name, now, value, DataSourceType::Gauge) {
fae4f6c5
DM
118 log::error!("rrd::update_value '{}' failed - {}", name, err);
119 }
120 }
121}
122
123/// Update RRD Derive values
124pub fn rrd_update_derive(name: &str, value: f64) {
125 if let Ok(rrd_cache) = get_rrd_cache() {
58f70bcc 126 let now = proxmox_time::epoch_f64();
f0c26122 127 if let Err(err) = rrd_cache.update_value(name, now, value, DataSourceType::Derive) {
fae4f6c5
DM
128 log::error!("rrd::update_value '{}' failed - {}", name, err);
129 }
130 }
131}