From: Adam C. Emerson Date: Tue, 5 May 2020 22:32:59 +0000 (-0400) Subject: common/async: Add handler for librados::AioCompletion X-Git-Tag: v17.0.0~1186^2~16 X-Git-Url: http://git.apps.os.sepia.ceph.com/?a=commitdiff_plain;h=813acd5d8650d41e9ae9b52579b16f21f4d4417d;p=ceph.git common/async: Add handler for librados::AioCompletion Support using a librados::AioCompletion as a completion handler in Boost.Asio when the arguments are void or only an error code. (To support more arguments we'd have to wrap up the AioCompletion with pointers to hold them.) Signed-off-by: Adam C. Emerson --- diff --git a/src/common/async/librados_completion.h b/src/common/async/librados_completion.h new file mode 100644 index 0000000000000..2fa5555e77475 --- /dev/null +++ b/src/common/async/librados_completion.h @@ -0,0 +1,125 @@ +// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*- +// vim: ts=8 sw=2 smarttab +/* + * Ceph - scalable distributed file system + * + * Copyright (C) 2020 Red Hat + * Author: Adam C. Emerson + * + * This is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License version 2.1, as published by the Free Software + * Foundation. See file COPYING. + * + */ + +#ifndef CEPH_COMMON_ASYNC_LIBRADOS_COMPLETION_H +#define CEPH_COMMON_ASYNC_LIBRADOS_COMPLETION_H + +#include +#include +#include +#include +#include + +#include + +#include +#include + +#include "include/rados/librados.hpp" +#include "librados/AioCompletionImpl.h" + +// Allow librados::AioCompletion to be provided as a completion +// handler. This is only allowed with a signature of +// (boost::system::error_code) or (). On completion the AioCompletion +// is completed with the error_code converted to an int with +// ceph::from_error_code. +// +// async_result::return_type is void. + +namespace ceph::async { + +namespace bs = boost::system; +namespace lr = librados; + +namespace detail { + +struct librados_handler { + lr::AioCompletionImpl* pc; + + explicit librados_handler(lr::AioCompletion* c) : pc(c->pc) { + pc->get(); + } + ~librados_handler() { + if (pc) { + pc->put(); + pc = nullptr; + } + } + + librados_handler(const librados_handler&) = delete; + librados_handler& operator =(const librados_handler&) = delete; + librados_handler(librados_handler&& rhs) { + pc = rhs.pc; + rhs.pc = nullptr; + } + + void operator()(bs::error_code ec) { + pc->lock.lock(); + pc->rval = ceph::from_error_code(ec); + pc->complete = true; + pc->lock.unlock(); + + auto cb_complete = pc->callback_complete; + auto cb_complete_arg = pc->callback_complete_arg; + if (cb_complete) + cb_complete(pc, cb_complete_arg); + + auto cb_safe = pc->callback_safe; + auto cb_safe_arg = pc->callback_safe_arg; + if (cb_safe) + cb_safe(pc, cb_safe_arg); + + pc->lock.lock(); + pc->callback_complete = NULL; + pc->callback_safe = NULL; + pc->cond.notify_all(); + pc->put_unlock(); + pc = nullptr; + } + + void operator ()() { + (*this)(bs::error_code{}); + } +}; +} // namespace detail +} // namespace ceph::async + + +namespace boost::asio { +template +class async_result { +public: + using completion_handler_type = ceph::async::detail::librados_handler; + explicit async_result(completion_handler_type&) {}; + using return_type = void; + void get() { + return; + } +}; + +template +class async_result { +public: + using completion_handler_type = ceph::async::detail::librados_handler; + explicit async_result(completion_handler_type&) {}; + using return_type = void; + void get() { + return; + } +}; +} + +#endif // !CEPH_COMMON_ASYNC_LIBRADOS_COMPLETION_H