brk_vec/structs/
compressed_pages_meta.rs1use 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}