diff --git a/src/api2/admin/datastore.rs b/src/api2/admin/datastore.rs index ebba7a43..1f764a0f 100644 --- a/src/api2/admin/datastore.rs +++ b/src/api2/admin/datastore.rs @@ -314,7 +314,7 @@ fn prune( let list = group.list_backups(&datastore.base_path())?; - let mut prune_info = BackupGroup::compute_prune_info( + let mut prune_info = compute_prune_info( list, param["keep-last"].as_u64(), param["keep-daily"].as_u64(), diff --git a/src/backup/backup_info.rs b/src/backup/backup_info.rs index 86697761..a96d17a6 100644 --- a/src/backup/backup_info.rs +++ b/src/backup/backup_info.rs @@ -3,9 +3,8 @@ use crate::tools; use failure::*; use regex::Regex; use std::os::unix::io::RawFd; -use std::collections::{HashMap, HashSet}; -use chrono::{DateTime, Datelike, TimeZone, SecondsFormat, Utc, Local}; +use chrono::{DateTime, TimeZone, SecondsFormat, Utc}; use std::path::{PathBuf, Path}; use lazy_static::lazy_static; @@ -44,8 +43,6 @@ pub struct BackupGroup { backup_id: String, } -enum PruneMark { Keep, Remove } - impl BackupGroup { pub fn new, U: Into>(backup_type: T, backup_id: U) -> Self { @@ -103,118 +100,6 @@ impl BackupGroup { Ok(list) } - fn mark_selections, &BackupInfo) -> String> ( - mark: &mut HashMap, - list: &Vec, - keep: usize, - select_id: F, - ) { - - let mut include_hash = HashSet::new(); - - let mut already_included = HashSet::new(); - for info in list { - let backup_id = info.backup_dir.relative_path(); - if let Some(PruneMark::Keep) = mark.get(&backup_id) { - let local_time = info.backup_dir.backup_time().with_timezone(&Local); - let sel_id: String = select_id(local_time, &info); - already_included.insert(sel_id); - } - } - - for info in list { - let backup_id = info.backup_dir.relative_path(); - if let Some(_) = mark.get(&backup_id) { continue; } - let local_time = info.backup_dir.backup_time().with_timezone(&Local); - let sel_id: String = select_id(local_time, &info); - - if already_included.contains(&sel_id) { continue; } - - if !include_hash.contains(&sel_id) { - if include_hash.len() >= keep { break; } - include_hash.insert(sel_id); - mark.insert(backup_id, PruneMark::Keep); - } else { - mark.insert(backup_id, PruneMark::Remove); - } - } - } - - pub fn compute_prune_info( - mut list: Vec, - keep_last: Option, - keep_daily: Option, - keep_weekly: Option, - keep_monthly: Option, - keep_yearly: Option, - ) -> Result, Error> { - - let mut mark = HashMap::new(); - - BackupInfo::sort_list(&mut list, false); - - // remove inclomplete snapshots - let mut keep_unfinished = true; - for info in list.iter() { - // backup is considered unfinished if there is no manifest - if info.files.iter().any(|name| name == super::MANIFEST_BLOB_NAME) { - // There is a new finished backup, so there is no need - // to keep older unfinished backups. - keep_unfinished = false; - } else { - let backup_id = info.backup_dir.relative_path(); - if keep_unfinished { // keep first unfinished - mark.insert(backup_id, PruneMark::Keep); - } else { - mark.insert(backup_id, PruneMark::Remove); - } - keep_unfinished = false; - } - } - - if let Some(keep_last) = keep_last { - Self::mark_selections(&mut mark, &list, keep_last as usize, |_local_time, info| { - BackupDir::backup_time_to_string(info.backup_dir.backup_time) - }); - } - - if let Some(keep_daily) = keep_daily { - Self::mark_selections(&mut mark, &list, keep_daily as usize, |local_time, _info| { - format!("{}/{}/{}", local_time.year(), local_time.month(), local_time.day()) - }); - } - - if let Some(keep_weekly) = keep_weekly { - Self::mark_selections(&mut mark, &list, keep_weekly as usize, |local_time, _info| { - format!("{}/{}", local_time.year(), local_time.iso_week().week()) - }); - } - - if let Some(keep_monthly) = keep_monthly { - Self::mark_selections(&mut mark, &list, keep_monthly as usize, |local_time, _info| { - format!("{}/{}", local_time.year(), local_time.month()) - }); - } - - if let Some(keep_yearly) = keep_yearly { - Self::mark_selections(&mut mark, &list, keep_yearly as usize, |local_time, _info| { - format!("{}/{}", local_time.year(), local_time.year()) - }); - } - - let prune_info: Vec<(BackupInfo, bool)> = list.into_iter() - .map(|info| { - let backup_id = info.backup_dir.relative_path(); - let keep = match mark.get(&backup_id) { - Some(PruneMark::Keep) => true, - _ => false, - }; - (info, keep) - }) - .collect(); - - Ok(prune_info) - } } /// Uniquely identify a Backup (relative to data store)