bbolt_rs/
cursor.rs

1use crate::bucket::{BucketCell, BucketIApi, BucketRwIApi};
2use crate::common::page::tree::branch::MappedBranchPage;
3use crate::common::page::tree::leaf::{MappedLeafPage, BUCKET_LEAF_FLAG};
4use crate::common::page::tree::TreePage;
5use crate::common::page::{CoerciblePage, RefPage};
6use crate::common::{BVec, PgId, SplitRef};
7use crate::node::NodeRwCell;
8use crate::Error::IncompatibleValue;
9use bumpalo::Bump;
10use std::marker::PhantomData;
11
12/// Read-only Cursor API
13pub trait CursorApi {
14  /// Moves the cursor to the first item in the bucket and returns its key and value.
15  ///
16  /// If the bucket is empty then None is returned.
17  ///
18  /// ```rust
19  /// use bbolt_rs::*;
20  ///
21  /// fn main() -> Result<()> {
22  ///   let mut db = Bolt::open_mem()?;
23  ///
24  ///   db.update(|mut tx| {
25  ///     let mut b = tx.create_bucket_if_not_exists("test")?;
26  ///     b.put("key1", "value1")?;
27  ///     b.put("key2", "value2")?;
28  ///     b.put("key3", "value3")?;
29  ///     Ok(())
30  ///   })?;
31  ///
32  ///   db.view(|tx| {
33  ///     let b = tx.bucket("test").unwrap();
34  ///     let mut c = b.cursor();
35  ///     let first = c.first();
36  ///     assert_eq!(Some((b"key1".as_slice(), Some(b"value1".as_slice()))), first);
37  ///     Ok(())
38  ///   })?;
39  ///
40  ///   Ok(())
41  /// }
42  /// ```
43  fn first(&mut self) -> Option<(&[u8], Option<&[u8]>)>;
44
45  /// Moves the cursor to the last item in the bucket and returns its key and value.
46  ///
47  /// If the bucket is empty then None is returned.
48  ///
49  /// ```rust
50  /// use bbolt_rs::*;
51  ///
52  /// fn main() -> Result<()> {
53  ///   let mut db = Bolt::open_mem()?;
54  ///
55  ///   db.update(|mut tx| {
56  ///     let mut b = tx.create_bucket_if_not_exists("test")?;
57  ///     b.put("key1", "value1")?;
58  ///     b.put("key2", "value2")?;
59  ///     b.put("key3", "value3")?;
60  ///     Ok(())
61  ///   })?;
62  ///
63  ///   db.view(|tx| {
64  ///     let b = tx.bucket("test").unwrap();
65  ///     let mut c = b.cursor();
66  ///     let last = c.last();
67  ///     assert_eq!(Some((b"key3".as_slice(), Some(b"value3".as_slice()))), last);
68  ///     Ok(())
69  ///   })?;
70  ///
71  ///   Ok(())
72  /// }
73  /// ```
74  fn last(&mut self) -> Option<(&[u8], Option<&[u8]>)>;
75
76  /// Moves the cursor to the next item in the bucket and returns its key and value.
77  ///
78  /// If the cursor is at the end of the bucket then None is returned.
79  ///
80  /// ```rust
81  /// use bbolt_rs::*;
82  ///
83  /// fn main() -> Result<()> {
84  ///   let mut db = Bolt::open_mem()?;
85  ///
86  ///   db.update(|mut tx| {
87  ///     let mut b = tx.create_bucket_if_not_exists("test")?;
88  ///     b.put("key1", "value1")?;
89  ///     b.put("key2", "value2")?;
90  ///     b.put("key3", "value3")?;
91  ///     Ok(())
92  ///   })?;
93  ///
94  ///   db.view(|tx| {
95  ///     let b = tx.bucket("test").unwrap();
96  ///     let mut c = b.cursor();
97  ///     c.first();
98  ///     let next = c.next();
99  ///     assert_eq!(Some((b"key2".as_slice(), Some(b"value2".as_slice()))), next);
100  ///     Ok(())
101  ///   })?;
102  ///
103  ///   Ok(())
104  /// }
105  /// ```
106  fn next(&mut self) -> Option<(&[u8], Option<&[u8]>)>;
107
108  /// Moves the cursor to the previous item in the bucket and returns its key and value.
109  /// If the cursor is at the beginning of the bucket then None is returned.
110  ///
111  /// ```rust
112  /// use bbolt_rs::*;
113  ///
114  /// fn main() -> Result<()> {
115  ///   let mut db = Bolt::open_mem()?;
116  ///
117  ///   db.update(|mut tx| {
118  ///     let mut b = tx.create_bucket_if_not_exists("test")?;
119  ///     b.put("key1", "value1")?;
120  ///     b.put("key2", "value2")?;
121  ///     b.put("key3", "value3")?;
122  ///     Ok(())
123  ///   })?;
124  ///
125  ///   db.view(|tx| {
126  ///     let b = tx.bucket("test").unwrap();
127  ///     let mut c = b.cursor();
128  ///     c.last();
129  ///     let prev = c.prev();
130  ///     assert_eq!(Some((b"key2".as_slice(), Some(b"value2".as_slice()))), prev);
131  ///     Ok(())
132  ///   })?;
133  ///
134  ///   Ok(())
135  /// }
136  /// ```
137  fn prev(&mut self) -> Option<(&[u8], Option<&[u8]>)>;
138
139  /// Moves the cursor to a given key using a b-tree search and returns it.
140  ///
141  /// If the key does not exist then the next key is used. If no keys
142  /// follow, None is returned.
143  ///
144  /// ```rust
145  /// use bbolt_rs::*;
146  ///
147  /// fn main() -> Result<()> {
148  ///   let mut db = Bolt::open_mem()?;
149  ///
150  ///   db.update(|mut tx| {
151  ///     let mut b = tx.create_bucket_if_not_exists("test")?;
152  ///     b.put("key1", "value1")?;
153  ///     b.put("key2", "value2")?;
154  ///     b.put("key3", "value3")?;
155  ///     Ok(())
156  ///   })?;
157  ///
158  ///   db.view(|tx| {
159  ///     let b = tx.bucket("test").unwrap();
160  ///     let mut c = b.cursor();
161  ///     let seek = c.seek("key2");
162  ///     assert_eq!(Some((b"key2".as_slice(), Some(b"value2".as_slice()))), seek);
163  ///     Ok(())
164  ///   })?;
165  ///
166  ///   Ok(())
167  /// }
168  /// ```
169  fn seek<T: AsRef<[u8]>>(&mut self, seek: T) -> Option<(&[u8], Option<&[u8]>)>;
170}
171
172/// RW Bucket API
173pub trait CursorRwApi: CursorApi {
174  /// Removes the current key/value under the cursor from the bucket.
175  ///
176  /// ```rust
177  /// use bbolt_rs::*;
178  ///
179  /// fn main() -> Result<()> {
180  ///   let mut db = Bolt::open_mem()?;
181  ///
182  ///   db.update(|mut tx| {
183  ///     let mut b = tx.create_bucket_if_not_exists("test")?;
184  ///     b.put("key1", "value1")?;
185  ///     b.put("key2", "value2")?;
186  ///     b.put("key3", "value3")?;
187  ///     Ok(())
188  ///   })?;
189  ///
190  ///   db.update(|mut tx| {
191  ///     let mut b = tx.bucket_mut("test").unwrap();
192  ///     let mut c = b.cursor_mut();
193  ///     c.seek("key2");
194  ///     c.delete()?;
195  ///     Ok(())
196  ///   })?;
197  ///
198  ///   db.view(|tx| {
199  ///     let b = tx.bucket("test").unwrap();
200  ///     let mut c = b.cursor();
201  ///     let seek = c.seek("key2");
202  ///     assert_eq!(Some((b"key3".as_slice(), Some(b"value3".as_slice()))), seek);
203  ///     Ok(())
204  ///   })?;
205  ///
206  ///   Ok(())
207  /// }
208  /// ```
209  fn delete(&mut self) -> crate::Result<()>;
210}
211
212/// Read-only Cursor
213///
214pub struct CursorImpl<'tx: 'a, 'a> {
215  pub(crate) c: InnerCursor<'tx>,
216  p: PhantomData<&'a u8>,
217}
218
219impl<'tx: 'a, 'a> From<InnerCursor<'tx>> for CursorImpl<'tx, 'a> {
220  fn from(value: InnerCursor<'tx>) -> Self {
221    CursorImpl {
222      c: value,
223      p: PhantomData,
224    }
225  }
226}
227
228impl<'tx: 'a, 'a> CursorApi for CursorImpl<'tx, 'a> {
229  fn first(&mut self) -> Option<(&[u8], Option<&[u8]>)> {
230    self.c.api_first()
231  }
232
233  fn last(&mut self) -> Option<(&[u8], Option<&[u8]>)> {
234    self.c.api_last()
235  }
236
237  fn next(&mut self) -> Option<(&[u8], Option<&[u8]>)> {
238    self.c.api_next()
239  }
240
241  fn prev(&mut self) -> Option<(&[u8], Option<&[u8]>)> {
242    self.c.api_prev()
243  }
244
245  fn seek<T: AsRef<[u8]>>(&mut self, seek: T) -> Option<(&[u8], Option<&[u8]>)> {
246    self.c.api_seek(seek.as_ref())
247  }
248}
249
250/// Read/Write Cursor
251pub struct CursorRwImpl<'tx: 'a, 'a> {
252  c: InnerCursor<'tx>,
253  p: PhantomData<&'a u8>,
254}
255
256impl<'tx: 'a, 'a> CursorRwImpl<'tx, 'a> {
257  pub(crate) fn new(c: InnerCursor<'tx>) -> Self {
258    CursorRwImpl { c, p: PhantomData }
259  }
260}
261
262impl<'tx: 'a, 'a> From<InnerCursor<'tx>> for CursorRwImpl<'tx, 'a> {
263  fn from(value: InnerCursor<'tx>) -> Self {
264    CursorRwImpl::new(value)
265  }
266}
267
268impl<'tx: 'a, 'a> CursorApi for CursorRwImpl<'tx, 'a> {
269  fn first(&mut self) -> Option<(&[u8], Option<&[u8]>)> {
270    self.c.api_first()
271  }
272
273  fn last(&mut self) -> Option<(&[u8], Option<&[u8]>)> {
274    self.c.api_last()
275  }
276
277  fn next(&mut self) -> Option<(&[u8], Option<&[u8]>)> {
278    self.c.api_next()
279  }
280
281  fn prev(&mut self) -> Option<(&[u8], Option<&[u8]>)> {
282    self.c.api_prev()
283  }
284
285  fn seek<T: AsRef<[u8]>>(&mut self, seek: T) -> Option<(&[u8], Option<&[u8]>)> {
286    self.c.api_seek(seek.as_ref())
287  }
288}
289
290impl<'tx: 'a, 'a> CursorRwApi for CursorRwImpl<'tx, 'a> {
291  fn delete(&mut self) -> crate::Result<()> {
292    self.c.api_delete()
293  }
294}
295
296pub(crate) trait CursorIApi<'tx>: Clone {
297  /// See [CursorApi::first]
298  fn api_first(&mut self) -> Option<(&'tx [u8], Option<&'tx [u8]>)>;
299
300  fn i_first(&mut self) -> Option<(&'tx [u8], &'tx [u8], u32)>;
301
302  /// See [CursorApi::next]
303  fn api_next(&mut self) -> Option<(&'tx [u8], Option<&'tx [u8]>)>;
304
305  /// i_next moves to the next leaf element and returns the key and value.
306  /// If the cursor is at the last leaf element then it stays there and returns nil.
307  fn i_next(&mut self) -> Option<(&'tx [u8], &'tx [u8], u32)>;
308
309  /// See [CursorApi::prev]
310  fn api_prev(&mut self) -> Option<(&'tx [u8], Option<&'tx [u8]>)>;
311
312  /// i_prev moves the cursor to the previous item in the bucket and returns its key and value.
313  /// If the cursor is at the beginning of the bucket then a nil key and value are returned.
314  fn i_prev(&mut self) -> Option<(&'tx [u8], &'tx [u8], u32)>;
315
316  /// See [CursorApi::last]
317  fn api_last(&mut self) -> Option<(&'tx [u8], Option<&'tx [u8]>)>;
318
319  /// i_last moves the cursor to the last leaf element under the last page in the stack.
320  fn i_last(&mut self) -> Option<(&'tx [u8], &'tx [u8], u32)>;
321
322  /// key_value returns the key and value of the current leaf element.
323  fn key_value(&self) -> Option<(&'tx [u8], &'tx [u8], u32)>;
324
325  /// See [CursorApi::seek]
326  fn api_seek(&mut self, seek: &[u8]) -> Option<(&'tx [u8], Option<&'tx [u8]>)>;
327
328  /// i_seek moves the cursor to a given key and returns it.
329  /// If the key does not exist then the next key is used.
330  fn i_seek(&mut self, seek: &[u8]) -> Option<(&'tx [u8], &'tx [u8], u32)>;
331
332  /// first moves the cursor to the first leaf element under the last page in the stack.
333  fn go_to_first_element_on_the_stack(&mut self);
334
335  /// search recursively performs a binary search against a given page/node until it finds a given key.
336  fn search(&mut self, key: &[u8], pgid: PgId);
337
338  fn search_inodes(&mut self, key: &[u8]);
339
340  fn search_node(&mut self, key: &[u8], node: NodeRwCell<'tx>);
341
342  fn search_page(&mut self, key: &[u8], page: &RefPage);
343}
344
345pub(crate) trait CursorRwIApi<'tx>: CursorIApi<'tx> {
346  /// node returns the node that the cursor is currently positioned on.
347  fn node(&mut self) -> NodeRwCell<'tx>;
348
349  /// See [CursorRwApi::delete]
350  fn api_delete(&mut self) -> crate::Result<()>;
351}
352
353#[derive(Copy, Clone, Eq, PartialEq)]
354pub enum PageNode<'tx> {
355  Page(RefPage<'tx>),
356  Node(NodeRwCell<'tx>),
357}
358
359#[derive(Clone, Eq, PartialEq)]
360pub struct ElemRef<'tx> {
361  pn: PageNode<'tx>,
362  index: i32,
363}
364
365impl<'tx> ElemRef<'tx> {
366  /// count returns the number of inodes or page elements.
367  fn count(&self) -> u32 {
368    match &self.pn {
369      PageNode::Page(r) => r.count as u32,
370      PageNode::Node(n) => n.cell.borrow().inodes.len() as u32,
371    }
372  }
373
374  /// is_leaf returns whether the ref is pointing at a leaf page/node.
375  fn is_leaf(&self) -> bool {
376    match &self.pn {
377      PageNode::Page(r) => r.is_leaf(),
378      PageNode::Node(n) => n.cell.borrow().is_leaf,
379    }
380  }
381}
382
383#[derive(Clone, Eq, PartialEq)]
384pub(crate) struct InnerCursor<'tx> {
385  pub(crate) bucket: BucketCell<'tx>,
386  stack: BVec<'tx, ElemRef<'tx>>,
387}
388
389impl<'tx> InnerCursor<'tx> {
390  pub(crate) fn new(cell: BucketCell<'tx>, bump: &'tx Bump) -> Self {
391    cell
392      .tx()
393      .split_r()
394      .stats
395      .as_ref()
396      .unwrap()
397      .inc_cursor_count(1);
398    InnerCursor {
399      bucket: cell,
400      stack: BVec::with_capacity_in(0, bump),
401    }
402  }
403}
404
405impl<'tx> CursorIApi<'tx> for InnerCursor<'tx> {
406  fn api_first(&mut self) -> Option<(&'tx [u8], Option<&'tx [u8]>)> {
407    let (k, v, flags) = self.i_first()?;
408    if (flags & BUCKET_LEAF_FLAG) != 0 {
409      return Some((k, None));
410    }
411    Some((k, Some(v)))
412  }
413
414  fn i_first(&mut self) -> Option<(&'tx [u8], &'tx [u8], u32)> {
415    self.stack.clear();
416
417    // TODO: Optimize this a bit for the internal API. BucketImpl::root_page_node?
418    let root = self.bucket.root();
419    let pn = self.bucket.page_node(root);
420    self.stack.push(ElemRef { pn, index: 0 });
421
422    self.go_to_first_element_on_the_stack();
423
424    // If we land on an empty page then move to the next value.
425    // https://github.com/boltdb/bolt/issues/450
426    if self.stack.last().unwrap().count() == 0 {
427      self.i_next();
428    }
429
430    self.key_value()
431  }
432
433  fn api_next(&mut self) -> Option<(&'tx [u8], Option<&'tx [u8]>)> {
434    let (k, v, flags) = self.i_next()?;
435    if flags & BUCKET_LEAF_FLAG != 0 {
436      Some((k, None))
437    } else {
438      Some((k, Some(v)))
439    }
440  }
441
442  /// next moves to the next leaf element and returns the key and value.
443  /// If the cursor is at the last leaf element then it stays there and returns nil.
444  fn i_next(&mut self) -> Option<(&'tx [u8], &'tx [u8], u32)> {
445    loop {
446      // Attempt to move over one element until we're successful.
447      // Move up the stack as we hit the end of each page in our stack.
448      let mut stack_exhausted = true;
449      let mut new_stack_depth = 0;
450      for (depth, elem) in self.stack.iter_mut().enumerate().rev() {
451        new_stack_depth = depth + 1;
452        if elem.index < elem.count() as i32 - 1 {
453          elem.index += 1;
454          stack_exhausted = false;
455          break;
456        }
457      }
458
459      // If we've hit the root page then stop and return. This will leave the
460      // cursor on the last element of the last page.
461      if stack_exhausted {
462        return None;
463      }
464
465      // Otherwise start from where we left off in the stack and find the
466      // first element of the first leaf page.
467      self.stack.truncate(new_stack_depth);
468      self.go_to_first_element_on_the_stack();
469
470      // If this is an empty page then restart and move back up the stack.
471      // https://github.com/boltdb/bolt/issues/450
472      if let Some(elem) = self.stack.last() {
473        if elem.count() == 0 {
474          continue;
475        }
476      }
477
478      return self.key_value();
479    }
480  }
481
482  fn api_prev(&mut self) -> Option<(&'tx [u8], Option<&'tx [u8]>)> {
483    let (k, v, flags) = self.i_prev()?;
484    if flags & BUCKET_LEAF_FLAG != 0 {
485      Some((k, None))
486    } else {
487      Some((k, Some(v)))
488    }
489  }
490
491  /// prev moves the cursor to the previous item in the bucket and returns its key and value.
492  /// If the cursor is at the beginning of the bucket then a nil key and value are returned.
493  fn i_prev(&mut self) -> Option<(&'tx [u8], &'tx [u8], u32)> {
494    // Attempt to move back one element until we're successful.
495    // Move up the stack as we hit the beginning of each page in our stack.
496    let mut new_stack_depth = 0;
497    let mut stack_exhausted = true;
498    for (depth, elem) in self.stack.iter_mut().enumerate().rev() {
499      new_stack_depth = depth + 1;
500      if elem.index > 0 {
501        elem.index -= 1;
502        stack_exhausted = false;
503        break;
504      }
505      // If we've hit the beginning, we should stop moving the cursor,
506      // and stay at the first element, so that users can continue to
507      // iterate over the elements in reverse direction by calling `Next`.
508      // We should return nil in such case.
509      // Refer to https://github.com/etcd-io/bbolt/issues/733
510      if new_stack_depth == 1 {
511        self.i_first();
512        return None;
513      }
514    }
515    if stack_exhausted {
516      self.stack.truncate(0);
517    } else {
518      self.stack.truncate(new_stack_depth);
519    }
520
521    // If we've hit the end then return None
522    if self.stack.is_empty() {
523      return None;
524    }
525
526    // Move down the stack to find the last element of the last leaf under this branch.
527    self.i_last();
528
529    self.key_value()
530  }
531
532  fn api_last(&mut self) -> Option<(&'tx [u8], Option<&'tx [u8]>)> {
533    self.stack.truncate(0);
534    let root = self.bucket.root();
535    let pn = self.bucket.page_node(root);
536    let mut elem_ref = ElemRef { pn, index: 0 };
537    elem_ref.index = elem_ref.count() as i32 - 1;
538    self.stack.push(elem_ref);
539    self.i_last();
540
541    while self.stack.len() > 1 && self.stack.last().unwrap().count() == 0 {
542      self.i_prev();
543    }
544
545    if self.stack.is_empty() {
546      return None;
547    }
548
549    let (k, v, flags) = self.key_value()?;
550
551    if flags & BUCKET_LEAF_FLAG != 0 {
552      Some((k, None))
553    } else {
554      Some((k, Some(v)))
555    }
556  }
557
558  /// last moves the cursor to the last leaf element under the last page in the stack.
559
560  fn i_last(&mut self) -> Option<(&'tx [u8], &'tx [u8], u32)> {
561    loop {
562      // Exit when we hit a leaf page.
563      if let Some(elem) = self.stack.last() {
564        if elem.is_leaf() {
565          break;
566        }
567
568        // Keep adding pages pointing to the last element in the stack.
569        let pgid = match &elem.pn {
570          PageNode::Page(page) => {
571            let branch_page = MappedBranchPage::coerce_ref(page).unwrap();
572            branch_page.get_elem(elem.index as u16).unwrap().pgid()
573          }
574          PageNode::Node(node) => node.cell.borrow().inodes[elem.index as usize].pgid(),
575        };
576
577        let pn = self.bucket.page_node(pgid);
578        let mut next_elem = ElemRef { pn, index: 0 };
579        next_elem.index = next_elem.count() as i32 - 1;
580        self.stack.push(next_elem);
581      }
582    }
583    self.key_value()
584  }
585
586  fn key_value(&self) -> Option<(&'tx [u8], &'tx [u8], u32)> {
587    let elem_ref = self.stack.last().unwrap();
588    let pn_count = elem_ref.count();
589
590    // If the cursor is pointing to the end of page/node then return nil.
591    if pn_count == 0 || elem_ref.index as u32 > pn_count {
592      return None;
593    }
594
595    match &elem_ref.pn {
596      // Retrieve value from page.
597      PageNode::Page(r) => {
598        let l = MappedLeafPage::coerce_ref(r).unwrap();
599        l.get_elem(elem_ref.index as u16)
600          .map(|inode| (inode.key(), inode.value(), inode.flags()))
601      }
602      // Retrieve value from node.
603      PageNode::Node(n) => {
604        let ref_node = n.cell.borrow();
605        ref_node
606          .inodes
607          .get(elem_ref.index as usize)
608          .map(|inode| (inode.key(), inode.value(), inode.flags()))
609      }
610    }
611  }
612
613  fn api_seek(&mut self, seek: &[u8]) -> Option<(&'tx [u8], Option<&'tx [u8]>)> {
614    let mut vals = self.i_seek(seek);
615
616    if let Some(elem_ref) = self.stack.last() {
617      if elem_ref.index >= elem_ref.count() as i32 {
618        vals = self.i_next();
619      }
620    }
621
622    let (k, v, flags) = vals?;
623    if flags & BUCKET_LEAF_FLAG != 0 {
624      Some((k, None))
625    } else {
626      Some((k, Some(v)))
627    }
628  }
629
630  fn i_seek(&mut self, seek: &[u8]) -> Option<(&'tx [u8], &'tx [u8], u32)> {
631    self.stack.truncate(0);
632    let root = self.bucket.root();
633    self.search(seek, root);
634
635    self.key_value()
636  }
637
638  /// first moves the cursor to the first leaf element under the last page in the stack.
639  fn go_to_first_element_on_the_stack(&mut self) {
640    loop {
641      let _slice = self.stack.as_slice();
642      let pgid = {
643        // Exit when we hit a leaf page.
644        let r = self.stack.last().unwrap();
645        if r.is_leaf() {
646          break;
647        }
648
649        // Keep adding pages pointing to the first element to the stack.
650        match r.pn {
651          PageNode::Page(page) => {
652            let branch_page = MappedBranchPage::coerce_ref(&page).unwrap();
653            let elem = branch_page.get_elem(r.index as u16).unwrap();
654            elem.pgid()
655          }
656          PageNode::Node(node) => {
657            let node_borrow = node.cell.borrow();
658            node_borrow.inodes[r.index as usize].pgid()
659          }
660        }
661      };
662      let pn = self.bucket.page_node(pgid);
663      self.stack.push(ElemRef { pn, index: 0 })
664    }
665  }
666
667  /// search recursively performs a binary search against a given page/node until it finds a given key.
668  fn search(&mut self, key: &[u8], pgid: PgId) {
669    let pn = self.bucket.page_node(pgid);
670
671    if let PageNode::Page(page) = &pn {
672      if !page.is_leaf() && !page.is_branch() {
673        panic!("invalid page type: {}, {:X}", page.id, page.flags);
674      }
675    }
676
677    let elem = ElemRef { pn, index: 0 };
678
679    // If we're on a leaf page/node then find the specific node.
680    let elem_is_leaf = elem.is_leaf();
681
682    self.stack.push(elem);
683
684    if elem_is_leaf {
685      self.search_inodes(key);
686      return;
687    }
688
689    match &pn {
690      PageNode::Page(page) => self.search_page(key, page),
691      PageNode::Node(node) => self.search_node(key, *node),
692    }
693  }
694
695  /// search_inodes searches the leaf node on the top of the stack for a key.
696  fn search_inodes(&mut self, key: &[u8]) {
697    if let Some(elem) = self.stack.last_mut() {
698      let index = match &elem.pn {
699        // If we have a page then search its leaf elements.
700        PageNode::Page(page) => {
701          let leaf_page = MappedLeafPage::coerce_ref(page).unwrap();
702          leaf_page
703            .elements()
704            .partition_point(|elem| unsafe { elem.key(leaf_page.page_ptr().cast_const()) } < key)
705        }
706        // If we have a node then search its inodes.
707        PageNode::Node(node) => node
708          .cell
709          .borrow()
710          .inodes
711          .partition_point(|inode| inode.key() < key),
712      };
713      elem.index = index as i32;
714    }
715  }
716
717  fn search_node(&mut self, key: &[u8], node: NodeRwCell<'tx>) {
718    let (index, pgid) = {
719      let w = node.cell.borrow();
720
721      let r = w.inodes.binary_search_by_key(&key, |inode| inode.key());
722      let index = r.unwrap_or_else(|index| if index > 0 { index - 1 } else { index });
723      (index as u32, w.inodes[index].pgid())
724    };
725
726    if let Some(elem) = self.stack.last_mut() {
727      elem.index = index as i32;
728    }
729
730    // Recursively search to the next page.
731    self.search(key, pgid)
732  }
733
734  fn search_page(&mut self, key: &[u8], page: &RefPage) {
735    let branch_page = MappedBranchPage::coerce_ref(page).unwrap();
736    let elements = branch_page.elements();
737    debug_assert_ne!(0, elements.len());
738    let r = branch_page
739      .elements()
740      .binary_search_by_key(&key, |elem| unsafe {
741        elem.key(branch_page.page_ptr().cast_const())
742      });
743    let index = r.unwrap_or_else(|index| if index > 0 { index - 1 } else { index });
744
745    if let Some(elem) = self.stack.last_mut() {
746      elem.index = index as i32;
747    }
748    let pgid = branch_page.elements()[index].pgid();
749
750    // Recursively search to the next page.
751    self.search(key, pgid)
752  }
753}
754
755impl<'tx> CursorRwIApi<'tx> for InnerCursor<'tx> {
756  fn node(&mut self) -> NodeRwCell<'tx> {
757    assert!(
758      !self.stack.is_empty(),
759      "accessing a node with a zero-length cursor stack"
760    );
761
762    // If the top of the stack is a leaf node then just return it.
763    if let Some(elem_ref) = self.stack.last() {
764      if let PageNode::Node(node) = elem_ref.pn {
765        if node.cell.borrow().is_leaf {
766          return node;
767        }
768      }
769    }
770
771    // Start from root and traverse down the hierarchy.
772    let mut n = {
773      match &self.stack.first().unwrap().pn {
774        PageNode::Page(page) => self.bucket.node(page.id, None),
775        PageNode::Node(node) => *node,
776      }
777    };
778    let _stack = &self.stack[0..self.stack.len() - 1];
779    for elem in &self.stack[0..self.stack.len() - 1] {
780      assert!(!n.cell.borrow().is_leaf, "expected branch node");
781      n = n.child_at(elem.index as u32);
782    }
783    assert!(n.cell.borrow().is_leaf, "expected leaf node");
784    n
785  }
786
787  fn api_delete(&mut self) -> crate::Result<()> {
788    let (k, _, flags) = self.key_value().unwrap();
789    if flags & BUCKET_LEAF_FLAG != 0 {
790      return Err(IncompatibleValue);
791    }
792    self.node().del(k);
793    Ok(())
794  }
795}
796
797#[cfg(test)]
798mod tests {
799  use crate::test_support::{quick_check, DummyVec, TestDb};
800  use crate::{
801    BucketApi, BucketImpl, BucketRwApi, BucketRwImpl, CursorApi, CursorRwApi, DbApi, DbRwAPI,
802    Error, TxApi, TxRwApi, TxRwRefApi,
803  };
804
805  #[test]
806  fn test_cursor_repeat_operations() -> crate::Result<()> {
807    let tests: Vec<(&'static str, fn(&BucketImpl) -> crate::Result<()>)> = vec![
808      (
809        "Repeat NextPrevNext",
810        test_repeat_cursor_operations_next_prev_next,
811      ),
812      (
813        "Repeat PrevNextPrev",
814        test_repeat_cursor_operations_prev_next_prev,
815      ),
816    ];
817    for (_name, f) in tests {
818      let mut db = TestDb::new()?;
819      let bucket_name = "data";
820      db.update(|mut tx| {
821        let mut b = tx.create_bucket_if_not_exists(bucket_name)?;
822        test_cursor_repeat_operations_prepare_data(&mut b)
823      })?;
824
825      db.view(|tx| {
826        let b = tx.bucket(bucket_name).unwrap();
827        f(&b)
828      })?;
829    }
830    Ok(())
831  }
832
833  fn test_cursor_repeat_operations_prepare_data(b: &mut BucketRwImpl) -> crate::Result<()> {
834    for i in 0..1000 {
835      let k = format!("{:05}", i);
836      b.put(&k, &k)?;
837    }
838    Ok(())
839  }
840
841  fn test_repeat_cursor_operations_next_prev_next(b: &BucketImpl) -> crate::Result<()> {
842    let mut c = b.cursor();
843    c.first();
844    let start_key = format!("{:05}", 2);
845    let (returned_key, _) = c.seek(&start_key).unwrap();
846    assert_eq!(start_key.as_bytes(), returned_key);
847
848    // Step 1: verify next
849    for i in 3..1000 {
850      let expected_key = format!("{:05}", i);
851      let (actual_key, _) = c.next().unwrap();
852      assert_eq!(expected_key.as_bytes(), actual_key);
853    }
854
855    // Once we've reached the end, it should always return nil no matter how many times we call `Next`.
856    for _ in 0..10 {
857      assert_eq!(None, c.next());
858    }
859
860    // Step 2: verify prev
861    for i in (0..999).rev() {
862      let expected_key = format!("{:05}", i);
863      let (actual_key, _) = c.prev().unwrap();
864      assert_eq!(expected_key.as_bytes(), actual_key);
865    }
866
867    // Once we've reached the beginning, it should always return nil no matter how many times we call `Prev`.
868    for _ in 0..10 {
869      assert_eq!(None, c.prev());
870    }
871
872    // Step 3: verify next again
873    for i in 1..1000 {
874      let expected_key = format!("{:05}", i);
875      let (actual_key, _) = c.next().unwrap();
876      assert_eq!(expected_key.as_bytes(), actual_key);
877    }
878
879    Ok(())
880  }
881
882  fn test_repeat_cursor_operations_prev_next_prev(b: &BucketImpl) -> crate::Result<()> {
883    let mut c = b.cursor();
884    let start_key = format!("{:05}", 998);
885    let (returned_key, _) = c.seek(&start_key).unwrap();
886    assert_eq!(start_key.as_bytes(), returned_key);
887
888    // Step 1: verify prev
889    for i in (0..998).rev() {
890      let expected_key = format!("{:05}", i);
891      let (actual_key, _) = c.prev().unwrap();
892      assert_eq!(expected_key.as_bytes(), actual_key);
893    }
894
895    // Once we've reached the beginning, it should always return nil no matter how many times we call `Prev`.
896    for _ in 0..10 {
897      assert_eq!(None, c.prev());
898    }
899
900    // Step 2: verify next
901    for i in 1..1000 {
902      let expected_key = format!("{:05}", i);
903      let (actual_key, _) = c.next().unwrap();
904      assert_eq!(expected_key.as_bytes(), actual_key);
905    }
906
907    // Once we've reached the end, it should always return nil no matter how many times we call `Next`.
908    for _ in 0..10 {
909      assert_eq!(None, c.next());
910    }
911
912    // Step 1: verify prev again
913    for i in (0..999).rev() {
914      let expected_key = format!("{:05}", i);
915      let (actual_key, _) = c.prev().unwrap();
916      assert_eq!(expected_key.as_bytes(), actual_key);
917    }
918
919    Ok(())
920  }
921
922  /// Ensure that a Tx cursor can seek to the appropriate keys.
923  #[test]
924  fn test_cursor_seek() -> crate::Result<()> {
925    let mut db = TestDb::new()?;
926    db.update(|mut tx| {
927      let mut b = tx.create_bucket(b"widgets")?;
928      b.put(b"foo", b"0001")?;
929      b.put(b"bar", b"0002")?;
930      b.put(b"baz", b"0003")?;
931      let _ = b.create_bucket(b"bkt")?;
932      Ok(())
933    })?;
934    db.view(|tx| {
935      let b = tx.bucket(b"widgets").unwrap();
936      let mut c = b.cursor();
937      // Exact match should go to the key.
938      assert_eq!(
939        (b"bar".as_slice(), Some(b"0002".as_slice())),
940        c.seek(b"bar").unwrap()
941      );
942      // Inexact match should go to the next key.
943      assert_eq!(
944        (b"baz".as_slice(), Some(b"0003".as_slice())),
945        c.seek(b"bas").unwrap()
946      );
947      // Low key should go to the first key.
948      assert_eq!(
949        (b"bar".as_slice(), Some(b"0002".as_slice())),
950        c.seek(b"").unwrap()
951      );
952      // High key should return no key.
953      assert_eq!(None, c.seek(b"zzz"));
954      // Buckets should return their key but no value.
955      assert_eq!((b"bkt".as_slice(), None), c.seek(b"bkt").unwrap());
956      Ok(())
957    })
958  }
959
960  #[test]
961  #[cfg(not(miri))]
962  fn test_cursor_delete() -> crate::Result<()> {
963    let mut db = TestDb::new()?;
964    let count = 1000u64;
965    let value = [0u8; 100];
966    db.update(|mut tx| {
967      let mut b = tx.create_bucket(b"widgets")?;
968      for i in 0..count {
969        let be_i = i.to_be_bytes();
970        b.put(be_i, value)?;
971      }
972      let _ = b.create_bucket(b"sub")?;
973      Ok(())
974    })?;
975    db.must_check();
976    db.update(|mut tx| {
977      let b = tx.bucket_mut(b"widgets").unwrap();
978      let mut c = b.cursor_mut();
979      let bound = (count / 2).to_be_bytes();
980      let (mut key, _) = c.first().unwrap();
981      while key < bound.as_slice() {
982        c.delete()?;
983        key = c.next().unwrap().0;
984      }
985      c.seek(b"sub");
986      assert_eq!(Err(Error::IncompatibleValue), c.delete());
987      Ok(())
988    })?;
989    db.must_check();
990    db.view(|tx| {
991      let b = tx.bucket(b"widgets").unwrap();
992      let stats = b.stats();
993      assert_eq!((count / 2) + 1, stats.key_n as u64);
994      Ok(())
995    })?;
996    Ok(())
997  }
998
999  #[test]
1000  #[cfg(not(miri))]
1001  fn test_cursor_seek_large() -> crate::Result<()> {
1002    let mut db = TestDb::new()?;
1003    let count = 1000u64;
1004    let value = [0u8; 100];
1005    db.update(|mut tx| {
1006      let mut b = tx.create_bucket(b"widgets")?;
1007      for i in (0..count).step_by(100) {
1008        for j in (i..i + 100).step_by(2) {
1009          let k = j.to_be_bytes();
1010          b.put(k, value)?;
1011        }
1012      }
1013      Ok(())
1014    })?;
1015    db.view(|tx| {
1016      let b = tx.bucket(b"widgets").unwrap();
1017      let mut c = b.cursor();
1018      for i in 0..count {
1019        let seek = i.to_be_bytes();
1020        let sought = c.seek(seek);
1021
1022        if i == count - 1 {
1023          assert!(sought.is_none(), "expected None");
1024          continue;
1025        }
1026        let k = sought.unwrap().0;
1027        let num = u64::from_be_bytes(k.try_into().unwrap());
1028        if i % 2 == 0 {
1029          assert_eq!(num, i, "unexpected num: {}", num)
1030        } else {
1031          assert_eq!(num, i + 1, "unexpected num: {}", num)
1032        }
1033      }
1034      Ok(())
1035    })?;
1036    Ok(())
1037  }
1038
1039  #[test]
1040  fn test_cursor_empty_bucket() -> crate::Result<()> {
1041    let mut db = TestDb::new()?;
1042    db.update(|mut tx| {
1043      let _ = tx.create_bucket(b"widgets")?;
1044      Ok(())
1045    })?;
1046    db.view(|tx| {
1047      let b = tx.bucket(b"widgets").unwrap();
1048      let mut c = b.cursor();
1049      let kv = c.first();
1050      assert_eq!(None, kv, "unexpected kv: {:?}", kv);
1051      Ok(())
1052    })?;
1053    Ok(())
1054  }
1055
1056  #[test]
1057  fn test_cursor_empty_bucket_reverse() -> crate::Result<()> {
1058    let mut db = TestDb::new()?;
1059    db.update(|mut tx| {
1060      let _ = tx.create_bucket(b"widgets")?;
1061      Ok(())
1062    })?;
1063    db.view(|tx| {
1064      let b = tx.bucket(b"widgets").unwrap();
1065      let mut c = b.cursor();
1066      let kv = c.last();
1067      assert_eq!(None, kv, "unexpected kv: {:?}", kv);
1068      Ok(())
1069    })?;
1070    Ok(())
1071  }
1072
1073  #[test]
1074  fn test_cursor_iterate_leaf() -> crate::Result<()> {
1075    let mut db = TestDb::new()?;
1076    db.update(|mut tx| {
1077      let mut b = tx.create_bucket(b"widgets")?;
1078      b.put(b"baz", [])?;
1079      b.put(b"foo", [0])?;
1080      b.put(b"bar", [1])?;
1081      Ok(())
1082    })?;
1083    let tx = db.begin()?;
1084    {
1085      let b = tx.bucket(b"widgets").unwrap();
1086      let mut c = b.cursor();
1087      assert_eq!(Some((b"bar".as_slice(), Some([1].as_slice()))), c.first());
1088      assert_eq!(Some((b"baz".as_slice(), Some([].as_slice()))), c.next());
1089      assert_eq!(Some((b"foo".as_slice(), Some([0].as_slice()))), c.next());
1090      assert_eq!(None, c.next());
1091      assert_eq!(None, c.next());
1092    }
1093    Ok(())
1094  }
1095
1096  #[test]
1097  fn test_cursor_leaf_root_reverse() -> crate::Result<()> {
1098    let mut db = TestDb::new()?;
1099    db.update(|mut tx| {
1100      let mut b = tx.create_bucket(b"widgets")?;
1101      b.put(b"baz", [])?;
1102      b.put(b"foo", [0])?;
1103      b.put(b"bar", [1])?;
1104      Ok(())
1105    })?;
1106    let tx = db.begin()?;
1107    {
1108      let b = tx.bucket(b"widgets").unwrap();
1109      let mut c = b.cursor();
1110      assert_eq!(Some((b"foo".as_slice(), Some([0].as_slice()))), c.last());
1111      assert_eq!(Some((b"baz".as_slice(), Some([].as_slice()))), c.prev());
1112      assert_eq!(Some((b"bar".as_slice(), Some([1].as_slice()))), c.prev());
1113      assert_eq!(None, c.prev());
1114      assert_eq!(None, c.prev());
1115    }
1116    Ok(())
1117  }
1118
1119  #[test]
1120  fn test_cursor_restart() -> crate::Result<()> {
1121    let mut db = TestDb::new()?;
1122    db.update(|mut tx| {
1123      let mut b = tx.create_bucket(b"widgets")?;
1124      b.put("foo", [])?;
1125      b.put("bar", [])?;
1126      Ok(())
1127    })?;
1128    let tx = db.begin()?;
1129    {
1130      let b = tx.bucket(b"widgets").unwrap();
1131      let mut c = b.cursor();
1132      assert_eq!(Some((b"bar".as_slice(), Some([].as_slice()))), c.first());
1133      assert_eq!(Some((b"foo".as_slice(), Some([].as_slice()))), c.next());
1134      assert_eq!(Some((b"bar".as_slice(), Some([].as_slice()))), c.first());
1135      assert_eq!(Some((b"foo".as_slice(), Some([].as_slice()))), c.next());
1136    }
1137    Ok(())
1138  }
1139
1140  #[test]
1141  fn test_cursor_first_empty_pages() -> crate::Result<()> {
1142    let mut db = TestDb::new()?;
1143    db.update(|mut tx| {
1144      let mut b = tx.create_bucket(b"widgets")?;
1145      for i in 1..1000u64 {
1146        b.put(bytemuck::bytes_of(&i), [])?;
1147      }
1148      Ok(())
1149    })?;
1150    db.update(|mut tx| {
1151      let mut b = tx.bucket_mut(b"widgets").unwrap();
1152      for i in 1..600u64 {
1153        b.delete(bytemuck::bytes_of(&i))?;
1154      }
1155      let mut c = b.cursor();
1156      let mut kv = c.first();
1157      let mut n = 0;
1158      while kv.is_some() {
1159        n += 1;
1160        kv = c.next();
1161      }
1162      assert_eq!(400, n, "unexpected key count");
1163      Ok(())
1164    })
1165  }
1166
1167  #[test]
1168  fn test_cursor_last_empty_pages() -> crate::Result<()> {
1169    let mut db = TestDb::new()?;
1170    db.update(|mut tx| {
1171      let mut b = tx.create_bucket(b"widgets")?;
1172      for i in 0..1000u64 {
1173        b.put(bytemuck::bytes_of(&i), [])?;
1174      }
1175      Ok(())
1176    })?;
1177    db.update(|mut tx| {
1178      let mut b = tx.bucket_mut(b"widgets").unwrap();
1179      for i in 200..1000u64 {
1180        b.delete(bytemuck::bytes_of(&i))?;
1181      }
1182      let mut c = b.cursor();
1183      let mut kv = c.last();
1184      let mut n = 0;
1185      while kv.is_some() {
1186        n += 1;
1187        kv = c.prev();
1188      }
1189      assert_eq!(200, n, "unexpected key count");
1190      Ok(())
1191    })
1192  }
1193
1194  #[test]
1195  fn test_cursor_quick_check() {
1196    quick_check(5, |d: &mut DummyVec| {
1197      let mut db = TestDb::new().expect("error");
1198      let mut tx = db.begin_rw_tx().expect("error");
1199      let mut b = tx.create_bucket("widgets").expect("error");
1200
1201      for entry in &d.values {
1202        b.put(&entry.key, &entry.value).expect("error");
1203      }
1204
1205      tx.commit().expect("error");
1206
1207      d.values.sort_by(|d1, d2| d1.key.cmp(&d2.key));
1208
1209      let tx = db.begin_tx().expect("error");
1210
1211      let b = tx.bucket("widgets").unwrap();
1212      for (entry, (key, value)) in d.values.iter().zip(b.iter_entries()) {
1213        assert_eq!(&entry.key, key, "unexpected key");
1214        assert_eq!(&entry.value, value, "unexpected value");
1215      }
1216
1217      true
1218    });
1219  }
1220
1221  #[test]
1222  fn test_cursor_quick_check_reverse() {
1223    quick_check(5, |d: &mut DummyVec| {
1224      let mut db = TestDb::new().expect("error");
1225      let mut tx = db.begin_rw_tx().expect("error");
1226      let mut b = tx.create_bucket("widgets").expect("error");
1227
1228      for entry in &d.values {
1229        b.put(&entry.key, &entry.value).expect("error");
1230      }
1231
1232      tx.commit().expect("error");
1233
1234      d.values.sort_by(|d1, d2| d1.key.cmp(&d2.key).reverse());
1235
1236      let tx = db.begin_tx().expect("error");
1237
1238      let b = tx.bucket("widgets").unwrap();
1239      for (entry, (key, value)) in d.values.iter().zip(b.iter_entries().rev()) {
1240        assert_eq!(&entry.key, key, "unexpected key");
1241        assert_eq!(&entry.value, value, "unexpected value");
1242      }
1243
1244      true
1245    });
1246  }
1247
1248  #[test]
1249  fn test_cursor_quick_check_buckets_only() -> crate::Result<()> {
1250    let mut expected = vec![b"foo".to_vec(), b"bar".to_vec(), b"baz".to_vec()];
1251    let mut db = TestDb::new()?;
1252    db.update(|mut tx| {
1253      let mut b = tx.create_bucket("widgets")?;
1254      for bucket in &expected {
1255        b.create_bucket(bucket)?;
1256      }
1257      Ok(())
1258    })?;
1259    expected.sort();
1260    db.view(|tx| {
1261      let b = tx.bucket("widgets").unwrap();
1262      let actual: Vec<Vec<u8>> = b.iter_buckets().map(|(key, _)| key.to_vec()).collect();
1263      assert_eq!(expected.as_ref(), actual);
1264      Ok(())
1265    })?;
1266    Ok(())
1267  }
1268
1269  #[test]
1270  fn test_cursor_quick_check_buckets_only_reverse() -> crate::Result<()> {
1271    let mut expected = vec![b"foo".to_vec(), b"bar".to_vec(), b"baz".to_vec()];
1272    let mut db = TestDb::new()?;
1273    db.update(|mut tx| {
1274      let mut b = tx.create_bucket("widgets")?;
1275      for bucket in &expected {
1276        b.create_bucket(bucket)?;
1277      }
1278      Ok(())
1279    })?;
1280    expected.sort_by(|a, b| b.cmp(a));
1281    db.view(|tx| {
1282      let b = tx.bucket("widgets").unwrap();
1283      let actual: Vec<Vec<u8>> = b
1284        .iter_buckets()
1285        .rev()
1286        .map(|(key, _)| key.to_vec())
1287        .collect();
1288      assert_eq!(expected.as_ref(), actual);
1289      Ok(())
1290    })?;
1291    Ok(())
1292  }
1293}