diff --git a/ecstore/src/disk/error.rs b/ecstore/src/disk/error.rs index 0b5e36301..de6009866 100644 --- a/ecstore/src/disk/error.rs +++ b/ecstore/src/disk/error.rs @@ -1,36 +1,103 @@ -use crate::error::{Error, Result}; +use crate::{ + error::{Error, Result}, + quorum::CheckErrorFn, +}; +// DiskError == StorageErr #[derive(Debug, thiserror::Error)] pub enum DiskError { + #[error("maximum versions exceeded, please delete few versions to proceed")] + MaxVersionsExceeded, + + #[error("unexpected error")] + Unexpected, + + #[error("corrupted format")] + CorruptedFormat, + + #[error("corrupted backend")] + CorruptedBackend, + + #[error("unformatted disk error")] + UnformattedDisk, + + #[error("inconsistent drive found")] + InconsistentDisk, + + #[error("drive does not support O_DIRECT")] + UnsupportedDisk, + + #[error("drive path full")] + DiskFull, + + #[error("disk not a dir")] + DiskNotDir, + + #[error("disk not found")] + DiskNotFound, + + #[error("drive still did not complete the request")] + DiskOngoingReq, + + #[error("drive is part of root drive, will not be used")] + DriveIsRoot, + + #[error("remote drive is faulty")] + FaultyRemoteDisk, + + #[error("drive is faulty")] + FaultyDisk, + + #[error("drive access denied")] + DiskAccessDenied, + #[error("file not found")] FileNotFound, #[error("file version not found")] FileVersionNotFound, - #[error("disk not found")] - DiskNotFound, + #[error("too many open files, please increase 'ulimit -n'")] + TooManyOpenFiles, - #[error("disk access denied")] - FileAccessDenied, - - #[error("InconsistentDisk")] - InconsistentDisk, + #[error("file name too long")] + FileNameTooLong, #[error("volume already exists")] VolumeExists, - #[error("unformatted disk error")] - UnformattedDisk, + #[error("not of regular file type")] + IsNotRegular, - #[error("unsupport disk")] - UnsupportedDisk, - - #[error("disk not a dir")] - DiskNotDir, + #[error("path not found")] + PathNotFound, #[error("volume not found")] VolumeNotFound, + + #[error("volume is not empty")] + VolumeNotEmpty, + + #[error("volume access denied")] + VolumeAccessDenied, + + #[error("disk access denied")] + FileAccessDenied, + + #[error("file is corrupted")] + FileCorrupt, + + #[error("bit-rot hash algorithm is invalid")] + BitrotHashAlgoInvalid, + + #[error("Rename across devices not allowed, please fix your backend configuration")] + CrossDeviceLink, + + #[error("less data available than what was requested")] + LessData, + + #[error("more data was sent than what was advertised")] + MoreData, } impl DiskError { @@ -93,3 +160,9 @@ impl PartialEq for DiskError { core::mem::discriminant(self) == core::mem::discriminant(other) } } + +impl CheckErrorFn for DiskError { + fn is(&self, e: &Error) -> bool { + self.is(e) + } +} diff --git a/ecstore/src/erasure.rs b/ecstore/src/erasure.rs index dfff7a2b8..82a5ec3d0 100644 --- a/ecstore/src/erasure.rs +++ b/ecstore/src/erasure.rs @@ -94,7 +94,7 @@ impl Erasure { warn!("Erasure encode errs {:?}", errs); - let err_idx = reduce_write_quorum_errs(&errs, object_ignored_errs().as_slice(), write_quorum)?; + let err_idx = reduce_write_quorum_errs(&errs, object_ignored_errs().as_ref(), write_quorum)?; if errs[err_idx].is_some() { let err = errs[err_idx].take().unwrap(); return Err(err); diff --git a/ecstore/src/quorum.rs b/ecstore/src/quorum.rs index 124ccfcba..1fd80b36d 100644 --- a/ecstore/src/quorum.rs +++ b/ecstore/src/quorum.rs @@ -1,7 +1,11 @@ use crate::{disk::error::DiskError, error::Error}; -use std::collections::HashMap; +use std::{collections::HashMap, fmt::Debug}; -pub type CheckErrorFn = fn(e: &Error) -> bool; +// pub type CheckErrorFn = fn(e: &Error) -> bool; + +pub trait CheckErrorFn: Debug + Send + Sync + 'static { + fn is(&self, e: &Error) -> bool; +} #[derive(Debug, thiserror::Error)] enum QuorumError { @@ -15,17 +19,25 @@ pub fn is_file_not_found(e: &Error) -> bool { DiskError::FileNotFound.is(e) } -pub fn object_ignored_errs() -> Vec { - vec![is_file_not_found] +pub fn base_ignored_errs() -> Vec> { + vec![ + Box::new(DiskError::DiskNotFound), + Box::new(DiskError::FaultyDisk), + Box::new(DiskError::FaultyRemoteDisk), + ] +} + +pub fn object_ignored_errs() -> Vec> { + vec![Box::new(DiskError::FileNotFound)] } // 用于检查错误是否被忽略的函数 -fn is_err_ignored(err: &Error, ignored_errs: &[CheckErrorFn]) -> bool { - ignored_errs.iter().any(|&ignored_err| ignored_err(err)) +fn is_err_ignored(err: &Error, ignored_errs: &Vec>) -> bool { + ignored_errs.iter().any(|ignored_err| ignored_err.is(err)) } // 减少错误数量并返回出现次数最多的错误 -fn reduce_errs(errs: &Vec>, ignored_errs: &[CheckErrorFn]) -> (usize, Option) { +fn reduce_errs(errs: &Vec>, ignored_errs: &Vec>) -> (usize, Option) { let mut error_counts: HashMap = HashMap::new(); let mut error_map: HashMap = HashMap::new(); // 存err位置 let nil = "nil".to_string(); @@ -69,7 +81,7 @@ fn reduce_errs(errs: &Vec>, ignored_errs: &[CheckErrorFn]) -> (usi } // 根据quorum验证错误数量 -fn reduce_quorum_errs(errs: &Vec>, ignored_errs: &[CheckErrorFn], quorum: usize) -> Option { +fn reduce_quorum_errs(errs: &Vec>, ignored_errs: &Vec>, quorum: usize) -> Option { let (max_count, max_err) = reduce_errs(errs, ignored_errs); if max_count >= quorum { max_err @@ -81,7 +93,7 @@ fn reduce_quorum_errs(errs: &Vec>, ignored_errs: &[CheckErrorFn], // 根据读quorum验证错误数量 pub fn reduce_read_quorum_errs( errs: &mut Vec>, - ignored_errs: &[CheckErrorFn], + ignored_errs: &Vec>, read_quorum: usize, ) -> Result { let idx = reduce_quorum_errs(errs, ignored_errs, read_quorum); @@ -95,7 +107,7 @@ pub fn reduce_read_quorum_errs( // 根据写quorum验证错误数量 pub fn reduce_write_quorum_errs( errs: &Vec>, - ignored_errs: &[CheckErrorFn], + ignored_errs: &Vec>, write_quorum: usize, ) -> Result { let idx = reduce_quorum_errs(errs, ignored_errs, write_quorum);