From 69431c15bb8b272607158b7916ad15d16b0b96b8 Mon Sep 17 00:00:00 2001 From: Dan Burkert Date: Sun, 21 Dec 2014 00:42:56 -0800 Subject: [PATCH] Nested transactions --- src/transaction.rs | 53 ++++++++++++++++++++++++++++++++++++++-------- 1 file changed, 44 insertions(+), 9 deletions(-) diff --git a/src/transaction.rs b/src/transaction.rs index ff9d0aa..35ef6b7 100644 --- a/src/transaction.rs +++ b/src/transaction.rs @@ -131,11 +131,11 @@ pub trait WriteTransaction<'env> : ReadTransaction<'env> { /// Returns a `BufWriter` which can be used to write a value into the item at the given key /// and with the given length. The buffer must be completely filled by the caller. fn reserve<'txn>(&'txn mut self, - database: Database, - key: &[u8], - len: size_t, - flags: WriteFlags) - -> LmdbResult> { + database: Database, + key: &[u8], + len: size_t, + flags: WriteFlags) + -> LmdbResult> { let mut key_val: ffi::MDB_val = ffi::MDB_val { mv_size: key.len() as size_t, mv_data: key.as_ptr() as *mut c_void }; let mut data_val: ffi::MDB_val = ffi::MDB_val { mv_size: len, @@ -164,10 +164,10 @@ pub trait WriteTransaction<'env> : ReadTransaction<'env> { /// data item will be deleted. This function will return `MDB_NOTFOUND` if the specified key/data /// pair is not in the database. fn del(&mut self, - database: Database, - key: &[u8], - data: Option<&[u8]>) - -> LmdbResult<()> { + database: Database, + key: &[u8], + data: Option<&[u8]>) + -> LmdbResult<()> { let mut key_val: ffi::MDB_val = ffi::MDB_val { mv_size: key.len() as size_t, mv_data: key.as_ptr() as *mut c_void }; let data_val: Option = @@ -181,6 +181,21 @@ pub trait WriteTransaction<'env> : ReadTransaction<'env> { .unwrap_or(ptr::null_mut()))) } } + + /// Begins a new nested transaction inside of this transaction. + fn begin_nested_txn<'txn>(&'txn mut self) -> LmdbResult> { + let mut nested: *mut ffi::MDB_txn = ptr::null_mut(); + unsafe { + let env: *mut ffi::MDB_env = ffi::mdb_txn_env(self.txn()); + ffi::mdb_txn_begin(env, self.txn(), 0, &mut nested); + } + Ok(RwTransaction { + txn: nested, + _no_sync: marker::NoSync, + _no_send: marker::NoSend, + _contravariant: marker::ContravariantLifetime::<'env>, + }) + } } /// An LMDB read-only transaction. @@ -427,6 +442,26 @@ mod test { assert!(active.get(db, b"key").is_ok()); } + #[test] + fn test_nested_txn() { + let dir = io::TempDir::new("test").unwrap(); + let env = Environment::new().open(dir.path(), io::USER_RWX).unwrap(); + let db = env.open_db(None).unwrap(); + + let mut txn = env.begin_write_txn().unwrap(); + txn.put(db, b"key1", b"val1", WriteFlags::empty()).unwrap(); + + { + let mut nested = txn.begin_nested_txn().unwrap(); + nested.put(db, b"key2", b"val2", WriteFlags::empty()).unwrap(); + assert_eq!(nested.get(db, b"key1").unwrap(), Some(b"val1")); + assert_eq!(nested.get(db, b"key2").unwrap(), Some(b"val2")); + } + + assert_eq!(txn.get(db, b"key1").unwrap(), Some(b"val1")); + assert_eq!(txn.get(db, b"key2").unwrap(), None); + } + #[test] fn test_concurrent_readers_single_writer() { let dir = io::TempDir::new("test").unwrap();