]>
git.proxmox.com Git - ceph.git/blob - ceph/src/crush/CrushTreeDumper.h
40691c697d3a75487eb0414ded0470b597b5ec4c
1 // -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
2 // vim: ts=8 sw=2 smarttab
4 * Ceph distributed storage system
6 * Copyright (C) 2015 Mirantis Inc
8 * Author: Mykola Golub <mgolub@mirantis.com>
10 * This library is free software; you can redistribute it and/or
11 * modify it under the terms of the GNU Lesser General Public
12 * License as published by the Free Software Foundation; either
13 * version 2.1 of the License, or (at your option) any later version.
17 #ifndef CRUSH_TREE_DUMPER_H
18 #define CRUSH_TREE_DUMPER_H
20 #include "CrushWrapper.h"
24 * A helper class and functions to dump a crush tree.
28 * class SimpleDumper : public CrushTreeDumper::Dumper<ostream> {
30 * SimpleDumper(const CrushWrapper *crush) :
31 * CrushTreeDumper::Dumper<ostream>(crush) {}
33 * virtual void dump_item(const CrushTreeDumper::Item &qi, ostream *out) {
35 * for (int k = 0; k < qi.depth; k++)
38 * *out << crush->get_item_name(qi.id)
40 * *out << "osd." << qi.id;
45 * SimpleDumper(crush).dump(out);
49 namespace CrushTreeDumper
{
57 Item() : id(0), depth(0), weight(0) {}
58 Item(int i
, int d
, float w
) : id(i
), depth(d
), weight(w
) {}
60 bool is_bucket() const { return id
< 0; }
64 class Dumper
: public list
<Item
> {
66 explicit Dumper(const CrushWrapper
*crush_
) : crush(crush_
) {
67 crush
->find_roots(roots
);
73 virtual void reset() {
79 virtual bool should_dump_leaf(int i
) const {
82 virtual bool should_dump_empty_bucket() const {
86 bool should_dump(int id
) {
88 return should_dump_leaf(id
);
89 if (should_dump_empty_bucket())
91 int s
= crush
->get_bucket_size(id
);
92 for (int k
= s
- 1; k
>= 0; k
--) {
93 int c
= crush
->get_bucket_item(id
, k
);
100 bool next(Item
&qi
) {
102 while (root
!= roots
.end() && !should_dump(*root
))
104 if (root
== roots
.end())
106 push_back(Item(*root
, 0, crush
->get_bucket_weightf(*root
)));
112 touched
.insert(qi
.id
);
114 if (qi
.is_bucket()) {
115 // queue bucket contents...
116 int s
= crush
->get_bucket_size(qi
.id
);
117 for (int k
= s
- 1; k
>= 0; k
--) {
118 int id
= crush
->get_bucket_item(qi
.id
, k
);
119 if (should_dump(id
)) {
120 qi
.children
.push_back(id
);
121 push_front(Item(id
, qi
.depth
+ 1,
122 crush
->get_bucket_item_weightf(qi
.id
, k
)));
136 bool is_touched(int id
) const { return touched
.count(id
) > 0; }
139 virtual void dump_item(const Item
&qi
, F
*f
) = 0;
142 const CrushWrapper
*crush
;
147 set
<int>::iterator root
;
150 inline void dump_item_fields(const CrushWrapper
*crush
,
151 const Item
&qi
, Formatter
*f
) {
152 f
->dump_int("id", qi
.id
);
153 if (qi
.is_bucket()) {
154 int type
= crush
->get_bucket_type(qi
.id
);
155 f
->dump_string("name", crush
->get_item_name(qi
.id
));
156 f
->dump_string("type", crush
->get_type_name(type
));
157 f
->dump_int("type_id", type
);
159 f
->dump_stream("name") << "osd." << qi
.id
;
160 f
->dump_string("type", crush
->get_type_name(0));
161 f
->dump_int("type_id", 0);
162 f
->dump_float("crush_weight", qi
.weight
);
163 f
->dump_unsigned("depth", qi
.depth
);
167 inline void dump_bucket_children(const CrushWrapper
*crush
,
168 const Item
&qi
, Formatter
*f
) {
172 f
->open_array_section("children");
173 for (list
<int>::const_iterator i
= qi
.children
.begin();
174 i
!= qi
.children
.end();
176 f
->dump_int("child", *i
);
181 class FormattingDumper
: public Dumper
<Formatter
> {
183 explicit FormattingDumper(const CrushWrapper
*crush
) : Dumper
<Formatter
>(crush
) {}
186 void dump_item(const Item
&qi
, Formatter
*f
) override
{
187 f
->open_object_section("item");
188 dump_item_fields(qi
, f
);
189 dump_bucket_children(qi
, f
);
193 virtual void dump_item_fields(const Item
&qi
, Formatter
*f
) {
194 CrushTreeDumper::dump_item_fields(crush
, qi
, f
);
197 virtual void dump_bucket_children(const Item
&qi
, Formatter
*f
) {
198 CrushTreeDumper::dump_bucket_children(crush
, qi
, f
);