use std::borrow::Cow;
use std::fmt::Debug;
use crate::common::universal_io::UniversalRead;
use crate::segment::common::operation_error::{OperationError, OperationResult};
pub(super) trait GraphLinksStorage: Debug + Send + Sync {
fn bytes(&self) -> OperationResult<&[u8]>;
fn populate(&self) -> OperationResult<()>;
fn clear_cache(&self) -> OperationResult<()>;
}
impl<S: UniversalRead> GraphLinksStorage for S {
fn bytes(&self) -> OperationResult<&[u8]> {
match self.read_whole::<u8>()? {
Cow::Borrowed(bytes) => Ok(bytes),
Cow::Owned(_) => Err(OperationError::service_error(
"Universal graph links storage must be borrowable (mmap-backed)",
)),
}
}
fn populate(&self) -> OperationResult<()> {
UniversalRead::populate(self)?;
Ok(())
}
fn clear_cache(&self) -> OperationResult<()> {
self.clear_ram_cache()?;
Ok(())
}
}
#[derive(Debug)]
pub(super) enum GraphLinksEnum {
Ram(Vec<u8>),
Universal(Box<dyn GraphLinksStorage>),
}
impl GraphLinksEnum {
pub(super) fn from_storage<S: UniversalRead + 'static>(storage: S) -> OperationResult<Self> {
if S::kind().is_in_ram_or_mmap() {
Ok(GraphLinksEnum::Universal(Box::new(storage)))
} else {
Self::pinned_from_storage(storage)
}
}
pub(super) fn pinned_from_storage<S: UniversalRead>(storage: S) -> OperationResult<Self> {
let bytes = storage.read_whole::<u8>()?.into_owned();
storage.clear_ram_cache()?;
Ok(GraphLinksEnum::Ram(bytes))
}
pub(super) fn as_bytes(&self) -> OperationResult<&[u8]> {
match self {
GraphLinksEnum::Ram(data) => Ok(data.as_slice()),
GraphLinksEnum::Universal(storage) => storage.bytes(),
}
}
pub(super) fn heap_size_bytes(&self) -> usize {
match self {
GraphLinksEnum::Ram(data) => data.len(),
GraphLinksEnum::Universal(_) => 0,
}
}
pub(super) fn populate(&self) -> OperationResult<()> {
match self {
GraphLinksEnum::Universal(storage) => storage.populate(),
GraphLinksEnum::Ram(_) => Ok(()),
}
}
pub(super) fn clear_cache(&self) -> OperationResult<()> {
match self {
GraphLinksEnum::Universal(storage) => storage.clear_cache(),
GraphLinksEnum::Ram(_) => Ok(()),
}
}
}