1 // -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
2 // vim: ts=8 sw=2 smarttab
4 * Ceph - scalable distributed file system
6 * Copyright (C) 2004-2006 Sage Weil <sage@newdream.net>
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.
15 #ifndef CEPH_MON_TYPES_H
16 #define CEPH_MON_TYPES_H
20 #include "include/utime.h"
21 #include "include/util.h"
22 #include "common/Formatter.h"
23 #include "common/bit_str.h"
24 #include "include/Context.h"
26 #define PAXOS_PGMAP 0 // before osd, for pg kick to behave
27 #define PAXOS_MDSMAP 1
28 #define PAXOS_OSDMAP 2
30 #define PAXOS_MONMAP 4
33 #define PAXOS_MGRSTAT 7
34 #define PAXOS_HEALTH 8
37 inline const char *get_paxos_name(int p) {
39 case PAXOS_MDSMAP: return "mdsmap";
40 case PAXOS_MONMAP: return "monmap";
41 case PAXOS_OSDMAP: return "osdmap";
42 case PAXOS_PGMAP: return "pgmap";
43 case PAXOS_LOG: return "logm";
44 case PAXOS_AUTH: return "auth";
45 case PAXOS_MGR: return "mgr";
46 case PAXOS_MGRSTAT: return "mgrstat";
47 case PAXOS_HEALTH: return "health";
48 default: ceph_abort(); return 0;
52 #define CEPH_MON_ONDISK_MAGIC "ceph mon volume v012"
54 // map of entity_type -> features -> count
56 std::map<uint32_t,std::map<uint64_t,uint64_t>> m;
58 void add(uint32_t type, uint64_t features) {
59 if (type == CEPH_ENTITY_TYPE_MON) {
65 void add_mon(uint64_t features) {
66 m[CEPH_ENTITY_TYPE_MON][features]++;
69 void rm(uint32_t type, uint64_t features) {
70 if (type == CEPH_ENTITY_TYPE_MON) {
73 auto p = m.find(type);
75 auto q = p->second.find(features);
76 assert(q != p->second.end());
77 if (--q->second == 0) {
79 if (p->second.empty()) {
85 FeatureMap& operator+=(const FeatureMap& o) {
88 for (auto& q : p.second) {
89 v[q.first] += q.second;
95 void encode(bufferlist& bl) const {
96 ENCODE_START(1, 1, bl);
101 void decode(bufferlist::iterator& p) {
107 void dump(Formatter *f) const {
109 f->open_object_section(ceph_entity_type_name(p.first));
110 for (auto& q : p.second) {
111 f->open_object_section("group");
112 std::stringstream ss;
113 ss << "0x" << std::hex << q.first << std::dec;
114 f->dump_string("features", ss.str());
115 f->dump_string("release", ceph_release_name(
116 ceph_release_from_features(q.first)));
117 f->dump_unsigned("num", q.second);
124 WRITE_CLASS_ENCODER(FeatureMap)
127 * leveldb store stats
129 * If we ever decide to support multiple backends for the monitor store,
130 * we should then create an abstract class 'MonitorStoreStats' of sorts
131 * and inherit it on LevelDBStoreStats. I'm sure you'll figure something
134 struct LevelDBStoreStats {
135 uint64_t bytes_total;
141 LevelDBStoreStats() :
148 void dump(Formatter *f) const {
150 f->dump_int("bytes_total", bytes_total);
151 f->dump_int("bytes_sst", bytes_sst);
152 f->dump_int("bytes_log", bytes_log);
153 f->dump_int("bytes_misc", bytes_misc);
154 f->dump_stream("last_updated") << last_update;
157 void encode(bufferlist &bl) const {
158 ENCODE_START(1, 1, bl);
159 ::encode(bytes_total, bl);
160 ::encode(bytes_sst, bl);
161 ::encode(bytes_log, bl);
162 ::encode(bytes_misc, bl);
163 ::encode(last_update, bl);
167 void decode(bufferlist::iterator &p) {
169 ::decode(bytes_total, p);
170 ::decode(bytes_sst, p);
171 ::decode(bytes_log, p);
172 ::decode(bytes_misc, p);
173 ::decode(last_update, p);
177 static void generate_test_instances(list<LevelDBStoreStats*>& ls) {
178 ls.push_back(new LevelDBStoreStats);
179 ls.push_back(new LevelDBStoreStats);
180 ls.back()->bytes_total = 1024*1024;
181 ls.back()->bytes_sst = 512*1024;
182 ls.back()->bytes_log = 256*1024;
183 ls.back()->bytes_misc = 256*1024;
184 ls.back()->last_update = utime_t();
187 WRITE_CLASS_ENCODER(LevelDBStoreStats)
192 ceph_data_stats_t fs_stats;
195 LevelDBStoreStats store_stats;
197 void dump(Formatter *f) const {
199 f->dump_int("kb_total", (fs_stats.byte_total/1024));
200 f->dump_int("kb_used", (fs_stats.byte_used/1024));
201 f->dump_int("kb_avail", (fs_stats.byte_avail/1024));
202 f->dump_int("avail_percent", fs_stats.avail_percent);
203 f->dump_stream("last_updated") << last_update;
204 f->open_object_section("store_stats");
209 void encode(bufferlist &bl) const {
210 ENCODE_START(3, 1, bl);
211 ::encode(fs_stats.byte_total, bl);
212 ::encode(fs_stats.byte_used, bl);
213 ::encode(fs_stats.byte_avail, bl);
214 ::encode(fs_stats.avail_percent, bl);
215 ::encode(last_update, bl);
216 ::encode(store_stats, bl);
219 void decode(bufferlist::iterator &p) {
221 // we moved from having fields in kb to fields in byte
223 ::decode(fs_stats.byte_total, p);
224 ::decode(fs_stats.byte_used, p);
225 ::decode(fs_stats.byte_avail, p);
229 fs_stats.byte_total = t*1024;
231 fs_stats.byte_used = t*1024;
233 fs_stats.byte_avail = t*1024;
235 ::decode(fs_stats.avail_percent, p);
236 ::decode(last_update, p);
238 ::decode(store_stats, p);
243 WRITE_CLASS_ENCODER(DataStats)
246 map<string,uint32_t> prefix_crc; ///< prefix -> crc
247 map<string,uint64_t> prefix_keys; ///< prefix -> key count
249 bool operator!=(const ScrubResult& other) {
250 return prefix_crc != other.prefix_crc || prefix_keys != other.prefix_keys;
253 void encode(bufferlist& bl) const {
254 ENCODE_START(1, 1, bl);
255 ::encode(prefix_crc, bl);
256 ::encode(prefix_keys, bl);
259 void decode(bufferlist::iterator& p) {
261 ::decode(prefix_crc, p);
262 ::decode(prefix_keys, p);
265 void dump(Formatter *f) const {
266 f->open_object_section("crc");
267 for (map<string,uint32_t>::const_iterator p = prefix_crc.begin(); p != prefix_crc.end(); ++p)
268 f->dump_unsigned(p->first.c_str(), p->second);
270 f->open_object_section("keys");
271 for (map<string,uint64_t>::const_iterator p = prefix_keys.begin(); p != prefix_keys.end(); ++p)
272 f->dump_unsigned(p->first.c_str(), p->second);
275 static void generate_test_instances(list<ScrubResult*>& ls) {
276 ls.push_back(new ScrubResult);
277 ls.push_back(new ScrubResult);
278 ls.back()->prefix_crc["foo"] = 123;
279 ls.back()->prefix_keys["bar"] = 456;
282 WRITE_CLASS_ENCODER(ScrubResult)
284 static inline ostream& operator<<(ostream& out, const ScrubResult& r) {
285 return out << "ScrubResult(keys " << r.prefix_keys << " crc " << r.prefix_crc << ")";
288 /// for information like os, kernel, hostname, memory info, cpu model.
289 typedef map<string, string> Metadata;
295 * Get a feature's name based on its value.
297 * @param b raw feature value
300 * Consumers should not assume this interface will never change.
302 * As the number of features increase, so may the internal representation
303 * of the raw features. When this happens, this interface will change
304 * accordingly. So should consumers of this interface.
306 static inline const char *get_feature_name(uint64_t b);
312 inline const char *ceph_mon_feature_name(uint64_t b)
314 return ceph::features::mon::get_feature_name(b);
317 class mon_feature_t {
319 static const int HEAD_VERSION = 1;
320 static const int COMPAT_VERSION = 1;
322 // mon-specific features
328 mon_feature_t(const uint64_t f) : features(f) { }
334 mon_feature_t(const mon_feature_t &o) :
335 features(o.features) { }
337 mon_feature_t& operator&=(const mon_feature_t other) {
338 features &= other.features;
343 * Obtain raw features
346 * Consumers should not assume this interface will never change.
348 * As the number of features increase, so may the internal representation
349 * of the raw features. When this happens, this interface will change
350 * accordingly. So should consumers of this interface.
352 uint64_t get_raw() const {
357 friend mon_feature_t operator&(const mon_feature_t a,
358 const mon_feature_t b) {
359 return mon_feature_t(a.features & b.features);
362 mon_feature_t& operator|=(const mon_feature_t other) {
363 features |= other.features;
368 friend mon_feature_t operator|(const mon_feature_t a,
369 const mon_feature_t b) {
370 return mon_feature_t(a.features | b.features);
374 friend mon_feature_t operator^(const mon_feature_t a,
375 const mon_feature_t b) {
376 return mon_feature_t(a.features ^ b.features);
379 mon_feature_t& operator^=(const mon_feature_t other) {
380 features ^= other.features;
384 bool operator==(const mon_feature_t other) const {
385 return (features == other.features);
388 bool operator!=(const mon_feature_t other) const {
389 return (features != other.features);
393 return features == 0;
397 * Set difference of our features in respect to @p other
399 * Returns all the elements in our features that are not in @p other
401 * @returns all the features not in @p other
403 mon_feature_t diff(const mon_feature_t other) const {
404 return mon_feature_t((features ^ other.features) & features);
408 * Set intersection of our features and @p other
410 * Returns all the elements common to both our features and the
411 * features of @p other
413 * @returns the features common to @p other and us
415 mon_feature_t intersection(const mon_feature_t other) const {
416 return mon_feature_t((features & other.features));
420 * Checks whether we have all the features in @p other
422 * Returns true if we have all the features in @p other
424 * @returns true if we contain all the features in @p other
425 * @returns false if we do not contain some of the features in @p other
427 bool contains_all(const mon_feature_t other) const {
428 mon_feature_t d = intersection(other);
433 * Checks whether we contain any of the features in @p other.
435 * @returns true if we contain any of the features in @p other
436 * @returns false if we don't contain any of the features in @p other
438 bool contains_any(const mon_feature_t other) const {
439 mon_feature_t d = intersection(other);
443 void set_feature(const mon_feature_t f) {
444 features |= f.features;
447 void unset_feature(const mon_feature_t f) {
448 features &= ~(f.features);
451 void print(ostream& out) const {
453 print_bit_str(features, out, ceph::features::mon::get_feature_name);
457 void print_with_value(ostream& out) const {
459 print_bit_str(features, out, ceph::features::mon::get_feature_name, true);
463 void dump(Formatter *f, const char *sec_name = NULL) const {
464 f->open_array_section((sec_name ? sec_name : "features"));
465 dump_bit_str(features, f, ceph::features::mon::get_feature_name);
469 void dump_with_value(Formatter *f, const char *sec_name = NULL) const {
470 f->open_array_section((sec_name ? sec_name : "features"));
471 dump_bit_str(features, f, ceph::features::mon::get_feature_name, true);
475 void encode(bufferlist& bl) const {
476 ENCODE_START(HEAD_VERSION, COMPAT_VERSION, bl);
477 ::encode(features, bl);
480 void decode(bufferlist::iterator& p) {
481 DECODE_START(COMPAT_VERSION, p);
482 ::decode(features, p);
486 WRITE_CLASS_ENCODER(mon_feature_t)
491 constexpr mon_feature_t FEATURE_KRAKEN( (1ULL << 0));
492 constexpr mon_feature_t FEATURE_LUMINOUS( (1ULL << 1));
494 constexpr mon_feature_t FEATURE_RESERVED( (1ULL << 63));
495 constexpr mon_feature_t FEATURE_NONE( (0ULL));
498 * All the features this monitor supports
500 * If there's a feature above, it should be OR'ed to this list.
502 constexpr mon_feature_t get_supported() {
510 * All the features that, once set, cannot be removed.
512 * Features should only be added to this list if you want to make
513 * sure downgrades are not possible after a quorum supporting all
514 * these features has been formed.
516 * Any feature in this list will be automatically set on the monmap's
517 * features once all the monitors in the quorum support it.
519 constexpr mon_feature_t get_persistent() {
527 static inline mon_feature_t get_feature_by_name(std::string n);
532 static inline const char *ceph::features::mon::get_feature_name(uint64_t b) {
535 if (f == FEATURE_KRAKEN) {
537 } else if (f == FEATURE_LUMINOUS) {
539 } else if (f == FEATURE_RESERVED) {
546 mon_feature_t ceph::features::mon::get_feature_by_name(std::string n) {
549 return FEATURE_KRAKEN;
550 } else if (n == "luminous") {
551 return FEATURE_LUMINOUS;
552 } else if (n == "reserved") {
553 return FEATURE_RESERVED;
558 static inline ostream& operator<<(ostream& out, const mon_feature_t& f) {
559 out << "mon_feature_t(";