]>
git.proxmox.com Git - ceph.git/blob - ceph/src/crush/CrushTreeDumper.h
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"
21 #include "include/stringify.h"
25 * A helper class and functions to dump a crush tree.
29 * class SimpleDumper : public CrushTreeDumper::Dumper<ostream> {
31 * SimpleDumper(const CrushWrapper *crush) :
32 * CrushTreeDumper::Dumper<ostream>(crush) {}
34 * virtual void dump_item(const CrushTreeDumper::Item &qi, ostream *out) {
36 * for (int k = 0; k < qi.depth; k++)
39 * *out << crush->get_item_name(qi.id)
41 * *out << "osd." << qi.id;
46 * SimpleDumper(crush).dump(out);
50 namespace CrushTreeDumper
{
57 std::list
<int> children
;
59 Item() : id(0), parent(0), depth(0), weight(0) {}
60 Item(int i
, int p
, int d
, float w
) : id(i
), parent(p
), depth(d
), weight(w
) {}
62 bool is_bucket() const { return id
< 0; }
66 class Dumper
: public std::list
<Item
> {
68 explicit Dumper(const CrushWrapper
*crush_
,
69 const name_map_t
& weight_set_names_
)
70 : crush(crush_
), weight_set_names(weight_set_names_
) {
71 crush
->find_nonshadow_roots(&roots
);
74 explicit Dumper(const CrushWrapper
*crush_
,
75 const name_map_t
& weight_set_names_
,
77 : crush(crush_
), weight_set_names(weight_set_names_
) {
79 crush
->find_roots(&roots
);
81 crush
->find_nonshadow_roots(&roots
);
88 virtual void reset() {
94 virtual bool should_dump_leaf(int i
) const {
97 virtual bool should_dump_empty_bucket() const {
101 bool should_dump(int id
) {
103 return should_dump_leaf(id
);
104 if (should_dump_empty_bucket())
106 int s
= crush
->get_bucket_size(id
);
107 for (int k
= s
- 1; k
>= 0; k
--) {
108 int c
= crush
->get_bucket_item(id
, k
);
115 bool next(Item
&qi
) {
117 while (root
!= roots
.end() && !should_dump(*root
))
119 if (root
== roots
.end())
121 push_back(Item(*root
, 0, 0, crush
->get_bucket_weightf(*root
)));
127 touched
.insert(qi
.id
);
129 if (qi
.is_bucket()) {
130 // queue bucket contents, sorted by (class, name)
131 int s
= crush
->get_bucket_size(qi
.id
);
132 std::map
<std::string
, std::pair
<int,float>> sorted
;
133 for (int k
= s
- 1; k
>= 0; k
--) {
134 int id
= crush
->get_bucket_item(qi
.id
, k
);
135 if (should_dump(id
)) {
138 const char *c
= crush
->get_item_class(id
);
139 sort_by
= c
? c
: "";
142 snprintf(nn
, sizeof(nn
), "osd.%08d", id
);
146 sort_by
+= crush
->get_item_name(id
);
148 sorted
[sort_by
] = std::make_pair(
149 id
, crush
->get_bucket_item_weightf(qi
.id
, k
));
152 for (auto p
= sorted
.rbegin(); p
!= sorted
.rend(); ++p
) {
153 qi
.children
.push_back(p
->second
.first
);
154 push_front(Item(p
->second
.first
, qi
.id
, qi
.depth
+ 1,
168 bool is_touched(int id
) const { return touched
.count(id
) > 0; }
170 void set_root(const std::string
& bucket
) {
172 if (crush
->name_exists(bucket
)) {
173 int i
= crush
->get_item_id(bucket
);
179 virtual void dump_item(const Item
&qi
, F
*f
) = 0;
182 const CrushWrapper
*crush
;
183 const name_map_t
&weight_set_names
;
186 std::set
<int> touched
;
188 std::set
<int>::iterator root
;
191 inline void dump_item_fields(const CrushWrapper
*crush
,
192 const name_map_t
& weight_set_names
,
193 const Item
&qi
, ceph::Formatter
*f
) {
194 f
->dump_int("id", qi
.id
);
195 const char *c
= crush
->get_item_class(qi
.id
);
197 f
->dump_string("device_class", c
);
198 if (qi
.is_bucket()) {
199 int type
= crush
->get_bucket_type(qi
.id
);
200 f
->dump_string("name", crush
->get_item_name(qi
.id
));
201 f
->dump_string("type", crush
->get_type_name(type
));
202 f
->dump_int("type_id", type
);
204 f
->dump_stream("name") << "osd." << qi
.id
;
205 f
->dump_string("type", crush
->get_type_name(0));
206 f
->dump_int("type_id", 0);
207 f
->dump_float("crush_weight", qi
.weight
);
208 f
->dump_unsigned("depth", qi
.depth
);
211 f
->open_object_section("pool_weights");
212 for (auto& p
: crush
->choose_args
) {
213 const crush_choose_arg_map
& cmap
= p
.second
;
214 int bidx
= -1 - qi
.parent
;
215 const crush_bucket
*b
= crush
->get_bucket(qi
.parent
);
217 bidx
< (int)cmap
.size
&&
218 cmap
.args
[bidx
].weight_set
&&
219 cmap
.args
[bidx
].weight_set_positions
>= 1) {
222 bpos
< (int)cmap
.args
[bidx
].weight_set
[0].size
&&
223 b
->items
[bpos
] != qi
.id
;
226 if (p
.first
== CrushWrapper::DEFAULT_CHOOSE_ARGS
) {
229 auto q
= weight_set_names
.find(p
.first
);
230 name
= q
!= weight_set_names
.end() ? q
->second
:
233 f
->open_array_section(name
.c_str());
234 for (unsigned opos
= 0;
235 opos
< cmap
.args
[bidx
].weight_set_positions
;
237 float w
= (float)cmap
.args
[bidx
].weight_set
[opos
].weights
[bpos
] /
239 f
->dump_float("weight", w
);
248 inline void dump_bucket_children(const CrushWrapper
*crush
,
249 const Item
&qi
, ceph::Formatter
*f
) {
253 f
->open_array_section("children");
254 for (std::list
<int>::const_iterator i
= qi
.children
.begin();
255 i
!= qi
.children
.end();
257 f
->dump_int("child", *i
);
262 class FormattingDumper
: public Dumper
<ceph::Formatter
> {
264 explicit FormattingDumper(const CrushWrapper
*crush
,
265 const name_map_t
& weight_set_names
)
266 : Dumper
<ceph::Formatter
>(crush
, weight_set_names
) {}
267 explicit FormattingDumper(const CrushWrapper
*crush
,
268 const name_map_t
& weight_set_names
,
270 : Dumper
<ceph::Formatter
>(crush
, weight_set_names
, show_shadow
) {}
273 void dump_item(const Item
&qi
, ceph::Formatter
*f
) override
{
274 f
->open_object_section("item");
275 dump_item_fields(qi
, f
);
276 dump_bucket_children(qi
, f
);
280 virtual void dump_item_fields(const Item
&qi
, ceph::Formatter
*f
) {
281 CrushTreeDumper::dump_item_fields(crush
, weight_set_names
, qi
, f
);
284 virtual void dump_bucket_children(const Item
&qi
, ceph::Formatter
*f
) {
285 CrushTreeDumper::dump_bucket_children(crush
, qi
, f
);