use std::sync::Arc;
use std::fmt::Debug;
use std::ops::Deref;
use std::hash::Hash;
use std::io::Result;
use std::time::Duration;
use futures::future::BoxFuture;
use url::Url;
use dashmap::DashMap;
pub mod simple_device;
pub const EMPTY_BLOCK: u64 = 0;
pub const EMPTY_BLOCK_LOCATION: BlockLocation = BlockLocation(EMPTY_BLOCK);
pub enum DeviceType<D: DeviceDetail> {
VM(D), NVM(D), HDD(D), SSD(D), Disk(D), }
unsafe impl<D: DeviceDetail> Send for DeviceType<D> {}
unsafe impl<D: DeviceDetail> Sync for DeviceType<D> {}
pub trait DeviceDetail: Send + Sync + 'static {
type Key: Debug + Clone + Hash + Eq + Send + Sync + 'static;
type Val: Debug + Clone + Hash + Eq + Send + Sync + 'static;
fn get(&self, key: &Self::Key) -> Option<Self::Val>;
}
#[derive(Debug, Clone, Hash)]
pub enum DeviceValueType {
Integer(i128), Str(String), }
unsafe impl Send for DeviceValueType {}
unsafe impl Sync for DeviceValueType {}
impl Eq for DeviceValueType {}
impl PartialEq for DeviceValueType {
fn eq(&self, other: &Self) -> bool {
match self {
DeviceValueType::Integer(x) => {
match other {
DeviceValueType::Integer(y) => {
x.to_string().eq(&y.to_string())
},
DeviceValueType::Str(y) => {
x.to_string().eq(y)
}
}
},
DeviceValueType::Str(x) => {
match other {
DeviceValueType::Integer(y) => {
x.eq(&y.to_string())
},
DeviceValueType::Str(y) => {
x.eq(y)
}
}
},
}
}
}
pub struct DeviceDetailMap {
inner: Arc<DashMap<DeviceValueType, DeviceValueType>>, }
unsafe impl Send for DeviceDetailMap {}
unsafe impl Sync for DeviceDetailMap {}
impl DeviceDetail for DeviceDetailMap {
type Key = DeviceValueType;
type Val = DeviceValueType;
fn get(&self, key: &Self::Key) -> Option<Self::Val> {
if let Some(val) = self.inner.get(&key) {
Some(val.value().clone())
} else {
None
}
}
}
impl DeviceDetailMap {
pub fn new() -> Self {
DeviceDetailMap {
inner: Arc::new(DashMap::new()),
}
}
}
#[derive(Debug, Clone, Hash)]
pub enum DeviceStatus {
Inited = 0, Running, Busy, Pended, Closing, Closed, }
unsafe impl Send for DeviceStatus {}
unsafe impl Sync for DeviceStatus {}
impl From<u8> for DeviceStatus {
fn from(src: u8) -> Self {
match src {
0 => DeviceStatus::Inited,
1 => DeviceStatus::Running,
2 => DeviceStatus::Busy,
3 => DeviceStatus::Pended,
4 => DeviceStatus::Closing,
_ => DeviceStatus::Closed,
}
}
}
impl From<DeviceStatus> for u8 {
fn from(value: DeviceStatus) -> Self {
match value {
DeviceStatus::Inited => 0,
DeviceStatus::Running => 1,
DeviceStatus::Busy => 2,
DeviceStatus::Pended => 3,
DeviceStatus::Closing => 4,
DeviceStatus::Closed => 5,
}
}
}
pub struct DeviceStatistics {
alloc_blocks: u128, alloc_bytes: u128, free_blocks: u128, free_bytes: u128, blocks_in: u128, blocks_out: u128, bytes_in: u128, bytes_out: u128, time: u128, slow_alloc_count: Option<u64>, slow_free_count: Option<u64>, slow_in_count: Option<u64>, slow_out_count: Option<u64>, min_alloc_bytes: Option<u64>, max_alloc_bytes: Option<u64>, min_alloc_time: Option<u64>, max_alloc_time: Option<u64>, min_free_time: Option<u64>, max_free_time: Option<u64>, min_in_time: Option<u64>, max_in_time: Option<u64>, min_out_time: Option<u64>, max_out_time: Option<u64>, soft_faults: Option<u64>, hard_faults: Option<u64>, }
impl DeviceStatistics {
pub fn new(alloc_blocks: u128,
alloc_bytes: u128,
free_blocks: u128,
free_bytes: u128,
blocks_in: u128,
blocks_out: u128,
bytes_in: u128,
bytes_out: u128,
time: u128) -> Self {
DeviceStatistics {
alloc_blocks,
alloc_bytes,
free_blocks,
free_bytes,
blocks_in,
blocks_out,
bytes_in,
bytes_out,
time,
slow_alloc_count: None,
slow_free_count: None,
slow_in_count: None,
slow_out_count: None,
min_alloc_bytes: None,
max_alloc_bytes: None,
min_alloc_time: None,
max_alloc_time: None,
min_free_time: None,
max_free_time: None,
min_in_time: None,
max_in_time: None,
min_out_time: None,
max_out_time: None,
soft_faults: None,
hard_faults: None,
}
}
}
pub trait BlockDevice: Send + Sync + 'static {
type Uid: Debug + Clone + Hash + Ord + Send + Sync + 'static;
type Status: Debug + Clone + Hash + Send + Sync + 'static;
type DetailKey: Debug + Clone + Hash + Eq + Send + Sync + 'static;
type DetailVal: Debug + Clone + Hash + Eq + Send + Sync + 'static;
type Detail: DeviceDetail<Key = Self::DetailKey, Val = Self::DetailVal>;
type Buf: AsRef<[u8]> + Clone + Send + Sync + 'static;
fn is_full_free(&self) -> bool;
fn is_local(&self) -> bool;
fn is_persistent(&self) -> bool;
fn is_security(&self) -> bool;
fn is_safety(&self) -> bool;
fn enable_compression(&self) -> bool;
fn is_require_collect(&self) -> bool;
fn is_freed(&self, location: &BlockLocation) -> bool;
fn capacity(&self) -> Option<u64>;
fn avail_size(&self) -> Option<u64>;
fn used_size(&self) -> u64;
fn block_unit_len(&self) -> usize;
fn max_block_size(&self) -> usize;
fn block_size(&self, location: &BlockLocation) -> usize;
fn get_url(&self) -> Option<Url>;
fn get_uid(&self) -> Option<Self::Uid>;
fn get_info(&self) -> DeviceType<Self::Detail>;
fn get_status(&self) -> Self::Status;
fn statistics(&self) -> Option<DeviceStatistics>;
fn alloc_block(&self, size: usize) -> BoxFuture<BlockLocation>;
fn read(&self, location: &BlockLocation) -> BoxFuture<Result<Self::Buf>>;
fn write(&self,
location: &BlockLocation,
buf: &Self::Buf,
option: WriteOption) -> BoxFuture<Result<usize>>;
fn free_block(&self, location: &BlockLocation) -> BoxFuture<bool>;
fn collect_alloced_blocks(&self, alloced: &[BlockLocation]) -> BoxFuture<Result<usize>>;
fn blocks_iter(&self)
-> BoxFuture<Option<Box<dyn DoubleEndedIterator<Item = BlockLocation>>>>;
fn commit_round(&self) -> u64;
fn on_commit(&self) -> BoxFuture<Result<Box<dyn CommitEvent>>>;
}
#[derive(Debug, Clone, Copy)]
pub enum WriteOption {
None, Sync, SyncAll, }
pub trait CommitEvent {
fn is_commiting(&self) -> bool;
fn is_commited(&self) -> bool;
fn round(&self) -> u64;
fn time(&self) -> Duration;
fn result(&self) -> Option<&Result<()>>;
}
#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord)]
pub struct BlockLocation(u64);
unsafe impl Send for BlockLocation {}
unsafe impl Sync for BlockLocation {}
impl From<u64> for BlockLocation {
fn from(src: u64) -> Self {
BlockLocation::new(src)
}
}
impl From<BlockLocation> for u64 {
fn from(BlockLocation(locaction): BlockLocation) -> Self {
locaction
}
}
impl Deref for BlockLocation {
type Target = u64;
fn deref(&self) -> &Self::Target {
&self.0
}
}
impl AsRef<u64> for BlockLocation {
fn as_ref(&self) -> &u64 {
&self.0
}
}
impl BlockLocation {
#[inline]
pub(crate) fn new(location: u64) -> Self {
BlockLocation(location)
}
#[inline]
pub fn empty() -> Self {
BlockLocation(EMPTY_BLOCK)
}
#[inline]
pub fn is_empty(&self) -> bool {
self.0 == 0
}
}