From 27d7e681c3d9d00e90b21bd7c9fd8985183ea54c Mon Sep 17 00:00:00 2001 From: Chewing_Bever Date: Thu, 15 Jun 2023 22:54:17 +0200 Subject: [PATCH] feat: temporarily disable "remove old backups" --- src/server/backups.rs | 102 ++++++++++++++++++++++++++++-------------- src/server/process.rs | 6 +-- 2 files changed, 71 insertions(+), 37 deletions(-) diff --git a/src/server/backups.rs b/src/server/backups.rs index 8012b5f..e225aec 100644 --- a/src/server/backups.rs +++ b/src/server/backups.rs @@ -14,8 +14,7 @@ extern "C" { fn getegid() -> u32; } -const FILENAME_FORMAT: &str = "%Y-%m-%d_%H-%M-%S.tar.gz"; - +/// List all files in `src_dir` and all child directories. fn files(src_dir: PathBuf) -> io::Result> { let mut dirs = vec![src_dir.clone()]; let mut files: HashSet = HashSet::new(); @@ -159,7 +158,18 @@ pub struct Backup { } impl Backup { - /// Calculate the full state of the backup by applying all its ancestors delta's in order, + const FILENAME_FORMAT: &str = "%Y-%m-%d_%H-%M-%S.tar.gz"; + + /// Returns a pointer to this backup's previous backup by cloning the Arc pointer. + pub fn previous(&self) -> Option> { + if let Some(previous) = &self.previous { + Some(Arc::clone(&previous)) + } else { + None + } + } + + /// Calculate the full state of the backup by applying all its ancestors' delta's in order, /// starting from the last full ancestor. pub fn state(&self) -> BackupResult>> { if self.type_ == BackupType::Full { @@ -177,8 +187,27 @@ impl Backup { } } - pub fn set_previous(&mut self, previous: Arc) { - self.previous = Some(previous); + /// Returns the n'th ancestor of the given backup, if it exists. + pub fn ancestor(&self, n: u64) -> Option> { + if n == 0 { + None + } else if let Some(previous) = &self.previous { + if n == 1 { + Some(Arc::clone(&previous)) + } else { + previous.ancestor(n - 1) + } + } else { + None + } + } + + /// Return the path to a backup file by properly formatting the data. + pub fn path>(backup_dir: P, start_time: chrono::DateTime) -> PathBuf { + let backup_dir = backup_dir.as_ref(); + + let filename = format!("{}", start_time.format(Self::FILENAME_FORMAT)); + backup_dir.join(filename) } /// Create a new Full backup, populated with the given directories. @@ -196,11 +225,9 @@ impl Backup { backup_dir: P, dirs: Vec<(PathBuf, PathBuf)>, ) -> io::Result { - let backup_dir = backup_dir.as_ref(); let start_time = chrono::offset::Utc::now(); - let filename = format!("{}", start_time.format(FILENAME_FORMAT)); - let path = backup_dir.join(filename); + let path = Self::path(backup_dir, start_time); let tar_gz = File::create(path)?; let enc = GzEncoder::new(tar_gz, Compression::default()); let mut ar = tar::Builder::new(enc); @@ -234,17 +261,16 @@ impl Backup { backup_dir: P, dirs: Vec<(PathBuf, PathBuf)>, ) -> io::Result { - let backup_dir = backup_dir.as_ref(); let start_time = chrono::offset::Utc::now(); - let filename = format!("{}", start_time.format(FILENAME_FORMAT)); - let path = backup_dir.join(filename); + let path = Self::path(backup_dir, start_time); let tar_gz = File::create(path)?; let enc = GzEncoder::new(tar_gz, Compression::default()); let mut ar = tar::Builder::new(enc); - // TODO remove unwrap - let previous_state = previous.state().unwrap(); + let previous_state = previous + .state() + .map_err(|_| io::Error::new(io::ErrorKind::Other, "No Full ancestor"))?; let mut delta = BackupDelta::new(); for (dir_in_tar, src_dir) in dirs { @@ -337,28 +363,38 @@ impl BackupManager { } /// Remove the oldest backups - pub fn remove_old_backups(&mut self) -> std::io::Result<()> { - // The naming format used allows us to sort the backups by name and still get a sorting by - // creation time - let mut backups = self - .backup_dir - .read_dir()? - .filter_map(|res| res.map(|e| e.path()).ok()) - .collect::>(); - backups.sort(); + // pub fn remove_old_backups(&mut self) -> std::io::Result<()> { + // if let Some(last_backup) = &self.last_backup { + // let last_valid_ancestor = last_backup.ancestor(self.max_backups - 1); + // let ancestor = last_valid_ancestor.previous(); - let max_backups: usize = self.max_backups.try_into().unwrap(); + // while let Some(backup) = &ancestor { + // let path = Backup::path(&self.backup_dir, backup.start_time); + // std::fs::remove_file(path)?; + // } + // } - if backups.len() > max_backups { - let excess_backups = backups.len() - max_backups; + // // The naming format used allows us to sort the backups by name and still get a sorting by + // // creation time + // let mut backups = self + // .backup_dir + // .read_dir()? + // .filter_map(|res| res.map(|e| e.path()).ok()) + // .collect::>(); + // backups.sort(); - for backup in &backups[0..excess_backups] { - std::fs::remove_file(backup)?; - } - } + // let max_backups: usize = self.max_backups.try_into().unwrap(); - Ok(()) - } + // if backups.len() > max_backups { + // let excess_backups = backups.len() - max_backups; + + // for backup in &backups[0..excess_backups] { + // std::fs::remove_file(backup)?; + // } + // } + + // Ok(()) + // } pub fn write_json(&self) -> std::io::Result<()> { // Put the backup chain into a list that can be serialized @@ -385,9 +421,7 @@ impl BackupManager { let previous = Arc::clone(&backups[i - 1]); // We can unwrap here, as this function creates the first instance of each Arc, // meaning we're definitely the only pointer. - Arc::get_mut(&mut backups[i]) - .unwrap() - .set_previous(previous); + Arc::get_mut(&mut backups[i]).unwrap().previous = Some(previous); } self.last_backup = Some(Arc::clone(backups.last().unwrap())); diff --git a/src/server/process.rs b/src/server/process.rs index fbd806a..d784061 100644 --- a/src/server/process.rs +++ b/src/server/process.rs @@ -70,9 +70,9 @@ impl ServerProcess { let start_time = chrono::offset::Utc::now(); let res = self.backups.create_backup(); - if res.is_ok() { - self.backups.remove_old_backups()?; - } + // if res.is_ok() { + // self.backups.remove_old_backups()?; + // } // The server's save feature needs to be enabled again even if the archive failed to create self.custom("save-on")?;