diff --git a/core/storage/pager.rs b/core/storage/pager.rs index 7d1acde7d..f369c9d57 100644 --- a/core/storage/pager.rs +++ b/core/storage/pager.rs @@ -461,6 +461,9 @@ impl Pager { Some(wal) => wal.borrow().get_max_frame(), None => 0, }; + let max_frame_after_append = self.wal.as_ref().map(|wal| { + wal.borrow().get_max_frame() + self.dirty_pages.borrow().len() as u64 + }); for page_id in self.dirty_pages.borrow().iter() { let mut cache = self.page_cache.write(); let page_key = PageCacheKey::new(*page_id, Some(max_frame)); @@ -473,6 +476,17 @@ impl Pager { db_size, self.flush_info.borrow().in_flight_writes.clone(), )?; + // Assuming writer will always end append frames at frameid == this_transaction.max_frame + dirty_pages, + // we can insert this page with a new key into that new "snapshot" that has the newest max frame. We don't + // simply clone the page and insert with new key because next cache.delete will invalidate the contents of the page, + // therefore we need to clone the contents itself and place them on the new page. Cloning contents should be fast because + // buffer is wrapped around an Arc. + let new_page = Page::new(*page_id); + new_page.get().contents = Some(page.get_contents().clone()); + new_page.set_loaded(); + let new_page: Arc = Arc::new(new_page); + let new_page_key = PageCacheKey::new(*page_id, max_frame_after_append); + cache.insert(new_page_key, new_page).map_err(|e| {LimboError::InternalError(format!("Failed to delete page {:?} from cache during flush: {:?}. Might be actively referenced.", page_id, e))})?; } page.clear_dirty(); // This page is no longer valid.