redb/tree_store/page_store/file_backend/
unix.rs1#![cfg_attr(target_os = "wasi", allow(unused_imports))]
7
8use crate::{DatabaseError, Result, StorageBackend};
9use std::fs::File;
10use std::io;
11
12#[cfg(unix)]
13use std::os::unix::{fs::FileExt, io::AsRawFd};
14
15#[cfg(target_os = "wasi")]
16use std::os::wasi::{fs::FileExt, io::AsRawFd};
17
18#[derive(Debug)]
20pub struct FileBackend {
21 file: File,
22}
23
24impl FileBackend {
25 #[cfg(target_os = "wasi")]
29 pub fn new(file: File) -> Result<Self, DatabaseError> {
30 Ok(Self { file })
31 }
32
33 #[cfg(unix)] pub fn new(file: File) -> Result<Self, DatabaseError> {
36 let fd = file.as_raw_fd();
37 let result = unsafe { libc::flock(fd, libc::LOCK_EX | libc::LOCK_NB) };
38 if result != 0 {
39 let err = io::Error::last_os_error();
40 if err.kind() == io::ErrorKind::WouldBlock {
41 Err(DatabaseError::DatabaseAlreadyOpen)
42 } else {
43 Err(err.into())
44 }
45 } else {
46 Ok(Self { file })
47 }
48 }
49}
50
51impl StorageBackend for FileBackend {
52 fn len(&self) -> Result<u64, io::Error> {
53 Ok(self.file.metadata()?.len())
54 }
55
56 fn read(&self, offset: u64, len: usize) -> Result<Vec<u8>, io::Error> {
57 let mut buffer = vec![0; len];
58 self.file.read_exact_at(&mut buffer, offset)?;
59 Ok(buffer)
60 }
61
62 fn set_len(&self, len: u64) -> Result<(), io::Error> {
63 self.file.set_len(len)
64 }
65
66 #[cfg(not(target_os = "macos"))]
67 fn sync_data(&self, _: bool) -> Result<(), io::Error> {
68 self.file.sync_data()
69 }
70
71 #[cfg(target_os = "macos")]
72 fn sync_data(&self, eventual: bool) -> Result<(), io::Error> {
73 if eventual {
74 let code = unsafe { libc::fcntl(self.file.as_raw_fd(), libc::F_BARRIERFSYNC) };
75 if code == -1 {
76 Err(io::Error::last_os_error())
77 } else {
78 Ok(())
79 }
80 } else {
81 self.file.sync_data()
82 }
83 }
84
85 fn write(&self, offset: u64, data: &[u8]) -> Result<(), io::Error> {
86 self.file.write_all_at(data, offset)
87 }
88}
89
90#[cfg(unix)] impl Drop for FileBackend {
92 fn drop(&mut self) {
93 unsafe { libc::flock(self.file.as_raw_fd(), libc::LOCK_UN) };
94 }
95}