use crate::error::BackendError;
use crate::{DatabaseError, Result, StorageBackend};
use std::fs::File;
use std::io::{Read, Seek, SeekFrom, Write};
use std::sync::Mutex;
#[derive(Debug)]
pub struct FileBackend {
file: Mutex<File>,
}
impl FileBackend {
pub fn new(file: File) -> Result<Self, DatabaseError> {
Self::new_internal(file, false)
}
pub(crate) fn new_internal(file: File, _: bool) -> Result<Self, DatabaseError> {
Ok(Self {
file: Mutex::new(file),
})
}
}
impl StorageBackend for FileBackend {
fn len(&self) -> core::result::Result<u64, BackendError> {
Ok(self
.file
.lock()
.map_err(|_| {
BackendError::Io(std::io::Error::new(
std::io::ErrorKind::Other,
"mutex poisoned",
))
})?
.metadata()
.map_err(BackendError::Io)?
.len())
}
fn read(&self, offset: u64, out: &mut [u8]) -> core::result::Result<(), BackendError> {
let mut file = self.file.lock().map_err(|_| {
BackendError::Io(std::io::Error::new(
std::io::ErrorKind::Other,
"mutex poisoned",
))
})?;
file.seek(SeekFrom::Start(offset))
.map_err(BackendError::Io)?;
file.read_exact(out).map_err(BackendError::Io)?;
Ok(())
}
fn set_len(&self, len: u64) -> core::result::Result<(), BackendError> {
self.file
.lock()
.map_err(|_| {
BackendError::Io(std::io::Error::new(
std::io::ErrorKind::Other,
"mutex poisoned",
))
})?
.set_len(len)
.map_err(BackendError::Io)
}
fn sync_data(&self) -> core::result::Result<(), BackendError> {
self.file
.lock()
.map_err(|_| {
BackendError::Io(std::io::Error::new(
std::io::ErrorKind::Other,
"mutex poisoned",
))
})?
.sync_data()
.map_err(BackendError::Io)
}
fn write(&self, offset: u64, data: &[u8]) -> core::result::Result<(), BackendError> {
let mut file = self.file.lock().map_err(|_| {
BackendError::Io(std::io::Error::new(
std::io::ErrorKind::Other,
"mutex poisoned",
))
})?;
file.seek(SeekFrom::Start(offset))
.map_err(BackendError::Io)?;
file.write_all(data).map_err(BackendError::Io)
}
}