|
|
|
@ -10,12 +10,10 @@ |
|
|
|
|
|
|
|
|
|
use std::collections::HashMap; |
|
|
|
|
|
|
|
|
|
use uuid::Uuid; |
|
|
|
|
|
|
|
|
|
use super::{ |
|
|
|
|
database::Snapshot, |
|
|
|
|
DatabaseFlagsImpl, |
|
|
|
|
DatabaseImpl, |
|
|
|
|
DatabaseId, |
|
|
|
|
EnvironmentImpl, |
|
|
|
|
ErrorImpl, |
|
|
|
|
RoCursorImpl, |
|
|
|
@ -31,12 +29,12 @@ use crate::backend::traits::{ |
|
|
|
|
#[derive(Debug)] |
|
|
|
|
pub struct RoTransactionImpl<'env> { |
|
|
|
|
env: &'env EnvironmentImpl, |
|
|
|
|
snapshots: HashMap<Uuid, Result<Snapshot, ErrorImpl>>, |
|
|
|
|
snapshots: HashMap<DatabaseId, Snapshot>, |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
impl<'env> RoTransactionImpl<'env> { |
|
|
|
|
pub(crate) fn new(env: &'env EnvironmentImpl) -> Result<RoTransactionImpl<'env>, ErrorImpl> { |
|
|
|
|
let snapshots = env.dbs()?.iter().map(|(_, db)| (*db.id(), db.snapshot())).collect(); |
|
|
|
|
let snapshots = env.dbs()?.iter().map(|(id, db)| (id, db.snapshot())).collect(); |
|
|
|
|
Ok(RoTransactionImpl { |
|
|
|
|
env, |
|
|
|
|
snapshots, |
|
|
|
@ -46,12 +44,11 @@ impl<'env> RoTransactionImpl<'env> { |
|
|
|
|
|
|
|
|
|
impl<'env> BackendRoTransaction for RoTransactionImpl<'env> { |
|
|
|
|
type Error = ErrorImpl; |
|
|
|
|
type Database = DatabaseImpl; |
|
|
|
|
type Database = DatabaseId; |
|
|
|
|
|
|
|
|
|
fn get(&self, db: &Self::Database, key: &[u8]) -> Result<&[u8], Self::Error> { |
|
|
|
|
let snapshot = self.snapshots.get(db.id()).ok_or_else(|| ErrorImpl::DbIsForeignError)?; |
|
|
|
|
let data = snapshot.as_ref().map_err(|_| ErrorImpl::TxnPoisonError)?; |
|
|
|
|
data.get(key).ok_or_else(|| ErrorImpl::KeyValuePairNotFound) |
|
|
|
|
let snapshot = self.snapshots.get(db).ok_or_else(|| ErrorImpl::DbIsForeignError)?; |
|
|
|
|
snapshot.get(key).ok_or_else(|| ErrorImpl::KeyValuePairNotFound) |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
fn abort(self) { |
|
|
|
@ -63,21 +60,20 @@ impl<'env> BackendRoCursorTransaction<'env> for RoTransactionImpl<'env> { |
|
|
|
|
type RoCursor = RoCursorImpl<'env>; |
|
|
|
|
|
|
|
|
|
fn open_ro_cursor(&'env self, db: &Self::Database) -> Result<Self::RoCursor, Self::Error> { |
|
|
|
|
let snapshot = self.snapshots.get(db.id()).ok_or_else(|| ErrorImpl::DbIsForeignError)?; |
|
|
|
|
let data = snapshot.as_ref().map_err(|_| ErrorImpl::TxnPoisonError)?; |
|
|
|
|
Ok(RoCursorImpl(data)) |
|
|
|
|
let snapshot = self.snapshots.get(db).ok_or_else(|| ErrorImpl::DbIsForeignError)?; |
|
|
|
|
Ok(RoCursorImpl(snapshot)) |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
#[derive(Debug)] |
|
|
|
|
pub struct RwTransactionImpl<'env> { |
|
|
|
|
env: &'env EnvironmentImpl, |
|
|
|
|
snapshots: HashMap<Uuid, Result<Snapshot, ErrorImpl>>, |
|
|
|
|
snapshots: HashMap<DatabaseId, Snapshot>, |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
impl<'env> RwTransactionImpl<'env> { |
|
|
|
|
pub(crate) fn new(env: &'env EnvironmentImpl) -> Result<RwTransactionImpl<'env>, ErrorImpl> { |
|
|
|
|
let snapshots = env.dbs()?.iter().map(|(_, db)| (*db.id(), db.snapshot())).collect(); |
|
|
|
|
let snapshots = env.dbs()?.iter().map(|(id, db)| (id, db.snapshot())).collect(); |
|
|
|
|
Ok(RwTransactionImpl { |
|
|
|
|
env, |
|
|
|
|
snapshots, |
|
|
|
@ -87,40 +83,36 @@ impl<'env> RwTransactionImpl<'env> { |
|
|
|
|
|
|
|
|
|
impl<'env> BackendRwTransaction for RwTransactionImpl<'env> { |
|
|
|
|
type Error = ErrorImpl; |
|
|
|
|
type Database = DatabaseImpl; |
|
|
|
|
type Database = DatabaseId; |
|
|
|
|
type Flags = WriteFlagsImpl; |
|
|
|
|
|
|
|
|
|
fn get(&self, db: &Self::Database, key: &[u8]) -> Result<&[u8], Self::Error> { |
|
|
|
|
let snapshot = self.snapshots.get(db.id()).ok_or_else(|| ErrorImpl::DbIsForeignError)?; |
|
|
|
|
let data = snapshot.as_ref().map_err(|_| ErrorImpl::TxnPoisonError)?; |
|
|
|
|
data.get(key).ok_or_else(|| ErrorImpl::KeyValuePairNotFound) |
|
|
|
|
let snapshot = self.snapshots.get(db).ok_or_else(|| ErrorImpl::DbIsForeignError)?; |
|
|
|
|
snapshot.get(key).ok_or_else(|| ErrorImpl::KeyValuePairNotFound) |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
fn put(&mut self, db: &Self::Database, key: &[u8], value: &[u8], _flags: Self::Flags) -> Result<(), Self::Error> { |
|
|
|
|
let snapshot = self.snapshots.get_mut(db.id()).ok_or_else(|| ErrorImpl::DbIsForeignError)?; |
|
|
|
|
let data = snapshot.as_mut().map_err(|_| ErrorImpl::TxnPoisonError)?; |
|
|
|
|
if db.flags().contains(DatabaseFlagsImpl::DUP_SORT) { |
|
|
|
|
data.put_dup(key, value); |
|
|
|
|
let snapshot = self.snapshots.get_mut(db).ok_or_else(|| ErrorImpl::DbIsForeignError)?; |
|
|
|
|
if snapshot.flags().contains(DatabaseFlagsImpl::DUP_SORT) { |
|
|
|
|
snapshot.put_dup(key, value); |
|
|
|
|
} else { |
|
|
|
|
data.put_one(key, value); |
|
|
|
|
snapshot.put_one(key, value); |
|
|
|
|
} |
|
|
|
|
Ok(()) |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
fn del(&mut self, db: &Self::Database, key: &[u8], value: Option<&[u8]>) -> Result<(), Self::Error> { |
|
|
|
|
let snapshot = self.snapshots.get_mut(db.id()).ok_or_else(|| ErrorImpl::DbIsForeignError)?; |
|
|
|
|
let data = snapshot.as_mut().map_err(|_| ErrorImpl::TxnPoisonError)?; |
|
|
|
|
let deleted = match (value, db.flags()) { |
|
|
|
|
(Some(value), flags) if flags.contains(DatabaseFlagsImpl::DUP_SORT) => data.del_exact(key, value), |
|
|
|
|
_ => data.del_all(key), |
|
|
|
|
let snapshot = self.snapshots.get_mut(db).ok_or_else(|| ErrorImpl::DbIsForeignError)?; |
|
|
|
|
let deleted = match (value, snapshot.flags()) { |
|
|
|
|
(Some(value), flags) if flags.contains(DatabaseFlagsImpl::DUP_SORT) => snapshot.del_exact(key, value), |
|
|
|
|
_ => snapshot.del_all(key), |
|
|
|
|
}; |
|
|
|
|
Ok(deleted.ok_or_else(|| ErrorImpl::KeyValuePairNotFound)?) |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
fn clear_db(&mut self, db: &Self::Database) -> Result<(), Self::Error> { |
|
|
|
|
let snapshot = self.snapshots.get_mut(db.id()).ok_or_else(|| ErrorImpl::DbIsForeignError)?; |
|
|
|
|
let data = snapshot.as_mut().map_err(|_| ErrorImpl::TxnPoisonError)?; |
|
|
|
|
data.clear(); |
|
|
|
|
let snapshot = self.snapshots.get_mut(db).ok_or_else(|| ErrorImpl::DbIsForeignError)?; |
|
|
|
|
snapshot.clear(); |
|
|
|
|
Ok(()) |
|
|
|
|
} |
|
|
|
|
|
|
|
|
@ -128,14 +120,8 @@ impl<'env> BackendRwTransaction for RwTransactionImpl<'env> { |
|
|
|
|
let mut dbs = self.env.dbs_mut()?; |
|
|
|
|
|
|
|
|
|
for (id, snapshot) in self.snapshots { |
|
|
|
|
match dbs.iter_mut().find(|(_, db)| db.id() == &id) { |
|
|
|
|
Some((_, db)) => { |
|
|
|
|
db.replace(snapshot?)?; |
|
|
|
|
}, |
|
|
|
|
None => { |
|
|
|
|
unreachable!(); |
|
|
|
|
}, |
|
|
|
|
} |
|
|
|
|
let db = dbs.get_mut(id).ok_or_else(|| ErrorImpl::DbIsForeignError)?; |
|
|
|
|
db.replace(snapshot); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
drop(dbs); |
|
|
|
@ -151,8 +137,7 @@ impl<'env> BackendRwCursorTransaction<'env> for RwTransactionImpl<'env> { |
|
|
|
|
type RoCursor = RoCursorImpl<'env>; |
|
|
|
|
|
|
|
|
|
fn open_ro_cursor(&'env self, db: &Self::Database) -> Result<Self::RoCursor, Self::Error> { |
|
|
|
|
let snapshot = self.snapshots.get(db.id()).ok_or_else(|| ErrorImpl::DbIsForeignError)?; |
|
|
|
|
let data = snapshot.as_ref().map_err(|_| ErrorImpl::TxnPoisonError)?; |
|
|
|
|
Ok(RoCursorImpl(data)) |
|
|
|
|
let snapshot = self.snapshots.get(db).ok_or_else(|| ErrorImpl::DbIsForeignError)?; |
|
|
|
|
Ok(RoCursorImpl(snapshot)) |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|