feat: configurable parameters for incremental backups
parent
b51d951688
commit
b48c531d80
10
CHANGELOG.md
10
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
|
||||
|
|
15
src/cli.rs
15
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)]
|
||||
|
|
10
src/main.rs
10
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()
|
||||
|
|
|
@ -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<T> = Result<T, BackupError>;
|
||||
|
||||
/// 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<Backup>) -> HashMap<PathBuf, HashSet<PathBuf>> {
|
||||
let mut state: HashMap<PathBuf, HashSet<PathBuf>> = 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<Arc<Backup>>,
|
||||
chains: Vec<Vec<Backup>>,
|
||||
}
|
||||
|
||||
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<Self> {
|
||||
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)
|
||||
|
|
|
@ -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()?;
|
||||
|
|
Loading…
Reference in New Issue