mirror of https://github.com/dswd/zvault
Nice error when remote storage is not mounted
fastcdc speedup
This commit is contained in:
parent
a29e95e4f4
commit
ccc76dc713
3
TODO.md
3
TODO.md
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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")
|
||||
}
|
||||
|
|
|
@ -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()))));
|
||||
|
|
Loading…
Reference in New Issue