zvault/src/repository/integrity.rs

87 lines
2.8 KiB
Rust
Raw Normal View History

2017-03-16 08:42:30 +00:00
use super::{Repository, RepositoryError};
2017-03-10 11:43:32 +00:00
2017-03-16 08:42:30 +00:00
use ::bundle::BundleId;
2017-03-10 11:43:32 +00:00
use ::util::Hash;
2017-03-16 08:42:30 +00:00
quick_error!{
#[derive(Debug)]
pub enum RepositoryIntegrityError {
MissingChunk(hash: Hash) {
description("Missing chunk")
display("Missing chunk: {}", hash)
}
MissingBundleId(id: u32) {
description("Missing bundle")
display("Missing bundle: {}", id)
}
MissingBundle(id: BundleId) {
description("Missing bundle")
display("Missing bundle: {}", id)
}
NoSuchChunk(bundle: BundleId, chunk: u32) {
description("No such chunk")
display("Bundle {} does not conain the chunk {}", bundle, chunk)
}
InvalidNextBundleId {
description("Invalid next bundle id")
}
SymlinkWithoutTarget {
description("Symlink without target")
}
}
}
2017-03-10 11:43:32 +00:00
impl Repository {
2017-03-16 08:42:30 +00:00
fn check_chunk(&self, hash: Hash) -> Result<(), RepositoryError> {
2017-03-10 11:43:32 +00:00
// Find bundle and chunk id in index
let found = if let Some(found) = self.index.get(&hash) {
found
} else {
2017-03-16 08:42:30 +00:00
return Err(RepositoryIntegrityError::MissingChunk(hash).into());
2017-03-10 11:43:32 +00:00
};
// Lookup bundle id from map
2017-03-16 08:42:30 +00:00
let bundle_id = try!(self.get_bundle_id(found.bundle));
2017-03-10 11:43:32 +00:00
// Get bundle object from bundledb
let bundle = if let Some(bundle) = self.bundles.get_bundle(&bundle_id) {
bundle
} else {
2017-03-16 08:42:30 +00:00
return Err(RepositoryIntegrityError::MissingBundle(bundle_id.clone()).into())
2017-03-10 11:43:32 +00:00
};
// Get chunk from bundle
2017-03-15 07:27:27 +00:00
if bundle.info.chunk_count > found.chunk as usize {
2017-03-10 11:43:32 +00:00
Ok(())
} else {
2017-03-16 08:42:30 +00:00
Err(RepositoryIntegrityError::NoSuchChunk(bundle_id.clone(), found.chunk).into())
2017-03-10 11:43:32 +00:00
}
//TODO: check that contents match their hash
}
2017-03-16 08:42:30 +00:00
pub fn check(&mut self, full: bool) -> Result<(), RepositoryError> {
2017-03-10 11:43:32 +00:00
try!(self.flush());
2017-03-16 08:42:30 +00:00
try!(self.bundles.check(full));
try!(self.index.check());
2017-03-10 11:43:32 +00:00
let mut pos = 0;
loop {
pos = if let Some(pos) = self.index.next_entry(pos) {
pos
} else {
break
};
let entry = self.index.get_entry(pos).unwrap();
try!(self.check_chunk(entry.key));
pos += 1;
}
if self.next_content_bundle == self.next_meta_bundle {
2017-03-16 08:42:30 +00:00
return Err(RepositoryIntegrityError::InvalidNextBundleId.into())
2017-03-10 11:43:32 +00:00
}
if self.bundle_map.get(self.next_content_bundle).is_some() {
2017-03-16 08:42:30 +00:00
return Err(RepositoryIntegrityError::InvalidNextBundleId.into())
2017-03-10 11:43:32 +00:00
}
if self.bundle_map.get(self.next_meta_bundle).is_some() {
2017-03-16 08:42:30 +00:00
return Err(RepositoryIntegrityError::InvalidNextBundleId.into())
2017-03-10 11:43:32 +00:00
}
Ok(())
}
}