Recover from missing index and bundle map by rebuilding those

pull/10/head
Dennis Schwerdel 2017-04-08 15:28:01 +02:00 committed by Dennis Schwerdel
parent ccc76dc713
commit 0b3ab57335
4 changed files with 43 additions and 23 deletions

View File

@ -8,7 +8,6 @@
## Stability / Reliability
* Lock the local repository to avoid index corruption
* Recover from missing index, bundle cache and bundle map by rebuilding those
## Usability
* Verbosity control

View File

@ -125,9 +125,6 @@ pub enum Arguments {
compression: Option<Compression>,
encrypt: bool,
hash: HashMethod
},
RebuildIndex {
repo_path: String
}
}
@ -400,9 +397,6 @@ pub fn parse() -> Result<Arguments, ErrorCode> {
.validator(|val| validate_repo_path(val, true, Some(false), Some(false))))
.arg(Arg::from_usage("[FILE] 'File containing the keypair'")
.required_unless("generate").validator(validate_existing_path)))
.subcommand(SubCommand::with_name("rebuild-index").about("Rebuild the index")
.arg(Arg::from_usage("<REPO> 'Path of the repository'")
.validator(|val| validate_repo_path(val, true, Some(false), Some(false)))))
.subcommand(SubCommand::with_name("algotest").about("Test a specific algorithm combination")
.arg(Arg::from_usage("[bundle_size] --bundle-size [SIZE] 'Set the target bundle size in MiB'")
.default_value(DEFAULT_BUNDLE_SIZE_STR).validator(validate_num))
@ -553,12 +547,6 @@ pub fn parse() -> Result<Arguments, ErrorCode> {
repo_path: repository.to_string()
})
},
("rebuild-index", Some(args)) => {
let (repository, _backup, _inode) = parse_repo_path(args.value_of("REPO").unwrap(), true, Some(false), Some(false)).unwrap();
Ok(Arguments::RebuildIndex {
repo_path: repository.to_string()
})
},
("import", Some(args)) => {
let (repository, _backup, _inode) = parse_repo_path(args.value_of("REPO").unwrap(), false, Some(false), Some(false)).unwrap();
Ok(Arguments::Import {

View File

@ -24,7 +24,7 @@ pub enum ErrorCode {
SaveConfig,
LoadExcludes, InvalidExcludes,
BackupRun, RestoreRun, RemoveRun, PruneRun, VacuumRun, CheckRun, AnalyzeRun, DiffRun,
VersionsRun, ImportRun, FuseMount, RebuildIndexRun
VersionsRun, ImportRun, FuseMount
}
impl ErrorCode {
pub fn code(&self) -> i32 {
@ -58,8 +58,7 @@ impl ErrorCode {
ErrorCode::DiffRun => 21,
ErrorCode::VersionsRun => 22,
ErrorCode::ImportRun => 23,
ErrorCode::FuseMount => 24,
ErrorCode::RebuildIndexRun => 25
ErrorCode::FuseMount => 24
}
}
}
@ -482,10 +481,6 @@ pub fn run() -> Result<(), ErrorCode> {
let mut repo = try!(open_repository(&repo_path));
print_analysis(&checked!(repo.analyze_usage(), "analyze repository", ErrorCode::AnalyzeRun));
},
Arguments::RebuildIndex{repo_path} => {
let mut repo = try!(open_repository(&repo_path));
checked!(repo.rebuild_index(), "rebuild index", ErrorCode::RebuildIndexRun);
},
Arguments::BundleList{repo_path} => {
let repo = try!(open_repository(&repo_path));
for bundle in repo.list_bundles() {

View File

@ -78,8 +78,20 @@ impl Repository {
let locks = LockFolder::new(layout.remote_locks_path());
let crypto = Arc::new(Mutex::new(try!(Crypto::open(layout.keys_path()))));
let (bundles, new, gone) = try!(BundleDb::open(layout.clone(), crypto.clone()));
let index = try!(Index::open(layout.index_path()));
let bundle_map = try!(BundleMap::load(layout.bundle_map_path()));
let (index, mut rebuild_index) = match Index::open(layout.index_path()) {
Ok(index) => (index, false),
Err(err) => {
error!("Failed to load local index:\n\tcaused by: {}", err);
(try!(Index::create(layout.index_path())), true)
}
};
let (bundle_map, rebuild_bundle_map) = match BundleMap::load(layout.bundle_map_path()) {
Ok(bundle_map) => (bundle_map, false),
Err(err) => {
error!("Failed to load local bundle map:\n\tcaused by: {}", err);
(BundleMap::create(), true)
}
};
let mut repo = Repository {
layout: layout,
chunker: config.chunker.create(),
@ -103,6 +115,13 @@ impl Repository {
try!(repo.save_bundle_map());
repo.next_meta_bundle = repo.next_free_bundle_id();
repo.next_data_bundle = repo.next_free_bundle_id();
if rebuild_bundle_map {
try!(repo.rebuild_bundle_map());
rebuild_index = true;
}
if rebuild_index {
try!(repo.rebuild_index());
}
Ok(repo)
}
@ -208,7 +227,26 @@ impl Repository {
Ok(())
}
pub fn rebuild_index(&mut self) -> Result<(), RepositoryError> {
fn rebuild_bundle_map(&mut self) -> Result<(), RepositoryError> {
info!("Rebuilding bundle map from bundles");
for bundle in self.bundles.list_bundles() {
let bundle_id = match bundle.mode {
BundleMode::Data => self.next_data_bundle,
BundleMode::Meta => self.next_meta_bundle
};
self.bundle_map.set(bundle_id, bundle.id.clone());
if self.next_meta_bundle == bundle_id {
self.next_meta_bundle = self.next_free_bundle_id()
}
if self.next_data_bundle == bundle_id {
self.next_data_bundle = self.next_free_bundle_id()
}
}
self.save_bundle_map()
}
fn rebuild_index(&mut self) -> Result<(), RepositoryError> {
info!("Rebuilding index from bundles");
self.index.clear();
for (num, id) in self.bundle_map.bundles() {
let chunks = try!(self.bundles.get_chunk_list(&id));