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/Context.h"
21 #include "include/util.h"
22 #include "include/utime.h"
23 #include "common/Formatter.h"
24 #include "common/bit_str.h"
25 #include "common/ceph_releases.h"
27 // use as paxos_service index
42 #define CEPH_MON_ONDISK_MAGIC "ceph mon volume v012"
44 // map of entity_type -> features -> count
46 std::map
<uint32_t,std::map
<uint64_t,uint64_t>> m
;
48 void add(uint32_t type
, uint64_t features
) {
49 if (type
== CEPH_ENTITY_TYPE_MON
) {
55 void add_mon(uint64_t features
) {
56 m
[CEPH_ENTITY_TYPE_MON
][features
]++;
59 void rm(uint32_t type
, uint64_t features
) {
60 if (type
== CEPH_ENTITY_TYPE_MON
) {
63 auto p
= m
.find(type
);
64 ceph_assert(p
!= m
.end());
65 auto q
= p
->second
.find(features
);
66 ceph_assert(q
!= p
->second
.end());
67 if (--q
->second
== 0) {
69 if (p
->second
.empty()) {
75 FeatureMap
& operator+=(const FeatureMap
& o
) {
78 for (auto& q
: p
.second
) {
79 v
[q
.first
] += q
.second
;
85 void encode(ceph::buffer::list
& bl
) const {
86 ENCODE_START(1, 1, bl
);
91 void decode(ceph::buffer::list::const_iterator
& p
) {
97 void dump(ceph::Formatter
*f
) const {
99 f
->open_array_section(ceph_entity_type_name(p
.first
));
100 for (auto& q
: p
.second
) {
101 f
->open_object_section("group");
102 std::stringstream ss
;
103 ss
<< "0x" << std::hex
<< q
.first
<< std::dec
;
104 f
->dump_string("features", ss
.str());
105 f
->dump_string("release", ceph_release_name(
106 ceph_release_from_features(q
.first
)));
107 f
->dump_unsigned("num", q
.second
);
114 WRITE_CLASS_ENCODER(FeatureMap
)
117 * leveldb store stats
119 * If we ever decide to support multiple backends for the monitor store,
120 * we should then create an abstract class 'MonitorStoreStats' of sorts
121 * and inherit it on LevelDBStoreStats. I'm sure you'll figure something
124 struct LevelDBStoreStats
{
125 uint64_t bytes_total
;
131 LevelDBStoreStats() :
138 void dump(ceph::Formatter
*f
) const {
139 ceph_assert(f
!= NULL
);
140 f
->dump_int("bytes_total", bytes_total
);
141 f
->dump_int("bytes_sst", bytes_sst
);
142 f
->dump_int("bytes_log", bytes_log
);
143 f
->dump_int("bytes_misc", bytes_misc
);
144 f
->dump_stream("last_updated") << last_update
;
147 void encode(ceph::buffer::list
&bl
) const {
148 ENCODE_START(1, 1, bl
);
149 encode(bytes_total
, bl
);
150 encode(bytes_sst
, bl
);
151 encode(bytes_log
, bl
);
152 encode(bytes_misc
, bl
);
153 encode(last_update
, bl
);
157 void decode(ceph::buffer::list::const_iterator
&p
) {
159 decode(bytes_total
, p
);
160 decode(bytes_sst
, p
);
161 decode(bytes_log
, p
);
162 decode(bytes_misc
, p
);
163 decode(last_update
, p
);
167 static void generate_test_instances(std::list
<LevelDBStoreStats
*>& ls
) {
168 ls
.push_back(new LevelDBStoreStats
);
169 ls
.push_back(new LevelDBStoreStats
);
170 ls
.back()->bytes_total
= 1024*1024;
171 ls
.back()->bytes_sst
= 512*1024;
172 ls
.back()->bytes_log
= 256*1024;
173 ls
.back()->bytes_misc
= 256*1024;
174 ls
.back()->last_update
= utime_t();
177 WRITE_CLASS_ENCODER(LevelDBStoreStats
)
182 ceph_data_stats_t fs_stats
;
185 LevelDBStoreStats store_stats
;
187 void dump(ceph::Formatter
*f
) const {
188 ceph_assert(f
!= NULL
);
189 f
->dump_int("kb_total", (fs_stats
.byte_total
/1024));
190 f
->dump_int("kb_used", (fs_stats
.byte_used
/1024));
191 f
->dump_int("kb_avail", (fs_stats
.byte_avail
/1024));
192 f
->dump_int("avail_percent", fs_stats
.avail_percent
);
193 f
->dump_stream("last_updated") << last_update
;
194 f
->open_object_section("store_stats");
199 void encode(ceph::buffer::list
&bl
) const {
200 ENCODE_START(3, 1, bl
);
201 encode(fs_stats
.byte_total
, bl
);
202 encode(fs_stats
.byte_used
, bl
);
203 encode(fs_stats
.byte_avail
, bl
);
204 encode(fs_stats
.avail_percent
, bl
);
205 encode(last_update
, bl
);
206 encode(store_stats
, bl
);
209 void decode(ceph::buffer::list::const_iterator
&p
) {
211 // we moved from having fields in kb to fields in byte
213 decode(fs_stats
.byte_total
, p
);
214 decode(fs_stats
.byte_used
, p
);
215 decode(fs_stats
.byte_avail
, p
);
219 fs_stats
.byte_total
= t
*1024;
221 fs_stats
.byte_used
= t
*1024;
223 fs_stats
.byte_avail
= t
*1024;
225 decode(fs_stats
.avail_percent
, p
);
226 decode(last_update
, p
);
228 decode(store_stats
, p
);
233 WRITE_CLASS_ENCODER(DataStats
)
236 std::map
<std::string
,uint32_t> prefix_crc
; ///< prefix -> crc
237 std::map
<std::string
,uint64_t> prefix_keys
; ///< prefix -> key count
239 bool operator!=(const ScrubResult
& other
) {
240 return prefix_crc
!= other
.prefix_crc
|| prefix_keys
!= other
.prefix_keys
;
243 void encode(ceph::buffer::list
& bl
) const {
244 ENCODE_START(1, 1, bl
);
245 encode(prefix_crc
, bl
);
246 encode(prefix_keys
, bl
);
249 void decode(ceph::buffer::list::const_iterator
& p
) {
251 decode(prefix_crc
, p
);
252 decode(prefix_keys
, p
);
255 void dump(ceph::Formatter
*f
) const {
256 f
->open_object_section("crc");
257 for (auto p
= prefix_crc
.begin(); p
!= prefix_crc
.end(); ++p
)
258 f
->dump_unsigned(p
->first
.c_str(), p
->second
);
260 f
->open_object_section("keys");
261 for (auto p
= prefix_keys
.begin(); p
!= prefix_keys
.end(); ++p
)
262 f
->dump_unsigned(p
->first
.c_str(), p
->second
);
265 static void generate_test_instances(std::list
<ScrubResult
*>& ls
) {
266 ls
.push_back(new ScrubResult
);
267 ls
.push_back(new ScrubResult
);
268 ls
.back()->prefix_crc
["foo"] = 123;
269 ls
.back()->prefix_keys
["bar"] = 456;
272 WRITE_CLASS_ENCODER(ScrubResult
)
274 inline std::ostream
& operator<<(std::ostream
& out
, const ScrubResult
& r
) {
275 return out
<< "ScrubResult(keys " << r
.prefix_keys
<< " crc " << r
.prefix_crc
<< ")";
278 /// for information like os, kernel, hostname, memory info, cpu model.
279 typedef std::map
<std::string
, std::string
> Metadata
;
285 * Get a feature's name based on its value.
287 * @param b raw feature value
290 * Consumers should not assume this interface will never change.
292 * As the number of features increase, so may the internal representation
293 * of the raw features. When this happens, this interface will change
294 * accordingly. So should consumers of this interface.
296 static inline const char *get_feature_name(uint64_t b
);
302 inline const char *ceph_mon_feature_name(uint64_t b
)
304 return ceph::features::mon::get_feature_name(b
);
307 class mon_feature_t
{
309 static constexpr int HEAD_VERSION
= 1;
310 static constexpr int COMPAT_VERSION
= 1;
312 // mon-specific features
318 mon_feature_t(const uint64_t f
) : features(f
) { }
324 mon_feature_t(const mon_feature_t
&o
) :
325 features(o
.features
) { }
327 mon_feature_t
& operator&=(const mon_feature_t other
) {
328 features
&= other
.features
;
333 * Obtain raw features
336 * Consumers should not assume this interface will never change.
338 * As the number of features increase, so may the internal representation
339 * of the raw features. When this happens, this interface will change
340 * accordingly. So should consumers of this interface.
342 uint64_t get_raw() const {
347 friend mon_feature_t
operator&(const mon_feature_t a
,
348 const mon_feature_t b
) {
349 return mon_feature_t(a
.features
& b
.features
);
352 mon_feature_t
& operator|=(const mon_feature_t other
) {
353 features
|= other
.features
;
358 friend mon_feature_t
operator|(const mon_feature_t a
,
359 const mon_feature_t b
) {
360 return mon_feature_t(a
.features
| b
.features
);
364 friend mon_feature_t
operator^(const mon_feature_t a
,
365 const mon_feature_t b
) {
366 return mon_feature_t(a
.features
^ b
.features
);
369 mon_feature_t
& operator^=(const mon_feature_t other
) {
370 features
^= other
.features
;
374 bool operator==(const mon_feature_t other
) const {
375 return (features
== other
.features
);
378 bool operator!=(const mon_feature_t other
) const {
379 return (features
!= other
.features
);
383 return features
== 0;
387 * Set difference of our features in respect to @p other
389 * Returns all the elements in our features that are not in @p other
391 * @returns all the features not in @p other
393 mon_feature_t
diff(const mon_feature_t other
) const {
394 return mon_feature_t((features
^ other
.features
) & features
);
398 * Set intersection of our features and @p other
400 * Returns all the elements common to both our features and the
401 * features of @p other
403 * @returns the features common to @p other and us
405 mon_feature_t
intersection(const mon_feature_t other
) const {
406 return mon_feature_t((features
& other
.features
));
410 * Checks whether we have all the features in @p other
412 * Returns true if we have all the features in @p other
414 * @returns true if we contain all the features in @p other
415 * @returns false if we do not contain some of the features in @p other
417 bool contains_all(const mon_feature_t other
) const {
418 mon_feature_t d
= intersection(other
);
423 * Checks whether we contain any of the features in @p other.
425 * @returns true if we contain any of the features in @p other
426 * @returns false if we don't contain any of the features in @p other
428 bool contains_any(const mon_feature_t other
) const {
429 mon_feature_t d
= intersection(other
);
433 void set_feature(const mon_feature_t f
) {
434 features
|= f
.features
;
437 void unset_feature(const mon_feature_t f
) {
438 features
&= ~(f
.features
);
441 void print(std::ostream
& out
) const {
443 print_bit_str(features
, out
, ceph::features::mon::get_feature_name
);
447 void print_with_value(std::ostream
& out
) const {
449 print_bit_str(features
, out
, ceph::features::mon::get_feature_name
, true);
453 void dump(ceph::Formatter
*f
, const char *sec_name
= NULL
) const {
454 f
->open_array_section((sec_name
? sec_name
: "features"));
455 dump_bit_str(features
, f
, ceph::features::mon::get_feature_name
);
459 void dump_with_value(ceph::Formatter
*f
, const char *sec_name
= NULL
) const {
460 f
->open_array_section((sec_name
? sec_name
: "features"));
461 dump_bit_str(features
, f
, ceph::features::mon::get_feature_name
, true);
465 void encode(ceph::buffer::list
& bl
) const {
466 ENCODE_START(HEAD_VERSION
, COMPAT_VERSION
, bl
);
467 encode(features
, bl
);
470 void decode(ceph::buffer::list::const_iterator
& p
) {
471 DECODE_START(COMPAT_VERSION
, p
);
476 WRITE_CLASS_ENCODER(mon_feature_t
)
481 constexpr mon_feature_t
FEATURE_KRAKEN( (1ULL << 0));
482 constexpr mon_feature_t
FEATURE_LUMINOUS( (1ULL << 1));
483 constexpr mon_feature_t
FEATURE_MIMIC( (1ULL << 2));
484 constexpr mon_feature_t
FEATURE_OSDMAP_PRUNE (1ULL << 3);
485 constexpr mon_feature_t
FEATURE_NAUTILUS( (1ULL << 4));
486 constexpr mon_feature_t
FEATURE_OCTOPUS( (1ULL << 5));
487 constexpr mon_feature_t
FEATURE_PACIFIC( (1ULL << 6));
488 // elector pinging and CONNECTIVITY mode:
489 constexpr mon_feature_t
FEATURE_PINGING( (1ULL << 7));
491 constexpr mon_feature_t
FEATURE_RESERVED( (1ULL << 63));
492 constexpr mon_feature_t
FEATURE_NONE( (0ULL));
495 * All the features this monitor supports
497 * If there's a feature above, it should be OR'ed to this list.
499 constexpr mon_feature_t
get_supported() {
504 FEATURE_OSDMAP_PRUNE
|
513 * All the features that, once set, cannot be removed.
515 * Features should only be added to this list if you want to make
516 * sure downgrades are not possible after a quorum supporting all
517 * these features has been formed.
519 * Any feature in this list will be automatically set on the monmap's
520 * features once all the monitors in the quorum support it.
522 constexpr mon_feature_t
get_persistent() {
528 FEATURE_OSDMAP_PRUNE
|
536 constexpr mon_feature_t
get_optional() {
538 FEATURE_OSDMAP_PRUNE
|
543 static inline mon_feature_t
get_feature_by_name(const std::string
&n
);
548 static inline ceph_release_t
infer_ceph_release_from_mon_features(mon_feature_t f
)
550 if (f
.contains_all(ceph::features::mon::FEATURE_PACIFIC
)) {
551 return ceph_release_t::pacific
;
553 if (f
.contains_all(ceph::features::mon::FEATURE_OCTOPUS
)) {
554 return ceph_release_t::octopus
;
556 if (f
.contains_all(ceph::features::mon::FEATURE_NAUTILUS
)) {
557 return ceph_release_t::nautilus
;
559 if (f
.contains_all(ceph::features::mon::FEATURE_MIMIC
)) {
560 return ceph_release_t::mimic
;
562 if (f
.contains_all(ceph::features::mon::FEATURE_LUMINOUS
)) {
563 return ceph_release_t::luminous
;
565 if (f
.contains_all(ceph::features::mon::FEATURE_KRAKEN
)) {
566 return ceph_release_t::kraken
;
568 return ceph_release_t::unknown
;
571 static inline const char *ceph::features::mon::get_feature_name(uint64_t b
) {
574 if (f
== FEATURE_KRAKEN
) {
576 } else if (f
== FEATURE_LUMINOUS
) {
578 } else if (f
== FEATURE_MIMIC
) {
580 } else if (f
== FEATURE_OSDMAP_PRUNE
) {
581 return "osdmap-prune";
582 } else if (f
== FEATURE_NAUTILUS
) {
584 } else if (f
== FEATURE_PINGING
) {
585 return "elector-pinging";
586 } else if (f
== FEATURE_OCTOPUS
) {
588 } else if (f
== FEATURE_PACIFIC
) {
590 } else if (f
== FEATURE_RESERVED
) {
596 inline mon_feature_t
ceph::features::mon::get_feature_by_name(const std::string
&n
) {
599 return FEATURE_KRAKEN
;
600 } else if (n
== "luminous") {
601 return FEATURE_LUMINOUS
;
602 } else if (n
== "mimic") {
603 return FEATURE_MIMIC
;
604 } else if (n
== "osdmap-prune") {
605 return FEATURE_OSDMAP_PRUNE
;
606 } else if (n
== "nautilus") {
607 return FEATURE_NAUTILUS
;
608 } else if (n
== "feature-pinging") {
609 return FEATURE_PINGING
;
610 } else if (n
== "octopus") {
611 return FEATURE_OCTOPUS
;
612 } else if (n
== "pacific") {
613 return FEATURE_PACIFIC
;
614 } else if (n
== "reserved") {
615 return FEATURE_RESERVED
;
620 inline std::ostream
& operator<<(std::ostream
& out
, const mon_feature_t
& f
) {
621 out
<< "mon_feature_t(";
628 struct ProgressEvent
{
629 std::string message
; ///< event description
630 float progress
; ///< [0..1]
632 void encode(ceph::buffer::list
& bl
) const {
633 ENCODE_START(2, 1, bl
);
635 encode(progress
, bl
);
636 encode(add_to_ceph_s
, bl
);
639 void decode(ceph::buffer::list::const_iterator
& p
) {
644 decode(add_to_ceph_s
, p
);
646 if (!message
.empty()) {
647 add_to_ceph_s
= true;
652 void dump(ceph::Formatter
*f
) const {
653 f
->dump_string("message", message
);
654 f
->dump_float("progress", progress
);
655 f
->dump_bool("add_to_ceph_s", add_to_ceph_s
);
658 WRITE_CLASS_ENCODER(ProgressEvent
)