use crate::db::cf_handle;
use crate::{internal_error, Result};
use ckb_db_schema::Col;
use rocksdb::ops::{DeleteCF, GetPinnedCF, PutCF};
pub use rocksdb::{DBPinnableSlice, DBVector};
use rocksdb::{
OptimisticTransaction, OptimisticTransactionDB, OptimisticTransactionSnapshot, ReadOptions,
};
use std::sync::Arc;
pub struct RocksDBTransaction {
pub(crate) db: Arc<OptimisticTransactionDB>,
pub(crate) inner: OptimisticTransaction,
}
impl RocksDBTransaction {
pub fn get_pinned(&self, col: Col, key: &[u8]) -> Result<Option<DBPinnableSlice>> {
let cf = cf_handle(&self.db, col)?;
self.inner.get_pinned_cf(cf, key).map_err(internal_error)
}
pub fn put(&self, col: Col, key: &[u8], value: &[u8]) -> Result<()> {
let cf = cf_handle(&self.db, col)?;
self.inner.put_cf(cf, key, value).map_err(internal_error)
}
pub fn delete(&self, col: Col, key: &[u8]) -> Result<()> {
let cf = cf_handle(&self.db, col)?;
self.inner.delete_cf(cf, key).map_err(internal_error)
}
pub fn get_for_update(
&self,
col: Col,
key: &[u8],
snapshot: &RocksDBTransactionSnapshot<'_>,
) -> Result<Option<DBVector>> {
let cf = cf_handle(&self.db, col)?;
let mut opts = ReadOptions::default();
opts.set_snapshot(&snapshot.inner);
self.inner
.get_for_update_cf_opt(cf, key, &opts, true)
.map_err(internal_error)
}
pub fn commit(&self) -> Result<()> {
self.inner.commit().map_err(internal_error)
}
pub fn rollback(&self) -> Result<()> {
self.inner.rollback().map_err(internal_error)
}
pub fn get_snapshot(&self) -> RocksDBTransactionSnapshot<'_> {
RocksDBTransactionSnapshot {
db: Arc::clone(&self.db),
inner: self.inner.snapshot(),
}
}
pub fn set_savepoint(&self) {
self.inner.set_savepoint()
}
pub fn rollback_to_savepoint(&self) -> Result<()> {
self.inner.rollback_to_savepoint().map_err(internal_error)
}
}
pub struct RocksDBTransactionSnapshot<'a> {
pub(crate) db: Arc<OptimisticTransactionDB>,
pub(crate) inner: OptimisticTransactionSnapshot<'a>,
}
impl<'a> RocksDBTransactionSnapshot<'a> {
pub fn get_pinned(&self, col: Col, key: &[u8]) -> Result<Option<DBPinnableSlice>> {
let cf = cf_handle(&self.db, col)?;
self.inner.get_pinned_cf(cf, key).map_err(internal_error)
}
}