mirror of
https://github.com/aljazceru/turso.git
synced 2026-02-07 09:14:26 +01:00
Merge 'btree/chore: remove unnecessary parameters to .cell_get()' from Jussi Saurio
we were providing the same damn arguments to `.cell_get()` and `.cell_get_raw_region()` over and OVER and **OVER** and `O V E R` Reviewed-by: Preston Thorpe (@PThorpe92) Closes #2021
This commit is contained in:
@@ -674,12 +674,7 @@ impl BTreeCursor {
|
||||
}
|
||||
let cell_idx = self.stack.current_cell_index() as usize;
|
||||
|
||||
let cell = contents.cell_get(
|
||||
cell_idx,
|
||||
payload_overflow_threshold_max(contents.page_type(), self.usable_space() as u16),
|
||||
payload_overflow_threshold_min(contents.page_type(), self.usable_space() as u16),
|
||||
self.usable_space(),
|
||||
)?;
|
||||
let cell = contents.cell_get(cell_idx, self.usable_space())?;
|
||||
|
||||
match cell {
|
||||
BTreeCell::TableInteriorCell(TableInteriorCell {
|
||||
@@ -871,14 +866,7 @@ impl BTreeCursor {
|
||||
}
|
||||
|
||||
let usable_size = self.usable_space();
|
||||
let cell = contents
|
||||
.cell_get(
|
||||
cell_idx,
|
||||
payload_overflow_threshold_max(contents.page_type(), usable_size as u16),
|
||||
payload_overflow_threshold_min(contents.page_type(), usable_size as u16),
|
||||
usable_size,
|
||||
)
|
||||
.unwrap();
|
||||
let cell = contents.cell_get(cell_idx, usable_size).unwrap();
|
||||
|
||||
let (payload, payload_size, first_overflow_page) = match cell {
|
||||
BTreeCell::TableLeafCell(cell) => {
|
||||
@@ -1215,12 +1203,7 @@ impl BTreeCursor {
|
||||
}
|
||||
turso_assert!(cell_idx < contents.cell_count(), "cell index out of bounds");
|
||||
|
||||
let cell = contents.cell_get(
|
||||
cell_idx,
|
||||
payload_overflow_threshold_max(contents.page_type(), self.usable_space() as u16),
|
||||
payload_overflow_threshold_min(contents.page_type(), self.usable_space() as u16),
|
||||
self.usable_space(),
|
||||
)?;
|
||||
let cell = contents.cell_get(cell_idx, self.usable_space())?;
|
||||
match &cell {
|
||||
BTreeCell::TableInteriorCell(TableInteriorCell {
|
||||
left_child_page, ..
|
||||
@@ -1513,18 +1496,8 @@ impl BTreeCursor {
|
||||
}
|
||||
}
|
||||
};
|
||||
let matching_cell = contents.cell_get(
|
||||
leftmost_matching_cell,
|
||||
payload_overflow_threshold_max(
|
||||
contents.page_type(),
|
||||
self.usable_space() as u16,
|
||||
),
|
||||
payload_overflow_threshold_min(
|
||||
contents.page_type(),
|
||||
self.usable_space() as u16,
|
||||
),
|
||||
self.usable_space(),
|
||||
)?;
|
||||
let matching_cell =
|
||||
contents.cell_get(leftmost_matching_cell, self.usable_space())?;
|
||||
self.stack.set_cell_index(leftmost_matching_cell as i32);
|
||||
// we don't advance in case of forward iteration and index tree internal nodes because we will visit this node going up.
|
||||
// in backwards iteration, we must retreat because otherwise we would unnecessarily visit this node again.
|
||||
@@ -1552,18 +1525,7 @@ impl BTreeCursor {
|
||||
|
||||
let cur_cell_idx = (min + max) >> 1; // rustc generates extra insns for (min+max)/2 due to them being isize. we know min&max are >=0 here.
|
||||
self.stack.set_cell_index(cur_cell_idx as i32);
|
||||
let cell = contents.cell_get(
|
||||
cur_cell_idx as usize,
|
||||
payload_overflow_threshold_max(
|
||||
contents.page_type(),
|
||||
self.usable_space() as u16,
|
||||
),
|
||||
payload_overflow_threshold_min(
|
||||
contents.page_type(),
|
||||
self.usable_space() as u16,
|
||||
),
|
||||
self.usable_space(),
|
||||
)?;
|
||||
let cell = contents.cell_get(cur_cell_idx as usize, self.usable_space())?;
|
||||
let BTreeCell::IndexInteriorCell(IndexInteriorCell {
|
||||
payload,
|
||||
payload_size,
|
||||
@@ -1845,12 +1807,7 @@ impl BTreeCursor {
|
||||
let page = page.get();
|
||||
let contents = page.get().contents.as_ref().unwrap();
|
||||
let cur_cell_idx = self.stack.current_cell_index() as usize;
|
||||
let cell = contents.cell_get(
|
||||
cur_cell_idx,
|
||||
payload_overflow_threshold_max(contents.page_type(), self.usable_space() as u16),
|
||||
payload_overflow_threshold_min(contents.page_type(), self.usable_space() as u16),
|
||||
self.usable_space(),
|
||||
)?;
|
||||
let cell = contents.cell_get(cur_cell_idx, self.usable_space())?;
|
||||
let BTreeCell::IndexInteriorCell(IndexInteriorCell {
|
||||
payload,
|
||||
first_overflow_page,
|
||||
@@ -1944,12 +1901,7 @@ impl BTreeCursor {
|
||||
let cur_cell_idx = (min + max) >> 1; // rustc generates extra insns for (min+max)/2 due to them being isize. we know min&max are >=0 here.
|
||||
self.stack.set_cell_index(cur_cell_idx as i32);
|
||||
|
||||
let cell = contents.cell_get(
|
||||
cur_cell_idx as usize,
|
||||
payload_overflow_threshold_max(contents.page_type(), self.usable_space() as u16),
|
||||
payload_overflow_threshold_min(contents.page_type(), self.usable_space() as u16),
|
||||
self.usable_space(),
|
||||
)?;
|
||||
let cell = contents.cell_get(cur_cell_idx as usize, self.usable_space())?;
|
||||
let BTreeCell::IndexLeafCell(IndexLeafCell {
|
||||
payload,
|
||||
first_overflow_page,
|
||||
@@ -2139,12 +2091,10 @@ impl BTreeCursor {
|
||||
// if the cell index is less than the total cells, check: if its an existing
|
||||
// rowid, we are going to update / overwrite the cell
|
||||
if cell_idx < page.get().get_contents().cell_count() {
|
||||
let cell = page.get().get_contents().cell_get(
|
||||
cell_idx,
|
||||
payload_overflow_threshold_max(page_type, self.usable_space() as u16),
|
||||
payload_overflow_threshold_min(page_type, self.usable_space() as u16),
|
||||
self.usable_space(),
|
||||
)?;
|
||||
let cell = page
|
||||
.get()
|
||||
.get_contents()
|
||||
.cell_get(cell_idx, self.usable_space())?;
|
||||
match cell {
|
||||
BTreeCell::TableLeafCell(tbl_leaf) => {
|
||||
if tbl_leaf.rowid == bkey.to_rowid() {
|
||||
@@ -2429,14 +2379,6 @@ impl BTreeCursor {
|
||||
} else {
|
||||
let (start_of_cell, _) = parent_contents.cell_get_raw_region(
|
||||
first_cell_divider + sibling_pointer,
|
||||
payload_overflow_threshold_max(
|
||||
parent_contents.page_type(),
|
||||
self.usable_space() as u16,
|
||||
),
|
||||
payload_overflow_threshold_min(
|
||||
parent_contents.page_type(),
|
||||
self.usable_space() as u16,
|
||||
),
|
||||
self.usable_space(),
|
||||
);
|
||||
let buf = parent_contents.as_ptr().as_mut_ptr();
|
||||
@@ -2472,18 +2414,7 @@ impl BTreeCursor {
|
||||
break;
|
||||
}
|
||||
let next_cell_divider = i + first_cell_divider - 1;
|
||||
pgno = match parent_contents.cell_get(
|
||||
next_cell_divider,
|
||||
payload_overflow_threshold_max(
|
||||
parent_contents.page_type(),
|
||||
self.usable_space() as u16,
|
||||
),
|
||||
payload_overflow_threshold_min(
|
||||
parent_contents.page_type(),
|
||||
self.usable_space() as u16,
|
||||
),
|
||||
self.usable_space(),
|
||||
)? {
|
||||
pgno = match parent_contents.cell_get(next_cell_divider, self.usable_space())? {
|
||||
BTreeCell::TableInteriorCell(table_interior_cell) => {
|
||||
table_interior_cell.left_child_page
|
||||
}
|
||||
@@ -2571,18 +2502,8 @@ impl BTreeCursor {
|
||||
}
|
||||
// Since we know we have a left sibling, take the divider that points to left sibling of this page
|
||||
let cell_idx = balance_info.first_divider_cell + i;
|
||||
let (cell_start, cell_len) = parent_contents.cell_get_raw_region(
|
||||
cell_idx,
|
||||
payload_overflow_threshold_max(
|
||||
parent_contents.page_type(),
|
||||
self.usable_space() as u16,
|
||||
),
|
||||
payload_overflow_threshold_min(
|
||||
parent_contents.page_type(),
|
||||
self.usable_space() as u16,
|
||||
),
|
||||
self.usable_space(),
|
||||
);
|
||||
let (cell_start, cell_len) =
|
||||
parent_contents.cell_get_raw_region(cell_idx, self.usable_space());
|
||||
let buf = parent_contents.as_ptr();
|
||||
let cell_buf = &buf[cell_start..cell_start + cell_len];
|
||||
max_cells += 1;
|
||||
@@ -2634,18 +2555,8 @@ impl BTreeCursor {
|
||||
let old_page_contents = old_page.get_contents();
|
||||
debug_validate_cells!(&old_page_contents, self.usable_space() as u16);
|
||||
for cell_idx in 0..old_page_contents.cell_count() {
|
||||
let (cell_start, cell_len) = old_page_contents.cell_get_raw_region(
|
||||
cell_idx,
|
||||
payload_overflow_threshold_max(
|
||||
old_page_contents.page_type(),
|
||||
self.usable_space() as u16,
|
||||
),
|
||||
payload_overflow_threshold_min(
|
||||
old_page_contents.page_type(),
|
||||
self.usable_space() as u16,
|
||||
),
|
||||
self.usable_space(),
|
||||
);
|
||||
let (cell_start, cell_len) =
|
||||
old_page_contents.cell_get_raw_region(cell_idx, self.usable_space());
|
||||
let buf = old_page_contents.as_ptr();
|
||||
let cell_buf = &mut buf[cell_start..cell_start + cell_len];
|
||||
// TODO(pere): make this reference and not copy
|
||||
@@ -3267,18 +3178,8 @@ impl BTreeCursor {
|
||||
page: &std::sync::Arc<crate::Page>,
|
||||
) {
|
||||
let left_pointer = if parent_contents.overflow_cells.is_empty() {
|
||||
let (cell_start, cell_len) = parent_contents.cell_get_raw_region(
|
||||
balance_info.first_divider_cell + i,
|
||||
payload_overflow_threshold_max(
|
||||
parent_contents.page_type(),
|
||||
self.usable_space() as u16,
|
||||
),
|
||||
payload_overflow_threshold_min(
|
||||
parent_contents.page_type(),
|
||||
self.usable_space() as u16,
|
||||
),
|
||||
self.usable_space(),
|
||||
);
|
||||
let (cell_start, cell_len) = parent_contents
|
||||
.cell_get_raw_region(balance_info.first_divider_cell + i, self.usable_space());
|
||||
tracing::debug!(
|
||||
"balance_non_root(cell_start={}, cell_len={})",
|
||||
cell_start,
|
||||
@@ -3323,18 +3224,7 @@ impl BTreeCursor {
|
||||
let mut current_index_cell = 0;
|
||||
for cell_idx in 0..parent_contents.cell_count() {
|
||||
let cell = parent_contents
|
||||
.cell_get(
|
||||
cell_idx,
|
||||
payload_overflow_threshold_max(
|
||||
parent_contents.page_type(),
|
||||
self.usable_space() as u16,
|
||||
),
|
||||
payload_overflow_threshold_min(
|
||||
parent_contents.page_type(),
|
||||
self.usable_space() as u16,
|
||||
),
|
||||
self.usable_space(),
|
||||
)
|
||||
.cell_get(cell_idx, self.usable_space())
|
||||
.unwrap();
|
||||
match cell {
|
||||
BTreeCell::TableInteriorCell(table_interior_cell) => {
|
||||
@@ -3372,18 +3262,8 @@ impl BTreeCursor {
|
||||
debug_validate_cells!(contents, self.usable_space() as u16);
|
||||
// Cells are distributed in order
|
||||
for cell_idx in 0..contents.cell_count() {
|
||||
let (cell_start, cell_len) = contents.cell_get_raw_region(
|
||||
cell_idx,
|
||||
payload_overflow_threshold_max(
|
||||
contents.page_type(),
|
||||
self.usable_space() as u16,
|
||||
),
|
||||
payload_overflow_threshold_min(
|
||||
contents.page_type(),
|
||||
self.usable_space() as u16,
|
||||
),
|
||||
self.usable_space(),
|
||||
);
|
||||
let (cell_start, cell_len) =
|
||||
contents.cell_get_raw_region(cell_idx, self.usable_space());
|
||||
let buf = contents.as_ptr();
|
||||
let cell_buf = to_static_buf(&mut buf[cell_start..cell_start + cell_len]);
|
||||
let cell_buf_in_array = &cells_debug[current_index_cell];
|
||||
@@ -3397,16 +3277,8 @@ impl BTreeCursor {
|
||||
|
||||
let cell = crate::storage::sqlite3_ondisk::read_btree_cell(
|
||||
cell_buf,
|
||||
&page_type,
|
||||
contents,
|
||||
0,
|
||||
payload_overflow_threshold_max(
|
||||
parent_contents.page_type(),
|
||||
self.usable_space() as u16,
|
||||
),
|
||||
payload_overflow_threshold_min(
|
||||
parent_contents.page_type(),
|
||||
self.usable_space() as u16,
|
||||
),
|
||||
self.usable_space(),
|
||||
)
|
||||
.unwrap();
|
||||
@@ -3540,31 +3412,11 @@ impl BTreeCursor {
|
||||
for (parent_cell_idx, cell_buf_in_array) in
|
||||
cells_debug.iter().enumerate().take(contents.cell_count())
|
||||
{
|
||||
let (parent_cell_start, parent_cell_len) = parent_contents.cell_get_raw_region(
|
||||
parent_cell_idx,
|
||||
payload_overflow_threshold_max(
|
||||
parent_contents.page_type(),
|
||||
self.usable_space() as u16,
|
||||
),
|
||||
payload_overflow_threshold_min(
|
||||
parent_contents.page_type(),
|
||||
self.usable_space() as u16,
|
||||
),
|
||||
self.usable_space(),
|
||||
);
|
||||
let (parent_cell_start, parent_cell_len) =
|
||||
parent_contents.cell_get_raw_region(parent_cell_idx, self.usable_space());
|
||||
|
||||
let (cell_start, cell_len) = contents.cell_get_raw_region(
|
||||
parent_cell_idx,
|
||||
payload_overflow_threshold_max(
|
||||
contents.page_type(),
|
||||
self.usable_space() as u16,
|
||||
),
|
||||
payload_overflow_threshold_min(
|
||||
contents.page_type(),
|
||||
self.usable_space() as u16,
|
||||
),
|
||||
self.usable_space(),
|
||||
);
|
||||
let (cell_start, cell_len) =
|
||||
contents.cell_get_raw_region(parent_cell_idx, self.usable_space());
|
||||
|
||||
let buf = contents.as_ptr();
|
||||
let cell_buf = to_static_buf(&mut buf[cell_start..cell_start + cell_len]);
|
||||
@@ -3622,18 +3474,8 @@ impl BTreeCursor {
|
||||
}
|
||||
// check if overflow
|
||||
// check if right pointer, this is the last page. Do we update rightmost pointer and defragment moves it?
|
||||
let (cell_start, cell_len) = parent_contents.cell_get_raw_region(
|
||||
cell_divider_idx,
|
||||
payload_overflow_threshold_max(
|
||||
parent_contents.page_type(),
|
||||
self.usable_space() as u16,
|
||||
),
|
||||
payload_overflow_threshold_min(
|
||||
parent_contents.page_type(),
|
||||
self.usable_space() as u16,
|
||||
),
|
||||
self.usable_space(),
|
||||
);
|
||||
let (cell_start, cell_len) =
|
||||
parent_contents.cell_get_raw_region(cell_divider_idx, self.usable_space());
|
||||
let cell_left_pointer = read_u32(&parent_buf[cell_start..cell_start + cell_len], 0);
|
||||
if cell_left_pointer != page.get().id as u32 {
|
||||
tracing::error!("balance_non_root(cell_divider_left_pointer, should point to page_id={}, but points to {}, divider_cell={}, overflow_cells_parent={})",
|
||||
@@ -3655,32 +3497,13 @@ impl BTreeCursor {
|
||||
to_static_buf(&mut cells_debug[current_index_cell - 1]);
|
||||
let cell = crate::storage::sqlite3_ondisk::read_btree_cell(
|
||||
cell_buf,
|
||||
&page_type,
|
||||
contents,
|
||||
0,
|
||||
payload_overflow_threshold_max(
|
||||
parent_contents.page_type(),
|
||||
self.usable_space() as u16,
|
||||
),
|
||||
payload_overflow_threshold_min(
|
||||
parent_contents.page_type(),
|
||||
self.usable_space() as u16,
|
||||
),
|
||||
self.usable_space(),
|
||||
)
|
||||
.unwrap();
|
||||
let parent_cell = parent_contents
|
||||
.cell_get(
|
||||
cell_divider_idx,
|
||||
payload_overflow_threshold_max(
|
||||
parent_contents.page_type(),
|
||||
self.usable_space() as u16,
|
||||
),
|
||||
payload_overflow_threshold_min(
|
||||
parent_contents.page_type(),
|
||||
self.usable_space() as u16,
|
||||
),
|
||||
self.usable_space(),
|
||||
)
|
||||
.cell_get(cell_divider_idx, self.usable_space())
|
||||
.unwrap();
|
||||
let rowid = match cell {
|
||||
BTreeCell::TableLeafCell(table_leaf_cell) => table_leaf_cell.rowid,
|
||||
@@ -3727,18 +3550,8 @@ impl BTreeCursor {
|
||||
}
|
||||
continue;
|
||||
}
|
||||
let (parent_cell_start, parent_cell_len) = parent_contents.cell_get_raw_region(
|
||||
cell_divider_idx,
|
||||
payload_overflow_threshold_max(
|
||||
parent_contents.page_type(),
|
||||
self.usable_space() as u16,
|
||||
),
|
||||
payload_overflow_threshold_min(
|
||||
parent_contents.page_type(),
|
||||
self.usable_space() as u16,
|
||||
),
|
||||
self.usable_space(),
|
||||
);
|
||||
let (parent_cell_start, parent_cell_len) =
|
||||
parent_contents.cell_get_raw_region(cell_divider_idx, self.usable_space());
|
||||
let cell_buf_in_array = &cells_debug[current_index_cell];
|
||||
let left_pointer = read_u32(
|
||||
&parent_buf[parent_cell_start..parent_cell_start + parent_cell_len],
|
||||
@@ -3886,12 +3699,7 @@ impl BTreeCursor {
|
||||
while low <= high && cell_count > 0 {
|
||||
let mid = low + (high - low) / 2;
|
||||
self.find_cell_state.set((low, high));
|
||||
let cell = match page.cell_get(
|
||||
mid,
|
||||
payload_overflow_threshold_max(page.page_type(), self.usable_space() as u16),
|
||||
payload_overflow_threshold_min(page.page_type(), self.usable_space() as u16),
|
||||
self.usable_space(),
|
||||
) {
|
||||
let cell = match page.cell_get(mid, self.usable_space()) {
|
||||
Ok(c) => c,
|
||||
Err(e) => return Err(e),
|
||||
};
|
||||
@@ -4074,12 +3882,7 @@ impl BTreeCursor {
|
||||
let page = page.get();
|
||||
let contents = page.get_contents();
|
||||
let cell_idx = self.stack.current_cell_index();
|
||||
let cell = contents.cell_get(
|
||||
cell_idx as usize,
|
||||
payload_overflow_threshold_max(contents.page_type(), self.usable_space() as u16),
|
||||
payload_overflow_threshold_min(contents.page_type(), self.usable_space() as u16),
|
||||
self.usable_space(),
|
||||
)?;
|
||||
let cell = contents.cell_get(cell_idx as usize, self.usable_space())?;
|
||||
if page_type.is_table() {
|
||||
let BTreeCell::TableLeafCell(TableLeafCell { rowid, .. }) = cell else {
|
||||
unreachable!(
|
||||
@@ -4144,12 +3947,7 @@ impl BTreeCursor {
|
||||
let page = page.get();
|
||||
let contents = page.get_contents();
|
||||
let cell_idx = self.stack.current_cell_index();
|
||||
let cell = contents.cell_get(
|
||||
cell_idx as usize,
|
||||
payload_overflow_threshold_max(contents.page_type(), self.usable_space() as u16),
|
||||
payload_overflow_threshold_min(contents.page_type(), self.usable_space() as u16),
|
||||
self.usable_space(),
|
||||
)?;
|
||||
let cell = contents.cell_get(cell_idx as usize, self.usable_space())?;
|
||||
let (payload, payload_size, first_overflow_page) = match cell {
|
||||
BTreeCell::TableLeafCell(TableLeafCell {
|
||||
payload,
|
||||
@@ -4354,18 +4152,7 @@ impl BTreeCursor {
|
||||
cell_idx
|
||||
);
|
||||
|
||||
let cell = contents.cell_get(
|
||||
cell_idx,
|
||||
payload_overflow_threshold_max(
|
||||
contents.page_type(),
|
||||
self.usable_space() as u16,
|
||||
),
|
||||
payload_overflow_threshold_min(
|
||||
contents.page_type(),
|
||||
self.usable_space() as u16,
|
||||
),
|
||||
self.usable_space(),
|
||||
)?;
|
||||
let cell = contents.cell_get(cell_idx, self.usable_space())?;
|
||||
|
||||
let original_child_pointer = match &cell {
|
||||
BTreeCell::TableInteriorCell(interior) => Some(interior.left_child_page),
|
||||
@@ -4432,18 +4219,8 @@ impl BTreeCursor {
|
||||
assert!(leaf_contents.is_leaf());
|
||||
assert!(leaf_contents.cell_count() > 0);
|
||||
let leaf_cell_idx = leaf_contents.cell_count() - 1;
|
||||
let last_cell_on_child_page = leaf_contents.cell_get(
|
||||
leaf_cell_idx,
|
||||
payload_overflow_threshold_max(
|
||||
leaf_contents.page_type(),
|
||||
self.usable_space() as u16,
|
||||
),
|
||||
payload_overflow_threshold_min(
|
||||
leaf_contents.page_type(),
|
||||
self.usable_space() as u16,
|
||||
),
|
||||
self.usable_space(),
|
||||
)?;
|
||||
let last_cell_on_child_page =
|
||||
leaf_contents.cell_get(leaf_cell_idx, self.usable_space())?;
|
||||
|
||||
let mut cell_payload: Vec<u8> = Vec::new();
|
||||
let child_pointer =
|
||||
@@ -4798,18 +4575,7 @@ impl BTreeCursor {
|
||||
|
||||
// We have not yet processed all cells in this page
|
||||
// Get the current cell
|
||||
let cell = contents.cell_get(
|
||||
cell_idx as usize,
|
||||
payload_overflow_threshold_max(
|
||||
contents.page_type(),
|
||||
self.usable_space() as u16,
|
||||
),
|
||||
payload_overflow_threshold_min(
|
||||
contents.page_type(),
|
||||
self.usable_space() as u16,
|
||||
),
|
||||
self.usable_space(),
|
||||
)?;
|
||||
let cell = contents.cell_get(cell_idx as usize, self.usable_space())?;
|
||||
|
||||
match contents.is_leaf() {
|
||||
// For a leaf cell, clear the overflow pages associated with this cell
|
||||
@@ -4926,12 +4692,7 @@ impl BTreeCursor {
|
||||
let (old_offset, old_local_size) = {
|
||||
let page_ref = page_ref.get();
|
||||
let page = page_ref.get().contents.as_ref().unwrap();
|
||||
page.cell_get_raw_region(
|
||||
cell_idx,
|
||||
payload_overflow_threshold_max(page_type, self.usable_space() as u16),
|
||||
payload_overflow_threshold_min(page_type, self.usable_space() as u16),
|
||||
self.usable_space(),
|
||||
)
|
||||
page.cell_get_raw_region(cell_idx, self.usable_space())
|
||||
};
|
||||
|
||||
// if it all fits in local space and old_local_size is enough, do an in-place overwrite
|
||||
@@ -5059,18 +4820,7 @@ impl BTreeCursor {
|
||||
self.stack.push(mem_page);
|
||||
} else {
|
||||
// Move to child left page
|
||||
let cell = contents.cell_get(
|
||||
cell_idx,
|
||||
payload_overflow_threshold_max(
|
||||
contents.page_type(),
|
||||
self.usable_space() as u16,
|
||||
),
|
||||
payload_overflow_threshold_min(
|
||||
contents.page_type(),
|
||||
self.usable_space() as u16,
|
||||
),
|
||||
self.usable_space(),
|
||||
)?;
|
||||
let cell = contents.cell_get(cell_idx, self.usable_space())?;
|
||||
|
||||
match cell {
|
||||
BTreeCell::TableInteriorCell(TableInteriorCell {
|
||||
@@ -5267,12 +5017,8 @@ pub fn integrity_check(
|
||||
// have seen.
|
||||
let mut next_rowid = max_intkey;
|
||||
for cell_idx in (0..contents.cell_count()).rev() {
|
||||
let (cell_start, cell_length) = contents.cell_get_raw_region(
|
||||
cell_idx,
|
||||
payload_overflow_threshold_max(contents.page_type(), usable_space),
|
||||
payload_overflow_threshold_min(contents.page_type(), usable_space),
|
||||
usable_space as usize,
|
||||
);
|
||||
let (cell_start, cell_length) =
|
||||
contents.cell_get_raw_region(cell_idx, usable_space as usize);
|
||||
if cell_start < contents.cell_content_area() as usize
|
||||
|| cell_start > usable_space as usize - 4
|
||||
{
|
||||
@@ -5296,12 +5042,7 @@ pub fn integrity_check(
|
||||
});
|
||||
}
|
||||
coverage_checker.add_cell(cell_start, cell_start + cell_length);
|
||||
let cell = contents.cell_get(
|
||||
cell_idx,
|
||||
payload_overflow_threshold_max(contents.page_type(), usable_space),
|
||||
payload_overflow_threshold_min(contents.page_type(), usable_space),
|
||||
usable_space as usize,
|
||||
)?;
|
||||
let cell = contents.cell_get(cell_idx, usable_space as usize)?;
|
||||
match cell {
|
||||
BTreeCell::TableInteriorCell(table_interior_cell) => {
|
||||
state.page_stack.push(IntegrityCheckPageEntry {
|
||||
@@ -6104,12 +5845,7 @@ fn defragment_page(page: &PageContent, usable_space: u16) {
|
||||
|
||||
assert!(pc <= last_cell);
|
||||
|
||||
let (_, size) = cloned_page.cell_get_raw_region(
|
||||
i,
|
||||
payload_overflow_threshold_max(page.page_type(), usable_space),
|
||||
payload_overflow_threshold_min(page.page_type(), usable_space),
|
||||
usable_space as usize,
|
||||
);
|
||||
let (_, size) = cloned_page.cell_get_raw_region(i, usable_space as usize);
|
||||
let size = size as u16;
|
||||
cbrk -= size;
|
||||
if cbrk < first_cell || pc + size > usable_space {
|
||||
@@ -6142,12 +5878,7 @@ fn defragment_page(page: &PageContent, usable_space: u16) {
|
||||
/// Only enabled in debug mode, where we ensure that all cells are valid.
|
||||
fn debug_validate_cells_core(page: &PageContent, usable_space: u16) {
|
||||
for i in 0..page.cell_count() {
|
||||
let (offset, size) = page.cell_get_raw_region(
|
||||
i,
|
||||
payload_overflow_threshold_max(page.page_type(), usable_space),
|
||||
payload_overflow_threshold_min(page.page_type(), usable_space),
|
||||
usable_space as usize,
|
||||
);
|
||||
let (offset, size) = page.cell_get_raw_region(i, usable_space as usize);
|
||||
let buf = &page.as_ptr()[offset..offset + size];
|
||||
// E.g. the following table btree cell may just have two bytes:
|
||||
// Payload size 0 (stored as SerialTypeKind::ConstInt0)
|
||||
@@ -6431,7 +6162,7 @@ fn fill_cell_payload(
|
||||
/// - Give a minimum fanout of 4 for index b-trees
|
||||
/// - Ensure enough payload is on the b-tree page that the record header can usually be accessed
|
||||
/// without consulting an overflow page
|
||||
fn payload_overflow_threshold_max(page_type: PageType, usable_space: u16) -> usize {
|
||||
pub fn payload_overflow_threshold_max(page_type: PageType, usable_space: u16) -> usize {
|
||||
match page_type {
|
||||
PageType::IndexInterior | PageType::IndexLeaf => {
|
||||
((usable_space as usize - 12) * 64 / 255) - 23 // Index page formula
|
||||
@@ -6451,7 +6182,7 @@ fn payload_overflow_threshold_max(page_type: PageType, usable_space: u16) -> usi
|
||||
/// - Otherwise: store M bytes on page
|
||||
///
|
||||
/// The remaining bytes are stored on overflow pages in both cases.
|
||||
fn payload_overflow_threshold_min(_page_type: PageType, usable_space: u16) -> usize {
|
||||
pub fn payload_overflow_threshold_min(_page_type: PageType, usable_space: u16) -> usize {
|
||||
// Same formula for all page types
|
||||
((usable_space as usize - 12) * 32 / 255) - 23
|
||||
}
|
||||
@@ -6459,12 +6190,7 @@ fn payload_overflow_threshold_min(_page_type: PageType, usable_space: u16) -> us
|
||||
/// Drop a cell from a page.
|
||||
/// This is done by freeing the range of bytes that the cell occupies.
|
||||
fn drop_cell(page: &mut PageContent, cell_idx: usize, usable_space: u16) -> Result<()> {
|
||||
let (cell_start, cell_len) = page.cell_get_raw_region(
|
||||
cell_idx,
|
||||
payload_overflow_threshold_max(page.page_type(), usable_space),
|
||||
payload_overflow_threshold_min(page.page_type(), usable_space),
|
||||
usable_space as usize,
|
||||
);
|
||||
let (cell_start, cell_len) = page.cell_get_raw_region(cell_idx, usable_space as usize);
|
||||
free_cell_range(page, cell_start as u16, cell_len as u16, usable_space)?;
|
||||
if page.cell_count() > 1 {
|
||||
shift_pointers_left(page, cell_idx);
|
||||
@@ -6523,10 +6249,7 @@ mod tests {
|
||||
use crate::{
|
||||
io::BufferData,
|
||||
storage::{
|
||||
btree::{
|
||||
compute_free_space, fill_cell_payload, payload_overflow_threshold_max,
|
||||
payload_overflow_threshold_min,
|
||||
},
|
||||
btree::{compute_free_space, fill_cell_payload, payload_overflow_threshold_max},
|
||||
sqlite3_ondisk::{BTreeCell, PageContent, PageType},
|
||||
},
|
||||
types::Value,
|
||||
@@ -6573,12 +6296,7 @@ mod tests {
|
||||
}
|
||||
|
||||
fn ensure_cell(page: &mut PageContent, cell_idx: usize, payload: &Vec<u8>) {
|
||||
let cell = page.cell_get_raw_region(
|
||||
cell_idx,
|
||||
payload_overflow_threshold_max(page.page_type(), 4096),
|
||||
payload_overflow_threshold_min(page.page_type(), 4096),
|
||||
4096,
|
||||
);
|
||||
let cell = page.cell_get_raw_region(cell_idx, 4096);
|
||||
tracing::trace!("cell idx={} start={} len={}", cell_idx, cell.0, cell.1);
|
||||
let buf = &page.as_ptr()[cell.0..cell.0 + cell.1];
|
||||
assert_eq!(buf.len(), payload.len());
|
||||
@@ -6674,21 +6392,13 @@ mod tests {
|
||||
// Pin page in order to not drop it in between
|
||||
page.set_dirty();
|
||||
let contents = page.get().contents.as_ref().unwrap();
|
||||
let page_type = contents.page_type();
|
||||
let mut previous_key = None;
|
||||
let mut valid = true;
|
||||
let mut depth = None;
|
||||
debug_validate_cells!(contents, pager.usable_space() as u16);
|
||||
let mut child_pages = Vec::new();
|
||||
for cell_idx in 0..contents.cell_count() {
|
||||
let cell = contents
|
||||
.cell_get(
|
||||
cell_idx,
|
||||
payload_overflow_threshold_max(page_type, 4096),
|
||||
payload_overflow_threshold_min(page_type, 4096),
|
||||
cursor.usable_space(),
|
||||
)
|
||||
.unwrap();
|
||||
let cell = contents.cell_get(cell_idx, cursor.usable_space()).unwrap();
|
||||
let current_depth = match cell {
|
||||
BTreeCell::TableLeafCell(..) => 1,
|
||||
BTreeCell::TableInteriorCell(TableInteriorCell {
|
||||
@@ -6791,18 +6501,10 @@ mod tests {
|
||||
// Pin page in order to not drop it in between loading of different pages. If not contents will be a dangling reference.
|
||||
page.set_dirty();
|
||||
let contents = page.get().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,
|
||||
payload_overflow_threshold_max(page_type, 4096),
|
||||
payload_overflow_threshold_min(page_type, 4096),
|
||||
cursor.usable_space(),
|
||||
)
|
||||
.unwrap();
|
||||
let cell = contents.cell_get(cell_idx, cursor.usable_space()).unwrap();
|
||||
match cell {
|
||||
BTreeCell::TableInteriorCell(cell) => {
|
||||
current.push(format!(
|
||||
@@ -7743,12 +7445,7 @@ mod tests {
|
||||
continue;
|
||||
}
|
||||
let cell_idx = rng.next_u64() as usize % page.cell_count();
|
||||
let (_, len) = page.cell_get_raw_region(
|
||||
cell_idx,
|
||||
payload_overflow_threshold_max(page.page_type(), 4096),
|
||||
payload_overflow_threshold_min(page.page_type(), 4096),
|
||||
usable_space as usize,
|
||||
);
|
||||
let (_, len) = page.cell_get_raw_region(cell_idx, usable_space as usize);
|
||||
drop_cell(page, cell_idx, usable_space).unwrap();
|
||||
total_size -= len as u16 + 2;
|
||||
cells.remove(cell_idx);
|
||||
@@ -7824,12 +7521,7 @@ mod tests {
|
||||
continue;
|
||||
}
|
||||
let cell_idx = rng.next_u64() as usize % page.cell_count();
|
||||
let (_, len) = page.cell_get_raw_region(
|
||||
cell_idx,
|
||||
payload_overflow_threshold_max(page.page_type(), 4096),
|
||||
payload_overflow_threshold_min(page.page_type(), 4096),
|
||||
usable_space as usize,
|
||||
);
|
||||
let (_, len) = page.cell_get_raw_region(cell_idx, usable_space as usize);
|
||||
drop_cell(page, cell_idx, usable_space).unwrap();
|
||||
total_size -= len as u16 + 2;
|
||||
cells.remove(cell_idx);
|
||||
@@ -7979,12 +7671,7 @@ mod tests {
|
||||
assert_eq!(page.cell_count(), 1);
|
||||
defragment_page(page, usable_space);
|
||||
assert_eq!(page.cell_count(), 1);
|
||||
let (start, len) = page.cell_get_raw_region(
|
||||
0,
|
||||
payload_overflow_threshold_max(page.page_type(), 4096),
|
||||
payload_overflow_threshold_min(page.page_type(), 4096),
|
||||
usable_space as usize,
|
||||
);
|
||||
let (start, len) = page.cell_get_raw_region(0, usable_space as usize);
|
||||
let buf = page.as_ptr();
|
||||
assert_eq!(&payload, &buf[start..start + len]);
|
||||
}
|
||||
@@ -8015,12 +7702,7 @@ mod tests {
|
||||
let payload = add_record(0, 0, page, record, &conn);
|
||||
assert_eq!(page.cell_count(), 1);
|
||||
|
||||
let (start, len) = page.cell_get_raw_region(
|
||||
0,
|
||||
payload_overflow_threshold_max(page.page_type(), 4096),
|
||||
payload_overflow_threshold_min(page.page_type(), 4096),
|
||||
usable_space as usize,
|
||||
);
|
||||
let (start, len) = page.cell_get_raw_region(0, usable_space as usize);
|
||||
let buf = page.as_ptr();
|
||||
assert_eq!(&payload, &buf[start..start + len]);
|
||||
}
|
||||
@@ -8052,12 +7734,7 @@ mod tests {
|
||||
let payload = add_record(0, 0, page, record, &conn);
|
||||
assert_eq!(page.cell_count(), 1);
|
||||
|
||||
let (start, len) = page.cell_get_raw_region(
|
||||
0,
|
||||
payload_overflow_threshold_max(page.page_type(), 4096),
|
||||
payload_overflow_threshold_min(page.page_type(), 4096),
|
||||
usable_space as usize,
|
||||
);
|
||||
let (start, len) = page.cell_get_raw_region(0, usable_space as usize);
|
||||
let buf = page.as_ptr();
|
||||
assert_eq!(&payload, &buf[start..start + len]);
|
||||
}
|
||||
@@ -8618,12 +8295,7 @@ mod tests {
|
||||
let contents = page.get_contents();
|
||||
for cell_idx in 0..contents.cell_count() {
|
||||
let buf = contents.as_ptr();
|
||||
let (start, len) = contents.cell_get_raw_region(
|
||||
cell_idx,
|
||||
payload_overflow_threshold_max(contents.page_type(), 4096),
|
||||
payload_overflow_threshold_min(contents.page_type(), 4096),
|
||||
pager.usable_space(),
|
||||
);
|
||||
let (start, len) = contents.cell_get_raw_region(cell_idx, pager.usable_space());
|
||||
cell_array
|
||||
.cells
|
||||
.push(to_static_buf(&mut buf[start..start + len]));
|
||||
@@ -8662,12 +8334,7 @@ mod tests {
|
||||
let mut cell_idx_cloned = if prefix { size } else { 0 };
|
||||
for cell_idx in 0..contents.cell_count() {
|
||||
let buf = contents.as_ptr();
|
||||
let (start, len) = contents.cell_get_raw_region(
|
||||
cell_idx,
|
||||
payload_overflow_threshold_max(contents.page_type(), 4096),
|
||||
payload_overflow_threshold_min(contents.page_type(), 4096),
|
||||
pager.usable_space(),
|
||||
);
|
||||
let (start, len) = contents.cell_get_raw_region(cell_idx, pager.usable_space());
|
||||
let cell_in_page = &buf[start..start + len];
|
||||
let cell_in_array = &cells_cloned[cell_idx_cloned];
|
||||
assert_eq!(cell_in_page, cell_in_array);
|
||||
|
||||
@@ -56,6 +56,7 @@ use crate::storage::btree::offset::{
|
||||
BTREE_CELL_CONTENT_AREA, BTREE_CELL_COUNT, BTREE_FIRST_FREEBLOCK, BTREE_FRAGMENTED_BYTES_COUNT,
|
||||
BTREE_PAGE_TYPE, BTREE_RIGHTMOST_PTR,
|
||||
};
|
||||
use crate::storage::btree::{payload_overflow_threshold_max, payload_overflow_threshold_min};
|
||||
use crate::storage::buffer_pool::BufferPool;
|
||||
use crate::storage::database::DatabaseStorage;
|
||||
use crate::storage::pager::Pager;
|
||||
@@ -536,13 +537,7 @@ impl PageContent {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn cell_get(
|
||||
&self,
|
||||
idx: usize,
|
||||
payload_overflow_threshold_max: usize,
|
||||
payload_overflow_threshold_min: usize,
|
||||
usable_size: usize,
|
||||
) -> Result<BTreeCell> {
|
||||
pub fn cell_get(&self, idx: usize, usable_size: usize) -> Result<BTreeCell> {
|
||||
tracing::trace!("cell_get(idx={})", idx);
|
||||
let buf = self.as_ptr();
|
||||
|
||||
@@ -560,14 +555,7 @@ impl PageContent {
|
||||
// SAFETY: this buffer is valid as long as the page is alive. We could store the page in the cell and do some lifetime magic
|
||||
// but that is extra memory for no reason at all. Just be careful like in the old times :).
|
||||
let static_buf: &'static [u8] = unsafe { std::mem::transmute::<&[u8], &'static [u8]>(buf) };
|
||||
read_btree_cell(
|
||||
static_buf,
|
||||
&self.page_type(),
|
||||
cell_pointer,
|
||||
payload_overflow_threshold_max,
|
||||
payload_overflow_threshold_min,
|
||||
usable_size,
|
||||
)
|
||||
read_btree_cell(static_buf, self, cell_pointer, usable_size)
|
||||
}
|
||||
|
||||
/// Read the rowid of a table interior cell.
|
||||
@@ -629,13 +617,7 @@ impl PageContent {
|
||||
}
|
||||
|
||||
/// Get region(start end length) of a cell's payload
|
||||
pub fn cell_get_raw_region(
|
||||
&self,
|
||||
idx: usize,
|
||||
payload_overflow_threshold_max: usize,
|
||||
payload_overflow_threshold_min: usize,
|
||||
usable_size: usize,
|
||||
) -> (usize, usize) {
|
||||
pub fn cell_get_raw_region(&self, idx: usize, usable_size: usize) -> (usize, usize) {
|
||||
let buf = self.as_ptr();
|
||||
let ncells = self.cell_count();
|
||||
let (cell_pointer_array_start, _) = self.cell_pointer_array_offset_and_size();
|
||||
@@ -643,6 +625,10 @@ impl PageContent {
|
||||
let cell_pointer = cell_pointer_array_start + (idx * CELL_POINTER_SIZE_BYTES);
|
||||
let cell_pointer = self.read_u16_no_offset(cell_pointer) as usize;
|
||||
let start = cell_pointer;
|
||||
let payload_overflow_threshold_max =
|
||||
payload_overflow_threshold_max(self.page_type(), usable_size as u16);
|
||||
let payload_overflow_threshold_min =
|
||||
payload_overflow_threshold_min(self.page_type(), usable_size as u16);
|
||||
let len = match self.page_type() {
|
||||
PageType::IndexInterior => {
|
||||
let (len_payload, n_payload) = read_varint(&buf[cell_pointer + 4..]).unwrap();
|
||||
@@ -890,12 +876,13 @@ pub struct IndexLeafCell {
|
||||
/// buffer input "page" is static because we want the cell to point to the data in the page in case it has any payload.
|
||||
pub fn read_btree_cell(
|
||||
page: &'static [u8],
|
||||
page_type: &PageType,
|
||||
page_content: &PageContent,
|
||||
pos: usize,
|
||||
max_local: usize,
|
||||
min_local: usize,
|
||||
usable_size: usize,
|
||||
) -> Result<BTreeCell> {
|
||||
let page_type = page_content.page_type();
|
||||
let max_local = payload_overflow_threshold_max(page_type, usable_size as u16);
|
||||
let min_local = payload_overflow_threshold_min(page_type, usable_size as u16);
|
||||
match page_type {
|
||||
PageType::IndexInterior => {
|
||||
let mut pos = pos;
|
||||
|
||||
Reference in New Issue
Block a user