From 30c7bef27ba00849a0ead4057d190c718f577184 Mon Sep 17 00:00:00 2001 From: Nikita Sivukhin Date: Wed, 23 Jul 2025 18:28:41 +0400 Subject: [PATCH] make add dirty to change flag and also add page to the dirty list --- core/storage/btree.rs | 34 ++++++++++++++++----------------- core/storage/header_accessor.rs | 6 ++---- core/storage/pager.rs | 18 +++++++---------- 3 files changed, 26 insertions(+), 32 deletions(-) diff --git a/core/storage/btree.rs b/core/storage/btree.rs index 3139ac492..c549ee547 100644 --- a/core/storage/btree.rs +++ b/core/storage/btree.rs @@ -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. { diff --git a/core/storage/header_accessor.rs b/core/storage/header_accessor.rs index 33edbfe37..5258c97f1 100644 --- a/core/storage/header_accessor.rs +++ b/core/storage/header_accessor.rs @@ -59,8 +59,7 @@ fn get_header_page_for_write(pager: &Pager) -> Result> { 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(())) } diff --git a/core/storage/pager.rs b/core/storage/pager.rs index 777f22a69..c63ebbdf6 100644 --- a/core/storage/pager.rs +++ b/core/storage/pager.rs @@ -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 { @@ -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();