Files
markbase/markbase-raid/src/raid/controller.rs
Warren d94cb2df4c Fix code quality: trailing whitespace, unused imports, clippy warnings
- Fix trailing whitespace in kex.rs and s3.rs
- Add missing KexProposal import in kex_complete.rs
- Auto-fix clippy warnings across all crates
- All 153 tests pass
2026-06-19 05:21:38 +08:00

135 lines
4.0 KiB
Rust

use super::{MemberStatus, RaidAlgorithm, RaidError, RaidLevel};
use std::path::PathBuf;
use std::sync::{Arc, Mutex};
#[derive(Debug, Clone)]
pub struct RaidMember {
pub device_id: String,
pub device_path: PathBuf,
pub size: u64,
pub status: MemberStatus,
}
#[derive(Debug)]
pub struct RaidArray {
pub raid_level: RaidLevel,
pub members: Vec<RaidMember>,
pub stripe_size: u64,
pub total_size: u64,
}
pub struct RaidController {
arrays: Mutex<Vec<Arc<RaidArray>>>,
}
impl Default for RaidController {
fn default() -> Self {
Self::new()
}
}
impl RaidController {
pub fn new() -> Self {
RaidController {
arrays: Mutex::new(Vec::new()),
}
}
pub fn create_array(
&self,
level: RaidLevel,
member_paths: Vec<PathBuf>,
stripe_size: u64,
) -> Result<String, RaidError> {
let members: Vec<RaidMember> = member_paths
.iter()
.enumerate()
.map(|(i, path)| {
let size = if path.exists() {
std::fs::metadata(path).unwrap().len()
} else {
0
};
RaidMember {
device_id: format!("member_{}", i),
device_path: path.clone(),
size,
status: MemberStatus::Online,
}
})
.collect();
let total_size = calculate_total_size(level, &members, stripe_size);
let array = RaidArray {
raid_level: level,
members,
stripe_size,
total_size,
};
let array_id = format!("raid_{}", chrono::Utc::now().timestamp());
let mut arrays = self.arrays.lock().unwrap();
arrays.push(Arc::new(array));
Ok(array_id)
}
pub fn get_array(&self, _array_id: &str) -> Option<Arc<RaidArray>> {
let arrays = self.arrays.lock().unwrap();
arrays.iter().find(|_a| true).cloned()
}
pub fn read(&self, array_id: &str, offset: u64, size: u64) -> Result<Vec<u8>, RaidError> {
let array = self.get_array(array_id).ok_or("RAID array not found")?;
match array.raid_level {
RaidLevel::RAID0 => {
let mut raid0 = super::level_0::Raid0::new(array.clone());
raid0.read(offset, size)
}
RaidLevel::RAID1 => {
let mut raid1 = super::level_1::Raid1::new(array.clone());
raid1.read(offset, size)
}
RaidLevel::RAID5 => {
let mut raid5 = super::level_5::Raid5::new(array.clone())?;
raid5.read(offset, size)
}
_ => Err("RAID level not implemented yet".into()),
}
}
pub fn write(&self, array_id: &str, offset: u64, data: &[u8]) -> Result<(), RaidError> {
let array = self.get_array(array_id).ok_or("RAID array not found")?;
match array.raid_level {
RaidLevel::RAID0 => {
let mut raid0 = super::level_0::Raid0::new(array.clone());
raid0.write(offset, data)
}
RaidLevel::RAID1 => {
let mut raid1 = super::level_1::Raid1::new(array.clone());
raid1.write(offset, data)
}
RaidLevel::RAID5 => {
let mut raid5 = super::level_5::Raid5::new(array.clone())?;
raid5.write(offset, data)
}
_ => Err("RAID level not implemented yet".into()),
}
}
}
fn calculate_total_size(level: RaidLevel, members: &[RaidMember], _stripe_size: u64) -> u64 {
match level {
RaidLevel::RAID0 => members.iter().map(|m| m.size).sum(),
RaidLevel::RAID1 => members.iter().map(|m| m.size).min().unwrap_or(0),
RaidLevel::RAID5 => {
let min_size = members.iter().map(|m| m.size).min().unwrap_or(0);
min_size * (members.len() - 1) as u64
}
_ => 0,
}
}