use super::*;
#[cfg(unix)]
use std::os::unix::fs::FileExt;
pub(crate) trait Pio {
fn pread_exact(&self, to_buf: &mut [u8], offset: LogId) -> io::Result<()>;
fn pwrite_all(&self, from_buf: &[u8], offset: LogId) -> io::Result<()>;
}
#[cfg(unix)]
impl Pio for std::fs::File {
fn pread_exact(
&self,
mut buf: &mut [u8],
mut offset: LogId,
) -> io::Result<()> {
while !buf.is_empty() {
match self.read_at(buf, offset) {
Ok(0) => break,
Ok(n) => {
offset += n as LogId;
let tmp = buf;
buf = &mut tmp[n..];
}
Err(ref e) if e.kind() == io::ErrorKind::Interrupted => {}
Err(e) => return Err(e),
}
}
if !buf.is_empty() {
Err(io::Error::new(
io::ErrorKind::UnexpectedEof,
"failed to fill whole buffer",
))
} else {
Ok(())
}
}
fn pwrite_all(&self, mut buf: &[u8], mut offset: LogId) -> io::Result<()> {
while !buf.is_empty() {
match self.write_at(buf, offset) {
Ok(0) => {
return Err(io::Error::new(
io::ErrorKind::WriteZero,
"failed to write whole buffer",
));
}
Ok(n) => {
offset += n as LogId;
buf = &buf[n..]
}
Err(ref e) if e.kind() == io::ErrorKind::Interrupted => {}
Err(e) => return Err(e),
}
}
Ok(())
}
}
#[cfg(not(unix))]
use std::{
io::{Read, Seek, Write},
sync::Mutex,
};
#[cfg(not(unix))]
lazy_static! {
pub(crate) static ref GLOBAL_FILE_LOCK: Mutex<()> = Mutex::new(());
}
#[cfg(not(unix))]
impl Pio for std::fs::File {
fn pread_exact(&self, mut buf: &mut [u8], offset: LogId) -> io::Result<()> {
let _lock = GLOBAL_FILE_LOCK.lock().unwrap();
let mut f = self.try_clone()?;
f.seek(std::io::SeekFrom::Start(offset))?;
while !buf.is_empty() {
match f.read(buf) {
Ok(0) => break,
Ok(n) => {
let tmp = buf;
buf = &mut tmp[n..];
}
Err(ref e) if e.kind() == io::ErrorKind::Interrupted => {}
Err(e) => return Err(e),
}
}
if !buf.is_empty() {
Err(io::Error::new(
io::ErrorKind::UnexpectedEof,
"failed to fill whole buffer",
))
} else {
Ok(())
}
}
fn pwrite_all(&self, mut buf: &[u8], offset: LogId) -> io::Result<()> {
let _lock = GLOBAL_FILE_LOCK.lock().unwrap();
let mut f = self.try_clone()?;
f.seek(std::io::SeekFrom::Start(offset))?;
while !buf.is_empty() {
match f.write(buf) {
Ok(0) => {
return Err(io::Error::new(
io::ErrorKind::WriteZero,
"failed to write whole buffer",
));
}
Ok(n) => buf = &buf[n..],
Err(ref e) if e.kind() == io::ErrorKind::Interrupted => {}
Err(e) => return Err(e),
}
}
Ok(())
}
}