raft_engine/env/
default.rs

1// Copyright (c) 2017-present, PingCAP, Inc. Licensed under Apache-2.0.
2
3#[cfg(feature = "failpoints")]
4use std::io::{Error, ErrorKind};
5use std::io::{Read, Result as IoResult, Seek, SeekFrom, Write};
6use std::path::Path;
7use std::sync::Arc;
8
9use fail::fail_point;
10
11use crate::env::log_fd::LogFd;
12use crate::env::{FileSystem, Handle, Permission, WriteExt};
13
14/// A low-level file adapted for standard interfaces including [`Seek`],
15/// [`Write`] and [`Read`].
16pub struct LogFile {
17    inner: Arc<LogFd>,
18    offset: usize,
19}
20
21impl LogFile {
22    /// Creates a new [`LogFile`] from a shared [`LogFd`].
23    pub fn new(fd: Arc<LogFd>) -> Self {
24        Self {
25            inner: fd,
26            offset: 0,
27        }
28    }
29}
30
31impl Write for LogFile {
32    fn write(&mut self, buf: &[u8]) -> IoResult<usize> {
33        fail_point!("log_file::write::zero", |_| { Ok(0) });
34
35        let len = self.inner.write(self.offset, buf)?;
36
37        fail_point!("log_file::write::err", |_| {
38            Err(Error::new(ErrorKind::InvalidInput, "fp"))
39        });
40
41        self.offset += len;
42        Ok(len)
43    }
44
45    fn flush(&mut self) -> IoResult<()> {
46        Ok(())
47    }
48}
49
50impl Read for LogFile {
51    fn read(&mut self, buf: &mut [u8]) -> IoResult<usize> {
52        fail_point!("log_file::read::err", |_| {
53            Err(Error::new(ErrorKind::InvalidInput, "fp"))
54        });
55
56        let len = self.inner.read(self.offset, buf)?;
57        self.offset += len;
58        Ok(len)
59    }
60}
61
62impl Seek for LogFile {
63    fn seek(&mut self, pos: SeekFrom) -> IoResult<u64> {
64        fail_point!("log_file::seek::err", |_| {
65            Err(std::io::Error::new(std::io::ErrorKind::Other, "fp"))
66        });
67        match pos {
68            SeekFrom::Start(offset) => self.offset = offset as usize,
69            SeekFrom::Current(i) => self.offset = (self.offset as i64 + i) as usize,
70            SeekFrom::End(i) => self.offset = (self.inner.file_size()? as i64 + i) as usize,
71        }
72        Ok(self.offset as u64)
73    }
74}
75
76impl WriteExt for LogFile {
77    fn truncate(&mut self, offset: usize) -> IoResult<()> {
78        fail_point!("log_file::truncate::err", |_| {
79            Err(Error::new(ErrorKind::InvalidInput, "fp"))
80        });
81
82        self.inner.truncate(offset)?;
83        self.offset = offset;
84        Ok(())
85    }
86
87    fn allocate(&mut self, offset: usize, size: usize) -> IoResult<()> {
88        fail_point!("log_file::allocate::err", |_| {
89            Err(Error::new(ErrorKind::InvalidInput, "fp"))
90        });
91
92        self.inner.allocate(offset, size)
93    }
94}
95
96pub struct DefaultFileSystem;
97
98impl FileSystem for DefaultFileSystem {
99    type Handle = LogFd;
100    type Reader = LogFile;
101    type Writer = LogFile;
102
103    fn create<P: AsRef<Path>>(&self, path: P) -> IoResult<Self::Handle> {
104        fail_point!("default_fs::create::err", |_| {
105            Err(Error::new(ErrorKind::InvalidInput, "fp"))
106        });
107
108        LogFd::create(path.as_ref())
109    }
110
111    fn open<P: AsRef<Path>>(&self, path: P, perm: Permission) -> IoResult<Self::Handle> {
112        fail_point!("default_fs::open::err", |_| {
113            Err(Error::new(ErrorKind::InvalidInput, "fp"))
114        });
115
116        LogFd::open(path.as_ref(), perm)
117    }
118
119    fn delete<P: AsRef<Path>>(&self, path: P) -> IoResult<()> {
120        fail_point!("default_fs::delete_skipped", |_| { Ok(()) });
121        std::fs::remove_file(path)
122    }
123
124    fn rename<P: AsRef<Path>>(&self, src_path: P, dst_path: P) -> IoResult<()> {
125        std::fs::rename(src_path, dst_path)
126    }
127
128    fn new_reader(&self, handle: Arc<Self::Handle>) -> IoResult<Self::Reader> {
129        Ok(LogFile::new(handle))
130    }
131
132    fn new_writer(&self, handle: Arc<Self::Handle>) -> IoResult<Self::Writer> {
133        Ok(LogFile::new(handle))
134    }
135}