Skip to main content

range_tree_rs/
lib.rs

1#![cfg_attr(docsrs, feature(doc_cfg))]
2#![cfg_attr(docsrs, allow(unused_attributes))]
3//! This crate provides a range-tree implementation, automatically merge and split range section.
4//!
5//! The usage scenario for persistent slab allocators (Similar to the range-tree in ZFS),
6//! while the underlayer is not avl, but [b+tree](https://docs.rs/embed-collections/latest/embed_collections/#btree),
7//! which has more friendly for CPU cache and smaller in memory usage.
8
9use core::{
10    cmp::Ordering,
11    fmt,
12    ops::{AddAssign, Bound, RangeBounds, SubAssign},
13};
14use embed_btree::btree::{BTreeMap, Cursor, Entry, IntoIter as _IntoIter, Iter as _Iter};
15use num_traits::*;
16
17pub trait RangeTreeKey:
18    Unsigned + AddAssign + SubAssign + Ord + Copy + fmt::Debug + fmt::Display + Default + 'static
19{
20}
21
22impl<T> RangeTreeKey for T where
23    T: Unsigned
24        + AddAssign
25        + SubAssign
26        + Ord
27        + Copy
28        + fmt::Debug
29        + fmt::Display
30        + Default
31        + 'static
32{
33}
34
35/// A b+tree stores range segment of [start, start+size)
36pub struct RangeTree<T: RangeTreeKey> {
37    tree: BTreeMap<T, T>,
38    space: T,
39}
40
41/// Trait for allocator
42///
43/// when range tree merge/split, need to mirror the adding and removal range from size_tree
44pub trait RangeTreeOps<T: RangeTreeKey> {
45    /// Callback for manage size tree
46    fn op_add(&mut self, start: T, size: T);
47    /// Callback for manage size tree
48    fn op_remove(&mut self, start: T, size: T);
49}
50
51struct DummyOps();
52
53impl<T: RangeTreeKey> RangeTreeOps<T> for DummyOps {
54    #[inline]
55    fn op_add(&mut self, _start: T, _size: T) {}
56
57    #[inline]
58    fn op_remove(&mut self, _start: T, _size: T) {}
59}
60
61impl<T: RangeTreeKey> RangeTree<T> {
62    pub fn new() -> Self {
63        Self { tree: BTreeMap::new(), space: T::zero() }
64    }
65
66    #[inline]
67    pub fn is_empty(&self) -> bool {
68        self.tree.is_empty()
69    }
70
71    #[inline(always)]
72    pub fn get_space(&self) -> T {
73        self.space
74    }
75
76    #[inline(always)]
77    pub fn len(&self) -> usize {
78        self.tree.len()
79    }
80
81    /// Add range segment, merge with adjacent ranges, assuming no intersections.
82    ///
83    /// # Return value
84    ///
85    /// - `Ok(())` if there are no intersection;
86    /// - otherwise returns the overlapping range as `Err((existing_start, existing_size))`.
87    ///
88    /// # Compatibility
89    ///
90    /// This equals to add + add_find_overlap in v0.1
91    #[inline]
92    pub fn add(&mut self, start: T, size: T) -> Result<(), (T, T)> {
93        self.add_with(start, size, &mut DummyOps {})
94    }
95
96    /// The same with [add()](Self::add), with additional mirror operation to `RangeTreeOps`
97    #[inline]
98    pub fn add_with<O>(&mut self, start: T, size: T, ops: &mut O) -> Result<(), (T, T)>
99    where
100        O: RangeTreeOps<T>,
101    {
102        assert!(size > T::zero(), "range tree add size={} error", size);
103        let end = start + size;
104        let mut prev = None;
105        let mut next = None;
106        match self.tree.entry(start) {
107            Entry::Occupied(ent) => Err((*ent.key(), *ent.get())),
108            Entry::Vacant(ent) => {
109                if let Some((_start, _size)) = ent.peek_backward() {
110                    let _end = *_start + *_size;
111                    match _end.cmp(&start) {
112                        Ordering::Equal => {
113                            prev = Some((*_start, *_size));
114                        }
115                        Ordering::Greater => return Err((*_start, *_size)),
116                        _ => {}
117                    }
118                }
119                if let Some((_start, _size)) = ent.peek_forward() {
120                    match end.cmp(_start) {
121                        Ordering::Equal => {
122                            next = Some((*_start, *_size));
123                        }
124                        Ordering::Greater => return Err((*_start, *_size)),
125                        _ => {}
126                    }
127                }
128                match (prev, next) {
129                    (None, None) => {
130                        ops.op_add(start, size);
131                        ent.insert(size);
132                    }
133                    (None, Some((next_start, mut next_size))) => {
134                        let mut ent_next = ent.move_forward().expect("merge next");
135                        ops.op_remove(next_start, next_size);
136                        next_size += size;
137                        *ent_next.get_mut() = next_size;
138                        ent_next.alter_key(start).expect("merge next alter_key");
139                        ops.op_add(start, next_size);
140                    }
141                    (Some((prev_start, mut prev_size)), None) => {
142                        ops.op_remove(prev_start, prev_size);
143                        let mut ent_prev = ent.move_backward().expect("merge prev");
144                        prev_size += size;
145                        *ent_prev.get_mut() = prev_size;
146                        ops.op_add(prev_start, prev_size);
147                    }
148                    (Some((prev_start, prev_size)), Some((next_start, next_size))) => {
149                        ops.op_remove(prev_start, prev_size);
150                        ops.op_remove(next_start, next_size);
151                        let mut ent_prev = ent.move_backward().expect("merge prev");
152                        let final_size = prev_size + size + next_size;
153                        *ent_prev.get_mut() = final_size;
154                        ops.op_add(prev_start, final_size);
155                        let ent_next = ent_prev.move_forward().expect("merge next");
156                        ent_next.remove();
157                    }
158                }
159                self.space += size;
160                Ok(())
161            }
162        }
163    }
164
165    /// Add to the tree with [start, end)
166    ///
167    /// # Return value
168    ///
169    /// - `Ok(())` if there are no intersection;
170    /// - otherwise returns the overlapping range as `Err((existing_start, existing_size))`.
171    #[inline(always)]
172    pub fn add_abs(&mut self, start: T, end: T) -> Result<(), (T, T)> {
173        assert!(start < end, "range tree add start={} end={}", start, end);
174        self.add(start, end - start)
175    }
176
177    /// Add range which may have multiple intersections with existing range, ensuring union result
178    /// stores in the tree
179    #[inline]
180    pub fn add_loosely(&mut self, start: T, size: T) {
181        assert!(size > T::zero(), "range tree add size error");
182        let new_end = start + size;
183        let base_ent = match self.tree.entry(start) {
184            Entry::Occupied(oe) => {
185                if start + *oe.get() >= new_end {
186                    return;
187                }
188                Entry::Occupied(oe)
189            }
190            Entry::Vacant(ve) => {
191                if let Some((pre_start, pre_size)) = ve.peek_backward() {
192                    let cur_end = *pre_start + *pre_size;
193                    if cur_end >= new_end {
194                        return;
195                    }
196                    if cur_end >= start {
197                        Entry::Occupied(ve.move_backward().expect("move back to merge"))
198                    } else {
199                        Entry::Vacant(ve)
200                    }
201                } else {
202                    Entry::Vacant(ve)
203                }
204            }
205        };
206
207        macro_rules! remove_intersect {
208            ($next_start: expr, $new_end: expr) => {
209                if let Some((last_start, last_size)) = self.tree.remove_range_with(
210                    $next_start..=$new_end,
211                    |_removed_start, removed_size| {
212                        self.space -= *removed_size;
213                    },
214                ) {
215                    let last_end = last_start + last_size;
216                    if last_end > new_end {
217                        let _size = last_end - new_end;
218                        // add back and join with previous range
219                        self.add(new_end, _size)
220                            .expect("add {new_end:?}:{_size:?} should not fail");
221                    }
222                }
223            };
224        }
225        match base_ent {
226            Entry::Occupied(mut oe) => {
227                let base_start = *oe.key();
228                let old_size = *oe.get();
229
230                // extend the size to final size
231                let final_size = new_end - base_start;
232                self.space += final_size - old_size;
233                *oe.get_mut() = final_size;
234
235                if let Some((_next_start, _next_size)) = oe.peek_forward() {
236                    let next_start = *_next_start;
237                    let next_size = *_next_size;
238                    if next_start < new_end {
239                        _ = oe;
240                        remove_intersect!(next_start, new_end);
241                    } else if next_start == new_end {
242                        // space is neutral (moving between segments)
243                        *oe.get_mut() += next_size;
244                        self.tree.remove(&next_start);
245                    }
246                }
247            }
248            Entry::Vacant(ve) => {
249                let base_start = start;
250                self.space += size;
251
252                if let Some((_next_start, _next_size)) = ve.peek_forward() {
253                    let next_start = *_next_start;
254                    let next_size = *_next_size;
255                    if next_start < new_end {
256                        ve.insert(size);
257                        remove_intersect!(next_start, new_end);
258                    } else if next_start == new_end {
259                        let final_size = new_end - base_start + next_size;
260                        ve.insert(final_size);
261                        self.tree.remove(&next_start);
262                    } else {
263                        ve.insert(size);
264                    }
265                } else {
266                    ve.insert(size);
267                }
268            }
269        }
270    }
271
272    /// Valid and remove specify range start:size
273    ///
274    /// # Return value
275    ///
276    /// - Only return Ok(()) when there's existing range equal to or contain the removal range in the tree,
277    /// - return Err(None) when not found,
278    /// - return Err(Some(start, size)) when a range intersect with the removal range, or when the
279    ///   removal range larger than existing range.
280    #[inline]
281    pub fn remove(&mut self, start: T, size: T) -> Result<(), Option<(T, T)>> {
282        self.remove_with(start, size, &mut DummyOps {})
283    }
284
285    /// The same with [remove()](Self::remove), with additional mirror operation to `RangeTreeOps`
286    #[inline]
287    pub fn remove_with<O>(&mut self, start: T, size: T, ops: &mut O) -> Result<(), Option<(T, T)>>
288    where
289        O: RangeTreeOps<T>,
290    {
291        let end = start + size;
292        let ent = self.tree.entry(start);
293        match ent {
294            Entry::Occupied(mut oent) => {
295                let rs_size = *oent.get();
296                ops.op_remove(start, rs_size);
297                if rs_size == size {
298                    // Exact match or subset removed
299                    oent.remove();
300                    self.space -= rs_size;
301                    Ok(())
302                } else if rs_size > size {
303                    // Shrink from front
304                    let new_start = start + size;
305                    let new_size = rs_size - size;
306                    oent.alter_key(new_start).expect("shrink alter_key");
307                    *oent.get_mut() = new_size;
308                    ops.op_add(new_start, new_size);
309                    self.space -= size;
310                    Ok(())
311                } else {
312                    // existing range smaller than what need to remove
313                    Err(Some((start, rs_size)))
314                }
315            }
316            Entry::Vacant(vent) => {
317                if let Some((&rs_start, &rs_size)) = vent.peek_backward() {
318                    let rs_end = rs_start + rs_size;
319                    if rs_end > start {
320                        ops.op_remove(rs_start, rs_size);
321                        let mut oent = vent.move_backward().expect("move back to overlapping");
322                        if rs_end > end {
323                            let new_size = start - rs_start;
324                            // punch a hold in the middle
325                            *oent.get_mut() = new_size;
326                            ops.op_add(rs_start, new_size);
327                            let new_size2 = rs_end - end;
328                            // TODO optimize add insert after entry for btree
329                            self.tree.insert(end, new_size2);
330                            ops.op_add(end, new_size2);
331                            self.space -= size;
332                            Ok(())
333                        } else if rs_end == end {
334                            // Shrink from back
335                            let new_size = start - rs_start;
336                            *oent.get_mut() = new_size;
337                            ops.op_add(rs_start, new_size);
338                            self.space -= rs_end - start;
339                            Ok(())
340                        } else {
341                            Err(Some((rs_start, rs_size)))
342                        }
343                    } else {
344                        Err(None)
345                    }
346                } else {
347                    Err(None)
348                }
349            }
350        }
351    }
352
353    /// Remove all the intersection ranges in the tree
354    ///
355    /// Unlike the strict behavior of [RangeTree::remove()],
356    /// this function allows the removal range start:size to to be larger than the existing range.
357    ///
358    /// # Return value
359    ///
360    /// return true if overlapping range found and removed.
361    /// return false if overlapping range not found.
362    ///
363    /// # Compatibility
364    ///
365    /// Equals to remove_and_split in v0.1
366    #[inline]
367    pub fn remove_loosely(&mut self, mut start: T, mut size: T) -> bool {
368        let end = start + size;
369        let mut ent = self.tree.entry(start);
370        let mut removed = false;
371        loop {
372            match ent {
373                Entry::Occupied(mut oent) => {
374                    let rs_size = *oent.get();
375                    if rs_size == size {
376                        // Exact match or subset removed
377                        oent.remove();
378                        self.space -= rs_size;
379                        return true;
380                    } else if rs_size > size {
381                        // Shrink from front
382                        let new_start = start + size;
383                        let new_size = rs_size - size;
384                        oent.alter_key(new_start).expect("shrink alter_key");
385                        *oent.get_mut() = new_size;
386                        self.space -= size;
387                        return true;
388                    } else {
389                        if let Some((_next_start, _next_size)) = oent.peek_forward()
390                            && *_next_start < end
391                        {
392                            start = *_next_start;
393                            size = end - start;
394                            self.space -= *oent.get();
395                            oent.remove();
396                            ent = self.tree.entry(start);
397                            removed = true;
398                            continue;
399                        }
400                        self.space -= rs_size;
401                        oent.remove();
402                        return true;
403                    }
404                }
405                Entry::Vacant(vent) => {
406                    if let Some((&rs_start, &rs_size)) = vent.peek_backward() {
407                        let rs_end = rs_start + rs_size;
408                        if rs_end > start {
409                            let mut oent = vent.move_backward().expect("move back to overlapping");
410                            if rs_end > end {
411                                let new_size = start - rs_start;
412                                // punch a hold in the middle
413                                *oent.get_mut() = new_size;
414                                let new_size2 = rs_end - end;
415                                // TODO optimize add insert after entry for btree
416                                self.tree.insert(end, new_size2);
417                                self.space -= size;
418                                return true;
419                            } else {
420                                // Shrink from back
421                                let new_size = start - rs_start;
422                                *oent.get_mut() = new_size;
423                                self.space -= rs_end - start;
424                                if rs_end == end {
425                                    return true;
426                                }
427                                if let Some((next_start, _)) = oent.peek_forward()
428                                    && *next_start < end
429                                {
430                                    start = *next_start;
431                                    size = end - *next_start;
432                                    ent = Entry::Occupied(
433                                        oent.move_forward().expect("move forward to overlapping"),
434                                    );
435                                    continue;
436                                }
437                                return true;
438                            }
439                        }
440                    }
441                    // Handle the case where range starts before the first overlapping segment
442                    if let Some((next_start, _)) = vent.peek_forward()
443                        && *next_start < end
444                    {
445                        start = *next_start;
446                        size = end - *next_start;
447                        ent = Entry::Occupied(
448                            vent.move_forward().expect("move forward to overlapping"),
449                        );
450                        continue;
451                    }
452                    return removed;
453                }
454            }
455        }
456    }
457
458    /// return only when segment overlaps with start..end
459    ///
460    /// # NOTE
461    ///
462    /// Be aware the first range may have `_start < start`, and the last range may have `_start + _size > end`
463    #[inline]
464    pub fn range<'a, R: RangeBounds<T>>(&'a self, r: R) -> RangeIter<'a, T> {
465        let start = match r.start_bound() {
466            Bound::Included(start) => Some(*start),
467            Bound::Excluded(start) => Some(*start),
468            _ => None,
469        };
470        let cursor = if let Some(_start) = start {
471            let mut _cursor = self.tree.cursor(&_start);
472            if let Some((pre_start, pre_size)) = _cursor.peek_backward() {
473                let pre_end = *pre_start + *pre_size;
474                if pre_end > _start {
475                    _cursor.previous();
476                }
477                // TODO what if we find pre_start < start but pre_start + size >= start
478            }
479            _cursor
480        } else {
481            self.tree.first_cursor()
482        };
483        RangeIter { cursor, end: r.end_bound().cloned(), not_empty: true }
484    }
485
486    pub fn collect(&self) -> Vec<(T, T)> {
487        let mut v = Vec::with_capacity(self.len());
488        for (start, size) in &self.tree {
489            v.push((*start, *size))
490        }
491        v
492    }
493
494    #[inline]
495    pub fn iter(&self) -> Iter<'_, T> {
496        Iter(self.tree.iter())
497    }
498
499    pub fn validate(&self) {
500        self.tree.validate();
501    }
502
503    #[inline]
504    pub fn memory_used(&self) -> usize {
505        self.tree.memory_used()
506    }
507}
508
509impl<'a, T: RangeTreeKey> IntoIterator for &'a RangeTree<T> {
510    type Item = (T, T);
511    type IntoIter = Iter<'a, T>;
512
513    #[inline]
514    fn into_iter(self) -> Self::IntoIter {
515        self.iter()
516    }
517}
518
519impl<T: RangeTreeKey> IntoIterator for RangeTree<T> {
520    type Item = (T, T);
521    type IntoIter = IntoIter<T>;
522
523    #[inline]
524    fn into_iter(self) -> Self::IntoIter {
525        IntoIter(self.tree.into_iter())
526    }
527}
528
529/// An iterator without bound, acquire from [RangeTree::iter()]
530pub struct Iter<'a, T: RangeTreeKey>(_Iter<'a, T, T>);
531
532impl<'a, T: RangeTreeKey> Iterator for Iter<'a, T> {
533    type Item = (T, T);
534
535    #[inline]
536    fn next(&mut self) -> Option<Self::Item> {
537        self.0.next().map(|(start, size)| (*start, *size))
538    }
539}
540
541/// An consuming iterator for RangeTree
542pub struct IntoIter<T: RangeTreeKey>(_IntoIter<T, T>);
543
544impl<T: RangeTreeKey> Iterator for IntoIter<T> {
545    type Item = (T, T);
546
547    #[inline]
548    fn next(&mut self) -> Option<Self::Item> {
549        self.0.next()
550    }
551}
552
553/// An iterator for RangeTree with bound, acquire from [RangeTree::range()]
554pub struct RangeIter<'a, T: RangeTreeKey> {
555    cursor: Cursor<'a, T, T>,
556    end: Bound<T>,
557    not_empty: bool,
558}
559
560impl<'a, T: RangeTreeKey> Iterator for RangeIter<'a, T> {
561    type Item = (T, T);
562
563    #[inline]
564    fn next(&mut self) -> Option<Self::Item> {
565        if self.not_empty {
566            if let Some((start, size)) = self.cursor.next() {
567                match self.end {
568                    Bound::Unbounded => return Some((*start, *size)),
569                    Bound::Excluded(end) => {
570                        if *start < end {
571                            return Some((*start, *size));
572                        }
573                        self.not_empty = false;
574                        return None;
575                    }
576                    Bound::Included(end) => {
577                        if *start <= end {
578                            return Some((*start, *size));
579                        }
580                        self.not_empty = false;
581                        return None;
582                    }
583                }
584            }
585            self.not_empty = false;
586        }
587        None
588    }
589}