]> git.apps.os.sepia.ceph.com Git - ceph.git/commitdiff
neorados: Use C++20 Coroutines in exerciser/demo
authorAdam C. Emerson <aemerson@redhat.com>
Thu, 15 Sep 2022 20:42:51 +0000 (16:42 -0400)
committerAdam Emerson <aemerson@redhat.com>
Thu, 14 Sep 2023 21:03:29 +0000 (17:03 -0400)
Just as a demonstration to see how well they work and how to put
things together with them.

Signed-off-by: Adam C. Emerson <aemerson@redhat.com>
src/tools/CMakeLists.txt
src/tools/neorados.cc

index aeb9d0248ea6ef70ff98b4644e7b1699aec92974..4a891e22fa174b07eb4a637ba6948492d3db3a23 100644 (file)
@@ -20,7 +20,7 @@ if(NOT WIN32)
   set(neorados_srcs
       neorados.cc)
   add_executable(neorados ${neorados_srcs})
-  target_link_libraries(neorados libneorados spawn fmt::fmt ${CMAKE_DL_LIBS})
+  target_link_libraries(neorados libneorados fmt::fmt ${CMAKE_DL_LIBS})
   #install(TARGETS neorados DESTINATION bin)
 endif()
 
index c89fb49c9c50fc03ce06076301daaebc1f4e710a..f1b0eff753e94899976773eb67ccde82e40e9ff4 100644 (file)
  *
  */
 
-#define BOOST_COROUTINES_NO_DEPRECATION_WARNING
-
 #include <algorithm>
 #include <cassert>
+#include <coroutine>
 #include <iostream>
 #include <string>
 #include <string_view>
@@ -24,6 +23,7 @@
 #include <vector>
 
 #include <boost/asio.hpp>
+#include <boost/asio/awaitable.hpp>
 #include <boost/io/ios_state.hpp>
 #include <boost/program_options.hpp>
 #include <boost/system/system_error.hpp>
@@ -31,8 +31,6 @@
 #include <fmt/format.h>
 #include <fmt/ostream.h>
 
-#include <spawn/spawn.hpp>
-
 #include "include/buffer.h" // :(
 
 #include "include/neorados/RADOS.hpp"
@@ -42,7 +40,6 @@ using namespace std::literals;
 namespace ba = boost::asio;
 namespace bs = boost::system;
 namespace R = neorados;
-namespace s = spawn;
 
 std::string verstr(const std::tuple<uint32_t, uint32_t, uint32_t>& v)
 {
@@ -68,91 +65,94 @@ void printseq(const V& v, std::ostream& m, F&& f)
                });
 }
 
-R::IOContext lookup_pool(R::RADOS& r, const std::string& pname,
-                        s::yield_context y)
+ba::awaitable<R::IOContext> lookup_pool(R::RADOS& r, const std::string& pname)
 {
   bs::error_code ec;
-  auto p = r.lookup_pool(pname, y[ec]);
+  auto p = co_await r.lookup_pool(pname,
+                                 ba::redirect_error(ba::use_awaitable, ec));
   if (ec)
     throw bs::system_error(
       ec, fmt::format("when looking up '{}'", pname));
-  return R::IOContext(p);
+  co_return R::IOContext(p);
 }
 
 
-void lspools(R::RADOS& r, const std::vector<std::string>&,
-            s::yield_context y)
+ba::awaitable<void> lspools(R::RADOS& r, const std::vector<std::string>&)
 {
-  const auto l = r.list_pools(y);
+  const auto l = co_await r.list_pools(ba::use_awaitable);
   printseq(l, std::cout, [](const auto& p) -> const std::string& {
                           return p.second;
                         });
+  co_return;
 }
 
 
-void ls(R::RADOS& r, const std::vector<std::string>& p, s::yield_context y)
+ba::awaitable<void> ls(R::RADOS& r, const std::vector<std::string>& p)
 {
   const auto& pname = p[0];
-  const auto pool = lookup_pool(r, pname, y).set_ns(R::all_nspaces);
-
+  const auto pool = (co_await lookup_pool(r, pname)).set_ns(R::all_nspaces);
   std::vector<R::Entry> ls;
   R::Cursor next = R::Cursor::begin();
   bs::error_code ec;
   do {
-    std::tie(ls, next) = r.enumerate_objects(pool, next, R::Cursor::end(),
-                                            1000, {}, y[ec]);
+    std::tie(ls, next) =
+      co_await r.enumerate_objects(pool, next, R::Cursor::end(), 1000, {},
+                                  ba::redirect_error(ba::use_awaitable, ec));
     if (ec)
       throw bs::system_error(ec, fmt::format("when listing {}", pname));
     printseq(ls, std::cout);
     ls.clear();
   } while (next != R::Cursor::end());
+  co_return;
 }
 
-void mkpool(R::RADOS& r, const std::vector<std::string>& p,
-           s::yield_context y)
+ba::awaitable<void> mkpool(R::RADOS& r, const std::vector<std::string>& p)
 {
   const auto& pname = p[0];
   bs::error_code ec;
-  r.create_pool(pname, std::nullopt, y[ec]);
+  co_await r.create_pool(pname, std::nullopt,
+                        ba::redirect_error(ba::use_awaitable, ec));
   if (ec)
     throw bs::system_error(ec, fmt::format("when creating pool '{}'", pname));
+  co_return;
 }
 
-void rmpool(R::RADOS& r, const std::vector<std::string>& p,
-           s::yield_context y)
+ba::awaitable<void> rmpool(R::RADOS& r, const std::vector<std::string>& p)
 {
   const auto& pname = p[0];
   bs::error_code ec;
-  r.delete_pool(pname, y[ec]);
+  co_await r.delete_pool(pname, ba::redirect_error(ba::use_awaitable, ec));
   if (ec)
     throw bs::system_error(ec, fmt::format("when removing pool '{}'", pname));
+  co_return;
 }
 
