From f0790479b8f293d8f15ebd5b165a60ca6f19c7f1 Mon Sep 17 00:00:00 2001 From: Linwei Zhang Date: Thu, 15 Feb 2024 19:09:42 +0800 Subject: [PATCH] Improve code --- bustubx/src/buffer/buffer_pool.rs | 81 ++++++++++---------- bustubx/src/buffer/replacer.rs | 108 ++++++++++++++------------- bustubx/src/catalog/catalog.rs | 3 +- bustubx/src/storage/index.rs | 118 +++++++++++++++++++++--------- bustubx/src/storage/table_heap.rs | 58 +++++++++------ 5 files changed, 220 insertions(+), 148 deletions(-) diff --git a/bustubx/src/buffer/buffer_pool.rs b/bustubx/src/buffer/buffer_pool.rs index e240891..ec49664 100644 --- a/bustubx/src/buffer/buffer_pool.rs +++ b/bustubx/src/buffer/buffer_pool.rs @@ -11,7 +11,7 @@ use crate::{BustubxError, BustubxResult}; use super::replacer::LRUKReplacer; -pub type FrameId = u32; +pub type FrameId = usize; pub const TABLE_HEAP_BUFFER_POOL_SIZE: usize = 100; @@ -32,7 +32,7 @@ impl BufferPoolManager { pub fn new(num_pages: usize, disk_manager: Arc) -> Self { let mut free_list = VecDeque::with_capacity(num_pages); for i in 0..num_pages { - free_list.push_back(i as FrameId); + free_list.push_back(i); } Self { pool: vec![Arc::new(RwLock::new(Page::new(0))); num_pages], @@ -58,7 +58,7 @@ impl BufferPoolManager { } else { // 无空闲frame,从缓冲池中替换一个页 if let Some(frame_id) = self.replacer.evict() { - let evicted_page = self.pool[frame_id as usize].clone(); + let evicted_page = self.pool[frame_id].clone(); let evicted_page_id = evicted_page.read().unwrap().page_id; // 如果页被修改过,则将其写回磁盘 let is_dirty = evicted_page.read().unwrap().is_dirty; @@ -77,20 +77,20 @@ impl BufferPoolManager { self.page_table.insert(new_page_id, frame_id); let mut new_page = Page::new(new_page_id); new_page.pin_count = 1; - self.pool[frame_id as usize] = Arc::new(RwLock::new(new_page)); + self.pool[frame_id] = Arc::new(RwLock::new(new_page)); - self.replacer.record_access(frame_id); - self.replacer.set_evictable(frame_id, false); + self.replacer.record_access(frame_id)?; + self.replacer.set_evictable(frame_id, false)?; - Ok(self.pool[frame_id as usize].clone()) + Ok(self.pool[frame_id].clone()) } pub fn fetch_page(&mut self, page_id: PageId) -> BustubxResult>> { if self.page_table.contains_key(&page_id) { let frame_id = self.page_table[&page_id]; - let page = self.pool[frame_id as usize].clone(); + let page = self.pool[frame_id].clone(); page.write().unwrap().pin_count += 1; - self.replacer.set_evictable(frame_id, false); + self.replacer.set_evictable(frame_id, false)?; return Ok(page); } else { // 分配一个frame @@ -98,7 +98,7 @@ impl BufferPoolManager { self.free_list.pop_front().unwrap() } else { if let Some(frame_id) = self.replacer.evict() { - let evicted_page = self.pool[frame_id as usize].clone(); + let evicted_page = self.pool[frame_id].clone(); let evicted_page_id = evicted_page.read().unwrap().page_id; let is_dirty = evicted_page.read().unwrap().is_dirty; if is_dirty { @@ -115,40 +115,41 @@ impl BufferPoolManager { let mut new_page = Page::new(page_id); new_page.pin_count = 1; new_page.data = self.disk_manager.read_page(page_id).unwrap(); - self.pool[frame_id as usize] = Arc::new(RwLock::new(new_page)); + self.pool[frame_id] = Arc::new(RwLock::new(new_page)); - self.replacer.record_access(frame_id); - self.replacer.set_evictable(frame_id, false); + self.replacer.record_access(frame_id)?; + self.replacer.set_evictable(frame_id, false)?; - Ok(self.pool[frame_id as usize].clone()) + Ok(self.pool[frame_id].clone()) } } pub fn write_page(&mut self, page_id: PageId, data: [u8; BUSTUBX_PAGE_SIZE]) { if self.page_table.contains_key(&page_id) { let frame_id = self.page_table[&page_id]; - let page = self.pool[frame_id as usize].clone(); + let page = self.pool[frame_id].clone(); page.write().unwrap().data = data; page.write().unwrap().is_dirty = true; } } // 从缓冲池中取消固定页 - pub fn unpin_page(&mut self, page_id: PageId, is_dirty: bool) -> bool { + pub fn unpin_page(&mut self, page_id: PageId, is_dirty: bool) -> BustubxResult { if self.page_table.contains_key(&page_id) { let frame_id = self.page_table[&page_id]; - let page = self.pool[frame_id as usize].clone(); + let page = self.pool[frame_id].clone(); if page.read().unwrap().pin_count == 0 { - return false; + return Ok(false); } page.write().unwrap().pin_count -= 1; page.write().unwrap().is_dirty |= is_dirty; - if page.read().unwrap().pin_count == 0 { - self.replacer.set_evictable(frame_id, true); + let pin_count = page.read().unwrap().pin_count; + if pin_count == 0 { + self.replacer.set_evictable(frame_id, true)?; } - true + Ok(true) } else { - false + Ok(false) } } @@ -156,7 +157,7 @@ impl BufferPoolManager { pub fn flush_page(&mut self, page_id: PageId) -> BustubxResult { if self.page_table.contains_key(&page_id) { let frame_id = self.page_table[&page_id]; - let page = self.pool[frame_id as usize].clone(); + let page = self.pool[frame_id].clone(); self.disk_manager .write_page(page_id, &page.read().unwrap().data)?; page.write().unwrap().is_dirty = false; @@ -176,15 +177,15 @@ impl BufferPoolManager { } // 删除缓冲池中的页 - pub fn delete_page(&mut self, page_id: PageId) -> bool { + pub fn delete_page(&mut self, page_id: PageId) -> BustubxResult { if !self.page_table.contains_key(&page_id) { - return true; + return Ok(true); } let frame_id = self.page_table[&page_id]; - let page = self.pool[frame_id as usize].clone(); + let page = self.pool[frame_id].clone(); if page.read().unwrap().pin_count > 0 { // 页被固定,无法删除 - return false; + return Ok(false); } // 从缓冲池中删除 @@ -194,8 +195,8 @@ impl BufferPoolManager { self.replacer.remove(frame_id); // 从磁盘上删除 - self.disk_manager.deallocate_page(page_id).unwrap(); - return true; + self.disk_manager.deallocate_page(page_id)?; + Ok(true) } } @@ -231,7 +232,7 @@ mod tests { let page = buffer_pool_manager.new_page(); assert!(page.is_err()); - buffer_pool_manager.unpin_page(0, false); + buffer_pool_manager.unpin_page(0, false).unwrap(); let page = buffer_pool_manager.new_page().unwrap(); assert_eq!(page.read().unwrap().page_id, 3); @@ -252,7 +253,7 @@ mod tests { let page = buffer_pool_manager.new_page(); assert!(page.is_err()); - buffer_pool_manager.unpin_page(0, true); + buffer_pool_manager.unpin_page(0, true).unwrap(); let page = buffer_pool_manager.new_page().unwrap(); assert_eq!(page.read().unwrap().page_id, 3); @@ -268,19 +269,19 @@ mod tests { let mut buffer_pool_manager = BufferPoolManager::new(3, Arc::new(disk_manager)); let page = buffer_pool_manager.new_page().unwrap(); - buffer_pool_manager.unpin_page(0, true); + buffer_pool_manager.unpin_page(0, true).unwrap(); let page = buffer_pool_manager.new_page().unwrap(); - buffer_pool_manager.unpin_page(1, false); + buffer_pool_manager.unpin_page(1, false).unwrap(); let page = buffer_pool_manager.new_page().unwrap(); - buffer_pool_manager.unpin_page(2, false); + buffer_pool_manager.unpin_page(2, false).unwrap(); let page = buffer_pool_manager.fetch_page(0).unwrap(); assert_eq!(page.read().unwrap().page_id, 0); - buffer_pool_manager.unpin_page(0, false); + buffer_pool_manager.unpin_page(0, false).unwrap(); let page = buffer_pool_manager.fetch_page(1).unwrap(); assert_eq!(page.read().unwrap().page_id, 1); - buffer_pool_manager.unpin_page(1, false); + buffer_pool_manager.unpin_page(1, false).unwrap(); assert_eq!(buffer_pool_manager.replacer.size(), 3); let _ = remove_file(db_path); @@ -295,13 +296,13 @@ mod tests { let mut buffer_pool_manager = BufferPoolManager::new(3, Arc::new(disk_manager)); let page_id = buffer_pool_manager.new_page().unwrap(); - buffer_pool_manager.unpin_page(0, true); + buffer_pool_manager.unpin_page(0, true).unwrap(); let page_id = buffer_pool_manager.new_page().unwrap(); - buffer_pool_manager.unpin_page(1, true); + buffer_pool_manager.unpin_page(1, true).unwrap(); let page_id = buffer_pool_manager.new_page().unwrap(); - buffer_pool_manager.unpin_page(2, false); + buffer_pool_manager.unpin_page(2, false).unwrap(); - let res = buffer_pool_manager.delete_page(0); + let res = buffer_pool_manager.delete_page(0).unwrap(); assert!(res); assert_eq!(buffer_pool_manager.pool.len(), 3); assert_eq!(buffer_pool_manager.free_list.len(), 1); diff --git a/bustubx/src/buffer/replacer.rs b/bustubx/src/buffer/replacer.rs index fdba408..46acb4b 100644 --- a/bustubx/src/buffer/replacer.rs +++ b/bustubx/src/buffer/replacer.rs @@ -1,3 +1,4 @@ +use crate::{BustubxError, BustubxResult}; use std::collections::{HashMap, LinkedList}; use super::buffer_pool::FrameId; @@ -59,7 +60,7 @@ impl LRUKReplacer { continue; } let k_distance = if node.history.len() < self.k { - std::u64::MAX - node.history.front().unwrap() + u64::MAX - node.history.front().unwrap() } else { self.current_timestamp - node.history.front().unwrap() }; @@ -68,32 +69,34 @@ impl LRUKReplacer { result = Some(*frame_id); } } - if result.is_some() { - self.remove(result.unwrap()); + if let Some(frame_id) = result { + self.remove(frame_id); } result } // 记录frame的访问 - pub fn record_access(&mut self, frame_id: FrameId) { + pub fn record_access(&mut self, frame_id: FrameId) -> BustubxResult<()> { if let Some(node) = self.node_store.get_mut(&frame_id) { node.record_access(self.current_timestamp); self.current_timestamp += 1; } else { // 创建新node - assert!( - self.node_store.len() < self.replacer_size, - "frame size exceeds the limit" - ); + if self.node_store.len() >= self.replacer_size { + return Err(BustubxError::Internal( + "frame size exceeds the limit".to_string(), + )); + } let mut node = LRUKNode::new(frame_id, self.k); node.record_access(self.current_timestamp); self.current_timestamp += 1; self.node_store.insert(frame_id, node); } + Ok(()) } // 设置frame是否可被置换 - pub fn set_evictable(&mut self, frame_id: FrameId, set_evictable: bool) { + pub fn set_evictable(&mut self, frame_id: FrameId, set_evictable: bool) -> BustubxResult<()> { if let Some(node) = self.node_store.get_mut(&frame_id) { let evictable = node.is_evictable; node.is_evictable = set_evictable; @@ -102,8 +105,9 @@ impl LRUKReplacer { } else if !set_evictable && evictable { self.current_size -= 1; } + Ok(()) } else { - panic!("frame not found") + Err(BustubxError::Internal("frame not found".to_string())) } } @@ -129,22 +133,22 @@ mod tests { #[test] pub fn test_lru_k_set_evictable() { let mut replacer = LRUKReplacer::new(3, 2); - replacer.record_access(1); - replacer.set_evictable(1, true); + replacer.record_access(1).unwrap(); + replacer.set_evictable(1, true).unwrap(); assert_eq!(replacer.size(), 1); - replacer.set_evictable(1, false); + replacer.set_evictable(1, false).unwrap(); assert_eq!(replacer.size(), 0); } #[test] pub fn test_lru_k_evict_all_pages_at_least_k() { let mut replacer = LRUKReplacer::new(2, 3); - replacer.record_access(1); - replacer.record_access(2); - replacer.record_access(2); - replacer.record_access(1); - replacer.set_evictable(1, true); - replacer.set_evictable(2, true); + replacer.record_access(1).unwrap(); + replacer.record_access(2).unwrap(); + replacer.record_access(2).unwrap(); + replacer.record_access(1).unwrap(); + replacer.set_evictable(1, true).unwrap(); + replacer.set_evictable(2, true).unwrap(); let frame_id = replacer.evict(); assert_eq!(frame_id, Some(1)); } @@ -152,15 +156,15 @@ mod tests { #[test] pub fn test_lru_k_evict_some_page_less_than_k() { let mut replacer = LRUKReplacer::new(3, 3); - replacer.record_access(1); - replacer.record_access(2); - replacer.record_access(3); - replacer.record_access(1); - replacer.record_access(1); - replacer.record_access(3); - replacer.set_evictable(1, true); - replacer.set_evictable(2, true); - replacer.set_evictable(3, true); + replacer.record_access(1).unwrap(); + replacer.record_access(2).unwrap(); + replacer.record_access(3).unwrap(); + replacer.record_access(1).unwrap(); + replacer.record_access(1).unwrap(); + replacer.record_access(3).unwrap(); + replacer.set_evictable(1, true).unwrap(); + replacer.set_evictable(2, true).unwrap(); + replacer.set_evictable(3, true).unwrap(); let frame_id = replacer.evict(); assert_eq!(frame_id, Some(2)); } @@ -170,23 +174,23 @@ mod tests { let mut lru_replacer = LRUKReplacer::new(7, 2); // Scenario: add six elements to the replacer. We have [1,2,3,4,5]. Frame 6 is non-evictable. - lru_replacer.record_access(1); - lru_replacer.record_access(2); - lru_replacer.record_access(3); - lru_replacer.record_access(4); - lru_replacer.record_access(5); - lru_replacer.record_access(6); - lru_replacer.set_evictable(1, true); - lru_replacer.set_evictable(2, true); - lru_replacer.set_evictable(3, true); - lru_replacer.set_evictable(4, true); - lru_replacer.set_evictable(5, true); - lru_replacer.set_evictable(6, false); + lru_replacer.record_access(1).unwrap(); + lru_replacer.record_access(2).unwrap(); + lru_replacer.record_access(3).unwrap(); + lru_replacer.record_access(4).unwrap(); + lru_replacer.record_access(5).unwrap(); + lru_replacer.record_access(6).unwrap(); + lru_replacer.set_evictable(1, true).unwrap(); + lru_replacer.set_evictable(2, true).unwrap(); + lru_replacer.set_evictable(3, true).unwrap(); + lru_replacer.set_evictable(4, true).unwrap(); + lru_replacer.set_evictable(5, true).unwrap(); + lru_replacer.set_evictable(6, false).unwrap(); assert_eq!(5, lru_replacer.size()); // Scenario: Insert access history for frame 1. Now frame 1 has two access histories. // All other frames have max backward k-dist. The order of eviction is [2,3,4,5,1]. - lru_replacer.record_access(1); + lru_replacer.record_access(1).unwrap(); // Scenario: Evict three pages from the replacer. Elements with max k-distance should be // popped first based on LRU. @@ -200,12 +204,12 @@ mod tests { // Scenario: Now replacer has frames [5,1]. Insert new frames 3, 4, and update access // history for 5. We should end with [3,1,5,4] - lru_replacer.record_access(3); - lru_replacer.record_access(4); - lru_replacer.record_access(5); - lru_replacer.record_access(4); - lru_replacer.set_evictable(3, true); - lru_replacer.set_evictable(4, true); + lru_replacer.record_access(3).unwrap(); + lru_replacer.record_access(4).unwrap(); + lru_replacer.record_access(5).unwrap(); + lru_replacer.record_access(4).unwrap(); + lru_replacer.set_evictable(3, true).unwrap(); + lru_replacer.set_evictable(4, true).unwrap(); assert_eq!(4, lru_replacer.size()); // Scenario: continue looking for victims. We expect 3 to be evicted next. @@ -214,23 +218,23 @@ mod tests { assert_eq!(3, lru_replacer.size()); // Set 6 to be evictable. 6 Should be evicted next since it has max backward k-dist. - lru_replacer.set_evictable(6, true); + lru_replacer.set_evictable(6, true).unwrap(); assert_eq!(4, lru_replacer.size()); let value = lru_replacer.evict(); assert_eq!(Some(6), value); assert_eq!(3, lru_replacer.size()); // Now we have [1,5,4]. Continue looking for victims. - lru_replacer.set_evictable(1, false); + lru_replacer.set_evictable(1, false).unwrap(); assert_eq!(2, lru_replacer.size()); let value = lru_replacer.evict(); assert_eq!(Some(5), value); assert_eq!(1, lru_replacer.size()); // Update access history for 1. Now we have [4,1]. Next victim is 4. - lru_replacer.record_access(1); - lru_replacer.record_access(1); - lru_replacer.set_evictable(1, true); + lru_replacer.record_access(1).unwrap(); + lru_replacer.record_access(1).unwrap(); + lru_replacer.set_evictable(1, true).unwrap(); assert_eq!(2, lru_replacer.size()); let value = lru_replacer.evict(); assert_eq!(Some(4), value); diff --git a/bustubx/src/catalog/catalog.rs b/bustubx/src/catalog/catalog.rs index 72fb353..89091fa 100644 --- a/bustubx/src/catalog/catalog.rs +++ b/bustubx/src/catalog/catalog.rs @@ -8,6 +8,7 @@ use crate::{ index::{BPlusTreeIndex, IndexMetadata}, TableHeap, }, + BustubxResult, }; pub type TableOid = u32; @@ -67,7 +68,7 @@ impl Catalog { TABLE_HEAP_BUFFER_POOL_SIZE, self.buffer_pool_manager.disk_manager.clone(), ); - let table_heap = TableHeap::try_new(schema.clone(), buffer_pool_manager); + let table_heap = TableHeap::try_new(schema.clone(), buffer_pool_manager).unwrap(); let table_oid = self .next_table_oid .fetch_add(1, std::sync::atomic::Ordering::SeqCst); diff --git a/bustubx/src/storage/index.rs b/bustubx/src/storage/index.rs index e84a96e..10ea4bc 100644 --- a/bustubx/src/storage/index.rs +++ b/bustubx/src/storage/index.rs @@ -118,7 +118,9 @@ impl BPlusTreeIndex { data.copy_from_slice(&BPlusTreePageCodec::encode(&curr_page)); self.buffer_pool_manager.write_page(curr_page_id, data); - self.buffer_pool_manager.unpin_page(curr_page_id, true); + self.buffer_pool_manager + .unpin_page(curr_page_id, true) + .unwrap(); if let Some(page_id) = context.read_set.pop_back() { // 更新父节点 @@ -131,7 +133,7 @@ impl BPlusTreeIndex { self.index_metadata.key_schema.clone(), ) .unwrap(); - self.buffer_pool_manager.unpin_page(page_id, false); + self.buffer_pool_manager.unpin_page(page_id, false).unwrap(); tree_page.insert_internalkv(internalkv, &self.index_metadata.key_schema); curr_page = tree_page; @@ -164,7 +166,9 @@ impl BPlusTreeIndex { data.copy_from_slice(&BPlusTreeInternalPageCodec::encode(&new_internal_page)); new_root_page.write().unwrap().data = data; - self.buffer_pool_manager.unpin_page(new_root_page_id, true); + self.buffer_pool_manager + .unpin_page(new_root_page_id, true) + .unwrap(); // 更新root page id self.root_page_id = new_root_page_id; @@ -178,7 +182,9 @@ impl BPlusTreeIndex { data.copy_from_slice(&BPlusTreePageCodec::encode(&curr_page)); self.buffer_pool_manager.write_page(curr_page_id, data); - self.buffer_pool_manager.unpin_page(curr_page_id, true); + self.buffer_pool_manager + .unpin_page(curr_page_id, true) + .unwrap(); return true; } @@ -280,7 +286,8 @@ impl BPlusTreeIndex { self.buffer_pool_manager .write_page(left_sibling_page_id, data); self.buffer_pool_manager - .unpin_page(left_sibling_page_id, true); + .unpin_page(left_sibling_page_id, true) + .unwrap(); // 更新父节点 let parent_page = self @@ -304,12 +311,15 @@ impl BPlusTreeIndex { )); parent_page.write().unwrap().data = data; - self.buffer_pool_manager.unpin_page(parent_page_id, true); + self.buffer_pool_manager + .unpin_page(parent_page_id, true) + .unwrap(); break; } self.buffer_pool_manager - .unpin_page(left_sibling_page_id, false); + .unpin_page(left_sibling_page_id, false) + .unwrap(); } // 尝试从右兄弟借一个 @@ -364,7 +374,8 @@ impl BPlusTreeIndex { self.buffer_pool_manager .write_page(right_sibling_page_id, data); self.buffer_pool_manager - .unpin_page(right_sibling_page_id, true); + .unpin_page(right_sibling_page_id, true) + .unwrap(); // 更新父节点 let parent_page = self @@ -388,12 +399,15 @@ impl BPlusTreeIndex { )); parent_page.write().unwrap().data = data; - self.buffer_pool_manager.unpin_page(parent_page_id, true); + self.buffer_pool_manager + .unpin_page(parent_page_id, true) + .unwrap(); break; } self.buffer_pool_manager - .unpin_page(right_sibling_page_id, false); + .unpin_page(right_sibling_page_id, false) + .unwrap(); } // 跟左兄弟合并 @@ -444,8 +458,12 @@ impl BPlusTreeIndex { // 删除当前页 let deleted_page_id = curr_page_id; - self.buffer_pool_manager.unpin_page(deleted_page_id, false); - self.buffer_pool_manager.delete_page(deleted_page_id); + self.buffer_pool_manager + .unpin_page(deleted_page_id, false) + .unwrap(); + self.buffer_pool_manager + .delete_page(deleted_page_id) + .unwrap(); // 更新当前页为左兄弟页 curr_page_id = left_sibling_page_id; @@ -468,8 +486,12 @@ impl BPlusTreeIndex { { self.root_page_id = curr_page_id; // 删除旧的根节点 - self.buffer_pool_manager.unpin_page(parent_page_id, false); - self.buffer_pool_manager.delete_page(parent_page_id); + self.buffer_pool_manager + .unpin_page(parent_page_id, false) + .unwrap(); + self.buffer_pool_manager + .delete_page(parent_page_id) + .unwrap(); } else { let mut data = [0; BUSTUBX_PAGE_SIZE]; data.copy_from_slice(&BPlusTreeInternalPageCodec::encode( @@ -477,7 +499,9 @@ impl BPlusTreeIndex { )); parent_page.write().unwrap().data = data; - self.buffer_pool_manager.unpin_page(curr_page_id, true); + self.buffer_pool_manager + .unpin_page(curr_page_id, true) + .unwrap(); curr_page = BPlusTreePage::Internal(parent_internal_page); curr_page_id = parent_page_id; } @@ -532,8 +556,12 @@ impl BPlusTreeIndex { // 删除右兄弟页 let deleted_page_id = right_sibling_page_id; - self.buffer_pool_manager.unpin_page(deleted_page_id, false); - self.buffer_pool_manager.delete_page(deleted_page_id); + self.buffer_pool_manager + .unpin_page(deleted_page_id, false) + .unwrap(); + self.buffer_pool_manager + .delete_page(deleted_page_id) + .unwrap(); // 更新父节点 let parent_page = self @@ -552,8 +580,12 @@ impl BPlusTreeIndex { { self.root_page_id = curr_page_id; // 删除旧的根节点 - self.buffer_pool_manager.unpin_page(parent_page_id, false); - self.buffer_pool_manager.delete_page(parent_page_id); + self.buffer_pool_manager + .unpin_page(parent_page_id, false) + .unwrap(); + self.buffer_pool_manager + .delete_page(parent_page_id) + .unwrap(); } else { let mut data = [0; BUSTUBX_PAGE_SIZE]; data.copy_from_slice(&BPlusTreeInternalPageCodec::encode( @@ -561,7 +593,9 @@ impl BPlusTreeIndex { )); parent_page.write().unwrap().data = data; - self.buffer_pool_manager.unpin_page(curr_page_id, true); + self.buffer_pool_manager + .unpin_page(curr_page_id, true) + .unwrap(); curr_page = BPlusTreePage::Internal(parent_internal_page); curr_page_id = parent_page_id; } @@ -574,7 +608,9 @@ impl BPlusTreeIndex { data.copy_from_slice(&BPlusTreePageCodec::encode(&curr_page)); self.buffer_pool_manager.write_page(curr_page_id, data); - self.buffer_pool_manager.unpin_page(curr_page_id, true); + self.buffer_pool_manager + .unpin_page(curr_page_id, true) + .unwrap(); } pub fn scan(&self, key: &Tuple) -> Vec { @@ -600,7 +636,9 @@ impl BPlusTreeIndex { // 更新root page id self.root_page_id = new_page_id; - self.buffer_pool_manager.unpin_page(new_page_id, true); + self.buffer_pool_manager + .unpin_page(new_page_id, true) + .unwrap(); } // 找到叶子节点上对应的Value @@ -626,7 +664,9 @@ impl BPlusTreeIndex { ) .unwrap(); let result = leaf_page.look_up(key, &self.index_metadata.key_schema); - self.buffer_pool_manager.unpin_page(leaf_page_id, false); + self.buffer_pool_manager + .unpin_page(leaf_page_id, false) + .unwrap(); return result; } @@ -651,7 +691,9 @@ impl BPlusTreeIndex { BPlusTreePage::Internal(internal_page) => { context.read_set.push_back(curr_page_id); // 释放上一页 - self.buffer_pool_manager.unpin_page(curr_page_id, false); + self.buffer_pool_manager + .unpin_page(curr_page_id, false) + .unwrap(); // 查找下一页 let next_page_id = internal_page.look_up(key, &self.index_metadata.key_schema); let next_page = self @@ -667,7 +709,9 @@ impl BPlusTreeIndex { curr_page = next_page; } BPlusTreePage::Leaf(leaf_page) => { - self.buffer_pool_manager.unpin_page(curr_page_id, false); + self.buffer_pool_manager + .unpin_page(curr_page_id, false) + .unwrap(); return curr_page_id; } } @@ -702,7 +746,9 @@ impl BPlusTreeIndex { data.copy_from_slice(&BPlusTreeLeafPageCodec::encode(&new_leaf_page)); new_page.write().unwrap().data = data; - self.buffer_pool_manager.unpin_page(new_page_id, true); + self.buffer_pool_manager + .unpin_page(new_page_id, true) + .unwrap(); return (new_leaf_page.key_at(0).clone(), new_page_id); } @@ -716,7 +762,7 @@ impl BPlusTreeIndex { // 拆分kv对 let mut new_internal_page = BPlusTreeInternalPage::new( self.index_metadata.key_schema.clone(), - self.internal_max_size as u32, + self.internal_max_size, ); new_internal_page.batch_insert( internal_page.split_off(internal_page.header.current_size as usize / 2), @@ -727,7 +773,9 @@ impl BPlusTreeIndex { data.copy_from_slice(&BPlusTreeInternalPageCodec::encode(&new_internal_page)); new_page.write().unwrap().data = data; - self.buffer_pool_manager.unpin_page(new_page_id, true); + self.buffer_pool_manager + .unpin_page(new_page_id, true) + .unwrap(); let min_leafkv = self.find_min_leafkv(new_page_id); return (min_leafkv.0, new_page_id); @@ -753,7 +801,9 @@ impl BPlusTreeIndex { self.index_metadata.key_schema.clone(), ) .unwrap(); - self.buffer_pool_manager.unpin_page(parent_page_id, false); + self.buffer_pool_manager + .unpin_page(parent_page_id, false) + .unwrap(); return parent_page.sibling_page_ids(child_page_id); } @@ -772,7 +822,7 @@ impl BPlusTreeIndex { self.index_metadata.key_schema.clone(), ) .unwrap(); - self.buffer_pool_manager.unpin_page(page_id, false); + self.buffer_pool_manager.unpin_page(page_id, false).unwrap(); loop { match curr_page { BPlusTreePage::Internal(internal_page) => { @@ -787,7 +837,7 @@ impl BPlusTreeIndex { ) .unwrap() .0; - self.buffer_pool_manager.unpin_page(page_id, false); + self.buffer_pool_manager.unpin_page(page_id, false).unwrap(); } BPlusTreePage::Leaf(leaf_page) => { return leaf_page.kv_at(0).clone(); @@ -807,7 +857,7 @@ impl BPlusTreeIndex { self.index_metadata.key_schema.clone(), ) .unwrap(); - self.buffer_pool_manager.unpin_page(page_id, false); + self.buffer_pool_manager.unpin_page(page_id, false).unwrap(); loop { match curr_page { BPlusTreePage::Internal(internal_page) => { @@ -823,7 +873,7 @@ impl BPlusTreeIndex { ) .unwrap() .0; - self.buffer_pool_manager.unpin_page(page_id, false); + self.buffer_pool_manager.unpin_page(page_id, false).unwrap(); } BPlusTreePage::Leaf(leaf_page) => { return leaf_page @@ -861,7 +911,7 @@ impl BPlusTreeIndex { self.index_metadata.key_schema.clone(), ) .unwrap(); - self.buffer_pool_manager.unpin_page(page_id, false); + self.buffer_pool_manager.unpin_page(page_id, false).unwrap(); match curr_page { BPlusTreePage::Internal(internal_page) => { internal_page.print_page(page_id, &self.index_metadata.key_schema); diff --git a/bustubx/src/storage/table_heap.rs b/bustubx/src/storage/table_heap.rs index 4b0fb57..26c2061 100644 --- a/bustubx/src/storage/table_heap.rs +++ b/bustubx/src/storage/table_heap.rs @@ -1,7 +1,7 @@ use crate::buffer::{PageId, BUSTUBX_PAGE_SIZE, INVALID_PAGE_ID}; use crate::catalog::SchemaRef; use crate::storage::codec::TablePageCodec; -use crate::{buffer::BufferPoolManager, common::rid::Rid}; +use crate::{buffer::BufferPoolManager, common::rid::Rid, BustubxResult}; use super::{ table_page::TablePage, @@ -17,24 +17,25 @@ pub struct TableHeap { } impl TableHeap { - pub fn try_new(schema: SchemaRef, mut buffer_pool_manager: BufferPoolManager) -> Self { + pub fn try_new( + schema: SchemaRef, + mut buffer_pool_manager: BufferPoolManager, + ) -> BustubxResult { // new a page and initialize - let first_page = buffer_pool_manager - .new_page() - .expect("Can not new page for table heap"); + let first_page = buffer_pool_manager.new_page()?; let first_page_id = first_page.read().unwrap().page_id; let table_page = TablePage::new(schema.clone(), INVALID_PAGE_ID); let mut data = [0u8; BUSTUBX_PAGE_SIZE]; data.copy_from_slice(&TablePageCodec::encode(&table_page)); first_page.write().unwrap().data = data; - buffer_pool_manager.unpin_page(first_page_id, true); + buffer_pool_manager.unpin_page(first_page_id, true)?; - Self { + Ok(Self { schema, buffer_pool_manager, first_page_id, last_page_id: first_page_id, - } + }) } /// Inserts a tuple into the table. @@ -89,7 +90,9 @@ impl TableHeap { data.copy_from_slice(&TablePageCodec::encode(&last_table_page)); self.buffer_pool_manager.write_page(last_page_id, data); - self.buffer_pool_manager.unpin_page(last_page_id, true); + self.buffer_pool_manager + .unpin_page(last_page_id, true) + .unwrap(); // Update last_page_id. last_page_id = next_page_id; @@ -104,7 +107,9 @@ impl TableHeap { data.copy_from_slice(&TablePageCodec::encode(&last_table_page)); self.buffer_pool_manager.write_page(last_page_id, data); - self.buffer_pool_manager.unpin_page(last_page_id, true); + self.buffer_pool_manager + .unpin_page(last_page_id, true) + .unwrap(); // Map the slot_id to a Rid and return slot_id.map(|slot_id| Rid::new(last_page_id, slot_id as u32)) @@ -123,7 +128,9 @@ impl TableHeap { data.copy_from_slice(&TablePageCodec::encode(&table_page)); page.write().unwrap().data = data; - self.buffer_pool_manager.unpin_page(rid.page_id, true); + self.buffer_pool_manager + .unpin_page(rid.page_id, true) + .unwrap(); } pub fn get_tuple(&mut self, rid: Rid) -> (TupleMeta, Tuple) { @@ -134,7 +141,9 @@ impl TableHeap { let (mut table_page, _) = TablePageCodec::decode(&page.read().unwrap().data, self.schema.clone()).unwrap(); let result = table_page.get_tuple(&rid); - self.buffer_pool_manager.unpin_page(rid.page_id, false); + self.buffer_pool_manager + .unpin_page(rid.page_id, false) + .unwrap(); result } @@ -146,7 +155,9 @@ impl TableHeap { let (mut table_page, _) = TablePageCodec::decode(&page.read().unwrap().data, self.schema.clone()).unwrap(); let result = table_page.get_tuple_meta(&rid); - self.buffer_pool_manager.unpin_page(rid.page_id, false); + self.buffer_pool_manager + .unpin_page(rid.page_id, false) + .unwrap(); result } @@ -158,7 +169,8 @@ impl TableHeap { let (table_page, _) = TablePageCodec::decode(&page.read().unwrap().data, self.schema.clone()).unwrap(); self.buffer_pool_manager - .unpin_page(self.first_page_id, false); + .unpin_page(self.first_page_id, false) + .unwrap(); if table_page.header.num_tuples == 0 { // TODO 忽略删除的tuple return None; @@ -174,7 +186,9 @@ impl TableHeap { .expect("Can not fetch page"); let (table_page, _) = TablePageCodec::decode(&page.read().unwrap().data, self.schema.clone()).unwrap(); - self.buffer_pool_manager.unpin_page(rid.page_id, false); + self.buffer_pool_manager + .unpin_page(rid.page_id, false) + .unwrap(); let next_rid = table_page.get_next_rid(&rid); if next_rid.is_some() { return next_rid; @@ -190,7 +204,8 @@ impl TableHeap { let (next_table_page, _) = TablePageCodec::decode(&next_page.read().unwrap().data, self.schema.clone()).unwrap(); self.buffer_pool_manager - .unpin_page(table_page.header.next_page_id, false); + .unpin_page(table_page.header.next_page_id, false) + .unwrap(); if next_table_page.header.num_tuples == 0 { // TODO 忽略删除的tuple return None; @@ -246,7 +261,8 @@ mod tests { let disk_manager = DiskManager::try_new(&temp_path).unwrap(); let buffer_pool_manager = BufferPoolManager::new(10, Arc::new(disk_manager)); - let table_heap = TableHeap::try_new(Arc::new(Schema::empty()), buffer_pool_manager); + let table_heap = + TableHeap::try_new(Arc::new(Schema::empty()), buffer_pool_manager).unwrap(); assert_eq!(table_heap.first_page_id, 0); assert_eq!(table_heap.last_page_id, 0); } @@ -262,7 +278,7 @@ mod tests { ])); let disk_manager = DiskManager::try_new(&temp_path).unwrap(); let buffer_pool_manager = BufferPoolManager::new(1000, Arc::new(disk_manager)); - let mut table_heap = TableHeap::try_new(schema.clone(), buffer_pool_manager); + let mut table_heap = TableHeap::try_new(schema.clone(), buffer_pool_manager).unwrap(); let meta = super::TupleMeta { insert_txn_id: 0, delete_txn_id: 0, @@ -302,7 +318,7 @@ mod tests { ])); let disk_manager = DiskManager::try_new(&temp_path).unwrap(); let buffer_pool_manager = BufferPoolManager::new(1000, Arc::new(disk_manager)); - let mut table_heap = TableHeap::try_new(schema.clone(), buffer_pool_manager); + let mut table_heap = TableHeap::try_new(schema.clone(), buffer_pool_manager).unwrap(); let meta = super::TupleMeta { insert_txn_id: 0, delete_txn_id: 0, @@ -351,7 +367,7 @@ mod tests { ])); let disk_manager = DiskManager::try_new(&temp_path).unwrap(); let buffer_pool_manager = BufferPoolManager::new(1000, Arc::new(disk_manager)); - let mut table_heap = TableHeap::try_new(schema.clone(), buffer_pool_manager); + let mut table_heap = TableHeap::try_new(schema.clone(), buffer_pool_manager).unwrap(); let meta1 = super::TupleMeta { insert_txn_id: 1, @@ -412,7 +428,7 @@ mod tests { let disk_manager = DiskManager::try_new(&temp_path).unwrap(); let buffer_pool_manager = BufferPoolManager::new(1000, Arc::new(disk_manager)); - let mut table_heap = TableHeap::try_new(schema.clone(), buffer_pool_manager); + let mut table_heap = TableHeap::try_new(schema.clone(), buffer_pool_manager).unwrap(); let meta1 = super::TupleMeta { insert_txn_id: 1,