Fix some bugs when testing opensds ansible
[stor4nfv.git] / src / 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_HEALTH    8
35 #define PAXOS_NUM        9
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";
46   case PAXOS_MGRSTAT: return "mgrstat";
47   case PAXOS_HEALTH: return "health";
48   default: ceph_abort(); return 0;
49   }
50 }
51
52 #define CEPH_MON_ONDISK_MAGIC "ceph mon volume v012"
53
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) {
59     if (type == CEPH_ENTITY_TYPE_MON) {
60       return;
61     }
62     m[type][features]++;
63   }
64
65   void add_mon(uint64_t features) {
66     m[CEPH_ENTITY_TYPE_MON][features]++;
67   }
68
69   void rm(uint32_t type, uint64_t features) {
70     if (type == CEPH_ENTITY_TYPE_MON) {
71       return;
72     }
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");
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);
118         f->close_section();
119       }
120       f->close_section();
121     }
122   }
123 };
124 WRITE_CLASS_ENCODER(FeatureMap)
125
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
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