Skip to main content

photondb_engine/tree/
mod.rs

1mod error;
2pub use error::{Error, Result};
3
4mod map;
5pub use map::{Map, RawMap};
6
7mod stats;
8pub use stats::Stats;
9
10mod node;
11mod page;
12mod pagecache;
13mod pagestore;
14mod pagetable;
15#[allow(clippy::module_inception)]
16mod tree;
17
18#[derive(Clone, Debug)]
19pub struct Options {
20    pub cache_size: usize,
21    pub data_node_size: usize,
22    pub data_delta_length: usize,
23    pub index_node_size: usize,
24    pub index_delta_length: usize,
25}
26
27impl Default for Options {
28    fn default() -> Self {
29        Self {
30            cache_size: usize::MAX,
31            data_node_size: 8 * 1024,
32            data_delta_length: 8,
33            index_node_size: 4 * 1024,
34            index_delta_length: 4,
35        }
36    }
37}
38
39#[cfg(test)]
40mod tests {
41    use super::*;
42
43    const OPTIONS: Options = Options {
44        cache_size: usize::MAX,
45        data_node_size: 128,
46        data_delta_length: 4,
47        index_node_size: 64,
48        index_delta_length: 3,
49    };
50
51    fn init() {
52        let _ = env_logger::builder().try_init();
53    }
54
55    fn open(opts: Options) -> Map {
56        init();
57        Map::open(opts).unwrap()
58    }
59
60    fn get(map: &Map, i: usize, should_exists: bool) {
61        let buf = i.to_be_bytes();
62        let key = buf.as_slice();
63        let expect = if should_exists { Some(key) } else { None };
64        map.get(key, |got| {
65            assert_eq!(got, expect);
66        })
67        .unwrap();
68    }
69
70    fn iter(map: &Map, start: usize, end: usize, step: usize) {
71        let mut iter = map.iter();
72        for _ in 0..2 {
73            let mut i = start;
74            iter.reset();
75            iter.next_with(|item| {
76                let buf = i.to_be_bytes();
77                let key = buf.as_slice();
78                assert_eq!(item, (key, key));
79                i += step;
80            })
81            .unwrap();
82            assert_eq!(i, end);
83        }
84    }
85
86    fn put(map: &Map, i: usize) {
87        let buf = i.to_be_bytes();
88        let key = buf.as_slice();
89        map.put(key, key).unwrap();
90        map.get(key, |got| {
91            assert_eq!(got, Some(key));
92        })
93        .unwrap();
94    }
95
96    fn delete(map: &Map, i: usize) {
97        let buf = i.to_be_bytes();
98        let key = buf.as_slice();
99        map.delete(key).unwrap();
100        map.get(key, |got| {
101            assert_eq!(got, None);
102        })
103        .unwrap();
104    }
105
106    #[cfg(miri)]
107    const N: usize = 1 << 4;
108    #[cfg(miri)]
109    const T: usize = 4;
110    #[cfg(not(miri))]
111    const N: usize = 1 << 10;
112    #[cfg(not(miri))]
113    const T: usize = 8;
114
115    #[test]
116    fn crud() {
117        let map = open(OPTIONS);
118        for _ in 0..2 {
119            for i in 0..N {
120                put(&map, i);
121            }
122            for i in 0..N {
123                get(&map, i, true);
124            }
125            iter(&map, 0, N, 1);
126            for i in (1..N).step_by(2) {
127                delete(&map, i);
128            }
129            iter(&map, 0, N, 2);
130        }
131    }
132
133    #[test]
134    fn concurrent_crud() {
135        let map = open(OPTIONS);
136        let mut handles = Vec::new();
137        for _ in 0..T {
138            let map = map.clone();
139            let handle = std::thread::spawn(move || {
140                for i in 0..N {
141                    put(&map, i);
142                }
143                for i in 0..N {
144                    get(&map, i, true);
145                }
146                iter(&map, 0, N, 1);
147            });
148            handles.push(handle);
149        }
150        for handle in handles {
151            handle.join().unwrap();
152        }
153    }
154}