quill_sql/storage/page/
freelist_page.rs

1use 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}