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
|
## Usability
|
||||||
* Verbosity control
|
* Verbosity control
|
||||||
|
* Error: Backup already exists
|
||||||
|
* Backup directories as a thing (list, remove)
|
||||||
* Display backup name and path on backup integrity error
|
* Display backup name and path on backup integrity error
|
||||||
* Better control over what is checked in `check` subcommand
|
* Better control over what is checked in `check` subcommand
|
||||||
* Nice error when remote storage is not mounted
|
|
||||||
* Man pages for all minor subcommands
|
* Man pages for all minor subcommands
|
||||||
|
|
||||||
## Code quality
|
## 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> {
|
fn chunk<R: Read, W: Write>(&mut self, r: &mut R, mut w: &mut W) -> Result<ChunkerStatus, ChunkerError> {
|
||||||
let mut max;
|
let mut max;
|
||||||
let mut hash = 0u64;
|
let mut hash = 0u64;
|
||||||
let mut pos = 0;
|
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 {
|
loop {
|
||||||
// Fill the buffer, there might be some bytes still in there from last chunk
|
// 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 nothing to do, finish
|
||||||
if max == 0 {
|
if max == 0 {
|
||||||
return Ok(ChunkerStatus::Finished)
|
return Ok(ChunkerStatus::Finished)
|
||||||
}
|
}
|
||||||
for i in 0..max {
|
for i in 0..max {
|
||||||
if pos >= self.min_size {
|
if pos >= min_size {
|
||||||
// Hash update
|
// 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
|
// 3 options for break point
|
||||||
// 1) mask_short matches and chunk is smaller than average
|
// 1) mask_short matches and chunk is smaller than average
|
||||||
// 2) mask_long matches and chunk is longer or equal to average
|
// 2) mask_long matches and chunk is longer or equal to average
|
||||||
// 3) chunk reached max_size
|
// 3) chunk reached max_size
|
||||||
if pos < self.avg_size && hash & self.mask_short == 0
|
if pos < avg_size && hash & mask_short == 0
|
||||||
|| pos >= self.avg_size && hash & self.mask_long == 0
|
|| pos >= avg_size && hash & mask_long == 0
|
||||||
|| pos >= self.max_size {
|
|| pos >= max_size {
|
||||||
// Write all bytes from this chunk out to sink and store rest for next chunk
|
// 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));
|
try!(w.write_all(&buffer[..i+1]).map_err(ChunkerError::Write));
|
||||||
unsafe { ptr::copy(self.buffer[i+1..].as_ptr(), self.buffer.as_mut_ptr(), max-i-1) };
|
unsafe { ptr::copy(buffer[i+1..].as_ptr(), buffer.as_mut_ptr(), max-i-1) };
|
||||||
self.buffered = max-i-1;
|
self.buffered = max-i-1;
|
||||||
return Ok(ChunkerStatus::Continue);
|
return Ok(ChunkerStatus::Continue);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
pos += 1;
|
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;
|
self.buffered = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -14,6 +14,10 @@ quick_error!{
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
#[allow(unknown_lints,large_enum_variant)]
|
#[allow(unknown_lints,large_enum_variant)]
|
||||||
pub enum RepositoryError {
|
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) {
|
Index(err: IndexError) {
|
||||||
from()
|
from()
|
||||||
cause(err)
|
cause(err)
|
||||||
|
|
|
@ -46,6 +46,10 @@ impl RepositoryLayout {
|
||||||
self.0.join("remote")
|
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 {
|
pub fn remote_readme_path(&self) -> PathBuf {
|
||||||
self.0.join("remote/README.md")
|
self.0.join("remote/README.md")
|
||||||
}
|
}
|
||||||
|
|
|
@ -54,8 +54,7 @@ pub struct Repository {
|
||||||
|
|
||||||
impl Repository {
|
impl Repository {
|
||||||
pub fn create<P: AsRef<Path>, R: AsRef<Path>>(path: P, config: Config, remote: R) -> Result<Self, RepositoryError> {
|
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.as_ref().to_path_buf());
|
||||||
let layout = RepositoryLayout::new(path.clone());
|
|
||||||
try!(fs::create_dir(layout.base_path()));
|
try!(fs::create_dir(layout.base_path()));
|
||||||
try!(File::create(layout.excludes_path()).and_then(|mut f| f.write_all(DEFAULT_EXCLUDES)));
|
try!(File::create(layout.excludes_path()).and_then(|mut f| f.write_all(DEFAULT_EXCLUDES)));
|
||||||
try!(fs::create_dir(layout.keys_path()));
|
try!(fs::create_dir(layout.keys_path()));
|
||||||
|
@ -71,8 +70,10 @@ impl Repository {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn open<P: AsRef<Path>>(path: P) -> Result<Self, RepositoryError> {
|
pub fn open<P: AsRef<Path>>(path: P) -> Result<Self, RepositoryError> {
|
||||||
let path = path.as_ref().to_owned();
|
let layout = RepositoryLayout::new(path.as_ref().to_path_buf());
|
||||||
let layout = RepositoryLayout::new(path.clone());
|
if !layout.remote_exists() {
|
||||||
|
return Err(RepositoryError::NoRemote)
|
||||||
|
}
|
||||||
let config = try!(Config::load(layout.config_path()));
|
let config = try!(Config::load(layout.config_path()));
|
||||||
let locks = LockFolder::new(layout.remote_locks_path());
|
let locks = LockFolder::new(layout.remote_locks_path());
|
||||||
let crypto = Arc::new(Mutex::new(try!(Crypto::open(layout.keys_path()))));
|
let crypto = Arc::new(Mutex::new(try!(Crypto::open(layout.keys_path()))));
|
||||||
|
|
Loading…
Reference in New Issue