-void create(R::RADOS& r, const std::vector<std::string>& p,
-           s::yield_context y)
+ba::awaitable<void> create(R::RADOS& r, const std::vector<std::string>& p)
 {
   const auto& pname = p[0];
   const R::Object obj = p[1];
-  const auto pool = lookup_pool(r, pname, y);
+  const auto pool = co_await lookup_pool(r, pname);
 
   bs::error_code ec;
   R::WriteOp op;
   op.create(true);
-  r.execute(obj, pool, std::move(op), y[ec]);
+  co_await r.execute(obj, pool, std::move(op),
+                    ba::redirect_error(ba::use_awaitable, ec));
   if (ec)
     throw bs::system_error(ec,
                           fmt::format(
                             "when creating object '{}' in pool '{}'",
                             obj, pname));
+  co_return;
 }
 
 inline constexpr std::size_t io_size = 4 << 20;
 
-void write(R::RADOS& r, const std::vector<std::string>& p, s::yield_context y)
+ba::awaitable<void> write(R::RADOS& r, const std::vector<std::string>& p)
 {
   const auto& pname = p[0];
   const R::Object obj(p[1]);
-  const auto pool = lookup_pool(r, pname, y);
+  const auto pool = co_await lookup_pool(r, pname);
 
   bs::error_code ec;
   std::unique_ptr<char[]> buf = std::make_unique<char[]>(io_size);
@@ -174,28 +174,30 @@ void write(R::RADOS& r, const std::vector<std::string>& p, s::yield_context y)
     bl.append(buffer::create_static(len, buf.get()));
     R::WriteOp op;
     op.write(curoff, std::move(bl));
-    r.execute(obj, pool, std::move(op), y[ec]);
+    co_await r.execute(obj, pool, std::move(op),
+                      ba::redirect_error(ba::use_awaitable, ec));
 
     if (ec)
       throw bs::system_error(ec, fmt::format(
                               "when writing object '{}' in pool '{}'",
                               obj, pname));
   }
+  co_return;
 }
 
-void read(R::RADOS& r, const std::vector<std::string>& p, s::yield_context y)
+ba::awaitable<void> read(R::RADOS& r, const std::vector<std::string>& p)
 {
   const auto& pname = p[0];
   const R::Object obj(p[1]);
-  const auto pool = lookup_pool(r, pname, y);
+  const auto pool = co_await lookup_pool(r, pname);
 
   bs::error_code ec;
   std::uint64_t len;
   {
     R::ReadOp op;
     op.stat(&len, nullptr);
-    r.execute(obj, pool, std::move(op),
-             nullptr, y[ec]);
+    co_await r.execute(obj, pool, std::move(op),
+                      nullptr, ba::redirect_error(ba::use_awaitable, ec));
     if (ec)
       throw bs::system_error(
        ec,
@@ -208,7 +210,8 @@ void read(R::RADOS& r, const std::vector<std::string>& p, s::yield_context y)
   while (auto toread = std::min(len - off, io_size)) {
     R::ReadOp op;
     op.read(off, toread, &bl);
-    r.execute(obj, pool, std::move(op), nullptr, y[ec]);
+    co_await r.execute(obj, pool, std::move(op), nullptr,
+                      ba::redirect_error(ba::use_awaitable, ec));
     if (ec)
       throw bs::system_error(
        ec,
@@ -219,28 +222,31 @@ void read(R::RADOS& r, const std::vector<std::string>& p, s::yield_context y)
     bl.write_stream(std::cout);
     bl.clear();
   }
+  co_return;
 }
 
-void rm(R::RADOS& r, const std::vector<std::string>& p, s::yield_context y)
+ba::awaitable<void> rm(R::RADOS& r, const std::vector<std::string>& p)
 {
   const auto& pname = p[0];
   const R::Object obj = p[1];
-  const auto pool = lookup_pool(r, pname, y);
+  const auto pool = co_await lookup_pool(r, pname);
 
   bs::error_code ec;
   R::WriteOp op;
   op.remove();
-  r.execute(obj, pool, std::move(op), y[ec]);
+  co_await r.execute(obj, pool, std::move(op),
+                    ba::redirect_error(ba::use_awaitable, ec));
   if (ec)
     throw bs::system_error(ec, fmt::format(
                             "when removing object '{}' in pool '{}'",
                             obj, pname));
+  co_return;
 }
 
 static constexpr auto version = std::make_tuple(0ul, 0ul, 1ul);
 
-using cmdfunc = void (*)(R::RADOS& r, const std::vector<std::string>& p,
-                        s::yield_context);
+using cmdfunc =
+  ba::awaitable<void> (*)(R::RADOS& r, const std::vector<std::string>& p);
 
 struct cmdesc {
   std::string_view name;
@@ -371,10 +377,14 @@ int main(int argc, char* argv[])
                   prog, command, ci->name, ci->usage);
        return 1;
       }
-      s::spawn(c, [&](s::yield_context y) {
-                   auto r = R::RADOS::Builder{}.build(c, y);
-                   ci->f(r, parameters, y);
-                 });
+      ba::co_spawn(c,
+                  [&]() -> ba::awaitable<void> {
+                    auto r = co_await R::RADOS::Builder{}.build(
+                      c, ba::use_awaitable);
+                    co_await ci->f(r, parameters);
+                  }, [](std::exception_ptr e) {
+                    if (e) std::rethrow_exception(e);
+                  });
     } else {
       fmt::print(std::cerr, "{}: {}: unknown command\n", prog, command);
       return 1;