#![cfg(target_os = "linux")]
mod engine;
use std::{
num::{NonZeroU32, NonZeroUsize},
path::Path,
};
use vfsi_core::{VfError, VfResult};
#[bitfields::bitfield(u8)]
struct Flags {
cached_reads: bool,
syscall_writes: bool,
#[bits(6)]
_reserved: u8,
}
#[derive(Clone, Copy, Debug)]
pub struct Options {
pub(crate) queue_depth: NonZeroU32,
pub(crate) max_batch_bytes: NonZeroUsize,
pub(crate) flags: Flags,
}
impl Default for Options {
fn default() -> Self {
Self {
queue_depth: NonZeroU32::new(256).unwrap(),
max_batch_bytes: NonZeroUsize::new(2 * 1024 * 1024).unwrap(),
flags: Flags::new(),
}
}
}
impl Options {
pub fn syscall_writes(mut self, enabled: bool) -> Self {
self.flags.set_syscall_writes(enabled);
self
}
pub fn cached_reads(mut self, enabled: bool) -> Self {
self.flags.set_cached_reads(enabled);
self
}
pub fn queue_depth(mut self, depth: NonZeroU32) -> Self {
self.queue_depth = depth;
self
}
pub fn max_batch_bytes(mut self, bytes: NonZeroUsize) -> Self {
self.max_batch_bytes = bytes;
self
}
}
pub use engine::{Stats, Telemetry};
pub fn connect(
root: impl AsRef<Path>,
options: Options,
) -> VfResult<vfsi_sync::FsClient<vfsi_local::LocalBackend>> {
connect_with_telemetry(root, options).map(|(fs, _)| fs)
}
pub fn connect_with_telemetry(
root: impl AsRef<Path>,
options: Options,
) -> VfResult<(vfsi_sync::FsClient<vfsi_local::LocalBackend>, Telemetry)> {
let (engine, telemetry) = engine::Engine::new(options).map_err(|e| {
VfError::client(0, e.raw_os_error().unwrap_or(libc::EIO) as u32)
.with_context("io_uring_setup", root.as_ref())
})?;
let backend = vfsi_local::LocalBackend::new(root.as_ref().to_path_buf(), engine)?;
Ok((vfsi_sync::FsClient::new(backend), telemetry))
}