]> git.proxmox.com Git - ceph.git/blobdiff - ceph/src/include/interval_set.h
import 15.2.0 Octopus source
[ceph.git] / ceph / src / include / interval_set.h
index 4fb6be45a9e6be62ec2b92b8b32aeab5bf15efac..5b2b90d87ac1bab6c783729a8211bfd119ad27fc 100644 (file)
 template<typename T, typename Map = std::map<T,T>>
 class interval_set {
  public:
-  using value_type = T;
+  using value_type = typename Map::value_type;
+  using offset_type = T;
+  using length_type = T;
+  using reference = value_type&;
+  using const_reference = const value_type&;
+  using size_type = typename Map::size_type;
 
   class const_iterator;
 
@@ -56,48 +61,49 @@ class interval_set {
         }
 
         // Dereference this iterator to get a pair.
-        std::pair < T, T > &operator*() {
-                return *_iter;
+        reference operator*() const {
+          return *_iter;
         }
 
         // Return the interval start.
-        T get_start() const {
-                return _iter->first;
+        offset_type get_start() const {
+          return _iter->first;
         }
 
         // Return the interval length.
-        T get_len() const {
-                return _iter->second;
+        length_type get_len() const {
+          return _iter->second;
         }
-        T get_end() const {
-                return _iter->first + _iter->second;
+
+        offset_type get_end() const {
+          return _iter->first + _iter->second;
         }
 
         // Set the interval length.
-        void set_len(T len) {
-                _iter->second = len;
+        void set_len(const length_type& len) {
+          _iter->second = len;
         }
 
         // Preincrement
-        iterator &operator++()
+        iteratoroperator++()
         {
-                ++_iter;
-                return *this;
+          ++_iter;
+          return *this;
         }
 
         // Postincrement
         iterator operator++(int)
         {
-                iterator prev(_iter);
-                ++_iter;
-                return prev;
+          iterator prev(_iter);
+          ++_iter;
+          return prev;
         }
 
-    friend class interval_set<T,Map>::const_iterator;
+    friend class interval_set::const_iterator;
 
     protected:
         typename Map::iterator _iter;
-    friend class interval_set<T,Map>;
+    friend class interval_set;
   };
 
   class const_iterator : public std::iterator <std::forward_iterator_tag, T>
@@ -123,137 +129,136 @@ class interval_set {
         }
 
         // Dereference this iterator to get a pair.
-        std::pair < T, T > operator*() const {
-                return *_iter;
+        const_reference operator*() const {
+          return *_iter;
         }
 
         // Return the interval start.
-        T get_start() const {
-                return _iter->first;
+        offset_type get_start() const {
+          return _iter->first;
         }
-        T get_end() const {
-                return _iter->first + _iter->second;
+        offset_type get_end() const {
+          return _iter->first + _iter->second;
         }
 
         // Return the interval length.
-        T get_len() const {
-                return _iter->second;
+        length_type get_len() const {
+          return _iter->second;
         }
 
         // Preincrement
-        const_iterator &operator++()
+        const_iteratoroperator++()
         {
-                ++_iter;
-                return *this;
+          ++_iter;
+          return *this;
         }
 
         // Postincrement
         const_iterator operator++(int)
         {
-                const_iterator prev(_iter);
-                ++_iter;
-                return prev;
+          const_iterator prev(_iter);
+          ++_iter;
+          return prev;
         }
 
     protected:
         typename Map::const_iterator _iter;
   };
 
-  interval_set() : _size(0) {}
-  interval_set(Map& other) {
+  interval_set() = default;
+  interval_set(Map&& other) {
     m.swap(other);
-    _size = 0;
-    for (auto& i : m) {
-      _size += i.second;
+    for (const auto& p : m) {
+      _size += p.second;
     }
   }
 
-  int num_intervals() const
+  size_type num_intervals() const
   {
     return m.size();
   }
 
-  typename interval_set<T,Map>::iterator begin() {
-    return typename interval_set<T,Map>::iterator(m.begin());
+  iterator begin() {
+    return iterator(m.begin());
   }
 
-  typename interval_set<T,Map>::iterator lower_bound(T start) {
-    return typename interval_set<T,Map>::iterator(find_inc_m(start));
+  iterator lower_bound(T start) {
+    return iterator(find_inc_m(start));
   }
 
-  typename interval_set<T,Map>::iterator end() {
-    return typename interval_set<T,Map>::iterator(m.end());
+  iterator end() {
+    return iterator(m.end());
   }
 
-  typename interval_set<T,Map>::const_iterator begin() const {
-    return typename interval_set<T,Map>::const_iterator(m.begin());
+  const_iterator begin() const {
+    return const_iterator(m.begin());
   }
 
-  typename interval_set<T,Map>::const_iterator lower_bound(T start) const {
-    return typename interval_set<T,Map>::const_iterator(find_inc(start));
+  const_iterator lower_bound(T start) const {
+    return const_iterator(find_inc(start));
   }
 
-  typename interval_set<T,Map>::const_iterator end() const {
-    return typename interval_set<T,Map>::const_iterator(m.end());
+  const_iterator end() const {
+    return const_iterator(m.end());
   }
 
   // helpers
  private:
-  typename Map::const_iterator find_inc(T start) const {
-    typename Map::const_iterator p = m.lower_bound(start);  // p->first >= start
+  auto find_inc(T start) const {
+    auto p = m.lower_bound(start);  // p->first >= start
     if (p != m.begin() &&
         (p == m.end() || p->first > start)) {
-      p--;   // might overlap?
+      --p;   // might overlap?
       if (p->first + p->second <= start)
-        p++; // it doesn't.
+        ++p; // it doesn't.
     }
     return p;
   }
   
-  typename Map::iterator find_inc_m(T start) {
-    typename Map::iterator p = m.lower_bound(start);
+  auto find_inc_m(T start) {
+    auto p = m.lower_bound(start);
     if (p != m.begin() &&
         (p == m.end() || p->first > start)) {
-      p--;   // might overlap?
+      --p;   // might overlap?
       if (p->first + p->second <= start)
-        p++; // it doesn't.
+        ++p; // it doesn't.
     }
     return p;
   }
   
-  typename Map::const_iterator find_adj(T start) const {
-    typename Map::const_iterator p = m.lower_bound(start);
+  auto find_adj(T start) const {
+    auto p = m.lower_bound(start);
     if (p != m.begin() &&
         (p == m.end() || p->first > start)) {
-      p--;   // might touch?
+      --p;   // might touch?
       if (p->first + p->second < start)
-        p++; // it doesn't.
+        ++p; // it doesn't.
     }
     return p;
   }
   
-  typename Map::iterator find_adj_m(T start) {
-    typename Map::iterator p = m.lower_bound(start);
+  auto find_adj_m(T start) {
+    auto p = m.lower_bound(start);
     if (p != m.begin() &&
         (p == m.end() || p->first > start)) {
-      p--;   // might touch?
+      --p;   // might touch?
       if (p->first + p->second < start)
-        p++; // it doesn't.
+        ++p; // it doesn't.
     }
     return p;
   }
 
   void intersection_size_asym(const interval_set &s, const interval_set &l) {
-    typename decltype(m)::const_iterator ps = s.m.begin(), pl;
+    auto ps = s.m.begin();
     ceph_assert(ps != s.m.end());
-    T offset = ps->first;
+    auto offset = ps->first;
     bool first = true;
-    typename decltype(m)::iterator mi = m.begin();
+    auto mi = m.begin();
 
     while (1) {
       if (first)
         first = false;
-      pl = l.find_inc(offset);
+      auto pl = l.find_inc(offset);
       if (pl == l.m.end())
         break;
       while (ps != s.m.end() && ps->first + ps->second <= pl->first)
@@ -279,12 +284,11 @@ class interval_set {
         continue;
       }
 
-      T start = std::max<T>(ps->first, pl->first);
-      T en = std::min<T>(ps->first + ps->second, offset);
+      auto start = std::max<T>(ps->first, pl->first);
+      auto en = std::min<T>(ps->first + ps->second, offset);
       ceph_assert(en > start);
-      typename decltype(m)::value_type i{start, en - start};
-      mi = m.insert(mi, i);
-      _size += i.second;
+      mi = m.emplace_hint(mi, start, en - start);
+      _size += mi->second;
       if (ps->first + ps->second <= offset) {
         ++ps;
         if (ps == s.m.end())
@@ -331,39 +335,39 @@ class interval_set {
     return _size == other._size && m == other.m;
   }
 
-  int64_t size() const {
+  uint64_t size() const {
     return _size;
   }
 
   void bound_encode(size_t& p) const {
     denc_traits<Map>::bound_encode(m, p);
   }
-  void encode(bufferlist::contiguous_appender& p) const {
+  void encode(ceph::buffer::list::contiguous_appender& p) const {
     denc(m, p);
   }
-  void decode(bufferptr::const_iterator& p) {
+  void decode(ceph::buffer::ptr::const_iterator& p) {
     denc(m, p);
     _size = 0;
-    for (const auto& i : m) {
-      _size += i.second;
+    for (const auto& p : m) {
+      _size += p.second;
     }
   }
-  void decode(bufferlist::iterator& p) {
+  void decode(ceph::buffer::list::iterator& p) {
     denc(m, p);
     _size = 0;
-    for (const auto& i : m) {
-      _size += i.second;
+    for (const auto& p : m) {
+      _size += p.second;
     }
   }
 
-  void encode_nohead(bufferlist::contiguous_appender& p) const {
+  void encode_nohead(ceph::buffer::list::contiguous_appender& p) const {
     denc_traits<Map>::encode_nohead(m, p);
   }
-  void decode_nohead(int n, bufferptr::const_iterator& p) {
+  void decode_nohead(int n, ceph::buffer::ptr::const_iterator& p) {
     denc_traits<Map>::decode_nohead(n, m, p);
     _size = 0;
-    for (const auto& i : m) {
-      _size += i.second;
+    for (const auto& p : m) {
+      _size += p.second;
     }
   }
 
@@ -373,7 +377,7 @@ class interval_set {
   }
 
   bool contains(T i, T *pstart=0, T *plen=0) const {
-    typename Map::const_iterator p = find_inc(i);
+    auto p = find_inc(i);
     if (p == m.end()) return false;
     if (p->first > i) return false;
     if (p->first+p->second <= i) return false;
@@ -385,7 +389,7 @@ class interval_set {
     return true;
   }
   bool contains(T start, T len) const {
-    typename Map::const_iterator p = find_inc(start);
+    auto p = find_inc(start);
     if (p == m.end()) return false;
     if (p->first > start) return false;
     if (p->first+p->second <= start) return false;
@@ -406,14 +410,14 @@ class interval_set {
   bool empty() const {
     return m.empty();
   }
-  T range_start() const {
+  offset_type range_start() const {
     ceph_assert(!empty());
-    typename Map::const_iterator p = m.begin();
+    auto p = m.begin();
     return p->first;
   }
-  T range_end() const {
+  offset_type range_end() const {
     ceph_assert(!empty());
-    typename Map::const_iterator p = m.end();
+    auto p = m.end();
     p--;
     return p->first+p->second;
   }
@@ -421,20 +425,20 @@ class interval_set {
   // interval start after p (where p not in set)
   bool starts_after(T i) const {
     ceph_assert(!contains(i));
-    typename Map::const_iterator p = find_inc(i);
+    auto p = find_inc(i);
     if (p == m.end()) return false;
     return true;
   }
-  T start_after(T i) const {
+  offset_type start_after(T i) const {
     ceph_assert(!contains(i));
-    typename Map::const_iterator p = find_inc(i);
+    auto p = find_inc(i);
     return p->first;
   }
 
   // interval end that contains start
-  T end_after(T start) const {
+  offset_type end_after(T start) const {
     ceph_assert(contains(start));
-    typename Map::const_iterator p = find_inc(start);
+    auto p = find_inc(start);
     return p->first+p->second;
   }
   
@@ -446,7 +450,7 @@ class interval_set {
     //cout << "insert " << start << "~" << len << endl;
     ceph_assert(len > 0);
     _size += len;
-    typename Map::iterator p = find_adj_m(start);
+    auto p = find_adj_m(start);
     if (p == m.end()) {
       m[start] = len;                  // new interval
       if (pstart)
@@ -463,8 +467,8 @@ class interval_set {
         
         p->second += len;               // append to end
         
-        typename Map::iterator n = p;
-        n++;
+        auto n = p;
+        ++n;
        if (pstart)
          *pstart = p->first;
         if (n != m.end() && 
@@ -498,7 +502,7 @@ class interval_set {
     }
   }
 
-  void swap(interval_set<T,Map>& other) {
+  void swap(interval_set& other) {
     m.swap(other.m);
     std::swap(_size, other._size);
   }    
@@ -515,7 +519,7 @@ class interval_set {
 
   void erase(T start, T len, 
     std::function<bool(T, T)> claim = {}) {
-    typename Map::iterator p = find_inc_m(start);
+    auto p = find_inc_m(start);
 
     _size -= len;
     ceph_assert(_size >= 0);
@@ -546,17 +550,15 @@ class interval_set {
   }
 
   void subtract(const interval_set &a) {
-    for (typename Map::const_iterator p = a.m.begin();
-         p != a.m.end();
-         p++)
-      erase(p->first, p->second);
+    for (const auto& [start, len] : a.m) {
+      erase(start, len);
+    }
   }
 
   void insert(const interval_set &a) {
-    for (typename Map::const_iterator p = a.m.begin();
-         p != a.m.end();
-         p++)
-      insert(p->first, p->second);
+    for (const auto& [start, len] : a.m) {
+      insert(start, len);
+    }
   }
 
 
@@ -588,9 +590,9 @@ class interval_set {
       return;
     }
 
-    typename Map::const_iterator pa = a.m.begin();
-    typename Map::const_iterator pb = b.m.begin();
-    typename decltype(m)::iterator mi = m.begin();
+    auto pa = a.m.begin();
+    auto pb = b.m.begin();
+    auto mi = m.begin();
 
     while (pa != a.m.end() && pb != b.m.end()) {
       // passing?
@@ -612,9 +614,8 @@ class interval_set {
       T start = std::max(pa->first, pb->first);
       T en = std::min(pa->first+pa->second, pb->first+pb->second);
       ceph_assert(en > start);
-      typename decltype(m)::value_type i{start, en - start};
-      mi = m.insert(mi, i);
-      _size += i.second;
+      mi = m.emplace_hint(mi, start, en - start);
+      _size += mi->second;
       if (pa->first+pa->second > pb->first+pb->second)
         pb++;
       else
@@ -674,10 +675,9 @@ class interval_set {
     if (big.size() / size() < 10)
       return subset_size_sym(big);
 
-    for (typename Map::const_iterator i = m.begin();
-         i != m.end();
-         i++) 
-      if (!big.contains(i->first, i->second)) return false;
+    for (const auto& [start, len] : m) {
+      if (!big.contains(start, len)) return false;
+    }
     return true;
   }  
 
@@ -688,7 +688,7 @@ class interval_set {
    */
   void span_of(const interval_set &other, T start, T len) {
     clear();
-    typename Map::const_iterator p = other.find_inc(start);
+    auto p = other.find_inc(start);
     if (p == other.m.end())
       return;
     if (p->first < start) {
@@ -720,13 +720,13 @@ class interval_set {
    * Move contents of m into another Map. Use that instead of
    * encoding interval_set into bufferlist then decoding it back into Map.
    */
-  void move_into(Map& other) {
-    other = std::move(m);
+  Map detach() && {
+    return std::move(m);
   }
 
 private:
   // data
-  int64_t _size;
+  uint64_t _size = 0;
   Map m;   // map start -> len
 };
 
@@ -742,23 +742,23 @@ struct denc_traits<interval_set<T,Map>> {
     v.bound_encode(p);
   }
   static void encode(const interval_set<T,Map>& v,
-                    bufferlist::contiguous_appender& p) {
+                    ceph::buffer::list::contiguous_appender& p) {
     v.encode(p);
   }
-  static void decode(interval_set<T,Map>& v, bufferptr::const_iterator& p) {
+  static void decode(interval_set<T,Map>& v, ceph::buffer::ptr::const_iterator& p) {
     v.decode(p);
   }
   template<typename U=T>
     static typename std::enable_if<sizeof(U) && !need_contiguous>::type
-    decode(interval_set<T,Map>& v, bufferlist::iterator& p) {
+  decode(interval_set<T,Map>& v, ceph::buffer::list::iterator& p) {
     v.decode(p);
   }
   static void encode_nohead(const interval_set<T,Map>& v,
-                           bufferlist::contiguous_appender& p) {
+                           ceph::buffer::list::contiguous_appender& p) {
     v.encode_nohead(p);
   }
   static void decode_nohead(size_t n, interval_set<T,Map>& v,
-                           bufferptr::const_iterator& p) {
+                           ceph::buffer::ptr::const_iterator& p) {
     v.decode_nohead(n, p);
   }
 };
@@ -767,13 +767,11 @@ struct denc_traits<interval_set<T,Map>> {
 template<class T, typename Map>
 inline std::ostream& operator<<(std::ostream& out, const interval_set<T,Map> &s) {
   out << "[";
-  const char *prequel = "";
-  for (typename interval_set<T,Map>::const_iterator i = s.begin();
-       i != s.end();
-       ++i)
-  {
-    out << prequel << i.get_start() << "~" << i.get_len();
-    prequel = ",";
+  bool first = true;
+  for (const auto& [start, len] : s) {
+    if (!first) out << ",";
+    out << start << "~" << len;
+    first = false;
   }
   out << "]";
   return out;