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>
// 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();
{
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)));
}));