mod config;
mod file;
mod fs;
mod local_state;
pub mod pipeline;
#[cfg(test)]
mod tests;
use std::ops::Range;
pub use config::DiskCacheConfig;
pub use file::DiskCache;
pub use fs::{DiskCacheFs, DiskCacheFsContext};
use crate::common::mmap::AdviceSetting;
use crate::common::universal_io::{OpenOptions, Populate, UniversalRead, UniversalReadFs};
pub trait DiskCacheRemote:
UniversalRead<
Fs: Clone + Send + Sync + UniversalReadFs<OpenExtra: Clone + Send + Sync>,
ReadPipeline<'static, ()>: Send,
ReadPipeline<'static, Range<u32>>: Send,
> + 'static
{
}
impl<R> DiskCacheRemote for R
where
R: UniversalRead + 'static,
R::Fs: Clone + Send + Sync,
<R::Fs as UniversalReadFs>::OpenExtra: Clone + Send + Sync,
R::ReadPipeline<'static, ()>: Send,
R::ReadPipeline<'static, Range<u32>>: Send,
{
}
const BLOCK_SIZE: usize = 16 * 1024;
const REMOTE_OPEN_OPTIONS: OpenOptions = OpenOptions {
writeable: false,
populate: Populate::No,
need_sequential: false,
advice: AdviceSetting::Global,
};
fn to_block_range(byte_range: Range<u64>) -> Range<u32> {
let start = (byte_range.start / BLOCK_SIZE as u64) as u32;
if byte_range.start >= byte_range.end {
return start..start;
}
let end = byte_range.end.div_ceil(BLOCK_SIZE as u64) as u32;
start..end
}
fn block_aligned_fetch(byte_range: Range<u64>, file_len: u64) -> Option<(Range<u32>, Range<u64>)> {
let blocks_range = to_block_range(byte_range);
if blocks_range.is_empty() {
return None;
}
let byte_offset = u64::from(blocks_range.start) * BLOCK_SIZE as u64;
let fetch_length = blocks_range.len() as u64 * BLOCK_SIZE as u64;
let max_length = file_len.saturating_sub(byte_offset);
let blocks_byte_range = byte_offset..byte_offset + max_length.min(fetch_length);
if blocks_byte_range.is_empty() {
return None;
}
Some((blocks_range, blocks_byte_range))
}