#include <exception>
#include <system_error>
+#include "crimson/common/errorator.h"
+
namespace crimson::osd {
class error : private std::system_error {
public:
static inline int execute_osd_op(cls_method_context_t hctx, OSDOp& op)
{
- try {
- reinterpret_cast<ceph::osd::OpsExecuter*>(hctx)->execute_osd_op(op).get();
- return 0;
- } catch (crimson::osd::error& e) {
- return -e.code().value();
- }
+ // we can expect the memory under `ret` will be still fine after
+ // executing the osd op as we're running inside `seastar::thread`
+ // 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) {
+ assert(err.value() > 0);
+ ret = -err.value();
+ return seastar::now();
+ })).get(); // we're blocking here which requires `seastar::thread`.
+ return ret;
}
int cls_call(cls_method_context_t hctx, const char *cls, const char *method,
}
if (ret < 0) {
return call_errorator::make_plain_exception_future<>(
-<<<<<<< HEAD
- crimson::stateful_errint{ ret });
-=======
- ceph::stateful_ec{ std::error_code(-ret, std::generic_category()) });
->>>>>>> 520100f... crimson: use std::error_code instances for errors.
+ crimson::stateful_ec{ std::error_code(-ret, std::generic_category()) });
}
return seastar::now();
}
});
}
-seastar::future<>
+OpsExecuter::osd_op_errorator::future<>
OpsExecuter::execute_osd_op(OSDOp& osd_op)
{
// TODO: dispatch via call table?
osd_op.rval = bl.length();
osd_op.outdata = std::move(bl);
return seastar::now();
- },
- // TODO: move this error handling do PG::do_osd_ops().
- crimson::ct_error::input_output_error::handle([] {
- throw ceph::osd::input_output_error{};
- }),
- crimson::ct_error::object_corrupted::handle([] {
- throw ceph::osd::object_corrupted{};
- }),
- crimson::ct_error::enoent::handle([] {
- throw ceph::osd::object_not_found{};
- }),
- crimson::ct_error::enodata::handle([] {
- throw ceph::osd::no_message_available{};
- }));
+ }, read_errorator::pass_further{});
});
case CEPH_OSD_OP_GETXATTR:
return do_read_op([&osd_op] (auto& backend, const auto& os) {
return backend.remove(os, txn);
});
case CEPH_OSD_OP_CALL:
- return this->do_op_call(osd_op).safe_then(
- [] {
- return seastar::now();
- }, call_errorator::all_same_way([] (const std::error_code& err) {
- assert(err.value() > 0);
- throw crimson::osd::make_error(err.value());
- }));
+ return this->do_op_call(osd_op);
case CEPH_OSD_OP_STAT:
// note: stat does not require RD
return do_const_op([&osd_op] (/* const */auto& backend, const auto& os) {
throw crimson::osd::operation_not_supported();
}
+ using read_errorator = PGBackend::read_errorator;
+ using get_attr_errorator = PGBackend::get_attr_errorator;
+
public:
OpsExecuter(PGBackend::cached_os_t os, PG& pg, Ref<MOSDOp> msg)
: os(std::move(os)),
: OpsExecuter{PGBackend::cached_os_t{}, pg, std::move(msg)}
{}
- seastar::future<> execute_osd_op(class OSDOp& osd_op);
+ using osd_op_errorator = crimson::compound_errorator_t<
+ call_errorator,
+ read_errorator,
+ get_attr_errorator>;
+ osd_op_errorator::future<> execute_osd_op(class OSDOp& osd_op);
seastar::future<> execute_pg_op(class OSDOp& osd_op);
template <typename Func>
[this, m] (auto& ox) {
return seastar::do_for_each(m->ops, [this, &ox](OSDOp& osd_op) {
logger().debug("will be handling op {}", ceph_osd_op_name(osd_op.op.op));
- return ox.execute_osd_op(osd_op);
+ return ox.execute_osd_op(osd_op).safe_then(
+ [] {
+ return seastar::now();
+ }, OpsExecuter::osd_op_errorator::all_same_way([] (const std::error_code& err) {
+ assert(err.value() > 0);
+ throw ceph::osd::make_error(err.value());
+ }));
}).then([this, m, &ox] {
logger().debug("all operations have been executed successfully");
return std::move(ox).submit_changes([this, m] (auto&& txn, auto&& os) {