From 8e5b83cc11243c9ca429233c833ad3f634e729ad Mon Sep 17 00:00:00 2001 From: "Adam C. Emerson" Date: Mon, 20 Mar 2023 12:20:38 -0400 Subject: [PATCH] neorados: Op builder functions should chain Make every operation function return the (Read/Write)Op, for chaining. Signed-off-by: Adam C. Emerson --- src/include/neorados/RADOS.hpp | 881 ++++++++++++++++-- src/neorados/RADOS.cc | 135 +-- .../librados_test_stub/NeoradosTestStub.cc | 49 +- 3 files changed, 931 insertions(+), 134 deletions(-) diff --git a/src/include/neorados/RADOS.hpp b/src/include/neorados/RADOS.hpp index 15bff7df7c40e..acc1ca3e01bbd 100644 --- a/src/include/neorados/RADOS.hpp +++ b/src/include/neorados/RADOS.hpp @@ -16,6 +16,7 @@ #ifndef NEORADOS_RADOS_HPP #define NEORADOS_RADOS_HPP +#include #include #include #include @@ -216,6 +217,71 @@ enum alloc_hint_t { }; } +class Op; +class ReadOp; +class WriteOp; + +template F> +class ClsOp { + F f; +public: + ClsOp(F&& f) : f(std::move(f)) {} + + ReadOp& operator()(ReadOp& op) { + std::move(f)(op); + return op; + } + + ReadOp&& operator()(ReadOp&& op) { + std::move(f)(op); + return std::move(op); + } + + WriteOp& operator()(WriteOp& op) { + std::move(f)(op); + return op; + } + + WriteOp&& operator()(WriteOp&& op) { + std::move(f)(op); + return std::move(op); + } +}; + +template F> +class ClsReadOp { + F f; +public: + ClsReadOp(F&& f) : f(std::move(f)) {} + + ReadOp& operator()(ReadOp& op) { + std::move(f)(op); + return op; + } + + ReadOp&& operator()(ReadOp&& op) { + std::move(f)(op); + return std::move(op); + } +}; + +template F> +class ClsWriteOp { + F f; +public: + ClsWriteOp(F&& f) : f(std::move(f)) {} + + WriteOp& operator()(WriteOp& op) { + std::move(f)(op); + return op; + } + + WriteOp&& operator()(WriteOp&& op) { + std::move(f)(op); + return std::move(op); + } +}; + class Op { friend RADOS; @@ -241,9 +307,9 @@ public: void cmpxattr(std::string_view name, cmpxattr_op op, std::uint64_t val); void assert_version(uint64_t ver); void assert_exists(); - void cmp_omap(const boost::container::flat_map< - std::string, - std::pair>& assertions); + void cmp_omap(const boost::container::flat_map>& assertions); void exec(std::string_view cls, std::string_view method, const ceph::buffer::list& inbl, @@ -301,51 +367,398 @@ public: ReadOp& operator =(const ReadOp&) = delete; ReadOp& operator =(ReadOp&&) = default; - void read(size_t off, uint64_t len, ceph::buffer::list* out, - boost::system::error_code* ec = nullptr); - void get_xattr(std::string_view name, ceph::buffer::list* out, - boost::system::error_code* ec = nullptr); - void get_omap_header(ceph::buffer::list*, - boost::system::error_code* ec = nullptr); + ReadOp& read(size_t off, uint64_t len, ceph::buffer::list* out, + boost::system::error_code* ec = nullptr) &; + ReadOp&& read(size_t off, uint64_t len, ceph::buffer::list* out, + boost::system::error_code* ec = nullptr) && { + return std::move(read(off, len, out, ec)); + } + ReadOp& get_xattr(std::string_view name, ceph::buffer::list* out, + boost::system::error_code* ec = nullptr) &; + ReadOp&& get_xattr(std::string_view name, ceph::buffer::list* out, + boost::system::error_code* ec = nullptr) && { + return std::move(get_xattr(name, out, ec)); + } + ReadOp& get_omap_header(ceph::buffer::list* bl, + boost::system::error_code* ec = nullptr) &; + ReadOp&& get_omap_header(ceph::buffer::list* bl, + boost::system::error_code* ec = nullptr) && { + return std::move(get_omap_header(bl, ec)); + } + ReadOp& sparse_read(uint64_t off, uint64_t len, + ceph::buffer::list* out, + std::vector>* extents, + boost::system::error_code* ec = nullptr) &; + ReadOp&& sparse_read(uint64_t off, uint64_t len, + ceph::buffer::list* out, + std::vector>* extents, + boost::system::error_code* ec = nullptr) && { + return std::move(sparse_read(off, len, out, extents, ec)); + } - void sparse_read(uint64_t off, uint64_t len, - ceph::buffer::list* out, - std::vector>* extents, - boost::system::error_code* ec = nullptr); + ReadOp& stat(std::uint64_t* size, ceph::real_time* mtime, + boost::system::error_code* ec = nullptr) &; + ReadOp&& stat(std::uint64_t* size, ceph::real_time* mtime, + boost::system::error_code* ec = nullptr) && { + return std::move(stat(size, mtime, ec)); + } - void stat(std::uint64_t* size, ceph::real_time* mtime, - boost::system::error_code* ec = nullptr); + ReadOp& get_omap_keys(std::optional start_after, + std::uint64_t max_return, + boost::container::flat_set* keys, + bool* truncated, + boost::system::error_code* ec = nullptr) &; + ReadOp&& get_omap_keys(std::optional start_after, + std::uint64_t max_return, + boost::container::flat_set* keys, + bool* truncated, + boost::system::error_code* ec = nullptr) && { + return std::move(get_omap_keys(start_after, max_return, keys, truncated, ec)); + } - void get_omap_keys(std::optional start_after, - std::uint64_t max_return, - boost::container::flat_set* keys, - bool* truncated, - boost::system::error_code* ec = nullptr); + ReadOp& get_xattrs(boost::container::flat_map* kv, + boost::system::error_code* ec = nullptr) &; + ReadOp&& get_xattrs(boost::container::flat_map* kv, + boost::system::error_code* ec = nullptr) && { + return std::move(get_xattrs(kv, ec)); + } - void get_xattrs(boost::container::flat_map* kv, - boost::system::error_code* ec = nullptr); + ReadOp& get_omap_vals(std::optional start_after, + std::optional filter_prefix, + uint64_t max_return, + boost::container::flat_map* kv, + bool* truncated, + boost::system::error_code* ec = nullptr) &; + ReadOp&& get_omap_vals(std::optional start_after, + std::optional filter_prefix, + uint64_t max_return, + boost::container::flat_map* kv, + bool* truncated, + boost::system::error_code* ec = nullptr) && { + return std::move(get_omap_vals(start_after, filter_prefix, max_return, kv, + truncated, ec)); + } - void get_omap_vals(std::optional start_after, - std::optional filter_prefix, - uint64_t max_return, - boost::container::flat_map* kv, - bool* truncated, - boost::system::error_code* ec = nullptr); + ReadOp& get_omap_vals_by_keys( + const boost::container::flat_set& keys, + boost::container::flat_map* kv, + boost::system::error_code* ec = nullptr) &; + ReadOp&& get_omap_vals_by_keys( + const boost::container::flat_set& keys, + boost::container::flat_map* kv, + boost::system::error_code* ec = nullptr) && { + return std::move(get_omap_vals_by_keys(keys, kv, ec)); + } + ReadOp& list_watchers(std::vector* watchers, + boost::system::error_code* ec = nullptr) &; + ReadOp&& list_watchers(std::vector* watchers, + boost::system::error_code* ec = nullptr) && { + return std::move(list_watchers(watchers, ec)); + } - void get_omap_vals_by_keys(const boost::container::flat_set& keys, - boost::container::flat_map* kv, - boost::system::error_code* ec = nullptr); + ReadOp& list_snaps(struct SnapSet* snaps, + boost::system::error_code* ec = nullptr) &; + ReadOp&& list_snaps(struct SnapSet* snaps, + boost::system::error_code* ec = nullptr) && { + return std::move(list_snaps(snaps, ec)); + } - void list_watchers(std::vector* watchers, - boost::system::error_code* ec = nullptr); + // Chaining versions of functions from Op + ReadOp& set_excl() & { + Op::set_excl(); + return *this; + } + ReadOp&& set_excl() && { + Op::set_excl(); + return std::move(*this); + } + + ReadOp& set_failok() & { + Op::set_failok(); + return *this; + } + ReadOp&& set_failok() && { + Op::set_failok(); + return std::move(*this); + } + + ReadOp& set_fadvise_random() & { + Op::set_fadvise_random(); + return *this; + } + ReadOp&& set_fadvise_random() && { + Op::set_fadvise_random(); + return std::move(*this); + } + + ReadOp& set_fadvise_sequential() & { + Op::set_fadvise_sequential(); + return *this; + } + ReadOp&& set_fadvise_sequential() && { + Op::set_fadvise_sequential(); + return std::move(*this); + } + + ReadOp& set_fadvise_willneed() & { + Op::set_fadvise_willneed(); + return *this; + } + ReadOp&& set_fadvise_willneed() && { + Op::set_fadvise_willneed(); + return std::move(*this); + } - void list_snaps(struct SnapSet* snaps, - boost::system::error_code* ec = nullptr); + ReadOp& set_fadvise_dontneed() & { + Op::set_fadvise_dontneed(); + return *this; + } + ReadOp&& set_fadvise_dontneed() && { + Op::set_fadvise_dontneed(); + return std::move(*this); + } + + ReadOp& set_fadvise_nocache() & { + Op::set_fadvise_nocache(); + return *this; + } + ReadOp&& set_fadvise_nocache() && { + Op::set_fadvise_nocache(); + return std::move(*this); + } + + ReadOp& cmpext(uint64_t off, ceph::buffer::list&& cmp_bl, std::size_t* s) & { + Op::cmpext(off, std::move(cmp_bl), s); + return *this; + } + ReadOp&& cmpext(uint64_t off, ceph::buffer::list&& cmp_bl, std::size_t* s) && { + Op::cmpext(off, std::move(cmp_bl), s); + return std::move(*this); + } + + ReadOp& cmpxattr(std::string_view name, cmpxattr_op op, + const ceph::buffer::list& val) & { + Op::cmpxattr(name, op, val); + return *this; + } + ReadOp&& cmpxattr(std::string_view name, cmpxattr_op op, + const ceph::buffer::list& val) && { + Op::cmpxattr(name, op, val); + return std::move(*this); + } + + ReadOp& cmpxattr(std::string_view name, cmpxattr_op op, std::uint64_t val) & { + Op::cmpxattr(name, op, val); + return *this; + } + ReadOp&& cmpxattr(std::string_view name, cmpxattr_op op, std::uint64_t val) && { + Op::cmpxattr(name, op, val); + return std::move(*this); + } + + ReadOp& assert_version(uint64_t ver) & { + Op::assert_version(ver); + return *this; + } + ReadOp&& assert_version(uint64_t ver) && { + Op::assert_version(ver); + return std::move(*this); + } + + ReadOp& assert_exists() & { + Op::assert_exists(); + return *this; + } + ReadOp&& assert_exists() && { + Op::assert_exists(); + return std::move(*this); + } + + ReadOp& cmp_omap( + const boost::container::flat_map< + std::string, std::pair>& assertions) & { + Op::cmp_omap(assertions); + return *this; + } + ReadOp&& cmp_omap( + const boost::container::flat_map< + std::string, std::pair>& assertions) && { + Op::cmp_omap(assertions); + return std::move(*this); + } + + ReadOp& exec(std::string_view cls, std::string_view method, + const ceph::buffer::list& inbl, + ceph::buffer::list* out, + boost::system::error_code* ec = nullptr) & { + Op::exec(cls, method, inbl, out, ec); + return *this; + } + ReadOp&& exec(std::string_view cls, std::string_view method, + const ceph::buffer::list& inbl, + ceph::buffer::list* out, + boost::system::error_code* ec = nullptr) && { + Op::exec(cls, method, inbl, out, ec); + return std::move(*this); + } + + ReadOp& exec(std::string_view cls, std::string_view method, + const ceph::buffer::list& inbl, + fu2::unique_function f) & { + Op::exec(cls, method, inbl, std::move(f)); + return *this; + } + ReadOp&& exec(std::string_view cls, std::string_view method, + const ceph::buffer::list& inbl, + fu2::unique_function f) && { + Op::exec(cls, method, inbl, std::move(f)); + return std::move(*this); + } + + ReadOp& exec(std::string_view cls, std::string_view method, + const ceph::buffer::list& inbl, + fu2::unique_function f) & { + Op::exec(cls, method, inbl, std::move(f)); + return *this; + } + ReadOp&& exec(std::string_view cls, std::string_view method, + const ceph::buffer::list& inbl, + fu2::unique_function f) && { + Op::exec(cls, method, inbl, std::move(f)); + return std::move(*this); + } + + ReadOp& exec(std::string_view cls, std::string_view method, + const ceph::buffer::list& inbl, + boost::system::error_code* ec = nullptr) & { + Op::exec(cls, method, inbl, ec); + return *this; + } + ReadOp&& exec(std::string_view cls, std::string_view method, + const ceph::buffer::list& inbl, + boost::system::error_code* ec = nullptr) && { + Op::exec(cls, method, inbl, ec); + return std::move(*this); + } + + template + ReadOp& exec(ClsOp&& clsop) & { + return clsop(*this); + } + template + ReadOp&& exec(ClsOp&& clsop) && { + return std::move(clsop(*this)); + } + template + ReadOp& exec(ClsReadOp&& clsop) & { + return clsop(*this); + } + template + ReadOp&& exec(ClsReadOp&& clsop) && { + return std::move(clsop(*this)); + } + + // Flags that apply to all ops in the operation vector + ReadOp& balance_reads() & { + Op::balance_reads(); + return *this; + } + ReadOp&& balance_reads() && { + Op::balance_reads(); + return std::move(*this); + } + ReadOp& localize_reads() & { + Op::localize_reads(); + return *this; + } + ReadOp&& localize_reads() && { + Op::localize_reads(); + return std::move(*this); + } + ReadOp& order_reads_writes() & { + Op::order_reads_writes(); + return *this; + } + ReadOp&& order_reads_writes() && { + Op::order_reads_writes(); + return std::move(*this); + } + ReadOp& ignore_cache() & { + Op::ignore_cache(); + return *this; + } + ReadOp&& ignore_cache() && { + Op::ignore_cache(); + return std::move(*this); + } + ReadOp& skiprwlocks() & { + Op::skiprwlocks(); + return *this; + } + ReadOp&& skiprwlocks() && { + Op::skiprwlocks(); + return std::move(*this); + } + ReadOp& ignore_overlay() & { + Op::ignore_overlay(); + return *this; + } + ReadOp&& ignore_overlay() && { + Op::ignore_overlay(); + return std::move(*this); + } + ReadOp& full_try() & { + Op::full_try(); + return *this; + } + ReadOp&& full_try() && { + Op::full_try(); + return std::move(*this); + } + ReadOp& full_force() & { + Op::full_force(); + return *this; + } + ReadOp&& full_force() && { + Op::full_force(); + return std::move(*this); + } + ReadOp& ignore_redirect() & { + Op::ignore_redirect(); + return *this; + } + ReadOp&& ignore_redirect() && { + Op::ignore_redirect(); + return std::move(*this); + } + ReadOp& ordersnap() & { + Op::ordersnap(); + return *this; + } + ReadOp&& ordersnap() && { + Op::ordersnap(); + return std::move(*this); + } + ReadOp& returnvec() & { + Op::returnvec(); + return *this; + } + ReadOp&& returnvec() && { + Op::returnvec(); + return std::move(*this); + } }; class WriteOp final : public Op { @@ -359,28 +772,376 @@ public: WriteOp& operator =(const WriteOp&) = delete; WriteOp& operator =(WriteOp&&) = default; - void set_mtime(ceph::real_time t); - void create(bool exclusive); - void write(uint64_t off, ceph::buffer::list&& bl); - void write_full(ceph::buffer::list&& bl); - void writesame(std::uint64_t off, std::uint64_t write_len, - ceph::buffer::list&& bl); - void append(ceph::buffer::list&& bl); - void remove(); - void truncate(uint64_t off); - void zero(uint64_t off, uint64_t len); - void rmxattr(std::string_view name); - void setxattr(std::string_view name, - ceph::buffer::list&& bl); - void rollback(uint64_t snapid); - void set_omap(const boost::container::flat_map& map); - void set_omap_header(ceph::buffer::list&& bl); - void clear_omap(); - void rm_omap_keys(const boost::container::flat_set& to_rm); - void set_alloc_hint(uint64_t expected_object_size, - uint64_t expected_write_size, - alloc_hint::alloc_hint_t flags); + WriteOp& set_mtime(ceph::real_time t) &; + WriteOp&& set_mtime(ceph::real_time t) && { + return std::move(set_mtime(t)); + } + WriteOp& create(bool exclusive) &; + WriteOp&& create(bool exclusive) && { + return std::move(create(exclusive)); + } + WriteOp& write(uint64_t off, ceph::buffer::list&& bl) &; + WriteOp&& write(uint64_t off, ceph::buffer::list&& bl) && { + return std::move(write(off, std::move(bl))); + } + WriteOp& write_full(ceph::buffer::list&& bl) &; + WriteOp&& write_full(ceph::buffer::list&& bl) && { + return std::move(write_full(std::move(bl))); + } + WriteOp& writesame(std::uint64_t off, std::uint64_t write_len, + ceph::buffer::list&& bl) &; + WriteOp&& writesame(std::uint64_t off, std::uint64_t write_len, + ceph::buffer::list&& bl) && { + return std::move(writesame(off, write_len, std::move(bl))); + } + WriteOp& append(ceph::buffer::list&& bl) &; + WriteOp&& append(ceph::buffer::list&& bl) && { + return std::move(append(std::move(bl))); + } + WriteOp& remove() &; + WriteOp&& remove() && { + return std::move(remove()); + } + WriteOp& truncate(uint64_t off) &; + WriteOp&& truncate(uint64_t off) && { + return std::move(truncate(off)); + } + WriteOp& zero(uint64_t off, uint64_t len) &; + WriteOp&& zero(uint64_t off, uint64_t len) && { + return std::move(zero(off, len)); + } + WriteOp& rmxattr(std::string_view name) &; + WriteOp&& rmxattr(std::string_view name) && { + return std::move(rmxattr(name)); + } + WriteOp& setxattr(std::string_view name, + ceph::buffer::list&& bl) &; + WriteOp&& setxattr(std::string_view name, + ceph::buffer::list&& bl) && { + return std::move(setxattr(name, std::move(bl))); + } + WriteOp& rollback(uint64_t snapid) &; + WriteOp&& rollback(uint64_t snapid) && { + return std::move(rollback(snapid)); + } + WriteOp& set_omap( + const boost::container::flat_map& map) &; + WriteOp&& set_omap( + const boost::container::flat_map& map) && { + return std::move(set_omap(map)); + } + WriteOp& set_omap_header(ceph::buffer::list&& bl) &; + WriteOp&& set_omap_header(ceph::buffer::list&& bl) && { + return std::move(set_omap_header(std::move(bl))); + } + WriteOp& clear_omap() &; + WriteOp&& clear_omap() && { + return std::move(clear_omap()); + } + WriteOp& rm_omap_keys(const boost::container::flat_set& to_rm) &; + WriteOp&& rm_omap_keys(const boost::container::flat_set& to_rm) && { + return std::move(rm_omap_keys(to_rm)); + } + WriteOp& set_alloc_hint(uint64_t expected_object_size, + uint64_t expected_write_size, + alloc_hint::alloc_hint_t flags) &; + WriteOp&& set_alloc_hint(uint64_t expected_object_size, + uint64_t expected_write_size, + alloc_hint::alloc_hint_t flags) && { + return std::move(set_alloc_hint(expected_object_size, + expected_write_size, + flags)); + } + + // Chaining versions of functions from Op + WriteOp& set_excl() & { + Op::set_excl(); + return *this; + } + WriteOp&& set_excl() && { + Op::set_excl(); + return std::move(*this); + } + + WriteOp& set_failok() & { + Op::set_failok(); + return *this; + } + WriteOp&& set_failok() && { + Op::set_failok(); + return std::move(*this); + } + + WriteOp& set_fadvise_random() & { + Op::set_fadvise_random(); + return *this; + } + WriteOp&& set_fadvise_random() && { + Op::set_fadvise_random(); + return std::move(*this); + } + + WriteOp& set_fadvise_sequential() & { + Op::set_fadvise_sequential(); + return *this; + } + WriteOp&& set_fadvise_sequential() && { + Op::set_fadvise_sequential(); + return std::move(*this); + } + + WriteOp& set_fadvise_willneed() & { + Op::set_fadvise_willneed(); + return *this; + } + WriteOp&& set_fadvise_willneed() && { + Op::set_fadvise_willneed(); + return std::move(*this); + } + + WriteOp& set_fadvise_dontneed() & { + Op::set_fadvise_dontneed(); + return *this; + } + WriteOp&& set_fadvise_dontneed() && { + Op::set_fadvise_dontneed(); + return std::move(*this); + } + + WriteOp& set_fadvise_nocache() & { + Op::set_fadvise_nocache(); + return *this; + } + WriteOp&& set_fadvise_nocache() && { + Op::set_fadvise_nocache(); + return std::move(*this); + } + + WriteOp& cmpext(uint64_t off, ceph::buffer::list&& cmp_bl, std::size_t* s) & { + Op::cmpext(off, std::move(cmp_bl), s); + return *this; + } + WriteOp&& cmpext(uint64_t off, ceph::buffer::list&& cmp_bl, std::size_t* s) && { + Op::cmpext(off, std::move(cmp_bl), s); + return std::move(*this); + } + + WriteOp& cmpxattr(std::string_view name, cmpxattr_op op, + const ceph::buffer::list& val) & { + Op::cmpxattr(name, op, val); + return *this; + } + WriteOp&& cmpxattr(std::string_view name, cmpxattr_op op, + const ceph::buffer::list& val) && { + Op::cmpxattr(name, op, val); + return std::move(*this); + } + + WriteOp& cmpxattr(std::string_view name, cmpxattr_op op, std::uint64_t val) & { + Op::cmpxattr(name, op, val); + return *this; + } + WriteOp&& cmpxattr(std::string_view name, cmpxattr_op op, std::uint64_t val) && { + Op::cmpxattr(name, op, val); + return std::move(*this); + } + + WriteOp& assert_version(uint64_t ver) & { + Op::assert_version(ver); + return *this; + } + WriteOp&& assert_version(uint64_t ver) && { + Op::assert_version(ver); + return std::move(*this); + } + + WriteOp& assert_exists() & { + Op::assert_exists(); + return *this; + } + WriteOp&& assert_exists() && { + Op::assert_exists(); + return std::move(*this); + } + + WriteOp& cmp_omap( + const boost::container::flat_map< + std::string, std::pair>& assertions) & { + Op::cmp_omap(assertions); + return *this; + } + WriteOp&& cmp_omap( + const boost::container::flat_map< + std::string, std::pair>& assertions) && { + Op::cmp_omap(assertions); + return std::move(*this); + } + + WriteOp& exec(std::string_view cls, std::string_view method, + const ceph::buffer::list& inbl, + ceph::buffer::list* out, + boost::system::error_code* ec = nullptr) & { + Op::exec(cls, method, inbl, out, ec); + return *this; + } + WriteOp&& exec(std::string_view cls, std::string_view method, + const ceph::buffer::list& inbl, + ceph::buffer::list* out, + boost::system::error_code* ec = nullptr) && { + Op::exec(cls, method, inbl, out, ec); + return std::move(*this); + } + + WriteOp& exec(std::string_view cls, std::string_view method, + const ceph::buffer::list& inbl, + fu2::unique_function f) & { + Op::exec(cls, method, inbl, std::move(f)); + return *this; + } + WriteOp&& exec(std::string_view cls, std::string_view method, + const ceph::buffer::list& inbl, + fu2::unique_function f) && { + Op::exec(cls, method, inbl, std::move(f)); + return std::move(*this); + } + + WriteOp& exec(std::string_view cls, std::string_view method, + const ceph::buffer::list& inbl, + fu2::unique_function f) & { + Op::exec(cls, method, inbl, std::move(f)); + return *this; + } + WriteOp&& exec(std::string_view cls, std::string_view method, + const ceph::buffer::list& inbl, + fu2::unique_function f) && { + Op::exec(cls, method, inbl, std::move(f)); + return std::move(*this); + } + + WriteOp& exec(std::string_view cls, std::string_view method, + const ceph::buffer::list& inbl, + boost::system::error_code* ec = nullptr) & { + Op::exec(cls, method, inbl, ec); + return *this; + } + WriteOp&& exec(std::string_view cls, std::string_view method, + const ceph::buffer::list& inbl, + boost::system::error_code* ec = nullptr) && { + Op::exec(cls, method, inbl, ec); + return std::move(*this); + } + + template + WriteOp& exec(ClsOp&& clsop) & { + return clsop(*this); + } + template + WriteOp&& exec(ClsOp&& clsop) && { + return std::move(clsop(*this)); + } + template + WriteOp& exec(ClsWriteOp&& clsop) & { + return clsop(*this); + } + template + WriteOp&& exec(ClsWriteOp&& clsop) && { + return std::move(clsop(*this)); + } + + + // Flags that apply to all ops in the operation vector + WriteOp& balance_reads() & { + Op::balance_reads(); + return *this; + } + WriteOp&& balance_reads() && { + Op::balance_reads(); + return std::move(*this); + } + WriteOp& localize_reads() & { + Op::localize_reads(); + return *this; + } + WriteOp&& localize_reads() && { + Op::localize_reads(); + return std::move(*this); + } + WriteOp& order_reads_writes() & { + Op::order_reads_writes(); + return *this; + } + WriteOp&& order_reads_writes() && { + Op::order_reads_writes(); + return std::move(*this); + } + WriteOp& ignore_cache() & { + Op::ignore_cache(); + return *this; + } + WriteOp&& ignore_cache() && { + Op::ignore_cache(); + return std::move(*this); + } + WriteOp& skiprwlocks() & { + Op::skiprwlocks(); + return *this; + } + WriteOp&& skiprwlocks() && { + Op::skiprwlocks(); + return std::move(*this); + } + WriteOp& ignore_overlay() & { + Op::ignore_overlay(); + return *this; + } + WriteOp&& ignore_overlay() && { + Op::ignore_overlay(); + return std::move(*this); + } + WriteOp& full_try() & { + Op::full_try(); + return *this; + } + WriteOp&& full_try() && { + Op::full_try(); + return std::move(*this); + } + WriteOp& full_force() & { + Op::full_force(); + return *this; + } + WriteOp&& full_force() && { + Op::full_force(); + return std::move(*this); + } + WriteOp& ignore_redirect() & { + Op::ignore_redirect(); + return *this; + } + WriteOp&& ignore_redirect() && { + Op::ignore_redirect(); + return std::move(*this); + } + WriteOp& ordersnap() & { + Op::ordersnap(); + return *this; + } + WriteOp&& ordersnap() && { + Op::ordersnap(); + return std::move(*this); + } + WriteOp& returnvec() & { + Op::returnvec(); + return *this; + } + WriteOp&& returnvec() && { + Op::returnvec(); + return std::move(*this); + } }; diff --git a/src/neorados/RADOS.cc b/src/neorados/RADOS.cc index ece5697a03fcf..1b49db3476295 100644 --- a/src/neorados/RADOS.cc +++ b/src/neorados/RADOS.cc @@ -562,149 +562,173 @@ std::ostream& operator <<(std::ostream& m, const Op& o) { // ReadOp / WriteOp -void ReadOp::read(size_t off, uint64_t len, cb::list* out, - bs::error_code* ec) { +ReadOp& ReadOp::read(size_t off, uint64_t len, cb::list* out, + bs::error_code* ec) & { reinterpret_cast(&impl)->op.read(off, len, ec, out); + return *this; } -void ReadOp::get_xattr(std::string_view name, cb::list* out, - bs::error_code* ec) { +ReadOp& ReadOp::get_xattr(std::string_view name, cb::list* out, + bs::error_code* ec) & { reinterpret_cast(&impl)->op.getxattr(name, ec, out); + return *this; } -void ReadOp::get_omap_header(cb::list* out, - bs::error_code* ec) { +ReadOp& ReadOp::get_omap_header(cb::list* out, + bs::error_code* ec) & { reinterpret_cast(&impl)->op.omap_get_header(ec, out); + return *this; } -void ReadOp::sparse_read(uint64_t off, uint64_t len, cb::list* out, - std::vector>* extents, - bs::error_code* ec) { +ReadOp& ReadOp::sparse_read(uint64_t off, uint64_t len, cb::list* out, + std::vector>* extents, + bs::error_code* ec) & { reinterpret_cast(&impl)->op.sparse_read(off, len, ec, extents, out); + return *this; } -void ReadOp::stat(std::uint64_t* size, ceph::real_time* mtime, - bs::error_code* ec) { +ReadOp& ReadOp::stat(std::uint64_t* size, ceph::real_time* mtime, + bs::error_code* ec) & { reinterpret_cast(&impl)->op.stat(size, mtime, ec); + return *this; } -void ReadOp::get_omap_keys(std::optional start_after, - std::uint64_t max_return, - bc::flat_set* keys, - bool* done, - bs::error_code* ec) { +ReadOp& ReadOp::get_omap_keys(std::optional start_after, + std::uint64_t max_return, + bc::flat_set* keys, + bool* done, + bs::error_code* ec) & { reinterpret_cast(&impl)->op.omap_get_keys(start_after, max_return, ec, keys, done); + return *this; } -void ReadOp::get_xattrs(bc::flat_map* kv, - bs::error_code* ec) { +ReadOp& ReadOp::get_xattrs(bc::flat_map* kv, + bs::error_code* ec) & { reinterpret_cast(&impl)->op.getxattrs(ec, kv); + return *this; } -void ReadOp::get_omap_vals(std::optional start_after, - std::optional filter_prefix, - uint64_t max_return, - bc::flat_map* kv, - bool* done, - bs::error_code* ec) { +ReadOp& ReadOp::get_omap_vals(std::optional start_after, + std::optional filter_prefix, + uint64_t max_return, + bc::flat_map* kv, + bool* done, + bs::error_code* ec) & { reinterpret_cast(&impl)->op.omap_get_vals(start_after, filter_prefix, max_return, ec, kv, done); + return *this; } -void ReadOp::get_omap_vals_by_keys( +ReadOp& ReadOp::get_omap_vals_by_keys( const bc::flat_set& keys, bc::flat_map* kv, - bs::error_code* ec) { + bs::error_code* ec) & { reinterpret_cast(&impl)->op.omap_get_vals_by_keys(keys, ec, kv); + return *this; } -void ReadOp::list_watchers(std::vector* watchers, - bs::error_code* ec) { +ReadOp& ReadOp::list_watchers(std::vector* watchers, + bs::error_code* ec) & { reinterpret_cast(&impl)-> op.list_watchers(watchers, ec); + return *this; } -void ReadOp::list_snaps(SnapSet* snaps, - bs::error_code* ec) { +ReadOp& ReadOp::list_snaps(SnapSet* snaps, + bs::error_code* ec) & { reinterpret_cast(&impl)->op.list_snaps(snaps, nullptr, ec); + return *this; } // WriteOp -void WriteOp::set_mtime(ceph::real_time t) { +WriteOp& WriteOp::set_mtime(ceph::real_time t) & { auto o = reinterpret_cast(&impl); o->mtime = t; + return *this; } -void WriteOp::create(bool exclusive) { +WriteOp& WriteOp::create(bool exclusive) & { reinterpret_cast(&impl)->op.create(exclusive); + return *this; } -void WriteOp::write(uint64_t off, bufferlist&& bl) { +WriteOp& WriteOp::write(uint64_t off, bufferlist&& bl) & { reinterpret_cast(&impl)->op.write(off, bl); + return *this; } -void WriteOp::write_full(bufferlist&& bl) { +WriteOp& WriteOp::write_full(bufferlist&& bl) & { reinterpret_cast(&impl)->op.write_full(bl); + return *this; } -void WriteOp::writesame(uint64_t off, uint64_t write_len, bufferlist&& bl) { +WriteOp& WriteOp::writesame(uint64_t off, uint64_t write_len, bufferlist&& bl) & { reinterpret_cast(&impl)->op.writesame(off, write_len, bl); + return *this; } -void WriteOp::append(bufferlist&& bl) { +WriteOp& WriteOp::append(bufferlist&& bl) & { reinterpret_cast(&impl)->op.append(bl); + return *this; } -void WriteOp::remove() { +WriteOp& WriteOp::remove() & { reinterpret_cast(&impl)->op.remove(); + return *this; } -void WriteOp::truncate(uint64_t off) { +WriteOp& WriteOp::truncate(uint64_t off) & { reinterpret_cast(&impl)->op.truncate(off); + return *this; } -void WriteOp::zero(uint64_t off, uint64_t len) { +WriteOp& WriteOp::zero(uint64_t off, uint64_t len) & { reinterpret_cast(&impl)->op.zero(off, len); + return *this; } -void WriteOp::rmxattr(std::string_view name) { +WriteOp& WriteOp::rmxattr(std::string_view name) & { reinterpret_cast(&impl)->op.rmxattr(name); + return *this; } -void WriteOp::setxattr(std::string_view name, - bufferlist&& bl) { +WriteOp& WriteOp::setxattr(std::string_view name, + bufferlist&& bl) & { reinterpret_cast(&impl)->op.setxattr(name, bl); + return *this; } -void WriteOp::rollback(uint64_t snapid) { +WriteOp& WriteOp::rollback(uint64_t snapid) & { reinterpret_cast(&impl)->op.rollback(snapid); + return *this; } -void WriteOp::set_omap( - const bc::flat_map& map) { +WriteOp& WriteOp::set_omap( + const bc::flat_map& map) & { reinterpret_cast(&impl)->op.omap_set(map); + return *this; } -void WriteOp::set_omap_header(bufferlist&& bl) { +WriteOp& WriteOp::set_omap_header(bufferlist&& bl) & { reinterpret_cast(&impl)->op.omap_set_header(bl); + return *this; } -void WriteOp::clear_omap() { +WriteOp& WriteOp::clear_omap() & { reinterpret_cast(&impl)->op.omap_clear(); + return *this; } -void WriteOp::rm_omap_keys( - const bc::flat_set& to_rm) { +WriteOp& WriteOp::rm_omap_keys(const bc::flat_set& to_rm) & { reinterpret_cast(&impl)->op.omap_rm_keys(to_rm); + return *this; } -void WriteOp::set_alloc_hint(uint64_t expected_object_size, - uint64_t expected_write_size, - alloc_hint::alloc_hint_t flags) { +WriteOp& WriteOp::set_alloc_hint(uint64_t expected_object_size, + uint64_t expected_write_size, + alloc_hint::alloc_hint_t flags) & { using namespace alloc_hint; static_assert(sequential_write == static_cast(CEPH_OSD_ALLOC_HINT_FLAG_SEQUENTIAL_WRITE)); @@ -730,6 +754,7 @@ void WriteOp::set_alloc_hint(uint64_t expected_object_size, reinterpret_cast(&impl)->op.set_alloc_hint(expected_object_size, expected_write_size, flags); + return *this; } // RADOS diff --git a/src/test/librados_test_stub/NeoradosTestStub.cc b/src/test/librados_test_stub/NeoradosTestStub.cc index c1b29bad6c476..de12496c86130 100644 --- a/src/test/librados_test_stub/NeoradosTestStub.cc +++ b/src/test/librados_test_stub/NeoradosTestStub.cc @@ -437,8 +437,8 @@ void Op::exec(std::string_view cls, std::string_view method, o->ops.push_back(op); } -void ReadOp::read(size_t off, uint64_t len, ceph::buffer::list* out, - boost::system::error_code* ec) { +ReadOp& ReadOp::read(size_t off, uint64_t len, ceph::buffer::list* out, + boost::system::error_code* ec) & { auto o = *reinterpret_cast(&impl); librados::ObjectOperationTestImpl op; if (out != nullptr) { @@ -454,13 +454,14 @@ void ReadOp::read(size_t off, uint64_t len, ceph::buffer::list* out, save_operation_ec, std::bind(op, _1, _2, _3, _4, _5, _6), ec); } o->ops.push_back(op); + return *this; } -void ReadOp::sparse_read(uint64_t off, uint64_t len, - ceph::buffer::list* out, - std::vector>* extents, - boost::system::error_code* ec) { +ReadOp& ReadOp::sparse_read(uint64_t off, uint64_t len, + ceph::buffer::list* out, + std::vector>* extents, + boost::system::error_code* ec) & { auto o = *reinterpret_cast(&impl); librados::ObjectOperationTestImpl op = [off, len, out, extents] @@ -480,9 +481,10 @@ void ReadOp::sparse_read(uint64_t off, uint64_t len, std::bind(op, _1, _2, _3, _4, _5, _6), ec); } o->ops.push_back(op); + return *this; } -void ReadOp::list_snaps(SnapSet* snaps, bs::error_code* ec) { +ReadOp& ReadOp::list_snaps(SnapSet* snaps, bs::error_code* ec) & { auto o = *reinterpret_cast(&impl); librados::ObjectOperationTestImpl op = [snaps] @@ -510,55 +512,64 @@ void ReadOp::list_snaps(SnapSet* snaps, bs::error_code* ec) { std::bind(op, _1, _2, _3, _4, _5, _6), ec); } o->ops.push_back(op); + return *this; } -void WriteOp::create(bool exclusive) { +WriteOp& WriteOp::create(bool exclusive) & { auto o = *reinterpret_cast(&impl); o->ops.push_back(std::bind( &librados::TestIoCtxImpl::create, _1, _2, exclusive, _5)); + return *this; } -void WriteOp::write(uint64_t off, ceph::buffer::list&& bl) { +WriteOp& WriteOp::write(uint64_t off, ceph::buffer::list&& bl) & { auto o = *reinterpret_cast(&impl); o->ops.push_back(std::bind( &librados::TestIoCtxImpl::write, _1, _2, bl, bl.length(), off, _5)); + return *this; } -void WriteOp::write_full(ceph::buffer::list&& bl) { +WriteOp& WriteOp::write_full(ceph::buffer::list&& bl) & { auto o = *reinterpret_cast(&impl); o->ops.push_back(std::bind( &librados::TestIoCtxImpl::write_full, _1, _2, bl, _5)); + return *this; } -void WriteOp::remove() { +WriteOp& WriteOp::remove() & { auto o = *reinterpret_cast(&impl); o->ops.push_back(std::bind( &librados::TestIoCtxImpl::remove, _1, _2, _5)); + return *this; } -void WriteOp::truncate(uint64_t off) { +WriteOp& WriteOp::truncate(uint64_t off) & { auto o = *reinterpret_cast(&impl); o->ops.push_back(std::bind( &librados::TestIoCtxImpl::truncate, _1, _2, off, _5)); + return *this; } -void WriteOp::zero(uint64_t off, uint64_t len) { +WriteOp& WriteOp::zero(uint64_t off, uint64_t len) & { auto o = *reinterpret_cast(&impl); o->ops.push_back(std::bind( &librados::TestIoCtxImpl::zero, _1, _2, off, len, _5)); + return *this; } -void WriteOp::writesame(std::uint64_t off, std::uint64_t write_len, - ceph::buffer::list&& bl) { +WriteOp& WriteOp::writesame(std::uint64_t off, std::uint64_t write_len, + ceph::buffer::list&& bl) & { auto o = *reinterpret_cast(&impl); o->ops.push_back(std::bind( &librados::TestIoCtxImpl::writesame, _1, _2, bl, write_len, off, _5)); + return *this; } -void WriteOp::set_alloc_hint(uint64_t expected_object_size, - uint64_t expected_write_size, - alloc_hint::alloc_hint_t flags) { +WriteOp& WriteOp::set_alloc_hint(uint64_t expected_object_size, + uint64_t expected_write_size, + alloc_hint::alloc_hint_t flags) & { // no-op + return *this; } RADOS::RADOS() = default; -- 2.39.5