reddb_engine/storage/btree/
reclaim.rs1use super::*;
2
3impl<P: PageStore> BTree<P> {
4 pub fn has_retirement_readers(&self) -> bool {
5 Arc::strong_count(&self.retirement_pin) != 1
6 }
7
8 pub fn retired_pages(&self) -> BTreeResult<Vec<u32>> {
12 let mut pending = vec![self.root_page_id()];
13 let mut seen = std::collections::HashSet::new();
14 let mut pages = Vec::new();
15 let page_count = self.pager.page_count()?;
16 while let Some(id) = pending.pop() {
17 if id == 0 {
18 continue;
19 }
20 if id >= page_count || !seen.insert(id) {
21 return Err(BTreeError::Corrupted(
22 "invalid retired tree page ownership".into(),
23 ));
24 }
25 let page = self.pager.read_page(id)?;
26 match page.page_type()? {
27 PageType::BTreeInterior => {
28 let (_, children) = read_interior_keys_children(&page)?;
29 pending.extend(children);
30 }
31 PageType::BTreeLeaf => {
32 for index in 0..usize::from(page.cell_count()) {
33 let (_, stored) = read_leaf_cell(&page, index)?;
34 if let Some(head) = value_layout::pointer_head(&stored) {
35 pending.push(head);
36 }
37 }
38 }
39 PageType::Overflow => {
40 let content = page.content();
41 let next = u32::from_le_bytes(content[..4].try_into().expect("chain header"));
42 let len = u32::from_le_bytes(content[4..8].try_into().expect("chain length"));
43 if len as usize > crate::storage::overflow::OVERFLOW_PAYLOAD_PER_PAGE {
44 return Err(BTreeError::Corrupted(
45 "invalid retired overflow length".into(),
46 ));
47 }
48 pending.push(next);
49 }
50 _ => {
51 return Err(BTreeError::Corrupted(
52 "unexpected retired tree page type".into(),
53 ))
54 }
55 }
56 pages.push(id);
57 }
58 Ok(pages)
59 }
60}