From d5cea49c8b3020bef4cb8f19576e2478e92d10ad Mon Sep 17 00:00:00 2001 From: Chewing_Bever Date: Fri, 23 Jun 2023 14:36:20 +0200 Subject: [PATCH] feat: further generalize backup code --- src/backup/manager/meta.rs | 22 ++++++++++++---------- src/backup/manager/mod.rs | 28 +++++++++++++--------------- src/backup/mod.rs | 14 +++++++------- src/server/command.rs | 13 +++++++------ 4 files changed, 39 insertions(+), 38 deletions(-) diff --git a/src/backup/manager/meta.rs b/src/backup/manager/meta.rs index bf5cc4b..076bf14 100644 --- a/src/backup/manager/meta.rs +++ b/src/backup/manager/meta.rs @@ -6,13 +6,13 @@ use std::collections::HashMap; use std::io; use std::path::PathBuf; +/// Manages a collection of backup layers, allowing them to be utilized as a single object. pub struct MetaManager where T: Clone + Serialize + for<'de> Deserialize<'de>, { backup_dir: PathBuf, - config_dir: PathBuf, - world_dir: PathBuf, + dirs: Vec<(PathBuf, PathBuf)>, default_metadata: T, managers: HashMap>, } @@ -21,21 +21,20 @@ impl MetaManager where T: Clone + Serialize + for<'de> Deserialize<'de>, { - pub fn new, P2: Into, P3: Into>( - backup_dir: P1, - config_dir: P2, - world_dir: P3, + pub fn new>( + backup_dir: P, + dirs: Vec<(PathBuf, PathBuf)>, default_metadata: T, ) -> Self { MetaManager { backup_dir: backup_dir.into(), - config_dir: config_dir.into(), - world_dir: world_dir.into(), + dirs, default_metadata, managers: HashMap::new(), } } + /// Add a new manager to track, initializing it first. pub fn add(&mut self, config: &ManagerConfig) -> io::Result<()> { // Backup dir itself should exist, but we control its contents, so we can create // separate directories for each layer @@ -52,8 +51,7 @@ where let mut manager = Manager::new( path, - self.config_dir.clone(), - self.world_dir.clone(), + self.dirs.clone(), self.default_metadata.clone(), config.chain_len, config.chains, @@ -65,6 +63,7 @@ where Ok(()) } + /// Convenient wrapper for `add`. pub fn add_all(&mut self, configs: &Vec) -> io::Result<()> { for config in configs { self.add(config)?; @@ -73,6 +72,7 @@ where Ok(()) } + /// Return the name of the next scheduled layer, if one or more managers are present. pub fn next_scheduled_layer(&self) -> Option<&str> { self.managers .iter() @@ -80,6 +80,7 @@ where .map(|(k, _)| k.as_str()) } + /// Return the earliest scheduled time for the underlying managers. pub fn next_scheduled_time(&self) -> Option> { self.managers .values() @@ -87,6 +88,7 @@ where .min() } + /// Perform a backup cycle for the earliest scheduled manager. pub fn perform_backup_cycle(&mut self) -> io::Result<()> { if let Some(manager) = self .managers diff --git a/src/backup/manager/mod.rs b/src/backup/manager/mod.rs index 6c991c0..32c452a 100644 --- a/src/backup/manager/mod.rs +++ b/src/backup/manager/mod.rs @@ -12,13 +12,13 @@ use std::fs::File; use std::io; use std::path::PathBuf; +/// Manages a single backup layer consisting of one or more chains of backups. pub struct Manager where T: Clone + Serialize + for<'de> Deserialize<'de>, { backup_dir: PathBuf, - config_dir: PathBuf, - world_dir: PathBuf, + dirs: Vec<(PathBuf, PathBuf)>, default_metadata: T, chain_len: u64, chains_to_keep: u64, @@ -32,10 +32,9 @@ where { const METADATA_FILE: &str = "alex.json"; - pub fn new, P2: Into, P3: Into>( - backup_dir: P1, - config_dir: P2, - world_dir: P3, + pub fn new>( + backup_dir: P, + dirs: Vec<(PathBuf, PathBuf)>, metadata: T, chain_len: u64, chains_to_keep: u64, @@ -43,8 +42,7 @@ where ) -> Self { Self { backup_dir: backup_dir.into(), - config_dir: config_dir.into(), - world_dir: world_dir.into(), + dirs, default_metadata: metadata, chain_len, chains_to_keep, @@ -55,11 +53,6 @@ where /// Create a new backup with the expected type. pub fn create_backup(&mut self) -> io::Result<()> { - let dirs = vec![ - (PathBuf::from("config"), self.config_dir.clone()), - (PathBuf::from("worlds"), self.world_dir.clone()), - ]; - // We start a new chain if the current chain is complete, or if there isn't a first chain // yet if let Some(current_chain) = self.chains.last() { @@ -78,9 +71,14 @@ where let previous_backup = current_chain.last().unwrap(); let state = Backup::state(current_chain); - Backup::create_from(state, previous_backup.start_time, &self.backup_dir, dirs)? + Backup::create_from( + state, + previous_backup.start_time, + &self.backup_dir, + &self.dirs, + )? } else { - Backup::create(&self.backup_dir, dirs)? + Backup::create(&self.backup_dir, &self.dirs)? }; backup.set_metadata(self.default_metadata.clone()); diff --git a/src/backup/mod.rs b/src/backup/mod.rs index 780c557..0168e67 100644 --- a/src/backup/mod.rs +++ b/src/backup/mod.rs @@ -77,7 +77,7 @@ impl Backup { /// The `Backup` instance describing this new backup. pub fn create>( backup_dir: P, - dirs: Vec<(PathBuf, PathBuf)>, + dirs: &Vec<(PathBuf, PathBuf)>, ) -> io::Result { let start_time = chrono::offset::Utc::now(); @@ -93,13 +93,13 @@ impl Backup { for entry in src_dir.read_dir_recursive()?.ignored("cache").files() { let path = entry?.path(); - let stripped = path.strip_prefix(&src_dir).unwrap(); + let stripped = path.strip_prefix(src_dir).unwrap(); ar.append_path_with_name(&path, dir_in_tar.join(stripped))?; added_files.insert(stripped.to_path_buf()); } - delta.added.insert(dir_in_tar, added_files); + delta.added.insert(dir_in_tar.to_path_buf(), added_files); } Ok(Backup { @@ -115,7 +115,7 @@ impl Backup { previous_state: HashMap>, previous_start_time: chrono::DateTime, backup_dir: P, - dirs: Vec<(PathBuf, PathBuf)>, + dirs: &Vec<(PathBuf, PathBuf)>, ) -> io::Result { let start_time = chrono::offset::Utc::now(); @@ -132,7 +132,7 @@ impl Backup { for entry in src_dir.read_dir_recursive()?.ignored("cache").files() { let path = entry?.path(); - let stripped = path.strip_prefix(&src_dir).unwrap(); + let stripped = path.strip_prefix(src_dir).unwrap(); if !path.not_modified_since(previous_start_time) { ar.append_path_with_name(&path, dir_in_tar.join(stripped))?; @@ -144,9 +144,9 @@ impl Backup { delta.added.insert(dir_in_tar.clone(), added_files); - if let Some(previous_files) = previous_state.get(&dir_in_tar) { + if let Some(previous_files) = previous_state.get(dir_in_tar) { delta.removed.insert( - dir_in_tar, + dir_in_tar.to_path_buf(), previous_files.difference(&all_files).cloned().collect(), ); } diff --git a/src/server/command.rs b/src/server/command.rs index ec1b302..258bb86 100644 --- a/src/server/command.rs +++ b/src/server/command.rs @@ -166,12 +166,13 @@ impl ServerCommand { server_type: self.type_, server_version: self.version.clone(), }; - let mut meta = MetaManager::new( - self.backup_dir.clone(), - self.config_dir.clone(), - self.world_dir.clone(), - metadata, - ); + + let dirs = vec![ + (PathBuf::from("config"), self.config_dir.clone()), + (PathBuf::from("worlds"), self.world_dir.clone()), + ]; + + let mut meta = MetaManager::new(self.backup_dir.clone(), dirs, metadata); meta.add_all(&self.managers)?; let mut cmd = self.create_cmd();