proxmox-rrd: improve developer docs

This commit is contained in:
Dietmar Maurer 2021-10-06 12:19:54 +02:00
parent dbc42e6f75
commit 0191759316
4 changed files with 74 additions and 31 deletions

View File

@ -8,7 +8,7 @@ use proxmox::tools::fs::{create_path, CreateOptions};
use proxmox_rrd_api_types::{RRDMode, RRDTimeFrameResolution}; use proxmox_rrd_api_types::{RRDMode, RRDTimeFrameResolution};
use super::*; use crate::{DST, rrd::RRD};
/// RRD cache - keep RRD data in RAM, but write updates to disk /// RRD cache - keep RRD data in RAM, but write updates to disk
/// ///

View File

@ -1,5 +1,21 @@
mod rrd; //! # Simple Round Robin Database files with fixed format
pub use rrd::*; //!
//! ## Features
//!
//! * One file stores a single data source
//! * Small/constant file size (6008 bytes)
//! * Stores avarage and maximum values
//! * Stores data for different time resolution ([RRDTimeFrameResolution](proxmox_rrd_api_types::RRDTimeFrameResolution))
pub mod rrd;
mod cache; mod cache;
pub use cache::*; pub use cache::*;
/// RRD data source tyoe
pub enum DST {
/// Gauge values are stored unmodified.
Gauge,
/// Stores the difference to the previous value.
Derive,
}

View File

