]>
Commit | Line | Data |
---|---|---|
1 | // -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*- | |
2 | // vim: ts=8 sw=2 smarttab | |
3 | /* | |
4 | * Ceph - scalable distributed file system | |
5 | * | |
6 | * Copyright (C) 2015 Red Hat <contact@redhat.com> | |
7 | * Copyright (C) 2015 SUSE LINUX GmbH | |
8 | * | |
9 | * This is free software; you can redistribute it and/or | |
10 | * modify it under the terms of the GNU Lesser General Public | |
11 | * License version 2.1, as published by the Free Software | |
12 | * Foundation. See file COPYING. | |
13 | */ | |
14 | ||
15 | #ifndef MON_OPREQUEST_H_ | |
16 | #define MON_OPREQUEST_H_ | |
17 | #include <iosfwd> | |
18 | #include <stdint.h> | |
19 | ||
20 | #include "common/TrackedOp.h" | |
21 | #include "include/memory.h" | |
22 | #include "mon/Session.h" | |
23 | #include "msg/Message.h" | |
24 | ||
25 | struct MonOpRequest : public TrackedOp { | |
26 | friend class OpTracker; | |
27 | ||
28 | void mark_dispatch() { | |
29 | mark_event("monitor_dispatch"); | |
30 | } | |
31 | void mark_wait_for_quorum() { | |
32 | mark_event("wait_for_quorum"); | |
33 | } | |
34 | void mark_zap() { | |
35 | mark_event("monitor_zap"); | |
36 | } | |
37 | void mark_forwarded() { | |
38 | mark_event("forwarded"); | |
39 | forwarded_to_leader = true; | |
40 | } | |
41 | ||
42 | void mark_svc_event(const string &service, const string &event) { | |
43 | string s = service; | |
44 | s.append(":").append(event); | |
45 | mark_event_string(s); | |
46 | } | |
47 | ||
48 | void mark_logmon_event(const string &event) { | |
49 | mark_svc_event("logm", event); | |
50 | } | |
51 | void mark_osdmon_event(const string &event) { | |
52 | mark_svc_event("osdmap", event); | |
53 | } | |
54 | void mark_pgmon_event(const string &event) { | |
55 | mark_svc_event("pgmap", event); | |
56 | } | |
57 | void mark_mdsmon_event(const string &event) { | |
58 | mark_svc_event("mdsmap", event); | |
59 | } | |
60 | void mark_authmon_event(const string &event) { | |
61 | mark_svc_event("auth", event); | |
62 | } | |
63 | void mark_paxos_event(const string &event) { | |
64 | mark_svc_event("paxos", event); | |
65 | } | |
66 | ||
67 | ||
68 | enum op_type_t { | |
69 | OP_TYPE_NONE = 0, ///< no type defined (default) | |
70 | OP_TYPE_SERVICE, ///< belongs to a Paxos Service or similar | |
71 | OP_TYPE_MONITOR, ///< belongs to the Monitor class | |
72 | OP_TYPE_ELECTION, ///< belongs to the Elector class | |
73 | OP_TYPE_PAXOS, ///< refers to Paxos messages | |
74 | OP_TYPE_COMMAND, ///< is a command | |
75 | }; | |
76 | ||
77 | MonOpRequest(const MonOpRequest &other) = delete; | |
78 | MonOpRequest & operator = (const MonOpRequest &other) = delete; | |
79 | ||
80 | private: | |
81 | Message *request; | |
82 | utime_t dequeued_time; | |
83 | MonSession *session; | |
84 | ConnectionRef con; | |
85 | bool forwarded_to_leader; | |
86 | op_type_t op_type; | |
87 | ||
88 | MonOpRequest(Message *req, OpTracker *tracker) : | |
89 | TrackedOp(tracker, | |
90 | req->get_recv_stamp().is_zero() ? | |
91 | req->get_recv_stamp() : ceph_clock_now()), | |
92 | request(req), | |
93 | session(NULL), | |
94 | con(NULL), | |
95 | forwarded_to_leader(false), | |
96 | op_type(OP_TYPE_NONE) | |
97 | { | |
98 | mark_event("header_read", request->get_recv_stamp()); | |
99 | mark_event("throttled", request->get_throttle_stamp()); | |
100 | mark_event("all_read", request->get_recv_complete_stamp()); | |
101 | mark_event("dispatched", request->get_dispatch_stamp()); | |
102 | ||
103 | if (req) { | |
104 | con = req->get_connection(); | |
105 | if (con) { | |
106 | session = static_cast<MonSession*>(con->get_priv()); | |
107 | } | |
108 | } | |
109 | } | |
110 | ||
111 | void _dump(Formatter *f) const override { | |
112 | { | |
113 | f->open_array_section("events"); | |
114 | Mutex::Locker l(lock); | |
115 | for (auto& i : events) { | |
116 | f->dump_object("event", i); | |
117 | } | |
118 | f->close_section(); | |
119 | f->open_object_section("info"); | |
120 | f->dump_int("seq", seq); | |
121 | f->dump_bool("src_is_mon", is_src_mon()); | |
122 | f->dump_stream("source") << request->get_source_inst(); | |
123 | f->dump_bool("forwarded_to_leader", forwarded_to_leader); | |
124 | f->close_section(); | |
125 | } | |
126 | } | |
127 | ||
128 | protected: | |
129 | void _dump_op_descriptor_unlocked(ostream& stream) const override { | |
130 | get_req()->print(stream); | |
131 | } | |
132 | ||
133 | public: | |
134 | ~MonOpRequest() override { | |
135 | request->put(); | |
136 | // certain ops may not have a session (e.g., AUTH or PING) | |
137 | if (session) | |
138 | session->put(); | |
139 | } | |
140 | ||
141 | MonSession *get_session() const { | |
142 | if (!session) | |
143 | return NULL; | |
144 | return session; | |
145 | } | |
146 | ||
147 | template<class T> | |
148 | T *get_req() const { return static_cast<T*>(request); } | |
149 | ||
150 | Message *get_req() const { return get_req<Message>(); } | |
151 | ||
152 | int get_req_type() const { | |
153 | if (!request) | |
154 | return 0; | |
155 | return request->get_type(); | |
156 | } | |
157 | ||
158 | ConnectionRef get_connection() { return con; } | |
159 | ||
160 | void set_session(MonSession *s) { | |
161 | if (session) { | |
162 | // we will be rewriting the existing session; drop the ref. | |
163 | session->put(); | |
164 | } | |
165 | ||
166 | if (s == NULL) { | |
167 | session = NULL; | |
168 | } else { | |
169 | session = static_cast<MonSession*>(s->get()); | |
170 | } | |
171 | } | |
172 | ||
173 | bool is_src_mon() const { | |
174 | return (con && con->get_peer_type() & CEPH_ENTITY_TYPE_MON); | |
175 | } | |
176 | ||
177 | typedef boost::intrusive_ptr<MonOpRequest> Ref; | |
178 | ||
179 | void set_op_type(op_type_t t) { | |
180 | op_type = t; | |
181 | } | |
182 | void set_type_service() { | |
183 | set_op_type(OP_TYPE_SERVICE); | |
184 | } | |
185 | void set_type_monitor() { | |
186 | set_op_type(OP_TYPE_MONITOR); | |
187 | } | |
188 | void set_type_paxos() { | |
189 | set_op_type(OP_TYPE_PAXOS); | |
190 | } | |
191 | void set_type_election() { | |
192 | set_op_type(OP_TYPE_ELECTION); | |
193 | } | |
194 | void set_type_command() { | |
195 | set_op_type(OP_TYPE_COMMAND); | |
196 | } | |
197 | ||
198 | op_type_t get_op_type() { | |
199 | return op_type; | |
200 | } | |
201 | ||
202 | bool is_type_service() { | |
203 | return (get_op_type() == OP_TYPE_SERVICE); | |
204 | } | |
205 | bool is_type_monitor() { | |
206 | return (get_op_type() == OP_TYPE_MONITOR); | |
207 | } | |
208 | bool is_type_paxos() { | |
209 | return (get_op_type() == OP_TYPE_PAXOS); | |
210 | } | |
211 | bool is_type_election() { | |
212 | return (get_op_type() == OP_TYPE_ELECTION); | |
213 | } | |
214 | bool is_type_command() { | |
215 | return (get_op_type() == OP_TYPE_COMMAND); | |
216 | } | |
217 | }; | |
218 | ||
219 | typedef MonOpRequest::Ref MonOpRequestRef; | |
220 | ||
221 | struct C_MonOp : public Context | |
222 | { | |
223 | MonOpRequestRef op; | |
224 | ||
225 | explicit C_MonOp(MonOpRequestRef o) : | |
226 | op(o) { } | |
227 | ||
228 | void finish(int r) override { | |
229 | if (op && r == -ECANCELED) { | |
230 | op->mark_event("callback canceled"); | |
231 | } else if (op && r == -EAGAIN) { | |
232 | op->mark_event("callback retry"); | |
233 | } else if (op && r == 0) { | |
234 | op->mark_event("callback finished"); | |
235 | } | |
236 | _finish(r); | |
237 | } | |
238 | ||
239 | void mark_op_event(const string &event) { | |
240 | if (op) | |
241 | op->mark_event_string(event); | |
242 | } | |
243 | ||
244 | virtual void _finish(int r) = 0; | |
245 | }; | |
246 | ||
247 | #endif /* MON_OPREQUEST_H_ */ |