diff --git a/docs/man/zvault-vacuum.1.md b/docs/man/zvault-vacuum.1.md index 2520049..cce7432 100644 --- a/docs/man/zvault-vacuum.1.md +++ b/docs/man/zvault-vacuum.1.md @@ -43,6 +43,11 @@ should be avoided when the storage space permits it. ## OPTIONS + * `--combine`: + + Also combine small bundles into larger ones. + + * `-r`, `--ratio `: Do not rewrite bundles with more than `NUM`% of used chunks. diff --git a/src/cli/args.rs b/src/cli/args.rs index 2dba5e0..c587546 100644 --- a/src/cli/args.rs +++ b/src/cli/args.rs @@ -52,7 +52,8 @@ pub enum Arguments { Vacuum { repo_path: String, ratio: f32, - force: bool + force: bool, + combine: bool }, Check { repo_path: String, @@ -337,6 +338,7 @@ pub fn parse() -> Result<(LogLevel, Arguments), ErrorCode> { .subcommand(SubCommand::with_name("vacuum").about("Reclaim space by rewriting bundles") .arg(Arg::from_usage("-r --ratio [NUM] 'Ratio in % of unused space in a bundle to rewrite that bundle'") .default_value(DEFAULT_VACUUM_RATIO_STR).validator(validate_num)) + .arg(Arg::from_usage("--combine 'Combine small bundles into larger ones'")) .arg(Arg::from_usage("-f --force 'Actually run the vacuum instead of simulating it'")) .arg(Arg::from_usage(" 'Path of the repository'") .validator(|val| validate_repo_path(val, true, Some(false), Some(false))))) @@ -490,6 +492,7 @@ pub fn parse() -> Result<(LogLevel, Arguments), ErrorCode> { Arguments::Vacuum { repo_path: repository.to_string(), force: args.is_present("force"), + combine: args.is_present("combine"), ratio: parse_num(args.value_of("ratio").unwrap()).unwrap() as f32 / 100.0 } }, diff --git a/src/cli/mod.rs b/src/cli/mod.rs index a82b416..f8d0b55 100644 --- a/src/cli/mod.rs +++ b/src/cli/mod.rs @@ -435,10 +435,10 @@ pub fn run() -> Result<(), ErrorCode> { info!("Run with --force to actually execute this command"); } }, - Arguments::Vacuum{repo_path, ratio, force} => { + Arguments::Vacuum{repo_path, ratio, force, combine} => { let mut repo = try!(open_repository(&repo_path)); let info_before = repo.info(); - checked!(repo.vacuum(ratio, force), "vacuum", ErrorCode::VacuumRun); + checked!(repo.vacuum(ratio, combine, force), "vacuum", ErrorCode::VacuumRun); if !force { info!("Run with --force to actually execute this command"); } else { diff --git a/src/repository/integrity.rs b/src/repository/integrity.rs index 084f3fb..7ed0c46 100644 --- a/src/repository/integrity.rs +++ b/src/repository/integrity.rs @@ -284,7 +284,7 @@ impl Repository { }, Err(err) => return Err(err) }; - for (name, mut backup) in ProgressIter::new("ckecking backups", backup_map.len(), backup_map.into_iter()) { + for (name, mut backup) in ProgressIter::new("checking backups", backup_map.len(), backup_map.into_iter()) { let path = format!("{}::", name); match self.check_subtree(Path::new(&path).to_path_buf(), &backup.root, &mut checked, repair) { Ok(None) => (), diff --git a/src/repository/vacuum.rs b/src/repository/vacuum.rs index 3b95b80..6f30de6 100644 --- a/src/repository/vacuum.rs +++ b/src/repository/vacuum.rs @@ -13,7 +13,7 @@ impl Repository { } } - pub fn vacuum(&mut self, ratio: f32, force: bool) -> Result<(), RepositoryError> { + pub fn vacuum(&mut self, ratio: f32, combine: bool, force: bool) -> Result<(), RepositoryError> { try!(self.flush()); info!("Locking repository"); try!(self.write_mode()); @@ -36,6 +36,28 @@ impl Repository { reclaim_space += bundle.get_unused_size(); } } + if combine { + let mut small_meta = vec![]; + let mut small_data = vec![]; + for (id, bundle) in &usage { + if bundle.info.encoded_size * 4 < self.config.bundle_size { + match bundle.info.mode { + BundleMode::Meta => small_meta.push(*id), + BundleMode::Data => small_data.push(*id), + } + } + } + if small_meta.len() >= 2 { + for bundle in small_meta { + rewrite_bundles.insert(bundle); + } + } + if small_data.len() >= 2 { + for bundle in small_data { + rewrite_bundles.insert(bundle); + } + } + } info!("Reclaiming {} by rewriting {} bundles", to_file_size(reclaim_space as u64), rewrite_bundles.len()); if !force { self.dirty = false;