sweep_bptree/tree/
iterator.rs

1use std::iter::FusedIterator;
2
3use super::*;
4
5/// A borrowed iterator for BPlusTree
6/// Borrowed, means the underlying tree won't change, so this is faster
7/// compare to Cursor.
8#[derive(Clone)]
9pub struct Iter<'a, S: NodeStore> {
10    tree: &'a BPlusTree<S>,
11    len: usize,
12    leaf: Option<&'a LeafNode<S::K, S::V>>,
13    leaf_offset: usize,
14
15    end: Option<(&'a LeafNode<S::K, S::V>, usize)>,
16}
17
18impl<'a, S: NodeStore> Iter<'a, S> {
19    pub(crate) fn new(tree: &'a BPlusTree<S>) -> Self {
20        let leaf = tree
21            .first_leaf()
22            .map(|leaf_id| tree.node_store.get_leaf(leaf_id));
23        Self {
24            tree,
25            len: tree.len(),
26            leaf,
27            leaf_offset: 0,
28            end: None,
29        }
30    }
31}
32
33impl<'a, S: NodeStore> Iterator for Iter<'a, S> {
34    type Item = (&'a S::K, &'a S::V);
35
36    #[inline]
37    fn size_hint(&self) -> (usize, Option<usize>) {
38        (self.len, Some(self.len))
39    }
40
41    fn next(&mut self) -> Option<Self::Item> {
42        if self.len == 0 {
43            return None;
44        }
45
46        let leaf = self.leaf?;
47        let offset = self.leaf_offset;
48        let kv = leaf.data_at(offset);
49
50        // move the position to next valid
51        if offset + 1 < leaf.len() {
52            self.leaf_offset = offset + 1;
53            self.len -= 1;
54            Some(kv)
55        } else {
56            match leaf.next() {
57                Some(next_id) => {
58                    self.leaf = Some(self.tree.node_store.get_leaf(next_id));
59                    self.leaf_offset = 0;
60                }
61                None => {
62                    self.leaf = None;
63                    self.leaf_offset = 0;
64                }
65            }
66
67            self.len -= 1;
68            Some(kv)
69        }
70    }
71}
72
73impl<'a, S: NodeStore> DoubleEndedIterator for Iter<'a, S> {
74    fn next_back(&mut self) -> Option<Self::Item> {
75        if self.len == 0 {
76            return None;
77        }
78
79        match self.end {
80            Some((leaf, offset)) => {
81                if offset > 0 {
82                    let offset = offset - 1;
83                    let kv = leaf.data_at(offset);
84                    self.end = Some((leaf, offset));
85                    Some(kv)
86                } else {
87                    // move to previous leaf
88                    let prev_id = leaf.prev()?;
89                    let leaf = self.tree.node_store.get_leaf(prev_id);
90                    let offset = leaf.len() - 1;
91
92                    self.end = Some((leaf, offset));
93                    Some(leaf.data_at(offset))
94                }
95            }
96            None => {
97                let last_leaf_id = self.tree.last_leaf()?;
98                let last_leaf = self.tree.node_store.get_leaf(last_leaf_id);
99                let last_leaf_size = last_leaf.len();
100                if last_leaf_size == 0 {
101                    return None;
102                }
103
104                let offset = last_leaf_size - 1;
105
106                self.end = Some((last_leaf, offset));
107                Some(last_leaf.data_at(offset))
108            }
109        }
110    }
111}
112
113impl<'a, S: NodeStore> FusedIterator for Iter<'a, S> {}
114impl<'a, S: NodeStore> ExactSizeIterator for Iter<'a, S> {}
115
116pub struct IntoIter<S: NodeStore> {
117    node_store: S,
118    len: usize,
119    /// current iterator pos
120    pos: (LeafNodeId, usize),
121    /// the end of the iterator
122    end: (LeafNodeId, usize),
123}
124
125impl<S: NodeStore> IntoIter<S> {
126    pub fn new(tree: BPlusTree<S>) -> Self {
127        // the tree ensures there is at least one leaf
128        let first_leaf_id = tree.first_leaf().unwrap();
129        let last_leaf_id = tree.last_leaf().unwrap();
130
131        let (node_store, _root_id, len) = tree.into_parts();
132
133        let last_leaf_size = node_store.get_leaf(last_leaf_id).len();
134
135        Self {
136            node_store,
137            len,
138            pos: (first_leaf_id, 0),
139            end: (last_leaf_id, last_leaf_size),
140        }
141    }
142}
143
144impl<S: NodeStore> Iterator for IntoIter<S> {
145    type Item = (S::K, S::V);
146
147    #[inline]
148    fn size_hint(&self) -> (usize, Option<usize>) {
149        (self.len, Some(self.len))
150    }
151
152    fn next(&mut self) -> Option<Self::Item> {
153        if self.len() == 0 {
154            return None;
155        }
156
157        let (leaf_id, offset) = self.pos;
158        let leaf = self.node_store.get_mut_leaf(leaf_id);
159
160        if offset < leaf.len() {
161            // book keeping current len
162            self.len -= 1;
163            // we should not call delete_at which internally memcpy, instead, use mark_uninit to take
164            // the value out and leaves the memory uninit
165            // safety: right after we called this, the pos moves to next.
166            let kv = unsafe { leaf.take_data(offset) };
167            self.pos = (leaf_id, offset + 1);
168            return Some(kv);
169        } else {
170            // move to next leaf
171            match leaf.next() {
172                Some(next_id) => {
173                    self.pos = (next_id, 0);
174                    self.next()
175                }
176                None => {
177                    // pos is the valid position, so it should not be the end
178                    // we only reach here if len is mis counted
179                    unreachable!()
180                }
181            }
182        }
183    }
184}
185
186impl<S: NodeStore> DoubleEndedIterator for IntoIter<S> {
187    fn next_back(&mut self) -> Option<Self::Item> {
188        if self.len() == 0 {
189            return None;
190        }
191
192        let (leaf_id, offset) = self.end;
193        let leaf = self.node_store.get_mut_leaf(leaf_id);
194
195        if offset > 0 {
196            // book keeping current len
197            self.len -= 1;
198            // we should not call delete_at which internally memcpy, instead, use mark_uninit to take
199            // the value out and leaves the memory uninit
200            // safety: right after we called this, the pos moves to next.
201            let kv = unsafe { leaf.take_data(offset - 1) };
202            self.end = (leaf_id, offset - 1);
203            return Some(kv);
204        } else {
205            // move to prev leaf
206            match leaf.prev() {
207                Some(prev_id) => {
208                    let prev_leaf = self.node_store.get_mut_leaf(prev_id);
209                    self.end = (prev_id, prev_leaf.len());
210                    self.next_back()
211                }
212                None => {
213                    // we only reach here if len is mis counted
214                    unreachable!()
215                }
216            }
217        }
218    }
219}
220
221impl<S: NodeStore> FusedIterator for IntoIter<S> {}
222impl<S: NodeStore> ExactSizeIterator for IntoIter<S> {}
223
224impl<S: NodeStore> Drop for IntoIter<S> {
225    fn drop(&mut self) {
226        // drop all the remaining items
227        while self.next().is_some() {}
228    }
229}
230
231#[cfg(test)]
232mod tests {
233    use std::rc::Rc;
234
235    use super::*;
236    use crate::tree::tests::create_test_tree;
237
238    #[derive(Clone)]
239    struct TestValue {
240        counter: Rc<std::sync::atomic::AtomicU64>,
241    }
242
243    impl TestValue {
244        fn new(counter: Rc<std::sync::atomic::AtomicU64>) -> Self {
245            Self { counter }
246        }
247    }
248
249    impl Drop for TestValue {
250        fn drop(&mut self) {
251            self.counter
252                .fetch_add(1, std::sync::atomic::Ordering::Relaxed);
253        }
254    }
255
256    #[test]
257    fn test_iter() {
258        let (tree, _) = create_test_tree::<100>();
259        let iter = Iter::new(&tree);
260        let kvs = iter.collect::<Vec<_>>();
261        assert_eq!(kvs.len(), tree.len());
262    }
263
264    #[test]
265    fn test_iter_double_ended() {
266        let (tree, _keys) = create_test_tree::<100>();
267        let kvs = Iter::new(&tree).collect::<Vec<_>>();
268        let rev_kvs = Iter::new(&tree).rev().collect::<Vec<_>>();
269
270        assert_eq!(rev_kvs.len(), kvs.len());
271        assert_eq!(rev_kvs, kvs.iter().rev().cloned().collect::<Vec<_>>());
272    }
273
274    #[test]
275    fn test_into_iter_collect() {
276        // test collect and drop
277        let node_store = NodeStoreVec::<i64, TestValue>::new();
278        let mut tree = BPlusTree::new(node_store);
279        let counter = Rc::new(std::sync::atomic::AtomicU64::new(0));
280        for i in 0..10 {
281            tree.insert(i, TestValue::new(counter.clone()));
282        }
283        let iter = IntoIter::new(tree);
284        let items = iter.collect::<Vec<_>>();
285        assert_eq!(items.len(), 10);
286        drop(items);
287
288        assert_eq!(counter.load(std::sync::atomic::Ordering::Relaxed), 10);
289    }
290
291    #[test]
292    fn test_into_iter_drop() {
293        // test drop
294        let node_store = NodeStoreVec::<i64, TestValue>::new();
295        let mut tree = BPlusTree::new(node_store);
296        let counter = Rc::new(std::sync::atomic::AtomicU64::new(0));
297        for i in 0..10 {
298            tree.insert(i, TestValue::new(counter.clone()));
299        }
300        let iter = IntoIter::new(tree);
301        drop(iter);
302
303        assert_eq!(counter.load(std::sync::atomic::Ordering::Relaxed), 10);
304    }
305
306    #[test]
307    fn test_into_iter_double_ended() {
308        let node_store = NodeStoreVec::<i64, TestValue>::new();
309        let mut tree = BPlusTree::new(node_store);
310        let counter = Rc::new(std::sync::atomic::AtomicU64::new(0));
311        for i in 0..10 {
312            tree.insert(i, TestValue::new(counter.clone()));
313        }
314        let items = IntoIter::new(tree)
315            .rev()
316            .map(|(k, _v)| k)
317            .collect::<Vec<_>>();
318        assert_eq!(items.len(), 10);
319        assert_eq!(counter.load(std::sync::atomic::Ordering::Relaxed), 10);
320        assert_eq!(items, (0..10).rev().collect::<Vec<_>>());
321    }
322}