Combine smaller bundles into larger ones (closes #15)

This commit is contained in:
Dennis Schwerdel 2017-04-17 16:31:58 +02:00
parent 001a36a1eb
commit d18cb17281
5 changed files with 35 additions and 5 deletions

View File

@ -43,6 +43,11 @@ should be avoided when the storage space permits it.
## OPTIONS ## OPTIONS
* `--combine`:
Also combine small bundles into larger ones.
* `-r`, `--ratio <NUM>`: * `-r`, `--ratio <NUM>`:
Do not rewrite bundles with more than `NUM`% of used chunks. Do not rewrite bundles with more than `NUM`% of used chunks.

View File

@ -52,7 +52,8 @@ pub enum Arguments {
Vacuum { Vacuum {
repo_path: String, repo_path: String,
ratio: f32, ratio: f32,
force: bool force: bool,
combine: bool
}, },
Check { Check {
repo_path: String, 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") .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'") .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)) .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("-f --force 'Actually run the vacuum instead of simulating it'"))
.arg(Arg::from_usage("<REPO> 'Path of the repository'") .arg(Arg::from_usage("<REPO> 'Path of the repository'")
.validator(|val| validate_repo_path(val, true, Some(false), Some(false))))) .validator(|val| validate_repo_path(val, true, Some(false), Some(false)))))
@ -490,6 +492,7 @@ pub fn parse() -> Result<(LogLevel, Arguments), ErrorCode> {
Arguments::Vacuum { Arguments::Vacuum {
repo_path: repository.to_string(), repo_path: repository.to_string(),
force: args.is_present("force"), force: args.is_present("force"),
combine: args.is_present("combine"),
ratio: parse_num(args.value_of("ratio").unwrap()).unwrap() as f32 / 100.0 ratio: parse_num(args.value_of("ratio").unwrap()).unwrap() as f32 / 100.0
} }
}, },

View File

@ -435,10 +435,10 @@ pub fn run() -> Result<(), ErrorCode> {
info!("Run with --force to actually execute this command"); 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 mut repo = try!(open_repository(&repo_path));
let info_before = repo.info(); let info_before = repo.info();
checked!(repo.vacuum(ratio, force), "vacuum", ErrorCode::VacuumRun); checked!(repo.vacuum(ratio, combine, force), "vacuum", ErrorCode::VacuumRun);
if !force { if !force {
info!("Run with --force to actually execute this command"); info!("Run with --force to actually execute this command");
} else { } else {

View File

@ -284,7 +284,7 @@ impl Repository {
}, },
Err(err) => return Err(err) 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); let path = format!("{}::", name);
match self.check_subtree(Path::new(&path).to_path_buf(), &backup.root, &mut checked, repair) { match self.check_subtree(Path::new(&path).to_path_buf(), &backup.root, &mut checked, repair) {
Ok(None) => (), Ok(None) => (),

View File

@ -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()); try!(self.flush());
info!("Locking repository"); info!("Locking repository");
try!(self.write_mode()); try!(self.write_mode());
@ -36,6 +36,28 @@ impl Repository {
reclaim_space += bundle.get_unused_size(); 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()); info!("Reclaiming {} by rewriting {} bundles", to_file_size(reclaim_space as u64), rewrite_bundles.len());
if !force { if !force {
self.dirty = false; self.dirty = false;