mirror of
https://github.com/rustfs/rustfs.git
synced 2026-07-26 08:18:18 +00:00
7172e151de
Co-authored-by: heihutu <heihutu@gmail.com> Co-authored-by: houseme <housemecn@gmail.com>
392 lines
12 KiB
Rust
392 lines
12 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.
|
|
|
|
//! Unified configuration interface for I/O operations.
|
|
//!
|
|
//! This module provides a centralized configuration interface
|
|
//! for all I/O-related settings.
|
|
|
|
use std::time::Duration;
|
|
|
|
// ============================================================================
|
|
// Configuration Constants
|
|
// ============================================================================
|
|
|
|
/// Default cache max capacity.
|
|
pub const DEFAULT_CACHE_MAX_CAPACITY: u64 = 10_000;
|
|
/// Default cache TTL in seconds.
|
|
pub const DEFAULT_CACHE_TTL_SECS: u64 = 300;
|
|
/// Default cache max memory in bytes (100 MB).
|
|
pub const DEFAULT_CACHE_MAX_MEMORY: u64 = 100 * 1024 * 1024;
|
|
|
|
/// Default I/O scheduler max concurrent reads.
|
|
pub const DEFAULT_MAX_CONCURRENT_READS: usize = 32;
|
|
/// Default high priority size threshold (64 KB).
|
|
pub const DEFAULT_HIGH_PRIORITY_SIZE_THRESHOLD: usize = 64 * 1024;
|
|
/// Default low priority size threshold (4 MB).
|
|
pub const DEFAULT_LOW_PRIORITY_SIZE_THRESHOLD: usize = 4 * 1024 * 1024;
|
|
|
|
/// Default backpressure high watermark.
|
|
pub const DEFAULT_BACKPRESSURE_HIGH_WATERMARK: f64 = 0.8;
|
|
/// Default backpressure low watermark.
|
|
pub const DEFAULT_BACKPRESSURE_LOW_WATERMARK: f64 = 0.5;
|
|
|
|
/// Default lock acquire timeout in seconds.
|
|
pub const DEFAULT_LOCK_ACQUIRE_TIMEOUT_SECS: u64 = 5;
|
|
/// Default deadlock detection interval in seconds.
|
|
pub const DEFAULT_DEADLOCK_DETECTION_INTERVAL_SECS: u64 = 1;
|
|
|
|
/// Default base buffer size (128 KB).
|
|
pub const DEFAULT_BASE_BUFFER_SIZE: usize = 128 * 1024;
|
|
/// Default max buffer size (1 MB).
|
|
pub const DEFAULT_MAX_BUFFER_SIZE: usize = 1024 * 1024;
|
|
/// Default min buffer size (4 KB).
|
|
pub const DEFAULT_MIN_BUFFER_SIZE: usize = 4 * 1024;
|
|
|
|
// ============================================================================
|
|
// Cache Configuration
|
|
// ============================================================================
|
|
|
|
/// Cache configuration settings.
|
|
#[derive(Debug, Clone)]
|
|
pub struct CacheSettings {
|
|
/// Maximum cache capacity.
|
|
pub max_capacity: u64,
|
|
/// Default TTL.
|
|
pub default_ttl: Duration,
|
|
/// Maximum memory usage.
|
|
pub max_memory: u64,
|
|
/// Whether adaptive TTL is enabled.
|
|
pub adaptive_ttl_enabled: bool,
|
|
}
|
|
|
|
impl Default for CacheSettings {
|
|
fn default() -> Self {
|
|
Self {
|
|
max_capacity: DEFAULT_CACHE_MAX_CAPACITY,
|
|
default_ttl: Duration::from_secs(DEFAULT_CACHE_TTL_SECS),
|
|
max_memory: DEFAULT_CACHE_MAX_MEMORY,
|
|
adaptive_ttl_enabled: true,
|
|
}
|
|
}
|
|
}
|
|
|
|
impl CacheSettings {
|
|
/// Create new cache settings.
|
|
pub fn new() -> Self {
|
|
Self::default()
|
|
}
|
|
|
|
/// Builder: set max capacity.
|
|
pub fn with_max_capacity(mut self, capacity: u64) -> Self {
|
|
self.max_capacity = capacity;
|
|
self
|
|
}
|
|
|
|
/// Builder: set TTL.
|
|
pub fn with_ttl(mut self, ttl: Duration) -> Self {
|
|
self.default_ttl = ttl;
|
|
self
|
|
}
|
|
|
|
/// Builder: set max memory.
|
|
pub fn with_max_memory(mut self, memory: u64) -> Self {
|
|
self.max_memory = memory;
|
|
self
|
|
}
|
|
}
|
|
|
|
// ============================================================================
|
|
// I/O Scheduler Configuration
|
|
// ============================================================================
|
|
|
|
/// I/O scheduler configuration settings.
|
|
#[derive(Debug, Clone)]
|
|
pub struct IoSchedulerSettings {
|
|
/// Maximum concurrent reads.
|
|
pub max_concurrent_reads: usize,
|
|
/// High priority size threshold.
|
|
pub high_priority_threshold: usize,
|
|
/// Low priority size threshold.
|
|
pub low_priority_threshold: usize,
|
|
/// Base buffer size.
|
|
pub base_buffer_size: usize,
|
|
/// Max buffer size.
|
|
pub max_buffer_size: usize,
|
|
/// Min buffer size.
|
|
pub min_buffer_size: usize,
|
|
/// Whether priority scheduling is enabled.
|
|
pub priority_enabled: bool,
|
|
}
|
|
|
|
impl Default for IoSchedulerSettings {
|
|
fn default() -> Self {
|
|
Self {
|
|
max_concurrent_reads: DEFAULT_MAX_CONCURRENT_READS,
|
|
high_priority_threshold: DEFAULT_HIGH_PRIORITY_SIZE_THRESHOLD,
|
|
low_priority_threshold: DEFAULT_LOW_PRIORITY_SIZE_THRESHOLD,
|
|
base_buffer_size: DEFAULT_BASE_BUFFER_SIZE,
|
|
max_buffer_size: DEFAULT_MAX_BUFFER_SIZE,
|
|
min_buffer_size: DEFAULT_MIN_BUFFER_SIZE,
|
|
priority_enabled: true,
|
|
}
|
|
}
|
|
}
|
|
|
|
impl IoSchedulerSettings {
|
|
/// Create new settings.
|
|
pub fn new() -> Self {
|
|
Self::default()
|
|
}
|
|
|
|
/// Builder: set max concurrent reads.
|
|
pub fn with_max_concurrent_reads(mut self, max: usize) -> Self {
|
|
self.max_concurrent_reads = max;
|
|
self
|
|
}
|
|
|
|
/// Builder: set buffer sizes.
|
|
pub fn with_buffer_sizes(mut self, base: usize, min: usize, max: usize) -> Self {
|
|
self.base_buffer_size = base;
|
|
self.min_buffer_size = min;
|
|
self.max_buffer_size = max;
|
|
self
|
|
}
|
|
}
|
|
|
|
// ============================================================================
|
|
// Backpressure Configuration
|
|
// ============================================================================
|
|
|
|
/// Backpressure configuration settings.
|
|
#[derive(Debug, Clone)]
|
|
pub struct BackpressureSettings {
|
|
/// Whether backpressure is enabled.
|
|
pub enabled: bool,
|
|
/// High watermark (percentage).
|
|
pub high_watermark: f64,
|
|
/// Low watermark (percentage).
|
|
pub low_watermark: f64,
|
|
/// Cooldown duration.
|
|
pub cooldown: Duration,
|
|
}
|
|
|
|
impl Default for BackpressureSettings {
|
|
fn default() -> Self {
|
|
Self {
|
|
enabled: true,
|
|
high_watermark: DEFAULT_BACKPRESSURE_HIGH_WATERMARK,
|
|
low_watermark: DEFAULT_BACKPRESSURE_LOW_WATERMARK,
|
|
cooldown: Duration::from_millis(100),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl BackpressureSettings {
|
|
/// Create new settings.
|
|
pub fn new() -> Self {
|
|
Self::default()
|
|
}
|
|
|
|
/// Get high watermark threshold for a given max value.
|
|
pub fn high_threshold(&self, max: usize) -> usize {
|
|
(max as f64 * self.high_watermark) as usize
|
|
}
|
|
|
|
/// Get low watermark threshold for a given max value.
|
|
pub fn low_threshold(&self, max: usize) -> usize {
|
|
(max as f64 * self.low_watermark) as usize
|
|
}
|
|
}
|
|
|
|
// ============================================================================
|
|
// Timeout Configuration
|
|
// ============================================================================
|
|
|
|
/// Timeout configuration settings.
|
|
#[derive(Debug, Clone)]
|
|
pub struct TimeoutSettings {
|
|
/// Default operation timeout.
|
|
pub default_timeout: Duration,
|
|
/// Maximum retries.
|
|
pub max_retries: usize,
|
|
/// Retry backoff factor.
|
|
pub retry_backoff_factor: f64,
|
|
/// Lock acquire timeout.
|
|
pub lock_acquire_timeout: Duration,
|
|
}
|
|
|
|
impl Default for TimeoutSettings {
|
|
fn default() -> Self {
|
|
Self {
|
|
default_timeout: Duration::from_secs(30),
|
|
max_retries: 3,
|
|
retry_backoff_factor: 2.0,
|
|
lock_acquire_timeout: Duration::from_secs(DEFAULT_LOCK_ACQUIRE_TIMEOUT_SECS),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl TimeoutSettings {
|
|
/// Create new settings.
|
|
pub fn new() -> Self {
|
|
Self::default()
|
|
}
|
|
|
|
/// Calculate timeout with backoff for a given retry count.
|
|
pub fn timeout_with_backoff(&self, retry_count: usize) -> Duration {
|
|
let multiplier = self.retry_backoff_factor.powi(retry_count as i32);
|
|
Duration::from_secs_f64(self.default_timeout.as_secs_f64() * multiplier)
|
|
}
|
|
}
|
|
|
|
// ============================================================================
|
|
// Deadlock Detection Configuration
|
|
// ============================================================================
|
|
|
|
/// Deadlock detection configuration settings.
|
|
#[derive(Debug, Clone)]
|
|
pub struct DeadlockDetectionSettings {
|
|
/// Whether detection is enabled.
|
|
pub enabled: bool,
|
|
/// Detection interval.
|
|
pub detection_interval: Duration,
|
|
/// Maximum lock hold time before warning.
|
|
pub max_hold_time: Duration,
|
|
}
|
|
|
|
impl Default for DeadlockDetectionSettings {
|
|
fn default() -> Self {
|
|
Self {
|
|
enabled: true,
|
|
detection_interval: Duration::from_secs(DEFAULT_DEADLOCK_DETECTION_INTERVAL_SECS),
|
|
max_hold_time: Duration::from_secs(30),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl DeadlockDetectionSettings {
|
|
/// Create new settings.
|
|
pub fn new() -> Self {
|
|
Self::default()
|
|
}
|
|
}
|
|
|
|
// ============================================================================
|
|
// Unified Configuration
|
|
// ============================================================================
|
|
|
|
/// Unified configuration for all I/O operations.
|
|
#[derive(Debug, Clone, Default)]
|
|
pub struct IoConfig {
|
|
/// Cache settings.
|
|
pub cache: CacheSettings,
|
|
/// I/O scheduler settings.
|
|
pub scheduler: IoSchedulerSettings,
|
|
/// Backpressure settings.
|
|
pub backpressure: BackpressureSettings,
|
|
/// Timeout settings.
|
|
pub timeout: TimeoutSettings,
|
|
/// Deadlock detection settings.
|
|
pub deadlock_detection: DeadlockDetectionSettings,
|
|
}
|
|
|
|
impl IoConfig {
|
|
/// Create new unified configuration.
|
|
pub fn new() -> Self {
|
|
Self::default()
|
|
}
|
|
|
|
/// Builder: set cache settings.
|
|
pub fn with_cache(mut self, cache: CacheSettings) -> Self {
|
|
self.cache = cache;
|
|
self
|
|
}
|
|
|
|
/// Builder: set scheduler settings.
|
|
pub fn with_scheduler(mut self, scheduler: IoSchedulerSettings) -> Self {
|
|
self.scheduler = scheduler;
|
|
self
|
|
}
|
|
|
|
/// Builder: set backpressure settings.
|
|
pub fn with_backpressure(mut self, backpressure: BackpressureSettings) -> Self {
|
|
self.backpressure = backpressure;
|
|
self
|
|
}
|
|
|
|
/// Builder: set timeout settings.
|
|
pub fn with_timeout(mut self, timeout: TimeoutSettings) -> Self {
|
|
self.timeout = timeout;
|
|
self
|
|
}
|
|
}
|
|
|
|
#[cfg(test)]
|
|
mod tests {
|
|
use super::*;
|
|
|
|
#[test]
|
|
fn test_cache_settings() {
|
|
let settings = CacheSettings::new()
|
|
.with_max_capacity(5000)
|
|
.with_ttl(Duration::from_secs(600));
|
|
|
|
assert_eq!(settings.max_capacity, 5000);
|
|
assert_eq!(settings.default_ttl, Duration::from_secs(600));
|
|
}
|
|
|
|
#[test]
|
|
fn test_io_scheduler_settings() {
|
|
let settings =
|
|
IoSchedulerSettings::new()
|
|
.with_max_concurrent_reads(64)
|
|
.with_buffer_sizes(256 * 1024, 8 * 1024, 2 * 1024 * 1024);
|
|
|
|
assert_eq!(settings.max_concurrent_reads, 64);
|
|
assert_eq!(settings.base_buffer_size, 256 * 1024);
|
|
}
|
|
|
|
#[test]
|
|
fn test_backpressure_settings() {
|
|
let settings = BackpressureSettings::new();
|
|
|
|
assert_eq!(settings.high_threshold(100), 80);
|
|
assert_eq!(settings.low_threshold(100), 50);
|
|
}
|
|
|
|
#[test]
|
|
fn test_timeout_settings() {
|
|
let settings = TimeoutSettings::new();
|
|
|
|
// First retry: 30s * 2 = 60s
|
|
let timeout1 = settings.timeout_with_backoff(1);
|
|
assert!(timeout1.as_secs() >= 60);
|
|
|
|
// Second retry: 30s * 4 = 120s
|
|
let timeout2 = settings.timeout_with_backoff(2);
|
|
assert!(timeout2.as_secs() >= 120);
|
|
}
|
|
|
|
#[test]
|
|
fn test_unified_config() {
|
|
let config = IoConfig::new()
|
|
.with_cache(CacheSettings::new().with_max_capacity(5000))
|
|
.with_scheduler(IoSchedulerSettings::new().with_max_concurrent_reads(64));
|
|
|
|
assert_eq!(config.cache.max_capacity, 5000);
|
|
assert_eq!(config.scheduler.max_concurrent_reads, 64);
|
|
}
|
|
}
|