From b63b0762753106f15f17e2ea82959659d63d7aa5 Mon Sep 17 00:00:00 2001 From: Zhengchao An Date: Mon, 22 Jun 2026 16:53:14 +0800 Subject: [PATCH] refactor: remove remaining compatibility bridges (#3738) --- crates/heal/tests/common/mod.rs | 15 --- crates/heal/tests/common/storage_compat.rs | 43 ------ crates/heal/tests/endpoint_index_test.rs | 10 +- crates/heal/tests/heal_bug_fixes_test.rs | 22 +--- crates/heal/tests/heal_integration_test.rs | 13 +- crates/scanner/tests/common/mod.rs | 15 --- crates/scanner/tests/common/storage_compat.rs | 124 ------------------ .../tests/lifecycle_integration_test.rs | 58 ++++---- docs/architecture/migration-progress.md | 98 ++++++++++++-- fuzz/fuzz_targets/bucket_validation.rs | 5 +- .../bucket_validation/storage_compat.rs | 36 ----- fuzz/fuzz_targets/path_containment.rs | 7 +- .../path_containment/storage_compat.rs | 31 ----- rustfs/src/config/config_test.rs | 4 +- rustfs/src/config_storage_compat.rs | 19 --- rustfs/src/error.rs | 2 +- rustfs/src/error_storage_compat.rs | 19 --- rustfs/src/init.rs | 30 +++-- rustfs/src/lib.rs | 6 - rustfs/src/runtime_capabilities.rs | 10 +- .../runtime_capabilities_storage_compat.rs | 34 ----- rustfs/src/startup_background.rs | 2 +- rustfs/src/startup_bucket_metadata.rs | 19 +-- rustfs/src/startup_fs_guard.rs | 2 +- rustfs/src/startup_iam.rs | 2 +- rustfs/src/startup_lifecycle.rs | 2 +- rustfs/src/startup_notification.rs | 14 +- rustfs/src/startup_server.rs | 2 +- rustfs/src/startup_services.rs | 2 +- rustfs/src/startup_shutdown.rs | 2 +- rustfs/src/startup_storage.rs | 43 +++--- rustfs/src/startup_storage_compat.rs | 105 --------------- rustfs/src/table_catalog.rs | 55 ++++---- rustfs/src/table_catalog_storage_compat.rs | 41 ------ rustfs/src/workload_admission.rs | 18 ++- .../src/workload_admission_storage_compat.rs | 36 ----- scripts/check_architecture_migration_rules.sh | 69 +++++++++- 37 files changed, 324 insertions(+), 691 deletions(-) delete mode 100644 crates/heal/tests/common/mod.rs delete mode 100644 crates/heal/tests/common/storage_compat.rs delete mode 100644 crates/scanner/tests/common/mod.rs delete mode 100644 crates/scanner/tests/common/storage_compat.rs delete mode 100644 fuzz/fuzz_targets/bucket_validation/storage_compat.rs delete mode 100644 fuzz/fuzz_targets/path_containment/storage_compat.rs delete mode 100644 rustfs/src/config_storage_compat.rs delete mode 100644 rustfs/src/error_storage_compat.rs delete mode 100644 rustfs/src/runtime_capabilities_storage_compat.rs delete mode 100644 rustfs/src/startup_storage_compat.rs delete mode 100644 rustfs/src/table_catalog_storage_compat.rs delete mode 100644 rustfs/src/workload_admission_storage_compat.rs diff --git a/crates/heal/tests/common/mod.rs b/crates/heal/tests/common/mod.rs deleted file mode 100644 index c689b0969..000000000 --- a/crates/heal/tests/common/mod.rs +++ /dev/null @@ -1,15 +0,0 @@ -// Copyright 2024 RustFS Team -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -pub(crate) mod storage_compat; diff --git a/crates/heal/tests/common/storage_compat.rs b/crates/heal/tests/common/storage_compat.rs deleted file mode 100644 index c422931b6..000000000 --- a/crates/heal/tests/common/storage_compat.rs +++ /dev/null @@ -1,43 +0,0 @@ -// Copyright 2024 RustFS Team -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -#![allow(dead_code, unused_imports)] - -use std::sync::Arc; - -use rustfs_ecstore::api::bucket as ecstore_bucket; -use rustfs_ecstore::api::disk as ecstore_disk; -use rustfs_ecstore::api::error as ecstore_error; -use rustfs_ecstore::api::layout as ecstore_layout; -use rustfs_ecstore::api::storage as ecstore_storage; - -pub(crate) type DiskStore = ecstore_disk::DiskStore; -pub(crate) type ECStore = ecstore_storage::ECStore; -pub(crate) type Endpoint = ecstore_disk::endpoint::Endpoint; -pub(crate) type EndpointServerPools = ecstore_layout::EndpointServerPools; -pub(crate) type Endpoints = ecstore_layout::Endpoints; -pub(crate) type PoolEndpoints = ecstore_layout::PoolEndpoints; - -#[allow(non_snake_case)] -pub(crate) fn EndpointServerPools(pools: Vec) -> EndpointServerPools { - ecstore_layout::EndpointServerPools::from(pools) -} - -pub(crate) async fn init_bucket_metadata_sys(api: Arc, buckets: Vec) { - ecstore_bucket::metadata_sys::init_bucket_metadata_sys(api, buckets).await; -} - -pub(crate) async fn init_local_disks(endpoint_pools: EndpointServerPools) -> ecstore_error::Result<()> { - ecstore_storage::init_local_disks(endpoint_pools).await -} diff --git a/crates/heal/tests/endpoint_index_test.rs b/crates/heal/tests/endpoint_index_test.rs index 26f4f037d..dca523588 100644 --- a/crates/heal/tests/endpoint_index_test.rs +++ b/crates/heal/tests/endpoint_index_test.rs @@ -14,9 +14,11 @@ //! test endpoint index settings -mod common; - -use common::storage_compat::{ECStore, Endpoint, EndpointServerPools, Endpoints, PoolEndpoints, init_local_disks}; +use rustfs_ecstore::api::{ + disk::endpoint::Endpoint, + layout::{EndpointServerPools, Endpoints, PoolEndpoints}, + storage::{ECStore, init_local_disks}, +}; use std::net::SocketAddr; use tempfile::TempDir; use tokio_util::sync::CancellationToken; @@ -58,7 +60,7 @@ async fn test_endpoint_index_settings() -> anyhow::Result<()> { platform: format!("OS: {} | Arch: {}", std::env::consts::OS, std::env::consts::ARCH), }; - let endpoint_pools = EndpointServerPools(vec![pool_endpoints]); + let endpoint_pools = EndpointServerPools::from(vec![pool_endpoints]); // validate all endpoint indexes are in valid range for (i, ep) in endpoints.iter().enumerate() { diff --git a/crates/heal/tests/heal_bug_fixes_test.rs b/crates/heal/tests/heal_bug_fixes_test.rs index 26e76d0f5..25142623d 100644 --- a/crates/heal/tests/heal_bug_fixes_test.rs +++ b/crates/heal/tests/heal_bug_fixes_test.rs @@ -12,8 +12,7 @@ // See the License for the specific language governing permissions and // limitations under the License. -mod common; - +use rustfs_ecstore::api::disk::{DiskStore, endpoint::Endpoint}; use rustfs_heal::heal::{ event::{HealEvent, Severity}, task::{HealPriority, HealType}, @@ -22,8 +21,6 @@ use rustfs_heal::heal::{ #[test] fn test_heal_event_to_heal_request_no_panic() { - use common::storage_compat::Endpoint; - // Test that invalid pool/set indices don't cause panic // Create endpoint using try_from or similar method let endpoint_result = Endpoint::try_from("http://localhost:9000"); @@ -47,8 +44,6 @@ fn test_heal_event_to_heal_request_no_panic() { #[test] fn test_heal_event_to_heal_request_valid_indices() { - use common::storage_compat::Endpoint; - // Test that valid indices work correctly let endpoint_result = Endpoint::try_from("http://localhost:9000"); if let Ok(mut endpoint) = endpoint_result { @@ -190,13 +185,10 @@ fn test_heal_task_status_atomic_update() { async fn ec_decode_rebuild(&self, _bucket: &str, _object: &str) -> rustfs_heal::Result> { Ok(vec![]) } - async fn get_disk_status( - &self, - _endpoint: &common::storage_compat::Endpoint, - ) -> rustfs_heal::Result { + async fn get_disk_status(&self, _endpoint: &Endpoint) -> rustfs_heal::Result { Ok(rustfs_heal::heal::storage::DiskStatus::Ok) } - async fn format_disk(&self, _endpoint: &common::storage_compat::Endpoint) -> rustfs_heal::Result<()> { + async fn format_disk(&self, _endpoint: &Endpoint) -> rustfs_heal::Result<()> { Ok(()) } async fn get_bucket_info(&self, _bucket: &str) -> rustfs_heal::Result> { @@ -250,7 +242,7 @@ fn test_heal_task_status_atomic_update() { ) -> rustfs_heal::Result<(Vec, Option, bool)> { Ok((vec![], None, false)) } - async fn get_disk_for_resume(&self, _set_disk_id: &str) -> rustfs_heal::Result { + async fn get_disk_for_resume(&self, _set_disk_id: &str) -> rustfs_heal::Result { Err(rustfs_heal::Error::other("Not implemented in mock")) } } @@ -320,11 +312,11 @@ async fn test_heal_task_transient_object_exists_skip_avoids_recreate() { Ok(Vec::new()) } - async fn get_disk_status(&self, _endpoint: &common::storage_compat::Endpoint) -> rustfs_heal::Result { + async fn get_disk_status(&self, _endpoint: &Endpoint) -> rustfs_heal::Result { Ok(DiskStatus::Ok) } - async fn format_disk(&self, _endpoint: &common::storage_compat::Endpoint) -> rustfs_heal::Result<()> { + async fn format_disk(&self, _endpoint: &Endpoint) -> rustfs_heal::Result<()> { Ok(()) } @@ -394,7 +386,7 @@ async fn test_heal_task_transient_object_exists_skip_avoids_recreate() { Ok((Vec::new(), None, false)) } - async fn get_disk_for_resume(&self, _set_disk_id: &str) -> rustfs_heal::Result { + async fn get_disk_for_resume(&self, _set_disk_id: &str) -> rustfs_heal::Result { Err(rustfs_heal::Error::other("not implemented")) } } diff --git a/crates/heal/tests/heal_integration_test.rs b/crates/heal/tests/heal_integration_test.rs index 7f11eeb83..135b560e5 100644 --- a/crates/heal/tests/heal_integration_test.rs +++ b/crates/heal/tests/heal_integration_test.rs @@ -12,13 +12,14 @@ // See the License for the specific language governing permissions and // limitations under the License. -mod common; - -use common::storage_compat::{ - ECStore, Endpoint, EndpointServerPools, Endpoints, PoolEndpoints, init_bucket_metadata_sys, init_local_disks, -}; use http::HeaderMap; use rustfs_common::heal_channel::{HealOpts, HealScanMode}; +use rustfs_ecstore::api::{ + bucket::metadata_sys::init_bucket_metadata_sys, + disk::endpoint::Endpoint, + layout::{EndpointServerPools, Endpoints, PoolEndpoints}, + storage::{ECStore, init_local_disks}, +}; use rustfs_heal::heal::{ manager::{HealConfig, HealManager}, storage::{ECStoreHealStorage, HealObjectOptions as ObjectOptions, HealPutObjReader as PutObjReader, HealStorageAPI}, @@ -119,7 +120,7 @@ async fn setup_test_env() -> (Vec, Arc, Arc ecstore_disk::error::Result; -} - -impl ScannerTestDiskExt for T -where - T: ecstore_disk::DiskAPI, -{ - async fn read_metadata(&self, volume: &str, path: &str) -> ecstore_disk::error::Result { - ecstore_disk::DiskAPI::read_metadata(self, volume, path).await - } -} - -#[allow(non_snake_case)] -pub(crate) fn EndpointServerPools(pools: Vec) -> EndpointServerPools { - ecstore_layout::EndpointServerPools::from(pools) -} - -pub(crate) struct GlobalTierConfigMgrCompat; - -#[allow(non_upper_case_globals)] -pub(crate) static GLOBAL_TierConfigMgr: GlobalTierConfigMgrCompat = GlobalTierConfigMgrCompat; - -impl std::ops::Deref for GlobalTierConfigMgrCompat { - type Target = Arc>; - - fn deref(&self) -> &Self::Target { - &ecstore_global::GLOBAL_TierConfigMgr - } -} - -pub(crate) fn build_transition_put_options( - storage_class: String, - metadata: HashMap, -) -> ecstore_client::api_put_object::PutObjectOptions { - ecstore_tier::warm_backend::build_transition_put_options(storage_class, metadata) -} - -pub(crate) async fn enqueue_transition_for_existing_objects(api: Arc, bucket: &str) -> ecstore_error::Result<()> { - ecstore_bucket::lifecycle::bucket_lifecycle_ops::enqueue_transition_for_existing_objects(api, bucket).await -} - -pub(crate) async fn init_background_expiry(api: Arc) { - ecstore_bucket::lifecycle::bucket_lifecycle_ops::init_background_expiry(api).await; -} - -pub(crate) async fn get_bucket_metadata(bucket: &str) -> ecstore_error::Result> { - ecstore_bucket::metadata_sys::get(bucket).await -} - -pub(crate) async fn init_bucket_metadata_sys(api: Arc, buckets: Vec) { - ecstore_bucket::metadata_sys::init_bucket_metadata_sys(api, buckets).await; -} - -pub(crate) async fn init_local_disks(endpoint_pools: EndpointServerPools) -> ecstore_error::Result<()> { - ecstore_storage::init_local_disks(endpoint_pools).await -} - -pub(crate) async fn new_disk(ep: &Endpoint, opt: &DiskOption) -> ecstore_disk::error::Result { - ecstore_disk::new_disk(ep, opt).await -} - -pub(crate) fn path2_bucket_object_with_base_path(base_path: &str, path: &str) -> (String, String) { - ecstore_capacity::path2_bucket_object_with_base_path(base_path, path) -} - -pub(crate) async fn update_bucket_metadata( - bucket: &str, - config_file: &str, - data: Vec, -) -> ecstore_error::Result { - ecstore_bucket::metadata_sys::update(bucket, config_file, data).await -} diff --git a/crates/scanner/tests/lifecycle_integration_test.rs b/crates/scanner/tests/lifecycle_integration_test.rs index a0142fdd8..fe91e7da6 100644 --- a/crates/scanner/tests/lifecycle_integration_test.rs +++ b/crates/scanner/tests/lifecycle_integration_test.rs @@ -12,17 +12,29 @@ // See the License for the specific language governing permissions and // limitations under the License. -mod common; - -use common::storage_compat::{ - BUCKET_LIFECYCLE_CONFIG, BucketVersioningSys, DiskOption, ECStore, Endpoint, EndpointServerPools, Endpoints, - GLOBAL_TierConfigMgr, PoolEndpoints, ReadCloser, ReaderImpl, STORAGE_FORMAT_FILE, ScannerTestDiskExt as _, - ScannerWarmBackend, TierConfig, TierMinIO, TierType, TransitionOptions, WarmBackendGetOpts, build_transition_put_options, - enqueue_transition_for_existing_objects, get_bucket_metadata, init_background_expiry, init_bucket_metadata_sys, - init_local_disks, new_disk, path2_bucket_object_with_base_path, update_bucket_metadata, -}; use futures::FutureExt; use rustfs_config::ENV_TEST_FORCE_IMMEDIATE_TRANSITION_ENQUEUE_TIMEOUT; +use rustfs_ecstore::api::{ + bucket::{ + lifecycle::{ + bucket_lifecycle_ops::{enqueue_transition_for_existing_objects, init_background_expiry}, + lifecycle::TransitionOptions, + }, + metadata::BUCKET_LIFECYCLE_CONFIG, + metadata_sys::{self, init_bucket_metadata_sys}, + versioning_sys::BucketVersioningSys, + }, + capacity::path2_bucket_object_with_base_path, + client::transition_api::{ReadCloser, ReaderImpl}, + disk::{DiskAPI as _, DiskOption, STORAGE_FORMAT_FILE, endpoint::Endpoint, new_disk}, + global::GLOBAL_TierConfigMgr, + layout::{EndpointServerPools, Endpoints, PoolEndpoints}, + storage::{ECStore, init_local_disks}, + tier::{ + tier_config::{TierConfig, TierMinIO, TierType}, + warm_backend::{WarmBackend as ScannerWarmBackend, WarmBackendGetOpts, build_transition_put_options}, + }, +}; use rustfs_filemeta::FileMeta; use rustfs_scanner::scanner_folder::ScannerItem; use rustfs_scanner::scanner_io::ScannerIODisk; @@ -110,7 +122,7 @@ async fn setup_test_env() -> (Vec, Arc) { platform: format!("OS: {} | Arch: {}", std::env::consts::OS, std::env::consts::ARCH), }; - let endpoint_pools = EndpointServerPools(vec![pool_endpoints]); + let endpoint_pools = EndpointServerPools::from(vec![pool_endpoints]); // format disks (only first time) init_local_disks(endpoint_pools.clone()).await.unwrap(); @@ -181,7 +193,7 @@ async fn setup_isolated_test_env(init_expiry: bool) -> (Vec, Arc Result<(), Box "#; - update_bucket_metadata(bucket_name, BUCKET_LIFECYCLE_CONFIG, lifecycle_xml.as_bytes().to_vec()).await?; + metadata_sys::update(bucket_name, BUCKET_LIFECYCLE_CONFIG, lifecycle_xml.as_bytes().to_vec()).await?; Ok(()) } @@ -293,7 +305,7 @@ async fn set_bucket_lifecycle_deletemarker(bucket_name: &str) -> Result<(), Box< "#; - update_bucket_metadata(bucket_name, BUCKET_LIFECYCLE_CONFIG, lifecycle_xml.as_bytes().to_vec()).await?; + metadata_sys::update(bucket_name, BUCKET_LIFECYCLE_CONFIG, lifecycle_xml.as_bytes().to_vec()).await?; Ok(()) } @@ -316,7 +328,7 @@ async fn set_bucket_lifecycle_delmarker_expiration(bucket_name: &str, days: i64) "# ); - update_bucket_metadata(bucket_name, BUCKET_LIFECYCLE_CONFIG, lifecycle_xml.into_bytes()).await?; + metadata_sys::update(bucket_name, BUCKET_LIFECYCLE_CONFIG, lifecycle_xml.into_bytes()).await?; Ok(()) } @@ -360,7 +372,7 @@ async fn set_bucket_lifecycle_transition_with_tier( "# ); - update_bucket_metadata(bucket_name, BUCKET_LIFECYCLE_CONFIG, lifecycle_xml.into_bytes()).await?; + metadata_sys::update(bucket_name, BUCKET_LIFECYCLE_CONFIG, lifecycle_xml.into_bytes()).await?; Ok(()) } @@ -595,7 +607,7 @@ async fn scan_object_with_lifecycle(disk_path: &Path, bucket: &str, object: &str .await .expect("failed to stat object metadata") .file_type(); - let lifecycle = get_bucket_metadata(bucket) + let lifecycle = metadata_sys::get(bucket) .await .expect("failed to load bucket metadata") .lifecycle_config @@ -860,7 +872,7 @@ mod serial_tests { println!("✅ Lifecycle configuration set for bucket: {bucket_name}"); // Verify lifecycle configuration was set - match get_bucket_metadata(bucket_name.as_str()).await { + match metadata_sys::get(bucket_name.as_str()).await { Ok(bucket_meta) => { assert!(bucket_meta.lifecycle_config.is_some()); println!("✅ Bucket metadata retrieved successfully"); @@ -1417,7 +1429,7 @@ mod serial_tests { "# ); - update_bucket_metadata(bucket_name.as_str(), BUCKET_LIFECYCLE_CONFIG, lifecycle_xml.into_bytes()) + metadata_sys::update(bucket_name.as_str(), BUCKET_LIFECYCLE_CONFIG, lifecycle_xml.into_bytes()) .await .expect("Failed to set lifecycle configuration"); @@ -1502,7 +1514,7 @@ mod serial_tests { "# ); - update_bucket_metadata(bucket_name.as_str(), BUCKET_LIFECYCLE_CONFIG, lifecycle_xml.into_bytes()) + metadata_sys::update(bucket_name.as_str(), BUCKET_LIFECYCLE_CONFIG, lifecycle_xml.into_bytes()) .await .expect("Failed to set lifecycle configuration"); @@ -1729,7 +1741,7 @@ mod serial_tests { "# ); - update_bucket_metadata(bucket_name.as_str(), BUCKET_LIFECYCLE_CONFIG, lifecycle_xml.into_bytes()) + metadata_sys::update(bucket_name.as_str(), BUCKET_LIFECYCLE_CONFIG, lifecycle_xml.into_bytes()) .await .expect("Failed to set lifecycle configuration"); @@ -1794,7 +1806,7 @@ mod serial_tests { "#; - update_bucket_metadata(bucket_name.as_str(), BUCKET_LIFECYCLE_CONFIG, lifecycle_xml.as_bytes().to_vec()) + metadata_sys::update(bucket_name.as_str(), BUCKET_LIFECYCLE_CONFIG, lifecycle_xml.as_bytes().to_vec()) .await .expect("Failed to set noncurrent lifecycle configuration"); @@ -1832,7 +1844,7 @@ mod serial_tests { "#; - update_bucket_metadata(bucket_name.as_str(), BUCKET_LIFECYCLE_CONFIG, lifecycle_xml.as_bytes().to_vec()) + metadata_sys::update(bucket_name.as_str(), BUCKET_LIFECYCLE_CONFIG, lifecycle_xml.as_bytes().to_vec()) .await .expect("Failed to set noncurrent lifecycle configuration"); @@ -1919,7 +1931,7 @@ mod serial_tests { "# ); - update_bucket_metadata(bucket_name.as_str(), BUCKET_LIFECYCLE_CONFIG, lifecycle_xml.into_bytes()) + metadata_sys::update(bucket_name.as_str(), BUCKET_LIFECYCLE_CONFIG, lifecycle_xml.into_bytes()) .await .expect("Failed to set lifecycle configuration"); upload_test_object(&ecstore, bucket_name.as_str(), object_name, b"expire immediately").await; diff --git a/docs/architecture/migration-progress.md b/docs/architecture/migration-progress.md index 698cb5b2e..6fb8701b4 100644 --- a/docs/architecture/migration-progress.md +++ b/docs/architecture/migration-progress.md @@ -5,16 +5,16 @@ Status values: `[ ]` not started, `[~]` in progress, `[x]` complete, `[!]` block ## Current Context - Issue: [`rustfs/backlog#660`](https://github.com/rustfs/backlog/issues/660) -- Branch: `overtrue/arch-runtime-local-compat-bridges` -- Baseline: completed `C-011/C-012/C-013/API-055/API-059/API-079/API-080/API-081/API-082/API-083/API-084/API-085/API-086/API-087/API-088/API-089/API-090/API-091/API-092/API-093/API-094/API-095/API-096/API-097/API-098/API-099/API-100/API-101/API-102/API-103/API-104/API-105/API-106/API-107/API-108/API-109/API-110/API-111/API-112/API-113/API-114/API-115/API-116`. -- Based on: API-116 slice. +- Branch: `overtrue/arch-test-fuzz-compat-bridge-cleanup` +- Baseline: completed `C-011/C-012/C-013/API-055/API-059/API-079/API-080/API-081/API-082/API-083/API-084/API-085/API-086/API-087/API-088/API-089/API-090/API-091/API-092/API-093/API-094/API-095/API-096/API-097/API-098/API-099/API-100/API-101/API-102/API-103/API-104/API-105/API-106/API-107/API-108/API-109/API-110/API-111/API-112/API-113/API-114/API-115/API-116/API-117/API-118/API-119/API-120/API-121/API-122/API-123`. +- Based on: API-123 slice. - PR type for this branch: `pure-move` - Runtime behavior changes: none. -- Rust code changes: remove app/admin, storage core, nested, handler, capacity, - server, and S3 API secondary compatibility bridges. -- CI/script changes: guard against reintroducing the removed secondary bridge - modules or their consumer paths. -- Docs changes: record the API-117 through API-121 compatibility bridge cleanup. +- Rust code changes: remove heal/scanner test and fuzz storage compatibility + bridges, then route their consumers directly to ECStore API owner modules. +- CI/script changes: allow the migrated test/fuzz targets to import owner APIs + directly and reject reintroduced test/fuzz bridge modules. +- Docs changes: record the API-124 test/fuzz bridge cleanup. ## Phase 0 Tasks @@ -709,6 +709,48 @@ Status values: `[ ]` not started, `[~]` in progress, `[x]` complete, `[!]` block - Verification: RustFS compile coverage, runtime local bridge residual scan, migration and layer guards, formatting, diff hygiene, path-only risk review, and three-expert review. +- [x] `API-122` Remove root one-off compatibility bridges. + - Completed slice: replace config test, error mapping, runtime capability, + table catalog, and workload admission consumers with direct ECStore API + imports, then delete the root one-off bridge modules. + - Acceptance: the deleted bridge files and module declarations are gone; + migration rules reject reintroduced files, declarations, or bridge + references. + - Must preserve: config disk-layout tests, API error mapping, runtime + topology snapshots, table-catalog paths and lock behavior, and workload + admission snapshots. + - Verification: RustFS compile coverage, root one-off bridge residual scan, + migration and layer guards, formatting, diff hygiene, Rust risk scan, and + three-expert review. +- [x] `API-123` Remove startup storage compatibility bridge. + - Completed slice: replace startup storage, notification, bucket metadata, + service, shutdown, server, lifecycle, IAM, background, fs guard, and init + consumers with direct ECStore API owner imports, then delete + `startup_storage_compat.rs`. + - Acceptance: startup/init consumers no longer route through the startup + compatibility bridge; migration rules reject the deleted file, module + declaration, or bridge references. + - Must preserve: endpoint parsing, unsupported filesystem policy, ECStore + initialization, global endpoint/erasure registration, local disk and lock + client initialization, config migration/retry behavior, metadata/IAM + migration, notification startup, background replication, scanner/heal + startup and shutdown, and readiness marking. + - Verification: RustFS compile coverage, startup bridge residual scan, + migration and layer guards, formatting, diff hygiene, Rust risk scan, and + three-expert review. +- [x] `API-124` Remove test and fuzz storage compatibility bridges. + - Completed slice: replace heal tests, scanner lifecycle tests, and bucket/path + fuzz targets with direct ECStore API owner imports, then delete their local + `storage_compat.rs` modules. + - Acceptance: migrated test/fuzz targets no longer route through local + storage compatibility bridges; migration rules reject deleted files, module + declarations, or bridge references. + - Must preserve: heal endpoint indexing, heal mock storage signatures, + lifecycle metadata updates, scanner warm-tier mocks, fuzz target validation + invariants, and direct compile coverage for affected crates/targets. + - Verification: heal/scanner test compile coverage, fuzz target compile + coverage, test/fuzz bridge residual scan, migration and layer guards, + formatting, diff hygiene, Rust risk scan, and three-expert review. - [x] `G-012` Inventory placement and repair invariants. - Acceptance: [`placement-repair-invariants.md`](placement-repair-invariants.md) records @@ -3742,14 +3784,48 @@ Status values: `[ ]` not started, `[~]` in progress, `[x]` complete, `[!]` block | Expert | Status | Notes | |---|---|---| -| Quality/architecture | pass | API-121 removes capacity, server, and S3 API local bridge modules while keeping direct owner API calls explicit. | -| Migration preservation | pass | The extended guard rejects deleted runtime bridge files, module declarations, and local bridge consumers. | -| Testing/verification | pass | RustFS compile, runtime local bridge residual scan, migration guard, layer guard, formatting, diff hygiene, pre-commit, and path-only risk review passed. | +| Quality/architecture | pass | API-124 removes only test/fuzz bridge modules and keeps call sites on explicit ECStore owner APIs. | +| Migration preservation | pass | The migration guard now rejects the deleted test/fuzz bridge files, module declarations, and bridge consumers. | +| Testing/verification | pass | Heal/scanner test compile, fuzz target compile, residual scan, migration guard, layer guard, formatting, and diff hygiene passed. | ## Verification Notes Passed before push: +- Issue #660 API-124 current slice: + - `cargo check --tests -p rustfs-heal -p rustfs-scanner`: passed. + - `cargo check --manifest-path fuzz/Cargo.toml --bins`: passed; transient `fuzz/Cargo.lock` refresh was restored to avoid dependency churn. + - `cargo fmt --all`: passed. + - `cargo fmt --all --check`: passed. + - `git diff --check`: passed. + - `bash -n scripts/check_architecture_migration_rules.sh`: passed. + - `./scripts/check_architecture_migration_rules.sh`: passed. + - `./scripts/check_layer_dependencies.sh`: passed. + - Test/fuzz compatibility bridge residual scan: passed. + - Rust risk scan: reviewed pre-existing test-only unwrap/expect/panic/unsafe usage; no new production risk. + +- Issue #660 API-123 current slice: + - `cargo check -p rustfs --tests`: passed. + - `cargo fmt --all`: passed. + - `cargo fmt --all --check`: passed. + - `git diff --check`: passed. + - `bash -n scripts/check_architecture_migration_rules.sh`: passed. + - `./scripts/check_architecture_migration_rules.sh`: passed. + - `./scripts/check_layer_dependencies.sh`: passed. + - Startup compatibility bridge residual scan: passed. + - Rust risk scan: passed. + +- Issue #660 API-122 current slice: + - `cargo check -p rustfs --tests`: passed. + - `cargo fmt --all`: passed. + - `cargo fmt --all --check`: passed. + - `git diff --check`: passed. + - `bash -n scripts/check_architecture_migration_rules.sh`: passed. + - `./scripts/check_architecture_migration_rules.sh`: passed. + - `./scripts/check_layer_dependencies.sh`: passed. + - Root one-off compatibility bridge residual scan: passed. + - Rust risk scan: passed. + - Issue #660 API-121 current slice: - `cargo check -p rustfs --tests`: passed. - `cargo fmt --all`: passed. diff --git a/fuzz/fuzz_targets/bucket_validation.rs b/fuzz/fuzz_targets/bucket_validation.rs index 99198e3a9..46009b0a0 100644 --- a/fuzz/fuzz_targets/bucket_validation.rs +++ b/fuzz/fuzz_targets/bucket_validation.rs @@ -1,10 +1,7 @@ #![no_main] -#[path = "bucket_validation/storage_compat.rs"] -mod storage_compat; - use libfuzzer_sys::fuzz_target; -use self::storage_compat::{ +use rustfs_ecstore::api::bucket::utils::{ check_bucket_and_object_names, check_list_objs_args, check_valid_bucket_name_strict, is_meta_bucketname, }; diff --git a/fuzz/fuzz_targets/bucket_validation/storage_compat.rs b/fuzz/fuzz_targets/bucket_validation/storage_compat.rs deleted file mode 100644 index efa575fba..000000000 --- a/fuzz/fuzz_targets/bucket_validation/storage_compat.rs +++ /dev/null @@ -1,36 +0,0 @@ -// Copyright 2024 RustFS Team -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -use rustfs_ecstore::api::bucket as ecstore_bucket; -use rustfs_ecstore::api::error as ecstore_error; - -pub(crate) fn check_bucket_and_object_names(bucket: &str, object: &str) -> ecstore_error::Result<()> { - ecstore_bucket::utils::check_bucket_and_object_names(bucket, object) -} - -pub(crate) fn check_list_objs_args( - bucket: &str, - prefix: &str, - marker: &Option, -) -> ecstore_error::Result<()> { - ecstore_bucket::utils::check_list_objs_args(bucket, prefix, marker) -} - -pub(crate) fn check_valid_bucket_name_strict(bucket_name: &str) -> ecstore_error::Result<()> { - ecstore_bucket::utils::check_valid_bucket_name_strict(bucket_name) -} - -pub(crate) fn is_meta_bucketname(name: &str) -> bool { - ecstore_bucket::utils::is_meta_bucketname(name) -} diff --git a/fuzz/fuzz_targets/path_containment.rs b/fuzz/fuzz_targets/path_containment.rs index c1ef55fd1..2bba67086 100644 --- a/fuzz/fuzz_targets/path_containment.rs +++ b/fuzz/fuzz_targets/path_containment.rs @@ -1,10 +1,9 @@ #![no_main] -#[path = "path_containment/storage_compat.rs"] -mod storage_compat; - use libfuzzer_sys::fuzz_target; -use self::storage_compat::{check_object_name_for_length_and_slash, has_bad_path_component, is_valid_object_prefix}; +use rustfs_ecstore::api::bucket::utils::{ + check_object_name_for_length_and_slash, has_bad_path_component, is_valid_object_prefix, +}; use rustfs_utils::path::{clean, path_join}; use std::path::{Path, PathBuf}; diff --git a/fuzz/fuzz_targets/path_containment/storage_compat.rs b/fuzz/fuzz_targets/path_containment/storage_compat.rs deleted file mode 100644 index 7fdd4fa7a..000000000 --- a/fuzz/fuzz_targets/path_containment/storage_compat.rs +++ /dev/null @@ -1,31 +0,0 @@ -// Copyright 2024 RustFS Team -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -use rustfs_ecstore::api::bucket as ecstore_bucket; -use rustfs_ecstore::api::error as ecstore_error; - -pub(crate) fn check_object_name_for_length_and_slash( - bucket: &str, - object: &str, -) -> ecstore_error::Result<()> { - ecstore_bucket::utils::check_object_name_for_length_and_slash(bucket, object) -} - -pub(crate) fn has_bad_path_component(path: &str) -> bool { - ecstore_bucket::utils::has_bad_path_component(path) -} - -pub(crate) fn is_valid_object_prefix(object: &str) -> bool { - ecstore_bucket::utils::is_valid_object_prefix(object) -} diff --git a/rustfs/src/config/config_test.rs b/rustfs/src/config/config_test.rs index c2f9d8cb3..ca851e851 100644 --- a/rustfs/src/config/config_test.rs +++ b/rustfs/src/config/config_test.rs @@ -15,10 +15,10 @@ #[cfg(test)] #[allow(unsafe_op_in_unsafe_fn)] mod tests { - use super::super::super::config_storage_compat::DisksLayout; use crate::config::{CommandResult, Config, Opt, TlsCommands}; use rustfs_config::{DEFAULT_CONSOLE_ADDRESS, DEFAULT_CONSOLE_ENABLE, DEFAULT_OBS_ENDPOINT, RUSTFS_REGION}; use rustfs_credentials::{DEFAULT_ACCESS_KEY, DEFAULT_SECRET_KEY}; + use rustfs_ecstore::api::layout::DisksLayout; use serial_test::serial; use std::env; @@ -262,7 +262,7 @@ mod tests { #[test] #[serial] fn test_volumes_and_disk_layout_parsing() { - use super::super::super::config_storage_compat::DisksLayout; + use rustfs_ecstore::api::layout::DisksLayout; // Test case 1: Single volume path let args = vec!["rustfs", "/data/vol1"]; diff --git a/rustfs/src/config_storage_compat.rs b/rustfs/src/config_storage_compat.rs deleted file mode 100644 index ab5880427..000000000 --- a/rustfs/src/config_storage_compat.rs +++ /dev/null @@ -1,19 +0,0 @@ -// Copyright 2024 RustFS Team -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -#[cfg(test)] -use rustfs_ecstore::api::layout as ecstore_layout; - -#[cfg(test)] -pub(crate) type DisksLayout = ecstore_layout::DisksLayout; diff --git a/rustfs/src/error.rs b/rustfs/src/error.rs index 59fc99a84..c5a6eaf21 100644 --- a/rustfs/src/error.rs +++ b/rustfs/src/error.rs @@ -12,7 +12,7 @@ // See the License for the specific language governing permissions and // limitations under the License. -use super::error_storage_compat::{QuotaError, StorageError}; +use rustfs_ecstore::api::{bucket::quota::QuotaError, error::StorageError}; use rustfs_storage_api::HTTPRangeError; use s3s::{S3Error, S3ErrorCode}; diff --git a/rustfs/src/error_storage_compat.rs b/rustfs/src/error_storage_compat.rs deleted file mode 100644 index cc259cbf9..000000000 --- a/rustfs/src/error_storage_compat.rs +++ /dev/null @@ -1,19 +0,0 @@ -// Copyright 2024 RustFS Team -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -use rustfs_ecstore::api::bucket as ecstore_bucket; -use rustfs_ecstore::api::error as ecstore_error; - -pub(crate) type QuotaError = ecstore_bucket::quota::QuotaError; -pub(crate) type StorageError = ecstore_error::StorageError; diff --git a/rustfs/src/init.rs b/rustfs/src/init.rs index 0623b08a2..deb72e289 100644 --- a/rustfs/src/init.rs +++ b/rustfs/src/init.rs @@ -12,7 +12,6 @@ // See the License for the specific language governing permissions and // limitations under the License. -use super::startup_storage_compat::{get_global_region, get_notification_config}; use crate::server::ShutdownHandle; use crate::storage::{process_lambda_configurations, process_queue_configurations, process_topic_configurations}; use crate::{admin, config, version}; @@ -20,6 +19,7 @@ use rustfs_config::{ DEFAULT_BUFFER_MAX_SIZE, DEFAULT_BUFFER_MIN_SIZE, DEFAULT_BUFFER_PROFILE, DEFAULT_BUFFER_UNKNOWN_SIZE, DEFAULT_UPDATE_CHECK, ENV_RUSTFS_BUFFER_DEFAULT_SIZE, ENV_RUSTFS_BUFFER_MAX_SIZE, ENV_RUSTFS_BUFFER_MIN_SIZE, ENV_UPDATE_CHECK, RUSTFS_REGION, }; +use rustfs_ecstore::api::{bucket::metadata_sys as ecstore_metadata_sys, global as ecstore_global}; use rustfs_notify::notifier_global; use rustfs_targets::arn::{ARN, TargetIDError}; use rustfs_utils::get_env_usize; @@ -157,7 +157,7 @@ fn arn_to_target_id(arn_str: &str) -> Result) { - let global_region = get_global_region(); + let global_region = ecstore_global::get_global_region(); let region = global_region .as_ref() .filter(|r| !r.as_str().is_empty()) @@ -174,18 +174,20 @@ pub async fn add_bucket_notification_configuration(buckets: Vec) { RUSTFS_REGION }); for bucket in buckets.iter() { - let has_notification_config = get_notification_config(bucket).await.unwrap_or_else(|err| { - warn!( - target: "rustfs::init", - event = "notification_config_load_failed", - component = LOG_COMPONENT_INIT, - subsystem = LOG_SUBSYSTEM_NOTIFICATION, - bucket = %bucket, - error = ?err, - "Failed to load bucket notification configuration" - ); - None - }); + let has_notification_config = ecstore_metadata_sys::get_notification_config(bucket) + .await + .unwrap_or_else(|err| { + warn!( + target: "rustfs::init", + event = "notification_config_load_failed", + component = LOG_COMPONENT_INIT, + subsystem = LOG_SUBSYSTEM_NOTIFICATION, + bucket = %bucket, + error = ?err, + "Failed to load bucket notification configuration" + ); + None + }); match has_notification_config { Some(cfg) => { diff --git a/rustfs/src/lib.rs b/rustfs/src/lib.rs index 0909a5a66..100f7ac90 100644 --- a/rustfs/src/lib.rs +++ b/rustfs/src/lib.rs @@ -57,11 +57,9 @@ pub mod auth; pub mod auth_keystone; pub mod capacity; pub mod config; -pub(crate) mod config_storage_compat; pub mod delete_tail_activity; pub mod embedded; pub mod error; -pub(crate) mod error_storage_compat; pub mod init; pub mod license; pub mod memory_observability; @@ -69,7 +67,6 @@ pub mod profiling; #[cfg(any(feature = "ftps", feature = "webdav", feature = "sftp"))] pub mod protocols; pub mod runtime_capabilities; -pub(crate) mod runtime_capabilities_storage_compat; pub mod server; pub(crate) mod startup_audit; pub(crate) mod startup_auth; @@ -93,16 +90,13 @@ pub(crate) mod startup_server; pub(crate) mod startup_services; pub(crate) mod startup_shutdown; pub(crate) mod startup_storage; -pub(crate) mod startup_storage_compat; pub(crate) mod startup_tls_material; pub mod storage; pub(crate) mod table_catalog; -pub(crate) mod table_catalog_storage_compat; pub mod tls; pub mod update; pub mod version; pub mod workload_admission; -pub(crate) mod workload_admission_storage_compat; // Re-export from rustfs_utils so that config sub-modules can use // `crate::apply_external_env_compat` without breaking. diff --git a/rustfs/src/runtime_capabilities.rs b/rustfs/src/runtime_capabilities.rs index d4b9b2440..a91fd61ec 100644 --- a/rustfs/src/runtime_capabilities.rs +++ b/rustfs/src/runtime_capabilities.rs @@ -12,14 +12,13 @@ // See the License for the specific language governing permissions and // limitations under the License. +use rustfs_ecstore::api::{cluster as ecstore_cluster, layout::EndpointServerPools}; use rustfs_storage_api::{ CapabilitySnapshotError, CapabilityStatus, DiskCapabilities, MemorySamplingState, ObservabilitySnapshot, ObservabilitySnapshotProvider, PlatformSupport, TopologyCapabilities, TopologySnapshot, TopologySnapshotProvider, UserspaceProfilingCapability, }; -use super::runtime_capabilities_storage_compat::{EndpointServerPools, topology_snapshot_from_endpoint_pools_with_capabilities}; - const NOT_WIRED_INTO_RUNTIME: &str = "not wired into runtime"; const STORAGE_MEDIA_NOT_REPORTED: &str = "storage media not reported by endpoints"; const FAILURE_DOMAIN_NOT_REPORTED: &str = "failure domain labels not reported by endpoints"; @@ -80,7 +79,7 @@ impl TopologySnapshotProvider for EndpointTopologySnapshotProvider { } pub fn topology_snapshot_from_endpoint_pools(endpoint_pools: &EndpointServerPools) -> TopologySnapshot { - topology_snapshot_from_endpoint_pools_with_capabilities( + ecstore_cluster::topology_snapshot_from_endpoint_pools_with_capabilities( endpoint_pools, TopologyCapabilities { profiling: cpu_profiling_status(), @@ -131,8 +130,11 @@ fn cgroup_memory_status() -> CapabilityStatus { #[cfg(test)] mod tests { - use super::super::runtime_capabilities_storage_compat::{Endpoint, Endpoints, PoolEndpoints}; use super::*; + use rustfs_ecstore::api::{ + disk::endpoint::Endpoint, + layout::{Endpoints, PoolEndpoints}, + }; use rustfs_storage_api::{CapabilityState, ObservabilitySnapshotProvider, TopologySnapshotProvider}; #[tokio::test] diff --git a/rustfs/src/runtime_capabilities_storage_compat.rs b/rustfs/src/runtime_capabilities_storage_compat.rs deleted file mode 100644 index 8e68856d5..000000000 --- a/rustfs/src/runtime_capabilities_storage_compat.rs +++ /dev/null @@ -1,34 +0,0 @@ -// Copyright 2024 RustFS Team -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -use rustfs_ecstore::api::cluster as ecstore_cluster; -#[cfg(test)] -use rustfs_ecstore::api::disk as ecstore_disk; -use rustfs_ecstore::api::layout as ecstore_layout; - -#[cfg(test)] -pub(crate) type Endpoint = ecstore_disk::endpoint::Endpoint; -pub(crate) type EndpointServerPools = ecstore_layout::EndpointServerPools; -#[cfg(test)] -pub(crate) type Endpoints = ecstore_layout::Endpoints; -#[cfg(test)] -pub(crate) type PoolEndpoints = ecstore_layout::PoolEndpoints; - -pub(crate) fn topology_snapshot_from_endpoint_pools_with_capabilities( - endpoint_pools: &EndpointServerPools, - capabilities: rustfs_storage_api::TopologyCapabilities, - disk_capabilities: rustfs_storage_api::DiskCapabilities, -) -> rustfs_storage_api::TopologySnapshot { - ecstore_cluster::topology_snapshot_from_endpoint_pools_with_capabilities(endpoint_pools, capabilities, disk_capabilities) -} diff --git a/rustfs/src/startup_background.rs b/rustfs/src/startup_background.rs index 0f75471fe..b637b8cf4 100644 --- a/rustfs/src/startup_background.rs +++ b/rustfs/src/startup_background.rs @@ -12,7 +12,7 @@ // See the License for the specific language governing permissions and // limitations under the License. -use super::startup_storage_compat::ECStore; +use rustfs_ecstore::api::storage::ECStore; use rustfs_heal::{create_ahm_services_cancel_token, heal::storage::ECStoreHealStorage, init_heal_manager}; use rustfs_utils::get_env_bool_with_aliases; use std::{io::Result, sync::Arc}; diff --git a/rustfs/src/startup_bucket_metadata.rs b/rustfs/src/startup_bucket_metadata.rs index ad49248e9..2da3b085f 100644 --- a/rustfs/src/startup_bucket_metadata.rs +++ b/rustfs/src/startup_bucket_metadata.rs @@ -12,8 +12,9 @@ // See the License for the specific language governing permissions and // limitations under the License. -use super::startup_storage_compat::{ - ECStore, get_global_replication_pool, init_bucket_metadata_sys, try_migrate_bucket_metadata, try_migrate_iam_config, +use rustfs_ecstore::api::{ + bucket::{metadata_sys as ecstore_metadata_sys, migration as ecstore_migration, replication as ecstore_replication}, + storage::ECStore, }; use rustfs_storage_api::{BucketOperations, BucketOptions}; use std::{ @@ -33,9 +34,9 @@ pub(crate) async fn init_embedded_bucket_metadata_runtime(store: Arc) - let buckets: Vec = buckets_list.into_iter().map(|v| v.name).collect(); - try_migrate_bucket_metadata(store.clone()).await; - init_bucket_metadata_sys(store.clone(), buckets.clone()).await; - try_migrate_iam_config(store).await; + ecstore_migration::try_migrate_bucket_metadata(store.clone()).await; + ecstore_metadata_sys::init_bucket_metadata_sys(store.clone(), buckets.clone()).await; + ecstore_migration::try_migrate_iam_config(store).await; Ok(buckets) } @@ -51,14 +52,14 @@ pub(crate) async fn init_bucket_metadata_runtime(store: Arc, ctx: Cance let buckets: Vec = buckets_list.into_iter().map(|v| v.name).collect(); - try_migrate_bucket_metadata(store.clone()).await; + ecstore_migration::try_migrate_bucket_metadata(store.clone()).await; - if let Some(pool) = get_global_replication_pool() { + if let Some(pool) = ecstore_replication::get_global_replication_pool() { pool.init_resync(ctx, buckets.clone()).await?; } - try_migrate_iam_config(store.clone()).await; - init_bucket_metadata_sys(store, buckets.clone()).await; + ecstore_migration::try_migrate_iam_config(store.clone()).await; + ecstore_metadata_sys::init_bucket_metadata_sys(store, buckets.clone()).await; Ok(buckets) } diff --git a/rustfs/src/startup_fs_guard.rs b/rustfs/src/startup_fs_guard.rs index f9be8258a..c9012c175 100644 --- a/rustfs/src/startup_fs_guard.rs +++ b/rustfs/src/startup_fs_guard.rs @@ -12,11 +12,11 @@ // See the License for the specific language governing permissions and // limitations under the License. -use super::startup_storage_compat::EndpointServerPools; use rustfs_config::{ DEFAULT_RUSTFS_UNSUPPORTED_FS_POLICY, ENV_RUSTFS_UNSUPPORTED_FS_POLICY, RUSTFS_UNSUPPORTED_FS_POLICY_FAIL, RUSTFS_UNSUPPORTED_FS_POLICY_WARN, }; +use rustfs_ecstore::api::layout::EndpointServerPools; use std::collections::BTreeSet; use std::io::{Error, Result}; use tracing::warn; diff --git a/rustfs/src/startup_iam.rs b/rustfs/src/startup_iam.rs index 3c54f10e3..51d894286 100644 --- a/rustfs/src/startup_iam.rs +++ b/rustfs/src/startup_iam.rs @@ -12,10 +12,10 @@ // See the License for the specific language governing permissions and // limitations under the License. -use super::startup_storage_compat::ECStore; use crate::app::context::AppContext; use crate::server::{ServiceStateManager, publish_ready_when_runtime_ready}; use rustfs_common::{GlobalReadiness, SystemStage}; +use rustfs_ecstore::api::storage::ECStore; use rustfs_iam::init_iam_sys; use rustfs_kms::KmsServiceManager; use std::future::Future; diff --git a/rustfs/src/startup_lifecycle.rs b/rustfs/src/startup_lifecycle.rs index 93ecef737..95924e1f1 100644 --- a/rustfs/src/startup_lifecycle.rs +++ b/rustfs/src/startup_lifecycle.rs @@ -17,9 +17,9 @@ use crate::{ startup_iam::{IamBootstrapDisposition, publish_ready_for_iam_bootstrap}, startup_services::StartupServiceRuntime, startup_shutdown::run_startup_shutdown_sequence, - startup_storage_compat::ECStore, }; use rustfs_common::GlobalReadiness; +use rustfs_ecstore::api::storage::ECStore; use rustfs_scanner::init_data_scanner; use std::{ io::Result, diff --git a/rustfs/src/startup_notification.rs b/rustfs/src/startup_notification.rs index 6637d2786..58655d45f 100644 --- a/rustfs/src/startup_notification.rs +++ b/rustfs/src/startup_notification.rs @@ -12,8 +12,8 @@ // See the License for the specific language governing permissions and // limitations under the License. -use super::startup_storage_compat::{EcstoreResult, EndpointServerPools, new_global_notification_sys}; use crate::init::add_bucket_notification_configuration; +use rustfs_ecstore::api::{error as ecstore_error, layout::EndpointServerPools, notification as ecstore_notification}; use std::{ future::Future, io::{Error, Result}, @@ -50,14 +50,14 @@ pub(crate) async fn init_notification_runtime(endpoint_pools: EndpointServerPool }) } -pub(crate) async fn init_notification_system(endpoint_pools: EndpointServerPools) -> EcstoreResult<()> { - init_notification_system_with(|| new_global_notification_sys(endpoint_pools)).await +pub(crate) async fn init_notification_system(endpoint_pools: EndpointServerPools) -> ecstore_error::Result<()> { + init_notification_system_with(|| ecstore_notification::new_global_notification_sys(endpoint_pools)).await } -async fn init_notification_system_with(init_notification: InitFn) -> EcstoreResult<()> +async fn init_notification_system_with(init_notification: InitFn) -> ecstore_error::Result<()> where InitFn: FnOnce() -> InitFuture, - InitFuture: Future>, + InitFuture: Future>, { init_notification().await } @@ -76,11 +76,11 @@ fn log_embedded_optional_service_skipped(service: &str, err: impl std::fmt::Disp #[cfg(test)] mod tests { use super::init_notification_system_with; + use rustfs_ecstore::api::error::Error as EcstoreError; #[tokio::test] async fn notification_system_returns_source_error() { - let result = - init_notification_system_with(|| async { Err(super::super::startup_storage_compat::EcstoreError::FaultyDisk) }).await; + let result = init_notification_system_with(|| async { Err(EcstoreError::FaultyDisk) }).await; assert!(result.is_err()); } diff --git a/rustfs/src/startup_server.rs b/rustfs/src/startup_server.rs index cdb7c6263..32d9fcd33 100644 --- a/rustfs/src/startup_server.rs +++ b/rustfs/src/startup_server.rs @@ -12,7 +12,6 @@ // See the License for the specific language governing permissions and // limitations under the License. -use super::startup_storage_compat::{set_global_region, set_global_rustfs_port}; use crate::{ capacity::capacity_integration::init_capacity_management, config::Config, @@ -20,6 +19,7 @@ use crate::{ }; use rustfs_common::{GlobalReadiness, set_global_addr}; use rustfs_credentials::init_global_action_credentials; +use rustfs_ecstore::api::global::{set_global_region, set_global_rustfs_port}; use rustfs_utils::net::parse_and_resolve_address; use std::{ io::{Error, Result}, diff --git a/rustfs/src/startup_services.rs b/rustfs/src/startup_services.rs index fdeb0b160..64fb33525 100644 --- a/rustfs/src/startup_services.rs +++ b/rustfs/src/startup_services.rs @@ -12,7 +12,6 @@ // See the License for the specific language governing permissions and // limitations under the License. -use super::startup_storage_compat::{ECStore, EndpointServerPools}; use crate::{ config::Config, init::{init_buffer_profile_system, init_kms_system}, @@ -29,6 +28,7 @@ use crate::{ startup_optional_runtime_sidecars::{OptionalRuntimeServices, init_optional_runtime_services}, }; use rustfs_common::GlobalReadiness; +use rustfs_ecstore::api::{layout::EndpointServerPools, storage::ECStore}; use std::{io::Result, sync::Arc}; use tokio_util::sync::CancellationToken; diff --git a/rustfs/src/startup_shutdown.rs b/rustfs/src/startup_shutdown.rs index 4412600b3..b6a299903 100644 --- a/rustfs/src/startup_shutdown.rs +++ b/rustfs/src/startup_shutdown.rs @@ -17,8 +17,8 @@ use crate::{ startup_optional_runtime_sidecars::{ OptionalRuntimeServices, prepare_optional_runtime_shutdowns, shutdown_optional_runtime_services, }, - startup_storage_compat::shutdown_background_services, }; +use rustfs_ecstore::api::global::shutdown_background_services; use rustfs_heal::shutdown_ahm_services; use rustfs_utils::get_env_bool_with_aliases; use std::path::Path; diff --git a/rustfs/src/startup_storage.rs b/rustfs/src/startup_storage.rs index 48c66111e..137513666 100644 --- a/rustfs/src/startup_storage.rs +++ b/rustfs/src/startup_storage.rs @@ -12,12 +12,13 @@ // See the License for the specific language governing permissions and // limitations under the License. -use super::startup_storage_compat::{ - ECStore, EndpointServerPools, init_background_replication, init_ecstore_config, init_global_config_sys, init_local_disks, - init_lock_clients, prewarm_local_disk_id_map, set_global_endpoints, try_migrate_server_config, update_erasure_type, -}; use crate::startup_fs_guard::enforce_unsupported_fs_policy; use rustfs_common::{GlobalReadiness, SystemStage}; +use rustfs_ecstore::api::storage::ECStore; +use rustfs_ecstore::api::{ + bucket::replication as ecstore_replication, config as ecstore_config, global as ecstore_global, layout::EndpointServerPools, + storage as ecstore_storage, +}; use std::{ io::{Error, Result}, net::SocketAddr, @@ -70,8 +71,8 @@ pub(crate) async fn init_startup_storage_foundation(server_address: &str, volume .map_err(Error::other)?; enforce_unsupported_fs_policy(&endpoint_pools)?; - set_global_endpoints(endpoint_pools.as_ref().clone()); - update_erasure_type(setup_type).await; + ecstore_global::set_global_endpoints(endpoint_pools.as_ref().clone()); + ecstore_global::update_erasure_type(setup_type).await; debug!( target: "rustfs::main::run", @@ -82,7 +83,7 @@ pub(crate) async fn init_startup_storage_foundation(server_address: &str, volume state = "starting", "starting local disk initialization" ); - init_local_disks(endpoint_pools.clone()) + ecstore_storage::init_local_disks(endpoint_pools.clone()) .await .inspect_err(|err| { error!( @@ -97,8 +98,8 @@ pub(crate) async fn init_startup_storage_foundation(server_address: &str, volume ); }) .map_err(Error::other)?; - prewarm_local_disk_id_map().await; - init_lock_clients(endpoint_pools.clone()); + ecstore_storage::prewarm_local_disk_id_map().await; + ecstore_storage::init_lock_clients(endpoint_pools.clone()); log_storage_pool_layout(&endpoint_pools); @@ -114,13 +115,13 @@ pub(crate) async fn init_embedded_startup_storage_foundation( .map_err(|err| Error::other(format!("endpoints: {err}")))?; enforce_unsupported_fs_policy(&endpoint_pools).map_err(|err| Error::other(format!("unsupported fs guard: {err}")))?; - set_global_endpoints(endpoint_pools.as_ref().clone()); - update_erasure_type(setup_type).await; + ecstore_global::set_global_endpoints(endpoint_pools.as_ref().clone()); + ecstore_global::update_erasure_type(setup_type).await; - init_local_disks(endpoint_pools.clone()) + ecstore_storage::init_local_disks(endpoint_pools.clone()) .await .map_err(|err| Error::other(format!("local disks: {err}")))?; - init_lock_clients(endpoint_pools.clone()); + ecstore_storage::init_lock_clients(endpoint_pools.clone()); Ok(endpoint_pools) } @@ -158,7 +159,7 @@ pub(crate) async fn init_startup_storage_runtime( init_startup_storage_global_config(store.clone()).await?; readiness.mark_stage(SystemStage::StorageReady); - init_background_replication(store.clone()).await; + ecstore_replication::init_background_replication(store.clone()).await; Ok(StartupStorageRuntime { store, @@ -189,17 +190,17 @@ pub(crate) async fn init_embedded_startup_storage_runtime( init_embedded_startup_storage_global_config(store.clone()).await?; readiness.mark_stage(SystemStage::StorageReady); - init_background_replication(store.clone()).await; + ecstore_replication::init_background_replication(store.clone()).await; Ok(StartupStorageRuntime { store, shutdown_token }) } async fn init_startup_storage_global_config(store: Arc) -> Result<()> { - init_ecstore_config(); - try_migrate_server_config(store.clone()).await; + ecstore_config::init(); + ecstore_config::try_migrate_server_config(store.clone()).await; let mut retry_count = 0; - while let Err(e) = init_global_config_sys(store.clone()).await { + while let Err(e) = ecstore_config::init_global_config_sys(store.clone()).await { let next_retry_count = retry_count + 1; error!( target: "rustfs::main::run", @@ -224,11 +225,11 @@ async fn init_startup_storage_global_config(store: Arc) -> Result<()> { } async fn init_embedded_startup_storage_global_config(store: Arc) -> Result<()> { - init_ecstore_config(); - try_migrate_server_config(store.clone()).await; + ecstore_config::init(); + ecstore_config::try_migrate_server_config(store.clone()).await; let mut retry = 0; - while let Err(err) = init_global_config_sys(store.clone()).await { + while let Err(err) = ecstore_config::init_global_config_sys(store.clone()).await { retry += 1; if retry > GLOBAL_CONFIG_INIT_MAX_RETRIES { return Err(Error::other(format!( diff --git a/rustfs/src/startup_storage_compat.rs b/rustfs/src/startup_storage_compat.rs deleted file mode 100644 index 917006e8f..000000000 --- a/rustfs/src/startup_storage_compat.rs +++ /dev/null @@ -1,105 +0,0 @@ -// Copyright 2024 RustFS Team -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -use std::sync::Arc; - -use rustfs_ecstore::api::bucket as ecstore_bucket; -use rustfs_ecstore::api::config as ecstore_config; -use rustfs_ecstore::api::error as ecstore_error; -use rustfs_ecstore::api::global as ecstore_global; -use rustfs_ecstore::api::layout as ecstore_layout; -use rustfs_ecstore::api::notification as ecstore_notification; -use rustfs_ecstore::api::storage as ecstore_storage; - -pub(crate) type ECStore = ecstore_storage::ECStore; -#[cfg(test)] -pub(crate) type EcstoreError = ecstore_error::Error; -pub(crate) type EcstoreResult = ecstore_error::Result; -pub(crate) type EndpointServerPools = ecstore_layout::EndpointServerPools; - -pub(crate) async fn get_notification_config(bucket: &str) -> ecstore_error::Result> { - ecstore_bucket::metadata_sys::get_notification_config(bucket).await -} - -pub(crate) async fn init_bucket_metadata_sys(api: Arc, buckets: Vec) { - ecstore_bucket::metadata_sys::init_bucket_metadata_sys(api, buckets).await; -} - -pub(crate) async fn try_migrate_bucket_metadata(store: Arc) { - ecstore_bucket::migration::try_migrate_bucket_metadata(store).await; -} - -pub(crate) async fn try_migrate_iam_config(store: Arc) { - ecstore_bucket::migration::try_migrate_iam_config(store).await; -} - -pub(crate) fn get_global_replication_pool() -> Option> { - ecstore_bucket::replication::get_global_replication_pool() -} - -pub(crate) async fn init_background_replication(storage: Arc) { - ecstore_bucket::replication::init_background_replication(storage).await; -} - -pub(crate) fn init_ecstore_config() { - ecstore_config::init(); -} - -pub(crate) async fn init_global_config_sys(api: Arc) -> EcstoreResult<()> { - ecstore_config::init_global_config_sys(api).await -} - -pub(crate) async fn try_migrate_server_config(api: Arc) { - ecstore_config::try_migrate_server_config(api).await; -} - -pub(crate) fn get_global_region() -> Option { - ecstore_global::get_global_region() -} - -pub(crate) fn set_global_endpoints(eps: Vec) { - ecstore_global::set_global_endpoints(eps); -} - -pub(crate) fn set_global_region(region: s3s::region::Region) { - ecstore_global::set_global_region(region); -} - -pub(crate) fn set_global_rustfs_port(value: u16) { - ecstore_global::set_global_rustfs_port(value); -} - -pub(crate) fn shutdown_background_services() { - ecstore_global::shutdown_background_services(); -} - -pub(crate) async fn update_erasure_type(setup_type: ecstore_layout::SetupType) { - ecstore_global::update_erasure_type(setup_type).await -} - -pub(crate) async fn new_global_notification_sys(eps: EndpointServerPools) -> EcstoreResult<()> { - ecstore_notification::new_global_notification_sys(eps).await -} - -pub(crate) async fn init_local_disks(endpoint_pools: EndpointServerPools) -> EcstoreResult<()> { - ecstore_storage::init_local_disks(endpoint_pools).await -} - -pub(crate) fn init_lock_clients(endpoint_pools: EndpointServerPools) { - ecstore_storage::init_lock_clients(endpoint_pools); -} - -pub(crate) async fn prewarm_local_disk_id_map() { - ecstore_storage::prewarm_local_disk_id_map().await; -} diff --git a/rustfs/src/table_catalog.rs b/rustfs/src/table_catalog.rs index ba21a1767..5fd4afbaf 100644 --- a/rustfs/src/table_catalog.rs +++ b/rustfs/src/table_catalog.rs @@ -27,11 +27,6 @@ use std::{ time::{Duration as StdDuration, Instant}, }; -use super::table_catalog_storage_compat::{ - BUCKET_TABLE_CATALOG_META_PREFIX, BUCKET_TABLE_CATALOG_TABLE_BUCKETS_PREFIX, BUCKET_TABLE_CONFIG, - BUCKET_TABLE_RESERVED_PREFIX, EcstoreError, RUSTFS_META_BUCKET, StorageError, get_bucket_metadata, get_lock_acquire_timeout, - table_catalog_path_hash, -}; use bytes::Bytes; use datafusion::{ arrow::datatypes::SchemaRef, @@ -39,6 +34,10 @@ use datafusion::{ }; use http::HeaderMap; use metrics::{counter, histogram}; +use rustfs_ecstore::api::{ + bucket::{metadata as ecstore_metadata, metadata_sys as ecstore_metadata_sys}, + disk as ecstore_disk, error as ecstore_error, set_disk as ecstore_set_disk, +}; use rustfs_filemeta::FileInfo; use rustfs_storage_api::{ HTTPPreconditions, HTTPRangeSpec, ListObjectVersionsInfo as StorageListObjectVersionsInfo, @@ -56,7 +55,8 @@ use crate::storage::{ StorageObjectOptions as ObjectOptions, StorageObjectToDelete as ObjectToDelete, StoragePutObjReader as PutObjReader, }; -pub(crate) const TABLE_BUCKET_MARKER_CONFIG: &str = BUCKET_TABLE_CONFIG; +pub(crate) const TABLE_BUCKET_MARKER_CONFIG: &str = ecstore_metadata::BUCKET_TABLE_CONFIG; +const RUSTFS_META_BUCKET: &str = ecstore_disk::RUSTFS_META_BUCKET; pub(crate) const RESERVED_CATALOG_OBJECT_MESSAGE: &str = "Object key is reserved for the table catalog"; pub(crate) const TABLE_BUCKET_CATALOG_TYPE: &str = "iceberg-rest"; pub(crate) const TABLE_BUCKET_CONFIG_VERSION: u16 = 1; @@ -69,7 +69,7 @@ pub(crate) const TABLE_MAINTENANCE_CONFIG_VERSION: u16 = 1; pub(crate) const TABLE_EXTERNAL_CATALOG_BRIDGE_VERSION: u16 = 1; pub(crate) const TABLE_CATALOG_BACKING_MANIFEST_VERSION: u16 = 1; pub(crate) const TABLE_METADATA_FILE_NAME_MAX_LEN: usize = 128; -pub const TABLE_RESERVED_PREFIX: &str = BUCKET_TABLE_RESERVED_PREFIX; +pub const TABLE_RESERVED_PREFIX: &str = ecstore_metadata::BUCKET_TABLE_RESERVED_PREFIX; const WAREHOUSE_ROOT: &str = "warehouses"; const NAMESPACE_ROOT: &str = "namespaces"; const TABLE_ROOT: &str = "tables"; @@ -85,8 +85,8 @@ const TABLE_BUCKET_ENTRY_FILE: &str = "table-bucket.json"; const NAMESPACE_ENTRY_FILE: &str = "namespace-entry.json"; const TABLE_ENTRY_FILE: &str = "table-entry.json"; const VIEW_ENTRY_FILE: &str = "view-entry.json"; -const INTERNAL_CATALOG_ROOT: &str = BUCKET_TABLE_CATALOG_META_PREFIX; -const TABLE_BUCKET_ROOT: &str = BUCKET_TABLE_CATALOG_TABLE_BUCKETS_PREFIX; +const INTERNAL_CATALOG_ROOT: &str = ecstore_metadata::BUCKET_TABLE_CATALOG_META_PREFIX; +const TABLE_BUCKET_ROOT: &str = ecstore_metadata::BUCKET_TABLE_CATALOG_TABLE_BUCKETS_PREFIX; const COMMIT_LOG_ROOT: &str = "commits"; const COMMIT_IDEMPOTENCY_ROOT: &str = "commit-idempotency"; const EXTERNAL_CATALOG_ROOT: &str = "external-catalog"; @@ -115,8 +115,10 @@ const ICEBERG_REF_MAX_REF_AGE_MS_FIELD: &str = "max-ref-age-ms"; type CatalogListObjectsV2Info = StorageListObjectsV2Info; type CatalogListObjectVersionsInfo = StorageListObjectVersionsInfo; +type EcstoreError = ecstore_error::Error; type CatalogObjectInfoOrErr = StorageObjectInfoOrErr; type CatalogWalkOptions = StorageWalkOptions bool>; +type StorageError = ecstore_error::StorageError; pub(crate) trait TableCatalogStorage: StorageObjectIO< @@ -1461,7 +1463,7 @@ impl TableCatalogObjectPaths { "{}{}/{MAINTENANCE_ROOT}/{}/{MAINTENANCE_CONFIG_FILE}", self.table_entries_prefix(table_bucket, namespace), table.as_str(), - table_catalog_path_hash(table_id) + ecstore_metadata::table_catalog_path_hash(table_id) ) } @@ -1477,8 +1479,8 @@ impl TableCatalogObjectPaths { "{}{}/{MAINTENANCE_ROOT}/{}/{MAINTENANCE_JOB_ROOT}/{}.json", self.table_entries_prefix(table_bucket, namespace), table.as_str(), - table_catalog_path_hash(table_id), - table_catalog_path_hash(job_id) + ecstore_metadata::table_catalog_path_hash(table_id), + ecstore_metadata::table_catalog_path_hash(job_id) ) } @@ -1493,7 +1495,7 @@ impl TableCatalogObjectPaths { "{}{}/{MAINTENANCE_ROOT}/{}/{MAINTENANCE_LATEST_JOB_FILE}", self.table_entries_prefix(table_bucket, namespace), table.as_str(), - table_catalog_path_hash(table_id) + ecstore_metadata::table_catalog_path_hash(table_id) ) } @@ -1508,7 +1510,7 @@ impl TableCatalogObjectPaths { "{}{}/{MAINTENANCE_ROOT}/{}/{MAINTENANCE_CURRENT_JOB_FILE}", self.table_entries_prefix(table_bucket, namespace), table.as_str(), - table_catalog_path_hash(table_id) + ecstore_metadata::table_catalog_path_hash(table_id) ) } @@ -1517,8 +1519,8 @@ impl TableCatalogObjectPaths { "{}{}/{}/{}.json", self.table_bucket_root_prefix(table_bucket), COMMIT_LOG_ROOT, - table_catalog_path_hash(table_id), - table_catalog_path_hash(commit_id) + ecstore_metadata::table_catalog_path_hash(table_id), + ecstore_metadata::table_catalog_path_hash(commit_id) ) } @@ -1527,7 +1529,7 @@ impl TableCatalogObjectPaths { "{}{}/{}/", self.table_bucket_root_prefix(table_bucket), COMMIT_LOG_ROOT, - table_catalog_path_hash(table_id) + ecstore_metadata::table_catalog_path_hash(table_id) ) } @@ -1536,8 +1538,8 @@ impl TableCatalogObjectPaths { "{}{}/{}/{}.json", self.table_bucket_root_prefix(table_bucket), COMMIT_IDEMPOTENCY_ROOT, - table_catalog_path_hash(table_id), - table_catalog_path_hash(idempotency_key) + ecstore_metadata::table_catalog_path_hash(table_id), + ecstore_metadata::table_catalog_path_hash(idempotency_key) ) } @@ -1546,12 +1548,17 @@ impl TableCatalogObjectPaths { "{}{}/{}/", self.table_bucket_root_prefix(table_bucket), COMMIT_IDEMPOTENCY_ROOT, - table_catalog_path_hash(table_id) + ecstore_metadata::table_catalog_path_hash(table_id) ) } fn table_bucket_root_prefix(&self, table_bucket: &str) -> String { - format!("{}/{}/{}/", self.catalog_root, TABLE_BUCKET_ROOT, table_catalog_path_hash(table_bucket)) + format!( + "{}/{}/{}/", + self.catalog_root, + TABLE_BUCKET_ROOT, + ecstore_metadata::table_catalog_path_hash(table_bucket) + ) } } @@ -4031,7 +4038,7 @@ where .await .map_err(|err| storage_error_to_catalog("create catalog table lock", err))?; let guard = lock - .get_write_lock(get_lock_acquire_timeout()) + .get_write_lock(ecstore_set_disk::get_lock_acquire_timeout()) .await .map_err(|err| TableCatalogStoreError::Internal(format!("failed to acquire catalog table lock: {err}")))?; Ok(Box::new(guard)) @@ -7002,7 +7009,7 @@ pub fn validate_object_mutation(table_bucket_enabled: bool, object_key: &str) -> } pub(crate) async fn validate_bucket_object_mutation(bucket: &str, object_key: &str) -> Result<(), TableObjectMutationError> { - let table_bucket_enabled = get_bucket_metadata(bucket) + let table_bucket_enabled = ecstore_metadata_sys::get(bucket) .await .is_ok_and(|metadata| metadata.table_bucket_enabled()); @@ -7410,7 +7417,7 @@ mod tests { let bucket = "analytics"; let namespace = Namespace::parse("analytics.daily_events").unwrap(); let table = IdentifierSegment::parse("events").unwrap(); - let bucket_root = format!("s3tables/catalog/table-buckets/{}/", table_catalog_path_hash(bucket)); + let bucket_root = format!("s3tables/catalog/table-buckets/{}/", ecstore_metadata::table_catalog_path_hash(bucket)); assert_eq!(paths.table_bucket_entry_path(bucket), format!("{bucket_root}table-bucket.json")); assert_eq!( diff --git a/rustfs/src/table_catalog_storage_compat.rs b/rustfs/src/table_catalog_storage_compat.rs deleted file mode 100644 index e6919b307..000000000 --- a/rustfs/src/table_catalog_storage_compat.rs +++ /dev/null @@ -1,41 +0,0 @@ -// Copyright 2024 RustFS Team -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -use std::{sync::Arc, time::Duration}; - -use rustfs_ecstore::api::bucket as ecstore_bucket; -use rustfs_ecstore::api::disk as ecstore_disk; -use rustfs_ecstore::api::error as ecstore_error; -use rustfs_ecstore::api::set_disk as ecstore_set_disk; - -pub(crate) const BUCKET_TABLE_CATALOG_META_PREFIX: &str = ecstore_bucket::metadata::BUCKET_TABLE_CATALOG_META_PREFIX; -pub(crate) const BUCKET_TABLE_CATALOG_TABLE_BUCKETS_PREFIX: &str = - ecstore_bucket::metadata::BUCKET_TABLE_CATALOG_TABLE_BUCKETS_PREFIX; -pub(crate) const BUCKET_TABLE_CONFIG: &str = ecstore_bucket::metadata::BUCKET_TABLE_CONFIG; -pub(crate) const BUCKET_TABLE_RESERVED_PREFIX: &str = ecstore_bucket::metadata::BUCKET_TABLE_RESERVED_PREFIX; -pub(crate) const RUSTFS_META_BUCKET: &str = ecstore_disk::RUSTFS_META_BUCKET; -pub(crate) type EcstoreError = ecstore_error::Error; -pub(crate) type StorageError = ecstore_error::StorageError; - -pub(crate) fn table_catalog_path_hash(value: &str) -> String { - ecstore_bucket::metadata::table_catalog_path_hash(value) -} - -pub(crate) async fn get_bucket_metadata(bucket: &str) -> ecstore_error::Result> { - ecstore_bucket::metadata_sys::get(bucket).await -} - -pub(crate) fn get_lock_acquire_timeout() -> Duration { - ecstore_set_disk::get_lock_acquire_timeout() -} diff --git a/rustfs/src/workload_admission.rs b/rustfs/src/workload_admission.rs index 76fde4657..0c6be0d43 100644 --- a/rustfs/src/workload_admission.rs +++ b/rustfs/src/workload_admission.rs @@ -16,10 +16,8 @@ use rustfs_concurrency::{ AdmissionState, WorkloadAdmissionRegistrySnapshot, WorkloadAdmissionSnapshot, WorkloadAdmissionSnapshotProvider, WorkloadClass, }; +use rustfs_ecstore::api::bucket::{metadata_sys, replication}; -use super::workload_admission_storage_compat::{ - get_global_bucket_metadata_sys, get_global_replication_pool, replication_queue_current_count, -}; use crate::storage::concurrency::get_concurrency_manager; const BUCKET_METADATA_RUNTIME_NOT_INITIALIZED: &str = "bucket metadata runtime not initialized"; @@ -77,7 +75,7 @@ pub fn foreground_read_workload_admission_snapshot() -> WorkloadAdmissionSnapsho } pub fn metadata_workload_admission_snapshot() -> WorkloadAdmissionSnapshot { - metadata_workload_admission_snapshot_from_initialized(get_global_bucket_metadata_sys().is_some()) + metadata_workload_admission_snapshot_from_initialized(metadata_sys::get_global_bucket_metadata_sys().is_some()) } fn metadata_workload_admission_snapshot_from_initialized(runtime_initialized: bool) -> WorkloadAdmissionSnapshot { @@ -153,7 +151,7 @@ fn repair_workload_admission_snapshot_from_counts( } pub fn replication_workload_admission_snapshot() -> WorkloadAdmissionSnapshot { - let Some(pool) = get_global_replication_pool() else { + let Some(pool) = replication::get_global_replication_pool() else { return replication_workload_admission_snapshot_from_counts(false, None, None); }; @@ -200,6 +198,16 @@ fn i32_to_usize_saturated(value: i32) -> usize { usize::try_from(value.max(0)).unwrap_or(usize::MAX) } +fn replication_queue_current_count() -> Option { + replication::GLOBAL_REPLICATION_STATS.get().and_then(|stats| { + stats + .q_cache + .try_lock() + .ok() + .map(|cache| cache.sr_queue_stats.curr.get_current_count()) + }) +} + #[cfg(test)] mod tests { use super::*; diff --git a/rustfs/src/workload_admission_storage_compat.rs b/rustfs/src/workload_admission_storage_compat.rs deleted file mode 100644 index 20a983e22..000000000 --- a/rustfs/src/workload_admission_storage_compat.rs +++ /dev/null @@ -1,36 +0,0 @@ -// Copyright 2024 RustFS Team -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -use std::sync::Arc; - -use rustfs_ecstore::api::bucket as ecstore_bucket; - -pub(crate) fn get_global_bucket_metadata_sys() -> Option>> -{ - ecstore_bucket::metadata_sys::get_global_bucket_metadata_sys() -} - -pub(crate) fn get_global_replication_pool() -> Option> { - ecstore_bucket::replication::get_global_replication_pool() -} - -pub(crate) fn replication_queue_current_count() -> Option { - ecstore_bucket::replication::GLOBAL_REPLICATION_STATS.get().and_then(|stats| { - stats - .q_cache - .try_lock() - .ok() - .map(|cache| cache.sr_queue_stats.curr.get_current_count()) - }) -} diff --git a/scripts/check_architecture_migration_rules.sh b/scripts/check_architecture_migration_rules.sh index 748232c57..cb1a1a250 100755 --- a/scripts/check_architecture_migration_rules.sh +++ b/scripts/check_architecture_migration_rules.sh @@ -107,6 +107,8 @@ RUSTFS_STORAGE_SECONDARY_COMPAT_BRIDGE_HITS_FILE="${TMP_DIR}/rustfs_storage_seco RUSTFS_NESTED_SECONDARY_COMPAT_BRIDGE_HITS_FILE="${TMP_DIR}/rustfs_nested_secondary_compat_bridge_hits.txt" RUSTFS_STORAGE_LOCAL_COMPAT_RELATIVE_CONSUMER_HITS_FILE="${TMP_DIR}/rustfs_storage_local_compat_relative_consumer_hits.txt" RUSTFS_RUNTIME_LOCAL_COMPAT_BRIDGE_HITS_FILE="${TMP_DIR}/rustfs_runtime_local_compat_bridge_hits.txt" +RUSTFS_ROOT_ONE_OFF_COMPAT_BRIDGE_HITS_FILE="${TMP_DIR}/rustfs_root_one_off_compat_bridge_hits.txt" +RUSTFS_STARTUP_COMPAT_BRIDGE_HITS_FILE="${TMP_DIR}/rustfs_startup_compat_bridge_hits.txt" RUSTFS_ADMIN_LOCAL_COMPAT_RELATIVE_CONSUMER_HITS_FILE="${TMP_DIR}/rustfs_admin_local_compat_relative_consumer_hits.txt" RUSTFS_APP_SERVER_LOCAL_COMPAT_RELATIVE_CONSUMER_HITS_FILE="${TMP_DIR}/rustfs_app_server_local_compat_relative_consumer_hits.txt" RUSTFS_HEAL_TEST_LOCAL_COMPAT_RELATIVE_CONSUMER_HITS_FILE="${TMP_DIR}/rustfs_heal_test_local_compat_relative_consumer_hits.txt" @@ -116,6 +118,7 @@ NOTIFY_STORAGE_COMPAT_MODULE_HITS_FILE="${TMP_DIR}/notify_storage_compat_module_ OBS_STORAGE_COMPAT_PASSTHROUGH_HITS_FILE="${TMP_DIR}/obs_storage_compat_passthrough_hits.txt" E2E_STORAGE_COMPAT_RPC_PASSTHROUGH_HITS_FILE="${TMP_DIR}/e2e_storage_compat_rpc_passthrough_hits.txt" TEST_STORAGE_COMPAT_PASSTHROUGH_HITS_FILE="${TMP_DIR}/test_storage_compat_passthrough_hits.txt" +TEST_FUZZ_COMPAT_BRIDGE_HITS_FILE="${TMP_DIR}/test_fuzz_compat_bridge_hits.txt" PRODUCTION_UNUSED_COMPAT_ALLOW_HITS_FILE="${TMP_DIR}/production_unused_compat_allow_hits.txt" BROAD_STORE_API_COMPAT_REEXPORT_HITS_FILE="${TMP_DIR}/broad_store_api_compat_reexport_hits.txt" NESTED_STORE_API_COMPAT_MODULE_HITS_FILE="${TMP_DIR}/nested_store_api_compat_module_hits.txt" @@ -710,7 +713,7 @@ fi --glob '!**/storage_compat.rs' \ --glob '!**/*storage_compat.rs' \ --glob '!target/**' \ - | rg -v '^(rustfs/src/capacity/service\.rs|rustfs/src/server/(event|http|module_switch|readiness)\.rs|rustfs/src/storage/s3_api/(bucket|multipart)\.rs):' || true + | rg -v '^(rustfs/src/(capacity/service|config/config_test|error|init|runtime_capabilities|startup_(background|bucket_metadata|fs_guard|iam|lifecycle|notification|server|services|shutdown|storage)|table_catalog|workload_admission)\.rs|rustfs/src/server/(event|http|module_switch|readiness)\.rs|rustfs/src/storage/s3_api/(bucket|multipart)\.rs|crates/heal/tests/(endpoint_index_test|heal_bug_fixes_test|heal_integration_test)\.rs|crates/scanner/tests/lifecycle_integration_test\.rs|fuzz/fuzz_targets/(bucket_validation|path_containment)\.rs):' || true ) | cat >"$DIRECT_ECSTORE_IMPORT_HITS_FILE" @@ -989,10 +992,6 @@ fi crates/protocols/src/swift/storage_compat.rs \ crates/s3select-api/src/storage_compat.rs \ crates/scanner/src/storage_compat.rs \ - crates/heal/tests/common/storage_compat.rs \ - crates/scanner/tests/common/storage_compat.rs \ - fuzz/fuzz_targets/path_containment/storage_compat.rs \ - fuzz/fuzz_targets/bucket_validation/storage_compat.rs \ | rg -v '^[^:]+:[0-9]+:use rustfs_ecstore::api::[a-z_]+ as ecstore_[a-z_]+;' || true ) >"$OUTER_CONSUMER_COMPAT_RAW_FACADE_PATH_HITS_FILE" @@ -1058,7 +1057,7 @@ fi ( cd "$ROOT_DIR" - rg -n --with-filename 'crate::(?:startup_storage_compat|runtime_capabilities_storage_compat|workload_admission_storage_compat|table_catalog_storage_compat|error_storage_compat)' \ + rg -n --with-filename 'crate::startup_storage_compat' \ rustfs/src/startup_*.rs \ rustfs/src/init.rs \ rustfs/src/runtime_capabilities.rs \ @@ -1193,6 +1192,41 @@ if [[ -s "$RUSTFS_RUNTIME_LOCAL_COMPAT_BRIDGE_HITS_FILE" ]]; then report_failure "RustFS capacity/server/S3 API runtime consumers must use direct owner APIs instead of local compatibility bridge modules: $(paste -sd '; ' "$RUSTFS_RUNTIME_LOCAL_COMPAT_BRIDGE_HITS_FILE")" fi +( + cd "$ROOT_DIR" + { + for file in \ + rustfs/src/config_storage_compat.rs \ + rustfs/src/error_storage_compat.rs \ + rustfs/src/runtime_capabilities_storage_compat.rs \ + rustfs/src/table_catalog_storage_compat.rs \ + rustfs/src/workload_admission_storage_compat.rs; do + [[ -e "$file" ]] && printf '%s:1:root one-off bridge file exists\n' "$file" + done + rg -n --with-filename '\bmod\s+(?:config_storage_compat|error_storage_compat|runtime_capabilities_storage_compat|table_catalog_storage_compat|workload_admission_storage_compat)|(?:crate::|self::|super::)(?:config_storage_compat|error_storage_compat|runtime_capabilities_storage_compat|table_catalog_storage_compat|workload_admission_storage_compat)|(?:config_storage_compat|error_storage_compat|runtime_capabilities_storage_compat|table_catalog_storage_compat|workload_admission_storage_compat)::' \ + rustfs/src \ + -g '*.rs' || true + } +) >"$RUSTFS_ROOT_ONE_OFF_COMPAT_BRIDGE_HITS_FILE" + +if [[ -s "$RUSTFS_ROOT_ONE_OFF_COMPAT_BRIDGE_HITS_FILE" ]]; then + report_failure "RustFS root one-off consumers must use direct ECStore owner APIs instead of compatibility bridge modules: $(paste -sd '; ' "$RUSTFS_ROOT_ONE_OFF_COMPAT_BRIDGE_HITS_FILE")" +fi + +( + cd "$ROOT_DIR" + { + [[ -e rustfs/src/startup_storage_compat.rs ]] && printf '%s:1:startup bridge file exists\n' "rustfs/src/startup_storage_compat.rs" + rg -n --with-filename '\bmod\s+startup_storage_compat|(?:crate::|self::|super::)startup_storage_compat|startup_storage_compat::' \ + rustfs/src \ + -g '*.rs' || true + } +) >"$RUSTFS_STARTUP_COMPAT_BRIDGE_HITS_FILE" + +if [[ -s "$RUSTFS_STARTUP_COMPAT_BRIDGE_HITS_FILE" ]]; then + report_failure "RustFS startup consumers must use direct ECStore owner APIs instead of startup compatibility bridge modules: $(paste -sd '; ' "$RUSTFS_STARTUP_COMPAT_BRIDGE_HITS_FILE")" +fi + ( cd "$ROOT_DIR" { @@ -1246,6 +1280,29 @@ if [[ -s "$RUSTFS_HEAL_TEST_LOCAL_COMPAT_RELATIVE_CONSUMER_HITS_FILE" ]]; then report_failure "RustFS config/heal/scanner compatibility consumers must use relative owner paths instead of crate-qualified local compatibility paths: $(paste -sd '; ' "$RUSTFS_HEAL_TEST_LOCAL_COMPAT_RELATIVE_CONSUMER_HITS_FILE")" fi +( + cd "$ROOT_DIR" + { + for file in \ + crates/heal/tests/common/storage_compat.rs \ + crates/scanner/tests/common/storage_compat.rs \ + fuzz/fuzz_targets/bucket_validation/storage_compat.rs \ + fuzz/fuzz_targets/path_containment/storage_compat.rs; do + [[ -e "$file" ]] && printf '%s:1:test/fuzz bridge file exists\n' "$file" + done + rg -n --with-filename 'common::storage_compat|storage_compat::|\bmod\s+storage_compat|#\[path\s*=\s*"[^"]*storage_compat\.rs"\]' \ + crates/heal/tests \ + crates/scanner/tests/lifecycle_integration_test.rs \ + fuzz/fuzz_targets/bucket_validation.rs \ + fuzz/fuzz_targets/path_containment.rs \ + -g '*.rs' || true + } +) >"$TEST_FUZZ_COMPAT_BRIDGE_HITS_FILE" + +if [[ -s "$TEST_FUZZ_COMPAT_BRIDGE_HITS_FILE" ]]; then + report_failure "heal/scanner test and fuzz targets must import ECStore owner APIs directly instead of local storage compatibility bridges: $(paste -sd '; ' "$TEST_FUZZ_COMPAT_BRIDGE_HITS_FILE")" +fi + ( cd "$ROOT_DIR" rg -n --with-filename 'crate::storage_compat' \