From fc3d1b2f014794532631f5d4b380ca387721948c Mon Sep 17 00:00:00 2001 From: =?utf8?q?Rados=C5=82aw=20Zarzy=C5=84ski?= Date: Wed, 30 Mar 2022 15:02:20 +0200 Subject: [PATCH] crimson/common: let errorator's handlers to conditionally forward errors MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit 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(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 { logger().debug("build_push_op: read exception"); - return seastar::make_exception_future(e); - })); + if (42) { + return std::move(e_raw); + } else { + return seastar::make_exception_future(e); + } + })).handle_error_interruptible(PGBackend::read_errorator::discard_all{}); } RecoveryBackend::interruptible_future<> ``` Signed-off-by: Radosław Zarzyński --- src/crimson/common/errorator.h | 18 ++++++++++++++---- 1 file changed, 14 insertions(+), 4 deletions(-) diff --git a/src/crimson/common/errorator.h b/src/crimson/common/errorator.h index 5f817eec918..71dddf2b5a1 100644 --- a/src/crimson/common/errorator.h +++ b/src/crimson/common/errorator.h @@ -131,8 +131,14 @@ struct unthrowable_wrapper : error_t> { static auto handle(Func&& func) { return [ func = std::forward(func) - ] (const unthrowable_wrapper&) mutable -> decltype(auto) { - if constexpr (std::is_invocable_v) { + ] (const unthrowable_wrapper& raw_error) mutable -> decltype(auto) { + if constexpr (std::is_invocable_v) { + // 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), + ErrorV, + std::move(raw_error)); + } else if constexpr (std::is_invocable_v) { return std::invoke(std::forward(func), ErrorV); } else { return std::invoke(std::forward(func)); @@ -197,13 +203,17 @@ struct stateful_error_t : error_t> { return [ func = std::forward(func) ] (stateful_error_t&& e) mutable -> decltype(auto) { - if constexpr (std::is_invocable_v) { + if constexpr (std::is_invocable_v) { return std::invoke(std::forward(func)); } try { std::rethrow_exception(e.ep); } catch (const ErrorT& obj) { - return std::invoke(std::forward(func), obj); + if constexpr (std::is_invocable_v) { + return std::invoke(std::forward(func), obj, e); + } else if constexpr (std::is_invocable_v) { + return std::invoke(std::forward(func), obj); + } } ceph_abort_msg("exception type mismatch -- impossible!"); }; -- 2.39.5