]> git.apps.os.sepia.ceph.com Git - ceph.git/commitdiff
crimson: use explicit, abstract interfaces for backfill's facades. 38392/head
authorRadoslaw Zarzynski <rzarzyns@redhat.com>
Wed, 2 Dec 2020 09:26:29 +0000 (10:26 +0100)
committerRadoslaw Zarzynski <rzarzyns@redhat.com>
Tue, 8 Dec 2020 13:14:09 +0000 (14:14 +0100)
Signed-off-by: Radoslaw Zarzynski <rzarzyns@redhat.com>
src/crimson/osd/backfill_facades.h
src/crimson/osd/backfill_state.cc
src/crimson/osd/backfill_state.h
src/crimson/osd/pg.h
src/crimson/osd/pg_recovery.cc
src/test/crimson/CMakeLists.txt
src/test/crimson/test_backfill.cc
src/test/crimson/test_backfill_facades.h [deleted file]

index 21b18a8b3b05f4b613becd95d7b39d8ac919e678..683dc6ea649484bc5c6ee09b6cc54bee933318e8 100644 (file)
@@ -9,47 +9,46 @@
 
 namespace crimson::osd {
 
-// PeeringFacade -- a facade (in the GoF-defined meaning) simplifying
-// the interface of PeeringState. The motivation is to have an inventory
-// of behaviour that must be provided by a unit test's mock.
-struct BackfillState::PeeringFacade {
+// PeeringFacade -- main implementation of the BackfillState::PeeringFacade
+// interface. We have the abstraction to decuple BackfillState from Peering
+// State, and thus cut depedencies in unit testing. The second implemention
+// is BackfillFixture::PeeringFacade and sits in test_backfill.cc.
+struct PeeringFacade final : BackfillState::PeeringFacade {
   PeeringState& peering_state;
 
-  decltype(auto) earliest_backfill() const {
+  hobject_t earliest_backfill() const override {
     return peering_state.earliest_backfill();
   }
 
-  decltype(auto) get_backfill_targets() const {
+  const std::set<pg_shard_t>& get_backfill_targets() const override {
     return peering_state.get_backfill_targets();
   }
 
-  decltype(auto) get_peer_last_backfill(pg_shard_t peer) const {
+  const hobject_t& get_peer_last_backfill(pg_shard_t peer) const override {
     return peering_state.get_peer_info(peer).last_backfill;
   }
 
-  decltype(auto) get_last_update() const {
+  const eversion_t& get_last_update() const override {
     return peering_state.get_info().last_update;
   }
 
-  decltype(auto) get_log_tail() const {
+  const eversion_t& get_log_tail() const override {
     return peering_state.get_info().log_tail;
   }
 
-  template <class... Args>
-  void scan_log_after(Args&&... args) const {
-    peering_state.get_pg_log().get_log().scan_log_after(
-      std::forward<Args>(args)...);
+  void scan_log_after(eversion_t v, scan_log_func_t f) const override {
+    peering_state.get_pg_log().get_log().scan_log_after(v, std::move(f));
   }
 
-  bool is_backfill_target(pg_shard_t peer) const {
+  bool is_backfill_target(pg_shard_t peer) const override {
     return peering_state.is_backfill_target(peer);
   }
   void update_complete_backfill_object_stats(const hobject_t &hoid,
-                                             const pg_stat_t &stats) {
-    return peering_state.update_complete_backfill_object_stats(hoid, stats);
+                                             const pg_stat_t &stats) override {
+    peering_state.update_complete_backfill_object_stats(hoid, stats);
   }
 
-  bool is_backfilling() const {
+  bool is_backfilling() const override {
     return peering_state.is_backfilling();
   }
 
@@ -61,10 +60,10 @@ struct BackfillState::PeeringFacade {
 // PGFacade -- a facade (in the GoF-defined meaning) simplifying the huge
 // interface of crimson's PG class. The motivation is to have an inventory
 // of behaviour that must be provided by a unit test's mock.
-struct BackfillState::PGFacade {
+struct PGFacade final : BackfillState::PGFacade {
   PG& pg;
 
-  decltype(auto) get_projected_last_update() const {
+  const eversion_t& get_projected_last_update() const override {
     return pg.projected_last_update;
   }
 
index 4a8b11f59769c1aab1cc068912efc428a1060dfe..fe4cb3288218cfc4f65e58c9e17e8a40c4de8b56 100644 (file)
@@ -5,11 +5,6 @@
 #include <boost/type_index.hpp>
 
 #include "crimson/osd/backfill_state.h"
-#ifndef BACKFILL_UNITTEST
-#include "crimson/osd/backfill_facades.h"
-#else
-#include "test/crimson/test_backfill_facades.h"
-#endif
 
 namespace {
   seastar::logger& logger() {
index e742fd10a9a0f3eca5fc5721b0c74126ffba64d9..00b111dc3810333d780dd92948d4d203f2e0ffa0 100644 (file)
@@ -308,6 +308,37 @@ struct BackfillState::BackfillListener {
   virtual ~BackfillListener() = default;
 };
 
+// PeeringFacade -- a facade (in the GoF-defined meaning) simplifying
+// the interface of PeeringState. The motivation is to have an inventory
+// of behaviour that must be provided by a unit test's mock.
+struct BackfillState::PeeringFacade {
+  virtual hobject_t earliest_backfill() const = 0;
+  virtual const std::set<pg_shard_t>& get_backfill_targets() const = 0;
+  virtual const hobject_t& get_peer_last_backfill(pg_shard_t peer) const = 0;
+  virtual const eversion_t& get_last_update() const = 0;
+  virtual const eversion_t& get_log_tail() const = 0;
+
+  // the performance impact of `std::function` has not been considered yet.
+  // If there is any proof (from e.g. profiling) about its significance, we
+  // can switch back to the template variant.
+  using scan_log_func_t = std::function<void(const pg_log_entry_t&)>;
+  virtual void scan_log_after(eversion_t, scan_log_func_t) const = 0;
+
+  virtual bool is_backfill_target(pg_shard_t peer) const = 0;
+  virtual void update_complete_backfill_object_stats(const hobject_t &hoid,
+                                             const pg_stat_t &stats) = 0;
+  virtual bool is_backfilling() const = 0;
+  virtual ~PeeringFacade() {}
+};
+
+// PGFacade -- a facade (in the GoF-defined meaning) simplifying the huge
+// interface of crimson's PG class. The motivation is to have an inventory
+// of behaviour that must be provided by a unit test's mock.
+struct BackfillState::PGFacade {
+  virtual const eversion_t& get_projected_last_update() const = 0;
+  virtual ~PGFacade() {}
+};
+
 class BackfillState::ProgressTracker {
   // TODO: apply_stat,
   enum class op_stage_t {
index f7db6ba6cda167f2f1e02cb7e780828e6ca8c628..35b5f01a94691aa51035334cd8308357dcecd90e 100644 (file)
@@ -670,7 +670,7 @@ private:
   friend class PeeringEvent;
   friend class RepRequest;
   friend class BackfillRecovery;
-  friend struct BackfillState::PGFacade;
+  friend struct PGFacade;
 private:
   seastar::future<bool> find_unfound() {
     return seastar::make_ready_future<bool>(true);
index cdf26274533bae71efbd27017f9fc2e1887f2c95..390449728cc81702434879da1fb97925c596903a 100644 (file)
@@ -523,8 +523,8 @@ void PGRecovery::on_backfill_reserved()
   using BackfillState = crimson::osd::BackfillState;
   backfill_state = std::make_unique<BackfillState>(
     *this,
-    std::make_unique<BackfillState::PeeringFacade>(pg->get_peering_state()),
-    std::make_unique<BackfillState::PGFacade>(
+    std::make_unique<crimson::osd::PeeringFacade>(pg->get_peering_state()),
+    std::make_unique<crimson::osd::PGFacade>(
       *static_cast<crimson::osd::PG*>(pg)));
   // yes, it's **not** backfilling yet. The PG_STATE_BACKFILLING
   // will be set after on_backfill_reserved() returns.
index 2882cc6e541640861970904cb5106aacc5cbfdf3..3dedce103f62f68fb366e54888072976eb725cbb 100644 (file)
@@ -5,7 +5,6 @@ add_executable(unittest-crimson-backfill
   ${PROJECT_SOURCE_DIR}/src/crimson/osd/backfill_state.cc
   ${PROJECT_SOURCE_DIR}/src/osd/recovery_types.cc)
 add_ceph_unittest(unittest-crimson-backfill)
-target_compile_definitions(unittest-crimson-backfill PRIVATE -DBACKFILL_UNITTEST)
 target_link_libraries(unittest-crimson-backfill crimson GTest::Main)
 
 add_executable(unittest-seastar-buffer
index 01f435fd41687f5f23d1475b1e1192e9f187effb..14309f9660659e099dbc35d6b6f7e60c49152991 100644 (file)
@@ -17,7 +17,6 @@
 #include "common/hobject.h"
 #include "crimson/osd/backfill_state.h"
 #include "osd/recovery_types.h"
-#include "test/crimson/test_backfill_facades.h"
 
 
 // The sole purpose is to convert from the string representation.
@@ -172,11 +171,19 @@ struct BackfillFixture::PeeringFacade
   : public crimson::osd::BackfillState::PeeringFacade {
   FakePrimary& backfill_source;
   std::map<pg_shard_t, FakeReplica>& backfill_targets;
+  // sorry, this is duplicative but that's the interface
+  std::set<pg_shard_t> backfill_targets_as_set;
 
   PeeringFacade(FakePrimary& backfill_source,
                 std::map<pg_shard_t, FakeReplica>& backfill_targets)
     : backfill_source(backfill_source),
       backfill_targets(backfill_targets) {
+    std::transform(
+      std::begin(backfill_targets), std::end(backfill_targets),
+      std::inserter(backfill_targets_as_set, std::end(backfill_targets_as_set)),
+      [](auto pair) {
+        return pair.first;
+      });
   }
 
   hobject_t earliest_backfill() const override {
@@ -186,15 +193,8 @@ struct BackfillFixture::PeeringFacade
     }
     return e;
   }
-  std::set<pg_shard_t> get_backfill_targets() const override {
-    std::set<pg_shard_t> result;
-    std::transform(
-      std::begin(backfill_targets), std::end(backfill_targets),
-      std::inserter(result, std::end(result)),
-      [](auto pair) {
-        return pair.first;
-      });
-    return result;
+  const std::set<pg_shard_t>& get_backfill_targets() const override {
+    return backfill_targets_as_set;
   }
   const hobject_t& get_peer_last_backfill(pg_shard_t peer) const override {
     return backfill_targets.at(peer).last_backfill;
@@ -205,8 +205,9 @@ struct BackfillFixture::PeeringFacade
   const eversion_t& get_log_tail() const override {
     return backfill_source.log_tail;
   }
-  template <class... Args>
-  void scan_log_after(Args&&... args) const {
+
+  void scan_log_after(eversion_t, scan_log_func_t) const override {
+    /* NOP */
   }
 
   bool is_backfill_target(pg_shard_t peer) const override {
diff --git a/src/test/crimson/test_backfill_facades.h b/src/test/crimson/test_backfill_facades.h
deleted file mode 100644 (file)
index d54d14c..0000000
+++ /dev/null
@@ -1,39 +0,0 @@
-// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
-// vim: ts=8 sw=2 smarttab
-
-#pragma once
-
-#include "crimson/osd/backfill_state.h"
-
-namespace crimson::osd {
-
-// PeeringFacade -- a facade (in the GoF-defined meaning) simplifying
-// the interface of PeeringState. The motivation is to have an inventory
-// of behaviour that must be provided by a unit test's mock.
-struct BackfillState::PeeringFacade {
-  virtual hobject_t earliest_backfill() const = 0;
-  virtual std::set<pg_shard_t> get_backfill_targets() const = 0;
-  virtual const hobject_t& get_peer_last_backfill(pg_shard_t peer) const = 0;
-  virtual const eversion_t& get_last_update() const = 0;
-  virtual const eversion_t& get_log_tail() const = 0;
-
-  template <class... Args>
-  void scan_log_after(Args&&... args) const {
-  }
-
-  virtual bool is_backfill_target(pg_shard_t peer) const = 0;
-  virtual void update_complete_backfill_object_stats(const hobject_t &hoid,
-                                             const pg_stat_t &stats) = 0;
-  virtual bool is_backfilling() const = 0;
-  virtual ~PeeringFacade() {}
-};
-
-// PGFacade -- a facade (in the GoF-defined meaning) simplifying the huge
-// interface of crimson's PG class. The motivation is to have an inventory
-// of behaviour that must be provided by a unit test's mock.
-struct BackfillState::PGFacade {
-  virtual const eversion_t& get_projected_last_update() const = 0;
-  virtual ~PGFacade() {}
-};
-
-} // namespace crimson::osd