diff options
Diffstat (limited to 'src/mon/MonOpRequest.h')
-rw-r--r-- | src/mon/MonOpRequest.h | 238 |
1 files changed, 238 insertions, 0 deletions
diff --git a/src/mon/MonOpRequest.h b/src/mon/MonOpRequest.h new file mode 100644 index 000000000..73275e81e --- /dev/null +++ b/src/mon/MonOpRequest.h @@ -0,0 +1,238 @@ +// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*- +// vim: ts=8 sw=2 smarttab +/* + * Ceph - scalable distributed file system + * + * Copyright (C) 2015 Red Hat <contact@redhat.com> + * Copyright (C) 2015 SUSE LINUX GmbH + * + * This is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License version 2.1, as published by the Free Software + * Foundation. See file COPYING. + */ + +#ifndef MON_OPREQUEST_H_ +#define MON_OPREQUEST_H_ +#include <iosfwd> +#include <stdint.h> + +#include "common/TrackedOp.h" +#include "mon/Session.h" +#include "msg/Message.h" + +struct MonOpRequest : public TrackedOp { + friend class OpTracker; + + void mark_dispatch() { + mark_event("monitor_dispatch"); + } + void mark_wait_for_quorum() { + mark_event("wait_for_quorum"); + } + void mark_zap() { + mark_event("monitor_zap"); + } + void mark_forwarded() { + mark_event("forwarded"); + forwarded_to_leader = true; + } + + void mark_svc_event(const std::string &service, const std::string &event) { + std::string s = service; + s.append(":").append(event); + mark_event(s); + } + + void mark_logmon_event(const std::string &event) { + mark_svc_event("logm", event); + } + void mark_osdmon_event(const std::string &event) { + mark_svc_event("osdmap", event); + } + void mark_pgmon_event(const std::string &event) { + mark_svc_event("pgmap", event); + } + void mark_mdsmon_event(const std::string &event) { + mark_svc_event("mdsmap", event); + } + void mark_authmon_event(const std::string &event) { + mark_svc_event("auth", event); + } + void mark_paxos_event(const std::string &event) { + mark_svc_event("paxos", event); + } + + + enum op_type_t { + OP_TYPE_NONE = 0, ///< no type defined (default) + OP_TYPE_SERVICE, ///< belongs to a Paxos Service or similar + OP_TYPE_MONITOR, ///< belongs to the Monitor class + OP_TYPE_ELECTION, ///< belongs to the Elector class + OP_TYPE_PAXOS, ///< refers to Paxos messages + OP_TYPE_COMMAND, ///< is a command + }; + + MonOpRequest(const MonOpRequest &other) = delete; + MonOpRequest & operator = (const MonOpRequest &other) = delete; + +private: + Message *request; + utime_t dequeued_time; + RefCountedPtr session; + ConnectionRef con; + bool forwarded_to_leader; + op_type_t op_type; + + MonOpRequest(Message *req, OpTracker *tracker) : + TrackedOp(tracker, + req->get_recv_stamp().is_zero() ? + ceph_clock_now() : req->get_recv_stamp()), + request(req), + con(NULL), + forwarded_to_leader(false), + op_type(OP_TYPE_NONE) + { + if (req) { + con = req->get_connection(); + if (con) { + session = con->get_priv(); + } + } + } + + void _dump(ceph::Formatter *f) const override { + { + f->open_array_section("events"); + std::lock_guard l(lock); + for (auto i = events.begin(); i != events.end(); ++i) { + f->open_object_section("event"); + f->dump_string("event", i->str); + f->dump_stream("time") << i->stamp; + + auto i_next = i + 1; + + if (i_next < events.end()) { + f->dump_float("duration", i_next->stamp - i->stamp); + } else { + f->dump_float("duration", events.rbegin()->stamp - get_initiated()); + } + + f->close_section(); + } + f->close_section(); + f->open_object_section("info"); + f->dump_int("seq", seq); + f->dump_bool("src_is_mon", is_src_mon()); + f->dump_stream("source") << request->get_source_inst(); + f->dump_bool("forwarded_to_leader", forwarded_to_leader); + f->close_section(); + } + } + +protected: + void _dump_op_descriptor_unlocked(std::ostream& stream) const override { + get_req()->print(stream); + } + +public: + ~MonOpRequest() override { + request->put(); + } + + MonSession *get_session() const { + return static_cast<MonSession*>(session.get()); + } + + template<class T> + T *get_req() const { return static_cast<T*>(request); } + + Message *get_req() const { return get_req<Message>(); } + + int get_req_type() const { + if (!request) + return 0; + return request->get_type(); + } + + ConnectionRef get_connection() { return con; } + + void set_session(MonSession *s) { + session.reset(s); + } + + bool is_src_mon() const { + return (con && con->get_peer_type() & CEPH_ENTITY_TYPE_MON); + } + + typedef boost::intrusive_ptr<MonOpRequest> Ref; + + void set_op_type(op_type_t t) { + op_type = t; + } + void set_type_service() { + set_op_type(OP_TYPE_SERVICE); + } + void set_type_monitor() { + set_op_type(OP_TYPE_MONITOR); + } + void set_type_paxos() { + set_op_type(OP_TYPE_PAXOS); + } + void set_type_election_or_ping() { + set_op_type(OP_TYPE_ELECTION); + } + void set_type_command() { + set_op_type(OP_TYPE_COMMAND); + } + + op_type_t get_op_type() { + return op_type; + } + + bool is_type_service() { + return (get_op_type() == OP_TYPE_SERVICE); + } + bool is_type_monitor() { + return (get_op_type() == OP_TYPE_MONITOR); + } + bool is_type_paxos() { + return (get_op_type() == OP_TYPE_PAXOS); + } + bool is_type_election_or_ping() { + return (get_op_type() == OP_TYPE_ELECTION); + } + bool is_type_command() { + return (get_op_type() == OP_TYPE_COMMAND); + } +}; + +typedef MonOpRequest::Ref MonOpRequestRef; + +struct C_MonOp : public Context +{ + MonOpRequestRef op; + + explicit C_MonOp(MonOpRequestRef o) : + op(o) { } + + void finish(int r) override { + if (op && r == -ECANCELED) { + op->mark_event("callback canceled"); + } else if (op && r == -EAGAIN) { + op->mark_event("callback retry"); + } else if (op && r == 0) { + op->mark_event("callback finished"); + } + _finish(r); + } + + void mark_op_event(const std::string &event) { + if (op) + op->mark_event(event); + } + + virtual void _finish(int r) = 0; +}; + +#endif /* MON_OPREQUEST_H_ */ |