make add dirty to change flag and also add page to the dirty list

This commit is contained in:
Nikita Sivukhin
2025-07-23 18:28:41 +04:00
parent 1e38202084
commit 30c7bef27b
3 changed files with 26 additions and 32 deletions

View File

@@ -1152,8 +1152,7 @@ impl BTreeCursor {
buffer: &mut [u8],
page: BTreePage,
) {
page.get().set_dirty();
self.pager.add_dirty(page.get().get().id);
self.pager.add_dirty(page.get().get().id, &page.get());
// SAFETY: This is safe as long as the page is not evicted from the cache.
let payload_mut =
unsafe { std::slice::from_raw_parts_mut(payload.as_ptr() as *mut u8, payload.len()) };
@@ -2127,8 +2126,7 @@ impl BTreeCursor {
return_if_locked!(page.get());
let page = page.get();
page.set_dirty();
self.pager.add_dirty(page.get().id);
self.pager.add_dirty(page.get().id, &page);
self.stack.current_cell_index()
};
@@ -2389,8 +2387,7 @@ impl BTreeCursor {
// to prevent panic in the asserts below due to -1 index
self.stack.advance();
}
parent_page.set_dirty();
self.pager.add_dirty(parent_page.get().id);
self.pager.add_dirty(parent_page.get().id, &parent_page);
let parent_contents = parent_page.get().contents.as_ref().unwrap();
let page_to_balance_idx = self.stack.current_cell_index() as usize;
@@ -2469,8 +2466,7 @@ impl BTreeCursor {
{
// mark as dirty
let sibling_page = page.get();
sibling_page.set_dirty();
self.pager.add_dirty(sibling_page.get().id);
self.pager.add_dirty(sibling_page.get().id, &sibling_page);
}
#[cfg(debug_assertions)]
{
@@ -2964,7 +2960,10 @@ impl BTreeCursor {
for i in 0..sibling_count_new {
if i < balance_info.sibling_count {
let page = balance_info.pages_to_balance[i].as_ref().unwrap();
page.get().set_dirty();
turso_assert!(
page.get().is_dirty(),
"sibling page must be already marked dirty"
);
pages_to_balance_new[i].replace(page.clone());
} else {
// FIXME: handle page cache is full
@@ -3865,8 +3864,11 @@ impl BTreeCursor {
root.get_contents().page_type()
);
self.pager.add_dirty(root.get().id);
self.pager.add_dirty(child_btree.get().get().id);
turso_assert!(root.is_dirty(), "root must be marked dirty");
turso_assert!(
child_btree.get().is_dirty(),
"child must be marked dirty as freshly allocated page"
);
let root_buf = root_contents.as_ptr();
let child = child_btree.get();
@@ -4285,8 +4287,7 @@ impl BTreeCursor {
match delete_state {
DeleteState::Start => {
let page = self.stack.top();
page.get().set_dirty();
self.pager.add_dirty(page.get().get().id);
self.pager.add_dirty(page.get().get().id, &page.get());
if matches!(
page.get().get_contents().page_type(),
PageType::TableLeaf | PageType::TableInterior
@@ -4469,10 +4470,9 @@ impl BTreeCursor {
let leaf_page = self.stack.top();
page.set_dirty();
self.pager.add_dirty(page.get().id);
leaf_page.get().set_dirty();
self.pager.add_dirty(leaf_page.get().get().id);
self.pager.add_dirty(page.get().id, &page);
self.pager
.add_dirty(leaf_page.get().get().id, &leaf_page.get());
// Step 2: Replace the cell in the parent (interior) page.
{

View File

@@ -59,8 +59,7 @@ fn get_header_page_for_write(pager: &Pager) -> Result<IOResult<PageRef>> {
if page.is_locked() {
return Ok(IOResult::IO);
}
page.set_dirty();
pager.add_dirty(DATABASE_HEADER_PAGE_ID);
pager.add_dirty(DATABASE_HEADER_PAGE_ID, &page);
Ok(IOResult::Done(page))
}
@@ -143,8 +142,7 @@ macro_rules! impl_header_field_accessor {
let mut buf = page_content.buffer.borrow_mut();
let buf_slice = buf.as_mut_slice();
buf_slice[$offset..$offset + std::mem::size_of::<$type>()].copy_from_slice(&value.to_be_bytes());
page.set_dirty();
pager.add_dirty(1);
pager.add_dirty(1, &page);
Ok(IOResult::Done(()))
}

View File

@@ -580,8 +580,7 @@ impl Pager {
[offset_in_ptrmap_page..offset_in_ptrmap_page + PTRMAP_ENTRY_SIZE],
)?;
ptrmap_page.set_dirty();
self.add_dirty(ptrmap_pg_no as usize);
self.add_dirty(ptrmap_pg_no as usize, &ptrmap_page);
Ok(IOResult::Done(()))
}
@@ -874,10 +873,11 @@ impl Pager {
Ok(page_cache.resize(capacity))
}
pub fn add_dirty(&self, page_id: usize) {
pub fn add_dirty(&self, page_id: usize, page: &Page) {
// TODO: check duplicates?
let mut dirty_pages = RefCell::borrow_mut(&self.dirty_pages);
dirty_pages.insert(page_id);
page.set_dirty();
}
pub fn wal_frame_count(&self) -> Result<u64> {
@@ -1197,8 +1197,7 @@ impl Pager {
(self.usable_space() / LEAF_ENTRY_SIZE) - RESERVED_SLOTS;
if number_of_leaf_pages < max_free_list_entries as u32 {
trunk_page.set_dirty();
self.add_dirty(trunk_page_id as usize);
self.add_dirty(trunk_page_id as usize, &trunk_page);
trunk_page_contents
.write_u32(TRUNK_PAGE_LEAF_COUNT_OFFSET, number_of_leaf_pages + 1);
@@ -1218,8 +1217,7 @@ impl Pager {
return Ok(IOResult::IO);
}
// If we get here, need to make this page a new trunk
page.set_dirty();
self.add_dirty(page_id);
self.add_dirty(page_id, &page);
let trunk_page_id = header_accessor::get_freelist_trunk_page(self)?;
@@ -1333,8 +1331,7 @@ impl Pager {
&& is_ptrmap_page(new_db_size, header_accessor::get_page_size(self)? as usize)
{
let page = allocate_page(new_db_size as usize, &self.buffer_pool, 0);
page.set_dirty();
self.add_dirty(page.get().id);
self.add_dirty(page.get().id, &page);
let page_key = PageCacheKey::new(page.get().id);
let mut cache = self.page_cache.write();
@@ -1358,8 +1355,7 @@ impl Pager {
let page = allocate_page(new_db_size as usize, &self.buffer_pool, 0);
{
// setup page and add to cache
page.set_dirty();
self.add_dirty(page.get().id);
self.add_dirty(page.get().id, &page);
let page_key = PageCacheKey::new(page.get().id);
let mut cache = self.page_cache.write();