LCOV - code coverage report
Current view: top level - libs/pageserver_api/src - keyspace.rs (source / functions) Coverage Total Hit
Test: 322b88762cba8ea666f63cda880cccab6936bf37.info Lines: 92.5 % 466 431
Test Date: 2024-02-29 11:57:12 Functions: 86.7 % 60 52

            Line data    Source code
       1              : use postgres_ffi::BLCKSZ;
       2              : use std::ops::Range;
       3              : 
       4              : use crate::key::Key;
       5              : use itertools::Itertools;
       6              : 
       7              : ///
       8              : /// Represents a set of Keys, in a compact form.
       9              : ///
      10        11770 : #[derive(Clone, Debug, Default, PartialEq, Eq)]
      11              : pub struct KeySpace {
      12              :     /// Contiguous ranges of keys that belong to the key space. In key order,
      13              :     /// and with no overlap.
      14              :     pub ranges: Vec<Range<Key>>,
      15              : }
      16              : 
      17              : impl KeySpace {
      18              :     ///
      19              :     /// Partition a key space into roughly chunks of roughly 'target_size' bytes
      20              :     /// in each partition.
      21              :     ///
      22          174 :     pub fn partition(&self, target_size: u64) -> KeyPartitioning {
      23          174 :         // Assume that each value is 8k in size.
      24          174 :         let target_nblocks = (target_size / BLCKSZ as u64) as usize;
      25          174 : 
      26          174 :         let mut parts = Vec::new();
      27          174 :         let mut current_part = Vec::new();
      28          174 :         let mut current_part_size: usize = 0;
      29         1218 :         for range in &self.ranges {
      30              :             // If appending the next contiguous range in the keyspace to the current
      31              :             // partition would cause it to be too large, start a new partition.
      32         1044 :             let this_size = key_range_size(range) as usize;
      33         1044 :             if current_part_size + this_size > target_nblocks && !current_part.is_empty() {
      34            0 :                 parts.push(KeySpace {
      35            0 :                     ranges: current_part,
      36            0 :                 });
      37            0 :                 current_part = Vec::new();
      38            0 :                 current_part_size = 0;
      39         1044 :             }
      40              : 
      41              :             // If the next range is larger than 'target_size', split it into
      42              :             // 'target_size' chunks.
      43         1044 :             let mut remain_size = this_size;
      44         1044 :             let mut start = range.start;
      45         1044 :             while remain_size > target_nblocks {
      46            0 :                 let next = start.add(target_nblocks as u32);
      47            0 :                 parts.push(KeySpace {
      48            0 :                     ranges: vec![start..next],
      49            0 :                 });
      50            0 :                 start = next;
      51            0 :                 remain_size -= target_nblocks
      52              :             }
      53         1044 :             current_part.push(start..range.end);
      54         1044 :             current_part_size += remain_size;
      55              :         }
      56              : 
      57              :         // add last partition that wasn't full yet.
      58          174 :         if !current_part.is_empty() {
      59          174 :             parts.push(KeySpace {
      60          174 :                 ranges: current_part,
      61          174 :             });
      62          174 :         }
      63              : 
      64          174 :         KeyPartitioning { parts }
      65          174 :     }
      66              : 
      67              :     /// Merge another keyspace into the current one.
      68              :     /// Note: the keyspaces must not ovelap (enforced via assertions)
      69           20 :     pub fn merge(&mut self, other: &KeySpace) {
      70           20 :         let all_ranges = self
      71           20 :             .ranges
      72           20 :             .iter()
      73           20 :             .merge_by(other.ranges.iter(), |lhs, rhs| lhs.start < rhs.start);
      74           20 : 
      75           20 :         let mut accum = KeySpaceAccum::new();
      76           20 :         let mut prev: Option<&Range<Key>> = None;
      77           30 :         for range in all_ranges {
      78           10 :             if let Some(prev) = prev {
      79            0 :                 let overlap =
      80            0 :                     std::cmp::max(range.start, prev.start) < std::cmp::min(range.end, prev.end);
      81            0 :                 assert!(
      82            0 :                     !overlap,
      83            0 :                     "Attempt to merge ovelapping keyspaces: {:?} overlaps {:?}",
      84              :                     prev, range
      85              :                 );
      86           10 :             }
      87              : 
      88           10 :             accum.add_range(range.clone());
      89           10 :             prev = Some(range);
      90              :         }
      91              : 
      92           20 :         self.ranges = accum.to_keyspace().ranges;
      93           20 :     }
      94              : 
      95              :     /// Remove all keys in `other` from `self`.
      96              :     /// This can involve splitting or removing of existing ranges.
      97           38 :     pub fn remove_overlapping_with(&mut self, other: &KeySpace) {
      98           38 :         let (self_start, self_end) = match (self.start(), self.end()) {
      99           38 :             (Some(start), Some(end)) => (start, end),
     100              :             _ => {
     101              :                 // self is empty
     102            0 :                 return;
     103              :             }
     104              :         };
     105              : 
     106              :         // Key spaces are sorted by definition, so skip ahead to the first
     107              :         // potentially intersecting range. Similarly, ignore ranges that start
     108              :         // after the current keyspace ends.
     109           38 :         let other_ranges = other
     110           38 :             .ranges
     111           38 :             .iter()
     112           38 :             .skip_while(|range| self_start >= range.end)
     113           40 :             .take_while(|range| self_end > range.start);
     114              : 
     115           76 :         for range in other_ranges {
     116           76 :             while let Some(overlap_at) = self.overlaps_at(range) {
     117           38 :                 let overlapped = self.ranges[overlap_at].clone();
     118           38 : 
     119           38 :                 if overlapped.start < range.start && overlapped.end <= range.end {
     120           10 :                     // Higher part of the range is completely overlapped.
     121           10 :                     self.ranges[overlap_at].end = range.start;
     122           28 :                 }
     123           38 :                 if overlapped.start >= range.start && overlapped.end > range.end {
     124            2 :                     // Lower part of the range is completely overlapped.
     125            2 :                     self.ranges[overlap_at].start = range.end;
     126           36 :                 }
     127           38 :                 if overlapped.start < range.start && overlapped.end > range.end {
     128            4 :                     // Middle part of the range is overlapped.
     129            4 :                     self.ranges[overlap_at].end = range.start;
     130            4 :                     self.ranges
     131            4 :                         .insert(overlap_at + 1, range.end..overlapped.end);
     132           34 :                 }
     133           38 :                 if overlapped.start >= range.start && overlapped.end <= range.end {
     134           22 :                     // Whole range is overlapped
     135           22 :                     self.ranges.remove(overlap_at);
     136           22 :                 }
     137              :             }
     138              :         }
     139           38 :     }
     140              : 
     141           38 :     pub fn start(&self) -> Option<Key> {
     142           38 :         self.ranges.first().map(|range| range.start)
     143           38 :     }
     144              : 
     145           38 :     pub fn end(&self) -> Option<Key> {
     146           38 :         self.ranges.last().map(|range| range.end)
     147           38 :     }
     148              : 
     149              :     #[allow(unused)]
     150          464 :     pub fn total_size(&self) -> usize {
     151          464 :         self.ranges
     152          464 :             .iter()
     153          464 :             .map(|range| key_range_size(range) as usize)
     154          464 :             .sum()
     155          464 :     }
     156              : 
     157          102 :     fn overlaps_at(&self, range: &Range<Key>) -> Option<usize> {
     158          134 :         match self.ranges.binary_search_by_key(&range.end, |r| r.start) {
     159            2 :             Ok(0) => None,
     160           24 :             Err(0) => None,
     161           18 :             Ok(index) if self.ranges[index - 1].end > range.start => Some(index - 1),
     162           58 :             Err(index) if self.ranges[index - 1].end > range.start => Some(index - 1),
     163           26 :             _ => None,
     164              :         }
     165          102 :     }
     166              : 
     167              :     ///
     168              :     /// Check if key space contains overlapping range
     169              :     ///
     170           26 :     pub fn overlaps(&self, range: &Range<Key>) -> bool {
     171           26 :         self.overlaps_at(range).is_some()
     172           26 :     }
     173              : }
     174              : 
     175              : ///
     176              : /// Represents a partitioning of the key space.
     177              : ///
     178              : /// The only kind of partitioning we do is to partition the key space into
     179              : /// partitions that are roughly equal in physical size (see KeySpace::partition).
     180              : /// But this data structure could represent any partitioning.
     181              : ///
     182          482 : #[derive(Clone, Debug, Default)]
     183              : pub struct KeyPartitioning {
     184              :     pub parts: Vec<KeySpace>,
     185              : }
     186              : 
     187              : impl KeyPartitioning {
     188          296 :     pub fn new() -> Self {
     189          296 :         KeyPartitioning { parts: Vec::new() }
     190          296 :     }
     191              : }
     192              : 
     193              : ///
     194              : /// A helper object, to collect a set of keys and key ranges into a KeySpace
     195              : /// object. This takes care of merging adjacent keys and key ranges into
     196              : /// contiguous ranges.
     197              : ///
     198        16918 : #[derive(Clone, Debug, Default)]
     199              : pub struct KeySpaceAccum {
     200              :     accum: Option<Range<Key>>,
     201              : 
     202              :     ranges: Vec<Range<Key>>,
     203              :     size: u64,
     204              : }
     205              : 
     206              : impl KeySpaceAccum {
     207         7368 :     pub fn new() -> Self {
     208         7368 :         Self {
     209         7368 :             accum: None,
     210         7368 :             ranges: Vec::new(),
     211         7368 :             size: 0,
     212         7368 :         }
     213         7368 :     }
     214              : 
     215              :     #[inline(always)]
     216      2077864 :     pub fn add_key(&mut self, key: Key) {
     217      2077864 :         self.add_range(singleton_range(key))
     218      2077864 :     }
     219              : 
     220              :     #[inline(always)]
     221      2089536 :     pub fn add_range(&mut self, range: Range<Key>) {
     222      2089536 :         self.size += key_range_size(&range) as u64;
     223      2089536 : 
     224      2089536 :         match self.accum.as_mut() {
     225      2068626 :             Some(accum) => {
     226      2068626 :                 if range.start == accum.end {
     227      2064728 :                     accum.end = range.end;
     228      2064728 :                 } else {
     229              :                     // TODO: to efficiently support small sharding stripe sizes, we should avoid starting
     230              :                     // a new range here if the skipped region was all keys that don't belong on this shard.
     231              :                     // (https://github.com/neondatabase/neon/issues/6247)
     232         3898 :                     assert!(range.start > accum.end);
     233         3898 :                     self.ranges.push(accum.clone());
     234         3898 :                     *accum = range;
     235              :                 }
     236              :             }
     237        20910 :             None => self.accum = Some(range),
     238              :         }
     239      2089536 :     }
     240              : 
     241        24194 :     pub fn to_keyspace(mut self) -> KeySpace {
     242        24194 :         if let Some(accum) = self.accum.take() {
     243        20902 :             self.ranges.push(accum);
     244        20902 :         }
     245        24194 :         KeySpace {
     246        24194 :             ranges: self.ranges,
     247        24194 :         }
     248        24194 :     }
     249              : 
     250          448 :     pub fn consume_keyspace(&mut self) -> KeySpace {
     251          448 :         std::mem::take(self).to_keyspace()
     252          448 :     }
     253              : 
     254          598 :     pub fn size(&self) -> u64 {
     255          598 :         self.size
     256          598 :     }
     257              : }
     258              : 
     259              : ///
     260              : /// A helper object, to collect a set of keys and key ranges into a KeySpace
     261              : /// object. Key ranges may be inserted in any order and can overlap.
     262              : ///
     263           18 : #[derive(Clone, Debug, Default)]
     264              : pub struct KeySpaceRandomAccum {
     265              :     ranges: Vec<Range<Key>>,
     266              : }
     267              : 
     268              : impl KeySpaceRandomAccum {
     269           30 :     pub fn new() -> Self {
     270           30 :         Self { ranges: Vec::new() }
     271           30 :     }
     272              : 
     273          320 :     pub fn add_key(&mut self, key: Key) {
     274          320 :         self.add_range(singleton_range(key))
     275          320 :     }
     276              : 
     277          362 :     pub fn add_range(&mut self, range: Range<Key>) {
     278          362 :         self.ranges.push(range);
     279          362 :     }
     280              : 
     281           38 :     pub fn to_keyspace(mut self) -> KeySpace {
     282           38 :         let mut ranges = Vec::new();
     283           38 :         if !self.ranges.is_empty() {
     284          680 :             self.ranges.sort_by_key(|r| r.start);
     285           28 :             let mut start = self.ranges.first().unwrap().start;
     286           28 :             let mut end = self.ranges.first().unwrap().end;
     287          390 :             for r in self.ranges {
     288          362 :                 assert!(r.start >= start);
     289          362 :                 if r.start > end {
     290            4 :                     ranges.push(start..end);
     291            4 :                     start = r.start;
     292            4 :                     end = r.end;
     293          358 :                 } else if r.end > end {
     294          322 :                     end = r.end;
     295          322 :                 }
     296              :             }
     297           28 :             ranges.push(start..end);
     298           10 :         }
     299           38 :         KeySpace { ranges }
     300           38 :     }
     301              : 
     302           20 :     pub fn consume_keyspace(&mut self) -> KeySpace {
     303           20 :         let mut prev_accum = KeySpaceRandomAccum::new();
     304           20 :         std::mem::swap(self, &mut prev_accum);
     305           20 : 
     306           20 :         prev_accum.to_keyspace()
     307           20 :     }
     308              : }
     309              : 
     310              : #[inline(always)]
     311      2091030 : pub fn key_range_size(key_range: &Range<Key>) -> u32 {
     312      2091030 :     let start = key_range.start;
     313      2091030 :     let end = key_range.end;
     314      2091030 : 
     315      2091030 :     if end.field1 != start.field1
     316      2091030 :         || end.field2 != start.field2
     317      2091030 :         || end.field3 != start.field3
     318      2091030 :         || end.field4 != start.field4
     319              :     {
     320            0 :         return u32::MAX;
     321      2091030 :     }
     322      2091030 : 
     323      2091030 :     let start = (start.field5 as u64) << 32 | start.field6 as u64;
     324      2091030 :     let end = (end.field5 as u64) << 32 | end.field6 as u64;
     325      2091030 : 
     326      2091030 :     let diff = end - start;
     327      2091030 :     if diff > u32::MAX as u64 {
     328            0 :         u32::MAX
     329              :     } else {
     330      2091030 :         diff as u32
     331              :     }
     332      2091030 : }
     333              : 
     334      2078184 : pub fn singleton_range(key: Key) -> Range<Key> {
     335      2078184 :     key..key.next()
     336      2078184 : }
     337              : 
     338              : #[cfg(test)]
     339              : mod tests {
     340              :     use super::*;
     341              :     use std::fmt::Write;
     342              : 
     343              :     // Helper function to create a key range.
     344              :     //
     345              :     // Make the tests below less verbose.
     346           92 :     fn kr(irange: Range<i128>) -> Range<Key> {
     347           92 :         Key::from_i128(irange.start)..Key::from_i128(irange.end)
     348           92 :     }
     349              : 
     350              :     #[allow(dead_code)]
     351            0 :     fn dump_keyspace(ks: &KeySpace) {
     352            0 :         for r in ks.ranges.iter() {
     353            0 :             println!("  {}..{}", r.start.to_i128(), r.end.to_i128());
     354            0 :         }
     355            0 :     }
     356              : 
     357           22 :     fn assert_ks_eq(actual: &KeySpace, expected: Vec<Range<Key>>) {
     358           22 :         if actual.ranges != expected {
     359            0 :             let mut msg = String::new();
     360            0 : 
     361            0 :             writeln!(msg, "expected:").unwrap();
     362            0 :             for r in &expected {
     363            0 :                 writeln!(msg, "  {}..{}", r.start.to_i128(), r.end.to_i128()).unwrap();
     364            0 :             }
     365            0 :             writeln!(msg, "got:").unwrap();
     366            0 :             for r in &actual.ranges {
     367            0 :                 writeln!(msg, "  {}..{}", r.start.to_i128(), r.end.to_i128()).unwrap();
     368            0 :             }
     369            0 :             panic!("{}", msg);
     370           22 :         }
     371           22 :     }
     372              : 
     373            2 :     #[test]
     374            2 :     fn keyspace_consume() {
     375            2 :         let ranges = vec![kr(0..10), kr(20..35), kr(40..45)];
     376            2 : 
     377            2 :         let mut accum = KeySpaceAccum::new();
     378            8 :         for range in &ranges {
     379            6 :             accum.add_range(range.clone());
     380            6 :         }
     381              : 
     382            6 :         let expected_size: u64 = ranges.iter().map(|r| key_range_size(r) as u64).sum();
     383            2 :         assert_eq!(accum.size(), expected_size);
     384              : 
     385            2 :         assert_ks_eq(&accum.consume_keyspace(), ranges.clone());
     386            2 :         assert_eq!(accum.size(), 0);
     387              : 
     388            2 :         assert_ks_eq(&accum.consume_keyspace(), vec![]);
     389            2 :         assert_eq!(accum.size(), 0);
     390              : 
     391            8 :         for range in &ranges {
     392            6 :             accum.add_range(range.clone());
     393            6 :         }
     394            2 :         assert_ks_eq(&accum.to_keyspace(), ranges);
     395            2 :     }
     396              : 
     397            2 :     #[test]
     398            2 :     fn keyspace_add_range() {
     399            2 :         // two separate ranges
     400            2 :         //
     401            2 :         // #####
     402            2 :         //         #####
     403            2 :         let mut ks = KeySpaceRandomAccum::default();
     404            2 :         ks.add_range(kr(0..10));
     405            2 :         ks.add_range(kr(20..30));
     406            2 :         assert_ks_eq(&ks.to_keyspace(), vec![kr(0..10), kr(20..30)]);
     407            2 : 
     408            2 :         // two separate ranges, added in reverse order
     409            2 :         //
     410            2 :         //         #####
     411            2 :         // #####
     412            2 :         let mut ks = KeySpaceRandomAccum::default();
     413            2 :         ks.add_range(kr(20..30));
     414            2 :         ks.add_range(kr(0..10));
     415            2 : 
     416            2 :         // add range that is adjacent to the end of an existing range
     417            2 :         //
     418            2 :         // #####
     419            2 :         //      #####
     420            2 :         ks.add_range(kr(0..10));
     421            2 :         ks.add_range(kr(10..30));
     422            2 :         assert_ks_eq(&ks.to_keyspace(), vec![kr(0..30)]);
     423            2 : 
     424            2 :         // add range that is adjacent to the start of an existing range
     425            2 :         //
     426            2 :         //      #####
     427            2 :         // #####
     428            2 :         let mut ks = KeySpaceRandomAccum::default();
     429            2 :         ks.add_range(kr(10..30));
     430            2 :         ks.add_range(kr(0..10));
     431            2 :         assert_ks_eq(&ks.to_keyspace(), vec![kr(0..30)]);
     432            2 : 
     433            2 :         // add range that overlaps with the end of an existing range
     434            2 :         //
     435            2 :         // #####
     436            2 :         //    #####
     437            2 :         let mut ks = KeySpaceRandomAccum::default();
     438            2 :         ks.add_range(kr(0..10));
     439            2 :         ks.add_range(kr(5..30));
     440            2 :         assert_ks_eq(&ks.to_keyspace(), vec![kr(0..30)]);
     441            2 : 
     442            2 :         // add range that overlaps with the start of an existing range
     443            2 :         //
     444            2 :         //    #####
     445            2 :         // #####
     446            2 :         let mut ks = KeySpaceRandomAccum::default();
     447            2 :         ks.add_range(kr(5..30));
     448            2 :         ks.add_range(kr(0..10));
     449            2 :         assert_ks_eq(&ks.to_keyspace(), vec![kr(0..30)]);
     450            2 : 
     451            2 :         // add range that is fully covered by an existing range
     452            2 :         //
     453            2 :         // #########
     454            2 :         //   #####
     455            2 :         let mut ks = KeySpaceRandomAccum::default();
     456            2 :         ks.add_range(kr(0..30));
     457            2 :         ks.add_range(kr(10..20));
     458            2 :         assert_ks_eq(&ks.to_keyspace(), vec![kr(0..30)]);
     459            2 : 
     460            2 :         // add range that extends an existing range from both ends
     461            2 :         //
     462            2 :         //   #####
     463            2 :         // #########
     464            2 :         let mut ks = KeySpaceRandomAccum::default();
     465            2 :         ks.add_range(kr(10..20));
     466            2 :         ks.add_range(kr(0..30));
     467            2 :         assert_ks_eq(&ks.to_keyspace(), vec![kr(0..30)]);
     468            2 : 
     469            2 :         // add a range that overlaps with two existing ranges, joining them
     470            2 :         //
     471            2 :         // #####   #####
     472            2 :         //    #######
     473            2 :         let mut ks = KeySpaceRandomAccum::default();
     474            2 :         ks.add_range(kr(0..10));
     475            2 :         ks.add_range(kr(20..30));
     476            2 :         ks.add_range(kr(5..25));
     477            2 :         assert_ks_eq(&ks.to_keyspace(), vec![kr(0..30)]);
     478            2 :     }
     479              : 
     480            2 :     #[test]
     481            2 :     fn keyspace_overlaps() {
     482            2 :         let mut ks = KeySpaceRandomAccum::default();
     483            2 :         ks.add_range(kr(10..20));
     484            2 :         ks.add_range(kr(30..40));
     485            2 :         let ks = ks.to_keyspace();
     486            2 : 
     487            2 :         //        #####      #####
     488            2 :         // xxxx
     489            2 :         assert!(!ks.overlaps(&kr(0..5)));
     490              : 
     491              :         //        #####      #####
     492              :         //   xxxx
     493            2 :         assert!(!ks.overlaps(&kr(5..9)));
     494              : 
     495              :         //        #####      #####
     496              :         //    xxxx
     497            2 :         assert!(!ks.overlaps(&kr(5..10)));
     498              : 
     499              :         //        #####      #####
     500              :         //     xxxx
     501            2 :         assert!(ks.overlaps(&kr(5..11)));
     502              : 
     503              :         //        #####      #####
     504              :         //        xxxx
     505            2 :         assert!(ks.overlaps(&kr(10..15)));
     506              : 
     507              :         //        #####      #####
     508              :         //         xxxx
     509            2 :         assert!(ks.overlaps(&kr(15..20)));
     510              : 
     511              :         //        #####      #####
     512              :         //           xxxx
     513            2 :         assert!(ks.overlaps(&kr(15..25)));
     514              : 
     515              :         //        #####      #####
     516              :         //              xxxx
     517            2 :         assert!(!ks.overlaps(&kr(22..28)));
     518              : 
     519              :         //        #####      #####
     520              :         //               xxxx
     521            2 :         assert!(!ks.overlaps(&kr(25..30)));
     522              : 
     523              :         //        #####      #####
     524              :         //                      xxxx
     525            2 :         assert!(ks.overlaps(&kr(35..35)));
     526              : 
     527              :         //        #####      #####
     528              :         //                        xxxx
     529            2 :         assert!(!ks.overlaps(&kr(40..45)));
     530              : 
     531              :         //        #####      #####
     532              :         //                        xxxx
     533            2 :         assert!(!ks.overlaps(&kr(45..50)));
     534              : 
     535              :         //        #####      #####
     536              :         //        xxxxxxxxxxx
     537            2 :         assert!(ks.overlaps(&kr(0..30))); // XXXXX This fails currently!
     538            2 :     }
     539              : 
     540            2 :     #[test]
     541            2 :     fn test_remove_full_overlapps() {
     542            2 :         let mut key_space1 = KeySpace {
     543            2 :             ranges: vec![
     544            2 :                 Key::from_i128(1)..Key::from_i128(4),
     545            2 :                 Key::from_i128(5)..Key::from_i128(8),
     546            2 :                 Key::from_i128(10)..Key::from_i128(12),
     547            2 :             ],
     548            2 :         };
     549            2 :         let key_space2 = KeySpace {
     550            2 :             ranges: vec![
     551            2 :                 Key::from_i128(2)..Key::from_i128(3),
     552            2 :                 Key::from_i128(6)..Key::from_i128(7),
     553            2 :                 Key::from_i128(11)..Key::from_i128(13),
     554            2 :             ],
     555            2 :         };
     556            2 :         key_space1.remove_overlapping_with(&key_space2);
     557            2 :         assert_eq!(
     558            2 :             key_space1.ranges,
     559            2 :             vec![
     560            2 :                 Key::from_i128(1)..Key::from_i128(2),
     561            2 :                 Key::from_i128(3)..Key::from_i128(4),
     562            2 :                 Key::from_i128(5)..Key::from_i128(6),
     563            2 :                 Key::from_i128(7)..Key::from_i128(8),
     564            2 :                 Key::from_i128(10)..Key::from_i128(11)
     565            2 :             ]
     566            2 :         );
     567            2 :     }
     568              : 
     569            2 :     #[test]
     570            2 :     fn test_remove_partial_overlaps() {
     571            2 :         // Test partial ovelaps
     572            2 :         let mut key_space1 = KeySpace {
     573            2 :             ranges: vec![
     574            2 :                 Key::from_i128(1)..Key::from_i128(5),
     575            2 :                 Key::from_i128(7)..Key::from_i128(10),
     576            2 :                 Key::from_i128(12)..Key::from_i128(15),
     577            2 :             ],
     578            2 :         };
     579            2 :         let key_space2 = KeySpace {
     580            2 :             ranges: vec![
     581            2 :                 Key::from_i128(3)..Key::from_i128(6),
     582            2 :                 Key::from_i128(8)..Key::from_i128(11),
     583            2 :                 Key::from_i128(14)..Key::from_i128(17),
     584            2 :             ],
     585            2 :         };
     586            2 :         key_space1.remove_overlapping_with(&key_space2);
     587            2 :         assert_eq!(
     588            2 :             key_space1.ranges,
     589            2 :             vec![
     590            2 :                 Key::from_i128(1)..Key::from_i128(3),
     591            2 :                 Key::from_i128(7)..Key::from_i128(8),
     592            2 :                 Key::from_i128(12)..Key::from_i128(14),
     593            2 :             ]
     594            2 :         );
     595            2 :     }
     596              : 
     597            2 :     #[test]
     598            2 :     fn test_remove_no_overlaps() {
     599            2 :         let mut key_space1 = KeySpace {
     600            2 :             ranges: vec![
     601            2 :                 Key::from_i128(1)..Key::from_i128(5),
     602            2 :                 Key::from_i128(7)..Key::from_i128(10),
     603            2 :                 Key::from_i128(12)..Key::from_i128(15),
     604            2 :             ],
     605            2 :         };
     606            2 :         let key_space2 = KeySpace {
     607            2 :             ranges: vec![
     608            2 :                 Key::from_i128(6)..Key::from_i128(7),
     609            2 :                 Key::from_i128(11)..Key::from_i128(12),
     610            2 :                 Key::from_i128(15)..Key::from_i128(17),
     611            2 :             ],
     612            2 :         };
     613            2 :         key_space1.remove_overlapping_with(&key_space2);
     614            2 :         assert_eq!(
     615            2 :             key_space1.ranges,
     616            2 :             vec![
     617            2 :                 Key::from_i128(1)..Key::from_i128(5),
     618            2 :                 Key::from_i128(7)..Key::from_i128(10),
     619            2 :                 Key::from_i128(12)..Key::from_i128(15),
     620            2 :             ]
     621            2 :         );
     622            2 :     }
     623              : 
     624            2 :     #[test]
     625            2 :     fn test_remove_one_range_overlaps_multiple() {
     626            2 :         let mut key_space1 = KeySpace {
     627            2 :             ranges: vec![
     628            2 :                 Key::from_i128(1)..Key::from_i128(3),
     629            2 :                 Key::from_i128(3)..Key::from_i128(6),
     630            2 :                 Key::from_i128(6)..Key::from_i128(10),
     631            2 :                 Key::from_i128(12)..Key::from_i128(15),
     632            2 :                 Key::from_i128(17)..Key::from_i128(20),
     633            2 :                 Key::from_i128(20)..Key::from_i128(30),
     634            2 :                 Key::from_i128(30)..Key::from_i128(40),
     635            2 :             ],
     636            2 :         };
     637            2 :         let key_space2 = KeySpace {
     638            2 :             ranges: vec![Key::from_i128(9)..Key::from_i128(19)],
     639            2 :         };
     640            2 :         key_space1.remove_overlapping_with(&key_space2);
     641            2 :         assert_eq!(
     642            2 :             key_space1.ranges,
     643            2 :             vec![
     644            2 :                 Key::from_i128(1)..Key::from_i128(3),
     645            2 :                 Key::from_i128(3)..Key::from_i128(6),
     646            2 :                 Key::from_i128(6)..Key::from_i128(9),
     647            2 :                 Key::from_i128(19)..Key::from_i128(20),
     648            2 :                 Key::from_i128(20)..Key::from_i128(30),
     649            2 :                 Key::from_i128(30)..Key::from_i128(40),
     650            2 :             ]
     651            2 :         );
     652            2 :     }
     653              : }
        

Generated by: LCOV version 2.1-beta