print btree for debugging

This commit is contained in:
Nikita Sivukhin
2025-02-08 13:03:38 +04:00
parent 55dd108878
commit 75e2f01ec4
4 changed files with 84 additions and 14 deletions

5
Cargo.lock generated
View File

@@ -736,6 +736,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "186e05a59d4c50738528153b83b0b0194d3a29507dfec16eccd4b342903397d0"
dependencies = [
"log",
"regex",
]
[[package]]
@@ -767,7 +768,10 @@ version = "0.11.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "dcaee3d8e3cfc3fd92428d477bc97fc29ec8716d180c0d74c643bb26166660e0"
dependencies = [
"anstream",
"anstyle",
"env_filter",
"humantime",
"log",
]
@@ -1612,6 +1616,7 @@ dependencies = [
"chrono",
"criterion",
"crossbeam-skiplist",
"env_logger 0.11.6",
"fallible-iterator 0.3.0",
"getrandom 0.2.15",
"hex",

View File

@@ -96,6 +96,7 @@ quickcheck = { version = "1.0", default-features = false }
quickcheck_macros = { version = "1.0", default-features = false }
rand = "0.8.5" # Required for quickcheck
rand_chacha = "0.9.0"
env_logger = "0.11.6"
[[bench]]
name = "benchmark"

View File

@@ -2375,6 +2375,65 @@ mod tests {
use std::cell::RefCell;
use std::sync::Arc;
fn format_btree(pager: Rc<Pager>, page_idx: usize, depth: usize) -> String {
let cursor = BTreeCursor::new(pager.clone(), page_idx);
let page = pager.read_page(page_idx).unwrap();
let page = page.get();
let contents = page.contents.as_ref().unwrap();
let page_type = contents.page_type();
let mut current = Vec::new();
let mut child = Vec::new();
for cell_idx in 0..contents.cell_count() {
let cell = contents
.cell_get(
cell_idx,
pager.clone(),
cursor.payload_overflow_threshold_max(page_type),
cursor.payload_overflow_threshold_min(page_type),
cursor.usable_space(),
)
.unwrap();
match cell {
BTreeCell::TableInteriorCell(cell) => {
current.push(format!(
"node[rowid:{}, ptr(<=):{}]",
cell._rowid, cell._left_child_page
));
child.push(format_btree(
pager.clone(),
cell._left_child_page as usize,
depth + 2,
));
}
BTreeCell::TableLeafCell(cell) => {
current.push(format!(
"leaf[rowid:{}, len(payload):{}, overflow:{}]",
cell._rowid,
cell._payload.len(),
cell.first_overflow_page.is_some()
));
}
_ => panic!("unsupported btree cell: {:?}", cell),
}
}
if let Some(rightmost) = contents.rightmost_pointer() {
child.push(format_btree(pager.clone(), rightmost as usize, depth + 2));
}
let current = format!(
"{}-page:{}, ptr(right):{}\n{}+cells:{}",
" ".repeat(depth),
page_idx,
contents.rightmost_pointer().unwrap_or(0),
" ".repeat(depth),
current.join(", ")
);
if child.is_empty() {
current
} else {
current + "\n" + &child.join("\n")
}
}
fn empty_btree() -> (Rc<Pager>, usize) {
let db_header = DatabaseHeader::default();
let page_size = db_header.page_size as usize;
@@ -2401,30 +2460,35 @@ mod tests {
#[test]
pub fn btree_insert_fuzz() {
let _ = env_logger::init();
let (pager, root_page) = empty_btree();
let mut cursor = BTreeCursor::new(pager, root_page);
let mut cursor = BTreeCursor::new(pager.clone(), root_page);
let mut keys = Vec::new();
let mut rng = ChaCha8Rng::seed_from_u64(0);
for _ in 0..16 {
let size = (rng.next_u64() % 4096) as usize;
let key = (rng.next_u64() % (1 << 30)) as i64;
keys.push(key);
println!("INSERT INTO t VALUES ({}, randomblob({}));", key, size);
log::info!("INSERT INTO t VALUES ({}, randomblob({}));", key, size);
let key = OwnedValue::Integer(key);
let value = Record::new(vec![OwnedValue::Blob(Rc::new(vec![0; size]))]);
cursor.insert(&key, &value, false).unwrap();
}
for key in keys {
let seek_key = SeekKey::TableRowId(key as u64);
assert!(
matches!(
cursor.seek(seek_key, SeekOp::EQ).unwrap(),
CursorResult::Ok(true)
),
"key {} is not found",
key
log::info!(
"=========== btree ===========\n{}\n\n",
format_btree(pager.clone(), root_page, 0)
);
for key in keys.iter() {
let seek_key = SeekKey::TableRowId(*key as u64);
assert!(
matches!(
cursor.seek(seek_key, SeekOp::EQ).unwrap(),
CursorResult::Ok(true)
),
"key {} is not found",
key
);
}
}
}

View File

@@ -362,7 +362,7 @@ pub fn write_header_to_buf(buf: &mut [u8], header: &DatabaseHeader) {
}
#[repr(u8)]
#[derive(Debug, PartialEq, Clone)]
#[derive(Debug, PartialEq, Clone, Copy)]
pub enum PageType {
IndexInterior = 2,
TableInterior = 5,