quill_sql/storage/page/
freelist_page.rs1use crate::buffer::{PageId, INVALID_PAGE_ID, PAGE_SIZE};
2use crate::storage::codec::{CommonCodec, FreelistPageHeaderCodec};
3use std::sync::LazyLock;
4
5static EMPTY_FREELIST_PAGE_HEADER: FreelistPageHeader = FreelistPageHeader {
6 next_page_id: 0,
7 current_size: 0,
8 max_size: 0,
9};
10
11pub static FREELIST_PAGE_MAX_SIZE: LazyLock<usize> = LazyLock::new(|| {
12 (PAGE_SIZE - FreelistPageHeaderCodec::encode(&EMPTY_FREELIST_PAGE_HEADER).len())
13 / CommonCodec::encode_u32(INVALID_PAGE_ID).len()
14});
15
16#[derive(Debug, Eq, PartialEq)]
17pub struct FreelistPage {
18 pub header: FreelistPageHeader,
19 pub array: Vec<PageId>,
20}
21
22#[derive(Debug, Eq, PartialEq)]
23pub struct FreelistPageHeader {
24 pub next_page_id: PageId,
25 pub current_size: u32,
26 pub max_size: u32,
27}
28
29impl FreelistPage {
30 pub fn new() -> Self {
31 Self {
32 header: FreelistPageHeader {
33 next_page_id: INVALID_PAGE_ID,
34 current_size: 0,
35 max_size: *FREELIST_PAGE_MAX_SIZE as u32,
36 },
37 array: vec![],
38 }
39 }
40
41 pub fn is_full(&self) -> bool {
42 self.header.current_size >= self.header.max_size
43 }
44
45 pub fn push(&mut self, page_id: PageId) {
46 self.array.push(page_id);
47 self.header.current_size += 1;
48 }
49
50 pub fn pop(&mut self) -> Option<PageId> {
51 let page_id = self.array.pop();
52 if page_id.is_some() {
53 self.header.current_size -= 1;
54 }
55 page_id
56 }
57}