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