From 506c1a236cf00b741a5c1b4795b56698e0ca9841 Mon Sep 17 00:00:00 2001 From: Pere Diaz Bou Date: Thu, 10 Apr 2025 18:08:29 +0200 Subject: [PATCH 1/3] find_free_cell fix use of `no_offset` writes --- core/storage/btree.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/core/storage/btree.rs b/core/storage/btree.rs index 001049dfb..e3405322a 100644 --- a/core/storage/btree.rs +++ b/core/storage/btree.rs @@ -4117,7 +4117,7 @@ fn find_free_cell(page_ref: &PageContent, usable_space: u16, amount: usize) -> R return Ok(0); } // Delete the slot from freelist and update the page's fragment count. - page_ref.write_u16(prev_pc, next); + page_ref.write_u16_no_offset(prev_pc, next); let frag = page_ref.num_frag_free_bytes() + new_size as u8; page_ref.write_u8(offset::BTREE_FRAGMENTED_BYTES_COUNT, frag); return Ok(pc); @@ -4126,7 +4126,7 @@ fn find_free_cell(page_ref: &PageContent, usable_space: u16, amount: usize) -> R } else { // Requested amount fits inside the current free slot so we reduce its size // to account for newly allocated space. - page_ref.write_u16(pc + 2, new_size as u16); + page_ref.write_u16_no_offset(pc + 2, new_size as u16); return Ok(pc + new_size); } } From 038d78f0960949d35f2994090740d14ee212d517 Mon Sep 17 00:00:00 2001 From: Pere Diaz Bou Date: Thu, 10 Apr 2025 22:14:30 +0200 Subject: [PATCH 2/3] overwrite when payload is equal size as current cell only Prevoiusly we would overwrite even though size less than cell size. This was wrong because it didn't update any fragment size or free blocks it could. To be safe let's just overwrite only if local size is the same amount. --- core/storage/btree.rs | 47 ++++--------------------------------------- 1 file changed, 4 insertions(+), 43 deletions(-) diff --git a/core/storage/btree.rs b/core/storage/btree.rs index e3405322a..dc6e24e58 100644 --- a/core/storage/btree.rs +++ b/core/storage/btree.rs @@ -1924,6 +1924,7 @@ impl BTreeCursor { let mut count_cells_in_old_pages = Vec::new(); let page_type = balance_info.pages_to_balance[0].get_contents().page_type(); + tracing::debug!("balance_non_root(page_type={:?})", page_type); let leaf_data = matches!(page_type, PageType::TableLeaf); let leaf = matches!(page_type, PageType::TableLeaf | PageType::IndexLeaf); for (i, old_page) in balance_info.pages_to_balance.iter().enumerate() { @@ -3859,25 +3860,8 @@ impl BTreeCursor { }; // if it all fits in local space and old_local_size is enough, do an in-place overwrite - if new_payload.len() <= old_local_size { - self.overwrite_content( - page_ref.clone(), - old_offset, - &new_payload, - 0, - new_payload.len(), - )?; - let remaining = old_local_size - new_payload.len(); - if remaining > 0 { - // fill the rest with zeros - self.overwrite_content( - page_ref.clone(), - old_offset + new_payload.len(), - &[0; 1], - 0, - remaining, - )?; - } + if new_payload.len() == old_local_size { + self.overwrite_content(page_ref.clone(), old_offset, &new_payload)?; Ok(CursorResult::Ok(())) } else { // doesn't fit, drop it and insert a new one @@ -3901,36 +3885,13 @@ impl BTreeCursor { page_ref: PageRef, dest_offset: usize, new_payload: &[u8], - src_offset: usize, - amount: usize, ) -> Result> { return_if_locked!(page_ref); page_ref.set_dirty(); self.pager.add_dirty(page_ref.get().id); let buf = page_ref.get().contents.as_mut().unwrap().as_ptr(); + buf[dest_offset..dest_offset + new_payload.len()].copy_from_slice(&new_payload); - // if new_payload doesn't have enough data, we fill with zeros - let n_data = new_payload.len().saturating_sub(src_offset); - if n_data == 0 { - // everything is zeros - for i in 0..amount { - if buf[dest_offset + i] != 0 { - buf[dest_offset + i] = 0; - } - } - } else { - let copy_len = n_data.min(amount); - // copy the overlapping portion - buf[dest_offset..dest_offset + copy_len] - .copy_from_slice(&new_payload[src_offset..src_offset + copy_len]); - - // if copy_len < amount => fill remainder with 0 - if copy_len < amount { - for i in copy_len..amount { - buf[dest_offset + i] = 0; - } - } - } Ok(CursorResult::Ok(())) } From 745c2b92d0baa81b7242048c6880efe75b2292de Mon Sep 17 00:00:00 2001 From: Pere Diaz Bou Date: Thu, 10 Apr 2025 22:19:09 +0200 Subject: [PATCH 3/3] unnecessary dirty set on overwrite --- core/storage/btree.rs | 2 -- 1 file changed, 2 deletions(-) diff --git a/core/storage/btree.rs b/core/storage/btree.rs index dc6e24e58..9ab993d2d 100644 --- a/core/storage/btree.rs +++ b/core/storage/btree.rs @@ -3887,8 +3887,6 @@ impl BTreeCursor { new_payload: &[u8], ) -> Result> { return_if_locked!(page_ref); - page_ref.set_dirty(); - self.pager.add_dirty(page_ref.get().id); let buf = page_ref.get().contents.as_mut().unwrap().as_ptr(); buf[dest_offset..dest_offset + new_payload.len()].copy_from_slice(&new_payload);