]> git-server-git.apps.pok.os.sepia.ceph.com Git - ceph.git/commitdiff
crimson/common: let errorator's handlers to conditionally forward errors 45707/head
authorRadosław Zarzyński <rzarzyns@redhat.com>
Wed, 30 Mar 2022 13:02:20 +0000 (15:02 +0200)
committerRadosław Zarzyński <rzarzyns@redhat.com>
Wed, 30 Mar 2022 23:17:16 +0000 (01:17 +0200)
The use case is like the following one:

```diff
diff --git a/src/crimson/osd/replicated_recovery_backend.cc b/src/crimson/osd/replicated_recovery_backend.cc
index a96f1b8dd2b..055add2e407 100644
--- a/src/crimson/osd/replicated_recovery_backend.cc
+++ b/src/crimson/osd/replicated_recovery_backend.cc
@@ -516,10 +516,14 @@ ReplicatedRecoveryBackend::read_object_for_push_op(
       recovered_to = push_op->data_included.range_end();
     }
     return seastar::make_ready_future<uint64_t>(recovered_to);
-  }, PGBackend::read_errorator::all_same_way([](auto e) {
+  }, PGBackend::read_errorator::all_same_way([](auto e, auto&& e_raw) -> PGBackend::read_errorator::future<uint64_t> {
     logger().debug("build_push_op: read exception");
-    return seastar::make_exception_future<uint64_t>(e);
-  }));
+    if (42) {
+      return std::move(e_raw);
+    } else {
+      return seastar::make_exception_future<uint64_t>(e);
+    }
+  })).handle_error_interruptible(PGBackend::read_errorator::discard_all{});
 }

 RecoveryBackend::interruptible_future<>
```

Signed-off-by: Radosław Zarzyński <rzarzyns@redhat.com>
src/crimson/common/errorator.h

index 5f817eec918ee762395f6d5ad77348d3c61c90e2..71dddf2b5a1d60f4e53db53236db9cc066afffe8 100644 (file)
@@ -131,8 +131,14 @@ struct unthrowable_wrapper : error_t<unthrowable_wrapper<ErrorT, ErrorV>> {
   static auto handle(Func&& func) {
     return [
       func = std::forward<Func>(func)
-    ] (const unthrowable_wrapper&) mutable -> decltype(auto) {
-      if constexpr (std::is_invocable_v<Func, ErrorT>) {
+    ] (const unthrowable_wrapper& raw_error) mutable -> decltype(auto) {
+      if constexpr (std::is_invocable_v<Func, ErrorT, decltype(raw_error)>) {
+       // check whether the handler wants to take the raw error object which
+       // would be the case if it wants conditionally handle-or-pass-further.
+        return std::invoke(std::forward<Func>(func),
+                           ErrorV,
+                           std::move(raw_error));
+      } else if constexpr (std::is_invocable_v<Func, ErrorT>) {
         return std::invoke(std::forward<Func>(func), ErrorV);
       } else {
         return std::invoke(std::forward<Func>(func));
@@ -197,13 +203,17 @@ struct stateful_error_t : error_t<stateful_error_t<ErrorT>> {
     return [
       func = std::forward<Func>(func)
     ] (stateful_error_t<ErrorT>&& e) mutable -> decltype(auto) {
-      if constexpr (std::is_invocable_v<Func, void>) {
+      if constexpr (std::is_invocable_v<Func>) {
         return std::invoke(std::forward<Func>(func));
       }
       try {
         std::rethrow_exception(e.ep);
       } catch (const ErrorT& obj) {
-        return std::invoke(std::forward<Func>(func), obj);
+        if constexpr (std::is_invocable_v<Func, decltype(obj), decltype(e)>) {
+          return std::invoke(std::forward<Func>(func), obj, e);
+       } else if constexpr (std::is_invocable_v<Func, decltype(obj)>) {
+          return std::invoke(std::forward<Func>(func), obj);
+       }
       }
       ceph_abort_msg("exception type mismatch -- impossible!");
     };