pub mod file;
#[cfg(target_os = "linux")]
pub mod uring;
use async_trait::async_trait;
use bufpool::buf::Buf;
use off64::u64;
use std::sync::Arc;
#[async_trait]
pub(crate) trait BackingStore: Send + Sync {
async fn read_at(&self, offset: u64, len: u64) -> Buf;
async fn write_at(&self, offset: u64, data: Buf) -> Buf;
async fn sync(&self);
}
#[derive(Clone)]
pub(crate) struct PartitionStore {
backing_store: Arc<dyn BackingStore>,
offset: u64,
len: u64,
}
impl PartitionStore {
pub fn new(backing_store: Arc<dyn BackingStore>, offset: u64, len: u64) -> Self {
Self {
backing_store,
offset,
len,
}
}
pub fn offset(&self) -> u64 {
self.offset
}
pub fn len(&self) -> u64 {
self.len
}
pub async fn read_at(&self, offset: u64, len: u64) -> Buf {
assert!(
offset + len <= self.len,
"attempted to read at {} with length {} but partition has length {}",
offset,
len,
self.len
);
self.backing_store.read_at(self.offset + offset, len).await
}
pub async fn write_at(&self, offset: u64, data: Buf) {
let len = u64!(data.len());
assert!(
offset + len <= self.len,
"attempted to write at {} with length {} but partition has length {}",
offset,
len,
self.len
);
self
.backing_store
.write_at(self.offset + offset, data)
.await;
}
pub async fn sync(&self) {
self.backing_store.sync().await;
}
pub fn bounded(&self, offset: u64, len: u64) -> BoundedStore {
assert!(offset + len <= self.len);
BoundedStore {
partition_store: self.clone(),
offset,
len,
}
}
}
#[derive(Clone)]
pub(crate) struct BoundedStore {
partition_store: PartitionStore,
offset: u64,
len: u64,
}
#[allow(unused)]
impl BoundedStore {
pub fn len(&self) -> u64 {
self.len
}
pub async fn read_at(&self, offset: u64, len: u64) -> Buf {
assert!(offset + len <= self.len);
self
.partition_store
.read_at(self.offset + offset, len)
.await
}
pub async fn write_at(&self, offset: u64, data: Buf) {
assert!(offset + u64!(data.len()) <= self.len);
self
.partition_store
.write_at(self.offset + offset, data)
.await;
}
}