Skip to main content

ab_farmer/single_disk_farm/
direct_io_file_wrapper.rs

1//! Wrapper data structure for direct/unbuffered I/O
2
3use ab_direct_io_file::DirectIoFile;
4use ab_farmer_components::ReadAtSync;
5use ab_farmer_components::file_ext::FileExt;
6use std::fs::OpenOptions;
7use std::io;
8use std::path::Path;
9
10/// Wrapper data structure for direct/unbuffered I/O
11#[derive(Debug)]
12pub struct DirectIoFileWrapper {
13    file: DirectIoFile,
14}
15
16impl ReadAtSync for DirectIoFileWrapper {
17    #[inline]
18    fn read_at(&self, buf: &mut [u8], offset: u64) -> io::Result<()> {
19        self.read_exact_at(buf, offset)
20    }
21}
22
23impl ReadAtSync for &DirectIoFileWrapper {
24    #[inline]
25    fn read_at(&self, buf: &mut [u8], offset: u64) -> io::Result<()> {
26        (*self).read_at(buf, offset)
27    }
28}
29
30impl FileExt for DirectIoFileWrapper {
31    fn size(&self) -> io::Result<u64> {
32        self.file.len()
33    }
34
35    fn preallocate(&self, len: u64) -> io::Result<()> {
36        self.file.allocate(len)
37    }
38
39    fn advise_random_access(&self) -> io::Result<()> {
40        // Ignore, already set
41        Ok(())
42    }
43
44    fn advise_sequential_access(&self) -> io::Result<()> {
45        // Ignore, not supported
46        Ok(())
47    }
48
49    fn disable_cache(&self) -> io::Result<()> {
50        // Ignore, not supported
51        Ok(())
52    }
53
54    fn read_exact_at(&self, buf: &mut [u8], offset: u64) -> io::Result<()> {
55        self.file.read_exact_at(buf, offset)
56    }
57
58    fn write_all_at(&self, buf: &[u8], offset: u64) -> io::Result<()> {
59        self.file.write_all_at(buf, offset)
60    }
61}
62
63impl DirectIoFileWrapper {
64    /// Open file at specified path for direct/unbuffered I/O for reads (if file doesn't exist, it
65    /// will be created).
66    ///
67    /// This is especially important on Windows to prevent huge memory usage.
68    pub fn open<P>(path: P) -> io::Result<Self>
69    where
70        P: AsRef<Path>,
71    {
72        let mut open_options = OpenOptions::new();
73        open_options
74            .read(true)
75            .write(true)
76            .create(true)
77            .truncate(false);
78
79        let file = DirectIoFile::open(open_options, path)?;
80
81        Ok(Self { file })
82    }
83
84    /// Truncates or extends the underlying file, updating the size of this file to become `size`.
85    pub fn set_len(&self, size: u64) -> io::Result<()> {
86        self.file.set_len(size)
87    }
88}