use crate::storage::unified_memory::CompressionType;
use std::path::PathBuf;
use std::time::{Duration, Instant};
#[derive(Debug, Clone)]
pub struct HybridConfig {
pub hot_tier: TierConfig,
pub warm_tier: TierConfig,
pub cold_tier: TierConfig,
pub analysis_window: Duration,
pub promotion_threshold: f64,
pub demotion_threshold: Duration,
pub enable_auto_tiering: bool,
pub tiering_interval: Duration,
pub enable_cold_compression: bool,
pub max_hot_memory: usize,
pub enable_deduplication: bool,
}
impl Default for HybridConfig {
fn default() -> Self {
Self {
hot_tier: TierConfig {
name: "hot".to_string(),
storage_type: TierStorageType::InMemory,
max_size: 512 * 1024 * 1024, compression: CompressionType::None,
access_latency: Duration::from_micros(1),
throughput_mbps: 10000.0,
directory: None,
durable_writes: false,
},
warm_tier: TierConfig {
name: "warm".to_string(),
storage_type: TierStorageType::SSD,
max_size: 10 * 1024 * 1024 * 1024, compression: CompressionType::Lz4,
access_latency: Duration::from_millis(1),
throughput_mbps: 500.0,
directory: None,
durable_writes: false,
},
cold_tier: TierConfig {
name: "cold".to_string(),
storage_type: TierStorageType::HDD,
max_size: 1024 * 1024 * 1024 * 1024, compression: CompressionType::Zstd,
access_latency: Duration::from_millis(10),
throughput_mbps: 100.0,
directory: None,
durable_writes: false,
},
analysis_window: Duration::from_secs(3600),
promotion_threshold: 10.0,
demotion_threshold: Duration::from_secs(24 * 3600),
enable_auto_tiering: true,
tiering_interval: Duration::from_secs(5 * 60),
enable_cold_compression: true,
max_hot_memory: 1024 * 1024 * 1024,
enable_deduplication: true,
}
}
}
impl HybridConfig {
pub fn normalized(mut self) -> Self {
if !self.enable_cold_compression {
self.cold_tier.compression = CompressionType::None;
}
if self.hot_tier.max_size > self.max_hot_memory {
self.hot_tier.max_size = self.max_hot_memory;
}
self
}
}
#[derive(Debug, Clone)]
pub struct TierConfig {
pub name: String,
pub storage_type: TierStorageType,
pub max_size: usize,
pub compression: CompressionType,
pub access_latency: Duration,
pub throughput_mbps: f64,
pub directory: Option<PathBuf>,
pub durable_writes: bool,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum TierStorageType {
InMemory,
SSD,
HDD,
Network,
Custom,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub enum DataTier {
Hot,
Warm,
Cold,
}
#[derive(Debug, Clone)]
pub struct AccessPattern {
pub access_count: u64,
pub last_access: Instant,
pub first_access: Instant,
pub access_frequency: f64,
pub data_size: usize,
pub pattern_type: AccessPatternType,
}
impl AccessPattern {
pub fn new(data_size: usize) -> Self {
let now = Instant::now();
Self {
access_count: 1,
last_access: now,
first_access: now,
access_frequency: 0.0,
data_size,
pattern_type: AccessPatternType::Unknown,
}
}
pub fn record_access(&mut self) {
self.access_count += 1;
self.last_access = Instant::now();
let time_since_first = self.last_access.duration_since(self.first_access);
if time_since_first.as_secs() > 0 {
self.access_frequency =
self.access_count as f64 / (time_since_first.as_secs_f64() / 3600.0);
}
self.pattern_type = if self.access_frequency > 100.0 {
AccessPatternType::VeryHot
} else if self.access_frequency > 10.0 {
AccessPatternType::Hot
} else if self.access_frequency > 1.0 {
AccessPatternType::Warm
} else {
AccessPatternType::Cold
};
}
pub fn time_since_last_access(&self) -> Duration {
Instant::now().duration_since(self.last_access)
}
pub fn should_promote(&self, threshold: f64) -> bool {
self.access_frequency > threshold
}
pub fn should_demote(&self, threshold: Duration) -> bool {
self.time_since_last_access() > threshold
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum AccessPatternType {
VeryHot,
Hot,
Warm,
Cold,
Unknown,
}
#[derive(Debug, Clone)]
pub struct TieredDataMetadata {
pub created_at: Instant,
pub original_size: usize,
pub compressed_size: usize,
pub checksum: u64,
pub tier_history: Vec<TierHistoryEntry>,
}
#[derive(Debug, Clone)]
pub struct TierHistoryEntry {
pub tier: DataTier,
pub timestamp: Instant,
pub reason: TierMoveReason,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum TierMoveReason {
HighFrequency,
LowFrequency,
CapacityPressure,
InitialPlacement,
Manual,
}
#[derive(Debug, Clone)]
pub struct CompressionState {
pub algorithm: CompressionType,
pub ratio: f64,
pub processing_time: Duration,
}
#[derive(Debug, Clone)]
pub struct TierStatistics {
pub current_usage: usize,
pub max_capacity: usize,
pub chunk_count: u64,
pub total_accesses: u64,
pub total_access_nanos: u64,
pub hits: u64,
pub misses: u64,
pub promotions: u64,
pub demotions: u64,
}
impl TierStatistics {
pub fn new(max_capacity: usize) -> Self {
Self {
current_usage: 0,
max_capacity,
chunk_count: 0,
total_accesses: 0,
total_access_nanos: 0,
hits: 0,
misses: 0,
promotions: 0,
demotions: 0,
}
}
pub fn utilization(&self) -> f64 {
if self.max_capacity == 0 {
0.0
} else {
self.current_usage as f64 / self.max_capacity as f64
}
}
pub fn available_space(&self) -> usize {
self.max_capacity.saturating_sub(self.current_usage)
}
pub fn avg_access_latency(&self) -> Duration {
if self.total_accesses == 0 {
Duration::ZERO
} else {
Duration::from_nanos(self.total_access_nanos / self.total_accesses)
}
}
pub fn hit_rate(&self) -> f64 {
let total = self.hits + self.misses;
if total == 0 {
0.0
} else {
self.hits as f64 / total as f64
}
}
}
#[derive(Debug, Clone)]
pub struct TieringReport {
pub promotions: u64,
pub demotions: u64,
pub bytes_moved: usize,
pub duration: Duration,
}
#[derive(Debug)]
pub struct TieringScheduler {
interval: Duration,
last_run: Instant,
}
impl TieringScheduler {
pub fn new(interval: Duration) -> Self {
Self {
interval,
last_run: Instant::now(),
}
}
pub fn should_run(&self) -> bool {
self.last_run.elapsed() >= self.interval
}
pub fn mark_run(&mut self) {
self.last_run = Instant::now();
}
}