From a13a61c721ab4eef180272a6bf40c2770fbb54a4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=BC=A0=E6=9E=97=E4=BC=9F?= Date: Wed, 21 Feb 2024 21:24:26 +0800 Subject: [PATCH] Load catalog data --- Cargo.lock | 20 ++++ bustubx-cli/src/main.rs | 3 + bustubx/Cargo.toml | 3 +- bustubx/src/buffer/buffer_pool.rs | 159 ++++++++++++++++------------- bustubx/src/buffer/page.rs | 7 ++ bustubx/src/catalog/catalog.rs | 21 ++-- bustubx/src/catalog/information.rs | 15 +-- bustubx/src/database.rs | 22 ++-- bustubx/src/storage/index.rs | 26 +---- bustubx/src/storage/table_heap.rs | 11 +- 10 files changed, 156 insertions(+), 131 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index f2a7161..e0775e1 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -102,6 +102,7 @@ name = "bustubx" version = "0.2.0" dependencies = [ "comfy-table", + "dashmap", "derive-new", "derive-with", "itertools 0.11.0", @@ -241,6 +242,19 @@ dependencies = [ "typenum", ] +[[package]] +name = "dashmap" +version = "5.5.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "978747c1d849a7d2ee5e8adc0159961c48fb7e5db2f06af6723b80123bb53856" +dependencies = [ + "cfg-if", + "hashbrown", + "lock_api", + "once_cell", + "parking_lot_core", +] + [[package]] name = "derive-new" version = "0.5.9" @@ -470,6 +484,12 @@ version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d2fabcfbdc87f4758337ca535fb41a6d701b65693ce38287d856d1674551ec9b" +[[package]] +name = "hashbrown" +version = "0.14.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "290f1a1d9242c78d09ce40a5e87e7554ee637af1351968159f4952f028f75604" + [[package]] name = "heck" version = "0.4.1" diff --git a/bustubx-cli/src/main.rs b/bustubx-cli/src/main.rs index 3faaaf6..f961ce2 100644 --- a/bustubx-cli/src/main.rs +++ b/bustubx-cli/src/main.rs @@ -45,14 +45,17 @@ fn main() { } } Err(ReadlineError::Interrupted) => { + db.flush().unwrap(); println!("CTRL-C"); break; } Err(ReadlineError::Eof) => { + db.flush().unwrap(); println!("CTRL-D"); break; } Err(err) => { + db.flush().unwrap(); println!("Error: {:?}", err); break; } diff --git a/bustubx/Cargo.toml b/bustubx/Cargo.toml index e4c37d9..e1d8b90 100644 --- a/bustubx/Cargo.toml +++ b/bustubx/Cargo.toml @@ -23,4 +23,5 @@ log = "0.4.19" thiserror = "1.0.56" tempfile = "3" derive-with = "0.5.0" -strum = { version = "0.26", features = ["derive"]} \ No newline at end of file +strum = { version = "0.26", features = ["derive"]} +dashmap = "5.5.3" \ No newline at end of file diff --git a/bustubx/src/buffer/buffer_pool.rs b/bustubx/src/buffer/buffer_pool.rs index 485ac0a..7954200 100644 --- a/bustubx/src/buffer/buffer_pool.rs +++ b/bustubx/src/buffer/buffer_pool.rs @@ -1,3 +1,4 @@ +use dashmap::DashMap; use std::sync::RwLock; use std::{ collections::{HashMap, VecDeque}, @@ -19,47 +20,46 @@ pub const TABLE_HEAP_BUFFER_POOL_SIZE: usize = 100; pub struct BufferPoolManager { pool: Vec>>, // LRU-K置换算法 - pub replacer: LRUKReplacer, + pub replacer: Arc>, pub disk_manager: Arc, // 缓冲池中的页号与frame号的映射 - page_table: HashMap, + page_table: DashMap, // 缓冲池中空闲的frame - free_list: VecDeque, - // 缓冲池中的页数 - num_pages: usize, + free_list: Arc>>, } impl BufferPoolManager { pub fn new(num_pages: usize, disk_manager: Arc) -> Self { let mut free_list = VecDeque::with_capacity(num_pages); + let mut pool = vec![]; for i in 0..num_pages { free_list.push_back(i); + pool.push(Arc::new(RwLock::new(Page::new(0)))); } + Self { - pool: vec![Arc::new(RwLock::new(Page::new(0))); num_pages], - replacer: LRUKReplacer::new(num_pages, 2), + pool, + replacer: Arc::new(RwLock::new(LRUKReplacer::new(num_pages, 2))), disk_manager, - page_table: HashMap::new(), - free_list, - num_pages, + page_table: DashMap::new(), + free_list: Arc::new(RwLock::new(free_list)), } } // 从缓冲池创建一个新页 - pub fn new_page(&mut self) -> BustubxResult>> { + pub fn new_page(&self) -> BustubxResult>> { // 缓冲池已满且无可替换的页 - if self.free_list.is_empty() && self.replacer.size() == 0 { + if self.free_list.read().unwrap().is_empty() && self.replacer.read().unwrap().size() == 0 { return Err(BustubxError::Storage( "Cannot new page because buffer pool is full and no page to evict".to_string(), )); } // 分配一个frame - let frame_id = if !self.free_list.is_empty() { - // 有空闲frame则直接分配 - self.free_list.pop_front().unwrap() + let frame_id = if let Some(frame_id) = self.free_list.write().unwrap().pop_front() { + frame_id } else { // 无空闲frame,从缓冲池中替换一个页 - if let Some(frame_id) = self.replacer.evict() { + if let Some(frame_id) = self.replacer.write().unwrap().evict() { let evicted_page = self.pool[frame_id].clone(); let evicted_page_id = evicted_page.read().unwrap().page_id; // 如果页被修改过,则将其写回磁盘 @@ -79,26 +79,32 @@ 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] = Arc::new(RwLock::new(new_page)); + self.pool[frame_id].write().unwrap().replace(new_page); - self.replacer.record_access(frame_id)?; - self.replacer.set_evictable(frame_id, false)?; + self.replacer.write().unwrap().record_access(frame_id)?; + self.replacer + .write() + .unwrap() + .set_evictable(frame_id, false)?; 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].clone(); + pub fn fetch_page(&self, page_id: PageId) -> BustubxResult>> { + if let Some(frame_id) = self.page_table.get(&page_id) { + println!("LWZTEST frame_id: {}", *frame_id); + let page = self.pool[*frame_id].clone(); page.write().unwrap().pin_count += 1; - self.replacer.set_evictable(frame_id, false)?; + self.replacer + .write() + .unwrap() + .set_evictable(*frame_id, false)?; Ok(page) } else { // 分配一个frame - let frame_id = if !self.free_list.is_empty() { - self.free_list.pop_front().unwrap() - } else if let Some(frame_id) = self.replacer.evict() { + let frame_id = if let Some(frame_id) = self.free_list.write().unwrap().pop_front() { + frame_id + } else if let Some(frame_id) = self.replacer.write().unwrap().evict() { 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; @@ -110,34 +116,36 @@ impl BufferPoolManager { } else { return Err(BustubxError::Storage("Failed to evict page".to_string())); }; + // 从磁盘读取页 self.page_table.insert(page_id, frame_id); 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] = Arc::new(RwLock::new(new_page)); + new_page.data = self.disk_manager.read_page(page_id)?; + self.pool[frame_id].write().unwrap().replace(new_page); - self.replacer.record_access(frame_id)?; - self.replacer.set_evictable(frame_id, false)?; + self.replacer.write().unwrap().record_access(frame_id)?; + self.replacer + .write() + .unwrap() + .set_evictable(frame_id, false)?; 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].clone(); + pub fn write_page(&self, page_id: PageId, data: [u8; BUSTUBX_PAGE_SIZE]) { + if let Some(frame_id) = self.page_table.get(&page_id) { + 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) -> BustubxResult { - if self.page_table.contains_key(&page_id) { - let frame_id = self.page_table[&page_id]; - let page = self.pool[frame_id].clone(); + pub fn unpin_page(&self, page_id: PageId, is_dirty: bool) -> BustubxResult { + if let Some(frame_id) = self.page_table.get(&page_id) { + let page = self.pool[*frame_id].clone(); if page.read().unwrap().pin_count == 0 { return Ok(false); } @@ -145,7 +153,10 @@ impl BufferPoolManager { page.write().unwrap().is_dirty |= is_dirty; let pin_count = page.read().unwrap().pin_count; if pin_count == 0 { - self.replacer.set_evictable(frame_id, true)?; + self.replacer + .write() + .unwrap() + .set_evictable(*frame_id, true)?; } Ok(true) } else { @@ -154,10 +165,9 @@ 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].clone(); + pub fn flush_page(&self, page_id: PageId) -> BustubxResult { + if let Some(frame_id) = self.page_table.get(&page_id) { + let page = self.pool[*frame_id].clone(); self.disk_manager .write_page(page_id, &page.read().unwrap().data)?; page.write().unwrap().is_dirty = false; @@ -168,8 +178,8 @@ impl BufferPoolManager { } // 将缓冲池中的所有页写回磁盘 - pub fn flush_all_pages(&mut self) -> BustubxResult<()> { - let page_ids: Vec = self.page_table.keys().copied().collect(); + pub fn flush_all_pages(&self) -> BustubxResult<()> { + let page_ids: Vec = self.page_table.iter().map(|e| *e.key()).collect(); for page_id in page_ids { self.flush_page(page_id)?; } @@ -177,26 +187,29 @@ impl BufferPoolManager { } // 删除缓冲池中的页 - pub fn delete_page(&mut self, page_id: PageId) -> BustubxResult { - if !self.page_table.contains_key(&page_id) { - return Ok(true); - } - let frame_id = self.page_table[&page_id]; - let page = self.pool[frame_id].clone(); - if page.read().unwrap().pin_count > 0 { - // 页被固定,无法删除 - return Ok(false); - } + pub fn delete_page(&self, page_id: PageId) -> BustubxResult { + if let Some(frame_id_lock) = self.page_table.get(&page_id) { + let frame_id = *frame_id_lock; + drop(frame_id_lock); - // 从缓冲池中删除 - page.write().unwrap().destroy(); - self.page_table.remove(&page_id); - self.free_list.push_back(frame_id); - self.replacer.remove(frame_id); + let page = self.pool[frame_id].clone(); + if page.read().unwrap().pin_count > 0 { + // 页被固定,无法删除 + return Ok(false); + } + + // 从缓冲池中删除 + page.write().unwrap().destroy(); + self.page_table.remove(&page_id); + self.free_list.write().unwrap().push_back(frame_id); + self.replacer.write().unwrap().remove(frame_id); - // 从磁盘上删除 - self.disk_manager.deallocate_page(page_id)?; - Ok(true) + // 从磁盘上删除 + self.disk_manager.deallocate_page(page_id)?; + Ok(true) + } else { + Ok(true) + } } } @@ -216,9 +229,15 @@ mod tests { let page1 = buffer_pool.new_page().unwrap().clone(); let page1_id = page1.read().unwrap().page_id; assert_eq!(buffer_pool.pool[0].read().unwrap().page_id, page1_id,); - assert_eq!(buffer_pool.page_table[&page1.read().unwrap().page_id], 0); - assert_eq!(buffer_pool.free_list.len(), 2); - assert_eq!(buffer_pool.replacer.size(), 0); + assert_eq!( + *buffer_pool + .page_table + .get(&page1.read().unwrap().page_id) + .unwrap(), + 0 + ); + assert_eq!(buffer_pool.free_list.read().unwrap().len(), 2); + assert_eq!(buffer_pool.replacer.read().unwrap().size(), 0); let page2 = buffer_pool.new_page().unwrap(); let page2_id = page2.read().unwrap().page_id; @@ -285,7 +304,7 @@ mod tests { assert_eq!(page.read().unwrap().page_id, page2_id); buffer_pool.unpin_page(page2_id, false).unwrap(); - assert_eq!(buffer_pool.replacer.size(), 3); + assert_eq!(buffer_pool.replacer.read().unwrap().size(), 3); } #[test] @@ -311,8 +330,8 @@ mod tests { let res = buffer_pool.delete_page(page1_id).unwrap(); assert!(res); assert_eq!(buffer_pool.pool.len(), 3); - assert_eq!(buffer_pool.free_list.len(), 1); - assert_eq!(buffer_pool.replacer.size(), 2); + assert_eq!(buffer_pool.free_list.read().unwrap().len(), 1); + assert_eq!(buffer_pool.replacer.read().unwrap().size(), 2); assert_eq!(buffer_pool.page_table.len(), 2); let page = buffer_pool.fetch_page(page1_id).unwrap(); diff --git a/bustubx/src/buffer/page.rs b/bustubx/src/buffer/page.rs index 716f1cc..16bcde8 100644 --- a/bustubx/src/buffer/page.rs +++ b/bustubx/src/buffer/page.rs @@ -28,4 +28,11 @@ impl Page { self.pin_count = 0; self.is_dirty = false; } + + pub fn replace(&mut self, other: Page) { + self.page_id = other.page_id; + self.data = other.data; + self.pin_count = other.pin_count; + self.is_dirty = other.is_dirty; + } } diff --git a/bustubx/src/catalog/catalog.rs b/bustubx/src/catalog/catalog.rs index 6af4793..0bb68d5 100644 --- a/bustubx/src/catalog/catalog.rs +++ b/bustubx/src/catalog/catalog.rs @@ -1,4 +1,5 @@ use std::collections::HashMap; +use std::sync::Arc; use crate::buffer::TABLE_HEAP_BUFFER_POOL_SIZE; use crate::catalog::{ @@ -40,11 +41,11 @@ pub struct IndexInfo { pub struct Catalog { pub tables: HashMap, pub indexes: HashMap, - pub buffer_pool: BufferPoolManager, + pub buffer_pool: Arc, } impl Catalog { - pub fn new(buffer_pool: BufferPoolManager) -> Self { + pub fn new(buffer_pool: Arc) -> Self { Self { tables: HashMap::new(), indexes: HashMap::new(), @@ -59,12 +60,7 @@ impl Catalog { ) -> BustubxResult<&TableInfo> { let full_table_ref = table_ref.extend_to_full(); if !self.tables.contains_key(&full_table_ref) { - // 一个table对应一个buffer pool manager - let buffer_pool = BufferPoolManager::new( - TABLE_HEAP_BUFFER_POOL_SIZE, - self.buffer_pool.disk_manager.clone(), - ); - let table_heap = TableHeap::try_new(schema.clone(), buffer_pool)?; + let table_heap = TableHeap::try_new(schema.clone(), self.buffer_pool.clone())?; let first_page_id = table_heap.first_page_id; let last_page_id = table_heap.last_page_id; let table_info = TableInfo { @@ -167,14 +163,9 @@ impl Catalog { tuple_schema.clone(), key_attrs, ); - // one buffer pool manager for one index - let buffer_pool = BufferPoolManager::new( - TABLE_HEAP_BUFFER_POOL_SIZE, - self.buffer_pool.disk_manager.clone(), - ); let b_plus_tree_index = BPlusTreeIndex::new( index_metadata, - buffer_pool, + self.buffer_pool.clone(), BPLUS_LEAF_PAGE_MAX_SIZE as u32, BPLUS_INTERNAL_PAGE_MAX_SIZE as u32, ); @@ -260,7 +251,7 @@ mod tests { let temp_path = temp_dir.path().join("test.db"); let disk_manager = DiskManager::try_new(temp_path).unwrap(); - let buffer_pool = BufferPoolManager::new(1000, Arc::new(disk_manager)); + let buffer_pool = Arc::new(BufferPoolManager::new(1000, Arc::new(disk_manager))); let mut catalog = super::Catalog::new(buffer_pool); let table_ref = TableReference::bare("test_table1".to_string()); diff --git a/bustubx/src/catalog/information.rs b/bustubx/src/catalog/information.rs index 99774ae..f21b292 100644 --- a/bustubx/src/catalog/information.rs +++ b/bustubx/src/catalog/information.rs @@ -103,10 +103,7 @@ fn load_user_tables(db: &mut Database) -> BustubxResult<()> { name: table_name.to_string(), table: TableHeap { schema: schema.clone(), - buffer_pool: BufferPoolManager::new( - TABLE_HEAP_BUFFER_POOL_SIZE, - db.catalog.buffer_pool.disk_manager.clone(), - ), + buffer_pool: db.buffer_pool.clone(), first_page_id: *first_page_id as u32, last_page_id: *last_page_id as u32, }, @@ -141,10 +138,7 @@ fn load_information_schema(catalog: &mut Catalog) -> BustubxResult<()> { name: INFORMATION_SCHEMA_TABLES.to_string(), table: TableHeap { schema: TABLES_SCHMEA.clone(), - buffer_pool: BufferPoolManager::new( - TABLE_HEAP_BUFFER_POOL_SIZE, - catalog.buffer_pool.disk_manager.clone(), - ), + buffer_pool: catalog.buffer_pool.clone(), first_page_id: information_schema_tables_first_page_id, last_page_id: information_schema_tables_last_page_id, }, @@ -158,10 +152,7 @@ fn load_information_schema(catalog: &mut Catalog) -> BustubxResult<()> { name: INFORMATION_SCHEMA_COLUMNS.to_string(), table: TableHeap { schema: COLUMNS_SCHMEA.clone(), - buffer_pool: BufferPoolManager::new( - TABLE_HEAP_BUFFER_POOL_SIZE, - catalog.buffer_pool.disk_manager.clone(), - ), + buffer_pool: catalog.buffer_pool.clone(), first_page_id: information_schema_columns_first_page_id, last_page_id: information_schema_columns_last_page_id, }, diff --git a/bustubx/src/database.rs b/bustubx/src/database.rs index 3ec4fc5..f029d5f 100644 --- a/bustubx/src/database.rs +++ b/bustubx/src/database.rs @@ -19,18 +19,23 @@ use crate::{ pub struct Database { disk_manager: Arc, + pub(crate) buffer_pool: Arc, pub(crate) catalog: Catalog, temp_dir: Option, } impl Database { pub fn new_on_disk(db_path: &str) -> BustubxResult { let disk_manager = Arc::new(DiskManager::try_new(db_path)?); - let buffer_pool = BufferPoolManager::new(TABLE_HEAP_BUFFER_POOL_SIZE, disk_manager.clone()); + let buffer_pool = Arc::new(BufferPoolManager::new( + TABLE_HEAP_BUFFER_POOL_SIZE, + disk_manager.clone(), + )); - let mut catalog = Catalog::new(buffer_pool); + let mut catalog = Catalog::new(buffer_pool.clone()); let mut db = Self { disk_manager, + buffer_pool, catalog, temp_dir: None, }; @@ -45,12 +50,16 @@ impl Database { Arc::new(DiskManager::try_new(temp_path.to_str().ok_or( BustubxError::Internal("Invalid temp path".to_string()), )?)?); - let buffer_pool = BufferPoolManager::new(TABLE_HEAP_BUFFER_POOL_SIZE, disk_manager.clone()); + let buffer_pool = Arc::new(BufferPoolManager::new( + TABLE_HEAP_BUFFER_POOL_SIZE, + disk_manager.clone(), + )); - let mut catalog = Catalog::new(buffer_pool); + let mut catalog = Catalog::new(buffer_pool.clone()); let mut db = Self { disk_manager, + buffer_pool, catalog, temp_dir: Some(temp_dir), }; @@ -104,8 +113,7 @@ impl Database { planner.plan(stmt) } - pub fn flush(&mut self) -> BustubxResult<()> { - // TODO flush buffer pool - todo!() + pub fn flush(&self) -> BustubxResult<()> { + self.buffer_pool.flush_all_pages() } } diff --git a/bustubx/src/storage/index.rs b/bustubx/src/storage/index.rs index b535d9c..438f434 100644 --- a/bustubx/src/storage/index.rs +++ b/bustubx/src/storage/index.rs @@ -1,4 +1,5 @@ use std::collections::VecDeque; +use std::sync::Arc; use crate::buffer::{PageId, INVALID_PAGE_ID}; use crate::catalog::SchemaRef; @@ -60,7 +61,7 @@ impl Context { // B+树索引 pub struct BPlusTreeIndex { pub index_metadata: IndexMetadata, - pub buffer_pool: BufferPoolManager, + pub buffer_pool: Arc, pub leaf_max_size: u32, pub internal_max_size: u32, pub root_page_id: PageId, @@ -69,7 +70,7 @@ pub struct BPlusTreeIndex { impl BPlusTreeIndex { pub fn new( index_metadata: IndexMetadata, - buffer_pool: BufferPoolManager, + buffer_pool: Arc, leaf_max_size: u32, internal_max_size: u32, ) -> Self { @@ -831,7 +832,7 @@ mod tests { vec![0, 1], ); let disk_manager = DiskManager::try_new(temp_path).unwrap(); - let buffer_pool = BufferPoolManager::new(1000, Arc::new(disk_manager)); + let buffer_pool = Arc::new(BufferPoolManager::new(1000, Arc::new(disk_manager))); let mut index = BPlusTreeIndex::new(index_metadata, buffer_pool, 2, 3); index.insert( @@ -845,7 +846,6 @@ mod tests { Rid::new(1, 1) ); assert_eq!(index.root_page_id, 4); - assert_eq!(index.buffer_pool.replacer.size(), 1); index.insert( &Tuple::new(schema.clone(), vec![2i8.into(), 4i16.into()]), @@ -858,7 +858,6 @@ mod tests { Rid::new(2, 2) ); assert_eq!(index.root_page_id, 4); - assert_eq!(index.buffer_pool.replacer.size(), 1); index.insert( &Tuple::new(schema.clone(), vec![3i8.into(), 6i16.into()]), @@ -871,7 +870,6 @@ mod tests { Rid::new(3, 3) ); assert_eq!(index.root_page_id, 6); - assert_eq!(index.buffer_pool.replacer.size(), 3); index.insert( &Tuple::new(schema.clone(), vec![4i8.into(), 8i16.into()]), @@ -884,7 +882,6 @@ mod tests { Rid::new(4, 4) ); assert_eq!(index.root_page_id, 6); - assert_eq!(index.buffer_pool.replacer.size(), 4); index.insert( &Tuple::new(schema.clone(), vec![5i8.into(), 10i16.into()]), @@ -897,7 +894,6 @@ mod tests { Rid::new(5, 5) ); assert_eq!(index.root_page_id, 10); - assert_eq!(index.buffer_pool.replacer.size(), 7); } #[test] @@ -917,7 +913,7 @@ mod tests { vec![0, 1], ); let disk_manager = DiskManager::try_new(temp_path).unwrap(); - let buffer_pool = BufferPoolManager::new(1000, Arc::new(disk_manager)); + let buffer_pool = Arc::new(BufferPoolManager::new(1000, Arc::new(disk_manager))); let mut index = BPlusTreeIndex::new(index_metadata, buffer_pool, 4, 5); index.insert( @@ -960,7 +956,6 @@ mod tests { &Tuple::new(schema.clone(), vec![10i8.into(), 10i16.into()]), Rid::new(10, 10), ); - assert_eq!(index.buffer_pool.replacer.size(), 5); assert_eq!(index.root_page_id, 6); index.print_tree(); @@ -970,7 +965,6 @@ mod tests { index.get(&Tuple::new(schema.clone(), vec![1i8.into(), 1i16.into()])), None ); - assert_eq!(index.buffer_pool.replacer.size(), 4); index.delete(&Tuple::new(schema.clone(), vec![3i8.into(), 3i16.into()])); assert_eq!(index.root_page_id, 6); @@ -978,7 +972,6 @@ mod tests { index.get(&Tuple::new(schema.clone(), vec![3i8.into(), 3i16.into()])), None ); - assert_eq!(index.buffer_pool.replacer.size(), 4); index.delete(&Tuple::new(schema.clone(), vec![5i8.into(), 5i16.into()])); assert_eq!(index.root_page_id, 6); @@ -986,7 +979,6 @@ mod tests { index.get(&Tuple::new(schema.clone(), vec![5i8.into(), 5i16.into()])), None ); - assert_eq!(index.buffer_pool.replacer.size(), 4); index.delete(&Tuple::new(schema.clone(), vec![7i8.into(), 7i16.into()])); assert_eq!(index.root_page_id, 6); @@ -994,7 +986,6 @@ mod tests { index.get(&Tuple::new(schema.clone(), vec![7i8.into(), 7i16.into()])), None ); - assert_eq!(index.buffer_pool.replacer.size(), 4); index.delete(&Tuple::new(schema.clone(), vec![9i8.into(), 9i16.into()])); assert_eq!(index.root_page_id, 6); @@ -1002,7 +993,6 @@ mod tests { index.get(&Tuple::new(schema.clone(), vec![9i8.into(), 9i16.into()])), None ); - assert_eq!(index.buffer_pool.replacer.size(), 3); index.delete(&Tuple::new(schema.clone(), vec![10i8.into(), 10i16.into()])); assert_eq!(index.root_page_id, 6); @@ -1010,7 +1000,6 @@ mod tests { index.get(&Tuple::new(schema.clone(), vec![10i8.into(), 10i16.into()])), None ); - assert_eq!(index.buffer_pool.replacer.size(), 3); index.delete(&Tuple::new(schema.clone(), vec![8i8.into(), 8i16.into()])); assert_eq!(index.root_page_id, 4); @@ -1018,7 +1007,6 @@ mod tests { index.get(&Tuple::new(schema.clone(), vec![8i8.into(), 8i16.into()])), None ); - assert_eq!(index.buffer_pool.replacer.size(), 1); index.delete(&Tuple::new(schema.clone(), vec![6i8.into(), 6i16.into()])); assert_eq!(index.root_page_id, 4); @@ -1026,7 +1014,6 @@ mod tests { index.get(&Tuple::new(schema.clone(), vec![6i8.into(), 6i16.into()])), None ); - assert_eq!(index.buffer_pool.replacer.size(), 1); index.delete(&Tuple::new(schema.clone(), vec![4i8.into(), 4i16.into()])); assert_eq!(index.root_page_id, 4); @@ -1034,7 +1021,6 @@ mod tests { index.get(&Tuple::new(schema.clone(), vec![4i8.into(), 4i16.into()])), None ); - assert_eq!(index.buffer_pool.replacer.size(), 1); index.delete(&Tuple::new(schema.clone(), vec![2i8.into(), 2i16.into()])); assert_eq!(index.root_page_id, 4); @@ -1042,7 +1028,6 @@ mod tests { index.get(&Tuple::new(schema.clone(), vec![2i8.into(), 2i16.into()])), None ); - assert_eq!(index.buffer_pool.replacer.size(), 1); index.delete(&Tuple::new(schema.clone(), vec![2i8.into(), 2i16.into()])); assert_eq!(index.root_page_id, 4); @@ -1050,6 +1035,5 @@ mod tests { index.get(&Tuple::new(schema.clone(), vec![2i8.into(), 2i16.into()])), None ); - assert_eq!(index.buffer_pool.replacer.size(), 1); } } diff --git a/bustubx/src/storage/table_heap.rs b/bustubx/src/storage/table_heap.rs index 4dfb973..79f6289 100644 --- a/bustubx/src/storage/table_heap.rs +++ b/bustubx/src/storage/table_heap.rs @@ -4,19 +4,20 @@ use crate::common::util::page_bytes_to_array; use crate::storage::codec::TablePageCodec; use crate::storage::{TablePage, TupleMeta}; use crate::{buffer::BufferPoolManager, common::rid::Rid, BustubxResult}; +use std::sync::Arc; use super::tuple::Tuple; #[derive(Debug)] pub struct TableHeap { pub schema: SchemaRef, - pub buffer_pool: BufferPoolManager, + pub buffer_pool: Arc, pub first_page_id: PageId, pub last_page_id: PageId, } impl TableHeap { - pub fn try_new(schema: SchemaRef, mut buffer_pool: BufferPoolManager) -> BustubxResult { + pub fn try_new(schema: SchemaRef, buffer_pool: Arc) -> BustubxResult { // new a page and initialize let first_page = buffer_pool.new_page()?; let first_page_id = first_page.read().unwrap().page_id; @@ -227,7 +228,7 @@ mod tests { Column::new("b".to_string(), DataType::Int16, false), ])); let disk_manager = DiskManager::try_new(temp_path).unwrap(); - let buffer_pool = BufferPoolManager::new(1000, Arc::new(disk_manager)); + let buffer_pool = Arc::new(BufferPoolManager::new(1000, Arc::new(disk_manager))); let mut table_heap = TableHeap::try_new(schema.clone(), buffer_pool).unwrap(); let meta = super::TupleMeta { insert_txn_id: 0, @@ -276,7 +277,7 @@ mod tests { Column::new("b".to_string(), DataType::Int16, false), ])); let disk_manager = DiskManager::try_new(temp_path).unwrap(); - let buffer_pool = BufferPoolManager::new(1000, Arc::new(disk_manager)); + let buffer_pool = Arc::new(BufferPoolManager::new(1000, Arc::new(disk_manager))); let mut table_heap = TableHeap::try_new(schema.clone(), buffer_pool).unwrap(); let meta1 = super::TupleMeta { @@ -337,7 +338,7 @@ mod tests { ])); let disk_manager = DiskManager::try_new(temp_path).unwrap(); - let buffer_pool = BufferPoolManager::new(1000, Arc::new(disk_manager)); + let buffer_pool = Arc::new(BufferPoolManager::new(1000, Arc::new(disk_manager))); let mut table_heap = TableHeap::try_new(schema.clone(), buffer_pool).unwrap(); let meta1 = super::TupleMeta {