mirror of
https://github.com/rustfs/rustfs.git
synced 2026-08-19 11:06:17 +00:00
feat(lock): Add support for disabling lock manager (#511)
* feat(lock): Add support for disabling lock manager Implement control of lock system activation and deactivation via environment variables Add DisabledLockManager for lock-free operation scenarios Introduce LockManager trait to uniformly manage different lock managers Signed-off-by: junxiang Mu <1948535941@qq.com> * refactor(lock): Optimize implementation of global lock manager and parsing of boolean environment variables Refactor the implementation of the global lock manager: wrap FastObjectLockManager with Arc and add the as_fast_lock_manager method Extract the boolean environment variable parsing logic into an independent function parse_bool_env_var Signed-off-by: junxiang Mu <1948535941@qq.com> --------- Signed-off-by: junxiang Mu <1948535941@qq.com>
This commit is contained in:
@@ -0,0 +1,291 @@
|
||||
// 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.
|
||||
|
||||
//! Disabled lock manager that bypasses all locking operations
|
||||
//! Used when RUSTFS_ENABLE_LOCKS environment variable is set to false
|
||||
|
||||
use std::sync::Arc;
|
||||
|
||||
use crate::fast_lock::{
|
||||
guard::FastLockGuard,
|
||||
manager_trait::LockManager,
|
||||
metrics::AggregatedMetrics,
|
||||
types::{BatchLockRequest, BatchLockResult, LockConfig, LockResult, ObjectKey, ObjectLockInfo, ObjectLockRequest},
|
||||
};
|
||||
|
||||
/// Disabled lock manager that always returns success without actual locking
|
||||
///
|
||||
/// This manager is used when locks are disabled via environment variables.
|
||||
/// All lock operations immediately return success, effectively bypassing
|
||||
/// the locking mechanism entirely.
|
||||
#[derive(Debug)]
|
||||
pub struct DisabledLockManager {
|
||||
_config: LockConfig,
|
||||
}
|
||||
|
||||
impl DisabledLockManager {
|
||||
/// Create new disabled lock manager
|
||||
pub fn new() -> Self {
|
||||
Self::with_config(LockConfig::default())
|
||||
}
|
||||
|
||||
/// Create new disabled lock manager with custom config
|
||||
pub fn with_config(config: LockConfig) -> Self {
|
||||
Self { _config: config }
|
||||
}
|
||||
|
||||
/// Always succeeds - returns a no-op guard
|
||||
pub async fn acquire_lock(&self, request: ObjectLockRequest) -> Result<FastLockGuard, LockResult> {
|
||||
Ok(FastLockGuard::new_disabled(request.key, request.mode, request.owner))
|
||||
}
|
||||
|
||||
/// Always succeeds - returns a no-op guard
|
||||
pub async fn acquire_read_lock(
|
||||
&self,
|
||||
bucket: impl Into<Arc<str>>,
|
||||
object: impl Into<Arc<str>>,
|
||||
owner: impl Into<Arc<str>>,
|
||||
) -> Result<FastLockGuard, LockResult> {
|
||||
let request = ObjectLockRequest::new_read(bucket, object, owner);
|
||||
self.acquire_lock(request).await
|
||||
}
|
||||
|
||||
/// Always succeeds - returns a no-op guard
|
||||
pub async fn acquire_read_lock_versioned(
|
||||
&self,
|
||||
bucket: impl Into<Arc<str>>,
|
||||
object: impl Into<Arc<str>>,
|
||||
version: impl Into<Arc<str>>,
|
||||
owner: impl Into<Arc<str>>,
|
||||
) -> Result<FastLockGuard, LockResult> {
|
||||
let request = ObjectLockRequest::new_read(bucket, object, owner).with_version(version);
|
||||
self.acquire_lock(request).await
|
||||
}
|
||||
|
||||
/// Always succeeds - returns a no-op guard
|
||||
pub async fn acquire_write_lock(
|
||||
&self,
|
||||
bucket: impl Into<Arc<str>>,
|
||||
object: impl Into<Arc<str>>,
|
||||
owner: impl Into<Arc<str>>,
|
||||
) -> Result<FastLockGuard, LockResult> {
|
||||
let request = ObjectLockRequest::new_write(bucket, object, owner);
|
||||
self.acquire_lock(request).await
|
||||
}
|
||||
|
||||
/// Always succeeds - returns a no-op guard
|
||||
pub async fn acquire_write_lock_versioned(
|
||||
&self,
|
||||
bucket: impl Into<Arc<str>>,
|
||||
object: impl Into<Arc<str>>,
|
||||
version: impl Into<Arc<str>>,
|
||||
owner: impl Into<Arc<str>>,
|
||||
) -> Result<FastLockGuard, LockResult> {
|
||||
let request = ObjectLockRequest::new_write(bucket, object, owner).with_version(version);
|
||||
self.acquire_lock(request).await
|
||||
}
|
||||
|
||||
/// Always succeeds - all locks acquired
|
||||
pub async fn acquire_locks_batch(&self, batch_request: BatchLockRequest) -> BatchLockResult {
|
||||
let successful_locks: Vec<ObjectKey> = batch_request.requests.into_iter().map(|req| req.key).collect();
|
||||
|
||||
BatchLockResult {
|
||||
successful_locks,
|
||||
failed_locks: Vec::new(),
|
||||
all_acquired: true,
|
||||
}
|
||||
}
|
||||
|
||||
/// Always returns None - no locks to query
|
||||
pub fn get_lock_info(&self, _key: &ObjectKey) -> Option<ObjectLockInfo> {
|
||||
None
|
||||
}
|
||||
|
||||
/// Returns empty metrics
|
||||
pub fn get_metrics(&self) -> AggregatedMetrics {
|
||||
AggregatedMetrics::empty()
|
||||
}
|
||||
|
||||
/// Always returns 0 - no locks exist
|
||||
pub fn total_lock_count(&self) -> usize {
|
||||
0
|
||||
}
|
||||
|
||||
/// Returns empty pool stats
|
||||
pub fn get_pool_stats(&self) -> Vec<(u64, u64, u64, usize)> {
|
||||
Vec::new()
|
||||
}
|
||||
|
||||
/// No-op cleanup - nothing to clean
|
||||
pub async fn cleanup_expired(&self) -> usize {
|
||||
0
|
||||
}
|
||||
|
||||
/// No-op cleanup - nothing to clean
|
||||
pub async fn cleanup_expired_traditional(&self) -> usize {
|
||||
0
|
||||
}
|
||||
|
||||
/// No-op shutdown
|
||||
pub async fn shutdown(&self) {
|
||||
// Nothing to shutdown
|
||||
}
|
||||
}
|
||||
|
||||
impl Default for DisabledLockManager {
|
||||
fn default() -> Self {
|
||||
Self::new()
|
||||
}
|
||||
}
|
||||
|
||||
#[async_trait::async_trait]
|
||||
impl LockManager for DisabledLockManager {
|
||||
async fn acquire_lock(&self, request: ObjectLockRequest) -> Result<FastLockGuard, LockResult> {
|
||||
self.acquire_lock(request).await
|
||||
}
|
||||
|
||||
async fn acquire_read_lock(
|
||||
&self,
|
||||
bucket: impl Into<Arc<str>> + Send,
|
||||
object: impl Into<Arc<str>> + Send,
|
||||
owner: impl Into<Arc<str>> + Send,
|
||||
) -> Result<FastLockGuard, LockResult> {
|
||||
self.acquire_read_lock(bucket, object, owner).await
|
||||
}
|
||||
|
||||
async fn acquire_read_lock_versioned(
|
||||
&self,
|
||||
bucket: impl Into<Arc<str>> + Send,
|
||||
object: impl Into<Arc<str>> + Send,
|
||||
version: impl Into<Arc<str>> + Send,
|
||||
owner: impl Into<Arc<str>> + Send,
|
||||
) -> Result<FastLockGuard, LockResult> {
|
||||
self.acquire_read_lock_versioned(bucket, object, version, owner).await
|
||||
}
|
||||
|
||||
async fn acquire_write_lock(
|
||||
&self,
|
||||
bucket: impl Into<Arc<str>> + Send,
|
||||
object: impl Into<Arc<str>> + Send,
|
||||
owner: impl Into<Arc<str>> + Send,
|
||||
) -> Result<FastLockGuard, LockResult> {
|
||||
self.acquire_write_lock(bucket, object, owner).await
|
||||
}
|
||||
|
||||
async fn acquire_write_lock_versioned(
|
||||
&self,
|
||||
bucket: impl Into<Arc<str>> + Send,
|
||||
object: impl Into<Arc<str>> + Send,
|
||||
version: impl Into<Arc<str>> + Send,
|
||||
owner: impl Into<Arc<str>> + Send,
|
||||
) -> Result<FastLockGuard, LockResult> {
|
||||
self.acquire_write_lock_versioned(bucket, object, version, owner).await
|
||||
}
|
||||
|
||||
async fn acquire_locks_batch(&self, batch_request: BatchLockRequest) -> BatchLockResult {
|
||||
self.acquire_locks_batch(batch_request).await
|
||||
}
|
||||
|
||||
fn get_lock_info(&self, key: &ObjectKey) -> Option<ObjectLockInfo> {
|
||||
self.get_lock_info(key)
|
||||
}
|
||||
|
||||
fn get_metrics(&self) -> AggregatedMetrics {
|
||||
self.get_metrics()
|
||||
}
|
||||
|
||||
fn total_lock_count(&self) -> usize {
|
||||
self.total_lock_count()
|
||||
}
|
||||
|
||||
fn get_pool_stats(&self) -> Vec<(u64, u64, u64, usize)> {
|
||||
self.get_pool_stats()
|
||||
}
|
||||
|
||||
async fn cleanup_expired(&self) -> usize {
|
||||
self.cleanup_expired().await
|
||||
}
|
||||
|
||||
async fn cleanup_expired_traditional(&self) -> usize {
|
||||
self.cleanup_expired_traditional().await
|
||||
}
|
||||
|
||||
async fn shutdown(&self) {
|
||||
self.shutdown().await
|
||||
}
|
||||
|
||||
fn is_disabled(&self) -> bool {
|
||||
true
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
||||
#[tokio::test]
|
||||
async fn test_disabled_manager_basic_operations() {
|
||||
let manager = DisabledLockManager::new();
|
||||
|
||||
// All operations should succeed immediately
|
||||
let read_guard = manager
|
||||
.acquire_read_lock("bucket", "object", "owner1")
|
||||
.await
|
||||
.expect("Disabled manager should always succeed");
|
||||
|
||||
let write_guard = manager
|
||||
.acquire_write_lock("bucket", "object", "owner2")
|
||||
.await
|
||||
.expect("Disabled manager should always succeed");
|
||||
|
||||
// Guards should indicate they are disabled
|
||||
assert!(read_guard.is_disabled());
|
||||
assert!(write_guard.is_disabled());
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn test_disabled_manager_batch_operations() {
|
||||
let manager = DisabledLockManager::new();
|
||||
|
||||
let batch = BatchLockRequest::new("owner")
|
||||
.add_read_lock("bucket", "obj1")
|
||||
.add_write_lock("bucket", "obj2")
|
||||
.with_all_or_nothing(true);
|
||||
|
||||
let result = manager.acquire_locks_batch(batch).await;
|
||||
assert!(result.all_acquired);
|
||||
assert_eq!(result.successful_locks.len(), 2);
|
||||
assert!(result.failed_locks.is_empty());
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn test_disabled_manager_metrics() {
|
||||
let manager = DisabledLockManager::new();
|
||||
|
||||
// Metrics should indicate empty/disabled state
|
||||
let metrics = manager.get_metrics();
|
||||
assert!(metrics.is_empty());
|
||||
assert_eq!(manager.total_lock_count(), 0);
|
||||
assert!(manager.get_pool_stats().is_empty());
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn test_disabled_manager_cleanup() {
|
||||
let manager = DisabledLockManager::new();
|
||||
|
||||
// Cleanup should be no-op
|
||||
assert_eq!(manager.cleanup_expired().await, 0);
|
||||
assert_eq!(manager.cleanup_expired_traditional().await, 0);
|
||||
}
|
||||
}
|
||||
@@ -26,8 +26,9 @@ pub struct FastLockGuard {
|
||||
key: ObjectKey,
|
||||
mode: LockMode,
|
||||
owner: Arc<str>,
|
||||
shard: Arc<LockShard>,
|
||||
shard: Option<Arc<LockShard>>, // None when locks are disabled
|
||||
released: bool,
|
||||
disabled: bool, // True when locks are disabled globally
|
||||
}
|
||||
|
||||
impl FastLockGuard {
|
||||
@@ -36,8 +37,21 @@ impl FastLockGuard {
|
||||
key,
|
||||
mode,
|
||||
owner,
|
||||
shard,
|
||||
shard: Some(shard),
|
||||
released: false,
|
||||
disabled: false,
|
||||
}
|
||||
}
|
||||
|
||||
/// Create a disabled guard (when locks are globally disabled)
|
||||
pub(crate) fn new_disabled(key: ObjectKey, mode: LockMode, owner: Arc<str>) -> Self {
|
||||
Self {
|
||||
key,
|
||||
mode,
|
||||
owner,
|
||||
shard: None,
|
||||
released: false,
|
||||
disabled: true,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -65,11 +79,23 @@ impl FastLockGuard {
|
||||
return false;
|
||||
}
|
||||
|
||||
let success = self.shard.release_lock(&self.key, &self.owner, self.mode);
|
||||
if success {
|
||||
if self.disabled {
|
||||
// For disabled locks, always succeed
|
||||
self.released = true;
|
||||
return true;
|
||||
}
|
||||
|
||||
if let Some(shard) = &self.shard {
|
||||
let success = shard.release_lock(&self.key, &self.owner, self.mode);
|
||||
if success {
|
||||
self.released = true;
|
||||
}
|
||||
success
|
||||
} else {
|
||||
// Should not happen, but handle gracefully
|
||||
self.released = true;
|
||||
false
|
||||
}
|
||||
success
|
||||
}
|
||||
|
||||
/// Check if the lock has been released
|
||||
@@ -77,27 +103,36 @@ impl FastLockGuard {
|
||||
self.released
|
||||
}
|
||||
|
||||
/// Check if this guard represents a disabled lock
|
||||
pub fn is_disabled(&self) -> bool {
|
||||
self.disabled
|
||||
}
|
||||
|
||||
/// Get lock information for monitoring
|
||||
pub fn lock_info(&self) -> Option<crate::fast_lock::types::ObjectLockInfo> {
|
||||
if self.released {
|
||||
if self.released || self.disabled {
|
||||
None
|
||||
} else if let Some(shard) = &self.shard {
|
||||
shard.get_lock_info(&self.key)
|
||||
} else {
|
||||
self.shard.get_lock_info(&self.key)
|
||||
None
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Drop for FastLockGuard {
|
||||
fn drop(&mut self) {
|
||||
if !self.released {
|
||||
let success = self.shard.release_lock(&self.key, &self.owner, self.mode);
|
||||
if !success {
|
||||
tracing::warn!(
|
||||
"Failed to release lock during drop: key={}, owner={}, mode={:?}",
|
||||
self.key,
|
||||
self.owner,
|
||||
self.mode
|
||||
);
|
||||
if !self.released && !self.disabled {
|
||||
if let Some(shard) = &self.shard {
|
||||
let success = shard.release_lock(&self.key, &self.owner, self.mode);
|
||||
if !success {
|
||||
tracing::warn!(
|
||||
"Failed to release lock during drop: key={}, owner={}, mode={:?}",
|
||||
self.key,
|
||||
self.owner,
|
||||
self.mode
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -110,6 +145,7 @@ impl std::fmt::Debug for FastLockGuard {
|
||||
.field("mode", &self.mode)
|
||||
.field("owner", &self.owner)
|
||||
.field("released", &self.released)
|
||||
.field("disabled", &self.disabled)
|
||||
.finish()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -18,9 +18,10 @@ use tokio::time::{Instant, interval};
|
||||
|
||||
use crate::fast_lock::{
|
||||
guard::FastLockGuard,
|
||||
metrics::GlobalMetrics,
|
||||
manager_trait::LockManager,
|
||||
metrics::{AggregatedMetrics, GlobalMetrics},
|
||||
shard::LockShard,
|
||||
types::{BatchLockRequest, BatchLockResult, LockConfig, LockResult, ObjectLockRequest},
|
||||
types::{BatchLockRequest, BatchLockResult, LockConfig, LockResult, ObjectKey, ObjectLockInfo, ObjectLockRequest},
|
||||
};
|
||||
|
||||
/// High-performance object lock manager
|
||||
@@ -361,6 +362,87 @@ impl Drop for FastObjectLockManager {
|
||||
}
|
||||
}
|
||||
|
||||
#[async_trait::async_trait]
|
||||
impl LockManager for FastObjectLockManager {
|
||||
async fn acquire_lock(&self, request: ObjectLockRequest) -> Result<FastLockGuard, LockResult> {
|
||||
self.acquire_lock(request).await
|
||||
}
|
||||
|
||||
async fn acquire_read_lock(
|
||||
&self,
|
||||
bucket: impl Into<Arc<str>> + Send,
|
||||
object: impl Into<Arc<str>> + Send,
|
||||
owner: impl Into<Arc<str>> + Send,
|
||||
) -> Result<FastLockGuard, LockResult> {
|
||||
self.acquire_read_lock(bucket, object, owner).await
|
||||
}
|
||||
|
||||
async fn acquire_read_lock_versioned(
|
||||
&self,
|
||||
bucket: impl Into<Arc<str>> + Send,
|
||||
object: impl Into<Arc<str>> + Send,
|
||||
version: impl Into<Arc<str>> + Send,
|
||||
owner: impl Into<Arc<str>> + Send,
|
||||
) -> Result<FastLockGuard, LockResult> {
|
||||
self.acquire_read_lock_versioned(bucket, object, version, owner).await
|
||||
}
|
||||
|
||||
async fn acquire_write_lock(
|
||||
&self,
|
||||
bucket: impl Into<Arc<str>> + Send,
|
||||
object: impl Into<Arc<str>> + Send,
|
||||
owner: impl Into<Arc<str>> + Send,
|
||||
) -> Result<FastLockGuard, LockResult> {
|
||||
self.acquire_write_lock(bucket, object, owner).await
|
||||
}
|
||||
|
||||
async fn acquire_write_lock_versioned(
|
||||
&self,
|
||||
bucket: impl Into<Arc<str>> + Send,
|
||||
object: impl Into<Arc<str>> + Send,
|
||||
version: impl Into<Arc<str>> + Send,
|
||||
owner: impl Into<Arc<str>> + Send,
|
||||
) -> Result<FastLockGuard, LockResult> {
|
||||
self.acquire_write_lock_versioned(bucket, object, version, owner).await
|
||||
}
|
||||
|
||||
async fn acquire_locks_batch(&self, batch_request: BatchLockRequest) -> BatchLockResult {
|
||||
self.acquire_locks_batch(batch_request).await
|
||||
}
|
||||
|
||||
fn get_lock_info(&self, key: &ObjectKey) -> Option<ObjectLockInfo> {
|
||||
self.get_lock_info(key)
|
||||
}
|
||||
|
||||
fn get_metrics(&self) -> AggregatedMetrics {
|
||||
self.get_metrics()
|
||||
}
|
||||
|
||||
fn total_lock_count(&self) -> usize {
|
||||
self.total_lock_count()
|
||||
}
|
||||
|
||||
fn get_pool_stats(&self) -> Vec<(u64, u64, u64, usize)> {
|
||||
self.get_pool_stats()
|
||||
}
|
||||
|
||||
async fn cleanup_expired(&self) -> usize {
|
||||
self.cleanup_expired().await
|
||||
}
|
||||
|
||||
async fn cleanup_expired_traditional(&self) -> usize {
|
||||
self.cleanup_expired_traditional().await
|
||||
}
|
||||
|
||||
async fn shutdown(&self) {
|
||||
self.shutdown().await
|
||||
}
|
||||
|
||||
fn is_disabled(&self) -> bool {
|
||||
false
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
||||
@@ -0,0 +1,93 @@
|
||||
// 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.
|
||||
|
||||
//! Unified trait for lock managers (enabled and disabled)
|
||||
|
||||
use crate::fast_lock::{
|
||||
guard::FastLockGuard,
|
||||
metrics::AggregatedMetrics,
|
||||
types::{BatchLockRequest, BatchLockResult, LockResult, ObjectKey, ObjectLockInfo, ObjectLockRequest},
|
||||
};
|
||||
use std::sync::Arc;
|
||||
|
||||
/// Unified trait for lock managers
|
||||
///
|
||||
/// This trait allows transparent switching between enabled and disabled lock managers
|
||||
/// based on environment variables.
|
||||
#[async_trait::async_trait]
|
||||
pub trait LockManager: Send + Sync {
|
||||
/// Acquire object lock
|
||||
async fn acquire_lock(&self, request: ObjectLockRequest) -> Result<FastLockGuard, LockResult>;
|
||||
|
||||
/// Acquire shared (read) lock
|
||||
async fn acquire_read_lock(
|
||||
&self,
|
||||
bucket: impl Into<Arc<str>> + Send,
|
||||
object: impl Into<Arc<str>> + Send,
|
||||
owner: impl Into<Arc<str>> + Send,
|
||||
) -> Result<FastLockGuard, LockResult>;
|
||||
|
||||
/// Acquire shared (read) lock for specific version
|
||||
async fn acquire_read_lock_versioned(
|
||||
&self,
|
||||
bucket: impl Into<Arc<str>> + Send,
|
||||
object: impl Into<Arc<str>> + Send,
|
||||
version: impl Into<Arc<str>> + Send,
|
||||
owner: impl Into<Arc<str>> + Send,
|
||||
) -> Result<FastLockGuard, LockResult>;
|
||||
|
||||
/// Acquire exclusive (write) lock
|
||||
async fn acquire_write_lock(
|
||||
&self,
|
||||
bucket: impl Into<Arc<str>> + Send,
|
||||
object: impl Into<Arc<str>> + Send,
|
||||
owner: impl Into<Arc<str>> + Send,
|
||||
) -> Result<FastLockGuard, LockResult>;
|
||||
|
||||
/// Acquire exclusive (write) lock for specific version
|
||||
async fn acquire_write_lock_versioned(
|
||||
&self,
|
||||
bucket: impl Into<Arc<str>> + Send,
|
||||
object: impl Into<Arc<str>> + Send,
|
||||
version: impl Into<Arc<str>> + Send,
|
||||
owner: impl Into<Arc<str>> + Send,
|
||||
) -> Result<FastLockGuard, LockResult>;
|
||||
|
||||
/// Acquire multiple locks atomically
|
||||
async fn acquire_locks_batch(&self, batch_request: BatchLockRequest) -> BatchLockResult;
|
||||
|
||||
/// Get lock information for monitoring
|
||||
fn get_lock_info(&self, key: &ObjectKey) -> Option<ObjectLockInfo>;
|
||||
|
||||
/// Get aggregated metrics
|
||||
fn get_metrics(&self) -> AggregatedMetrics;
|
||||
|
||||
/// Get total number of active locks across all shards
|
||||
fn total_lock_count(&self) -> usize;
|
||||
|
||||
/// Get pool statistics from all shards
|
||||
fn get_pool_stats(&self) -> Vec<(u64, u64, u64, usize)>;
|
||||
|
||||
/// Force cleanup of expired locks
|
||||
async fn cleanup_expired(&self) -> usize;
|
||||
|
||||
/// Force cleanup with traditional strategy
|
||||
async fn cleanup_expired_traditional(&self) -> usize;
|
||||
|
||||
/// Shutdown the lock manager and cleanup resources
|
||||
async fn shutdown(&self);
|
||||
|
||||
/// Check if this manager is disabled
|
||||
fn is_disabled(&self) -> bool;
|
||||
}
|
||||
@@ -142,6 +142,20 @@ pub struct MetricsSnapshot {
|
||||
}
|
||||
|
||||
impl MetricsSnapshot {
|
||||
/// Create empty snapshot (for disabled lock manager)
|
||||
pub fn empty() -> Self {
|
||||
Self {
|
||||
fast_path_success: 0,
|
||||
slow_path_success: 0,
|
||||
timeouts: 0,
|
||||
releases: 0,
|
||||
cleanups: 0,
|
||||
contention_events: 0,
|
||||
total_wait_time_ns: 0,
|
||||
max_wait_time_ns: 0,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn total_acquisitions(&self) -> u64 {
|
||||
self.fast_path_success + self.slow_path_success
|
||||
}
|
||||
@@ -251,6 +265,22 @@ pub struct AggregatedMetrics {
|
||||
}
|
||||
|
||||
impl AggregatedMetrics {
|
||||
/// Create empty metrics (for disabled lock manager)
|
||||
pub fn empty() -> Self {
|
||||
Self {
|
||||
shard_metrics: MetricsSnapshot::empty(),
|
||||
shard_count: 0,
|
||||
uptime: Duration::ZERO,
|
||||
cleanup_runs: 0,
|
||||
total_objects_cleaned: 0,
|
||||
}
|
||||
}
|
||||
|
||||
/// Check if metrics are empty (indicates disabled or no activity)
|
||||
pub fn is_empty(&self) -> bool {
|
||||
self.shard_count == 0 && self.shard_metrics.total_acquisitions() == 0 && self.shard_metrics.releases == 0
|
||||
}
|
||||
|
||||
/// Get operations per second
|
||||
pub fn ops_per_second(&self) -> f64 {
|
||||
let total_ops = self.shard_metrics.total_acquisitions() + self.shard_metrics.releases;
|
||||
|
||||
@@ -24,10 +24,12 @@
|
||||
//! 4. **Async Optimized** - True async locks that avoid thread blocking
|
||||
//! 5. **Auto Cleanup** - Access-time based automatic lock reclamation
|
||||
|
||||
pub mod disabled_manager;
|
||||
pub mod guard;
|
||||
pub mod integration_example;
|
||||
pub mod integration_test;
|
||||
pub mod manager;
|
||||
pub mod manager_trait;
|
||||
pub mod metrics;
|
||||
pub mod object_pool;
|
||||
pub mod optimized_notify;
|
||||
@@ -39,8 +41,10 @@ pub mod types;
|
||||
// pub mod benchmarks; // Temporarily disabled due to compilation issues
|
||||
|
||||
// Re-export main types
|
||||
pub use disabled_manager::DisabledLockManager;
|
||||
pub use guard::FastLockGuard;
|
||||
pub use manager::FastObjectLockManager;
|
||||
pub use manager_trait::LockManager;
|
||||
pub use types::*;
|
||||
|
||||
/// Default shard count (must be power of 2)
|
||||
|
||||
Reference in New Issue
Block a user