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