value_log/
scanner.rs

1// Copyright (c) 2024-present, fjall-rs
2// This source code is licensed under both the Apache 2.0 and MIT License
3// (found in the LICENSE-* files in the repository)
4
5use crate::{id::SegmentId, ValueHandle};
6use std::{collections::BTreeMap, sync::MutexGuard};
7
8#[derive(Debug, Default)]
9pub struct SegmentCounter {
10    pub size: u64,
11    pub item_count: u64,
12}
13
14pub type SizeMap = BTreeMap<SegmentId, SegmentCounter>;
15
16/// Scans a value log, building a size map for the GC report
17pub struct Scanner<'a, I: Iterator<Item = std::io::Result<(ValueHandle, u32)>>> {
18    iter: I,
19
20    #[allow(unused)]
21    lock_guard: MutexGuard<'a, ()>,
22
23    size_map: SizeMap,
24}
25
26impl<'a, I: Iterator<Item = std::io::Result<(ValueHandle, u32)>>> Scanner<'a, I> {
27    pub fn new(iter: I, lock_guard: MutexGuard<'a, ()>, ids: &[SegmentId]) -> Self {
28        let mut size_map = BTreeMap::default();
29
30        for &id in ids {
31            size_map.insert(id, SegmentCounter::default());
32        }
33
34        Self {
35            iter,
36            lock_guard,
37            size_map,
38        }
39    }
40
41    pub fn finish(self) -> SizeMap {
42        self.size_map
43    }
44
45    pub fn scan(&mut self) -> crate::Result<()> {
46        for vhandle in self.iter.by_ref() {
47            let (vhandle, size) = vhandle.map_err(|_| {
48                crate::Error::Io(std::io::Error::new(
49                    std::io::ErrorKind::Other,
50                    "Index returned error",
51                ))
52            })?;
53            let size = u64::from(size);
54
55            self.size_map
56                .entry(vhandle.segment_id)
57                .and_modify(|x| {
58                    x.item_count += 1;
59                    x.size += size;
60                })
61                .or_insert_with(|| SegmentCounter {
62                    size,
63                    item_count: 1,
64                });
65        }
66
67        Ok(())
68    }
69}