@ -1,7 +1,10 @@
//! # Round Robin Database file format
use std::io::Read; use std::io::Read;
use std::path::Path; use std::path::Path;
use anyhow::Error; use anyhow::Error;
use bitflags::bitflags;
use proxmox::tools::{fs::replace_file, fs::CreateOptions}; use proxmox::tools::{fs::replace_file, fs::CreateOptions};
@ -14,10 +17,11 @@ pub const RRD_DATA_ENTRIES: usize = 70;
// openssl::sha::sha256(b"Proxmox Round Robin Database file v1.0")[0..8]; // openssl::sha::sha256(b"Proxmox Round Robin Database file v1.0")[0..8];
pub const PROXMOX_RRD_MAGIC_1_0: [u8; 8] = [206, 46, 26, 212, 172, 158, 5, 186]; pub const PROXMOX_RRD_MAGIC_1_0: [u8; 8] = [206, 46, 26, 212, 172, 158, 5, 186];
use bitflags::bitflags; use crate::DST;
bitflags!{ bitflags!{
struct RRAFlags: u64 { /// Flags to specify the data soure type and consolidation function
pub struct RRAFlags: u64 {
// Data Source Types // Data Source Types
const DST_GAUGE = 1; const DST_GAUGE = 1;
const DST_DERIVE = 2; const DST_DERIVE = 2;
@ -31,20 +35,24 @@ bitflags!{
} }
} }
/// RRD data source tyoe /// Round Robin Archive with [RRD_DATA_ENTRIES] data slots.
pub enum DST { ///
Gauge, /// This data structure is used inside [RRD] and directly written to the
Derive, /// RRD files.
}
#[repr(C)] #[repr(C)]
struct RRA { pub struct RRA {
flags: RRAFlags, /// Defined the data soure type and consolidation function
resolution: u64, pub flags: RRAFlags,
last_update: f64, /// Resulution (seconds) from [RRDTimeFrameResolution]
last_count: u64, pub resolution: u64,
counter_value: f64, // used for derive/counters /// Last update time (epoch)
data: [f64; RRD_DATA_ENTRIES], pub last_update: f64,
/// Count values computed inside this update interval
pub last_count: u64,
/// Stores the last value, used to compute differential value for derive/counters
pub counter_value: f64,
/// Data slots
pub data: [f64; RRD_DATA_ENTRIES],
} }
impl RRA { impl RRA {
@ -157,24 +165,37 @@ impl RRA {
} }
} }
/// Round Robin Database file format with fixed number of [RRA]s
#[repr(C)] #[repr(C)]
// Note: Avoid alignment problems by using 8byte types only // Note: Avoid alignment problems by using 8byte types only
pub struct RRD { pub struct RRD {
magic: [u8; 8], /// The magic number to identify the file type
hour_avg: RRA, pub magic: [u8; 8],
hour_max: RRA, /// Hourly data (average values)
day_avg: RRA, pub hour_avg: RRA,
day_max: RRA, /// Hourly data (maximum values)
week_avg: RRA, pub hour_max: RRA,
week_max: RRA, /// Dayly data (average values)
month_avg: RRA, pub day_avg: RRA,
month_max: RRA, /// Dayly data (maximum values)
year_avg: RRA, pub day_max: RRA,
year_max: RRA, /// Weekly data (average values)
pub week_avg: RRA,
/// Weekly data (maximum values)
pub week_max: RRA,
/// Monthly data (average values)
pub month_avg: RRA,
/// Monthly data (maximum values)
pub month_max: RRA,
/// Yearly data (average values)
pub year_avg: RRA,
/// Yearly data (maximum values)
pub year_max: RRA,
} }
impl RRD { impl RRD {
/// Create a new empty instance
pub fn new(dst: DST) -> Self { pub fn new(dst: DST) -> Self {
let flags = match dst { let flags = match dst {
DST::Gauge => RRAFlags::DST_GAUGE, DST::Gauge => RRAFlags::DST_GAUGE,
@ -226,6 +247,7 @@ impl RRD {
} }
} }
/// Extract data from the archive
pub fn extract_data( pub fn extract_data(
&self, &self,
time: f64, time: f64,
@ -276,6 +298,7 @@ impl RRD {
(start, reso, list) (start, reso, list)
} }
/// Create instance from raw data, testing data len and magic number
pub fn from_raw(mut raw: &[u8]) -> Result<Self, std::io::Error> { pub fn from_raw(mut raw: &[u8]) -> Result<Self, std::io::Error> {
let expected_len = std::mem::size_of::<RRD>(); let expected_len = std::mem::size_of::<RRD>();
if raw.len() != expected_len { if raw.len() != expected_len {
@ -297,11 +320,13 @@ impl RRD {
Ok(rrd) Ok(rrd)
} }
/// Load data from a file
pub fn load(path: &Path) -> Result<Self, std::io::Error> { pub fn load(path: &Path) -> Result<Self, std::io::Error> {
let raw = std::fs::read(path)?; let raw = std::fs::read(path)?;
Self::from_raw(&raw) Self::from_raw(&raw)
} }
/// Store data into a file (atomic replace file)
pub fn save(&self, filename: &Path, options: CreateOptions) -> Result<(), Error> { pub fn save(&self, filename: &Path, options: CreateOptions) -> Result<(), Error> {
let rrd_slice = unsafe { let rrd_slice = unsafe {
std::slice::from_raw_parts(self as *const _ as *const u8, std::mem::size_of::<RRD>()) std::slice::from_raw_parts(self as *const _ as *const u8, std::mem::size_of::<RRD>())
@ -309,7 +334,9 @@ impl RRD {
replace_file(filename, rrd_slice, options) replace_file(filename, rrd_slice, options)
} }
/// Update the value (in memory)
///
/// Note: This does not call [Self::save].
pub fn update(&mut self, time: f64, value: f64) { pub fn update(&mut self, time: f64, value: f64) {
self.hour_avg.update(time, value); self.hour_avg.update(time, value);
self.hour_max.update(time, value); self.hour_max.update(time, value);

View File

@ -7,7 +7,7 @@ use pbs_api_types::{
NODE_SCHEMA, RRDMode, RRDTimeFrameResolution, PRIV_SYS_AUDIT, NODE_SCHEMA, RRDMode, RRDTimeFrameResolution, PRIV_SYS_AUDIT,
}; };
use proxmox_rrd::RRD_DATA_ENTRIES; use proxmox_rrd::rrd::RRD_DATA_ENTRIES;
use crate::RRD_CACHE; use crate::RRD_CACHE;