]> git-server-git.apps.pok.os.sepia.ceph.com Git - ceph.git/commitdiff
crimson/onode-staged-tree: fix insert_stage calculation
authorYingxin Cheng <yingxin.cheng@intel.com>
Fri, 25 Sep 2020 07:57:44 +0000 (15:57 +0800)
committerYingxin Cheng <yingxin.cheng@intel.com>
Tue, 1 Dec 2020 04:50:54 +0000 (12:50 +0800)
Fix incorrect insert_stage calculation when insert into the front of
leaf node.

Signed-off-by: Yingxin Cheng <yingxin.cheng@intel.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_impl.h
src/crimson/os/seastore/onode_manager/staged-fltree/node_layout.h
src/crimson/os/seastore/onode_manager/staged-fltree/node_types.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.cc

index 28db24a28f498ebd1b4435ab674c1a2123041204..36900606443a0209eeb044127655b49bb1333330 100644 (file)
@@ -125,13 +125,13 @@ node_future<std::pair<Ref<tree_cursor_t>, bool>> Node::insert(
     MatchHistory(), [this, c, &key, &value](auto& history) {
       return lower_bound_tracked(c, key, history
       ).safe_then([c, &key, &value, &history](auto result) {
-        if (result.match == MatchKindBS::EQ) {
+        if (result.match() == MatchKindBS::EQ) {
           return node_ertr::make_ready_future<std::pair<Ref<tree_cursor_t>, bool>>(
               std::make_pair(result.p_cursor, false));
         } else {
           auto leaf_node = result.p_cursor->get_leaf_node();
           return leaf_node->insert_value(
-              c, key, value, result.p_cursor->get_position(), history
+              c, key, value, result.p_cursor->get_position(), history, result.mstat
           ).safe_then([](auto p_cursor) {
             return node_ertr::make_ready_future<std::pair<Ref<tree_cursor_t>, bool>>(
                 std::make_pair(p_cursor, true));
@@ -564,7 +564,7 @@ LeafNode::lower_bound_tracked(
     cursor = get_or_track_cursor(result.position, index_key, result.p_value);
   }
   return node_ertr::make_ready_future<search_result_t>(
-      search_result_t{cursor, result.match()});
+      search_result_t{cursor, result.mstat});
 }
 
 node_future<> LeafNode::test_clone_root(
@@ -586,7 +586,8 @@ node_future<> LeafNode::test_clone_root(
 
 node_future<Ref<tree_cursor_t>> LeafNode::insert_value(
     context_t c, const key_hobj_t& key, const onode_t& value,
-    const search_position_t& pos, const MatchHistory& history) {
+    const search_position_t& pos, const MatchHistory& history,
+    match_stat_t mstat) {
 #ifndef NDEBUG
   if (pos.is_end()) {
     assert(impl->is_level_tail());
@@ -594,6 +595,7 @@ node_future<Ref<tree_cursor_t>> LeafNode::insert_value(
 #endif
   std::cout << "leaf insert at pos(" << pos << "), "
             << key << ", " << value << ", " << history
+            << ", mstat(" << (int)mstat << ")"
             << std::endl;
 #if 0
   std::cout << "before insert:" << std::endl;
@@ -602,7 +604,7 @@ node_future<Ref<tree_cursor_t>> LeafNode::insert_value(
 
   search_position_t insert_pos = pos;
   auto [insert_stage, insert_size] = impl->evaluate_insert(
-      key, value, history, insert_pos);
+      key, value, history, mstat, insert_pos);
   auto free_size = impl->free_size();
   if (free_size >= insert_size) {
     // insert
index 97f7cfad02d25a29ec1bb0047a3e3db9685094c2..328fe454bc5f138bf712670f94527f5e66a88304 100644 (file)
@@ -93,7 +93,12 @@ class Node
   struct search_result_t {
     bool is_end() const { return p_cursor->is_end(); }
     Ref<tree_cursor_t> p_cursor;
-    MatchKindBS match;
+    match_stat_t mstat;
+
+    MatchKindBS match() const {
+      assert(mstat >= MSTAT_MIN && mstat <= MSTAT_MAX);
+      return (mstat == MSTAT_EQ ? MatchKindBS::EQ : MatchKindBS::NE);
+    }
   };
 
   virtual ~Node();
@@ -283,7 +288,8 @@ class LeafNode final : public Node {
   LeafNode(LeafNodeImpl*, NodeImplURef&&);
   node_future<Ref<tree_cursor_t>> insert_value(
       context_t, const key_hobj_t&, const onode_t&,
-      const search_position_t&, const MatchHistory&);
+      const search_position_t&, const MatchHistory&,
+      match_stat_t mstat);
   static node_future<Ref<LeafNode>> allocate_root(context_t, RootNodeTracker&);
   friend class Node;
 
index a2027dd74c98549bb92309a59d8719410a09a7d0..d752bae70a016543e5d1acaf848a3cd59e477ab8 100644 (file)
@@ -125,7 +125,7 @@ class LeafNodeImpl : public NodeImpl {
       search_position_t&, key_view_t&, const onode_t**) const = 0;
   virtual std::tuple<match_stage_t, node_offset_t> evaluate_insert(
       const key_hobj_t&, const onode_t&,
-      const MatchHistory&, search_position_t&) const = 0;
+      const MatchHistory&, match_stat_t, search_position_t&) const = 0;
 
   struct fresh_impl_t {
     LeafNodeImplURef impl;
index dc98943b2e6a3d6b3a11fae188b194725832e091..eae101db1e26b44a6880ce5935ddf307c9a44ee0 100644 (file)
@@ -411,11 +411,12 @@ class NodeLayoutT final : public InternalNodeImpl, public LeafNodeImpl {
   }
 
   std::tuple<match_stage_t, node_offset_t> evaluate_insert(
-      const key_hobj_t& key, const onode_t& value, const MatchHistory& history,
+      const key_hobj_t& key, const onode_t& value,
+      const MatchHistory& history, match_stat_t mstat,
       search_position_t& insert_pos) const override {
     if constexpr (NODE_TYPE == node_type_t::LEAF) {
       return STAGE_T::evaluate_insert(
-          key, value, history, cast_down<STAGE>(insert_pos));
+          key, value, history, mstat, cast_down<STAGE>(insert_pos));
     } else {
       assert(false && "impossible path");
     }
index c1b4d190da58da279183946865e20fbc2aabee34..512dcaece94bacf15905a99b2766a1d21e70f3f3 100644 (file)
@@ -47,4 +47,15 @@ struct laddr_packed_t {
   laddr_t value;
 } __attribute__((packed));
 
+using match_stat_t = int8_t;
+constexpr match_stat_t MSTAT_END = -2; // index is search_position_t::end()
+constexpr match_stat_t MSTAT_EQ  = -1; // key == index
+constexpr match_stat_t MSTAT_NE0 =  0; // key == index [pool/shard crush ns/oid]; key < index [snap/gen]
+constexpr match_stat_t MSTAT_NE1 =  1; // key == index [pool/shard crush]; key < index [ns/oid]
+constexpr match_stat_t MSTAT_NE2 =  2; // key < index [pool/shard crush ns/oid] ||
+                                       // key == index [pool/shard]; key < index [crush]
+constexpr match_stat_t MSTAT_NE3 =  3; // key < index [pool/shard]
+constexpr match_stat_t MSTAT_MIN = MSTAT_END;
+constexpr match_stat_t MSTAT_MAX = MSTAT_NE3;
+
 }
index 0a6ba4c25b36548cb241e30ae9040e965474878f..3c4482613405c2c9046e1fe9592158c70185913e 100644 (file)
@@ -1091,7 +1091,7 @@ struct staged {
   template <typename T = std::tuple<match_stage_t, node_offset_t>>
   static std::enable_if_t<NODE_TYPE == node_type_t::LEAF, T> evaluate_insert(
       const full_key_t<KeyT::HOBJ>& key, const onode_t& value,
-      const MatchHistory& history, position_t& position) {
+      const MatchHistory& history, match_stat_t mstat, position_t& position) {
     match_stage_t insert_stage = STAGE_TOP;
     while (*history.get_by_stage(insert_stage) == MatchKindCMP::EQ) {
       assert(insert_stage != STAGE_BOTTOM && "insert conflict!");
@@ -1104,14 +1104,18 @@ struct staged {
         assert(insert_stage <= STAGE && "impossible insert stage");
       } else if (position == position_t::begin()) {
         // I must be short-circuited by staged::smallest_result()
-        // in staged::lower_bound()
-
+        // in staged::lower_bound(), so we need to rely on mstat instead
+        assert(mstat >= MSTAT_NE0 && mstat <= MSTAT_NE3);
+        if (mstat == MSTAT_NE0) {
+          insert_stage = STAGE_RIGHT;
+        } else if (mstat == MSTAT_NE1) {
+          insert_stage = STAGE_STRING;
+        } else {
+          insert_stage = STAGE_LEFT;
+        }
         // XXX(multi-type): need to upgrade node type before inserting an
         // incompatible index at front.
         assert(insert_stage <= STAGE && "incompatible insert");
-
-        // insert at begin and at the top stage
-        insert_stage = STAGE;
       } else {
         assert(insert_stage <= STAGE && "impossible insert stage");
         bool ret = compensate_insert_position_at(insert_stage, position);
index 4aef1ede1f5aca2866c5cf271b4bda42f400e33e..55144e10f0c8b58590eb2537ddfbe424d113f2c5 100644 (file)
@@ -315,25 +315,10 @@ template<> struct value_type<node_type_t::LEAF> { using type = onode_t; };
 template <node_type_t NODE_TYPE>
 using value_type_t = typename value_type<NODE_TYPE>::type;
 
-using match_stat_t = int8_t;
-constexpr match_stat_t MSTAT_END = -2; // index is search_position_t::end()
-constexpr match_stat_t MSTAT_EQ  = -1; // key == index
-constexpr match_stat_t MSTAT_NE0 =  0; // key == index [pool/shard crush ns/oid]; key < index [snap/gen]
-constexpr match_stat_t MSTAT_NE1 =  1; // key == index [pool/shard crush]; key < index [ns/oid]
-constexpr match_stat_t MSTAT_NE2 =  2; // key < index [pool/shard crush ns/oid] ||
-                                       // key == index [pool/shard]; key < index [crush]
-constexpr match_stat_t MSTAT_NE3 =  3; // key < index [pool/shard]
-constexpr match_stat_t MSTAT_MIN = MSTAT_END;
-constexpr match_stat_t MSTAT_MAX = MSTAT_NE3;
-
 template <node_type_t NODE_TYPE, match_stage_t STAGE>
 struct staged_result_t {
   using me_t = staged_result_t<NODE_TYPE, STAGE>;
   bool is_end() const { return position.is_end(); }
-  MatchKindBS match() const {
-    assert(mstat >= MSTAT_MIN && mstat <= MSTAT_MAX);
-    return (mstat == MSTAT_EQ ? MatchKindBS::EQ : MatchKindBS::NE);
-  }
 
   static me_t end() {
     return {staged_position_t<STAGE>::end(), nullptr, MSTAT_END};
index b5ccc60c23b631b6ceaba81fc701f6020dde8a7b..0e20f567ecdbccf88a2782dcc72d34e581087723 100644 (file)
@@ -105,7 +105,7 @@ Btree::contains(Transaction& t, const ghobject_t& obj) {
         // TODO: improve lower_bound()
         return root->lower_bound(get_context(t), key);
       }).safe_then([](auto result) {
-        return MatchKindBS::EQ == result.match;
+        return MatchKindBS::EQ == result.match();
       });
     }
   );
@@ -120,7 +120,7 @@ Btree::find(Transaction& t, const ghobject_t& obj) {
         // TODO: improve lower_bound()
         return root->lower_bound(get_context(t), key);
       }).safe_then([this](auto result) {
-        if (result.match == MatchKindBS::EQ) {
+        if (result.match() == MatchKindBS::EQ) {
           return Cursor(this, result.p_cursor);
         } else {
           return Cursor::make_end(this);