diff --git a/.gitignore b/.gitignore index 0dc3785f..3f19f03b 100644 --- a/.gitignore +++ b/.gitignore @@ -2,3 +2,4 @@ .DS_Store .idea .vscode +/test \ No newline at end of file diff --git a/ecstore/src/disk/error.rs b/ecstore/src/disk/error.rs index 7b69463a..24864213 100644 --- a/ecstore/src/disk/error.rs +++ b/ecstore/src/disk/error.rs @@ -100,9 +100,6 @@ pub enum DiskError { #[error("more data was sent than what was advertised")] MoreData, - - #[error("other io err {0}")] - IoError(io::Error), } impl DiskError { @@ -172,95 +169,89 @@ impl CheckErrorFn for DiskError { } } -pub fn clone_err(err: &Error) -> Error { - if let Some(e) = err.downcast_ref::() { - match e { - DiskError::MaxVersionsExceeded => Error::new(DiskError::MaxVersionsExceeded), - DiskError::Unexpected => Error::new(DiskError::Unexpected), - DiskError::CorruptedFormat => Error::new(DiskError::CorruptedFormat), - DiskError::CorruptedBackend => Error::new(DiskError::CorruptedBackend), - DiskError::UnformattedDisk => Error::new(DiskError::UnformattedDisk), - DiskError::InconsistentDisk => Error::new(DiskError::InconsistentDisk), - DiskError::UnsupportedDisk => Error::new(DiskError::UnsupportedDisk), - DiskError::DiskFull => Error::new(DiskError::DiskFull), - DiskError::DiskNotDir => Error::new(DiskError::DiskNotDir), - DiskError::DiskNotFound => Error::new(DiskError::DiskNotFound), - DiskError::DiskOngoingReq => Error::new(DiskError::DiskOngoingReq), - DiskError::DriveIsRoot => Error::new(DiskError::DriveIsRoot), - DiskError::FaultyRemoteDisk => Error::new(DiskError::FaultyRemoteDisk), - DiskError::FaultyDisk => Error::new(DiskError::FaultyDisk), - DiskError::DiskAccessDenied => Error::new(DiskError::DiskAccessDenied), - DiskError::FileNotFound => Error::new(DiskError::FileNotFound), - DiskError::FileVersionNotFound => Error::new(DiskError::FileVersionNotFound), - DiskError::TooManyOpenFiles => Error::new(DiskError::TooManyOpenFiles), - DiskError::FileNameTooLong => Error::new(DiskError::FileNameTooLong), - DiskError::VolumeExists => Error::new(DiskError::VolumeExists), - DiskError::IsNotRegular => Error::new(DiskError::IsNotRegular), - DiskError::PathNotFound => Error::new(DiskError::PathNotFound), - DiskError::VolumeNotFound => Error::new(DiskError::VolumeNotFound), - DiskError::VolumeNotEmpty => Error::new(DiskError::VolumeNotEmpty), - DiskError::VolumeAccessDenied => Error::new(DiskError::VolumeAccessDenied), - DiskError::FileAccessDenied => Error::new(DiskError::FileAccessDenied), - DiskError::FileCorrupt => Error::new(DiskError::FileCorrupt), - DiskError::BitrotHashAlgoInvalid => Error::new(DiskError::BitrotHashAlgoInvalid), - DiskError::CrossDeviceLink => Error::new(DiskError::CrossDeviceLink), - DiskError::LessData => Error::new(DiskError::LessData), - DiskError::MoreData => Error::new(DiskError::MoreData), - DiskError::IoError(ioerr) => Error::msg(ioerr.to_string()), - } - } else { - Error::msg(err.to_string()) +pub fn clone_disk_err(e: &DiskError) -> Error { + match e { + DiskError::MaxVersionsExceeded => Error::new(DiskError::MaxVersionsExceeded), + DiskError::Unexpected => Error::new(DiskError::Unexpected), + DiskError::CorruptedFormat => Error::new(DiskError::CorruptedFormat), + DiskError::CorruptedBackend => Error::new(DiskError::CorruptedBackend), + DiskError::UnformattedDisk => Error::new(DiskError::UnformattedDisk), + DiskError::InconsistentDisk => Error::new(DiskError::InconsistentDisk), + DiskError::UnsupportedDisk => Error::new(DiskError::UnsupportedDisk), + DiskError::DiskFull => Error::new(DiskError::DiskFull), + DiskError::DiskNotDir => Error::new(DiskError::DiskNotDir), + DiskError::DiskNotFound => Error::new(DiskError::DiskNotFound), + DiskError::DiskOngoingReq => Error::new(DiskError::DiskOngoingReq), + DiskError::DriveIsRoot => Error::new(DiskError::DriveIsRoot), + DiskError::FaultyRemoteDisk => Error::new(DiskError::FaultyRemoteDisk), + DiskError::FaultyDisk => Error::new(DiskError::FaultyDisk), + DiskError::DiskAccessDenied => Error::new(DiskError::DiskAccessDenied), + DiskError::FileNotFound => Error::new(DiskError::FileNotFound), + DiskError::FileVersionNotFound => Error::new(DiskError::FileVersionNotFound), + DiskError::TooManyOpenFiles => Error::new(DiskError::TooManyOpenFiles), + DiskError::FileNameTooLong => Error::new(DiskError::FileNameTooLong), + DiskError::VolumeExists => Error::new(DiskError::VolumeExists), + DiskError::IsNotRegular => Error::new(DiskError::IsNotRegular), + DiskError::PathNotFound => Error::new(DiskError::PathNotFound), + DiskError::VolumeNotFound => Error::new(DiskError::VolumeNotFound), + DiskError::VolumeNotEmpty => Error::new(DiskError::VolumeNotEmpty), + DiskError::VolumeAccessDenied => Error::new(DiskError::VolumeAccessDenied), + DiskError::FileAccessDenied => Error::new(DiskError::FileAccessDenied), + DiskError::FileCorrupt => Error::new(DiskError::FileCorrupt), + DiskError::BitrotHashAlgoInvalid => Error::new(DiskError::BitrotHashAlgoInvalid), + DiskError::CrossDeviceLink => Error::new(DiskError::CrossDeviceLink), + DiskError::LessData => Error::new(DiskError::LessData), + DiskError::MoreData => Error::new(DiskError::MoreData), } } - -pub fn ioerr_to_diskerr(e:io::Error)->DiskError{ -match e.kind(){ - io::ErrorKind::NotFound => DiskError::FileNotFound, - io::ErrorKind::PermissionDenied => DiskError::FileAccessDenied, - // io::ErrorKind::ConnectionRefused => todo!(), - // io::ErrorKind::ConnectionReset => todo!(), - // io::ErrorKind::HostUnreachable => todo!(), - // io::ErrorKind::NetworkUnreachable => todo!(), - // io::ErrorKind::ConnectionAborted => todo!(), - // io::ErrorKind::NotConnected => todo!(), - // io::ErrorKind::AddrInUse => todo!(), - // io::ErrorKind::AddrNotAvailable => todo!(), - // io::ErrorKind::NetworkDown => todo!(), - // io::ErrorKind::BrokenPipe => todo!(), - // io::ErrorKind::AlreadyExists => todo!(), - // io::ErrorKind::WouldBlock => todo!(), - // io::ErrorKind::NotADirectory => DiskError::FileNotFound, - // io::ErrorKind::IsADirectory => DiskError::FileNotFound, - // io::ErrorKind::DirectoryNotEmpty => DiskError::VolumeNotEmpty, - // io::ErrorKind::ReadOnlyFilesystem => todo!(), - // io::ErrorKind::FilesystemLoop => todo!(), - // io::ErrorKind::StaleNetworkFileHandle => todo!(), - // io::ErrorKind::InvalidInput => todo!(), - // io::ErrorKind::InvalidData => todo!(), - // io::ErrorKind::TimedOut => todo!(), - // io::ErrorKind::WriteZero => todo!(), - // io::ErrorKind::StorageFull => DiskError::DiskFull, - // io::ErrorKind::NotSeekable => todo!(), - // io::ErrorKind::FilesystemQuotaExceeded => todo!(), - // io::ErrorKind::FileTooLarge => todo!(), - // io::ErrorKind::ResourceBusy => todo!(), - // io::ErrorKind::ExecutableFileBusy => todo!(), - // io::ErrorKind::Deadlock => todo!(), - // io::ErrorKind::CrossesDevices => todo!(), - // io::ErrorKind::TooManyLinks =>DiskError::TooManyOpenFiles, - // io::ErrorKind::InvalidFilename => todo!(), - // io::ErrorKind::ArgumentListTooLong => todo!(), - // io::ErrorKind::Interrupted => todo!(), - // io::ErrorKind::Unsupported => todo!(), - // io::ErrorKind::UnexpectedEof => todo!(), - // io::ErrorKind::OutOfMemory => todo!(), - // io::ErrorKind::Other => todo!(), - // TODO: 把不支持的king用字符串处理 - _ => DiskError::IoError(e), -} +pub fn ioerr_to_err(e: io::Error) -> Error { + match e.kind() { + io::ErrorKind::NotFound => Error::new(DiskError::FileNotFound), + io::ErrorKind::PermissionDenied => Error::new(DiskError::FileAccessDenied), + // io::ErrorKind::ConnectionRefused => todo!(), + // io::ErrorKind::ConnectionReset => todo!(), + // io::ErrorKind::HostUnreachable => todo!(), + // io::ErrorKind::NetworkUnreachable => todo!(), + // io::ErrorKind::ConnectionAborted => todo!(), + // io::ErrorKind::NotConnected => todo!(), + // io::ErrorKind::AddrInUse => todo!(), + // io::ErrorKind::AddrNotAvailable => todo!(), + // io::ErrorKind::NetworkDown => todo!(), + // io::ErrorKind::BrokenPipe => todo!(), + // io::ErrorKind::AlreadyExists => todo!(), + // io::ErrorKind::WouldBlock => todo!(), + // io::ErrorKind::NotADirectory => DiskError::FileNotFound, + // io::ErrorKind::IsADirectory => DiskError::FileNotFound, + // io::ErrorKind::DirectoryNotEmpty => DiskError::VolumeNotEmpty, + // io::ErrorKind::ReadOnlyFilesystem => todo!(), + // io::ErrorKind::FilesystemLoop => todo!(), + // io::ErrorKind::StaleNetworkFileHandle => todo!(), + // io::ErrorKind::InvalidInput => todo!(), + // io::ErrorKind::InvalidData => todo!(), + // io::ErrorKind::TimedOut => todo!(), + // io::ErrorKind::WriteZero => todo!(), + // io::ErrorKind::StorageFull => DiskError::DiskFull, + // io::ErrorKind::NotSeekable => todo!(), + // io::ErrorKind::FilesystemQuotaExceeded => todo!(), + // io::ErrorKind::FileTooLarge => todo!(), + // io::ErrorKind::ResourceBusy => todo!(), + // io::ErrorKind::ExecutableFileBusy => todo!(), + // io::ErrorKind::Deadlock => todo!(), + // io::ErrorKind::CrossesDevices => todo!(), + // io::ErrorKind::TooManyLinks =>DiskError::TooManyOpenFiles, + // io::ErrorKind::InvalidFilename => todo!(), + // io::ErrorKind::ArgumentListTooLong => todo!(), + // io::ErrorKind::Interrupted => todo!(), + // io::ErrorKind::Unsupported => todo!(), + // io::ErrorKind::UnexpectedEof => todo!(), + // io::ErrorKind::OutOfMemory => todo!(), + // io::ErrorKind::Other => todo!(), + // TODO: 把不支持的king用字符串处理 + _ => Error::new(e), + } } -pub fn os_is_not_exist(e:io::Error) -> bool{ - e.kind() == ErrorKind::NotFound -} \ No newline at end of file +pub fn os_is_not_exist(e: io::Error) -> bool { + e.kind() == ErrorKind::NotFound +} diff --git a/ecstore/src/disk/local.rs b/ecstore/src/disk/local.rs index fd0e5d38..9cd6a70f 100644 --- a/ecstore/src/disk/local.rs +++ b/ecstore/src/disk/local.rs @@ -1,4 +1,4 @@ -use super::error::{ioerr_to_diskerr, os_is_not_exist}; +use super::error::os_is_not_exist; use super::{endpoint::Endpoint, error::DiskError, format::FormatV3}; use super::{ os, DeleteOptions, DiskAPI, DiskLocation, FileInfoVersions, FileReader, FileWriter, MetaCacheEntry, ReadMultipleReq, @@ -971,7 +971,7 @@ impl DiskAPI for LocalDisk { })?; for entry in entries { - if utils::path::has_suffix(&entry, SLASH_SEPARATOR) || !Self::is_valid_volname(&entry) { + if !utils::path::has_suffix(&entry, SLASH_SEPARATOR) || !Self::is_valid_volname(&entry) { continue; } diff --git a/ecstore/src/disk/os.rs b/ecstore/src/disk/os.rs index 4fa9336b..016e5e3c 100644 --- a/ecstore/src/disk/os.rs +++ b/ecstore/src/disk/os.rs @@ -8,7 +8,7 @@ use crate::{ utils, }; -use super::error::{ioerr_to_diskerr, DiskError}; +use super::error::{ioerr_to_err, DiskError}; fn check_path_length(path_name: &str) -> Result<()> { // Apple OS X path length is limited to 1016 @@ -51,7 +51,7 @@ fn check_path_length(path_name: &str) -> Result<()> { pub async fn make_dir_all(path: impl AsRef) -> Result<()> { check_path_length(path.as_ref().to_string_lossy().to_string().as_str())?; - utils::fs::make_dir_all(path.as_ref()).map_err(ioerr_to_diskerr).await?; + utils::fs::make_dir_all(path.as_ref()).map_err(ioerr_to_err).await?; Ok(()) } diff --git a/ecstore/src/disk/remote.rs b/ecstore/src/disk/remote.rs index 0034235f..82723e1f 100644 --- a/ecstore/src/disk/remote.rs +++ b/ecstore/src/disk/remote.rs @@ -401,10 +401,12 @@ impl DiskAPI for RemoteDisk { Ok(volume_info) } - async fn delete_paths(&self, volume: &str, paths: &[&str]) -> Result<()> { + async fn delete_paths(&self, _volume: &str, _paths: &[&str]) -> Result<()> { + // TODO: unimplemented!() } - async fn update_metadata(&self, volume: &str, path: &str, fi: FileInfo, opts: UpdateMetadataOpts) { + async fn update_metadata(&self, _volume: &str, _path: &str, _fi: FileInfo, _opts: UpdateMetadataOpts) { + // TODO: unimplemented!() } diff --git a/ecstore/src/erasure.rs b/ecstore/src/erasure.rs index cd2d227a..da245116 100644 --- a/ecstore/src/erasure.rs +++ b/ecstore/src/erasure.rs @@ -94,11 +94,14 @@ impl Erasure { } } - warn!("Erasure encode errs {:?}", errs); + warn!("Erasure encode errs {:?}", &errs); - let err_idx = reduce_write_quorum_errs(&errs, object_op_ignored_errs().as_ref(), write_quorum)?; - if errs[err_idx].is_some() { - let err = errs[err_idx].take().unwrap(); + let none_count = errs.iter().filter(|&x| x.is_none()).count(); + if none_count >= write_quorum { + continue; + } + + if let Some(err) = reduce_write_quorum_errs(&errs, object_op_ignored_errs().as_ref(), write_quorum) { return Err(err); } } diff --git a/ecstore/src/error.rs b/ecstore/src/error.rs index 24d2936b..aa513fc5 100644 --- a/ecstore/src/error.rs +++ b/ecstore/src/error.rs @@ -1,5 +1,9 @@ +use std::io; + use tracing_error::{SpanTrace, SpanTraceStatus}; +use crate::disk::error::{clone_disk_err, DiskError}; + pub type StdError = Box; pub type Result = std::result::Result; @@ -80,3 +84,16 @@ impl std::fmt::Display for Error { Ok(()) } } + +impl Clone for Error { + fn clone(&self) -> Self { + if let Some(e) = self.downcast_ref::() { + clone_disk_err(e) + } else if let Some(e) = self.downcast_ref::() { + Error::new(io::Error::new(e.kind(), e.to_string())) + } else { + // TODO: 优化其他类型 + Error::msg(self.to_string()) + } + } +} diff --git a/ecstore/src/peer.rs b/ecstore/src/peer.rs index 241280c0..89eea2c0 100644 --- a/ecstore/src/peer.rs +++ b/ecstore/src/peer.rs @@ -262,6 +262,7 @@ impl PeerS3Client for LocalPeerS3Client { } } + warn!("list_bucket ress {:?}", &ress); warn!("list_bucket errs {:?}", &errs); let mut uniq_map: HashMap<&String, &VolumeInfo> = HashMap::new(); diff --git a/ecstore/src/quorum.rs b/ecstore/src/quorum.rs index 13544632..72e33109 100644 --- a/ecstore/src/quorum.rs +++ b/ecstore/src/quorum.rs @@ -1,4 +1,7 @@ -use crate::{disk::error::DiskError, error::Error}; +use crate::{ + disk::error::DiskError, + error::{Error, Result}, +}; use std::{collections::HashMap, fmt::Debug}; // pub type CheckErrorFn = fn(e: &Error) -> bool; @@ -27,8 +30,7 @@ pub fn base_ignored_errs() -> Vec> { pub fn object_op_ignored_errs() -> Vec> { let mut base = base_ignored_errs(); - - let ext:Vec> = vec![ + let ext: Vec> = vec![ // Box::new(DiskError::DiskNotFound), // Box::new(DiskError::FaultyDisk), // Box::new(DiskError::FaultyRemoteDisk), @@ -47,7 +49,7 @@ fn is_err_ignored(err: &Error, ignored_errs: &Vec>) -> boo } // 减少错误数量并返回出现次数最多的错误 -fn reduce_errs(errs: &Vec>, ignored_errs: &Vec>) -> (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(); @@ -80,8 +82,10 @@ fn reduce_errs(errs: &Vec>, ignored_errs: &Vec>, ignored_errs: &Vec>, ignored_errs: &Vec>, quorum: usize) -> Option { +fn reduce_quorum_errs( + errs: &Vec>, + ignored_errs: &Vec>, + quorum: usize, + quorum_err: QuorumError, +) -> Option { let (max_count, max_err) = reduce_errs(errs, ignored_errs); if max_count >= quorum { max_err } else { - None + Some(Error::new(quorum_err)) } } @@ -106,13 +115,8 @@ pub fn reduce_read_quorum_errs( errs: &mut Vec>, ignored_errs: &Vec>, read_quorum: usize, -) -> Result { - let idx = reduce_quorum_errs(errs, ignored_errs, read_quorum); - if idx.is_none() { - return Err(Error::new(QuorumError::Read)); - } - - Ok(idx.unwrap()) +) -> Option { + reduce_quorum_errs(errs, ignored_errs, read_quorum, QuorumError::Read) } // 根据写quorum验证错误数量 @@ -121,12 +125,6 @@ pub fn reduce_write_quorum_errs( errs: &Vec>, ignored_errs: &Vec>, write_quorum: usize, -) -> Result { - let idx = reduce_quorum_errs(errs, ignored_errs, write_quorum); - - if idx.is_none() { - return Err(Error::new(QuorumError::Write)); - } - - Ok(idx.unwrap()) +) -> Option { + reduce_quorum_errs(errs, ignored_errs, write_quorum, QuorumError::Write) } diff --git a/ecstore/src/utils/fs.rs b/ecstore/src/utils/fs.rs index 67405d4d..1e1cae40 100644 --- a/ecstore/src/utils/fs.rs +++ b/ecstore/src/utils/fs.rs @@ -1,10 +1,10 @@ -use std::{fs::Metadata, path::Path}; +use std::{fs::Metadata, path::Path}; use tokio::{fs, io}; -#[cfg(target_os = "linux")] +#[cfg(not(target_os = "windows"))] pub fn same_file(f1: &Metadata, f2: &Metadata) -> bool { - use os::unix::fs::MetadataExt; + use std::os::unix::fs::MetadataExt; if f1.dev() != f2.dev() { return false; @@ -31,12 +31,11 @@ pub fn same_file(f1: &Metadata, f2: &Metadata) -> bool { #[cfg(target_os = "windows")] pub fn same_file(f1: &Metadata, f2: &Metadata) -> bool { if f1.permissions() != f2.permissions() { - return false; + return false; } - if f1.file_type() != f2.file_type() { - return false; + return false; } if f1.len() != f2.len() { @@ -45,11 +44,11 @@ pub fn same_file(f1: &Metadata, f2: &Metadata) -> bool { true } -pub async fn access(path: impl AsRef) -> io::Result<()>{ +pub async fn access(path: impl AsRef) -> io::Result<()> { fs::metadata(path).await?; Ok(()) } -pub async fn make_dir_all(path: impl AsRef) -> io::Result<()>{ +pub async fn make_dir_all(path: impl AsRef) -> io::Result<()> { fs::create_dir_all(path.as_ref()).await -} \ No newline at end of file +} diff --git a/scripts/run.sh b/scripts/run.sh index b48b9abc..1a7b2073 100755 --- a/scripts/run.sh +++ b/scripts/run.sh @@ -1,24 +1,27 @@ #!/bin/bash +current_dir=$(pwd) + mkdir -p ./target/volume/test mkdir -p ./target/volume/test{0..4} -# DATA_DIR="./target/volume/test" -DATA_DIR="./target/volume/test{0...4}" - -if [ -n "$1" ]; then - DATA_DIR="$1" -fi if [ -z "$RUST_LOG" ]; then export RUST_LOG="rustfs=debug,ecstore=debug,s3s=debug" fi -# cargo run "$DATA_DIR" +DATA_DIR_ARG="./target/volume/test{0...4}" + +if [ -n "$1" ]; then + DATA_DIR_ARG="$1" +fi + + +# cargo run "$DATA_DIR_ARG" # -- --access-key AKEXAMPLERUSTFS \ # --secret-key SKEXAMPLERUSTFS \ # --address 0.0.0.0:9010 \ # --domain-name 127.0.0.1:9010 \ - # "$DATA_DIR" + # "$DATA_DIR_ARG" -cargo run "$DATA_DIR" \ No newline at end of file +cargo run "$DATA_DIR_ARG" \ No newline at end of file