]> git.apps.os.sepia.ceph.com Git - ceph.git/commitdiff
neorados: Implement `ReadOp::checksum`
authorAdam Emerson <aemerson@redhat.com>
Thu, 10 Aug 2023 02:00:24 +0000 (22:00 -0400)
committerAdam Emerson <aemerson@redhat.com>
Thu, 14 Sep 2023 21:48:00 +0000 (17:48 -0400)
Rather than using `buffer::list`s for initial values and hash results,
serialize to/from the expected types.

Signed-off-by: Adam Emerson <aemerson@redhat.com>
src/include/neorados/RADOS.hpp
src/neorados/RADOS.cc
src/osdc/Objecter.h

index 3f86d4fc25f5e11ae36bc23243f69f80a6d8a14a..cf7e309c5f2334dd17457f1faef3d3d523df7470 100644 (file)
@@ -19,6 +19,7 @@
 #include <concepts>
 #include <cstddef>
 #include <memory>
+#include <optional>
 #include <tuple>
 #include <string>
 #include <string_view>
@@ -223,6 +224,33 @@ enum alloc_hint_t {
 };
 }
 
+namespace hash_alg {
+struct xxhash32_t {
+  using init_value = std::uint32_t;
+  using hash_value = std::uint32_t;
+};
+struct xxhash64_t {
+  using init_value = std::uint64_t;
+  using hash_value = std::uint64_t;
+};
+struct crc32c_t {
+  using init_value = std::uint32_t;
+  using hash_value = std::uint32_t;
+};
+
+inline constexpr xxhash32_t xxhash32;
+inline constexpr xxhash64_t xxhash64;
+inline constexpr crc32c_t crc32c;
+};
+
+template<typename T>
+concept HashAlg = requires {
+  // Just enumerate, what's supported is what's on the OSD.
+  (std::is_same_v<hash_alg::xxhash32_t, T> ||
+   std::is_same_v<hash_alg::xxhash64_t, T> ||
+   std::is_same_v<hash_alg::crc32c_t, T>);
+};
+
 class Op;
 class ReadOp;
 class WriteOp;
@@ -476,6 +504,21 @@ public:
     return std::move(list_snaps(snaps, ec));
   }
 
+  template<HashAlg T>
+  ReadOp& checksum(T, const typename T::init_value& iv,
+                  std::uint64_t off, std::uint64_t len,
+                  std::uint64_t chunk_size,
+                  std::vector<typename T::hash_value>* out,
+                  boost::system::error_code* ec = nullptr) &;
+  template<HashAlg T>
+  ReadOp&& checksum(T t, const typename T::init_value& iv,
+                   std::uint64_t off, std::uint64_t len,
+                   std::uint64_t chunk_size,
+                   std::vector<typename T::hash_value>* out,
+                   boost::system::error_code* ec = nullptr) && {
+    return std::move(checksum(t, iv, off, len, chunk_size, out, ec));
+  }
+
   // Chaining versions of functions from Op
   ReadOp& set_excl() & {
     Op::set_excl();
index d78b7cf71a16a561f4ce3ca9118661c55e7c7377..9ea9d95916a058ba4d898517c80bab9d3879d1b4 100644 (file)
@@ -646,6 +646,62 @@ ReadOp& ReadOp::list_snaps(SnapSet* snaps,
   return *this;
 }
 
+inline uint8_t checksum_op_type(hash_alg::xxhash32_t) {
+  return CEPH_OSD_CHECKSUM_OP_TYPE_XXHASH32;
+}
+inline uint8_t checksum_op_type(hash_alg::xxhash64_t) {
+  return CEPH_OSD_CHECKSUM_OP_TYPE_XXHASH64;
+}
+inline uint8_t checksum_op_type(hash_alg::crc32c_t) {
+    return CEPH_OSD_CHECKSUM_OP_TYPE_CRC32C;
+}
+
+template<HashAlg T>
+ReadOp& ReadOp::checksum(T t, const typename T::init_value& iv,
+                        std::uint64_t off, std::uint64_t len,
+                        std::uint64_t chunk_size,
+                        std::vector<typename T::hash_value>* out,
+                        boost::system::error_code* ec) & {
+  using ceph::encode;
+  buffer::list init_bl;
+  encode(iv, init_bl);
+  // If this isn't the case we have a programming error
+  assert(init_bl.length() == sizeof(typename T::init_value));
+  reinterpret_cast<OpImpl*>(&impl)->op.
+    checksum(checksum_op_type(t), std::move(init_bl),
+            off, len, chunk_size,
+            [out](bs::error_code ec, int, const buffer::list& bl) {
+              if (!ec) {
+                std::vector<typename T::hash_value> v;
+                auto bi = bl.begin();
+                decode(v, bi);
+                if (out) {
+                  *out = std::move(v);
+                };
+              }
+            }, ec);
+  return *this;
+}
+
+template
+ReadOp& ReadOp::checksum<hash_alg::xxhash32_t>(
+  hash_alg::xxhash32_t, const typename hash_alg::xxhash32_t::init_value&,
+  std::uint64_t off, std::uint64_t len, std::uint64_t chunk_size,
+  std::vector<typename hash_alg::xxhash32_t::hash_value>* out,
+  boost::system::error_code* ec) &;
+template
+ReadOp& ReadOp::checksum<hash_alg::xxhash64_t>(
+  hash_alg::xxhash64_t, const typename hash_alg::xxhash64_t::init_value&,
+  std::uint64_t off, std::uint64_t len, std::uint64_t chunk_size,
+  std::vector<typename hash_alg::xxhash64_t::hash_value>* out,
+  boost::system::error_code* ec) &;
+template
+ReadOp& ReadOp::checksum<hash_alg::crc32c_t>(
+  hash_alg::crc32c_t, const typename hash_alg::crc32c_t::init_value&,
+  std::uint64_t off, std::uint64_t len, std::uint64_t chunk_size,
+  std::vector<typename hash_alg::crc32c_t::hash_value>* out,
+  boost::system::error_code* ec) &;
+
 // WriteOp
 
 WriteOp& WriteOp::set_mtime(ceph::real_time t) & {
index 3cfcb2d68800a15e6d6d744ea57614b7aea98df9..7ee4b4de9fe41459608db8978504ce131a4694b6 100644 (file)
@@ -605,6 +605,23 @@ struct ObjectOperation {
     set_handler(ctx);
   }
 
+  void checksum(uint8_t type, ceph::buffer::list&& init_value,
+               uint64_t off, uint64_t len, size_t chunk_size,
+               fu2::unique_function<void(boost::system::error_code, int,
+                                         const ceph::buffer::list&) &&> f,
+               boost::system::error_code* ec) {
+    OSDOp& osd_op = add_op(CEPH_OSD_OP_CHECKSUM);
+    osd_op.op.checksum.offset = off;
+    osd_op.op.checksum.length = len;
+    osd_op.op.checksum.type = type;
+    osd_op.op.checksum.chunk_size = chunk_size;
+    osd_op.indata.append(std::move(init_value));
+
+    unsigned p = ops.size() - 1;
+    out_ec[p] = ec;
+    set_handler(std::move(f));
+  }
+
   // object attrs
   void getxattr(const char *name, ceph::buffer::list *pbl, int *prval) {
     ceph::buffer::list bl;