Skip to content

Commit

Permalink
WIP: use std file_lock
Browse files Browse the repository at this point in the history
  • Loading branch information
cberner committed Nov 16, 2024
1 parent 2aa5276 commit eb83c8e
Show file tree
Hide file tree
Showing 8 changed files with 125 additions and 208 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ jobs:
- name: Install Rust
if: steps.rust-cache.outputs.cache-hit != 'true'
run: |
rustup default 1.81
rustup default nightly-2024-11-15
rustup component add rustfmt
rustup component add clippy
Expand Down
2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ pyo3-build-config = { version = "0.22.0", optional = true }
log = { version = "0.4.17", optional = true }
pyo3 = { version = "0.22.0", features=["extension-module", "abi3-py37"], optional = true }

[target.'cfg(unix)'.dependencies]
[target.'cfg(target_os = "macos")'.dependencies]
libc = "0.2.104"

# Common test/bench dependencies
Expand Down
2 changes: 1 addition & 1 deletion rust-toolchain
Original file line number Diff line number Diff line change
@@ -1 +1 @@
1.81
nightly-2024-11-15
1 change: 1 addition & 0 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
)]
// TODO remove this once wasi no longer requires nightly
#![cfg_attr(target_os = "wasi", feature(wasi_ext))]
#![feature(file_lock)]

//! # redb
//!
Expand Down
13 changes: 4 additions & 9 deletions src/tree_store/page_store/file_backend/mod.rs
Original file line number Diff line number Diff line change
@@ -1,12 +1,7 @@
#[cfg(any(unix, target_os = "wasi"))]
mod unix;
#[cfg(any(unix, target_os = "wasi"))]
pub use unix::FileBackend;

#[cfg(windows)]
mod windows;
#[cfg(windows)]
pub use windows::FileBackend;
#[cfg(any(windows, unix, target_os = "wasi"))]
mod optimized;
#[cfg(any(windows, unix, target_os = "wasi"))]
pub use optimized::FileBackend;

#[cfg(not(any(windows, unix, target_os = "wasi")))]
mod fallback;
Expand Down
117 changes: 117 additions & 0 deletions src/tree_store/page_store/file_backend/optimized.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,117 @@
use crate::{DatabaseError, Result, StorageBackend};
use std::fs::File;
use std::io;

#[cfg(feature = "logging")]
use log::warn;

#[cfg(unix)]
use std::os::unix::{fs::FileExt};
#[cfg(target_os = "macos")]
use std::os::unix::io::AsRawFd;

#[cfg(target_os = "wasi")]
use std::os::wasi::fs::FileExt;

/// Stores a database as a file on-disk.
#[derive(Debug)]
pub struct FileBackend {
lock_supported: bool,
file: File,
}

impl FileBackend {
/// Creates a new backend which stores data to the given file.
pub fn new(file: File) -> Result<Self, DatabaseError> {
match file.try_lock() {
Ok(locked) => {
if locked {
Ok(Self { file, lock_supported: true})
} else {
Err(DatabaseError::DatabaseAlreadyOpen)
}
},
Err(err) if err.kind() == io::ErrorKind::Unsupported => {
#[cfg(feature = "logging")]
warn!("File locks not supported on this platform. You must ensure that only a single process opens the database file, at a time");

Ok(Self { file, lock_supported: false })
}
Err(err) => {
Err(err.into())
}
}
}
}

impl StorageBackend for FileBackend {
fn len(&self) -> Result<u64, io::Error> {
Ok(self.file.metadata()?.len())
}

#[cfg(any(unix, target_os = "wasi"))]
fn read(&self, offset: u64, len: usize) -> Result<Vec<u8>, io::Error> {
let mut buffer = vec![0; len];
self.file.read_exact_at(&mut buffer, offset)?;
Ok(buffer)
}

#[cfg(windows)]
fn read(&self, mut offset: u64, len: usize) -> std::result::Result<Vec<u8>, io::Error> {
let mut buffer = vec![0; len];
let mut data_offset = 0;
while data_offset < buffer.len() {
let read = self.file.seek_read(&mut buffer[data_offset..], offset)?;
offset += read as u64;
data_offset += read;
}
Ok(buffer)
}

fn set_len(&self, len: u64) -> Result<(), io::Error> {
self.file.set_len(len)
}

#[cfg(not(target_os = "macos"))]
fn sync_data(&self, _: bool) -> Result<(), io::Error> {
self.file.sync_data()
}

#[cfg(target_os = "macos")]
fn sync_data(&self, eventual: bool) -> Result<(), io::Error> {
if eventual {
let code = unsafe { libc::fcntl(self.file.as_raw_fd(), libc::F_BARRIERFSYNC) };
if code == -1 {
Err(io::Error::last_os_error())
} else {
Ok(())
}
} else {
self.file.sync_data()
}
}

#[cfg(any(unix, target_os = "wasi"))]
fn write(&self, offset: u64, data: &[u8]) -> Result<(), io::Error> {
self.file.write_all_at(data, offset)
}

#[cfg(windows)]
fn write(&self, mut offset: u64, data: &[u8]) -> std::result::Result<(), io::Error> {
let mut data_offset = 0;
while data_offset < data.len() {
let written = self.file.seek_write(&data[data_offset..], offset)?;
offset += written as u64;
data_offset += written;
}
Ok(())
}
}

impl Drop for FileBackend {
fn drop(&mut self) {
if self.lock_supported {
let _ = self.file.unlock();
}
}
}
95 changes: 0 additions & 95 deletions src/tree_store/page_store/file_backend/unix.rs

This file was deleted.

101 changes: 0 additions & 101 deletions src/tree_store/page_store/file_backend/windows.rs

This file was deleted.

0 comments on commit eb83c8e

Please sign in to comment.