simple_db_rust/btree/
buffer_pool.rs1use log::info;
2
3use crate::{util::simple_int_tuple_scheme, Tuple};
4
5use std::{
6 cell::RefCell,
7 collections::HashMap,
8 fs::File,
9 io::{prelude::*, Result, Seek, SeekFrom},
10 rc::Rc,
11 sync::atomic::{AtomicUsize, Ordering},
12};
13
14use std::{mem, sync::Once};
15
16use super::{
17 page::{BTreeInternalPage, BTreeRootPointerPage, PageCategory},
18 tuple::TupleScheme,
19};
20
21use super::{
22 catalog::Catalog,
23 page::{BTreeLeafPage, BTreePageID},
24};
25
26pub const DEFAULT_PAGE_SIZE: usize = 4096;
27static PAGE_SIZE: AtomicUsize = AtomicUsize::new(DEFAULT_PAGE_SIZE);
28
29pub struct BufferPool {
30 roop_pointer_buffer:
31 HashMap<BTreePageID, Rc<RefCell<BTreeRootPointerPage>>>,
32 pub internal_buffer: HashMap<BTreePageID, Rc<RefCell<BTreeInternalPage>>>,
33 pub leaf_buffer: HashMap<BTreePageID, Rc<RefCell<BTreeLeafPage>>>,
34}
35
36type Key = BTreePageID;
37
38impl BufferPool {
39 fn new() -> BufferPool {
40 BufferPool {
41 roop_pointer_buffer: HashMap::new(),
42 internal_buffer: HashMap::new(),
43 leaf_buffer: HashMap::new(),
44 }
45 }
46
47 pub fn global() -> &'static mut Self {
48 static mut SINGLETON: *mut BufferPool = 0 as *mut BufferPool;
50 static ONCE: Once = Once::new();
51
52 ONCE.call_once(|| {
53 let singleton = Self::new();
55
56 unsafe {
57 SINGLETON = mem::transmute(Box::new(singleton));
59 }
60 });
61
62 unsafe {
63 SINGLETON.as_mut().unwrap()
67 }
68 }
69
70 pub fn clear(&mut self) {
71 self.roop_pointer_buffer.clear();
72 self.internal_buffer.clear();
73 self.leaf_buffer.clear();
74 }
75
76 fn read_page(&self, file: &mut File, key: &Key) -> Result<Vec<u8>> {
77 let page_size = Self::get_page_size();
78 let start_pos = key.page_index * page_size;
79 file.seek(SeekFrom::Start(start_pos as u64))
80 .expect("io error");
81
82 let mut buf: Vec<u8> = vec![0; page_size];
83 file.read_exact(&mut buf).expect("io error");
84 Ok(buf)
85 }
86
87 pub fn get_internal_page(
88 &mut self,
89 key: &Key,
90 ) -> Result<Rc<RefCell<BTreeInternalPage>>> {
91 match self.internal_buffer.get(key) {
92 Some(_) => {}
93 None => {
94 let v =
96 Catalog::global().get_table(key.get_table_id()).unwrap();
97 let table = v.borrow();
98
99 let buf = self.read_page(&mut table.get_file(), key)?;
101
102 let page = BTreeInternalPage::new(
104 key,
105 buf.to_vec(),
106 &table.tuple_scheme,
107 table.key_field,
108 );
109
110 self.internal_buffer
112 .insert(*key, Rc::new(RefCell::new(page)));
113 }
114 }
115
116 Ok(Rc::clone(self.internal_buffer.get(key).unwrap()))
117 }
118
119 pub fn get_leaf_page(
120 &mut self,
121 key: &Key,
122 ) -> Result<Rc<RefCell<BTreeLeafPage>>> {
123 match self.leaf_buffer.get(key) {
124 Some(_) => {}
125 None => {
126 let v =
128 Catalog::global().get_table(key.get_table_id()).unwrap();
129 let table = v.borrow();
130
131 let buf = self.read_page(&mut table.get_file(), key)?;
133
134 let page = BTreeLeafPage::new(
136 key,
137 buf.to_vec(),
138 &table.tuple_scheme,
139 table.key_field,
140 );
141
142 self.leaf_buffer.insert(*key, Rc::new(RefCell::new(page)));
144 }
145 }
146
147 Ok(Rc::clone(self.leaf_buffer.get(key).unwrap()))
148 }
149
150 pub fn get_root_pointer_page(
151 &mut self,
152 key: &Key,
153 ) -> Result<Rc<RefCell<BTreeRootPointerPage>>> {
154 match self.roop_pointer_buffer.get(key) {
155 Some(_) => {}
156 None => {
157 let v =
159 Catalog::global().get_table(key.get_table_id()).unwrap();
160 let table = v.borrow();
161
162 let buf = self.read_page(&mut table.get_file(), key)?;
164
165 let pid = BTreePageID::new(
167 PageCategory::RootPointer,
168 table.get_id(),
169 0,
170 );
171 let page = BTreeRootPointerPage::new(&pid, buf.to_vec());
172
173 self.roop_pointer_buffer
175 .insert(*key, Rc::new(RefCell::new(page)));
176 }
177 }
178
179 Ok(Rc::clone(self.roop_pointer_buffer.get(key).unwrap()))
180 }
181
182 pub fn set_page_size(page_size: usize) {
183 PAGE_SIZE.store(page_size, Ordering::Relaxed);
184
185 info!("set page size to {}", page_size);
186 let scheme = simple_int_tuple_scheme(2, "");
187 info!(
188 "leaf page slot count: {}",
189 BTreeLeafPage::get_max_tuples(&scheme)
190 );
191 info!(
192 "internal page entries count: {}, children count: {}",
193 BTreeInternalPage::get_max_entries(4),
194 BTreeInternalPage::get_max_entries(4) + 1,
195 );
196 }
197
198 pub fn rows_per_page(scheme: &TupleScheme) -> usize {
199 BTreeLeafPage::get_max_tuples(&scheme)
200 }
201
202 pub fn children_per_page() -> usize {
203 BTreeInternalPage::get_max_entries(4) + 1
204 }
205
206 pub fn get_page_size() -> usize {
207 PAGE_SIZE.load(Ordering::Relaxed)
208 }
209
210 pub fn insert_tuple(&mut self, table_id: i32, t: Tuple) {
222 let v = Catalog::global().get_table(&table_id).unwrap().borrow();
223 v.insert_tuple(&t);
224 }
225}
226
227#[cfg(test)]
228mod tests {
229 use crate::{
230 btree::page::PageCategory, util::simple_int_tuple_scheme, BTreeTable,
231 };
232
233 use super::*;
234
235 #[test]
236 fn test_buffer_pool() {
237 let bp = BufferPool::global();
238
239 let table = BTreeTable::new(
241 "test_buffer_pool.db",
242 0,
243 &simple_int_tuple_scheme(3, ""),
244 );
245 let table_id = table.get_id();
246 Catalog::global().add_table(Rc::new(RefCell::new(table)));
247
248 let page_id = BTreePageID::new(PageCategory::RootPointer, table_id, 0);
252 match bp.get_root_pointer_page(&page_id) {
253 Ok(_) => {}
254 Err(e) => {
255 panic!("err: {}", e)
256 }
257 }
258
259 let page_id = BTreePageID::new(PageCategory::Leaf, table_id, 1);
260 match bp.get_root_pointer_page(&page_id) {
261 Ok(_) => {}
262 Err(e) => {
263 panic!("err: {}", e)
264 }
265 }
266
267 let page_id = BTreePageID::new(PageCategory::Leaf, table_id, 1);
268 match bp.get_root_pointer_page(&page_id) {
269 Ok(_) => {}
270 Err(e) => {
271 panic!("err: {}", e)
272 }
273 }
274 }
275}