Returns `Some(plan)` when the store should compact, else `None`.
(store: &ArrayStore)
| 31 | impl CompactionPicker { |
| 32 | /// Returns `Some(plan)` when the store should compact, else `None`. |
| 33 | pub fn pick(store: &ArrayStore) -> Option<CompactionPlan> { |
| 34 | let manifest = store.manifest(); |
| 35 | let l0: Vec<&SegmentRef> = manifest.segments_at_level(0).collect(); |
| 36 | if l0.len() < L0_TRIGGER { |
| 37 | return None; |
| 38 | } |
| 39 | let mut inputs: Vec<(u64, String)> = |
| 40 | l0.iter().map(|s| (s.flush_lsn, s.id.clone())).collect(); |
| 41 | // L1 absorption: if any existing L1 segment overlaps the L0 |
| 42 | // tile range, fold it into the merge so we don't leave shadowed |
| 43 | // versions behind. |
| 44 | let l0_min = l0.iter().map(|s| s.min_tile).min(); |
| 45 | let l0_max = l0.iter().map(|s| s.max_tile).max(); |
| 46 | if let (Some(min), Some(max)) = (l0_min, l0_max) { |
| 47 | for s in manifest.segments_at_level(1) { |
| 48 | if s.max_tile >= min && s.min_tile <= max { |
| 49 | inputs.push((s.flush_lsn, s.id.clone())); |
| 50 | } |
| 51 | } |
| 52 | } |
| 53 | // Stable order by flush_lsn so the merger applies older→newer. |
| 54 | inputs.sort_by_key(|(lsn, _)| *lsn); |
| 55 | Some(CompactionPlan { |
| 56 | inputs: inputs.into_iter().map(|(_, id)| id).collect(), |
| 57 | output_level: 1, |
| 58 | }) |
| 59 | } |
| 60 | } |
| 61 | |
| 62 | #[cfg(test)] |