mirror of https://github.com/dswd/zvault
Compiles
This commit is contained in:
parent
46e94bc7a6
commit
381bdf654d
|
@ -4,10 +4,17 @@ use super::*;
|
||||||
|
|
||||||
use std::path::{Path, PathBuf};
|
use std::path::{Path, PathBuf};
|
||||||
|
|
||||||
|
pub use ::repository::ModuleIntegrityReport;
|
||||||
|
|
||||||
|
|
||||||
quick_error!{
|
quick_error!{
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub enum InodeIntegrityError {
|
pub enum InodeIntegrityError {
|
||||||
|
BackupRead(path: PathBuf, err: Box<RepositoryError>) {
|
||||||
|
cause(err)
|
||||||
|
description(tr!("Backup unreadable"))
|
||||||
|
display("{}", tr_format!("Backup unreadable: {:?}\n\tcaused by: {}", path, err))
|
||||||
|
}
|
||||||
BrokenInode(path: PathBuf, err: Box<RepositoryError>) {
|
BrokenInode(path: PathBuf, err: Box<RepositoryError>) {
|
||||||
cause(err)
|
cause(err)
|
||||||
description(tr!("Broken inode"))
|
description(tr!("Broken inode"))
|
||||||
|
@ -27,32 +34,32 @@ pub trait RepositoryIntegrityIO {
|
||||||
) -> Result<(), RepositoryError>;
|
) -> Result<(), RepositoryError>;
|
||||||
|
|
||||||
fn check_subtree(&mut self, path: PathBuf, chunks: &[Chunk], checked: &mut Bitmap,
|
fn check_subtree(&mut self, path: PathBuf, chunks: &[Chunk], checked: &mut Bitmap,
|
||||||
lock: &OnlineMode
|
errors: &mut Vec<InodeIntegrityError>, lock: &OnlineMode
|
||||||
) -> Result<(), RepositoryError>;
|
);
|
||||||
|
|
||||||
|
fn check_backup_inode(&mut self, inode: &Inode, path: &Path, lock: &OnlineMode
|
||||||
|
) -> ModuleIntegrityReport<InodeIntegrityError>;
|
||||||
|
|
||||||
|
fn check_backup(&mut self, name: &str, backup: &mut BackupFile, lock: &OnlineMode
|
||||||
|
) -> ModuleIntegrityReport<InodeIntegrityError>;
|
||||||
|
|
||||||
|
fn check_backups(&mut self, lock: &OnlineMode) -> ModuleIntegrityReport<InodeIntegrityError>;
|
||||||
|
|
||||||
fn check_and_repair_subtree(&mut self, path: PathBuf, chunks: &[Chunk], checked: &mut Bitmap,
|
fn check_and_repair_subtree(&mut self, path: PathBuf, chunks: &[Chunk], checked: &mut Bitmap,
|
||||||
lock: &BackupMode
|
errors: &mut Vec<InodeIntegrityError>, lock: &BackupMode
|
||||||
) -> Result<Option<ChunkList>, RepositoryError>;
|
) -> Result<Option<ChunkList>, RepositoryError>;
|
||||||
|
|
||||||
fn evacuate_broken_backup(&self, name: &str, lock: &BackupMode) -> Result<(), RepositoryError>;
|
fn evacuate_broken_backup(&self, name: &str, lock: &BackupMode) -> Result<(), RepositoryError>;
|
||||||
|
|
||||||
fn check_backup_inode(&mut self, name: &str, backup: &mut BackupFile, path: &Path,
|
|
||||||
lock: &OnlineMode
|
|
||||||
) -> Result<(), RepositoryError>;
|
|
||||||
|
|
||||||
fn check_and_repair_backup_inode(&mut self, name: &str, backup: &mut BackupFile, path: &Path,
|
fn check_and_repair_backup_inode(&mut self, name: &str, backup: &mut BackupFile, path: &Path,
|
||||||
lock: &BackupMode,
|
lock: &BackupMode,
|
||||||
) -> Result<(), RepositoryError>;
|
) -> Result<ModuleIntegrityReport<InodeIntegrityError>, RepositoryError>;
|
||||||
|
|
||||||
fn check_backup(&mut self, name: &str, backup: &mut BackupFile, lock: &OnlineMode
|
|
||||||
) -> Result<(), RepositoryError>;
|
|
||||||
|
|
||||||
fn check_and_repair_backup(&mut self, name: &str, backup: &mut BackupFile, lock: &BackupMode
|
fn check_and_repair_backup(&mut self, name: &str, backup: &mut BackupFile, lock: &BackupMode
|
||||||
) -> Result<(), RepositoryError>;
|
) -> Result<ModuleIntegrityReport<InodeIntegrityError>, RepositoryError>;
|
||||||
|
|
||||||
fn check_backups(&mut self, lock: &OnlineMode) -> Result<(), RepositoryError>;
|
fn check_and_repair_backups(&mut self, lock: &BackupMode
|
||||||
|
) -> Result<ModuleIntegrityReport<InodeIntegrityError>, RepositoryError>;
|
||||||
fn check_and_repair_backups(&mut self, lock: &BackupMode) -> Result<(), RepositoryError>;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -78,31 +85,92 @@ impl RepositoryIntegrityIO for Repository {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn check_subtree(&mut self, path: PathBuf, chunks: &[Chunk], checked: &mut Bitmap,
|
fn check_subtree(&mut self, path: PathBuf, chunks: &[Chunk], checked: &mut Bitmap,
|
||||||
lock: &OnlineMode,
|
errors: &mut Vec<InodeIntegrityError>, lock: &OnlineMode
|
||||||
) -> Result<(), RepositoryError> {
|
) {
|
||||||
let mut modified = false;
|
let mut modified = false;
|
||||||
match self.mark_chunks(checked, chunks, false) {
|
match self.mark_chunks(checked, chunks, false) {
|
||||||
Ok(false) => return Ok(()),
|
Ok(false) => return,
|
||||||
Ok(true) => (),
|
Ok(true) => (),
|
||||||
Err(err) => return Err(InodeIntegrityError::BrokenInode(path, Box::new(err)).into()),
|
Err(err) => {
|
||||||
|
errors.push(InodeIntegrityError::BrokenInode(path, Box::new(err)));
|
||||||
|
return
|
||||||
|
},
|
||||||
}
|
}
|
||||||
let mut inode = try!(self.get_inode(chunks, lock));
|
let mut inode = match self.get_inode(chunks, lock) {
|
||||||
|
Ok(inode) => inode,
|
||||||
|
Err(err) => {
|
||||||
|
errors.push(InodeIntegrityError::BrokenInode(path, Box::new(err)));
|
||||||
|
return
|
||||||
|
}
|
||||||
|
};
|
||||||
// Mark the content chunks as used
|
// Mark the content chunks as used
|
||||||
if let Err(err) = self.check_inode_contents(&inode, checked, lock) {
|
if let Err(err) = self.check_inode_contents(&inode, checked, lock) {
|
||||||
return Err(InodeIntegrityError::MissingInodeData(path, Box::new(err)).into());
|
errors.push(InodeIntegrityError::MissingInodeData(path, Box::new(err)));
|
||||||
|
return
|
||||||
}
|
}
|
||||||
// Put children in to do
|
|
||||||
if let Some(ref mut children) = inode.children {
|
if let Some(ref mut children) = inode.children {
|
||||||
for (name, chunks) in children.iter_mut() {
|
for (name, chunks) in children.iter_mut() {
|
||||||
try!(self.check_subtree(path.join(name), chunks, checked, lock));
|
self.check_subtree(path.join(name), chunks, checked, errors, lock);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
try!(self.mark_chunks(checked, chunks, true));
|
self.mark_chunks(checked, chunks, true).unwrap();
|
||||||
Ok(())
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn check_backup_inode(&mut self, inode: &Inode, path: &Path, lock: &OnlineMode
|
||||||
|
) -> ModuleIntegrityReport<InodeIntegrityError> {
|
||||||
|
tr_info!("Checking inode...");
|
||||||
|
let mut report = ModuleIntegrityReport { errors_unfixed: vec![], errors_fixed: vec![] };
|
||||||
|
let mut checked = self.get_chunk_marker();
|
||||||
|
if let Err(err) = self.check_inode_contents(inode, &mut checked, lock) {
|
||||||
|
report.errors_unfixed.push(InodeIntegrityError::MissingInodeData(path.to_path_buf(), Box::new(err)));
|
||||||
|
}
|
||||||
|
if let Some(ref children) = inode.children {
|
||||||
|
for (name, chunks) in children.iter() {
|
||||||
|
self.check_subtree(path.join(name), chunks, &mut checked, &mut report.errors_unfixed, lock);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
report
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn check_backup(&mut self, name: &str, backup: &mut BackupFile, lock: &OnlineMode,
|
||||||
|
) -> ModuleIntegrityReport<InodeIntegrityError> {
|
||||||
|
tr_info!("Checking backup...");
|
||||||
|
let mut checked = self.get_chunk_marker();
|
||||||
|
let mut report = ModuleIntegrityReport { errors_unfixed: vec![], errors_fixed: vec![] };
|
||||||
|
self.check_subtree(Path::new("").to_path_buf(), &backup.root, &mut checked, &mut report.errors_unfixed, lock);
|
||||||
|
report
|
||||||
|
}
|
||||||
|
|
||||||
|
fn check_backups(&mut self, lock: &OnlineMode) -> ModuleIntegrityReport<InodeIntegrityError> {
|
||||||
|
tr_info!("Checking backups...");
|
||||||
|
let mut checked = self.get_chunk_marker();
|
||||||
|
let mut report = ModuleIntegrityReport { errors_unfixed: vec![], errors_fixed: vec![] };
|
||||||
|
let backup_map = match self.get_all_backups() {
|
||||||
|
Ok(backup_map) => backup_map,
|
||||||
|
Err(RepositoryError::BackupFile(BackupFileError::PartialBackupsList(backup_map,
|
||||||
|
failed))) => {
|
||||||
|
tr_warn!("Some backups could not be read, ignoring them");
|
||||||
|
for path in &failed {
|
||||||
|
report.errors_unfixed.push(InodeIntegrityError::BackupRead(path.to_path_buf(),
|
||||||
|
Box::new(RepositoryError::BackupFile(BackupFileError::PartialBackupsList(backup_map.clone(), failed.clone())))
|
||||||
|
))
|
||||||
|
}
|
||||||
|
backup_map
|
||||||
|
},
|
||||||
|
_ => return report
|
||||||
|
};
|
||||||
|
for (name, mut backup) in ProgressIter::new(tr!("checking backups"), backup_map.len(), backup_map.into_iter()) {
|
||||||
|
let path = format!("{}::", name);
|
||||||
|
self.check_subtree(Path::new(&path).to_path_buf(), &backup.root,
|
||||||
|
&mut checked, &mut report.errors_unfixed, lock);
|
||||||
|
}
|
||||||
|
report
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
fn check_and_repair_subtree(&mut self, path: PathBuf, chunks: &[Chunk], checked: &mut Bitmap,
|
fn check_and_repair_subtree(&mut self, path: PathBuf, chunks: &[Chunk], checked: &mut Bitmap,
|
||||||
lock: &BackupMode,
|
errors: &mut Vec<InodeIntegrityError>, lock: &BackupMode,
|
||||||
) -> Result<Option<ChunkList>, RepositoryError> {
|
) -> Result<Option<ChunkList>, RepositoryError> {
|
||||||
let mut modified = false;
|
let mut modified = false;
|
||||||
match self.mark_chunks(checked, chunks, false) {
|
match self.mark_chunks(checked, chunks, false) {
|
||||||
|
@ -113,12 +181,7 @@ impl RepositoryIntegrityIO for Repository {
|
||||||
let mut inode = try!(self.get_inode(chunks, lock.as_online()));
|
let mut inode = try!(self.get_inode(chunks, lock.as_online()));
|
||||||
// Mark the content chunks as used
|
// Mark the content chunks as used
|
||||||
if let Err(err) = self.check_inode_contents(&inode, checked, lock.as_online()) {
|
if let Err(err) = self.check_inode_contents(&inode, checked, lock.as_online()) {
|
||||||
tr_warn!(
|
errors.push(InodeIntegrityError::MissingInodeData(path.clone(), Box::new(err)));
|
||||||
"Problem detected: data of {:?} is corrupt\n\tcaused by: {}",
|
|
||||||
path,
|
|
||||||
err
|
|
||||||
);
|
|
||||||
tr_info!("Removing inode data");
|
|
||||||
inode.data = Some(FileData::Inline(vec![].into()));
|
inode.data = Some(FileData::Inline(vec![].into()));
|
||||||
inode.size = 0;
|
inode.size = 0;
|
||||||
modified = true;
|
modified = true;
|
||||||
|
@ -127,19 +190,14 @@ impl RepositoryIntegrityIO for Repository {
|
||||||
if let Some(ref mut children) = inode.children {
|
if let Some(ref mut children) = inode.children {
|
||||||
let mut removed = vec![];
|
let mut removed = vec![];
|
||||||
for (name, chunks) in children.iter_mut() {
|
for (name, chunks) in children.iter_mut() {
|
||||||
match self.check_and_repair_subtree(path.join(name), chunks, checked, lock) {
|
match self.check_and_repair_subtree(path.join(name), chunks, checked, errors, lock) {
|
||||||
Ok(None) => (),
|
Ok(None) => (),
|
||||||
Ok(Some(c)) => {
|
Ok(Some(c)) => {
|
||||||
*chunks = c;
|
*chunks = c;
|
||||||
modified = true;
|
modified = true;
|
||||||
}
|
}
|
||||||
Err(err) => {
|
Err(err) => {
|
||||||
tr_warn!(
|
errors.push(InodeIntegrityError::BrokenInode(path.join(name), Box::new(err)));
|
||||||
"Problem detected: inode {:?} is corrupt\n\tcaused by: {}",
|
|
||||||
path.join(name),
|
|
||||||
err
|
|
||||||
);
|
|
||||||
tr_info!("Removing broken inode from backup");
|
|
||||||
removed.push(name.to_string());
|
removed.push(name.to_string());
|
||||||
modified = true;
|
modified = true;
|
||||||
}
|
}
|
||||||
|
@ -178,42 +236,17 @@ impl RepositoryIntegrityIO for Repository {
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn check_backup_inode(&mut self, name: &str, backup: &mut BackupFile, path: &Path,
|
|
||||||
lock: &OnlineMode
|
|
||||||
) -> Result<(), RepositoryError> {
|
|
||||||
tr_info!("Checking inode...");
|
|
||||||
let mut checked = self.get_chunk_marker();
|
|
||||||
let mut inodes = try!(self.get_backup_path(backup, path, lock));
|
|
||||||
let mut inode = inodes.pop().unwrap();
|
|
||||||
let mut modified = false;
|
|
||||||
if let Err(err) = self.check_inode_contents(&inode, &mut checked, lock) {
|
|
||||||
return Err(
|
|
||||||
InodeIntegrityError::MissingInodeData(path.to_path_buf(), Box::new(err)).into()
|
|
||||||
);
|
|
||||||
}
|
|
||||||
if let Some(ref mut children) = inode.children {
|
|
||||||
for (name, chunks) in children.iter_mut() {
|
|
||||||
try!(self.check_subtree(path.join(name), chunks, &mut checked, lock));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
fn check_and_repair_backup_inode(&mut self, name: &str, backup: &mut BackupFile, path: &Path,
|
fn check_and_repair_backup_inode(&mut self, name: &str, backup: &mut BackupFile, path: &Path,
|
||||||
lock: &BackupMode
|
lock: &BackupMode
|
||||||
) -> Result<(), RepositoryError> {
|
) -> Result<ModuleIntegrityReport<InodeIntegrityError>, RepositoryError> {
|
||||||
tr_info!("Checking inode...");
|
tr_info!("Checking inode...");
|
||||||
let mut checked = self.get_chunk_marker();
|
let mut checked = self.get_chunk_marker();
|
||||||
let mut inodes = try!(self.get_backup_path(backup, path, lock.as_online()));
|
let mut inodes = try!(self.get_backup_path(backup, path, lock.as_online()));
|
||||||
let mut inode = inodes.pop().unwrap();
|
let mut inode = inodes.pop().unwrap();
|
||||||
let mut modified = false;
|
let mut modified = false;
|
||||||
|
let mut errors = vec![];
|
||||||
if let Err(err) = self.check_inode_contents(&inode, &mut checked, lock.as_online()) {
|
if let Err(err) = self.check_inode_contents(&inode, &mut checked, lock.as_online()) {
|
||||||
tr_warn!(
|
errors.push(InodeIntegrityError::MissingInodeData(path.to_path_buf(), Box::new(err)));
|
||||||
"Problem detected: data of {:?} is corrupt\n\tcaused by: {}",
|
|
||||||
path,
|
|
||||||
err
|
|
||||||
);
|
|
||||||
tr_info!("Removing inode data");
|
|
||||||
inode.data = Some(FileData::Inline(vec![].into()));
|
inode.data = Some(FileData::Inline(vec![].into()));
|
||||||
inode.size = 0;
|
inode.size = 0;
|
||||||
modified = true;
|
modified = true;
|
||||||
|
@ -221,19 +254,14 @@ impl RepositoryIntegrityIO for Repository {
|
||||||
if let Some(ref mut children) = inode.children {
|
if let Some(ref mut children) = inode.children {
|
||||||
let mut removed = vec![];
|
let mut removed = vec![];
|
||||||
for (name, chunks) in children.iter_mut() {
|
for (name, chunks) in children.iter_mut() {
|
||||||
match self.check_and_repair_subtree(path.join(name), chunks, &mut checked, lock) {
|
match self.check_and_repair_subtree(path.join(name), chunks, &mut checked, &mut errors, lock) {
|
||||||
Ok(None) => (),
|
Ok(None) => (),
|
||||||
Ok(Some(c)) => {
|
Ok(Some(c)) => {
|
||||||
*chunks = c;
|
*chunks = c;
|
||||||
modified = true;
|
modified = true;
|
||||||
}
|
}
|
||||||
Err(err) => {
|
Err(err) => {
|
||||||
tr_warn!(
|
errors.push(InodeIntegrityError::BrokenInode(path.join(name), Box::new(err)));
|
||||||
"Problem detected: inode {:?} is corrupt\n\tcaused by: {}",
|
|
||||||
path.join(name),
|
|
||||||
err
|
|
||||||
);
|
|
||||||
tr_info!("Removing broken inode from backup");
|
|
||||||
removed.push(name.to_string());
|
removed.push(name.to_string());
|
||||||
modified = true;
|
modified = true;
|
||||||
}
|
}
|
||||||
|
@ -256,25 +284,17 @@ impl RepositoryIntegrityIO for Repository {
|
||||||
try!(self.evacuate_broken_backup(name, lock));
|
try!(self.evacuate_broken_backup(name, lock));
|
||||||
try!(self.save_backup(backup, name, lock));
|
try!(self.save_backup(backup, name, lock));
|
||||||
}
|
}
|
||||||
Ok(())
|
Ok(ModuleIntegrityReport{errors_unfixed: vec![], errors_fixed: errors})
|
||||||
}
|
|
||||||
|
|
||||||
#[inline]
|
|
||||||
fn check_backup(&mut self, name: &str, backup: &mut BackupFile, lock: &OnlineMode,
|
|
||||||
) -> Result<(), RepositoryError> {
|
|
||||||
tr_info!("Checking backup...");
|
|
||||||
let mut checked = self.get_chunk_marker();
|
|
||||||
try!(self.check_subtree(Path::new("").to_path_buf(), &backup.root, &mut checked, lock));
|
|
||||||
Ok(())
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
fn check_and_repair_backup(&mut self, name: &str, backup: &mut BackupFile, lock: &BackupMode,
|
fn check_and_repair_backup(&mut self, name: &str, backup: &mut BackupFile, lock: &BackupMode,
|
||||||
) -> Result<(), RepositoryError> {
|
) -> Result<ModuleIntegrityReport<InodeIntegrityError>, RepositoryError> {
|
||||||
tr_info!("Checking backup...");
|
tr_info!("Checking backup...");
|
||||||
let mut checked = self.get_chunk_marker();
|
let mut checked = self.get_chunk_marker();
|
||||||
|
let mut errors = vec![];
|
||||||
match self.check_and_repair_subtree(Path::new("").to_path_buf(),
|
match self.check_and_repair_subtree(Path::new("").to_path_buf(),
|
||||||
&backup.root, &mut checked, lock
|
&backup.root, &mut checked, &mut errors, lock
|
||||||
) {
|
) {
|
||||||
Ok(None) => (),
|
Ok(None) => (),
|
||||||
Ok(Some(chunks)) => {
|
Ok(Some(chunks)) => {
|
||||||
|
@ -285,43 +305,18 @@ impl RepositoryIntegrityIO for Repository {
|
||||||
try!(self.save_backup(backup, name, lock));
|
try!(self.save_backup(backup, name, lock));
|
||||||
}
|
}
|
||||||
Err(err) => {
|
Err(err) => {
|
||||||
tr_warn!(
|
errors.push(InodeIntegrityError::BrokenInode(PathBuf::from("/"), Box::new(err)));
|
||||||
"The root of the backup {} has been corrupted\n\tcaused by: {}",
|
|
||||||
name,
|
|
||||||
err
|
|
||||||
);
|
|
||||||
try!(self.evacuate_broken_backup(name, lock));
|
try!(self.evacuate_broken_backup(name, lock));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Ok(())
|
Ok(ModuleIntegrityReport{errors_unfixed: vec![], errors_fixed: errors})
|
||||||
}
|
}
|
||||||
|
|
||||||
fn check_backups(&mut self, lock: &OnlineMode) -> Result<(), RepositoryError> {
|
fn check_and_repair_backups(&mut self, lock: &BackupMode
|
||||||
tr_info!("Checking backups...");
|
) -> Result<ModuleIntegrityReport<InodeIntegrityError>, RepositoryError> {
|
||||||
let mut checked = self.get_chunk_marker();
|
|
||||||
let backup_map = match self.get_all_backups() {
|
|
||||||
Ok(backup_map) => backup_map,
|
|
||||||
Err(RepositoryError::BackupFile(BackupFileError::PartialBackupsList(backup_map,
|
|
||||||
_failed))) => {
|
|
||||||
tr_warn!("Some backups could not be read, ignoring them");
|
|
||||||
backup_map
|
|
||||||
}
|
|
||||||
Err(err) => return Err(err),
|
|
||||||
};
|
|
||||||
for (name, mut backup) in
|
|
||||||
ProgressIter::new(tr!("checking backups"), backup_map.len(), backup_map.into_iter())
|
|
||||||
{
|
|
||||||
let path = format!("{}::", name);
|
|
||||||
try!(self.check_subtree(Path::new(&path).to_path_buf(), &backup.root,
|
|
||||||
&mut checked, lock));
|
|
||||||
}
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
fn check_and_repair_backups(&mut self, lock: &BackupMode) -> Result<(), RepositoryError> {
|
|
||||||
tr_info!("Checking backups...");
|
tr_info!("Checking backups...");
|
||||||
let mut checked = self.get_chunk_marker();
|
let mut checked = self.get_chunk_marker();
|
||||||
|
let mut errors = vec![];
|
||||||
let backup_map = match self.get_all_backups() {
|
let backup_map = match self.get_all_backups() {
|
||||||
Ok(backup_map) => backup_map,
|
Ok(backup_map) => backup_map,
|
||||||
Err(RepositoryError::BackupFile(BackupFileError::PartialBackupsList(backup_map,
|
Err(RepositoryError::BackupFile(BackupFileError::PartialBackupsList(backup_map,
|
||||||
|
@ -339,6 +334,7 @@ impl RepositoryIntegrityIO for Repository {
|
||||||
Path::new(&path).to_path_buf(),
|
Path::new(&path).to_path_buf(),
|
||||||
&backup.root,
|
&backup.root,
|
||||||
&mut checked,
|
&mut checked,
|
||||||
|
&mut errors,
|
||||||
lock
|
lock
|
||||||
) {
|
) {
|
||||||
Ok(None) => (),
|
Ok(None) => (),
|
||||||
|
@ -350,15 +346,11 @@ impl RepositoryIntegrityIO for Repository {
|
||||||
try!(self.save_backup(&backup, &name, lock));
|
try!(self.save_backup(&backup, &name, lock));
|
||||||
}
|
}
|
||||||
Err(err) => {
|
Err(err) => {
|
||||||
tr_warn!(
|
errors.push(InodeIntegrityError::BrokenInode(PathBuf::from(format!("{}::/", name)), Box::new(err)));
|
||||||
"The root of the backup {} has been corrupted\n\tcaused by: {}",
|
|
||||||
name,
|
|
||||||
err
|
|
||||||
);
|
|
||||||
try!(self.evacuate_broken_backup(&name, lock));
|
try!(self.evacuate_broken_backup(&name, lock));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Ok(())
|
Ok(ModuleIntegrityReport{errors_unfixed: vec![], errors_fixed: errors})
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -321,7 +321,11 @@ impl BackupRepository {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn check(&mut self, options: CheckOptions) -> Result<(), RepositoryError> {
|
pub fn check(&mut self, options: &CheckOptions) -> Result<(), RepositoryError> {
|
||||||
|
self.0.online_mode(|r, l| {
|
||||||
|
r.check(options.index, options.bundles, options.bundle_data, l);
|
||||||
|
Ok(())
|
||||||
|
});
|
||||||
unimplemented!()
|
unimplemented!()
|
||||||
//TODO: implement
|
//TODO: implement
|
||||||
}
|
}
|
||||||
|
|
|
@ -827,7 +827,7 @@ pub fn run() -> Result<(), ErrorCode> {
|
||||||
options.all_backups();
|
options.all_backups();
|
||||||
}
|
}
|
||||||
checked!(
|
checked!(
|
||||||
repo.check(options),
|
repo.check(&options),
|
||||||
"check repository",
|
"check repository",
|
||||||
ErrorCode::CheckRun
|
ErrorCode::CheckRun
|
||||||
);
|
);
|
||||||
|
|
|
@ -46,15 +46,15 @@ quick_error!{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
pub struct ModuleIntegrityReport {
|
pub struct ModuleIntegrityReport<T> {
|
||||||
pub errors_fixed: Vec<IntegrityError>,
|
pub errors_fixed: Vec<T>,
|
||||||
pub errors_unfixed: Vec<IntegrityError>
|
pub errors_unfixed: Vec<T>
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct IntegrityReport {
|
pub struct IntegrityReport {
|
||||||
pub bundle_map: Option<ModuleIntegrityReport>,
|
pub bundle_map: Option<ModuleIntegrityReport<IntegrityError>>,
|
||||||
pub index: Option<ModuleIntegrityReport>,
|
pub index: Option<ModuleIntegrityReport<IntegrityError>>,
|
||||||
pub bundles: Option<ModuleIntegrityReport>
|
pub bundles: Option<ModuleIntegrityReport<IntegrityError>>
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -83,7 +83,7 @@ impl Repository {
|
||||||
Ok(new)
|
Ok(new)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn check_bundle_map(&mut self) -> ModuleIntegrityReport {
|
pub fn check_bundle_map(&mut self) -> ModuleIntegrityReport<IntegrityError> {
|
||||||
tr_info!("Checking bundle map...");
|
tr_info!("Checking bundle map...");
|
||||||
let mut errors = vec![];
|
let mut errors = vec![];
|
||||||
for (_id, bundle_id) in self.bundle_map.bundles() {
|
for (_id, bundle_id) in self.bundle_map.bundles() {
|
||||||
|
@ -120,7 +120,7 @@ impl Repository {
|
||||||
self.save_bundle_map(lock.as_localwrite())
|
self.save_bundle_map(lock.as_localwrite())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn check_and_repair_bundle_map(&mut self, lock: &OnlineMode) -> Result<ModuleIntegrityReport, RepositoryError> {
|
pub fn check_and_repair_bundle_map(&mut self, lock: &OnlineMode) -> Result<ModuleIntegrityReport<IntegrityError>, RepositoryError> {
|
||||||
let mut report = self.check_bundle_map();
|
let mut report = self.check_bundle_map();
|
||||||
if !report.errors_unfixed.is_empty() {
|
if !report.errors_unfixed.is_empty() {
|
||||||
try!(self.rebuild_bundle_map(lock));
|
try!(self.rebuild_bundle_map(lock));
|
||||||
|
@ -183,7 +183,7 @@ impl Repository {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn check_index(&mut self, lock: &ReadonlyMode) -> ModuleIntegrityReport {
|
pub fn check_index(&mut self, lock: &ReadonlyMode) -> ModuleIntegrityReport<IntegrityError> {
|
||||||
tr_info!("Checking index integrity...");
|
tr_info!("Checking index integrity...");
|
||||||
let mut errors: Vec<IntegrityError> = self.index.check().into_iter().map(IntegrityError::Index).collect();
|
let mut errors: Vec<IntegrityError> = self.index.check().into_iter().map(IntegrityError::Index).collect();
|
||||||
tr_info!("Checking index entries...");
|
tr_info!("Checking index entries...");
|
||||||
|
@ -191,7 +191,7 @@ impl Repository {
|
||||||
ModuleIntegrityReport { errors_fixed: vec![], errors_unfixed: errors }
|
ModuleIntegrityReport { errors_fixed: vec![], errors_unfixed: errors }
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn check_and_repair_index(&mut self, lock: &OnlineMode) -> Result<ModuleIntegrityReport, RepositoryError> {
|
pub fn check_and_repair_index(&mut self, lock: &OnlineMode) -> Result<ModuleIntegrityReport<IntegrityError>, RepositoryError> {
|
||||||
let mut report = self.check_index(lock.as_readonly());
|
let mut report = self.check_index(lock.as_readonly());
|
||||||
if !report.errors_unfixed.is_empty() {
|
if !report.errors_unfixed.is_empty() {
|
||||||
try!(self.rebuild_index(lock));
|
try!(self.rebuild_index(lock));
|
||||||
|
@ -201,7 +201,7 @@ impl Repository {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
fn check_bundles_internal(&mut self, full: bool, lock: &OnlineMode) -> (ModuleIntegrityReport, Vec<BundleId>) {
|
fn check_bundles_internal(&mut self, full: bool, lock: &OnlineMode) -> (ModuleIntegrityReport<IntegrityError>, Vec<BundleId>) {
|
||||||
tr_info!("Checking bundle integrity...");
|
tr_info!("Checking bundle integrity...");
|
||||||
let mut errors = vec![];
|
let mut errors = vec![];
|
||||||
let mut bundles = vec![];
|
let mut bundles = vec![];
|
||||||
|
@ -213,11 +213,11 @@ impl Repository {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn check_bundles(&mut self, full: bool, lock: &OnlineMode) -> ModuleIntegrityReport {
|
pub fn check_bundles(&mut self, full: bool, lock: &OnlineMode) -> ModuleIntegrityReport<IntegrityError> {
|
||||||
self.check_bundles_internal(full, lock).0
|
self.check_bundles_internal(full, lock).0
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn check_and_repair_bundles(&mut self, full: bool, lock: &VacuumMode) -> Result<ModuleIntegrityReport, RepositoryError> {
|
pub fn check_and_repair_bundles(&mut self, full: bool, lock: &VacuumMode) -> Result<ModuleIntegrityReport<IntegrityError>, RepositoryError> {
|
||||||
let (mut report, bundles) = self.check_bundles_internal(full, lock.as_online());
|
let (mut report, bundles) = self.check_bundles_internal(full, lock.as_online());
|
||||||
if !report.errors_unfixed.is_empty() {
|
if !report.errors_unfixed.is_empty() {
|
||||||
try!(self.bundles.repair(lock, &bundles));
|
try!(self.bundles.repair(lock, &bundles));
|
||||||
|
|
Loading…
Reference in New Issue