YWFYZNLZ5JHLIFVBRKZK4TSWVPROUPRG77ZB5M7UHT2OKPL4ZSRQC PXF3R6SVXJXN2NMLMWNY5OFV5QYVE2VZTLGIZDZVK5ZVLFTVSSWQC X3QVVQIS7B7L3XYZAWL3OOBUXOJ6RMOKQ45YMLLGAHYPEEKZ45ZAC YXKP4AIWDBIWBBUDWF66YIPG5ECMHNKEV3PX6KYXOVXY3EWG3WGQC OP6SVMOD2GTQ7VNJ4E5KYFG4MIYA7HBMXJTADALMZH4PY7OQRMZQC WS4ZQM4RMIHZ6XZKSDQJGHN5SSSWFL4H236USOPUA33S6RC53RFAC EAAYH6BQWDK52EC5RG3BEZQU3FJPN5RRRN4U5KDKDVPKXBVJMNDAC ONES3V466GLO5CXKRF5ENK7VFOQPWM3YXLVRGWB56V5SH3W7XNBQC UAQX27N4PI4LHEW6LSHJETIE5MV7JTEMPLTJFYUBMYVPC43H7VOAC #[cfg(target_family="unix")]#[test]fn multi_txn() {env_logger::try_init().unwrap_or(());std::fs::remove_dir_all("/tmp/sanakirja0").unwrap_or(());std::fs::create_dir_all("/tmp/sanakirja0").unwrap();let env = Env::new("/tmp/sanakirja0", 4096 * 20, 2).unwrap();let mut txn = Env::mut_txn_begin(&env).unwrap();debug!("txn.root = {:?}", txn.env.root);let mut db = create_db::<MutTxn<&Env, ()>, u64, ()>(&mut txn).unwrap();debug!("db = {:?}", db.db.offset);txn.set_root(0, db.db.offset);txn.commit().unwrap();debug!("1. commit done");let mut txn = Env::mut_txn_begin(&env).unwrap();debug!("txn.root = {:?}", txn.env.root);let db: Db<_, u64, ()> = txn.root_db(0).unwrap().unwrap();debug!("txn.root = {:?}", db);txn.commit().unwrap();debug!("2. commit done");let mut txn = Env::mut_txn_begin(&env).unwrap();debug!("txn.root = {:?}", txn.env.root);txn.commit().unwrap();debug!("commit done");}
let root_dbs = std::slice::from_raw_parts_mut(maps[0].ptr.add(*root * PAGE_SIZE + GLOBAL_HEADER_SIZE) as *mut u64,N_ROOTS,);for (&r, rr) in self.roots.iter().zip(root_dbs.iter_mut()) {debug!("root_db: {:?}", rr as *mut u64);debug!("committing root: {:?} {:?}", r, rr);*rr = r}
let page = MutPage(CowPage {data,offset,});self.occupied_owned_pages.push(MutPage(CowPage { data, offset }));
let page = MutPage(CowPage { data, offset });self.occupied_owned_pages.push(MutPage(CowPage { data, offset }));
}}impl<E: Borrow<Env>, T> RootDb for MutTxn<E, T> {fn root_db<K: Representable<Self>,V: Representable<Self>,>(&self,n: usize,) -> Result<Option<sanakirja_core::btree::Db<Self, K, V>>, Error> {use sanakirja_core::LoadPage;if let Some(db) = self.roots.get(n) {Ok(Some(sanakirja_core::btree::Db {db: self.load_page(*db)?,marker: std::marker::PhantomData,}))} else {unsafe {let env = self.env.borrow();let db = {let root = env.root.lock();let maps = env.mmaps.lock();*(maps[0].ptr.add(*root * PAGE_SIZE + GLOBAL_HEADER_SIZE + 8 * n) as *mut u64)};if db != 0 {Ok(Some(sanakirja_core::btree::Db {db: self.load_page(db)?,marker: std::marker::PhantomData,}))} else {Ok(None)}}}
// Lock order: first take thread locks, then process locks.// Why are there two synchronization mechanisms?// Because we would need to upgrade the read lock into a write lock,// and there is no real way to do this with standard mechanisms.// So, we take a mutex to make sure no other mutable transaction can start,// and then at the time of writing, we also take the RwLock.