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
36 inline const char *get_paxos_name(int p
) {
38 case PAXOS_MDSMAP
: return "mdsmap";
39 case PAXOS_MONMAP
: return "monmap";
40 case PAXOS_OSDMAP
: return "osdmap";
41 case PAXOS_PGMAP
: return "pgmap";
42 case PAXOS_LOG
: return "logm";
43 case PAXOS_AUTH
: return "auth";
44 case PAXOS_MGR
: return "mgr";
45 case PAXOS_MGRSTAT
: return "mgrstat";
46 default: ceph_abort(); return 0;
50 #define CEPH_MON_ONDISK_MAGIC "ceph mon volume v012"
52 // map of entity_type -> features -> count
54 std::map
<uint32_t,std::map
<uint64_t,uint64_t>> m
;
56 void add(uint32_t type
, uint64_t features
) {
60 void rm(uint32_t type
, uint64_t features
) {
61 auto p
= m
.find(type
);
63 auto q
= p
->second
.find(features
);
64 assert(q
!= p
->second
.end());
65 if (--q
->second
== 0) {
67 if (p
->second
.empty()) {
73 FeatureMap
& operator+=(const FeatureMap
& o
) {
76 for (auto& q
: p
.second
) {
77 v
[q
.first
] += q
.second
;
83 void encode(bufferlist
& bl
) const {
84 ENCODE_START(1, 1, bl
);
89 void decode(bufferlist::iterator
& p
) {
95 void dump(Formatter
*f
) const {
97 f
->open_object_section(ceph_entity_type_name(p
.first
));
98 for (auto& q
: p
.second
) {
99 f
->open_object_section("group");
100 f
->dump_unsigned("features", q
.first
);
101 f
->dump_string("release", ceph_release_name(
102 ceph_release_from_features(q
.first
)));
103 f
->dump_unsigned("num", q
.second
);
110 WRITE_CLASS_ENCODER(FeatureMap
)
113 * leveldb store stats
115 * If we ever decide to support multiple backends for the monitor store,
116 * we should then create an abstract class 'MonitorStoreStats' of sorts
117 * and inherit it on LevelDBStoreStats. I'm sure you'll figure something
120 struct LevelDBStoreStats
{
121 uint64_t bytes_total
;
127 LevelDBStoreStats() :
134 void dump(Formatter
*f
) const {
136 f
->dump_int("bytes_total", bytes_total
);
137 f
->dump_int("bytes_sst", bytes_sst
);
138 f
->dump_int("bytes_log", bytes_log
);
139 f
->dump_int("bytes_misc", bytes_misc
);
140 f
->dump_stream("last_updated") << last_update
;
143 void encode(bufferlist
&bl
) const {
144 ENCODE_START(1, 1, bl
);
145 ::encode(bytes_total
, bl
);
146 ::encode(bytes_sst
, bl
);
147 ::encode(bytes_log
, bl
);
148 ::encode(bytes_misc
, bl
);
149 ::encode(last_update
, bl
);
153 void decode(bufferlist::iterator
&p
) {
155 ::decode(bytes_total
, p
);
156 ::decode(bytes_sst
, p
);
157 ::decode(bytes_log
, p
);
158 ::decode(bytes_misc
, p
);
159 ::decode(last_update
, p
);
163 static void generate_test_instances(list
<LevelDBStoreStats
*>& ls
) {
164 ls
.push_back(new LevelDBStoreStats
);
165 ls
.push_back(new LevelDBStoreStats
);
166 ls
.back()->bytes_total
= 1024*1024;
167 ls
.back()->bytes_sst
= 512*1024;
168 ls
.back()->bytes_log
= 256*1024;
169 ls
.back()->bytes_misc
= 256*1024;
170 ls
.back()->last_update
= utime_t();
173 WRITE_CLASS_ENCODER(LevelDBStoreStats
)
178 ceph_data_stats_t fs_stats
;
181 LevelDBStoreStats store_stats
;
183 void dump(Formatter
*f
) const {
185 f
->dump_int("kb_total", (fs_stats
.byte_total
/1024));
186 f
->dump_int("kb_used", (fs_stats
.byte_used
/1024));
187 f
->dump_int("kb_avail", (fs_stats
.byte_avail
/1024));
188 f
->dump_int("avail_percent", fs_stats
.avail_percent
);
189 f
->dump_stream("last_updated") << last_update
;
190 f
->open_object_section("store_stats");
195 void encode(bufferlist
&bl
) const {
196 ENCODE_START(3, 1, bl
);
197 ::encode(fs_stats
.byte_total
, bl
);
198 ::encode(fs_stats
.byte_used
, bl
);
199 ::encode(fs_stats
.byte_avail
, bl
);
200 ::encode(fs_stats
.avail_percent
, bl
);
201 ::encode(last_update
, bl
);
202 ::encode(store_stats
, bl
);
205 void decode(bufferlist::iterator
&p
) {
207 // we moved from having fields in kb to fields in byte
209 ::decode(fs_stats
.byte_total
, p
);
210 ::decode(fs_stats
.byte_used
, p
);
211 ::decode(fs_stats
.byte_avail
, p
);
215 fs_stats
.byte_total
= t
*1024;
217 fs_stats
.byte_used
= t
*1024;
219 fs_stats
.byte_avail
= t
*1024;
221 ::decode(fs_stats
.avail_percent
, p
);
222 ::decode(last_update
, p
);
224 ::decode(store_stats
, p
);
229 WRITE_CLASS_ENCODER(DataStats
)
232 map
<string
,uint32_t> prefix_crc
; ///< prefix -> crc
233 map
<string
,uint64_t> prefix_keys
; ///< prefix -> key count
235 bool operator!=(const ScrubResult
& other
) {
236 return prefix_crc
!= other
.prefix_crc
|| prefix_keys
!= other
.prefix_keys
;
239 void encode(bufferlist
& bl
) const {
240 ENCODE_START(1, 1, bl
);
241 ::encode(prefix_crc
, bl
);
242 ::encode(prefix_keys
, bl
);
245 void decode(bufferlist::iterator
& p
) {
247 ::decode(prefix_crc
, p
);
248 ::decode(prefix_keys
, p
);
251 void dump(Formatter
*f
) const {
252 f
->open_object_section("crc");
253 for (map
<string
,uint32_t>::const_iterator p
= prefix_crc
.begin(); p
!= prefix_crc
.end(); ++p
)
254 f
->dump_unsigned(p
->first
.c_str(), p
->second
);
256 f
->open_object_section("keys");
257 for (map
<string
,uint64_t>::const_iterator p
= prefix_keys
.begin(); p
!= prefix_keys
.end(); ++p
)
258 f
->dump_unsigned(p
->first
.c_str(), p
->second
);
261 static void generate_test_instances(list
<ScrubResult
*>& ls
) {
262 ls
.push_back(new ScrubResult
);
263 ls
.push_back(new ScrubResult
);
264 ls
.back()->prefix_crc
["foo"] = 123;
265 ls
.back()->prefix_keys
["bar"] = 456;
268 WRITE_CLASS_ENCODER(ScrubResult
)
270 static inline ostream
& operator<<(ostream
& out
, const ScrubResult
& r
) {
271 return out
<< "ScrubResult(keys " << r
.prefix_keys
<< " crc " << r
.prefix_crc
<< ")";
274 /// for information like os, kernel, hostname, memory info, cpu model.
275 typedef map
<string
, string
> Metadata
;
281 * Get a feature's name based on its value.
283 * @param b raw feature value
286 * Consumers should not assume this interface will never change.
288 * As the number of features increase, so may the internal representation
289 * of the raw features. When this happens, this interface will change
290 * accordingly. So should consumers of this interface.
292 static inline const char *get_feature_name(uint64_t b
);
298 inline const char *ceph_mon_feature_name(uint64_t b
)
300 return ceph::features::mon::get_feature_name(b
);
303 class mon_feature_t
{
305 static const int HEAD_VERSION
= 1;
306 static const int COMPAT_VERSION
= 1;
308 // mon-specific features
314 mon_feature_t(const uint64_t f
) : features(f
) { }
320 mon_feature_t(const mon_feature_t
&o
) :
321 features(o
.features
) { }
323 mon_feature_t
& operator&=(const mon_feature_t other
) {
324 features
&= other
.features
;
329 * Obtain raw features
332 * Consumers should not assume this interface will never change.
334 * As the number of features increase, so may the internal representation
335 * of the raw features. When this happens, this interface will change
336 * accordingly. So should consumers of this interface.
338 uint64_t get_raw() const {
343 friend mon_feature_t
operator&(const mon_feature_t a
,
344 const mon_feature_t b
) {
345 return mon_feature_t(a
.features
& b
.features
);
348 mon_feature_t
& operator|=(const mon_feature_t other
) {
349 features
|= other
.features
;
354 friend mon_feature_t
operator|(const mon_feature_t a
,
355 const mon_feature_t b
) {
356 return mon_feature_t(a
.features
| b
.features
);
360 friend mon_feature_t
operator^(const mon_feature_t a
,
361 const mon_feature_t b
) {
362 return mon_feature_t(a
.features
^ b
.features
);
365 mon_feature_t
& operator^=(const mon_feature_t other
) {
366 features
^= other
.features
;
370 bool operator==(const mon_feature_t other
) const {
371 return (features
== other
.features
);
374 bool operator!=(const mon_feature_t other
) const {
375 return (features
!= other
.features
);
379 return features
== 0;
383 * Set difference of our features in respect to @p other
385 * Returns all the elements in our features that are not in @p other
387 * @returns all the features not in @p other
389 mon_feature_t
diff(const mon_feature_t other
) const {
390 return mon_feature_t((features
^ other
.features
) & features
);
394 * Set intersection of our features and @p other
396 * Returns all the elements common to both our features and the
397 * features of @p other
399 * @returns the features common to @p other and us
401 mon_feature_t
intersection(const mon_feature_t other
) const {
402 return mon_feature_t((features
& other
.features
));
406 * Checks whether we have all the features in @p other
408 * Returns true if we have all the features in @p other
410 * @returns true if we contain all the features in @p other
411 * @returns false if we do not contain some of the features in @p other
413 bool contains_all(const mon_feature_t other
) const {
414 mon_feature_t d
= intersection(other
);
419 * Checks whether we contain any of the features in @p other.
421 * @returns true if we contain any of the features in @p other
422 * @returns false if we don't contain any of the features in @p other
424 bool contains_any(const mon_feature_t other
) const {
425 mon_feature_t d
= intersection(other
);
429 void set_feature(const mon_feature_t f
) {
430 features
|= f
.features
;
433 void unset_feature(const mon_feature_t f
) {
434 features
&= ~(f
.features
);
437 void print(ostream
& out
) const {
439 print_bit_str(features
, out
, ceph::features::mon::get_feature_name
);
443 void print_with_value(ostream
& out
) const {
445 print_bit_str(features
, out
, ceph::features::mon::get_feature_name
, true);
449 void dump(Formatter
*f
, const char *sec_name
= NULL
) const {
450 f
->open_array_section((sec_name
? sec_name
: "features"));
451 dump_bit_str(features
, f
, ceph::features::mon::get_feature_name
);
455 void dump_with_value(Formatter
*f
, const char *sec_name
= NULL
) const {
456 f
->open_array_section((sec_name
? sec_name
: "features"));
457 dump_bit_str(features
, f
, ceph::features::mon::get_feature_name
, true);
461 void encode(bufferlist
& bl
) const {
462 ENCODE_START(HEAD_VERSION
, COMPAT_VERSION
, bl
);
463 ::encode(features
, bl
);
466 void decode(bufferlist::iterator
& p
) {
467 DECODE_START(COMPAT_VERSION
, p
);
468 ::decode(features
, p
);
472 WRITE_CLASS_ENCODER(mon_feature_t
)
477 constexpr mon_feature_t
FEATURE_KRAKEN( (1ULL << 0));
478 constexpr mon_feature_t
FEATURE_LUMINOUS( (1ULL << 1));
480 constexpr mon_feature_t
FEATURE_RESERVED( (1ULL << 63));
481 constexpr mon_feature_t
FEATURE_NONE( (0ULL));
484 * All the features this monitor supports
486 * If there's a feature above, it should be OR'ed to this list.
488 constexpr mon_feature_t
get_supported() {
496 * All the features that, once set, cannot be removed.
498 * Features should only be added to this list if you want to make
499 * sure downgrades are not possible after a quorum supporting all
500 * these features has been formed.
502 * Any feature in this list will be automatically set on the monmap's
503 * features once all the monitors in the quorum support it.
505 constexpr mon_feature_t
get_persistent() {
513 static inline mon_feature_t
get_feature_by_name(std::string n
);
518 static inline const char *ceph::features::mon::get_feature_name(uint64_t b
) {
521 if (f
== FEATURE_KRAKEN
) {
523 } else if (f
== FEATURE_LUMINOUS
) {
525 } else if (f
== FEATURE_RESERVED
) {
532 mon_feature_t
ceph::features::mon::get_feature_by_name(std::string n
) {
535 return FEATURE_KRAKEN
;
536 } else if (n
== "luminous") {
537 return FEATURE_LUMINOUS
;
538 } else if (n
== "reserved") {
539 return FEATURE_RESERVED
;
544 static inline ostream
& operator<<(ostream
& out
, const mon_feature_t
& f
) {
545 out
<< "mon_feature_t(";