Nice error when remote storage is not mounted

fastcdc speedup
This commit is contained in:
Dennis Schwerdel 2017-04-08 15:10:02 +02:00 committed by Dennis Schwerdel
parent a29e95e4f4
commit ccc76dc713
5 changed files with 32 additions and 15 deletions

View File

@ -12,9 +12,10 @@
## Usability
* Verbosity control
* Error: Backup already exists
* Backup directories as a thing (list, remove)
* Display backup name and path on backup integrity error
* Better control over what is checked in `check` subcommand
* Nice error when remote storage is not mounted
* Man pages for all minor subcommands
## Code quality

View File

@ -81,39 +81,46 @@ impl IChunker for FastCdcChunker {
}
#[allow(unknown_lints,explicit_counter_loop)]
#[allow(unknown_lints,explicit_counter_loop,needless_range_loop)]
fn chunk<R: Read, W: Write>(&mut self, r: &mut R, mut w: &mut W) -> Result<ChunkerStatus, ChunkerError> {
let mut max;
let mut hash = 0u64;
let mut pos = 0;
let gear = &self.gear;
let buffer = &mut self.buffer;
let min_size = self.min_size;
let mask_short = self.mask_short;
let mask_long = self.mask_long;
let avg_size = self.avg_size;
let max_size = self.max_size;
loop {
// Fill the buffer, there might be some bytes still in there from last chunk
max = try!(r.read(&mut self.buffer[self.buffered..]).map_err(ChunkerError::Read)) + self.buffered;
max = try!(r.read(&mut buffer[self.buffered..]).map_err(ChunkerError::Read)) + self.buffered;
// If nothing to do, finish
if max == 0 {
return Ok(ChunkerStatus::Finished)
}
for i in 0..max {
if pos >= self.min_size {
if pos >= min_size {
// Hash update
hash = (hash << 1).wrapping_add(self.gear[self.buffer[i] as usize]);
hash = (hash << 1).wrapping_add(gear[buffer[i] as usize]);
// 3 options for break point
// 1) mask_short matches and chunk is smaller than average
// 2) mask_long matches and chunk is longer or equal to average
// 3) chunk reached max_size
if pos < self.avg_size && hash & self.mask_short == 0
|| pos >= self.avg_size && hash & self.mask_long == 0
|| pos >= self.max_size {
if pos < avg_size && hash & mask_short == 0
|| pos >= avg_size && hash & mask_long == 0
|| pos >= max_size {
// Write all bytes from this chunk out to sink and store rest for next chunk
try!(w.write_all(&self.buffer[..i+1]).map_err(ChunkerError::Write));
unsafe { ptr::copy(self.buffer[i+1..].as_ptr(), self.buffer.as_mut_ptr(), max-i-1) };
try!(w.write_all(&buffer[..i+1]).map_err(ChunkerError::Write));
unsafe { ptr::copy(buffer[i+1..].as_ptr(), buffer.as_mut_ptr(), max-i-1) };
self.buffered = max-i-1;
return Ok(ChunkerStatus::Continue);
}
}
pos += 1;
}
try!(w.write_all(&self.buffer[..max]).map_err(ChunkerError::Write));
try!(w.write_all(&buffer[..max]).map_err(ChunkerError::Write));
self.buffered = 0;
}
}

View File

@ -14,6 +14,10 @@ quick_error!{
#[derive(Debug)]
#[allow(unknown_lints,large_enum_variant)]
pub enum RepositoryError {
NoRemote {
description("Remote storage not found")
display("Repository error: The remote storage has not been found, may be it needs to be mounted?")
}
Index(err: IndexError) {
from()
cause(err)

View File

@ -46,6 +46,10 @@ impl RepositoryLayout {
self.0.join("remote")
}
pub fn remote_exists(&self) -> bool {
self.remote_bundles_path().exists() && self.backups_path().exists() && self.remote_locks_path().exists()
}
pub fn remote_readme_path(&self) -> PathBuf {
self.0.join("remote/README.md")
}

View File

@ -54,8 +54,7 @@ pub struct Repository {
impl Repository {
pub fn create<P: AsRef<Path>, R: AsRef<Path>>(path: P, config: Config, remote: R) -> Result<Self, RepositoryError> {
let path = path.as_ref().to_owned();
let layout = RepositoryLayout::new(path.clone());
let layout = RepositoryLayout::new(path.as_ref().to_path_buf());
try!(fs::create_dir(layout.base_path()));
try!(File::create(layout.excludes_path()).and_then(|mut f| f.write_all(DEFAULT_EXCLUDES)));
try!(fs::create_dir(layout.keys_path()));
@ -71,8 +70,10 @@ impl Repository {
}
pub fn open<P: AsRef<Path>>(path: P) -> Result<Self, RepositoryError> {
let path = path.as_ref().to_owned();
let layout = RepositoryLayout::new(path.clone());
let layout = RepositoryLayout::new(path.as_ref().to_path_buf());
if !layout.remote_exists() {
return Err(RepositoryError::NoRemote)
}
let config = try!(Config::load(layout.config_path()));
let locks = LockFolder::new(layout.remote_locks_path());
let crypto = Arc::new(Mutex::new(try!(Crypto::open(layout.keys_path()))));