RV2L6CZWTMUQ2A52YDAFVHDFGURZL3H4SSCDC347UGN23D3J5KZQC
NXMFNPZ7VWJRLC3M5QJJVTICXCMGE24F3HVIZA7A7RLVMLQMLDVQC
OP6SVMOD2GTQ7VNJ4E5KYFG4MIYA7HBMXJTADALMZH4PY7OQRMZQC
WS4ZQM4RMIHZ6XZKSDQJGHN5SSSWFL4H236USOPUA33S6RC53RFAC
OFINGD26ZWCRDVVDI2ZIBLMHXKEMJA6MRNLANJYUHQPIJLPA7J2AC
UUUVNC4DWEEL7WV5IRPKPZ6HZMYCPA53XM7LJWICUD4E6GN37IRQC
6DMPXOAT5GQ3BQQOMUZN2GMBQPRA4IB7CCPHTQTIFGO3KWWAKF3QC
6DCQHIFPEH4GZKSRRS32GMKDRPZH4MTCGOUEI7YEUVKWENBF3JWAC
W26CFMAQOXMUK4ZOJMAN4SMBXMWFQHO7HCTEVW73FQSRMJZFGJIQC
FMN7X4J24EYPOJNBUWM4NKGWSJTRV2DHCIBMPV2AXLZVVAMNOBKQC
6UVFCERMGSGNRWCVC3GWO5HWV6MSWE433DXBJVC7KRPP6LLJLCSQC
S4V4QZ5CF5LUDYWNR2UMWH6CHJDJ5FPGAZCQYM5GY7FJMJV4NN4QC
73Z2UB3JGRLFNFORE7D64O4IHIFSZASD4G4FLJ4FJLHANT75MGIAC
OTWDDJE7TTE73D6BGF4ZN6BH2NFUFLPME2VJ3CPALH463UGWLEIQC
ONES3V466GLO5CXKRF5ENK7VFOQPWM3YXLVRGWB56V5SH3W7XNBQC
KMT3MF5NLEQIPZLHCRYDGQ5EA46HJCG3C2ANEPMZGKGHDK77ADPAC
EAAYH6BQWDK52EC5RG3BEZQU3FJPN5RRRN4U5KDKDVPKXBVJMNDAC
// In both cases (`Ok` and `Split`), we need to walk up the tree
// and update each node.
// Moreover, since the middle elements of the splits may be on
// pages that must be freed at the end of this call, we collect
// them in the `free` array below, and free them only at the end
// of this function.
//
// If we didn't hold on to these pages, they could be reallocated
// in subsequent splits, and the middle element could be
// lost. This is important when the middle element climbs up more
// than one level (i.e. the middle element of the split of a leaf
// is also the middle element of the split of the leaf's parent,
// etc).
incr_descendants::<T, K, V, P>(txn, cursor, free, freed, last_freed)?;
last_freed = freed & !1;
// Here, we are copying all children of the freed
// page, except possibly the last freed page (which is
// a child of the current node, if we aren't at a
// leaf). This includes the split key/value, also
// incremented in the following call:
incr_descendants::<T, K, V, P>(txn, cursor, free, freed, &mut last_freed)?;
// Then, insert the split key/value in the relevant page:
// Splitting the root.
debug!("split root {:?} {:?}", split_key, split_value);
debug!("{:?} {:?}", left, right);
// If we are at the root, the root has
// split. Insert the split key/value in a new page
// above the entire tree.
incr_descendants::<T, K, V, P>(txn, cursor, free, freed, last_freed)?;
last_freed = freed & !1;
// Same as above: increment the relevant reference
// counters.
incr_descendants::<T, K, V, P>(txn, cursor, free, freed, &mut last_freed)?;
// And update the left child of the current cursor,
// since the main invariant of cursors is that we're
// always visiting the left child (if we're visiting
// the last child of a page, the cursor is set to the
// position strictly after the entries).
if let Ok(rc) = txn.rc(freed & !1) {
debug!("rc = {:?}", rc);
}
debug!("pointer {:?} {:?}", cursor.pointer(), cursor.first_rc_level);
// Else, the "freed" page is shared with another tree, and
// hence we just need to decrement its RC.
let mut c = P::cursor_before(cur.page.as_page());
P::move_next(&mut c);
// Start a cursor at the leftmost position and increase the
// leftmost child page's RC (if we aren't at a leaf, and if
// that child isn't the last freed page).
let mut c = P::cursor_first(cur.page.as_page());
// Finally, update the last freed page to be the page we just
// freed (the `&!1` is here because `freed` might have its LSB set
// to indicate that `freed` was allocated by the current
// transaction, but that bit isn't set in references to page
// `freed` on the parent page).
*last_freed = freed & !1;