]> git.proxmox.com Git - ceph.git/blob - ceph/src/mds/MDSMap.h
update sources to v12.1.3
[ceph.git] / ceph / src / mds / MDSMap.h
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 */
14
15
16 #ifndef CEPH_MDSMAP_H
17 #define CEPH_MDSMAP_H
18
19 #include <errno.h>
20
21 #include "include/types.h"
22 #include "common/Clock.h"
23 #include "msg/Message.h"
24 #include "include/health.h"
25
26 #include <set>
27 #include <map>
28 #include <string>
29 #include <algorithm>
30
31 #include "common/config.h"
32
33 #include "include/CompatSet.h"
34 #include "include/ceph_features.h"
35 #include "common/Formatter.h"
36 #include "mds/mdstypes.h"
37
38 /*
39
40 boot --> standby, creating, or starting.
41
42
43 dne ----> creating -----> active*
44 ^ ^___________/ / ^ ^
45 | / / |
46 destroying / / |
47 ^ / / |
48 | / / |
49 stopped <---- stopping* <-/ / |
50 \ / |
51 ----- starting* ----/ |
52 |
53 failed |
54 \ |
55 \--> replay* --> reconnect* --> rejoin*
56
57 * = can fail
58
59 */
60
61 class CephContext;
62 class health_check_map_t;
63
64 extern CompatSet get_mdsmap_compat_set_all();
65 extern CompatSet get_mdsmap_compat_set_default();
66 extern CompatSet get_mdsmap_compat_set_base(); // pre v0.20
67
68 #define MDS_FEATURE_INCOMPAT_BASE CompatSet::Feature(1, "base v0.20")
69 #define MDS_FEATURE_INCOMPAT_CLIENTRANGES CompatSet::Feature(2, "client writeable ranges")
70 #define MDS_FEATURE_INCOMPAT_FILELAYOUT CompatSet::Feature(3, "default file layouts on dirs")
71 #define MDS_FEATURE_INCOMPAT_DIRINODE CompatSet::Feature(4, "dir inode in separate object")
72 #define MDS_FEATURE_INCOMPAT_ENCODING CompatSet::Feature(5, "mds uses versioned encoding")
73 #define MDS_FEATURE_INCOMPAT_OMAPDIRFRAG CompatSet::Feature(6, "dirfrag is stored in omap")
74 #define MDS_FEATURE_INCOMPAT_INLINE CompatSet::Feature(7, "mds uses inline data")
75 #define MDS_FEATURE_INCOMPAT_NOANCHOR CompatSet::Feature(8, "no anchor table")
76 #define MDS_FEATURE_INCOMPAT_FILE_LAYOUT_V2 CompatSet::Feature(8, "file layout v2")
77
78 #define MDS_FS_NAME_DEFAULT "cephfs"
79
80 class MDSMap {
81 public:
82 /* These states are the union of the set of possible states of an MDS daemon,
83 * and the set of possible states of an MDS rank */
84 typedef enum {
85 // States of an MDS daemon not currently holding a rank
86 // ====================================================
87 STATE_NULL = CEPH_MDS_STATE_NULL, // null value for fns returning this type.
88 STATE_BOOT = CEPH_MDS_STATE_BOOT, // up, boot announcement. destiny unknown.
89 STATE_STANDBY = CEPH_MDS_STATE_STANDBY, // up, idle. waiting for assignment by monitor.
90 STATE_STANDBY_REPLAY = CEPH_MDS_STATE_STANDBY_REPLAY, // up, replaying active node, ready to take over.
91
92 // States of an MDS rank, and of any MDS daemon holding that rank
93 // ==============================================================
94 STATE_STOPPED = CEPH_MDS_STATE_STOPPED, // down, once existed, but no subtrees. empty log. may not be held by a daemon.
95
96 STATE_CREATING = CEPH_MDS_STATE_CREATING, // up, creating MDS instance (new journal, idalloc..).
97 STATE_STARTING = CEPH_MDS_STATE_STARTING, // up, starting prior stopped MDS instance.
98
99 STATE_REPLAY = CEPH_MDS_STATE_REPLAY, // up, starting prior failed instance. scanning journal.
100 STATE_RESOLVE = CEPH_MDS_STATE_RESOLVE, // up, disambiguating distributed operations (import, rename, etc.)
101 STATE_RECONNECT = CEPH_MDS_STATE_RECONNECT, // up, reconnect to clients
102 STATE_REJOIN = CEPH_MDS_STATE_REJOIN, // up, replayed journal, rejoining distributed cache
103 STATE_CLIENTREPLAY = CEPH_MDS_STATE_CLIENTREPLAY, // up, active
104 STATE_ACTIVE = CEPH_MDS_STATE_ACTIVE, // up, active
105 STATE_STOPPING = CEPH_MDS_STATE_STOPPING, // up, exporting metadata (-> standby or out)
106 STATE_DNE = CEPH_MDS_STATE_DNE, // down, rank does not exist
107
108 // State which a daemon may send to MDSMonitor in its beacon
109 // to indicate that offline repair is required. Daemon must stop
110 // immediately after indicating this state.
111 STATE_DAMAGED = CEPH_MDS_STATE_DAMAGED
112
113 /*
114 * In addition to explicit states, an MDS rank implicitly in state:
115 * - STOPPED if it is not currently associated with an MDS daemon gid but it
116 * is in MDSMap::stopped
117 * - FAILED if it is not currently associated with an MDS daemon gid but it
118 * is in MDSMap::failed
119 * - DNE if it is not currently associated with an MDS daemon gid and it is
120 * missing from both MDSMap::failed and MDSMap::stopped
121 */
122 } DaemonState;
123
124 struct mds_info_t {
125 mds_gid_t global_id;
126 std::string name;
127 mds_rank_t rank;
128 int32_t inc;
129 MDSMap::DaemonState state;
130 version_t state_seq;
131 entity_addr_t addr;
132 utime_t laggy_since;
133 mds_rank_t standby_for_rank;
134 std::string standby_for_name;
135 fs_cluster_id_t standby_for_fscid;
136 bool standby_replay;
137 std::set<mds_rank_t> export_targets;
138 uint64_t mds_features = 0;
139
140 mds_info_t() : global_id(MDS_GID_NONE), rank(MDS_RANK_NONE), inc(0),
141 state(STATE_STANDBY), state_seq(0),
142 standby_for_rank(MDS_RANK_NONE),
143 standby_for_fscid(FS_CLUSTER_ID_NONE),
144 standby_replay(false)
145 { }
146
147 bool laggy() const { return !(laggy_since == utime_t()); }
148 void clear_laggy() { laggy_since = utime_t(); }
149
150 entity_inst_t get_inst() const { return entity_inst_t(entity_name_t::MDS(rank), addr); }
151
152 void encode(bufferlist& bl, uint64_t features) const {
153 if ((features & CEPH_FEATURE_MDSENC) == 0 ) encode_unversioned(bl);
154 else encode_versioned(bl, features);
155 }
156 void decode(bufferlist::iterator& p);
157 void dump(Formatter *f) const;
158 void print_summary(ostream &out) const;
159
160 // The long form name for use in cluster log messages`
161 std::string human_name() const;
162
163 static void generate_test_instances(list<mds_info_t*>& ls);
164 private:
165 void encode_versioned(bufferlist& bl, uint64_t features) const;
166 void encode_unversioned(bufferlist& bl) const;
167 };
168
169
170 protected:
171 // base map
172 epoch_t epoch;
173 bool enabled;
174 std::string fs_name;
175 uint32_t flags; // flags
176 epoch_t last_failure; // mds epoch of last failure
177 epoch_t last_failure_osd_epoch; // osd epoch of last failure; any mds entering replay needs
178 // at least this osdmap to ensure the blacklist propagates.
179 utime_t created, modified;
180
181 mds_rank_t tableserver; // which MDS has snaptable
182 mds_rank_t root; // which MDS has root directory
183
184 __u32 session_timeout;
185 __u32 session_autoclose;
186 uint64_t max_file_size;
187
188 std::vector<int64_t> data_pools; // file data pools available to clients (via an ioctl). first is the default.
189 int64_t cas_pool; // where CAS objects go
190 int64_t metadata_pool; // where fs metadata objects go
191
192 /*
193 * in: the set of logical mds #'s that define the cluster. this is the set
194 * of mds's the metadata may be distributed over.
195 * up: map from logical mds #'s to the addrs filling those roles.
196 * failed: subset of @in that are failed.
197 * stopped: set of nodes that have been initialized, but are not active.
198 *
199 * @up + @failed = @in. @in * @stopped = {}.
200 */
201
202 mds_rank_t max_mds; /* The maximum number of active MDSes. Also, the maximum rank. */
203 mds_rank_t standby_count_wanted;
204 string balancer; /* The name/version of the mantle balancer (i.e. the rados obj name) */
205
206 std::set<mds_rank_t> in; // currently defined cluster
207
208 // which ranks are failed, stopped, damaged (i.e. not held by a daemon)
209 std::set<mds_rank_t> failed, stopped, damaged;
210 std::map<mds_rank_t, mds_gid_t> up; // who is in those roles
211 std::map<mds_gid_t, mds_info_t> mds_info;
212
213 uint8_t ever_allowed_features; //< bitmap of features the cluster has allowed
214 uint8_t explicitly_allowed_features; //< bitmap of features explicitly enabled
215
216 bool inline_data_enabled;
217
218 uint64_t cached_up_features;
219
220 public:
221 CompatSet compat;
222
223 friend class MDSMonitor;
224 friend class Filesystem;
225 friend class FSMap;
226
227 public:
228 MDSMap()
229 : epoch(0), enabled(false), fs_name(MDS_FS_NAME_DEFAULT),
230 flags(CEPH_MDSMAP_DEFAULTS), last_failure(0),
231 last_failure_osd_epoch(0),
232 tableserver(0), root(0),
233 session_timeout(0),
234 session_autoclose(0),
235 max_file_size(0),
236 cas_pool(-1),
237 metadata_pool(-1),
238 max_mds(0),
239 standby_count_wanted(-1),
240 ever_allowed_features(0),
241 explicitly_allowed_features(0),
242 inline_data_enabled(false),
243 cached_up_features(0)
244 { }
245
246 bool get_inline_data_enabled() const { return inline_data_enabled; }
247 void set_inline_data_enabled(bool enabled) { inline_data_enabled = enabled; }
248
249 utime_t get_session_timeout() const {
250 return utime_t(session_timeout,0);
251 }
252 uint64_t get_max_filesize() const { return max_file_size; }
253 void set_max_filesize(uint64_t m) { max_file_size = m; }
254
255 int get_flags() const { return flags; }
256 bool test_flag(int f) const { return flags & f; }
257 void set_flag(int f) { flags |= f; }
258 void clear_flag(int f) { flags &= ~f; }
259
260 const std::string &get_fs_name() const {return fs_name;}
261
262 void set_snaps_allowed() {
263 set_flag(CEPH_MDSMAP_ALLOW_SNAPS);
264 ever_allowed_features |= CEPH_MDSMAP_ALLOW_SNAPS;
265 explicitly_allowed_features |= CEPH_MDSMAP_ALLOW_SNAPS;
266 }
267 void clear_snaps_allowed() { clear_flag(CEPH_MDSMAP_ALLOW_SNAPS); }
268 bool allows_snaps() const { return test_flag(CEPH_MDSMAP_ALLOW_SNAPS); }
269
270 void set_multimds_allowed() {
271 set_flag(CEPH_MDSMAP_ALLOW_MULTIMDS);
272 ever_allowed_features |= CEPH_MDSMAP_ALLOW_MULTIMDS;
273 explicitly_allowed_features |= CEPH_MDSMAP_ALLOW_MULTIMDS;
274 }
275 void clear_multimds_allowed() { clear_flag(CEPH_MDSMAP_ALLOW_MULTIMDS); }
276 bool allows_multimds() const { return test_flag(CEPH_MDSMAP_ALLOW_MULTIMDS); }
277
278 void set_dirfrags_allowed() {
279 set_flag(CEPH_MDSMAP_ALLOW_DIRFRAGS);
280 ever_allowed_features |= CEPH_MDSMAP_ALLOW_DIRFRAGS;
281 explicitly_allowed_features |= CEPH_MDSMAP_ALLOW_DIRFRAGS;
282 }
283 void clear_dirfrags_allowed() { clear_flag(CEPH_MDSMAP_ALLOW_DIRFRAGS); }
284 bool allows_dirfrags() const { return test_flag(CEPH_MDSMAP_ALLOW_DIRFRAGS); }
285
286 epoch_t get_epoch() const { return epoch; }
287 void inc_epoch() { epoch++; }
288
289 bool get_enabled() const { return enabled; }
290
291 const utime_t& get_created() const { return created; }
292 void set_created(utime_t ct) { modified = created = ct; }
293 const utime_t& get_modified() const { return modified; }
294 void set_modified(utime_t mt) { modified = mt; }
295
296 epoch_t get_last_failure() const { return last_failure; }
297 epoch_t get_last_failure_osd_epoch() const { return last_failure_osd_epoch; }
298
299 mds_rank_t get_max_mds() const { return max_mds; }
300 void set_max_mds(mds_rank_t m) { max_mds = m; }
301
302 mds_rank_t get_standby_count_wanted(mds_rank_t standby_daemon_count) const {
303 assert(standby_daemon_count >= 0);
304 std::set<mds_rank_t> s;
305 get_standby_replay_mds_set(s);
306 mds_rank_t standbys_avail = (mds_rank_t)s.size()+standby_daemon_count;
307 mds_rank_t wanted = std::max(0, standby_count_wanted);
308 return wanted > standbys_avail ? wanted - standbys_avail : 0;
309 }
310 void set_standby_count_wanted(mds_rank_t n) { standby_count_wanted = n; }
311 bool check_health(mds_rank_t standby_daemon_count);
312
313 const std::string get_balancer() const { return balancer; }
314 void set_balancer(std::string val) { balancer.assign(val); }
315
316 mds_rank_t get_tableserver() const { return tableserver; }
317 mds_rank_t get_root() const { return root; }
318
319 const std::vector<int64_t> &get_data_pools() const { return data_pools; }
320 int64_t get_first_data_pool() const { return *data_pools.begin(); }
321 int64_t get_metadata_pool() const { return metadata_pool; }
322 bool is_data_pool(int64_t poolid) const {
323 auto p = std::find(data_pools.begin(), data_pools.end(), poolid);
324 if (p == data_pools.end())
325 return false;
326 return true;
327 }
328
329 bool pool_in_use(int64_t poolid) const {
330 return get_enabled() && (is_data_pool(poolid) || metadata_pool == poolid);
331 }
332
333 const std::map<mds_gid_t,mds_info_t>& get_mds_info() const { return mds_info; }
334 const mds_info_t& get_mds_info_gid(mds_gid_t gid) const {
335 return mds_info.at(gid);
336 }
337 const mds_info_t& get_mds_info(mds_rank_t m) const {
338 assert(up.count(m) && mds_info.count(up.at(m)));
339 return mds_info.at(up.at(m));
340 }
341 mds_gid_t find_mds_gid_by_name(const std::string& s) const {
342 for (std::map<mds_gid_t,mds_info_t>::const_iterator p = mds_info.begin();
343 p != mds_info.end();
344 ++p) {
345 if (p->second.name == s) {
346 return p->first;
347 }
348 }
349 return MDS_GID_NONE;
350 }
351
352 // counts
353 unsigned get_num_in_mds() const {
354 return in.size();
355 }
356 unsigned get_num_up_mds() const {
357 return up.size();
358 }
359 mds_rank_t get_last_in_mds() const {
360 auto p = in.rbegin();
361 return p == in.rend() ? MDS_RANK_NONE : *p;
362 }
363 int get_num_failed_mds() const {
364 return failed.size();
365 }
366 unsigned get_num_mds(int state) const {
367 unsigned n = 0;
368 for (std::map<mds_gid_t,mds_info_t>::const_iterator p = mds_info.begin();
369 p != mds_info.end();
370 ++p)
371 if (p->second.state == state) ++n;
372 return n;
373 }
374
375 // data pools
376 void add_data_pool(int64_t poolid) {
377 data_pools.push_back(poolid);
378 }
379 int remove_data_pool(int64_t poolid) {
380 std::vector<int64_t>::iterator p = std::find(data_pools.begin(), data_pools.end(), poolid);
381 if (p == data_pools.end())
382 return -ENOENT;
383 data_pools.erase(p);
384 return 0;
385 }
386
387 // sets
388 void get_mds_set(std::set<mds_rank_t>& s) const {
389 s = in;
390 }
391 void get_up_mds_set(std::set<mds_rank_t>& s) const {
392 for (std::map<mds_rank_t, mds_gid_t>::const_iterator p = up.begin();
393 p != up.end();
394 ++p)
395 s.insert(p->first);
396 }
397 void get_active_mds_set(std::set<mds_rank_t>& s) const {
398 get_mds_set(s, MDSMap::STATE_ACTIVE);
399 }
400 void get_standby_replay_mds_set(std::set<mds_rank_t>& s) const {
401 get_mds_set(s, MDSMap::STATE_STANDBY_REPLAY);
402 }
403 void get_failed_mds_set(std::set<mds_rank_t>& s) const {
404 s = failed;
405 }
406
407 // features
408 uint64_t get_up_features() {
409 if (!cached_up_features) {
410 bool first = true;
411 for (std::map<mds_rank_t, mds_gid_t>::const_iterator p = up.begin();
412 p != up.end();
413 ++p) {
414 std::map<mds_gid_t, mds_info_t>::const_iterator q =
415 mds_info.find(p->second);
416 assert(q != mds_info.end());
417 if (first) {
418 cached_up_features = q->second.mds_features;
419 first = false;
420 } else {
421 cached_up_features &= q->second.mds_features;
422 }
423 }
424 }
425 return cached_up_features;
426 }
427
428 /**
429 * Get MDS ranks which are in but not up.
430 */
431 void get_down_mds_set(std::set<mds_rank_t> *s) const
432 {
433 assert(s != NULL);
434 s->insert(failed.begin(), failed.end());
435 s->insert(damaged.begin(), damaged.end());
436 }
437
438 int get_failed() const {
439 if (!failed.empty()) return *failed.begin();
440 return -1;
441 }
442 void get_stopped_mds_set(std::set<mds_rank_t>& s) const {
443 s = stopped;
444 }
445 void get_recovery_mds_set(std::set<mds_rank_t>& s) const {
446 s = failed;
447 for (const auto& p : damaged)
448 s.insert(p);
449 for (const auto& p : mds_info)
450 if (p.second.state >= STATE_REPLAY && p.second.state <= STATE_STOPPING)
451 s.insert(p.second.rank);
452 }
453
454 void
455 get_clientreplay_or_active_or_stopping_mds_set(std::set<mds_rank_t>& s) const {
456 for (std::map<mds_gid_t, mds_info_t>::const_iterator p = mds_info.begin();
457 p != mds_info.end();
458 ++p)
459 if (p->second.state >= STATE_CLIENTREPLAY && p->second.state <= STATE_STOPPING)
460 s.insert(p->second.rank);
461 }
462 void get_mds_set(std::set<mds_rank_t>& s, DaemonState state) const {
463 for (std::map<mds_gid_t, mds_info_t>::const_iterator p = mds_info.begin();
464 p != mds_info.end();
465 ++p)
466 if (p->second.state == state)
467 s.insert(p->second.rank);
468 }
469
470 void get_health(list<pair<health_status_t,std::string> >& summary,
471 list<pair<health_status_t,std::string> > *detail) const;
472
473 void get_health_checks(health_check_map_t *checks) const;
474
475 typedef enum
476 {
477 AVAILABLE = 0,
478 TRANSIENT_UNAVAILABLE = 1,
479 STUCK_UNAVAILABLE = 2
480
481 } availability_t;
482
483 /**
484 * Return indication of whether cluster is available. This is a
485 * heuristic for clients to see if they should bother waiting to talk to
486 * MDSs, or whether they should error out at startup/mount.
487 *
488 * A TRANSIENT_UNAVAILABLE result indicates that the cluster is in a
489 * transition state like replaying, or is potentially about the fail over.
490 * Clients should wait for an updated map before making a final decision
491 * about whether the filesystem is mountable.
492 *
493 * A STUCK_UNAVAILABLE result indicates that we can't see a way that
494 * the cluster is about to recover on its own, so it'll probably require
495 * administrator intervention: clients should probaly not bother trying
496 * to mount.
497 */
498 availability_t is_cluster_available() const;
499
500 // mds states
501 bool is_down(mds_rank_t m) const { return up.count(m) == 0; }
502 bool is_up(mds_rank_t m) const { return up.count(m); }
503 bool is_in(mds_rank_t m) const { return up.count(m) || failed.count(m); }
504 bool is_out(mds_rank_t m) const { return !is_in(m); }
505
506 bool is_failed(mds_rank_t m) const { return failed.count(m); }
507 bool is_stopped(mds_rank_t m) const { return stopped.count(m); }
508
509 bool is_dne(mds_rank_t m) const { return in.count(m) == 0; }
510 bool is_dne_gid(mds_gid_t gid) const { return mds_info.count(gid) == 0; }
511
512 /**
513 * Get MDS rank state if the rank is up, else STATE_NULL
514 */
515 DaemonState get_state(mds_rank_t m) const {
516 std::map<mds_rank_t, mds_gid_t>::const_iterator u = up.find(m);
517 if (u == up.end())
518 return STATE_NULL;
519 return get_state_gid(u->second);
520 }
521
522 /**
523 * Get MDS daemon status by GID
524 */
525 DaemonState get_state_gid(mds_gid_t gid) const {
526 std::map<mds_gid_t,mds_info_t>::const_iterator i = mds_info.find(gid);
527 if (i == mds_info.end())
528 return STATE_NULL;
529 return i->second.state;
530 }
531
532 const mds_info_t& get_info(const mds_rank_t m) const {
533 return mds_info.at(up.at(m));
534 }
535 const mds_info_t& get_info_gid(const mds_gid_t gid) const {
536 return mds_info.at(gid);
537 }
538
539 bool is_boot(mds_rank_t m) const { return get_state(m) == STATE_BOOT; }
540 bool is_creating(mds_rank_t m) const { return get_state(m) == STATE_CREATING; }
541 bool is_starting(mds_rank_t m) const { return get_state(m) == STATE_STARTING; }
542 bool is_replay(mds_rank_t m) const { return get_state(m) == STATE_REPLAY; }
543 bool is_resolve(mds_rank_t m) const { return get_state(m) == STATE_RESOLVE; }
544 bool is_reconnect(mds_rank_t m) const { return get_state(m) == STATE_RECONNECT; }
545 bool is_rejoin(mds_rank_t m) const { return get_state(m) == STATE_REJOIN; }
546 bool is_clientreplay(mds_rank_t m) const { return get_state(m) == STATE_CLIENTREPLAY; }
547 bool is_active(mds_rank_t m) const { return get_state(m) == STATE_ACTIVE; }
548 bool is_stopping(mds_rank_t m) const { return get_state(m) == STATE_STOPPING; }
549 bool is_active_or_stopping(mds_rank_t m) const {
550 return is_active(m) || is_stopping(m);
551 }
552 bool is_clientreplay_or_active_or_stopping(mds_rank_t m) const {
553 return is_clientreplay(m) || is_active(m) || is_stopping(m);
554 }
555
556 bool is_followable(mds_rank_t m) const {
557 return (is_resolve(m) ||
558 is_replay(m) ||
559 is_rejoin(m) ||
560 is_clientreplay(m) ||
561 is_active(m) ||
562 is_stopping(m));
563 }
564
565 bool is_laggy_gid(mds_gid_t gid) const {
566 if (!mds_info.count(gid))
567 return false;
568 std::map<mds_gid_t,mds_info_t>::const_iterator p = mds_info.find(gid);
569 return p->second.laggy();
570 }
571
572 // degraded = some recovery in process. fixes active membership and
573 // recovery_set.
574 bool is_degraded() const {
575 if (!failed.empty() || !damaged.empty())
576 return true;
577 for (std::map<mds_gid_t,mds_info_t>::const_iterator p = mds_info.begin();
578 p != mds_info.end();
579 ++p)
580 if (p->second.state >= STATE_REPLAY && p->second.state <= STATE_CLIENTREPLAY)
581 return true;
582 return false;
583 }
584 bool is_any_failed() const {
585 return failed.size();
586 }
587 bool is_resolving() const {
588 return
589 get_num_mds(STATE_RESOLVE) > 0 &&
590 get_num_mds(STATE_REPLAY) == 0 &&
591 failed.empty() && damaged.empty();
592 }
593 bool is_rejoining() const {
594 // nodes are rejoining cache state
595 return
596 get_num_mds(STATE_REJOIN) > 0 &&
597 get_num_mds(STATE_REPLAY) == 0 &&
598 get_num_mds(STATE_RECONNECT) == 0 &&
599 get_num_mds(STATE_RESOLVE) == 0 &&
600 failed.empty() && damaged.empty();
601 }
602 bool is_stopped() const {
603 return up.empty();
604 }
605
606 /**
607 * Get whether a rank is 'up', i.e. has
608 * an MDS daemon's entity_inst_t associated
609 * with it.
610 */
611 bool have_inst(mds_rank_t m) const {
612 return up.count(m);
613 }
614
615 /**
616 * Get the MDS daemon entity_inst_t for a rank
617 * known to be up.
618 */
619 const entity_inst_t get_inst(mds_rank_t m) {
620 assert(up.count(m));
621 return mds_info[up[m]].get_inst();
622 }
623 const entity_addr_t get_addr(mds_rank_t m) {
624 assert(up.count(m));
625 return mds_info[up[m]].addr;
626 }
627
628 /**
629 * Get the MDS daemon entity_inst_t for a rank,
630 * if it is up.
631 *
632 * @return true if the rank was up and the inst
633 * was populated, else false.
634 */
635 bool get_inst(mds_rank_t m, entity_inst_t& inst) {
636 if (up.count(m)) {
637 inst = get_inst(m);
638 return true;
639 }
640 return false;
641 }
642
643 mds_rank_t get_rank_gid(mds_gid_t gid) const {
644 if (mds_info.count(gid)) {
645 return mds_info.at(gid).rank;
646 } else {
647 return MDS_RANK_NONE;
648 }
649 }
650
651 int get_inc_gid(mds_gid_t gid) const {
652 auto mds_info_entry = mds_info.find(gid);
653 if (mds_info_entry != mds_info.end())
654 return mds_info_entry->second.inc;
655 return -1;
656 }
657 void encode(bufferlist& bl, uint64_t features) const;
658 void decode(bufferlist::iterator& p);
659 void decode(bufferlist& bl) {
660 bufferlist::iterator p = bl.begin();
661 decode(p);
662 }
663
664
665 void print(ostream& out) const;
666 void print_summary(Formatter *f, ostream *out) const;
667
668 void dump(Formatter *f) const;
669 static void generate_test_instances(list<MDSMap*>& ls);
670
671 static bool state_transition_valid(DaemonState prev, DaemonState next);
672 };
673 WRITE_CLASS_ENCODER_FEATURES(MDSMap::mds_info_t)
674 WRITE_CLASS_ENCODER_FEATURES(MDSMap)
675
676 inline ostream& operator<<(ostream &out, const MDSMap &m) {
677 m.print_summary(NULL, &out);
678 return out;
679 }
680
681 #endif