]> git.apps.os.sepia.ceph.com Git - ceph-ci.git/commitdiff
librbd: helper image-meta list state machine
authorJason Dillaman <dillaman@redhat.com>
Thu, 13 Feb 2020 17:21:12 +0000 (12:21 -0500)
committerJason Dillaman <dillaman@redhat.com>
Fri, 21 Feb 2020 14:03:09 +0000 (09:03 -0500)
Several locations in librbd re-implement the same loop to collect
all image-meta from the OSD. Consolidate it all to a single state
machine.

Signed-off-by: Jason Dillaman <dillaman@redhat.com>
src/librbd/CMakeLists.txt
src/librbd/image/GetMetadataRequest.cc [new file with mode: 0644]
src/librbd/image/GetMetadataRequest.h [new file with mode: 0644]

index 48419541dc0ec078b6b4082f0280c5e42dbfe7bf..619d83db08d3cbc1ed4c2fb5751f25642aa73499 100644 (file)
@@ -59,6 +59,7 @@ set(librbd_internal_srcs
   image/CreateRequest.cc
   image/DetachChildRequest.cc
   image/DetachParentRequest.cc
+  image/GetMetadataRequest.cc
   image/ListWatchersRequest.cc
   image/OpenRequest.cc
   image/PreRemoveRequest.cc
diff --git a/src/librbd/image/GetMetadataRequest.cc b/src/librbd/image/GetMetadataRequest.cc
new file mode 100644 (file)
index 0000000..a662bcf
--- /dev/null
@@ -0,0 +1,111 @@
+// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
+// vim: ts=8 sw=2 smarttab
+
+#include "librbd/image/GetMetadataRequest.h"
+#include "cls/rbd/cls_rbd_client.h"
+#include "common/dout.h"
+#include "common/errno.h"
+#include "include/ceph_assert.h"
+#include "librbd/ImageCtx.h"
+#include "librbd/Utils.h"
+#include <boost/algorithm/string/predicate.hpp>
+
+#define dout_subsys ceph_subsys_rbd
+#undef dout_prefix
+#define dout_prefix *_dout << "librbd::image::GetMetadataRequest: " \
+                           << this << " " << __func__ << ": "
+
+#define MAX_KEYS 64U
+
+namespace librbd {
+namespace image {
+
+using util::create_rados_callback;
+
+template <typename I>
+GetMetadataRequest<I>::GetMetadataRequest(
+    IoCtx &io_ctx, const std::string &oid, const std::string& filter,
+    const std::string& last_key, uint32_t max_results,
+    KeyValues* key_values, Context *on_finish)
+  : m_io_ctx(io_ctx), m_oid(oid), m_filter(filter), m_last_key(last_key),
+    m_max_results(max_results), m_key_values(key_values),
+    m_on_finish(on_finish),
+    m_cct(reinterpret_cast<CephContext*>(m_io_ctx.cct())) {
+}
+
+template <typename I>
+void GetMetadataRequest<I>::send() {
+  metadata_list();
+}
+
+template <typename I>
+void GetMetadataRequest<I>::metadata_list() {
+  ldout(m_cct, 15) << "start_key=" << m_last_key << dendl;
+
+  m_expected_results = MAX_KEYS;
+  if (m_max_results > 0) {
+    m_expected_results = std::min<uint32_t>(
+      m_expected_results, m_max_results - m_key_values->size());
+  }
+
+  librados::ObjectReadOperation op;
+  cls_client::metadata_list_start(&op, m_last_key, m_expected_results);
+
+  auto aio_comp = create_rados_callback<
+    GetMetadataRequest<I>, &GetMetadataRequest<I>::handle_metadata_list>(this);
+  m_out_bl.clear();
+  m_io_ctx.aio_operate(m_oid, aio_comp, &op, &m_out_bl);
+  aio_comp->release();
+}
+
+template <typename I>
+void GetMetadataRequest<I>::handle_metadata_list(int r) {
+  ldout(m_cct, 15) << "r=" << r << dendl;
+
+  KeyValues metadata;
+  if (r == 0) {
+    auto it = m_out_bl.cbegin();
+    r = cls_client::metadata_list_finish(&it, &metadata);
+  }
+
+  if (r == -ENOENT || r == -EOPNOTSUPP) {
+    finish(0);
+    return;
+  } else if (r < 0) {
+    lderr(m_cct) << "failed to retrieve image metadata: " << cpp_strerror(r)
+                 << dendl;
+    finish(r);
+    return;
+  }
+
+  for (auto it = metadata.begin(); it != metadata.end(); ++it) {
+    if (!m_filter.empty() && !boost::starts_with(it->first, m_filter)) {
+      continue;
+    }
+    m_key_values->insert({it->first, std::move(it->second)});
+  }
+  if (!metadata.empty()) {
+    m_last_key = metadata.rbegin()->first;
+  }
+
+  if (metadata.size() == m_expected_results &&
+      (m_max_results == 0 || m_key_values->size() < m_max_results)) {
+    metadata_list();
+    return;
+  }
+
+  finish(0);
+}
+
+template <typename I>
+void GetMetadataRequest<I>::finish(int r) {
+  ldout(m_cct, 15) << "r=" << r << dendl;
+
+  m_on_finish->complete(r);
+  delete this;
+}
+
+} // namespace image
+} // namespace librbd
+
+template class librbd::image::GetMetadataRequest<librbd::ImageCtx>;
diff --git a/src/librbd/image/GetMetadataRequest.h b/src/librbd/image/GetMetadataRequest.h
new file mode 100644 (file)
index 0000000..c4b883f
--- /dev/null
@@ -0,0 +1,81 @@
+// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
+// vim: ts=8 sw=2 smarttab
+
+#ifndef CEPH_LIBRBD_IMAGE_GET_METADATA_REQUEST_H
+#define CEPH_LIBRBD_IMAGE_GET_METADATA_REQUEST_H
+
+#include "include/rados/librados.hpp"
+#include "include/rbd/librbd.hpp"
+#include <string>
+#include <map>
+
+class CephContext;
+class Context;
+
+namespace librbd {
+
+struct ImageCtx;
+
+namespace image {
+
+template <typename ImageCtxT = ImageCtx>
+class GetMetadataRequest {
+public:
+  typedef std::map<std::string, bufferlist> KeyValues;
+
+  static GetMetadataRequest* create(
+      IoCtx &io_ctx, const std::string &oid, const std::string& filter,
+      const std::string& last_key, uint32_t max_results, KeyValues* key_values,
+      Context *on_finish) {
+    return new GetMetadataRequest(io_ctx, oid, filter, last_key, max_results,
+                                  key_values, on_finish);
+  }
+
+  GetMetadataRequest(
+      IoCtx &io_ctx, const std::string &oid, const std::string& filter,
+      const std::string& last_key, uint32_t max_results, KeyValues* key_values,
+      Context *on_finish);
+
+  void send();
+
+private:
+  /**
+   * @verbatim
+   *
+   * <start>
+   *    |
+   *    |     /-------\
+   *    |     |       |
+   *    v     v       |
+   * METADATA_LIST ---/
+   *    |
+   *    v
+   * <finish>
+   *
+   * @endverbatim
+   */
+  librados::IoCtx m_io_ctx;
+  std::string m_oid;
+  std::string m_filter;
+  std::string m_last_key;
+  uint32_t m_max_results;
+  KeyValues* m_key_values;
+  Context* m_on_finish;
+
+  CephContext* m_cct;
+  bufferlist m_out_bl;
+  uint32_t m_expected_results = 0;
+
+  void metadata_list();
+  void handle_metadata_list(int r);
+
+  void finish(int r);
+
+};
+
+} //namespace image
+} //namespace librbd
+
+extern template class librbd::image::GetMetadataRequest<librbd::ImageCtx>;
+
+#endif // CEPH_LIBRBD_IMAGE_GET_METADATA_REQUEST_H