// 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. // Example integration of FastObjectLockManager in set_disk.rs // This shows how to replace the current slow lock system use crate::fast_lock::{BatchLockRequest, FastObjectLockManager, ObjectLockRequest}; use std::sync::Arc; use std::time::Duration; /// Example integration into SetDisks structure pub struct SetDisksWithFastLock { /// Replace the old namespace_lock with fast lock manager pub fast_lock_manager: Arc, pub locker_owner: String, // ... other fields remain the same } impl SetDisksWithFastLock { /// Example: Replace get_object_reader with fast locking pub async fn get_object_reader_fast( &self, bucket: &str, object: &str, version: Option<&str>, // ... other parameters ) -> Result<(), Box> { // Fast path: Try to acquire read lock immediately let _read_guard = if let Some(v) = version { // Version-specific lock self.fast_lock_manager .acquire_read_lock_versioned(bucket, object, v, self.locker_owner.as_str()) .await .map_err(|_| "Lock acquisition failed")? } else { // Latest version lock self.fast_lock_manager .acquire_read_lock(bucket, object, self.locker_owner.as_str()) .await .map_err(|_| "Lock acquisition failed")? }; // Critical section: Read object // The lock is automatically released when _read_guard goes out of scope // ... actual read operation logic Ok(()) } /// Example: Replace put_object with fast locking pub async fn put_object_fast( &self, bucket: &str, object: &str, version: Option<&str>, // ... other parameters ) -> Result<(), Box> { // Acquire exclusive write lock with timeout let request = ObjectLockRequest::new_write(bucket, object, self.locker_owner.as_str()) .with_acquire_timeout(Duration::from_secs(5)) .with_lock_timeout(Duration::from_secs(30)); let request = if let Some(v) = version { request.with_version(v) } else { request }; let _write_guard = self .fast_lock_manager .acquire_lock(request) .await .map_err(|_| "Lock acquisition failed")?; // Critical section: Write object // ... actual write operation logic Ok(()) // Lock automatically released when _write_guard drops } /// Example: Replace delete_objects with batch fast locking pub async fn delete_objects_fast( &self, bucket: &str, objects: Vec<(&str, Option<&str>)>, // (object_name, version) ) -> Result, Box> { // Create batch request for atomic locking let mut batch = BatchLockRequest::new(self.locker_owner.as_str()).with_all_or_nothing(true); // Either lock all or fail // Add all objects to batch (sorted internally to prevent deadlocks) for (object, version) in &objects { let mut request = ObjectLockRequest::new_write(bucket, *object, self.locker_owner.as_str()); if let Some(v) = version { request = request.with_version(*v); } batch.requests.push(request); } // Acquire all locks atomically let batch_result = self.fast_lock_manager.acquire_locks_batch(batch).await; if !batch_result.all_acquired { return Err("Failed to acquire all locks for batch delete".into()); } // Critical section: Delete all objects let mut deleted = Vec::new(); for (object, _version) in objects { // ... actual delete operation logic deleted.push(object.to_string()); } // All locks automatically released when guards go out of scope Ok(deleted) } /// Example: Health check integration pub fn get_lock_health(&self) -> crate::fast_lock::metrics::AggregatedMetrics { self.fast_lock_manager.get_metrics() } /// Example: Cleanup integration pub async fn cleanup_expired_locks(&self) -> usize { self.fast_lock_manager.cleanup_expired().await } } /// Performance comparison demonstration pub mod performance_comparison { use super::*; use std::time::Instant; pub async fn benchmark_fast_vs_old() { let fast_manager = Arc::new(FastObjectLockManager::new()); let owner = "benchmark_owner"; // Benchmark fast lock acquisition let start = Instant::now(); let mut guards = Vec::new(); for i in 0..1000 { let guard = fast_manager .acquire_write_lock("bucket", format!("object_{i}"), owner) .await .expect("Failed to acquire fast lock"); guards.push(guard); } let fast_duration = start.elapsed(); println!("Fast lock: 1000 acquisitions in {fast_duration:?}"); // Release all drop(guards); // Compare with metrics let metrics = fast_manager.get_metrics(); println!("Fast path rate: {:.2}%", metrics.shard_metrics.fast_path_rate() * 100.0); println!("Average wait time: {:?}", metrics.shard_metrics.avg_wait_time()); println!("Total operations/sec: {:.2}", metrics.ops_per_second()); } } /// Migration guide from old to new system pub mod migration_guide { /* Step-by-step migration from old lock system: 1. Replace namespace_lock field: OLD: pub namespace_lock: Arc NEW: pub fast_lock_manager: Arc 2. Replace lock acquisition: OLD: self.namespace_lock.lock_guard(object, &self.locker_owner, timeout, ttl).await? NEW: self.fast_lock_manager.acquire_write_lock(bucket, object, &self.locker_owner).await? 3. Replace read lock acquisition: OLD: self.namespace_lock.rlock_guard(object, &self.locker_owner, timeout, ttl).await? NEW: self.fast_lock_manager.acquire_read_lock(bucket, object, &self.locker_owner).await? 4. Add version support where needed: NEW: self.fast_lock_manager.acquire_write_lock_versioned(bucket, object, version, owner).await? 5. Replace batch operations: OLD: Multiple individual lock_guard calls in loop NEW: Single BatchLockRequest with all objects 6. Remove manual lock release (RAII handles it automatically) OLD: guard.disarm() or explicit release NEW: Just let guard go out of scope Expected performance improvements: - 10-50x faster lock acquisition - 90%+ fast path success rate - Sub-millisecond lock operations - No deadlock issues with batch operations - Automatic cleanup and monitoring */ } #[cfg(test)] mod tests { use super::*; #[tokio::test] async fn test_integration_example() { let fast_manager = Arc::new(FastObjectLockManager::new()); let set_disks = SetDisksWithFastLock { fast_lock_manager: fast_manager, locker_owner: "test_owner".to_string(), }; // Test read operation assert!(set_disks.get_object_reader_fast("bucket", "object", None).await.is_ok()); // Test write operation assert!(set_disks.put_object_fast("bucket", "object", Some("v1")).await.is_ok()); // Test batch delete let objects = vec![("obj1", None), ("obj2", Some("v1"))]; let result = set_disks.delete_objects_fast("bucket", objects).await; assert!(result.is_ok()); } #[tokio::test] async fn test_version_locking() { let fast_manager = Arc::new(FastObjectLockManager::new()); // Should be able to lock different versions simultaneously let guard_v1 = fast_manager .acquire_write_lock_versioned("bucket", "object", "v1", "owner1") .await .expect("Failed to lock v1"); let guard_v2 = fast_manager .acquire_write_lock_versioned("bucket", "object", "v2", "owner2") .await .expect("Failed to lock v2"); // Both locks should coexist assert!(!guard_v1.is_released()); assert!(!guard_v2.is_released()); } }