From 6af228d82b35ab2d648649cde4fdbd06568caec5 Mon Sep 17 00:00:00 2001 From: junxiang Mu <1948535941@qq.com> Date: Wed, 18 Dec 2024 20:50:22 +0800 Subject: [PATCH] refactor error framework Signed-off-by: junxiang Mu <1948535941@qq.com> --- .../src/generated/proto_gen/node_service.rs | 135 +++-- common/protos/src/node.proto | 71 +-- ecstore/src/bucket/error.rs | 29 + ecstore/src/config/error.rs | 18 +- ecstore/src/disk/error.rs | 43 +- ecstore/src/disk/mod.rs | 17 +- ecstore/src/disk/remote.rs | 142 ++++- ecstore/src/peer.rs | 36 +- ecstore/src/quorum.rs | 21 +- ecstore/src/store_err.rs | 65 +++ ecstore/src/store_init.rs | 24 + ecstore/src/utils/mod.rs | 100 +++- rustfs/src/grpc.rs | 547 +++++++++++++----- 13 files changed, 957 insertions(+), 291 deletions(-) diff --git a/common/protos/src/generated/proto_gen/node_service.rs b/common/protos/src/generated/proto_gen/node_service.rs index 6c4aef0e..58aaa10f 100644 --- a/common/protos/src/generated/proto_gen/node_service.rs +++ b/common/protos/src/generated/proto_gen/node_service.rs @@ -1,6 +1,13 @@ // This file is @generated by prost-build. /// -------------------------------------------------------------------- #[derive(Clone, PartialEq, ::prost::Message)] +pub struct Error { + #[prost(uint32, tag = "1")] + pub code: u32, + #[prost(string, tag = "2")] + pub error_info: ::prost::alloc::string::String, +} +#[derive(Clone, PartialEq, ::prost::Message)] pub struct PingRequest { #[prost(uint64, tag = "1")] pub version: u64, @@ -25,8 +32,8 @@ pub struct HealBucketRequest { pub struct HealBucketResponse { #[prost(bool, tag = "1")] pub success: bool, - #[prost(string, optional, tag = "2")] - pub error_info: ::core::option::Option<::prost::alloc::string::String>, + #[prost(message, optional, tag = "2")] + pub error: ::core::option::Option, } #[derive(Clone, PartialEq, ::prost::Message)] pub struct ListBucketRequest { @@ -39,8 +46,8 @@ pub struct ListBucketResponse { pub success: bool, #[prost(string, repeated, tag = "2")] pub bucket_infos: ::prost::alloc::vec::Vec<::prost::alloc::string::String>, - #[prost(string, optional, tag = "3")] - pub error_info: ::core::option::Option<::prost::alloc::string::String>, + #[prost(message, optional, tag = "3")] + pub error: ::core::option::Option, } #[derive(Clone, PartialEq, ::prost::Message)] pub struct MakeBucketRequest { @@ -53,8 +60,8 @@ pub struct MakeBucketRequest { pub struct MakeBucketResponse { #[prost(bool, tag = "1")] pub success: bool, - #[prost(string, optional, tag = "2")] - pub error_info: ::core::option::Option<::prost::alloc::string::String>, + #[prost(message, optional, tag = "2")] + pub error: ::core::option::Option, } #[derive(Clone, PartialEq, ::prost::Message)] pub struct GetBucketInfoRequest { @@ -69,8 +76,8 @@ pub struct GetBucketInfoResponse { pub success: bool, #[prost(string, tag = "2")] pub bucket_info: ::prost::alloc::string::String, - #[prost(string, optional, tag = "3")] - pub error_info: ::core::option::Option<::prost::alloc::string::String>, + #[prost(message, optional, tag = "3")] + pub error: ::core::option::Option, } #[derive(Clone, PartialEq, ::prost::Message)] pub struct DeleteBucketRequest { @@ -81,8 +88,8 @@ pub struct DeleteBucketRequest { pub struct DeleteBucketResponse { #[prost(bool, tag = "1")] pub success: bool, - #[prost(string, optional, tag = "2")] - pub error_info: ::core::option::Option<::prost::alloc::string::String>, + #[prost(message, optional, tag = "2")] + pub error: ::core::option::Option, } #[derive(Clone, PartialEq, ::prost::Message)] pub struct ReadAllRequest { @@ -100,8 +107,8 @@ pub struct ReadAllResponse { pub success: bool, #[prost(bytes = "vec", tag = "2")] pub data: ::prost::alloc::vec::Vec, - #[prost(string, optional, tag = "3")] - pub error_info: ::core::option::Option<::prost::alloc::string::String>, + #[prost(message, optional, tag = "3")] + pub error: ::core::option::Option, } #[derive(Clone, PartialEq, ::prost::Message)] pub struct WriteAllRequest { @@ -119,8 +126,8 @@ pub struct WriteAllRequest { pub struct WriteAllResponse { #[prost(bool, tag = "1")] pub success: bool, - #[prost(string, optional, tag = "2")] - pub error_info: ::core::option::Option<::prost::alloc::string::String>, + #[prost(message, optional, tag = "2")] + pub error: ::core::option::Option, } #[derive(Clone, PartialEq, ::prost::Message)] pub struct DeleteRequest { @@ -138,8 +145,8 @@ pub struct DeleteRequest { pub struct DeleteResponse { #[prost(bool, tag = "1")] pub success: bool, - #[prost(string, optional, tag = "2")] - pub error_info: ::core::option::Option<::prost::alloc::string::String>, + #[prost(message, optional, tag = "2")] + pub error: ::core::option::Option, } #[derive(Clone, PartialEq, ::prost::Message)] pub struct VerifyFileRequest { @@ -159,8 +166,8 @@ pub struct VerifyFileResponse { pub success: bool, #[prost(string, tag = "2")] pub check_parts_resp: ::prost::alloc::string::String, - #[prost(string, optional, tag = "3")] - pub error_info: ::core::option::Option<::prost::alloc::string::String>, + #[prost(message, optional, tag = "3")] + pub error: ::core::option::Option, } #[derive(Clone, PartialEq, ::prost::Message)] pub struct CheckPartsRequest { @@ -180,8 +187,8 @@ pub struct CheckPartsResponse { pub success: bool, #[prost(string, tag = "2")] pub check_parts_resp: ::prost::alloc::string::String, - #[prost(string, optional, tag = "3")] - pub error_info: ::core::option::Option<::prost::alloc::string::String>, + #[prost(message, optional, tag = "3")] + pub error: ::core::option::Option, } #[derive(Clone, PartialEq, ::prost::Message)] pub struct RenamePartRequst { @@ -202,8 +209,8 @@ pub struct RenamePartRequst { pub struct RenamePartResponse { #[prost(bool, tag = "1")] pub success: bool, - #[prost(string, optional, tag = "2")] - pub error_info: ::core::option::Option<::prost::alloc::string::String>, + #[prost(message, optional, tag = "2")] + pub error: ::core::option::Option, } #[derive(Clone, PartialEq, ::prost::Message)] pub struct RenameFileRequst { @@ -222,8 +229,8 @@ pub struct RenameFileRequst { pub struct RenameFileResponse { #[prost(bool, tag = "1")] pub success: bool, - #[prost(string, optional, tag = "2")] - pub error_info: ::core::option::Option<::prost::alloc::string::String>, + #[prost(message, optional, tag = "2")] + pub error: ::core::option::Option, } #[derive(Clone, PartialEq, ::prost::Message)] pub struct WriteRequest { @@ -243,8 +250,8 @@ pub struct WriteRequest { pub struct WriteResponse { #[prost(bool, tag = "1")] pub success: bool, - #[prost(string, optional, tag = "2")] - pub error_info: ::core::option::Option<::prost::alloc::string::String>, + #[prost(message, optional, tag = "2")] + pub error: ::core::option::Option, } #[derive(Clone, PartialEq, ::prost::Message)] pub struct ReadAtRequest { @@ -268,8 +275,8 @@ pub struct ReadAtResponse { pub data: ::prost::alloc::vec::Vec, #[prost(int64, tag = "3")] pub read_size: i64, - #[prost(string, optional, tag = "4")] - pub error_info: ::core::option::Option<::prost::alloc::string::String>, + #[prost(message, optional, tag = "4")] + pub error: ::core::option::Option, } #[derive(Clone, PartialEq, ::prost::Message)] pub struct ListDirRequest { @@ -285,8 +292,8 @@ pub struct ListDirResponse { pub success: bool, #[prost(string, repeated, tag = "2")] pub volumes: ::prost::alloc::vec::Vec<::prost::alloc::string::String>, - #[prost(string, optional, tag = "3")] - pub error_info: ::core::option::Option<::prost::alloc::string::String>, + #[prost(message, optional, tag = "3")] + pub error: ::core::option::Option, } #[derive(Clone, PartialEq, ::prost::Message)] pub struct WalkDirRequest { @@ -302,8 +309,8 @@ pub struct WalkDirResponse { pub success: bool, #[prost(string, repeated, tag = "2")] pub meta_cache_entry: ::prost::alloc::vec::Vec<::prost::alloc::string::String>, - #[prost(string, optional, tag = "3")] - pub error_info: ::core::option::Option<::prost::alloc::string::String>, + #[prost(message, optional, tag = "3")] + pub error: ::core::option::Option, } #[derive(Clone, PartialEq, ::prost::Message)] pub struct RenameDataRequest { @@ -327,8 +334,8 @@ pub struct RenameDataResponse { pub success: bool, #[prost(string, tag = "2")] pub rename_data_resp: ::prost::alloc::string::String, - #[prost(string, optional, tag = "3")] - pub error_info: ::core::option::Option<::prost::alloc::string::String>, + #[prost(message, optional, tag = "3")] + pub error: ::core::option::Option, } #[derive(Clone, PartialEq, ::prost::Message)] pub struct MakeVolumesRequest { @@ -342,8 +349,8 @@ pub struct MakeVolumesRequest { pub struct MakeVolumesResponse { #[prost(bool, tag = "1")] pub success: bool, - #[prost(string, optional, tag = "2")] - pub error_info: ::core::option::Option<::prost::alloc::string::String>, + #[prost(message, optional, tag = "2")] + pub error: ::core::option::Option, } #[derive(Clone, PartialEq, ::prost::Message)] pub struct MakeVolumeRequest { @@ -357,8 +364,8 @@ pub struct MakeVolumeRequest { pub struct MakeVolumeResponse { #[prost(bool, tag = "1")] pub success: bool, - #[prost(string, optional, tag = "2")] - pub error_info: ::core::option::Option<::prost::alloc::string::String>, + #[prost(message, optional, tag = "2")] + pub error: ::core::option::Option, } #[derive(Clone, PartialEq, ::prost::Message)] pub struct ListVolumesRequest { @@ -372,8 +379,8 @@ pub struct ListVolumesResponse { pub success: bool, #[prost(string, repeated, tag = "2")] pub volume_infos: ::prost::alloc::vec::Vec<::prost::alloc::string::String>, - #[prost(string, optional, tag = "3")] - pub error_info: ::core::option::Option<::prost::alloc::string::String>, + #[prost(message, optional, tag = "3")] + pub error: ::core::option::Option, } #[derive(Clone, PartialEq, ::prost::Message)] pub struct StatVolumeRequest { @@ -389,8 +396,8 @@ pub struct StatVolumeResponse { pub success: bool, #[prost(string, tag = "2")] pub volume_info: ::prost::alloc::string::String, - #[prost(string, optional, tag = "3")] - pub error_info: ::core::option::Option<::prost::alloc::string::String>, + #[prost(message, optional, tag = "3")] + pub error: ::core::option::Option, } #[derive(Clone, PartialEq, ::prost::Message)] pub struct DeletePathsRequest { @@ -405,8 +412,8 @@ pub struct DeletePathsRequest { pub struct DeletePathsResponse { #[prost(bool, tag = "1")] pub success: bool, - #[prost(string, optional, tag = "2")] - pub error_info: ::core::option::Option<::prost::alloc::string::String>, + #[prost(message, optional, tag = "2")] + pub error: ::core::option::Option, } #[derive(Clone, PartialEq, ::prost::Message)] pub struct UpdateMetadataRequest { @@ -425,8 +432,8 @@ pub struct UpdateMetadataRequest { pub struct UpdateMetadataResponse { #[prost(bool, tag = "1")] pub success: bool, - #[prost(string, optional, tag = "2")] - pub error_info: ::core::option::Option<::prost::alloc::string::String>, + #[prost(message, optional, tag = "2")] + pub error: ::core::option::Option, } #[derive(Clone, PartialEq, ::prost::Message)] pub struct WriteMetadataRequest { @@ -444,8 +451,8 @@ pub struct WriteMetadataRequest { pub struct WriteMetadataResponse { #[prost(bool, tag = "1")] pub success: bool, - #[prost(string, optional, tag = "2")] - pub error_info: ::core::option::Option<::prost::alloc::string::String>, + #[prost(message, optional, tag = "2")] + pub error: ::core::option::Option, } #[derive(Clone, PartialEq, ::prost::Message)] pub struct ReadVersionRequest { @@ -466,8 +473,8 @@ pub struct ReadVersionResponse { pub success: bool, #[prost(string, tag = "2")] pub file_info: ::prost::alloc::string::String, - #[prost(string, optional, tag = "3")] - pub error_info: ::core::option::Option<::prost::alloc::string::String>, + #[prost(message, optional, tag = "3")] + pub error: ::core::option::Option, } #[derive(Clone, PartialEq, ::prost::Message)] pub struct ReadXlRequest { @@ -486,8 +493,8 @@ pub struct ReadXlResponse { pub success: bool, #[prost(string, tag = "2")] pub raw_file_info: ::prost::alloc::string::String, - #[prost(string, optional, tag = "3")] - pub error_info: ::core::option::Option<::prost::alloc::string::String>, + #[prost(message, optional, tag = "3")] + pub error: ::core::option::Option, } #[derive(Clone, PartialEq, ::prost::Message)] pub struct DeleteVersionRequest { @@ -510,8 +517,8 @@ pub struct DeleteVersionResponse { pub success: bool, #[prost(string, tag = "2")] pub raw_file_info: ::prost::alloc::string::String, - #[prost(string, optional, tag = "3")] - pub error_info: ::core::option::Option<::prost::alloc::string::String>, + #[prost(message, optional, tag = "3")] + pub error: ::core::option::Option, } #[derive(Clone, PartialEq, ::prost::Message)] pub struct DeleteVersionsRequest { @@ -530,8 +537,8 @@ pub struct DeleteVersionsResponse { pub success: bool, #[prost(string, repeated, tag = "2")] pub errors: ::prost::alloc::vec::Vec<::prost::alloc::string::String>, - #[prost(string, optional, tag = "3")] - pub error_info: ::core::option::Option<::prost::alloc::string::String>, + #[prost(message, optional, tag = "3")] + pub error: ::core::option::Option, } #[derive(Clone, PartialEq, ::prost::Message)] pub struct ReadMultipleRequest { @@ -546,8 +553,8 @@ pub struct ReadMultipleResponse { pub success: bool, #[prost(string, repeated, tag = "2")] pub read_multiple_resps: ::prost::alloc::vec::Vec<::prost::alloc::string::String>, - #[prost(string, optional, tag = "3")] - pub error_info: ::core::option::Option<::prost::alloc::string::String>, + #[prost(message, optional, tag = "3")] + pub error: ::core::option::Option, } #[derive(Clone, PartialEq, ::prost::Message)] pub struct DeleteVolumeRequest { @@ -560,8 +567,8 @@ pub struct DeleteVolumeRequest { pub struct DeleteVolumeResponse { #[prost(bool, tag = "1")] pub success: bool, - #[prost(string, optional, tag = "2")] - pub error_info: ::core::option::Option<::prost::alloc::string::String>, + #[prost(message, optional, tag = "2")] + pub error: ::core::option::Option, } #[derive(Clone, PartialEq, ::prost::Message)] pub struct DiskInfoRequest { @@ -576,8 +583,8 @@ pub struct DiskInfoResponse { pub success: bool, #[prost(string, tag = "2")] pub disk_info: ::prost::alloc::string::String, - #[prost(string, optional, tag = "3")] - pub error_info: ::core::option::Option<::prost::alloc::string::String>, + #[prost(message, optional, tag = "3")] + pub error: ::core::option::Option, } #[derive(Clone, PartialEq, ::prost::Message)] pub struct NsScannerRequest { @@ -596,8 +603,8 @@ pub struct NsScannerResponse { pub update: ::prost::alloc::string::String, #[prost(string, tag = "3")] pub data_usage_cache: ::prost::alloc::string::String, - #[prost(string, optional, tag = "4")] - pub error_info: ::core::option::Option<::prost::alloc::string::String>, + #[prost(message, optional, tag = "4")] + pub error: ::core::option::Option, } /// lock api have same argument type #[derive(Clone, PartialEq, ::prost::Message)] diff --git a/common/protos/src/node.proto b/common/protos/src/node.proto index 924f4695..2577ea0c 100644 --- a/common/protos/src/node.proto +++ b/common/protos/src/node.proto @@ -2,6 +2,11 @@ syntax = "proto3"; package node_service; /* -------------------------------------------------------------------- */ +message Error { + uint32 code = 1; + string error_info = 2; +} + message PingRequest { uint64 version = 1; bytes body = 2; @@ -19,7 +24,7 @@ message HealBucketRequest { message HealBucketResponse { bool success = 1; - optional string error_info = 2; + optional Error error = 2; } message ListBucketRequest { @@ -29,7 +34,7 @@ message ListBucketRequest { message ListBucketResponse { bool success = 1; repeated string bucket_infos = 2; - optional string error_info = 3; + optional Error error = 3; } message MakeBucketRequest { @@ -39,7 +44,7 @@ message MakeBucketRequest { message MakeBucketResponse { bool success = 1; - optional string error_info = 2; + optional Error error = 2; } message GetBucketInfoRequest { @@ -50,7 +55,7 @@ message GetBucketInfoRequest { message GetBucketInfoResponse { bool success = 1; string bucket_info = 2; - optional string error_info = 3; + optional Error error = 3; } message DeleteBucketRequest { @@ -59,7 +64,7 @@ message DeleteBucketRequest { message DeleteBucketResponse { bool success = 1; - optional string error_info = 2; + optional Error error = 2; } message ReadAllRequest { @@ -71,7 +76,7 @@ message ReadAllRequest { message ReadAllResponse { bool success = 1; bytes data = 2; - optional string error_info = 3; + optional Error error = 3; } message WriteAllRequest { @@ -83,7 +88,7 @@ message WriteAllRequest { message WriteAllResponse { bool success = 1; - optional string error_info = 2; + optional Error error = 2; } message DeleteRequest { @@ -95,7 +100,7 @@ message DeleteRequest { message DeleteResponse { bool success = 1; - optional string error_info = 2; + optional Error error = 2; } message VerifyFileRequest { @@ -108,7 +113,7 @@ message VerifyFileRequest { message VerifyFileResponse { bool success = 1; string check_parts_resp = 2; - optional string error_info = 3; + optional Error error = 3; } message CheckPartsRequest { @@ -121,7 +126,7 @@ message CheckPartsRequest { message CheckPartsResponse { bool success = 1; string check_parts_resp = 2; - optional string error_info = 3; + optional Error error = 3; } message RenamePartRequst { @@ -135,7 +140,7 @@ message RenamePartRequst { message RenamePartResponse { bool success = 1; - optional string error_info = 2; + optional Error error = 2; } message RenameFileRequst { @@ -148,7 +153,7 @@ message RenameFileRequst { message RenameFileResponse { bool success = 1; - optional string error_info = 2; + optional Error error = 2; } message WriteRequest { @@ -161,7 +166,7 @@ message WriteRequest { message WriteResponse { bool success = 1; - optional string error_info = 2; + optional Error error = 2; } // message AppendRequest { @@ -173,7 +178,7 @@ message WriteResponse { // // message AppendResponse { // bool success = 1; -// optional string error_info = 2; +// optional Error error = 2; // } message ReadAtRequest { @@ -188,7 +193,7 @@ message ReadAtResponse { bool success = 1; bytes data = 2; int64 read_size = 3; - optional string error_info = 4; + optional Error error = 4; } message ListDirRequest { @@ -199,7 +204,7 @@ message ListDirRequest { message ListDirResponse { bool success = 1; repeated string volumes = 2; - optional string error_info = 3; + optional Error error = 3; } message WalkDirRequest { @@ -210,7 +215,7 @@ message WalkDirRequest { message WalkDirResponse { bool success = 1; repeated string meta_cache_entry = 2; - optional string error_info = 3; + optional Error error = 3; } message RenameDataRequest { @@ -225,7 +230,7 @@ message RenameDataRequest { message RenameDataResponse { bool success = 1; string rename_data_resp = 2; - optional string error_info = 3; + optional Error error = 3; } message MakeVolumesRequest { @@ -235,7 +240,7 @@ message MakeVolumesRequest { message MakeVolumesResponse { bool success = 1; - optional string error_info = 2; + optional Error error = 2; } message MakeVolumeRequest { @@ -245,7 +250,7 @@ message MakeVolumeRequest { message MakeVolumeResponse { bool success = 1; - optional string error_info = 2; + optional Error error = 2; } message ListVolumesRequest { @@ -255,7 +260,7 @@ message ListVolumesRequest { message ListVolumesResponse { bool success = 1; repeated string volume_infos = 2; - optional string error_info = 3; + optional Error error = 3; } message StatVolumeRequest { @@ -266,7 +271,7 @@ message StatVolumeRequest { message StatVolumeResponse { bool success = 1; string volume_info = 2; - optional string error_info = 3; + optional Error error = 3; } message DeletePathsRequest { @@ -277,7 +282,7 @@ message DeletePathsRequest { message DeletePathsResponse { bool success = 1; - optional string error_info = 2; + optional Error error = 2; } message UpdateMetadataRequest { @@ -290,7 +295,7 @@ message UpdateMetadataRequest { message UpdateMetadataResponse { bool success = 1; - optional string error_info = 2; + optional Error error = 2; } message WriteMetadataRequest { @@ -302,7 +307,7 @@ message WriteMetadataRequest { message WriteMetadataResponse { bool success = 1; - optional string error_info = 2; + optional Error error = 2; } message ReadVersionRequest { @@ -316,7 +321,7 @@ message ReadVersionRequest { message ReadVersionResponse { bool success = 1; string file_info = 2; - optional string error_info = 3; + optional Error error = 3; } message ReadXLRequest { @@ -329,7 +334,7 @@ message ReadXLRequest { message ReadXLResponse { bool success = 1; string raw_file_info = 2; - optional string error_info = 3; + optional Error error = 3; } message DeleteVersionRequest { @@ -344,7 +349,7 @@ message DeleteVersionRequest { message DeleteVersionResponse { bool success = 1; string raw_file_info = 2; - optional string error_info = 3; + optional Error error = 3; } message DeleteVersionsRequest { @@ -357,7 +362,7 @@ message DeleteVersionsRequest { message DeleteVersionsResponse { bool success = 1; repeated string errors = 2; - optional string error_info = 3; + optional Error error = 3; } message ReadMultipleRequest { @@ -368,7 +373,7 @@ message ReadMultipleRequest { message ReadMultipleResponse { bool success = 1; repeated string read_multiple_resps = 2; - optional string error_info = 3; + optional Error error = 3; } message DeleteVolumeRequest { @@ -378,7 +383,7 @@ message DeleteVolumeRequest { message DeleteVolumeResponse { bool success = 1; - optional string error_info = 2; + optional Error error = 2; } message DiskInfoRequest { @@ -389,7 +394,7 @@ message DiskInfoRequest { message DiskInfoResponse { bool success = 1; string disk_info = 2; - optional string error_info = 3; + optional Error error = 3; } message NsScannerRequest { @@ -402,7 +407,7 @@ message NsScannerResponse { bool success = 1; string update = 2; string data_usage_cache = 3; - optional string error_info = 4; + optional Error error = 4; } // lock api have same argument type diff --git a/ecstore/src/bucket/error.rs b/ecstore/src/bucket/error.rs index f073637a..a6aa8232 100644 --- a/ecstore/src/bucket/error.rs +++ b/ecstore/src/bucket/error.rs @@ -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 { + 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, + } + } +} diff --git a/ecstore/src/config/error.rs b/ecstore/src/config/error.rs index 27518aef..a5ce45f1 100644 --- a/ecstore/src/config/error.rs +++ b/ecstore/src/config/error.rs @@ -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 { + match error { + 0x01 => Some(Self::NotFound), + _ => None, + } + } +} + pub fn is_not_found(err: &Error) -> bool { if let Some(e) = err.downcast_ref::() { ConfigError::is_not_found(e) diff --git a/ecstore/src/disk/error.rs b/ecstore/src/disk/error.rs index 6cba48a8..f0cf1b1c 100644 --- a/ecstore/src/disk/error.rs +++ b/ecstore/src/disk/error.rs @@ -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 { + 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 { diff --git a/ecstore/src/disk/mod.rs b/ecstore/src/disk/mod.rs index 03b51ba3..3c7bfd1f 100644 --- a/ecstore/src/disk/mod.rs +++ b/ecstore/src/disk/mod.rs @@ -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"; diff --git a/ecstore/src/disk/remote.rs b/ecstore/src/disk/remote.rs index 8c171113..4383174c 100644 --- a/ecstore/src/disk/remote.rs +++ b/ecstore/src/disk/remote.rs @@ -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::(&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::(&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::(&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::(&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::(&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::(&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::(&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::(&response.disk_info)?; diff --git a/ecstore/src/peer.rs b/ecstore/src/peer.rs index e9d02c60..9c1e0da1 100644 --- a/ecstore/src/peer.rs +++ b/ecstore/src/peer.rs @@ -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::(&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(()) } diff --git a/ecstore/src/quorum.rs b/ecstore/src/quorum.rs index 84d36df5..848cac03 100644 --- a/ecstore/src/quorum.rs +++ b/ecstore/src/quorum.rs @@ -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 { + match error { + 0x01 => Some(QuorumError::Read), + 0x02 => Some(QuorumError::Write), + _ => None, + } + } +} + pub fn base_ignored_errs() -> Vec> { vec![ Box::new(DiskError::DiskNotFound), diff --git a/ecstore/src/store_err.rs b/ecstore/src/store_err.rs index e0dabb87..518e48a8 100644 --- a/ecstore/src/store_err.rs +++ b/ecstore/src/store_err.rs @@ -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 { + 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::() { match e { diff --git a/ecstore/src/store_init.rs b/ecstore/src/store_init.rs index 1b154c16..df2e759a 100644 --- a/ecstore/src/store_init.rs +++ b/ecstore/src/store_init.rs @@ -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 { + 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, + } + } +} diff --git a/ecstore/src/utils/mod.rs b/ecstore/src/utils/mod.rs index 12d4d187..b45790ab 100644 --- a/ecstore/src/utils/mod.rs +++ b/ecstore/src/utils/mod.rs @@ -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::() { + DISK_ERROR_MASK | e.to_u32() } else if let Some(e) = err.downcast_ref::() { + STORAGE_ERROR_MASK | e.to_u32() } else if let Some(e) = err.downcast_ref::() { + BUCKET_METADATA_ERROR_MASK | e.to_u32() } else if let Some(e) = err.downcast_ref::() { + CONFIG_ERROR_MASK | e.to_u32() } else if let Some(e) = err.downcast_ref::() { + QUORUM_ERROR_MASK | e.to_u32() } else if let Some(e) = err.downcast_ref::() { + ERASURE_ERROR_MASK | e.to_u32() + } else { + 0 } - 0 +} + +pub fn u32_to_error(e: u32) -> Option { + 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::(), 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::(), + 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::(), + 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::(), 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::(), 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::(), Some(&ErasureError::ErasureReadQuorum)); } diff --git a/rustfs/src/grpc.rs b/rustfs/src/grpc.rs index 881b11c6..023cbd07 100644 --- a/rustfs/src/grpc.rs +++ b/rustfs/src/grpc.rs @@ -13,6 +13,7 @@ use ecstore::{ UpdateMetadataOpts, WalkDirOptions, }, erasure::Writer, + error::Error as EcsError, heal::{ data_usage_cache::DataUsageCache, heal_commands::{get_local_background_heal_status, HealOpts}, @@ -27,13 +28,15 @@ use futures::{Stream, StreamExt}; use lock::{lock_args::LockArgs, Locker, GLOBAL_LOCAL_SERVER}; use common::globals::GLOBAL_Local_Node_Name; +use ecstore::store_err::StorageError; +use ecstore::utils::{err_to_proto_err, error_to_u32}; use madmin::health::{ get_cpus, get_mem_info, get_os_info, get_partitions, get_proc_info, get_sys_config, get_sys_errors, get_sys_services, }; use madmin::net::get_net_info; use protos::{ models::{PingBody, PingBodyBuilder}, - proto_gen::node_service::{node_service_server::NodeService as Node, *}, + proto_gen::node_service::{node_service_server::NodeService as Node, Error as Proto_Error, *}, }; use rmp_serde::{Deserializer, Serializer}; use serde::{Deserialize, Serialize}; @@ -124,7 +127,10 @@ impl Node for NodeService { Err(err) => { return Ok(tonic::Response::new(HealBucketResponse { success: false, - error_info: Some(format!("decode HealOpts failed: {}", err)), + error: Some(err_to_proto_err( + &EcsError::new(StorageError::InvalidArgument(Default::default(), Default::default(), Default::default())), + &format!("decode HealOpts failed: {}", err), + )), })) } }; @@ -132,12 +138,12 @@ impl Node for NodeService { match self.local_peer.heal_bucket(&request.bucket, &options).await { Ok(_) => Ok(tonic::Response::new(HealBucketResponse { success: true, - error_info: None, + error: None, })), Err(err) => Ok(tonic::Response::new(HealBucketResponse { success: false, - error_info: Some(format!("heal bucket failed: {}", err)), + error: Some(err_to_proto_err(&err, &format!("heal bucket failed: {}", err))), })), } } @@ -152,7 +158,10 @@ impl Node for NodeService { return Ok(tonic::Response::new(ListBucketResponse { success: false, bucket_infos: Vec::new(), - error_info: Some(format!("decode BucketOptions failed: {}", err)), + error: Some(err_to_proto_err( + &EcsError::new(StorageError::InvalidArgument(Default::default(), Default::default(), Default::default())), + &format!("decode BucketOptions failed: {}", err), + )), })) } }; @@ -165,14 +174,14 @@ impl Node for NodeService { Ok(tonic::Response::new(ListBucketResponse { success: true, bucket_infos, - error_info: None, + error: None, })) } Err(err) => Ok(tonic::Response::new(ListBucketResponse { success: false, bucket_infos: Vec::new(), - error_info: Some(format!("make failed: {}", err)), + error: Some(err_to_proto_err(&err, &format!("list bucket failed: {}", err))), })), } } @@ -186,18 +195,21 @@ impl Node for NodeService { Err(err) => { return Ok(tonic::Response::new(MakeBucketResponse { success: false, - error_info: Some(format!("decode MakeBucketOptions failed: {}", err)), + error: Some(err_to_proto_err( + &EcsError::new(StorageError::InvalidArgument(Default::default(), Default::default(), Default::default())), + &format!("decode MakeBucketOptions failed: {}", err), + )), })) } }; match self.local_peer.make_bucket(&request.name, &options).await { Ok(_) => Ok(tonic::Response::new(MakeBucketResponse { success: true, - error_info: None, + error: None, })), Err(err) => Ok(tonic::Response::new(MakeBucketResponse { success: false, - error_info: Some(format!("make failed: {}", err)), + error: Some(err_to_proto_err(&err, &format!("make bucket failed: {}", err))), })), } } @@ -212,7 +224,10 @@ impl Node for NodeService { return Ok(tonic::Response::new(GetBucketInfoResponse { success: false, bucket_info: String::new(), - error_info: Some(format!("decode BucketOptions failed: {}", err)), + error: Some(err_to_proto_err( + &EcsError::new(StorageError::InvalidArgument(Default::default(), Default::default(), Default::default())), + &format!("decode BucketOptions failed: {}", err), + )), })) } }; @@ -224,21 +239,24 @@ impl Node for NodeService { return Ok(tonic::Response::new(GetBucketInfoResponse { success: false, bucket_info: String::new(), - error_info: Some(format!("encode BucketInfo failed: {}", err)), + error: Some(err_to_proto_err( + &EcsError::from_string("encode data failed"), + &format!("encode data failed: {}", err), + )), })); } }; Ok(tonic::Response::new(GetBucketInfoResponse { success: true, bucket_info, - error_info: None, + error: None, })) } Err(err) => Ok(tonic::Response::new(GetBucketInfoResponse { success: false, bucket_info: String::new(), - error_info: Some(format!("make failed: {}", err)), + error: Some(err_to_proto_err(&err, &format!("get bucket info failed: {}", err))), })), } } @@ -260,11 +278,11 @@ impl Node for NodeService { { Ok(_) => Ok(tonic::Response::new(DeleteBucketResponse { success: true, - error_info: None, + error: None, })), Err(err) => Ok(tonic::Response::new(DeleteBucketResponse { success: false, - error_info: Some(format!("make failed: {}", err)), + error: Some(err_to_proto_err(&err, &format!("delete bucket failed: {}", err))), })), } } @@ -278,19 +296,22 @@ impl Node for NodeService { Ok(data) => Ok(tonic::Response::new(ReadAllResponse { success: true, data: data.to_vec(), - error_info: None, + error: None, })), Err(err) => Ok(tonic::Response::new(ReadAllResponse { success: false, data: Vec::new(), - error_info: Some(err.to_string()), + error: Some(err_to_proto_err(&err, &format!("read all failed: {}", err))), })), } } else { Ok(tonic::Response::new(ReadAllResponse { success: false, data: Vec::new(), - error_info: Some("can not find disk".to_string()), + error: Some(err_to_proto_err( + &EcsError::new(StorageError::InvalidArgument(Default::default(), Default::default(), Default::default())), + "can not find disk", + )), })) } } @@ -301,17 +322,20 @@ impl Node for NodeService { match disk.write_all(&request.volume, &request.path, request.data).await { Ok(_) => Ok(tonic::Response::new(WriteAllResponse { success: true, - error_info: None, + error: None, })), Err(err) => Ok(tonic::Response::new(WriteAllResponse { success: false, - error_info: Some(err.to_string()), + error: Some(err_to_proto_err(&err, &format!("write all failed: {}", err))), })), } } else { Ok(tonic::Response::new(WriteAllResponse { success: false, - error_info: Some("can not find disk".to_string()), + error: Some(err_to_proto_err( + &EcsError::new(StorageError::InvalidArgument(Default::default(), Default::default(), Default::default())), + "can not find disk", + )), })) } } @@ -321,27 +345,37 @@ impl Node for NodeService { if let Some(disk) = self.find_disk(&request.disk).await { let options = match serde_json::from_str::(&request.options) { Ok(options) => options, - Err(_) => { + Err(err) => { return Ok(tonic::Response::new(DeleteResponse { success: false, - error_info: Some("can not decode DeleteOptions".to_string()), + error: Some(err_to_proto_err( + &EcsError::new(StorageError::InvalidArgument( + Default::default(), + Default::default(), + Default::default(), + )), + &format!("decode DeleteOptions failed: {}", err), + )), })); } }; match disk.delete(&request.volume, &request.path, options).await { Ok(_) => Ok(tonic::Response::new(DeleteResponse { success: true, - error_info: None, + error: None, })), Err(err) => Ok(tonic::Response::new(DeleteResponse { success: false, - error_info: Some(err.to_string()), + error: Some(err_to_proto_err(&err, &format!("delete failed: {}", err))), })), } } else { Ok(tonic::Response::new(DeleteResponse { success: false, - error_info: Some("can not find disk".to_string()), + error: Some(err_to_proto_err( + &EcsError::new(StorageError::InvalidArgument(Default::default(), Default::default(), Default::default())), + "can not find disk", + )), })) } } @@ -351,11 +385,18 @@ impl Node for NodeService { if let Some(disk) = self.find_disk(&request.disk).await { let file_info = match serde_json::from_str::(&request.file_info) { Ok(file_info) => file_info, - Err(_) => { + Err(err) => { return Ok(tonic::Response::new(VerifyFileResponse { success: false, check_parts_resp: "".to_string(), - error_info: Some("can not decode FileInfo".to_string()), + error: Some(err_to_proto_err( + &EcsError::new(StorageError::InvalidArgument( + Default::default(), + Default::default(), + Default::default(), + )), + &format!("decode FileInfo failed: {}", err), + )), })); } }; @@ -363,31 +404,37 @@ impl Node for NodeService { Ok(check_parts_resp) => { let check_parts_resp = match serde_json::to_string(&check_parts_resp) { Ok(check_parts_resp) => check_parts_resp, - Err(_) => { + Err(err) => { return Ok(tonic::Response::new(VerifyFileResponse { success: false, check_parts_resp: String::new(), - error_info: Some("can not encode RenameDataResp".to_string()), + error: Some(err_to_proto_err( + &EcsError::from_string("encode data failed"), + &format!("encode data failed: {}", err), + )), })); } }; Ok(tonic::Response::new(VerifyFileResponse { success: true, check_parts_resp, - error_info: None, + error: None, })) } Err(err) => Ok(tonic::Response::new(VerifyFileResponse { success: false, check_parts_resp: "".to_string(), - error_info: Some(err.to_string()), + error: Some(err_to_proto_err(&err, &format!("verify file failed: {}", err))), })), } } else { Ok(tonic::Response::new(VerifyFileResponse { success: false, check_parts_resp: "".to_string(), - error_info: Some("can not find disk".to_string()), + error: Some(err_to_proto_err( + &EcsError::new(StorageError::InvalidArgument(Default::default(), Default::default(), Default::default())), + "can not find disk", + )), })) } } @@ -397,11 +444,18 @@ impl Node for NodeService { if let Some(disk) = self.find_disk(&request.disk).await { let file_info = match serde_json::from_str::(&request.file_info) { Ok(file_info) => file_info, - Err(_) => { + Err(err) => { return Ok(tonic::Response::new(CheckPartsResponse { success: false, check_parts_resp: "".to_string(), - error_info: Some("can not decode FileInfo".to_string()), + error: Some(err_to_proto_err( + &EcsError::new(StorageError::InvalidArgument( + Default::default(), + Default::default(), + Default::default(), + )), + &format!("decode FileInfo failed: {}", err), + )), })); } }; @@ -409,31 +463,37 @@ impl Node for NodeService { Ok(check_parts_resp) => { let check_parts_resp = match serde_json::to_string(&check_parts_resp) { Ok(check_parts_resp) => check_parts_resp, - Err(_) => { + Err(err) => { return Ok(tonic::Response::new(CheckPartsResponse { success: false, check_parts_resp: String::new(), - error_info: Some("can not encode RenameDataResp".to_string()), + error: Some(err_to_proto_err( + &EcsError::from_string("encode data failed"), + &format!("encode data failed: {}", err), + )), })); } }; Ok(tonic::Response::new(CheckPartsResponse { success: true, check_parts_resp, - error_info: None, + error: None, })) } Err(err) => Ok(tonic::Response::new(CheckPartsResponse { success: false, check_parts_resp: "".to_string(), - error_info: Some(err.to_string()), + error: Some(err_to_proto_err(&err, &format!("check parts failed: {}", err))), })), } } else { Ok(tonic::Response::new(CheckPartsResponse { success: false, check_parts_resp: "".to_string(), - error_info: Some("can not find disk".to_string()), + error: Some(err_to_proto_err( + &EcsError::new(StorageError::InvalidArgument(Default::default(), Default::default(), Default::default())), + "can not find disk", + )), })) } } @@ -453,17 +513,20 @@ impl Node for NodeService { { Ok(_) => Ok(tonic::Response::new(RenamePartResponse { success: true, - error_info: None, + error: None, })), Err(err) => Ok(tonic::Response::new(RenamePartResponse { success: false, - error_info: Some(err.to_string()), + error: Some(err_to_proto_err(&err, &format!("rename part failed: {}", err))), })), } } else { Ok(tonic::Response::new(RenamePartResponse { success: false, - error_info: Some("can not find disk".to_string()), + error: Some(err_to_proto_err( + &EcsError::new(StorageError::InvalidArgument(Default::default(), Default::default(), Default::default())), + "can not find disk", + )), })) } } @@ -477,17 +540,20 @@ impl Node for NodeService { { Ok(_) => Ok(tonic::Response::new(RenameFileResponse { success: true, - error_info: None, + error: None, })), Err(err) => Ok(tonic::Response::new(RenameFileResponse { success: false, - error_info: Some(err.to_string()), + error: Some(err_to_proto_err(&err, &format!("rename file failed: {}", err))), })), } } else { Ok(tonic::Response::new(RenameFileResponse { success: false, - error_info: Some("can not find disk".to_string()), + error: Some(err_to_proto_err( + &EcsError::new(StorageError::InvalidArgument(Default::default(), Default::default(), Default::default())), + "can not find disk", + )), })) } } @@ -505,22 +571,25 @@ impl Node for NodeService { Ok(mut file_writer) => match file_writer.write(&request.data).await { Ok(_) => Ok(tonic::Response::new(WriteResponse { success: true, - error_info: None, + error: None, })), Err(err) => Ok(tonic::Response::new(WriteResponse { success: false, - error_info: Some(err.to_string()), + error: Some(err_to_proto_err(&err, &format!("write failed: {}", err))), })), }, Err(err) => Ok(tonic::Response::new(WriteResponse { success: false, - error_info: Some(err.to_string()), + error: Some(err_to_proto_err(&err, &format!("get writer failed: {}", err))), })), } } else { Ok(tonic::Response::new(WriteResponse { success: false, - error_info: Some("can not find disk".to_string()), + error: Some(err_to_proto_err( + &EcsError::new(StorageError::InvalidArgument(Default::default(), Default::default(), Default::default())), + "can not find disk", + )), })) } } @@ -556,7 +625,10 @@ impl Node for NodeService { Err(err) => { tx.send(Ok(WriteResponse { success: false, - error_info: Some(err.to_string()), + error: Some(err_to_proto_err( + &err, + &format!("get get file writer failed: {}", err), + )), })) .await .expect("working rx"); @@ -566,7 +638,14 @@ impl Node for NodeService { } else { tx.send(Ok(WriteResponse { success: false, - error_info: Some("can not find disk".to_string()), + error: Some(err_to_proto_err( + &EcsError::new(StorageError::InvalidArgument( + Default::default(), + Default::default(), + Default::default(), + )), + "can not find disk", + )), })) .await .expect("working rx"); @@ -578,11 +657,11 @@ impl Node for NodeService { match file_ref.as_mut().unwrap().write(&v.data).await { Ok(_) => tx.send(Ok(WriteResponse { success: true, - error_info: None, + error: None, })), Err(err) => tx.send(Ok(WriteResponse { success: false, - error_info: Some(err.to_string()), + error: Some(err_to_proto_err(&err, &format!("write failed: {}", err))), })), } .await @@ -635,7 +714,7 @@ impl Node for NodeService { tx.send(Ok(ReadAtResponse { success: false, data: Vec::new(), - error_info: Some(err.to_string()), + error: Some(err_to_proto_err(&err, &format!("read file failed: {}", err))), read_size: -1, })) .await @@ -647,7 +726,14 @@ impl Node for NodeService { tx.send(Ok(ReadAtResponse { success: false, data: Vec::new(), - error_info: Some("can not find disk".to_string()), + error: Some(err_to_proto_err( + &EcsError::new(StorageError::InvalidArgument( + Default::default(), + Default::default(), + Default::default(), + )), + "can not find disk", + )), read_size: -1, })) .await @@ -669,12 +755,12 @@ impl Node for NodeService { success: true, data, read_size: read_size.try_into().unwrap(), - error_info: None, + error: None, })), Err(err) => tx.send(Ok(ReadAtResponse { success: false, data: Vec::new(), - error_info: Some(err.to_string()), + error: Some(err_to_proto_err(&err, &format!("read at failed: {}", err))), read_size: -1, })), } @@ -713,19 +799,22 @@ impl Node for NodeService { Ok(volumes) => Ok(tonic::Response::new(ListDirResponse { success: true, volumes, - error_info: None, + error: None, })), Err(err) => Ok(tonic::Response::new(ListDirResponse { success: false, volumes: Vec::new(), - error_info: Some(err.to_string()), + error: Some(err_to_proto_err(&err, &format!("list dir failed: {}", err))), })), } } else { Ok(tonic::Response::new(ListDirResponse { success: false, volumes: Vec::new(), - error_info: Some("can not find disk".to_string()), + error: Some(err_to_proto_err( + &EcsError::new(StorageError::InvalidArgument(Default::default(), Default::default(), Default::default())), + "can not find disk", + )), })) } } @@ -735,11 +824,18 @@ impl Node for NodeService { if let Some(disk) = self.find_disk(&request.disk).await { let opts = match serde_json::from_str::(&request.walk_dir_options) { Ok(options) => options, - Err(_) => { + Err(err) => { return Ok(tonic::Response::new(WalkDirResponse { success: false, meta_cache_entry: Vec::new(), - error_info: Some("can not decode DeleteOptions".to_string()), + error: Some(err_to_proto_err( + &EcsError::new(StorageError::InvalidArgument( + Default::default(), + Default::default(), + Default::default(), + )), + &format!("decode WalkDirOptions failed: {}", err), + )), })); } }; @@ -752,20 +848,23 @@ impl Node for NodeService { Ok(tonic::Response::new(WalkDirResponse { success: true, meta_cache_entry: entries, - error_info: None, + error: None, })) } Err(err) => Ok(tonic::Response::new(WalkDirResponse { success: false, meta_cache_entry: Vec::new(), - error_info: Some(err.to_string()), + error: Some(err_to_proto_err(&err, &format!("walk dir failed: {}", err))), })), } } else { Ok(tonic::Response::new(WalkDirResponse { success: false, meta_cache_entry: Vec::new(), - error_info: Some("can not find disk".to_string()), + error: Some(err_to_proto_err( + &EcsError::new(StorageError::InvalidArgument(Default::default(), Default::default(), Default::default())), + "can not find disk", + )), })) } } @@ -775,11 +874,18 @@ impl Node for NodeService { if let Some(disk) = self.find_disk(&request.disk).await { let file_info = match serde_json::from_str::(&request.file_info) { Ok(file_info) => file_info, - Err(_) => { + Err(err) => { return Ok(tonic::Response::new(RenameDataResponse { success: false, rename_data_resp: String::new(), - error_info: Some("can not decode DeleteOptions".to_string()), + error: Some(err_to_proto_err( + &EcsError::new(StorageError::InvalidArgument( + Default::default(), + Default::default(), + Default::default(), + )), + &format!("decode FileInfo failed: {}", err), + )), })); } }; @@ -790,31 +896,37 @@ impl Node for NodeService { Ok(rename_data_resp) => { let rename_data_resp = match serde_json::to_string(&rename_data_resp) { Ok(file_info) => file_info, - Err(_) => { + Err(err) => { return Ok(tonic::Response::new(RenameDataResponse { success: false, rename_data_resp: String::new(), - error_info: Some("can not encode RenameDataResp".to_string()), + error: Some(err_to_proto_err( + &EcsError::from_string("encode data failed"), + &format!("encode data failed: {}", err), + )), })); } }; Ok(tonic::Response::new(RenameDataResponse { success: true, rename_data_resp, - error_info: None, + error: None, })) } Err(err) => Ok(tonic::Response::new(RenameDataResponse { success: false, rename_data_resp: String::new(), - error_info: Some(err.to_string()), + error: Some(err_to_proto_err(&err, &format!("rename data failed: {}", err))), })), } } else { Ok(tonic::Response::new(RenameDataResponse { success: false, rename_data_resp: String::new(), - error_info: Some("can not find disk".to_string()), + error: Some(err_to_proto_err( + &EcsError::new(StorageError::InvalidArgument(Default::default(), Default::default(), Default::default())), + "can not find disk", + )), })) } } @@ -825,17 +937,20 @@ impl Node for NodeService { match disk.make_volumes(request.volumes.iter().map(|s| &**s).collect()).await { Ok(_) => Ok(tonic::Response::new(MakeVolumesResponse { success: true, - error_info: None, + error: None, })), Err(err) => Ok(tonic::Response::new(MakeVolumesResponse { success: false, - error_info: Some(err.to_string()), + error: Some(err_to_proto_err(&err, &format!("make volume failed: {}", err))), })), } } else { Ok(tonic::Response::new(MakeVolumesResponse { success: false, - error_info: Some(format!("can not find disk, all disks: {:?}", self.all_disk().await)), + error: Some(err_to_proto_err( + &EcsError::new(StorageError::InvalidArgument(Default::default(), Default::default(), Default::default())), + "can not find disk", + )), })) } } @@ -846,17 +961,20 @@ impl Node for NodeService { match disk.make_volume(&request.volume).await { Ok(_) => Ok(tonic::Response::new(MakeVolumeResponse { success: true, - error_info: None, + error: None, })), Err(err) => Ok(tonic::Response::new(MakeVolumeResponse { success: false, - error_info: Some(err.to_string()), + error: Some(err_to_proto_err(&err, &format!("make volume failed: {}", err))), })), } } else { Ok(tonic::Response::new(MakeVolumeResponse { success: false, - error_info: Some(format!("can not find disk, all disks: {:?}", self.all_disk().await)), + error: Some(err_to_proto_err( + &EcsError::new(StorageError::InvalidArgument(Default::default(), Default::default(), Default::default())), + "can not find disk", + )), })) } } @@ -873,20 +991,23 @@ impl Node for NodeService { Ok(tonic::Response::new(ListVolumesResponse { success: true, volume_infos, - error_info: None, + error: None, })) } Err(err) => Ok(tonic::Response::new(ListVolumesResponse { success: false, volume_infos: Vec::new(), - error_info: Some(err.to_string()), + error: Some(err_to_proto_err(&err, &format!("list volume failed: {}", err))), })), } } else { Ok(tonic::Response::new(ListVolumesResponse { success: false, volume_infos: Vec::new(), - error_info: Some("can not find disk".to_string()), + error: Some(err_to_proto_err( + &EcsError::new(StorageError::InvalidArgument(Default::default(), Default::default(), Default::default())), + "can not find disk", + )), })) } } @@ -899,25 +1020,31 @@ impl Node for NodeService { Ok(volume_info) => Ok(tonic::Response::new(StatVolumeResponse { success: true, volume_info, - error_info: None, + error: None, })), Err(err) => Ok(tonic::Response::new(StatVolumeResponse { success: false, volume_info: String::new(), - error_info: Some(format!("encode VolumeInfo failed, {}", err)), + error: Some(err_to_proto_err( + &EcsError::from_string("encode data failed"), + &format!("encode data failed: {}", err), + )), })), }, Err(err) => Ok(tonic::Response::new(StatVolumeResponse { success: false, volume_info: String::new(), - error_info: Some(err.to_string()), + error: Some(err_to_proto_err(&err, &format!("state volume failed: {}", err))), })), } } else { Ok(tonic::Response::new(StatVolumeResponse { success: false, volume_info: String::new(), - error_info: Some("can not find disk".to_string()), + error: Some(err_to_proto_err( + &EcsError::new(StorageError::InvalidArgument(Default::default(), Default::default(), Default::default())), + "can not find disk", + )), })) } } @@ -929,17 +1056,20 @@ impl Node for NodeService { match disk.delete_paths(&request.volume, &paths).await { Ok(_) => Ok(tonic::Response::new(DeletePathsResponse { success: true, - error_info: None, + error: None, })), Err(err) => Ok(tonic::Response::new(DeletePathsResponse { success: false, - error_info: Some(err.to_string()), + error: Some(err_to_proto_err(&err, &format!("delte paths failed: {}", err))), })), } } else { Ok(tonic::Response::new(DeletePathsResponse { success: false, - error_info: Some("can not find disk".to_string()), + error: Some(err_to_proto_err( + &EcsError::new(StorageError::InvalidArgument(Default::default(), Default::default(), Default::default())), + "can not find disk", + )), })) } } @@ -949,19 +1079,33 @@ impl Node for NodeService { if let Some(disk) = self.find_disk(&request.disk).await { let file_info = match serde_json::from_str::(&request.file_info) { Ok(file_info) => file_info, - Err(_) => { + Err(err) => { return Ok(tonic::Response::new(UpdateMetadataResponse { success: false, - error_info: Some("can not decode FileInfoVersions".to_string()), + error: Some(err_to_proto_err( + &EcsError::new(StorageError::InvalidArgument( + Default::default(), + Default::default(), + Default::default(), + )), + &format!("decode FileInfo failed: {}", err), + )), })); } }; let opts = match serde_json::from_str::(&request.opts) { Ok(opts) => opts, - Err(_) => { + Err(err) => { return Ok(tonic::Response::new(UpdateMetadataResponse { success: false, - error_info: Some("can not decode UpdateMetadataOpts".to_string()), + error: Some(err_to_proto_err( + &EcsError::new(StorageError::InvalidArgument( + Default::default(), + Default::default(), + Default::default(), + )), + &format!("decode UpdateMetadataOpts failed: {}", err), + )), })); } }; @@ -969,17 +1113,20 @@ impl Node for NodeService { match disk.update_metadata(&request.volume, &request.path, file_info, &opts).await { Ok(_) => Ok(tonic::Response::new(UpdateMetadataResponse { success: true, - error_info: None, + error: None, })), Err(err) => Ok(tonic::Response::new(UpdateMetadataResponse { success: false, - error_info: Some(err.to_string()), + error: Some(err_to_proto_err(&err, &format!("update metadata failed: {}", err))), })), } } else { Ok(tonic::Response::new(UpdateMetadataResponse { success: false, - error_info: Some("can not find disk".to_string()), + error: Some(err_to_proto_err( + &EcsError::new(StorageError::InvalidArgument(Default::default(), Default::default(), Default::default())), + "can not find disk", + )), })) } } @@ -992,24 +1139,34 @@ impl Node for NodeService { Err(err) => { return Ok(tonic::Response::new(WriteMetadataResponse { success: false, - error_info: Some(format!("decode FileInfo failed, {}", err)), + error: Some(err_to_proto_err( + &EcsError::new(StorageError::InvalidArgument( + Default::default(), + Default::default(), + Default::default(), + )), + &format!("decode FileInfo failed: {}", err), + )), })); } }; match disk.write_metadata("", &request.volume, &request.path, file_info).await { Ok(_) => Ok(tonic::Response::new(WriteMetadataResponse { success: true, - error_info: None, + error: None, })), Err(err) => Ok(tonic::Response::new(WriteMetadataResponse { success: false, - error_info: Some(err.to_string()), + error: Some(err_to_proto_err(&err, &format!("write metadata failed: {}", err))), })), } } else { Ok(tonic::Response::new(WriteMetadataResponse { success: false, - error_info: Some("can not find disk".to_string()), + error: Some(err_to_proto_err( + &EcsError::new(StorageError::InvalidArgument(Default::default(), Default::default(), Default::default())), + "can not find disk", + )), })) } } @@ -1019,11 +1176,18 @@ impl Node for NodeService { if let Some(disk) = self.find_disk(&request.disk).await { let opts = match serde_json::from_str::(&request.opts) { Ok(options) => options, - Err(_) => { + Err(err) => { return Ok(tonic::Response::new(ReadVersionResponse { success: false, file_info: String::new(), - error_info: Some("can not decode DeleteOptions".to_string()), + error: Some(err_to_proto_err( + &EcsError::new(StorageError::InvalidArgument( + Default::default(), + Default::default(), + Default::default(), + )), + &format!("decode ReadOptions failed: {}", err), + )), })); } }; @@ -1035,25 +1199,31 @@ impl Node for NodeService { Ok(file_info) => Ok(tonic::Response::new(ReadVersionResponse { success: true, file_info, - error_info: None, + error: None, })), Err(err) => Ok(tonic::Response::new(ReadVersionResponse { success: false, file_info: String::new(), - error_info: Some(format!("encode VolumeInfo failed, {}", err)), + error: Some(err_to_proto_err( + &EcsError::from_string("encode data failed"), + &format!("encode data failed: {}", err), + )), })), }, Err(err) => Ok(tonic::Response::new(ReadVersionResponse { success: false, file_info: String::new(), - error_info: Some(err.to_string()), + error: Some(err_to_proto_err(&err, &format!("read version failed: {}", err))), })), } } else { Ok(tonic::Response::new(ReadVersionResponse { success: false, file_info: String::new(), - error_info: Some("can not find disk".to_string()), + error: Some(err_to_proto_err( + &EcsError::new(StorageError::InvalidArgument(Default::default(), Default::default(), Default::default())), + "can not find disk", + )), })) } } @@ -1066,25 +1236,31 @@ impl Node for NodeService { Ok(raw_file_info) => Ok(tonic::Response::new(ReadXlResponse { success: true, raw_file_info, - error_info: None, + error: None, })), Err(err) => Ok(tonic::Response::new(ReadXlResponse { success: false, raw_file_info: String::new(), - error_info: Some(format!("encode RawFileInfo failed, {}", err)), + error: Some(err_to_proto_err( + &EcsError::from_string("encode data failed"), + &format!("encode data failed: {}", err), + )), })), }, Err(err) => Ok(tonic::Response::new(ReadXlResponse { success: false, raw_file_info: String::new(), - error_info: Some(err.to_string()), + error: Some(err_to_proto_err(&err, &format!("read xl failed: {}", err))), })), } } else { Ok(tonic::Response::new(ReadXlResponse { success: false, raw_file_info: String::new(), - error_info: Some("can not find disk".to_string()), + error: Some(err_to_proto_err( + &EcsError::new(StorageError::InvalidArgument(Default::default(), Default::default(), Default::default())), + "can not find disk", + )), })) } } @@ -1094,21 +1270,35 @@ impl Node for NodeService { if let Some(disk) = self.find_disk(&request.disk).await { let file_info = match serde_json::from_str::(&request.file_info) { Ok(file_info) => file_info, - Err(_) => { + Err(err) => { return Ok(tonic::Response::new(DeleteVersionResponse { success: false, raw_file_info: "".to_string(), - error_info: Some("can not decode FileInfoVersions".to_string()), + error: Some(err_to_proto_err( + &EcsError::new(StorageError::InvalidArgument( + Default::default(), + Default::default(), + Default::default(), + )), + &format!("decode FileInfo failed: {}", err), + )), })); } }; let opts = match serde_json::from_str::(&request.opts) { Ok(opts) => opts, - Err(_) => { + Err(err) => { return Ok(tonic::Response::new(DeleteVersionResponse { success: false, raw_file_info: "".to_string(), - error_info: Some("can not decode DeleteOptions".to_string()), + error: Some(err_to_proto_err( + &EcsError::new(StorageError::InvalidArgument( + Default::default(), + Default::default(), + Default::default(), + )), + &format!("decode DeleteOptions failed: {}", err), + )), })); } }; @@ -1120,25 +1310,31 @@ impl Node for NodeService { Ok(raw_file_info) => Ok(tonic::Response::new(DeleteVersionResponse { success: true, raw_file_info, - error_info: None, + error: None, })), Err(err) => Ok(tonic::Response::new(DeleteVersionResponse { success: false, raw_file_info: "".to_string(), - error_info: Some(err.to_string()), + error: Some(err_to_proto_err( + &EcsError::from_string("encode data failed"), + &format!("encode data failed: {}", err), + )), })), }, Err(err) => Ok(tonic::Response::new(DeleteVersionResponse { success: false, raw_file_info: "".to_string(), - error_info: Some(err.to_string()), + error: Some(err_to_proto_err(&err, &format!("read version failed: {}", err))), })), } } else { Ok(tonic::Response::new(DeleteVersionResponse { success: false, raw_file_info: "".to_string(), - error_info: Some("can not find disk".to_string()), + error: Some(err_to_proto_err( + &EcsError::new(StorageError::InvalidArgument(Default::default(), Default::default(), Default::default())), + "can not find disk", + )), })) } } @@ -1150,22 +1346,36 @@ impl Node for NodeService { for version in request.versions.iter() { match serde_json::from_str::(version) { Ok(version) => versions.push(version), - Err(_) => { + Err(err) => { return Ok(tonic::Response::new(DeleteVersionsResponse { success: false, errors: Vec::new(), - error_info: Some("can not decode FileInfoVersions".to_string()), + error: Some(err_to_proto_err( + &EcsError::new(StorageError::InvalidArgument( + Default::default(), + Default::default(), + Default::default(), + )), + &format!("decode FileInfoVersions failed: {}", err), + )), })); } }; } let opts = match serde_json::from_str::(&request.opts) { Ok(opts) => opts, - Err(_) => { + Err(err) => { return Ok(tonic::Response::new(DeleteVersionsResponse { success: false, errors: Vec::new(), - error_info: Some("can not decode DeleteOptions".to_string()), + error: Some(err_to_proto_err( + &EcsError::new(StorageError::InvalidArgument( + Default::default(), + Default::default(), + Default::default(), + )), + &format!("decode DeleteOptions failed: {}", err), + )), })); } }; @@ -1182,20 +1392,23 @@ impl Node for NodeService { Ok(tonic::Response::new(DeleteVersionsResponse { success: true, errors, - error_info: None, + error: None, })) } Err(err) => Ok(tonic::Response::new(DeleteVersionsResponse { success: false, errors: Vec::new(), - error_info: Some(err.to_string()), + error: Some(err_to_proto_err(&err, &format!("delete version failed: {}", err))), })), } } else { Ok(tonic::Response::new(DeleteVersionsResponse { success: false, errors: Vec::new(), - error_info: Some("can not find disk".to_string()), + error: Some(err_to_proto_err( + &EcsError::new(StorageError::InvalidArgument(Default::default(), Default::default(), Default::default())), + "can not find disk", + )), })) } } @@ -1205,11 +1418,18 @@ impl Node for NodeService { if let Some(disk) = self.find_disk(&request.disk).await { let read_multiple_req = match serde_json::from_str::(&request.read_multiple_req) { Ok(read_multiple_req) => read_multiple_req, - Err(_) => { + Err(err) => { return Ok(tonic::Response::new(ReadMultipleResponse { success: false, read_multiple_resps: Vec::new(), - error_info: Some("can not decode ReadMultipleReq".to_string()), + error: Some(err_to_proto_err( + &EcsError::new(StorageError::InvalidArgument( + Default::default(), + Default::default(), + Default::default(), + )), + &format!("decode ReadMultipleReq failed: {}", err), + )), })); } }; @@ -1223,20 +1443,23 @@ impl Node for NodeService { Ok(tonic::Response::new(ReadMultipleResponse { success: true, read_multiple_resps, - error_info: None, + error: None, })) } Err(err) => Ok(tonic::Response::new(ReadMultipleResponse { success: false, read_multiple_resps: Vec::new(), - error_info: Some(err.to_string()), + error: Some(err_to_proto_err(&err, &format!("read multiple failed: {}", err))), })), } } else { Ok(tonic::Response::new(ReadMultipleResponse { success: false, read_multiple_resps: Vec::new(), - error_info: Some("can not find disk".to_string()), + error: Some(err_to_proto_err( + &EcsError::new(StorageError::InvalidArgument(Default::default(), Default::default(), Default::default())), + "can not find disk", + )), })) } } @@ -1247,17 +1470,20 @@ impl Node for NodeService { match disk.delete_volume(&request.volume).await { Ok(_) => Ok(tonic::Response::new(DeleteVolumeResponse { success: true, - error_info: None, + error: None, })), Err(err) => Ok(tonic::Response::new(DeleteVolumeResponse { success: false, - error_info: Some(err.to_string()), + error: Some(err_to_proto_err(&err, &format!("delete volume failed: {}", err))), })), } } else { Ok(tonic::Response::new(DeleteVolumeResponse { success: false, - error_info: Some("can not find disk".to_string()), + error: Some(err_to_proto_err( + &EcsError::new(StorageError::InvalidArgument(Default::default(), Default::default(), Default::default())), + "can not find disk", + )), })) } } @@ -1267,11 +1493,18 @@ impl Node for NodeService { if let Some(disk) = self.find_disk(&request.disk).await { let opts = match serde_json::from_str::(&request.opts) { Ok(opts) => opts, - Err(_) => { + Err(err) => { return Ok(tonic::Response::new(DiskInfoResponse { success: false, disk_info: "".to_string(), - error_info: Some("can not decode DiskInfoOptions".to_string()), + error: Some(err_to_proto_err( + &EcsError::new(StorageError::InvalidArgument( + Default::default(), + Default::default(), + Default::default(), + )), + &format!("decode DiskInfoOptions failed: {}", err), + )), })); } }; @@ -1280,25 +1513,31 @@ impl Node for NodeService { Ok(disk_info) => Ok(tonic::Response::new(DiskInfoResponse { success: true, disk_info, - error_info: None, + error: None, })), Err(err) => Ok(tonic::Response::new(DiskInfoResponse { success: false, disk_info: "".to_string(), - error_info: Some(err.to_string()), + error: Some(err_to_proto_err( + &EcsError::from_string("encode data failed"), + &format!("encode data failed: {}", err), + )), })), }, Err(err) => Ok(tonic::Response::new(DiskInfoResponse { success: false, disk_info: "".to_string(), - error_info: Some(err.to_string()), + error: Some(err_to_proto_err(&err, &format!("disk info failed: {}", err))), })), } } else { Ok(tonic::Response::new(DiskInfoResponse { success: false, disk_info: "".to_string(), - error_info: Some("can not find disk".to_string()), + error: Some(err_to_proto_err( + &EcsError::new(StorageError::InvalidArgument(Default::default(), Default::default(), Default::default())), + "can not find disk", + )), })) } } @@ -1316,12 +1555,19 @@ impl Node for NodeService { if let Some(disk) = find_local_disk(&request.disk).await { let cache = match serde_json::from_str::(&request.cache) { Ok(cache) => cache, - Err(_) => { + Err(err) => { tx.send(Ok(NsScannerResponse { success: false, update: "".to_string(), data_usage_cache: "".to_string(), - error_info: Some("can not decode DataUsageCache".to_string()), + error: Some(err_to_proto_err( + &EcsError::new(StorageError::InvalidArgument( + Default::default(), + Default::default(), + Default::default(), + )), + &format!("decode DataUsageCache failed: {}", err), + )), })) .await .expect("working rx"); @@ -1340,7 +1586,7 @@ impl Node for NodeService { success: true, update, data_usage_cache: "".to_string(), - error_info: Some("can not decode DataUsageCache".to_string()), + error: None, })) .await .expect("working rx"); @@ -1358,17 +1604,17 @@ impl Node for NodeService { success: true, update: "".to_string(), data_usage_cache, - error_info: Some("can not decode DataUsageCache".to_string()), + error: None, })) .await .expect("working rx"); } - Err(_) => { + Err(err) => { tx.send(Ok(NsScannerResponse { success: false, update: "".to_string(), data_usage_cache: "".to_string(), - error_info: Some("scanner failed".to_string()), + error: Some(err_to_proto_err(&err, &format!("scanner failed: {}", err))), })) .await .expect("working rx"); @@ -1379,7 +1625,14 @@ impl Node for NodeService { success: false, update: "".to_string(), data_usage_cache: "".to_string(), - error_info: Some("can not find disk".to_string()), + error: Some(err_to_proto_err( + &EcsError::new(StorageError::InvalidArgument( + Default::default(), + Default::default(), + Default::default(), + )), + "can not find disk", + )), })) .await .expect("working rx");