mod conflict_manager;
mod keyspace;
mod oracle;
mod write_tx;
use crate::{
keyspace::KeyspaceKey,
tx::{optimistic::oracle::Oracle, single_writer::Openable},
Config, Database, KeyspaceCreateOptions, PersistMode, Snapshot,
};
use std::{
path::Path,
sync::{Arc, Mutex},
};
pub use keyspace::OptimisticTxKeyspace;
pub use write_tx::{Conflict, WriteTransaction};
#[derive(Clone)]
pub struct OptimisticTxDatabase {
pub(crate) inner: Database,
pub(super) oracle: Arc<Oracle>,
}
impl Openable for OptimisticTxDatabase {
fn open(config: Config) -> crate::Result<Self>
where
Self: Sized,
{
let inner = Database::create_or_recover(config)?;
Ok(Self {
oracle: Arc::new(Oracle {
write_serialize_lock: Mutex::default(),
snapshot_tracker: inner.supervisor.snapshot_tracker.clone(),
}),
inner,
})
}
}
impl OptimisticTxDatabase {
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
}
pub fn write_tx(&self) -> crate::Result<WriteTransaction> {
let snapshot = {
let _guard = self.oracle.write_serialize_lock()?;
self.inner.supervisor.snapshot_tracker.open()
};
let mut write_tx =
WriteTransaction::new(self.inner().clone(), snapshot, self.oracle.clone());
if !self.inner.config.manual_journal_persist {
write_tx = write_tx.durability(Some(PersistMode::Buffer));
}
Ok(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<OptimisticTxKeyspace> {
let keyspace = self.inner.keyspace(name, create_options)?;
Ok(OptimisticTxKeyspace {
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()
}
}