diff --git a/CHANGELOG.md b/CHANGELOG.md index a973aea..d961db0 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -13,7 +13,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 * Chain length describes how many incremental backups to create from the same full backup * "backups to keep" has been replaced by "chains to keep" -* Server type & version is now stored as metadata in the metadata file +* Server type & version and backup size are now stored as metadata in the + metadata file * Backup layers * Store multiple chains of backups in parallel, configuring each with different parameters (son-father-grandfather principle) diff --git a/Dockerfile b/Dockerfile index dba2674..7c63117 100644 --- a/Dockerfile +++ b/Dockerfile @@ -47,13 +47,15 @@ COPY --from=builder /app/target/debug/alex /bin/alex RUN chmod +x /bin/alex # Default value to keep users from eating up all ram accidentally -ENV ALEX_XMS=1024 \ +ENV ALEX_CONFIG_DIR=/app/config \ + ALEX_WORLD_DIR=/app/worlds \ + ALEX_BACKUP_DIR=/app/backups \ + ALEX_SERVER=paper \ + ALEX_XMS=1024 \ ALEX_XMX=2048 \ ALEX_JAR=/app/server.jar \ - ALEX_CONFIG_DIR=/app/config \ - ALEX_WORLD_DIR=/app/worlds \ - ALEX_BACKUPS_DIR=/app/backups \ - ALEX_SERVER_VERSION="${MC_VERSION}-${PAPERMC_VERSION}" + ALEX_SERVER_VERSION="${MC_VERSION}-${PAPERMC_VERSION}" \ + ALEX_LAYERS="2min,2,4,4;3min,3,2,2" # Document exposed ports EXPOSE 25565 @@ -62,4 +64,4 @@ EXPOSE 25565 USER paper:paper ENTRYPOINT ["/bin/dumb-init", "--"] -CMD ["/bin/alex", "paper"] +CMD ["/bin/alex", "run"] diff --git a/src/backup/io_ext.rs b/src/backup/io_ext.rs new file mode 100644 index 0000000..30b919e --- /dev/null +++ b/src/backup/io_ext.rs @@ -0,0 +1,43 @@ +use std::io::{self, Write}; + +/// Wrapper around the Write trait that counts how many bytes have been written in total. +/// Heavily inspired by https://stackoverflow.com/a/42189386 +pub struct CountingWrite { + inner: W, + count: usize, +} + +impl CountingWrite +where + W: Write, +{ + pub fn new(writer: W) -> Self { + Self { + inner: writer, + count: 0, + } + } + + pub fn bytes_written(&self) -> usize { + self.count + } +} + +impl Write for CountingWrite +where + W: Write, +{ + fn write(&mut self, buf: &[u8]) -> io::Result { + let res = self.inner.write(buf); + + if let Ok(count) = res { + self.count += count; + } + + res + } + + fn flush(&mut self) -> io::Result<()> { + self.inner.flush() + } +} diff --git a/src/backup/mod.rs b/src/backup/mod.rs index 602df19..e1d6bfb 100644 --- a/src/backup/mod.rs +++ b/src/backup/mod.rs @@ -1,4 +1,5 @@ mod delta; +mod io_ext; pub mod manager; mod path; @@ -30,6 +31,7 @@ pub enum BackupType { pub struct Backup { /// When the backup was started (also corresponds to the name) pub start_time: chrono::DateTime, + pub size: usize, /// Type of the backup pub type_: BackupType, pub delta: Delta, @@ -84,7 +86,7 @@ impl Backup { let start_time = chrono::offset::Utc::now(); let path = Backup::path(backup_dir, start_time); - let tar_gz = File::create(path)?; + let tar_gz = io_ext::CountingWrite::new(File::create(path)?); let enc = GzEncoder::new(tar_gz, Compression::default()); let mut ar = tar::Builder::new(enc); @@ -104,9 +106,16 @@ impl Backup { delta.added.insert(dir_in_tar.to_path_buf(), added_files); } + let mut enc = ar.into_inner()?; + + // The docs recommend running try_finish before unwrapping using finish + enc.try_finish()?; + let tar_gz = enc.finish()?; + Ok(Backup { type_: BackupType::Full, start_time, + size: tar_gz.bytes_written(), delta, metadata: None, }) @@ -122,7 +131,7 @@ impl Backup { let start_time = chrono::offset::Utc::now(); let path = Backup::path(backup_dir, start_time); - let tar_gz = File::create(path)?; + let tar_gz = io_ext::CountingWrite::new(File::create(path)?); let enc = GzEncoder::new(tar_gz, Compression::default()); let mut ar = tar::Builder::new(enc); @@ -154,9 +163,16 @@ impl Backup { } } + let mut enc = ar.into_inner()?; + + // The docs recommend running try_finish before unwrapping using finish + enc.try_finish()?; + let tar_gz = enc.finish()?; + Ok(Backup { type_: BackupType::Incremental, start_time, + size: tar_gz.bytes_written(), delta, metadata: None, })