From b48c531d80d08b0772e264bf1249fc653fe90d48 Mon Sep 17 00:00:00 2001 From: Chewing_Bever Date: Sun, 18 Jun 2023 22:45:35 +0200 Subject: [PATCH] feat: configurable parameters for incremental backups --- CHANGELOG.md | 10 +++++++++- src/cli.rs | 15 ++++++++++++--- src/main.rs | 10 ++++++---- src/server/backups.rs | 29 +++++++++++------------------ src/server/command.rs | 18 +++++++++++++----- 5 files changed, 51 insertions(+), 31 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index e2ec666..8157f9e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,12 +9,20 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Added -* Added `backup` CLI command +* `backup` CLI command +* Incremental backups + * Chain length descibres how many incremental backups to create from the + same full backup + * "backups to keep" has been replaced by "chains to keep" ### Changed * Running the server now uses the `run` CLI subcommand +### Removed + +* `max_backups` setting + ## [0.2.2](https://git.rustybever.be/Chewing_Bever/alex/src/tag/0.2.2) ### Fixed diff --git a/src/cli.rs b/src/cli.rs index 3c588aa..613dfa1 100644 --- a/src/cli.rs +++ b/src/cli.rs @@ -35,15 +35,24 @@ pub struct Cli { )] pub backup: PathBuf, - /// How many backups to keep + /// Length of a backup chain + #[arg( + short = 'l', + long, + default_value_t = 4, + env = "ALEX_CHAIN_LEN", + global = true + )] + pub chain_len: u64, + /// How many backup chains to keep #[arg( short = 'n', long, default_value_t = 7, - env = "ALEX_MAX_BACKUPS", + env = "ALEX_CHAINS", global = true )] - pub max_backups: u64, + pub chains: u64, } #[derive(Subcommand)] diff --git a/src/main.rs b/src/main.rs index c057db2..1898e90 100644 --- a/src/main.rs +++ b/src/main.rs @@ -32,7 +32,8 @@ fn command_run(cli: &Cli, args: &RunArgs) -> io::Result<()> { .backup(cli.backup.clone()) .xms(args.xms) .xmx(args.xmx) - .max_backups(cli.max_backups); + .chain_len(cli.chain_len) + .chains_to_keep(cli.chains); cmd.canonicalize()?; if args.dry { @@ -58,12 +59,13 @@ fn command_run(cli: &Cli, args: &RunArgs) -> io::Result<()> { } fn commands_backup(cli: &Cli, _args: &BackupArgs) -> io::Result<()> { - let mut manager = server::BackupManager::open( + let mut manager = server::BackupManager::new( cli.backup.clone(), cli.config.clone(), cli.world.clone(), - cli.max_backups, - )?; + cli.chain_len, + cli.chains, + ); manager.create_backup()?; manager.remove_old_backups() diff --git a/src/server/backups.rs b/src/server/backups.rs index 82d56a7..c8f235a 100644 --- a/src/server/backups.rs +++ b/src/server/backups.rs @@ -1,5 +1,5 @@ use crate::server::path::PathExt; -use chrono::{Local, Utc}; +use chrono::Utc; use flate2::write::GzEncoder; use flate2::Compression; use serde::{Deserialize, Serialize}; @@ -7,7 +7,6 @@ use std::collections::{HashMap, HashSet}; use std::fs::File; use std::io; use std::path::{Path, PathBuf}; -use std::sync::Arc; #[link(name = "c")] extern "C" { @@ -21,13 +20,6 @@ pub enum BackupType { Incremental, } -#[derive(Debug)] -pub enum BackupError { - NoFullAncestor, -} - -type BackupResult = Result; - /// Represents the changes relative to the previous backup #[derive(Debug, Serialize, Deserialize)] pub struct BackupDelta { @@ -113,6 +105,8 @@ pub struct Backup { impl Backup { const FILENAME_FORMAT: &str = "%Y-%m-%d_%H-%M-%S.tar.gz"; + /// Resolve the state of the list of backups by applying their deltas in-order to an initially + /// empty state. pub fn state(backups: &Vec) -> HashMap> { let mut state: HashMap> = HashMap::new(); @@ -232,29 +226,27 @@ pub struct BackupManager { world_dir: PathBuf, chain_len: u64, chains_to_keep: u64, - max_backups: u64, - last_backup: Option>, chains: Vec>, } impl BackupManager { const METADATA_FILE: &str = "alex.json"; + /// Initialize a new instance of a `BackupManager`. pub fn new( backup_dir: PathBuf, config_dir: PathBuf, world_dir: PathBuf, - max_backups: u64, + chain_len: u64, + chains_to_keep: u64, ) -> Self { BackupManager { backup_dir, config_dir, world_dir, - max_backups, - chain_len: 2, - chains_to_keep: 1, + chain_len, + chains_to_keep, chains: Vec::new(), - last_backup: None, } } @@ -262,9 +254,10 @@ impl BackupManager { backup_dir: PathBuf, config_dir: PathBuf, world_dir: PathBuf, - max_backups: u64, + chain_len: u64, + chains_to_keep: u64, ) -> std::io::Result { - let mut manager = Self::new(backup_dir, config_dir, world_dir, max_backups); + let mut manager = Self::new(backup_dir, config_dir, world_dir, chain_len, chains_to_keep); manager.load_json()?; Ok(manager) diff --git a/src/server/command.rs b/src/server/command.rs index 1c44d5b..fa92804 100644 --- a/src/server/command.rs +++ b/src/server/command.rs @@ -35,7 +35,8 @@ pub struct ServerCommand { backup_dir: PathBuf, xms: u64, xmx: u64, - max_backups: u64, + chain_len: u64, + chains_to_keep: u64, } impl ServerCommand { @@ -50,7 +51,8 @@ impl ServerCommand { backup_dir: PathBuf::from("backups"), xms: 1024, xmx: 2048, - max_backups: 7, + chain_len: 4, + chains_to_keep: 7, } } @@ -91,8 +93,13 @@ impl ServerCommand { self } - pub fn max_backups(mut self, v: u64) -> Self { - self.max_backups = v; + pub fn chain_len(mut self, v: u64) -> Self { + self.chain_len = v; + self + } + + pub fn chains_to_keep(mut self, v: u64) -> Self { + self.chains_to_keep = v; self } @@ -183,7 +190,8 @@ impl ServerCommand { self.backup_dir.clone(), self.config_dir.clone(), self.world_dir.clone(), - self.max_backups, + self.chain_len, + self.chains_to_keep, )?; let mut cmd = self.create_cmd(); self.accept_eula()?;