Skip to content

Commit

Permalink
Add PageRef
Browse files Browse the repository at this point in the history
  • Loading branch information
lewiszlw committed Feb 25, 2024
1 parent fa6c987 commit 79de483
Show file tree
Hide file tree
Showing 2 changed files with 74 additions and 2 deletions.
4 changes: 2 additions & 2 deletions bustubx/src/buffer/buffer_pool.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ pub struct BufferPoolManager {
pub replacer: Arc<RwLock<LRUKReplacer>>,
pub disk_manager: Arc<DiskManager>,
// 缓冲池中的页号与frame号的映射
page_table: DashMap<PageId, FrameId>,
page_table: Arc<DashMap<PageId, FrameId>>,
// 缓冲池中空闲的frame
free_list: Arc<RwLock<VecDeque<FrameId>>>,
}
Expand All @@ -37,7 +37,7 @@ impl BufferPoolManager {
pool,
replacer: Arc::new(RwLock::new(LRUKReplacer::new(num_pages, 2))),
disk_manager,
page_table: DashMap::new(),
page_table: Arc::new(DashMap::new()),
free_list: Arc::new(RwLock::new(free_list)),
}
}
Expand Down
72 changes: 72 additions & 0 deletions bustubx/src/buffer/page.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,11 @@
use crate::buffer::buffer_pool::FrameId;
use crate::buffer::replacer::LRUKReplacer;
use dashmap::DashMap;
use derive_with::With;
use log::error;
use std::ops::Deref;
use std::sync::atomic::AtomicU32;
use std::sync::{Arc, RwLock};

pub type PageId = u32;
pub type AtomicPageId = AtomicU32;
Expand Down Expand Up @@ -52,3 +58,69 @@ impl Page {
self.is_dirty = other.is_dirty;
}
}

pub struct PageRef {
page: Arc<RwLock<Page>>,
page_table: Arc<DashMap<PageId, FrameId>>,
replacer: Arc<RwLock<LRUKReplacer>>,
}

impl Deref for PageRef {
type Target = Arc<RwLock<Page>>;

fn deref(&self) -> &Self::Target {
&self.page
}
}

impl Drop for PageRef {
fn drop(&mut self) {
if self.page.read().unwrap().pin_count == 0 {
return;
}
let page_id = self.page.read().unwrap().page_id;
if let Some(frame_id) = self.page_table.get(&page_id) {
self.page.write().unwrap().pin_count -= 1;
if self.page.read().unwrap().pin_count == 0 {
if let Err(e) = self
.replacer
.write()
.unwrap()
.set_evictable(*frame_id, true)
{
panic!(
"Failed to set evictable to frame {}, err: {:?}",
*frame_id, e
);
}
}
} else {
error!("Cannot unpin page id {} as it is not in the pool", page_id);
}
}
}

#[cfg(test)]
mod tests {
use crate::buffer::replacer::LRUKReplacer;
use crate::buffer::{Page, PageRef};
use dashmap::DashMap;
use std::sync::{Arc, RwLock};

#[test]
fn page_ref() {
let page = Arc::new(RwLock::new(Page::new(1)));
let page_table = Arc::new(DashMap::new());
let replacer = Arc::new(RwLock::new(LRUKReplacer::new(10, 2)));

let page_ref = PageRef {
page: page.clone(),
page_table,
replacer,
};
assert_eq!(Arc::strong_count(&page), 2);
assert_eq!(page_ref.read().unwrap().page_id, 1);
drop(page_ref);
assert_eq!(Arc::strong_count(&page), 1);
}
}

0 comments on commit 79de483

Please sign in to comment.