Enforce ordering for bundles with duplicate chunks (closes #13)

This commit is contained in:
Dennis Schwerdel 2017-04-16 21:06:59 +02:00
parent e0f4f30933
commit ca7153117b
4 changed files with 17 additions and 11 deletions

View File

@ -21,7 +21,7 @@ pub static HEADER_STRING: [u8; 7] = *b"zvault\x01";
pub static HEADER_VERSION: u8 = 1; pub static HEADER_VERSION: u8 = 1;
#[derive(Hash, PartialEq, Eq, Clone, Default)] #[derive(Hash, PartialEq, Eq, Clone, Default, Ord, PartialOrd)]
pub struct BundleId(pub Hash); pub struct BundleId(pub Hash);
impl Serialize for BundleId { impl Serialize for BundleId {

View File

@ -341,13 +341,13 @@ impl Index {
} }
/// Adds the key, data pair into the table. /// Adds the key, data pair into the table.
/// If the key existed in the table before, it is overwritten and false is returned. /// If the key existed the old data is returned.
/// Otherwise it will be added to the table and true is returned. pub fn set(&mut self, key: &Hash, data: &Location) -> Result<Option<Location>, IndexError> {
pub fn set(&mut self, key: &Hash, data: &Location) -> Result<bool, IndexError> {
match self.locate(key) { match self.locate(key) {
LocateResult::Found(pos) => { LocateResult::Found(pos) => {
self.data[pos].data = *data; let mut old = *data;
Ok(false) mem::swap(&mut old, &mut self.data[pos].data);
Ok(Some(old))
}, },
LocateResult::Hole(pos) => { LocateResult::Hole(pos) => {
{ {
@ -356,7 +356,7 @@ impl Index {
entry.data = *data; entry.data = *data;
} }
try!(self.increase_count()); try!(self.increase_count());
Ok(true) Ok(None)
}, },
LocateResult::Steal(pos) => { LocateResult::Steal(pos) => {
let mut stolen_key; let mut stolen_key;
@ -382,7 +382,7 @@ impl Index {
} }
} }
try!(self.increase_count()); try!(self.increase_count());
Ok(true) Ok(None)
} }
} }
} }

View File

@ -268,7 +268,7 @@ impl Repository {
BundleMode::Meta => self.next_meta_bundle BundleMode::Meta => self.next_meta_bundle
}; };
let chunks = try!(self.bundles.get_chunk_list(&bundle.id)); let chunks = try!(self.bundles.get_chunk_list(&bundle.id));
self.bundle_map.set(bundle_id, bundle.id); self.bundle_map.set(bundle_id, bundle.id.clone());
if self.next_meta_bundle == bundle_id { if self.next_meta_bundle == bundle_id {
self.next_meta_bundle = self.next_free_bundle_id() self.next_meta_bundle = self.next_free_bundle_id()
} }
@ -276,7 +276,13 @@ impl Repository {
self.next_data_bundle = self.next_free_bundle_id() self.next_data_bundle = self.next_free_bundle_id()
} }
for (i, (hash, _len)) in chunks.into_inner().into_iter().enumerate() { for (i, (hash, _len)) in chunks.into_inner().into_iter().enumerate() {
try!(self.index.set(&hash, &Location{bundle: bundle_id as u32, chunk: i as u32})); if let Some(old) = try!(self.index.set(&hash, &Location{bundle: bundle_id as u32, chunk: i as u32})) {
// Duplicate chunk, forced ordering: higher bundle id wins
let old_bundle_id = try!(self.get_bundle_id(old.bundle));
if old_bundle_id > bundle.id {
try!(self.index.set(&hash, &old));
}
}
} }
Ok(()) Ok(())
} }

View File

@ -13,7 +13,7 @@ use std::io::{self, Read, Write};
#[repr(packed)] #[repr(packed)]
#[derive(Clone, Copy, PartialEq, Hash, Eq, Default)] #[derive(Clone, Copy, PartialEq, Hash, Eq, Default, Ord, PartialOrd)]
pub struct Hash { pub struct Hash {
pub high: u64, pub high: u64,
pub low: u64 pub low: u64