use crate::{
AsColumnFamilyRef, DB, DBIteratorWithThreadMode, DBPinnableSlice, DBRawIteratorWithThreadMode,
Error, IteratorMode, ReadOptions, db::DBAccess, ffi,
};
pub type Snapshot<'a> = SnapshotWithThreadMode<'a, DB>;
pub struct SnapshotReadOptions<'snapshot, 'db, D: DBAccess = DB> {
snapshot: &'snapshot SnapshotWithThreadMode<'db, D>,
readopts: ReadOptions,
}
pub struct SnapshotWithThreadMode<'a, D: DBAccess> {
db: &'a D,
pub(crate) inner: *const ffi::rocksdb_snapshot_t,
}
impl<'a, D: DBAccess> SnapshotWithThreadMode<'a, D> {
pub fn new(db: &'a D) -> Self {
let snapshot = unsafe { db.create_snapshot() };
Self {
db,
inner: snapshot,
}
}
pub fn sequence_number(&self) -> Option<u64> {
let mut seqno: u64 = 0;
let present = unsafe {
ffi::rust_rocksdb_snapshot_try_get_sequence_number(self.inner, &raw mut seqno)
};
(present != 0).then_some(seqno)
}
pub fn read_options(&'_ self) -> SnapshotReadOptions<'_, 'a, D> {
self.read_options_opt(ReadOptions::default())
}
pub fn read_options_opt(&'_ self, mut readopts: ReadOptions) -> SnapshotReadOptions<'_, 'a, D> {
readopts.set_snapshot(self);
SnapshotReadOptions {
snapshot: self,
readopts,
}
}
pub fn iterator(&'_ self, mode: IteratorMode) -> DBIteratorWithThreadMode<'_, D> {
let readopts = ReadOptions::default();
self.iterator_opt(mode, readopts)
}
pub fn iterator_cf(
&'_ self,
cf_handle: &impl AsColumnFamilyRef,
mode: IteratorMode,
) -> DBIteratorWithThreadMode<'_, D> {
let readopts = ReadOptions::default();
self.iterator_cf_opt(cf_handle, readopts, mode)
}
pub fn iterator_opt(
&'_ self,
mode: IteratorMode,
mut readopts: ReadOptions,
) -> DBIteratorWithThreadMode<'_, D> {
readopts.set_snapshot(self);
DBIteratorWithThreadMode::<D>::new(self.db, readopts, mode)
}
pub fn iterator_cf_opt(
&'_ self,
cf_handle: &impl AsColumnFamilyRef,
mut readopts: ReadOptions,
mode: IteratorMode,
) -> DBIteratorWithThreadMode<'_, D> {
readopts.set_snapshot(self);
DBIteratorWithThreadMode::new_cf(self.db, cf_handle.inner(), readopts, mode)
}
pub fn raw_iterator(&'_ self) -> DBRawIteratorWithThreadMode<'_, D> {
let readopts = ReadOptions::default();
self.raw_iterator_opt(readopts)
}
pub fn raw_iterator_cf(
&'_ self,
cf_handle: &impl AsColumnFamilyRef,
) -> DBRawIteratorWithThreadMode<'_, D> {
let readopts = ReadOptions::default();
self.raw_iterator_cf_opt(cf_handle, readopts)
}
pub fn raw_iterator_opt(
&'_ self,
mut readopts: ReadOptions,
) -> DBRawIteratorWithThreadMode<'_, D> {
readopts.set_snapshot(self);
DBRawIteratorWithThreadMode::new(self.db, readopts)
}
pub fn raw_iterator_cf_opt(
&'_ self,
cf_handle: &impl AsColumnFamilyRef,
mut readopts: ReadOptions,
) -> DBRawIteratorWithThreadMode<'_, D> {
readopts.set_snapshot(self);
DBRawIteratorWithThreadMode::new_cf(self.db, cf_handle.inner(), readopts)
}
pub fn get<K: AsRef<[u8]>>(&self, key: K) -> Result<Option<Vec<u8>>, Error> {
self.read_options().get(key)
}
pub fn get_cf<K: AsRef<[u8]>>(
&self,
cf: &impl AsColumnFamilyRef,
key: K,
) -> Result<Option<Vec<u8>>, Error> {
self.read_options().get_cf(cf, key)
}
pub fn get_opt<K: AsRef<[u8]>>(
&self,
key: K,
readopts: ReadOptions,
) -> Result<Option<Vec<u8>>, Error> {
self.read_options_opt(readopts).get(key)
}
pub fn get_cf_opt<K: AsRef<[u8]>>(
&self,
cf: &impl AsColumnFamilyRef,
key: K,
readopts: ReadOptions,
) -> Result<Option<Vec<u8>>, Error> {
self.read_options_opt(readopts).get_cf(cf, key)
}
pub fn get_pinned<K: AsRef<[u8]>>(
&'_ self,
key: K,
) -> Result<Option<DBPinnableSlice<'_>>, Error> {
self.read_options().get_pinned(key)
}
pub fn get_pinned_cf<K: AsRef<[u8]>>(
&'_ self,
cf: &impl AsColumnFamilyRef,
key: K,
) -> Result<Option<DBPinnableSlice<'_>>, Error> {
self.read_options().get_pinned_cf(cf, key)
}
pub fn get_pinned_opt<K: AsRef<[u8]>>(
&'_ self,
key: K,
readopts: ReadOptions,
) -> Result<Option<DBPinnableSlice<'_>>, Error> {
self.read_options_opt(readopts).get_pinned(key)
}
pub fn get_pinned_cf_opt<K: AsRef<[u8]>>(
&'_ self,
cf: &impl AsColumnFamilyRef,
key: K,
readopts: ReadOptions,
) -> Result<Option<DBPinnableSlice<'_>>, Error> {
self.read_options_opt(readopts).get_pinned_cf(cf, key)
}
pub fn multi_get<K: AsRef<[u8]>, I>(&self, keys: I) -> Vec<Result<Option<Vec<u8>>, Error>>
where
I: IntoIterator<Item = K>,
{
self.read_options().multi_get(keys)
}
pub fn multi_get_cf<'b, K, I, W>(&self, keys_cf: I) -> Vec<Result<Option<Vec<u8>>, Error>>
where
K: AsRef<[u8]>,
I: IntoIterator<Item = (&'b W, K)>,
W: AsColumnFamilyRef + 'b,
{
self.read_options().multi_get_cf(keys_cf)
}
pub fn multi_get_opt<K, I>(
&self,
keys: I,
readopts: ReadOptions,
) -> Vec<Result<Option<Vec<u8>>, Error>>
where
K: AsRef<[u8]>,
I: IntoIterator<Item = K>,
{
self.read_options_opt(readopts).multi_get(keys)
}
pub fn multi_get_cf_opt<'b, K, I, W>(
&self,
keys_cf: I,
readopts: ReadOptions,
) -> Vec<Result<Option<Vec<u8>>, Error>>
where
K: AsRef<[u8]>,
I: IntoIterator<Item = (&'b W, K)>,
W: AsColumnFamilyRef + 'b,
{
self.read_options_opt(readopts).multi_get_cf(keys_cf)
}
}
impl<'db, D: DBAccess> SnapshotReadOptions<'_, 'db, D> {
pub fn get<K: AsRef<[u8]>>(&self, key: K) -> Result<Option<Vec<u8>>, Error> {
self.snapshot.db.get_opt(key, &self.readopts)
}
pub fn get_cf<K: AsRef<[u8]>>(
&self,
cf: &impl AsColumnFamilyRef,
key: K,
) -> Result<Option<Vec<u8>>, Error> {
self.snapshot.db.get_cf_opt(cf, key, &self.readopts)
}
pub fn get_pinned<K: AsRef<[u8]>>(
&self,
key: K,
) -> Result<Option<DBPinnableSlice<'db>>, Error> {
let db: &'db D = self.snapshot.db;
db.get_pinned_opt(key, &self.readopts)
}
pub fn get_pinned_cf<K: AsRef<[u8]>>(
&self,
cf: &impl AsColumnFamilyRef,
key: K,
) -> Result<Option<DBPinnableSlice<'db>>, Error> {
let db: &'db D = self.snapshot.db;
db.get_pinned_cf_opt(cf, key, &self.readopts)
}
pub fn multi_get<K, I>(&self, keys: I) -> Vec<Result<Option<Vec<u8>>, Error>>
where
K: AsRef<[u8]>,
I: IntoIterator<Item = K>,
{
self.snapshot.db.multi_get_opt(keys, &self.readopts)
}
pub fn multi_get_cf<'b, K, I, W>(&self, keys_cf: I) -> Vec<Result<Option<Vec<u8>>, Error>>
where
K: AsRef<[u8]>,
I: IntoIterator<Item = (&'b W, K)>,
W: AsColumnFamilyRef + 'b,
{
self.snapshot.db.multi_get_cf_opt(keys_cf, &self.readopts)
}
}
impl<D: DBAccess> Drop for SnapshotWithThreadMode<'_, D> {
fn drop(&mut self) {
unsafe {
self.db.release_snapshot(self.inner);
}
}
}
unsafe impl<D: DBAccess + Sync> Send for SnapshotWithThreadMode<'_, D> {}
unsafe impl<D: DBAccess + Sync> Sync for SnapshotWithThreadMode<'_, D> {}