use crate::config::FileConfig;
use crate::error::NetabaseError;
use crate::traits::backend_store::{BackendStore, PathBasedBackend};
use crate::traits::definition::NetabaseDefinitionTrait;
use crate::traits::model::{NetabaseModelTrait, NetabaseModelTraitKey};
use redb::{Database, ReadableDatabase};
use std::marker::PhantomData;
use std::path::Path;
use std::sync::Arc;
pub struct RedbStoreZeroCopy<D>
where
D: NetabaseDefinitionTrait,
{
db: Arc<Database>,
_phantom: PhantomData<D>,
}
impl<D> RedbStoreZeroCopy<D>
where
D: NetabaseDefinitionTrait,
{
pub fn new<P: AsRef<Path>>(path: P) -> Result<Self, NetabaseError> {
let _ = std::fs::remove_file(path.as_ref());
let db = Database::create(path)?;
Ok(Self {
db: Arc::new(db),
_phantom: PhantomData,
})
}
pub fn open<P: AsRef<Path>>(path: P) -> Result<Self, NetabaseError> {
let db = Database::open(path)?;
Ok(Self {
db: Arc::new(db),
_phantom: PhantomData,
})
}
pub fn begin_write(
&self,
) -> Result<super::transaction::RedbWriteTransactionZC<'_, D>, NetabaseError> {
let txn = self.db.as_ref().begin_write()?;
Ok(super::transaction::RedbWriteTransactionZC::new(txn))
}
pub fn begin_read(
&self,
) -> Result<super::transaction::RedbReadTransactionZC<'_, D>, NetabaseError> {
let txn = self.db.as_ref().begin_read()?;
Ok(super::transaction::RedbReadTransactionZC::new(txn))
}
pub fn quick_put<M>(&self, model: M) -> Result<(), NetabaseError>
where
M: NetabaseModelTrait<D>,
M::Keys: NetabaseModelTraitKey<D>,
{
let mut txn = self.begin_write()?;
let mut tree = txn.open_tree::<M>()?;
tree.put(model)?;
txn.commit()
}
pub fn quick_get<M>(
&self,
key: &<M::Keys as NetabaseModelTraitKey<D>>::PrimaryKey,
) -> Result<Option<M>, NetabaseError>
where
M: NetabaseModelTrait<D>,
M::Keys: NetabaseModelTraitKey<D>,
{
let txn = self.begin_read()?;
let tree = txn.open_tree::<M>()?;
tree.get(key)
}
pub fn quick_remove<M>(
&self,
key: &<M::Keys as NetabaseModelTraitKey<D>>::PrimaryKey,
) -> Result<Option<M>, NetabaseError>
where
M: NetabaseModelTrait<D>,
M::Keys: NetabaseModelTraitKey<D>,
{
let mut txn = self.begin_write()?;
let mut tree = txn.open_tree::<M>()?;
let result = tree.remove(key.clone())?;
txn.commit()?;
Ok(result)
}
pub fn database(&self) -> &Database {
&self.db
}
}
impl<D> Clone for RedbStoreZeroCopy<D>
where
D: NetabaseDefinitionTrait,
{
fn clone(&self) -> Self {
Self {
db: self.db.clone(),
_phantom: PhantomData,
}
}
}
impl<D> BackendStore<D> for RedbStoreZeroCopy<D>
where
D: NetabaseDefinitionTrait,
{
type Config = FileConfig;
fn new(config: Self::Config) -> Result<Self, NetabaseError> {
if config.truncate && config.path.exists() {
std::fs::remove_dir_all(&config.path)?;
}
let db = Database::create(&config.path)?;
Ok(Self {
db: Arc::new(db),
_phantom: PhantomData,
})
}
fn open(config: Self::Config) -> Result<Self, NetabaseError> {
let db = Database::open(&config.path)?;
Ok(Self {
db: Arc::new(db),
_phantom: PhantomData,
})
}
fn temp() -> Result<Self, NetabaseError> {
let config = FileConfig::temp();
<Self as BackendStore<D>>::new(config)
}
}
impl<D> PathBasedBackend<D> for RedbStoreZeroCopy<D>
where
D: NetabaseDefinitionTrait,
{
fn at_path<P: AsRef<Path>>(path: P) -> Result<Self, NetabaseError> {
let config = FileConfig::new(path.as_ref());
<Self as BackendStore<D>>::open(config)
}
}