use crate::storage::{Page, PageId};
use std::collections::{HashMap, VecDeque};
#[derive(Debug, Clone)]
pub struct BufferPool {
capacity: usize,
pages: HashMap<PageId, Page>,
lru_order: VecDeque<PageId>,
}
impl BufferPool {
pub fn new(capacity: usize) -> Self {
Self {
capacity: capacity,
pages: HashMap::new(),
lru_order: VecDeque::new(),
}
}
pub fn get(&mut self, page_id: PageId) -> Option<&Page> {
if self.pages.contains_key(&page_id) {
self.update_lru(page_id);
return self.pages.get(&page_id);
} else {
return None;
}
}
pub fn put(&mut self, page: Page) {
let page_id = page.id;
if self.pages.contains_key(&page_id) {
self.pages.insert(page_id, page);
self.update_lru(page_id);
return;
}
if self.pages.len() >= self.capacity && self.capacity > 0 {
if let Some(lru_id) = self.lru_order.pop_back() {
self.pages.remove(&lru_id);
}
}
if self.capacity > 0 && (self.pages.len() < self.capacity) {
self.pages.insert(page_id, page);
self.lru_order.push_front(page_id);
}
}
fn update_lru(&mut self, page_id: PageId) {
self.lru_order.retain(|&id| id != page_id);
self.lru_order.push_front(page_id);
}
pub fn remove(&mut self, page_id: PageId) {
self.pages.remove(&page_id);
self.lru_order.retain(|&id| id != page_id);
}
#[cfg(test)]
pub fn len(&self) -> usize {
self.pages.len()
}
}