use std::io::{self, IoSliceMut, Read, Seek};
use std::ops::Deref;
use std::path::Path;
use fs_err::File;
#[cfg(posix_fadvise_supported)]
use nix::fcntl::{PosixFadviseAdvice, posix_fadvise};
#[cfg(posix_fadvise_supported)]
fn fadvise(f: &impl std::os::unix::io::AsFd, advise: PosixFadviseAdvice) -> io::Result<()> {
Ok(posix_fadvise(f, 0, 0, advise)?)
}
pub fn clear_disk_cache(file_path: &Path) -> io::Result<()> {
#[cfg(posix_fadvise_supported)]
match File::open(file_path.to_path_buf()) {
Ok(file) => fadvise(&file, PosixFadviseAdvice::POSIX_FADV_DONTNEED),
Err(e) if e.kind() == io::ErrorKind::NotFound => Ok(()),
Err(e) => Err(e),
}
#[cfg(not(posix_fadvise_supported))]
{
let _ = file_path;
Ok(())
}
}
pub struct OneshotFile {
file: Option<File>,
}
impl OneshotFile {
pub fn open(path: impl AsRef<Path>) -> io::Result<Self> {
let file = File::open(path.as_ref().to_path_buf())?;
#[cfg(posix_fadvise_supported)]
{
fadvise(&file, PosixFadviseAdvice::POSIX_FADV_SEQUENTIAL)?;
fadvise(&file, PosixFadviseAdvice::POSIX_FADV_NOREUSE)?;
}
Ok(Self { file: Some(file) })
}
pub fn drop_cache(mut self) -> io::Result<()> {
let file = self.file.take().unwrap();
#[cfg(posix_fadvise_supported)]
fadvise(&file, PosixFadviseAdvice::POSIX_FADV_DONTNEED)?;
let _ = file;
Ok(())
}
}
impl Deref for OneshotFile {
type Target = File;
fn deref(&self) -> &Self::Target {
self.file.as_ref().unwrap()
}
}
impl Read for OneshotFile {
fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
self.file.as_ref().unwrap().read(buf)
}
fn read_vectored(&mut self, bufs: &mut [IoSliceMut<'_>]) -> io::Result<usize> {
self.file.as_ref().unwrap().read_vectored(bufs)
}
fn read_to_end(&mut self, buf: &mut Vec<u8>) -> io::Result<usize> {
self.file.as_ref().unwrap().read_to_end(buf)
}
fn read_to_string(&mut self, buf: &mut String) -> io::Result<usize> {
self.file.as_ref().unwrap().read_to_string(buf)
}
}
impl Seek for OneshotFile {
fn seek(&mut self, pos: std::io::SeekFrom) -> io::Result<u64> {
self.file.as_ref().unwrap().seek(pos)
}
}
impl Drop for OneshotFile {
fn drop(&mut self) {
if let Some(file) = self.file.take() {
#[cfg(posix_fadvise_supported)]
let _ = fadvise(&file, PosixFadviseAdvice::POSIX_FADV_DONTNEED);
let _ = file;
}
}
}