mod keyspace;
mod write_tx;
use crate::{
keyspace::KeyspaceKey, Config, Database, KeyspaceCreateOptions, PersistMode, Snapshot,
};
use std::{
path::Path,
sync::{Arc, Mutex},
};
pub use keyspace::SingleWriterTxKeyspace;
pub use write_tx::WriteTransaction;
pub trait Openable {
fn open(config: Config) -> crate::Result<Self>
where
Self: Sized;
}
#[derive(Clone)]
pub struct TxDatabase {
pub(crate) inner: Database,
single_writer_lock: Arc<Mutex<()>>,
}
impl Openable for TxDatabase {
fn open(config: Config) -> crate::Result<Self>
where
Self: Sized,
{
Ok(Self {
inner: crate::Database::open(config)?,
single_writer_lock: Arc::default(),
})
}
}
impl TxDatabase {
pub fn builder(path: impl AsRef<Path>) -> crate::DatabaseBuilder<Self> {
crate::DatabaseBuilder::new(path.as_ref())
}
#[doc(hidden)]
#[must_use]
pub fn inner(&self) -> &Database {
&self.inner
}
#[must_use]
#[expect(clippy::missing_panics_doc)]
pub fn write_tx(&self) -> WriteTransaction<'_> {
#[expect(clippy::expect_used)]
let guard = self.single_writer_lock.lock().expect("poisoned tx lock");
let mut write_tx = WriteTransaction::new(
self.clone(),
self.inner.supervisor.snapshot_tracker.open(),
guard,
);
if !self.inner.config.manual_journal_persist {
write_tx = write_tx.durability(Some(PersistMode::Buffer));
}
write_tx
}
#[must_use]
pub fn read_tx(&self) -> Snapshot {
self.inner.snapshot()
}
pub fn persist(&self, mode: PersistMode) -> crate::Result<()> {
self.inner.persist(mode)
}
pub fn keyspace(
&self,
name: &str,
create_options: impl FnOnce() -> KeyspaceCreateOptions,
) -> crate::Result<SingleWriterTxKeyspace> {
let keyspace = self.inner.keyspace(name, create_options)?;
Ok(SingleWriterTxKeyspace {
inner: keyspace,
db: self.clone(),
})
}
#[must_use]
pub fn keyspace_count(&self) -> usize {
self.inner.keyspace_count()
}
#[must_use]
pub fn list_keyspace_names(&self) -> Vec<KeyspaceKey> {
self.inner.list_keyspace_names()
}
#[must_use]
pub fn keyspace_exists(&self, name: &str) -> bool {
self.inner.keyspace_exists(name)
}
#[must_use]
pub fn write_buffer_size(&self) -> u64 {
self.inner.write_buffer_size()
}
#[must_use]
pub fn journal_count(&self) -> usize {
self.inner.journal_count()
}
pub fn disk_space(&self) -> crate::Result<u64> {
self.inner.disk_space()
}
pub fn open(config: Config) -> crate::Result<Self> {
let inner = Database::create_or_recover(config)?;
Ok(Self {
inner,
single_writer_lock: Arc::default(),
})
}
}