]> git.proxmox.com Git - ceph.git/blame - ceph/src/mon/mon_types.h
bump version to 18.2.2-pve1
[ceph.git] / ceph / src / mon / mon_types.h
CommitLineData
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
9f95a23c 20#include "include/Context.h"
7c673cae 21#include "include/util.h"
9f95a23c 22#include "include/utime.h"
7c673cae
FG
23#include "common/Formatter.h"
24#include "common/bit_str.h"
9f95a23c 25#include "common/ceph_releases.h"
7c673cae 26
f67539c2
TL
27// use as paxos_service index
28enum {
29 PAXOS_MDSMAP,
30 PAXOS_OSDMAP,
31 PAXOS_LOG,
32 PAXOS_MONMAP,
33 PAXOS_AUTH,
34 PAXOS_MGR,
35 PAXOS_MGRSTAT,
36 PAXOS_HEALTH,
37 PAXOS_CONFIG,
38 PAXOS_KV,
39 PAXOS_NUM
40};
7c673cae
FG
41
42#define CEPH_MON_ONDISK_MAGIC "ceph mon volume v012"
43
31f18b77
FG
44// map of entity_type -> features -> count
45struct FeatureMap {
46 std::map<uint32_t,std::map<uint64_t,uint64_t>> m;
47
48 void add(uint32_t type, uint64_t features) {
b5b8bbf5
FG
49 if (type == CEPH_ENTITY_TYPE_MON) {
50 return;
51 }
31f18b77
FG
52 m[type][features]++;
53 }
54
b5b8bbf5
FG
55 void add_mon(uint64_t features) {
56 m[CEPH_ENTITY_TYPE_MON][features]++;
57 }
58
31f18b77 59 void rm(uint32_t type, uint64_t features) {
b5b8bbf5
FG
60 if (type == CEPH_ENTITY_TYPE_MON) {
61 return;
62 }
31f18b77 63 auto p = m.find(type);
11fdf7f2 64 ceph_assert(p != m.end());
31f18b77 65 auto q = p->second.find(features);
11fdf7f2 66 ceph_assert(q != p->second.end());
31f18b77
FG
67 if (--q->second == 0) {
68 p->second.erase(q);
69 if (p->second.empty()) {
70 m.erase(p);
71 }
72 }
73 }
74
75 FeatureMap& operator+=(const FeatureMap& o) {
76 for (auto& p : o.m) {
77 auto &v = m[p.first];
78 for (auto& q : p.second) {
79 v[q.first] += q.second;
80 }
81 }
82 return *this;
83 }
84
9f95a23c 85 void encode(ceph::buffer::list& bl) const {
31f18b77 86 ENCODE_START(1, 1, bl);
11fdf7f2 87 encode(m, bl);
31f18b77
FG
88 ENCODE_FINISH(bl);
89 }
90
9f95a23c 91 void decode(ceph::buffer::list::const_iterator& p) {
31f18b77 92 DECODE_START(1, p);
11fdf7f2 93 decode(m, p);
31f18b77
FG
94 DECODE_FINISH(p);
95 }
96
9f95a23c 97 void dump(ceph::Formatter *f) const {
31f18b77 98 for (auto& p : m) {
11fdf7f2 99 f->open_array_section(ceph_entity_type_name(p.first));
31f18b77
FG
100 for (auto& q : p.second) {
101 f->open_object_section("group");
b5b8bbf5
FG
102 std::stringstream ss;
103 ss << "0x" << std::hex << q.first << std::dec;
104 f->dump_string("features", ss.str());
31f18b77
FG
105 f->dump_string("release", ceph_release_name(
106 ceph_release_from_features(q.first)));
107 f->dump_unsigned("num", q.second);
108 f->close_section();
109 }
110 f->close_section();
111 }
112 }
113};
114WRITE_CLASS_ENCODER(FeatureMap)
115
7c673cae
FG
116/**
117 * leveldb store stats
118 *
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
122 * out.
123 */
124struct LevelDBStoreStats {
125 uint64_t bytes_total;
126 uint64_t bytes_sst;
127 uint64_t bytes_log;
128 uint64_t bytes_misc;
129 utime_t last_update;
130
131 LevelDBStoreStats() :
132 bytes_total(0),
133 bytes_sst(0),
134 bytes_log(0),
135 bytes_misc(0)
136 {}
137
9f95a23c 138 void dump(ceph::Formatter *f) const {
11fdf7f2 139 ceph_assert(f != NULL);
7c673cae
FG
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;
145 }
146
9f95a23c 147 void encode(ceph::buffer::list &bl) const {
7c673cae 148 ENCODE_START(1, 1, bl);
11fdf7f2
TL
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);
7c673cae
FG
154 ENCODE_FINISH(bl);
155 }
156
9f95a23c 157 void decode(ceph::buffer::list::const_iterator &p) {
7c673cae 158 DECODE_START(1, p);
11fdf7f2
TL
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);
7c673cae
FG
164 DECODE_FINISH(p);
165 }
166
9f95a23c 167 static void generate_test_instances(std::list<LevelDBStoreStats*>& ls) {
7c673cae
FG
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();
175 }
176};
177WRITE_CLASS_ENCODER(LevelDBStoreStats)
178
179// data stats
180
181struct DataStats {
182 ceph_data_stats_t fs_stats;
183 // data dir
184 utime_t last_update;
185 LevelDBStoreStats store_stats;
186
9f95a23c 187 void dump(ceph::Formatter *f) const {
11fdf7f2 188 ceph_assert(f != NULL);
7c673cae
FG
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");
195 store_stats.dump(f);
196 f->close_section();
197 }
198
9f95a23c 199 void encode(ceph::buffer::list &bl) const {
7c673cae 200 ENCODE_START(3, 1, bl);
11fdf7f2
TL
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);
7c673cae
FG
207 ENCODE_FINISH(bl);
208 }
9f95a23c 209 void decode(ceph::buffer::list::const_iterator &p) {
7c673cae
FG
210 DECODE_START(1, p);
211 // we moved from having fields in kb to fields in byte
212 if (struct_v > 2) {
11fdf7f2
TL
213 decode(fs_stats.byte_total, p);
214 decode(fs_stats.byte_used, p);
215 decode(fs_stats.byte_avail, p);
7c673cae
FG
216 } else {
217 uint64_t t;
11fdf7f2 218 decode(t, p);
7c673cae 219 fs_stats.byte_total = t*1024;
11fdf7f2 220 decode(t, p);
7c673cae 221 fs_stats.byte_used = t*1024;
11fdf7f2 222 decode(t, p);
7c673cae
FG
223 fs_stats.byte_avail = t*1024;
224 }
11fdf7f2
TL
225 decode(fs_stats.avail_percent, p);
226 decode(last_update, p);
7c673cae 227 if (struct_v > 1)
11fdf7f2 228 decode(store_stats, p);
7c673cae
FG
229
230 DECODE_FINISH(p);
231 }
232};
233WRITE_CLASS_ENCODER(DataStats)
234
235struct ScrubResult {
9f95a23c
TL
236 std::map<std::string,uint32_t> prefix_crc; ///< prefix -> crc
237 std::map<std::string,uint64_t> prefix_keys; ///< prefix -> key count
7c673cae
FG
238
239 bool operator!=(const ScrubResult& other) {
240 return prefix_crc != other.prefix_crc || prefix_keys != other.prefix_keys;
241 }
242
9f95a23c 243 void encode(ceph::buffer::list& bl) const {
7c673cae 244 ENCODE_START(1, 1, bl);
11fdf7f2
TL
245 encode(prefix_crc, bl);
246 encode(prefix_keys, bl);
7c673cae
FG
247 ENCODE_FINISH(bl);
248 }
9f95a23c 249 void decode(ceph::buffer::list::const_iterator& p) {
7c673cae 250 DECODE_START(1, p);
11fdf7f2
TL
251 decode(prefix_crc, p);
252 decode(prefix_keys, p);
7c673cae
FG
253 DECODE_FINISH(p);
254 }
9f95a23c 255 void dump(ceph::Formatter *f) const {
7c673cae 256 f->open_object_section("crc");
9f95a23c 257 for (auto p = prefix_crc.begin(); p != prefix_crc.end(); ++p)
7c673cae
FG
258 f->dump_unsigned(p->first.c_str(), p->second);
259 f->close_section();
260 f->open_object_section("keys");
9f95a23c 261 for (auto p = prefix_keys.begin(); p != prefix_keys.end(); ++p)
7c673cae
FG
262 f->dump_unsigned(p->first.c_str(), p->second);
263 f->close_section();
264 }
9f95a23c 265 static void generate_test_instances(std::list<ScrubResult*>& ls) {
7c673cae
FG
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;
270 }
271};
272WRITE_CLASS_ENCODER(ScrubResult)
273
9f95a23c 274inline std::ostream& operator<<(std::ostream& out, const ScrubResult& r) {
7c673cae
FG
275 return out << "ScrubResult(keys " << r.prefix_keys << " crc " << r.prefix_crc << ")";
276}
277
278/// for information like os, kernel, hostname, memory info, cpu model.
9f95a23c 279typedef std::map<std::string, std::string> Metadata;
7c673cae 280
7c673cae
FG
281namespace ceph {
282 namespace features {
283 namespace mon {
284 /**
285 * Get a feature's name based on its value.
286 *
287 * @param b raw feature value
288 *
289 * @remarks
290 * Consumers should not assume this interface will never change.
291 * @remarks
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.
295 */
296 static inline const char *get_feature_name(uint64_t b);
297 }
298 }
299}
300
301
302inline const char *ceph_mon_feature_name(uint64_t b)
303{
304 return ceph::features::mon::get_feature_name(b);
305};
306
307class mon_feature_t {
308
11fdf7f2
TL
309 static constexpr int HEAD_VERSION = 1;
310 static constexpr int COMPAT_VERSION = 1;
7c673cae
FG
311
312 // mon-specific features
313 uint64_t features;
314
315public:
316
317 explicit constexpr
318 mon_feature_t(const uint64_t f) : features(f) { }
319
320 mon_feature_t() :
321 features(0) { }
322
323 constexpr
324 mon_feature_t(const mon_feature_t &o) :
325 features(o.features) { }
326
327 mon_feature_t& operator&=(const mon_feature_t other) {
328 features &= other.features;
329 return (*this);
330 }
331
332 /**
333 * Obtain raw features
334 *
335 * @remarks
336 * Consumers should not assume this interface will never change.
337 * @remarks
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.
341 */
342 uint64_t get_raw() const {
343 return features;
344 }
345
346 constexpr
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);
350 }
351
352 mon_feature_t& operator|=(const mon_feature_t other) {
353 features |= other.features;
354 return (*this);
355 }
356
357 constexpr
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);
361 }
362
363 constexpr
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);
367 }
368
369 mon_feature_t& operator^=(const mon_feature_t other) {
370 features ^= other.features;
371 return (*this);
372 }
373
374 bool operator==(const mon_feature_t other) const {
375 return (features == other.features);
376 }
377
378 bool operator!=(const mon_feature_t other) const {
379 return (features != other.features);
380 }
381
382 bool empty() const {
383 return features == 0;
384 }
385
386 /**
387 * Set difference of our features in respect to @p other
388 *
389 * Returns all the elements in our features that are not in @p other
390 *
391 * @returns all the features not in @p other
392 */
393 mon_feature_t diff(const mon_feature_t other) const {
394 return mon_feature_t((features ^ other.features) & features);
395 }
396
397 /**
398 * Set intersection of our features and @p other
399 *
400 * Returns all the elements common to both our features and the
401 * features of @p other
402 *
403 * @returns the features common to @p other and us
404 */
405 mon_feature_t intersection(const mon_feature_t other) const {
406 return mon_feature_t((features & other.features));
407 }
408
409 /**
410 * Checks whether we have all the features in @p other
411 *
412 * Returns true if we have all the features in @p other
413 *
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
416 */
417 bool contains_all(const mon_feature_t other) const {
418 mon_feature_t d = intersection(other);
419 return d == other;
420 }
421
422 /**
423 * Checks whether we contain any of the features in @p other.
424 *
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
427 */
428 bool contains_any(const mon_feature_t other) const {
429 mon_feature_t d = intersection(other);
430 return !d.empty();
431 }
432
433 void set_feature(const mon_feature_t f) {
434 features |= f.features;
435 }
436
437 void unset_feature(const mon_feature_t f) {
438 features &= ~(f.features);
439 }
440
9f95a23c 441 void print(std::ostream& out) const {
7c673cae
FG
442 out << "[";
443 print_bit_str(features, out, ceph::features::mon::get_feature_name);
444 out << "]";
445 }
446
9f95a23c 447 void print_with_value(std::ostream& out) const {
7c673cae
FG
448 out << "[";
449 print_bit_str(features, out, ceph::features::mon::get_feature_name, true);
450 out << "]";
451 }
452
9f95a23c 453 void dump(ceph::Formatter *f, const char *sec_name = NULL) const {
7c673cae
FG
454 f->open_array_section((sec_name ? sec_name : "features"));
455 dump_bit_str(features, f, ceph::features::mon::get_feature_name);
456 f->close_section();
457 }
458
9f95a23c 459 void dump_with_value(ceph::Formatter *f, const char *sec_name = NULL) const {
7c673cae
FG
460 f->open_array_section((sec_name ? sec_name : "features"));
461 dump_bit_str(features, f, ceph::features::mon::get_feature_name, true);
462 f->close_section();
463 }
464
9f95a23c 465 void encode(ceph::buffer::list& bl) const {
7c673cae 466 ENCODE_START(HEAD_VERSION, COMPAT_VERSION, bl);
11fdf7f2 467 encode(features, bl);
7c673cae
FG
468 ENCODE_FINISH(bl);
469 }
9f95a23c 470 void decode(ceph::buffer::list::const_iterator& p) {
7c673cae 471 DECODE_START(COMPAT_VERSION, p);
11fdf7f2 472 decode(features, p);
7c673cae
FG
473 DECODE_FINISH(p);
474 }
475};
476WRITE_CLASS_ENCODER(mon_feature_t)
477
478namespace ceph {
479 namespace features {
480 namespace mon {
481 constexpr mon_feature_t FEATURE_KRAKEN( (1ULL << 0));
482 constexpr mon_feature_t FEATURE_LUMINOUS( (1ULL << 1));
11fdf7f2
TL
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));
9f95a23c 486 constexpr mon_feature_t FEATURE_OCTOPUS( (1ULL << 5));
f67539c2
TL
487 constexpr mon_feature_t FEATURE_PACIFIC( (1ULL << 6));
488 // elector pinging and CONNECTIVITY mode:
489 constexpr mon_feature_t FEATURE_PINGING( (1ULL << 7));
20effc67 490 constexpr mon_feature_t FEATURE_QUINCY( (1ULL << 8));
1e59de90 491 constexpr mon_feature_t FEATURE_REEF( (1ULL << 9));
7c673cae
FG
492
493 constexpr mon_feature_t FEATURE_RESERVED( (1ULL << 63));
494 constexpr mon_feature_t FEATURE_NONE( (0ULL));
495
496 /**
497 * All the features this monitor supports
498 *
499 * If there's a feature above, it should be OR'ed to this list.
500 */
501 constexpr mon_feature_t get_supported() {
502 return (
503 FEATURE_KRAKEN |
504 FEATURE_LUMINOUS |
11fdf7f2
TL
505 FEATURE_MIMIC |
506 FEATURE_OSDMAP_PRUNE |
507 FEATURE_NAUTILUS |
9f95a23c 508 FEATURE_OCTOPUS |
f67539c2
TL
509 FEATURE_PACIFIC |
510 FEATURE_PINGING |
20effc67 511 FEATURE_QUINCY |
1e59de90 512 FEATURE_REEF |
7c673cae
FG
513 FEATURE_NONE
514 );
515 }
516 /**
517 * All the features that, once set, cannot be removed.
518 *
519 * Features should only be added to this list if you want to make
520 * sure downgrades are not possible after a quorum supporting all
521 * these features has been formed.
522 *
523 * Any feature in this list will be automatically set on the monmap's
524 * features once all the monitors in the quorum support it.
525 */
526 constexpr mon_feature_t get_persistent() {
527 return (
528 FEATURE_KRAKEN |
529 FEATURE_LUMINOUS |
11fdf7f2
TL
530 FEATURE_MIMIC |
531 FEATURE_NAUTILUS |
532 FEATURE_OSDMAP_PRUNE |
9f95a23c 533 FEATURE_OCTOPUS |
f67539c2
TL
534 FEATURE_PACIFIC |
535 FEATURE_PINGING |
20effc67 536 FEATURE_QUINCY |
1e59de90 537 FEATURE_REEF |
7c673cae
FG
538 FEATURE_NONE
539 );
540 }
541
11fdf7f2
TL
542 constexpr mon_feature_t get_optional() {
543 return (
544 FEATURE_OSDMAP_PRUNE |
545 FEATURE_NONE
546 );
547 }
548
549 static inline mon_feature_t get_feature_by_name(const std::string &n);
7c673cae
FG
550 }
551 }
552}
553
9f95a23c 554static inline ceph_release_t infer_ceph_release_from_mon_features(mon_feature_t f)
11fdf7f2 555{
1e59de90
TL
556 if (f.contains_all(ceph::features::mon::FEATURE_REEF)) {
557 return ceph_release_t::reef;
558 }
20effc67
TL
559 if (f.contains_all(ceph::features::mon::FEATURE_QUINCY)) {
560 return ceph_release_t::quincy;
561 }
f67539c2
TL
562 if (f.contains_all(ceph::features::mon::FEATURE_PACIFIC)) {
563 return ceph_release_t::pacific;
564 }
9f95a23c
TL
565 if (f.contains_all(ceph::features::mon::FEATURE_OCTOPUS)) {
566 return ceph_release_t::octopus;
567 }
11fdf7f2 568 if (f.contains_all(ceph::features::mon::FEATURE_NAUTILUS)) {
9f95a23c 569 return ceph_release_t::nautilus;
11fdf7f2
TL
570 }
571 if (f.contains_all(ceph::features::mon::FEATURE_MIMIC)) {
9f95a23c 572 return ceph_release_t::mimic;
11fdf7f2
TL
573 }
574 if (f.contains_all(ceph::features::mon::FEATURE_LUMINOUS)) {
9f95a23c 575 return ceph_release_t::luminous;
11fdf7f2
TL
576 }
577 if (f.contains_all(ceph::features::mon::FEATURE_KRAKEN)) {
9f95a23c 578 return ceph_release_t::kraken;
11fdf7f2 579 }
9f95a23c 580 return ceph_release_t::unknown;
11fdf7f2
TL
581}
582
7c673cae
FG
583static inline const char *ceph::features::mon::get_feature_name(uint64_t b) {
584 mon_feature_t f(b);
585
586 if (f == FEATURE_KRAKEN) {
587 return "kraken";
588 } else if (f == FEATURE_LUMINOUS) {
589 return "luminous";
11fdf7f2
TL
590 } else if (f == FEATURE_MIMIC) {
591 return "mimic";
592 } else if (f == FEATURE_OSDMAP_PRUNE) {
593 return "osdmap-prune";
594 } else if (f == FEATURE_NAUTILUS) {
595 return "nautilus";
f67539c2
TL
596 } else if (f == FEATURE_PINGING) {
597 return "elector-pinging";
9f95a23c
TL
598 } else if (f == FEATURE_OCTOPUS) {
599 return "octopus";
f67539c2
TL
600 } else if (f == FEATURE_PACIFIC) {
601 return "pacific";
20effc67
TL
602 } else if (f == FEATURE_QUINCY) {
603 return "quincy";
1e59de90
TL
604 } else if (f == FEATURE_REEF) {
605 return "reef";
7c673cae
FG
606 } else if (f == FEATURE_RESERVED) {
607 return "reserved";
608 }
609 return "unknown";
610}
611
11fdf7f2 612inline mon_feature_t ceph::features::mon::get_feature_by_name(const std::string &n) {
7c673cae
FG
613
614 if (n == "kraken") {
615 return FEATURE_KRAKEN;
616 } else if (n == "luminous") {
617 return FEATURE_LUMINOUS;
11fdf7f2
TL
618 } else if (n == "mimic") {
619 return FEATURE_MIMIC;
620 } else if (n == "osdmap-prune") {
621 return FEATURE_OSDMAP_PRUNE;
622 } else if (n == "nautilus") {
623 return FEATURE_NAUTILUS;
f67539c2
TL
624 } else if (n == "feature-pinging") {
625 return FEATURE_PINGING;
9f95a23c
TL
626 } else if (n == "octopus") {
627 return FEATURE_OCTOPUS;
f67539c2
TL
628 } else if (n == "pacific") {
629 return FEATURE_PACIFIC;
20effc67
TL
630 } else if (n == "quincy") {
631 return FEATURE_QUINCY;
1e59de90
TL
632 } else if (n == "reef") {
633 return FEATURE_REEF;
7c673cae
FG
634 } else if (n == "reserved") {
635 return FEATURE_RESERVED;
636 }
637 return FEATURE_NONE;
638}
639
9f95a23c 640inline std::ostream& operator<<(std::ostream& out, const mon_feature_t& f) {
7c673cae
FG
641 out << "mon_feature_t(";
642 f.print(out);
643 out << ")";
644 return out;
645}
646
11fdf7f2
TL
647
648struct ProgressEvent {
9f95a23c 649 std::string message; ///< event description
11fdf7f2 650 float progress; ///< [0..1]
f67539c2 651 bool add_to_ceph_s;
9f95a23c 652 void encode(ceph::buffer::list& bl) const {
f67539c2 653 ENCODE_START(2, 1, bl);
11fdf7f2
TL
654 encode(message, bl);
655 encode(progress, bl);
f67539c2 656 encode(add_to_ceph_s, bl);
11fdf7f2
TL
657 ENCODE_FINISH(bl);
658 }
9f95a23c 659 void decode(ceph::buffer::list::const_iterator& p) {
f67539c2 660 DECODE_START(2, p);
11fdf7f2
TL
661 decode(message, p);
662 decode(progress, p);
f67539c2
TL
663 if (struct_v >= 2){
664 decode(add_to_ceph_s, p);
665 } else {
666 if (!message.empty()) {
667 add_to_ceph_s = true;
668 }
669 }
11fdf7f2
TL
670 DECODE_FINISH(p);
671 }
9f95a23c 672 void dump(ceph::Formatter *f) const {
11fdf7f2
TL
673 f->dump_string("message", message);
674 f->dump_float("progress", progress);
f67539c2 675 f->dump_bool("add_to_ceph_s", add_to_ceph_s);
11fdf7f2
TL
676 }
677};
678WRITE_CLASS_ENCODER(ProgressEvent)
679
7c673cae 680#endif