photondb_engine/tree/
mod.rs1mod 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}