#include <concepts>
#include <cstddef>
#include <memory>
+#include <optional>
#include <tuple>
#include <string>
#include <string_view>
};
}
+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;
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();
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) & {
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;