summaryrefslogtreecommitdiffstats
path: root/src/mon/mon_types.h
blob: 02aad5a0b870b4bef7eae32563eba536c3de848e (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*- 
// vim: ts=8 sw=2 smarttab
/*
 * Ceph - scalable distributed file system
 *
 * Copyright (C) 2004-2006 Sage Weil <sage@newdream.net>
 *
 * This is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License version 2.1, as published by the Free Software 
 * Foundation.  See file COPYING.
 * 
 */

#ifndef CEPH_MON_TYPES_H
#define CEPH_MON_TYPES_H

#include <map>

#include "include/Context.h"
#include "include/util.h"
#include "include/utime.h"
#include "common/Formatter.h"
#include "common/bit_str.h"
#include "common/ceph_releases.h"

// use as paxos_service index
enum {
  PAXOS_MDSMAP,
  PAXOS_OSDMAP,
  PAXOS_LOG,
  PAXOS_MONMAP,
  PAXOS_AUTH,
  PAXOS_MGR,
  PAXOS_MGRSTAT,
  PAXOS_HEALTH,
  PAXOS_CONFIG,
  PAXOS_KV,
  PAXOS_NUM
};

#define CEPH_MON_ONDISK_MAGIC "ceph mon volume v012"

// map of entity_type -> features -> count
struct FeatureMap {
  std::map<uint32_t,std::map<uint64_t,uint64_t>> m;

  void add(uint32_t type, uint64_t features) {
    if (type == CEPH_ENTITY_TYPE_MON) {
      return;
    }
    m[type][features]++;
  }

  void add_mon(uint64_t features) {
    m[CEPH_ENTITY_TYPE_MON][features]++;
  }

  void rm(uint32_t type, uint64_t features) {
    if (type == CEPH_ENTITY_TYPE_MON) {
      return;
    }
    auto p = m.find(type);
    ceph_assert(p != m.end());
    auto q = p->second.find(features);
    ceph_assert(q != p->second.end());
    if (--q->second == 0) {
      p->second.erase(q);
      if (p->second.empty()) {
	m.erase(p);
      }
    }
  }

  FeatureMap& operator+=(const FeatureMap& o) {
    for (auto& p : o.m) {
      auto &v = m[p.first];
      for (auto& q : p.second) {
	v[q.first] += q.second;
      }
    }
    return *this;
  }

  void encode(ceph::buffer::list& bl) const {
    ENCODE_START(1, 1, bl);
    encode(m, bl);
    ENCODE_FINISH(bl);
  }

  void decode(ceph::buffer::list::const_iterator& p) {
    DECODE_START(1, p);
    decode(m, p);
    DECODE_FINISH(p);
  }

  void dump(ceph::Formatter *f) const {
    for (auto& p : m) {
      f->open_array_section(ceph_entity_type_name(p.first));
      for (auto& q : p.second) {
	f->open_object_section("group");
        std::stringstream ss;
        ss << "0x" << std::hex << q.first << std::dec;
        f->dump_string("features", ss.str());
	f->dump_string("release", ceph_release_name(
			 ceph_release_from_features(q.first)));
	f->dump_unsigned("num", q.second);
	f->close_section();
      }
      f->close_section();
    }
  }
};
WRITE_CLASS_ENCODER(FeatureMap)

/**
 * leveldb store stats
 *
 * If we ever decide to support multiple backends for the monitor store,
 * we should then create an abstract class 'MonitorStoreStats' of sorts
 * and inherit it on LevelDBStoreStats.  I'm sure you'll figure something
 * out.
 */
struct LevelDBStoreStats {
  uint64_t bytes_total;
  uint64_t bytes_sst;
  uint64_t bytes_log;
  uint64_t bytes_misc;
  utime_t last_update;

  LevelDBStoreStats() :
    bytes_total(0),
    bytes_sst(0),
    bytes_log(0),
    bytes_misc(0)
  {}

  void dump(ceph::Formatter *f) const {
    ceph_assert(f != NULL);
    f->dump_int("bytes_total", bytes_total);
    f->dump_int("bytes_sst", bytes_sst);
    f->dump_int("bytes_log", bytes_log);
    f->dump_int("bytes_misc", bytes_misc);
    f->dump_stream("last_updated") << last_update;
  }

  void encode(ceph::buffer::list &bl) const {
    ENCODE_START(1, 1, bl);
    encode(bytes_total, bl);
    encode(bytes_sst, bl);
    encode(bytes_log, bl);
    encode(bytes_misc, bl);
    encode(last_update, bl);
    ENCODE_FINISH(bl);
  }

  void decode(ceph::buffer::list::const_iterator &p) {
    DECODE_START(1, p);
    decode(bytes_total, p);
    decode(bytes_sst, p);
    decode(bytes_log, p);
    decode(bytes_misc, p);
    decode(last_update, p);
    DECODE_FINISH(p);
  }

  static void generate_test_instances(std::list<LevelDBStoreStats*>& ls) {
    ls.push_back(new LevelDBStoreStats);
    ls.push_back(new LevelDBStoreStats);
    ls.back()->bytes_total = 1024*1024;
    ls.back()->bytes_sst = 512*1024;
    ls.back()->bytes_log = 256*1024;
    ls.back()->bytes_misc = 256*1024;
    ls.back()->last_update = utime_t();
  }
};
WRITE_CLASS_ENCODER(LevelDBStoreStats)

// data stats

struct DataStats {
  ceph_data_stats_t fs_stats;
  // data dir
  utime_t last_update;
  LevelDBStoreStats store_stats;

  void dump(ceph::Formatter *f) const {
    ceph_assert(f != NULL);
    f->dump_int("kb_total", (fs_stats.byte_total/1024));
    f->dump_int("kb_used", (fs_stats.byte_used/1024));
    f->dump_int("kb_avail", (fs_stats.byte_avail/1024));
    f->dump_int("avail_percent", fs_stats.avail_percent);
    f->dump_stream("last_updated") << last_update;
    f->open_object_section("store_stats");
    store_stats.dump(f);
    f->close_section();
  }

  void encode(ceph::buffer::list &bl) const {
    ENCODE_START(3, 1, bl);
    encode(fs_stats.byte_total, bl);
    encode(fs_stats.byte_used, bl);
    encode(fs_stats.byte_avail, bl);
    encode(fs_stats.avail_percent, bl);
    encode(last_update, bl);
    encode(store_stats, bl);
    ENCODE_FINISH(bl);
  }
  void decode(ceph::buffer::list::const_iterator &p) {
    DECODE_START(1, p);
    // we moved from having fields in kb to fields in byte
    if (struct_v > 2) {
      decode(fs_stats.byte_total, p);
      decode(fs_stats.byte_used, p);
      decode(fs_stats.byte_avail, p);
    } else {
      uint64_t t;
      decode(t, p);
      fs_stats.byte_total = t*1024;
      decode(t, p);
      fs_stats.byte_used = t*1024;
      decode(t, p);
      fs_stats.byte_avail = t*1024;
    }
    decode(fs_stats.avail_percent, p);
    decode(last_update, p);
    if (struct_v > 1)
      decode(store_stats, p);

    DECODE_FINISH(p);
  }
};
WRITE_CLASS_ENCODER(DataStats)

struct ScrubResult {
  std::map<std::string,uint32_t> prefix_crc;  ///< prefix -> crc
  std::map<std::string,uint64_t> prefix_keys; ///< prefix -> key count

  bool operator!=(const ScrubResult& other) {
    return prefix_crc != other.prefix_crc || prefix_keys != other.prefix_keys;
  }

  void encode(ceph::buffer::list& bl) const {
    ENCODE_START(1, 1, bl);
    encode(prefix_crc, bl);
    encode(prefix_keys, bl);
    ENCODE_FINISH(bl);
  }
  void decode(ceph::buffer::list::const_iterator& p) {
    DECODE_START(1, p);
    decode(prefix_crc, p);
    decode(prefix_keys, p);
    DECODE_FINISH(p);
  }
  void dump(ceph::Formatter *f) const {
    f->open_object_section("crc");
    for (auto p = prefix_crc.begin(); p != prefix_crc.end(); ++p)
      f->dump_unsigned(p->first.c_str(), p->second);
    f->close_section();
    f->open_object_section("keys");
    for (auto p = prefix_keys.begin(); p != prefix_keys.end(); ++p)
      f->dump_unsigned(p->first.c_str(), p->second);
    f->close_section();
  }
  static void generate_test_instances(std::list<ScrubResult*>& ls) {
    ls.push_back(new ScrubResult);
    ls.push_back(new ScrubResult);
    ls.back()->prefix_crc["foo"] = 123;
    ls.back()->prefix_keys["bar"] = 456;
  }
};
WRITE_CLASS_ENCODER(ScrubResult)

inline std::ostream& operator<<(std::ostream& out, const ScrubResult& r) {
  return out << "ScrubResult(keys " << r.prefix_keys << " crc " << r.prefix_crc << ")";
}

/// for information like os, kernel, hostname, memory info, cpu model.
typedef std::map<std::string, std::string> Metadata;

namespace ceph {
  namespace features {
    namespace mon {
      /**
       * Get a feature's name based on its value.
       *
       * @param b raw feature value
       *
       * @remarks
       *    Consumers should not assume this interface will never change.
       * @remarks
       *    As the number of features increase, so may the internal representation
       *    of the raw features. When this happens, this interface will change
       *    accordingly. So should consumers of this interface.
       */
      static inline const char *get_feature_name(uint64_t b);
    }
  }
}


inline const char *ceph_mon_feature_name(uint64_t b)
{
  return ceph::features::mon::get_feature_name(b);
};

class mon_feature_t {

  static constexpr int HEAD_VERSION = 1;
  static constexpr int COMPAT_VERSION = 1;

  // mon-specific features
  uint64_t features;

public:

  explicit constexpr
  mon_feature_t(const uint64_t f) : features(f) { }

  mon_feature_t() :
    features(0) { }

  constexpr
  mon_feature_t(const mon_feature_t &o) :
    features(o.features) { }

  mon_feature_t& operator&=(const mon_feature_t other) {
    features &= other.features;
    return (*this);
  }

  /**
   * Obtain raw features
   *
   * @remarks
   *    Consumers should not assume this interface will never change.
   * @remarks
   *    As the number of features increase, so may the internal representation
   *    of the raw features. When this happens, this interface will change
   *    accordingly. So should consumers of this interface.
   */
  uint64_t get_raw() const {
    return features;
  }

  constexpr
  friend mon_feature_t operator&(const mon_feature_t a,
                                 const mon_feature_t b) {
    return mon_feature_t(a.features & b.features);
  }

  mon_feature_t& operator|=(const mon_feature_t other) {
    features |= other.features;
    return (*this);
  }

  constexpr
  friend mon_feature_t operator|(const mon_feature_t a,
                                 const mon_feature_t b) {
    return mon_feature_t(a.features | b.features);
  }

  constexpr
  friend mon_feature_t operator^(const mon_feature_t a,
                                 const mon_feature_t b) {
    return mon_feature_t(a.features ^ b.features);
  }

  mon_feature_t& operator^=(const mon_feature_t other) {
    features ^= other.features;
    return (*this);
  }

  bool operator==(const mon_feature_t other) const {
    return (features == other.features);
  }

  bool operator!=(const mon_feature_t other) const {
    return (features != other.features);
  }

  bool empty() const {
    return features == 0;
  }

  /**
   * Set difference of our features in respect to @p other
   *
   * Returns all the elements in our features that are not in @p other
   *
   * @returns all the features not in @p other
   */
  mon_feature_t diff(const mon_feature_t other) const {
    return mon_feature_t((features ^ other.features) & features);
  }

  /**
   * Set intersection of our features and @p other
   *
   * Returns all the elements common to both our features and the
   * features of @p other
   *
   * @returns the features common to @p other and us
   */
  mon_feature_t intersection(const mon_feature_t other) const {
    return mon_feature_t((features & other.features));
  }

  /**
   * Checks whether we have all the features in @p other
   *
   * Returns true if we have all the features in @p other
   *
   * @returns true if we contain all the features in @p other
   * @returns false if we do not contain some of the features in @p other
   */
  bool contains_all(const mon_feature_t other) const {
    mon_feature_t d = intersection(other);
    return d == other;
  }

  /**
   * Checks whether we contain any of the features in @p other.
   *
   * @returns true if we contain any of the features in @p other
   * @returns false if we don't contain any of the features in @p other
   */
  bool contains_any(const mon_feature_t other) const {
    mon_feature_t d = intersection(other);
    return !d.empty();
  }

  void set_feature(const mon_feature_t f) {
    features |= f.features;
  }

  void unset_feature(const mon_feature_t f) {
    features &= ~(f.features);
  }

  void print(std::ostream& out) const {
    out << "[";
    print_bit_str(features, out, ceph::features::mon::get_feature_name);
    out << "]";
  }

  void print_with_value(std::ostream& out) const {
    out << "[";
    print_bit_str(features, out, ceph::features::mon::get_feature_name, true);
    out << "]";
  }

  void dump(ceph::Formatter *f, const char *sec_name = NULL) const {
    f->open_array_section((sec_name ? sec_name : "features"));
    dump_bit_str(features, f, ceph::features::mon::get_feature_name);
    f->close_section();
  }

  void dump_with_value(ceph::Formatter *f, const char *sec_name = NULL) const {
    f->open_array_section((sec_name ? sec_name : "features"));
    dump_bit_str(features, f, ceph::features::mon::get_feature_name, true);
    f->close_section();
  }

  void encode(ceph::buffer::list& bl) const {
    ENCODE_START(HEAD_VERSION, COMPAT_VERSION, bl);
    encode(features, bl);
    ENCODE_FINISH(bl);
  }
  void decode(ceph::buffer::list::const_iterator& p) {
    DECODE_START(COMPAT_VERSION, p);
    decode(features, p);
    DECODE_FINISH(p);
  }
};
WRITE_CLASS_ENCODER(mon_feature_t)

namespace ceph {
  namespace features {
    namespace mon {
      constexpr mon_feature_t FEATURE_KRAKEN(     (1ULL << 0));
      constexpr mon_feature_t FEATURE_LUMINOUS(   (1ULL << 1));
      constexpr mon_feature_t FEATURE_MIMIC(      (1ULL << 2));
      constexpr mon_feature_t FEATURE_OSDMAP_PRUNE (1ULL << 3);
      constexpr mon_feature_t FEATURE_NAUTILUS(    (1ULL << 4));
      constexpr mon_feature_t FEATURE_OCTOPUS(    (1ULL << 5));
      constexpr mon_feature_t FEATURE_PACIFIC(    (1ULL << 6));
      // elector pinging and CONNECTIVITY mode:
      constexpr mon_feature_t FEATURE_PINGING(    (1ULL << 7));
      constexpr mon_feature_t FEATURE_QUINCY(    (1ULL << 8));
      constexpr mon_feature_t FEATURE_REEF(    (1ULL << 9));

      constexpr mon_feature_t FEATURE_RESERVED(   (1ULL << 63));
      constexpr mon_feature_t FEATURE_NONE(       (0ULL));

      /**
       * All the features this monitor supports
       *
       * If there's a feature above, it should be OR'ed to this list.
       */
      constexpr mon_feature_t get_supported() {
        return (
	  FEATURE_KRAKEN |
	  FEATURE_LUMINOUS |
	  FEATURE_MIMIC |
          FEATURE_OSDMAP_PRUNE |
	  FEATURE_NAUTILUS |
	  FEATURE_OCTOPUS |
	  FEATURE_PACIFIC |
	  FEATURE_PINGING |
	  FEATURE_QUINCY |
	  FEATURE_REEF |
	  FEATURE_NONE
	  );
      }
      /**
       * All the features that, once set, cannot be removed.
       *
       * Features should only be added to this list if you want to make
       * sure downgrades are not possible after a quorum supporting all
       * these features has been formed.
       *
       * Any feature in this list will be automatically set on the monmap's
       * features once all the monitors in the quorum support it.
       */
      constexpr mon_feature_t get_persistent() {
        return (
	  FEATURE_KRAKEN |
	  FEATURE_LUMINOUS |
	  FEATURE_MIMIC |
	  FEATURE_NAUTILUS |
	  FEATURE_OSDMAP_PRUNE |
	  FEATURE_OCTOPUS |
	  FEATURE_PACIFIC |
	  FEATURE_PINGING |
	  FEATURE_QUINCY |
	  FEATURE_REEF |
	  FEATURE_NONE
	  );
      }

      constexpr mon_feature_t get_optional() {
        return (
          FEATURE_OSDMAP_PRUNE |
          FEATURE_NONE
          );
      }

      static inline mon_feature_t get_feature_by_name(const std::string &n);
    }
  }
}

static inline ceph_release_t infer_ceph_release_from_mon_features(mon_feature_t f)
{
  if (f.contains_all(ceph::features::mon::FEATURE_REEF)) {
    return ceph_release_t::reef;
  }
  if (f.contains_all(ceph::features::mon::FEATURE_QUINCY)) {
    return ceph_release_t::quincy;
  }
  if (f.contains_all(ceph::features::mon::FEATURE_PACIFIC)) {
    return ceph_release_t::pacific;
  }
  if (f.contains_all(ceph::features::mon::FEATURE_OCTOPUS)) {
    return ceph_release_t::octopus;
  }
  if (f.contains_all(ceph::features::mon::FEATURE_NAUTILUS)) {
    return ceph_release_t::nautilus;
  }
  if (f.contains_all(ceph::features::mon::FEATURE_MIMIC)) {
    return ceph_release_t::mimic;
  }
  if (f.contains_all(ceph::features::mon::FEATURE_LUMINOUS)) {
    return ceph_release_t::luminous;
  }
  if (f.contains_all(ceph::features::mon::FEATURE_KRAKEN)) {
    return ceph_release_t::kraken;
  }
  return ceph_release_t::unknown;
}

static inline const char *ceph::features::mon::get_feature_name(uint64_t b) {
  mon_feature_t f(b);

  if (f == FEATURE_KRAKEN) {
    return "kraken";
  } else if (f == FEATURE_LUMINOUS) {
    return "luminous";
  } else if (f == FEATURE_MIMIC) {
    return "mimic";
  } else if (f == FEATURE_OSDMAP_PRUNE) {
    return "osdmap-prune";
  } else if (f == FEATURE_NAUTILUS) {
    return "nautilus";
  } else if (f == FEATURE_PINGING) {
    return "elector-pinging";
  } else if (f == FEATURE_OCTOPUS) {
    return "octopus";
  } else if (f == FEATURE_PACIFIC) {
    return "pacific";
  } else if (f == FEATURE_QUINCY) {
    return "quincy";
  } else if (f == FEATURE_REEF) {
    return "reef";
  } else if (f == FEATURE_RESERVED) {
    return "reserved";
  }
  return "unknown";
}

inline mon_feature_t ceph::features::mon::get_feature_by_name(const std::string &n) {

  if (n == "kraken") {
    return FEATURE_KRAKEN;
  } else if (n == "luminous") {
    return FEATURE_LUMINOUS;
  } else if (n == "mimic") {
    return FEATURE_MIMIC;
  } else if (n == "osdmap-prune") {
    return FEATURE_OSDMAP_PRUNE;
  } else if (n == "nautilus") {
    return FEATURE_NAUTILUS;
  } else if (n == "feature-pinging") {
    return FEATURE_PINGING;
  } else if (n == "octopus") {
    return FEATURE_OCTOPUS;
  } else if (n == "pacific") {
    return FEATURE_PACIFIC;
  } else if (n == "quincy") {
    return FEATURE_QUINCY;
  } else if (n == "reef") {
    return FEATURE_REEF;
  } else if (n == "reserved") {
    return FEATURE_RESERVED;
  }
  return FEATURE_NONE;
}

inline std::ostream& operator<<(std::ostream& out, const mon_feature_t& f) {
  out << "mon_feature_t(";
  f.print(out);
  out << ")";
  return out;
}


struct ProgressEvent {
  std::string message;                  ///< event description
  float progress;                  ///< [0..1]
  bool add_to_ceph_s;
  void encode(ceph::buffer::list& bl) const {
    ENCODE_START(2, 1, bl);
    encode(message, bl);
    encode(progress, bl);
    encode(add_to_ceph_s, bl);
    ENCODE_FINISH(bl);
  }
  void decode(ceph::buffer::list::const_iterator& p) {
    DECODE_START(2, p);
    decode(message, p);
    decode(progress, p);
    if (struct_v >= 2){
	decode(add_to_ceph_s, p);
    } else {
      if (!message.empty()) {
	add_to_ceph_s = true;
      }
    }
    DECODE_FINISH(p);
  }
  void dump(ceph::Formatter *f) const {
    f->dump_string("message", message);
    f->dump_float("progress", progress);
    f->dump_bool("add_to_ceph_s", add_to_ceph_s);
  }
};
WRITE_CLASS_ENCODER(ProgressEvent)

#endif