nodedb_columnar/
delete_bitmap.rs1use roaring::RoaringBitmap;
13
14use crate::error::ColumnarError;
15
16#[derive(Debug, Clone)]
21pub struct DeleteBitmap {
22 inner: RoaringBitmap,
23}
24
25impl DeleteBitmap {
26 pub fn new() -> Self {
28 Self {
29 inner: RoaringBitmap::new(),
30 }
31 }
32
33 pub fn mark_deleted(&mut self, row_idx: u32) -> bool {
35 self.inner.insert(row_idx)
36 }
37
38 pub fn mark_deleted_batch(&mut self, row_indices: &[u32]) {
40 for &idx in row_indices {
41 self.inner.insert(idx);
42 }
43 }
44
45 pub fn is_deleted(&self, row_idx: u32) -> bool {
47 self.inner.contains(row_idx)
48 }
49
50 pub fn deleted_count(&self) -> u64 {
52 self.inner.len()
53 }
54
55 pub fn is_empty(&self) -> bool {
57 self.inner.is_empty()
58 }
59
60 pub fn delete_ratio(&self, total_rows: u64) -> f64 {
62 if total_rows == 0 {
63 return 0.0;
64 }
65 self.inner.len() as f64 / total_rows as f64
66 }
67
68 pub fn should_compact(&self, total_rows: u64, threshold: f64) -> bool {
70 self.delete_ratio(total_rows) > threshold
71 }
72
73 pub fn is_block_fully_deleted(&self, block_start: u32, block_len: u32) -> bool {
78 if block_len == 0 {
79 return true;
80 }
81 let count = self
83 .inner
84 .range(block_start..block_start + block_len)
85 .count() as u32;
86 count == block_len
87 }
88
89 pub fn apply_to_validity(&self, valid: &mut [bool], global_offset: u32) {
94 for (i, v) in valid.iter_mut().enumerate() {
95 if self.inner.contains(global_offset + i as u32) {
96 *v = false;
97 }
98 }
99 }
100
101 pub fn to_bytes(&self) -> Result<Vec<u8>, ColumnarError> {
103 let mut buf = Vec::with_capacity(self.inner.serialized_size());
105 self.inner
106 .serialize_into(&mut buf)
107 .map_err(|e| ColumnarError::Serialization(format!("delete bitmap: {e}")))?;
108 Ok(buf)
109 }
110
111 pub fn from_bytes(data: &[u8]) -> Result<Self, ColumnarError> {
113 let inner = RoaringBitmap::deserialize_from(data)
114 .map_err(|e| ColumnarError::Serialization(format!("delete bitmap: {e}")))?;
115 Ok(Self { inner })
116 }
117
118 pub fn iter(&self) -> impl Iterator<Item = u32> + '_ {
120 self.inner.iter()
121 }
122
123 pub fn unmark_deleted(&mut self, row_idx: u32) -> bool {
129 self.inner.remove(row_idx)
130 }
131
132 pub fn merge(&mut self, other: &DeleteBitmap) {
135 self.inner |= &other.inner;
136 }
137}
138
139impl Default for DeleteBitmap {
140 fn default() -> Self {
141 Self::new()
142 }
143}
144
145#[cfg(test)]
146mod tests {
147 use super::*;
148
149 #[test]
150 fn mark_and_check() {
151 let mut bm = DeleteBitmap::new();
152 assert!(!bm.is_deleted(5));
153 assert!(bm.mark_deleted(5));
154 assert!(bm.is_deleted(5));
155 assert!(!bm.mark_deleted(5)); assert_eq!(bm.deleted_count(), 1);
157 }
158
159 #[test]
160 fn batch_delete() {
161 let mut bm = DeleteBitmap::new();
162 bm.mark_deleted_batch(&[1, 3, 5, 7, 9]);
163 assert_eq!(bm.deleted_count(), 5);
164 assert!(bm.is_deleted(3));
165 assert!(!bm.is_deleted(4));
166 }
167
168 #[test]
169 fn serialization_roundtrip() {
170 let mut bm = DeleteBitmap::new();
171 bm.mark_deleted_batch(&[0, 10, 100, 1000, 10000]);
172
173 let bytes = bm.to_bytes().unwrap();
174 let restored = DeleteBitmap::from_bytes(&bytes).expect("deserialize");
175
176 assert_eq!(restored.deleted_count(), 5);
177 assert!(restored.is_deleted(0));
178 assert!(restored.is_deleted(10));
179 assert!(restored.is_deleted(10000));
180 assert!(!restored.is_deleted(50));
181 }
182
183 #[test]
184 fn delete_ratio_and_compaction() {
185 let mut bm = DeleteBitmap::new();
186 for i in 0..30 {
187 bm.mark_deleted(i);
188 }
189 assert!((bm.delete_ratio(100) - 0.3).abs() < 0.001);
191 assert!(bm.should_compact(100, 0.2));
193 assert!(!bm.should_compact(100, 0.5));
195 }
196
197 #[test]
198 fn block_fully_deleted() {
199 let mut bm = DeleteBitmap::new();
200 for i in 10..20 {
202 bm.mark_deleted(i);
203 }
204 assert!(bm.is_block_fully_deleted(10, 10));
205 assert!(!bm.is_block_fully_deleted(10, 11)); assert!(!bm.is_block_fully_deleted(5, 10)); }
208
209 #[test]
210 fn apply_to_validity() {
211 let mut bm = DeleteBitmap::new();
212 bm.mark_deleted_batch(&[2, 4]);
213
214 let mut valid = vec![true, true, true, true, true];
215 bm.apply_to_validity(&mut valid, 0);
216
217 assert!(valid[0]);
218 assert!(valid[1]);
219 assert!(!valid[2]); assert!(valid[3]);
221 assert!(!valid[4]); }
223
224 #[test]
225 fn apply_to_validity_with_offset() {
226 let mut bm = DeleteBitmap::new();
227 bm.mark_deleted(1025); let mut valid = vec![true; 1024];
230 bm.apply_to_validity(&mut valid, 1024); assert!(valid[0]); assert!(!valid[1]); assert!(valid[2]); }
236
237 #[test]
238 fn merge_bitmaps() {
239 let mut bm1 = DeleteBitmap::new();
240 bm1.mark_deleted_batch(&[1, 2, 3]);
241
242 let mut bm2 = DeleteBitmap::new();
243 bm2.mark_deleted_batch(&[3, 4, 5]);
244
245 bm1.merge(&bm2);
246 assert_eq!(bm1.deleted_count(), 5); }
248
249 #[test]
250 fn empty_bitmap() {
251 let bm = DeleteBitmap::new();
252 assert!(bm.is_empty());
253 assert_eq!(bm.deleted_count(), 0);
254 assert!(!bm.is_deleted(0));
255
256 let bytes = bm.to_bytes().unwrap();
258 let restored = DeleteBitmap::from_bytes(&bytes).expect("deserialize");
259 assert!(restored.is_empty());
260 }
261}