]>
Commit | Line | Data |
---|---|---|
7c673cae FG |
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) 2004-2006 Sage Weil <sage@newdream.net> | |
7 | * | |
8 | * This is free software; you can redistribute it and/or | |
9 | * modify it under the terms of the GNU Lesser General Public | |
10 | * License version 2.1, as published by the Free Software | |
11 | * Foundation. See file COPYING. | |
12 | * | |
13 | */ | |
7c673cae FG |
14 | #ifndef CEPH_MONCLIENT_H |
15 | #define CEPH_MONCLIENT_H | |
16 | ||
17 | #include <memory> | |
18 | ||
19 | #include "msg/Messenger.h" | |
20 | ||
21 | #include "MonMap.h" | |
11fdf7f2 | 22 | #include "MonSub.h" |
7c673cae FG |
23 | |
24 | #include "common/Timer.h" | |
25 | #include "common/Finisher.h" | |
26 | #include "common/config.h" | |
27 | ||
11fdf7f2 TL |
28 | #include "auth/AuthClient.h" |
29 | #include "auth/AuthServer.h" | |
7c673cae FG |
30 | |
31 | class MMonMap; | |
11fdf7f2 | 32 | class MConfig; |
7c673cae FG |
33 | class MMonGetVersionReply; |
34 | struct MMonSubscribeAck; | |
35 | class MMonCommandAck; | |
36 | struct MAuthReply; | |
7c673cae | 37 | class LogClient; |
11fdf7f2 | 38 | class AuthAuthorizer; |
7c673cae | 39 | class AuthClientHandler; |
11fdf7f2 TL |
40 | class AuthMethodList; |
41 | class AuthRegistry; | |
7c673cae FG |
42 | class KeyRing; |
43 | class RotatingKeyRing; | |
44 | ||
11fdf7f2 TL |
45 | class MonConnection { |
46 | public: | |
47 | MonConnection(CephContext *cct, | |
48 | ConnectionRef conn, | |
49 | uint64_t global_id, | |
50 | AuthRegistry *auth_registry); | |
51 | ~MonConnection(); | |
52 | MonConnection(MonConnection&& rhs) = default; | |
53 | MonConnection& operator=(MonConnection&&) = default; | |
54 | MonConnection(const MonConnection& rhs) = delete; | |
55 | MonConnection& operator=(const MonConnection&) = delete; | |
56 | int handle_auth(MAuthReply *m, | |
57 | const EntityName& entity_name, | |
58 | uint32_t want_keys, | |
59 | RotatingKeyRing* keyring); | |
60 | int authenticate(MAuthReply *m); | |
61 | void start(epoch_t epoch, | |
62 | const EntityName& entity_name); | |
63 | bool have_session() const; | |
64 | uint64_t get_global_id() const { | |
65 | return global_id; | |
66 | } | |
67 | ConnectionRef get_con() { | |
68 | return con; | |
69 | } | |
70 | std::unique_ptr<AuthClientHandler>& get_auth() { | |
71 | return auth; | |
72 | } | |
73 | ||
74 | int get_auth_request( | |
75 | uint32_t *method, | |
76 | std::vector<uint32_t> *preferred_modes, | |
77 | bufferlist *out, | |
78 | const EntityName& entity_name, | |
79 | uint32_t want_keys, | |
80 | RotatingKeyRing* keyring); | |
81 | int handle_auth_reply_more( | |
82 | AuthConnectionMeta *auth_meta, | |
83 | const bufferlist& bl, | |
84 | bufferlist *reply); | |
85 | int handle_auth_done( | |
86 | AuthConnectionMeta *auth_meta, | |
87 | uint64_t global_id, | |
88 | const bufferlist& bl, | |
89 | CryptoKey *session_key, | |
90 | std::string *connection_secret); | |
91 | int handle_auth_bad_method( | |
92 | uint32_t old_auth_method, | |
93 | int result, | |
94 | const std::vector<uint32_t>& allowed_methods, | |
95 | const std::vector<uint32_t>& allowed_modes); | |
96 | ||
97 | bool is_con(Connection *c) const { | |
98 | return con.get() == c; | |
99 | } | |
100 | ||
101 | private: | |
102 | int _negotiate(MAuthReply *m, | |
103 | const EntityName& entity_name, | |
104 | uint32_t want_keys, | |
105 | RotatingKeyRing* keyring); | |
106 | int _init_auth(uint32_t method, | |
107 | const EntityName& entity_name, | |
108 | uint32_t want_keys, | |
109 | RotatingKeyRing* keyring, | |
110 | bool msgr2); | |
111 | ||
112 | private: | |
113 | CephContext *cct; | |
114 | enum class State { | |
115 | NONE, | |
116 | NEGOTIATING, // v1 only | |
117 | AUTHENTICATING, // v1 and v2 | |
118 | HAVE_SESSION, | |
119 | }; | |
120 | State state = State::NONE; | |
121 | ConnectionRef con; | |
122 | int auth_method = -1; | |
123 | utime_t auth_start; | |
124 | ||
125 | std::unique_ptr<AuthClientHandler> auth; | |
126 | uint64_t global_id; | |
127 | ||
128 | AuthRegistry *auth_registry; | |
129 | }; | |
130 | ||
131 | ||
132 | struct MonClientPinger : public Dispatcher, | |
133 | public AuthClient { | |
7c673cae FG |
134 | |
135 | Mutex lock; | |
136 | Cond ping_recvd_cond; | |
137 | string *result; | |
138 | bool done; | |
11fdf7f2 TL |
139 | RotatingKeyRing *keyring; |
140 | std::unique_ptr<MonConnection> mc; | |
7c673cae | 141 | |
11fdf7f2 TL |
142 | MonClientPinger(CephContext *cct_, |
143 | RotatingKeyRing *keyring, | |
144 | string *res_) : | |
7c673cae FG |
145 | Dispatcher(cct_), |
146 | lock("MonClientPinger::lock"), | |
147 | result(res_), | |
11fdf7f2 TL |
148 | done(false), |
149 | keyring(keyring) | |
7c673cae FG |
150 | { } |
151 | ||
152 | int wait_for_reply(double timeout = 0.0) { | |
153 | utime_t until = ceph_clock_now(); | |
154 | until += (timeout > 0 ? timeout : cct->_conf->client_mount_timeout); | |
155 | done = false; | |
156 | ||
157 | int ret = 0; | |
158 | while (!done) { | |
159 | ret = ping_recvd_cond.WaitUntil(lock, until); | |
160 | if (ret == ETIMEDOUT) | |
161 | break; | |
162 | } | |
163 | return ret; | |
164 | } | |
165 | ||
166 | bool ms_dispatch(Message *m) override { | |
11fdf7f2 | 167 | std::lock_guard l(lock); |
7c673cae FG |
168 | if (m->get_type() != CEPH_MSG_PING) |
169 | return false; | |
170 | ||
171 | bufferlist &payload = m->get_payload(); | |
172 | if (result && payload.length() > 0) { | |
11fdf7f2 TL |
173 | auto p = std::cbegin(payload); |
174 | decode(*result, p); | |
7c673cae FG |
175 | } |
176 | done = true; | |
177 | ping_recvd_cond.SignalAll(); | |
178 | m->put(); | |
179 | return true; | |
180 | } | |
181 | bool ms_handle_reset(Connection *con) override { | |
11fdf7f2 | 182 | std::lock_guard l(lock); |
7c673cae FG |
183 | done = true; |
184 | ping_recvd_cond.SignalAll(); | |
185 | return true; | |
186 | } | |
187 | void ms_handle_remote_reset(Connection *con) override {} | |
188 | bool ms_handle_refused(Connection *con) override { | |
189 | return false; | |
190 | } | |
7c673cae | 191 | |
11fdf7f2 TL |
192 | // AuthClient |
193 | int get_auth_request( | |
194 | Connection *con, | |
195 | AuthConnectionMeta *auth_meta, | |
196 | uint32_t *auth_method, | |
197 | std::vector<uint32_t> *preferred_modes, | |
198 | bufferlist *bl) override { | |
199 | return mc->get_auth_request(auth_method, preferred_modes, bl, | |
200 | cct->_conf->name, 0, keyring); | |
7c673cae | 201 | } |
11fdf7f2 TL |
202 | int handle_auth_reply_more( |
203 | Connection *con, | |
204 | AuthConnectionMeta *auth_meta, | |
205 | const bufferlist& bl, | |
206 | bufferlist *reply) override { | |
207 | return mc->handle_auth_reply_more(auth_meta, bl, reply); | |
7c673cae | 208 | } |
11fdf7f2 TL |
209 | int handle_auth_done( |
210 | Connection *con, | |
211 | AuthConnectionMeta *auth_meta, | |
212 | uint64_t global_id, | |
213 | uint32_t con_mode, | |
214 | const bufferlist& bl, | |
215 | CryptoKey *session_key, | |
216 | std::string *connection_secret) override { | |
217 | return mc->handle_auth_done(auth_meta, global_id, bl, | |
218 | session_key, connection_secret); | |
219 | } | |
220 | int handle_auth_bad_method( | |
221 | Connection *con, | |
222 | AuthConnectionMeta *auth_meta, | |
223 | uint32_t old_auth_method, | |
224 | int result, | |
225 | const std::vector<uint32_t>& allowed_methods, | |
226 | const std::vector<uint32_t>& allowed_modes) override { | |
227 | return mc->handle_auth_bad_method(old_auth_method, result, | |
228 | allowed_methods, allowed_modes); | |
7c673cae | 229 | } |
7c673cae FG |
230 | }; |
231 | ||
11fdf7f2 TL |
232 | |
233 | class MonClient : public Dispatcher, | |
234 | public AuthClient, | |
235 | public AuthServer /* for mgr, osd, mds */ { | |
7c673cae FG |
236 | public: |
237 | MonMap monmap; | |
11fdf7f2 TL |
238 | map<string,string> config_mgr; |
239 | ||
7c673cae FG |
240 | private: |
241 | Messenger *messenger; | |
242 | ||
243 | std::unique_ptr<MonConnection> active_con; | |
11fdf7f2 | 244 | std::map<entity_addrvec_t, MonConnection> pending_cons; |
7c673cae FG |
245 | |
246 | EntityName entity_name; | |
247 | ||
7c673cae FG |
248 | mutable Mutex monc_lock; |
249 | SafeTimer timer; | |
250 | Finisher finisher; | |
251 | ||
252 | bool initialized; | |
11fdf7f2 | 253 | bool stopping = false; |
7c673cae FG |
254 | |
255 | LogClient *log_client; | |
256 | bool more_log_pending; | |
257 | ||
258 | void send_log(bool flush = false); | |
259 | ||
7c673cae FG |
260 | bool ms_dispatch(Message *m) override; |
261 | bool ms_handle_reset(Connection *con) override; | |
262 | void ms_handle_remote_reset(Connection *con) override {} | |
263 | bool ms_handle_refused(Connection *con) override { return false; } | |
264 | ||
265 | void handle_monmap(MMonMap *m); | |
11fdf7f2 | 266 | void handle_config(MConfig *m); |
7c673cae FG |
267 | |
268 | void handle_auth(MAuthReply *m); | |
269 | ||
270 | // monitor session | |
271 | void tick(); | |
272 | void schedule_tick(); | |
273 | ||
274 | // monclient | |
275 | bool want_monmap; | |
276 | Cond map_cond; | |
31f18b77 | 277 | bool passthrough_monmap = false; |
11fdf7f2 | 278 | bool got_config = false; |
31f18b77 | 279 | |
7c673cae FG |
280 | // authenticate |
281 | std::unique_ptr<AuthClientHandler> auth; | |
282 | uint32_t want_keys = 0; | |
283 | uint64_t global_id = 0; | |
284 | Cond auth_cond; | |
285 | int authenticate_err = 0; | |
286 | bool authenticated = false; | |
287 | ||
288 | list<Message*> waiting_for_session; | |
289 | utime_t last_rotating_renew_sent; | |
290 | std::unique_ptr<Context> session_established_context; | |
291 | bool had_a_connection; | |
292 | double reopen_interval_multiplier; | |
293 | ||
11fdf7f2 TL |
294 | Dispatcher *handle_authentication_dispatcher = nullptr; |
295 | ||
7c673cae FG |
296 | bool _opened() const; |
297 | bool _hunting() const; | |
298 | void _start_hunting(); | |
11fdf7f2 | 299 | void _finish_hunting(int auth_err); |
7c673cae FG |
300 | void _finish_auth(int auth_err); |
301 | void _reopen_session(int rank = -1); | |
302 | MonConnection& _add_conn(unsigned rank, uint64_t global_id); | |
c07f9fc5 | 303 | void _un_backoff(); |
7c673cae FG |
304 | void _add_conns(uint64_t global_id); |
305 | void _send_mon_message(Message *m); | |
306 | ||
11fdf7f2 TL |
307 | std::map<entity_addrvec_t, MonConnection>::iterator _find_pending_con( |
308 | const ConnectionRef& con) { | |
309 | for (auto i = pending_cons.begin(); i != pending_cons.end(); ++i) { | |
310 | if (i->second.get_con() == con) { | |
311 | return i; | |
312 | } | |
313 | } | |
314 | return pending_cons.end(); | |
315 | } | |
316 | ||
7c673cae | 317 | public: |
11fdf7f2 TL |
318 | // AuthClient |
319 | int get_auth_request( | |
320 | Connection *con, | |
321 | AuthConnectionMeta *auth_meta, | |
322 | uint32_t *method, | |
323 | std::vector<uint32_t> *preferred_modes, | |
324 | bufferlist *bl) override; | |
325 | int handle_auth_reply_more( | |
326 | Connection *con, | |
327 | AuthConnectionMeta *auth_meta, | |
328 | const bufferlist& bl, | |
329 | bufferlist *reply) override; | |
330 | int handle_auth_done( | |
331 | Connection *con, | |
332 | AuthConnectionMeta *auth_meta, | |
333 | uint64_t global_id, | |
334 | uint32_t con_mode, | |
335 | const bufferlist& bl, | |
336 | CryptoKey *session_key, | |
337 | std::string *connection_secret) override; | |
338 | int handle_auth_bad_method( | |
339 | Connection *con, | |
340 | AuthConnectionMeta *auth_meta, | |
341 | uint32_t old_auth_method, | |
342 | int result, | |
343 | const std::vector<uint32_t>& allowed_methods, | |
344 | const std::vector<uint32_t>& allowed_modes) override; | |
345 | // AuthServer | |
346 | int handle_auth_request( | |
347 | Connection *con, | |
348 | AuthConnectionMeta *auth_meta, | |
349 | bool more, | |
350 | uint32_t auth_method, | |
351 | const bufferlist& bl, | |
352 | bufferlist *reply); | |
7c673cae | 353 | |
11fdf7f2 TL |
354 | void set_entity_name(EntityName name) { entity_name = name; } |
355 | void set_handle_authentication_dispatcher(Dispatcher *d) { | |
356 | handle_authentication_dispatcher = d; | |
357 | } | |
7c673cae FG |
358 | int _check_auth_tickets(); |
359 | int _check_auth_rotating(); | |
360 | int wait_auth_rotating(double timeout); | |
361 | ||
362 | int authenticate(double timeout=0.0); | |
363 | bool is_authenticated() const {return authenticated;} | |
364 | ||
94b18763 FG |
365 | bool is_connected() const { return active_con != nullptr; } |
366 | ||
7c673cae FG |
367 | /** |
368 | * Try to flush as many log messages as we can in a single | |
369 | * message. Use this before shutting down to transmit your | |
370 | * last message. | |
371 | */ | |
372 | void flush_log(); | |
373 | ||
7c673cae | 374 | private: |
11fdf7f2 TL |
375 | // mon subscriptions |
376 | MonSub sub; | |
7c673cae FG |
377 | void _renew_subs(); |
378 | void handle_subscribe_ack(MMonSubscribeAck* m); | |
379 | ||
7c673cae FG |
380 | public: |
381 | void renew_subs() { | |
11fdf7f2 | 382 | std::lock_guard l(monc_lock); |
7c673cae FG |
383 | _renew_subs(); |
384 | } | |
385 | bool sub_want(string what, version_t start, unsigned flags) { | |
11fdf7f2 TL |
386 | std::lock_guard l(monc_lock); |
387 | return sub.want(what, start, flags); | |
7c673cae FG |
388 | } |
389 | void sub_got(string what, version_t have) { | |
11fdf7f2 TL |
390 | std::lock_guard l(monc_lock); |
391 | sub.got(what, have); | |
7c673cae FG |
392 | } |
393 | void sub_unwant(string what) { | |
11fdf7f2 TL |
394 | std::lock_guard l(monc_lock); |
395 | sub.unwant(what); | |
7c673cae | 396 | } |
7c673cae | 397 | bool sub_want_increment(string what, version_t start, unsigned flags) { |
11fdf7f2 TL |
398 | std::lock_guard l(monc_lock); |
399 | return sub.inc_want(what, start, flags); | |
7c673cae FG |
400 | } |
401 | ||
402 | std::unique_ptr<KeyRing> keyring; | |
403 | std::unique_ptr<RotatingKeyRing> rotating_secrets; | |
404 | ||
405 | public: | |
406 | explicit MonClient(CephContext *cct_); | |
407 | MonClient(const MonClient &) = delete; | |
408 | MonClient& operator=(const MonClient &) = delete; | |
409 | ~MonClient() override; | |
410 | ||
411 | int init(); | |
412 | void shutdown(); | |
413 | ||
414 | void set_log_client(LogClient *clog) { | |
415 | log_client = clog; | |
416 | } | |
417 | ||
418 | int build_initial_monmap(); | |
419 | int get_monmap(); | |
11fdf7f2 | 420 | int get_monmap_and_config(); |
31f18b77 FG |
421 | /** |
422 | * If you want to see MonMap messages, set this and | |
423 | * the MonClient will tell the Messenger it hasn't | |
424 | * dealt with it. | |
425 | * Note that if you do this, *you* are of course responsible for | |
426 | * putting the message reference! | |
427 | */ | |
428 | void set_passthrough_monmap() { | |
11fdf7f2 | 429 | std::lock_guard l(monc_lock); |
31f18b77 FG |
430 | passthrough_monmap = true; |
431 | } | |
432 | void unset_passthrough_monmap() { | |
11fdf7f2 | 433 | std::lock_guard l(monc_lock); |
31f18b77 FG |
434 | passthrough_monmap = false; |
435 | } | |
7c673cae FG |
436 | /** |
437 | * Ping monitor with ID @p mon_id and record the resulting | |
438 | * reply in @p result_reply. | |
439 | * | |
440 | * @param[in] mon_id Target monitor's ID | |
441 | * @param[out] result_reply reply from mon.ID, if param != NULL | |
442 | * @returns 0 in case of success; < 0 in case of error, | |
443 | * -ETIMEDOUT if monitor didn't reply before timeout | |
444 | * expired (default: conf->client_mount_timeout). | |
445 | */ | |
446 | int ping_monitor(const string &mon_id, string *result_reply); | |
447 | ||
448 | void send_mon_message(Message *m) { | |
11fdf7f2 | 449 | std::lock_guard l(monc_lock); |
7c673cae FG |
450 | _send_mon_message(m); |
451 | } | |
452 | /** | |
453 | * If you specify a callback, you should not call | |
454 | * reopen_session() again until it has been triggered. The MonClient | |
455 | * will behave, but the first callback could be triggered after | |
456 | * the session has been killed and the MonClient has started trying | |
457 | * to reconnect to another monitor. | |
458 | */ | |
459 | void reopen_session(Context *cb=NULL) { | |
11fdf7f2 | 460 | std::lock_guard l(monc_lock); |
7c673cae FG |
461 | if (cb) { |
462 | session_established_context.reset(cb); | |
463 | } | |
464 | _reopen_session(); | |
465 | } | |
466 | ||
7c673cae FG |
467 | const uuid_d& get_fsid() const { |
468 | return monmap.fsid; | |
469 | } | |
470 | ||
11fdf7f2 TL |
471 | entity_addrvec_t get_mon_addrs(unsigned i) const { |
472 | std::lock_guard l(monc_lock); | |
7c673cae | 473 | if (i < monmap.size()) |
11fdf7f2 TL |
474 | return monmap.get_addrs(i); |
475 | return entity_addrvec_t(); | |
7c673cae FG |
476 | } |
477 | int get_num_mon() const { | |
11fdf7f2 | 478 | std::lock_guard l(monc_lock); |
7c673cae FG |
479 | return monmap.size(); |
480 | } | |
481 | ||
482 | uint64_t get_global_id() const { | |
11fdf7f2 | 483 | std::lock_guard l(monc_lock); |
7c673cae FG |
484 | return global_id; |
485 | } | |
486 | ||
487 | void set_messenger(Messenger *m) { messenger = m; } | |
11fdf7f2 | 488 | entity_addrvec_t get_myaddrs() const { return messenger->get_myaddrs(); } |
7c673cae FG |
489 | AuthAuthorizer* build_authorizer(int service_id) const; |
490 | ||
491 | void set_want_keys(uint32_t want) { | |
492 | want_keys = want; | |
493 | } | |
494 | ||
495 | // admin commands | |
496 | private: | |
497 | uint64_t last_mon_command_tid; | |
11fdf7f2 | 498 | |
7c673cae FG |
499 | struct MonCommand { |
500 | string target_name; | |
501 | int target_rank; | |
eafe8130 | 502 | unsigned send_attempts = 0; |
7c673cae FG |
503 | uint64_t tid; |
504 | vector<string> cmd; | |
505 | bufferlist inbl; | |
506 | bufferlist *poutbl; | |
507 | string *prs; | |
508 | int *prval; | |
509 | Context *onfinish, *ontimeout; | |
510 | ||
511 | explicit MonCommand(uint64_t t) | |
512 | : target_rank(-1), | |
513 | tid(t), | |
514 | poutbl(NULL), prs(NULL), prval(NULL), onfinish(NULL), ontimeout(NULL) | |
515 | {} | |
516 | }; | |
517 | map<uint64_t,MonCommand*> mon_commands; | |
518 | ||
519 | void _send_command(MonCommand *r); | |
520 | void _resend_mon_commands(); | |
31f18b77 | 521 | int _cancel_mon_command(uint64_t tid); |
7c673cae FG |
522 | void _finish_command(MonCommand *r, int ret, string rs); |
523 | void _finish_auth(); | |
524 | void handle_mon_command_ack(MMonCommandAck *ack); | |
525 | ||
526 | public: | |
527 | void start_mon_command(const vector<string>& cmd, const bufferlist& inbl, | |
528 | bufferlist *outbl, string *outs, | |
529 | Context *onfinish); | |
530 | void start_mon_command(int mon_rank, | |
531 | const vector<string>& cmd, const bufferlist& inbl, | |
532 | bufferlist *outbl, string *outs, | |
533 | Context *onfinish); | |
534 | void start_mon_command(const string &mon_name, ///< mon name, with mon. prefix | |
535 | const vector<string>& cmd, const bufferlist& inbl, | |
536 | bufferlist *outbl, string *outs, | |
537 | Context *onfinish); | |
538 | ||
539 | // version requests | |
540 | public: | |
541 | /** | |
542 | * get latest known version(s) of cluster map | |
543 | * | |
544 | * @param map string name of map (e.g., 'osdmap') | |
545 | * @param newest pointer where newest map version will be stored | |
546 | * @param oldest pointer where oldest map version will be stored | |
547 | * @param onfinish context that will be triggered on completion | |
548 | * @return (via context) 0 on success, -EAGAIN if we need to resubmit our request | |
549 | */ | |
550 | void get_version(string map, version_t *newest, version_t *oldest, Context *onfinish); | |
7c673cae FG |
551 | /** |
552 | * Run a callback within our lock, with a reference | |
553 | * to the MonMap | |
554 | */ | |
555 | template<typename Callback, typename...Args> | |
556 | auto with_monmap(Callback&& cb, Args&&...args) const -> | |
557 | decltype(cb(monmap, std::forward<Args>(args)...)) { | |
11fdf7f2 | 558 | std::lock_guard l(monc_lock); |
7c673cae FG |
559 | return std::forward<Callback>(cb)(monmap, std::forward<Args>(args)...); |
560 | } | |
561 | ||
11fdf7f2 TL |
562 | void register_config_callback(md_config_t::config_callback fn); |
563 | void register_config_notify_callback(std::function<void(void)> f) { | |
564 | config_notify_cb = f; | |
565 | } | |
566 | md_config_t::config_callback get_config_callback(); | |
567 | ||
7c673cae FG |
568 | private: |
569 | struct version_req_d { | |
570 | Context *context; | |
571 | version_t *newest, *oldest; | |
572 | version_req_d(Context *con, version_t *n, version_t *o) : context(con),newest(n), oldest(o) {} | |
573 | }; | |
574 | ||
575 | map<ceph_tid_t, version_req_d*> version_requests; | |
576 | ceph_tid_t version_req_id; | |
577 | void handle_get_version_reply(MMonGetVersionReply* m); | |
578 | ||
11fdf7f2 TL |
579 | md_config_t::config_callback config_cb; |
580 | std::function<void(void)> config_notify_cb; | |
7c673cae FG |
581 | }; |
582 | ||
583 | #endif |