From b188a59c6a805645f4a9850068ad6b7dcb076b26 Mon Sep 17 00:00:00 2001 From: "Adam C. Emerson" Date: Fri, 20 Jan 2023 20:58:00 -0500 Subject: [PATCH] neorados/cls: Helper function for reading CLS values Since reading CLS values in a friendly way requires calling out to RADOS then decoding the returned structure, make a function to help with that. Signed-off-by: Adam C. Emerson --- src/neorados/cls/common.h | 155 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 155 insertions(+) create mode 100644 src/neorados/cls/common.h diff --git a/src/neorados/cls/common.h b/src/neorados/cls/common.h new file mode 100644 index 00000000000..475d239438c --- /dev/null +++ b/src/neorados/cls/common.h @@ -0,0 +1,155 @@ +// -*- 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) 2023 IBM + * + * See file COPYING for license information. + * + */ + +#pragma once + +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +#include + +#include +#include + +#include "include/neorados/RADOS.hpp" + +#include "include/buffer.h" +#include "include/encoding.h" + +/// \file neorados/cls/common.h +/// +/// \brief Helpers for writing simple CLS clients +/// +/// For writing functions that call out to the OSD, perform a CLS +/// call, and return its data in a user friendly way, we need to +/// coordinate asynchronous operation with decoding and returning the +/// relevant data. +/// +/// Ideally, these functions will help. + +namespace neorados::cls { +namespace detail { +template +struct return_sig; + +template +struct return_sig { +using type = void(boost::system::error_code, T); +}; +template +struct return_sig> { + using type = void(boost::system::error_code, Ts...); +}; + +template +using return_sig_t = typename return_sig::type; + +template +auto maybecat(boost::system::error_code ec, + T&& t) +{ + return std::make_tuple(ec, std::forward(t)); +} + +template +auto maybecat(boost::system::error_code ec, + std::tuple&& ts) +{ + return std::tuple_cat(std::tuple(ec), + std::move(ts)); +} +} // namespace detail + +/// \brief Perform a CLS read operation and return the result +/// +/// Asynchronously call into the OSD, decode its response and +/// pass it to a supplied function that extracts the relevant +/// information. +/// +/// \tparam Rep The type of the CLS operation's result that will be +/// passed to `f` +/// +/// \param r RADOS handle +/// \param oid Object name +/// \param ioc IOContext locator +/// \param cls Name of the object class +/// \param method Object class method to call +/// \param req Request (parameters to the class method). Pass nullptr if there +/// is no request structure. +/// \param f Function to extract/process call result +/// \param token Boost.Asio CompletionToken +/// +/// \return The relevant data in a way appropriate to the completion +/// token. See Boost.Asio documentation. The signature is +/// void(error_code, T) if f returns a non-tuple, and +/// void(error_code, Ts...) if f returns a tuple. +template F, + std::default_initializable Ret = std::invoke_result_t, + boost::asio::completion_token_for< + detail::return_sig_t> CompletionToken> +auto exec( + RADOS& r, + Object oid, + IOContext ioc, + std::string cls, + std::string method, + const Req& req, + F&& f, + CompletionToken&& token) +{ + namespace asio = boost::asio; + namespace buffer = ceph::buffer; + using boost::system::error_code; + using boost::system::system_error; + + buffer::list in; + if (!std::is_same_v) { + encode(req, in); + } + return asio::async_initiate> + (asio::experimental::co_composed> + ([](auto state, RADOS& r, Object oid, IOContext ioc, std::string cls, + std::string method, buffer::list in, F&& f) -> void { + try { + ReadOp op; + buffer::list out; + error_code ec; + op.exec(cls, method, std::move(in), &out, &ec); + co_await r.execute(std::move(oid), std::move(ioc), std::move(op), + nullptr, asio::deferred); + if (ec) { + co_return detail::maybecat(ec, Ret{}); + } + Rep rep; + decode(rep, out); + co_return detail::maybecat(error_code{}, + std::invoke(std::forward(f), + std::move(rep))); + } catch (const system_error& e) { + co_return detail::maybecat(e.code(), Ret{}); + } + }, r.get_executor()), + token, std::ref(r), std::move(oid), std::move(ioc), std::move(cls), + std::move(method), std::move(in), std::forward(f)); +} +} // namespace neorados::cls -- 2.39.5