mirror of
https://github.com/dswd/zvault
synced 2025-01-10 14:27:54 +00:00
Recover from missing index and bundle map by rebuilding those
This commit is contained in:
parent
ccc76dc713
commit
0b3ab57335
1
TODO.md
1
TODO.md
@ -8,7 +8,6 @@
|
|||||||
|
|
||||||
## Stability / Reliability
|
## Stability / Reliability
|
||||||
* Lock the local repository to avoid index corruption
|
* Lock the local repository to avoid index corruption
|
||||||
* Recover from missing index, bundle cache and bundle map by rebuilding those
|
|
||||||
|
|
||||||
## Usability
|
## Usability
|
||||||
* Verbosity control
|
* Verbosity control
|
||||||
|
@ -125,9 +125,6 @@ pub enum Arguments {
|
|||||||
compression: Option<Compression>,
|
compression: Option<Compression>,
|
||||||
encrypt: bool,
|
encrypt: bool,
|
||||||
hash: HashMethod
|
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))))
|
.validator(|val| validate_repo_path(val, true, Some(false), Some(false))))
|
||||||
.arg(Arg::from_usage("[FILE] 'File containing the keypair'")
|
.arg(Arg::from_usage("[FILE] 'File containing the keypair'")
|
||||||
.required_unless("generate").validator(validate_existing_path)))
|
.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")
|
.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'")
|
.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))
|
.default_value(DEFAULT_BUNDLE_SIZE_STR).validator(validate_num))
|
||||||
@ -553,12 +547,6 @@ pub fn parse() -> Result<Arguments, ErrorCode> {
|
|||||||
repo_path: repository.to_string()
|
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)) => {
|
("import", Some(args)) => {
|
||||||
let (repository, _backup, _inode) = parse_repo_path(args.value_of("REPO").unwrap(), false, Some(false), Some(false)).unwrap();
|
let (repository, _backup, _inode) = parse_repo_path(args.value_of("REPO").unwrap(), false, Some(false), Some(false)).unwrap();
|
||||||
Ok(Arguments::Import {
|
Ok(Arguments::Import {
|
||||||
|
@ -24,7 +24,7 @@ pub enum ErrorCode {
|
|||||||
SaveConfig,
|
SaveConfig,
|
||||||
LoadExcludes, InvalidExcludes,
|
LoadExcludes, InvalidExcludes,
|
||||||
BackupRun, RestoreRun, RemoveRun, PruneRun, VacuumRun, CheckRun, AnalyzeRun, DiffRun,
|
BackupRun, RestoreRun, RemoveRun, PruneRun, VacuumRun, CheckRun, AnalyzeRun, DiffRun,
|
||||||
VersionsRun, ImportRun, FuseMount, RebuildIndexRun
|
VersionsRun, ImportRun, FuseMount
|
||||||
}
|
}
|
||||||
impl ErrorCode {
|
impl ErrorCode {
|
||||||
pub fn code(&self) -> i32 {
|
pub fn code(&self) -> i32 {
|
||||||
@ -58,8 +58,7 @@ impl ErrorCode {
|
|||||||
ErrorCode::DiffRun => 21,
|
ErrorCode::DiffRun => 21,
|
||||||
ErrorCode::VersionsRun => 22,
|
ErrorCode::VersionsRun => 22,
|
||||||
ErrorCode::ImportRun => 23,
|
ErrorCode::ImportRun => 23,
|
||||||
ErrorCode::FuseMount => 24,
|
ErrorCode::FuseMount => 24
|
||||||
ErrorCode::RebuildIndexRun => 25
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -482,10 +481,6 @@ pub fn run() -> Result<(), ErrorCode> {
|
|||||||
let mut repo = try!(open_repository(&repo_path));
|
let mut repo = try!(open_repository(&repo_path));
|
||||||
print_analysis(&checked!(repo.analyze_usage(), "analyze repository", ErrorCode::AnalyzeRun));
|
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} => {
|
Arguments::BundleList{repo_path} => {
|
||||||
let repo = try!(open_repository(&repo_path));
|
let repo = try!(open_repository(&repo_path));
|
||||||
for bundle in repo.list_bundles() {
|
for bundle in repo.list_bundles() {
|
||||||
|
@ -78,8 +78,20 @@ impl Repository {
|
|||||||
let locks = LockFolder::new(layout.remote_locks_path());
|
let locks = LockFolder::new(layout.remote_locks_path());
|
||||||
let crypto = Arc::new(Mutex::new(try!(Crypto::open(layout.keys_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 (bundles, new, gone) = try!(BundleDb::open(layout.clone(), crypto.clone()));
|
||||||
let index = try!(Index::open(layout.index_path()));
|
let (index, mut rebuild_index) = match Index::open(layout.index_path()) {
|
||||||
let bundle_map = try!(BundleMap::load(layout.bundle_map_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 {
|
let mut repo = Repository {
|
||||||
layout: layout,
|
layout: layout,
|
||||||
chunker: config.chunker.create(),
|
chunker: config.chunker.create(),
|
||||||
@ -103,6 +115,13 @@ impl Repository {
|
|||||||
try!(repo.save_bundle_map());
|
try!(repo.save_bundle_map());
|
||||||
repo.next_meta_bundle = repo.next_free_bundle_id();
|
repo.next_meta_bundle = repo.next_free_bundle_id();
|
||||||
repo.next_data_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)
|
Ok(repo)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -208,7 +227,26 @@ impl Repository {
|
|||||||
Ok(())
|
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();
|
self.index.clear();
|
||||||
for (num, id) in self.bundle_map.bundles() {
|
for (num, id) in self.bundle_map.bundles() {
|
||||||
let chunks = try!(self.bundles.get_chunk_list(&id));
|
let chunks = try!(self.bundles.get_chunk_list(&id));
|
||||||
|
Loading…
Reference in New Issue
Block a user