use std::error::Error;
use std::collections::HashMap;
use std::sync::Arc;
use tokio::sync::{RwLock, Mutex};
use serde::{Serialize, Deserialize};
#[derive(Debug, Clone)]
pub struct AdaptiveReplicationManager {
config: ReplicationConfig,
data_states: Arc<RwLock<HashMap<String, DataReplicationState>>>,
resource_tracker: Arc<Mutex<HardwareResourceTracker>>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct ReplicationConfig {
pub max_replicas: usize,
pub min_critical_replicas: usize,
pub pruning_strategy: PruningStrategy,
pub state_preservation_rules: StatePreservationRules,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub enum PruningStrategy {
TimeBased {
max_data_age_seconds: u64,
},
SizeBased {
max_storage_bytes: u64,
},
Adaptive {
max_data_age_seconds: u64,
max_storage_bytes: u64,
usage_frequency_weight: f64,
},
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct StatePreservationRules {
pub preserve_critical_data: bool,
pub min_state_retention_seconds: u64,
pub compression_strategy: CompressionStrategy,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub enum CompressionStrategy {
None,
Light,
Aggressive,
}
#[derive(Debug, Clone)]
struct DataReplicationState {
id: String,
replica_count: usize,
last_accessed: std::time::SystemTime,
criticality: DataCriticality,
preservation_status: PreservationStatus,
}
#[derive(Debug, Clone, PartialEq)]
enum DataCriticality {
Critical,
High,
Medium,
Low,
}
#[derive(Debug, Clone)]
enum PreservationStatus {
FullyPreserved,
Compressed,
Prunable,
}
impl AdaptiveReplicationManager {
pub fn new(config: ReplicationConfig) -> Self {
Self {
config,
data_states: Arc::new(RwLock::new(HashMap::new())),
resource_tracker: Arc::new(Mutex::new(HardwareResourceTracker::new())),
}
}
pub async fn determine_replication_strategy(&self, data_id: &str) -> Result<ReplicationAction, String> {
let resources = self.resource_tracker.lock().await;
let mut data_states = self.data_states.write().await;
let data_state = data_states.entry(data_id.to_string())
.or_insert(DataReplicationState {
id: data_id.to_string(),
replica_count: 0,
last_accessed: std::time::SystemTime::now(),
criticality: DataCriticality::Medium,
preservation_status: PreservationStatus::FullyPreserved,
});
let action = match self.config.pruning_strategy {
PruningStrategy::Adaptive {
max_data_age_seconds,
max_storage_bytes,
usage_frequency_weight
} => {
if resources.available_storage() > max_storage_bytes {
ReplicationAction::Replicate
} else if self.is_data_old_and_unused(data_state, max_data_age_seconds, usage_frequency_weight) {
ReplicationAction::Prune
} else {
ReplicationAction::Compress
}
},
PruningStrategy::TimeBased { max_data_age_seconds } => {
if self.is_data_old(data_state, max_data_age_seconds) {
ReplicationAction::Prune
} else {
ReplicationAction::Maintain
}
},
PruningStrategy::SizeBased { max_storage_bytes } => {
if resources.available_storage() > max_storage_bytes {
ReplicationAction::Prune
} else {
ReplicationAction::Maintain
}
},
};
Ok(action)
}
fn is_data_old_and_unused(&self,
data_state: &DataReplicationState,
max_age: u64,
usage_weight: f64
) -> bool {
let age = std::time::SystemTime::now()
.duration_since(data_state.last_accessed)
.map(|d| d.as_secs())
.unwrap_or(0);
age > max_age && (data_state.replica_count as f64 * usage_weight) < 1.0
}
fn is_data_old(&self,
data_state: &DataReplicationState,
max_age: u64
) -> bool {
std::time::SystemTime::now()
.duration_since(data_state.last_accessed)
.map(|d| d.as_secs() > max_age)
.unwrap_or(false)
}
}
#[derive(Debug)]
enum ReplicationAction {
Replicate,
Prune,
Compress,
Maintain,
}
#[derive(Debug)]
struct HardwareResourceTracker {
total_storage: u64,
used_storage: u64,
available_ram: u64,
cpu_cores: usize,
}
impl HardwareResourceTracker {
fn new() -> Self {
Self {
total_storage: 1_000_000_000_000, used_storage: 0,
available_ram: 32_000_000_000, cpu_cores: 8,
}
}
fn available_storage(&self) -> u64 {
self.total_storage - self.used_storage
}
}
impl AdaptiveReplicationManager {
pub fn default_config() -> ReplicationConfig {
ReplicationConfig {
max_replicas: 5,
min_critical_replicas: 3,
pruning_strategy: PruningStrategy::Adaptive {
max_data_age_seconds: 30 * 24 * 60 * 60, max_storage_bytes: 500_000_000_000, usage_frequency_weight: 0.7,
},
state_preservation_rules: StatePreservationRules {
preserve_critical_data: true,
min_state_retention_seconds: 7 * 24 * 60 * 60, compression_strategy: CompressionStrategy::Light,
},
}
}
}