Skip to content

Commit

Permalink
WIP: use std file_lock
Browse files Browse the repository at this point in the history
cberner committed Nov 17, 2024
1 parent c66447a commit d1eeb66
Showing 9 changed files with 131 additions and 240 deletions.
11 changes: 1 addition & 10 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
@@ -14,9 +14,6 @@ jobs:

runs-on: ${{ matrix.os }}

env:
RUSTFLAGS: --deny warnings

steps:
- uses: actions/checkout@v4
- name: Cache
@@ -43,7 +40,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
@@ -80,12 +77,6 @@ jobs:
- name: Run tests
run: just build test

- name: Clippy
run: cargo clippy --all --all-targets -- -Dwarnings

- name: Format
run: cargo fmt --all -- --check

- name: Run CPython wrapper tests
if: runner.os != 'Windows'
run: |
2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
@@ -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
2 changes: 0 additions & 2 deletions justfile
Original file line number Diff line number Diff line change
@@ -4,8 +4,6 @@ build: pre

pre:
cargo deny --all-features check licenses
cargo fmt --all -- --check
cargo clippy --all --all-targets

release: pre
cargo build --release
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
24 changes: 3 additions & 21 deletions src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,27 +1,9 @@
#![deny(clippy::all, clippy::pedantic, clippy::disallowed_methods)]
#![deny(clippy::disallowed_methods)]
// TODO: revisit this list and see if we can enable some
#![allow(
let_underscore_drop,
clippy::default_trait_access,
clippy::if_not_else,
clippy::inline_always,
clippy::iter_not_returning_iterator,
clippy::manual_let_else,
clippy::missing_errors_doc,
clippy::missing_panics_doc,
clippy::module_name_repetitions,
clippy::must_use_candidate,
clippy::needless_pass_by_value,
clippy::option_option,
clippy::redundant_closure_for_method_calls,
clippy::similar_names,
clippy::too_many_lines,
clippy::unnecessary_wraps,
clippy::unreadable_literal,
clippy::wildcard_imports
)]
#![allow(clippy::all)]
// TODO remove this once wasi no longer requires nightly
#![cfg_attr(target_os = "wasi", feature(wasi_ext))]
#![feature(file_lock)]

//! # redb
//!
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;
121 changes: 121 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,121 @@
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(windows)]
use std::os::windows::fs::FileExt;

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

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

/// 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 d1eeb66

Please sign in to comment.