Debugging
[?]
Mar 2, 2021, 5:16 PM
DASFQGORX56YK5E4Y7GGYZSQQQMUXYTZZ4A6IVWSTI3QGRUORLPACDependencies
- [2]
ACB4A27ZCode coverage - [3]
QDTOA3CQForgot a file - [4]
6BG65Y2PCursor::set_last was panicking on empty pages - [5]
PRDUE4YACleanup + published on crates.io - [6]
5LSYTRQ6More docs, example, and fixing the free page diagnostic function for mutable transactions - [7]
DEKK3RUIFixing a bug when splitting unsized pages - [8]
PPI5ZTZPRebalance: put can free pages without splitting (compaction) - [9]
QEUTVAZ4Splitting btree::page - [10]
RV2L6CZWA few comments - [11]
H3FVSQIQUnsized pages - [12]
6UVFCERMFormatting, debugging, etc. - [13]
QYDGYIZRSplit trait Representable into its mandatory part and an optional part - [14]
CCNPHVQCCleanup, comments, renaming - [15]
UUUVNC4DDebugging/cleanup around cursors - [16]
LROAI3NBTwo iterators (convenience functions), along with tests to move cursors (put and del still destroy cursors though) - [17]
FMN7X4J2Micro-improvements, now noticeably faster than std::collections::BTreeMap - [18]
TSMS6W4DFully commented implementation of Sized nodes + massive cleanup - [19]
W2MIZD5BSingle file databases + CRC for the root pages (checking the other pages makes everything very slow) - [20]
E4MD6T3LProofreading and commenting of this crate (massive bug fixes included) - [21]
52X5P7NDCleaning up the unsized part - [22]
ONES3V46reference counting works for put - [23]
L5CVF6UJDebugging - [24]
6DCQHIFPMinor changes after benchmarking - [25]
6DMPXOATMore debugging - [26]
OTWDDJE7Trait/type cleanup - [27]
KX3WVNZWTesting/debugging "rebalance causes split of the root" - [28]
73Z2UB3JCleanup + comments - [29]
YWFYZNLZCleanup + inter-process concurrency - [30]
LSQ6V7M6Cleanup + docs - [31]
OHUZ73MKVersions - [32]
HN6Z5DU4Cleanup - [33]
T7QB6QEPAdding debug.rs - [34]
OP6SVMODResetting history - [35]
WS4ZQM4RDebugging, tests, etc. - [36]
S4V4QZ5CDebugging reference-counting for put - [37]
X3QVVQISMore debugging (del seems to work now) - [38]
YXKP4AIWNew file locks, with multiple sets of free pages - [39]
GPP7KJSFVersion bump - [40]
UAQX27N4Tests - [41]
FZBLNBGNDiagnostic tools (add_refs, check_free) + cleanup - [42]
T73WR2BXCleaner RC increments for keys and values containing references + more comments in `del` - [43]
DV4A2LR7Double-inserts (rebalancing near an internal deletion) - [44]
EAAYH6BQDebugging put - [45]
ESUI5EUZMaking as_page() unsafe - [46]
W26CFMAQImproving safety of cursors - [47]
OFINGD26implementing prev() on cursors (+ some cleanup) - [48]
PXF3R6SVImproving test coverage for btree::cursor - [49]
XEU2QVLCDebugging after plugging this into Pijul - [50]
APPY2E7MUnsized deletions + custom sizes back
Change contents
- file move: sanakirja-core → sanakirja-core
- file move: src → src
- file move: main.rs → main.rs
- file move: lib.rs → lib.rs
- file move: btree → btree
- file move: put.rs → put.rs
- edit in sanakirja-core/src/btree/put.rs at line 4
- edit in sanakirja-core/src/btree/put.rs at line 109
let mut last_freed = 0; - replacement in sanakirja-core/src/btree/put.rs at line 123
incr_descendants::<T, K, V, P>(txn, cursor, free, freed, &mut last_freed)?;incr_descendants::<T, K, V, P>(txn, cursor, free, freed)?; - replacement in sanakirja-core/src/btree/put.rs at line 142
)?)?; - replacement in sanakirja-core/src/btree/put.rs at line 172
incr_descendants::<T, K, V, P>(txn, cursor, free, freed, &mut last_freed)?;incr_descendants::<T, K, V, P>(txn, cursor, free, freed)?; - replacement in sanakirja-core/src/btree/put.rs at line 207
freed: u64,last_freed: &mut u64,mut freed: u64, - edit in sanakirja-core/src/btree/put.rs at line 209
// The freed page is on the page below. - edit in sanakirja-core/src/btree/put.rs at line 216[9.7865]→[9.3054:3172](∅→∅),[9.3172]→[9.919:970](∅→∅),[9.176]→[9.7918:7958](∅→∅),[9.505]→[9.7918:7958](∅→∅),[9.705]→[9.7918:7958](∅→∅),[9.970]→[9.7918:7958](∅→∅),[9.3117]→[9.7918:7958](∅→∅),[9.7918]→[9.7918:7958](∅→∅),[9.7958]→[9.3118:3158](∅→∅),[9.550]→[9.8113:8123](∅→∅),[9.748]→[9.8113:8123](∅→∅),[9.3158]→[9.8113:8123](∅→∅),[9.8113]→[9.8113:8123](∅→∅)
// Else, the "freed" page is shared with another tree, and// hence we just need to decrement its RC.if cursor.len() == cursor.first_rc_len() {debug_assert_ne!(freed, 0);free[cursor.len()] = freed;} - replacement in sanakirja-core/src/btree/put.rs at line 220
let cur = cursor.current();let cur = cursor.cur(); - replacement in sanakirja-core/src/btree/put.rs at line 227[9.173]→[9.3668:3714](∅→∅),[9.3217]→[9.3668:3714](∅→∅),[9.1125]→[9.3668:3714](∅→∅),[9.883]→[9.8290:8322](∅→∅),[9.3714]→[9.8290:8322](∅→∅),[9.8290]→[9.8290:8322](∅→∅)
if left != 0 && left != *last_freed {txn.incr_rc(left)?;if left != 0 {if left != (freed & !1) {txn.incr_rc(left)?;} else if cursor.len() == cursor.first_rc_len() {freed = 0} - replacement in sanakirja-core/src/btree/put.rs at line 241[9.8508]→[9.3888:3932](∅→∅),[9.967]→[9.8536:8569](∅→∅),[9.3932]→[9.8536:8569](∅→∅),[9.8536]→[9.8536:8569](∅→∅)
if r != 0 && r != *last_freed {txn.incr_rc(r)?;if r != 0 {if r != (freed & !1) {txn.incr_rc(r)?;} else if cursor.len() == cursor.first_rc_len() {freed = 0} - edit in sanakirja-core/src/btree/put.rs at line 248
}// Else, the "freed" page is shared with another tree, and// hence we just need to decrement its RC.if freed > 0 && cursor.len() == cursor.first_rc_len() {free[cursor.len()] = freed; - edit in sanakirja-core/src/btree/put.rs at line 255
// 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; - file move: page_unsized.rs → page_unsized.rs
- replacement in sanakirja-core/src/btree/page_unsized.rs at line 143
unsafe { *(page.data.as_ptr().add((HDR + c.cur as usize * 8) - 8) as *const u64) };unsafe { *(page.data.as_ptr().offset(HDR as isize + c.cur * 8 - 8) as *const u64) }; - replacement in sanakirja-core/src/btree/page_unsized.rs at line 153
let off = unsafe { *(page.data.as_ptr().add(HDR + c.cur as usize * 8) as *const u64) };let off = unsafe { *(page.data.as_ptr().offset(HDR as isize + c.cur * 8) as *const u64) }; - edit in sanakirja-core/src/btree/page_unsized.rs at line 632
fn set_left_child(new: &mut MutPage, n: isize, l: u64); - edit in sanakirja-core/src/btree/page_unsized.rs at line 642
// This is the exact same implementation as in the sized// module. I'm not convinced - edit in sanakirja-core/src/btree/page_unsized.rs at line 665
if l != 0 {// The while loop above didn't run, i.e. the insertion// happened at the end of the page. In this case, we haven't// had a chance to update the left page, so do it now.L::set_left_child(new, *n, l)} - replacement in sanakirja-core/src/btree/page_unsized.rs at line 685
// This algorithm is probably a bit naive, especially for leaves,// where if the left page is mutable, we can copy the other page// onto it.// Indeed, we first allocate a page, then clone both pages onto// it, in a different order depending on whether the modified page// is the left or the right child.// Here, we first allocate a page, then clone both pages onto it,// in a different order depending on whether the modified page is// the left or the right child.//// Note that in the case that this merge happens immediately after// a put that reallocated the two sides of the merge in order to// split (not all splits do that), we could be slightly more// efficient, but with considerably more code. - file move: page_unsized → page_unsized
- file move: rebalance.rs → rebalance.rs
- edit in sanakirja-core/src/btree/page_unsized/rebalance.rs at line 79
- replacement in sanakirja-core/src/btree/page_unsized/rebalance.rs at line 84
if let Put::Ok(Ok { freed, page }) = <Page<K, V>>::put(txn, page.0, true, false, &lc, m.mid.0, m.mid.1, None, 0, rl,)? {if let Put::Ok(Ok { freed, page }) =<Page<K, V>>::put(txn, page.0, true, false, &lc, m.mid.0, m.mid.1, None, 0, rl)?{ - edit in sanakirja-core/src/btree/page_unsized/rebalance.rs at line 95
- replacement in sanakirja-core/src/btree/page_unsized/rebalance.rs at line 102
txn, m.modified.page, m.modified.mutable, false, &lc, m.mid.0, m.mid.1, None, 0, rl,txn,m.modified.page,m.modified.mutable,false,&lc,m.mid.0,m.mid.1,None,0,rl, - edit in sanakirja-core/src/btree/page_unsized/rebalance.rs at line 113
if m.modified.l > 0 {assert_eq!(m.modified.r, 0);unsafe {let off = (page.0.data.add(HDR) as *mut u64).offset(m.modified.c1.cur - 1);*off = (m.modified.l | (u64::from_le(*off) & 0xfff)).to_le();}} else if m.modified.r > 0 {unsafe {let off = (page.0.data.add(HDR) as *mut u64).offset(m.modified.c1.cur);*off = (m.modified.r | (u64::from_le(*off) & 0xfff)).to_le();}} - edit in sanakirja-core/src/btree/page_unsized/rebalance.rs at line 153
incr_kv_rc: !m.other_is_mutable, - replacement in sanakirja-core/src/btree/page_unsized/rebalance.rs at line 168
pub(crate) fn rebalance_right<'a, T: AllocPage, K: ?Sized, V: ?Sized, P: BTreeMutPage<K, V>>(pub(crate) fn rebalance_right<'a,T: AllocPage,K: ?Sized,V: ?Sized,P: BTreeMutPage<K, V, Cursor = super::PageCursor>,>( - edit in sanakirja-core/src/btree/page_unsized/rebalance.rs at line 182[9.2032]→[9.25475:25516](∅→∅),[9.4746]→[9.25475:25516](∅→∅),[9.5676]→[9.25475:25516](∅→∅),[9.23290]→[9.25475:25516](∅→∅),[9.25475]→[9.25475:25516](∅→∅),[9.25516]→[9.23291:23399](∅→∅)
// First element of the right page.let rc = P::cursor_first(&m.modified.page);let rl = P::left_child(m.modified.page.as_page(), &rc); - edit in sanakirja-core/src/btree/page_unsized/rebalance.rs at line 211
// First element of the right page (after potential// modification by `put` above).let rc = P::cursor_first(&new_right.0);let rl = P::left_child(new_right.0.as_page(), &rc); - replacement in sanakirja-core/src/btree/page_unsized/rebalance.rs at line 247
// mutable, since we just modified it (hence the// `assert_eq!(freed, 0)`.// mutable, since we just modified it. Moreover, if it is// compacted by the `put` below, we know that the `del` didn't// free anything, hence we can reuse the slot 0..// First element of the right page (after potential// modification by `del` above).let rc = P::cursor_first(&page.0);let rl = P::left_child(page.0.as_page(), &rc); - replacement in sanakirja-core/src/btree/page_unsized/rebalance.rs at line 256
txn,page.0,true,false,&rc,m.mid.0,m.mid.1,None,r0,rl,txn, page.0, true, false, &rc, m.mid.0, m.mid.1, None, r0, rl, - replacement in sanakirja-core/src/btree/page_unsized/rebalance.rs at line 258
debug_assert_eq!(freed, 0);if freed > 0 {freed_[0] = if is_dirty { freed | 1 } else { freed };} - edit in sanakirja-core/src/btree/page_unsized/rebalance.rs at line 267
let rc = P::cursor_first(&m.modified.page);let rl = P::left_child(m.modified.page.as_page(), &rc); - edit in sanakirja-core/src/btree/page_unsized/rebalance.rs at line 281
// Update the left and right offsets. We know that at// least one of them is 0, but it can be either one (or// both), depending on what happened on the page below.//// Since we inserted an entry at the beginning of the// page, we need to add 1 to the index given by// `m.modified.c1.cur`.if m.modified.l > 0 {assert_eq!(m.modified.r, 0);unsafe {let off = (page.0.data.add(HDR) as *mut u64).offset(m.modified.c1.cur);*off = (m.modified.l | (u64::from_le(*off) & 0xfff)).to_le();}} else if m.modified.r > 0 {unsafe {let off = (page.0.data.add(HDR) as *mut u64).offset(m.modified.c1.cur + 1);*off = (m.modified.r | (u64::from_le(*off) & 0xfff)).to_le();}} - edit in sanakirja-core/src/btree/page_unsized/rebalance.rs at line 325
incr_kv_rc: !m.modified.mutable, - file move: put.rs → put.rs
- file move: header.rs → header.rs
- file move: cursor.rs → cursor.rs
- file move: alloc.rs → alloc.rs
- edit in sanakirja-core/src/btree/page_unsized/alloc.rs at line 184
}fn set_left_child(_new: &mut MutPage, _n: isize, l: u64) {debug_assert_eq!(l, 0); - edit in sanakirja-core/src/btree/page_unsized/alloc.rs at line 193
}fn set_left_child(new: &mut MutPage, n: isize, l: u64) {if l > 0 {Internal::set_right_child(new, n - 1, l);} - file move: page.rs → page.rs
- edit in sanakirja-core/src/btree/page.rs at line 200
- replacement in sanakirja-core/src/btree/page.rs at line 665
assert!(off as usize + core::mem::size_of::<Tuple<K, V>>() <= PAGE_SIZE);if off as usize + core::mem::size_of::<Tuple<K, V>>() > PAGE_SIZE {panic!("off = {:?}, size = {:?}", off, core::mem::size_of::<Tuple<K, V>>());} - replacement in sanakirja-core/src/btree/page.rs at line 775
let a = core::mem::size_of::<Tuple<K, V>>();let a = core::mem::align_of::<Tuple<K, V>>(); - file move: page → page
- file move: rebalance.rs → rebalance.rs
- edit in sanakirja-core/src/btree/page/rebalance.rs at line 68
// Looking at module `super::del`, the only way we can be in// this case - edit in sanakirja-core/src/btree/page/rebalance.rs at line 107
if m.modified.l > 0 {assert_eq!(m.modified.r, 0);unsafe {let off = (page.0.data.add(HDR) as *mut u64).offset(m.modified.c1.cur - 1);*off = (m.modified.l | (u64::from_le(*off) & 0xfff)).to_le();}} else if m.modified.r > 0 {unsafe {let off = (page.0.data.add(HDR) as *mut u64).offset(m.modified.c1.cur);*off = (m.modified.r | (u64::from_le(*off) & 0xfff)).to_le();}} - edit in sanakirja-core/src/btree/page/rebalance.rs at line 190
incr_kv_rc: !m.other_is_mutable, - file move: put.rs → put.rs
- edit in sanakirja-core/src/btree/page/put.rs at line 161
<Page<K, V> as BTreeMutPage<K, V>>::init(&mut left); - edit in sanakirja-core/src/btree/page/put.rs at line 163
L::set_right_child(&mut left, -1, hdr.left_page() & !0xfff); - file move: alloc.rs → alloc.rs
- edit in sanakirja-core/src/btree/page/alloc.rs at line 308
}fn set_left_child(new: &mut MutPage, n: isize, l: u64) {if l > 0 {Internal::set_right_child(new, n - 1, l);} - edit in sanakirja-core/src/btree/page/alloc.rs at line 319
}fn set_left_child(_new: &mut MutPage, _n: isize, l: u64) {debug_assert_eq!(l, 0); - file move: mod.rs → mod.rs
- file move: del.rs → del.rs
- edit in sanakirja-core/src/btree/del.rs at line 23
// Do `k` and `v` come from a page shared with another tree?incr_kv_rc: bool, - replacement in sanakirja-core/src/btree/del.rs at line 80
K: Storable + ?Sized + core::fmt::Debug,K: Storable + ?Sized + core::fmt::Debug + PartialEq, - replacement in sanakirja-core/src/btree/del.rs at line 107
K: Storable + ?Sized + core::fmt::Debug,K: Storable + ?Sized + core::fmt::Debug + PartialEq, - replacement in sanakirja-core/src/btree/del.rs at line 127
let cur = cursor.current();let cur = cursor.cur(); - replacement in sanakirja-core/src/btree/del.rs at line 137
let cur = cursor.current();let cur = cursor.cur(); - edit in sanakirja-core/src/btree/del.rs at line 168
let incr_page = if !concat.other_is_mutable {Some(CowPage {offset: concat.other.offset,data: concat.other.data,})} else {None};let incr_mid = if cursor.len() >= cursor.first_rc_len() {Some(concat.mid)} else {None}; - edit in sanakirja-core/src/btree/del.rs at line 189
- replacement in sanakirja-core/src/btree/del.rs at line 191
last_op = handle_merge(txn, cursor, p0, &k0v0, mil, merge, &mut free)?;last_op = handle_merge(txn, cursor, p0, &k0v0, incr_page, incr_mid, mil, merge, &mut free)?; - replacement in sanakirja-core/src/btree/del.rs at line 228[9.31559]→[9.31559:31607](∅→∅),[9.31607]→[9.11882:11972](∅→∅),[9.2755]→[9.18370:18421](∅→∅),[9.11972]→[9.18370:18421](∅→∅),[9.18370]→[9.18370:18421](∅→∅)
T: AllocPage + LoadPage + core::fmt::Debug,K: Storable + ?Sized + core::fmt::Debug,V: Storable + ?Sized + core::fmt::Debug,P: BTreeMutPage<K, V> + core::fmt::Debug + 'a,T: AllocPage + LoadPage,K: Storable + ?Sized,V: Storable + ?Sized,P: BTreeMutPage<K, V> + 'a, - edit in sanakirja-core/src/btree/del.rs at line 241
- replacement in sanakirja-core/src/btree/del.rs at line 361
K: Storable + ?Sized,K: Storable + ?Sized + PartialEq, - replacement in sanakirja-core/src/btree/del.rs at line 363
P: BTreeMutPage<K, V> + core::fmt::Debug,P: BTreeMutPage<K, V>, - edit in sanakirja-core/src/btree/del.rs at line 369
incr_other: Option<CowPage>,incr_mid: Option<(&K, &V)>, - edit in sanakirja-core/src/btree/del.rs at line 393
// For merges and rebalances, take care of the reference counts of// pages and key/values.match merge {Op::Merged {.. } | Op::Rebalanced { .. } => {// Increase the RC of the "other page's" descendants. In// the case of a rebalance, this has the effect of// increasing the RC of the new middle entry if that entry// comes from a shared page, which is what we want.if let Some(other) = incr_other {let mut curs = P::cursor_first(&other);let left = P::left_child(other.as_page(), &curs);txn.incr_rc(left)?;while let Some((k0, v0, r)) = P::next(txn, other.as_page(), &mut curs) {for o in k0.page_references().chain(v0.page_references()) {txn.incr_rc(o)?;}if r != 0 {txn.incr_rc(r)?;}}}// If the middle element comes from a shared page,// increment its references.if let Some((ref k, ref v)) = incr_mid {for o in k.page_references().chain(v.page_references()) {txn.incr_rc(o)?;}}}_ => {}} - edit in sanakirja-core/src/btree/del.rs at line 449
incr_kv_rc, - edit in sanakirja-core/src/btree/del.rs at line 455[9.35444]→[9.4908:5226](∅→∅),[9.5226]→[9.3565:3639](∅→∅),[9.3639]→[9.5294:5363](∅→∅),[9.5294]→[9.5294:5363](∅→∅)
if incr_kv_rc {// Here, note that the rebalancing element cannot// possibly be the replacement element, so since it is// copied, we need to increment its RC (the// replacement entry has its RC incremented at// deletion).for o in k.page_references().chain(v.page_references()) {txn.incr_rc(o)?;}} - replacement in sanakirja-core/src/btree/del.rs at line 589
if m.r == 0 && r != 0 {// If `m.skip_first`, we have already skipped the entry above,// so this `r` has nothing to do with any update.//// Else, if we aren't skipping, but also aren't updating the// right child of the current entry, also increase the RC.if (m.skip_first || m.r == 0) && r != 0 { - file move: cursor.rs → cursor.rs
- replacement in sanakirja-core/src/btree/cursor.rs at line 36
impl<K: ?Sized + core::fmt::Debug, V: ?Sized, P: BTreePage<K, V>> Cursor<K, V, P> {impl<K: ?Sized + Storable, V: ?Sized + Storable, P: BTreePage<K, V>> Cursor<K, V, P> { - replacement in sanakirja-core/src/btree/cursor.rs at line 92
pub(super) fn current(&self) -> &PageCursor<K, V, P> {pub(super) fn cur(&self) -> &PageCursor<K, V, P> { - replacement in sanakirja-core/src/btree/cursor.rs at line 204
) -> Result<Option<(&'a K, &'a V)>, T::Error> {let mut last_match;) -> Result<(), T::Error> { - replacement in sanakirja-core/src/btree/cursor.rs at line 207
current.cursor = P::cursor_last(¤t.page);current.cursor = P::cursor_after(¤t.page); - edit in sanakirja-core/src/btree/cursor.rs at line 212
}let l = P::left_child(current.page.as_page(), ¤t.cursor);if l > 0 {let page = txn.load_page(l)?;self.push(PageCursor {cursor: P::cursor_after(&page),page,})} else {break; - replacement in sanakirja-core/src/btree/cursor.rs at line 223
if let Some((k, v, r)) = P::current(txn, current.page.as_page(), &mut current.cursor) {last_match = Some((k, v));if r > 0 {let page = txn.load_page(r)?;self.push(PageCursor {cursor: P::cursor_last(&page),page,})} else {break;}Ok(())}/// Return the current position of the cursor.pub fn current<'a, T: LoadPage>(&mut self,txn: &'a T,) -> Result<Option<(&'a K, &'a V)>, T::Error> {loop {let current = unsafe { &mut *self.stack[self.len - 1].as_mut_ptr() };if P::is_init(¤t.cursor) {// The cursor hasn't been set.return Ok(None)} else if let Some((k, v, _)) = P::current(txn, current.page.as_page(), ¤t.cursor){unsafe {return Ok(Some((core::mem::transmute(k), core::mem::transmute(v)))); - edit in sanakirja-core/src/btree/cursor.rs at line 242
} else if self.len > 1 {self.len -= 1 - replacement in sanakirja-core/src/btree/cursor.rs at line 245
// The page is empty, meaning there's no right or left child.debug_assert!(P::is_init(¤t.cursor));// Assert we're looking at the root.debug_assert_eq!(self.len, 1);// And the root has no child.debug_assert_eq!(P::right_child(current.page.as_page(), ¤t.cursor), 0);// We're past the last element at the root. - edit in sanakirja-core/src/btree/cursor.rs at line 249
Ok(last_match.map(|(k, v)| unsafe { (core::mem::transmute(k), core::mem::transmute(v)) })) - replacement in sanakirja-core/src/btree/cursor.rs at line 291
/// Move the cursor to the previous entry, and return that/// entry./// Move the cursor to the previous entry, and return the current/// entry. If the cursor is initially after all the entries, this/// moves it back by two steps. - edit in sanakirja-core/src/btree/cursor.rs at line 309
// We are at a leaf. - file move: Cargo.toml → Cargo.toml
- replacement in sanakirja-core/Cargo.toml at line 3
version = "1.0.2"version = "1.1.0" - replacement in sanakirja-core/Cargo.toml at line 38
crc32fast = { version = "1.2", optional = true, default-features = false }[9.70978]crc32fast = { version = "1.2", optional = true, default-features = false } - file move: sanakirja → sanakirja
- file move: src → src
- file move: tests.rs → tests.rs
- edit in sanakirja/src/tests.rs at line 38
}#[derive(Eq, PartialEq, PartialOrd, Ord, Hash, Clone, Copy)]struct U([u64; 3]);direct_repr!(U);#[derive(Eq, PartialEq, PartialOrd, Ord, Hash, Clone, Copy)]struct V([u64; 5]);direct_repr!(V);impl std::fmt::Debug for U {fn fmt(&self, fmt: &mut std::fmt::Formatter) -> std::fmt::Result {write!(fmt, "U({})", self.0[0])}}impl std::fmt::Debug for V {fn fmt(&self, fmt: &mut std::fmt::Formatter) -> std::fmt::Result {write!(fmt, "V")}}#[test]pub fn random_scenario_sized_fork() {let path = "/home/pe/bla/db";let l0 = 1 << 20;std::fs::remove_file(path).unwrap_or(());let env = Env::new(&path, l0, 1).unwrap();let mut txn = Env::mut_txn_begin(&env).unwrap();let mut db = create_db::<MutTxn<&Env, ()>, U, V>(&mut txn).unwrap();use rand::{Rng, SeedableRng};let mut rng = rand::rngs::SmallRng::from_seed(*b"rc',.snjcg'sthomw,.vbw,.p84fcxjw");let mut ve: Vec<(U, V)> = Vec::with_capacity(100_000);use std::collections::HashMap;let mut h: HashMap<U, V> = HashMap::with_capacity(100_000);let mut refs = BTreeMap::new();let mut dbs = Vec::new();for i in 0.. {let do_debug = i > 5618; // i % 1_000_000 == 0;if do_debug {env_logger::try_init().unwrap_or(());info!("========== i = {:?} {:?}", i, db.db);}dbs.push(fork_db(&mut txn, &db).unwrap());if rng.gen_range(0..4) == 3 {if let Some((k, v)) = ve.pop() {if do_debug {debug!("del {:?} {:?}", k.0[0], v.0[0]);}assert!(del(&mut txn, &mut db, &k, Some(&v)).unwrap())}} else {let k = U([rng.gen(), rng.gen(), rng.gen()]);let v = V([rng.gen(), rng.gen(), rng.gen(), rng.gen(), rng.gen()]);if do_debug {debug!("put {:?} {:?}", k.0[0], v.0[0]);}put(&mut txn, &mut db, &k, &v).unwrap();ve.push((k, v));h.insert(k, v);}if do_debug {debug(&txn, &[&db], format!("debug_{}", i), true);for (i, (k, v)) in ve.iter().enumerate() {if get(&txn, &db, k, None).unwrap() != Some((k, v)) {panic!("test {:?} {:?} {:?}", i, k.0[0], v.0[0]);}}for x in iter(&txn, &db, None).unwrap() {let (k, v) = x.unwrap();if h.get(k) != Some(v) {panic!("test {:?}", k);}}refs.clear();add_refs(&txn, &db, &mut refs).unwrap();for db in dbs.iter() {add_refs(&txn, db, &mut refs).unwrap();}add_free_refs_mut(&txn, &mut refs).unwrap();check_free_mut(&mut txn, &refs);if let Some(ref rc) = txn.rc {let mut last = 0;for r in iter(&txn, rc, None).unwrap() {let (r, _) = r.unwrap();if last > 0 && last == (r & !0xfff) {panic!("r = {:?} last = {:?}", r, last);}last = r & !0xfff;}}let mut n = Vec::new();for (p, r) in refs.iter() {if *r >= 2 {let rc = txn.rc(*p).unwrap();if rc != *r as u64 {n.push((p, *r, rc))}} else {assert_eq!(txn.rc(*p).unwrap(), 0);}}if !n.is_empty() {panic!("n = {:?} {:?}", n, n.len());}}}}#[test]pub fn random_scenario_sized_test() {let path = "/home/pe/bla/db";let l0 = 1 << 20;std::fs::remove_file(path).unwrap_or(());let env = Env::new(&path, l0, 1).unwrap();let mut txn = Env::mut_txn_begin(&env).unwrap();let mut db = create_db::<MutTxn<&Env, ()>, U, V>(&mut txn).unwrap();use rand::{Rng, SeedableRng};let mut rng = rand::rngs::SmallRng::from_seed(*b"rc',.snjcg'sthomw,.vbw,.p84fcxjw");let mut ve: Vec<(U, V)> = Vec::with_capacity(100_000);use std::collections::HashMap;let mut h: HashMap<U, V> = HashMap::with_capacity(100_000);let mut refs = BTreeMap::new();for i in 0.. {let do_debug = i % 10_000_000 == 0;if do_debug {env_logger::try_init().unwrap_or(());info!("========== i = {:?} {:?}", i, db.db);}if rng.gen_range(0..4) == 3 {if let Some((k, v)) = ve.pop() {if do_debug {debug!("del {:?} {:?}", k.0[0], v.0[0]);}assert!(del(&mut txn, &mut db, &k, Some(&v)).unwrap())}} else {let k = U([rng.gen(), rng.gen(), rng.gen()]);let v = V([rng.gen(), rng.gen(), rng.gen(), rng.gen(), rng.gen()]);if do_debug {debug!("put {:?} {:?}", k.0[0], v.0[0]);}put(&mut txn, &mut db, &k, &v).unwrap();ve.push((k, v));h.insert(k, v);}if do_debug {for (i, (k, v)) in ve.iter().enumerate() {if get(&txn, &db, k, None).unwrap() != Some((k, v)) {panic!("test {:?} {:?} {:?}", i, k.0[0], v.0[0]);}}for x in iter(&txn, &db, None).unwrap() {let (k, v) = x.unwrap();if h.get(k) != Some(v) {panic!("test {:?}", k);}}refs.clear();add_refs(&txn, &db, &mut refs).unwrap();check_free_mut(&mut txn, &refs);for (p, r) in refs.iter() {if *r >= 2 {let rc = txn.rc(*p).unwrap();if rc != *r as u64 {panic!("p {:?} r {:?} {:?}", p, r, rc);}} else {assert_eq!(txn.rc(*p).unwrap(), 0);}}}}}#[test]pub fn random_scenario_unsized_test() {let path = "/home/pe/bla/udb";let l0 = 1 << 20;std::fs::remove_file(path).unwrap_or(());let env = Env::new(&path, l0, 1).unwrap();let mut txn = Env::mut_txn_begin(&env).unwrap();let mut db = create_db_::<MutTxn<&Env, ()>, U, V, btree::page_unsized::Page<U, V>>(&mut txn).unwrap();use rand::{Rng, SeedableRng};let mut rng = rand::rngs::SmallRng::from_seed(*b"rc',.snjcg'sthomw,.vbw,.p84fcxjw");let mut ve: Vec<(U, V)> = Vec::with_capacity(100_000);use std::collections::HashMap;let mut h: HashMap<U, V> = HashMap::with_capacity(100_000);let mut refs = BTreeMap::new();for i in 0.. {let do_debug = true; // i % 10_000_000 == 0;if do_debug {env_logger::try_init().unwrap_or(());info!("========== i = {:?} {:?}", i, db.db);}if rng.gen_range(0..4) == 3 {if let Some((k, v)) = ve.pop() {if do_debug {debug!("del {:?} {:?}", k.0[0], v.0[0]);}assert!(del(&mut txn, &mut db, &k, Some(&v)).unwrap())}} else {let k = U([rng.gen(), rng.gen(), rng.gen()]);let v = V([rng.gen(), rng.gen(), rng.gen(), rng.gen(), rng.gen()]);if do_debug {debug!("put {:?} {:?}", k.0[0], v.0[0]);}put(&mut txn, &mut db, &k, &v).unwrap();ve.push((k, v));h.insert(k, v);}if do_debug {for (i, (k, v)) in ve.iter().enumerate() {if get(&txn, &db, k, None).unwrap() != Some((k, v)) {panic!("test {:?} {:?} {:?}", i, k.0[0], v.0[0]);}}for x in iter(&txn, &db, None).unwrap() {let (k, v) = x.unwrap();if h.get(k) != Some(v) {panic!("test {:?}", k);}}refs.clear();add_refs(&txn, &db, &mut refs).unwrap();check_free_mut(&mut txn, &refs);for (p, r) in refs.iter() {if *r >= 2 {let rc = txn.rc(*p).unwrap();if rc != *r as u64 {panic!("p {:?} r {:?} {:?}", p, r, rc);}} else {assert_eq!(txn.rc(*p).unwrap(), 0);}}}} - edit in sanakirja/src/tests.rs at line 289
- edit in sanakirja/src/tests.rs at line 316
- file move: lib.rs → lib.rs
- file move: environment → environment
- file move: muttxn.rs → muttxn.rs
- edit in sanakirja/src/environment/muttxn.rs at line 2
use log::*; - replacement in sanakirja/src/environment/muttxn.rs at line 353
debug!("FREEING OWNED PAGE {:?}", offset);debug!("FREEING OWNED PAGE {:?} {:x}", offset, offset); - replacement in sanakirja/src/environment/muttxn.rs at line 362
debug!("FREEING PAGE {:?}", offset);debug!("FREEING PAGE {:?} {:x}", offset, offset); - replacement in sanakirja/src/environment/muttxn.rs at line 375
let mut f = if let Some((f, ())) = curs.set_last(self)? {curs.set_last(self)?;let mut f = if let Some((f, ())) = curs.prev(self)? { - replacement in sanakirja/src/environment/muttxn.rs at line 395
btree::del::del_at_cursor(self, &mut db, &mut curs)?;assert!(btree::del::del(self, &mut db, &f, None)?); - replacement in sanakirja/src/environment/muttxn.rs at line 475
let rc = if let Some((rc, _)) = curs.set(self, &off, None)? {curs.set(self, &off, None)?;let rc = if let Some((rc, _)) = curs.current(self)? { - edit in sanakirja/src/environment/muttxn.rs at line 488
debug!("incr rc {:?} {:?}", off, rc+1); - file move: mod.rs → mod.rs
- edit in sanakirja/src/environment/mod.rs at line 17
use log::*; - replacement in sanakirja/src/environment/mod.rs at line 167
GlobalHeader::from_le(&*(map as *const GlobalHeader)).n_roots as usizelet g = &*(map as *const GlobalHeader);assert_eq!(g.version, CURRENT_VERSION);g.n_roots as usize - edit in sanakirja/src/environment/mod.rs at line 343
info!("find_offset, i = {:?}/{:?}, extending, offset = {:?}, length0 = {:?}", i, mmaps.len(), offset, length0); - replacement in sanakirja/src/environment/mod.rs at line 379
let page_ptr = maps[0].ptr.add(root * PAGE_SIZE);let crc = (&*(page_ptr as *const GlobalHeader)).crc;let root_page = std::slice::from_raw_parts(page_ptr.add(8), PAGE_SIZE - 8);let mut h = HASHER.clone();h.update(root_page);if h.finalize() != crc {return Err(crate::CRCError {});}check_crc(maps[0].ptr.add(root * PAGE_SIZE)) - edit in sanakirja/src/environment/mod.rs at line 381
Ok(()) - edit in sanakirja/src/environment/mod.rs at line 432
debug!("SETTING CRC {:?}", (&*globptr).crc); - edit in sanakirja/src/environment/mod.rs at line 528
check_crc(data)?; - replacement in sanakirja/src/environment/mod.rs at line 575
let crc = u32::from_le(*(p as *const u32));let globptr = p as *mut GlobalHeader;let crc = u32::from_le((&*globptr).crc); - replacement in sanakirja/src/environment/mod.rs at line 578
let data = std::slice::from_raw_parts(p.offset(4), PAGE_SIZE - 4);let data = std::slice::from_raw_parts(p.offset(8), PAGE_SIZE - 8); - edit in sanakirja/src/environment/mod.rs at line 581
debug!("CHECKING CRC {:?} {:?}", crc_, crc); - edit in sanakirja/src/environment/mod.rs at line 588
#[cfg(not(feature = "crc32"))]unsafe fn check_crc(_: *const u8) -> Result<(), crate::CRCError> {Ok(())} - file move: global_header.rs → global_header.rs
- file move: debug.rs → debug.rs
- edit in sanakirja/src/debug.rs at line 100
debug!("CURSOR: {:?} {:?}", p.offset, cursor); - file move: Cargo.toml → Cargo.toml
- replacement in sanakirja/Cargo.toml at line 3
version = "1.0.1"version = "1.1.2" - replacement in sanakirja/Cargo.toml at line 29
sanakirja-core = { path = "../sanakirja-core", version = "1.0.1" }sanakirja-core = { path = "../sanakirja-core", version = "1.1.0" } - replacement in sanakirja/Cargo.toml at line 40
rand = "0.8"rand = {version = "0.8", features = [ "small_rng" ] } - file move: cover → cover
- file move: Cargo.toml → Cargo.toml