Compact sealed segments by removing tombstoned nodes. Rewrites `surrogate_map` and `multi_doc_map` for every sealed segment so that global ids continue to resolve to the correct surrogate after local-id renumbering.
(&mut self)
| 13 | /// segment so that global ids continue to resolve to the correct |
| 14 | /// surrogate after local-id renumbering. |
| 15 | pub fn compact(&mut self) -> usize { |
| 16 | let mut total_removed = 0; |
| 17 | for seg in &mut self.sealed { |
| 18 | let base_id = seg.base_id; |
| 19 | let (removed, id_map) = seg.index.compact_with_map(); |
| 20 | total_removed += removed; |
| 21 | if removed == 0 { |
| 22 | continue; |
| 23 | } |
| 24 | |
| 25 | let segment_end = base_id as u64 + id_map.len() as u64; |
| 26 | let global_keys: Vec<u32> = self |
| 27 | .surrogate_map |
| 28 | .keys() |
| 29 | .copied() |
| 30 | .filter(|&k| (k as u64) >= base_id as u64 && (k as u64) < segment_end) |
| 31 | .collect(); |
| 32 | // Two-phase: remove old entries first, then insert new ones |
| 33 | // so we don't clobber a freshly-remapped entry with a later |
| 34 | // tombstone removal. |
| 35 | let mut new_entries: Vec<(u32, Surrogate)> = Vec::with_capacity(global_keys.len()); |
| 36 | for old_global in &global_keys { |
| 37 | let surrogate = self.surrogate_map.remove(old_global); |
| 38 | let old_local = (old_global - base_id) as usize; |
| 39 | let new_local = id_map[old_local]; |
| 40 | if new_local != u32::MAX |
| 41 | && let Some(s) = surrogate |
| 42 | { |
| 43 | new_entries.push((base_id + new_local, s)); |
| 44 | } else if let Some(s) = surrogate { |
| 45 | // Tombstoned — drop reverse mapping too. |
| 46 | self.surrogate_to_local.remove(&s); |
| 47 | } |
| 48 | } |
| 49 | for (k, s) in new_entries { |
| 50 | self.surrogate_map.insert(k, s); |
| 51 | self.surrogate_to_local.insert(s, k); |
| 52 | } |
| 53 | |
| 54 | // Rewrite multi_doc_map entries for this segment. |
| 55 | for ids in self.multi_doc_map.values_mut() { |
| 56 | ids.retain_mut(|vid| { |
| 57 | let v = *vid; |
| 58 | if (v as u64) >= base_id as u64 && (v as u64) < segment_end { |
| 59 | let old_local = (v - base_id) as usize; |
| 60 | let new_local = id_map[old_local]; |
| 61 | if new_local == u32::MAX { |
| 62 | false |
| 63 | } else { |
| 64 | *vid = base_id + new_local; |
| 65 | true |
| 66 | } |
| 67 | } else { |
| 68 | true |
| 69 | } |
| 70 | }); |
| 71 | } |
| 72 | } |
no test coverage detected