use std::fs::{Metadata, OpenOptions, Permissions};
use std::os::unix::prelude::*;
use std::path::{Path, PathBuf};
use std::{fmt, io};
use intrusive_collections::DefaultLinkOps;
use intrusive_collections::linked_list::LinkedListOps;
use lock_api::RawMutex;
use crate::errors::AioCommandError;
use crate::fs::AioOpenOptionsExt;
use crate::{GenericAioContextHandle, LockedBuf, RawCommand, ReadFlags, WriteFlags};
pub struct File {
pub(crate) inner: tokio::fs::File,
}
impl fmt::Debug for File {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
f.debug_struct("File").field("inner", &self.inner).finish()
}
}
impl File {
pub async fn open(path: impl AsRef<Path>, is_sync: bool) -> io::Result<File> {
let mut open_options = OpenOptions::new();
open_options.read(true).write(false);
let mut path_buf = PathBuf::new();
path_buf.push(path);
open_options.aio_open(path_buf, is_sync).await
}
pub async fn create(path: impl AsRef<Path>, is_sync: bool) -> io::Result<File> {
let mut open_options = OpenOptions::new();
open_options.write(true).truncate(true).create(true);
let mut path_buf = PathBuf::new();
path_buf.push(path);
open_options.aio_open(path_buf, is_sync).await
}
pub async fn set_len(&mut self, size: u64) -> io::Result<()> {
self.inner.set_len(size).await
}
pub async fn metadata(&self) -> io::Result<Metadata> {
self.inner.metadata().await
}
pub async fn set_permissions(&self, perm: Permissions) -> io::Result<()> {
self.inner.set_permissions(perm).await
}
pub async fn read_at<
M: RawMutex,
A: crate::IntrusiveAdapter<M, L>,
L: DefaultLinkOps<Ops = A::LinkOps> + Default,
>(
&self,
aio_handle: &GenericAioContextHandle<M, A, L>,
offset: u64,
buffer: &mut LockedBuf,
len: u64,
flags: ReadFlags,
) -> Result<u64, AioCommandError>
where
A::LinkOps: LinkedListOps + Default,
{
assert!(len <= buffer.size() as u64);
aio_handle
.submit_request(
self,
RawCommand::Pread {
offset,
buffer,
flags,
len,
},
)
.await
}
pub async fn write_at<
M: RawMutex,
A: crate::IntrusiveAdapter<M, L>,
L: DefaultLinkOps<Ops = A::LinkOps> + Default,
>(
&self,
aio_handle: &GenericAioContextHandle<M, A, L>,
offset: u64,
buffer: &LockedBuf,
len: u64,
flags: WriteFlags,
) -> Result<u64, AioCommandError>
where
A::LinkOps: LinkedListOps + Default,
{
assert!(len <= buffer.size() as u64);
aio_handle
.submit_request(
self,
RawCommand::Pwrite {
offset,
buffer,
flags,
len,
},
)
.await
}
pub async fn sync_all<
M: RawMutex,
A: crate::IntrusiveAdapter<M, L>,
L: DefaultLinkOps<Ops = A::LinkOps> + Default,
>(
&self,
aio_handle: &GenericAioContextHandle<M, A, L>,
) -> Result<(), AioCommandError>
where
A::LinkOps: LinkedListOps + Default,
{
let r = aio_handle.submit_request(self, RawCommand::Fsync).await?;
if r != 0 {
return Err(AioCommandError::NonZeroCode);
}
Ok(())
}
pub async fn sync_data<
M: RawMutex,
A: crate::IntrusiveAdapter<M, L>,
L: DefaultLinkOps<Ops = A::LinkOps> + Default,
>(
&self,
aio_handle: &GenericAioContextHandle<M, A, L>,
) -> Result<(), AioCommandError>
where
A::LinkOps: LinkedListOps + Default,
{
let r = aio_handle.submit_request(self, RawCommand::Fdsync).await?;
if r != 0 {
return Err(AioCommandError::NonZeroCode);
}
Ok(())
}
}
impl AsRawFd for File {
fn as_raw_fd(&self) -> RawFd {
self.inner.as_raw_fd()
}
}
impl AsRawFd for &'_ File {
fn as_raw_fd(&self) -> RawFd {
self.inner.as_raw_fd()
}
}