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());
104 self.inner
105 .serialize_into(&mut buf)
106 .map_err(|e| ColumnarError::Serialization(format!("delete bitmap: {e}")))?;
107 Ok(buf)
108 }
109
110 pub fn from_bytes(data: &[u8]) -> Result<Self, ColumnarError> {
112 let inner = RoaringBitmap::deserialize_from(data)
113 .map_err(|e| ColumnarError::Serialization(format!("delete bitmap: {e}")))?;
114 Ok(Self { inner })
115 }
116
117 pub fn iter(&self) -> impl Iterator<Item = u32> + '_ {
119 self.inner.iter()
120 }
121
122 pub fn unmark_deleted(&mut self, row_idx: u32) -> bool {
128 self.inner.remove(row_idx)
129 }
130
131 pub fn merge(&mut self, other: &DeleteBitmap) {
134 self.inner |= &other.inner;
135 }
136}
137
138impl Default for DeleteBitmap {
139 fn default() -> Self {
140 Self::new()
141 }
142}
143
144#[cfg(test)]
145mod tests {
146 use super::*;
147
148 #[test]
149 fn mark_and_check() {
150 let mut bm = DeleteBitmap::new();
151 assert!(!bm.is_deleted(5));
152 assert!(bm.mark_deleted(5));
153 assert!(bm.is_deleted(5));
154 assert!(!bm.mark_deleted(5)); assert_eq!(bm.deleted_count(), 1);
156 }
157
158 #[test]
159 fn batch_delete() {
160 let mut bm = DeleteBitmap::new();
161 bm.mark_deleted_batch(&[1, 3, 5, 7, 9]);
162 assert_eq!(bm.deleted_count(), 5);
163 assert!(bm.is_deleted(3));
164 assert!(!bm.is_deleted(4));
165 }
166
167 #[test]
168 fn serialization_roundtrip() {
169 let mut bm = DeleteBitmap::new();
170 bm.mark_deleted_batch(&[0, 10, 100, 1000, 10000]);
171
172 let bytes = bm.to_bytes().unwrap();
173 let restored = DeleteBitmap::from_bytes(&bytes).expect("deserialize");
174
175 assert_eq!(restored.deleted_count(), 5);
176 assert!(restored.is_deleted(0));
177 assert!(restored.is_deleted(10));
178 assert!(restored.is_deleted(10000));
179 assert!(!restored.is_deleted(50));
180 }
181
182 #[test]
183 fn delete_ratio_and_compaction() {
184 let mut bm = DeleteBitmap::new();
185 for i in 0..30 {
186 bm.mark_deleted(i);
187 }
188 assert!((bm.delete_ratio(100) - 0.3).abs() < 0.001);
190 assert!(bm.should_compact(100, 0.2));
192 assert!(!bm.should_compact(100, 0.5));
194 }
195
196 #[test]
197 fn block_fully_deleted() {
198 let mut bm = DeleteBitmap::new();
199 for i in 10..20 {
201 bm.mark_deleted(i);
202 }
203 assert!(bm.is_block_fully_deleted(10, 10));
204 assert!(!bm.is_block_fully_deleted(10, 11)); assert!(!bm.is_block_fully_deleted(5, 10)); }
207
208 #[test]
209 fn apply_to_validity() {
210 let mut bm = DeleteBitmap::new();
211 bm.mark_deleted_batch(&[2, 4]);
212
213 let mut valid = vec![true, true, true, true, true];
214 bm.apply_to_validity(&mut valid, 0);
215
216 assert!(valid[0]);
217 assert!(valid[1]);
218 assert!(!valid[2]); assert!(valid[3]);
220 assert!(!valid[4]); }
222
223 #[test]
224 fn apply_to_validity_with_offset() {
225 let mut bm = DeleteBitmap::new();
226 bm.mark_deleted(1025); let mut valid = vec![true; 1024];
229 bm.apply_to_validity(&mut valid, 1024); assert!(valid[0]); assert!(!valid[1]); assert!(valid[2]); }
235
236 #[test]
237 fn merge_bitmaps() {
238 let mut bm1 = DeleteBitmap::new();
239 bm1.mark_deleted_batch(&[1, 2, 3]);
240
241 let mut bm2 = DeleteBitmap::new();
242 bm2.mark_deleted_batch(&[3, 4, 5]);
243
244 bm1.merge(&bm2);
245 assert_eq!(bm1.deleted_count(), 5); }
247
248 #[test]
249 fn empty_bitmap() {
250 let bm = DeleteBitmap::new();
251 assert!(bm.is_empty());
252 assert_eq!(bm.deleted_count(), 0);
253 assert!(!bm.is_deleted(0));
254
255 let bytes = bm.to_bytes().unwrap();
257 let restored = DeleteBitmap::from_bytes(&bytes).expect("deserialize");
258 assert!(restored.is_empty());
259 }
260}