]> git.apps.os.sepia.ceph.com Git - ceph.git/commitdiff
interval_set: Enhancements to improve efficiency of insert() and to allow more flexib...
authorAlex Ainscow <aainscow@uk.ibm.com>
Wed, 8 Jan 2025 22:16:49 +0000 (22:16 +0000)
committerAlex Ainscow <aainscow@uk.ibm.com>
Mon, 27 Jan 2025 11:20:01 +0000 (11:20 +0000)
The old insert was restrictive in ranges that could be added in. The new interface allows for a range to be added, whether it extends or joins other intervals.

Also change a number of interfaces to use the new insert.

Signed-off-by: Alex Ainscow <aainscow@uk.ibm.com>
src/include/interval_set.h

index 2e2e47e0d345963552cc081ac420feb779b45629..6372b35f818a4ad53de86411b51f22447f1a636f 100644 (file)
@@ -495,58 +495,55 @@ class interval_set {
 
   void insert(T start, T len, T *pstart=0, T *plen=0) {
     //cout << "insert " << start << "~" << len << endl;
-    ceph_assert(len > 0);
-    _size += len;
+    T new_len = len;
     auto p = find_adj_m(start);
-    if (p == m.end()) {
+    auto o = std::pair(start, len);
+    T end = start+len;
+
+    if(len == 0) {
+      if (p != m.end() && start >= p->first && start < p->first + p->second) {
+        o = *p;
+      }
+    } else if (p == m.end()) {
       m[start] = len;                  // new interval
-      if (pstart)
-       *pstart = start;
-      if (plen)
-       *plen = len;
     } else {
       if (p->first < start) {
-        
-        if (p->first + p->second != start) {
-          //cout << "p is " << p->first << "~" << p->second << ", start is " << start << ", len is " << len << endl;
-          ceph_abort();
-        }
-        
-        p->second += len;               // append to end
-        
+        T pend = p->first + p->second;
+        new_len = new_len - (std::min(pend, end) - start); // Remove the overlap
+        p->second = std::max(pend, end) - p->first; // Adjust existing
+
+        // Some usages of interval_set do not implement the + operator.
         auto n = p;
         ++n;
-       if (pstart)
-         *pstart = p->first;
-        if (n != m.end() && 
-            start+len == n->first) {   // combine with next, too!
-          p->second += n->second;
-         if (plen)
-           *plen = p->second;
-          m.erase(n);
-        } else {
-         if (plen)
-           *plen = p->second;
-       }
+        for (; n != m.end() && end >= n->first; n = m.erase(n)) {
+          // The follow is split out to avoid template issues.
+          // This adds the part of n which is not overlapping with the insert.
+          T a = n->second;
+          T b = end - n->first;
+          new_len = new_len - std::min(a, b);
+          p->second += n->second - std::min(a, b);
+        }
+
+        o = *p;
       } else {
-        if (start+len == p->first) {
-         if (pstart)
-           *pstart = start;
-         if (plen)
-           *plen = len + p->second;
-         T psecond = p->second;
-          m.erase(p);
-          m[start] = len + psecond;  // append to front
-        } else {
-          ceph_assert(p->first > start+len);
-         if (pstart)
-           *pstart = start;
-         if (plen)
-           *plen = len;
-          m[start] = len;              // new interval
+        T old_len = 0;
+        T new_end = end;
+        for (;p != m.end() && end >= p->first; p = m.erase(p)) {
+          T pend = p->first + p->second;
+          new_end = std::max(pend, end);
+          old_len = old_len + p->second;
         }
+        m[start] = o.second = new_end - start;
+        new_len = o.second - old_len;
       }
     }
+
+    _size += new_len;
+
+    if (pstart)
+      *pstart = o.first;
+    if (plen)
+      *plen = o.second;
   }
 
   void swap(interval_set& other) {
@@ -677,31 +674,17 @@ class interval_set {
     ceph_assert(&a != this);
     ceph_assert(&b != this);
     clear();
-    
-    //cout << "union_of" << endl;
-
-    // a
-    m = a.m;
-    _size = a._size;
-
-    // - (a*b)
-    interval_set ab;
-    ab.intersection_of(a, b);
-    subtract(ab);
 
-    // + b
+    insert(a);
     insert(b);
-    return;
   }
+
   void union_of(const interval_set &b) {
-    interval_set a;
-    swap(a);    
-    union_of(a, b);
+    insert(b);
   }
   void union_insert(T off, T len) {
-    interval_set a;
-    a.insert(off, len);
-    union_of(a);
+    // insert supports overlapping entries. This function is redundant.
+    insert(off, len);
   }
 
   bool subset_of(const interval_set &big) const {