]> git.apps.os.sepia.ceph.com Git - ceph-ci.git/commitdiff
crimson/onode-staged-tree: add more validations
authorYingxin Cheng <yingxin.cheng@intel.com>
Fri, 25 Sep 2020 07:29:10 +0000 (15:29 +0800)
committerYingxin Cheng <yingxin.cheng@intel.com>
Tue, 1 Dec 2020 04:50:54 +0000 (12:50 +0800)
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_impl.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/test/crimson/seastore/onode_tree/test_staged_fltree.cc

index bd72c8f33d2997c5e61a11fe57dc29039f774dee..28db24a28f498ebd1b4435ab674c1a2123041204 100644 (file)
@@ -593,7 +593,8 @@ node_future<Ref<tree_cursor_t>> LeafNode::insert_value(
   }
 #endif
   std::cout << "leaf insert at pos(" << pos << "), "
-            << key << ", " << value << std::endl;
+            << key << ", " << value << ", " << history
+            << std::endl;
 #if 0
   std::cout << "before insert:" << std::endl;
   dump(std::cout) << std::endl;
index a01e73eff010b1ccf1a8ec6b85d28bf5292e0424..a2027dd74c98549bb92309a59d8719410a09a7d0 100644 (file)
@@ -36,6 +36,7 @@ class NodeImpl {
 
   virtual std::ostream& dump(std::ostream&) const = 0;
   virtual std::ostream& dump_brief(std::ostream&) const = 0;
+  virtual void validate_layout() const = 0;
 
   virtual void test_copy_to(NodeExtentMutable&) const = 0;
   virtual void test_set_tail(NodeExtentMutable&) = 0;
index e7bdadc11fb96fd756a2ee8c1a26bcc7dec00ad9..dc98943b2e6a3d6b3a11fae188b194725832e091 100644 (file)
@@ -145,6 +145,12 @@ class NodeLayoutT final : public InternalNodeImpl, public LeafNodeImpl {
     return os;
   }
 
+  void validate_layout() const override {
+#ifndef NDEBUG
+    STAGE_T::validate(extent.read());
+#endif
+  }
+
   void test_copy_to(NodeExtentMutable& to) const override {
     extent.test_copy_to(to);
   }
@@ -255,6 +261,7 @@ class NodeLayoutT final : public InternalNodeImpl, public LeafNodeImpl {
               << "), insert_stage=" << (int)insert_stage
               << ", insert_size=" << insert_size
               << std::endl << std::endl;
+    validate_layout();
     assert(get_key_view(insert_pos) == key);
     return ret;
   }
@@ -326,6 +333,7 @@ class NodeLayoutT final : public InternalNodeImpl, public LeafNodeImpl {
     assert(append_at.is_end());
     right_appender.wrap();
     right_impl.dump(std::cout) << std::endl;
+    right_impl.validate_layout();
 
     // mutate left node
     if (is_insert_left) {
@@ -341,6 +349,7 @@ class NodeLayoutT final : public InternalNodeImpl, public LeafNodeImpl {
       extent.split_replayable(split_at);
     }
     dump(std::cout) << std::endl;
+    validate_layout();
     assert(p_value);
 
     auto split_pos = normalize(split_at.get_pos());
index f0e2673a8ff1971a6e6fd67463688596a8f2043e..2334c4c349830ebf63faf3ccc498f7df44a4ccf2 100644 (file)
@@ -54,6 +54,12 @@ struct shard_pool_t {
 inline std::ostream& operator<<(std::ostream& os, const shard_pool_t& sp) {
   return os << (unsigned)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);
+}
 
 struct crush_t {
   bool operator==(const crush_t& x) const { return crush == x.crush; }
@@ -67,6 +73,9 @@ struct crush_t {
 inline std::ostream& operator<<(std::ostream& os, const crush_t& c) {
   return os << c.crush;
 }
+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 {
@@ -83,6 +92,13 @@ struct shard_pool_crush_t {
 inline std::ostream& operator<<(std::ostream& os, const shard_pool_crush_t& spc) {
   return os << spc.shard_pool << "," << spc.crush;
 }
+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 {
@@ -99,6 +115,12 @@ 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);
+}
 
 struct string_key_view_t {
   enum class Type {MIN, STR, MAX};
@@ -301,6 +323,12 @@ struct ns_oid_view_t {
 inline std::ostream& operator<<(std::ostream& os, const ns_oid_view_t& ns_oid) {
   return os << ns_oid.nspace << "," << ns_oid.oid;
 }
+inline MatchKindCMP compare_to(const ns_oid_view_t& l, const ns_oid_view_t& r) {
+  auto ret = compare_to(l.nspace, r.nspace);
+  if (ret != MatchKindCMP::EQ)
+    return ret;
+  return compare_to(l.oid, r.oid);
+}
 
 class key_hobj_t {
  public:
@@ -343,29 +371,33 @@ class key_hobj_t {
     return !operator==(o);
   }
 
+  std::ostream& dump(std::ostream& os) const {
+    os << "key_hobj(" << (unsigned)shard() << ","
+       << pool() << "," << crush() << "; ";
+    if (nspace().size() <= 12) {
+      os << "\"" << nspace() << "\",";
+    } else {
+      os << "\"" << nspace().substr(0, 4) << ".."
+         << nspace().substr(nspace().size() - 2, 2)
+         << "/" << nspace().size() << "B\",";
+    }
+    if (oid().size() <= 12) {
+      os << "\"" << oid() << "\"; ";
+    } else {
+      os << "\"" << oid().substr(0, 4) << ".."
+         << oid().substr(oid().size() - 2, 2)
+         << "/" << oid().size() << "B\"; ";
+    }
+    os << snap() << "," << gen() << ")";
+    return os;
+  }
+
  private:
   ns_oid_view_t::Type _dedup_type = ns_oid_view_t::Type::STR;
   ghobject_t ghobj;
 };
 inline std::ostream& operator<<(std::ostream& os, const key_hobj_t& key) {
-  os << "key_hobj(" << (unsigned)key.shard() << ","
-     << key.pool() << "," << key.crush() << "; ";
-  if (key.nspace().size() <= 12) {
-    os << "\"" << key.nspace() << "\",";
-  } else {
-    os << "\"" << key.nspace().substr(0, 4) << ".."
-       << key.nspace().substr(key.nspace().size() - 2, 2)
-       << "/" << key.nspace().size() << "B\",";
-  }
-  if (key.oid().size() <= 12) {
-    os << "\"" << key.oid() << "\"; ";
-  } else {
-    os << "\"" << key.oid().substr(0, 4) << ".."
-       << key.oid().substr(key.oid().size() - 2, 2)
-       << "/" << key.oid().size() << "B\"; ";
-  }
-  os << key.snap() << "," << key.gen() << ")";
-  return os;
+  return key.dump(os);
 }
 
 class key_view_t {
@@ -471,6 +503,31 @@ class key_view_t {
     p_snap_gen = &key;
   }
 
+  std::ostream& dump(std::ostream& os) const {
+    os << "key_view(";
+    if (has_shard_pool()) {
+      os << (unsigned)shard() << "," << pool() << ",";
+    } else {
+      os << "X,X,";
+    }
+    if (has_crush()) {
+      os << crush() << "; ";
+    } else {
+      os << "X; ";
+    }
+    if (has_ns_oid()) {
+      os << nspace() << "," << oid() << "; ";
+    } else {
+      os << "X,X; ";
+    }
+    if (has_snap_gen()) {
+      os << snap() << "," << gen() << ")";
+    } else {
+      os << "X,X)";
+    }
+    return os;
+  }
+
  private:
   const shard_pool_t* p_shard_pool = nullptr;
   const crush_t* p_crush = nullptr;
@@ -511,28 +568,7 @@ inline bool key_view_t::operator==(const full_key_t<KeyT::HOBJ>& o) const {
 }
 
 inline std::ostream& operator<<(std::ostream& os, const key_view_t& key) {
-  os << "key_view(";
-  if (key.has_shard_pool()) {
-    os << (unsigned)key.shard() << "," << key.pool() << ",";
-  } else {
-    os << "X,X,";
-  }
-  if (key.has_crush()) {
-    os << key.crush() << "; ";
-  } else {
-    os << "X; ";
-  }
-  if (key.has_ns_oid()) {
-    os << key.nspace() << "," << key.oid() << "; ";
-  } else {
-    os << "X,X; ";
-  }
-  if (key.has_snap_gen()) {
-    os << key.snap() << "," << key.gen() << ")";
-  } else {
-    os << "X,X)";
-  }
-  return os;
+  return key.dump(os);
 }
 
 template <KeyT Type>
index 984c6fce07a229ef59da69c9e1a9d5deb9549c71..0a6ba4c25b36548cb241e30ae9040e965474878f 100644 (file)
@@ -1276,6 +1276,25 @@ struct staged {
     return os;
   }
 
+  static void validate(const container_t& container) {
+    auto iter = iterator_t(container);
+    assert(!iter.is_end());
+    auto key = iter.get_key();
+    do {
+      if constexpr (!IS_BOTTOM) {
+        auto nxt_container = iter.get_nxt_container();
+        NXT_STAGE_T::validate(nxt_container);
+      }
+      if (iter.is_last()) {
+        break;
+      } else {
+        ++iter;
+        assert(compare_to(key, iter.get_key()) == MatchKindCMP::NE);
+        key = iter.get_key();
+      }
+    } while (true);
+  }
+
   struct _BaseEmpty {};
   class _BaseWithNxtIterator {
    protected:
index b900d666a79b3ad24da9f4d759fa9e9f96036c24..4aef1ede1f5aca2866c5cf271b4bda42f400e33e 100644 (file)
@@ -69,10 +69,36 @@ struct MatchHistory {
     const_cast<std::optional<MatchKindCMP>&>(get<STAGE>()) = match;
   }
 
+  std::ostream& dump(std::ostream& os) const {
+    os << "history(";
+    dump_each(os, left_match) << ", ";
+    dump_each(os, string_match) << ", ";
+    dump_each(os, right_match) << ")";
+    return os;
+  }
+
+  std::ostream& dump_each(
+      std::ostream& os, const std::optional<MatchKindCMP>& match) const {
+    if (!match.has_value()) {
+      return os << "--";
+    } else if (*match == MatchKindCMP::NE) {
+      return os << "NE";
+    } else if (*match == MatchKindCMP::EQ) {
+      return os << "EQ";
+    } else if (*match == MatchKindCMP::PO) {
+      return os << "PO";
+    } else {
+      assert(false && "impossble path");
+    }
+  }
+
   std::optional<MatchKindCMP> left_match;
   std::optional<MatchKindCMP> string_match;
   std::optional<MatchKindCMP> right_match;
 };
+inline std::ostream& operator<<(std::ostream& os, const MatchHistory& pos) {
+  return pos.dump(os);
+}
 
 template <match_stage_t STAGE>
 struct _check_PO_t {
index c94199bf5cd6c0e4286fb3f116556a197ea18634..6375d8bb71b81bdfe04f80eb34c9a76e47fef9c1 100644 (file)
@@ -657,6 +657,8 @@ class DummyChildPool {
       assert(false && "impossible path"); }
     std::ostream& dump_brief(std::ostream&) const override {
       assert(false && "impossible path"); }
+    void validate_layout() const override {
+      assert(false && "impossible path"); }
     void test_copy_to(NodeExtentMutable&) const override {
       assert(false && "impossible path"); }
     void test_set_tail(NodeExtentMutable&) override {