brk_vec/structs/
compressed_pages_meta.rs

1use std::{
2    fs::{self, OpenOptions},
3    io::{self, Seek, SeekFrom, Write},
4    path::{Path, PathBuf},
5};
6
7use brk_core::Result;
8use rayon::prelude::*;
9use zerocopy::{IntoBytes, TryFromBytes};
10
11use super::{CompressedPageMetadata, UnsafeSlice};
12
13#[derive(Debug, Clone)]
14pub struct CompressedPagesMetadata {
15    vec: Vec<CompressedPageMetadata>,
16    change_at: Option<usize>,
17    path: PathBuf,
18}
19
20impl CompressedPagesMetadata {
21    const PAGE_SIZE: usize = size_of::<CompressedPageMetadata>();
22
23    pub fn read(path: &Path) -> Result<CompressedPagesMetadata> {
24        let path = path.join("pages_meta");
25
26        let slf = Self {
27            vec: fs::read(&path)
28                .unwrap_or_default()
29                .chunks(Self::PAGE_SIZE)
30                .map(|bytes| {
31                    if bytes.len() != Self::PAGE_SIZE {
32                        panic!()
33                    }
34                    CompressedPageMetadata::try_read_from_bytes(bytes).unwrap()
35                })
36                .collect::<Vec<_>>(),
37            path: path.to_owned(),
38            change_at: None,
39        };
40
41        Ok(slf)
42    }
43
44    pub fn write(&mut self) -> io::Result<()> {
45        if self.change_at.is_none() {
46            return Ok(());
47        }
48
49        let change_at = self.change_at.take().unwrap();
50
51        let len = (self.vec.len() - change_at) * Self::PAGE_SIZE;
52
53        let mut bytes: Vec<u8> = vec![0; len];
54
55        let unsafe_bytes = UnsafeSlice::new(&mut bytes);
56
57        self.vec[change_at..]
58            .par_iter()
59            .enumerate()
60            .for_each(|(i, v)| unsafe_bytes.copy_slice(i * Self::PAGE_SIZE, v.as_bytes()));
61
62        let mut file = OpenOptions::new()
63            .read(true)
64            .create(true)
65            .truncate(false)
66            .append(true)
67            .open(&self.path)?;
68
69        file.set_len((change_at * Self::PAGE_SIZE) as u64)?;
70        file.seek(SeekFrom::End(0))?;
71
72        file.write_all(&bytes)?;
73
74        Ok(())
75    }
76
77    pub fn len(&self) -> usize {
78        self.vec.len()
79    }
80
81    pub fn is_empty(&self) -> bool {
82        self.len() == 0
83    }
84
85    pub fn get(&self, page_index: usize) -> Option<&CompressedPageMetadata> {
86        self.vec.get(page_index)
87    }
88
89    pub fn last(&self) -> Option<&CompressedPageMetadata> {
90        self.vec.last()
91    }
92
93    pub fn pop(&mut self) -> Option<CompressedPageMetadata> {
94        self.vec.pop()
95    }
96
97    pub fn push(&mut self, page_index: usize, page: CompressedPageMetadata) {
98        if page_index != self.vec.len() {
99            panic!();
100        }
101
102        self.set_changed_at(page_index);
103
104        self.vec.push(page);
105    }
106
107    fn set_changed_at(&mut self, page_index: usize) {
108        if self.change_at.is_none_or(|pi| pi > page_index) {
109            self.change_at.replace(page_index);
110        }
111    }
112
113    pub fn truncate(&mut self, page_index: usize) -> Option<CompressedPageMetadata> {
114        let page = self.get(page_index).cloned();
115        self.vec.truncate(page_index);
116        self.set_changed_at(page_index);
117        page
118    }
119}