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
|
||||||
|
|
||||||
* 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
|
### Changed
|
||||||
|
|
||||||
* Running the server now uses the `run` CLI subcommand
|
* 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)
|
## [0.2.2](https://git.rustybever.be/Chewing_Bever/alex/src/tag/0.2.2)
|
||||||
|
|
||||||
### Fixed
|
### Fixed
|
||||||
|
|
15
src/cli.rs
15
src/cli.rs
|
@ -35,15 +35,24 @@ pub struct Cli {
|
||||||
)]
|
)]
|
||||||
pub backup: PathBuf,
|
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(
|
#[arg(
|
||||||
short = 'n',
|
short = 'n',
|
||||||
long,
|
long,
|
||||||
default_value_t = 7,
|
default_value_t = 7,
|
||||||
env = "ALEX_MAX_BACKUPS",
|
env = "ALEX_CHAINS",
|
||||||
global = true
|
global = true
|
||||||
)]
|
)]
|
||||||
pub max_backups: u64,
|
pub chains: u64,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Subcommand)]
|
#[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())
|
.backup(cli.backup.clone())
|
||||||
.xms(args.xms)
|
.xms(args.xms)
|
||||||
.xmx(args.xmx)
|
.xmx(args.xmx)
|
||||||
.max_backups(cli.max_backups);
|
.chain_len(cli.chain_len)
|
||||||
|
.chains_to_keep(cli.chains);
|
||||||
cmd.canonicalize()?;
|
cmd.canonicalize()?;
|
||||||
|
|
||||||
if args.dry {
|
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<()> {
|
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.backup.clone(),
|
||||||
cli.config.clone(),
|
cli.config.clone(),
|
||||||
cli.world.clone(),
|
cli.world.clone(),
|
||||||
cli.max_backups,
|
cli.chain_len,
|
||||||
)?;
|
cli.chains,
|
||||||
|
);
|
||||||
|
|
||||||
manager.create_backup()?;
|
manager.create_backup()?;
|
||||||
manager.remove_old_backups()
|
manager.remove_old_backups()
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
use crate::server::path::PathExt;
|
use crate::server::path::PathExt;
|
||||||
use chrono::{Local, Utc};
|
use chrono::Utc;
|
||||||
use flate2::write::GzEncoder;
|
use flate2::write::GzEncoder;
|
||||||
use flate2::Compression;
|
use flate2::Compression;
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
|
@ -7,7 +7,6 @@ use std::collections::{HashMap, HashSet};
|
||||||
use std::fs::File;
|
use std::fs::File;
|
||||||
use std::io;
|
use std::io;
|
||||||
use std::path::{Path, PathBuf};
|
use std::path::{Path, PathBuf};
|
||||||
use std::sync::Arc;
|
|
||||||
|
|
||||||
#[link(name = "c")]
|
#[link(name = "c")]
|
||||||
extern "C" {
|
extern "C" {
|
||||||
|
@ -21,13 +20,6 @@ pub enum BackupType {
|
||||||
Incremental,
|
Incremental,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug)]
|
|
||||||
pub enum BackupError {
|
|
||||||
NoFullAncestor,
|
|
||||||
}
|
|
||||||
|
|
||||||
type BackupResult<T> = Result<T, BackupError>;
|
|
||||||
|
|
||||||
/// Represents the changes relative to the previous backup
|
/// Represents the changes relative to the previous backup
|
||||||
#[derive(Debug, Serialize, Deserialize)]
|
#[derive(Debug, Serialize, Deserialize)]
|
||||||
pub struct BackupDelta {
|
pub struct BackupDelta {
|
||||||
|
@ -113,6 +105,8 @@ pub struct Backup {
|
||||||
impl Backup {
|
impl Backup {
|
||||||
const FILENAME_FORMAT: &str = "%Y-%m-%d_%H-%M-%S.tar.gz";
|
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>> {
|
pub fn state(backups: &Vec<Backup>) -> HashMap<PathBuf, HashSet<PathBuf>> {
|
||||||
let mut state: HashMap<PathBuf, HashSet<PathBuf>> = HashMap::new();
|
let mut state: HashMap<PathBuf, HashSet<PathBuf>> = HashMap::new();
|
||||||
|
|
||||||
|
@ -232,29 +226,27 @@ pub struct BackupManager {
|
||||||
world_dir: PathBuf,
|
world_dir: PathBuf,
|
||||||
chain_len: u64,
|
chain_len: u64,
|
||||||
chains_to_keep: u64,
|
chains_to_keep: u64,
|
||||||
max_backups: u64,
|
|
||||||
last_backup: Option<Arc<Backup>>,
|
|
||||||
chains: Vec<Vec<Backup>>,
|
chains: Vec<Vec<Backup>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl BackupManager {
|
impl BackupManager {
|
||||||
const METADATA_FILE: &str = "alex.json";
|
const METADATA_FILE: &str = "alex.json";
|
||||||
|
|
||||||
|
/// Initialize a new instance of a `BackupManager`.
|
||||||
pub fn new(
|
pub fn new(
|
||||||
backup_dir: PathBuf,
|
backup_dir: PathBuf,
|
||||||
config_dir: PathBuf,
|
config_dir: PathBuf,
|
||||||
world_dir: PathBuf,
|
world_dir: PathBuf,
|
||||||
max_backups: u64,
|
chain_len: u64,
|
||||||
|
chains_to_keep: u64,
|
||||||
) -> Self {
|
) -> Self {
|
||||||
BackupManager {
|
BackupManager {
|
||||||
backup_dir,
|
backup_dir,
|
||||||
config_dir,
|
config_dir,
|
||||||
world_dir,
|
world_dir,
|
||||||
max_backups,
|
chain_len,
|
||||||
chain_len: 2,
|
chains_to_keep,
|
||||||
chains_to_keep: 1,
|
|
||||||
chains: Vec::new(),
|
chains: Vec::new(),
|
||||||
last_backup: None,
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -262,9 +254,10 @@ impl BackupManager {
|
||||||
backup_dir: PathBuf,
|
backup_dir: PathBuf,
|
||||||
config_dir: PathBuf,
|
config_dir: PathBuf,
|
||||||
world_dir: PathBuf,
|
world_dir: PathBuf,
|
||||||
max_backups: u64,
|
chain_len: u64,
|
||||||
|
chains_to_keep: u64,
|
||||||
) -> std::io::Result<Self> {
|
) -> 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()?;
|
manager.load_json()?;
|
||||||
|
|
||||||
Ok(manager)
|
Ok(manager)
|
||||||
|
|
|
@ -35,7 +35,8 @@ pub struct ServerCommand {
|
||||||
backup_dir: PathBuf,
|
backup_dir: PathBuf,
|
||||||
xms: u64,
|
xms: u64,
|
||||||
xmx: u64,
|
xmx: u64,
|
||||||
max_backups: u64,
|
chain_len: u64,
|
||||||
|
chains_to_keep: u64,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ServerCommand {
|
impl ServerCommand {
|
||||||
|
@ -50,7 +51,8 @@ impl ServerCommand {
|
||||||
backup_dir: PathBuf::from("backups"),
|
backup_dir: PathBuf::from("backups"),
|
||||||
xms: 1024,
|
xms: 1024,
|
||||||
xmx: 2048,
|
xmx: 2048,
|
||||||
max_backups: 7,
|
chain_len: 4,
|
||||||
|
chains_to_keep: 7,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -91,8 +93,13 @@ impl ServerCommand {
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn max_backups(mut self, v: u64) -> Self {
|
pub fn chain_len(mut self, v: u64) -> Self {
|
||||||
self.max_backups = v;
|
self.chain_len = v;
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn chains_to_keep(mut self, v: u64) -> Self {
|
||||||
|
self.chains_to_keep = v;
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -183,7 +190,8 @@ impl ServerCommand {
|
||||||
self.backup_dir.clone(),
|
self.backup_dir.clone(),
|
||||||
self.config_dir.clone(),
|
self.config_dir.clone(),
|
||||||
self.world_dir.clone(),
|
self.world_dir.clone(),
|
||||||
self.max_backups,
|
self.chain_len,
|
||||||
|
self.chains_to_keep,
|
||||||
)?;
|
)?;
|
||||||
let mut cmd = self.create_cmd();
|
let mut cmd = self.create_cmd();
|
||||||
self.accept_eula()?;
|
self.accept_eula()?;
|
||||||
|
|
Loading…
Reference in New Issue