refactor error framework

Signed-off-by: junxiang Mu <1948535941@qq.com>
This commit is contained in:
junxiang Mu
2024-12-18 20:50:22 +08:00
parent 2951b7ef28
commit 84953bf15b
13 changed files with 957 additions and 291 deletions
+29
View File
@@ -29,3 +29,32 @@ impl BucketMetadataError {
}
}
}
impl BucketMetadataError {
pub fn to_u32(&self) -> u32 {
match self {
BucketMetadataError::TaggingNotFound => 0x01,
BucketMetadataError::BucketPolicyNotFound => 0x02,
BucketMetadataError::BucketObjectLockConfigNotFound => 0x03,
BucketMetadataError::BucketLifecycleNotFound => 0x04,
BucketMetadataError::BucketSSEConfigNotFound => 0x05,
BucketMetadataError::BucketQuotaConfigNotFound => 0x06,
BucketMetadataError::BucketReplicationConfigNotFound => 0x07,
BucketMetadataError::BucketRemoteTargetNotFound => 0x08,
}
}
pub fn from_u32(error: u32) -> Option<Self> {
match error {
0x01 => Some(BucketMetadataError::TaggingNotFound),
0x02 => Some(BucketMetadataError::BucketPolicyNotFound),
0x03 => Some(BucketMetadataError::BucketObjectLockConfigNotFound),
0x04 => Some(BucketMetadataError::BucketLifecycleNotFound),
0x05 => Some(BucketMetadataError::BucketSSEConfigNotFound),
0x06 => Some(BucketMetadataError::BucketQuotaConfigNotFound),
0x07 => Some(BucketMetadataError::BucketReplicationConfigNotFound),
0x08 => Some(BucketMetadataError::BucketRemoteTargetNotFound),
_ => None,
}
}
}
+17 -1
View File
@@ -1,6 +1,6 @@
use crate::{disk, error::Error};
#[derive(Debug, thiserror::Error)]
#[derive(Debug, PartialEq, thiserror::Error)]
pub enum ConfigError {
#[error("config not found")]
NotFound,
@@ -15,6 +15,22 @@ impl ConfigError {
matches!(self, Self::NotFound)
}
}
impl ConfigError {
pub fn to_u32(&self) -> u32 {
match self {
ConfigError::NotFound => 0x01,
}
}
pub fn from_u32(error: u32) -> Option<Self> {
match error {
0x01 => Some(Self::NotFound),
_ => None,
}
}
}
pub fn is_not_found(err: &Error) -> bool {
if let Some(e) = err.downcast_ref::<ConfigError>() {
ConfigError::is_not_found(e)
+42 -1
View File
@@ -2,6 +2,7 @@ use std::io::{self, ErrorKind};
use tracing::error;
use crate::utils::ERROR_TYPE_MASK;
use crate::{
error::{Error, Result},
quorum::CheckErrorFn,
@@ -168,7 +169,7 @@ impl DiskError {
}
impl DiskError {
pub fn to_u8(&self) -> u32 {
pub fn to_u32(&self) -> u32 {
match self {
DiskError::MaxVersionsExceeded => 0x01,
DiskError::Unexpected => 0x02,
@@ -206,6 +207,46 @@ impl DiskError {
DiskError::NoHealRequired => 0x22,
}
}
pub fn from_u32(error: u32) -> Option<Self> {
match error & ERROR_TYPE_MASK {
0x01 => Some(DiskError::MaxVersionsExceeded),
0x02 => Some(DiskError::Unexpected),
0x03 => Some(DiskError::CorruptedFormat),
0x04 => Some(DiskError::CorruptedBackend),
0x05 => Some(DiskError::UnformattedDisk),
0x06 => Some(DiskError::InconsistentDisk),
0x07 => Some(DiskError::UnsupportedDisk),
0x08 => Some(DiskError::DiskFull),
0x09 => Some(DiskError::DiskNotDir),
0x0A => Some(DiskError::DiskNotFound),
0x0B => Some(DiskError::DiskOngoingReq),
0x0C => Some(DiskError::DriveIsRoot),
0x0D => Some(DiskError::FaultyRemoteDisk),
0x0E => Some(DiskError::FaultyDisk),
0x0F => Some(DiskError::DiskAccessDenied),
0x10 => Some(DiskError::FileNotFound),
0x11 => Some(DiskError::FileVersionNotFound),
0x12 => Some(DiskError::TooManyOpenFiles),
0x13 => Some(DiskError::FileNameTooLong),
0x14 => Some(DiskError::VolumeExists),
0x15 => Some(DiskError::IsNotRegular),
0x16 => Some(DiskError::PathNotFound),
0x17 => Some(DiskError::VolumeNotFound),
0x18 => Some(DiskError::VolumeNotEmpty),
0x19 => Some(DiskError::VolumeAccessDenied),
0x1A => Some(DiskError::FileAccessDenied),
0x1B => Some(DiskError::FileCorrupt),
0x1C => Some(DiskError::BitrotHashAlgoInvalid),
0x1D => Some(DiskError::CrossDeviceLink),
0x1E => Some(DiskError::LessData),
0x1F => Some(DiskError::MoreData),
0x20 => Some(DiskError::OutdatedXLMeta),
0x21 => Some(DiskError::PartMissingOrCorrupt),
0x22 => Some(DiskError::NoHealRequired),
_ => None,
}
}
}
impl PartialEq for DiskError {
+11 -6
View File
@@ -14,6 +14,7 @@ pub const FORMAT_CONFIG_FILE: &str = "format.json";
pub const STORAGE_FORMAT_FILE: &str = "xl.meta";
pub const STORAGE_FORMAT_FILE_BACKUP: &str = "xl.meta.bkp";
use crate::utils::proto_err_to_err;
use crate::{
erasure::Writer,
error::{Error, Result},
@@ -1109,9 +1110,11 @@ impl Writer for RemoteFileWriter {
if resp.success {
info!("write stream success");
} else {
let error_info = resp.error_info.unwrap_or("".to_string());
info!("write stream failed: {}", error_info);
return Err(Error::from_string(error_info));
return if let Some(err) = &resp.error {
Err(proto_err_to_err(err))
} else {
Err(Error::from_string(""))
};
}
} else {
let error_info = "can not get response";
@@ -1287,9 +1290,11 @@ impl Reader for RemoteFileReader {
Ok(resp.read_size.try_into().unwrap())
} else {
let error_info = resp.error_info.unwrap_or("".to_string());
info!("read at stream failed: {}", error_info);
Err(Error::from_string(error_info))
return if let Some(err) = &resp.error {
Err(proto_err_to_err(err))
} else {
Err(Error::from_string(""))
};
}
} else {
let error_info = "can not get response";
+116 -26
View File
@@ -21,6 +21,7 @@ use super::{
FileInfoVersions, FileReader, FileWriter, MetaCacheEntry, ReadMultipleReq, ReadMultipleResp, ReadOptions, RemoteFileReader,
RemoteFileWriter, RenameDataResp, UpdateMetadataOpts, VolumeInfo, WalkDirOptions,
};
use crate::utils::proto_err_to_err;
use crate::{
disk::error::DiskError,
error::{Error, Result},
@@ -161,7 +162,11 @@ impl DiskAPI for RemoteDisk {
let response = client.write_all(request).await?.into_inner();
if !response.success {
return Err(Error::from_string(response.error_info.unwrap_or("".to_string())));
return if let Some(err) = &response.error {
Err(proto_err_to_err(err))
} else {
Err(Error::from_string(""))
};
}
Ok(())
@@ -183,7 +188,11 @@ impl DiskAPI for RemoteDisk {
let response = client.delete(request).await?.into_inner();
if !response.success {
return Err(Error::from_string(response.error_info.unwrap_or("".to_string())));
return if let Some(err) = &response.error {
Err(proto_err_to_err(err))
} else {
Err(Error::from_string(""))
};
}
Ok(())
@@ -205,7 +214,11 @@ impl DiskAPI for RemoteDisk {
let response = client.verify_file(request).await?.into_inner();
if !response.success {
return Err(Error::from_string(response.error_info.unwrap_or("".to_string())));
return if let Some(err) = &response.error {
Err(proto_err_to_err(err))
} else {
Err(Error::from_string(""))
};
}
let check_parts_resp = serde_json::from_str::<CheckPartsResp>(&response.check_parts_resp)?;
@@ -229,7 +242,11 @@ impl DiskAPI for RemoteDisk {
let response = client.check_parts(request).await?.into_inner();
if !response.success {
return Err(Error::from_string(response.error_info.unwrap_or("".to_string())));
return if let Some(err) = &response.error {
Err(proto_err_to_err(err))
} else {
Err(Error::from_string(""))
};
}
let check_parts_resp = serde_json::from_str::<CheckPartsResp>(&response.check_parts_resp)?;
@@ -254,7 +271,11 @@ impl DiskAPI for RemoteDisk {
let response = client.rename_part(request).await?.into_inner();
if !response.success {
return Err(Error::from_string(response.error_info.unwrap_or("".to_string())));
return if let Some(err) = &response.error {
Err(proto_err_to_err(err))
} else {
Err(Error::from_string(""))
};
}
Ok(())
@@ -275,7 +296,11 @@ impl DiskAPI for RemoteDisk {
let response = client.rename_file(request).await?.into_inner();
if !response.success {
return Err(Error::from_string(response.error_info.unwrap_or("".to_string())));
return if let Some(err) = &response.error {
Err(proto_err_to_err(err))
} else {
Err(Error::from_string(""))
};
}
Ok(())
@@ -341,7 +366,11 @@ impl DiskAPI for RemoteDisk {
let response = client.list_dir(request).await?.into_inner();
if !response.success {
return Err(Error::from_string(response.error_info.unwrap_or("".to_string())));
return if let Some(err) = &response.error {
Err(proto_err_to_err(err))
} else {
Err(Error::from_string(""))
};
}
Ok(response.volumes)
@@ -361,7 +390,11 @@ impl DiskAPI for RemoteDisk {
let response = client.walk_dir(request).await?.into_inner();
if !response.success {
return Err(Error::from_string(response.error_info.unwrap_or("".to_string())));
return if let Some(err) = &response.error {
Err(proto_err_to_err(err))
} else {
Err(Error::from_string(""))
};
}
let entries = response
@@ -398,7 +431,11 @@ impl DiskAPI for RemoteDisk {
let response = client.rename_data(request).await?.into_inner();
if !response.success {
return Err(Error::from_string(response.error_info.unwrap_or("".to_string())));
return if let Some(err) = &response.error {
Err(proto_err_to_err(err))
} else {
Err(Error::from_string(""))
};
}
let rename_data_resp = serde_json::from_str::<RenameDataResp>(&response.rename_data_resp)?;
@@ -419,7 +456,11 @@ impl DiskAPI for RemoteDisk {
let response = client.make_volumes(request).await?.into_inner();
if !response.success {
return Err(Error::from_string(response.error_info.unwrap_or("".to_string())));
return if let Some(err) = &response.error {
Err(proto_err_to_err(err))
} else {
Err(Error::from_string(""))
};
}
Ok(())
@@ -438,7 +479,11 @@ impl DiskAPI for RemoteDisk {
let response = client.make_volume(request).await?.into_inner();
if !response.success {
return Err(Error::from_string(response.error_info.unwrap_or("".to_string())));
return if let Some(err) = &response.error {
Err(proto_err_to_err(err))
} else {
Err(Error::from_string(""))
};
}
Ok(())
@@ -456,7 +501,11 @@ impl DiskAPI for RemoteDisk {
let response = client.list_volumes(request).await?.into_inner();
if !response.success {
return Err(Error::from_string(response.error_info.unwrap_or("".to_string())));
return if let Some(err) = &response.error {
Err(proto_err_to_err(err))
} else {
Err(Error::from_string(""))
};
}
let infos = response
@@ -481,7 +530,11 @@ impl DiskAPI for RemoteDisk {
let response = client.stat_volume(request).await?.into_inner();
if !response.success {
return Err(Error::from_string(response.error_info.unwrap_or("".to_string())));
return if let Some(err) = &response.error {
Err(proto_err_to_err(err))
} else {
Err(Error::from_string(""))
};
}
let volume_info = serde_json::from_str::<VolumeInfo>(&response.volume_info)?;
@@ -504,7 +557,11 @@ impl DiskAPI for RemoteDisk {
let response = client.delete_paths(request).await?.into_inner();
if !response.success {
return Err(Error::from_string(response.error_info.unwrap_or("".to_string())));
return if let Some(err) = &response.error {
Err(proto_err_to_err(err))
} else {
Err(Error::from_string(""))
};
}
Ok(())
@@ -528,7 +585,11 @@ impl DiskAPI for RemoteDisk {
let response = client.update_metadata(request).await?.into_inner();
if !response.success {
return Err(Error::from_string(response.error_info.unwrap_or("".to_string())));
return if let Some(err) = &response.error {
Err(proto_err_to_err(err))
} else {
Err(Error::from_string(""))
};
}
Ok(())
@@ -550,7 +611,11 @@ impl DiskAPI for RemoteDisk {
let response = client.write_metadata(request).await?.into_inner();
if !response.success {
return Err(Error::from_string(response.error_info.unwrap_or("".to_string())));
return if let Some(err) = &response.error {
Err(proto_err_to_err(err))
} else {
Err(Error::from_string(""))
};
}
Ok(())
@@ -580,7 +645,11 @@ impl DiskAPI for RemoteDisk {
let response = client.read_version(request).await?.into_inner();
if !response.success {
return Err(Error::from_string(response.error_info.unwrap_or("".to_string())));
return if let Some(err) = &response.error {
Err(proto_err_to_err(err))
} else {
Err(Error::from_string(""))
};
}
let file_info = serde_json::from_str::<FileInfo>(&response.file_info)?;
@@ -603,7 +672,11 @@ impl DiskAPI for RemoteDisk {
let response = client.read_xl(request).await?.into_inner();
if !response.success {
return Err(Error::from_string(response.error_info.unwrap_or("".to_string())));
return if let Some(err) = &response.error {
Err(proto_err_to_err(err))
} else {
Err(Error::from_string(""))
};
}
let raw_file_info = serde_json::from_str::<RawFileInfo>(&response.raw_file_info)?;
@@ -637,7 +710,11 @@ impl DiskAPI for RemoteDisk {
let response = client.delete_version(request).await?.into_inner();
if !response.success {
return Err(Error::from_string(response.error_info.unwrap_or("".to_string())));
return if let Some(err) = &response.error {
Err(proto_err_to_err(err))
} else {
Err(Error::from_string(""))
};
}
// let raw_file_info = serde_json::from_str::<RawFileInfo>(&response.raw_file_info)?;
@@ -668,10 +745,11 @@ impl DiskAPI for RemoteDisk {
let response = client.delete_versions(request).await?.into_inner();
if !response.success {
return Err(Error::from_string(format!(
"delete versions remote err: {}",
response.error_info.unwrap_or("None".to_string())
)));
return if let Some(err) = &response.error {
Err(proto_err_to_err(err))
} else {
Err(Error::from_string(""))
};
}
let errors = response
.errors
@@ -702,7 +780,11 @@ impl DiskAPI for RemoteDisk {
let response = client.read_multiple(request).await?.into_inner();
if !response.success {
return Err(Error::from_string(response.error_info.unwrap_or("".to_string())));
return if let Some(err) = &response.error {
Err(proto_err_to_err(err))
} else {
Err(Error::from_string(""))
};
}
let read_multiple_resps = response
@@ -727,7 +809,11 @@ impl DiskAPI for RemoteDisk {
let response = client.delete_volume(request).await?.into_inner();
if !response.success {
return Err(Error::from_string(response.error_info.unwrap_or("".to_string())));
return if let Some(err) = &response.error {
Err(proto_err_to_err(err))
} else {
Err(Error::from_string(""))
};
}
Ok(())
@@ -747,7 +833,11 @@ impl DiskAPI for RemoteDisk {
let response = client.disk_info(request).await?.into_inner();
if !response.success {
return Err(Error::from_string(response.error_info.unwrap_or("".to_string())));
return if let Some(err) = &response.error {
Err(proto_err_to_err(err))
} else {
Err(Error::from_string(""))
};
}
let disk_info = serde_json::from_str::<DiskInfo>(&response.disk_info)?;
+33 -3
View File
@@ -20,6 +20,7 @@ use crate::heal::heal_commands::{
use crate::heal::heal_ops::RUESTFS_RESERVED_BUCKET;
use crate::quorum::{bucket_op_ignored_errs, reduce_write_quorum_errs};
use crate::store::all_local_disk;
use crate::utils::proto_err_to_err;
use crate::utils::wildcard::is_rustfs_meta_bucket_name;
use crate::{
disk::{self, error::DiskError, VolumeInfo},
@@ -523,7 +524,11 @@ impl PeerS3Client for RemotePeerS3Client {
});
let response = client.heal_bucket(request).await?.into_inner();
if !response.success {
return Err(Error::from_string(response.error_info.unwrap_or_default()));
return if let Some(err) = &response.error {
Err(proto_err_to_err(err))
} else {
Err(Error::from_string(""))
};
}
Ok(HealResultItem {
@@ -541,6 +546,13 @@ impl PeerS3Client for RemotePeerS3Client {
.map_err(|err| Error::from_string(format!("can not get client, err: {}", err)))?;
let request = Request::new(ListBucketRequest { options });
let response = client.list_bucket(request).await?.into_inner();
if !response.success {
return if let Some(err) = &response.error {
Err(proto_err_to_err(err))
} else {
Err(Error::from_string(""))
};
}
let bucket_infos = response
.bucket_infos
.into_iter()
@@ -562,7 +574,11 @@ impl PeerS3Client for RemotePeerS3Client {
// TODO: deal with error
if !response.success {
warn!("make bucket error: {:?}", response.error_info);
return if let Some(err) = &response.error {
Err(proto_err_to_err(err))
} else {
Err(Error::from_string(""))
};
}
Ok(())
@@ -577,6 +593,13 @@ impl PeerS3Client for RemotePeerS3Client {
options,
});
let response = client.get_bucket_info(request).await?.into_inner();
if !response.success {
return if let Some(err) = &response.error {
Err(proto_err_to_err(err))
} else {
Err(Error::from_string(""))
};
}
let bucket_info = serde_json::from_str::<BucketInfo>(&response.bucket_info)?;
Ok(bucket_info)
@@ -590,7 +613,14 @@ impl PeerS3Client for RemotePeerS3Client {
let request = Request::new(DeleteBucketRequest {
bucket: bucket.to_string(),
});
let _response = client.delete_bucket(request).await?.into_inner();
let response = client.delete_bucket(request).await?.into_inner();
if !response.success {
return if let Some(err) = &response.error {
Err(proto_err_to_err(err))
} else {
Err(Error::from_string(""))
};
}
Ok(())
}
+19 -2
View File
@@ -1,13 +1,13 @@
use crate::config::error::ConfigError;
use crate::{disk::error::DiskError, error::Error};
use std::{collections::HashMap, fmt::Debug};
// pub type CheckErrorFn = fn(e: &Error) -> bool;
pub trait CheckErrorFn: Debug + Send + Sync + 'static {
fn is(&self, e: &Error) -> bool;
}
#[derive(Debug, thiserror::Error)]
#[derive(Debug, PartialEq, thiserror::Error)]
pub enum QuorumError {
#[error("Read quorum not met")]
Read,
@@ -15,6 +15,23 @@ pub enum QuorumError {
Write,
}
impl QuorumError {
pub fn to_u32(&self) -> u32 {
match self {
QuorumError::Read => 0x01,
QuorumError::Write => 0x02,
}
}
pub fn from_u32(error: u32) -> Option<Self> {
match error {
0x01 => Some(QuorumError::Read),
0x02 => Some(QuorumError::Write),
_ => None,
}
}
}
pub fn base_ignored_errs() -> Vec<Box<dyn CheckErrorFn>> {
vec![
Box::new(DiskError::DiskNotFound),
+65
View File
@@ -76,6 +76,71 @@ pub enum StorageError {
DecommissionNotStarted,
}
impl StorageError {
pub fn to_u32(&self) -> u32 {
match self {
StorageError::NotImplemented => 0x01,
StorageError::InvalidArgument(_, _, _) => 0x02,
StorageError::MethodNotAllowed => 0x03,
StorageError::BucketNotFound(_) => 0x04,
StorageError::BucketNotEmpty(_) => 0x05,
StorageError::BucketNameInvalid(_) => 0x06,
StorageError::ObjectNameInvalid(_, _) => 0x07,
StorageError::BucketExists(_) => 0x08,
StorageError::StorageFull => 0x09,
StorageError::SlowDown => 0x0A,
StorageError::PrefixAccessDenied(_, _) => 0x0B,
StorageError::InvalidUploadIDKeyCombination(_, _) => 0x0C,
StorageError::MalformedUploadID(_) => 0x0D,
StorageError::ObjectNameTooLong(_, _) => 0x0E,
StorageError::ObjectNamePrefixAsSlash(_, _) => 0x0F,
StorageError::ObjectNotFound(_, _) => 0x10,
StorageError::VersionNotFound(_, _, _) => 0x11,
StorageError::InvalidUploadID(_, _, _) => 0x12,
StorageError::InvalidVersionID(_, _, _) => 0x13,
StorageError::DataMovementOverwriteErr(_, _, _) => 0x14,
StorageError::ObjectExistsAsDirectory(_, _) => 0x15,
StorageError::InsufficientReadQuorum => 0x16,
StorageError::InsufficientWriteQuorum => 0x17,
StorageError::DecommissionNotStarted => 0x18,
}
}
pub fn from_u32(error: u32) -> Option<Self> {
match error {
0x01 => Some(StorageError::NotImplemented),
0x02 => Some(StorageError::InvalidArgument(Default::default(), Default::default(), Default::default())),
0x03 => Some(StorageError::MethodNotAllowed),
0x04 => Some(StorageError::BucketNotFound(Default::default())),
0x05 => Some(StorageError::BucketNotEmpty(Default::default())),
0x06 => Some(StorageError::BucketNameInvalid(Default::default())),
0x07 => Some(StorageError::ObjectNameInvalid(Default::default(), Default::default())),
0x08 => Some(StorageError::BucketExists(Default::default())),
0x09 => Some(StorageError::StorageFull),
0x0A => Some(StorageError::SlowDown),
0x0B => Some(StorageError::PrefixAccessDenied(Default::default(), Default::default())),
0x0C => Some(StorageError::InvalidUploadIDKeyCombination(Default::default(), Default::default())),
0x0D => Some(StorageError::MalformedUploadID(Default::default())),
0x0E => Some(StorageError::ObjectNameTooLong(Default::default(), Default::default())),
0x0F => Some(StorageError::ObjectNamePrefixAsSlash(Default::default(), Default::default())),
0x10 => Some(StorageError::ObjectNotFound(Default::default(), Default::default())),
0x11 => Some(StorageError::VersionNotFound(Default::default(), Default::default(), Default::default())),
0x12 => Some(StorageError::InvalidUploadID(Default::default(), Default::default(), Default::default())),
0x13 => Some(StorageError::InvalidVersionID(Default::default(), Default::default(), Default::default())),
0x14 => Some(StorageError::DataMovementOverwriteErr(
Default::default(),
Default::default(),
Default::default(),
)),
0x15 => Some(StorageError::ObjectExistsAsDirectory(Default::default(), Default::default())),
0x16 => Some(StorageError::InsufficientReadQuorum),
0x17 => Some(StorageError::InsufficientWriteQuorum),
0x18 => Some(StorageError::DecommissionNotStarted),
_ => None,
}
}
}
pub fn to_object_err(err: Error, params: Vec<&str>) -> Error {
if let Some(e) = err.downcast_ref::<DiskError>() {
match e {
+24
View File
@@ -16,6 +16,7 @@ use std::{
fmt::Debug,
};
use crate::config::error::ConfigError;
use tracing::{debug, warn};
use uuid::Uuid;
@@ -330,3 +331,26 @@ impl ErasureError {
false
}
}
impl ErasureError {
pub fn to_u32(&self) -> u32 {
match self {
ErasureError::ErasureReadQuorum => 0x01,
ErasureError::_ErasureWriteQuorum => 0x02,
ErasureError::NotFirstDisk => 0x03,
ErasureError::FirstDiskWait => 0x04,
ErasureError::InvalidPart(_) => 0x05,
}
}
pub fn from_u32(error: u32) -> Option<Self> {
match error {
0x01 => Some(ErasureError::ErasureReadQuorum),
0x02 => Some(ErasureError::_ErasureWriteQuorum),
0x03 => Some(ErasureError::NotFirstDisk),
0x04 => Some(ErasureError::FirstDiskWait),
0x05 => Some(ErasureError::InvalidPart(Default::default())),
_ => None,
}
}
}
+92 -8
View File
@@ -5,6 +5,7 @@ use crate::error::Error;
use crate::quorum::QuorumError;
use crate::store_err::StorageError;
use crate::store_init::ErasureError;
use protos::proto_gen::node_service::Error as Proto_Error;
pub mod bool_flag;
pub mod crypto;
@@ -17,20 +18,103 @@ pub mod path;
pub mod wildcard;
pub mod xml;
const DISK_ERROR_MASK: u32 = 0x00001000;
const STORAGE_ERROR_MASK: u8 = 0x20;
const BUCKET_METADATA_ERROR_MASK: u8 = 0x30;
const CONFIG_ERROR_MASK: u8 = 0x40;
const QUORUM_ERROR_MASK: u8 = 0x50;
const ERASURE_ERROR_MASK: u8 = 0x60;
const ERROR_MODULE_MASK: u32 = 0xFF00;
pub const ERROR_TYPE_MASK: u32 = 0x00FF;
const DISK_ERROR_MASK: u32 = 0x0100;
const STORAGE_ERROR_MASK: u32 = 0x0200;
const BUCKET_METADATA_ERROR_MASK: u32 = 0x0300;
const CONFIG_ERROR_MASK: u32 = 0x04000;
const QUORUM_ERROR_MASK: u32 = 0x0500;
const ERASURE_ERROR_MASK: u32 = 0x0600;
// error to u8
pub fn error_to_u8(err: &Error) -> u8 {
pub fn error_to_u32(err: &Error) -> u32 {
if let Some(e) = err.downcast_ref::<DiskError>() {
DISK_ERROR_MASK | e.to_u32()
} else if let Some(e) = err.downcast_ref::<StorageError>() {
STORAGE_ERROR_MASK | e.to_u32()
} else if let Some(e) = err.downcast_ref::<BucketMetadataError>() {
BUCKET_METADATA_ERROR_MASK | e.to_u32()
} else if let Some(e) = err.downcast_ref::<ConfigError>() {
CONFIG_ERROR_MASK | e.to_u32()
} else if let Some(e) = err.downcast_ref::<QuorumError>() {
QUORUM_ERROR_MASK | e.to_u32()
} else if let Some(e) = err.downcast_ref::<ErasureError>() {
ERASURE_ERROR_MASK | e.to_u32()
} else {
0
}
0
}
pub fn u32_to_error(e: u32) -> Option<Error> {
match e & ERROR_MODULE_MASK {
DISK_ERROR_MASK => DiskError::from_u32(e & ERROR_TYPE_MASK).map(|e| Error::new(e)),
STORAGE_ERROR_MASK => StorageError::from_u32(e & ERROR_TYPE_MASK).map(|e| Error::new(e)),
BUCKET_METADATA_ERROR_MASK => BucketMetadataError::from_u32(e & ERROR_TYPE_MASK).map(|e| Error::new(e)),
CONFIG_ERROR_MASK => ConfigError::from_u32(e & ERROR_TYPE_MASK).map(|e| Error::new(e)),
QUORUM_ERROR_MASK => QuorumError::from_u32(e & ERROR_TYPE_MASK).map(|e| Error::new(e)),
ERASURE_ERROR_MASK => ErasureError::from_u32(e & ERROR_TYPE_MASK).map(|e| Error::new(e)),
_ => None,
}
}
pub fn err_to_proto_err(err: &Error, msg: &str) -> Proto_Error {
let num = error_to_u32(err);
Proto_Error {
code: num,
error_info: msg.to_string(),
}
}
pub fn proto_err_to_err(err: &Proto_Error) -> Error {
if let Some(e) = u32_to_error(err.code) {
e
} else {
Error::from_string(err.error_info.clone())
}
}
#[test]
fn test_u32_to_error() {
let error = Error::new(DiskError::FileCorrupt);
let num = error_to_u32(&error);
let new_error = u32_to_error(num);
assert!(new_error.is_some());
assert_eq!(new_error.unwrap().downcast_ref::<DiskError>(), Some(&DiskError::FileCorrupt));
let error = Error::new(StorageError::BucketNotEmpty(Default::default()));
let num = error_to_u32(&error);
let new_error = u32_to_error(num);
assert!(new_error.is_some());
assert_eq!(
new_error.unwrap().downcast_ref::<StorageError>(),
Some(&StorageError::BucketNotEmpty(Default::default()))
);
let error = Error::new(BucketMetadataError::BucketObjectLockConfigNotFound);
let num = error_to_u32(&error);
let new_error = u32_to_error(num);
assert!(new_error.is_some());
assert_eq!(
new_error.unwrap().downcast_ref::<BucketMetadataError>(),
Some(&BucketMetadataError::BucketObjectLockConfigNotFound)
);
let error = Error::new(ConfigError::NotFound);
let num = error_to_u32(&error);
let new_error = u32_to_error(num);
assert!(new_error.is_some());
assert_eq!(new_error.unwrap().downcast_ref::<ConfigError>(), Some(&ConfigError::NotFound));
let error = Error::new(QuorumError::Read);
let num = error_to_u32(&error);
let new_error = u32_to_error(num);
assert!(new_error.is_some());
assert_eq!(new_error.unwrap().downcast_ref::<QuorumError>(), Some(&QuorumError::Read));
let error = Error::new(ErasureError::ErasureReadQuorum);
let num = error_to_u32(&error);
let new_error = u32_to_error(num);
assert!(new_error.is_some());
assert_eq!(new_error.unwrap().downcast_ref::<ErasureError>(), Some(&ErasureError::ErasureReadQuorum));
}