mirror of https://github.com/dswd/zvault
Dirty flag on error
This commit is contained in:
parent
7efc3de78f
commit
26d73e79a4
2
TODO.md
2
TODO.md
|
@ -3,7 +3,7 @@
|
|||
## Functionality
|
||||
* XAttrs in fuse
|
||||
* XAttrs in tar
|
||||
* `check --repair`
|
||||
* Repair
|
||||
|
||||
## Stability / Reliability
|
||||
* Lock the local repository to avoid index corruption
|
||||
|
|
|
@ -438,6 +438,7 @@ pub fn run() -> Result<(), ErrorCode> {
|
|||
} else {
|
||||
checked!(repo.check_backups(), "check repository", ErrorCode::CheckRun)
|
||||
}
|
||||
repo.set_clean();
|
||||
info!("Integrity verified")
|
||||
},
|
||||
Arguments::List{repo_path, backup_name, inode} => {
|
||||
|
|
|
@ -225,6 +225,10 @@ impl Repository {
|
|||
#[allow(dead_code)]
|
||||
pub fn create_backup_recursively<P: AsRef<Path>>(&mut self, path: P, reference: Option<&Backup>, options: &BackupOptions) -> Result<Backup, RepositoryError> {
|
||||
let _lock = try!(self.lock(false));
|
||||
if self.dirty {
|
||||
return Err(RepositoryError::Dirty)
|
||||
}
|
||||
self.dirty = true;
|
||||
let reference_inode = reference.and_then(|b| self.get_inode(&b.root).ok());
|
||||
let mut backup = Backup::default();
|
||||
backup.config = self.config.clone();
|
||||
|
@ -251,6 +255,7 @@ impl Repository {
|
|||
backup.bundle_count = info_after.bundle_count - info_before.bundle_count;
|
||||
backup.chunk_count = info_after.chunk_count - info_before.chunk_count;
|
||||
backup.avg_chunk_size = backup.deduplicated_data_size as f32 / backup.chunk_count as f32;
|
||||
self.dirty = false;
|
||||
if failed_paths.is_empty() {
|
||||
Ok(backup)
|
||||
} else {
|
||||
|
|
|
@ -78,6 +78,10 @@ quick_error!{
|
|||
description("Integrity error")
|
||||
display("Repository error: integrity error\n\tcaused by: {}", err)
|
||||
}
|
||||
Dirty {
|
||||
description("Dirty repository")
|
||||
display("The repository is dirty, please run a check")
|
||||
}
|
||||
Backup(err: BackupError) {
|
||||
from()
|
||||
cause(err)
|
||||
|
|
|
@ -61,6 +61,10 @@ impl Repository {
|
|||
}
|
||||
|
||||
pub fn analyze_usage(&mut self) -> Result<HashMap<u32, BundleAnalysis>, RepositoryError> {
|
||||
if self.dirty {
|
||||
return Err(RepositoryError::Dirty)
|
||||
}
|
||||
self.dirty = true;
|
||||
let mut usage = HashMap::new();
|
||||
for (id, bundle) in self.bundle_map.bundles() {
|
||||
let bundle = try!(self.bundles.get_bundle_info(&bundle).ok_or_else(|| IntegrityError::MissingBundle(bundle)));
|
||||
|
@ -101,6 +105,7 @@ impl Repository {
|
|||
}
|
||||
}
|
||||
}
|
||||
self.dirty = false;
|
||||
Ok(usage)
|
||||
}
|
||||
|
||||
|
|
|
@ -102,4 +102,8 @@ impl RepositoryLayout {
|
|||
pub fn remote_bundle_cache_path(&self) -> PathBuf {
|
||||
self.0.join("bundles/remote.cache")
|
||||
}
|
||||
|
||||
pub fn dirtyfile_path(&self) -> PathBuf {
|
||||
self.0.join("dirty")
|
||||
}
|
||||
}
|
||||
|
|
|
@ -48,7 +48,8 @@ pub struct Repository {
|
|||
data_bundle: Option<BundleWriter>,
|
||||
meta_bundle: Option<BundleWriter>,
|
||||
chunker: Chunker,
|
||||
locks: LockFolder
|
||||
locks: LockFolder,
|
||||
dirty: bool
|
||||
}
|
||||
|
||||
|
||||
|
@ -92,8 +93,10 @@ impl Repository {
|
|||
(BundleMap::create(), true)
|
||||
}
|
||||
};
|
||||
let dirty = layout.dirtyfile_path().exists();
|
||||
let mut repo = Repository {
|
||||
layout: layout,
|
||||
dirty: true,
|
||||
chunker: config.chunker.create(),
|
||||
config: config,
|
||||
index: index,
|
||||
|
@ -128,6 +131,7 @@ impl Repository {
|
|||
if rebuild_index {
|
||||
try!(repo.rebuild_index());
|
||||
}
|
||||
repo.dirty = dirty;
|
||||
Ok(repo)
|
||||
}
|
||||
|
||||
|
@ -190,6 +194,10 @@ impl Repository {
|
|||
}
|
||||
|
||||
pub fn flush(&mut self) -> Result<(), RepositoryError> {
|
||||
let dirtyfile = self.layout.dirtyfile_path();
|
||||
if self.dirty && !dirtyfile.exists() {
|
||||
try!(File::create(&dirtyfile));
|
||||
}
|
||||
if self.data_bundle.is_some() {
|
||||
let mut finished = None;
|
||||
mem::swap(&mut self.data_bundle, &mut finished);
|
||||
|
@ -211,6 +219,9 @@ impl Repository {
|
|||
try!(self.bundles.finish_uploads());
|
||||
try!(self.save_bundle_map());
|
||||
try!(self.bundles.save_cache());
|
||||
if !self.dirty && dirtyfile.exists() {
|
||||
try!(fs::remove_file(&dirtyfile));
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
|
@ -281,6 +292,10 @@ impl Repository {
|
|||
fn lock(&self, exclusive: bool) -> Result<LockHandle, RepositoryError> {
|
||||
Ok(try!(self.locks.lock(exclusive)))
|
||||
}
|
||||
|
||||
pub fn set_clean(&mut self) {
|
||||
self.dirty = false;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -155,6 +155,10 @@ impl Repository {
|
|||
|
||||
pub fn import_tarfile<P: AsRef<Path>>(&mut self, tarfile: P) -> Result<Backup, RepositoryError> {
|
||||
let _lock = try!(self.lock(false));
|
||||
if self.dirty {
|
||||
return Err(RepositoryError::Dirty)
|
||||
}
|
||||
self.dirty = true;
|
||||
let mut backup = Backup::default();
|
||||
backup.config = self.config.clone();
|
||||
backup.host = get_hostname().unwrap_or_else(|_| "".to_string());
|
||||
|
@ -177,6 +181,7 @@ impl Repository {
|
|||
backup.bundle_count = info_after.bundle_count - info_before.bundle_count;
|
||||
backup.chunk_count = info_after.chunk_count - info_before.chunk_count;
|
||||
backup.avg_chunk_size = backup.deduplicated_data_size as f32 / backup.chunk_count as f32;
|
||||
self.dirty = false;
|
||||
if failed_paths.is_empty() {
|
||||
Ok(backup)
|
||||
} else {
|
||||
|
|
|
@ -17,6 +17,10 @@ impl Repository {
|
|||
try!(self.flush());
|
||||
info!("Locking repository");
|
||||
let _lock = try!(self.lock(true));
|
||||
if self.dirty {
|
||||
return Err(RepositoryError::Dirty)
|
||||
}
|
||||
self.dirty = true;
|
||||
info!("Analyzing chunk usage");
|
||||
let usage = try!(self.analyze_usage());
|
||||
let mut data_total = 0;
|
||||
|
@ -36,6 +40,7 @@ impl Repository {
|
|||
}
|
||||
info!("Reclaiming {} by rewriting {} bundles", to_file_size(reclaim_space as u64), rewrite_bundles.len());
|
||||
if !force {
|
||||
self.dirty = false;
|
||||
return Ok(())
|
||||
}
|
||||
for id in &rewrite_bundles {
|
||||
|
@ -65,6 +70,7 @@ impl Repository {
|
|||
try!(self.delete_bundle(id));
|
||||
}
|
||||
try!(self.save_bundle_map());
|
||||
self.dirty = false;
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue