Skip to main content

linux_aio_tokio/fs/
file.rs

1use std::fs::{Metadata, OpenOptions, Permissions};
2use std::os::unix::prelude::*;
3use std::path::{Path, PathBuf};
4use std::{fmt, io};
5
6use intrusive_collections::DefaultLinkOps;
7use intrusive_collections::linked_list::LinkedListOps;
8use lock_api::RawMutex;
9
10use crate::errors::AioCommandError;
11use crate::fs::AioOpenOptionsExt;
12use crate::{GenericAioContextHandle, LockedBuf, RawCommand, ReadFlags, WriteFlags};
13
14/// AIO version of tokio [`File`], to work through [`GenericAioContextHandle`]
15///
16/// [`File`]: ../tokio/fs/struct.File.html
17/// [`GenericAioContextHandle`]: struct.GenericAioContextHandle.html
18pub struct File {
19    pub(crate) inner: tokio::fs::File,
20}
21
22impl fmt::Debug for File {
23    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
24        f.debug_struct("File").field("inner", &self.inner).finish()
25    }
26}
27
28impl File {
29    /// Open the file. See tokio [`File::open`]
30    ///
31    /// [`File::open`]: ../tokio/fs/struct.File.html#method.open
32    pub async fn open(path: impl AsRef<Path>, is_sync: bool) -> io::Result<File> {
33        let mut open_options = OpenOptions::new();
34        open_options.read(true).write(false);
35
36        let mut path_buf = PathBuf::new();
37        path_buf.push(path);
38
39        open_options.aio_open(path_buf, is_sync).await
40    }
41
42    /// Open the file. See tokio [`File::create`]
43    ///
44    /// [`File::create`]: ../tokio/fs/struct.File.html#method.create
45    pub async fn create(path: impl AsRef<Path>, is_sync: bool) -> io::Result<File> {
46        let mut open_options = OpenOptions::new();
47        open_options.write(true).truncate(true).create(true);
48
49        let mut path_buf = PathBuf::new();
50        path_buf.push(path);
51
52        open_options.aio_open(path_buf, is_sync).await
53    }
54
55    /// Set file let. See tokio [`set_len`]
56    ///
57    /// [`set_len`]: ../tokio/fs/struct.File.html#method.set_len
58    pub async fn set_len(&mut self, size: u64) -> io::Result<()> {
59        self.inner.set_len(size).await
60    }
61
62    /// Retrieves file metadata. See tokio [`metadata`]
63    ///
64    /// [`metadata`]: ../tokio/fs/struct.File.html#method.metadata
65    pub async fn metadata(&self) -> io::Result<Metadata> {
66        self.inner.metadata().await
67    }
68
69    /// Set file permissions. See tokio [`set_permissions`]
70    ///
71    /// [`set_permissions`]: ../tokio/fs/struct.File.html#method.set_permissions
72    pub async fn set_permissions(&self, perm: Permissions) -> io::Result<()> {
73        self.inner.set_permissions(perm).await
74    }
75
76    /// Read the file through AIO at `offset` to the [`buffer`] with provided [`flags`].
77    ///
78    /// See [`submit_request`] for more information
79    ///
80    /// [`submit_request`]: struct.GenericAioContextHandle.html#method.submit_request
81    /// [`buffer`]: struct.LockedBuf.html
82    /// [`flags`]: struct.ReadFlags.html
83    pub async fn read_at<
84        M: RawMutex,
85        A: crate::IntrusiveAdapter<M, L>,
86        L: DefaultLinkOps<Ops = A::LinkOps> + Default,
87    >(
88        &self,
89        aio_handle: &GenericAioContextHandle<M, A, L>,
90        offset: u64,
91        buffer: &mut LockedBuf,
92        len: u64,
93        flags: ReadFlags,
94    ) -> Result<u64, AioCommandError>
95    where
96        A::LinkOps: LinkedListOps + Default,
97    {
98        assert!(len <= buffer.size() as u64);
99        aio_handle
100            .submit_request(
101                self,
102                RawCommand::Pread {
103                    offset,
104                    buffer,
105                    flags,
106                    len,
107                },
108            )
109            .await
110    }
111
112    /// Write to the file through AIO at `offset` from the [`buffer`] with provided [`flags`].
113    ///
114    /// See [`submit_request`] for more information
115    ///
116    /// [`submit_request`]: struct.GenericAioContextHandle.html#method.submit_request
117    /// [`buffer`]: struct.LockedBuf.html
118    /// [`flags`]: struct.ReadFlags.html
119    pub async fn write_at<
120        M: RawMutex,
121        A: crate::IntrusiveAdapter<M, L>,
122        L: DefaultLinkOps<Ops = A::LinkOps> + Default,
123    >(
124        &self,
125        aio_handle: &GenericAioContextHandle<M, A, L>,
126        offset: u64,
127        buffer: &LockedBuf,
128        len: u64,
129        flags: WriteFlags,
130    ) -> Result<u64, AioCommandError>
131    where
132        A::LinkOps: LinkedListOps + Default,
133    {
134        assert!(len <= buffer.size() as u64);
135        aio_handle
136            .submit_request(
137                self,
138                RawCommand::Pwrite {
139                    offset,
140                    buffer,
141                    flags,
142                    len,
143                },
144            )
145            .await
146    }
147
148    /// Sync data and metadata through AIO
149    ///
150    /// See [`submit_request`] for more information
151    ///
152    /// [`submit_request`]: struct.GenericAioContextHandle.html#method.submit_request
153    pub async fn sync_all<
154        M: RawMutex,
155        A: crate::IntrusiveAdapter<M, L>,
156        L: DefaultLinkOps<Ops = A::LinkOps> + Default,
157    >(
158        &self,
159        aio_handle: &GenericAioContextHandle<M, A, L>,
160    ) -> Result<(), AioCommandError>
161    where
162        A::LinkOps: LinkedListOps + Default,
163    {
164        let r = aio_handle.submit_request(self, RawCommand::Fsync).await?;
165        if r != 0 {
166            return Err(AioCommandError::NonZeroCode);
167        }
168        Ok(())
169    }
170
171    /// Sync only data through AIO
172    ///
173    /// See [`submit_request`] for more information
174    ///
175    /// [`submit_request`]: struct.GenericAioContextHandle.html#method.submit_request
176    pub async fn sync_data<
177        M: RawMutex,
178        A: crate::IntrusiveAdapter<M, L>,
179        L: DefaultLinkOps<Ops = A::LinkOps> + Default,
180    >(
181        &self,
182        aio_handle: &GenericAioContextHandle<M, A, L>,
183    ) -> Result<(), AioCommandError>
184    where
185        A::LinkOps: LinkedListOps + Default,
186    {
187        let r = aio_handle.submit_request(self, RawCommand::Fdsync).await?;
188        if r != 0 {
189            return Err(AioCommandError::NonZeroCode);
190        }
191        Ok(())
192    }
193}
194
195impl AsRawFd for File {
196    fn as_raw_fd(&self) -> RawFd {
197        self.inner.as_raw_fd()
198    }
199}
200
201impl AsRawFd for &'_ File {
202    fn as_raw_fd(&self) -> RawFd {
203        self.inner.as_raw_fd()
204    }
205}