brk_vec/traits/
generic.rs

1use std::{
2    fs::{File, OpenOptions},
3    io::{self, Seek, SeekFrom, Write},
4    path::{Path, PathBuf},
5    sync::Arc,
6    time::{self, Duration},
7};
8
9use arc_swap::ArcSwap;
10use brk_core::{Result, Value};
11use memmap2::Mmap;
12
13use super::{StoredIndex, StoredType};
14
15pub trait GenericStoredVec<I, T>: Send + Sync
16where
17    I: StoredIndex,
18    T: StoredType,
19{
20    const SIZE_OF_T: usize = size_of::<T>();
21
22    #[inline]
23    fn read(&self, index: I, mmap: &Mmap) -> Result<Option<T>> {
24        self.read_(index.to_usize()?, mmap)
25    }
26    fn read_(&self, index: usize, mmap: &Mmap) -> Result<Option<T>>;
27
28    #[inline]
29    fn get_or_read(&self, index: I, mmap: &Mmap) -> Result<Option<Value<T>>> {
30        self.get_or_read_(index.to_usize()?, mmap)
31    }
32    #[inline]
33    fn get_or_read_(&self, index: usize, mmap: &Mmap) -> Result<Option<Value<T>>> {
34        let stored_len = mmap.len() / Self::SIZE_OF_T;
35
36        if index >= stored_len {
37            let pushed = self.pushed();
38            let j = index - stored_len;
39            if j >= pushed.len() {
40                return Ok(None);
41            }
42            Ok(pushed.get(j).map(Value::Ref))
43        } else {
44            Ok(self.read_(index, mmap)?.map(Value::Owned))
45        }
46    }
47
48    #[inline]
49    fn len_(&self) -> usize {
50        self.stored_len() + self.pushed_len()
51    }
52
53    fn mmap(&self) -> &ArcSwap<Mmap>;
54
55    fn stored_len(&self) -> usize;
56
57    fn pushed(&self) -> &[T];
58    #[inline]
59    fn pushed_len(&self) -> usize {
60        self.pushed().len()
61    }
62    fn mut_pushed(&mut self) -> &mut Vec<T>;
63    #[inline]
64    fn push(&mut self, value: T) {
65        self.mut_pushed().push(value)
66    }
67
68    fn path(&self) -> &Path;
69
70    // ---
71
72    fn open_file(&self) -> io::Result<File> {
73        Self::open_file_(&self.path_vec())
74    }
75    fn open_file_(path: &Path) -> io::Result<File> {
76        OpenOptions::new()
77            .read(true)
78            .create(true)
79            .truncate(false)
80            .append(true)
81            .open(path)
82    }
83
84    fn file_set_len(&mut self, len: u64) -> Result<()> {
85        let mut file = self.open_file()?;
86        Self::file_set_len_(&mut file, len)?;
87        self.update_mmap(file)
88    }
89    fn file_set_len_(file: &mut File, len: u64) -> Result<()> {
90        file.set_len(len)?;
91        file.seek(SeekFrom::End(0))?;
92        Ok(())
93    }
94
95    fn file_write_all(&mut self, buf: &[u8]) -> Result<()> {
96        let mut file = self.open_file()?;
97        file.write_all(buf)?;
98        self.update_mmap(file)
99    }
100
101    fn file_truncate_and_write_all(&mut self, len: u64, buf: &[u8]) -> Result<()> {
102        let mut file = self.open_file()?;
103        Self::file_set_len_(&mut file, len)?;
104        file.write_all(buf)?;
105        self.update_mmap(file)
106    }
107
108    #[inline]
109    fn reset(&mut self) -> Result<()> {
110        self.file_truncate_and_write_all(0, &[])
111    }
112
113    fn new_mmap(file: File) -> Result<Arc<Mmap>> {
114        Ok(Arc::new(unsafe { Mmap::map(&file)? }))
115    }
116
117    fn update_mmap(&mut self, file: File) -> Result<()> {
118        let mmap = Self::new_mmap(file)?;
119        self.mmap().store(mmap);
120        Ok(())
121    }
122
123    #[inline]
124    fn is_pushed_empty(&self) -> bool {
125        self.pushed_len() == 0
126    }
127
128    #[inline]
129    fn has(&self, index: I) -> Result<bool> {
130        Ok(self.has_(index.to_usize()?))
131    }
132    #[inline]
133    fn has_(&self, index: usize) -> bool {
134        index < self.len_()
135    }
136
137    fn flush(&mut self) -> Result<()>;
138
139    fn truncate_if_needed(&mut self, index: I) -> Result<()>;
140
141    #[inline]
142    fn path_vec(&self) -> PathBuf {
143        Self::path_vec_(self.path())
144    }
145    #[inline]
146    fn path_vec_(path: &Path) -> PathBuf {
147        path.join("vec")
148    }
149
150    #[inline]
151    fn path_version_(path: &Path) -> PathBuf {
152        path.join("version")
153    }
154
155    #[inline]
156    fn path_compressed_(path: &Path) -> PathBuf {
157        path.join("compressed")
158    }
159
160    #[inline]
161    fn name_(&self) -> String {
162        self.path()
163            .file_name()
164            .unwrap()
165            .to_str()
166            .unwrap()
167            .to_owned()
168    }
169
170    fn modified_time_(&self) -> Result<Duration> {
171        Ok(self
172            .path_vec()
173            .metadata()?
174            .modified()?
175            .duration_since(time::UNIX_EPOCH)?)
176    }
177}