transaction.rs (2180B)
1 use crate::bindings; 2 use crate::error::Error; 3 use crate::ndb::Ndb; 4 use crate::result::Result; 5 6 /// A `nostrdb` transaction. Only one is allowed to be active per thread. 7 #[derive(Debug)] 8 pub struct Transaction { 9 txn: bindings::ndb_txn, 10 } 11 12 impl Transaction { 13 /// Create a new `nostrdb` transaction. These are reference counted 14 pub fn new(ndb: &Ndb) -> Result<Self> { 15 // Initialize your transaction here 16 let mut txn = bindings::ndb_txn::new(); 17 let res = unsafe { bindings::ndb_begin_query(ndb.as_ptr(), &mut txn) }; 18 19 if res == 0 { 20 return Err(Error::TransactionFailed); 21 } 22 23 Ok(Transaction { txn }) 24 } 25 26 pub fn as_ptr(&self) -> *const bindings::ndb_txn { 27 &self.txn 28 } 29 30 pub fn as_mut_ptr(&self) -> *mut bindings::ndb_txn { 31 self.as_ptr() as *mut bindings::ndb_txn 32 } 33 } 34 35 impl Drop for Transaction { 36 fn drop(&mut self) { 37 // End the transaction 38 unsafe { 39 // Replace with your actual function 40 bindings::ndb_end_query(&mut self.txn); 41 } 42 } 43 } 44 45 impl bindings::ndb_txn { 46 fn new() -> Self { 47 // just create something uninitialized. ndb_begin_query will initialize it for us 48 let lmdb: *mut bindings::ndb_lmdb = std::ptr::null_mut(); 49 let mdb_txn: *mut ::std::os::raw::c_void = std::ptr::null_mut(); 50 bindings::ndb_txn { lmdb, mdb_txn } 51 } 52 } 53 54 #[cfg(test)] 55 mod tests { 56 use super::*; 57 use crate::config::Config; 58 use crate::ndb::Ndb; 59 use crate::test_util; 60 61 #[test] 62 fn transaction_inheritence_fails() { 63 let db = "target/testdbs/txn_inheritence_fails"; 64 // Initialize ndb 65 { 66 let cfg = Config::new(); 67 let ndb = Ndb::new(db, &cfg).expect("ndb open failed"); 68 69 { 70 let _txn = Transaction::new(&ndb).expect("txn1 failed"); 71 let txn2 = Transaction::new(&ndb).expect_err("tx2"); 72 assert!(txn2 == Error::TransactionFailed); 73 } 74 75 { 76 let _txn = Transaction::new(&ndb).expect("txn1 failed"); 77 } 78 } 79 80 test_util::cleanup_db(db); 81 } 82 }