Skip to main content

siamesedb/filedb/
mod.rs

1use std::cell::RefCell;
2use std::io::Result;
3use std::path::{Path, PathBuf};
4use std::rc::Rc;
5
6mod dbmap;
7mod inner;
8
9pub use dbmap::{
10    DbBytes, DbInt, DbString, FileDbMap, FileDbMapDbBytes, FileDbMapDbInt, FileDbMapDbString,
11};
12pub use inner::dbxxx::{DbXxxIntoIter, DbXxxIter, DbXxxIterMut, FileDbXxxInner};
13use inner::semtype::*;
14use inner::FileDbInner;
15
16/// Parameters of buffer.
17#[derive(Debug, Clone)]
18pub enum FileBufSizeParam {
19    /// Fixed buffer size
20    Size(u32),
21    /// Auto buffer size by file size.
22    PerMille(u16),
23    /// Default auto buffer size by file size.
24    Auto,
25}
26
27/// Parameters of filedb.
28///
29/// chunk_size is MUST power of 2.
30#[derive(Debug, Clone)]
31pub struct FileDbParams {
32    /// buffer size of val file buffer. Default is auto buffer size.
33    pub val_buf_size: FileBufSizeParam,
34    /// buffer size of key file buffer. Default is full buffer size.
35    pub key_buf_size: FileBufSizeParam,
36    /// buffer size of idx file buffer. Default is full buffer size.
37    pub idx_buf_size: FileBufSizeParam,
38    /// buffer size of htx file buffer. Default is full buffer size.
39    pub htx_buf_size: FileBufSizeParam,
40}
41
42impl std::default::Default for FileDbParams {
43    fn default() -> Self {
44        Self {
45            val_buf_size: FileBufSizeParam::Auto,
46            key_buf_size: FileBufSizeParam::PerMille(1000),
47            idx_buf_size: FileBufSizeParam::PerMille(1000),
48            htx_buf_size: FileBufSizeParam::PerMille(1000),
49        }
50    }
51}
52
53/// Checks the file db map for debug.
54pub trait CheckFileDbMap {
55    /// hash table size and item counts in htx file.
56    #[cfg(feature = "htx")]
57    fn ht_size_and_count(&self) -> Result<(u64, u64)>;
58    /// convert the index node tree to graph string for debug.
59    fn graph_string(&self) -> Result<String>;
60    /// convert the index node tree to graph string for debug.
61    fn graph_string_with_key_string(&self) -> Result<String>;
62    /// check the index node tree is balanced
63    fn is_balanced(&self) -> Result<bool>;
64    /// check the index node tree is multi search tree
65    fn is_mst_valid(&self) -> Result<bool>;
66    /// check the index node except the root and leaves of the tree has branches of hm or more.
67    fn is_dense(&self) -> Result<bool>;
68    /// get the depth of the index node.
69    fn depth_of_node_tree(&self) -> Result<u64>;
70    /// count of the free node
71    fn count_of_free_node(&self) -> Result<CountOfPerSize>;
72    /// count of the free key piece
73    fn count_of_free_key_piece(&self) -> Result<CountOfPerSize>;
74    /// count of the free key piece
75    fn count_of_free_value_piece(&self) -> Result<CountOfPerSize>;
76    /// count of the used piece and the used node
77    fn count_of_used_node(&self) -> Result<(CountOfPerSize, CountOfPerSize, CountOfPerSize)>;
78    /// buffer statistics
79    #[cfg(feature = "buf_stats")]
80    fn buf_stats(&self) -> Vec<(String, i64)>;
81    /// key piece size statistics
82    fn key_piece_size_stats(&self) -> Result<RecordSizeStats<Key>>;
83    /// value piece size statistics
84    fn value_piece_size_stats(&self) -> Result<RecordSizeStats<Value>>;
85    /// keys count statistics
86    fn keys_count_stats(&self) -> Result<KeysCountStats>;
87    /// key length statistics
88    fn key_length_stats(&self) -> Result<LengthStats<Key>>;
89    /// value length statistics
90    fn value_length_stats(&self) -> Result<LengthStats<Value>>;
91    /// htx filling rate per mill
92    #[cfg(feature = "htx")]
93    fn htx_filling_rate_per_mill(&self) -> Result<(u64, u32)>;
94}
95
96pub type CountOfPerSize = Vec<(u32, u64)>;
97
98/// piece size statistics.
99#[derive(Debug, Default)]
100pub struct RecordSizeStats<T>(Vec<(PieceSize<T>, u64)>);
101
102impl<T: Copy + Ord> RecordSizeStats<T> {
103    pub fn new(vec: Vec<(PieceSize<T>, u64)>) -> Self {
104        Self(vec)
105    }
106    pub fn touch_size(&mut self, piece_size: PieceSize<T>) {
107        match self.0.binary_search_by_key(&piece_size, |&(a, _b)| a) {
108            Ok(sz_idx) => {
109                self.0[sz_idx].1 += 1;
110            }
111            Err(sz_idx) => {
112                self.0.insert(sz_idx, (piece_size, 1));
113            }
114        }
115    }
116}
117
118impl<T: Copy> std::fmt::Display for RecordSizeStats<T> {
119    fn fmt(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result {
120        formatter.write_str("[")?;
121        if self.0.len() > 1 {
122            for (a, b) in self.0.iter().take(self.0.len() - 1) {
123                formatter.write_fmt(format_args!("({}, {})", a, b))?;
124                formatter.write_str(", ")?;
125            }
126        }
127        if !self.0.is_empty() {
128            let (a, b) = self.0[self.0.len() - 1];
129            formatter.write_fmt(format_args!("({}, {})", a, b))?;
130        }
131        formatter.write_str("]")?;
132        Ok(())
133    }
134}
135
136pub type KeyPieceSizeStats = RecordSizeStats<Key>;
137pub type ValueRecordSizeStats = RecordSizeStats<Value>;
138
139/// piece size statistics.
140#[derive(Debug, Default)]
141pub struct KeysCountStats(Vec<(KeysCount, u64)>);
142
143impl KeysCountStats {
144    pub fn new(vec: Vec<(KeysCount, u64)>) -> Self {
145        Self(vec)
146    }
147    pub fn touch_size(&mut self, keys_count: KeysCount) {
148        match self.0.binary_search_by_key(&keys_count, |&(a, _b)| a) {
149            Ok(sz_idx) => {
150                self.0[sz_idx].1 += 1;
151            }
152            Err(sz_idx) => {
153                self.0.insert(sz_idx, (keys_count, 1));
154            }
155        }
156    }
157}
158
159impl std::fmt::Display for KeysCountStats {
160    fn fmt(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result {
161        formatter.write_str("[")?;
162        if self.0.len() > 1 {
163            for (a, b) in self.0.iter().take(self.0.len() - 1) {
164                formatter.write_fmt(format_args!("({}, {})", a, b))?;
165                formatter.write_str(", ")?;
166            }
167        }
168        if !self.0.is_empty() {
169            let (a, b) = self.0[self.0.len() - 1];
170            formatter.write_fmt(format_args!("({}, {})", a, b))?;
171        }
172        formatter.write_str("]")?;
173        Ok(())
174    }
175}
176
177/// key or value length statistics.
178#[derive(Debug, Default)]
179pub struct LengthStats<T: Default>(Vec<(Length<T>, u64)>);
180
181impl<T: Ord + Default + Copy> LengthStats<T> {
182    pub fn new(vec: Vec<(Length<T>, u64)>) -> Self {
183        Self(vec)
184    }
185    pub fn touch_length(&mut self, key_length: Length<T>) {
186        match self.0.binary_search_by_key(&key_length, |&(a, _b)| a) {
187            Ok(sz_idx) => {
188                self.0[sz_idx].1 += 1;
189            }
190            Err(sz_idx) => {
191                self.0.insert(sz_idx, (key_length, 1));
192            }
193        }
194    }
195}
196
197impl<T: Default + Copy> std::fmt::Display for LengthStats<T> {
198    fn fmt(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result {
199        formatter.write_str("[")?;
200        if self.0.len() > 1 {
201            for (a, b) in self.0.iter().take(self.0.len() - 1) {
202                formatter.write_fmt(format_args!("({}, {})", a, b))?;
203                formatter.write_str(", ")?;
204            }
205        }
206        if !self.0.is_empty() {
207            let (a, b) = self.0[self.0.len() - 1];
208            formatter.write_fmt(format_args!("({}, {})", a, b))?;
209        }
210        formatter.write_str("]")?;
211        Ok(())
212    }
213}
214
215/// File Database.
216#[derive(Debug, Clone)]
217pub struct FileDb(Rc<RefCell<FileDbInner>>);
218
219impl FileDb {
220    pub fn open<P: AsRef<Path>>(path: P) -> Result<Self> {
221        Ok(Self(Rc::new(RefCell::new(FileDbInner::open(path)?))))
222    }
223    pub fn db_map_string(&self, name: &str) -> Result<FileDbMapDbString> {
224        self.db_map_string_with_params(name, FileDbParams::default())
225    }
226    pub fn db_map_string_with_params(
227        &self,
228        name: &str,
229        params: FileDbParams,
230    ) -> Result<FileDbMapDbString> {
231        if let Some(m) = RefCell::borrow(&self.0).db_map_string(name) {
232            return Ok(m);
233        }
234        RefCell::borrow_mut(&self.0).create_db_map(name, params)?;
235        match RefCell::borrow(&self.0).db_map_string(name) {
236            Some(m) => Ok(m),
237            None => panic!("Cannot create db_maps: {}", name),
238        }
239    }
240    pub fn db_map_bytes(&self, name: &str) -> Result<FileDbMapDbBytes> {
241        self.db_map_bytes_with_params(name, FileDbParams::default())
242    }
243    pub fn db_map_bytes_with_params(
244        &self,
245        name: &str,
246        params: FileDbParams,
247    ) -> Result<FileDbMapDbBytes> {
248        if let Some(m) = RefCell::borrow(&self.0).db_map_bytes(name) {
249            return Ok(m);
250        }
251        RefCell::borrow_mut(&self.0).create_db_map_bytes(name, params)?;
252        match RefCell::borrow(&self.0).db_map_bytes(name) {
253            Some(m) => Ok(m),
254            None => panic!("Cannot create db_maps: {}", name),
255        }
256    }
257    pub fn db_map_int(&self, name: &str) -> Result<FileDbMapDbInt> {
258        self.db_map_int_with_params(name, FileDbParams::default())
259    }
260    pub fn db_map_int_with_params(
261        &self,
262        name: &str,
263        params: FileDbParams,
264    ) -> Result<FileDbMapDbInt> {
265        if let Some(m) = RefCell::borrow(&self.0).db_map_int(name) {
266            return Ok(m);
267        }
268        RefCell::borrow_mut(&self.0).create_db_map_dbint(name, params)?;
269        match RefCell::borrow(&self.0).db_map_int(name) {
270            Some(m) => Ok(m),
271            None => panic!("Cannot create db_maps: {}", name),
272        }
273    }
274    pub fn path(&self) -> PathBuf {
275        RefCell::borrow(&self.0).path().to_path_buf()
276    }
277    pub fn sync_all(&self) -> Result<()> {
278        RefCell::borrow_mut(&self.0).sync_all()
279    }
280    pub fn sync_data(&self) -> Result<()> {
281        RefCell::borrow_mut(&self.0).sync_data()
282    }
283}
284
285//--
286#[cfg(not(windows))]
287#[cfg(test)]
288mod debug {
289    use super::FileDbInner;
290    use super::{FileDb, FileDbMapDbInt, FileDbMapDbString};
291    use super::{KeyPieceSizeStats, ValueRecordSizeStats};
292    //
293    #[test]
294    fn test_size_of() {
295        #[cfg(target_pointer_width = "64")]
296        {
297            assert_eq!(std::mem::size_of::<FileDb>(), 8);
298            assert_eq!(std::mem::size_of::<FileDbMapDbString>(), 8);
299            assert_eq!(std::mem::size_of::<FileDbMapDbInt>(), 8);
300            //
301            assert_eq!(std::mem::size_of::<FileDbInner>(), 96);
302            //
303            assert_eq!(std::mem::size_of::<KeyPieceSizeStats>(), 24);
304            assert_eq!(std::mem::size_of::<ValueRecordSizeStats>(), 24);
305        }
306        //
307        #[cfg(target_pointer_width = "32")]
308        {
309            assert_eq!(std::mem::size_of::<FileDb>(), 4);
310            assert_eq!(std::mem::size_of::<FileDbMapDbString>(), 4);
311            assert_eq!(std::mem::size_of::<FileDbMapDbInt>(), 4);
312            //
313            assert_eq!(std::mem::size_of::<FileDbInner>(), 48);
314            //
315            assert_eq!(std::mem::size_of::<KeyPieceSizeStats>(), 12);
316            assert_eq!(std::mem::size_of::<ValueRecordSizeStats>(), 12);
317        }
318    }
319}