use crate::prelude::*;
use std::time::SystemTime;
#[derive(Debug, Clone)]
#[allow(dead_code)]
pub struct LogEntry {
pub(crate) free_space: Space,
pub(crate) action: LogAction,
pub(crate) pattern: String,
pub(crate) params: Parameters,
}
#[derive(Debug, Clone)]
#[allow(dead_code)]
pub struct LogAction {
pub situation: Situation,
pub action: &'static str,
pub was: Days,
pub now: Days,
pub now_lambda: Lambda,
}
#[derive(Clone)]
pub struct LogCollection {
when: String,
pub(crate) by_history_file: BTreeMap<String, Vec<LogEntry>>,
}
#[derive(Debug)]
struct LogEntryInCollection<'e> {
when: &'e str,
entry: &'e LogEntry,
}
impl Default for LogCollection { fn default() -> Self { Self::new() } }
impl LogCollection {
pub fn new() -> Self {
Self::with_mock_time(SystemTime::now())
}
pub fn with_mock_time(when: SystemTime) -> Self {
let when =
humantime::format_rfc3339_seconds(when)
.to_string()
.replacen('T', " ", 1);
LogCollection {
when,
by_history_file: BTreeMap::default(),
}
}
}
impl LogCollection {
pub(crate) fn log(&mut self, pattern: &str, free_space: Space,
params: &Parameters, action: LogAction) {
self.by_history_file
.entry(params.history.clone())
.or_default()
.push(LogEntry {
pattern: pattern.into(),
free_space,
action,
params: params.clone(),
});
}
pub fn into_by_history_file_map(self) -> BTreeMap<String, Vec<LogEntry>> {
self.by_history_file
}
}
impl Display for LogEntryInCollection<'_> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
let LogEntryInCollection {
when,
entry:
LogEntry {
free_space,
pattern,
params,
action:
LogAction {
situation,
action,
was,
now,
now_lambda,
}}} = self;
write!(
f, "{} {:12} {:#} [{:#}..{:#}] {:#} ->{:#} {} {:10} {}",
when,
free_space,
situation,
params.mindays,
params.maxdays,
was,
now,
now_lambda,
action,
pattern,
)
}
}
impl LogCollection {
pub fn write_out(self) -> AR<()> {
let when = &self.when;
for (histfile, entries) in &self.by_history_file {
(||{
let f = File::options().write(true).append(true).create(true)
.open(histfile)
.context("open")?;
let mut f = BufWriter::new(f);
for entry in entries {
writeln!(f, "{}", LogEntryInCollection { when, entry })
.context("write")?;
f.flush().context("flush")?;
}
AOk(())
})()
.with_context(|| histfile.to_string())
.context("log file (histfile)")?;
}
Ok(())
}
}
impl Debug for LogCollection {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
let when = &self.when;
for (histfile, entries) in &self.by_history_file {
writeln!(f, "{:?}", histfile)?;
for entry in entries {
writeln!(f, " {}", LogEntryInCollection { when, entry })?;
}
}
Ok(())
}
}