Nested transactions

without.crypto
Dan Burkert 10 years ago
parent d46d974c3f
commit 69431c15bb
  1. 53
      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 /// 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. /// and with the given length. The buffer must be completely filled by the caller.
fn reserve<'txn>(&'txn mut self, fn reserve<'txn>(&'txn mut self,
database: Database, database: Database,
key: &[u8], key: &[u8],
len: size_t, len: size_t,
flags: WriteFlags) flags: WriteFlags)
-> LmdbResult<BufWriter<'txn>> { -> LmdbResult<BufWriter<'txn>> {
let mut key_val: ffi::MDB_val = ffi::MDB_val { mv_size: key.len() as size_t, 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 }; mv_data: key.as_ptr() as *mut c_void };
let mut data_val: ffi::MDB_val = ffi::MDB_val { mv_size: len, 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 /// data item will be deleted. This function will return `MDB_NOTFOUND` if the specified key/data
/// pair is not in the database. /// pair is not in the database.
fn del(&mut self, fn del(&mut self,
database: Database, database: Database,
key: &[u8], key: &[u8],
data: Option<&[u8]>) data: Option<&[u8]>)
-> LmdbResult<()> { -> LmdbResult<()> {
let mut key_val: ffi::MDB_val = ffi::MDB_val { mv_size: key.len() as size_t, 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 }; mv_data: key.as_ptr() as *mut c_void };
let data_val: Option<ffi::MDB_val> = let data_val: Option<ffi::MDB_val> =
@ -181,6 +181,21 @@ pub trait WriteTransaction<'env> : ReadTransaction<'env> {
.unwrap_or(ptr::null_mut()))) .unwrap_or(ptr::null_mut())))
} }
} }
/// Begins a new nested transaction inside of this transaction.
fn begin_nested_txn<'txn>(&'txn mut self) -> LmdbResult<RwTransaction<'txn>> {
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. /// An LMDB read-only transaction.
@ -427,6 +442,26 @@ mod test {
assert!(active.get(db, b"key").is_ok()); 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] #[test]
fn test_concurrent_readers_single_writer() { fn test_concurrent_readers_single_writer() {
let dir = io::TempDir::new("test").unwrap(); let dir = io::TempDir::new("test").unwrap();

Loading…
Cancel
Save