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