NXMFNPZ7VWJRLC3M5QJJVTICXCMGE24F3HVIZA7A7RLVMLQMLDVQC 73Z2UB3JGRLFNFORE7D64O4IHIFSZASD4G4FLJ4FJLHANT75MGIAC OP6SVMOD2GTQ7VNJ4E5KYFG4MIYA7HBMXJTADALMZH4PY7OQRMZQC EAAYH6BQWDK52EC5RG3BEZQU3FJPN5RRRN4U5KDKDVPKXBVJMNDAC WS4ZQM4RMIHZ6XZKSDQJGHN5SSSWFL4H236USOPUA33S6RC53RFAC T73WR2BX2QDQ6APOREBXUKNH52FDLJNBGWPQUYB2TAF2PT7XCL2AC X3QVVQIS7B7L3XYZAWL3OOBUXOJ6RMOKQ45YMLLGAHYPEEKZ45ZAC DV4A2LR7Q5LAEGAQHLO34PZCHGJUHPAMRZFGT7GUFNKVQKPJNOYQC 6UVFCERMGSGNRWCVC3GWO5HWV6MSWE433DXBJVC7KRPP6LLJLCSQC H3FVSQIQGFCFKCPXVOSFHP4OSUOBBURJESCZNGQTNDAAD3WQSBEQC OTWDDJE7TTE73D6BGF4ZN6BH2NFUFLPME2VJ3CPALH463UGWLEIQC XEU2QVLCHPYOOD4TQIPEEVYOVSFMKFPLJYWEJYXYJAZ7S54KWDZAC OFINGD26ZWCRDVVDI2ZIBLMHXKEMJA6MRNLANJYUHQPIJLPA7J2AC G4JEQLLX6Q7VVFVAEJZAVQXX33MQ36CSCYSMJ5NQM5VZ76DXKU6QC YWFYZNLZ5JHLIFVBRKZK4TSWVPROUPRG77ZB5M7UHT2OKPL4ZSRQC ONES3V466GLO5CXKRF5ENK7VFOQPWM3YXLVRGWB56V5SH3W7XNBQC KMT3MF5NLEQIPZLHCRYDGQ5EA46HJCG3C2ANEPMZGKGHDK77ADPAC W26CFMAQOXMUK4ZOJMAN4SMBXMWFQHO7HCTEVW73FQSRMJZFGJIQC QEUTVAZ4F4EJXRDMWDMYXF6XEDMX7YPVG4IIXEKPIR3K54E5W5OAC Q7DRIBBRE4MNG4NP3PVIXAJF5PQYLFWYIVK2O4VVLEO6XY3BOSFQC UAQX27N4PI4LHEW6LSHJETIE5MV7JTEMPLTJFYUBMYVPC43H7VOAC KX3WVNZW5KHVEH6EOQTZ4RBEFFJ3SGF5I467X3JWZ74PURRK4HVAC impl<'a, K: Representable + ?Sized, V: Representable + ?Sized, P: BTreePage<K, V>>ModifiedPage<'a, K, V, P>{pub fn single_child(&self) -> Option<u64> {let mut c1 = self.c1.clone();if self.skip_first {P::move_next(&mut c1);}debug!("single_child: {:?} {:?} {:?} {:?}",self.page, self.c0, c1, self.ins);if P::is_empty(self.page.as_page(), &self.c0)&& self.ins.is_none()&& P::is_empty(self.page.as_page(), &c1){Some(self.l)} else {None}}}
/// Represents the concatenation of a modified page and one of its/// sibling (left or right).
pub fn fork_db<T: AllocPage + core::fmt::Debug,K: Representable + core::fmt::Debug,V: Representable + core::fmt::Debug,>(txn: &mut T,db: &Db<K, V>,) -> Result<Db<K, V>, T::Error> {fork_db_(txn, db)}
/// Get the first entry of a database greater than or equal to `k` (or/// to `(k, v)` if `v.is_some()`).
fn drop_<T: AllocPage, K: Representable + ?Sized, V: Representable + ?Sized, P: BTreePage<K, V>>(txn: &mut T,p: Page,) -> Result<(), T::Error> {let rc = if P::is_dirty(p) {txn.decr_rc_owned(p.offset)?} else {txn.decr_rc(p.offset)?};if rc == 0 {let mut cursor = P::cursor_before(p);let left_page = P::right_child(p, &cursor);if left_page == 0 {return Ok(());}drop_::<T, K, V, P>(txn, txn.load_page(left_page)?.as_page())?;while let Some((k, v, r)) = P::next(txn, p, &mut cursor) {for o in k.page_offsets().chain(v.page_offsets()) {txn.decr_rc(o)?;
let mut stack: [MaybeUninit<cursor::PageCursor<K, V, P>>; cursor::N_CURSORS] =[MaybeUninit::uninit(); cursor::N_CURSORS];let page = txn.load_page(db.db)?;stack[0] = MaybeUninit::new(cursor::PageCursor {page,cursor: P::cursor_before(page.as_page()),});let mut ptr = 0;loop {let cur = unsafe { &mut *stack[ptr].as_mut_ptr() };let rc = txn.rc(cur.page.offset)?;if rc <= 1 {if let Some((k, v, _)) = P::current(txn, cur.page.as_page(), &cur.cursor) {for o in k.page_offsets().chain(v.page_offsets()) {txn.decr_rc(o)?;}
drop_::<T, K, V, P>(txn, txn.load_page(r)?.as_page())?;
if P::move_next(&mut cur.cursor) {let r = P::left_child(cur.page.as_page(), &cur.cursor);if r > 0 {ptr += 1;let page = txn.load_page(r)?;stack[ptr] = MaybeUninit::new(cursor::PageCursor {page,cursor: P::cursor_before(page.as_page()),})}continue}
fn single_child<K: Representable+?Sized, V: Representable+?Sized, P: BTreeMutPage<K, V>>(m: &ModifiedPage<K, V, P>) -> Option<u64> {let mut c1 = m.c1.clone();if m.skip_first {P::move_next(&mut c1);}debug!("single_child: {:?} {:?} {:?} {:?}",m.page,m.c0, c1, m.ins);if P::is_empty(m.page.as_page(), &m.c0)&& m.ins.is_none()&& P::is_empty(m.page.as_page(), &c1){Some(m.l)} else {None}}
#[test]pub fn fork_drop() {env_logger::try_init().unwrap_or(());let env = Env::new_anon(409600000, 1).unwrap();let mut txn = Env::mut_txn_begin(&env).unwrap();let mut db: Db<u64, u64> = create_db(&mut txn).unwrap();let n = 1000 as u64;let i0 = 10 as u64;let mut values = Vec::with_capacity(n as usize);for i in 0..n {put(&mut txn, &mut db, &i, &i).unwrap();if i != i0 {values.push(i);}}let db2 = fork_db(&mut txn, &db).unwrap();put(&mut txn, &mut db, &n, &n).unwrap();crate::debug::debug(&txn, &[&db, &db2], "debug1", true);drop(&mut txn, db2).unwrap();crate::debug::debug(&txn, &[&db], "debug2", true);let mut refs = BTreeMap::new();add_refs(&txn, &db, &mut refs).unwrap();let mut err = 0;for (p, r) in refs.iter() {println!("{:?} {:?}", p, r);if *r >= 2 {error!("{:?} {:?} {:?}", p, txn.rc(*p).unwrap(), *r);err += 1;} else {if txn.rc(*p).unwrap() != 0 {error!("{:?} {:?} 0", p, txn.rc(*p).unwrap());err += 1;}}}assert_eq!(err, 0);}