use std::ops::Range;
use std::path::{Path, PathBuf};
use std::sync::atomic::AtomicBool;
use parking_lot::Mutex;
use super::DiskCacheRemote;
use super::local_state::LocalState;
use crate::common::universal_io::simple_disk_cache::REMOTE_OPEN_OPTIONS;
use crate::common::universal_io::{OpenOptions, OwnedPipeline, UioResult, UniversalRead, UniversalReadFs};
mod init;
mod read;
mod reopen;
#[derive(Debug)]
pub struct DiskCache<R>
where
R: UniversalRead + 'static,
{
remote_fs: R::Fs,
remote_extra: <R::Fs as UniversalReadFs>::OpenExtra,
remote_path: PathBuf,
pub(super) open_options: OpenOptions,
pub(super) local_path: PathBuf,
pub(super) state: Mutex<State<R>>,
pub(super) is_ready: AtomicBool,
}
#[derive(Debug)]
pub(crate) enum State<R: UniversalRead + 'static> {
Uninit,
Ready {
remote: R,
local: LocalState,
scheduled_reopen: ScheduledReopen<R>,
},
OpenPrefill { pipeline: OwnedPipeline<R, ()> },
PartialPrefill {
pipeline: OwnedPipeline<R, Range<u32>>,
len: u64,
},
}
#[derive(Debug)]
pub(crate) enum ScheduledReopen<R: UniversalRead + 'static> {
No,
Resize { target_len: u64 },
Tail {
pipeline: OwnedPipeline<R, Range<u32>>,
target_len: u64,
},
}
impl<R: UniversalRead + 'static> ScheduledReopen<R> {
pub(super) fn target_len(&self) -> Option<u64> {
match self {
ScheduledReopen::No => None,
ScheduledReopen::Resize { target_len }
| ScheduledReopen::Tail {
target_len,
pipeline: _,
} => Some(*target_len),
}
}
}
impl<R: UniversalRead + 'static> State<R> {
pub fn ready(remote: R, local: LocalState) -> Self {
State::Ready {
remote,
local,
scheduled_reopen: ScheduledReopen::No,
}
}
#[inline]
pub fn is_ready(&self) -> bool {
match self {
State::Ready { .. } => true,
State::Uninit | State::OpenPrefill { .. } | State::PartialPrefill { .. } => false,
}
}
#[inline]
pub fn is_uninit(&self) -> bool {
match self {
State::Uninit => true,
State::Ready { .. } | State::OpenPrefill { .. } | State::PartialPrefill { .. } => false,
}
}
}
impl<R> DiskCache<R>
where
R: DiskCacheRemote,
{
pub(super) fn new(
remote_fs: R::Fs,
remote_extra: <R::Fs as UniversalReadFs>::OpenExtra,
remote_path: impl AsRef<Path>,
local_path: PathBuf,
options: OpenOptions,
state: State<R>,
) -> Self {
let is_ready = state.is_ready();
Self {
remote_fs,
remote_extra,
remote_path: remote_path.as_ref().to_owned(),
open_options: options,
local_path,
state: Mutex::new(state),
is_ready: AtomicBool::new(is_ready),
}
}
pub(super) fn open_remote(&self) -> UioResult<R> {
self.remote_fs.open(
&self.remote_path,
REMOTE_OPEN_OPTIONS,
self.remote_extra.clone(),
)
}
}
impl<R> Drop for DiskCache<R>
where
R: UniversalRead + 'static,
{
fn drop(&mut self) {
let _ = fs_err::remove_file(&self.local_path);
}
}