]> git.apps.os.sepia.ceph.com Git - ceph-ci.git/commitdiff
crimson/common/errorator.h: add handle_error() method.
authorRadoslaw Zarzynski <rzarzyns@redhat.com>
Mon, 25 Nov 2019 13:36:36 +0000 (14:36 +0100)
committerRadoslaw Zarzynski <rzarzyns@redhat.com>
Thu, 28 Nov 2019 15:36:08 +0000 (16:36 +0100)
In contrast to `safe_then` it deals only with errors
and, on return, leaves the value type `future<ValueT>`
embodies unchanged.
While being basically a specialization of `safe_then`,
it's also a convenience method to squeeze boilerplate.

Signed-off-by: Radoslaw Zarzynski <rzarzyns@redhat.com>
src/crimson/common/errorator.h
src/crimson/osd/objclass.cc
src/crimson/osd/osd_meta.cc

index 17a95403fe6dcd255ebffe1b5b900361f7eccfe9..2c6f80e33d7043bd08bd4bbde125eb94169974e2 100644 (file)
@@ -544,6 +544,37 @@ private:
     template <class Func>
     void then(Func&&) = delete;
 
+    template <class ErrorVisitorT>
+    auto handle_error(ErrorVisitorT&& errfunc) {
+      static_assert((... && std::is_invocable_v<ErrorVisitorT,
+                                                AllowedErrors>),
+                    "provided Error Visitor is not exhaustive");
+      using return_errorator_t = make_errorator_t<
+        errorator<>,
+        std::decay_t<std::invoke_result_t<ErrorVisitorT, AllowedErrors>>...>;
+      using futurator_t = \
+        typename return_errorator_t::template futurize<::seastar::future<ValuesT...>>;
+      return this->then_wrapped(
+        [ errfunc = std::forward<ErrorVisitorT>(errfunc)
+        ] (auto&& future) mutable [[gnu::always_inline]] noexcept {
+          if (__builtin_expect(future.failed(), false)) {
+            return _safe_then_handle_errors<futurator_t>(
+              std::move(future), std::forward<ErrorVisitorT>(errfunc));
+          } else {
+            return typename futurator_t::type{ std::move(future) };
+          }
+        });
+    }
+    template <class ErrorFuncHead,
+              class... ErrorFuncTail>
+    auto handle_error(ErrorFuncHead&& error_func_head,
+                      ErrorFuncTail&&... error_func_tail) {
+      static_assert(sizeof...(ErrorFuncTail) > 0);
+      return this->handle_error(
+        composer(std::forward<ErrorFuncHead>(error_func_head),
+                 std::forward<ErrorFuncTail>(error_func_tail)...));
+    }
+
   private:
     // for ::crimson::do_for_each
     template <class Func>
index ef9336da1d7c31146d219453efc67d0101b3d819..da57b9c8a5cc6b01e013c874c49936d1ce798446 100644 (file)
@@ -25,11 +25,8 @@ static inline int execute_osd_op(cls_method_context_t hctx, OSDOp& op)
   // created for us by `seastar::async` in `::do_op_call()`.
   int ret = 0;
   using osd_op_errorator = crimson::osd::OpsExecuter::osd_op_errorator;
-  reinterpret_cast<crimson::osd::OpsExecuter*>(hctx)->execute_osd_op(op).safe_then(
-    [] {
-      // TODO: handle it nicer with `::handle_error()` in errorator
-      return seastar::now();
-    }, osd_op_errorator::all_same_way([&ret] (const std::error_code& err) {
+  reinterpret_cast<crimson::osd::OpsExecuter*>(hctx)->execute_osd_op(op).handle_error(
+    osd_op_errorator::all_same_way([&ret] (const std::error_code& err) {
       assert(err.value() > 0);
       ret = -err.value();
       return seastar::now();
index c608c8d3512207150774c52261f3acd169a11e4f..e7a1f06196442bd2550db9eead00df4e8515e330 100644 (file)
@@ -24,12 +24,8 @@ seastar::future<bufferlist> OSDMeta::load_map(epoch_t e)
 {
   return store->read(coll,
                      osdmap_oid(e), 0, 0,
-                     CEPH_OSD_OP_FLAG_FADVISE_WILLNEED).safe_then(
-    [] (auto&& bl) {
-      // TODO: introduce `::handle_error()` to errorated futures
-      // to avoid lambas like this one.
-      return bl;
-    }, crimson::ct_error::enoent::handle([e] {
+                     CEPH_OSD_OP_FLAG_FADVISE_WILLNEED).handle_error(
+    crimson::ct_error::enoent::handle([e] {
       throw std::runtime_error(fmt::format("read gave enoent on {}",
                                            osdmap_oid(e)));
     }));