diff --git a/src/bundledb/db.rs b/src/bundledb/db.rs index 1ff3192..f437c43 100644 --- a/src/bundledb/db.rs +++ b/src/bundledb/db.rs @@ -69,7 +69,7 @@ pub fn load_bundles(path: &Path, base: &Path, bundles: &mut HashMap Result<(), BundleDbError> { for bundle in new { if bundle.info.mode == BundleMode::Meta { - info!("Copying new meta bundle to local cache: {}", bundle.info.id); + debug!("Copying new meta bundle to local cache: {}", bundle.info.id); try!(self.copy_remote_bundle_to_cache(bundle)); } } @@ -304,4 +304,10 @@ impl BundleDb { } Ok(()) } + + #[inline] + pub fn len(&self) -> usize { + self.remote_bundles.len() + } + } diff --git a/src/repository/bundle_map.rs b/src/repository/bundle_map.rs index c5fb0a4..9611798 100644 --- a/src/repository/bundle_map.rs +++ b/src/repository/bundle_map.rs @@ -96,4 +96,9 @@ impl BundleMap { pub fn bundles(&self) -> Vec<(u32, BundleId)> { self.0.iter().map(|(id, bundle)| (*id, bundle.clone())).collect() } + + #[inline] + pub fn len(&self) -> usize { + self.0.len() + } } diff --git a/src/repository/integrity.rs b/src/repository/integrity.rs index f804a4c..fc3c140 100644 --- a/src/repository/integrity.rs +++ b/src/repository/integrity.rs @@ -23,6 +23,12 @@ quick_error!{ description("No such chunk") display("Bundle {} does not contain the chunk {}", bundle, chunk) } + RemoteBundlesNotInMap { + description("Remote bundles missing from map") + } + MapContainsDuplicates { + description("Map contains duplicates") + } InvalidNextBundleId { description("Invalid next bundle id") } @@ -158,12 +164,30 @@ impl Repository { Ok(()) } + fn check_bundle_map(&mut self) -> Result<(), RepositoryError> { + for (_id, bundle_id) in self.bundle_map.bundles() { + if self.bundles.get_bundle_info(&bundle_id).is_none() { + return Err(IntegrityError::MissingBundle(bundle_id).into()) + } + } + if self.bundle_map.len() < self.bundles.len() { + return Err(IntegrityError::RemoteBundlesNotInMap.into()) + } + if self.bundle_map.len() > self.bundles.len() { + return Err(IntegrityError::MapContainsDuplicates.into()) + } + Ok(()) + } + pub fn check(&mut self, full: bool) -> Result<(), RepositoryError> { try!(self.flush()); info!("Checking bundle integrity..."); try!(self.bundles.check(full)); info!("Checking index integrity..."); try!(self.index.check()); + info!("Checking bundle map..."); + try!(self.check_bundle_map()); + info!("Checking index entries..."); try!(self.check_index_chunks()); info!("Checking backup integrity..."); try!(self.check_backups()); diff --git a/src/repository/mod.rs b/src/repository/mod.rs index 54234e3..d3df8a0 100644 --- a/src/repository/mod.rs +++ b/src/repository/mod.rs @@ -216,6 +216,9 @@ impl Repository { fn add_new_remote_bundle(&mut self, bundle: BundleInfo) -> Result<(), RepositoryError> { debug!("Adding new bundle to index: {}", bundle.id); + if self.bundle_map.find(&bundle.id).is_some() { + return Ok(()) + } let bundle_id = match bundle.mode { BundleMode::Data => self.next_data_bundle, BundleMode::Meta => self.next_meta_bundle @@ -236,6 +239,7 @@ impl Repository { fn rebuild_bundle_map(&mut self) -> Result<(), RepositoryError> { info!("Rebuilding bundle map from bundles"); + self.bundle_map = BundleMap::create(); for bundle in self.bundles.list_bundles() { let bundle_id = match bundle.mode { BundleMode::Data => self.next_data_bundle,