]> git.proxmox.com Git - ceph.git/blob - ceph/src/mon/mon_types.h
883f4669e2b7f4ca52504a3240f7d111f07e7ea9
[ceph.git] / ceph / src / mon / mon_types.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 #ifndef CEPH_MON_TYPES_H
16 #define CEPH_MON_TYPES_H
17
18 #include <map>
19
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"
25
26 #define PAXOS_PGMAP 0 // before osd, for pg kick to behave
27 #define PAXOS_MDSMAP 1
28 #define PAXOS_OSDMAP 2
29 #define PAXOS_LOG 3
30 #define PAXOS_MONMAP 4
31 #define PAXOS_AUTH 5
32 #define PAXOS_MGR 6
33 #define PAXOS_MGRSTAT 7
34 #define PAXOS_NUM 8
35
36 inline const char *get_paxos_name(int p) {
37 switch (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;
47 }
48 }
49
50 #define CEPH_MON_ONDISK_MAGIC "ceph mon volume v012"
51
52 // map of entity_type -> features -> count
53 struct FeatureMap {
54 std::map<uint32_t,std::map<uint64_t,uint64_t>> m;
55
56 void add(uint32_t type, uint64_t features) {
57 m[type][features]++;
58 }
59
60 void rm(uint32_t type, uint64_t features) {
61 auto p = m.find(type);
62 assert(p != m.end());
63 auto q = p->second.find(features);
64 assert(q != p->second.end());
65 if (--q->second == 0) {
66 p->second.erase(q);
67 if (p->second.empty()) {
68 m.erase(p);
69 }
70 }
71 }
72
73 FeatureMap& operator+=(const FeatureMap& o) {
74 for (auto& p : o.m) {
75 auto &v = m[p.first];
76 for (auto& q : p.second) {
77 v[q.first] += q.second;
78 }
79 }
80 return *this;
81 }
82
83 void encode(bufferlist& bl) const {
84 ENCODE_START(1, 1, bl);
85 ::encode(m, bl);
86 ENCODE_FINISH(bl);
87 }
88
89 void decode(bufferlist::iterator& p) {
90 DECODE_START(1, p);
91 ::decode(m, p);
92 DECODE_FINISH(p);
93 }
94
95 void dump(Formatter *f) const {
96 for (auto& p : m) {
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);
104 f->close_section();
105 }
106 f->close_section();
107 }
108 }
109 };
110 WRITE_CLASS_ENCODER(FeatureMap)
111
112 /**
113 * leveldb store stats
114 *
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
118 * out.
119 */
120 struct LevelDBStoreStats {
121 uint64_t bytes_total;
122 uint64_t bytes_sst;
123 uint64_t bytes_log;
124 uint64_t bytes_misc;
125 utime_t last_update;
126
127 LevelDBStoreStats() :
128 bytes_total(0),
129 bytes_sst(0),
130 bytes_log(0),
131 bytes_misc(0)
132 {}
133
134 void dump(Formatter *f) const {
135 assert(f != NULL);
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;
141 }
142
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);
150 ENCODE_FINISH(bl);
151 }
152
153 void decode(bufferlist::iterator &p) {
154 DECODE_START(1, 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);
160 DECODE_FINISH(p);
161 }
162
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();
171 }
172 };
173 WRITE_CLASS_ENCODER(LevelDBStoreStats)
174
175 // data stats
176
177 struct DataStats {
178 ceph_data_stats_t fs_stats;
179 // data dir
180 utime_t last_update;
181 LevelDBStoreStats store_stats;
182
183 void dump(Formatter *f) const {
184 assert(f != NULL);
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");
191 store_stats.dump(f);
192 f->close_section();
193 }
194
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);
203 ENCODE_FINISH(bl);
204 }
205 void decode(bufferlist::iterator &p) {
206 DECODE_START(1, p);
207 // we moved from having fields in kb to fields in byte
208 if (struct_v > 2) {
209 ::decode(fs_stats.byte_total, p);
210 ::decode(fs_stats.byte_used, p);
211 ::decode(fs_stats.byte_avail, p);
212 } else {
213 uint64_t t;
214 ::decode(t, p);
215 fs_stats.byte_total = t*1024;
216 ::decode(t, p);
217 fs_stats.byte_used = t*1024;
218 ::decode(t, p);
219 fs_stats.byte_avail = t*1024;
220 }
221 ::decode(fs_stats.avail_percent, p);
222 ::decode(last_update, p);
223 if (struct_v > 1)
224 ::decode(store_stats, p);
225
226 DECODE_FINISH(p);
227 }
228 };
229 WRITE_CLASS_ENCODER(DataStats)
230
231 struct ScrubResult {
232 map<string,uint32_t> prefix_crc; ///< prefix -> crc
233 map<string,uint64_t> prefix_keys; ///< prefix -> key count
234
235 bool operator!=(const ScrubResult& other) {
236 return prefix_crc != other.prefix_crc || prefix_keys != other.prefix_keys;
237 }
238
239 void encode(bufferlist& bl) const {
240 ENCODE_START(1, 1, bl);
241 ::encode(prefix_crc, bl);
242 ::encode(prefix_keys, bl);
243 ENCODE_FINISH(bl);
244 }
245 void decode(bufferlist::iterator& p) {
246 DECODE_START(1, p);
247 ::decode(prefix_crc, p);
248 ::decode(prefix_keys, p);
249 DECODE_FINISH(p);
250 }
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);
255 f->close_section();
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);
259 f->close_section();
260 }
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;
266 }
267 };
268 WRITE_CLASS_ENCODER(ScrubResult)
269
270 static inline ostream& operator<<(ostream& out, const ScrubResult& r) {
271 return out << "ScrubResult(keys " << r.prefix_keys << " crc " << r.prefix_crc << ")";
272 }
273
274 /// for information like os, kernel, hostname, memory info, cpu model.
275 typedef map<string, string> Metadata;
276
277 namespace ceph {
278 namespace features {
279 namespace mon {
280 /**
281 * Get a feature's name based on its value.
282 *
283 * @param b raw feature value
284 *
285 * @remarks
286 * Consumers should not assume this interface will never change.
287 * @remarks
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.
291 */
292 static inline const char *get_feature_name(uint64_t b);
293 }
294 }
295 }
296
297
298 inline const char *ceph_mon_feature_name(uint64_t b)
299 {
300 return ceph::features::mon::get_feature_name(b);
301 };
302
303 class mon_feature_t {
304
305 static const int HEAD_VERSION = 1;
306 static const int COMPAT_VERSION = 1;
307
308 // mon-specific features
309 uint64_t features;
310
311 public:
312
313 explicit constexpr
314 mon_feature_t(const uint64_t f) : features(f) { }
315
316 mon_feature_t() :
317 features(0) { }
318
319 constexpr
320 mon_feature_t(const mon_feature_t &o) :
321 features(o.features) { }
322
323 mon_feature_t& operator&=(const mon_feature_t other) {
324 features &= other.features;
325 return (*this);
326 }
327
328 /**
329 * Obtain raw features
330 *
331 * @remarks
332 * Consumers should not assume this interface will never change.
333 * @remarks
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.
337 */
338 uint64_t get_raw() const {
339 return features;
340 }
341
342 constexpr
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);
346 }
347
348 mon_feature_t& operator|=(const mon_feature_t other) {
349 features |= other.features;
350 return (*this);
351 }
352
353 constexpr
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);
357 }
358
359 constexpr
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);
363 }
364
365 mon_feature_t& operator^=(const mon_feature_t other) {
366 features ^= other.features;
367 return (*this);
368 }
369
370 bool operator==(const mon_feature_t other) const {
371 return (features == other.features);
372 }
373
374 bool operator!=(const mon_feature_t other) const {
375 return (features != other.features);
376 }
377
378 bool empty() const {
379 return features == 0;
380 }
381
382 /**
383 * Set difference of our features in respect to @p other
384 *
385 * Returns all the elements in our features that are not in @p other
386 *
387 * @returns all the features not in @p other
388 */
389 mon_feature_t diff(const mon_feature_t other) const {
390 return mon_feature_t((features ^ other.features) & features);
391 }
392
393 /**
394 * Set intersection of our features and @p other
395 *
396 * Returns all the elements common to both our features and the
397 * features of @p other
398 *
399 * @returns the features common to @p other and us
400 */
401 mon_feature_t intersection(const mon_feature_t other) const {
402 return mon_feature_t((features & other.features));
403 }
404
405 /**
406 * Checks whether we have all the features in @p other
407 *
408 * Returns true if we have all the features in @p other
409 *
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
412 */
413 bool contains_all(const mon_feature_t other) const {
414 mon_feature_t d = intersection(other);
415 return d == other;
416 }
417
418 /**
419 * Checks whether we contain any of the features in @p other.
420 *
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
423 */
424 bool contains_any(const mon_feature_t other) const {
425 mon_feature_t d = intersection(other);
426 return !d.empty();
427 }
428
429 void set_feature(const mon_feature_t f) {
430 features |= f.features;
431 }
432
433 void unset_feature(const mon_feature_t f) {
434 features &= ~(f.features);
435 }
436
437 void print(ostream& out) const {
438 out << "[";
439 print_bit_str(features, out, ceph::features::mon::get_feature_name);
440 out << "]";
441 }
442
443 void print_with_value(ostream& out) const {
444 out << "[";
445 print_bit_str(features, out, ceph::features::mon::get_feature_name, true);
446 out << "]";
447 }
448
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);
452 f->close_section();
453 }
454
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);
458 f->close_section();
459 }
460
461 void encode(bufferlist& bl) const {
462 ENCODE_START(HEAD_VERSION, COMPAT_VERSION, bl);
463 ::encode(features, bl);
464 ENCODE_FINISH(bl);
465 }
466 void decode(bufferlist::iterator& p) {
467 DECODE_START(COMPAT_VERSION, p);
468 ::decode(features, p);
469 DECODE_FINISH(p);
470 }
471 };
472 WRITE_CLASS_ENCODER(mon_feature_t)
473
474 namespace ceph {
475 namespace features {
476 namespace mon {
477 constexpr mon_feature_t FEATURE_KRAKEN( (1ULL << 0));
478 constexpr mon_feature_t FEATURE_LUMINOUS( (1ULL << 1));
479
480 constexpr mon_feature_t FEATURE_RESERVED( (1ULL << 63));
481 constexpr mon_feature_t FEATURE_NONE( (0ULL));
482
483 /**
484 * All the features this monitor supports
485 *
486 * If there's a feature above, it should be OR'ed to this list.
487 */
488 constexpr mon_feature_t get_supported() {
489 return (
490 FEATURE_KRAKEN |
491 FEATURE_LUMINOUS |
492 FEATURE_NONE
493 );
494 }
495 /**
496 * All the features that, once set, cannot be removed.
497 *
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.
501 *
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.
504 */
505 constexpr mon_feature_t get_persistent() {
506 return (
507 FEATURE_KRAKEN |
508 FEATURE_LUMINOUS |
509 FEATURE_NONE
510 );
511 }
512
513 static inline mon_feature_t get_feature_by_name(std::string n);
514 }
515 }
516 }
517
518 static inline const char *ceph::features::mon::get_feature_name(uint64_t b) {
519 mon_feature_t f(b);
520
521 if (f == FEATURE_KRAKEN) {
522 return "kraken";
523 } else if (f == FEATURE_LUMINOUS) {
524 return "luminous";
525 } else if (f == FEATURE_RESERVED) {
526 return "reserved";
527 }
528 return "unknown";
529 }
530
531 static inline
532 mon_feature_t ceph::features::mon::get_feature_by_name(std::string n) {
533
534 if (n == "kraken") {
535 return FEATURE_KRAKEN;
536 } else if (n == "luminous") {
537 return FEATURE_LUMINOUS;
538 } else if (n == "reserved") {
539 return FEATURE_RESERVED;
540 }
541 return FEATURE_NONE;
542 }
543
544 static inline ostream& operator<<(ostream& out, const mon_feature_t& f) {
545 out << "mon_feature_t(";
546 f.print(out);
547 out << ")";
548 return out;
549 }
550
551 #endif