]> git.apps.os.sepia.ceph.com Git - ceph-ci.git/commitdiff
crimson/os: rewrite ordering using std::strong_ordering
authorKefu Chai <tchaikov@gmail.com>
Sat, 6 Aug 2022 10:26:44 +0000 (18:26 +0800)
committerKefu Chai <tchaikov@gmail.com>
Sat, 6 Aug 2022 11:07:57 +0000 (19:07 +0800)
the goals are

1. to use std::strong_ordering mechinary for better readability
   and maintainbility
2. to remove unnecessary abstraction
3. use concept for better error message and readability.

changes:

* replace MatchKindCMP with std::strong_ordering
* replace compare_to() with operator<=>
* introduce a concept `IsFullKey` so we can use it when developing
  generic facilities to operate on both materialized key or view.
* use `IsFullKey` in place of `KeyT` when appropriate

Signed-off-by: Kefu Chai <tchaikov@gmail.com>
src/crimson/os/seastore/onode_manager/staged-fltree/node.cc
src/crimson/os/seastore/onode_manager/staged-fltree/node.h
src/crimson/os/seastore/onode_manager/staged-fltree/node_layout.h
src/crimson/os/seastore/onode_manager/staged-fltree/stages/key_layout.h
src/crimson/os/seastore/onode_manager/staged-fltree/stages/stage.h
src/crimson/os/seastore/onode_manager/staged-fltree/stages/stage_types.h
src/crimson/os/seastore/onode_manager/staged-fltree/tree.h
src/test/crimson/seastore/onode_tree/test_staged_fltree.cc

index b35d003d360a324cb44a8aac0f2a11974474f73b..6a8f82feafdda1c098eab62b4a60c09567ff849b 100644 (file)
@@ -77,7 +77,7 @@ void tree_cursor_t::assert_next_to(
   } else if (is_tracked()) {
     auto key = get_key_view(magic);
     auto prv_key = prv.get_key_view(magic);
-    assert(key.compare_to(prv_key) == MatchKindCMP::GT);
+    assert(key > prv_key);
     if (ref_leaf_node == prv.ref_leaf_node) {
       position.assert_next_to(prv.position);
     } else {
@@ -103,32 +103,32 @@ tree_cursor_t::erase<true>(context_t, bool);
 template eagain_ifuture<Ref<tree_cursor_t>>
 tree_cursor_t::erase<false>(context_t, bool);
 
-MatchKindCMP tree_cursor_t::compare_to(
+std::strong_ordering tree_cursor_t::compare_to(
     const tree_cursor_t& o, value_magic_t magic) const
 {
   if (!is_tracked() && !o.is_tracked()) {
-    return MatchKindCMP::EQ;
+    return std::strong_ordering::equal;
   } else if (!is_tracked()) {
-    return MatchKindCMP::GT;
+    return std::strong_ordering::greater;
   } else if (!o.is_tracked()) {
-    return MatchKindCMP::LT;
+    return std::strong_ordering::less;
   }
 
   assert(is_tracked() && o.is_tracked());
   // all tracked cursors are singletons
   if (this == &o) {
-    return MatchKindCMP::EQ;
+    return std::strong_ordering::equal;
   }
 
-  MatchKindCMP ret;
+  std::strong_ordering ret = std::strong_ordering::equal;
   if (ref_leaf_node == o.ref_leaf_node) {
-    ret = position.compare_to(o.position);
+    ret = position <=> o.position;
   } else {
     auto key = get_key_view(magic);
     auto o_key = o.get_key_view(magic);
-    ret = key.compare_to(o_key);
+    ret = key <=> o_key;
   }
-  assert(ret != MatchKindCMP::EQ);
+  assert(ret != 0);
   return ret;
 }
 
@@ -259,7 +259,7 @@ void tree_cursor_t::Cache::validate_is_latest(const search_position_t& pos) cons
 
   auto [_key_view, _p_value_header] = ref_leaf_node->get_kv(pos);
   assert(p_node_base == ref_leaf_node->read());
-  assert(key_view->compare_to(_key_view) == MatchKindCMP::EQ);
+  assert(key_view ==_key_view);
   assert(p_value_header == _p_value_header);
 #endif
 }
@@ -1465,7 +1465,7 @@ eagain_ifuture<Ref<InternalNode>> InternalNode::insert_or_split(
   // XXX: check the insert_child is unlinked from this node
 #ifndef NDEBUG
   auto _insert_key = *insert_child->impl->get_pivot_index();
-  assert(insert_key.compare_to(_insert_key) == MatchKindCMP::EQ);
+  assert(insert_key == _insert_key);
 #endif
   auto insert_value = insert_child->impl->laddr();
   auto insert_pos = pos;
@@ -1730,7 +1730,7 @@ void InternalNode::validate_child(const Node& child) const
     key_view_t index_key;
     const laddr_packed_t* p_child_addr;
     impl->get_slot(child_pos, &index_key, &p_child_addr);
-    assert(index_key.compare_to(*child.impl->get_pivot_index()) == MatchKindCMP::EQ);
+    assert(index_key == *child.impl->get_pivot_index());
     assert(p_child_addr->value == child.impl->laddr());
   }
   // XXX(multi-type)
@@ -1752,7 +1752,7 @@ void InternalNode::validate_child_inconsistent(const Node& child) const
   const laddr_packed_t* p_value;
   impl->get_slot(child_pos, &current_key, &p_value);
   key_view_t new_key = *child.impl->get_pivot_index();
-  assert(current_key.compare_to(new_key) != MatchKindCMP::EQ);
+  assert(current_key != new_key);
   assert(p_value->value == child.impl->laddr());
 #endif
 }
@@ -2184,7 +2184,7 @@ void LeafNode::validate_cursor(const tree_cursor_t& cursor) const
   // behaviors.
   auto [key, p_value_header] = get_kv(cursor.get_position());
   auto magic = p_value_header->magic;
-  assert(key.compare_to(cursor.get_key_view(magic)) == MatchKindCMP::EQ);
+  assert(key == cursor.get_key_view(magic));
   assert(p_value_header == cursor.read_value_header(magic));
 #endif
 }
