mirror of
https://github.com/rustfs/rustfs.git
synced 2026-08-06 05:17:42 +00:00
79ffecbf14
Co-authored-by: heihutu <heihutu@gmail.com>
316 lines
9.0 KiB
Rust
316 lines
9.0 KiB
Rust
// 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.
|
|
|
|
//! Main concurrency manager
|
|
|
|
use crate::config::ConcurrencyConfig;
|
|
use std::sync::Arc;
|
|
|
|
/// Snapshot of disk permit queue usage for GetObject orchestration.
|
|
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
|
pub struct GetObjectQueueSnapshot {
|
|
/// Total permits configured for disk reads.
|
|
pub total_permits: usize,
|
|
/// Permits currently in use.
|
|
pub permits_in_use: usize,
|
|
}
|
|
|
|
impl GetObjectQueueSnapshot {
|
|
/// Create a queue snapshot from total and available permits.
|
|
pub fn from_available_permits(total_permits: usize, available_permits: usize) -> Self {
|
|
Self {
|
|
total_permits,
|
|
permits_in_use: total_permits.saturating_sub(available_permits),
|
|
}
|
|
}
|
|
|
|
/// Return currently available permits.
|
|
pub fn permits_available(&self) -> usize {
|
|
self.total_permits.saturating_sub(self.permits_in_use)
|
|
}
|
|
|
|
/// Return queue utilization percentage in the 0-100 range.
|
|
pub fn utilization_percent(&self) -> f64 {
|
|
if self.total_permits == 0 {
|
|
0.0
|
|
} else {
|
|
(self.permits_in_use as f64 / self.total_permits as f64) * 100.0
|
|
}
|
|
}
|
|
|
|
/// Return whether the queue is considered congested.
|
|
pub fn is_congested(&self, threshold_percent: f64) -> bool {
|
|
self.utilization_percent() > threshold_percent
|
|
}
|
|
}
|
|
|
|
/// Main concurrency manager that provides access to all concurrency features
|
|
pub struct ConcurrencyManager {
|
|
config: ConcurrencyConfig,
|
|
|
|
#[cfg(feature = "timeout")]
|
|
timeout: Arc<crate::timeout::TimeoutManager>,
|
|
|
|
#[cfg(feature = "lock")]
|
|
lock: Arc<crate::lock::LockManager>,
|
|
|
|
#[cfg(feature = "deadlock")]
|
|
deadlock: Arc<crate::deadlock::DeadlockManager>,
|
|
|
|
#[cfg(feature = "backpressure")]
|
|
backpressure: Arc<crate::backpressure::BackpressureManager>,
|
|
|
|
#[cfg(feature = "scheduler")]
|
|
scheduler: Arc<crate::scheduler::SchedulerManager>,
|
|
}
|
|
|
|
impl ConcurrencyManager {
|
|
/// Create a new concurrency manager with the given configuration
|
|
pub fn new(config: ConcurrencyConfig) -> Self {
|
|
// Validate configuration
|
|
if let Err(e) = config.validate() {
|
|
panic!("Invalid concurrency configuration: {}", e);
|
|
}
|
|
|
|
Self {
|
|
#[cfg(feature = "timeout")]
|
|
timeout: Arc::new(crate::timeout::TimeoutManager::new(
|
|
config.default_timeout,
|
|
config.max_timeout,
|
|
config.enable_dynamic_timeout,
|
|
)),
|
|
|
|
#[cfg(feature = "lock")]
|
|
lock: Arc::new(crate::lock::LockManager::new(
|
|
config.enable_lock_optimization,
|
|
config.lock_acquire_timeout,
|
|
)),
|
|
|
|
#[cfg(feature = "deadlock")]
|
|
deadlock: Arc::new(crate::deadlock::DeadlockManager::new(
|
|
config.enable_deadlock_detection,
|
|
config.deadlock_check_interval,
|
|
config.hang_threshold,
|
|
)),
|
|
|
|
#[cfg(feature = "backpressure")]
|
|
backpressure: Arc::new(crate::backpressure::BackpressureManager::new(
|
|
config.backpressure_buffer_size,
|
|
config.high_watermark,
|
|
config.low_watermark,
|
|
)),
|
|
|
|
#[cfg(feature = "scheduler")]
|
|
scheduler: Arc::new(crate::scheduler::SchedulerManager::new(
|
|
config.io_buffer_size,
|
|
config.max_buffer_size,
|
|
config.high_priority_threshold,
|
|
config.low_priority_threshold,
|
|
)),
|
|
|
|
config,
|
|
}
|
|
}
|
|
|
|
/// Create with default configuration
|
|
pub fn with_defaults() -> Self {
|
|
Self::new(ConcurrencyConfig::default())
|
|
}
|
|
|
|
/// Create from environment variables
|
|
pub fn from_env() -> Self {
|
|
Self::new(ConcurrencyConfig::from_env())
|
|
}
|
|
|
|
/// Get the configuration
|
|
pub fn config(&self) -> &ConcurrencyConfig {
|
|
&self.config
|
|
}
|
|
|
|
// ============================================
|
|
// Feature enable checks
|
|
// ============================================
|
|
|
|
/// Check if timeout feature is enabled
|
|
pub fn is_timeout_enabled(&self) -> bool {
|
|
#[cfg(feature = "timeout")]
|
|
{
|
|
self.config.features.timeout
|
|
}
|
|
#[cfg(not(feature = "timeout"))]
|
|
{
|
|
false
|
|
}
|
|
}
|
|
|
|
/// Check if lock feature is enabled
|
|
pub fn is_lock_enabled(&self) -> bool {
|
|
#[cfg(feature = "lock")]
|
|
{
|
|
self.config.features.lock
|
|
}
|
|
#[cfg(not(feature = "lock"))]
|
|
{
|
|
false
|
|
}
|
|
}
|
|
|
|
/// Check if deadlock feature is enabled
|
|
pub fn is_deadlock_enabled(&self) -> bool {
|
|
#[cfg(feature = "deadlock")]
|
|
{
|
|
self.config.features.deadlock
|
|
}
|
|
#[cfg(not(feature = "deadlock"))]
|
|
{
|
|
false
|
|
}
|
|
}
|
|
|
|
/// Check if backpressure feature is enabled
|
|
pub fn is_backpressure_enabled(&self) -> bool {
|
|
#[cfg(feature = "backpressure")]
|
|
{
|
|
self.config.features.backpressure
|
|
}
|
|
#[cfg(not(feature = "backpressure"))]
|
|
{
|
|
false
|
|
}
|
|
}
|
|
|
|
/// Check if scheduler feature is enabled
|
|
pub fn is_scheduler_enabled(&self) -> bool {
|
|
#[cfg(feature = "scheduler")]
|
|
{
|
|
self.config.features.scheduler
|
|
}
|
|
#[cfg(not(feature = "scheduler"))]
|
|
{
|
|
false
|
|
}
|
|
}
|
|
|
|
// ============================================
|
|
// Feature accessors
|
|
// ============================================
|
|
|
|
/// Get timeout manager
|
|
#[cfg(feature = "timeout")]
|
|
pub fn timeout(&self) -> Arc<crate::timeout::TimeoutManager> {
|
|
self.timeout.clone()
|
|
}
|
|
|
|
/// Get lock manager
|
|
#[cfg(feature = "lock")]
|
|
pub fn lock(&self) -> Arc<crate::lock::LockManager> {
|
|
self.lock.clone()
|
|
}
|
|
|
|
/// Get deadlock manager
|
|
#[cfg(feature = "deadlock")]
|
|
pub fn deadlock(&self) -> Arc<crate::deadlock::DeadlockManager> {
|
|
self.deadlock.clone()
|
|
}
|
|
|
|
/// Get backpressure manager
|
|
#[cfg(feature = "backpressure")]
|
|
pub fn backpressure(&self) -> Arc<crate::backpressure::BackpressureManager> {
|
|
self.backpressure.clone()
|
|
}
|
|
|
|
/// Get scheduler manager
|
|
#[cfg(feature = "scheduler")]
|
|
pub fn scheduler(&self) -> Arc<crate::scheduler::SchedulerManager> {
|
|
self.scheduler.clone()
|
|
}
|
|
|
|
// ============================================
|
|
// Lifecycle management
|
|
// ============================================
|
|
|
|
/// Start all enabled services (e.g., deadlock detection background task)
|
|
pub async fn start(&self) {
|
|
#[cfg(feature = "deadlock")]
|
|
{
|
|
if self.config.enable_deadlock_detection {
|
|
self.deadlock.start().await;
|
|
}
|
|
}
|
|
|
|
tracing::info!(
|
|
"Concurrency manager started (timeout={}, lock={}, deadlock={}, backpressure={}, scheduler={})",
|
|
self.is_timeout_enabled(),
|
|
self.is_lock_enabled(),
|
|
self.is_deadlock_enabled(),
|
|
self.is_backpressure_enabled(),
|
|
self.is_scheduler_enabled()
|
|
);
|
|
}
|
|
|
|
/// Stop all services
|
|
pub async fn stop(&self) {
|
|
#[cfg(feature = "deadlock")]
|
|
{
|
|
self.deadlock.stop().await;
|
|
}
|
|
|
|
tracing::info!("Concurrency manager stopped");
|
|
}
|
|
}
|
|
|
|
impl Default for ConcurrencyManager {
|
|
fn default() -> Self {
|
|
Self::with_defaults()
|
|
}
|
|
}
|
|
|
|
#[cfg(test)]
|
|
mod tests {
|
|
use super::*;
|
|
|
|
#[test]
|
|
fn test_queue_snapshot() {
|
|
let snapshot = GetObjectQueueSnapshot::from_available_permits(64, 16);
|
|
assert_eq!(snapshot.permits_in_use, 48);
|
|
assert_eq!(snapshot.permits_available(), 16);
|
|
assert!(snapshot.is_congested(70.0));
|
|
}
|
|
|
|
#[test]
|
|
fn test_manager_creation() {
|
|
let manager = ConcurrencyManager::with_defaults();
|
|
assert!(manager.config().validate().is_ok());
|
|
}
|
|
|
|
#[tokio::test]
|
|
async fn test_manager_lifecycle() {
|
|
let manager = ConcurrencyManager::with_defaults();
|
|
manager.start().await;
|
|
manager.stop().await;
|
|
}
|
|
|
|
#[test]
|
|
fn test_feature_checks() {
|
|
let manager = ConcurrencyManager::with_defaults();
|
|
|
|
// These should return the feature flag status
|
|
let _ = manager.is_timeout_enabled();
|
|
let _ = manager.is_lock_enabled();
|
|
let _ = manager.is_deadlock_enabled();
|
|
let _ = manager.is_backpressure_enabled();
|
|
let _ = manager.is_scheduler_enabled();
|
|
}
|
|
}
|