]>
Commit | Line | Data |
---|---|---|
7c673cae FG |
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 | ||
31f18b77 FG |
18 | #include <map> |
19 | ||
7c673cae FG |
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" | |
7c673cae FG |
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 | |
31f18b77 | 33 | #define PAXOS_MGRSTAT 7 |
224ce89b WB |
34 | #define PAXOS_HEALTH 8 |
35 | #define PAXOS_NUM 9 | |
7c673cae FG |
36 | |
37 | inline const char *get_paxos_name(int p) { | |
38 | switch (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"; | |
31f18b77 | 46 | case PAXOS_MGRSTAT: return "mgrstat"; |
224ce89b | 47 | case PAXOS_HEALTH: return "health"; |
7c673cae FG |
48 | default: ceph_abort(); return 0; |
49 | } | |
50 | } | |
51 | ||
52 | #define CEPH_MON_ONDISK_MAGIC "ceph mon volume v012" | |
53 | ||
31f18b77 FG |
54 | // map of entity_type -> features -> count |
55 | struct FeatureMap { | |
56 | std::map<uint32_t,std::map<uint64_t,uint64_t>> m; | |
57 | ||
58 | void add(uint32_t type, uint64_t features) { | |
b5b8bbf5 FG |
59 | if (type == CEPH_ENTITY_TYPE_MON) { |
60 | return; | |
61 | } | |
31f18b77 FG |
62 | m[type][features]++; |
63 | } | |
64 | ||
b5b8bbf5 FG |
65 | void add_mon(uint64_t features) { |
66 | m[CEPH_ENTITY_TYPE_MON][features]++; | |
67 | } | |
68 | ||
31f18b77 | 69 | void rm(uint32_t type, uint64_t features) { |
b5b8bbf5 FG |
70 | if (type == CEPH_ENTITY_TYPE_MON) { |
71 | return; | |
72 | } | |
31f18b77 FG |
73 | auto p = m.find(type); |
74 | assert(p != m.end()); | |
75 | auto q = p->second.find(features); | |
76 | assert(q != p->second.end()); | |
77 | if (--q->second == 0) { | |
78 | p->second.erase(q); | |
79 | if (p->second.empty()) { | |
80 | m.erase(p); | |
81 | } | |
82 | } | |
83 | } | |
84 | ||
85 | FeatureMap& operator+=(const FeatureMap& o) { | |
86 | for (auto& p : o.m) { | |
87 | auto &v = m[p.first]; | |
88 | for (auto& q : p.second) { | |
89 | v[q.first] += q.second; | |
90 | } | |
91 | } | |
92 | return *this; | |
93 | } | |
94 | ||
95 | void encode(bufferlist& bl) const { | |
96 | ENCODE_START(1, 1, bl); | |
97 | ::encode(m, bl); | |
98 | ENCODE_FINISH(bl); | |
99 | } | |
100 | ||
101 | void decode(bufferlist::iterator& p) { | |
102 | DECODE_START(1, p); | |
103 | ::decode(m, p); | |
104 | DECODE_FINISH(p); | |
105 | } | |
106 | ||
107 | void dump(Formatter *f) const { | |
108 | for (auto& p : m) { | |
109 | f->open_object_section(ceph_entity_type_name(p.first)); | |
110 | for (auto& q : p.second) { | |
111 | f->open_object_section("group"); | |
b5b8bbf5 FG |
112 | std::stringstream ss; |
113 | ss << "0x" << std::hex << q.first << std::dec; | |
114 | f->dump_string("features", ss.str()); | |
31f18b77 FG |
115 | f->dump_string("release", ceph_release_name( |
116 | ceph_release_from_features(q.first))); | |
117 | f->dump_unsigned("num", q.second); | |
118 | f->close_section(); | |
119 | } | |
120 | f->close_section(); | |
121 | } | |
122 | } | |
123 | }; | |
124 | WRITE_CLASS_ENCODER(FeatureMap) | |
125 | ||
7c673cae FG |
126 | /** |
127 | * leveldb store stats | |
128 | * | |
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 | |
132 | * out. | |
133 | */ | |
134 | struct LevelDBStoreStats { | |
135 | uint64_t bytes_total; | |
136 | uint64_t bytes_sst; | |
137 | uint64_t bytes_log; | |
138 | uint64_t bytes_misc; | |
139 | utime_t last_update; | |
140 | ||
141 | LevelDBStoreStats() : | |
142 | bytes_total(0), | |
143 | bytes_sst(0), | |
144 | bytes_log(0), | |
145 | bytes_misc(0) | |
146 | {} | |
147 | ||
148 | void dump(Formatter *f) const { | |
149 | assert(f != NULL); | |
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; | |
155 | } | |
156 | ||
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); | |
164 | ENCODE_FINISH(bl); | |
165 | } | |
166 | ||
167 | void decode(bufferlist::iterator &p) { | |
168 | DECODE_START(1, 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); | |
174 | DECODE_FINISH(p); | |
175 | } | |
176 | ||
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(); | |
185 | } | |
186 | }; | |
187 | WRITE_CLASS_ENCODER(LevelDBStoreStats) | |
188 | ||
189 | // data stats | |
190 | ||
191 | struct DataStats { | |
192 | ceph_data_stats_t fs_stats; | |
193 | // data dir | |
194 | utime_t last_update; | |
195 | LevelDBStoreStats store_stats; | |
196 | ||
197 | void dump(Formatter *f) const { | |
198 | assert(f != NULL); | |
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"); | |
205 | store_stats.dump(f); | |
206 | f->close_section(); | |
207 | } | |
208 | ||
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); | |
217 | ENCODE_FINISH(bl); | |
218 | } | |
219 | void decode(bufferlist::iterator &p) { | |
220 | DECODE_START(1, p); | |
221 | // we moved from having fields in kb to fields in byte | |
222 | if (struct_v > 2) { | |
223 | ::decode(fs_stats.byte_total, p); | |
224 | ::decode(fs_stats.byte_used, p); | |
225 | ::decode(fs_stats.byte_avail, p); | |
226 | } else { | |
227 | uint64_t t; | |
228 | ::decode(t, p); | |
229 | fs_stats.byte_total = t*1024; | |
230 | ::decode(t, p); | |
231 | fs_stats.byte_used = t*1024; | |
232 | ::decode(t, p); | |
233 | fs_stats.byte_avail = t*1024; | |
234 | } | |
235 | ::decode(fs_stats.avail_percent, p); | |
236 | ::decode(last_update, p); | |
237 | if (struct_v > 1) | |
238 | ::decode(store_stats, p); | |
239 | ||
240 | DECODE_FINISH(p); | |
241 | } | |
242 | }; | |
243 | WRITE_CLASS_ENCODER(DataStats) | |
244 | ||
245 | struct ScrubResult { | |
246 | map<string,uint32_t> prefix_crc; ///< prefix -> crc | |
247 | map<string,uint64_t> prefix_keys; ///< prefix -> key count | |
248 | ||
249 | bool operator!=(const ScrubResult& other) { | |
250 | return prefix_crc != other.prefix_crc || prefix_keys != other.prefix_keys; | |
251 | } | |
252 | ||
253 | void encode(bufferlist& bl) const { | |
254 | ENCODE_START(1, 1, bl); | |
255 | ::encode(prefix_crc, bl); | |
256 | ::encode(prefix_keys, bl); | |
257 | ENCODE_FINISH(bl); | |
258 | } | |
259 | void decode(bufferlist::iterator& p) { | |
260 | DECODE_START(1, p); | |
261 | ::decode(prefix_crc, p); | |
262 | ::decode(prefix_keys, p); | |
263 | DECODE_FINISH(p); | |
264 | } | |
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); | |
269 | f->close_section(); | |
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); | |
273 | f->close_section(); | |
274 | } | |
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; | |
280 | } | |
281 | }; | |
282 | WRITE_CLASS_ENCODER(ScrubResult) | |
283 | ||
284 | static inline ostream& operator<<(ostream& out, const ScrubResult& r) { | |
285 | return out << "ScrubResult(keys " << r.prefix_keys << " crc " << r.prefix_crc << ")"; | |
286 | } | |
287 | ||
288 | /// for information like os, kernel, hostname, memory info, cpu model. | |
289 | typedef map<string, string> Metadata; | |
290 | ||
7c673cae FG |
291 | namespace ceph { |
292 | namespace features { | |
293 | namespace mon { | |
294 | /** | |
295 | * Get a feature's name based on its value. | |
296 | * | |
297 | * @param b raw feature value | |
298 | * | |
299 | * @remarks | |
300 | * Consumers should not assume this interface will never change. | |
301 | * @remarks | |
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. | |
305 | */ | |
306 | static inline const char *get_feature_name(uint64_t b); | |
307 | } | |
308 | } | |
309 | } | |
310 | ||
311 | ||
312 | inline const char *ceph_mon_feature_name(uint64_t b) | |
313 | { | |
314 | return ceph::features::mon::get_feature_name(b); | |
315 | }; | |
316 | ||
317 | class mon_feature_t { | |
318 | ||
319 | static const int HEAD_VERSION = 1; | |
320 | static const int COMPAT_VERSION = 1; | |
321 | ||
322 | // mon-specific features | |
323 | uint64_t features; | |
324 | ||
325 | public: | |
326 | ||
327 | explicit constexpr | |
328 | mon_feature_t(const uint64_t f) : features(f) { } | |
329 | ||
330 | mon_feature_t() : | |
331 | features(0) { } | |
332 | ||
333 | constexpr | |
334 | mon_feature_t(const mon_feature_t &o) : | |
335 | features(o.features) { } | |
336 | ||
337 | mon_feature_t& operator&=(const mon_feature_t other) { | |
338 | features &= other.features; | |
339 | return (*this); | |
340 | } | |
341 | ||
342 | /** | |
343 | * Obtain raw features | |
344 | * | |
345 | * @remarks | |
346 | * Consumers should not assume this interface will never change. | |
347 | * @remarks | |
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. | |
351 | */ | |
352 | uint64_t get_raw() const { | |
353 | return features; | |
354 | } | |
355 | ||
356 | constexpr | |
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); | |
360 | } | |
361 | ||
362 | mon_feature_t& operator|=(const mon_feature_t other) { | |
363 | features |= other.features; | |
364 | return (*this); | |
365 | } | |
366 | ||
367 | constexpr | |
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); | |
371 | } | |
372 | ||
373 | constexpr | |
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); | |
377 | } | |
378 | ||
379 | mon_feature_t& operator^=(const mon_feature_t other) { | |
380 | features ^= other.features; | |
381 | return (*this); | |
382 | } | |
383 | ||
384 | bool operator==(const mon_feature_t other) const { | |
385 | return (features == other.features); | |
386 | } | |
387 | ||
388 | bool operator!=(const mon_feature_t other) const { | |
389 | return (features != other.features); | |
390 | } | |
391 | ||
392 | bool empty() const { | |
393 | return features == 0; | |
394 | } | |
395 | ||
396 | /** | |
397 | * Set difference of our features in respect to @p other | |
398 | * | |
399 | * Returns all the elements in our features that are not in @p other | |
400 | * | |
401 | * @returns all the features not in @p other | |
402 | */ | |
403 | mon_feature_t diff(const mon_feature_t other) const { | |
404 | return mon_feature_t((features ^ other.features) & features); | |
405 | } | |
406 | ||
407 | /** | |
408 | * Set intersection of our features and @p other | |
409 | * | |
410 | * Returns all the elements common to both our features and the | |
411 | * features of @p other | |
412 | * | |
413 | * @returns the features common to @p other and us | |
414 | */ | |
415 | mon_feature_t intersection(const mon_feature_t other) const { | |
416 | return mon_feature_t((features & other.features)); | |
417 | } | |
418 | ||
419 | /** | |
420 | * Checks whether we have all the features in @p other | |
421 | * | |
422 | * Returns true if we have all the features in @p other | |
423 | * | |
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 | |
426 | */ | |
427 | bool contains_all(const mon_feature_t other) const { | |
428 | mon_feature_t d = intersection(other); | |
429 | return d == other; | |
430 | } | |
431 | ||
432 | /** | |
433 | * Checks whether we contain any of the features in @p other. | |
434 | * | |
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 | |
437 | */ | |
438 | bool contains_any(const mon_feature_t other) const { | |
439 | mon_feature_t d = intersection(other); | |
440 | return !d.empty(); | |
441 | } | |
442 | ||
443 | void set_feature(const mon_feature_t f) { | |
444 | features |= f.features; | |
445 | } | |
446 | ||
447 | void unset_feature(const mon_feature_t f) { | |
448 | features &= ~(f.features); | |
449 | } | |
450 | ||
451 | void print(ostream& out) const { | |
452 | out << "["; | |
453 | print_bit_str(features, out, ceph::features::mon::get_feature_name); | |
454 | out << "]"; | |
455 | } | |
456 | ||
457 | void print_with_value(ostream& out) const { | |
458 | out << "["; | |
459 | print_bit_str(features, out, ceph::features::mon::get_feature_name, true); | |
460 | out << "]"; | |
461 | } | |
462 | ||
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); | |
466 | f->close_section(); | |
467 | } | |
468 | ||
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); | |
472 | f->close_section(); | |
473 | } | |
474 | ||
475 | void encode(bufferlist& bl) const { | |
476 | ENCODE_START(HEAD_VERSION, COMPAT_VERSION, bl); | |
477 | ::encode(features, bl); | |
478 | ENCODE_FINISH(bl); | |
479 | } | |
480 | void decode(bufferlist::iterator& p) { | |
481 | DECODE_START(COMPAT_VERSION, p); | |
482 | ::decode(features, p); | |
483 | DECODE_FINISH(p); | |
484 | } | |
485 | }; | |
486 | WRITE_CLASS_ENCODER(mon_feature_t) | |
487 | ||
488 | namespace ceph { | |
489 | namespace features { | |
490 | namespace mon { | |
491 | constexpr mon_feature_t FEATURE_KRAKEN( (1ULL << 0)); | |
492 | constexpr mon_feature_t FEATURE_LUMINOUS( (1ULL << 1)); | |
493 | ||
494 | constexpr mon_feature_t FEATURE_RESERVED( (1ULL << 63)); | |
495 | constexpr mon_feature_t FEATURE_NONE( (0ULL)); | |
496 | ||
497 | /** | |
498 | * All the features this monitor supports | |
499 | * | |
500 | * If there's a feature above, it should be OR'ed to this list. | |
501 | */ | |
502 | constexpr mon_feature_t get_supported() { | |
503 | return ( | |
504 | FEATURE_KRAKEN | | |
505 | FEATURE_LUMINOUS | | |
506 | FEATURE_NONE | |
507 | ); | |
508 | } | |
509 | /** | |
510 | * All the features that, once set, cannot be removed. | |
511 | * | |
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. | |
515 | * | |
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. | |
518 | */ | |
519 | constexpr mon_feature_t get_persistent() { | |
520 | return ( | |
521 | FEATURE_KRAKEN | | |
522 | FEATURE_LUMINOUS | | |
523 | FEATURE_NONE | |
524 | ); | |
525 | } | |
526 | ||
527 | static inline mon_feature_t get_feature_by_name(std::string n); | |
528 | } | |
529 | } | |
530 | } | |
531 | ||
532 | static inline const char *ceph::features::mon::get_feature_name(uint64_t b) { | |
533 | mon_feature_t f(b); | |
534 | ||
535 | if (f == FEATURE_KRAKEN) { | |
536 | return "kraken"; | |
537 | } else if (f == FEATURE_LUMINOUS) { | |
538 | return "luminous"; | |
539 | } else if (f == FEATURE_RESERVED) { | |
540 | return "reserved"; | |
541 | } | |
542 | return "unknown"; | |
543 | } | |
544 | ||
545 | static inline | |
546 | mon_feature_t ceph::features::mon::get_feature_by_name(std::string n) { | |
547 | ||
548 | if (n == "kraken") { | |
549 | return FEATURE_KRAKEN; | |
550 | } else if (n == "luminous") { | |
551 | return FEATURE_LUMINOUS; | |
552 | } else if (n == "reserved") { | |
553 | return FEATURE_RESERVED; | |
554 | } | |
555 | return FEATURE_NONE; | |
556 | } | |
557 | ||
558 | static inline ostream& operator<<(ostream& out, const mon_feature_t& f) { | |
559 | out << "mon_feature_t("; | |
560 | f.print(out); | |
561 | out << ")"; | |
562 | return out; | |
563 | } | |
564 | ||
565 | #endif |