}
};
- template <class... ValuesT, class ErrorT>
- static auto make_plain_exception_future(ErrorT&& e) noexcept {
- static_assert(contains_once_v<std::decay_t<ErrorT>>,
- "passing further disallowed ErrorT");
- return ::seastar::make_exception_future<ValuesT...>(
- make_exception_ptr(std::forward<ErrorT>(e)));
- }
-
// the visitor that forwards handling of all errors to next continuation
struct pass_further {
template <class ErrorT>
using type = errorator<AllowedErrors...>;
};
+ template <class... ValuesT>
+ class errorize {
+ seastar::future<ValuesT...> fut;
+ public:
+ errorize(seastar::future<ValuesT...>&& fut) : fut(std::move(fut)) {
+ }
+
+ template <class Func>
+ auto then(Func&& func) && {
+ using FuncResult = std::result_of_t<Func(ValuesT&&...)>;
+ using Futurator = futurize<FuncResult>;
+ return typename Futurator::type{ std::move(fut).then([
+ this, func = std::forward<Func>(func)
+ ] (ValuesT&&... args) mutable {
+ return plainify(std::invoke(std::forward<Func>(func),
+ std::forward<ValuesT>(args)...));
+ })};
+ }
+ };
+
private:
template <class... Args>
static decltype(auto) plainify(seastar::future<Args...>&& fut) {
#endif
logger().debug("calling method {}.{}", cname, mname);
- return seastar::async(
+ return call_errorator::errorize{ seastar::async(
[this, method, indata=std::move(indata)]() mutable {
ceph::bufferlist outdata;
auto cls_context = reinterpret_cast<cls_method_context_t>(this);
const auto ret = method->exec(cls_context, indata, outdata);
return std::make_pair(ret, std::move(outdata));
}
- ).then(
+ )}.then(
[prev_rd = num_read, prev_wr = num_write, this, &osd_op, flags]
- (auto outcome) {
+ (auto outcome) -> call_errorator::future<> {
auto& [ret, outdata] = outcome;
if (num_read > prev_rd && !(flags & CLS_METHOD_RD)) {
logger().error("method tried to read object but is not marked RD");
- return call_errorator::make_plain_exception_future<>(
- crimson::ct_error::input_output_error::make());
+ return crimson::ct_error::input_output_error::make();
}
if (num_write > prev_wr && !(flags & CLS_METHOD_WR)) {
logger().error("method tried to update object but is not marked WR");
- return call_errorator::make_plain_exception_future<>(
- crimson::ct_error::input_output_error::make());
+ return crimson::ct_error::input_output_error::make();
}
// for write calls we never return data expect errors. For details refer
osd_op.outdata.claim_append(outdata);
}
if (ret < 0) {
- return call_errorator::make_plain_exception_future<>(
- crimson::stateful_ec{ std::error_code(-ret, std::generic_category()) });
+ return crimson::stateful_ec{ std::error_code(-ret, std::generic_category()) };
}
return seastar::now();
}
return _load_os(oid);
} else {
// we want a snap
- return _load_ss(oid).then([oid,this](cached_ss_t ss) {
- // head?
- if (oid.snap > ss->seq) {
- return _load_os(oid.get_head());
- } else {
- // which clone would it be?
- auto clone = std::upper_bound(begin(ss->clones), end(ss->clones),
- oid.snap);
- if (clone == end(ss->clones)) {
- return get_os_errorator::make_plain_exception_future<cached_os_t>(
- crimson::ct_error::enoent::make());
- }
- // clone
- auto soid = oid;
- soid.snap = *clone;
- return _load_ss(soid).then([soid,this](cached_ss_t ss) {
- auto clone_snap = ss->clone_snaps.find(soid.snap);
- assert(clone_snap != end(ss->clone_snaps));
- if (clone_snap->second.empty()) {
- logger().trace("find_object: {}@[] -- DNE", soid);
- return get_os_errorator::make_plain_exception_future<cached_os_t>(
- crimson::ct_error::enoent::make());
- }
- auto first = clone_snap->second.back();
- auto last = clone_snap->second.front();
- if (first > soid.snap) {
- logger().trace("find_object: {}@[{},{}] -- DNE",
- soid, first, last);
- return get_os_errorator::make_plain_exception_future<cached_os_t>(
- crimson::ct_error::enoent::make());
+ return get_os_errorator::errorize{_load_ss(oid)}.then(
+ [oid,this](cached_ss_t ss) -> get_os_errorator::future<cached_os_t> {
+ // head?
+ if (oid.snap > ss->seq) {
+ return _load_os(oid.get_head());
+ } else {
+ // which clone would it be?
+ auto clone = std::upper_bound(begin(ss->clones), end(ss->clones),
+ oid.snap);
+ if (clone == end(ss->clones)) {
+ return crimson::ct_error::enoent::make();
}
- logger().trace("find_object: {}@[{},{}] -- HIT",
- soid, first, last);
- return _load_os(soid);
- });
- }
+ // clone
+ auto soid = oid;
+ soid.snap = *clone;
+ return get_os_errorator::errorize{_load_ss(soid)}.then(
+ [soid,this](cached_ss_t ss) -> get_os_errorator::future<cached_os_t> {
+ auto clone_snap = ss->clone_snaps.find(soid.snap);
+ assert(clone_snap != end(ss->clone_snaps));
+ if (clone_snap->second.empty()) {
+ logger().trace("find_object: {}@[] -- DNE", soid);
+ return crimson::ct_error::enoent::make();
+ }
+ auto first = clone_snap->second.back();
+ auto last = clone_snap->second.front();
+ if (first > soid.snap) {
+ logger().trace("find_object: {}@[{},{}] -- DNE",
+ soid, first, last);
+ return crimson::ct_error::enoent::make();
+ }
+ logger().trace("find_object: {}@[{},{}] -- HIT",
+ soid, first, last);
+ return _load_os(soid);
+ });
+ }
});
}
}