proxmox-rrd: log journal apply/flush times, split apply and flush
We need to apply the journal only once.
This commit is contained in:
parent
7484fce24d
commit
658357c5a8
|
@ -5,6 +5,7 @@ use std::sync::RwLock;
|
||||||
use std::io::Write;
|
use std::io::Write;
|
||||||
use std::io::{BufRead, BufReader};
|
use std::io::{BufRead, BufReader};
|
||||||
use std::os::unix::io::AsRawFd;
|
use std::os::unix::io::AsRawFd;
|
||||||
|
use std::time::SystemTime;
|
||||||
|
|
||||||
use anyhow::{format_err, bail, Error};
|
use anyhow::{format_err, bail, Error};
|
||||||
use nix::fcntl::OFlag;
|
use nix::fcntl::OFlag;
|
||||||
|
@ -33,6 +34,7 @@ struct RRDCacheState {
|
||||||
rrd_map: HashMap<String, RRD>,
|
rrd_map: HashMap<String, RRD>,
|
||||||
journal: File,
|
journal: File,
|
||||||
last_journal_flush: f64,
|
last_journal_flush: f64,
|
||||||
|
journal_applied: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
struct JournalEntry {
|
struct JournalEntry {
|
||||||
|
@ -83,6 +85,7 @@ impl RRDCache {
|
||||||
journal,
|
journal,
|
||||||
rrd_map: HashMap::new(),
|
rrd_map: HashMap::new(),
|
||||||
last_journal_flush: 0.0,
|
last_journal_flush: 0.0,
|
||||||
|
journal_applied: false,
|
||||||
};
|
};
|
||||||
|
|
||||||
Ok(Self {
|
Ok(Self {
|
||||||
|
@ -171,18 +174,46 @@ impl RRDCache {
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Apply journal. Should be used at server startup.
|
/// Apply and commit the journal. Should be used at server startup.
|
||||||
pub fn apply_journal(&self) -> Result<(), Error> {
|
pub fn apply_journal(&self) -> Result<(), Error> {
|
||||||
let mut state = self.state.write().unwrap(); // block writers
|
let mut state = self.state.write().unwrap(); // block writers
|
||||||
self.apply_journal_locked(&mut state)
|
self.apply_and_commit_journal_locked(&mut state)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn apply_journal_locked(&self, state: &mut RRDCacheState) -> Result<(), Error> {
|
fn apply_and_commit_journal_locked(&self, state: &mut RRDCacheState) -> Result<(), Error> {
|
||||||
|
|
||||||
log::info!("applying rrd journal");
|
|
||||||
|
|
||||||
state.last_journal_flush = proxmox_time::epoch_f64();
|
state.last_journal_flush = proxmox_time::epoch_f64();
|
||||||
|
|
||||||
|
if !state.journal_applied {
|
||||||
|
let start_time = SystemTime::now();
|
||||||
|
log::debug!("applying rrd journal");
|
||||||
|
|
||||||
|
match self.apply_journal_locked(state) {
|
||||||
|
Ok(entries) => {
|
||||||
|
let elapsed = start_time.elapsed()?.as_secs_f64();
|
||||||
|
log::info!("applied rrd journal ({} entries in {:.3} seconds)", entries, elapsed);
|
||||||
|
}
|
||||||
|
Err(err) => bail!("apply rrd journal failed - {}", err),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let start_time = SystemTime::now();
|
||||||
|
log::debug!("commit rrd journal");
|
||||||
|
|
||||||
|
match self.commit_journal_locked(state) {
|
||||||
|
Ok(rrd_file_count) => {
|
||||||
|
let elapsed = start_time.elapsed()?.as_secs_f64();
|
||||||
|
log::info!("rrd journal successfully committed ({} files in {:.3} seconds)",
|
||||||
|
rrd_file_count, elapsed);
|
||||||
|
}
|
||||||
|
Err(err) => bail!("rrd journal commit failed: {}", err),
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn apply_journal_locked(&self, state: &mut RRDCacheState) -> Result<usize, Error> {
|
||||||
|
|
||||||
let mut journal_path = self.basedir.clone();
|
let mut journal_path = self.basedir.clone();
|
||||||
journal_path.push(RRD_JOURNAL_NAME);
|
journal_path.push(RRD_JOURNAL_NAME);
|
||||||
|
|
||||||
|
@ -234,10 +265,22 @@ impl RRDCache {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// We need to apply the journal only once, because further updates
|
||||||
|
// are always directly applied.
|
||||||
|
state.journal_applied = true;
|
||||||
|
|
||||||
|
Ok(linenr)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn commit_journal_locked(&self, state: &mut RRDCacheState) -> Result<usize, Error> {
|
||||||
|
|
||||||
// save all RRDs
|
// save all RRDs
|
||||||
|
let mut rrd_file_count = 0;
|
||||||
|
|
||||||
let mut errors = 0;
|
let mut errors = 0;
|
||||||
for (rel_path, rrd) in state.rrd_map.iter() {
|
for (rel_path, rrd) in state.rrd_map.iter() {
|
||||||
|
rrd_file_count += 1;
|
||||||
let mut path = self.basedir.clone();
|
let mut path = self.basedir.clone();
|
||||||
path.push(&rel_path);
|
path.push(&rel_path);
|
||||||
if let Err(err) = rrd.save(&path, self.file_options.clone()) {
|
if let Err(err) = rrd.save(&path, self.file_options.clone()) {
|
||||||
|
@ -246,17 +289,16 @@ impl RRDCache {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// if everything went ok, commit the journal
|
if errors != 0 {
|
||||||
|
bail!("errors during rrd flush - unable to commit rrd journal");
|
||||||
if errors == 0 {
|
|
||||||
nix::unistd::ftruncate(state.journal.as_raw_fd(), 0)
|
|
||||||
.map_err(|err| format_err!("unable to truncate journal - {}", err))?;
|
|
||||||
log::info!("rrd journal successfully committed");
|
|
||||||
} else {
|
|
||||||
log::error!("errors during rrd flush - unable to commit rrd journal");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(())
|
// if everything went ok, commit the journal
|
||||||
|
|
||||||
|
nix::unistd::ftruncate(state.journal.as_raw_fd(), 0)
|
||||||
|
.map_err(|err| format_err!("unable to truncate journal - {}", err))?;
|
||||||
|
|
||||||
|
Ok(rrd_file_count)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Update data in RAM and write file back to disk (journal)
|
/// Update data in RAM and write file back to disk (journal)
|
||||||
|
@ -270,10 +312,8 @@ impl RRDCache {
|
||||||
|
|
||||||
let mut state = self.state.write().unwrap(); // block other writers
|
let mut state = self.state.write().unwrap(); // block other writers
|
||||||
|
|
||||||
if (time - state.last_journal_flush) > self.apply_interval {
|
if !state.journal_applied || (time - state.last_journal_flush) > self.apply_interval {
|
||||||
if let Err(err) = self.apply_journal_locked(&mut state) {
|
self.apply_and_commit_journal_locked(&mut state)?;
|
||||||
log::error!("apply journal failed: {}", err);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Self::append_journal_entry(&mut state, time, value, dst, rel_path)?;
|
Self::append_journal_entry(&mut state, time, value, dst, rel_path)?;
|
||||||
|
|
Loading…
Reference in New Issue