use std::fmt;
use std::ops::Deref;
use std::path::Path;
use crate::common::mmap::{Advice, AdviceSetting};
use crate::common::universal_io::{
CachedReadFs, OpenOptions, Populate, UioResult, UniversalRead, UniversalReadFs,
};
pub struct OneshotFile<S: UniversalRead> {
inner: S,
}
impl<S: UniversalRead> OneshotFile<S> {
fn open_options(populate: Populate) -> OpenOptions {
OpenOptions {
writeable: false,
need_sequential: true,
populate,
advice: AdviceSetting::Advice(Advice::Sequential),
}
}
pub fn preopen<Fs: CachedReadFs<File = S>>(fs: &Fs, path: impl AsRef<Path>) -> UioResult<()> {
fs.schedule_prefetch(
path.as_ref(),
Some(Self::open_options(Populate::PreferBackground)),
None,
)
}
pub fn open<Fs: UniversalReadFs<File = S>>(fs: &Fs, path: impl AsRef<Path>) -> UioResult<Self> {
let inner = fs.open(path, Self::open_options(Populate::No), Default::default())?;
Ok(Self { inner })
}
pub fn new(inner: S) -> Self {
Self { inner }
}
}
impl<S: UniversalRead> Deref for OneshotFile<S> {
type Target = S;
fn deref(&self) -> &S {
&self.inner
}
}
impl<S: UniversalRead> fmt::Debug for OneshotFile<S> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
let Self { inner } = self;
f.debug_struct("OneshotFile").field("inner", inner).finish()
}
}
impl<S: UniversalRead> Drop for OneshotFile<S> {
fn drop(&mut self) {
if let Err(err) = self.inner.clear_ram_cache() {
log::warn!("Failed to clear RAM cache for one-shot file: {err}");
}
}
}