index 51e8c54085f8b03650d7038fa8de10e102e8cd89..4ba1d5b5887b61f9c45775ade792043c41621350 100644 (file)
@@ -3,6 +3,7 @@
 
 #pragma once
 
+#include <compare>
 #include <map>
 #include <memory>
 #include <ostream>
@@ -123,7 +124,7 @@ class tree_cursor_t final
   template <bool FORCE_MERGE = false>
   eagain_ifuture<Ref<tree_cursor_t>> erase(context_t, bool get_next);
 
-  MatchKindCMP compare_to(const tree_cursor_t&, value_magic_t) const;
+  std::strong_ordering compare_to(const tree_cursor_t&, value_magic_t) const;
 
   // public to Value
 
@@ -274,11 +275,11 @@ class Node
     void validate_input_key(const key_hobj_t& key, value_magic_t magic) const {
 #ifndef NDEBUG
       if (match() == MatchKindBS::EQ) {
-        assert(key.compare_to(p_cursor->get_key_view(magic)) == MatchKindCMP::EQ);
+        assert(key == p_cursor->get_key_view(magic));
       } else {
         assert(match() == MatchKindBS::NE);
         if (p_cursor->is_tracked()) {
-          assert(key.compare_to(p_cursor->get_key_view(magic)) == MatchKindCMP::LT);
+          assert(key < p_cursor->get_key_view(magic));
         } else if (p_cursor->is_end()) {
           // good
         } else {
index 2433816d06d4aa9433c2e352e9fb34aafc2bc430..5f3b35de05de5c81a0e5dec5789926cc5f821821 100644 (file)
@@ -523,7 +523,7 @@ class NodeLayoutT final : public InternalNodeImpl, public LeafNodeImpl {
         full_key_t<KeyT::VIEW> index;
         stage_t::template get_slot<true, false>(
             node_stage, result_raw.position, &index, nullptr);
-        assert(index.compare_to(*index_key) == MatchKindCMP::EQ);
+        assert(index == *index_key);
       }
 #endif
     } else {
@@ -545,10 +545,10 @@ class NodeLayoutT final : public InternalNodeImpl, public LeafNodeImpl {
       // currently only internal node checks mstat
       if constexpr (NODE_TYPE == node_type_t::INTERNAL) {
         if (result_raw.mstat == MSTAT_LT2) {
-          auto cmp = compare_to<KeyT::HOBJ>(
-              key, node_stage[result_raw.position.index].shard_pool);
-          assert(cmp != MatchKindCMP::GT);
-          if (cmp != MatchKindCMP::EQ) {
+          auto cmp =
+              key <=> node_stage[result_raw.position.index].shard_pool;
+          assert(cmp != std::strong_ordering::greater);
+          if (cmp != 0) {
             result_raw.mstat = MSTAT_LT3;
           }
         }
@@ -595,7 +595,7 @@ class NodeLayoutT final : public InternalNodeImpl, public LeafNodeImpl {
 #ifndef NDEBUG
     full_key_t<KeyT::VIEW> index;
     get_slot(insert_pos, &index, nullptr);
-    assert(index.compare_to(key) == MatchKindCMP::EQ);
+    assert(index == key);
 #endif
     return ret;
   }
@@ -775,14 +775,14 @@ class NodeLayoutT final : public InternalNodeImpl, public LeafNodeImpl {
 #ifndef NDEBUG
       full_key_t<KeyT::VIEW> index;
       get_slot(_insert_pos, &index, nullptr);
-      assert(index.compare_to(key) == MatchKindCMP::EQ);
+      assert(index == key);
 #endif
     } else {
       SUBDEBUG(seastore_onode, "-- left trim ...");
 #ifndef NDEBUG
       full_key_t<KeyT::VIEW> index;
       right_impl.get_slot(_insert_pos, &index, nullptr);
-      assert(index.compare_to(key) == MatchKindCMP::EQ);
+      assert(index == key);
 #endif
       extent.split_replayable(split_at);
     }
index 93176a8fd4046d127c53e37cde0897b02639418f..5309e9a111b840ce3781a6659ff0fab1ece76f0c 100644 (file)
@@ -57,10 +57,7 @@ struct node_offset_packed_t {
 
 // TODO: consider alignments
 struct shard_pool_t {
-  bool operator==(const shard_pool_t& x) const {
-    return (shard == x.shard && pool() == x.pool());
-  }
-  bool operator!=(const shard_pool_t& x) const { return !(*this == x); }
+  auto operator<=>(const shard_pool_t&) const = default;
 
   pool_t pool() const { return _pool; }
 
@@ -73,17 +70,10 @@ struct shard_pool_t {
 inline std::ostream& operator<<(std::ostream& os, const shard_pool_t& sp) {
   return os << (int)sp.shard << "," << sp.pool();
 }
-inline MatchKindCMP compare_to(const shard_pool_t& l, const shard_pool_t& r) {
-  auto ret = toMatchKindCMP(l.shard, r.shard);
-  if (ret != MatchKindCMP::EQ)
-    return ret;
-  return toMatchKindCMP(l.pool(), r.pool());
-}
 
 // Note: this is the reversed version of the object hash
 struct crush_t {
-  bool operator==(const crush_t& x) const { return crush == x.crush; }
-  bool operator!=(const crush_t& x) const { return !(*this == x); }
+  auto operator<=>(const crush_t&) const = default;
 
   template <KeyT KT>
   static crush_t from_key(const full_key_t<KT>& key);
@@ -93,15 +83,9 @@ struct crush_t {
 inline std::ostream& operator<<(std::ostream& os, const crush_t& c) {
   return os << "0x" << std::hex << c.crush << std::dec;
 }
-inline MatchKindCMP compare_to(const crush_t& l, const crush_t& r) {
-  return toMatchKindCMP(l.crush, r.crush);
-}
 
 struct shard_pool_crush_t {
-  bool operator==(const shard_pool_crush_t& x) const {
-    return (shard_pool == x.shard_pool && crush == x.crush);
-  }
-  bool operator!=(const shard_pool_crush_t& x) const { return !(*this == x); }
+  auto operator<=>(const shard_pool_crush_t&) const = default;
 
   template <KeyT KT>
   static shard_pool_crush_t from_key(const full_key_t<KT>& key);
@@ -112,19 +96,9 @@ struct shard_pool_crush_t {
 inline std::ostream& operator<<(std::ostream& os, const shard_pool_crush_t& spc) {
   return os << spc.shard_pool << ",0x" << std::hex << spc.crush << std::dec;
 }
-inline MatchKindCMP compare_to(
-    const shard_pool_crush_t& l, const shard_pool_crush_t& r) {
-  auto ret = compare_to(l.shard_pool, r.shard_pool);
-  if (ret != MatchKindCMP::EQ)
-    return ret;
-  return compare_to(l.crush, r.crush);
-}
 
 struct snap_gen_t {
-  bool operator==(const snap_gen_t& x) const {
-    return (snap == x.snap && gen == x.gen);
-  }
-  bool operator!=(const snap_gen_t& x) const { return !(*this == x); }
+  auto operator<=>(const snap_gen_t&) const = default;
 
   template <KeyT KT>
   static snap_gen_t from_key(const full_key_t<KT>& key);
@@ -135,12 +109,6 @@ struct snap_gen_t {
 inline std::ostream& operator<<(std::ostream& os, const snap_gen_t& sg) {
   return os << sg.snap << "," << sg.gen;
 }
-inline MatchKindCMP compare_to(const snap_gen_t& l, const snap_gen_t& r) {
-  auto ret = toMatchKindCMP(l.snap, r.snap);
-  if (ret != MatchKindCMP::EQ)
-    return ret;
-  return toMatchKindCMP(l.gen, r.gen);
-}
 
 /**
  * string_key_view_t
@@ -317,7 +285,19 @@ class string_view_masked_t {
       return false;
     return (memcmp(view.data(), x.view.data(), size()) == 0);
   }
-  bool operator!=(const string_view_masked_t& x) const { return !(*this == x); }
+  auto operator<=>(std::string_view rhs) const {
+    using Type = string_view_masked_t::Type;
+    assert(string_key_view_t::is_valid_size(rhs.size()));
+    auto lhs_type = get_type();
+    if (lhs_type == Type::MIN) {
+      return std::strong_ordering::less;
+    } else if (lhs_type == Type::MAX) {
+      return std::strong_ordering::greater;
+    } else { // r_type == Type::STR
+      assert(string_key_view_t::is_valid_size(size()));
+      return to_string_view() <=> rhs;
+    }
+  }
   void encode(ceph::bufferlist& bl) const {
     if (get_type() == Type::MIN) {
       ceph::encode(string_key_view_t::MARKER_MIN, bl);
@@ -351,38 +331,24 @@ class string_view_masked_t {
   Type type;
   std::string_view view;
 };
-inline MatchKindCMP compare_to(const string_view_masked_t& l, const string_view_masked_t& r) {
+
+inline auto operator<=>(const string_view_masked_t& l, const string_view_masked_t& r) {
   using Type = string_view_masked_t::Type;
   auto l_type = l.get_type();
   auto r_type = r.get_type();
   if (l_type == Type::STR && r_type == Type::STR) {
     assert(string_key_view_t::is_valid_size(l.size()));
     assert(string_key_view_t::is_valid_size(r.size()));
-    return toMatchKindCMP(l.to_string_view(), r.to_string_view());
+    return l.to_string_view() <=> r.to_string_view();
   } else if (l_type == r_type) {
-    return MatchKindCMP::EQ;
+    return std::strong_ordering::equal;
   } else if (l_type == Type::MIN || r_type == Type::MAX) {
-    return MatchKindCMP::LT;
+    return std::strong_ordering::less;
   } else { // l_type == Type::MAX || r_type == Type::MIN
-    return MatchKindCMP::GT;
+    return std::strong_ordering::greater;
   }
 }
-inline MatchKindCMP compare_to(std::string_view l, const string_view_masked_t& r) {
-  using Type = string_view_masked_t::Type;
-  assert(string_key_view_t::is_valid_size(l.size()));
-  auto r_type = r.get_type();
-  if (r_type == Type::MIN) {
-    return MatchKindCMP::GT;
-  } else if (r_type == Type::MAX) {
-    return MatchKindCMP::LT;
-  } else { // r_type == Type::STR
-    assert(string_key_view_t::is_valid_size(r.size()));
-    return toMatchKindCMP(l, r.to_string_view());
-  }
-}
-inline MatchKindCMP compare_to(const string_view_masked_t& l, std::string_view r) {
-  return reverse(compare_to(r, l));
-}
+
 inline std::ostream& operator<<(std::ostream& os, const string_view_masked_t& masked) {
   using Type = string_view_masked_t::Type;
   auto type = masked.get_type();
@@ -430,7 +396,6 @@ struct ns_oid_view_t {
     return (string_view_masked_t{nspace} == string_view_masked_t{x.nspace} &&
             string_view_masked_t{oid} == string_view_masked_t{x.oid});
   }
-  bool operator!=(const ns_oid_view_t& x) const { return !(*this == x); }
 
   void reset_to(const char* origin_base,
                 const char* new_base,
@@ -468,13 +433,11 @@ inline std::ostream& operator<<(std::ostream& os, const ns_oid_view_t& ns_oid) {
   return os << string_view_masked_t{ns_oid.nspace} << ","
             << string_view_masked_t{ns_oid.oid};
 }
-inline MatchKindCMP compare_to(const ns_oid_view_t& l, const ns_oid_view_t& r) {
-  auto ret = compare_to(string_view_masked_t{l.nspace},
-                        string_view_masked_t{r.nspace});
-  if (ret != MatchKindCMP::EQ)
+inline auto operator<=>(const ns_oid_view_t& l, const ns_oid_view_t& r) {
+  auto ret = (string_view_masked_t{l.nspace} <=> string_view_masked_t{r.nspace});
+  if (ret != 0)
     return ret;
-  return compare_to(string_view_masked_t{l.oid},
-                    string_view_masked_t{r.oid});
+  return string_view_masked_t{l.oid} <=> string_view_masked_t{r.oid};
 }
 
 inline const ghobject_t _MIN_OID() {
@@ -560,9 +523,6 @@ class key_hobj_t {
     return ghobj.generation;
   }
 
-  MatchKindCMP compare_to(const full_key_t<KeyT::VIEW>&) const;
-  MatchKindCMP compare_to(const full_key_t<KeyT::HOBJ>&) const;
-
   std::ostream& dump(std::ostream& os) const {
     os << "key_hobj(" << (int)shard() << ","
        << pool() << ",0x" << std::hex << crush() << std::dec << "; "
@@ -657,9 +617,6 @@ class key_view_t {
     return snap_gen_packed().gen;
   }
 
-  MatchKindCMP compare_to(const full_key_t<KeyT::VIEW>&) const;
-  MatchKindCMP compare_to(const full_key_t<KeyT::HOBJ>&) const;
-
   /**
    * key_view_t specific interfaces
    */
@@ -787,92 +744,82 @@ void encode_key(const full_key_t<KT>& key, ceph::bufferlist& bl) {
   ceph::encode(key.gen(), bl);
 }
 
-template <KeyT TypeL, KeyT TypeR>
-MatchKindCMP compare_full_key(
-    const full_key_t<TypeL>& l, const full_key_t<TypeR>& r) {
-  auto ret = toMatchKindCMP(l.shard(), r.shard());
-  if (ret != MatchKindCMP::EQ)
-    return ret;
-  ret = toMatchKindCMP(l.pool(), r.pool());
-  if (ret != MatchKindCMP::EQ)
+template<typename T>
+concept IsFullKey = std::same_as<T, key_hobj_t> || std::same_as<T, key_view_t>;
+
+template<IsFullKey LHS, IsFullKey RHS>
+std::strong_ordering operator<=>(const LHS& lhs, const RHS& rhs) noexcept {
+  auto ret = lhs.shard() <=> rhs.shard();
+  if (ret != 0)
     return ret;
-  ret = toMatchKindCMP(l.crush(), r.crush());
-  if (ret != MatchKindCMP::EQ)
+  ret = lhs.pool() <=> rhs.pool();
+  if (ret != 0)
+     return ret;
+  ret = lhs.crush() <=> rhs.crush();
+  if (ret != 0)
     return ret;
-  ret = toMatchKindCMP(l.nspace(), r.nspace());
-  if (ret != MatchKindCMP::EQ)
+  ret = lhs.nspace() <=> rhs.nspace();
+  if (ret != 0)
     return ret;
-  ret = toMatchKindCMP(l.oid(), r.oid());
-  if (ret != MatchKindCMP::EQ)
+  ret = lhs.oid() <=> rhs.oid();
+  if (ret != 0)
     return ret;
-  ret = toMatchKindCMP(l.snap(), r.snap());
-  if (ret != MatchKindCMP::EQ)
+  ret = lhs.snap() <=> rhs.snap();
+  if (ret != 0)
     return ret;
-  return toMatchKindCMP(l.gen(), r.gen());
-}
-
-inline MatchKindCMP key_hobj_t::compare_to(
-    const full_key_t<KeyT::VIEW>& o) const {
-  return compare_full_key<KeyT::HOBJ, KeyT::VIEW>(*this, o);
-}
-inline MatchKindCMP key_hobj_t::compare_to(
-    const full_key_t<KeyT::HOBJ>& o) const {
-  return compare_full_key<KeyT::HOBJ, KeyT::HOBJ>(*this, o);
-}
-inline MatchKindCMP key_view_t::compare_to(
-    const full_key_t<KeyT::VIEW>& o) const {
-  return compare_full_key<KeyT::VIEW, KeyT::VIEW>(*this, o);
-}
-inline MatchKindCMP key_view_t::compare_to(
-    const full_key_t<KeyT::HOBJ>& o) const {
-  return compare_full_key<KeyT::VIEW, KeyT::HOBJ>(*this, o);
+  return lhs.gen() <=> rhs.gen();
 }
 
 template <KeyT KT>
 bool is_valid_key(const full_key_t<KT>& key) {
-  return key.compare_to(key_hobj_t(ghobject_t())) == MatchKindCMP::GT &&
-         key.compare_to(key_hobj_t(ghobject_t::get_max())) == MatchKindCMP::LT;
+  return (key > key_hobj_t(ghobject_t()) &&
+          key < key_hobj_t(ghobject_t::get_max()));
 }
 
 inline std::ostream& operator<<(std::ostream& os, const key_view_t& key) {
   return key.dump(os);
 }
 
-template <KeyT Type>
-MatchKindCMP compare_to(const full_key_t<Type>& key, const shard_pool_t& target) {
-  auto ret = toMatchKindCMP(key.shard(), target.shard);
-  if (ret != MatchKindCMP::EQ)
+template <IsFullKey T>
+auto operator<=>(const T& key, const shard_pool_t& target) {
+  auto ret = key.shard() <=> target.shard;
+  if (ret != 0)
     return ret;
-  return toMatchKindCMP(key.pool(), target.pool());
+  return key.pool() <=> target.pool();
 }
 
-template <KeyT Type>
-MatchKindCMP compare_to(const full_key_t<Type>& key, const crush_t& target) {
-  return toMatchKindCMP(key.crush(), target.crush);
+template <IsFullKey T>
+auto operator<=>(const T& key, const crush_t& target) {
+  return key.crush() <=> target.crush;
 }
 
-template <KeyT Type>
-MatchKindCMP compare_to(const full_key_t<Type>& key, const shard_pool_crush_t& target) {
-  auto ret = compare_to<Type>(key, target.shard_pool);
-  if (ret != MatchKindCMP::EQ)
+template <IsFullKey T>
+auto operator<=>(const T& key, const shard_pool_crush_t& target) {
+  auto ret = key <=> target.shard_pool;
+  if (ret != 0)
     return ret;
-  return compare_to<Type>(key, target.crush);
+  return key <=> target.crush;
 }
 
-template <KeyT Type>
-MatchKindCMP compare_to(const full_key_t<Type>& key, const ns_oid_view_t& target) {
-  auto ret = compare_to(key.nspace(), string_view_masked_t{target.nspace});
-  if (ret != MatchKindCMP::EQ)
+template <IsFullKey T>
+auto operator<=>(const T& key, const ns_oid_view_t& target) {
+  auto ret = key.nspace() <=> string_view_masked_t{target.nspace};
+  if (ret != 0)
     return ret;
-  return compare_to(key.oid(), string_view_masked_t{target.oid});
+  return key.oid() <=> string_view_masked_t{target.oid};
 }
 
-template <KeyT Type>
-MatchKindCMP compare_to(const full_key_t<Type>& key, const snap_gen_t& target) {
-  auto ret = toMatchKindCMP(key.snap(), target.snap);
-  if (ret != MatchKindCMP::EQ)
+template <IsFullKey T>
+auto operator<=>(const T& key, const snap_gen_t& target) {
+  auto ret = key.snap() <=> target.snap;
+  if (ret != 0)
     return ret;
-  return toMatchKindCMP(key.gen(), target.gen);
+  return key.gen() <=> target.gen;
+}
+
+template <IsFullKey LHS, typename RHS>
+bool operator==(LHS lhs, RHS rhs) {
+  return lhs <=> rhs == 0;
 }
 
 template <KeyT KT>
index 4ea88cadf753dfd7dd228fb353b6ecea1a388a45..0ccc4ce74dd809e455d7c0041eb931a494bd7f11 100644 (file)
@@ -4,6 +4,7 @@
 #pragma once
 
 #include <cassert>
+#include <compare>
 #include <optional>
 #include <ostream>
 #include <sstream>
@@ -30,10 +31,10 @@ search_result_bs_t binary_search(
     auto mid = total >> 1;
     // do not copy if return value is reference
     decltype(f_get_key(mid)) target = f_get_key(mid);
-    auto match = compare_to<KeyT::HOBJ>(key, target);
-    if (match == MatchKindCMP::LT) {
+    auto match = key <=> target;
+    if (match == std::strong_ordering::less) {
       end = mid;
-    } else if (match == MatchKindCMP::GT) {
+    } else if (match == std::strong_ordering::greater) {
       begin = mid + 1;
     } else {
       return {mid, MatchKindBS::EQ};
@@ -93,17 +94,17 @@ inline void assert_mstat(
    case MSTAT_EQ:
     break;
    case MSTAT_LT0:
-    assert(compare_to<KeyT::HOBJ>(key, index.snap_gen_packed()) == MatchKindCMP::LT);
+    assert(key < index.snap_gen_packed());
     break;
    case MSTAT_LT1:
-    assert(compare_to<KeyT::HOBJ>(key, index.ns_oid_view()) == MatchKindCMP::LT);
+    assert(key < index.ns_oid_view());
     break;
    case MSTAT_LT2:
     if (index.has_shard_pool()) {
-      assert(compare_to<KeyT::HOBJ>(key, shard_pool_crush_t{
-               index.shard_pool_packed(), index.crush_packed()}) == MatchKindCMP::LT);
+      assert((key < shard_pool_crush_t{
+               index.shard_pool_packed(), index.crush_packed()}));
     } else {
-      assert(compare_to<KeyT::HOBJ>(key, index.crush_packed()) == MatchKindCMP::LT);
+      assert(key < index.crush_packed());
     }
     break;
    default:
@@ -112,19 +113,19 @@ inline void assert_mstat(
   // key == index ...
   switch (mstat) {
    case MSTAT_EQ:
-    assert(compare_to<KeyT::HOBJ>(key, index.snap_gen_packed()) == MatchKindCMP::EQ);
+    assert(key == index.snap_gen_packed());
    case MSTAT_LT0:
     if (!index.has_ns_oid())
       break;
     assert(index.ns_oid_view().type() == ns_oid_view_t::Type::MAX ||
-           compare_to<KeyT::HOBJ>(key, index.ns_oid_view()) == MatchKindCMP::EQ);
+           key == index.ns_oid_view());
    case MSTAT_LT1:
     if (!index.has_crush())
       break;
-    assert(compare_to<KeyT::HOBJ>(key, index.crush_packed()) == MatchKindCMP::EQ);
+    assert(key == index.crush_packed());
     if (!index.has_shard_pool())
       break;
-    assert(compare_to<KeyT::HOBJ>(key, index.shard_pool_packed()) == MatchKindCMP::EQ);
+    assert(key == index.shard_pool_packed());
    default:
     break;
   }
@@ -307,7 +308,7 @@ struct staged {
       if (exclude_last) {
         assert(end_index);
         --end_index;
-        assert(compare_to<KeyT::HOBJ>(key, container[end_index]) == MatchKindCMP::LT);
+        assert(key < container[end_index]);
       }
       auto ret = binary_search(key, _index, end_index,
           [this] (index_t index) { return container[index]; });
@@ -624,13 +625,13 @@ struct staged {
       assert(index() == 0);
       do {
         if (exclude_last && is_last()) {
-          assert(compare_to<KeyT::HOBJ>(key, get_key()) == MatchKindCMP::LT);
+          assert(key < get_key());
           return MatchKindBS::NE;
         }
-        auto match = compare_to<KeyT::HOBJ>(key, get_key());
-        if (match == MatchKindCMP::LT) {
+        auto match = key <=> get_key();
+        if (match == std::strong_ordering::less) {
           return MatchKindBS::NE;
-        } else if (match == MatchKindCMP::EQ) {
+        } else if (match == std::strong_ordering::equal) {
           return MatchKindBS::EQ;
         } else {
           if (container.has_next()) {
@@ -1058,16 +1059,16 @@ struct staged {
             if constexpr (STAGE == STAGE_STRING) {
               // TODO(cross-node string dedup)
               // test_key_equal = (iter.get_key().type() == ns_oid_view_t::Type::MIN);
-              auto cmp = compare_to<KeyT::HOBJ>(key, iter.get_key());
-              assert(cmp != MatchKindCMP::GT);
-              test_key_equal = (cmp == MatchKindCMP::EQ);
+              auto cmp = key <=> iter.get_key();
+              assert(cmp != std::strong_ordering::greater);
+              test_key_equal = (cmp == 0);
             } else {
-              auto cmp = compare_to<KeyT::HOBJ>(key, iter.get_key());
+              auto cmp = key <=> iter.get_key();
               // From history, key[stage] == parent[stage][index - 1]
               // which should be the smallest possible value for all
               // index[stage][*]
-              assert(cmp != MatchKindCMP::GT);
-              test_key_equal = (cmp == MatchKindCMP::EQ);
+              assert(cmp != std::strong_ordering::greater);
+              test_key_equal = (cmp == 0);
             }
             if (test_key_equal) {
               return nxt_lower_bound<GET_KEY>(key, iter, history, index_key);
@@ -1083,9 +1084,9 @@ struct staged {
         if constexpr (STAGE == STAGE_STRING) {
           // TODO(cross-node string dedup)
           // assert(iter.get_key().type() == ns_oid_view_t::Type::MAX);
-          assert(compare_to<KeyT::HOBJ>(key, iter.get_key()) == MatchKindCMP::EQ);
+          assert(key == iter.get_key());
         } else {
-          assert(compare_to<KeyT::HOBJ>(key, iter.get_key()) == MatchKindCMP::EQ);
+          assert(key == iter.get_key());
         }
         if constexpr (GET_KEY) {
           index_key->set(iter.get_key());
@@ -1170,8 +1171,8 @@ struct staged {
       assert(is_valid_index(index));
       // evaluate the current index
       iter.seek_at(index);
-      auto match = compare_to<KeyT::VIEW>(key, iter.get_key());
-      if (match == MatchKindCMP::EQ) {
+      auto match = key <=> iter.get_key();
+      if (match == 0) {
         if constexpr (IS_BOTTOM) {
           ceph_abort("insert conflict at current index!");
         } else {
@@ -1181,7 +1182,7 @@ struct staged {
               nxt_container, key, value, position.nxt, false);
         }
       } else {
-        assert(match == MatchKindCMP::LT);
+        assert(match == std::strong_ordering::less);
         if (index == 0) {
           // already the first index, so insert at the current index
           return {STAGE, insert_size<KeyT::VIEW>(key, value)};
@@ -1194,13 +1195,13 @@ struct staged {
     }
 
     // XXX(multi-type): when key is from a different type of node
-    auto match = compare_to<KeyT::VIEW>(key, iter.get_key());
-    if (match == MatchKindCMP::GT) {
+    auto match = key <=> iter.get_key();
+    if (match == std::strong_ordering::greater) {
       // key doesn't match both indexes, so insert at the current index
       ++index;
       return {STAGE, insert_size<KeyT::VIEW>(key, value)};
     } else {
-      assert(match == MatchKindCMP::EQ);
+      assert(match == std::strong_ordering::equal);
       if constexpr (IS_BOTTOM) {
         // ceph_abort?
         ceph_abort("insert conflict at the previous index!");
@@ -1470,7 +1471,7 @@ struct staged {
         break;
       } else {
         ++iter;
-        assert(compare_to(key, iter.get_key()) == MatchKindCMP::LT);
+        assert(key < iter.get_key());
         key = iter.get_key();
       }
     } while (true);
@@ -2348,8 +2349,8 @@ struct staged {
     auto r_iter = iterator_t(right_container);
     r_iter.seek_at(0);
     node_offset_t compensate = r_iter.header_size();
-    auto cmp = compare_to<KeyT::VIEW>(left_pivot_index, r_iter.get_key());
-    if (cmp == MatchKindCMP::EQ) {
+    auto cmp = left_pivot_index <=> r_iter.get_key();
+    if (cmp == std::strong_ordering::equal) {
       if constexpr (!IS_BOTTOM) {
         // the index is equal, compensate and look at the lower stage
         compensate += r_iter.size_to_nxt();
@@ -2361,7 +2362,7 @@ struct staged {
       } else {
         ceph_abort("impossible path: left_pivot_key == right_first_key");
       }
-    } else if (cmp == MatchKindCMP::LT) {
+    } else if (cmp == std::strong_ordering::less) {
       // ok, do merge here
       return {STAGE, compensate};
     } else {
index 94017bb60079f0bb6e48d8bc125d8851ffe9bef3..7480c9a051cc4bc70d171f1663695d40b78f951a 100644 (file)
@@ -149,21 +149,7 @@ struct staged_position_t {
     }
   }
 
-  MatchKindCMP compare_to(const me_t& o) const {
-    if (index > o.index) {
-      return MatchKindCMP::GT;
-    } else if (index < o.index) {
-      return MatchKindCMP::LT;
-    } else {
-      return nxt.compare_to(o.nxt);
-    }
-  }
-  bool operator>(const me_t& o) const { return (int)compare_to(o) > 0; }
-  bool operator>=(const me_t& o) const { return (int)compare_to(o) >= 0; }
-  bool operator<(const me_t& o) const { return (int)compare_to(o) < 0; }
-  bool operator<=(const me_t& o) const { return (int)compare_to(o) <= 0; }
-  bool operator==(const me_t& o) const { return (int)compare_to(o) == 0; }
-  bool operator!=(const me_t& o) const { return (int)compare_to(o) != 0; }
+  auto operator<=>(const me_t& o) const = default;
 
   void assert_next_to(const me_t& prv) const {
 #ifndef NDEBUG
@@ -251,21 +237,7 @@ struct staged_position_t<STAGE_BOTTOM> {
     return index;
   }
 
-  MatchKindCMP compare_to(const staged_position_t<STAGE_BOTTOM>& o) const {
-    if (index > o.index) {
-      return MatchKindCMP::GT;
-    } else if (index < o.index) {
-      return MatchKindCMP::LT;
-    } else {
-      return MatchKindCMP::EQ;
-    }
-  }
-  bool operator>(const me_t& o) const { return (int)compare_to(o) > 0; }
-  bool operator>=(const me_t& o) const { return (int)compare_to(o) >= 0; }
-  bool operator<(const me_t& o) const { return (int)compare_to(o) < 0; }
-  bool operator<=(const me_t& o) const { return (int)compare_to(o) <= 0; }
-  bool operator==(const me_t& o) const { return (int)compare_to(o) == 0; }
-  bool operator!=(const me_t& o) const { return (int)compare_to(o) != 0; }
+  auto operator<=>(const me_t&) const = default;
 
   me_t& operator-=(const me_t& o) {
     assert(is_valid_index(o.index));
index 73bf8c631993f888a88998d9a53a0fb2e9c35910..2f379c7d319325c4c6edab21693d61a852c00991 100644 (file)
@@ -95,12 +95,7 @@ class Btree {
           *p_tree->nm, p_tree->value_builder, p_cursor);
     }
 
-    bool operator>(const Cursor& o) const { return (int)compare_to(o) > 0; }
-    bool operator>=(const Cursor& o) const { return (int)compare_to(o) >= 0; }
-    bool operator<(const Cursor& o) const { return (int)compare_to(o) < 0; }
-    bool operator<=(const Cursor& o) const { return (int)compare_to(o) <= 0; }
-    bool operator==(const Cursor& o) const { return (int)compare_to(o) == 0; }
-    bool operator!=(const Cursor& o) const { return (int)compare_to(o) != 0; }
+    bool operator==(const Cursor& o) const { return operator<=>(o) == 0; }
 
     eagain_ifuture<Cursor> get_next(Transaction& t) {
       assert(!is_end());
@@ -146,7 +141,7 @@ class Btree {
     }
     Cursor(Btree* p_tree) : p_tree{p_tree} {}
 
-    MatchKindCMP compare_to(const Cursor& o) const {
+    std::strong_ordering operator<=>(const Cursor& o) const {
       assert(p_tree == o.p_tree);
       return p_cursor->compare_to(
           *o.p_cursor, p_tree->value_builder.get_header_magic());
index a1c743bca2b7cbd6b629e0ab63f16fde1d174af9..99e60878ddacb086f6d982f223e1870d0a180b63 100644 (file)
@@ -1193,7 +1193,7 @@ class DummyChildPool {
       // erase and merge
       [[maybe_unused]] auto pivot_key = node_to_split->get_pivot_key();
       logger().info("\n\nERASE-MERGE {}:", node_to_split->get_name());
-      assert(pivot_key.compare_to(key_hobj_t(key)) == MatchKindCMP::EQ);
+      assert(pivot_key == key_hobj_t(key));
       with_trans_intr(pool_clone.get_context().t, [&] (auto &t) {
         return node_to_split->merge(
           pool_clone.get_context(), std::move(node_to_split));