From 8d7cd4cb1bad86781fb4647e78f7481c7f38aeac Mon Sep 17 00:00:00 2001 From: houseme Date: Fri, 2 Jan 2026 00:02:34 +0800 Subject: [PATCH] chore: upgrade dependencies and migrate to aws-lc-rs (#1333) --- Cargo.lock | 374 ++++------ Cargo.toml | 14 +- crates/ahm/src/heal/erasure_healer.rs | 2 +- crates/ahm/src/heal/manager.rs | 5 +- crates/ahm/src/heal/resume.rs | 8 +- crates/ahm/src/scanner/checkpoint.rs | 8 +- crates/ahm/src/scanner/data_scanner.rs | 473 ++++++------ crates/ahm/src/scanner/local_scan/mod.rs | 8 +- crates/ahm/src/scanner/local_stats.rs | 8 +- crates/ahm/src/scanner/node_scanner.rs | 8 +- crates/ahm/src/scanner/stats_aggregator.rs | 18 +- crates/ahm/tests/lifecycle_cache_test.rs | 148 ++-- .../ahm/tests/lifecycle_integration_test.rs | 78 +- crates/audit/src/factory.rs | 8 +- crates/audit/src/registry.rs | 19 +- crates/audit/src/system.rs | 8 +- crates/common/src/data_usage.rs | 21 +- crates/common/src/heal_channel.rs | 36 +- crates/common/src/metrics.rs | 18 +- crates/e2e_test/src/common.rs | 10 +- crates/e2e_test/src/kms/common.rs | 10 +- .../ecstore/src/bucket/bucket_target_sys.rs | 54 +- .../src/bucket/object_lock/objectlock_sys.rs | 8 +- .../ecstore/src/bucket/replication/config.rs | 52 +- .../bucket/replication/replication_pool.rs | 136 ++-- .../replication/replication_resyncer.rs | 35 +- .../bucket/replication/replication_state.rs | 22 +- crates/ecstore/src/bucket/versioning/mod.rs | 18 +- .../ecstore/src/cache_value/metacache_set.rs | 11 +- crates/ecstore/src/client/transition_api.rs | 2 +- crates/ecstore/src/config/com.rs | 9 +- crates/ecstore/src/config/mod.rs | 8 +- crates/ecstore/src/data_usage.rs | 70 +- crates/ecstore/src/disk/local.rs | 279 ++++---- crates/ecstore/src/disk/os.rs | 21 +- crates/ecstore/src/disks_layout.rs | 4 +- crates/ecstore/src/erasure_coding/decode.rs | 11 +- crates/ecstore/src/erasure_coding/encode.rs | 8 +- crates/ecstore/src/erasure_coding/heal.rs | 2 +- crates/ecstore/src/pools.rs | 106 +-- crates/ecstore/src/rebalance.rs | 122 ++-- crates/ecstore/src/rpc/peer_rest_client.rs | 12 +- crates/ecstore/src/rpc/peer_s3_client.rs | 16 +- crates/ecstore/src/set_disk.rs | 268 ++++--- crates/ecstore/src/sets.rs | 55 +- crates/ecstore/src/store.rs | 87 +-- crates/ecstore/src/store_api.rs | 179 +++-- crates/ecstore/src/store_list_objects.rs | 86 +-- crates/filemeta/src/fileinfo.rs | 8 +- crates/filemeta/src/filemeta.rs | 196 +++-- crates/filemeta/src/metacache.rs | 42 +- crates/filemeta/src/replication.rs | 12 +- crates/iam/src/manager.rs | 110 +-- crates/iam/src/store/object.rs | 29 +- crates/iam/src/sys.rs | 92 +-- crates/kms/src/backends/local.rs | 38 +- crates/kms/src/config.rs | 15 +- crates/kms/src/manager.rs | 16 +- crates/lock/src/client/mod.rs | 24 +- crates/lock/src/fast_lock/guard.rs | 8 +- crates/lock/src/fast_lock/manager.rs | 8 +- crates/lock/src/fast_lock/shard.rs | 62 +- crates/lock/src/namespace.rs | 8 +- crates/notify/src/factory.rs | 8 +- crates/notify/src/notifier.rs | 8 +- crates/notify/src/registry.rs | 19 +- crates/notify/src/rules/pattern.rs | 38 +- crates/obs/src/telemetry.rs | 24 +- crates/policy/src/policy/resource.rs | 8 +- crates/rio/src/checksum.rs | 70 +- crates/rio/src/hash_reader.rs | 69 +- .../s3select-query/src/dispatcher/manager.rs | 8 +- crates/signer/src/utils.rs | 8 +- crates/targets/src/store.rs | 10 +- crates/targets/src/target/mqtt.rs | 29 +- crates/utils/src/certs.rs | 2 +- crates/utils/src/http/ip.rs | 103 ++- crates/utils/src/net.rs | 17 +- crates/utils/src/notify/net.rs | 25 +- rustfs/src/admin/console.rs | 44 +- rustfs/src/admin/handlers.rs | 80 +-- rustfs/src/admin/handlers/group.rs | 9 +- rustfs/src/admin/handlers/user.rs | 16 +- rustfs/src/auth.rs | 114 +-- rustfs/src/error.rs | 22 +- rustfs/src/protocols/ftps/driver.rs | 16 +- rustfs/src/protocols/ftps/server.rs | 16 +- rustfs/src/protocols/sftp/handler.rs | 20 +- rustfs/src/protocols/sftp/server.rs | 8 +- rustfs/src/server/cert.rs | 20 +- rustfs/src/server/compress.rs | 51 +- rustfs/src/server/http.rs | 65 +- rustfs/src/storage/ecfs.rs | 676 +++++++++--------- rustfs/src/storage/helper.rs | 26 +- rustfs/src/storage/options.rs | 54 +- rustfs/src/version.rs | 16 +- 96 files changed, 2555 insertions(+), 2775 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 3ce8d55d..73fe7347 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -532,7 +532,7 @@ checksum = "3109e49b1e4909e9db6515a30c633684d68cdeaa252f215214cb4fa1a5bfee2c" dependencies = [ "proc-macro2", "quote", - "syn 2.0.111", + "syn 2.0.112", "synstructure 0.13.2", ] @@ -544,7 +544,7 @@ checksum = "7b18050c2cd6fe86c3a76584ef5e0baf286d038cda203eb6223df2cc413565f7" dependencies = [ "proc-macro2", "quote", - "syn 2.0.111", + "syn 2.0.112", ] [[package]] @@ -670,7 +670,7 @@ checksum = "3b43422f69d8ff38f95f1b2bb76517c91589a924d1559a0e935d7c8ce0274c11" dependencies = [ "proc-macro2", "quote", - "syn 2.0.111", + "syn 2.0.112", ] [[package]] @@ -718,7 +718,7 @@ checksum = "c7c24de15d275a1ecfd47a380fb4d5ec9bfe0933f309ed5e705b775596a3574d" dependencies = [ "proc-macro2", "quote", - "syn 2.0.111", + "syn 2.0.112", ] [[package]] @@ -735,7 +735,7 @@ checksum = "9035ad2d096bed7955a320ee7e2230574d28fd3c3a0f186cbea1ff3c7eed5dbb" dependencies = [ "proc-macro2", "quote", - "syn 2.0.111", + "syn 2.0.112", ] [[package]] @@ -761,7 +761,7 @@ checksum = "99e1aca718ea7b89985790c94aad72d77533063fe00bc497bb79a7c2dae6a661" dependencies = [ "proc-macro2", "quote", - "syn 2.0.111", + "syn 2.0.112", ] [[package]] @@ -1062,23 +1062,17 @@ dependencies = [ "aws-smithy-async", "aws-smithy-runtime-api", "aws-smithy-types", - "h2 0.3.27", - "h2 0.4.12", - "http 0.2.12", + "h2", "http 1.4.0", - "http-body 0.4.6", - "hyper 0.14.32", - "hyper 1.8.1", - "hyper-rustls 0.24.2", - "hyper-rustls 0.27.7", + "hyper", + "hyper-rustls", "hyper-util", "pin-project-lite", - "rustls 0.21.12", - "rustls 0.23.35", + "rustls", "rustls-native-certs", "rustls-pki-types", "tokio", - "tokio-rustls 0.26.4", + "tokio-rustls", "tower", "tracing", ] @@ -1214,7 +1208,7 @@ dependencies = [ "http 1.4.0", "http-body 1.0.1", "http-body-util", - "hyper 1.8.1", + "hyper", "hyper-util", "itoa", "matchit 0.8.4", @@ -1265,13 +1259,13 @@ dependencies = [ "fs-err", "http 1.4.0", "http-body 1.0.1", - "hyper 1.8.1", + "hyper", "hyper-util", "pin-project-lite", - "rustls 0.23.35", + "rustls", "rustls-pki-types", "tokio", - "tokio-rustls 0.26.4", + "tokio-rustls", "tower-service", ] @@ -1484,7 +1478,7 @@ dependencies = [ "proc-macro2", "quote", "rustversion", - "syn 2.0.111", + "syn 2.0.112", ] [[package]] @@ -1821,7 +1815,7 @@ dependencies = [ "heck", "proc-macro2", "quote", - "syn 2.0.111", + "syn 2.0.112", ] [[package]] @@ -1913,7 +1907,7 @@ checksum = "5c25c2a02ba19f2d4fd9f54d5f239f97c867deb7397763a9771edab63c44a4fa" dependencies = [ "proc-macro2", "quote", - "syn 2.0.111", + "syn 2.0.112", ] [[package]] @@ -2268,7 +2262,7 @@ checksum = "f46882e17999c6cc590af592290432be3bce0428cb0d5f8b6715e4dc7b383eb3" dependencies = [ "proc-macro2", "quote", - "syn 2.0.111", + "syn 2.0.112", ] [[package]] @@ -2336,7 +2330,7 @@ dependencies = [ "proc-macro2", "quote", "strsim 0.11.1", - "syn 2.0.111", + "syn 2.0.112", ] [[package]] @@ -2350,7 +2344,7 @@ dependencies = [ "proc-macro2", "quote", "strsim 0.11.1", - "syn 2.0.111", + "syn 2.0.112", ] [[package]] @@ -2363,7 +2357,7 @@ dependencies = [ "proc-macro2", "quote", "strsim 0.11.1", - "syn 2.0.111", + "syn 2.0.112", ] [[package]] @@ -2385,7 +2379,7 @@ checksum = "fc34b93ccb385b40dc71c6fceac4b2ad23662c7eeb248cf10d529b7e055b6ead" dependencies = [ "darling_core 0.20.11", "quote", - "syn 2.0.111", + "syn 2.0.112", ] [[package]] @@ -2396,7 +2390,7 @@ checksum = "d38308df82d1080de0afee5d069fa14b0326a88c14f15c5ccda35b4a6c414c81" dependencies = [ "darling_core 0.21.3", "quote", - "syn 2.0.111", + "syn 2.0.112", ] [[package]] @@ -2407,7 +2401,7 @@ checksum = "ac3984ec7bd6cfa798e62b4a642426a5be0e68f9401cfc2a01e3fa9ea2fcdb8d" dependencies = [ "darling_core 0.23.0", "quote", - "syn 2.0.111", + "syn 2.0.112", ] [[package]] @@ -2905,7 +2899,7 @@ checksum = "1063ad4c9e094b3f798acee16d9a47bd7372d9699be2de21b05c3bd3f34ab848" dependencies = [ "datafusion-doc", "quote", - "syn 2.0.111", + "syn 2.0.112", ] [[package]] @@ -3101,7 +3095,7 @@ checksum = "780eb241654bf097afb00fc5f054a09b687dad862e485fdcf8399bb056565370" dependencies = [ "proc-macro2", "quote", - "syn 2.0.111", + "syn 2.0.112", ] [[package]] @@ -3168,7 +3162,7 @@ checksum = "1e567bd82dcff979e4b03460c307b3cdc9e96fde3d73bed1496d2bc75d9dd62a" dependencies = [ "proc-macro2", "quote", - "syn 2.0.111", + "syn 2.0.112", ] [[package]] @@ -3210,7 +3204,7 @@ dependencies = [ "darling 0.20.11", "proc-macro2", "quote", - "syn 2.0.111", + "syn 2.0.112", ] [[package]] @@ -3230,7 +3224,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ab63b0e2bf4d5928aff72e83a7dace85d7bba5fe12dcc3c5a572d78caffd3f3c" dependencies = [ "derive_builder_core 0.20.2", - "syn 2.0.111", + "syn 2.0.112", ] [[package]] @@ -3252,7 +3246,7 @@ dependencies = [ "proc-macro2", "quote", "rustc_version", - "syn 2.0.111", + "syn 2.0.112", "unicode-xid", ] @@ -3324,7 +3318,7 @@ checksum = "97369cbbc041bc366949bc74d34658d6cda5621039731c6310521892a3a20ae0" dependencies = [ "proc-macro2", "quote", - "syn 2.0.111", + "syn 2.0.112", ] [[package]] @@ -3380,7 +3374,7 @@ dependencies = [ "rustfs-lock", "rustfs-madmin", "rustfs-protos", - "rustls 0.23.35", + "rustls", "rustls-pemfile", "serde", "serde_json", @@ -3511,7 +3505,7 @@ dependencies = [ "heck", "proc-macro2", "quote", - "syn 2.0.111", + "syn 2.0.112", ] [[package]] @@ -3523,7 +3517,7 @@ dependencies = [ "once_cell", "proc-macro2", "quote", - "syn 2.0.111", + "syn 2.0.112", ] [[package]] @@ -3544,7 +3538,7 @@ dependencies = [ "darling 0.21.3", "proc-macro2", "quote", - "syn 2.0.111", + "syn 2.0.112", ] [[package]] @@ -3583,7 +3577,7 @@ checksum = "44f23cf4b44bfce11a86ace86f8a73ffdec849c9fd00a386a53d278bd9e81fb3" dependencies = [ "proc-macro2", "quote", - "syn 2.0.111", + "syn 2.0.112", ] [[package]] @@ -3930,7 +3924,7 @@ checksum = "162ee34ebcb7c64a8abebc059ce0fee27c2262618d7b60ed8faf72fef13c3650" dependencies = [ "proc-macro2", "quote", - "syn 2.0.111", + "syn 2.0.112", ] [[package]] @@ -4039,7 +4033,7 @@ dependencies = [ "proc-macro-error2", "proc-macro2", "quote", - "syn 2.0.111", + "syn 2.0.112", ] [[package]] @@ -4099,7 +4093,7 @@ dependencies = [ "http 1.4.0", "reqwest", "rustc_version", - "rustls 0.23.35", + "rustls", "rustls-pemfile", "serde", "serde_json", @@ -4143,7 +4137,7 @@ dependencies = [ "http 1.4.0", "http-body 1.0.1", "http-body-util", - "hyper 1.8.1", + "hyper", "opentelemetry-semantic-conventions", "percent-encoding", "pin-project", @@ -4251,7 +4245,7 @@ dependencies = [ "google-cloud-wkt", "http 1.4.0", "http-body 1.0.1", - "hyper 1.8.1", + "hyper", "lazy_static", "md5 0.8.0", "mime", @@ -4323,25 +4317,6 @@ dependencies = [ "subtle", ] -[[package]] -name = "h2" -version = "0.3.27" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0beca50380b1fc32983fc1cb4587bfa4bb9e78fc259aad4a0032d2080309222d" -dependencies = [ - "bytes", - "fnv", - "futures-core", - "futures-sink", - "futures-util", - "http 0.2.12", - "indexmap 2.12.1", - "slab", - "tokio", - "tokio-util", - "tracing", -] - [[package]] name = "h2" version = "0.4.12" @@ -4444,7 +4419,7 @@ dependencies = [ "proc-macro-error2", "proc-macro2", "quote", - "syn 2.0.111", + "syn 2.0.112", ] [[package]] @@ -4667,30 +4642,6 @@ dependencies = [ "zeroize", ] -[[package]] -name = "hyper" -version = "0.14.32" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "41dfc780fdec9373c01bae43289ea34c972e40ee3c9f6b3c8801a35f35586ce7" -dependencies = [ - "bytes", - "futures-channel", - "futures-core", - "futures-util", - "h2 0.3.27", - "http 0.2.12", - "http-body 0.4.6", - "httparse", - "httpdate", - "itoa", - "pin-project-lite", - "socket2 0.5.10", - "tokio", - "tower-service", - "tracing", - "want", -] - [[package]] name = "hyper" version = "1.8.1" @@ -4701,7 +4652,7 @@ dependencies = [ "bytes", "futures-channel", "futures-core", - "h2 0.4.12", + "h2", "http 1.4.0", "http-body 1.0.1", "httparse", @@ -4714,21 +4665,6 @@ dependencies = [ "want", ] -[[package]] -name = "hyper-rustls" -version = "0.24.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ec3efd23720e2049821a693cbc7e65ea87c72f1c58ff2f9522ff332b1491e590" -dependencies = [ - "futures-util", - "http 0.2.12", - "hyper 0.14.32", - "log", - "rustls 0.21.12", - "tokio", - "tokio-rustls 0.24.1", -] - [[package]] name = "hyper-rustls" version = "0.27.7" @@ -4736,14 +4672,14 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e3c93eb611681b207e1fe55d5a71ecf91572ec8a6705cdb6857f7d8d5242cf58" dependencies = [ "http 1.4.0", - "hyper 1.8.1", + "hyper", "hyper-util", "log", - "rustls 0.23.35", + "rustls", "rustls-native-certs", "rustls-pki-types", "tokio", - "tokio-rustls 0.26.4", + "tokio-rustls", "tower-service", "webpki-roots", ] @@ -4754,7 +4690,7 @@ version = "0.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2b90d566bffbce6a75bd8b09a05aa8c2cb1fabb6cb348f8840c9e4c90a0d83b0" dependencies = [ - "hyper 1.8.1", + "hyper", "hyper-util", "pin-project-lite", "tokio", @@ -4774,12 +4710,12 @@ dependencies = [ "futures-util", "http 1.4.0", "http-body 1.0.1", - "hyper 1.8.1", + "hyper", "ipnet", "libc", "percent-encoding", "pin-project-lite", - "socket2 0.6.1", + "socket2", "system-configuration", "tokio", "tower-service", @@ -5236,7 +5172,7 @@ dependencies = [ "proc-macro2", "quote", "regex", - "syn 2.0.111", + "syn 2.0.112", ] [[package]] @@ -5473,13 +5409,13 @@ dependencies = [ "nix 0.29.0", "prometheus", "proxy-protocol", - "rustls 0.23.35", + "rustls", "rustls-pemfile", "slog", "slog-stdlog", "thiserror 2.0.17", "tokio", - "tokio-rustls 0.26.4", + "tokio-rustls", "tokio-util", "tracing", "tracing-attributes", @@ -5854,7 +5790,7 @@ dependencies = [ "proc-macro2", "quote", "serde", - "syn 2.0.111", + "syn 2.0.112", ] [[package]] @@ -6248,7 +6184,7 @@ checksum = "a948666b637a0f465e8564c73e89d4dde00d72d4d473cc972f390fc3dcee7d9c" dependencies = [ "proc-macro2", "quote", - "syn 2.0.111", + "syn 2.0.112", ] [[package]] @@ -6735,7 +6671,7 @@ dependencies = [ "phf_shared 0.11.3", "proc-macro2", "quote", - "syn 2.0.111", + "syn 2.0.112", ] [[package]] @@ -6773,7 +6709,7 @@ checksum = "6e918e4ff8c4549eb882f14b3a4bc8c8bc93de829416eacf579f1207a8fbf861" dependencies = [ "proc-macro2", "quote", - "syn 2.0.111", + "syn 2.0.112", ] [[package]] @@ -7058,7 +6994,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "479ca8adacdd7ce8f1fb39ce9ecccbfe93a3f1344b3d0d97f20bc0196208f62b" dependencies = [ "proc-macro2", - "syn 2.0.111", + "syn 2.0.112", ] [[package]] @@ -7098,7 +7034,7 @@ dependencies = [ "proc-macro-error-attr2", "proc-macro2", "quote", - "syn 2.0.111", + "syn 2.0.112", ] [[package]] @@ -7162,7 +7098,7 @@ dependencies = [ "pulldown-cmark", "pulldown-cmark-to-cmark", "regex", - "syn 2.0.111", + "syn 2.0.112", "tempfile", ] @@ -7176,7 +7112,7 @@ dependencies = [ "itertools 0.14.0", "proc-macro2", "quote", - "syn 2.0.111", + "syn 2.0.112", ] [[package]] @@ -7189,7 +7125,7 @@ dependencies = [ "itertools 0.14.0", "proc-macro2", "quote", - "syn 2.0.111", + "syn 2.0.112", ] [[package]] @@ -7334,8 +7270,8 @@ dependencies = [ "quinn-proto", "quinn-udp", "rustc-hash", - "rustls 0.23.35", - "socket2 0.6.1", + "rustls", + "socket2", "thiserror 2.0.17", "tokio", "tracing", @@ -7354,7 +7290,7 @@ dependencies = [ "rand 0.9.2", "ring", "rustc-hash", - "rustls 0.23.35", + "rustls", "rustls-pki-types", "slab", "thiserror 2.0.17", @@ -7372,7 +7308,7 @@ dependencies = [ "cfg_aliases", "libc", "once_cell", - "socket2 0.6.1", + "socket2", "tracing", "windows-sys 0.60.2", ] @@ -7529,7 +7465,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "76009fbe0614077fc1a2ce255e3a1881a2e3a3527097d5dc6d8212c585e7e38b" dependencies = [ "quote", - "syn 2.0.111", + "syn 2.0.112", ] [[package]] @@ -7590,7 +7526,7 @@ checksum = "b7186006dcb21920990093f30e3dea63b7d6e977bf1256be20c3563a5db070da" dependencies = [ "proc-macro2", "quote", - "syn 2.0.111", + "syn 2.0.112", ] [[package]] @@ -7646,12 +7582,12 @@ dependencies = [ "futures-channel", "futures-core", "futures-util", - "h2 0.4.12", + "h2", "http 1.4.0", "http-body 1.0.1", "http-body-util", - "hyper 1.8.1", - "hyper-rustls 0.27.7", + "hyper", + "hyper-rustls", "hyper-util", "js-sys", "log", @@ -7660,7 +7596,7 @@ dependencies = [ "percent-encoding", "pin-project-lite", "quinn", - "rustls 0.23.35", + "rustls", "rustls-native-certs", "rustls-pki-types", "serde", @@ -7668,7 +7604,7 @@ dependencies = [ "serde_urlencoded", "sync_wrapper", "tokio", - "tokio-rustls 0.26.4", + "tokio-rustls", "tokio-util", "tower", "tower-http", @@ -7757,7 +7693,7 @@ dependencies = [ "proc-macro2", "quote", "serde_json", - "syn 2.0.111", + "syn 2.0.112", ] [[package]] @@ -7844,7 +7780,7 @@ dependencies = [ "regex", "relative-path", "rustc_version", - "syn 2.0.111", + "syn 2.0.112", "unicode-ident", ] @@ -7864,7 +7800,7 @@ dependencies = [ "rustls-webpki 0.102.8", "thiserror 2.0.17", "tokio", - "tokio-rustls 0.26.4", + "tokio-rustls", "tokio-stream", "tokio-util", ] @@ -7994,7 +7930,7 @@ dependencies = [ "quote", "rust-embed-utils", "shellexpand", - "syn 2.0.111", + "syn 2.0.112", "walkdir", ] @@ -8053,7 +7989,7 @@ dependencies = [ "http 1.4.0", "http-body 1.0.1", "http-body-util", - "hyper 1.8.1", + "hyper", "hyper-util", "jemalloc_pprof", "libsystemd", @@ -8094,7 +8030,7 @@ dependencies = [ "rustfs-targets", "rustfs-utils", "rustfs-zip", - "rustls 0.23.35", + "rustls", "rustls-pemfile", "s3s", "serde", @@ -8102,7 +8038,7 @@ dependencies = [ "serde_urlencoded", "serial_test", "shadow-rs", - "socket2 0.6.1", + "socket2", "ssh-key", "subtle", "sysctl", @@ -8112,7 +8048,7 @@ dependencies = [ "tikv-jemallocator", "time", "tokio", - "tokio-rustls 0.26.4", + "tokio-rustls", "tokio-stream", "tokio-util", "tonic", @@ -8286,8 +8222,8 @@ dependencies = [ "hex-simd", "hmac 0.13.0-rc.3", "http 1.4.0", - "hyper 1.8.1", - "hyper-rustls 0.27.7", + "hyper", + "hyper-rustls", "hyper-util", "lazy_static", "md-5 0.11.0-rc.3", @@ -8316,7 +8252,7 @@ dependencies = [ "rustfs-signer", "rustfs-utils", "rustfs-workers", - "rustls 0.23.35", + "rustls", "s3s", "serde", "serde_json", @@ -8443,7 +8379,7 @@ version = "0.0.5" dependencies = [ "chrono", "humantime", - "hyper 1.8.1", + "hyper", "serde", "serde_json", "time", @@ -8645,7 +8581,7 @@ dependencies = [ "base64-simd", "bytes", "http 1.4.0", - "hyper 1.8.1", + "hyper", "rustfs-utils", "s3s", "serde_urlencoded", @@ -8690,7 +8626,7 @@ dependencies = [ "highway", "hmac 0.13.0-rc.3", "http 1.4.0", - "hyper 1.8.1", + "hyper", "libc", "local-ip-address", "lz4", @@ -8700,7 +8636,7 @@ dependencies = [ "rand 0.10.0-rc.5", "regex", "rustfs-config", - "rustls 0.23.35", + "rustls", "rustls-pemfile", "rustls-pki-types", "s3s", @@ -8807,18 +8743,6 @@ dependencies = [ "windows-sys 0.61.2", ] -[[package]] -name = "rustls" -version = "0.21.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3f56a14d1f48b391359b22f731fd4bd7e43c97f3c50eee276f3aa09c94784d3e" -dependencies = [ - "log", - "ring", - "rustls-webpki 0.101.7", - "sct", -] - [[package]] name = "rustls" version = "0.23.35" @@ -8866,16 +8790,6 @@ dependencies = [ "zeroize", ] -[[package]] -name = "rustls-webpki" -version = "0.101.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8b6275d1ee7a1cd780b64aca7726599a1dbc893b1e64144529e55c3c2f745765" -dependencies = [ - "ring", - "untrusted 0.9.0", -] - [[package]] name = "rustls-webpki" version = "0.102.8" @@ -8914,7 +8828,7 @@ checksum = "a50f4cf475b65d88e057964e0e9bb1f0aa9bbb2036dc65c64596b42932536984" [[package]] name = "s3s" version = "0.13.0-alpha" -source = "git+https://github.com/s3s-project/s3s.git?branch=main#9e41304ed549b89cfb03ede98e9c0d2ac7522051" +source = "git+https://github.com/s3s-project/s3s.git?branch=main#336ed86c77e99fd94fc7581a3a39ef246a63281b" dependencies = [ "arrayvec", "async-trait", @@ -8933,7 +8847,7 @@ dependencies = [ "http-body 1.0.1", "http-body-util", "httparse", - "hyper 1.8.1", + "hyper", "itoa", "md-5 0.11.0-rc.3", "memchr", @@ -9031,7 +8945,7 @@ dependencies = [ "proc-macro2", "quote", "serde_derive_internals", - "syn 2.0.111", + "syn 2.0.112", ] [[package]] @@ -9051,16 +8965,6 @@ dependencies = [ "sha2 0.10.9", ] -[[package]] -name = "sct" -version = "0.7.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "da046153aa2352493d6cb7da4b6e5c0c057d8a1d0a9aa8560baffdd945acd414" -dependencies = [ - "ring", - "untrusted 0.9.0", -] - [[package]] name = "sdd" version = "3.0.10" @@ -9190,7 +9094,7 @@ checksum = "d540f220d3187173da220f885ab66608367b6574e925011a9353e4badda91d79" dependencies = [ "proc-macro2", "quote", - "syn 2.0.111", + "syn 2.0.112", ] [[package]] @@ -9201,7 +9105,7 @@ checksum = "18d26a20a969b9e3fdf2fc2d9f21eda6c40e2de84c9408bb5d3b05d499aae711" dependencies = [ "proc-macro2", "quote", - "syn 2.0.111", + "syn 2.0.112", ] [[package]] @@ -9286,7 +9190,7 @@ dependencies = [ "darling 0.21.3", "proc-macro2", "quote", - "syn 2.0.111", + "syn 2.0.112", ] [[package]] @@ -9321,7 +9225,7 @@ checksum = "5d69265a08751de7844521fd15003ae0a888e035773ba05695c5c759a6f89eef" dependencies = [ "proc-macro2", "quote", - "syn 2.0.111", + "syn 2.0.112", ] [[package]] @@ -9576,7 +9480,7 @@ dependencies = [ "heck", "proc-macro2", "quote", - "syn 2.0.111", + "syn 2.0.112", ] [[package]] @@ -9585,16 +9489,6 @@ version = "1.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1b6b67fb9a61334225b5b790716f609cd58395f895b3fe8b328786812a40bc3b" -[[package]] -name = "socket2" -version = "0.5.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e22376abed350d73dd1cd119b57ffccad95b4e585a7cda43e286245ce23c0678" -dependencies = [ - "libc", - "windows-sys 0.52.0", -] - [[package]] name = "socket2" version = "0.6.1" @@ -9672,7 +9566,7 @@ checksum = "da5fc6819faabb412da764b99d3b713bb55083c11e7e0c00144d386cd6a1939c" dependencies = [ "proc-macro2", "quote", - "syn 2.0.111", + "syn 2.0.112", ] [[package]] @@ -9845,7 +9739,7 @@ dependencies = [ "heck", "proc-macro2", "quote", - "syn 2.0.111", + "syn 2.0.112", ] [[package]] @@ -9868,7 +9762,7 @@ dependencies = [ "log", "native-tls", "pin-project", - "rustls 0.23.35", + "rustls", "thiserror 2.0.17", ] @@ -9986,9 +9880,9 @@ dependencies = [ [[package]] name = "syn" -version = "2.0.111" +version = "2.0.112" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "390cc9a294ab71bdb1aa2e99d13be9c753cd2d7bd6560c77118597410c4d2e87" +checksum = "21f182278bf2d2bcb3c88b1b08a37df029d71ce3d3ae26168e3c653b213b99d4" dependencies = [ "proc-macro2", "quote", @@ -10033,7 +9927,7 @@ checksum = "728a70f3dbaf5bab7f0c4b1ac8d7ae5ea60a4b5549c8a5914361c99147a709d2" dependencies = [ "proc-macro2", "quote", - "syn 2.0.111", + "syn 2.0.112", ] [[package]] @@ -10132,7 +10026,7 @@ dependencies = [ "cfg-if", "proc-macro2", "quote", - "syn 2.0.111", + "syn 2.0.112", ] [[package]] @@ -10143,7 +10037,7 @@ checksum = "5c89e72a01ed4c579669add59014b9a524d609c0c88c6a585ce37485879f6ffb" dependencies = [ "proc-macro2", "quote", - "syn 2.0.111", + "syn 2.0.112", "test-case-core", ] @@ -10173,7 +10067,7 @@ checksum = "4fee6c4efc90059e10f81e6d42c60a18f76588c3d74cb83a0b242a2b6c7504c1" dependencies = [ "proc-macro2", "quote", - "syn 2.0.111", + "syn 2.0.112", ] [[package]] @@ -10184,7 +10078,7 @@ checksum = "3ff15c8ecd7de3849db632e14d18d2571fa09dfc5ed93479bc4485c7a517c913" dependencies = [ "proc-macro2", "quote", - "syn 2.0.111", + "syn 2.0.112", ] [[package]] @@ -10333,7 +10227,7 @@ checksum = "2d2e76690929402faae40aebdda620a2c0e25dd6d3b9afe48867dfd95991f4bd" dependencies = [ "proc-macro2", "quote", - "syn 2.0.111", + "syn 2.0.112", ] [[package]] @@ -10348,7 +10242,7 @@ dependencies = [ "parking_lot", "pin-project-lite", "signal-hook-registry", - "socket2 0.6.1", + "socket2", "tokio-macros", "windows-sys 0.61.2", ] @@ -10361,17 +10255,7 @@ checksum = "af407857209536a95c8e56f8231ef2c2e2aff839b22e07a1ffcbc617e9db9fa5" dependencies = [ "proc-macro2", "quote", - "syn 2.0.111", -] - -[[package]] -name = "tokio-rustls" -version = "0.24.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c28327cf380ac148141087fbfb9de9d7bd4e84ab5d2c28fbc911d753de8a7081" -dependencies = [ - "rustls 0.21.12", - "tokio", + "syn 2.0.112", ] [[package]] @@ -10380,7 +10264,7 @@ version = "0.26.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1729aa945f29d91ba541258c8df89027d5792d85a8841fb65e8bf0f4ede4ef61" dependencies = [ - "rustls 0.23.35", + "rustls", "tokio", ] @@ -10504,20 +10388,20 @@ dependencies = [ "base64", "bytes", "flate2", - "h2 0.4.12", + "h2", "http 1.4.0", "http-body 1.0.1", "http-body-util", - "hyper 1.8.1", + "hyper", "hyper-timeout", "hyper-util", "percent-encoding", "pin-project", "rustls-native-certs", - "socket2 0.6.1", + "socket2", "sync_wrapper", "tokio", - "tokio-rustls 0.26.4", + "tokio-rustls", "tokio-stream", "tower", "tower-layer", @@ -10534,7 +10418,7 @@ dependencies = [ "prettyplease", "proc-macro2", "quote", - "syn 2.0.111", + "syn 2.0.112", ] [[package]] @@ -10559,7 +10443,7 @@ dependencies = [ "prost-build", "prost-types", "quote", - "syn 2.0.111", + "syn 2.0.112", "tempfile", "tonic-build", ] @@ -10652,7 +10536,7 @@ checksum = "7490cfa5ec963746568740651ac6781f701c9c5ea257c58e057f3ba8cf69e8da" dependencies = [ "proc-macro2", "quote", - "syn 2.0.111", + "syn 2.0.112", ] [[package]] @@ -10910,7 +10794,7 @@ checksum = "39d11901c36b3650df7acb0f9ebe624f35b5ac4e1922ecd3c57f444648429594" dependencies = [ "proc-macro2", "quote", - "syn 2.0.111", + "syn 2.0.112", ] [[package]] @@ -11072,7 +10956,7 @@ dependencies = [ "bumpalo", "proc-macro2", "quote", - "syn 2.0.111", + "syn 2.0.112", "wasm-bindgen-shared", ] @@ -11278,7 +11162,7 @@ checksum = "053e2e040ab57b9dc951b72c264860db7eb3b0200ba345b4e4c3b14f67855ddf" dependencies = [ "proc-macro2", "quote", - "syn 2.0.111", + "syn 2.0.112", ] [[package]] @@ -11289,7 +11173,7 @@ checksum = "3f316c4a2570ba26bbec722032c4099d8c8bc095efccdc15688708623367e358" dependencies = [ "proc-macro2", "quote", - "syn 2.0.111", + "syn 2.0.112", ] [[package]] @@ -11578,7 +11462,7 @@ dependencies = [ "darling 0.20.11", "proc-macro2", "quote", - "syn 2.0.111", + "syn 2.0.112", ] [[package]] @@ -11687,7 +11571,7 @@ checksum = "b659052874eb698efe5b9e8cf382204678a0086ebf46982b79d6ca3182927e5d" dependencies = [ "proc-macro2", "quote", - "syn 2.0.111", + "syn 2.0.112", "synstructure 0.13.2", ] @@ -11708,7 +11592,7 @@ checksum = "d8a8d209fdf45cf5138cbb5a506f6b52522a25afccc534d1475dad8e31105c6a" dependencies = [ "proc-macro2", "quote", - "syn 2.0.111", + "syn 2.0.112", ] [[package]] @@ -11728,7 +11612,7 @@ checksum = "d71e5d6e06ab090c67b5e44993ec16b72dcbaabc526db883a360057678b48502" dependencies = [ "proc-macro2", "quote", - "syn 2.0.111", + "syn 2.0.112", "synstructure 0.13.2", ] @@ -11749,7 +11633,7 @@ checksum = "85a5b4158499876c763cb03bc4e49185d3cccbabb15b33c627f7884f43db852e" dependencies = [ "proc-macro2", "quote", - "syn 2.0.111", + "syn 2.0.112", ] [[package]] @@ -11782,7 +11666,7 @@ checksum = "eadce39539ca5cb3985590102671f2567e659fca9666581ad3411d59207951f3" dependencies = [ "proc-macro2", "quote", - "syn 2.0.111", + "syn 2.0.112", ] [[package]] @@ -11821,9 +11705,9 @@ checksum = "40990edd51aae2c2b6907af74ffb635029d5788228222c4bb811e9351c0caad3" [[package]] name = "zmij" -version = "1.0.3" +version = "1.0.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e9747e91771f56fd7893e1164abd78febd14a670ceec257caad15e051de35f06" +checksum = "aac060176f7020d62c3bcc1cdbcec619d54f48b07ad1963a3f80ce7a0c17755f" [[package]] name = "zopfli" diff --git a/Cargo.toml b/Cargo.toml index 7cf2bacc..d3cc3f2f 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -50,7 +50,7 @@ resolver = "2" edition = "2024" license = "Apache-2.0" repository = "https://github.com/rustfs/rustfs" -rust-version = "1.85" +rust-version = "1.88" version = "0.0.5" homepage = "https://rustfs.com" description = "RustFS is a high-performance distributed object storage software built using Rust, one of the most popular languages worldwide. " @@ -100,21 +100,21 @@ async-compression = { version = "0.4.19" } async-recursion = "1.1.1" async-trait = "0.1.89" axum = "0.8.8" -axum-server = { version = "0.8.0", features = ["tls-rustls-no-provider"], default-features = false } +axum-server = { version = "0.8.0", features = ["tls-rustls"], default-features = false } futures = "0.3.31" futures-core = "0.3.31" futures-util = "0.3.31" pollster = "0.4.0" hyper = { version = "1.8.1", features = ["http2", "http1", "server"] } -hyper-rustls = { version = "0.27.7", default-features = false, features = ["native-tokio", "http1", "tls12", "logging", "http2", "ring", "webpki-roots"] } +hyper-rustls = { version = "0.27.7", default-features = false, features = ["native-tokio", "http1", "tls12", "logging", "http2", "aws-lc-rs", "webpki-roots"] } hyper-util = { version = "0.1.19", features = ["tokio", "server-auto", "server-graceful"] } http = "1.4.0" http-body = "1.0.1" http-body-util = "0.1.3" -reqwest = { version = "0.12.28", default-features = false, features = ["rustls-tls-webpki-roots", "charset", "http2", "system-proxy", "stream", "json", "blocking"] } +reqwest = { version = "0.12.28", default-features = false, features = ["rustls-tls-no-provider", "charset", "http2", "system-proxy", "stream", "json", "blocking"] } socket2 = "0.6.1" tokio = { version = "1.48.0", features = ["fs", "rt-multi-thread"] } -tokio-rustls = { version = "0.26.4", default-features = false, features = ["logging", "tls12", "ring"] } +tokio-rustls = { version = "0.26.4", default-features = false, features = ["logging", "tls12", "aws-lc-rs"] } tokio-stream = { version = "0.1.17" } tokio-test = "0.4.4" tokio-util = { version = "0.7.17", features = ["io", "compat"] } @@ -150,7 +150,7 @@ hmac = { version = "0.13.0-rc.3" } jsonwebtoken = { version = "10.2.0", features = ["rust_crypto"] } pbkdf2 = "0.13.0-rc.5" rsa = { version = "0.10.0-rc.10" } -rustls = { version = "0.23.35", features = ["ring", "logging", "std", "tls12"], default-features = false } +rustls = { version = "0.23.35" } rustls-pemfile = "2.2.0" rustls-pki-types = "1.13.2" sha1 = "0.11.0-rc.3" @@ -171,7 +171,7 @@ atoi = "2.0.0" atomic_enum = "0.3.0" aws-config = { version = "1.8.12" } aws-credential-types = { version = "1.2.11" } -aws-sdk-s3 = { version = "1.119.0", default-features = false, features = ["sigv4a", "rustls", "rt-tokio"] } +aws-sdk-s3 = { version = "1.119.0", default-features = false, features = ["sigv4a", "default-https-client", "rt-tokio"] } aws-smithy-types = { version = "1.3.5" } base64 = "0.22.1" base64-simd = "0.8.0" diff --git a/crates/ahm/src/heal/erasure_healer.rs b/crates/ahm/src/heal/erasure_healer.rs index 209a0be3..25c8fef6 100644 --- a/crates/ahm/src/heal/erasure_healer.rs +++ b/crates/ahm/src/heal/erasure_healer.rs @@ -348,7 +348,7 @@ impl ErasureSetHealer { } // save checkpoint periodically - if global_obj_idx % 100 == 0 { + if global_obj_idx.is_multiple_of(100) { checkpoint_manager .update_position(bucket_index, *current_object_index) .await?; diff --git a/crates/ahm/src/heal/manager.rs b/crates/ahm/src/heal/manager.rs index 4e287e38..8a1843e2 100644 --- a/crates/ahm/src/heal/manager.rs +++ b/crates/ahm/src/heal/manager.rs @@ -492,12 +492,11 @@ impl HealManager { for (_, disk_opt) in GLOBAL_LOCAL_DISK_MAP.read().await.iter() { if let Some(disk) = disk_opt { // detect unformatted disk via get_disk_id() - if let Err(err) = disk.get_disk_id().await { - if err == DiskError::UnformattedDisk { + if let Err(err) = disk.get_disk_id().await + && err == DiskError::UnformattedDisk { endpoints.push(disk.endpoint()); continue; } - } } } diff --git a/crates/ahm/src/heal/resume.rs b/crates/ahm/src/heal/resume.rs index 39772785..93bf753f 100644 --- a/crates/ahm/src/heal/resume.rs +++ b/crates/ahm/src/heal/resume.rs @@ -541,10 +541,10 @@ impl ResumeUtils { for entry in entries { if entry.ends_with(&format!("_{RESUME_STATE_FILE}")) { // Extract task ID from filename: {task_id}_ahm_resume_state.json - if let Some(task_id) = entry.strip_suffix(&format!("_{RESUME_STATE_FILE}")) { - if !task_id.is_empty() { - task_ids.push(task_id.to_string()); - } + if let Some(task_id) = entry.strip_suffix(&format!("_{RESUME_STATE_FILE}")) + && !task_id.is_empty() + { + task_ids.push(task_id.to_string()); } } } diff --git a/crates/ahm/src/scanner/checkpoint.rs b/crates/ahm/src/scanner/checkpoint.rs index 3304791f..276fb87a 100644 --- a/crates/ahm/src/scanner/checkpoint.rs +++ b/crates/ahm/src/scanner/checkpoint.rs @@ -83,10 +83,10 @@ pub struct CheckpointManager { impl CheckpointManager { pub fn new(node_id: &str, data_dir: &Path) -> Self { - if !data_dir.exists() { - if let Err(e) = std::fs::create_dir_all(data_dir) { - error!("create data dir failed {:?}: {}", data_dir, e); - } + if !data_dir.exists() + && let Err(e) = std::fs::create_dir_all(data_dir) + { + error!("create data dir failed {:?}: {}", data_dir, e); } let checkpoint_file = data_dir.join(format!("scanner_checkpoint_{node_id}.json")); diff --git a/crates/ahm/src/scanner/data_scanner.rs b/crates/ahm/src/scanner/data_scanner.rs index eaf85255..ba3f2cad 100644 --- a/crates/ahm/src/scanner/data_scanner.rs +++ b/crates/ahm/src/scanner/data_scanner.rs @@ -401,10 +401,10 @@ impl Scanner { let mut latest_update: Option = None; for snapshot in &outcome.snapshots { - if let Some(update) = snapshot.last_update { - if latest_update.is_none_or(|current| update > current) { - latest_update = Some(update); - } + if let Some(update) = snapshot.last_update + && latest_update.is_none_or(|current| update > current) + { + latest_update = Some(update); } aggregated.objects_total_count = aggregated.objects_total_count.saturating_add(snapshot.objects_total_count); @@ -527,28 +527,20 @@ impl Scanner { let (disks, _) = set_disks.get_online_disks_with_healing(false).await; if let Some(disk) = disks.first() { let bucket_path = disk.path().join(bucket_name); - if bucket_path.exists() { - if let Ok(entries) = std::fs::read_dir(&bucket_path) { - for entry in entries.flatten() { - if let Ok(file_type) = entry.file_type() { - if file_type.is_dir() { - if let Some(object_name) = entry.file_name().to_str() { - if !object_name.starts_with('.') { - debug!("Deep scanning object: {}/{}", bucket_name, object_name); - if let Err(e) = self.verify_object_integrity(bucket_name, object_name).await { - warn!( - "Object integrity verification failed for {}/{}: {}", - bucket_name, object_name, e - ); - } else { - debug!( - "Object integrity verification passed for {}/{}", - bucket_name, object_name - ); - } - } - } - } + if bucket_path.exists() + && let Ok(entries) = std::fs::read_dir(&bucket_path) + { + for entry in entries.flatten() { + if let Ok(file_type) = entry.file_type() + && file_type.is_dir() + && let Some(object_name) = entry.file_name().to_str() + && !object_name.starts_with('.') + { + debug!("Deep scanning object: {}/{}", bucket_name, object_name); + if let Err(e) = self.verify_object_integrity(bucket_name, object_name).await { + warn!("Object integrity verification failed for {}/{}: {}", bucket_name, object_name, e); + } else { + debug!("Object integrity verification passed for {}/{}", bucket_name, object_name); } } } @@ -859,10 +851,10 @@ impl Scanner { // Phase 2: Minimal EC verification for critical objects only // Note: The main scanning is now handled by NodeScanner in the background - if let Some(ecstore) = rustfs_ecstore::new_object_layer_fn() { - if let Err(e) = self.minimal_ec_verification(&ecstore).await { - error!("Minimal EC verification failed: {}", e); - } + if let Some(ecstore) = rustfs_ecstore::new_object_layer_fn() + && let Err(e) = self.minimal_ec_verification(&ecstore).await + { + error!("Minimal EC verification failed: {}", e); } // Update scan duration @@ -950,13 +942,12 @@ impl Scanner { } // If there is still no data, try backend before persisting zeros - if data_usage.buckets_usage.is_empty() { - if let Ok(existing) = rustfs_ecstore::data_usage::load_data_usage_from_backend(ecstore.clone()).await { - if !existing.buckets_usage.is_empty() { - info!("Using existing backend data usage during fallback backoff"); - data_usage = existing; - } - } + if data_usage.buckets_usage.is_empty() + && let Ok(existing) = rustfs_ecstore::data_usage::load_data_usage_from_backend(ecstore.clone()).await + && !existing.buckets_usage.is_empty() + { + info!("Using existing backend data usage during fallback backoff"); + data_usage = existing; } // Avoid overwriting valid backend stats with zeros when fallback is throttled @@ -1721,36 +1712,34 @@ impl Scanner { // check disk status, if offline, submit erasure set heal task if !metrics.is_online { let enable_healing = self.config.read().await.enable_healing; - if enable_healing { - if let Some(heal_manager) = &self.heal_manager { - // Get bucket list for erasure set healing - let buckets = match rustfs_ecstore::new_object_layer_fn() { - Some(ecstore) => match ecstore.list_bucket(&ecstore::store_api::BucketOptions::default()).await { - Ok(buckets) => buckets.iter().map(|b| b.name.clone()).collect::>(), - Err(e) => { - error!("Failed to get bucket list for disk healing: {}", e); - return Err(Error::Storage(e)); - } - }, - None => { - error!("No ECStore available for getting bucket list"); - return Err(Error::Storage(ecstore::error::StorageError::other("No ECStore available"))); - } - }; - - let set_disk_id = format!("pool_{}_set_{}", disk.endpoint().pool_idx, disk.endpoint().set_idx); - let req = HealRequest::new( - crate::heal::task::HealType::ErasureSet { buckets, set_disk_id }, - crate::heal::task::HealOptions::default(), - crate::heal::task::HealPriority::High, - ); - match heal_manager.submit_heal_request(req).await { - Ok(task_id) => { - warn!("disk offline, submit erasure set heal task: {} {}", task_id, disk_path); - } + if enable_healing && let Some(heal_manager) = &self.heal_manager { + // Get bucket list for erasure set healing + let buckets = match rustfs_ecstore::new_object_layer_fn() { + Some(ecstore) => match ecstore.list_bucket(&ecstore::store_api::BucketOptions::default()).await { + Ok(buckets) => buckets.iter().map(|b| b.name.clone()).collect::>(), Err(e) => { - error!("disk offline, submit erasure set heal task failed: {} {}", disk_path, e); + error!("Failed to get bucket list for disk healing: {}", e); + return Err(Error::Storage(e)); } + }, + None => { + error!("No ECStore available for getting bucket list"); + return Err(Error::Storage(ecstore::error::StorageError::other("No ECStore available"))); + } + }; + + let set_disk_id = format!("pool_{}_set_{}", disk.endpoint().pool_idx, disk.endpoint().set_idx); + let req = HealRequest::new( + crate::heal::task::HealType::ErasureSet { buckets, set_disk_id }, + crate::heal::task::HealOptions::default(), + crate::heal::task::HealPriority::High, + ); + match heal_manager.submit_heal_request(req).await { + Ok(task_id) => { + warn!("disk offline, submit erasure set heal task: {} {}", task_id, disk_path); + } + Err(e) => { + error!("disk offline, submit erasure set heal task failed: {} {}", disk_path, e); } } } @@ -1778,36 +1767,34 @@ impl Scanner { // disk access failed, submit erasure set heal task let enable_healing = self.config.read().await.enable_healing; - if enable_healing { - if let Some(heal_manager) = &self.heal_manager { - // Get bucket list for erasure set healing - let buckets = match rustfs_ecstore::new_object_layer_fn() { - Some(ecstore) => match ecstore.list_bucket(&ecstore::store_api::BucketOptions::default()).await { - Ok(buckets) => buckets.iter().map(|b| b.name.clone()).collect::>(), - Err(e) => { - error!("Failed to get bucket list for disk healing: {}", e); - return Err(Error::Storage(e)); - } - }, - None => { - error!("No ECStore available for getting bucket list"); - return Err(Error::Storage(ecstore::error::StorageError::other("No ECStore available"))); + if enable_healing && let Some(heal_manager) = &self.heal_manager { + // Get bucket list for erasure set healing + let buckets = match rustfs_ecstore::new_object_layer_fn() { + Some(ecstore) => match ecstore.list_bucket(&ecstore::store_api::BucketOptions::default()).await { + Ok(buckets) => buckets.iter().map(|b| b.name.clone()).collect::>(), + Err(e) => { + error!("Failed to get bucket list for disk healing: {}", e); + return Err(Error::Storage(e)); } - }; + }, + None => { + error!("No ECStore available for getting bucket list"); + return Err(Error::Storage(ecstore::error::StorageError::other("No ECStore available"))); + } + }; - let set_disk_id = format!("pool_{}_set_{}", disk.endpoint().pool_idx, disk.endpoint().set_idx); - let req = HealRequest::new( - crate::heal::task::HealType::ErasureSet { buckets, set_disk_id }, - crate::heal::task::HealOptions::default(), - crate::heal::task::HealPriority::Urgent, - ); - match heal_manager.submit_heal_request(req).await { - Ok(task_id) => { - warn!("disk access failed, submit erasure set heal task: {} {}", task_id, disk_path); - } - Err(heal_err) => { - error!("disk access failed, submit erasure set heal task failed: {} {}", disk_path, heal_err); - } + let set_disk_id = format!("pool_{}_set_{}", disk.endpoint().pool_idx, disk.endpoint().set_idx); + let req = HealRequest::new( + crate::heal::task::HealType::ErasureSet { buckets, set_disk_id }, + crate::heal::task::HealOptions::default(), + crate::heal::task::HealPriority::Urgent, + ); + match heal_manager.submit_heal_request(req).await { + Ok(task_id) => { + warn!("disk access failed, submit erasure set heal task: {} {}", task_id, disk_path); + } + Err(heal_err) => { + error!("disk access failed, submit erasure set heal task failed: {} {}", disk_path, heal_err); } } } @@ -1820,11 +1807,11 @@ impl Scanner { let mut disk_objects = HashMap::new(); for volume in volumes { // check cancel token - if let Some(cancel_token) = get_ahm_services_cancel_token() { - if cancel_token.is_cancelled() { - info!("Cancellation requested, stopping disk scan"); - break; - } + if let Some(cancel_token) = get_ahm_services_cancel_token() + && cancel_token.is_cancelled() + { + info!("Cancellation requested, stopping disk scan"); + break; } match self.scan_volume(disk, &volume.name).await { @@ -1955,104 +1942,96 @@ impl Scanner { // object metadata damaged, submit metadata heal task let enable_healing = self.config.read().await.enable_healing; - if enable_healing { - if let Some(heal_manager) = &self.heal_manager { - let req = HealRequest::metadata(bucket.to_string(), entry.name.clone()); - match heal_manager.submit_heal_request(req).await { - Ok(task_id) => { - warn!( - "object metadata damaged, submit heal task: {} {} / {}", - task_id, bucket, entry.name - ); - } - Err(e) => { - error!( - "object metadata damaged, submit heal task failed: {} / {} {}", - bucket, entry.name, e - ); - } + if enable_healing && let Some(heal_manager) = &self.heal_manager { + let req = HealRequest::metadata(bucket.to_string(), entry.name.clone()); + match heal_manager.submit_heal_request(req).await { + Ok(task_id) => { + warn!("object metadata damaged, submit heal task: {} {} / {}", task_id, bucket, entry.name); + } + Err(e) => { + error!("object metadata damaged, submit heal task failed: {} / {} {}", bucket, entry.name, e); } } } } else { // Apply lifecycle actions - if let Some(lifecycle_config) = &lifecycle_config { - if disk.is_local() { - let vcfg = BucketVersioningSys::get(bucket).await.ok(); + if let Some(lifecycle_config) = &lifecycle_config + && disk.is_local() + { + let vcfg = BucketVersioningSys::get(bucket).await.ok(); - let mut scanner_item = ScannerItem { - bucket: bucket.to_string(), - object_name: entry.name.clone(), - lifecycle: Some(lifecycle_config.clone()), - versioning: versioning_config.clone(), - }; - //ScannerItem::new(bucket.to_string(), Some(lifecycle_config.clone()), versioning_config.clone()); - let fivs = match entry.clone().file_info_versions(&scanner_item.bucket) { - Ok(fivs) => fivs, - Err(_err) => { - stop_fn(); - return Err(Error::other("skip this file")); - } - }; - let mut size_s = SizeSummary::default(); - let obj_infos = match scanner_item.apply_versions_actions(&fivs.versions).await { - Ok(obj_infos) => obj_infos, - Err(_err) => { - stop_fn(); - return Err(Error::other("skip this file")); - } - }; + let mut scanner_item = ScannerItem { + bucket: bucket.to_string(), + object_name: entry.name.clone(), + lifecycle: Some(lifecycle_config.clone()), + versioning: versioning_config.clone(), + }; + //ScannerItem::new(bucket.to_string(), Some(lifecycle_config.clone()), versioning_config.clone()); + let fivs = match entry.clone().file_info_versions(&scanner_item.bucket) { + Ok(fivs) => fivs, + Err(_err) => { + stop_fn(); + return Err(Error::other("skip this file")); + } + }; + let mut size_s = SizeSummary::default(); + let obj_infos = match scanner_item.apply_versions_actions(&fivs.versions).await { + Ok(obj_infos) => obj_infos, + Err(_err) => { + stop_fn(); + return Err(Error::other("skip this file")); + } + }; - let versioned = if let Some(vcfg) = vcfg.as_ref() { - vcfg.versioned(&scanner_item.object_name) - } else { - false - }; + let versioned = if let Some(vcfg) = vcfg.as_ref() { + vcfg.versioned(&scanner_item.object_name) + } else { + false + }; - #[allow(unused_assignments)] - let mut obj_deleted = false; - for info in obj_infos.iter() { - let sz: i64; - (obj_deleted, sz) = scanner_item.apply_actions(info, &mut size_s).await; + #[allow(unused_assignments)] + let mut obj_deleted = false; + for info in obj_infos.iter() { + let sz: i64; + (obj_deleted, sz) = scanner_item.apply_actions(info, &mut size_s).await; - if obj_deleted { - break; - } - - let actual_sz = match info.get_actual_size() { - Ok(size) => size, - Err(_) => continue, - }; - - if info.delete_marker { - size_s.delete_markers += 1; - } - - if info.version_id.is_some() && sz == actual_sz { - size_s.versions += 1; - } - - size_s.total_size += sz as usize; - - if info.delete_marker { - continue; - } + if obj_deleted { + break; } - for free_version in fivs.free_versions.iter() { - let _obj_info = rustfs_ecstore::store_api::ObjectInfo::from_file_info( - free_version, - &scanner_item.bucket, - &scanner_item.object_name, - versioned, - ); + let actual_sz = match info.get_actual_size() { + Ok(size) => size, + Err(_) => continue, + }; + + if info.delete_marker { + size_s.delete_markers += 1; } - // todo: global trace - /*if obj_deleted { - return Err(Error::other(ERR_IGNORE_FILE_CONTRIB).into()); - }*/ + if info.version_id.is_some() && sz == actual_sz { + size_s.versions += 1; + } + + size_s.total_size += sz as usize; + + if info.delete_marker { + continue; + } } + + for free_version in fivs.free_versions.iter() { + let _obj_info = rustfs_ecstore::store_api::ObjectInfo::from_file_info( + free_version, + &scanner_item.bucket, + &scanner_item.object_name, + versioned, + ); + } + + // todo: global trace + /*if obj_deleted { + return Err(Error::other(ERR_IGNORE_FILE_CONTRIB).into()); + }*/ } // Store object metadata for later analysis @@ -2064,22 +2043,17 @@ impl Scanner { // object metadata parse failed, submit metadata heal task let enable_healing = self.config.read().await.enable_healing; - if enable_healing { - if let Some(heal_manager) = &self.heal_manager { - let req = HealRequest::metadata(bucket.to_string(), entry.name.clone()); - match heal_manager.submit_heal_request(req).await { - Ok(task_id) => { - warn!( - "object metadata parse failed, submit heal task: {} {} / {}", - task_id, bucket, entry.name - ); - } - Err(e) => { - error!( - "object metadata parse failed, submit heal task failed: {} / {} {}", - bucket, entry.name, e - ); - } + if enable_healing && let Some(heal_manager) = &self.heal_manager { + let req = HealRequest::metadata(bucket.to_string(), entry.name.clone()); + match heal_manager.submit_heal_request(req).await { + Ok(task_id) => { + warn!("object metadata parse failed, submit heal task: {} {} / {}", task_id, bucket, entry.name); + } + Err(e) => { + error!( + "object metadata parse failed, submit heal task failed: {} / {} {}", + bucket, entry.name, e + ); } } } @@ -2190,17 +2164,14 @@ impl Scanner { // the delete marker, but we keep it conservative here. let mut has_latest_delete_marker = false; for &disk_idx in locations { - if let Some(bucket_map) = all_disk_objects.get(disk_idx) { - if let Some(file_map) = bucket_map.get(bucket) { - if let Some(fm) = file_map.get(object_name) { - if let Some(first_ver) = fm.versions.first() { - if first_ver.header.version_type == VersionType::Delete { - has_latest_delete_marker = true; - break; - } - } - } - } + if let Some(bucket_map) = all_disk_objects.get(disk_idx) + && let Some(file_map) = bucket_map.get(bucket) + && let Some(fm) = file_map.get(object_name) + && let Some(first_ver) = fm.versions.first() + && first_ver.header.version_type == VersionType::Delete + { + has_latest_delete_marker = true; + break; } } if has_latest_delete_marker { @@ -2248,28 +2219,26 @@ impl Scanner { // submit heal task let enable_healing = self.config.read().await.enable_healing; - if enable_healing { - if let Some(heal_manager) = &self.heal_manager { - use crate::heal::{HealPriority, HealRequest}; - let req = HealRequest::new( - crate::heal::HealType::Object { - bucket: bucket.clone(), - object: object_name.clone(), - version_id: None, - }, - crate::heal::HealOptions::default(), - HealPriority::High, - ); - match heal_manager.submit_heal_request(req).await { - Ok(task_id) => { - warn!( - "object missing, submit heal task: {} {} / {} (missing disks: {:?})", - task_id, bucket, object_name, missing_disks - ); - } - Err(e) => { - error!("object missing, submit heal task failed: {} / {} {}", bucket, object_name, e); - } + if enable_healing && let Some(heal_manager) = &self.heal_manager { + use crate::heal::{HealPriority, HealRequest}; + let req = HealRequest::new( + crate::heal::HealType::Object { + bucket: bucket.clone(), + object: object_name.clone(), + version_id: None, + }, + crate::heal::HealOptions::default(), + HealPriority::High, + ); + match heal_manager.submit_heal_request(req).await { + Ok(task_id) => { + warn!( + "object missing, submit heal task: {} {} / {} (missing disks: {:?})", + task_id, bucket, object_name, missing_disks + ); + } + Err(e) => { + error!("object missing, submit heal task failed: {} / {} {}", bucket, object_name, e); } } } @@ -2277,11 +2246,11 @@ impl Scanner { // Step 3: Deep scan EC verification let config = self.config.read().await; - if config.scan_mode == ScanMode::Deep { - if let Err(e) = self.verify_object_integrity(bucket, object_name).await { - objects_with_ec_issues += 1; - warn!("Object integrity verification failed for object {}/{}: {}", bucket, object_name, e); - } + if config.scan_mode == ScanMode::Deep + && let Err(e) = self.verify_object_integrity(bucket, object_name).await + { + objects_with_ec_issues += 1; + warn!("Object integrity verification failed for object {}/{}: {}", bucket, object_name, e); } } } @@ -2293,10 +2262,10 @@ impl Scanner { // Step 4: Collect data usage statistics if enabled let config = self.config.read().await; - if config.enable_data_usage_stats { - if let Err(e) = self.collect_data_usage_statistics(all_disk_objects).await { - error!("Failed to collect data usage statistics: {}", e); - } + if config.enable_data_usage_stats + && let Err(e) = self.collect_data_usage_statistics(all_disk_objects).await + { + error!("Failed to collect data usage statistics: {}", e); } drop(config); @@ -2526,11 +2495,11 @@ impl Scanner { info!("Starting legacy scan loop for backward compatibility"); loop { - if let Some(token) = get_ahm_services_cancel_token() { - if token.is_cancelled() { - info!("Cancellation requested, exiting legacy scan loop"); - break; - } + if let Some(token) = get_ahm_services_cancel_token() + && token.is_cancelled() + { + info!("Cancellation requested, exiting legacy scan loop"); + break; } let (enable_data_usage_stats, scan_interval) = { @@ -2538,10 +2507,8 @@ impl Scanner { (config.enable_data_usage_stats, config.scan_interval) }; - if enable_data_usage_stats { - if let Err(e) = self.collect_and_persist_data_usage().await { - warn!("Background data usage collection failed: {}", e); - } + if enable_data_usage_stats && let Err(e) = self.collect_and_persist_data_usage().await { + warn!("Background data usage collection failed: {}", e); } // Update local stats in aggregator after latest scan @@ -2656,10 +2623,10 @@ mod tests { // create temp dir as 4 disks let test_base_dir = test_dir.unwrap_or("/tmp/rustfs_ahm_test"); let temp_dir = std::path::PathBuf::from(test_base_dir); - if temp_dir.exists() { - if let Err(e) = fs::remove_dir_all(&temp_dir) { - panic!("Failed to remove test directory: {e}"); - } + if temp_dir.exists() + && let Err(e) = fs::remove_dir_all(&temp_dir) + { + panic!("Failed to remove test directory: {e}"); } if let Err(e) = fs::create_dir_all(&temp_dir) { panic!("Failed to create test directory: {e}"); diff --git a/crates/ahm/src/scanner/local_scan/mod.rs b/crates/ahm/src/scanner/local_scan/mod.rs index 39387c24..24a5a260 100644 --- a/crates/ahm/src/scanner/local_scan/mod.rs +++ b/crates/ahm/src/scanner/local_scan/mod.rs @@ -305,10 +305,10 @@ fn compute_object_usage(bucket: &str, object: &str, file_meta: &FileMeta) -> Res has_live_object = true; versions_count = versions_count.saturating_add(1); - if latest_file_info.is_none() { - if let Ok(info) = file_meta.into_fileinfo(bucket, object, "", false, false) { - latest_file_info = Some(info); - } + if latest_file_info.is_none() + && let Ok(info) = file_meta.into_fileinfo(bucket, object, "", false, false) + { + latest_file_info = Some(info); } } } diff --git a/crates/ahm/src/scanner/local_stats.rs b/crates/ahm/src/scanner/local_stats.rs index 5529a824..0fe2f6e2 100644 --- a/crates/ahm/src/scanner/local_stats.rs +++ b/crates/ahm/src/scanner/local_stats.rs @@ -112,10 +112,10 @@ impl LocalStatsManager { /// create new local stats manager pub fn new(node_id: &str, data_dir: &Path) -> Self { // ensure data directory exists - if !data_dir.exists() { - if let Err(e) = std::fs::create_dir_all(data_dir) { - error!("create stats data directory failed {:?}: {}", data_dir, e); - } + if !data_dir.exists() + && let Err(e) = std::fs::create_dir_all(data_dir) + { + error!("create stats data directory failed {:?}: {}", data_dir, e); } let stats_file = data_dir.join(format!("scanner_stats_{node_id}.json")); diff --git a/crates/ahm/src/scanner/node_scanner.rs b/crates/ahm/src/scanner/node_scanner.rs index 5f3d4d43..36e2d186 100644 --- a/crates/ahm/src/scanner/node_scanner.rs +++ b/crates/ahm/src/scanner/node_scanner.rs @@ -436,10 +436,10 @@ impl NodeScanner { /// create a new node scanner pub fn new(node_id: String, config: NodeScannerConfig) -> Self { // Ensure data directory exists - if !config.data_dir.exists() { - if let Err(e) = std::fs::create_dir_all(&config.data_dir) { - error!("create data directory failed {:?}: {}", config.data_dir, e); - } + if !config.data_dir.exists() + && let Err(e) = std::fs::create_dir_all(&config.data_dir) + { + error!("create data directory failed {:?}: {}", config.data_dir, e); } let stats_manager = Arc::new(LocalStatsManager::new(&node_id, &config.data_dir)); diff --git a/crates/ahm/src/scanner/stats_aggregator.rs b/crates/ahm/src/scanner/stats_aggregator.rs index 0c019c3a..47297a03 100644 --- a/crates/ahm/src/scanner/stats_aggregator.rs +++ b/crates/ahm/src/scanner/stats_aggregator.rs @@ -327,16 +327,16 @@ impl DecentralizedStatsAggregator { ); // Check cache validity if timestamp is not initial value (UNIX_EPOCH) - if cache_timestamp != SystemTime::UNIX_EPOCH { - if let Ok(elapsed) = now.duration_since(cache_timestamp) { - if elapsed < cache_ttl { - if let Some(cached) = self.cached_stats.read().await.as_ref() { - debug!("Returning cached aggregated stats, remaining TTL: {:?}", cache_ttl - elapsed); - return Ok(cached.clone()); - } - } else { - debug!("Cache expired: elapsed={:?} >= ttl={:?}", elapsed, cache_ttl); + if cache_timestamp != SystemTime::UNIX_EPOCH + && let Ok(elapsed) = now.duration_since(cache_timestamp) + { + if elapsed < cache_ttl { + if let Some(cached) = self.cached_stats.read().await.as_ref() { + debug!("Returning cached aggregated stats, remaining TTL: {:?}", cache_ttl - elapsed); + return Ok(cached.clone()); } + } else { + debug!("Cache expired: elapsed={:?} >= ttl={:?}", elapsed, cache_ttl); } } diff --git a/crates/ahm/tests/lifecycle_cache_test.rs b/crates/ahm/tests/lifecycle_cache_test.rs index 5748ed25..b7e8fb45 100644 --- a/crates/ahm/tests/lifecycle_cache_test.rs +++ b/crates/ahm/tests/lifecycle_cache_test.rs @@ -421,86 +421,86 @@ mod serial_tests { } }; - if let Some(lmdb_env) = GLOBAL_LMDB_ENV.get() { - if let Some(lmdb) = GLOBAL_LMDB_DB.get() { - let mut wtxn = lmdb_env.write_txn().unwrap(); + if let Some(lmdb_env) = GLOBAL_LMDB_ENV.get() + && let Some(lmdb) = GLOBAL_LMDB_DB.get() + { + let mut wtxn = lmdb_env.write_txn().unwrap(); - /*if let Ok((lc_config, _)) = rustfs_ecstore::bucket::metadata_sys::get_lifecycle_config(bucket_name.as_str()).await { - if let Ok(object_info) = ecstore - .get_object_info(bucket_name.as_str(), object_name, &rustfs_ecstore::store_api::ObjectOptions::default()) - .await - { - let event = rustfs_ecstore::bucket::lifecycle::bucket_lifecycle_ops::eval_action_from_lifecycle( - &lc_config, - None, - None, - &object_info, - ) - .await; - - rustfs_ecstore::bucket::lifecycle::bucket_lifecycle_ops::apply_expiry_on_non_transitioned_objects( - ecstore.clone(), - &object_info, - &event, - &rustfs_ecstore::bucket::lifecycle::bucket_lifecycle_audit::LcEventSrc::Scanner, - ) - .await; - - expired = wait_for_object_absence(&ecstore, bucket_name.as_str(), object_name, Duration::from_secs(2)).await; - } - }*/ - - for record in records { - if !record.usage.has_live_object { - continue; - } - - let object_info = convert_record_to_object_info(record); - println!("object_info2: {object_info:?}"); - let mod_time = object_info.mod_time.unwrap_or(OffsetDateTime::now_utc()); - let expiry_time = rustfs_ecstore::bucket::lifecycle::lifecycle::expected_expiry_time(mod_time, 1); - - let version_id = if let Some(version_id) = object_info.version_id { - version_id.to_string() - } else { - "zzzzzzzz-zzzz-zzzz-zzzz-zzzzzzzzzzzz".to_string() - }; - - lmdb.put( - &mut wtxn, - &expiry_time.unix_timestamp(), - &LifecycleContent { - ver_no: 0, - ver_id: version_id, - mod_time, - type_: LifecycleType::TransitionNoncurrent, - object_name: object_info.name, - }, + /*if let Ok((lc_config, _)) = rustfs_ecstore::bucket::metadata_sys::get_lifecycle_config(bucket_name.as_str()).await { + if let Ok(object_info) = ecstore + .get_object_info(bucket_name.as_str(), object_name, &rustfs_ecstore::store_api::ObjectOptions::default()) + .await + { + let event = rustfs_ecstore::bucket::lifecycle::bucket_lifecycle_ops::eval_action_from_lifecycle( + &lc_config, + None, + None, + &object_info, ) - .unwrap(); + .await; + + rustfs_ecstore::bucket::lifecycle::bucket_lifecycle_ops::apply_expiry_on_non_transitioned_objects( + ecstore.clone(), + &object_info, + &event, + &rustfs_ecstore::bucket::lifecycle::bucket_lifecycle_audit::LcEventSrc::Scanner, + ) + .await; + + expired = wait_for_object_absence(&ecstore, bucket_name.as_str(), object_name, Duration::from_secs(2)).await; + } + }*/ + + for record in records { + if !record.usage.has_live_object { + continue; } - wtxn.commit().unwrap(); + let object_info = convert_record_to_object_info(record); + println!("object_info2: {object_info:?}"); + let mod_time = object_info.mod_time.unwrap_or(OffsetDateTime::now_utc()); + let expiry_time = rustfs_ecstore::bucket::lifecycle::lifecycle::expected_expiry_time(mod_time, 1); - let mut wtxn = lmdb_env.write_txn().unwrap(); - let iter = lmdb.iter_mut(&mut wtxn).unwrap(); - //let _ = unsafe { iter.del_current().unwrap() }; - for row in iter { - if let Ok(ref elm) = row { - let LifecycleContent { - ver_no, - ver_id, - mod_time, - type_, - object_name, - } = &elm.1; - println!("cache row:{ver_no} {ver_id} {mod_time} {type_:?} {object_name}"); - } - println!("row:{row:?}"); - } - //drop(iter); - wtxn.commit().unwrap(); + let version_id = if let Some(version_id) = object_info.version_id { + version_id.to_string() + } else { + "zzzzzzzz-zzzz-zzzz-zzzz-zzzzzzzzzzzz".to_string() + }; + + lmdb.put( + &mut wtxn, + &expiry_time.unix_timestamp(), + &LifecycleContent { + ver_no: 0, + ver_id: version_id, + mod_time, + type_: LifecycleType::TransitionNoncurrent, + object_name: object_info.name, + }, + ) + .unwrap(); } + + wtxn.commit().unwrap(); + + let mut wtxn = lmdb_env.write_txn().unwrap(); + let iter = lmdb.iter_mut(&mut wtxn).unwrap(); + //let _ = unsafe { iter.del_current().unwrap() }; + for row in iter { + if let Ok(ref elm) = row { + let LifecycleContent { + ver_no, + ver_id, + mod_time, + type_, + object_name, + } = &elm.1; + println!("cache row:{ver_no} {ver_id} {mod_time} {type_:?} {object_name}"); + } + println!("row:{row:?}"); + } + //drop(iter); + wtxn.commit().unwrap(); } println!("Lifecycle cache test completed"); diff --git a/crates/ahm/tests/lifecycle_integration_test.rs b/crates/ahm/tests/lifecycle_integration_test.rs index f491531c..2050722c 100644 --- a/crates/ahm/tests/lifecycle_integration_test.rs +++ b/crates/ahm/tests/lifecycle_integration_test.rs @@ -415,29 +415,28 @@ mod serial_tests { .await; println!("Pending expiry tasks: {pending}"); - if let Ok((lc_config, _)) = rustfs_ecstore::bucket::metadata_sys::get_lifecycle_config(bucket_name.as_str()).await { - if let Ok(object_info) = ecstore + if let Ok((lc_config, _)) = rustfs_ecstore::bucket::metadata_sys::get_lifecycle_config(bucket_name.as_str()).await + && let Ok(object_info) = ecstore .get_object_info(bucket_name.as_str(), object_name, &rustfs_ecstore::store_api::ObjectOptions::default()) .await - { - let event = rustfs_ecstore::bucket::lifecycle::bucket_lifecycle_ops::eval_action_from_lifecycle( - &lc_config, - None, - None, - &object_info, - ) - .await; + { + let event = rustfs_ecstore::bucket::lifecycle::bucket_lifecycle_ops::eval_action_from_lifecycle( + &lc_config, + None, + None, + &object_info, + ) + .await; - rustfs_ecstore::bucket::lifecycle::bucket_lifecycle_ops::apply_expiry_on_non_transitioned_objects( - ecstore.clone(), - &object_info, - &event, - &rustfs_ecstore::bucket::lifecycle::bucket_lifecycle_audit::LcEventSrc::Scanner, - ) - .await; + rustfs_ecstore::bucket::lifecycle::bucket_lifecycle_ops::apply_expiry_on_non_transitioned_objects( + ecstore.clone(), + &object_info, + &event, + &rustfs_ecstore::bucket::lifecycle::bucket_lifecycle_audit::LcEventSrc::Scanner, + ) + .await; - expired = wait_for_object_absence(&ecstore, bucket_name.as_str(), object_name, Duration::from_secs(2)).await; - } + expired = wait_for_object_absence(&ecstore, bucket_name.as_str(), object_name, Duration::from_secs(2)).await; } if !expired { @@ -550,32 +549,31 @@ mod serial_tests { .await; println!("Pending expiry tasks: {pending}"); - if let Ok((lc_config, _)) = rustfs_ecstore::bucket::metadata_sys::get_lifecycle_config(bucket_name.as_str()).await { - if let Ok(obj_info) = ecstore + if let Ok((lc_config, _)) = rustfs_ecstore::bucket::metadata_sys::get_lifecycle_config(bucket_name.as_str()).await + && let Ok(obj_info) = ecstore .get_object_info(bucket_name.as_str(), object_name, &rustfs_ecstore::store_api::ObjectOptions::default()) .await - { - let event = rustfs_ecstore::bucket::lifecycle::bucket_lifecycle_ops::eval_action_from_lifecycle( - &lc_config, None, None, &obj_info, - ) - .await; + { + let event = rustfs_ecstore::bucket::lifecycle::bucket_lifecycle_ops::eval_action_from_lifecycle( + &lc_config, None, None, &obj_info, + ) + .await; - rustfs_ecstore::bucket::lifecycle::bucket_lifecycle_ops::apply_expiry_on_non_transitioned_objects( - ecstore.clone(), - &obj_info, - &event, - &rustfs_ecstore::bucket::lifecycle::bucket_lifecycle_audit::LcEventSrc::Scanner, - ) - .await; + rustfs_ecstore::bucket::lifecycle::bucket_lifecycle_ops::apply_expiry_on_non_transitioned_objects( + ecstore.clone(), + &obj_info, + &event, + &rustfs_ecstore::bucket::lifecycle::bucket_lifecycle_audit::LcEventSrc::Scanner, + ) + .await; - deleted = wait_for_object_absence(&ecstore, bucket_name.as_str(), object_name, Duration::from_secs(2)).await; + deleted = wait_for_object_absence(&ecstore, bucket_name.as_str(), object_name, Duration::from_secs(2)).await; - if !deleted { - println!( - "Object info: name={}, size={}, mod_time={:?}", - obj_info.name, obj_info.size, obj_info.mod_time - ); - } + if !deleted { + println!( + "Object info: name={}, size={}, mod_time={:?}", + obj_info.name, obj_info.size, obj_info.mod_time + ); } } diff --git a/crates/audit/src/factory.rs b/crates/audit/src/factory.rs index 9beded31..18f7ebc1 100644 --- a/crates/audit/src/factory.rs +++ b/crates/audit/src/factory.rs @@ -204,10 +204,10 @@ impl TargetFactory for MQTTTargetFactory { if !std::path::Path::new(&queue_dir).is_absolute() { return Err(TargetError::Configuration("MQTT queue directory must be an absolute path".to_string())); } - if let Some(qos_str) = config.lookup(MQTT_QOS) { - if qos_str == "0" { - warn!("Using queue_dir with QoS 0 may result in event loss"); - } + if let Some(qos_str) = config.lookup(MQTT_QOS) + && qos_str == "0" + { + warn!("Using queue_dir with QoS 0 may result in event loss"); } } diff --git a/crates/audit/src/registry.rs b/crates/audit/src/registry.rs index c73b300a..76edcabf 100644 --- a/crates/audit/src/registry.rs +++ b/crates/audit/src/registry.rs @@ -138,12 +138,11 @@ impl AuditRegistry { format!("{ENV_PREFIX}{AUDIT_ROUTE_PREFIX}{target_type}{DEFAULT_DELIMITER}{ENABLE_KEY}{DEFAULT_DELIMITER}") .to_uppercase(); for (key, value) in &all_env { - if EnableState::from_str(value).ok().map(|s| s.is_enabled()).unwrap_or(false) { - if let Some(id) = key.strip_prefix(&enable_prefix) { - if !id.is_empty() { - instance_ids_from_env.insert(id.to_lowercase()); - } - } + if EnableState::from_str(value).ok().map(|s| s.is_enabled()).unwrap_or(false) + && let Some(id) = key.strip_prefix(&enable_prefix) + && !id.is_empty() + { + instance_ids_from_env.insert(id.to_lowercase()); } } @@ -292,10 +291,10 @@ impl AuditRegistry { for section in sections { let mut section_map: std::collections::HashMap = std::collections::HashMap::new(); // Add default item - if let Some(default_kvs) = section_defaults.get(§ion) { - if !default_kvs.is_empty() { - section_map.insert(DEFAULT_DELIMITER.to_string(), default_kvs.clone()); - } + if let Some(default_kvs) = section_defaults.get(§ion) + && !default_kvs.is_empty() + { + section_map.insert(DEFAULT_DELIMITER.to_string(), default_kvs.clone()); } // Add successful instance item diff --git a/crates/audit/src/system.rs b/crates/audit/src/system.rs index ad80ffe9..0441f280 100644 --- a/crates/audit/src/system.rs +++ b/crates/audit/src/system.rs @@ -573,10 +573,10 @@ impl AuditSystem { } // Remove existing target if present - if let Some(old_target) = registry.remove_target(&target_id) { - if let Err(e) = old_target.close().await { - error!(target_id = %target_id, error = %e, "Failed to close old target during upsert"); - } + if let Some(old_target) = registry.remove_target(&target_id) + && let Err(e) = old_target.close().await + { + error!(target_id = %target_id, error = %e, "Failed to close old target during upsert"); } registry.add_target(target_id.clone(), target); diff --git a/crates/common/src/data_usage.rs b/crates/common/src/data_usage.rs index 6eddc438..dabe5dc1 100644 --- a/crates/common/src/data_usage.rs +++ b/crates/common/src/data_usage.rs @@ -605,13 +605,12 @@ impl DataUsageCache { pub fn search_parent(&self, hash: &DataUsageHash) -> Option { let want = hash.key(); - if let Some(last_index) = want.rfind('/') { - if let Some(v) = self.find(&want[0..last_index]) { - if v.children.contains(&want) { - let found = hash_path(&want[0..last_index]); - return Some(found); - } - } + if let Some(last_index) = want.rfind('/') + && let Some(v) = self.find(&want[0..last_index]) + && v.children.contains(&want) + { + let found = hash_path(&want[0..last_index]); + return Some(found); } for (k, v) in self.cache.iter() { @@ -1150,10 +1149,10 @@ impl DataUsageInfo { self.buckets_count = self.buckets_usage.len() as u64; // Update last update time - if let Some(other_update) = other.last_update { - if self.last_update.is_none() || other_update > self.last_update.unwrap() { - self.last_update = Some(other_update); - } + if let Some(other_update) = other.last_update + && (self.last_update.is_none() || other_update > self.last_update.unwrap()) + { + self.last_update = Some(other_update); } } } diff --git a/crates/common/src/heal_channel.rs b/crates/common/src/heal_channel.rs index 67b7f46d..c4d4af90 100644 --- a/crates/common/src/heal_channel.rs +++ b/crates/common/src/heal_channel.rs @@ -403,10 +403,10 @@ fn lc_get_prefix(rule: &LifecycleRule) -> String { } else if let Some(filter) = &rule.filter { if let Some(p) = &filter.prefix { return p.to_string(); - } else if let Some(and) = &filter.and { - if let Some(p) = &and.prefix { - return p.to_string(); - } + } else if let Some(and) = &filter.and + && let Some(p) = &and.prefix + { + return p.to_string(); } } @@ -475,21 +475,19 @@ pub fn rep_has_active_rules(config: &ReplicationConfiguration, prefix: &str, rec { continue; } - if !prefix.is_empty() { - if let Some(filter) = &rule.filter { - if let Some(r_prefix) = &filter.prefix { - if !r_prefix.is_empty() { - // incoming prefix must be in rule prefix - if !recursive && !prefix.starts_with(r_prefix) { - continue; - } - // If recursive, we can skip this rule if it doesn't match the tested prefix or level below prefix - // does not match - if recursive && !r_prefix.starts_with(prefix) && !prefix.starts_with(r_prefix) { - continue; - } - } - } + if !prefix.is_empty() + && let Some(filter) = &rule.filter + && let Some(r_prefix) = &filter.prefix + && !r_prefix.is_empty() + { + // incoming prefix must be in rule prefix + if !recursive && !prefix.starts_with(r_prefix) { + continue; + } + // If recursive, we can skip this rule if it doesn't match the tested prefix or level below prefix + // does not match + if recursive && !r_prefix.starts_with(prefix) && !prefix.starts_with(r_prefix) { + continue; } } return true; diff --git a/crates/common/src/metrics.rs b/crates/common/src/metrics.rs index 9d2a5f64..78b04a64 100644 --- a/crates/common/src/metrics.rs +++ b/crates/common/src/metrics.rs @@ -466,21 +466,21 @@ impl Metrics { // Lifetime operations for i in 0..Metric::Last as usize { let count = self.operations[i].load(Ordering::Relaxed); - if count > 0 { - if let Some(metric) = Metric::from_index(i) { - metrics.life_time_ops.insert(metric.as_str().to_string(), count); - } + if count > 0 + && let Some(metric) = Metric::from_index(i) + { + metrics.life_time_ops.insert(metric.as_str().to_string(), count); } } // Last minute statistics for realtime metrics for i in 0..Metric::LastRealtime as usize { let last_min = self.latency[i].total().await; - if last_min.n > 0 { - if let Some(_metric) = Metric::from_index(i) { - // Convert to madmin TimedAction format if needed - // This would require implementing the conversion - } + if last_min.n > 0 + && let Some(_metric) = Metric::from_index(i) + { + // Convert to madmin TimedAction format if needed + // This would require implementing the conversion } } diff --git a/crates/e2e_test/src/common.rs b/crates/e2e_test/src/common.rs index ce220289..9b94005e 100644 --- a/crates/e2e_test/src/common.rs +++ b/crates/e2e_test/src/common.rs @@ -178,11 +178,11 @@ impl RustFSTestEnvironment { info!("Cleaning up any existing RustFS processes"); let output = Command::new("pkill").args(["-f", "rustfs"]).output(); - if let Ok(output) = output { - if output.status.success() { - info!("Killed existing RustFS processes"); - sleep(Duration::from_millis(1000)).await; - } + if let Ok(output) = output + && output.status.success() + { + info!("Killed existing RustFS processes"); + sleep(Duration::from_millis(1000)).await; } Ok(()) } diff --git a/crates/e2e_test/src/kms/common.rs b/crates/e2e_test/src/kms/common.rs index 390da7ad..68fac9c4 100644 --- a/crates/e2e_test/src/kms/common.rs +++ b/crates/e2e_test/src/kms/common.rs @@ -406,11 +406,11 @@ impl VaultTestEnvironment { let port_check = TcpStream::connect(VAULT_ADDRESS).await.is_ok(); if port_check { // Additional check by making a health request - if let Ok(response) = reqwest::get(&format!("{VAULT_URL}/v1/sys/health")).await { - if response.status().is_success() { - info!("Vault server is ready after {} seconds", i); - return Ok(()); - } + if let Ok(response) = reqwest::get(&format!("{VAULT_URL}/v1/sys/health")).await + && response.status().is_success() + { + info!("Vault server is ready after {} seconds", i); + return Ok(()); } } diff --git a/crates/ecstore/src/bucket/bucket_target_sys.rs b/crates/ecstore/src/bucket/bucket_target_sys.rs index 99b38ff4..5c83e4e3 100644 --- a/crates/ecstore/src/bucket/bucket_target_sys.rs +++ b/crates/ecstore/src/bucket/bucket_target_sys.rs @@ -498,19 +498,19 @@ impl BucketTargetSys { bucket: bucket.to_string(), })?; - if arn.arn_type == BucketTargetType::ReplicationService { - if let Ok((config, _)) = get_replication_config(bucket).await { - for rule in config.filter_target_arns(&ObjectOpts { - op_type: ReplicationType::All, - ..Default::default() - }) { - if rule == arn_str || config.role == arn_str { - let arn_remotes_map = self.arn_remotes_map.read().await; - if arn_remotes_map.get(arn_str).is_some() { - return Err(BucketTargetError::BucketRemoteRemoveDisallowed { - bucket: bucket.to_string(), - }); - } + if arn.arn_type == BucketTargetType::ReplicationService + && let Ok((config, _)) = get_replication_config(bucket).await + { + for rule in config.filter_target_arns(&ObjectOpts { + op_type: ReplicationType::All, + ..Default::default() + }) { + if rule == arn_str || config.role == arn_str { + let arn_remotes_map = self.arn_remotes_map.read().await; + if arn_remotes_map.get(arn_str).is_some() { + return Err(BucketTargetError::BucketRemoteRemoveDisallowed { + bucket: bucket.to_string(), + }); } } } @@ -691,22 +691,22 @@ impl BucketTargetSys { } // Add new targets - if let Some(new_targets) = targets { - if !new_targets.is_empty() { - for target in &new_targets.targets { - if let Ok(client) = self.get_remote_target_client_internal(target).await { - arn_remotes_map.insert( - target.arn.clone(), - ArnTarget { - client: Some(Arc::new(client)), - last_refresh: OffsetDateTime::now_utc(), - }, - ); - self.update_bandwidth_limit(bucket, &target.arn, target.bandwidth_limit); - } + if let Some(new_targets) = targets + && !new_targets.is_empty() + { + for target in &new_targets.targets { + if let Ok(client) = self.get_remote_target_client_internal(target).await { + arn_remotes_map.insert( + target.arn.clone(), + ArnTarget { + client: Some(Arc::new(client)), + last_refresh: OffsetDateTime::now_utc(), + }, + ); + self.update_bandwidth_limit(bucket, &target.arn, target.bandwidth_limit); } - targets_map.insert(bucket.to_string(), new_targets.targets.clone()); } + targets_map.insert(bucket.to_string(), new_targets.targets.clone()); } } diff --git a/crates/ecstore/src/bucket/object_lock/objectlock_sys.rs b/crates/ecstore/src/bucket/object_lock/objectlock_sys.rs index 56efd5f3..fb71339a 100644 --- a/crates/ecstore/src/bucket/object_lock/objectlock_sys.rs +++ b/crates/ecstore/src/bucket/object_lock/objectlock_sys.rs @@ -31,10 +31,10 @@ impl BucketObjectLockSys { } pub async fn get(bucket: &str) -> Option { - if let Ok(object_lock_config) = get_object_lock_config(bucket).await { - if let Some(object_lock_rule) = object_lock_config.0.rule { - return object_lock_rule.default_retention; - } + if let Ok(object_lock_config) = get_object_lock_config(bucket).await + && let Some(object_lock_rule) = object_lock_config.0.rule + { + return object_lock_rule.default_retention; } None } diff --git a/crates/ecstore/src/bucket/replication/config.rs b/crates/ecstore/src/bucket/replication/config.rs index 4e427301..422b76be 100644 --- a/crates/ecstore/src/bucket/replication/config.rs +++ b/crates/ecstore/src/bucket/replication/config.rs @@ -55,10 +55,10 @@ impl ReplicationConfigurationExt for ReplicationConfiguration { if !has_arn { has_arn = true; } - if let Some(status) = &rule.existing_object_replication { - if status.status == ExistingObjectReplicationStatus::from_static(ExistingObjectReplicationStatus::ENABLED) { - return (true, true); - } + if let Some(status) = &rule.existing_object_replication + && status.status == ExistingObjectReplicationStatus::from_static(ExistingObjectReplicationStatus::ENABLED) + { + return (true, true); } } } @@ -86,12 +86,11 @@ impl ReplicationConfigurationExt for ReplicationConfiguration { continue; } - if let Some(status) = &rule.existing_object_replication { - if obj.existing_object - && status.status == ExistingObjectReplicationStatus::from_static(ExistingObjectReplicationStatus::DISABLED) - { - continue; - } + if let Some(status) = &rule.existing_object_replication + && obj.existing_object + && status.status == ExistingObjectReplicationStatus::from_static(ExistingObjectReplicationStatus::DISABLED) + { + continue; } if !obj.name.starts_with(rule.prefix()) { @@ -145,12 +144,11 @@ impl ReplicationConfigurationExt for ReplicationConfiguration { continue; } - if let Some(status) = &rule.existing_object_replication { - if obj.existing_object - && status.status == ExistingObjectReplicationStatus::from_static(ExistingObjectReplicationStatus::DISABLED) - { - return false; - } + if let Some(status) = &rule.existing_object_replication + && obj.existing_object + && status.status == ExistingObjectReplicationStatus::from_static(ExistingObjectReplicationStatus::DISABLED) + { + return false; } if obj.op_type == ReplicationType::Delete { @@ -186,20 +184,20 @@ impl ReplicationConfigurationExt for ReplicationConfiguration { continue; } - if let Some(filter) = &rule.filter { - if let Some(filter_prefix) = &filter.prefix { - if !prefix.is_empty() && !filter_prefix.is_empty() { - // The provided prefix must fall within the rule prefix - if !recursive && !prefix.starts_with(filter_prefix) { - continue; - } - } - - // When recursive, skip this rule if it does not match the test prefix or hierarchy - if recursive && !rule.prefix().starts_with(prefix) && !prefix.starts_with(rule.prefix()) { + if let Some(filter) = &rule.filter + && let Some(filter_prefix) = &filter.prefix + { + if !prefix.is_empty() && !filter_prefix.is_empty() { + // The provided prefix must fall within the rule prefix + if !recursive && !prefix.starts_with(filter_prefix) { continue; } } + + // When recursive, skip this rule if it does not match the test prefix or hierarchy + if recursive && !rule.prefix().starts_with(prefix) && !prefix.starts_with(rule.prefix()) { + continue; + } } return true; } diff --git a/crates/ecstore/src/bucket/replication/replication_pool.rs b/crates/ecstore/src/bucket/replication/replication_pool.rs index 84c3a6ae..181096e6 100644 --- a/crates/ecstore/src/bucket/replication/replication_pool.rs +++ b/crates/ecstore/src/bucket/replication/replication_pool.rs @@ -512,20 +512,20 @@ impl ReplicationPool { if !lrg_workers.is_empty() { let index = (hash as usize) % lrg_workers.len(); - if let Some(worker) = lrg_workers.get(index) { - if worker.try_send(ReplicationOperation::Object(Box::new(ri.clone()))).is_err() { - // Queue to MRF if worker is busy - let _ = self.mrf_save_tx.try_send(ri.to_mrf_entry()); + if let Some(worker) = lrg_workers.get(index) + && worker.try_send(ReplicationOperation::Object(Box::new(ri.clone()))).is_err() + { + // Queue to MRF if worker is busy + let _ = self.mrf_save_tx.try_send(ri.to_mrf_entry()); - // Try to add more workers if possible - let max_l_workers = *self.max_l_workers.read().await; - let existing = lrg_workers.len(); - if self.active_lrg_workers() < std::cmp::min(max_l_workers, LARGE_WORKER_COUNT) as i32 { - let workers = std::cmp::min(existing + 1, max_l_workers); + // Try to add more workers if possible + let max_l_workers = *self.max_l_workers.read().await; + let existing = lrg_workers.len(); + if self.active_lrg_workers() < std::cmp::min(max_l_workers, LARGE_WORKER_COUNT) as i32 { + let workers = std::cmp::min(existing + 1, max_l_workers); - drop(lrg_workers); - self.resize_lrg_workers(workers, existing).await; - } + drop(lrg_workers); + self.resize_lrg_workers(workers, existing).await; } } } @@ -539,47 +539,45 @@ impl ReplicationPool { _ => self.get_worker_ch(&ri.bucket, &ri.name, ri.size).await, }; - if let Some(channel) = ch { - if channel.try_send(ReplicationOperation::Object(Box::new(ri.clone()))).is_err() { - // Queue to MRF if all workers are busy - let _ = self.mrf_save_tx.try_send(ri.to_mrf_entry()); + if let Some(channel) = ch + && channel.try_send(ReplicationOperation::Object(Box::new(ri.clone()))).is_err() + { + // Queue to MRF if all workers are busy + let _ = self.mrf_save_tx.try_send(ri.to_mrf_entry()); - // Try to scale up workers based on priority - let priority = self.priority.read().await.clone(); - let max_workers = *self.max_workers.read().await; + // Try to scale up workers based on priority + let priority = self.priority.read().await.clone(); + let max_workers = *self.max_workers.read().await; - match priority { - ReplicationPriority::Fast => { - // Log warning about unable to keep up - info!("Warning: Unable to keep up with incoming traffic"); + match priority { + ReplicationPriority::Fast => { + // Log warning about unable to keep up + info!("Warning: Unable to keep up with incoming traffic"); + } + ReplicationPriority::Slow => { + info!("Warning: Unable to keep up with incoming traffic - recommend increasing replication priority to auto"); + } + ReplicationPriority::Auto => { + let max_w = std::cmp::min(max_workers, WORKER_MAX_LIMIT); + let active_workers = self.active_workers(); + + if active_workers < max_w as i32 { + let workers = self.workers.read().await; + let new_count = std::cmp::min(workers.len() + 1, max_w); + let existing = workers.len(); + + drop(workers); + self.resize_workers(new_count, existing).await; } - ReplicationPriority::Slow => { - info!( - "Warning: Unable to keep up with incoming traffic - recommend increasing replication priority to auto" - ); - } - ReplicationPriority::Auto => { - let max_w = std::cmp::min(max_workers, WORKER_MAX_LIMIT); - let active_workers = self.active_workers(); - if active_workers < max_w as i32 { - let workers = self.workers.read().await; - let new_count = std::cmp::min(workers.len() + 1, max_w); - let existing = workers.len(); + let max_mrf_workers = std::cmp::min(max_workers, MRF_WORKER_MAX_LIMIT); + let active_mrf = self.active_mrf_workers(); - drop(workers); - self.resize_workers(new_count, existing).await; - } + if active_mrf < max_mrf_workers as i32 { + let current_mrf = self.mrf_worker_size.load(Ordering::SeqCst); + let new_mrf = std::cmp::min(current_mrf + 1, max_mrf_workers as i32); - let max_mrf_workers = std::cmp::min(max_workers, MRF_WORKER_MAX_LIMIT); - let active_mrf = self.active_mrf_workers(); - - if active_mrf < max_mrf_workers as i32 { - let current_mrf = self.mrf_worker_size.load(Ordering::SeqCst); - let new_mrf = std::cmp::min(current_mrf + 1, max_mrf_workers as i32); - - self.resize_failed_workers(new_mrf).await; - } + self.resize_failed_workers(new_mrf).await; } } } @@ -593,31 +591,29 @@ impl ReplicationPool { _ => self.get_worker_ch(&doi.bucket, &doi.delete_object.object_name, 0).await, }; - if let Some(channel) = ch { - if channel.try_send(ReplicationOperation::Delete(Box::new(doi.clone()))).is_err() { - let _ = self.mrf_save_tx.try_send(doi.to_mrf_entry()); + if let Some(channel) = ch + && channel.try_send(ReplicationOperation::Delete(Box::new(doi.clone()))).is_err() + { + let _ = self.mrf_save_tx.try_send(doi.to_mrf_entry()); - let priority = self.priority.read().await.clone(); - let max_workers = *self.max_workers.read().await; + let priority = self.priority.read().await.clone(); + let max_workers = *self.max_workers.read().await; - match priority { - ReplicationPriority::Fast => { - info!("Warning: Unable to keep up with incoming deletes"); - } - ReplicationPriority::Slow => { - info!( - "Warning: Unable to keep up with incoming deletes - recommend increasing replication priority to auto" - ); - } - ReplicationPriority::Auto => { - let max_w = std::cmp::min(max_workers, WORKER_MAX_LIMIT); - if self.active_workers() < max_w as i32 { - let workers = self.workers.read().await; - let new_count = std::cmp::min(workers.len() + 1, max_w); - let existing = workers.len(); - drop(workers); - self.resize_workers(new_count, existing).await; - } + match priority { + ReplicationPriority::Fast => { + info!("Warning: Unable to keep up with incoming deletes"); + } + ReplicationPriority::Slow => { + info!("Warning: Unable to keep up with incoming deletes - recommend increasing replication priority to auto"); + } + ReplicationPriority::Auto => { + let max_w = std::cmp::min(max_workers, WORKER_MAX_LIMIT); + if self.active_workers() < max_w as i32 { + let workers = self.workers.read().await; + let new_count = std::cmp::min(workers.len() + 1, max_w); + let existing = workers.len(); + drop(workers); + self.resize_workers(new_count, existing).await; } } } diff --git a/crates/ecstore/src/bucket/replication/replication_resyncer.rs b/crates/ecstore/src/bucket/replication/replication_resyncer.rs index eebc1ff8..39f1cf56 100644 --- a/crates/ecstore/src/bucket/replication/replication_resyncer.rs +++ b/crates/ecstore/src/bucket/replication/replication_resyncer.rs @@ -242,11 +242,10 @@ impl ReplicationResyncer { - if let Some(last_update) = status.last_update { - if last_update > *last_update_times.get(bucket).unwrap_or(&OffsetDateTime::UNIX_EPOCH) { + if let Some(last_update) = status.last_update + && last_update > *last_update_times.get(bucket).unwrap_or(&OffsetDateTime::UNIX_EPOCH) { update = true; } - } if update { if let Err(err) = save_resync_status(bucket, status, api.clone()).await { @@ -345,13 +344,12 @@ impl ReplicationResyncer { return; }; - if !heal { - if let Err(e) = self + if !heal + && let Err(e) = self .mark_status(ResyncStatusType::ResyncStarted, opts.clone(), storage.clone()) .await - { - error!("Failed to mark resync status: {}", e); - } + { + error!("Failed to mark resync status: {}", e); } let (tx, mut rx) = tokio::sync::mpsc::channel(100); @@ -1463,21 +1461,18 @@ async fn replicate_delete_to_target(dobj: &DeletedObjectReplicationInfo, tgt_cli Some(version_id.to_string()) }; - if dobj.delete_object.delete_marker_version_id.is_some() { - if let Err(e) = tgt_client + if dobj.delete_object.delete_marker_version_id.is_some() + && let Err(e) = tgt_client .head_object(&tgt_client.bucket, &dobj.delete_object.object_name, version_id.clone()) .await - { - if let SdkError::ServiceError(service_err) = &e { - if !service_err.err().is_not_found() { - rinfo.replication_status = ReplicationStatusType::Failed; - rinfo.error = Some(e.to_string()); + && let SdkError::ServiceError(service_err) = &e + && !service_err.err().is_not_found() + { + rinfo.replication_status = ReplicationStatusType::Failed; + rinfo.error = Some(e.to_string()); - return rinfo; - } - } - }; - } + return rinfo; + }; match tgt_client .remove_object( diff --git a/crates/ecstore/src/bucket/replication/replication_state.rs b/crates/ecstore/src/bucket/replication/replication_state.rs index 5de189be..1b887141 100644 --- a/crates/ecstore/src/bucket/replication/replication_state.rs +++ b/crates/ecstore/src/bucket/replication/replication_state.rs @@ -49,13 +49,13 @@ impl ExponentialMovingAverage { pub fn update_exponential_moving_average(&self, now: SystemTime) { if let Ok(mut last_update_guard) = self.last_update.try_lock() { let last_update = *last_update_guard; - if let Ok(duration) = now.duration_since(last_update) { - if duration.as_secs() > 0 { - let decay = (-duration.as_secs_f64() / 60.0).exp(); // 1 minute decay - let current_value = f64::from_bits(self.value.load(AtomicOrdering::Relaxed)); - self.value.store((current_value * decay).to_bits(), AtomicOrdering::Relaxed); - *last_update_guard = now; - } + if let Ok(duration) = now.duration_since(last_update) + && duration.as_secs() > 0 + { + let decay = (-duration.as_secs_f64() / 60.0).exp(); // 1 minute decay + let current_value = f64::from_bits(self.value.load(AtomicOrdering::Relaxed)); + self.value.store((current_value * decay).to_bits(), AtomicOrdering::Relaxed); + *last_update_guard = now; } } } @@ -757,10 +757,10 @@ impl ReplicationStats { /// Check if bucket replication statistics have usage pub fn has_replication_usage(&self, bucket: &str) -> bool { - if let Ok(cache) = self.cache.try_read() { - if let Some(stats) = cache.get(bucket) { - return stats.has_replication_usage(); - } + if let Ok(cache) = self.cache.try_read() + && let Some(stats) = cache.get(bucket) + { + return stats.has_replication_usage(); } false } diff --git a/crates/ecstore/src/bucket/versioning/mod.rs b/crates/ecstore/src/bucket/versioning/mod.rs index 23c3ee10..2750ee77 100644 --- a/crates/ecstore/src/bucket/versioning/mod.rs +++ b/crates/ecstore/src/bucket/versioning/mod.rs @@ -37,10 +37,11 @@ impl VersioningApi for VersioningConfiguration { return true; } - if let Some(exclude_folders) = self.exclude_folders { - if exclude_folders && prefix.ends_with('/') { - return false; - } + if let Some(exclude_folders) = self.exclude_folders + && exclude_folders + && prefix.ends_with('/') + { + return false; } if let Some(ref excluded_prefixes) = self.excluded_prefixes { @@ -67,10 +68,11 @@ impl VersioningApi for VersioningConfiguration { return false; } - if let Some(exclude_folders) = self.exclude_folders { - if exclude_folders && prefix.ends_with('/') { - return true; - } + if let Some(exclude_folders) = self.exclude_folders + && exclude_folders + && prefix.ends_with('/') + { + return true; } if let Some(ref excluded_prefixes) = self.excluded_prefixes { diff --git a/crates/ecstore/src/cache_value/metacache_set.rs b/crates/ecstore/src/cache_value/metacache_set.rs index b71b2c30..88a03e23 100644 --- a/crates/ecstore/src/cache_value/metacache_set.rs +++ b/crates/ecstore/src/cache_value/metacache_set.rs @@ -308,12 +308,11 @@ pub async fn list_path_raw(rx: CancellationToken, opts: ListPathRawOptions) -> d // Break if all at EOF or error. if at_eof + has_err == readers.len() { - if has_err > 0 { - if let Some(finished_fn) = opts.finished.as_ref() { - if has_err > 0 { - finished_fn(&errs).await; - } - } + if has_err > 0 + && let Some(finished_fn) = opts.finished.as_ref() + && has_err > 0 + { + finished_fn(&errs).await; } // error!("list_path_raw: at_eof + has_err == readers.len() break {:?}", &errs); diff --git a/crates/ecstore/src/client/transition_api.rs b/crates/ecstore/src/client/transition_api.rs index 58b17f13..9e422928 100644 --- a/crates/ecstore/src/client/transition_api.rs +++ b/crates/ecstore/src/client/transition_api.rs @@ -161,7 +161,7 @@ impl TransitionClient { async fn private_new(endpoint: &str, opts: Options, tier_type: &str) -> Result { let endpoint_url = get_endpoint_url(endpoint, opts.secure)?; - let _ = rustls::crypto::ring::default_provider().install_default(); + let _ = rustls::crypto::aws_lc_rs::default_provider().install_default(); let scheme = endpoint_url.scheme(); let client; let tls = if let Some(store) = load_root_store_from_tls_path() { diff --git a/crates/ecstore/src/config/com.rs b/crates/ecstore/src/config/com.rs index 443905d5..b1010bf0 100644 --- a/crates/ecstore/src/config/com.rs +++ b/crates/ecstore/src/config/com.rs @@ -211,10 +211,11 @@ async fn apply_dynamic_config_for_sub_sys(cfg: &mut Config, api: for (i, count) in set_drive_counts.iter().enumerate() { match storageclass::lookup_config(&kvs, *count) { Ok(res) => { - if i == 0 && GLOBAL_STORAGE_CLASS.get().is_none() { - if let Err(r) = GLOBAL_STORAGE_CLASS.set(res) { - error!("GLOBAL_STORAGE_CLASS.set failed {:?}", r); - } + if i == 0 + && GLOBAL_STORAGE_CLASS.get().is_none() + && let Err(r) = GLOBAL_STORAGE_CLASS.set(res) + { + error!("GLOBAL_STORAGE_CLASS.set failed {:?}", r); } } Err(err) => { diff --git a/crates/ecstore/src/config/mod.rs b/crates/ecstore/src/config/mod.rs index 33bc76f4..9a39df13 100644 --- a/crates/ecstore/src/config/mod.rs +++ b/crates/ecstore/src/config/mod.rs @@ -180,10 +180,10 @@ impl Config { let mut default = HashMap::new(); default.insert(DEFAULT_DELIMITER.to_owned(), v.clone()); self.0.insert(k.clone(), default); - } else if !self.0[k].contains_key(DEFAULT_DELIMITER) { - if let Some(m) = self.0.get_mut(k) { - m.insert(DEFAULT_DELIMITER.to_owned(), v.clone()); - } + } else if !self.0[k].contains_key(DEFAULT_DELIMITER) + && let Some(m) = self.0.get_mut(k) + { + m.insert(DEFAULT_DELIMITER.to_owned(), v.clone()); } } } diff --git a/crates/ecstore/src/data_usage.rs b/crates/ecstore/src/data_usage.rs index 4bfd1ea7..cc908e6a 100644 --- a/crates/ecstore/src/data_usage.rs +++ b/crates/ecstore/src/data_usage.rs @@ -65,18 +65,16 @@ lazy_static::lazy_static! { /// Store data usage info to backend storage pub async fn store_data_usage_in_backend(data_usage_info: DataUsageInfo, store: Arc) -> Result<(), Error> { // Prevent older data from overwriting newer persisted stats - if let Ok(buf) = read_config(store.clone(), &DATA_USAGE_OBJ_NAME_PATH).await { - if let Ok(existing) = serde_json::from_slice::(&buf) { - if let (Some(new_ts), Some(existing_ts)) = (data_usage_info.last_update, existing.last_update) { - if new_ts <= existing_ts { - info!( - "Skip persisting data usage: incoming last_update {:?} <= existing {:?}", - new_ts, existing_ts - ); - return Ok(()); - } - } - } + if let Ok(buf) = read_config(store.clone(), &DATA_USAGE_OBJ_NAME_PATH).await + && let Ok(existing) = serde_json::from_slice::(&buf) + && let (Some(new_ts), Some(existing_ts)) = (data_usage_info.last_update, existing.last_update) + && new_ts <= existing_ts + { + info!( + "Skip persisting data usage: incoming last_update {:?} <= existing {:?}", + new_ts, existing_ts + ); + return Ok(()); } let data = @@ -149,26 +147,24 @@ pub async fn load_data_usage_from_backend(store: Arc) -> Result 0 + if (bui.replicated_size_v1 > 0 || bui.replication_failed_count_v1 > 0 || bui.replication_failed_size_v1 > 0 - || bui.replication_pending_count_v1 > 0 + || bui.replication_pending_count_v1 > 0) + && let Ok((cfg, _)) = get_replication_config(bucket).await + && !cfg.role.is_empty() { - if let Ok((cfg, _)) = get_replication_config(bucket).await { - if !cfg.role.is_empty() { - data_usage_info.replication_info.insert( - cfg.role.clone(), - BucketTargetUsageInfo { - replication_failed_size: bui.replication_failed_size_v1, - replication_failed_count: bui.replication_failed_count_v1, - replicated_size: bui.replicated_size_v1, - replication_pending_count: bui.replication_pending_count_v1, - replication_pending_size: bui.replication_pending_size_v1, - ..Default::default() - }, - ); - } - } + data_usage_info.replication_info.insert( + cfg.role.clone(), + BucketTargetUsageInfo { + replication_failed_size: bui.replication_failed_size_v1, + replication_failed_count: bui.replication_failed_count_v1, + replicated_size: bui.replicated_size_v1, + replication_pending_count: bui.replication_pending_count_v1, + replication_pending_size: bui.replication_pending_size_v1, + ..Default::default() + }, + ); } } @@ -177,10 +173,10 @@ pub async fn load_data_usage_from_backend(store: Arc) -> Result) { - if let Some(update) = snapshot.last_update { - if latest_update.is_none_or(|current| update > current) { - *latest_update = Some(update); - } + if let Some(update) = snapshot.last_update + && latest_update.is_none_or(|current| update > current) + { + *latest_update = Some(update); } snapshot.recompute_totals(); @@ -255,10 +251,10 @@ pub async fn aggregate_local_snapshots(store: Arc) -> Result<(Vec { if err == Error::FileNotFound && !skip_access_checks(volume_dir.as_ref().to_string_lossy().to_string().as_str()) + && let Err(e) = access(volume_dir.as_ref()).await + && e.kind() == ErrorKind::NotFound { - if let Err(e) = access(volume_dir.as_ref()).await { - if e.kind() == ErrorKind::NotFound { - // warn!("read_metadata_with_dmtime os err {:?}", &aerr); - return Err(DiskError::VolumeNotFound); - } - } + // warn!("read_metadata_with_dmtime os err {:?}", &aerr); + return Err(DiskError::VolumeNotFound); } Err(err) @@ -763,13 +761,13 @@ impl LocalDisk { let mut f = match super::fs::open_file(file_path.as_ref(), O_RDONLY).await { Ok(f) => f, Err(e) => { - if e.kind() == ErrorKind::NotFound && !skip_access_checks(volume) { - if let Err(er) = access(volume_dir.as_ref()).await { - if er.kind() == ErrorKind::NotFound { - warn!("read_all_data_with_dmtime os err {:?}", &er); - return Err(DiskError::VolumeNotFound); - } - } + if e.kind() == ErrorKind::NotFound + && !skip_access_checks(volume) + && let Err(er) = access(volume_dir.as_ref()).await + && er.kind() == ErrorKind::NotFound + { + warn!("read_all_data_with_dmtime os err {:?}", &er); + return Err(DiskError::VolumeNotFound); } return Err(to_file_error(e).into()); @@ -828,10 +826,10 @@ impl LocalDisk { let _ = fm.data.remove(vec![vid, dir]); let dir_path = self.get_object_path(volume, format!("{path}/{dir}").as_str())?; - if let Err(err) = self.move_to_trash(&dir_path, true, false).await { - if !(err == DiskError::FileNotFound || err == DiskError::VolumeNotFound) { - return Err(err); - } + if let Err(err) = self.move_to_trash(&dir_path, true, false).await + && !(err == DiskError::FileNotFound || err == DiskError::VolumeNotFound) + { + return Err(err); }; } } @@ -1051,11 +1049,11 @@ impl LocalDisk { continue; } - if let Some(forward) = &forward { - if &entry < forward { - *item = "".to_owned(); - continue; - } + if let Some(forward) = &forward + && &entry < forward + { + *item = "".to_owned(); + continue; } if entry.ends_with(SLASH_SEPARATOR) { @@ -1133,10 +1131,10 @@ impl LocalDisk { }) .await?; - if opts.recursive { - if let Err(er) = Box::pin(self.scan_dir(pop, prefix.clone(), opts, out, objs_returned)).await { - error!("scan_dir err {:?}", er); - } + if opts.recursive + && let Err(er) = Box::pin(self.scan_dir(pop, prefix.clone(), opts, out, objs_returned)).await + { + error!("scan_dir err {:?}", er); } dir_stack.pop(); } @@ -1200,10 +1198,10 @@ impl LocalDisk { }) .await?; - if opts.recursive { - if let Err(er) = Box::pin(self.scan_dir(dir, prefix.clone(), opts, out, objs_returned)).await { - warn!("scan_dir err {:?}", &er); - } + if opts.recursive + && let Err(er) = Box::pin(self.scan_dir(dir, prefix.clone(), opts, out, objs_returned)).await + { + warn!("scan_dir err {:?}", &er); } } @@ -1345,23 +1343,23 @@ impl DiskAPI for LocalDisk { if format_info.file_info.is_some() && id.is_some() { // check last check time - if let Some(last_check) = format_info.last_check { - if last_check.unix_timestamp() + 1 < OffsetDateTime::now_utc().unix_timestamp() { - return Ok(id); - } + if let Some(last_check) = format_info.last_check + && last_check.unix_timestamp() + 1 < OffsetDateTime::now_utc().unix_timestamp() + { + return Ok(id); } } let file_meta = self.check_format_json().await?; - if let Some(file_info) = &format_info.file_info { - if super::fs::same_file(&file_meta, file_info) { - let mut format_info = self.format_info.write().await; - format_info.last_check = Some(OffsetDateTime::now_utc()); - drop(format_info); + if let Some(file_info) = &format_info.file_info + && super::fs::same_file(&file_meta, file_info) + { + let mut format_info = self.format_info.write().await; + format_info.last_check = Some(OffsetDateTime::now_utc()); + drop(format_info); - return Ok(id); - } + return Ok(id); } debug!("get_disk_id: read format.json"); @@ -1420,10 +1418,10 @@ impl DiskAPI for LocalDisk { #[tracing::instrument(skip(self))] async fn delete(&self, volume: &str, path: &str, opt: DeleteOptions) -> Result<()> { let volume_dir = self.get_bucket_path(volume)?; - if !skip_access_checks(volume) { - if let Err(e) = access(&volume_dir).await { - return Err(to_access_error(e, DiskError::VolumeAccessDenied).into()); - } + if !skip_access_checks(volume) + && let Err(e) = access(&volume_dir).await + { + return Err(to_access_error(e, DiskError::VolumeAccessDenied).into()); } let file_path = volume_dir.join(Path::new(&path)); @@ -1438,10 +1436,10 @@ impl DiskAPI for LocalDisk { #[tracing::instrument(skip(self))] async fn verify_file(&self, volume: &str, path: &str, fi: &FileInfo) -> Result { let volume_dir = self.get_bucket_path(volume)?; - if !skip_access_checks(volume) { - if let Err(e) = access(&volume_dir).await { - return Err(to_access_error(e, DiskError::VolumeAccessDenied).into()); - } + if !skip_access_checks(volume) + && let Err(e) = access(&volume_dir).await + { + return Err(to_access_error(e, DiskError::VolumeAccessDenied).into()); } let mut resp = CheckPartsResp { @@ -1466,14 +1464,14 @@ impl DiskAPI for LocalDisk { .await .err(); resp.results[i] = conv_part_err_to_int(&err); - if resp.results[i] == CHECK_PART_UNKNOWN { - if let Some(err) = err { - error!("verify_file: failed to bitrot verify file: {:?}, error: {:?}", &part_path, &err); - if err == DiskError::FileAccessDenied { - continue; - } - info!("part unknown, disk: {}, path: {:?}", self.to_string(), part_path); + if resp.results[i] == CHECK_PART_UNKNOWN + && let Some(err) = err + { + error!("verify_file: failed to bitrot verify file: {:?}, error: {:?}", &part_path, &err); + if err == DiskError::FileAccessDenied { + continue; } + info!("part unknown, disk: {}, path: {:?}", self.to_string(), part_path); } } @@ -1572,13 +1570,12 @@ impl DiskAPI for LocalDisk { let e: DiskError = to_file_error(err).into(); if e == DiskError::FileNotFound { - if !skip_access_checks(volume) { - if let Err(err) = access(&volume_dir).await { - if err.kind() == ErrorKind::NotFound { - resp.results[i] = CHECK_PART_VOLUME_NOT_FOUND; - continue; - } - } + if !skip_access_checks(volume) + && let Err(err) = access(&volume_dir).await + && err.kind() == ErrorKind::NotFound + { + resp.results[i] = CHECK_PART_VOLUME_NOT_FOUND; + continue; } resp.results[i] = CHECK_PART_FILE_NOT_FOUND; } else { @@ -1634,11 +1631,11 @@ impl DiskAPI for LocalDisk { } }; - if let Some(meta) = meta_op { - if !meta.is_dir() { - warn!("rename_part src is not dir {:?}", &src_file_path); - return Err(DiskError::FileAccessDenied); - } + if let Some(meta) = meta_op + && !meta.is_dir() + { + warn!("rename_part src is not dir {:?}", &src_file_path); + return Err(DiskError::FileAccessDenied); } remove_std(&dst_file_path).map_err(to_file_error)?; @@ -1695,10 +1692,10 @@ impl DiskAPI for LocalDisk { } }; - if let Some(meta) = meta_op { - if !meta.is_dir() { - return Err(DiskError::FileAccessDenied); - } + if let Some(meta) = meta_op + && !meta.is_dir() + { + return Err(DiskError::FileAccessDenied); } remove(&dst_file_path).await.map_err(to_file_error)?; @@ -1814,10 +1811,10 @@ impl DiskAPI for LocalDisk { async fn list_dir(&self, origvolume: &str, volume: &str, dir_path: &str, count: i32) -> Result> { if !origvolume.is_empty() { let origvolume_dir = self.get_bucket_path(origvolume)?; - if !skip_access_checks(origvolume) { - if let Err(e) = access(origvolume_dir).await { - return Err(to_access_error(e, DiskError::VolumeAccessDenied).into()); - } + if !skip_access_checks(origvolume) + && let Err(e) = access(origvolume_dir).await + { + return Err(to_access_error(e, DiskError::VolumeAccessDenied).into()); } } @@ -1827,10 +1824,11 @@ impl DiskAPI for LocalDisk { let entries = match os::read_dir(&dir_path_abs, count).await { Ok(res) => res, Err(e) => { - if e.kind() == std::io::ErrorKind::NotFound && !skip_access_checks(volume) { - if let Err(e) = access(&volume_dir).await { - return Err(to_access_error(e, DiskError::VolumeAccessDenied).into()); - } + if e.kind() == std::io::ErrorKind::NotFound + && !skip_access_checks(volume) + && let Err(e) = access(&volume_dir).await + { + return Err(to_access_error(e, DiskError::VolumeAccessDenied).into()); } return Err(to_file_error(e).into()); @@ -1845,10 +1843,10 @@ impl DiskAPI for LocalDisk { async fn walk_dir(&self, opts: WalkDirOptions, wr: &mut W) -> Result<()> { let volume_dir = self.get_bucket_path(&opts.bucket)?; - if !skip_access_checks(&opts.bucket) { - if let Err(e) = access(&volume_dir).await { - return Err(to_access_error(e, DiskError::VolumeAccessDenied).into()); - } + if !skip_access_checks(&opts.bucket) + && let Err(e) = access(&volume_dir).await + { + return Err(to_access_error(e, DiskError::VolumeAccessDenied).into()); } let mut wr = wr; @@ -1909,19 +1907,19 @@ impl DiskAPI for LocalDisk { dst_path: &str, ) -> Result { let src_volume_dir = self.get_bucket_path(src_volume)?; - if !skip_access_checks(src_volume) { - if let Err(e) = super::fs::access_std(&src_volume_dir) { - info!("access checks failed, src_volume_dir: {:?}, err: {}", src_volume_dir, e.to_string()); - return Err(to_access_error(e, DiskError::VolumeAccessDenied).into()); - } + if !skip_access_checks(src_volume) + && let Err(e) = super::fs::access_std(&src_volume_dir) + { + info!("access checks failed, src_volume_dir: {:?}, err: {}", src_volume_dir, e.to_string()); + return Err(to_access_error(e, DiskError::VolumeAccessDenied).into()); } let dst_volume_dir = self.get_bucket_path(dst_volume)?; - if !skip_access_checks(dst_volume) { - if let Err(e) = super::fs::access_std(&dst_volume_dir) { - info!("access checks failed, dst_volume_dir: {:?}, err: {}", dst_volume_dir, e.to_string()); - return Err(to_access_error(e, DiskError::VolumeAccessDenied).into()); - } + if !skip_access_checks(dst_volume) + && let Err(e) = super::fs::access_std(&dst_volume_dir) + { + info!("access checks failed, dst_volume_dir: {:?}, err: {}", dst_volume_dir, e.to_string()); + return Err(to_access_error(e, DiskError::VolumeAccessDenied).into()); } // xl.meta path @@ -1973,19 +1971,18 @@ impl DiskAPI for LocalDisk { let mut xlmeta = FileMeta::new(); - if let Some(dst_buf) = has_dst_buf.as_ref() { - if FileMeta::is_xl2_v1_format(dst_buf) { - if let Ok(nmeta) = FileMeta::load(dst_buf) { - xlmeta = nmeta - } - } + if let Some(dst_buf) = has_dst_buf.as_ref() + && FileMeta::is_xl2_v1_format(dst_buf) + && let Ok(nmeta) = FileMeta::load(dst_buf) + { + xlmeta = nmeta } let mut skip_parent = dst_volume_dir.clone(); - if has_dst_buf.as_ref().is_some() { - if let Some(parent) = dst_file_path.parent() { - skip_parent = parent.to_path_buf(); - } + if has_dst_buf.as_ref().is_some() + && let Some(parent) = dst_file_path.parent() + { + skip_parent = parent.to_path_buf(); } // TODO: Healing @@ -2017,22 +2014,20 @@ impl DiskAPI for LocalDisk { .await?; if let Some((src_data_path, dst_data_path)) = has_data_dir_path.as_ref() { let no_inline = fi.data.is_none() && fi.size > 0; - if no_inline { - if let Err(err) = rename_all(&src_data_path, &dst_data_path, &skip_parent).await { - let _ = self.delete_file(&dst_volume_dir, dst_data_path, false, false).await; - info!( - "rename all failed src_data_path: {:?}, dst_data_path: {:?}, err: {:?}", - src_data_path, dst_data_path, err - ); - return Err(err); - } + if no_inline && let Err(err) = rename_all(&src_data_path, &dst_data_path, &skip_parent).await { + let _ = self.delete_file(&dst_volume_dir, dst_data_path, false, false).await; + info!( + "rename all failed src_data_path: {:?}, dst_data_path: {:?}, err: {:?}", + src_data_path, dst_data_path, err + ); + return Err(err); } } if let Some(old_data_dir) = has_old_data_dir { // preserve current xl.meta inside the oldDataDir. - if let Some(dst_buf) = has_dst_buf { - if let Err(err) = self + if let Some(dst_buf) = has_dst_buf + && let Err(err) = self .write_all_private( dst_volume, format!("{}/{}/{}", &dst_path, &old_data_dir.to_string(), STORAGE_FORMAT_FILE).as_str(), @@ -2041,10 +2036,9 @@ impl DiskAPI for LocalDisk { &skip_parent, ) .await - { - info!("write_all_private failed err: {:?}", err); - return Err(err); - } + { + info!("write_all_private failed err: {:?}", err); + return Err(err); } } @@ -2075,11 +2069,11 @@ impl DiskAPI for LocalDisk { #[tracing::instrument(skip(self))] async fn make_volumes(&self, volumes: Vec<&str>) -> Result<()> { for vol in volumes { - if let Err(e) = self.make_volume(vol).await { - if e != DiskError::VolumeExists { - error!("local disk make volumes failed: {e}"); - return Err(e); - } + if let Err(e) = self.make_volume(vol).await + && e != DiskError::VolumeExists + { + error!("local disk make volumes failed: {e}"); + return Err(e); } // TODO: health check } @@ -2313,10 +2307,11 @@ impl DiskAPI for LocalDisk { let old_path = file_path.join(Path::new(uuid.to_string().as_str())); check_path_length(old_path.to_string_lossy().as_ref())?; - if let Err(err) = self.move_to_trash(&old_path, true, false).await { - if err != DiskError::FileNotFound && err != DiskError::VolumeNotFound { - return Err(err); - } + if let Err(err) = self.move_to_trash(&old_path, true, false).await + && err != DiskError::FileNotFound + && err != DiskError::VolumeNotFound + { + return Err(err); } } @@ -2328,13 +2323,13 @@ impl DiskAPI for LocalDisk { } // opts.undo_write && opts.old_data_dir.is_some_and(f) - if let Some(old_data_dir) = opts.old_data_dir { - if opts.undo_write { - let src_path = - file_path.join(Path::new(format!("{old_data_dir}{SLASH_SEPARATOR}{STORAGE_FORMAT_FILE_BACKUP}").as_str())); - let dst_path = file_path.join(Path::new(format!("{path}{SLASH_SEPARATOR}{STORAGE_FORMAT_FILE}").as_str())); - return rename_all(src_path, dst_path, file_path).await; - } + if let Some(old_data_dir) = opts.old_data_dir + && opts.undo_write + { + let src_path = + file_path.join(Path::new(format!("{old_data_dir}{SLASH_SEPARATOR}{STORAGE_FORMAT_FILE_BACKUP}").as_str())); + let dst_path = file_path.join(Path::new(format!("{path}{SLASH_SEPARATOR}{STORAGE_FORMAT_FILE}").as_str())); + return rename_all(src_path, dst_path, file_path).await; } self.delete_file(&volume_dir, &xl_path, true, false).await diff --git a/crates/ecstore/src/disk/os.rs b/crates/ecstore/src/disk/os.rs index 66a05e75..7ec5d0ff 100644 --- a/crates/ecstore/src/disk/os.rs +++ b/crates/ecstore/src/disk/os.rs @@ -147,11 +147,11 @@ async fn reliable_rename( dst_file_path: impl AsRef, base_dir: impl AsRef, ) -> io::Result<()> { - if let Some(parent) = dst_file_path.as_ref().parent() { - if !file_exists(parent) { - // info!("reliable_rename reliable_mkdir_all parent: {:?}", parent); - reliable_mkdir_all(parent, base_dir.as_ref()).await?; - } + if let Some(parent) = dst_file_path.as_ref().parent() + && !file_exists(parent) + { + // info!("reliable_rename reliable_mkdir_all parent: {:?}", parent); + reliable_mkdir_all(parent, base_dir.as_ref()).await?; } let mut i = 0; @@ -190,12 +190,11 @@ pub async fn reliable_mkdir_all(path: impl AsRef, base_dir: impl AsRef usize { fn possible_set_counts(set_size: usize) -> Vec { let mut ss = Vec::new(); for s in SET_SIZES { - if set_size % s == 0 { + if set_size.is_multiple_of(s) { ss.push(s); } } @@ -340,7 +340,7 @@ fn common_set_drive_count(divisible_size: usize, set_counts: &[usize]) -> usize let mut prev_d = divisible_size / set_counts[0]; let mut set_size = 0; for &cnt in set_counts { - if divisible_size % cnt == 0 { + if divisible_size.is_multiple_of(cnt) { let d = divisible_size / cnt; if d <= prev_d { prev_d = d; diff --git a/crates/ecstore/src/erasure_coding/decode.rs b/crates/ecstore/src/erasure_coding/decode.rs index 94b69391..c2a1daac 100644 --- a/crates/ecstore/src/erasure_coding/decode.rs +++ b/crates/ecstore/src/erasure_coding/decode.rs @@ -266,12 +266,11 @@ impl Erasure { let (mut shards, errs) = reader.read().await; - if ret_err.is_none() { - if let (_, Some(err)) = reduce_errs(&errs, &[]) { - if err == Error::FileNotFound || err == Error::FileCorrupt { - ret_err = Some(err.into()); - } - } + if ret_err.is_none() + && let (_, Some(err)) = reduce_errs(&errs, &[]) + && (err == Error::FileNotFound || err == Error::FileCorrupt) + { + ret_err = Some(err.into()); } if !reader.can_decode(&shards) { diff --git a/crates/ecstore/src/erasure_coding/encode.rs b/crates/ecstore/src/erasure_coding/encode.rs index e19690c1..1b082550 100644 --- a/crates/ecstore/src/erasure_coding/encode.rs +++ b/crates/ecstore/src/erasure_coding/encode.rs @@ -150,10 +150,10 @@ impl Erasure { } Err(e) if e.kind() == std::io::ErrorKind::UnexpectedEof => { // Check if the inner error is a checksum mismatch - if so, propagate it - if let Some(inner) = e.get_ref() { - if rustfs_rio::is_checksum_mismatch(inner) { - return Err(std::io::Error::new(std::io::ErrorKind::InvalidData, e.to_string())); - } + if let Some(inner) = e.get_ref() + && rustfs_rio::is_checksum_mismatch(inner) + { + return Err(std::io::Error::new(std::io::ErrorKind::InvalidData, e.to_string())); } break; } diff --git a/crates/ecstore/src/erasure_coding/heal.rs b/crates/ecstore/src/erasure_coding/heal.rs index bbcf12f8..e654a678 100644 --- a/crates/ecstore/src/erasure_coding/heal.rs +++ b/crates/ecstore/src/erasure_coding/heal.rs @@ -45,7 +45,7 @@ impl super::Erasure { let start_block = 0; let mut end_block = total_length / self.block_size; - if total_length % self.block_size != 0 { + if !total_length.is_multiple_of(self.block_size) { end_block += 1; } diff --git a/crates/ecstore/src/pools.rs b/crates/ecstore/src/pools.rs index f503ff9d..f0070867 100644 --- a/crates/ecstore/src/pools.rs +++ b/crates/ecstore/src/pools.rs @@ -244,10 +244,12 @@ impl PoolMeta { } pub fn decommission(&mut self, idx: usize, pi: PoolSpaceInfo) -> Result<()> { if let Some(pool) = self.pools.get_mut(idx) { - if let Some(ref info) = pool.decommission { - if !info.complete && !info.failed && !info.canceled { - return Err(StorageError::DecommissionAlreadyRunning); - } + if let Some(ref info) = pool.decommission + && !info.complete + && !info.failed + && !info.canceled + { + return Err(StorageError::DecommissionAlreadyRunning); } let now = OffsetDateTime::now_utc(); @@ -273,12 +275,12 @@ impl PoolMeta { pub fn pending_buckets(&self, idx: usize) -> Vec { let mut list = Vec::new(); - if let Some(pool) = self.pools.get(idx) { - if let Some(ref info) = pool.decommission { - for bk in info.queued_buckets.iter() { - let (name, prefix) = path2_bucket_object(bk); - list.push(DecomBucketInfo { name, prefix }); - } + if let Some(pool) = self.pools.get(idx) + && let Some(ref info) = pool.decommission + { + for bk in info.queued_buckets.iter() { + let (name, prefix) = path2_bucket_object(bk); + list.push(DecomBucketInfo { name, prefix }); } } @@ -306,15 +308,15 @@ impl PoolMeta { } pub fn count_item(&mut self, idx: usize, size: usize, failed: bool) { - if let Some(pool) = self.pools.get_mut(idx) { - if let Some(info) = pool.decommission.as_mut() { - if failed { - info.items_decommission_failed += 1; - info.bytes_failed += size; - } else { - info.items_decommissioned += 1; - info.bytes_done += size; - } + if let Some(pool) = self.pools.get_mut(idx) + && let Some(info) = pool.decommission.as_mut() + { + if failed { + info.items_decommission_failed += 1; + info.bytes_failed += size; + } else { + info.items_decommissioned += 1; + info.bytes_done += size; } } } @@ -324,11 +326,11 @@ impl PoolMeta { return; } - if let Some(pool) = self.pools.get_mut(idx) { - if let Some(info) = pool.decommission.as_mut() { - info.object = object; - info.bucket = bucket; - } + if let Some(pool) = self.pools.get_mut(idx) + && let Some(info) = pool.decommission.as_mut() + { + info.object = object; + info.bucket = bucket; } } @@ -407,10 +409,10 @@ impl PoolMeta { if specified_pools.len() == remembered_pools.len() { for (k, pi) in remembered_pools.iter() { - if let Some(pos) = specified_pools.get(k) { - if *pos != pi.position { - update = true; // Pool order changed, allow the update. - } + if let Some(pos) = specified_pools.get(k) + && *pos != pi.position + { + update = true; // Pool order changed, allow the update. } } } @@ -640,10 +642,12 @@ impl ECStore { pub async fn is_decommission_running(&self) -> bool { let pool_meta = self.pool_meta.read().await; for pool in pool_meta.pools.iter() { - if let Some(ref info) = pool.decommission { - if !info.complete && !info.failed && !info.canceled { - return true; - } + if let Some(ref info) = pool.decommission + && !info.complete + && !info.failed + && !info.canceled + { + return true; } } @@ -850,8 +854,8 @@ impl ECStore { decommissioned += 1; } - if decommissioned == fivs.versions.len() { - if let Err(err) = set + if decommissioned == fivs.versions.len() + && let Err(err) = set .delete_object( bucket.as_str(), &encode_dir_object(&entry.name), @@ -863,9 +867,8 @@ impl ECStore { }, ) .await - { - error!("decommission_pool: delete_object err {:?}", &err); - } + { + error!("decommission_pool: delete_object err {:?}", &err); } { @@ -879,10 +882,8 @@ impl ECStore { .unwrap_or_default(); drop(pool_meta); - if ok { - if let Some(notification_sys) = get_global_notification_sys() { - notification_sys.reload_pool_meta().await; - } + if ok && let Some(notification_sys) = get_global_notification_sys() { + notification_sys.reload_pool_meta().await; } } @@ -1080,10 +1081,10 @@ impl ECStore { { let mut pool_meta = self.pool_meta.write().await; - if pool_meta.bucket_done(idx, bucket.to_string()) { - if let Err(err) = pool_meta.save(self.pools.clone()).await { - error!("decom pool_meta.save err {:?}", err); - } + if pool_meta.bucket_done(idx, bucket.to_string()) + && let Err(err) = pool_meta.save(self.pools.clone()).await + { + error!("decom pool_meta.save err {:?}", err); } } continue; @@ -1100,10 +1101,10 @@ impl ECStore { { let mut pool_meta = self.pool_meta.write().await; - if pool_meta.bucket_done(idx, bucket.to_string()) { - if let Err(err) = pool_meta.save(self.pools.clone()).await { - error!("decom pool_meta.save err {:?}", err); - } + if pool_meta.bucket_done(idx, bucket.to_string()) + && let Err(err) = pool_meta.save(self.pools.clone()).await + { + error!("decom pool_meta.save err {:?}", err); } warn!("decommission: decommission_pool bucket_done {}", &bucket.name); @@ -1138,11 +1139,10 @@ impl ECStore { if let Err(err) = self .make_bucket(bk.to_string_lossy().to_string().as_str(), &MakeBucketOptions::default()) .await + && !is_err_bucket_exists(&err) { - if !is_err_bucket_exists(&err) { - error!("decommission: make bucket failed: {err}"); - return Err(err); - } + error!("decommission: make bucket failed: {err}"); + return Err(err); } } diff --git a/crates/ecstore/src/rebalance.rs b/crates/ecstore/src/rebalance.rs index d58d3a88..5fe75825 100644 --- a/crates/ecstore/src/rebalance.rs +++ b/crates/ecstore/src/rebalance.rs @@ -380,10 +380,10 @@ impl ECStore { #[tracing::instrument(skip(self, fi))] pub async fn update_pool_stats(&self, pool_index: usize, bucket: String, fi: &FileInfo) -> Result<()> { let mut rebalance_meta = self.rebalance_meta.write().await; - if let Some(meta) = rebalance_meta.as_mut() { - if let Some(pool_stat) = meta.pool_stats.get_mut(pool_index) { - pool_stat.update(bucket, fi); - } + if let Some(meta) = rebalance_meta.as_mut() + && let Some(pool_stat) = meta.pool_stats.get_mut(pool_index) + { + pool_stat.update(bucket, fi); } Ok(()) @@ -394,20 +394,20 @@ impl ECStore { info!("next_rebal_bucket: pool_index: {}", pool_index); let rebalance_meta = self.rebalance_meta.read().await; info!("next_rebal_bucket: rebalance_meta: {:?}", rebalance_meta); - if let Some(meta) = rebalance_meta.as_ref() { - if let Some(pool_stat) = meta.pool_stats.get(pool_index) { - if pool_stat.info.status == RebalStatus::Completed || !pool_stat.participating { - info!("next_rebal_bucket: pool_index: {} completed or not participating", pool_index); - return Ok(None); - } - - if pool_stat.buckets.is_empty() { - info!("next_rebal_bucket: pool_index: {} buckets is empty", pool_index); - return Ok(None); - } - info!("next_rebal_bucket: pool_index: {} bucket: {}", pool_index, pool_stat.buckets[0]); - return Ok(Some(pool_stat.buckets[0].clone())); + if let Some(meta) = rebalance_meta.as_ref() + && let Some(pool_stat) = meta.pool_stats.get(pool_index) + { + if pool_stat.info.status == RebalStatus::Completed || !pool_stat.participating { + info!("next_rebal_bucket: pool_index: {} completed or not participating", pool_index); + return Ok(None); } + + if pool_stat.buckets.is_empty() { + info!("next_rebal_bucket: pool_index: {} buckets is empty", pool_index); + return Ok(None); + } + info!("next_rebal_bucket: pool_index: {} bucket: {}", pool_index, pool_stat.buckets[0]); + return Ok(Some(pool_stat.buckets[0].clone())); } info!("next_rebal_bucket: pool_index: {} None", pool_index); @@ -417,28 +417,28 @@ impl ECStore { #[tracing::instrument(skip(self))] pub async fn bucket_rebalance_done(&self, pool_index: usize, bucket: String) -> Result<()> { let mut rebalance_meta = self.rebalance_meta.write().await; - if let Some(meta) = rebalance_meta.as_mut() { - if let Some(pool_stat) = meta.pool_stats.get_mut(pool_index) { - info!("bucket_rebalance_done: buckets {:?}", &pool_stat.buckets); + if let Some(meta) = rebalance_meta.as_mut() + && let Some(pool_stat) = meta.pool_stats.get_mut(pool_index) + { + info!("bucket_rebalance_done: buckets {:?}", &pool_stat.buckets); - // Use retain to filter out buckets slated for removal - let mut found = false; - pool_stat.buckets.retain(|b| { - if b.as_str() == bucket.as_str() { - found = true; - pool_stat.rebalanced_buckets.push(b.clone()); - false // Remove this element - } else { - true // Keep this element - } - }); - - if found { - info!("bucket_rebalance_done: bucket {} rebalanced", &bucket); - return Ok(()); + // Use retain to filter out buckets slated for removal + let mut found = false; + pool_stat.buckets.retain(|b| { + if b.as_str() == bucket.as_str() { + found = true; + pool_stat.rebalanced_buckets.push(b.clone()); + false // Remove this element } else { - info!("bucket_rebalance_done: bucket {} not found", bucket); + true // Keep this element } + }); + + if found { + info!("bucket_rebalance_done: bucket {} rebalanced", &bucket); + return Ok(()); + } else { + info!("bucket_rebalance_done: bucket {} not found", bucket); } } info!("bucket_rebalance_done: bucket {} not found", bucket); @@ -492,10 +492,10 @@ impl ECStore { #[tracing::instrument(skip(self))] pub async fn stop_rebalance(self: &Arc) -> Result<()> { let rebalance_meta = self.rebalance_meta.read().await; - if let Some(meta) = rebalance_meta.as_ref() { - if let Some(cancel_tx) = meta.cancel.as_ref() { - cancel_tx.cancel(); - } + if let Some(meta) = rebalance_meta.as_ref() + && let Some(cancel_tx) = meta.cancel.as_ref() + { + cancel_tx.cancel(); } Ok(()) @@ -690,24 +690,24 @@ impl ECStore { async fn check_if_rebalance_done(&self, pool_index: usize) -> bool { let mut rebalance_meta = self.rebalance_meta.write().await; - if let Some(meta) = rebalance_meta.as_mut() { - if let Some(pool_stat) = meta.pool_stats.get_mut(pool_index) { - // Check if the pool's rebalance status is already completed - if pool_stat.info.status == RebalStatus::Completed { - info!("check_if_rebalance_done: pool {} is already completed", pool_index); - return true; - } + if let Some(meta) = rebalance_meta.as_mut() + && let Some(pool_stat) = meta.pool_stats.get_mut(pool_index) + { + // Check if the pool's rebalance status is already completed + if pool_stat.info.status == RebalStatus::Completed { + info!("check_if_rebalance_done: pool {} is already completed", pool_index); + return true; + } - // Calculate the percentage of free space improvement - let pfi = (pool_stat.init_free_space + pool_stat.bytes) as f64 / pool_stat.init_capacity as f64; + // Calculate the percentage of free space improvement + let pfi = (pool_stat.init_free_space + pool_stat.bytes) as f64 / pool_stat.init_capacity as f64; - // Mark pool rebalance as done if within 5% of the PercentFreeGoal - if (pfi - meta.percent_free_goal).abs() <= 0.05 { - pool_stat.info.status = RebalStatus::Completed; - pool_stat.info.end_time = Some(OffsetDateTime::now_utc()); - info!("check_if_rebalance_done: pool {} is completed, pfi: {}", pool_index, pfi); - return true; - } + // Mark pool rebalance as done if within 5% of the PercentFreeGoal + if (pfi - meta.percent_free_goal).abs() <= 0.05 { + pool_stat.info.status = RebalStatus::Completed; + pool_stat.info.end_time = Some(OffsetDateTime::now_utc()); + info!("check_if_rebalance_done: pool {} is completed, pfi: {}", pool_index, pfi); + return true; } } @@ -1102,11 +1102,11 @@ impl ECStore { pub async fn save_rebalance_stats(&self, pool_idx: usize, opt: RebalSaveOpt) -> Result<()> { // TODO: lock let mut meta = RebalanceMeta::new(); - if let Err(err) = meta.load(self.pools[0].clone()).await { - if err != Error::ConfigNotFound { - info!("save_rebalance_stats: load err: {:?}", err); - return Err(err); - } + if let Err(err) = meta.load(self.pools[0].clone()).await + && err != Error::ConfigNotFound + { + info!("save_rebalance_stats: load err: {:?}", err); + return Err(err); } match opt { diff --git a/crates/ecstore/src/rpc/peer_rest_client.rs b/crates/ecstore/src/rpc/peer_rest_client.rs index c9e79972..178b6a14 100644 --- a/crates/ecstore/src/rpc/peer_rest_client.rs +++ b/crates/ecstore/src/rpc/peer_rest_client.rs @@ -66,13 +66,13 @@ impl PeerRestClient { let mut remote = Vec::with_capacity(hosts.len()); let mut all = vec![None; hosts.len()]; for (i, hs_host) in hosts.iter().enumerate() { - if let Some(host) = hs_host { - if let Some(grid_host) = eps.find_grid_hosts_from_peer(host) { - let client = PeerRestClient::new(host.clone(), grid_host); + if let Some(host) = hs_host + && let Some(grid_host) = eps.find_grid_hosts_from_peer(host) + { + let client = PeerRestClient::new(host.clone(), grid_host); - all[i] = Some(client.clone()); - remote.push(Some(client)); - } + all[i] = Some(client.clone()); + remote.push(Some(client)); } } diff --git a/crates/ecstore/src/rpc/peer_s3_client.rs b/crates/ecstore/src/rpc/peer_s3_client.rs index fe251a3e..fcd89f96 100644 --- a/crates/ecstore/src/rpc/peer_s3_client.rs +++ b/crates/ecstore/src/rpc/peer_s3_client.rs @@ -101,10 +101,10 @@ impl S3PeerSys { for pool_idx in 0..self.pools_count { let mut per_pool_errs = vec![None; self.clients.len()]; for (i, client) in self.clients.iter().enumerate() { - if let Some(v) = client.get_pools() { - if v.contains(&pool_idx) { - per_pool_errs[i] = errs[i].clone(); - } + if let Some(v) = client.get_pools() + && v.contains(&pool_idx) + { + per_pool_errs[i] = errs[i].clone(); } } let qu = per_pool_errs.len() / 2; @@ -136,10 +136,10 @@ impl S3PeerSys { for pool_idx in 0..self.pools_count { let mut per_pool_errs = vec![None; self.clients.len()]; for (i, client) in self.clients.iter().enumerate() { - if let Some(v) = client.get_pools() { - if v.contains(&pool_idx) { - per_pool_errs[i] = errs[i].clone(); - } + if let Some(v) = client.get_pools() + && v.contains(&pool_idx) + { + per_pool_errs[i] = errs[i].clone(); } } let qu = per_pool_errs.len() / 2; diff --git a/crates/ecstore/src/set_disk.rs b/crates/ecstore/src/set_disk.rs index d823f784..782c3690 100644 --- a/crates/ecstore/src/set_disk.rs +++ b/crates/ecstore/src/set_disk.rs @@ -266,10 +266,10 @@ impl SetDisks { let mut new_disk = Vec::with_capacity(disks.len()); for disk in disks.iter() { - if let Some(d) = disk { - if d.is_online().await { - new_disk.push(disk.clone()); - } + if let Some(d) = disk + && d.is_online().await + { + new_disk.push(disk.clone()); } } @@ -1417,22 +1417,21 @@ impl SetDisks { let mut valid_obj_map = HashMap::new(); for (i, op_hash) in meta_hashes.iter().enumerate() { - if let Some(hash) = op_hash { - if let Some(max_hash) = max_val { - if hash == max_hash { - if metas[i].is_valid() && !found { - found_fi = Some(metas[i].clone()); - found = true; - } - - let props = ObjProps { - mod_time: metas[i].mod_time, - num_versions: metas[i].num_versions, - }; - - *valid_obj_map.entry(props).or_insert(0) += 1; - } + if let Some(hash) = op_hash + && let Some(max_hash) = max_val + && hash == max_hash + { + if metas[i].is_valid() && !found { + found_fi = Some(metas[i].clone()); + found = true; } + + let props = ObjProps { + mod_time: metas[i].mod_time, + num_versions: metas[i].num_versions, + }; + + *valid_obj_map.entry(props).or_insert(0) += 1; } } @@ -3572,17 +3571,17 @@ impl SetDisks { let mut offline = 0; for (i, err) in errs.iter().enumerate() { let mut found = false; - if let Some(err) = err { - if err == &DiskError::DiskNotFound { - found = true; - } + if let Some(err) = err + && err == &DiskError::DiskNotFound + { + found = true; } for p in data_errs_by_part { - if let Some(v) = p.1.get(i) { - if *v == CHECK_PART_DISK_NOT_FOUND { - found = true; - break; - } + if let Some(v) = p.1.get(i) + && *v == CHECK_PART_DISK_NOT_FOUND + { + found = true; + break; } } @@ -3838,10 +3837,10 @@ impl ObjectIO for SetDisks { None }; - if let Some(http_preconditions) = opts.http_preconditions.clone() { - if let Some(err) = self.check_write_precondition(bucket, object, opts).await { - return Err(err); - } + if let Some(http_preconditions) = opts.http_preconditions.clone() + && let Some(err) = self.check_write_precondition(bucket, object, opts).await + { + return Err(err); } let mut user_defined = opts.user_defined.clone(); @@ -4002,16 +4001,16 @@ impl ObjectIO for SetDisks { } } - if fi.checksum.is_none() { - if let Some(content_hash) = data.as_hash_reader().content_hash() { - fi.checksum = Some(content_hash.to_bytes(&[])); - } + if fi.checksum.is_none() + && let Some(content_hash) = data.as_hash_reader().content_hash() + { + fi.checksum = Some(content_hash.to_bytes(&[])); } - if let Some(sc) = user_defined.get(AMZ_STORAGE_CLASS) { - if sc == storageclass::STANDARD { - let _ = user_defined.remove(AMZ_STORAGE_CLASS); - } + if let Some(sc) = user_defined.get(AMZ_STORAGE_CLASS) + && sc == storageclass::STANDARD + { + let _ = user_defined.remove(AMZ_STORAGE_CLASS); } let mod_time = if let Some(mod_time) = opts.mod_time { @@ -4062,11 +4061,11 @@ impl ObjectIO for SetDisks { self.delete_all(RUSTFS_META_TMP_BUCKET, &tmp_dir).await?; for (i, op_disk) in online_disks.iter().enumerate() { - if let Some(disk) = op_disk { - if disk.is_online().await { - fi = parts_metadatas[i].clone(); - break; - } + if let Some(disk) = op_disk + && disk.is_online().await + { + fi = parts_metadatas[i].clone(); + break; } } @@ -5568,10 +5567,10 @@ impl StorageAPI for SetDisks { user_defined.insert("etag".to_owned(), etag.clone()); } - if let Some(sc) = user_defined.get(AMZ_STORAGE_CLASS) { - if sc == storageclass::STANDARD { - let _ = user_defined.remove(AMZ_STORAGE_CLASS); - } + if let Some(sc) = user_defined.get(AMZ_STORAGE_CLASS) + && sc == storageclass::STANDARD + { + let _ = user_defined.remove(AMZ_STORAGE_CLASS); } let sc_parity_drives = { @@ -5620,10 +5619,10 @@ impl StorageAPI for SetDisks { // TODO: get content-type } - if let Some(sc) = user_defined.get(AMZ_STORAGE_CLASS) { - if sc == storageclass::STANDARD { - let _ = user_defined.remove(AMZ_STORAGE_CLASS); - } + if let Some(sc) = user_defined.get(AMZ_STORAGE_CLASS) + && sc == storageclass::STANDARD + { + let _ = user_defined.remove(AMZ_STORAGE_CLASS); } if let Some(checksum) = &opts.want_checksum { @@ -5925,14 +5924,14 @@ impl StorageAPI for SetDisks { return Err(Error::InvalidPart(p.part_num, ext_part.etag.clone(), p.etag.clone().unwrap_or_default())); } - if checksum_type.full_object_requested() { - if let Err(err) = checksum.add_part(&cs, ext_part.actual_size) { - error!( - "complete_multipart_upload checksum add_part failed part_id={}, bucket={}, object={}", - p.part_num, bucket, object - ); - return Err(Error::InvalidPart(p.part_num, ext_part.etag.clone(), p.etag.clone().unwrap_or_default())); - } + if checksum_type.full_object_requested() + && let Err(err) = checksum.add_part(&cs, ext_part.actual_size) + { + error!( + "complete_multipart_upload checksum add_part failed part_id={}, bucket={}, object={}", + p.part_num, bucket, object + ); + return Err(Error::InvalidPart(p.part_num, ext_part.etag.clone(), p.etag.clone().unwrap_or_default())); } checksum_combined.extend_from_slice(cs.raw.as_slice()); @@ -6112,11 +6111,11 @@ impl StorageAPI for SetDisks { }); for (i, op_disk) in online_disks.iter().enumerate() { - if let Some(disk) = op_disk { - if disk.is_online().await { - fi = parts_metadatas[i].clone(); - break; - } + if let Some(disk) = op_disk + && disk.is_online().await + { + fi = parts_metadatas[i].clone(); + break; } } @@ -6210,16 +6209,15 @@ impl StorageAPI for SetDisks { let _write_lock_guard = if !opts.no_lock { let key = rustfs_lock::fast_lock::types::ObjectKey::new(bucket, object); let mut skip_lock = false; - if let Some(lock_info) = self.fast_lock_manager.get_lock_info(&key) { - if lock_info.owner.as_ref() == self.locker_owner.as_str() - && matches!(lock_info.mode, rustfs_lock::fast_lock::types::LockMode::Exclusive) - { - debug!( - "Reusing existing exclusive lock for heal operation on {}/{} held by {}", - bucket, object, self.locker_owner - ); - skip_lock = true; - } + if let Some(lock_info) = self.fast_lock_manager.get_lock_info(&key) + && lock_info.owner.as_ref() == self.locker_owner.as_str() + && matches!(lock_info.mode, rustfs_lock::fast_lock::types::LockMode::Exclusive) + { + debug!( + "Reusing existing exclusive lock for heal operation on {}/{} held by {}", + bucket, object, self.locker_owner + ); + skip_lock = true; } if skip_lock { None @@ -6563,14 +6561,14 @@ async fn disks_with_all_parts( if err.is_some() { let part_err = conv_part_err_to_int(err); for p in 0..latest_meta.parts.len() { - if let Some(vec) = data_errs_by_part.get_mut(&p) { - if index < vec.len() { - info!( - "data_errs_by_part: copy meta errors to part errors: object_name={}, index: {index}, part: {p}, part_err: {part_err}", - object_name - ); - vec[index] = part_err; - } + if let Some(vec) = data_errs_by_part.get_mut(&p) + && index < vec.len() + { + info!( + "data_errs_by_part: copy meta errors to part errors: object_name={}, index: {index}, part: {p}, part_err: {part_err}", + object_name + ); + vec[index] = part_err; } } } @@ -6609,14 +6607,14 @@ async fn disks_with_all_parts( .await .err(); - if let Some(vec) = data_errs_by_part.get_mut(&0) { - if index < vec.len() { - vec[index] = conv_part_err_to_int(&verify_err.map(|e| e.into())); - info!( - "data_errs_by_part:bitrot check result: object_name={}, index: {index}, result: {}", - object_name, vec[index] - ); - } + if let Some(vec) = data_errs_by_part.get_mut(&0) + && index < vec.len() + { + vec[index] = conv_part_err_to_int(&verify_err.map(|e| e.into())); + info!( + "data_errs_by_part:bitrot check result: object_name={}, index: {index}, result: {}", + object_name, vec[index] + ); } } continue; @@ -6654,32 +6652,32 @@ async fn disks_with_all_parts( // Update dataErrsByPart for all parts for p in 0..latest_meta.parts.len() { - if let Some(vec) = data_errs_by_part.get_mut(&p) { - if index < vec.len() { - if verify_err.is_some() { + if let Some(vec) = data_errs_by_part.get_mut(&p) + && index < vec.len() + { + if verify_err.is_some() { + info!( + "data_errs_by_part: verify_err: object_name={}, index: {index}, part: {p}, verify_err: {verify_err:?}", + object_name + ); + vec[index] = conv_part_err_to_int(&verify_err.clone()); + } else { + // Fix: verify_resp.results length is based on meta.parts, not latest_meta.parts + // We need to check bounds to avoid panic + if p < verify_resp.results.len() { info!( - "data_errs_by_part: verify_err: object_name={}, index: {index}, part: {p}, verify_err: {verify_err:?}", + "data_errs_by_part: update data_errs_by_part: object_name={}, index: {}, part: {}, verify_resp.results: {:?}", + object_name, index, p, verify_resp.results[p] + ); + vec[index] = verify_resp.results[p]; + } else { + debug!( + "data_errs_by_part: verify_resp.results length mismatch: expected at least {}, got {}, object_name={}, index: {index}, part: {p}", + p + 1, + verify_resp.results.len(), object_name ); - vec[index] = conv_part_err_to_int(&verify_err.clone()); - } else { - // Fix: verify_resp.results length is based on meta.parts, not latest_meta.parts - // We need to check bounds to avoid panic - if p < verify_resp.results.len() { - info!( - "data_errs_by_part: update data_errs_by_part: object_name={}, index: {}, part: {}, verify_resp.results: {:?}", - object_name, index, p, verify_resp.results[p] - ); - vec[index] = verify_resp.results[p]; - } else { - debug!( - "data_errs_by_part: verify_resp.results length mismatch: expected at least {}, got {}, object_name={}, index: {index}, part: {p}", - p + 1, - verify_resp.results.len(), - object_name - ); - vec[index] = CHECK_PART_SUCCESS; - } + vec[index] = CHECK_PART_SUCCESS; } } } @@ -6689,14 +6687,14 @@ async fn disks_with_all_parts( // Build dataErrsByDisk from dataErrsByPart for (part, disks) in data_errs_by_part.iter() { for (disk_idx, disk_err) in disks.iter().enumerate() { - if let Some(vec) = data_errs_by_disk.get_mut(&disk_idx) { - if *part < vec.len() { - vec[*part] = *disk_err; - info!( - "data_errs_by_disk: update data_errs_by_disk: object_name={}, part: {part}, disk_idx: {disk_idx}, disk_err: {disk_err}", - object_name, - ); - } + if let Some(vec) = data_errs_by_disk.get_mut(&disk_idx) + && *part < vec.len() + { + vec[*part] = *disk_err; + info!( + "data_errs_by_disk: update data_errs_by_disk: object_name={}, part: {part}, disk_idx: {disk_idx}, disk_err: {disk_err}", + object_name, + ); } } } @@ -6738,10 +6736,10 @@ pub fn should_heal_object_on_disk( meta: &FileInfo, latest_meta: &FileInfo, ) -> (bool, Option) { - if let Some(err) = err { - if err == &DiskError::FileNotFound || err == &DiskError::FileVersionNotFound || err == &DiskError::FileCorrupt { - return (true, Some(err.clone())); - } + if let Some(err) = err + && (err == &DiskError::FileNotFound || err == &DiskError::FileVersionNotFound || err == &DiskError::FileCorrupt) + { + return (true, Some(err.clone())); } if latest_meta.volume != meta.volume @@ -6906,15 +6904,15 @@ pub fn e_tag_matches(etag: &str, condition: &str) -> bool { pub fn should_prevent_write(oi: &ObjectInfo, if_none_match: Option, if_match: Option) -> bool { match &oi.etag { Some(etag) => { - if let Some(if_none_match) = if_none_match { - if e_tag_matches(etag, &if_none_match) { - return true; - } + if let Some(if_none_match) = if_none_match + && e_tag_matches(etag, &if_none_match) + { + return true; } - if let Some(if_match) = if_match { - if !e_tag_matches(etag, &if_match) { - return true; - } + if let Some(if_match) = if_match + && !e_tag_matches(etag, &if_match) + { + return true; } false } diff --git a/crates/ecstore/src/sets.rs b/crates/ecstore/src/sets.rs index ad6fc5c9..a2d3769a 100644 --- a/crates/ecstore/src/sets.rs +++ b/crates/ecstore/src/sets.rs @@ -491,12 +491,12 @@ impl StorageAPI for Sets { let cp_src_dst_same = path_join_buf(&[src_bucket, src_object]) == path_join_buf(&[dst_bucket, dst_object]); if cp_src_dst_same { - if let (Some(src_vid), Some(dst_vid)) = (&src_opts.version_id, &dst_opts.version_id) { - if src_vid == dst_vid { - return src_set - .copy_object(src_bucket, src_object, dst_bucket, dst_object, src_info, src_opts, dst_opts) - .await; - } + if let (Some(src_vid), Some(dst_vid)) = (&src_opts.version_id, &dst_opts.version_id) + && src_vid == dst_vid + { + return src_set + .copy_object(src_bucket, src_object, dst_bucket, dst_object, src_info, src_opts, dst_opts) + .await; } if !dst_opts.versioned && src_opts.version_id.is_none() { @@ -823,10 +823,10 @@ impl StorageAPI for Sets { Ok((m, n)) => (m, n), Err(_) => continue, }; - if let Some(set) = self.disk_set.get(m) { - if let Some(Some(disk)) = set.disks.read().await.get(n) { - let _ = disk.close().await; - } + if let Some(set) = self.disk_set.get(m) + && let Some(Some(disk)) = set.disks.read().await.get(n) + { + let _ = disk.close().await; } if let Some(Some(disk)) = disks.get(index) { @@ -980,25 +980,24 @@ fn new_heal_format_sets( let mut current_disks_info = vec![vec![DiskInfo::default(); set_drive_count]; set_count]; for (i, set) in ref_format.erasure.sets.iter().enumerate() { for j in 0..set.len() { - if let Some(Some(err)) = errs.get(i * set_drive_count + j) { - if *err == DiskError::UnformattedDisk { - let mut fm = FormatV3::new(set_count, set_drive_count); - fm.id = ref_format.id; - fm.format = ref_format.format.clone(); - fm.version = ref_format.version.clone(); - fm.erasure.this = ref_format.erasure.sets[i][j]; - fm.erasure.sets = ref_format.erasure.sets.clone(); - fm.erasure.version = ref_format.erasure.version.clone(); - fm.erasure.distribution_algo = ref_format.erasure.distribution_algo.clone(); - new_formats[i][j] = Some(fm); - } + if let Some(Some(err)) = errs.get(i * set_drive_count + j) + && *err == DiskError::UnformattedDisk + { + let mut fm = FormatV3::new(set_count, set_drive_count); + fm.id = ref_format.id; + fm.format = ref_format.format.clone(); + fm.version = ref_format.version.clone(); + fm.erasure.this = ref_format.erasure.sets[i][j]; + fm.erasure.sets = ref_format.erasure.sets.clone(); + fm.erasure.version = ref_format.erasure.version.clone(); + fm.erasure.distribution_algo = ref_format.erasure.distribution_algo.clone(); + new_formats[i][j] = Some(fm); } - if let (Some(format), None) = (&formats[i * set_drive_count + j], &errs[i * set_drive_count + j]) { - if let Some(info) = &format.disk_info { - if !info.endpoint.is_empty() { - current_disks_info[i][j] = info.clone(); - } - } + if let (Some(format), None) = (&formats[i * set_drive_count + j], &errs[i * set_drive_count + j]) + && let Some(info) = &format.disk_info + && !info.endpoint.is_empty() + { + current_disks_info[i][j] = info.clone(); } } } diff --git a/crates/ecstore/src/store.rs b/crates/ecstore/src/store.rs index 23f127e5..4d4ed7a4 100644 --- a/crates/ecstore/src/store.rs +++ b/crates/ecstore/src/store.rs @@ -243,10 +243,10 @@ impl ECStore { }); // Only set it when the global deployment ID is not yet configured - if let Some(dep_id) = deployment_id { - if get_global_deployment_id().is_none() { - set_global_deployment_id(dep_id); - } + if let Some(dep_id) = deployment_id + && get_global_deployment_id().is_none() + { + set_global_deployment_id(dep_id); } let wait_sec = 5; @@ -768,10 +768,10 @@ impl ECStore { def_pool = pinfo.clone(); has_def_pool = true; // https://docs.aws.amazon.com/AmazonS3/latest/userguide/conditional-deletes.html - if is_err_object_not_found(err) { - if let Err(err) = opts.precondition_check(&pinfo.object_info) { - return Err(err.clone()); - } + if is_err_object_not_found(err) + && let Err(err) = opts.precondition_check(&pinfo.object_info) + { + return Err(err.clone()); } if !is_err_object_not_found(err) && !is_err_version_not_found(err) { @@ -885,13 +885,14 @@ impl ECStore { return Ok((obj, res.idx)); } - if let Some(err) = res.err { - if !is_err_object_not_found(&err) && !is_err_version_not_found(&err) { - return Err(err); - } - - // TODO: delete marker + if let Some(err) = res.err + && !is_err_object_not_found(&err) + && !is_err_version_not_found(&err) + { + return Err(err); } + + // TODO: delete marker } let object = decode_dir_object(object); @@ -918,12 +919,12 @@ impl ECStore { let mut derrs = Vec::new(); for pe in errs.iter() { - if let Some(err) = &pe.err { - if err == &StorageError::ErasureWriteQuorum { - objs.push(None); - derrs.push(Some(StorageError::ErasureWriteQuorum)); - continue; - } + if let Some(err) = &pe.err + && err == &StorageError::ErasureWriteQuorum + { + objs.push(None); + derrs.push(Some(StorageError::ErasureWriteQuorum)); + continue; } if let Some(idx) = pe.index { @@ -1226,14 +1227,14 @@ impl StorageAPI for ECStore { #[instrument(skip(self))] async fn make_bucket(&self, bucket: &str, opts: &MakeBucketOptions) -> Result<()> { - if !is_meta_bucketname(bucket) { - if let Err(err) = check_valid_bucket_name_strict(bucket) { - return Err(StorageError::BucketNameInvalid(err.to_string())); - } - - // TODO: nslock + if !is_meta_bucketname(bucket) + && let Err(err) = check_valid_bucket_name_strict(bucket) + { + return Err(StorageError::BucketNameInvalid(err.to_string())); } + // TODO: nslock + if let Err(err) = self.peer_sys.make_bucket(bucket, opts).await { let err = to_object_err(err.into(), vec![bucket]); if !is_err_bucket_exists(&err) { @@ -1427,12 +1428,12 @@ impl StorageAPI for ECStore { let pool_idx = self.get_pool_idx_no_lock(src_bucket, &src_object, src_info.size).await?; if cp_src_dst_same { - if let (Some(src_vid), Some(dst_vid)) = (&src_opts.version_id, &dst_opts.version_id) { - if src_vid == dst_vid { - return self.pools[pool_idx] - .copy_object(src_bucket, &src_object, dst_bucket, &dst_object, src_info, src_opts, dst_opts) - .await; - } + if let (Some(src_vid), Some(dst_vid)) = (&src_opts.version_id, &dst_opts.version_id) + && src_vid == dst_vid + { + return self.pools[pool_idx] + .copy_object(src_bucket, &src_object, dst_bucket, &dst_object, src_info, src_opts, dst_opts) + .await; } if !dst_opts.versioned && src_opts.version_id.is_none() { @@ -2433,13 +2434,13 @@ fn check_list_multipart_args( check_list_objs_args(bucket, prefix, key_marker)?; if let Some(upload_id_marker) = upload_id_marker { - if let Some(key_marker) = key_marker { - if key_marker.ends_with('/') { - return Err(StorageError::InvalidUploadIDKeyCombination( - upload_id_marker.to_string(), - key_marker.to_string(), - )); - } + if let Some(key_marker) = key_marker + && key_marker.ends_with('/') + { + return Err(StorageError::InvalidUploadIDKeyCombination( + upload_id_marker.to_string(), + key_marker.to_string(), + )); } if let Err(_e) = base64_simd::URL_SAFE_NO_PAD.decode_to_vec(upload_id_marker.as_bytes()) { @@ -2510,10 +2511,10 @@ pub async fn get_disk_infos(disks: &[Option]) -> Vec let opts = &DiskInfoOptions::default(); let mut res = vec![None; disks.len()]; for (idx, disk_op) in disks.iter().enumerate() { - if let Some(disk) = disk_op { - if let Ok(info) = disk.disk_info(opts).await { - res[idx] = Some(info); - } + if let Some(disk) = disk_op + && let Ok(info) = disk.disk_info(opts).await + { + res[idx] = Some(info); } } diff --git a/crates/ecstore/src/store_api.rs b/crates/ecstore/src/store_api.rs index 7c3ce857..ccf6aa43 100644 --- a/crates/ecstore/src/store_api.rs +++ b/crates/ecstore/src/store_api.rs @@ -144,10 +144,10 @@ impl GetObjectReader { ) -> Result<(Self, usize, i64)> { let mut rs = rs; - if let Some(part_number) = opts.part_number { - if rs.is_none() { - rs = HTTPRangeSpec::from_object_info(oi, part_number); - } + if let Some(part_number) = opts.part_number + && rs.is_none() + { + rs = HTTPRangeSpec::from_object_info(oi, part_number); } // TODO:Encrypted @@ -462,32 +462,30 @@ impl ObjectOptions { pub fn precondition_check(&self, obj_info: &ObjectInfo) -> Result<()> { let has_valid_mod_time = obj_info.mod_time.is_some_and(|t| t != OffsetDateTime::UNIX_EPOCH); - if let Some(part_number) = self.part_number { - if part_number > 1 && !obj_info.parts.is_empty() { - let part_found = obj_info.parts.iter().any(|pi| pi.number == part_number); - if !part_found { - return Err(Error::InvalidPartNumber(part_number)); - } + if let Some(part_number) = self.part_number + && part_number > 1 + && !obj_info.parts.is_empty() + { + let part_found = obj_info.parts.iter().any(|pi| pi.number == part_number); + if !part_found { + return Err(Error::InvalidPartNumber(part_number)); } } if let Some(pre) = &self.http_preconditions { - if let Some(if_none_match) = &pre.if_none_match { - if let Some(etag) = &obj_info.etag { - if is_etag_equal(etag, if_none_match) { - return Err(Error::NotModified); - } - } + if let Some(if_none_match) = &pre.if_none_match + && let Some(etag) = &obj_info.etag + && is_etag_equal(etag, if_none_match) + { + return Err(Error::NotModified); } - if has_valid_mod_time { - if let Some(if_modified_since) = &pre.if_modified_since { - if let Some(mod_time) = &obj_info.mod_time { - if !is_modified_since(mod_time, if_modified_since) { - return Err(Error::NotModified); - } - } - } + if has_valid_mod_time + && let Some(if_modified_since) = &pre.if_modified_since + && let Some(mod_time) = &obj_info.mod_time + && !is_modified_since(mod_time, if_modified_since) + { + return Err(Error::NotModified); } if let Some(if_match) = &pre.if_match { @@ -499,14 +497,13 @@ impl ObjectOptions { return Err(Error::PreconditionFailed); } } - if has_valid_mod_time && pre.if_match.is_none() { - if let Some(if_unmodified_since) = &pre.if_unmodified_since { - if let Some(mod_time) = &obj_info.mod_time { - if is_modified_since(mod_time, if_unmodified_since) { - return Err(Error::PreconditionFailed); - } - } - } + if has_valid_mod_time + && pre.if_match.is_none() + && let Some(if_unmodified_since) = &pre.if_unmodified_since + && let Some(mod_time) = &obj_info.mod_time + && is_modified_since(mod_time, if_unmodified_since) + { + return Err(Error::PreconditionFailed); } } @@ -698,12 +695,12 @@ impl ObjectInfo { } if self.is_compressed() { - if let Some(size_str) = self.user_defined.get(&format!("{RESERVED_METADATA_PREFIX_LOWER}actual-size")) { - if !size_str.is_empty() { - // Todo: deal with error - let size = size_str.parse::().map_err(|e| std::io::Error::other(e.to_string()))?; - return Ok(size); - } + if let Some(size_str) = self.user_defined.get(&format!("{RESERVED_METADATA_PREFIX_LOWER}actual-size")) + && !size_str.is_empty() + { + // Todo: deal with error + let size = size_str.parse::().map_err(|e| std::io::Error::other(e.to_string()))?; + return Ok(size); } let mut actual_size = 0; self.parts.iter().for_each(|part| { @@ -881,32 +878,31 @@ impl ObjectInfo { continue; } - if entry.is_dir() { - if let Some(delimiter) = &delimiter { - if let Some(idx) = { - let remaining = if entry.name.starts_with(prefix) { - &entry.name[prefix.len()..] - } else { - entry.name.as_str() - }; - remaining.find(delimiter.as_str()) - } { - let idx = prefix.len() + idx + delimiter.len(); - if let Some(curr_prefix) = entry.name.get(0..idx) { - if curr_prefix == prev_prefix { - continue; - } - - prev_prefix = curr_prefix; - - objects.push(ObjectInfo { - is_dir: true, - bucket: bucket.to_owned(), - name: curr_prefix.to_owned(), - ..Default::default() - }); - } + if entry.is_dir() + && let Some(delimiter) = &delimiter + && let Some(idx) = { + let remaining = if entry.name.starts_with(prefix) { + &entry.name[prefix.len()..] + } else { + entry.name.as_str() + }; + remaining.find(delimiter.as_str()) + } + { + let idx = prefix.len() + idx + delimiter.len(); + if let Some(curr_prefix) = entry.name.get(0..idx) { + if curr_prefix == prev_prefix { + continue; } + + prev_prefix = curr_prefix; + + objects.push(ObjectInfo { + is_dir: true, + bucket: bucket.to_owned(), + name: curr_prefix.to_owned(), + ..Default::default() + }); } } } @@ -966,32 +962,31 @@ impl ObjectInfo { continue; } - if entry.is_dir() { - if let Some(delimiter) = &delimiter { - if let Some(idx) = { - let remaining = if entry.name.starts_with(prefix) { - &entry.name[prefix.len()..] - } else { - entry.name.as_str() - }; - remaining.find(delimiter.as_str()) - } { - let idx = prefix.len() + idx + delimiter.len(); - if let Some(curr_prefix) = entry.name.get(0..idx) { - if curr_prefix == prev_prefix { - continue; - } - - prev_prefix = curr_prefix; - - objects.push(ObjectInfo { - is_dir: true, - bucket: bucket.to_owned(), - name: curr_prefix.to_owned(), - ..Default::default() - }); - } + if entry.is_dir() + && let Some(delimiter) = &delimiter + && let Some(idx) = { + let remaining = if entry.name.starts_with(prefix) { + &entry.name[prefix.len()..] + } else { + entry.name.as_str() + }; + remaining.find(delimiter.as_str()) + } + { + let idx = prefix.len() + idx + delimiter.len(); + if let Some(curr_prefix) = entry.name.get(0..idx) { + if curr_prefix == prev_prefix { + continue; } + + prev_prefix = curr_prefix; + + objects.push(ObjectInfo { + is_dir: true, + bucket: bucket.to_owned(), + name: curr_prefix.to_owned(), + ..Default::default() + }); } } } @@ -1026,10 +1021,10 @@ impl ObjectInfo { } pub fn decrypt_checksums(&self, part: usize, _headers: &HeaderMap) -> Result<(HashMap, bool)> { - if part > 0 { - if let Some(checksums) = self.parts.iter().find(|p| p.number == part).and_then(|p| p.checksums.clone()) { - return Ok((checksums, true)); - } + if part > 0 + && let Some(checksums) = self.parts.iter().find(|p| p.number == part).and_then(|p| p.checksums.clone()) + { + return Ok((checksums, true)); } // TODO: decrypt checksums diff --git a/crates/ecstore/src/store_list_objects.rs b/crates/ecstore/src/store_list_objects.rs index 214718ab..a1977969 100644 --- a/crates/ecstore/src/store_list_objects.rs +++ b/crates/ecstore/src/store_list_objects.rs @@ -302,10 +302,10 @@ impl ECStore { ..Default::default() }); - if let Some(err) = list_result.err.clone() { - if err != rustfs_filemeta::Error::Unexpected { - return Err(to_object_err(err.into(), vec![bucket, prefix])); - } + if let Some(err) = list_result.err.clone() + && err != rustfs_filemeta::Error::Unexpected + { + return Err(to_object_err(err.into(), vec![bucket, prefix])); } if let Some(result) = list_result.entries.as_mut() { @@ -418,10 +418,10 @@ impl ECStore { }, }; - if let Some(err) = list_result.err.clone() { - if err != rustfs_filemeta::Error::Unexpected { - return Err(to_object_err(err.into(), vec![bucket, prefix])); - } + if let Some(err) = list_result.err.clone() + && err != rustfs_filemeta::Error::Unexpected + { + return Err(to_object_err(err.into(), vec![bucket, prefix])); } if let Some(result) = list_result.entries.as_mut() { @@ -509,10 +509,11 @@ impl ECStore { let mut o = o.clone(); o.marker = o.marker.filter(|v| v >= &o.prefix); - if let Some(marker) = &o.marker { - if !o.prefix.is_empty() && !marker.starts_with(&o.prefix) { - return Err(Error::Unexpected); - } + if let Some(marker) = &o.marker + && !o.prefix.is_empty() + && !marker.starts_with(&o.prefix) + { + return Err(Error::Unexpected); } if o.limit == 0 { @@ -817,10 +818,10 @@ impl ECStore { let value = tx2.clone(); let resolver = resolver.clone(); async move { - if let Some(entry) = entries.resolve(resolver) { - if let Err(err) = value.send(entry).await { - error!("list_path send fail {:?}", err); - } + if let Some(entry) = entries.resolve(resolver) + && let Err(err) = value.send(entry).await + { + error!("list_path send fail {:?}", err); } } }) @@ -986,20 +987,21 @@ async fn gather_results( continue; } - if let Some(marker) = &opts.marker { - if &entry.name < marker { - continue; - } + if let Some(marker) = &opts.marker + && &entry.name < marker + { + continue; } if !entry.name.starts_with(&opts.prefix) { continue; } - if let Some(separator) = &opts.separator { - if !opts.recursive && !entry.is_in_dir(&opts.prefix, separator) { - continue; - } + if let Some(separator) = &opts.separator + && !opts.recursive + && !entry.is_in_dir(&opts.prefix, separator) + { + continue; } if !opts.incl_deleted && entry.is_object() && entry.is_latest_delete_marker() && !entry.is_object_dir() { @@ -1200,16 +1202,16 @@ async fn merge_entry_channels( } } - if let Some(xl) = has_xl.as_mut() { - if !versions.is_empty() { - xl.versions = merge_file_meta_versions(read_quorum, true, 0, &versions); + if let Some(xl) = has_xl.as_mut() + && !versions.is_empty() + { + xl.versions = merge_file_meta_versions(read_quorum, true, 0, &versions); - if let Ok(meta) = xl.marshal_msg() { - if let Some(b) = best.as_mut() { - b.metadata = meta; - b.cached = Some(xl.clone()); - } - } + if let Ok(meta) = xl.marshal_msg() + && let Some(b) = best.as_mut() + { + b.metadata = meta; + b.cached = Some(xl.clone()); } } } @@ -1217,11 +1219,11 @@ async fn merge_entry_channels( to_merge.clear(); } - if let Some(best_entry) = &best { - if best_entry.name > last { - out_channel.send(best_entry.clone()).await.map_err(Error::other)?; - last = best_entry.name.clone(); - } + if let Some(best_entry) = &best + && best_entry.name > last + { + out_channel.send(best_entry.clone()).await.map_err(Error::other)?; + last = best_entry.name.clone(); } select_from(&mut in_channels, best_idx, &mut top, &mut n_done).await?; @@ -1307,10 +1309,10 @@ impl SetDisks { let value = tx2.clone(); let resolver = resolver.clone(); async move { - if let Some(entry) = entries.resolve(resolver) { - if let Err(err) = value.send(entry).await { - error!("list_path send fail {:?}", err); - } + if let Some(entry) = entries.resolve(resolver) + && let Err(err) = value.send(entry).await + { + error!("list_path send fail {:?}", err); } } }) diff --git a/crates/filemeta/src/fileinfo.rs b/crates/filemeta/src/fileinfo.rs index 12c48bab..d56420ba 100644 --- a/crates/filemeta/src/fileinfo.rs +++ b/crates/filemeta/src/fileinfo.rs @@ -635,10 +635,10 @@ fn parse_restore_obj_status(restore_hdr: &str) -> Result { } pub fn is_restored_object_on_disk(meta: &HashMap) -> bool { - if let Some(restore_hdr) = meta.get(X_AMZ_RESTORE.as_str()) { - if let Ok(restore_status) = parse_restore_obj_status(restore_hdr) { - return restore_status.on_disk(); - } + if let Some(restore_hdr) = meta.get(X_AMZ_RESTORE.as_str()) + && let Ok(restore_status) = parse_restore_obj_status(restore_hdr) + { + return restore_status.on_disk(); } false } diff --git a/crates/filemeta/src/filemeta.rs b/crates/filemeta/src/filemeta.rs index d878967c..38d0b677 100644 --- a/crates/filemeta/src/filemeta.rs +++ b/crates/filemeta/src/filemeta.rs @@ -575,13 +575,12 @@ impl FileMeta { let mod_time = version.get_mod_time(); for (idx, exist) in self.versions.iter().enumerate() { - if let Some(ref ex_mt) = exist.header.mod_time { - if let Some(ref in_md) = mod_time { - if ex_mt <= in_md { - self.versions.insert(idx, FileMetaShallowVersion::try_from(version)?); - return Ok(()); - } - } + if let Some(ref ex_mt) = exist.header.mod_time + && let Some(ref in_md) = mod_time + && ex_mt <= in_md + { + self.versions.insert(idx, FileMetaShallowVersion::try_from(version)?); + return Ok(()); } } Err(Error::other("add_version failed")) @@ -657,58 +656,44 @@ impl FileMeta { } if fi.deleted { - if !fi.delete_marker_replication_status().is_empty() { - if let Some(delete_marker) = ventry.delete_marker.as_mut() { - if fi.delete_marker_replication_status() == ReplicationStatusType::Replica { - delete_marker.meta_sys.insert( - format!("{}{}", RESERVED_METADATA_PREFIX_LOWER, "replica-status"), - fi.replication_state_internal - .as_ref() - .map(|v| v.replica_status.clone()) - .unwrap_or_default() - .as_str() - .as_bytes() - .to_vec(), - ); - delete_marker.meta_sys.insert( - format!("{}{}", RESERVED_METADATA_PREFIX_LOWER, "replica-timestamp"), - fi.replication_state_internal - .as_ref() - .map(|v| v.replica_timestamp.unwrap_or(OffsetDateTime::UNIX_EPOCH).to_string()) - .unwrap_or_default() - .as_bytes() - .to_vec(), - ); - } else { - delete_marker.meta_sys.insert( - format!("{}{}", RESERVED_METADATA_PREFIX_LOWER, "replication-status"), - fi.replication_state_internal - .as_ref() - .map(|v| v.replication_status_internal.clone().unwrap_or_default()) - .unwrap_or_default() - .as_bytes() - .to_vec(), - ); - delete_marker.meta_sys.insert( - format!("{}{}", RESERVED_METADATA_PREFIX_LOWER, "replication-timestamp"), - fi.replication_state_internal - .as_ref() - .map(|v| v.replication_timestamp.unwrap_or(OffsetDateTime::UNIX_EPOCH).to_string()) - .unwrap_or_default() - .as_bytes() - .to_vec(), - ); - } - } - } - - if !fi.version_purge_status().is_empty() { - if let Some(delete_marker) = ventry.delete_marker.as_mut() { + if !fi.delete_marker_replication_status().is_empty() + && let Some(delete_marker) = ventry.delete_marker.as_mut() + { + if fi.delete_marker_replication_status() == ReplicationStatusType::Replica { delete_marker.meta_sys.insert( - VERSION_PURGE_STATUS_KEY.to_string(), + format!("{}{}", RESERVED_METADATA_PREFIX_LOWER, "replica-status"), fi.replication_state_internal .as_ref() - .map(|v| v.version_purge_status_internal.clone().unwrap_or_default()) + .map(|v| v.replica_status.clone()) + .unwrap_or_default() + .as_str() + .as_bytes() + .to_vec(), + ); + delete_marker.meta_sys.insert( + format!("{}{}", RESERVED_METADATA_PREFIX_LOWER, "replica-timestamp"), + fi.replication_state_internal + .as_ref() + .map(|v| v.replica_timestamp.unwrap_or(OffsetDateTime::UNIX_EPOCH).to_string()) + .unwrap_or_default() + .as_bytes() + .to_vec(), + ); + } else { + delete_marker.meta_sys.insert( + format!("{}{}", RESERVED_METADATA_PREFIX_LOWER, "replication-status"), + fi.replication_state_internal + .as_ref() + .map(|v| v.replication_status_internal.clone().unwrap_or_default()) + .unwrap_or_default() + .as_bytes() + .to_vec(), + ); + delete_marker.meta_sys.insert( + format!("{}{}", RESERVED_METADATA_PREFIX_LOWER, "replication-timestamp"), + fi.replication_state_internal + .as_ref() + .map(|v| v.replication_timestamp.unwrap_or(OffsetDateTime::UNIX_EPOCH).to_string()) .unwrap_or_default() .as_bytes() .to_vec(), @@ -716,6 +701,20 @@ impl FileMeta { } } + if !fi.version_purge_status().is_empty() + && let Some(delete_marker) = ventry.delete_marker.as_mut() + { + delete_marker.meta_sys.insert( + VERSION_PURGE_STATUS_KEY.to_string(), + fi.replication_state_internal + .as_ref() + .map(|v| v.version_purge_status_internal.clone().unwrap_or_default()) + .unwrap_or_default() + .as_bytes() + .to_vec(), + ); + } + if let Some(delete_marker) = ventry.delete_marker.as_mut() { for (k, v) in fi .replication_state_internal @@ -1917,42 +1916,41 @@ impl MetaObject { if let Some(status) = self .meta_sys .get(&format!("{RESERVED_METADATA_PREFIX_LOWER}{TRANSITION_STATUS}")) + && *status == TRANSITION_COMPLETE.as_bytes().to_vec() { - if *status == TRANSITION_COMPLETE.as_bytes().to_vec() { - let vid = Uuid::parse_str(&fi.tier_free_version_id()); - if let Err(err) = vid { - panic!("Invalid Tier Object delete marker versionId {} {}", fi.tier_free_version_id(), err); - } - let vid = vid.unwrap(); - let mut free_entry = FileMetaVersion { - version_type: VersionType::Delete, - write_version: 0, - ..Default::default() - }; - free_entry.delete_marker = Some(MetaDeleteMarker { - version_id: Some(vid), - mod_time: self.mod_time, - meta_sys: HashMap::>::new(), - }); - - let delete_marker = free_entry.delete_marker.as_mut().unwrap(); - - delete_marker - .meta_sys - .insert(format!("{RESERVED_METADATA_PREFIX_LOWER}{FREE_VERSION}"), vec![]); - - let tier_key = format!("{RESERVED_METADATA_PREFIX_LOWER}{TRANSITION_TIER}"); - let tier_obj_key = format!("{RESERVED_METADATA_PREFIX_LOWER}{TRANSITIONED_OBJECTNAME}"); - let tier_obj_vid_key = format!("{RESERVED_METADATA_PREFIX_LOWER}{TRANSITIONED_VERSION_ID}"); - - let aa = [tier_key, tier_obj_key, tier_obj_vid_key]; - for (k, v) in &self.meta_sys { - if aa.contains(k) { - delete_marker.meta_sys.insert(k.clone(), v.clone()); - } - } - return (free_entry, true); + let vid = Uuid::parse_str(&fi.tier_free_version_id()); + if let Err(err) = vid { + panic!("Invalid Tier Object delete marker versionId {} {}", fi.tier_free_version_id(), err); } + let vid = vid.unwrap(); + let mut free_entry = FileMetaVersion { + version_type: VersionType::Delete, + write_version: 0, + ..Default::default() + }; + free_entry.delete_marker = Some(MetaDeleteMarker { + version_id: Some(vid), + mod_time: self.mod_time, + meta_sys: HashMap::>::new(), + }); + + let delete_marker = free_entry.delete_marker.as_mut().unwrap(); + + delete_marker + .meta_sys + .insert(format!("{RESERVED_METADATA_PREFIX_LOWER}{FREE_VERSION}"), vec![]); + + let tier_key = format!("{RESERVED_METADATA_PREFIX_LOWER}{TRANSITION_TIER}"); + let tier_obj_key = format!("{RESERVED_METADATA_PREFIX_LOWER}{TRANSITIONED_OBJECTNAME}"); + let tier_obj_vid_key = format!("{RESERVED_METADATA_PREFIX_LOWER}{TRANSITIONED_VERSION_ID}"); + + let aa = [tier_key, tier_obj_key, tier_obj_vid_key]; + for (k, v) in &self.meta_sys { + if aa.contains(k) { + delete_marker.meta_sys.insert(k.clone(), v.clone()); + } + } + return (free_entry, true); } (FileMetaVersion::default(), false) } @@ -3568,15 +3566,15 @@ impl FileMeta { match version.header.version_type { VersionType::Object => { stats.object_versions += 1; - if let Ok(ver) = FileMetaVersion::try_from(version.meta.as_slice()) { - if let Some(obj) = &ver.object { - stats.total_size += obj.size; - if obj.uses_data_dir() { - stats.versions_with_data_dir += 1; - } - if obj.inlinedata() { - stats.versions_with_inline_data += 1; - } + if let Ok(ver) = FileMetaVersion::try_from(version.meta.as_slice()) + && let Some(obj) = &ver.object + { + stats.total_size += obj.size; + if obj.uses_data_dir() { + stats.versions_with_data_dir += 1; + } + if obj.inlinedata() { + stats.versions_with_inline_data += 1; } } } diff --git a/crates/filemeta/src/metacache.rs b/crates/filemeta/src/metacache.rs index 8daa9c1a..4cc2c9b1 100644 --- a/crates/filemeta/src/metacache.rs +++ b/crates/filemeta/src/metacache.rs @@ -442,10 +442,10 @@ impl MetaCacheEntriesSorted { } pub fn forward_past(&mut self, marker: Option) { - if let Some(val) = marker { - if let Some(idx) = self.o.0.iter().flatten().position(|v| v.name > val) { - self.o.0 = self.o.0.split_off(idx); - } + if let Some(val) = marker + && let Some(idx) = self.o.0.iter().flatten().position(|v| v.name > val) + { + self.o.0 = self.o.0.split_off(idx); } } } @@ -788,22 +788,23 @@ impl Cache { .duration_since(UNIX_EPOCH) .expect("Time went backwards") .as_secs(); - if now - self.last_update_ms.load(AtomicOrdering::SeqCst) < self.ttl.as_secs() { - if let Some(v) = v { - return Ok(v); - } + if now - self.last_update_ms.load(AtomicOrdering::SeqCst) < self.ttl.as_secs() + && let Some(v) = v + { + return Ok(v); } - if self.opts.no_wait && now - self.last_update_ms.load(AtomicOrdering::SeqCst) < self.ttl.as_secs() * 2 { - if let Some(value) = v { - if self.updating.try_lock().is_ok() { - let this = Arc::clone(&self); - spawn(async move { - let _ = this.update().await; - }); - } - return Ok(value); + if self.opts.no_wait + && now - self.last_update_ms.load(AtomicOrdering::SeqCst) < self.ttl.as_secs() * 2 + && let Some(value) = v + { + if self.updating.try_lock().is_ok() { + let this = Arc::clone(&self); + spawn(async move { + let _ = this.update().await; + }); } + return Ok(value); } let _ = self.updating.lock().await; @@ -811,10 +812,9 @@ impl Cache { if let (Ok(duration), Some(value)) = ( SystemTime::now().duration_since(UNIX_EPOCH + Duration::from_secs(self.last_update_ms.load(AtomicOrdering::SeqCst))), v, - ) { - if duration < self.ttl { - return Ok(value); - } + ) && duration < self.ttl + { + return Ok(value); } match self.update().await { diff --git a/crates/filemeta/src/replication.rs b/crates/filemeta/src/replication.rs index b7038362..7a3463ed 100644 --- a/crates/filemeta/src/replication.rs +++ b/crates/filemeta/src/replication.rs @@ -270,14 +270,12 @@ impl ReplicationState { return repl_status; } - if repl_status == ReplicationStatusType::Completed { - if let (Some(replica_timestamp), Some(replication_timestamp)) = + if repl_status == ReplicationStatusType::Completed + && let (Some(replica_timestamp), Some(replication_timestamp)) = (self.replica_timestamp, self.replication_timestamp) - { - if replica_timestamp > replication_timestamp { - return self.replica_status.clone(); - } - } + && replica_timestamp > replication_timestamp + { + return self.replica_status.clone(); } return repl_status; diff --git a/crates/iam/src/manager.rs b/crates/iam/src/manager.rs index cf4b0b28..2861e862 100644 --- a/crates/iam/src/manager.rs +++ b/crates/iam/src/manager.rs @@ -246,12 +246,12 @@ where } let sts_user = has_sts_user.map(|sts| sts.credentials.access_key.clone()); - if let Some(ref sts) = sts_user { - if let Some(plc) = sts_policy_map.get(sts) { - for p in plc.to_slice().iter() { - if !policy_docs_map.contains_key(p) { - let _ = self.api.load_policy_doc(p, &mut policy_docs_map).await; - } + if let Some(ref sts) = sts_user + && let Some(plc) = sts_policy_map.get(sts) + { + for p in plc.to_slice().iter() { + if !policy_docs_map.contains_key(p) { + let _ = self.api.load_policy_doc(p, &mut policy_docs_map).await; } } } @@ -635,10 +635,10 @@ where } let users = self.cache.users.load(); - if let Some(x) = users.get(&cred.access_key) { - if x.credentials.is_service_account() { - return Err(Error::IAMActionNotAllowed); - } + if let Some(x) = users.get(&cred.access_key) + && x.credentials.is_service_account() + { + return Err(Error::IAMActionNotAllowed); } let u = UserIdentity::new(cred); @@ -789,10 +789,10 @@ where if !policy_present { let mut m = HashMap::new(); - if let Err(err) = self.api.load_mapped_policy(name, UserType::Reg, true, &mut m).await { - if !is_err_no_such_policy(&err) { - return Err(err); - } + if let Err(err) = self.api.load_mapped_policy(name, UserType::Reg, true, &mut m).await + && !is_err_no_such_policy(&err) + { + return Err(err); } if let Some(p) = m.get(name) { Cache::add_or_update(&self.cache.group_policies, name, p, OffsetDateTime::now_utc()); @@ -815,10 +815,10 @@ where Some(p) => p.clone(), None => { let mut m = HashMap::new(); - if let Err(err) = self.api.load_mapped_policy(name, UserType::Reg, false, &mut m).await { - if !is_err_no_such_policy(&err) { - return Err(err); - } + if let Err(err) = self.api.load_mapped_policy(name, UserType::Reg, false, &mut m).await + && !is_err_no_such_policy(&err) + { + return Err(err); } if let Some(p) = m.get(name) { Cache::add_or_update(&self.cache.user_policies, name, p, OffsetDateTime::now_utc()); @@ -828,10 +828,10 @@ where Some(p) => p.clone(), None => { let mut m = HashMap::new(); - if let Err(err) = self.api.load_mapped_policy(name, UserType::Sts, false, &mut m).await { - if !is_err_no_such_policy(&err) { - return Err(err); - } + if let Err(err) = self.api.load_mapped_policy(name, UserType::Sts, false, &mut m).await + && !is_err_no_such_policy(&err) + { + return Err(err); } if let Some(p) = m.get(name) { Cache::add_or_update(&self.cache.sts_policies, name, p, OffsetDateTime::now_utc()); @@ -864,10 +864,10 @@ where Some(p) => p.clone(), None => { let mut m = HashMap::new(); - if let Err(err) = self.api.load_mapped_policy(group, UserType::Reg, true, &mut m).await { - if !is_err_no_such_policy(&err) { - return Err(err); - } + if let Err(err) = self.api.load_mapped_policy(group, UserType::Reg, true, &mut m).await + && !is_err_no_such_policy(&err) + { + return Err(err); } if let Some(p) = m.get(group) { Cache::add_or_update(&self.cache.group_policies, group, p, OffsetDateTime::now_utc()); @@ -910,10 +910,10 @@ where Some(p) => p.clone(), None => { let mut m = HashMap::new(); - if let Err(err) = self.api.load_mapped_policy(group, UserType::Reg, true, &mut m).await { - if !is_err_no_such_policy(&err) { - return Err(err); - } + if let Err(err) = self.api.load_mapped_policy(group, UserType::Reg, true, &mut m).await + && !is_err_no_such_policy(&err) + { + return Err(err); } if let Some(p) = m.get(group) { Cache::add_or_update(&self.cache.group_policies, group, p, OffsetDateTime::now_utc()); @@ -937,10 +937,10 @@ where } if policy.is_empty() { - if let Err(err) = self.api.delete_mapped_policy(name, user_type, is_group).await { - if !is_err_no_such_policy(&err) { - return Err(err); - } + if let Err(err) = self.api.delete_mapped_policy(name, user_type, is_group).await + && !is_err_no_such_policy(&err) + { + return Err(err); } if is_group { @@ -1220,10 +1220,10 @@ where Cache::delete(&self.cache.user_policies, access_key, OffsetDateTime::now_utc()); - if let Err(err) = self.api.delete_user_identity(access_key, utype).await { - if !is_err_no_such_user(&err) { - return Err(err); - } + if let Err(err) = self.api.delete_user_identity(access_key, utype).await + && !is_err_no_such_user(&err) + { + return Err(err); } if utype == UserType::Sts { @@ -1532,16 +1532,16 @@ where } if members.is_empty() { - if let Err(err) = self.api.delete_mapped_policy(group, UserType::Reg, true).await { - if !is_err_no_such_policy(&err) { - return Err(err); - } + if let Err(err) = self.api.delete_mapped_policy(group, UserType::Reg, true).await + && !is_err_no_such_policy(&err) + { + return Err(err); } - if let Err(err) = self.api.delete_group_info(group).await { - if !is_err_no_such_group(&err) { - return Err(err); - } + if let Err(err) = self.api.delete_group_info(group).await + && !is_err_no_such_group(&err) + { + return Err(err); } Cache::delete(&self.cache.groups, group, OffsetDateTime::now_utc()); @@ -1691,10 +1691,10 @@ where let member_of = self.cache.user_group_memberships.load(); if let Some(m) = member_of.get(name) { for group in m.iter() { - if let Err(err) = self.remove_members_from_group(group, vec![name.to_string()], true).await { - if !is_err_no_such_group(&err) { - return Err(err); - } + if let Err(err) = self.remove_members_from_group(group, vec![name.to_string()], true).await + && !is_err_no_such_group(&err) + { + return Err(err); } } } @@ -1859,11 +1859,11 @@ fn filter_policies(cache: &Cache, policy_name: &str, bucket_name: &str) -> (Stri continue; } - if let Some(p) = cache.policy_docs.load().get(&policy) { - if bucket_name.is_empty() || pollster::block_on(p.policy.match_resource(bucket_name)) { - policies.push(policy); - to_merge.push(p.policy.clone()); - } + if let Some(p) = cache.policy_docs.load().get(&policy) + && (bucket_name.is_empty() || pollster::block_on(p.policy.match_resource(bucket_name))) + { + policies.push(policy); + to_merge.push(p.policy.clone()); } } diff --git a/crates/iam/src/store/object.rs b/crates/iam/src/store/object.rs index 1e5fb591..930a8743 100644 --- a/crates/iam/src/store/object.rs +++ b/crates/iam/src/store/object.rs @@ -633,10 +633,10 @@ impl Store for ObjectStore { if let Some(item) = v.item { let name = rustfs_utils::path::dir(&item); - if let Err(err) = self.load_group(&name, m).await { - if !is_err_no_such_group(&err) { - return Err(err); - } + if let Err(err) = self.load_group(&name, m).await + && !is_err_no_such_group(&err) + { + return Err(err); } } } @@ -936,10 +936,10 @@ impl Store for ObjectStore { let name = item.trim_end_matches(".json"); info!("load group policy: {}", name); - if let Err(err) = self.load_mapped_policy(name, UserType::Reg, true, &mut items_cache).await { - if !is_err_no_such_policy(&err) { - return Err(Error::other(format!("load group policy failed: {err}"))); - } + if let Err(err) = self.load_mapped_policy(name, UserType::Reg, true, &mut items_cache).await + && !is_err_no_such_policy(&err) + { + return Err(Error::other(format!("load group policy failed: {err}"))); }; } @@ -955,10 +955,10 @@ impl Store for ObjectStore { for item in item_name_list.iter() { let name = rustfs_utils::path::dir(item); info!("load svc user: {}", name); - if let Err(err) = self.load_user(&name, UserType::Svc, &mut items_cache).await { - if !is_err_no_such_user(&err) { - return Err(Error::other(format!("load svc user failed: {err}"))); - } + if let Err(err) = self.load_user(&name, UserType::Svc, &mut items_cache).await + && !is_err_no_such_user(&err) + { + return Err(Error::other(format!("load svc user failed: {err}"))); }; } @@ -969,10 +969,9 @@ impl Store for ObjectStore { if let Err(err) = self .load_mapped_policy(&parent, UserType::Sts, false, &mut sts_policies_cache) .await + && !is_err_no_such_policy(&err) { - if !is_err_no_such_policy(&err) { - return Err(Error::other(format!("load_mapped_policy failed: {err}"))); - } + return Err(Error::other(format!("load_mapped_policy failed: {err}"))); } } } diff --git a/crates/iam/src/sys.rs b/crates/iam/src/sys.rs index 1173c873..476b73e4 100644 --- a/crates/iam/src/sys.rs +++ b/crates/iam/src/sys.rs @@ -203,13 +203,13 @@ impl IamSys { pub async fn set_policy(&self, name: &str, policy: Policy) -> Result { let updated_at = self.store.set_policy(name, policy).await?; - if !self.has_watcher() { - if let Some(notification_sys) = get_global_notification_sys() { - let resp = notification_sys.load_policy(name).await; - for r in resp { - if let Some(err) = r.err { - warn!("notify load_policy failed: {}", err); - } + if !self.has_watcher() + && let Some(notification_sys) = get_global_notification_sys() + { + let resp = notification_sys.load_policy(name).await; + for r in resp { + if let Some(err) = r.err { + warn!("notify load_policy failed: {}", err); } } } @@ -232,13 +232,14 @@ impl IamSys { pub async fn delete_user(&self, name: &str, notify: bool) -> Result<()> { self.store.delete_user(name, UserType::Reg).await?; - if notify && !self.has_watcher() { - if let Some(notification_sys) = get_global_notification_sys() { - let resp = notification_sys.delete_user(name).await; - for r in resp { - if let Some(err) = r.err { - warn!("notify delete_user failed: {}", err); - } + if notify + && !self.has_watcher() + && let Some(notification_sys) = get_global_notification_sys() + { + let resp = notification_sys.delete_user(name).await; + for r in resp { + if let Some(err) = r.err { + warn!("notify delete_user failed: {}", err); } } } @@ -476,13 +477,12 @@ impl IamSys { let op_pt = claims.get(&iam_policy_claim_name_sa()); let op_sp = claims.get(SESSION_POLICY_NAME); - if let (Some(pt), Some(sp)) = (op_pt, op_sp) { - if pt == EMBEDDED_POLICY_TYPE { - let policy = serde_json::from_slice( - &base64_simd::URL_SAFE_NO_PAD.decode_to_vec(sp.as_str().unwrap_or_default().as_bytes())?, - )?; - return Ok((sa, Some(policy))); - } + if let (Some(pt), Some(sp)) = (op_pt, op_sp) + && pt == EMBEDDED_POLICY_TYPE + { + let policy = + serde_json::from_slice(&base64_simd::URL_SAFE_NO_PAD.decode_to_vec(sp.as_str().unwrap_or_default().as_bytes())?)?; + return Ok((sa, Some(policy))); } Ok((sa, None)) @@ -537,13 +537,12 @@ impl IamSys { let op_pt = claims.get(&iam_policy_claim_name_sa()); let op_sp = claims.get(SESSION_POLICY_NAME); - if let (Some(pt), Some(sp)) = (op_pt, op_sp) { - if pt == EMBEDDED_POLICY_TYPE { - let policy = serde_json::from_slice( - &base64_simd::URL_SAFE_NO_PAD.decode_to_vec(sp.as_str().unwrap_or_default().as_bytes())?, - )?; - return Ok((sa, Some(policy))); - } + if let (Some(pt), Some(sp)) = (op_pt, op_sp) + && pt == EMBEDDED_POLICY_TYPE + { + let policy = + serde_json::from_slice(&base64_simd::URL_SAFE_NO_PAD.decode_to_vec(sp.as_str().unwrap_or_default().as_bytes())?)?; + return Ok((sa, Some(policy))); } Ok((sa, None)) @@ -572,13 +571,14 @@ impl IamSys { self.store.delete_user(access_key, UserType::Svc).await?; - if notify && !self.has_watcher() { - if let Some(notification_sys) = get_global_notification_sys() { - let resp = notification_sys.delete_service_account(access_key).await; - for r in resp { - if let Some(err) = r.err { - warn!("notify delete_service_account failed: {}", err); - } + if notify + && !self.has_watcher() + && let Some(notification_sys) = get_global_notification_sys() + { + let resp = notification_sys.delete_service_account(access_key).await; + for r in resp { + if let Some(err) = r.err { + warn!("notify delete_service_account failed: {}", err); } } } @@ -651,10 +651,10 @@ impl IamSys { } pub async fn check_key(&self, access_key: &str) -> Result<(Option, bool)> { - if let Some(sys_cred) = get_global_action_cred() { - if sys_cred.access_key == access_key { - return Ok((Some(UserIdentity::new(sys_cred)), true)); - } + if let Some(sys_cred) = get_global_action_cred() + && sys_cred.access_key == access_key + { + return Ok((Some(UserIdentity::new(sys_cred)), true)); } match self.store.get_user(access_key).await { @@ -725,13 +725,13 @@ impl IamSys { pub async fn policy_db_set(&self, name: &str, user_type: UserType, is_group: bool, policy: &str) -> Result { let updated_at = self.store.policy_db_set(name, user_type, is_group, policy).await?; - if !self.has_watcher() { - if let Some(notification_sys) = get_global_notification_sys() { - let resp = notification_sys.load_policy_mapping(name, user_type.to_u64(), is_group).await; - for r in resp { - if let Some(err) = r.err { - warn!("notify load_policy failed: {}", err); - } + if !self.has_watcher() + && let Some(notification_sys) = get_global_notification_sys() + { + let resp = notification_sys.load_policy_mapping(name, user_type.to_u64(), is_group).await; + for r in resp { + if let Some(err) = r.err { + warn!("notify load_policy failed: {}", err); } } } diff --git a/crates/kms/src/backends/local.rs b/crates/kms/src/backends/local.rs index a8f28795..d01ab5aa 100644 --- a/crates/kms/src/backends/local.rs +++ b/crates/kms/src/backends/local.rs @@ -452,27 +452,25 @@ impl KmsClient for LocalKmsClient { } let path = entry.path(); - if path.extension().is_some_and(|ext| ext == "key") { - if let Some(stem) = path.file_stem() { - if let Some(key_id) = stem.to_str() { - if let Ok(key_info) = self.describe_key(key_id, None).await { - // Apply filters - if let Some(ref status_filter) = request.status_filter { - if &key_info.status != status_filter { - continue; - } - } - if let Some(ref usage_filter) = request.usage_filter { - if &key_info.usage != usage_filter { - continue; - } - } - - keys.push(key_info); - count += 1; - } - } + if path.extension().is_some_and(|ext| ext == "key") + && let Some(stem) = path.file_stem() + && let Some(key_id) = stem.to_str() + && let Ok(key_info) = self.describe_key(key_id, None).await + { + // Apply filters + if let Some(ref status_filter) = request.status_filter + && &key_info.status != status_filter + { + continue; } + if let Some(ref usage_filter) = request.usage_filter + && &key_info.usage != usage_filter + { + continue; + } + + keys.push(key_info); + count += 1; } } diff --git a/crates/kms/src/config.rs b/crates/kms/src/config.rs index 299970b0..c963074b 100644 --- a/crates/kms/src/config.rs +++ b/crates/kms/src/config.rs @@ -279,14 +279,13 @@ impl KmsConfig { } // Validate TLS configuration if using HTTPS - if config.address.starts_with("https://") { - if let Some(ref tls) = config.tls { - if !tls.skip_verify { - // In production, we should have proper TLS configuration - if tls.ca_cert_path.is_none() && tls.client_cert_path.is_none() { - tracing::warn!("Using HTTPS without custom TLS configuration - relying on system CA"); - } - } + if config.address.starts_with("https://") + && let Some(ref tls) = config.tls + && !tls.skip_verify + { + // In production, we should have proper TLS configuration + if tls.ca_cert_path.is_none() && tls.client_cert_path.is_none() { + tracing::warn!("Using HTTPS without custom TLS configuration - relying on system CA"); } } } diff --git a/crates/kms/src/manager.rs b/crates/kms/src/manager.rs index 261cb124..9e45baa7 100644 --- a/crates/kms/src/manager.rs +++ b/crates/kms/src/manager.rs @@ -74,14 +74,14 @@ impl KmsManager { // Check cache first if enabled if self.config.enable_cache { let cache = self.cache.read().await; - if let Some(cached_key) = cache.get_data_key(&request.key_id).await { - if cached_key.key_spec == request.key_spec { - return Ok(GenerateDataKeyResponse { - key_id: request.key_id.clone(), - plaintext_key: cached_key.plaintext.clone(), - ciphertext_blob: cached_key.ciphertext.clone(), - }); - } + if let Some(cached_key) = cache.get_data_key(&request.key_id).await + && cached_key.key_spec == request.key_spec + { + return Ok(GenerateDataKeyResponse { + key_id: request.key_id.clone(), + plaintext_key: cached_key.plaintext.clone(), + ciphertext_blob: cached_key.ciphertext.clone(), + }); } } diff --git a/crates/lock/src/client/mod.rs b/crates/lock/src/client/mod.rs index a07f4775..572bd579 100644 --- a/crates/lock/src/client/mod.rs +++ b/crates/lock/src/client/mod.rs @@ -104,20 +104,20 @@ mod tests { let response = client.acquire_exclusive(&request).await; assert!(response.is_ok()); - if let Ok(response) = response { - if response.success { - let lock_info = response.lock_info.unwrap(); + if let Ok(response) = response + && response.success + { + let lock_info = response.lock_info.unwrap(); - // Test status check - let status = client.check_status(&lock_info.id).await; - assert!(status.is_ok()); - assert!(status.unwrap().is_some()); + // Test status check + let status = client.check_status(&lock_info.id).await; + assert!(status.is_ok()); + assert!(status.unwrap().is_some()); - // Test lock release - let released = client.release(&lock_info.id).await; - assert!(released.is_ok()); - assert!(released.unwrap()); - } + // Test lock release + let released = client.release(&lock_info.id).await; + assert!(released.is_ok()); + assert!(released.unwrap()); } } } diff --git a/crates/lock/src/fast_lock/guard.rs b/crates/lock/src/fast_lock/guard.rs index f7b8a0ea..e0e79bb0 100644 --- a/crates/lock/src/fast_lock/guard.rs +++ b/crates/lock/src/fast_lock/guard.rs @@ -953,10 +953,10 @@ mod tests { // Wait for all operations to complete let mut successful_operations = 0; for handle in handles { - if let Ok(success) = handle.await { - if success { - successful_operations += 1; - } + if let Ok(success) = handle.await + && success + { + successful_operations += 1; } } diff --git a/crates/lock/src/fast_lock/manager.rs b/crates/lock/src/fast_lock/manager.rs index 64767bde..48e73574 100644 --- a/crates/lock/src/fast_lock/manager.rs +++ b/crates/lock/src/fast_lock/manager.rs @@ -414,10 +414,10 @@ impl Default for FastObjectLockManager { impl Drop for FastObjectLockManager { fn drop(&mut self) { // Note: We can't use async in Drop, so we just abort the cleanup task - if let Ok(handle_guard) = self.cleanup_handle.try_read() { - if let Some(handle) = handle_guard.as_ref() { - handle.abort(); - } + if let Ok(handle_guard) = self.cleanup_handle.try_read() + && let Some(handle) = handle_guard.as_ref() + { + handle.abort(); } } } diff --git a/crates/lock/src/fast_lock/shard.rs b/crates/lock/src/fast_lock/shard.rs index 6ca24409..28f92a9f 100644 --- a/crates/lock/src/fast_lock/shard.rs +++ b/crates/lock/src/fast_lock/shard.rs @@ -69,10 +69,10 @@ impl LockShard { /// Try fast path only (without fallback to slow path) pub fn try_fast_path_only(&self, request: &ObjectLockRequest) -> bool { // Early check to avoid unnecessary lock contention - if let Some(state) = self.objects.read().get(&request.key) { - if !state.atomic_state.is_fast_path_available(request.mode) { - return false; - } + if let Some(state) = self.objects.read().get(&request.key) + && !state.atomic_state.is_fast_path_available(request.mode) + { + return false; } self.try_fast_path(request).is_some() } @@ -441,36 +441,36 @@ impl LockShard { /// Get lock information for monitoring pub fn get_lock_info(&self, key: &ObjectKey) -> Option { let objects = self.objects.read(); - if let Some(state) = objects.get(key) { - if let Some(mode) = state.current_mode() { - let (owner, acquired_at, lock_timeout) = match mode { - LockMode::Exclusive => { - let current_owner = state.current_owner.read(); - let info = current_owner.clone()?; - (info.owner, info.acquired_at, info.lock_timeout) - } - LockMode::Shared => { - let shared_owners = state.shared_owners.read(); - let entry = shared_owners.first()?.clone(); - (entry.owner, entry.acquired_at, entry.lock_timeout) - } - }; + if let Some(state) = objects.get(key) + && let Some(mode) = state.current_mode() + { + let (owner, acquired_at, lock_timeout) = match mode { + LockMode::Exclusive => { + let current_owner = state.current_owner.read(); + let info = current_owner.clone()?; + (info.owner, info.acquired_at, info.lock_timeout) + } + LockMode::Shared => { + let shared_owners = state.shared_owners.read(); + let entry = shared_owners.first()?.clone(); + (entry.owner, entry.acquired_at, entry.lock_timeout) + } + }; - let priority = *state.priority.read(); + let priority = *state.priority.read(); - let expires_at = acquired_at - .checked_add(lock_timeout) - .unwrap_or_else(|| acquired_at + crate::fast_lock::DEFAULT_LOCK_TIMEOUT); + let expires_at = acquired_at + .checked_add(lock_timeout) + .unwrap_or_else(|| acquired_at + crate::fast_lock::DEFAULT_LOCK_TIMEOUT); - return Some(crate::fast_lock::types::ObjectLockInfo { - key: key.clone(), - mode, - owner, - acquired_at, - expires_at, - priority, - }); - } + return Some(crate::fast_lock::types::ObjectLockInfo { + key: key.clone(), + mode, + owner, + acquired_at, + expires_at, + priority, + }); } None } diff --git a/crates/lock/src/namespace.rs b/crates/lock/src/namespace.rs index 19cdffa8..559ae40e 100644 --- a/crates/lock/src/namespace.rs +++ b/crates/lock/src/namespace.rs @@ -165,10 +165,10 @@ impl NamespaceLock { let mut successful_clients = Vec::new(); for (idx, res) in results { - if let Ok(resp) = res { - if resp.success { - successful_clients.push(idx); - } + if let Ok(resp) = res + && resp.success + { + successful_clients.push(idx); } } diff --git a/crates/notify/src/factory.rs b/crates/notify/src/factory.rs index fb4d6312..c324bf2f 100644 --- a/crates/notify/src/factory.rs +++ b/crates/notify/src/factory.rs @@ -204,10 +204,10 @@ impl TargetFactory for MQTTTargetFactory { if !std::path::Path::new(&queue_dir).is_absolute() { return Err(TargetError::Configuration("MQTT queue directory must be an absolute path".to_string())); } - if let Some(qos_str) = config.lookup(MQTT_QOS) { - if qos_str == "0" { - warn!("Using queue_dir with QoS 0 may result in event loss"); - } + if let Some(qos_str) = config.lookup(MQTT_QOS) + && qos_str == "0" + { + warn!("Using queue_dir with QoS 0 may result in event loss"); } } diff --git a/crates/notify/src/notifier.rs b/crates/notify/src/notifier.rs index 78beda9c..a5c8dd6e 100644 --- a/crates/notify/src/notifier.rs +++ b/crates/notify/src/notifier.rs @@ -345,10 +345,10 @@ impl TargetList { pub async fn clear_targets_only(&mut self) { let target_ids_to_clear: Vec = self.targets.keys().cloned().collect(); for id in target_ids_to_clear { - if let Some(target_arc) = self.targets.remove(&id) { - if let Err(e) = target_arc.close().await { - error!("Failed to close target {} during clear: {}", id, e); - } + if let Some(target_arc) = self.targets.remove(&id) + && let Err(e) = target_arc.close().await + { + error!("Failed to close target {} during clear: {}", id, e); } } self.targets.clear(); diff --git a/crates/notify/src/registry.rs b/crates/notify/src/registry.rs index cdf3aa11..4d727416 100644 --- a/crates/notify/src/registry.rs +++ b/crates/notify/src/registry.rs @@ -119,12 +119,11 @@ impl TargetRegistry { format!("{ENV_PREFIX}{NOTIFY_ROUTE_PREFIX}{target_type}{DEFAULT_DELIMITER}{ENABLE_KEY}{DEFAULT_DELIMITER}") .to_uppercase(); for (key, value) in &all_env { - if EnableState::from_str(value).ok().map(|s| s.is_enabled()).unwrap_or(false) { - if let Some(id) = key.strip_prefix(&enable_prefix) { - if !id.is_empty() { - instance_ids_from_env.insert(id.to_lowercase()); - } - } + if EnableState::from_str(value).ok().map(|s| s.is_enabled()).unwrap_or(false) + && let Some(id) = key.strip_prefix(&enable_prefix) + && !id.is_empty() + { + instance_ids_from_env.insert(id.to_lowercase()); } } @@ -273,10 +272,10 @@ impl TargetRegistry { for section in sections { let mut section_map: std::collections::HashMap = std::collections::HashMap::new(); // Add default item - if let Some(default_kvs) = section_defaults.get(§ion) { - if !default_kvs.is_empty() { - section_map.insert(DEFAULT_DELIMITER.to_string(), default_kvs.clone()); - } + if let Some(default_kvs) = section_defaults.get(§ion) + && !default_kvs.is_empty() + { + section_map.insert(DEFAULT_DELIMITER.to_string(), default_kvs.clone()); } // Add successful instance item diff --git a/crates/notify/src/rules/pattern.rs b/crates/notify/src/rules/pattern.rs index 4faceaee..34e5e05e 100644 --- a/crates/notify/src/rules/pattern.rs +++ b/crates/notify/src/rules/pattern.rs @@ -24,30 +24,30 @@ pub fn new_pattern(prefix: Option<&str>, suffix: Option<&str>) -> String { let mut pattern = String::new(); // Process the prefix part - if let Some(p) = prefix { - if !p.is_empty() { - pattern.push_str(p); - if !p.ends_with('*') { - pattern.push('*'); - } + if let Some(p) = prefix + && !p.is_empty() + { + pattern.push_str(p); + if !p.ends_with('*') { + pattern.push('*'); } } // Process the suffix part - if let Some(s) = suffix { - if !s.is_empty() { - let mut s_to_append = s.to_string(); - if !s.starts_with('*') { - s_to_append.insert(0, '*'); - } + if let Some(s) = suffix + && !s.is_empty() + { + let mut s_to_append = s.to_string(); + if !s.starts_with('*') { + s_to_append.insert(0, '*'); + } - // If the pattern is empty (only suffixes are provided), then the pattern is the suffix - // Otherwise, append the suffix to the pattern - if pattern.is_empty() { - pattern = s_to_append; - } else { - pattern.push_str(&s_to_append); - } + // If the pattern is empty (only suffixes are provided), then the pattern is the suffix + // Otherwise, append the suffix to the pattern + if pattern.is_empty() { + pattern = s_to_append; + } else { + pattern.push_str(&s_to_append); } } diff --git a/crates/obs/src/telemetry.rs b/crates/obs/src/telemetry.rs index 2aa2642c..54780f7c 100644 --- a/crates/obs/src/telemetry.rs +++ b/crates/obs/src/telemetry.rs @@ -86,21 +86,21 @@ impl std::fmt::Debug for OtelGuard { impl Drop for OtelGuard { fn drop(&mut self) { - if let Some(provider) = self.tracer_provider.take() { - if let Err(err) = provider.shutdown() { - eprintln!("Tracer shutdown error: {err:?}"); - } + if let Some(provider) = self.tracer_provider.take() + && let Err(err) = provider.shutdown() + { + eprintln!("Tracer shutdown error: {err:?}"); } - if let Some(provider) = self.meter_provider.take() { - if let Err(err) = provider.shutdown() { - eprintln!("Meter shutdown error: {err:?}"); - } + if let Some(provider) = self.meter_provider.take() + && let Err(err) = provider.shutdown() + { + eprintln!("Meter shutdown error: {err:?}"); } - if let Some(provider) = self.logger_provider.take() { - if let Err(err) = provider.shutdown() { - eprintln!("Logger shutdown error: {err:?}"); - } + if let Some(provider) = self.logger_provider.take() + && let Err(err) = provider.shutdown() + { + eprintln!("Logger shutdown error: {err:?}"); } if let Some(handle) = self.flexi_logger_handles.take() { diff --git a/crates/policy/src/policy/resource.rs b/crates/policy/src/policy/resource.rs index a491c55b..024c79a3 100644 --- a/crates/policy/src/policy/resource.rs +++ b/crates/policy/src/policy/resource.rs @@ -122,10 +122,10 @@ impl Resource { // Apply condition substitutions if !conditions.is_empty() { for key in KeyName::COMMON_KEYS { - if let Some(rvalue) = conditions.get(key.name()) { - if matches!(rvalue.first().map(|c| !c.is_empty()), Some(true)) { - resolved_pattern = resolved_pattern.replace(&key.var_name(), &rvalue[0]); - } + if let Some(rvalue) = conditions.get(key.name()) + && matches!(rvalue.first().map(|c| !c.is_empty()), Some(true)) + { + resolved_pattern = resolved_pattern.replace(&key.var_name(), &rvalue[0]); } } } diff --git a/crates/rio/src/checksum.rs b/crates/rio/src/checksum.rs index 4d1e475f..3239b429 100644 --- a/crates/rio/src/checksum.rs +++ b/crates/rio/src/checksum.rs @@ -387,7 +387,7 @@ impl Checksum { // Ensure we don't divide by 0 let raw_len = self.checksum_type.raw_byte_len(); - if raw_len == 0 || parts.len() % raw_len != 0 { + if raw_len == 0 || !parts.len().is_multiple_of(raw_len) { checksums = 0; } else if !parts.is_empty() { checksums = (parts.len() / raw_len) as i32; @@ -506,16 +506,16 @@ pub fn get_content_checksum(headers: &HeaderMap) -> Result, std for header in trailing_headers { let mut duplicates = false; for &checksum_type in crate::checksum::BASE_CHECKSUM_TYPES { - if let Some(key) = checksum_type.key() { - if header.eq_ignore_ascii_case(key) { - duplicates = result.is_some(); - result = Some(Checksum { - checksum_type: ChecksumType(checksum_type.0 | ChecksumType::TRAILING.0), - encoded: String::new(), - raw: Vec::new(), - want_parts: 0, - }); - } + if let Some(key) = checksum_type.key() + && header.eq_ignore_ascii_case(key) + { + duplicates = result.is_some(); + result = Some(Checksum { + checksum_type: ChecksumType(checksum_type.0 | ChecksumType::TRAILING.0), + encoded: String::new(), + raw: Vec::new(), + want_parts: 0, + }); } } if duplicates { @@ -567,13 +567,13 @@ fn get_content_checksum_direct(headers: &HeaderMap) -> (ChecksumType, String) { checksum_type = ChecksumType(checksum_type.0 | ChecksumType::FULL_OBJECT.0); } - if checksum_type.is_set() { - if let Some(key) = checksum_type.key() { - if let Some(value) = headers.get(key).and_then(|v| v.to_str().ok()) { - return (checksum_type, value.to_string()); - } else { - return (ChecksumType::NONE, String::new()); - } + if checksum_type.is_set() + && let Some(key) = checksum_type.key() + { + if let Some(value) = headers.get(key).and_then(|v| v.to_str().ok()) { + return (checksum_type, value.to_string()); + } else { + return (ChecksumType::NONE, String::new()); } } return (checksum_type, String::new()); @@ -581,22 +581,22 @@ fn get_content_checksum_direct(headers: &HeaderMap) -> (ChecksumType, String) { // Check individual checksum headers for &ct in crate::checksum::BASE_CHECKSUM_TYPES { - if let Some(key) = ct.key() { - if let Some(value) = headers.get(key).and_then(|v| v.to_str().ok()) { - // If already set, invalid - if checksum_type != ChecksumType::NONE { + if let Some(key) = ct.key() + && let Some(value) = headers.get(key).and_then(|v| v.to_str().ok()) + { + // If already set, invalid + if checksum_type != ChecksumType::NONE { + return (ChecksumType::INVALID, String::new()); + } + checksum_type = ct; + + if headers.get("x-amz-checksum-type").and_then(|v| v.to_str().ok()) == Some("FULL_OBJECT") { + if !checksum_type.can_merge() { return (ChecksumType::INVALID, String::new()); } - checksum_type = ct; - - if headers.get("x-amz-checksum-type").and_then(|v| v.to_str().ok()) == Some("FULL_OBJECT") { - if !checksum_type.can_merge() { - return (ChecksumType::INVALID, String::new()); - } - checksum_type = ChecksumType(checksum_type.0 | ChecksumType::FULL_OBJECT.0); - } - return (checksum_type, value.to_string()); + checksum_type = ChecksumType(checksum_type.0 | ChecksumType::FULL_OBJECT.0); } + return (checksum_type, value.to_string()); } } @@ -965,10 +965,10 @@ fn gf2_matrix_times(mat: &[u64], mut vec: u64) -> u64 { let mut mat_iter = mat.iter(); while vec != 0 { - if vec & 1 != 0 { - if let Some(&m) = mat_iter.next() { - sum ^= m; - } + if vec & 1 != 0 + && let Some(&m) = mat_iter.next() + { + sum ^= m; } vec >>= 1; mat_iter.next(); diff --git a/crates/rio/src/hash_reader.rs b/crates/rio/src/hash_reader.rs index 4d672e3c..7ef674a4 100644 --- a/crates/rio/src/hash_reader.rs +++ b/crates/rio/src/hash_reader.rs @@ -178,12 +178,11 @@ impl HashReader { )); } - if let Some(checksum) = existing_hash_reader.checksum() { - if let Some(ref md5) = md5hex { - if checksum != md5 { - return Err(std::io::Error::new(std::io::ErrorKind::InvalidData, "HashReader checksum mismatch")); - } - } + if let Some(checksum) = existing_hash_reader.checksum() + && let Some(ref md5) = md5hex + && checksum != md5 + { + return Err(std::io::Error::new(std::io::ErrorKind::InvalidData, "HashReader checksum mismatch")); } if existing_hash_reader.size() > 0 && size > 0 && existing_hash_reader.size() != size { @@ -359,15 +358,15 @@ impl HashReader { } if checksum.checksum_type.trailing() { - if let Some(trailer) = self.trailer_s3s.as_ref() { - if let Some(Some(checksum_str)) = trailer.read(|headers| { + if let Some(trailer) = self.trailer_s3s.as_ref() + && let Some(Some(checksum_str)) = trailer.read(|headers| { checksum .checksum_type .key() .and_then(|key| headers.get(key).and_then(|value| value.to_str().ok().map(|s| s.to_string()))) - }) { - map.insert(checksum.checksum_type.to_string(), checksum_str); - } + }) + { + map.insert(checksum.checksum_type.to_string(), checksum_str); } return map; } @@ -450,18 +449,18 @@ impl AsyncRead for HashReader { if filled > 0 { // Update SHA256 hasher - if let Some(hasher) = this.content_sha256_hasher { - if let Err(e) = hasher.write_all(data) { - error!("SHA256 hasher write error, error={:?}", e); - return Poll::Ready(Err(std::io::Error::other(e))); - } + if let Some(hasher) = this.content_sha256_hasher + && let Err(e) = hasher.write_all(data) + { + error!("SHA256 hasher write error, error={:?}", e); + return Poll::Ready(Err(std::io::Error::other(e))); } // Update content hasher - if let Some(hasher) = this.content_hasher { - if let Err(e) = hasher.write_all(data) { - return Poll::Ready(Err(std::io::Error::other(e))); - } + if let Some(hasher) = this.content_hasher + && let Err(e) = hasher.write_all(data) + { + return Poll::Ready(Err(std::io::Error::other(e))); } } @@ -477,22 +476,22 @@ impl AsyncRead for HashReader { // check content hasher if let (Some(hasher), Some(expected_content_hash)) = (this.content_hasher, this.content_hash) { - if expected_content_hash.checksum_type.trailing() { - if let Some(trailer) = this.trailer_s3s.as_ref() { - if let Some(Some(checksum_str)) = trailer.read(|headers| { - expected_content_hash.checksum_type.key().and_then(|key| { - headers.get(key).and_then(|value| value.to_str().ok().map(|s| s.to_string())) - }) - }) { - expected_content_hash.encoded = checksum_str; - expected_content_hash.raw = general_purpose::STANDARD - .decode(&expected_content_hash.encoded) - .map_err(|_| std::io::Error::other("Invalid base64 checksum"))?; + if expected_content_hash.checksum_type.trailing() + && let Some(trailer) = this.trailer_s3s.as_ref() + && let Some(Some(checksum_str)) = trailer.read(|headers| { + expected_content_hash + .checksum_type + .key() + .and_then(|key| headers.get(key).and_then(|value| value.to_str().ok().map(|s| s.to_string()))) + }) + { + expected_content_hash.encoded = checksum_str; + expected_content_hash.raw = general_purpose::STANDARD + .decode(&expected_content_hash.encoded) + .map_err(|_| std::io::Error::other("Invalid base64 checksum"))?; - if expected_content_hash.raw.is_empty() { - return Poll::Ready(Err(std::io::Error::other("Content hash mismatch"))); - } - } + if expected_content_hash.raw.is_empty() { + return Poll::Ready(Err(std::io::Error::other("Content hash mismatch"))); } } diff --git a/crates/s3select-query/src/dispatcher/manager.rs b/crates/s3select-query/src/dispatcher/manager.rs index 54972d97..468855e0 100644 --- a/crates/s3select-query/src/dispatcher/manager.rs +++ b/crates/s3select-query/src/dispatcher/manager.rs @@ -175,10 +175,10 @@ impl SimpleQueryDispatcher { .clone() .map(|e| e.as_bytes().first().copied().unwrap_or_default()), ); - if let Some(delimiter) = csv.field_delimiter.as_ref() { - if delimiter.len() == 1 { - file_format = file_format.with_delimiter(delimiter.as_bytes()[0]); - } + if let Some(delimiter) = csv.field_delimiter.as_ref() + && delimiter.len() == 1 + { + file_format = file_format.with_delimiter(delimiter.as_bytes()[0]); } // TODO waiting for processing @junxiang Mu // if csv.file_header_info.is_some() {} diff --git a/crates/signer/src/utils.rs b/crates/signer/src/utils.rs index a1754424..8f31f793 100644 --- a/crates/signer/src/utils.rs +++ b/crates/signer/src/utils.rs @@ -25,10 +25,10 @@ pub fn get_host_addr(req: &request::Request) -> String { } else { req_host = uri.host().unwrap().to_string(); } - if let Some(host) = host { - if req_host != *host.to_str().unwrap() { - return (*host.to_str().unwrap()).to_string(); - } + if let Some(host) = host + && req_host != *host.to_str().unwrap() + { + return (*host.to_str().unwrap()).to_string(); } /*if req.uri_ref().unwrap().host().is_some() { return req.uri_ref().unwrap().host().unwrap(); diff --git a/crates/targets/src/store.rs b/crates/targets/src/store.rs index be15a9b4..ee3a616f 100644 --- a/crates/targets/src/store.rs +++ b/crates/targets/src/store.rs @@ -97,11 +97,11 @@ pub fn parse_key(s: &str) -> Key { } // Number of batch items parsed - if let Some(colon_pos) = name.find(':') { - if let Ok(count) = name[..colon_pos].parse::() { - item_count = count; - name = name[colon_pos + 1..].to_string(); - } + if let Some(colon_pos) = name.find(':') + && let Ok(count) = name[..colon_pos].parse::() + { + item_count = count; + name = name[colon_pos + 1..].to_string(); } // Resolve extension diff --git a/crates/targets/src/target/mqtt.rs b/crates/targets/src/target/mqtt.rs index 9de8ac94..eb876d9c 100644 --- a/crates/targets/src/target/mqtt.rs +++ b/crates/targets/src/target/mqtt.rs @@ -225,17 +225,20 @@ where match tokio::time::timeout(DEFAULT_CONNECTION_TIMEOUT, async { while !self.connected.load(Ordering::SeqCst) { - if let Some(handle) = self.bg_task_manager.init_cell.get() { - if handle.is_finished() && !self.connected.load(Ordering::SeqCst) { - error!(target_id = %self.id, "MQTT background task exited prematurely before connection was established."); - return Err(TargetError::Network("MQTT background task exited prematurely".to_string())); - } + if let Some(handle) = self.bg_task_manager.init_cell.get() + && handle.is_finished() + && !self.connected.load(Ordering::SeqCst) + { + error!(target_id = %self.id, "MQTT background task exited prematurely before connection was established."); + return Err(TargetError::Network("MQTT background task exited prematurely".to_string())); } tokio::time::sleep(Duration::from_millis(100)).await; } debug!(target_id = %self.id, "MQTT target connected successfully."); Ok(()) - }).await { + }) + .await + { Ok(Ok(_)) => { info!(target_id = %self.id, "MQTT target initialized and connected."); Ok(()) @@ -243,9 +246,7 @@ where Ok(Err(e)) => Err(e), Err(_) => { error!(target_id = %self.id, "Timeout waiting for MQTT connection after task spawn."); - Err(TargetError::Network( - "Timeout waiting for MQTT connection".to_string(), - )) + Err(TargetError::Network("Timeout waiting for MQTT connection".to_string())) } } } @@ -470,11 +471,11 @@ where debug!(target_id = %self.id, "Checking if MQTT target is active."); if self.client.lock().await.is_none() && !self.connected.load(Ordering::SeqCst) { // Check if the background task is running and has not panicked - if let Some(handle) = self.bg_task_manager.init_cell.get() { - if handle.is_finished() { - error!(target_id = %self.id, "MQTT background task has finished, possibly due to an error. Target is not active."); - return Err(TargetError::Network("MQTT background task terminated".to_string())); - } + if let Some(handle) = self.bg_task_manager.init_cell.get() + && handle.is_finished() + { + error!(target_id = %self.id, "MQTT background task has finished, possibly due to an error. Target is not active."); + return Err(TargetError::Network("MQTT background task terminated".to_string())); } debug!(target_id = %self.id, "MQTT client not yet initialized or task not running/connected."); return Err(TargetError::Configuration( diff --git a/crates/utils/src/certs.rs b/crates/utils/src/certs.rs index 8615375a..878667cf 100644 --- a/crates/utils/src/certs.rs +++ b/crates/utils/src/certs.rs @@ -292,7 +292,7 @@ pub fn create_multi_cert_resolver( for (domain, (certs, key)) in cert_key_pairs { // create a signature - let signing_key = rustls::crypto::ring::sign::any_supported_type(&key) + let signing_key = rustls::crypto::aws_lc_rs::sign::any_supported_type(&key) .map_err(|e| certs_error(format!("unsupported private key types:{domain}, err:{e:?}")))?; // create a CertifiedKey diff --git a/crates/utils/src/http/ip.rs b/crates/utils/src/http/ip.rs index 6d42d142..76d0f1ed 100644 --- a/crates/utils/src/http/ip.rs +++ b/crates/utils/src/http/ip.rs @@ -56,36 +56,36 @@ fn is_xff_header_enabled() -> bool { /// pub fn get_source_scheme(headers: &HeaderMap) -> Option { // Retrieve the scheme from X-Forwarded-Proto. - if let Some(proto) = headers.get(X_FORWARDED_PROTO) { - if let Ok(proto_str) = proto.to_str() { - return Some(proto_str.to_lowercase()); - } + if let Some(proto) = headers.get(X_FORWARDED_PROTO) + && let Ok(proto_str) = proto.to_str() + { + return Some(proto_str.to_lowercase()); } - if let Some(proto) = headers.get(X_FORWARDED_SCHEME) { - if let Ok(proto_str) = proto.to_str() { - return Some(proto_str.to_lowercase()); - } + if let Some(proto) = headers.get(X_FORWARDED_SCHEME) + && let Ok(proto_str) = proto.to_str() + { + return Some(proto_str.to_lowercase()); } - if let Some(forwarded) = headers.get(FORWARDED) { - if let Ok(forwarded_str) = forwarded.to_str() { - // match should contain at least two elements if the protocol was - // specified in the Forwarded header. The first element will always be - // the 'for=', which we ignore, subsequently we proceed to look for - // 'proto=' which should precede right after `for=` if not - // we simply ignore the values and return empty. This is in line - // with the approach we took for returning first ip from multiple - // params. - if let Some(for_match) = FOR_REGEX.captures(forwarded_str) { - if for_match.len() > 1 { - let remaining = &for_match[2]; - if let Some(proto_match) = PROTO_REGEX.captures(remaining) { - if proto_match.len() > 1 { - return Some(proto_match[2].to_lowercase()); - } - } - } + if let Some(forwarded) = headers.get(FORWARDED) + && let Ok(forwarded_str) = forwarded.to_str() + { + // match should contain at least two elements if the protocol was + // specified in the Forwarded header. The first element will always be + // the 'for=', which we ignore, subsequently we proceed to look for + // 'proto=' which should precede right after `for=` if not + // we simply ignore the values and return empty. This is in line + // with the approach we took for returning first ip from multiple + // params. + if let Some(for_match) = FOR_REGEX.captures(forwarded_str) + && for_match.len() > 1 + { + let remaining = &for_match[2]; + if let Some(proto_match) = PROTO_REGEX.captures(remaining) + && proto_match.len() > 1 + { + return Some(proto_match[2].to_lowercase()); } } } @@ -105,17 +105,16 @@ pub fn get_source_scheme(headers: &HeaderMap) -> Option { pub fn get_source_ip_from_headers(headers: &HeaderMap) -> Option { let mut addr = None; - if is_xff_header_enabled() { - if let Some(forwarded_for) = headers.get(X_FORWARDED_FOR) { - if let Ok(forwarded_str) = forwarded_for.to_str() { - // Only grab the first (client) address. Note that '192.168.0.1, - // 10.1.1.1' is a valid key for X-Forwarded-For where addresses after - // the first may represent forwarding proxies earlier in the chain. - let first_comma = forwarded_str.find(", "); - let end = first_comma.unwrap_or(forwarded_str.len()); - addr = Some(forwarded_str[..end].to_string()); - } - } + if is_xff_header_enabled() + && let Some(forwarded_for) = headers.get(X_FORWARDED_FOR) + && let Ok(forwarded_str) = forwarded_for.to_str() + { + // Only grab the first (client) address. Note that '192.168.0.1, + // 10.1.1.1' is a valid key for X-Forwarded-For where addresses after + // the first may represent forwarding proxies earlier in the chain. + let first_comma = forwarded_str.find(", "); + let end = first_comma.unwrap_or(forwarded_str.len()); + addr = Some(forwarded_str[..end].to_string()); } if addr.is_none() { @@ -125,21 +124,21 @@ pub fn get_source_ip_from_headers(headers: &HeaderMap) -> Option { // request). addr = Some(real_ip_str.to_string()); } - } else if let Some(forwarded) = headers.get(FORWARDED) { - if let Ok(forwarded_str) = forwarded.to_str() { - // match should contain at least two elements if the protocol was - // specified in the Forwarded header. The first element will always be - // the 'for=' capture, which we ignore. In the case of multiple IP - // addresses (for=8.8.8.8, 8.8.4.4, 172.16.1.20 is valid) we only - // extract the first, which should be the client IP. - if let Some(for_match) = FOR_REGEX.captures(forwarded_str) { - if for_match.len() > 1 { - // IPv6 addresses in Forwarded headers are quoted-strings. We strip - // these quotes. - let ip = for_match[1].trim_matches('"'); - addr = Some(ip.to_string()); - } - } + } else if let Some(forwarded) = headers.get(FORWARDED) + && let Ok(forwarded_str) = forwarded.to_str() + { + // match should contain at least two elements if the protocol was + // specified in the Forwarded header. The first element will always be + // the 'for=' capture, which we ignore. In the case of multiple IP + // addresses (for=8.8.8.8, 8.8.4.4, 172.16.1.20 is valid) we only + // extract the first, which should be the client IP. + if let Some(for_match) = FOR_REGEX.captures(forwarded_str) + && for_match.len() > 1 + { + // IPv6 addresses in Forwarded headers are quoted-strings. We strip + // these quotes. + let ip = for_match[1].trim_matches('"'); + addr = Some(ip.to_string()); } } } diff --git a/crates/utils/src/net.rs b/crates/utils/src/net.rs index b15e4fba..57296275 100644 --- a/crates/utils/src/net.rs +++ b/crates/utils/src/net.rs @@ -174,16 +174,15 @@ pub async fn get_host_ip(host: Host<&str>) -> std::io::Result> { match host { Host::Domain(domain) => { // Check cache first - if CUSTOM_DNS_RESOLVER.read().unwrap().is_none() { - if let Ok(mut cache) = DNS_CACHE.lock() { - if let Some(entry) = cache.get(domain) { - if !entry.is_expired(DNS_CACHE_TTL) { - return Ok(entry.ips.clone()); - } - // Remove expired entry - cache.remove(domain); - } + if CUSTOM_DNS_RESOLVER.read().unwrap().is_none() + && let Ok(mut cache) = DNS_CACHE.lock() + && let Some(entry) = cache.get(domain) + { + if !entry.is_expired(DNS_CACHE_TTL) { + return Ok(entry.ips.clone()); } + // Remove expired entry + cache.remove(domain); } info!("Cache miss for domain {domain}, querying system resolver."); diff --git a/crates/utils/src/notify/net.rs b/crates/utils/src/notify/net.rs index d1312cb7..62ca5ed2 100644 --- a/crates/utils/src/notify/net.rs +++ b/crates/utils/src/notify/net.rs @@ -196,13 +196,12 @@ impl ParsedURL { impl std::fmt::Display for ParsedURL { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { let mut url = self.0.clone(); - if let Some(host) = url.host_str().map(|h| h.to_string()) { - if let Some(port) = url.port() { - if (url.scheme() == "http" && port == 80) || (url.scheme() == "https" && port == 443) { - url.set_host(Some(&host)).unwrap(); - url.set_port(None).unwrap(); - } - } + if let Some(host) = url.host_str().map(|h| h.to_string()) + && let Some(port) = url.port() + && ((url.scheme() == "http" && port == 80) || (url.scheme() == "https" && port == 443)) + { + url.set_host(Some(&host)).unwrap(); + url.set_port(None).unwrap(); } let mut s = url.to_string(); @@ -251,12 +250,12 @@ impl<'de> serde::Deserialize<'de> for ParsedURL { /// Returns NetError if parsing fails or host is invalid. /// pub fn parse_url(s: &str) -> Result { - if let Some(scheme_end) = s.find("://") { - if s[scheme_end + 3..].starts_with('/') { - let scheme = &s[..scheme_end]; - if !scheme.is_empty() { - return Err(NetError::SchemeWithEmptyHost); - } + if let Some(scheme_end) = s.find("://") + && s[scheme_end + 3..].starts_with('/') + { + let scheme = &s[..scheme_end]; + if !scheme.is_empty() { + return Err(NetError::SchemeWithEmptyHost); } } diff --git a/rustfs/src/admin/console.rs b/rustfs/src/admin/console.rs index 5bd0bbd0..6e5c9cc1 100644 --- a/rustfs/src/admin/console.rs +++ b/rustfs/src/admin/console.rs @@ -367,35 +367,35 @@ async fn _setup_console_tls_config(tls_path: Option<&String>) -> Result MetricsParams { for param in params { let mut parts = param.split('='); if let Some(key) = parts.next() { - if key == "disks" { - if let Some(value) = parts.next() { - mp.disks = value.to_string(); - } + if key == "disks" + && let Some(value) = parts.next() + { + mp.disks = value.to_string(); } - if key == "hosts" { - if let Some(value) = parts.next() { - mp.hosts = value.to_string(); - } + if key == "hosts" + && let Some(value) = parts.next() + { + mp.hosts = value.to_string(); } - if key == "interval" { - if let Some(value) = parts.next() { - mp.tick = value.to_string(); - } + if key == "interval" + && let Some(value) = parts.next() + { + mp.tick = value.to_string(); } - if key == "n" { - if let Some(value) = parts.next() { - mp.n = value.parse::().unwrap_or(u64::MAX); - } + if key == "n" + && let Some(value) = parts.next() + { + mp.n = value.parse::().unwrap_or(u64::MAX); } - if key == "types" { - if let Some(value) = parts.next() { - mp.types = value.parse::().unwrap_or_default(); - } + if key == "types" + && let Some(value) = parts.next() + { + mp.types = value.parse::().unwrap_or_default(); } - if key == "by-disk" { - if let Some(value) = parts.next() { - mp.by_disk = value.to_string(); - } + if key == "by-disk" + && let Some(value) = parts.next() + { + mp.by_disk = value.to_string(); } - if key == "by-host" { - if let Some(value) = parts.next() { - mp.by_host = value.to_string(); - } + if key == "by-host" + && let Some(value) = parts.next() + { + mp.by_host = value.to_string(); } - if key == "by-jobID" { - if let Some(value) = parts.next() { - mp.by_job_id = value.to_string(); - } + if key == "by-jobID" + && let Some(value) = parts.next() + { + mp.by_job_id = value.to_string(); } - if key == "by-depID" { - if let Some(value) = parts.next() { - mp.by_dep_id = value.to_string(); - } + if key == "by-depID" + && let Some(value) = parts.next() + { + mp.by_dep_id = value.to_string(); } } } @@ -830,10 +830,10 @@ fn extract_heal_init_params(body: &Bytes, uri: &Uri, params: Params<'_, '_>) -> for param in params { let mut parts = param.split('='); if let Some(key) = parts.next() { - if key == "clientToken" { - if let Some(value) = parts.next() { - hip.client_token = value.to_string(); - } + if key == "clientToken" + && let Some(value) = parts.next() + { + hip.client_token = value.to_string(); } if key == "forceStart" && parts.next().is_some() { hip.force_start = true; diff --git a/rustfs/src/admin/handlers/group.rs b/rustfs/src/admin/handlers/group.rs index e3dd7463..91e0c0e2 100644 --- a/rustfs/src/admin/handlers/group.rs +++ b/rustfs/src/admin/handlers/group.rs @@ -277,10 +277,11 @@ impl Operation for UpdateGroupMembers { } else { warn!("add group members"); - if let Err(err) = iam_store.get_group_description(&args.group).await { - if is_err_no_such_group(&err) && has_space_be(&args.group) { - return Err(s3_error!(InvalidArgument, "not such group")); - } + if let Err(err) = iam_store.get_group_description(&args.group).await + && is_err_no_such_group(&err) + && has_space_be(&args.group) + { + return Err(s3_error!(InvalidArgument, "not such group")); } iam_store.add_users_to_group(&args.group, args.members).await.map_err(|e| { diff --git a/rustfs/src/admin/handlers/user.rs b/rustfs/src/admin/handlers/user.rs index 1f47639f..5512d399 100644 --- a/rustfs/src/admin/handlers/user.rs +++ b/rustfs/src/admin/handlers/user.rs @@ -96,10 +96,10 @@ impl Operation for AddUser { return Err(s3_error!(InvalidArgument, "access key is empty")); } - if let Some(sys_cred) = get_global_action_cred() { - if constant_time_eq(&sys_cred.access_key, ak) { - return Err(s3_error!(InvalidArgument, "can't create user with system access key")); - } + if let Some(sys_cred) = get_global_action_cred() + && constant_time_eq(&sys_cred.access_key, ak) + { + return Err(s3_error!(InvalidArgument, "can't create user with system access key")); } let Ok(iam_store) = rustfs_iam::get() else { @@ -777,10 +777,10 @@ impl Operation for ImportIam { let groups: HashMap = serde_json::from_slice(&file_content) .map_err(|e| S3Error::with_message(S3ErrorCode::InternalError, e.to_string()))?; for (group_name, group_info) in groups { - if let Err(e) = iam_store.get_group_description(&group_name).await { - if matches!(e, rustfs_iam::error::Error::NoSuchGroup(_)) || has_space_be(&group_name) { - return Err(s3_error!(InvalidArgument, "group not found or has space be")); - } + if let Err(e) = iam_store.get_group_description(&group_name).await + && (matches!(e, rustfs_iam::error::Error::NoSuchGroup(_)) || has_space_be(&group_name)) + { + return Err(s3_error!(InvalidArgument, "group not found or has space be")); } if let Err(e) = iam_store.add_users_to_group(&group_name, group_info.members.clone()).await { diff --git a/rustfs/src/auth.rs b/rustfs/src/auth.rs index c673f686..15881c87 100644 --- a/rustfs/src/auth.rs +++ b/rustfs/src/auth.rs @@ -175,10 +175,10 @@ pub async fn check_key_valid(session_token: &str, access_key: &str) -> S3Result< .map_err(|e| S3Error::with_message(S3ErrorCode::InternalError, format!("check claims failed1 {e}")))?; if !ok { - if let Some(u) = u { - if u.credentials.status == "off" { - return Err(s3_error!(InvalidRequest, "ErrAccessKeyDisabled")); - } + if let Some(u) = u + && u.credentials.status == "off" + { + return Err(s3_error!(InvalidRequest, "ErrAccessKeyDisabled")); } return Err(s3_error!(InvalidRequest, "ErrAccessKeyDisabled")); @@ -200,10 +200,10 @@ pub async fn check_key_valid(session_token: &str, access_key: &str) -> S3Result< constant_time_eq(&sys_cred.access_key, &cred.access_key) || constant_time_eq(&cred.parent_user, &sys_cred.access_key); // permitRootAccess - if let Some(claims) = &cred.claims { - if claims.contains_key(SESSION_POLICY_NAME) { - owner = false - } + if let Some(claims) = &cred.claims + && claims.contains_key(SESSION_POLICY_NAME) + { + owner = false } Ok((cred, owner)) @@ -358,10 +358,10 @@ pub fn get_condition_values( args.insert("authType".to_owned(), vec![auth_type]); } - if let Some(lc) = region { - if !lc.is_empty() { - args.insert("LocationConstraint".to_owned(), vec![lc.to_string()]); - } + if let Some(lc) = region + && !lc.is_empty() + { + args.insert("LocationConstraint".to_owned(), vec![lc.to_string()]); } let mut clone_header = header.clone(); @@ -411,23 +411,23 @@ pub fn get_condition_values( } } - if let Some(grps_val) = claims.get("groups") { - if let Some(grps_is) = grps_val.as_array() { - let grps = grps_is - .iter() - .filter_map(|g| g.as_str().map(|s| s.to_string())) - .collect::>(); - if !grps.is_empty() { - args.insert("groups".to_string(), grps); - } + if let Some(grps_val) = claims.get("groups") + && let Some(grps_is) = grps_val.as_array() + { + let grps = grps_is + .iter() + .filter_map(|g| g.as_str().map(|s| s.to_string())) + .collect::>(); + if !grps.is_empty() { + args.insert("groups".to_string(), grps); } } } - if let Some(groups) = &cred.groups { - if !args.contains_key("groups") { - args.insert("groups".to_string(), groups.clone()); - } + if let Some(groups) = &cred.groups + && !args.contains_key("groups") + { + args.insert("groups".to_string(), groups.clone()); } args @@ -502,10 +502,10 @@ fn determine_auth_type_and_version(header: &HeaderMap) -> (String, String) { /// # Returns /// * `bool` - True if request has JWT, false otherwise fn is_request_jwt(header: &HeaderMap) -> bool { - if let Some(auth) = header.get("authorization") { - if let Ok(auth_str) = auth.to_str() { - return auth_str.starts_with(JWT_ALGORITHM); - } + if let Some(auth) = header.get("authorization") + && let Ok(auth_str) = auth.to_str() + { + return auth_str.starts_with(JWT_ALGORITHM); } false } @@ -518,10 +518,10 @@ fn is_request_jwt(header: &HeaderMap) -> bool { /// # Returns /// * `bool` - True if request has AWS Signature Version '4', false otherwise fn is_request_signature_v4(header: &HeaderMap) -> bool { - if let Some(auth) = header.get("authorization") { - if let Ok(auth_str) = auth.to_str() { - return auth_str.starts_with(SIGN_V4_ALGORITHM); - } + if let Some(auth) = header.get("authorization") + && let Ok(auth_str) = auth.to_str() + { + return auth_str.starts_with(SIGN_V4_ALGORITHM); } false } @@ -534,10 +534,10 @@ fn is_request_signature_v4(header: &HeaderMap) -> bool { /// # Returns /// * `bool` - True if request has AWS Signature Version '2', false otherwise fn is_request_signature_v2(header: &HeaderMap) -> bool { - if let Some(auth) = header.get("authorization") { - if let Ok(auth_str) = auth.to_str() { - return !auth_str.starts_with(SIGN_V4_ALGORITHM) && auth_str.starts_with(SIGN_V2_ALGORITHM); - } + if let Some(auth) = header.get("authorization") + && let Ok(auth_str) = auth.to_str() + { + return !auth_str.starts_with(SIGN_V4_ALGORITHM) && auth_str.starts_with(SIGN_V2_ALGORITHM); } false } @@ -578,40 +578,40 @@ fn is_request_presigned_signature_v2(header: &HeaderMap) -> bool { /// # Returns /// * `bool` - True if request has AWS Post policy Signature Version '4', false otherwise fn is_request_post_policy_signature_v4(header: &HeaderMap) -> bool { - if let Some(content_type) = header.get("content-type") { - if let Ok(ct) = content_type.to_str() { - return ct.contains("multipart/form-data"); - } + if let Some(content_type) = header.get("content-type") + && let Ok(ct) = content_type.to_str() + { + return ct.contains("multipart/form-data"); } false } /// Verify if the request has AWS Streaming Signature Version '4' fn is_request_sign_streaming_v4(header: &HeaderMap) -> bool { - if let Some(content_sha256) = header.get("x-amz-content-sha256") { - if let Ok(sha256_str) = content_sha256.to_str() { - return sha256_str == STREAMING_CONTENT_SHA256; - } + if let Some(content_sha256) = header.get("x-amz-content-sha256") + && let Ok(sha256_str) = content_sha256.to_str() + { + return sha256_str == STREAMING_CONTENT_SHA256; } false } // Verify if the request has AWS Streaming Signature Version '4' with trailer fn is_request_sign_streaming_trailer_v4(header: &HeaderMap) -> bool { - if let Some(content_sha256) = header.get("x-amz-content-sha256") { - if let Ok(sha256_str) = content_sha256.to_str() { - return sha256_str == STREAMING_CONTENT_SHA256_TRAILER; - } + if let Some(content_sha256) = header.get("x-amz-content-sha256") + && let Ok(sha256_str) = content_sha256.to_str() + { + return sha256_str == STREAMING_CONTENT_SHA256_TRAILER; } false } // Verify if the request has AWS Streaming Signature Version '4' with unsigned content and trailer fn is_request_unsigned_trailer_v4(header: &HeaderMap) -> bool { - if let Some(content_sha256) = header.get("x-amz-content-sha256") { - if let Ok(sha256_str) = content_sha256.to_str() { - return sha256_str == UNSIGNED_PAYLOAD_TRAILER; - } + if let Some(content_sha256) = header.get("x-amz-content-sha256") + && let Ok(sha256_str) = content_sha256.to_str() + { + return sha256_str == UNSIGNED_PAYLOAD_TRAILER; } false } @@ -634,10 +634,10 @@ pub fn get_query_param<'a>(query: &'a str, param_name: &str) -> Option<&'a str> for pair in query.split('&') { let mut parts = pair.splitn(2, '='); - if let (Some(key), Some(value)) = (parts.next(), parts.next()) { - if key.to_lowercase() == param_name { - return Some(value); - } + if let (Some(key), Some(value)) = (parts.next(), parts.next()) + && key.to_lowercase() == param_name + { + return Some(value); } } None diff --git a/rustfs/src/error.rs b/rustfs/src/error.rs index 5b4fe128..4ca5fd6c 100644 --- a/rustfs/src/error.rs +++ b/rustfs/src/error.rs @@ -193,18 +193,16 @@ impl From for S3Error { impl From for ApiError { fn from(err: StorageError) -> Self { // Special handling for Io errors that may contain ChecksumMismatch - if let StorageError::Io(ref io_err) = err { - if let Some(inner) = io_err.get_ref() { - if inner.downcast_ref::().is_some() - || inner.downcast_ref::().is_some() - { - return ApiError { - code: S3ErrorCode::BadDigest, - message: ApiError::error_code_to_message(&S3ErrorCode::BadDigest), - source: Some(Box::new(err)), - }; - } - } + if let StorageError::Io(ref io_err) = err + && let Some(inner) = io_err.get_ref() + && (inner.downcast_ref::().is_some() + || inner.downcast_ref::().is_some()) + { + return ApiError { + code: S3ErrorCode::BadDigest, + message: ApiError::error_code_to_message(&S3ErrorCode::BadDigest), + source: Some(Box::new(err)), + }; } let code = match &err { diff --git a/rustfs/src/protocols/ftps/driver.rs b/rustfs/src/protocols/ftps/driver.rs index 6d727d61..b216ed8d 100644 --- a/rustfs/src/protocols/ftps/driver.rs +++ b/rustfs/src/protocols/ftps/driver.rs @@ -735,14 +735,14 @@ impl StorageBackend for FtpsDriver { match s3_client.list_objects_v2(list_input).await { Ok(output) => { - if let Some(objects) = output.contents { - if !objects.is_empty() { - debug!("FTPS RMD - bucket '{}' is not empty, cannot delete", bucket); - return Err(Error::new( - ErrorKind::PermanentFileNotAvailable, - format!("Bucket '{}' is not empty", bucket), - )); - } + if let Some(objects) = output.contents + && !objects.is_empty() + { + debug!("FTPS RMD - bucket '{}' is not empty, cannot delete", bucket); + return Err(Error::new( + ErrorKind::PermanentFileNotAvailable, + format!("Bucket '{}' is not empty", bucket), + )); } } Err(e) => { diff --git a/rustfs/src/protocols/ftps/server.rs b/rustfs/src/protocols/ftps/server.rs index 95b93c92..94239ffb 100644 --- a/rustfs/src/protocols/ftps/server.rs +++ b/rustfs/src/protocols/ftps/server.rs @@ -98,16 +98,16 @@ impl FtpsConfig { )); } - if let Some(path) = &self.cert_file { - if !tokio::fs::try_exists(path).await.unwrap_or(false) { - return Err(FtpsInitError::InvalidConfig(format!("Certificate file not found: {}", path))); - } + if let Some(path) = &self.cert_file + && !tokio::fs::try_exists(path).await.unwrap_or(false) + { + return Err(FtpsInitError::InvalidConfig(format!("Certificate file not found: {}", path))); } - if let Some(path) = &self.key_file { - if !tokio::fs::try_exists(path).await.unwrap_or(false) { - return Err(FtpsInitError::InvalidConfig(format!("Key file not found: {}", path))); - } + if let Some(path) = &self.key_file + && !tokio::fs::try_exists(path).await.unwrap_or(false) + { + return Err(FtpsInitError::InvalidConfig(format!("Key file not found: {}", path))); } // Validate passive ports format diff --git a/rustfs/src/protocols/sftp/handler.rs b/rustfs/src/protocols/sftp/handler.rs index ff193264..e3bce987 100644 --- a/rustfs/src/protocols/sftp/handler.rs +++ b/rustfs/src/protocols/sftp/handler.rs @@ -753,16 +753,16 @@ impl Handler for SftpHandler { match s3_client.list_objects_v2(list_input).await { Ok(output) => { - if let Some(objects) = output.contents { - if !objects.is_empty() { - debug!("SFTP REMOVE - bucket '{}' is not empty, cannot delete", bucket); - return Ok(Status { - id, - status_code: StatusCode::Failure, - error_message: format!("Bucket '{}' is not empty", bucket), - language_tag: "en".into(), - }); - } + if let Some(objects) = output.contents + && !objects.is_empty() + { + debug!("SFTP REMOVE - bucket '{}' is not empty, cannot delete", bucket); + return Ok(Status { + id, + status_code: StatusCode::Failure, + error_message: format!("Bucket '{}' is not empty", bucket), + language_tag: "en".into(), + }); } } Err(e) => { diff --git a/rustfs/src/protocols/sftp/server.rs b/rustfs/src/protocols/sftp/server.rs index e549d73b..744700f4 100644 --- a/rustfs/src/protocols/sftp/server.rs +++ b/rustfs/src/protocols/sftp/server.rs @@ -696,10 +696,10 @@ fn compare_keys(stored_key: &str, client_key_base64: &str) -> bool { return true; } - if let Ok(stored_bytes) = BASE64.decode(stored_key_data) { - if let Ok(client_bytes) = BASE64.decode(client_key_base64) { - return stored_bytes == client_bytes; - } + if let Ok(stored_bytes) = BASE64.decode(stored_key_data) + && let Ok(client_bytes) = BASE64.decode(client_key_base64) + { + return stored_bytes == client_bytes; } false diff --git a/rustfs/src/server/cert.rs b/rustfs/src/server/cert.rs index 5c57e7f1..18f8656a 100644 --- a/rustfs/src/server/cert.rs +++ b/rustfs/src/server/cert.rs @@ -260,12 +260,12 @@ async fn walk_dir(path: PathBuf, cert_name: &str, cert_data: &mut Vec) { // Only check direct subdirectories, no deeper recursion if let Ok(mut sub_rd) = tokio::fs::read_dir(&entry.path()).await { while let Ok(Some(sub_entry)) = sub_rd.next_entry().await { - if let Ok(sub_ft) = sub_entry.file_type().await { - if sub_ft.is_file() { - load_if_matches(&sub_entry, cert_name, cert_data).await; - } - // Ignore subdirectories and symlinks in subdirs to limit to one level + if let Ok(sub_ft) = sub_entry.file_type().await + && sub_ft.is_file() + { + load_if_matches(&sub_entry, cert_name, cert_data).await; } + // Ignore subdirectories and symlinks in subdirs to limit to one level } } } else if ft.is_symlink() { @@ -277,12 +277,12 @@ async fn walk_dir(path: PathBuf, cert_name: &str, cert_data: &mut Vec) { // Treat as directory but only check its direct contents if let Ok(mut sub_rd) = tokio::fs::read_dir(&entry.path()).await { while let Ok(Some(sub_entry)) = sub_rd.next_entry().await { - if let Ok(sub_ft) = sub_entry.file_type().await { - if sub_ft.is_file() { - load_if_matches(&sub_entry, cert_name, cert_data).await; - } - // Ignore deeper levels + if let Ok(sub_ft) = sub_entry.file_type().await + && sub_ft.is_file() + { + load_if_matches(&sub_entry, cert_name, cert_data).await; } + // Ignore deeper levels } } } diff --git a/rustfs/src/server/compress.rs b/rustfs/src/server/compress.rs index 9276869f..24c4f39e 100644 --- a/rustfs/src/server/compress.rs +++ b/rustfs/src/server/compress.rs @@ -282,40 +282,35 @@ impl Predicate for CompressionPredicate { // CompressionLayer before calling this predicate, so we don't need to check them here. // Check Content-Length header for minimum size threshold - if let Some(content_length) = response.headers().get(http::header::CONTENT_LENGTH) { - if let Ok(length_str) = content_length.to_str() { - if let Ok(length) = length_str.parse::() { - if length < self.config.min_size { - debug!( - "Skipping compression for small response: size={} bytes, min_size={}", - length, self.config.min_size - ); - return false; - } - } - } + if let Some(content_length) = response.headers().get(http::header::CONTENT_LENGTH) + && let Ok(length_str) = content_length.to_str() + && let Ok(length) = length_str.parse::() + && length < self.config.min_size + { + debug!( + "Skipping compression for small response: size={} bytes, min_size={}", + length, self.config.min_size + ); + return false; } // Check if the response matches configured extension via Content-Disposition - if let Some(content_disposition) = response.headers().get(http::header::CONTENT_DISPOSITION) { - if let Ok(cd) = content_disposition.to_str() { - if let Some(filename) = CompressionConfig::extract_filename_from_content_disposition(cd) { - if self.config.matches_extension(&filename) { - debug!("Compressing response: filename '{}' matches configured extension", filename); - return true; - } - } - } + if let Some(content_disposition) = response.headers().get(http::header::CONTENT_DISPOSITION) + && let Ok(cd) = content_disposition.to_str() + && let Some(filename) = CompressionConfig::extract_filename_from_content_disposition(cd) + && self.config.matches_extension(&filename) + { + debug!("Compressing response: filename '{}' matches configured extension", filename); + return true; } // Check if the response matches configured MIME type - if let Some(content_type) = response.headers().get(http::header::CONTENT_TYPE) { - if let Ok(ct) = content_type.to_str() { - if self.config.matches_mime_type(ct) { - debug!("Compressing response: Content-Type '{}' matches configured MIME pattern", ct); - return true; - } - } + if let Some(content_type) = response.headers().get(http::header::CONTENT_TYPE) + && let Ok(ct) = content_type.to_str() + && self.config.matches_mime_type(ct) + { + debug!("Compressing response: Content-Type '{}' matches configured MIME pattern", ct); + return true; } // Default: don't compress (whitelist approach) diff --git a/rustfs/src/server/http.rs b/rustfs/src/server/http.rs index d1753019..fc6200bc 100644 --- a/rustfs/src/server/http.rs +++ b/rustfs/src/server/http.rs @@ -139,13 +139,13 @@ pub async fn start_http_server( }; // If address is IPv6 try to enable dual-stack; on failure, switch to IPv4 socket. - if server_addr.is_ipv6() { - if let Err(e) = socket.set_only_v6(false) { - warn!("Failed to set IPV6_V6ONLY=false, attempting IPv4 fallback: {}", e); - let ipv4_addr = SocketAddr::new(std::net::Ipv4Addr::UNSPECIFIED.into(), server_addr.port()); - server_addr = ipv4_addr; - socket = socket2::Socket::new(socket2::Domain::IPV4, socket2::Type::STREAM, Some(socket2::Protocol::TCP))?; - } + if server_addr.is_ipv6() + && let Err(e) = socket.set_only_v6(false) + { + warn!("Failed to set IPV6_V6ONLY=false, attempting IPv4 fallback: {}", e); + let ipv4_addr = SocketAddr::new(std::net::Ipv4Addr::UNSPECIFIED.into(), server_addr.port()); + server_addr = ipv4_addr; + socket = socket2::Socket::new(socket2::Domain::IPV4, socket2::Type::STREAM, Some(socket2::Protocol::TCP))?; } // Common setup for both IPv4 and successful dual-stack IPv6 @@ -434,38 +434,38 @@ async fn setup_tls_acceptor(tls_path: &str) -> Result> { debug!("Found TLS directory, checking for certificates"); // Make sure to use a modern encryption suite - let _ = rustls::crypto::ring::default_provider().install_default(); + let _ = rustls::crypto::aws_lc_rs::default_provider().install_default(); let mtls_verifier = rustfs_utils::build_webpki_client_verifier(tls_path)?; // 1. Attempt to load all certificates in the directory (multi-certificate support, for SNI) - if let Ok(cert_key_pairs) = rustfs_utils::load_all_certs_from_directory(tls_path) { - if !cert_key_pairs.is_empty() { - debug!("Found {} certificates, creating SNI-aware multi-cert resolver", cert_key_pairs.len()); + if let Ok(cert_key_pairs) = rustfs_utils::load_all_certs_from_directory(tls_path) + && !cert_key_pairs.is_empty() + { + debug!("Found {} certificates, creating SNI-aware multi-cert resolver", cert_key_pairs.len()); - // Create an SNI-enabled certificate resolver - let resolver = rustfs_utils::create_multi_cert_resolver(cert_key_pairs)?; + // Create an SNI-enabled certificate resolver + let resolver = rustfs_utils::create_multi_cert_resolver(cert_key_pairs)?; - // Configure the server to enable SNI support - let mut server_config = if let Some(verifier) = mtls_verifier.clone() { - ServerConfig::builder() - .with_client_cert_verifier(verifier) - .with_cert_resolver(Arc::new(resolver)) - } else { - ServerConfig::builder() - .with_no_client_auth() - .with_cert_resolver(Arc::new(resolver)) - }; + // Configure the server to enable SNI support + let mut server_config = if let Some(verifier) = mtls_verifier.clone() { + ServerConfig::builder() + .with_client_cert_verifier(verifier) + .with_cert_resolver(Arc::new(resolver)) + } else { + ServerConfig::builder() + .with_no_client_auth() + .with_cert_resolver(Arc::new(resolver)) + }; - // Configure ALPN protocol priority - server_config.alpn_protocols = vec![b"h2".to_vec(), b"http/1.1".to_vec(), b"http/1.0".to_vec()]; + // Configure ALPN protocol priority + server_config.alpn_protocols = vec![b"h2".to_vec(), b"http/1.1".to_vec(), b"http/1.0".to_vec()]; - // Log SNI requests - if rustfs_utils::tls_key_log() { - server_config.key_log = Arc::new(rustls::KeyLogFile::new()); - } - - return Ok(Some(TlsAcceptor::from(Arc::new(server_config)))); + // Log SNI requests + if rustfs_utils::tls_key_log() { + server_config.key_log = Arc::new(rustls::KeyLogFile::new()); } + + return Ok(Some(TlsAcceptor::from(Arc::new(server_config)))); } // 2. Revert to the traditional single-certificate mode @@ -520,7 +520,8 @@ struct ConnectionContext { /// 2. Build a complete service stack for this connection, including S3, RPC services, and all middleware. /// 3. Use Hyper to handle HTTP requests on this connection. /// 4. Incorporate connections into the management of elegant closures. -#[instrument(skip_all, fields(peer_addr = %socket.peer_addr().map(|a| a.to_string()).unwrap_or_else(|_| "unknown".to_string())))] +#[instrument(skip_all, fields(peer_addr = %socket.peer_addr().map(|a| a.to_string()).unwrap_or_else(|_| "unknown".to_string()) +))] fn process_connection( socket: TcpStream, tls_acceptor: Option>, diff --git a/rustfs/src/storage/ecfs.rs b/rustfs/src/storage/ecfs.rs index 9f5d8640..e7f4bfb6 100644 --- a/rustfs/src/storage/ecfs.rs +++ b/rustfs/src/storage/ecfs.rs @@ -519,13 +519,13 @@ fn validate_list_object_unordered_with_delimiter(delimiter: Option<&Delimiter>, return Ok(()); }; - if let Ok(params) = from_bytes::(query.as_bytes()) { - if params.allow_unordered.as_deref() == Some("true") { - return Err(S3Error::with_message( - S3ErrorCode::InvalidArgument, - "The allow-unordered parameter cannot be used when delimiter is specified.".to_string(), - )); - } + if let Ok(params) = from_bytes::(query.as_bytes()) + && params.allow_unordered.as_deref() == Some("true") + { + return Err(S3Error::with_message( + S3ErrorCode::InvalidArgument, + "The allow-unordered parameter cannot be used when delimiter is specified.".to_string(), + )); } Ok(()) @@ -735,8 +735,8 @@ impl FS { let mut checksum_sha256 = input.checksum_sha256; let mut checksum_crc64nvme = input.checksum_crc64nvme; - if let Some(alg) = &input.checksum_algorithm { - if let Some(Some(checksum_str)) = req.trailing_headers.as_ref().map(|trailer| { + if let Some(alg) = &input.checksum_algorithm + && let Some(Some(checksum_str)) = req.trailing_headers.as_ref().map(|trailer| { let key = match alg.as_str() { ChecksumAlgorithm::CRC32 => rustfs_rio::ChecksumType::CRC32.key(), ChecksumAlgorithm::CRC32C => rustfs_rio::ChecksumType::CRC32C.key(), @@ -750,15 +750,15 @@ impl FS { .get(key.unwrap_or_default()) .and_then(|value| value.to_str().ok().map(|s| s.to_string())) }) - }) { - match alg.as_str() { - ChecksumAlgorithm::CRC32 => checksum_crc32 = checksum_str, - ChecksumAlgorithm::CRC32C => checksum_crc32c = checksum_str, - ChecksumAlgorithm::SHA1 => checksum_sha1 = checksum_str, - ChecksumAlgorithm::SHA256 => checksum_sha256 = checksum_str, - ChecksumAlgorithm::CRC64NVME => checksum_crc64nvme = checksum_str, - _ => (), - } + }) + { + match alg.as_str() { + ChecksumAlgorithm::CRC32 => checksum_crc32 = checksum_str, + ChecksumAlgorithm::CRC32C => checksum_crc32c = checksum_str, + ChecksumAlgorithm::SHA1 => checksum_sha1 = checksum_str, + ChecksumAlgorithm::SHA256 => checksum_sha256 = checksum_str, + ChecksumAlgorithm::CRC64NVME => checksum_crc64nvme = checksum_str, + _ => (), } } @@ -977,64 +977,63 @@ impl S3 for FS { let mut reader = HashReader::new(reader, length, actual_size, None, None, false).map_err(ApiError::from)?; - if let Some(ref sse_alg) = effective_sse { - if is_managed_sse(sse_alg) { - let material = - create_managed_encryption_material(&bucket, &key, sse_alg, effective_kms_key_id.clone(), actual_size).await?; + if let Some(ref sse_alg) = effective_sse + && is_managed_sse(sse_alg) + { + let material = + create_managed_encryption_material(&bucket, &key, sse_alg, effective_kms_key_id.clone(), actual_size).await?; - let ManagedEncryptionMaterial { - data_key, - headers, - kms_key_id: kms_key_used, - } = material; + let ManagedEncryptionMaterial { + data_key, + headers, + kms_key_id: kms_key_used, + } = material; - let key_bytes = data_key.plaintext_key; - let nonce = data_key.nonce; + let key_bytes = data_key.plaintext_key; + let nonce = data_key.nonce; - src_info.user_defined.extend(headers.into_iter()); - effective_kms_key_id = Some(kms_key_used.clone()); + src_info.user_defined.extend(headers.into_iter()); + effective_kms_key_id = Some(kms_key_used.clone()); - let encrypt_reader = EncryptReader::new(reader, key_bytes, nonce); - reader = HashReader::new(Box::new(encrypt_reader), -1, actual_size, None, None, false).map_err(ApiError::from)?; - } + let encrypt_reader = EncryptReader::new(reader, key_bytes, nonce); + reader = HashReader::new(Box::new(encrypt_reader), -1, actual_size, None, None, false).map_err(ApiError::from)?; } // Apply SSE-C encryption if customer-provided key is specified if let (Some(sse_alg), Some(sse_key), Some(sse_md5)) = (&sse_customer_algorithm, &sse_customer_key, &sse_customer_key_md5) + && sse_alg.as_str() == "AES256" { - if sse_alg.as_str() == "AES256" { - let key_bytes = BASE64_STANDARD.decode(sse_key.as_str()).map_err(|e| { - error!("Failed to decode SSE-C key: {}", e); - ApiError::from(StorageError::other("Invalid SSE-C key")) - })?; + let key_bytes = BASE64_STANDARD.decode(sse_key.as_str()).map_err(|e| { + error!("Failed to decode SSE-C key: {}", e); + ApiError::from(StorageError::other("Invalid SSE-C key")) + })?; - if key_bytes.len() != 32 { - return Err(ApiError::from(StorageError::other("SSE-C key must be 32 bytes")).into()); - } - - let computed_md5 = BASE64_STANDARD.encode(md5::compute(&key_bytes).0); - if computed_md5 != sse_md5.as_str() { - return Err(ApiError::from(StorageError::other("SSE-C key MD5 mismatch")).into()); - } - - // Store original size before encryption - src_info - .user_defined - .insert("x-amz-server-side-encryption-customer-original-size".to_string(), actual_size.to_string()); - - // SAFETY: The length of `key_bytes` is checked to be 32 bytes above, - // so this conversion cannot fail. - let key_array: [u8; 32] = key_bytes.try_into().expect("key length already checked"); - // Generate deterministic nonce from bucket-key - let nonce_source = format!("{bucket}-{key}"); - let nonce_hash = md5::compute(nonce_source.as_bytes()); - let nonce: [u8; 12] = nonce_hash.0[..12] - .try_into() - .expect("MD5 hash is always 16 bytes; taking first 12 bytes for nonce is safe"); - - let encrypt_reader = EncryptReader::new(reader, key_array, nonce); - reader = HashReader::new(Box::new(encrypt_reader), -1, actual_size, None, None, false).map_err(ApiError::from)?; + if key_bytes.len() != 32 { + return Err(ApiError::from(StorageError::other("SSE-C key must be 32 bytes")).into()); } + + let computed_md5 = BASE64_STANDARD.encode(md5::compute(&key_bytes).0); + if computed_md5 != sse_md5.as_str() { + return Err(ApiError::from(StorageError::other("SSE-C key MD5 mismatch")).into()); + } + + // Store original size before encryption + src_info + .user_defined + .insert("x-amz-server-side-encryption-customer-original-size".to_string(), actual_size.to_string()); + + // SAFETY: The length of `key_bytes` is checked to be 32 bytes above, + // so this conversion cannot fail. + let key_array: [u8; 32] = key_bytes.try_into().expect("key length already checked"); + // Generate deterministic nonce from bucket-key + let nonce_source = format!("{bucket}-{key}"); + let nonce_hash = md5::compute(nonce_source.as_bytes()); + let nonce: [u8; 12] = nonce_hash.0[..12] + .try_into() + .expect("MD5 hash is always 16 bytes; taking first 12 bytes for nonce is safe"); + + let encrypt_reader = EncryptReader::new(reader, key_array, nonce); + reader = HashReader::new(Box::new(encrypt_reader), -1, actual_size, None, None, false).map_err(ApiError::from)?; } src_info.put_object_reader = Some(PutObjReader::new(reader)); @@ -1246,15 +1245,14 @@ impl S3 for FS { let restore_object = Uuid::new_v4().to_string(); //if let Some(rreq) = rreq { - if let Some(output_location) = &rreq.output_location { - if let Some(s3) = &output_location.s3 { - if !s3.bucket_name.is_empty() { - header.insert( - X_AMZ_RESTORE_OUTPUT_PATH, - format!("{}{}{}", s3.bucket_name, s3.prefix, restore_object).parse().unwrap(), - ); - } - } + if let Some(output_location) = &rreq.output_location + && let Some(s3) = &output_location.s3 + && !s3.bucket_name.is_empty() + { + header.insert( + X_AMZ_RESTORE_OUTPUT_PATH, + format!("{}{}{}", s3.bucket_name, s3.prefix, restore_object).parse().unwrap(), + ); } //} /*send_event(EventArgs { @@ -1730,24 +1728,23 @@ impl S3 for FS { }; for dobjs in delete_results.iter() { - if let Some(dobj) = &dobjs.delete_object { - if replicate_deletes - && (dobj.delete_marker_replication_status() == ReplicationStatusType::Pending - || dobj.version_purge_status() == VersionPurgeStatusType::Pending) - { - let mut dobj = dobj.clone(); - if is_dir_object(dobj.object_name.as_str()) && dobj.version_id.is_none() { - dobj.version_id = Some(Uuid::nil()); - } - - let deleted_object = DeletedObjectReplicationInfo { - delete_object: dobj, - bucket: bucket.clone(), - event_type: REPLICATE_INCOMING_DELETE.to_string(), - ..Default::default() - }; - schedule_replication_delete(deleted_object).await; + if let Some(dobj) = &dobjs.delete_object + && replicate_deletes + && (dobj.delete_marker_replication_status() == ReplicationStatusType::Pending + || dobj.version_purge_status() == VersionPurgeStatusType::Pending) + { + let mut dobj = dobj.clone(); + if is_dir_object(dobj.object_name.as_str()) && dobj.version_id.is_none() { + dobj.version_id = Some(Uuid::nil()); } + + let deleted_object = DeletedObjectReplicationInfo { + delete_object: dobj, + bucket: bucket.clone(), + event_type: REPLICATE_INCOMING_DELETE.to_string(), + ..Default::default() + }; + schedule_replication_delete(deleted_object).await; } } @@ -1854,96 +1851,98 @@ impl S3 for FS { let cache_key = ConcurrencyManager::make_cache_key(&bucket, &key, version_id.as_deref()); // Only attempt cache lookup if caching is enabled and for objects without range/part requests - if manager.is_cache_enabled() && part_number.is_none() && range.is_none() { - if let Some(cached) = manager.get_cached_object(&cache_key).await { - let cache_serve_duration = request_start.elapsed(); + if manager.is_cache_enabled() + && part_number.is_none() + && range.is_none() + && let Some(cached) = manager.get_cached_object(&cache_key).await + { + let cache_serve_duration = request_start.elapsed(); - debug!("Serving object from response cache: {} (latency: {:?})", cache_key, cache_serve_duration); + debug!("Serving object from response cache: {} (latency: {:?})", cache_key, cache_serve_duration); - #[cfg(feature = "metrics")] - { - use metrics::{counter, histogram}; - counter!("rustfs.get.object.cache.served.total").increment(1); - histogram!("rustfs.get.object.cache.serve.duration.seconds").record(cache_serve_duration.as_secs_f64()); - histogram!("rustfs.get.object.cache.size.bytes").record(cached.body.len() as f64); - } + #[cfg(feature = "metrics")] + { + use metrics::{counter, histogram}; + counter!("rustfs.get.object.cache.served.total").increment(1); + histogram!("rustfs.get.object.cache.serve.duration.seconds").record(cache_serve_duration.as_secs_f64()); + histogram!("rustfs.get.object.cache.size.bytes").record(cached.body.len() as f64); + } - // Build response from cached data with full metadata - let body_data = cached.body.clone(); - let body = Some(StreamingBlob::wrap::<_, Infallible>(futures::stream::once(async move { Ok(body_data) }))); + // Build response from cached data with full metadata + let body_data = cached.body.clone(); + let body = Some(StreamingBlob::wrap::<_, Infallible>(futures::stream::once(async move { Ok(body_data) }))); - // Parse last_modified from RFC3339 string if available - let last_modified = cached + // Parse last_modified from RFC3339 string if available + let last_modified = cached + .last_modified + .as_ref() + .and_then(|s| match OffsetDateTime::parse(s, &Rfc3339) { + Ok(dt) => Some(Timestamp::from(dt)), + Err(e) => { + warn!("Failed to parse cached last_modified '{}': {}", s, e); + None + } + }); + + // Parse content_type + let content_type = cached.content_type.as_ref().and_then(|ct| ContentType::from_str(ct).ok()); + + let output = GetObjectOutput { + body, + content_length: Some(cached.content_length), + accept_ranges: Some("bytes".to_string()), + e_tag: cached.e_tag.as_ref().map(|etag| to_s3s_etag(etag)), + last_modified, + content_type, + cache_control: cached.cache_control.clone(), + content_disposition: cached.content_disposition.clone(), + content_encoding: cached.content_encoding.clone(), + content_language: cached.content_language.clone(), + version_id: cached.version_id.clone(), + delete_marker: Some(cached.delete_marker), + tag_count: cached.tag_count, + metadata: if cached.user_metadata.is_empty() { + None + } else { + Some(cached.user_metadata.clone()) + }, + ..Default::default() + }; + + // CRITICAL: Build ObjectInfo for event notification before calling complete(). + // This ensures S3 bucket notifications (s3:GetObject events) include proper + // object metadata for event-driven workflows (Lambda, SNS, SQS). + let event_info = ObjectInfo { + bucket: bucket.clone(), + name: key.clone(), + storage_class: cached.storage_class.clone(), + mod_time: cached .last_modified .as_ref() - .and_then(|s| match OffsetDateTime::parse(s, &Rfc3339) { - Ok(dt) => Some(Timestamp::from(dt)), - Err(e) => { - warn!("Failed to parse cached last_modified '{}': {}", s, e); - None - } - }); + .and_then(|s| OffsetDateTime::parse(s, &Rfc3339).ok()), + size: cached.content_length, + actual_size: cached.content_length, + is_dir: false, + user_defined: cached.user_metadata.clone(), + version_id: cached.version_id.as_ref().and_then(|v| Uuid::parse_str(v).ok()), + delete_marker: cached.delete_marker, + content_type: cached.content_type.clone(), + content_encoding: cached.content_encoding.clone(), + etag: cached.e_tag.clone(), + ..Default::default() + }; - // Parse content_type - let content_type = cached.content_type.as_ref().and_then(|ct| ContentType::from_str(ct).ok()); + // Set object info and version_id on helper for proper event notification + let version_id_str = req.input.version_id.clone().unwrap_or_default(); + helper = helper.object(event_info).version_id(version_id_str); - let output = GetObjectOutput { - body, - content_length: Some(cached.content_length), - accept_ranges: Some("bytes".to_string()), - e_tag: cached.e_tag.as_ref().map(|etag| to_s3s_etag(etag)), - last_modified, - content_type, - cache_control: cached.cache_control.clone(), - content_disposition: cached.content_disposition.clone(), - content_encoding: cached.content_encoding.clone(), - content_language: cached.content_language.clone(), - version_id: cached.version_id.clone(), - delete_marker: Some(cached.delete_marker), - tag_count: cached.tag_count, - metadata: if cached.user_metadata.is_empty() { - None - } else { - Some(cached.user_metadata.clone()) - }, - ..Default::default() - }; - - // CRITICAL: Build ObjectInfo for event notification before calling complete(). - // This ensures S3 bucket notifications (s3:GetObject events) include proper - // object metadata for event-driven workflows (Lambda, SNS, SQS). - let event_info = ObjectInfo { - bucket: bucket.clone(), - name: key.clone(), - storage_class: cached.storage_class.clone(), - mod_time: cached - .last_modified - .as_ref() - .and_then(|s| OffsetDateTime::parse(s, &Rfc3339).ok()), - size: cached.content_length, - actual_size: cached.content_length, - is_dir: false, - user_defined: cached.user_metadata.clone(), - version_id: cached.version_id.as_ref().and_then(|v| Uuid::parse_str(v).ok()), - delete_marker: cached.delete_marker, - content_type: cached.content_type.clone(), - content_encoding: cached.content_encoding.clone(), - etag: cached.e_tag.clone(), - ..Default::default() - }; - - // Set object info and version_id on helper for proper event notification - let version_id_str = req.input.version_id.clone().unwrap_or_default(); - helper = helper.object(event_info).version_id(version_id_str); - - // Call helper.complete() for cache hits to ensure - // S3 bucket notifications (s3:GetObject events) are triggered. - // This ensures event-driven workflows (Lambda, SNS) work correctly - // for both cache hits and misses. - let result = Ok(S3Response::new(output)); - let _ = helper.complete(&result); - return result; - } + // Call helper.complete() for cache hits to ensure + // S3 bucket notifications (s3:GetObject events) are triggered. + // This ensures event-driven workflows (Lambda, SNS) work correctly + // for both cache hits and misses. + let result = Ok(S3Response::new(output)); + let _ = helper.complete(&result); + return result; } // TODO: getObjectInArchiveFileHandler object = xxx.zip/xxx/xxx.xxx @@ -1954,10 +1953,10 @@ impl S3 for FS { let part_number = part_number.map(|v| v as usize); - if let Some(part_num) = part_number { - if part_num == 0 { - return Err(s3_error!(InvalidArgument, "Invalid part number: part number must be greater than 0")); - } + if let Some(part_num) = part_number + && part_num == 0 + { + return Err(s3_error!(InvalidArgument, "Invalid part number: part number must be greater than 0")); } let rs = range.map(|v| match v { @@ -2065,10 +2064,10 @@ impl S3 for FS { let mut rs = rs; - if let Some(part_number) = part_number { - if rs.is_none() { - rs = HTTPRangeSpec::from_object_info(&info, part_number); - } + if let Some(part_number) = part_number + && rs.is_none() + { + rs = HTTPRangeSpec::from_object_info(&info, part_number); } let mut content_length = info.get_actual_size().map_err(ApiError::from)?; @@ -2183,24 +2182,23 @@ impl S3 for FS { } } - if stored_sse_algorithm.is_none() { - if let Some((key_bytes, nonce, original_size)) = + if stored_sse_algorithm.is_none() + && let Some((key_bytes, nonce, original_size)) = decrypt_managed_encryption_key(&bucket, &key, &info.user_defined).await? - { - if info.parts.len() > 1 { - let (reader, plain_size) = decrypt_multipart_managed_stream(final_stream, &info.parts, key_bytes, nonce) - .await - .map_err(ApiError::from)?; - final_stream = reader; - managed_original_size = Some(plain_size); - } else { - let warp_reader = WarpReader::new(final_stream); - let decrypt_reader = DecryptReader::new(warp_reader, key_bytes, nonce); - final_stream = Box::new(decrypt_reader); - managed_original_size = original_size; - } - managed_encryption_applied = true; + { + if info.parts.len() > 1 { + let (reader, plain_size) = decrypt_multipart_managed_stream(final_stream, &info.parts, key_bytes, nonce) + .await + .map_err(ApiError::from)?; + final_stream = reader; + managed_original_size = Some(plain_size); + } else { + let warp_reader = WarpReader::new(final_stream); + let decrypt_reader = DecryptReader::new(warp_reader, key_bytes, nonce); + final_stream = Box::new(decrypt_reader); + managed_original_size = original_size; } + managed_encryption_applied = true; } // For SSE-C encrypted objects, use the original size instead of encrypted size @@ -2518,10 +2516,10 @@ impl S3 for FS { let part_number = part_number.map(|v| v as usize); - if let Some(part_num) = part_number { - if part_num == 0 { - return Err(s3_error!(InvalidArgument, "part_number invalid")); - } + if let Some(part_num) = part_number + && part_num == 0 + { + return Err(s3_error!(InvalidArgument, "part_number invalid")); } let rs = range.map(|v| match v { @@ -2558,16 +2556,14 @@ impl S3 for FS { return Err(S3Error::new(S3ErrorCode::MethodNotAllowed)); } - if let Some(match_etag) = if_none_match { - if let Some(strong_etag) = match_etag.into_etag() { - if info - .etag - .as_ref() - .is_some_and(|etag| ETag::Strong(etag.clone()) == strong_etag) - { - return Err(S3Error::new(S3ErrorCode::NotModified)); - } - } + if let Some(match_etag) = if_none_match + && let Some(strong_etag) = match_etag.into_etag() + && info + .etag + .as_ref() + .is_some_and(|etag| ETag::Strong(etag.clone()) == strong_etag) + { + return Err(S3Error::new(S3ErrorCode::NotModified)); } if let Some(modified_since) = if_modified_since { @@ -2581,22 +2577,21 @@ impl S3 for FS { } if let Some(match_etag) = if_match { - if let Some(strong_etag) = match_etag.into_etag() { - if info + if let Some(strong_etag) = match_etag.into_etag() + && info .etag .as_ref() .is_some_and(|etag| ETag::Strong(etag.clone()) != strong_etag) - { - return Err(S3Error::new(S3ErrorCode::PreconditionFailed)); - } - } - } else if let Some(unmodified_since) = if_unmodified_since { - if info.mod_time.is_some_and(|mod_time| { - let give_time: OffsetDateTime = unmodified_since.into(); - mod_time > give_time.add(time::Duration::seconds(1)) - }) { + { return Err(S3Error::new(S3ErrorCode::PreconditionFailed)); } + } else if let Some(unmodified_since) = if_unmodified_since + && info.mod_time.is_some_and(|mod_time| { + let give_time: OffsetDateTime = unmodified_since.into(); + mod_time > give_time.add(time::Duration::seconds(1)) + }) + { + return Err(S3Error::new(S3ErrorCode::PreconditionFailed)); } let event_info = info.clone(); @@ -3080,10 +3075,10 @@ impl S3 for FS { let input = req.input; // Save SSE-C parameters before moving input - if let Some(ref storage_class) = input.storage_class { - if !is_valid_storage_class(storage_class.as_str()) { - return Err(s3_error!(InvalidStorageClass)); - } + if let Some(ref storage_class) = input.storage_class + && !is_valid_storage_class(storage_class.as_str()) + { + return Err(s3_error!(InvalidStorageClass)); } let PutObjectInput { body, @@ -3116,27 +3111,23 @@ impl S3 for FS { match store.get_object_info(&bucket, &key, &ObjectOptions::default()).await { Ok(info) => { if !info.delete_marker { - if let Some(ifmatch) = if_match { - if let Some(strong_etag) = ifmatch.into_etag() { - if info - .etag - .as_ref() - .is_some_and(|etag| ETag::Strong(etag.clone()) != strong_etag) - { - return Err(s3_error!(PreconditionFailed)); - } - } + if let Some(ifmatch) = if_match + && let Some(strong_etag) = ifmatch.into_etag() + && info + .etag + .as_ref() + .is_some_and(|etag| ETag::Strong(etag.clone()) != strong_etag) + { + return Err(s3_error!(PreconditionFailed)); } - if let Some(ifnonematch) = if_none_match { - if let Some(strong_etag) = ifnonematch.into_etag() { - if info - .etag - .as_ref() - .is_some_and(|etag| ETag::Strong(etag.clone()) == strong_etag) - { - return Err(s3_error!(PreconditionFailed)); - } - } + if let Some(ifnonematch) = if_none_match + && let Some(strong_etag) = ifnonematch.into_etag() + && info + .etag + .as_ref() + .is_some_and(|etag| ETag::Strong(etag.clone()) == strong_etag) + { + return Err(s3_error!(PreconditionFailed)); } } } @@ -3344,30 +3335,27 @@ impl S3 for FS { } // Apply managed SSE (SSE-S3 or SSE-KMS) when requested - if sse_customer_algorithm.is_none() { - if let Some(sse_alg) = &effective_sse { - if is_managed_sse(sse_alg) { - let material = - create_managed_encryption_material(&bucket, &key, sse_alg, effective_kms_key_id.clone(), actual_size) - .await?; + if sse_customer_algorithm.is_none() + && let Some(sse_alg) = &effective_sse + && is_managed_sse(sse_alg) + { + let material = + create_managed_encryption_material(&bucket, &key, sse_alg, effective_kms_key_id.clone(), actual_size).await?; - let ManagedEncryptionMaterial { - data_key, - headers, - kms_key_id: kms_key_used, - } = material; + let ManagedEncryptionMaterial { + data_key, + headers, + kms_key_id: kms_key_used, + } = material; - let key_bytes = data_key.plaintext_key; - let nonce = data_key.nonce; + let key_bytes = data_key.plaintext_key; + let nonce = data_key.nonce; - metadata.extend(headers); - effective_kms_key_id = Some(kms_key_used.clone()); + metadata.extend(headers); + effective_kms_key_id = Some(kms_key_used.clone()); - let encrypt_reader = EncryptReader::new(reader, key_bytes, nonce); - reader = - HashReader::new(Box::new(encrypt_reader), -1, actual_size, None, None, false).map_err(ApiError::from)?; - } - } + let encrypt_reader = EncryptReader::new(reader, key_bytes, nonce); + reader = HashReader::new(Box::new(encrypt_reader), -1, actual_size, None, None, false).map_err(ApiError::from)?; } let mut reader = PutObjReader::new(reader); @@ -3428,8 +3416,8 @@ impl S3 for FS { let mut checksum_sha256 = input.checksum_sha256; let mut checksum_crc64nvme = input.checksum_crc64nvme; - if let Some(alg) = &input.checksum_algorithm { - if let Some(Some(checksum_str)) = req.trailing_headers.as_ref().map(|trailer| { + if let Some(alg) = &input.checksum_algorithm + && let Some(Some(checksum_str)) = req.trailing_headers.as_ref().map(|trailer| { let key = match alg.as_str() { ChecksumAlgorithm::CRC32 => rustfs_rio::ChecksumType::CRC32.key(), ChecksumAlgorithm::CRC32C => rustfs_rio::ChecksumType::CRC32C.key(), @@ -3443,15 +3431,15 @@ impl S3 for FS { .get(key.unwrap_or_default()) .and_then(|value| value.to_str().ok().map(|s| s.to_string())) }) - }) { - match alg.as_str() { - ChecksumAlgorithm::CRC32 => checksum_crc32 = checksum_str, - ChecksumAlgorithm::CRC32C => checksum_crc32c = checksum_str, - ChecksumAlgorithm::SHA1 => checksum_sha1 = checksum_str, - ChecksumAlgorithm::SHA256 => checksum_sha256 = checksum_str, - ChecksumAlgorithm::CRC64NVME => checksum_crc64nvme = checksum_str, - _ => (), - } + }) + { + match alg.as_str() { + ChecksumAlgorithm::CRC32 => checksum_crc32 = checksum_str, + ChecksumAlgorithm::CRC32C => checksum_crc32c = checksum_str, + ChecksumAlgorithm::SHA1 => checksum_sha1 = checksum_str, + ChecksumAlgorithm::SHA256 => checksum_sha256 = checksum_str, + ChecksumAlgorithm::CRC64NVME => checksum_crc64nvme = checksum_str, + _ => (), } } @@ -3495,10 +3483,10 @@ impl S3 for FS { } = req.input.clone(); // Validate storage class if provided - if let Some(ref storage_class) = storage_class { - if !is_valid_storage_class(storage_class.as_str()) { - return Err(s3_error!(InvalidStorageClass)); - } + if let Some(ref storage_class) = storage_class + && !is_valid_storage_class(storage_class.as_str()) + { + return Err(s3_error!(InvalidStorageClass)); } // mc cp step 3 @@ -3654,10 +3642,10 @@ impl S3 for FS { let mut body_stream = body.ok_or_else(|| s3_error!(IncompleteBody))?; if size.is_none() { - if let Some(val) = req.headers.get(AMZ_DECODED_CONTENT_LENGTH) { - if let Some(x) = atoi::atoi::(val.as_bytes()) { - size = Some(x); - } + if let Some(val) = req.headers.get(AMZ_DECODED_CONTENT_LENGTH) + && let Some(x) = atoi::atoi::(val.as_bytes()) + { + size = Some(x); } if size.is_none() { @@ -3828,8 +3816,8 @@ impl S3 for FS { let mut checksum_sha256 = input.checksum_sha256; let mut checksum_crc64nvme = input.checksum_crc64nvme; - if let Some(alg) = &input.checksum_algorithm { - if let Some(Some(checksum_str)) = req.trailing_headers.as_ref().map(|trailer| { + if let Some(alg) = &input.checksum_algorithm + && let Some(Some(checksum_str)) = req.trailing_headers.as_ref().map(|trailer| { let key = match alg.as_str() { ChecksumAlgorithm::CRC32 => rustfs_rio::ChecksumType::CRC32.key(), ChecksumAlgorithm::CRC32C => rustfs_rio::ChecksumType::CRC32C.key(), @@ -3843,15 +3831,15 @@ impl S3 for FS { .get(key.unwrap_or_default()) .and_then(|value| value.to_str().ok().map(|s| s.to_string())) }) - }) { - match alg.as_str() { - ChecksumAlgorithm::CRC32 => checksum_crc32 = checksum_str, - ChecksumAlgorithm::CRC32C => checksum_crc32c = checksum_str, - ChecksumAlgorithm::SHA1 => checksum_sha1 = checksum_str, - ChecksumAlgorithm::SHA256 => checksum_sha256 = checksum_str, - ChecksumAlgorithm::CRC64NVME => checksum_crc64nvme = checksum_str, - _ => (), - } + }) + { + match alg.as_str() { + ChecksumAlgorithm::CRC32 => checksum_crc32 = checksum_str, + ChecksumAlgorithm::CRC32C => checksum_crc32c = checksum_str, + ChecksumAlgorithm::SHA1 => checksum_sha1 = checksum_str, + ChecksumAlgorithm::SHA256 => checksum_sha256 = checksum_str, + ChecksumAlgorithm::CRC64NVME => checksum_crc64nvme = checksum_str, + _ => (), } } @@ -3949,16 +3937,14 @@ impl S3 for FS { } } - if let Some(if_none_match) = copy_source_if_none_match { - if let Some(ref etag) = src_info.etag { - if let Some(strong_etag) = if_none_match.into_etag() { - if ETag::Strong(etag.clone()) == strong_etag { - return Err(s3_error!(PreconditionFailed)); - } - } - // Weak ETag in If-None-Match is ignored (doesn't match) - } + if let Some(if_none_match) = copy_source_if_none_match + && let Some(ref etag) = src_info.etag + && let Some(strong_etag) = if_none_match.into_etag() + && ETag::Strong(etag.clone()) == strong_etag + { + return Err(s3_error!(PreconditionFailed)); } + // Weak ETag in If-None-Match is ignored (doesn't match) // TODO: Implement proper time comparison for if_modified_since and if_unmodified_since // For now, we'll skip these conditions @@ -4157,10 +4143,10 @@ impl S3 for FS { let max_uploads = max_uploads.map(|x| x as usize).unwrap_or(MAX_PARTS_COUNT); - if let Some(key_marker) = &key_marker { - if !key_marker.starts_with(prefix.as_str()) { - return Err(s3_error!(NotImplemented, "Invalid key marker")); - } + if let Some(key_marker) = &key_marker + && !key_marker.starts_with(prefix.as_str()) + { + return Err(s3_error!(NotImplemented, "Invalid key marker")); } let result = store @@ -4227,27 +4213,23 @@ impl S3 for FS { match store.get_object_info(&bucket, &key, &ObjectOptions::default()).await { Ok(info) => { if !info.delete_marker { - if let Some(ifmatch) = if_match { - if let Some(strong_etag) = ifmatch.into_etag() { - if info - .etag - .as_ref() - .is_some_and(|etag| ETag::Strong(etag.clone()) != strong_etag) - { - return Err(s3_error!(PreconditionFailed)); - } - } + if let Some(ifmatch) = if_match + && let Some(strong_etag) = ifmatch.into_etag() + && info + .etag + .as_ref() + .is_some_and(|etag| ETag::Strong(etag.clone()) != strong_etag) + { + return Err(s3_error!(PreconditionFailed)); } - if let Some(ifnonematch) = if_none_match { - if let Some(strong_etag) = ifnonematch.into_etag() { - if info - .etag - .as_ref() - .is_some_and(|etag| ETag::Strong(etag.clone()) == strong_etag) - { - return Err(s3_error!(PreconditionFailed)); - } - } + if let Some(ifnonematch) = if_none_match + && let Some(strong_etag) = ifnonematch.into_etag() + && info + .etag + .as_ref() + .is_some_and(|etag| ETag::Strong(etag.clone()) == strong_etag) + { + return Err(s3_error!(PreconditionFailed)); } } } @@ -4852,11 +4834,11 @@ impl S3 for FS { let Some(input_cfg) = lifecycle_configuration else { return Err(s3_error!(InvalidArgument)) }; let rcfg = metadata_sys::get_object_lock_config(&bucket).await; - if let Ok(rcfg) = rcfg { - if let Err(err) = input_cfg.validate(&rcfg.0).await { - //return Err(S3Error::with_message(S3ErrorCode::Custom("BucketLockValidateFailed".into()), err.to_string())); - return Err(S3Error::with_message(S3ErrorCode::Custom("ValidateFailed".into()), err.to_string())); - } + if let Ok(rcfg) = rcfg + && let Err(err) = input_cfg.validate(&rcfg.0).await + { + //return Err(S3Error::with_message(S3ErrorCode::Custom("BucketLockValidateFailed".into()), err.to_string())); + return Err(S3Error::with_message(S3ErrorCode::Custom("ValidateFailed".into()), err.to_string())); } if let Err(err) = validate_transition_tier(&input_cfg).await { @@ -5735,23 +5717,23 @@ impl S3 for FS { /// Auxiliary functions: extract prefixes and suffixes fn extract_prefix_suffix(filter: Option<&NotificationConfigurationFilter>) -> (String, String) { - if let Some(filter) = filter { - if let Some(filter_rules) = &filter.key { - let mut prefix = String::new(); - let mut suffix = String::new(); - if let Some(rules) = &filter_rules.filter_rules { - for rule in rules { - if let (Some(name), Some(value)) = (rule.name.as_ref(), rule.value.as_ref()) { - match name.as_str() { - "prefix" => prefix = value.clone(), - "suffix" => suffix = value.clone(), - _ => {} - } + if let Some(filter) = filter + && let Some(filter_rules) = &filter.key + { + let mut prefix = String::new(); + let mut suffix = String::new(); + if let Some(rules) = &filter_rules.filter_rules { + for rule in rules { + if let (Some(name), Some(value)) = (rule.name.as_ref(), rule.value.as_ref()) { + match name.as_str() { + "prefix" => prefix = value.clone(), + "suffix" => suffix = value.clone(), + _ => {} } } } - return (prefix, suffix); } + return (prefix, suffix); } (String::new(), String::new()) } diff --git a/rustfs/src/storage/helper.rs b/rustfs/src/storage/helper.rs index 31ad115a..cf732fd1 100644 --- a/rustfs/src/storage/helper.rs +++ b/rustfs/src/storage/helper.rs @@ -86,10 +86,10 @@ impl OperationHelper { .req_path(req.uri.path().to_string()) .req_query(extract_req_params(req)); - if let Some(req_id) = req.headers.get("x-amz-request-id") { - if let Ok(id_str) = req_id.to_str() { - audit_builder = audit_builder.request_id(id_str); - } + if let Some(req_id) = req.headers.get("x-amz-request-id") + && let Ok(id_str) = req_id.to_str() + { + audit_builder = audit_builder.request_id(id_str); } // initialize event builder @@ -194,15 +194,15 @@ impl Drop for OperationHelper { } // Distribute event notification (only on success) - if self.api_builder.0.status.as_deref() == Some("success") { - if let Some(builder) = self.event_builder.take() { - let event_args = builder.build(); - // Avoid generating notifications for copy requests - if !event_args.is_replication_request() { - spawn_background(async move { - notifier_global::notify(event_args).await; - }); - } + if self.api_builder.0.status.as_deref() == Some("success") + && let Some(builder) = self.event_builder.take() + { + let event_args = builder.build(); + // Avoid generating notifications for copy requests + if !event_args.is_replication_request() { + spawn_background(async move { + notifier_global::notify(event_args).await; + }); } } } diff --git a/rustfs/src/storage/options.rs b/rustfs/src/storage/options.rs index aacd6089..8a3031f8 100644 --- a/rustfs/src/storage/options.rs +++ b/rustfs/src/storage/options.rs @@ -64,13 +64,12 @@ pub async fn del_opts( let vid = vid.map(|v| v.as_str().trim().to_owned()); - if let Some(ref id) = vid { - if *id != Uuid::nil().to_string() - && let Err(err) = Uuid::parse_str(id.as_str()) - { - error!("del_opts: invalid version id: {} error: {}", id, err); - return Err(StorageError::InvalidVersionID(bucket.to_owned(), object.to_owned(), id.clone())); - } + if let Some(ref id) = vid + && *id != Uuid::nil().to_string() + && let Err(err) = Uuid::parse_str(id.as_str()) + { + error!("del_opts: invalid version id: {} error: {}", id, err); + return Err(StorageError::InvalidVersionID(bucket.to_owned(), object.to_owned(), id.clone())); } let mut opts = put_opts_from_headers(headers, metadata.clone()).map_err(|err| { @@ -111,12 +110,11 @@ pub async fn get_opts( let vid = vid.map(|v| v.as_str().trim().to_owned()); - if let Some(ref id) = vid { - if *id != Uuid::nil().to_string() - && let Err(_err) = Uuid::parse_str(id.as_str()) - { - return Err(StorageError::InvalidVersionID(bucket.to_owned(), object.to_owned(), id.clone())); - } + if let Some(ref id) = vid + && *id != Uuid::nil().to_string() + && let Err(_err) = Uuid::parse_str(id.as_str()) + { + return Err(StorageError::InvalidVersionID(bucket.to_owned(), object.to_owned(), id.clone())); } let mut opts = get_default_opts(headers, HashMap::new(), false) @@ -187,12 +185,11 @@ pub async fn put_opts( let vid = vid.map(|v| v.as_str().trim().to_owned()); - if let Some(ref id) = vid { - if *id != Uuid::nil().to_string() - && let Err(_err) = Uuid::parse_str(id.as_str()) - { - return Err(StorageError::InvalidVersionID(bucket.to_owned(), object.to_owned(), id.clone())); - } + if let Some(ref id) = vid + && *id != Uuid::nil().to_string() + && let Err(_err) = Uuid::parse_str(id.as_str()) + { + return Err(StorageError::InvalidVersionID(bucket.to_owned(), object.to_owned(), id.clone())); } let mut opts = put_opts_from_headers(headers, metadata) @@ -512,12 +509,11 @@ fn skip_content_sha256_cksum(headers: &HeaderMap) -> bool { // such broken clients and content-length > 0. // For now, we'll assume strict compatibility is disabled // In a real implementation, you would check a global config - if let Some(content_length) = headers.get("content-length") { - if let Ok(length_str) = content_length.to_str() { - if let Ok(length) = length_str.parse::() { - return length > 0; // && !global_server_ctxt.strict_s3_compat - } - } + if let Some(content_length) = headers.get("content-length") + && let Ok(length_str) = content_length.to_str() + && let Ok(length) = length_str.parse::() + { + return length > 0; // && !global_server_ctxt.strict_s3_compat } false } @@ -546,10 +542,10 @@ fn get_content_sha256_cksum(headers: &HeaderMap, service_type: Serv }; // We found 'X-Amz-Content-Sha256' return the captured value. - if let Some(header_value) = content_sha256 { - if let Ok(value) = header_value.to_str() { - return value.to_string(); - } + if let Some(header_value) = content_sha256 + && let Ok(value) = header_value.to_str() + { + return value.to_string(); } // We couldn't find 'X-Amz-Content-Sha256'. diff --git a/rustfs/src/version.rs b/rustfs/src/version.rs index 51f9ee98..04678c2e 100644 --- a/rustfs/src/version.rs +++ b/rustfs/src/version.rs @@ -75,10 +75,10 @@ fn increment_version(version: &str) -> Result let (major, minor, patch, pre_release) = parse_version(version)?; // If there's a pre-release identifier, increment the pre-release version number - if let Some(pre) = pre_release { - if let Some(new_pre) = increment_pre_release(&pre) { - return Ok(format!("{major}.{minor}.{patch}-{new_pre}")); - } + if let Some(pre) = pre_release + && let Some(new_pre) = increment_pre_release(&pre) + { + return Ok(format!("{major}.{minor}.{patch}-{new_pre}")); } // Otherwise increment patch version number @@ -107,10 +107,10 @@ pub fn parse_version(version: &str) -> VersionParseResult { fn increment_pre_release(pre_release: &str) -> Option { // Handle pre-release versions like "alpha.19" let parts: Vec<&str> = pre_release.split('.').collect(); - if parts.len() == 2 { - if let Ok(num) = parts[1].parse::() { - return Some(format!("{}.{}", parts[0], num + 1)); - } + if parts.len() == 2 + && let Ok(num) = parts[1].parse::() + { + return Some(format!("{}.{}", parts[0], num + 1)); } // Handle pre-release versions like "alpha19"