}
static watch_info_t create_watch_info(const OSDOp& osd_op,
- const MOSDOp& msg)
+ const OpsExecuter::ExecutableMessage& msg)
{
using crimson::common::local_conf;
const uint32_t timeout =
crimson::net::ConnectionRef conn;
watch_info_t info;
- connect_ctx_t(const OSDOp& osd_op, const MOSDOp& msg)
+ connect_ctx_t(const OSDOp& osd_op, const ExecutableMessage& msg)
: key(osd_op.op.watch.cookie, msg.get_reqid().name),
conn(msg.get_connection()),
info(create_watch_info(osd_op, msg)) {
ObjectContext::watch_key_t key;
bool send_disconnect{ false };
- disconnect_ctx_t(const OSDOp& osd_op, const MOSDOp& msg)
+ disconnect_ctx_t(const OSDOp& osd_op, const ExecutableMessage& msg)
: key(osd_op.op.watch.cookie, msg.get_reqid().name) {
}
};
const uint64_t client_gid;
const epoch_t epoch;
- notify_ctx_t(const MOSDOp& msg)
+ notify_ctx_t(const ExecutableMessage& msg)
: conn(msg.get_connection()),
client_gid(msg.get_reqid().name.num()),
epoch(msg.get_map_epoch()) {
uint64_t notify_id;
ceph::bufferlist reply_bl;
- notifyack_ctx_t(const MOSDOp& msg) : entity(msg.get_reqid().name) {
+ notifyack_ctx_t(const ExecutableMessage& msg)
+ : entity(msg.get_reqid().name) {
}
};
return with_effect_on_obc(notifyack_ctx_t{ get_message() },
#include <memory>
#include <type_traits>
+#include <utility>
#include <boost/intrusive_ptr.hpp>
#include <boost/smart_ptr/intrusive_ref_counter.hpp>
#include <boost/smart_ptr/local_shared_ptr.hpp>
#include <seastar/core/shared_future.hh>
#include "common/dout.h"
+#include "common/static_ptr.h"
#include "messages/MOSDOp.h"
#include "os/Transaction.h"
#include "osd/osd_types.h"
IOInterruptCondition, T>;
public:
+ // ExecutableMessage -- an interface class to allow using OpsExecuter
+ // with other message types than just the `MOSDOp`. The type erasure
+ // happens in the ctor of `OpsExecuter`.
+ struct ExecutableMessage {
+ virtual crimson::net::ConnectionRef get_connection() const = 0;
+ virtual osd_reqid_t get_reqid() const = 0;
+ virtual epoch_t get_map_epoch() const = 0;
+ virtual entity_inst_t get_orig_source_inst() const = 0;
+ virtual uint64_t get_features() const = 0;
+ };
+
+ template <class ImplT>
+ class ExecutableMessagePimpl final : ExecutableMessage {
+ const ImplT* pimpl;
+ public:
+ ExecutableMessagePimpl(const ImplT* pimpl) : pimpl(pimpl) {
+ }
+ crimson::net::ConnectionRef get_connection() const final {
+ return pimpl->get_connection();
+ }
+ osd_reqid_t get_reqid() const final {
+ return pimpl->get_reqid();
+ }
+ epoch_t get_map_epoch() const final {
+ return pimpl->get_map_epoch();
+ }
+ entity_inst_t get_orig_source_inst() const final {
+ return pimpl->get_orig_source_inst();
+ }
+ uint64_t get_features() const final {
+ return pimpl->get_features();
+ }
+ };
+
// because OpsExecuter is pretty heavy-weight object we want to ensure
// it's not copied nor even moved by accident. Performance is the sole
// reason for prohibiting that.
const OpInfo& op_info;
const pg_pool_t& pool_info; // for the sake of the ObjClass API
PGBackend& backend;
- const MOSDOp& msg;
+ ceph::static_ptr<ExecutableMessage,
+ sizeof(ExecutableMessagePimpl<void>)> msg;
std::optional<osd_op_params_t> osd_op_params;
bool user_modify = false;
ceph::os::Transaction txn;
}
public:
+ template <class MsgT>
OpsExecuter(ObjectContextRef obc,
const OpInfo& op_info,
const pg_pool_t& pool_info,
PGBackend& backend,
- const MOSDOp& msg)
+ const MsgT& msg)
: obc(std::move(obc)),
op_info(op_info),
pool_info(pool_info),
backend(backend),
- msg(msg) {
+ msg(std::in_place_type_t<ExecutableMessagePimpl<MsgT>>{}, &msg) {
}
interruptible_errorated_future<osd_op_errorator>
}
const auto& get_message() const {
- return msg;
+ return *msg;
}
size_t get_processed_rw_ops_num() const {