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#[derive(Debug, Clone)]
18pub enum FileBufSizeParam {
19 Size(u32),
21 PerMille(u16),
23 Auto,
25}
26
27#[derive(Debug, Clone)]
31pub struct FileDbParams {
32 pub val_buf_size: FileBufSizeParam,
34 pub key_buf_size: FileBufSizeParam,
36 pub idx_buf_size: FileBufSizeParam,
38 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
53pub trait CheckFileDbMap {
55 #[cfg(feature = "htx")]
57 fn ht_size_and_count(&self) -> Result<(u64, u64)>;
58 fn graph_string(&self) -> Result<String>;
60 fn graph_string_with_key_string(&self) -> Result<String>;
62 fn is_balanced(&self) -> Result<bool>;
64 fn is_mst_valid(&self) -> Result<bool>;
66 fn is_dense(&self) -> Result<bool>;
68 fn depth_of_node_tree(&self) -> Result<u64>;
70 fn count_of_free_node(&self) -> Result<CountOfPerSize>;
72 fn count_of_free_key_piece(&self) -> Result<CountOfPerSize>;
74 fn count_of_free_value_piece(&self) -> Result<CountOfPerSize>;
76 fn count_of_used_node(&self) -> Result<(CountOfPerSize, CountOfPerSize, CountOfPerSize)>;
78 #[cfg(feature = "buf_stats")]
80 fn buf_stats(&self) -> Vec<(String, i64)>;
81 fn key_piece_size_stats(&self) -> Result<RecordSizeStats<Key>>;
83 fn value_piece_size_stats(&self) -> Result<RecordSizeStats<Value>>;
85 fn keys_count_stats(&self) -> Result<KeysCountStats>;
87 fn key_length_stats(&self) -> Result<LengthStats<Key>>;
89 fn value_length_stats(&self) -> Result<LengthStats<Value>>;
91 #[cfg(feature = "htx")]
93 fn htx_filling_rate_per_mill(&self) -> Result<(u64, u32)>;
94}
95
96pub type CountOfPerSize = Vec<(u32, u64)>;
97
98#[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#[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#[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#[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#[cfg(not(windows))]
287#[cfg(test)]
288mod debug {
289 use super::FileDbInner;
290 use super::{FileDb, FileDbMapDbInt, FileDbMapDbString};
291 use super::{KeyPieceSizeStats, ValueRecordSizeStats};
292 #[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 assert_eq!(std::mem::size_of::<FileDbInner>(), 96);
302 assert_eq!(std::mem::size_of::<KeyPieceSizeStats>(), 24);
304 assert_eq!(std::mem::size_of::<ValueRecordSizeStats>(), 24);
305 }
306 #[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 assert_eq!(std::mem::size_of::<FileDbInner>(), 48);
314 assert_eq!(std::mem::size_of::<KeyPieceSizeStats>(), 12);
316 assert_eq!(std::mem::size_of::<ValueRecordSizeStats>(), 12);
317 }
318 }
319}