use std::any::Any;
use std::io::Result;
use crate::device::BlobChunkInfo;
use crate::StorageResult;
pub use blob_state_map::BlobStateMap;
pub use digested_chunk_map::DigestedChunkMap;
pub use indexed_chunk_map::IndexedChunkMap;
pub use noop_chunk_map::NoopChunkMap;
pub use range_map::BlobRangeMap;
mod blob_state_map;
mod digested_chunk_map;
mod indexed_chunk_map;
mod noop_chunk_map;
mod persist_map;
mod range_map;
pub trait ChunkMap: Any + Send + Sync {
fn is_ready(&self, chunk: &dyn BlobChunkInfo) -> Result<bool>;
fn is_pending(&self, _chunk: &dyn BlobChunkInfo) -> Result<bool> {
Ok(false)
}
fn is_ready_or_pending(&self, chunk: &dyn BlobChunkInfo) -> Result<bool> {
if matches!(self.is_pending(chunk), Ok(true)) {
Ok(true)
} else {
self.is_ready(chunk)
}
}
fn check_ready_and_mark_pending(&self, _chunk: &dyn BlobChunkInfo) -> StorageResult<bool> {
panic!("no support of check_ready_and_mark_pending()");
}
fn set_ready_and_clear_pending(&self, _chunk: &dyn BlobChunkInfo) -> Result<()> {
panic!("no support of check_ready_and_mark_pending()");
}
fn clear_pending(&self, _chunk: &dyn BlobChunkInfo) {
panic!("no support of clear_pending()");
}
fn is_persist(&self) -> bool {
false
}
fn as_range_map(&self) -> Option<&dyn RangeMap<I = u32>> {
None
}
}
pub trait RangeMap: Send + Sync {
type I: Send + Sync;
fn is_range_all_ready(&self) -> bool {
false
}
fn is_range_ready(&self, _start: Self::I, _count: Self::I) -> Result<bool> {
Err(enosys!())
}
fn check_range_ready_and_mark_pending(
&self,
_start: Self::I,
_count: Self::I,
) -> Result<Option<Vec<Self::I>>> {
Err(enosys!())
}
fn set_range_ready_and_clear_pending(&self, _start: Self::I, _count: Self::I) -> Result<()> {
Err(enosys!())
}
fn clear_range_pending(&self, _start: Self::I, _count: Self::I) {}
fn wait_for_range_ready(&self, _start: Self::I, _count: Self::I) -> Result<bool> {
Err(enosys!())
}
}
pub trait ChunkIndexGetter {
type Index;
fn get_index(chunk: &dyn BlobChunkInfo) -> Self::Index;
}
#[cfg(test)]
mod tests {
use crate::test::MockChunkInfo;
use super::*;
impl RangeMap for NoopChunkMap {
type I = u32;
}
#[test]
fn test_trait_default_impl() {
let m = NoopChunkMap::new(false);
let chunk_info = MockChunkInfo {
index: 128,
..Default::default()
};
assert!(m.is_pending(&chunk_info).is_ok());
assert!(!m.is_pending(&chunk_info).unwrap());
assert!(!m.is_range_all_ready());
assert!(m.is_range_ready(0, 1).is_err());
assert!(m.check_range_ready_and_mark_pending(0, 1).is_err());
assert!(m.set_range_ready_and_clear_pending(0, 1).is_err());
m.clear_range_pending(0, 1);
assert!(m.wait_for_range_ready(0, 1).is_err());
assert!(m.as_range_map().is_none());
assert!(!m.is_persist());
assert!(!m.is_ready(&chunk_info).unwrap());
}
#[test]
#[should_panic]
fn test_check_ready_and_mark_pending_default_impl() {
let chunk_info = MockChunkInfo::default();
let m = NoopChunkMap::new(false);
m.check_ready_and_mark_pending(&chunk_info).unwrap();
}
#[test]
#[should_panic]
fn test_set_ready_and_clear_pending_default_impl() {
let chunk_info = MockChunkInfo::default();
let m = NoopChunkMap::new(false);
m.set_ready_and_clear_pending(&chunk_info).unwrap();
}
}