]> git.proxmox.com Git - ceph.git/blame - ceph/src/crush/CrushTester.h
bump version to 18.2.2-pve1
[ceph.git] / ceph / src / crush / CrushTester.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#ifndef CEPH_CRUSH_TESTER_H
5#define CEPH_CRUSH_TESTER_H
6
7#include "crush/CrushWrapper.h"
39ae355f 8#include "include/common_fwd.h"
7c673cae
FG
9
10#include <fstream>
7c673cae
FG
11
12class CrushTester {
13 CrushWrapper& crush;
9f95a23c 14 std::ostream& err;
7c673cae 15
9f95a23c 16 std::map<int, int> device_weight;
7c673cae 17 int min_rule, max_rule;
7c673cae
FG
18 int min_x, max_x;
19 int min_rep, max_rep;
20 int64_t pool_id;
21
22 int num_batches;
23 bool use_crush;
24
25 float mark_down_device_ratio;
26 float mark_down_bucket_ratio;
27
28 bool output_utilization;
29 bool output_utilization_all;
30 bool output_statistics;
31 bool output_mappings;
32 bool output_bad_mappings;
33 bool output_choose_tries;
34
35 bool output_data_file;
36 bool output_csv;
37
9f95a23c 38 std::string output_data_file_name;
7c673cae
FG
39
40/*
41 * mark a ratio of devices down, can be used to simulate placement distributions
42 * under degrated cluster conditions
43 */
9f95a23c 44 void adjust_weights(std::vector<__u32>& weight);
7c673cae
FG
45
46 /*
47 * Get the maximum number of devices that could be selected to satisfy ruleno.
48 */
49 int get_maximum_affected_by_rule(int ruleno);
50
51 /*
52 * for maps where in devices have non-sequential id numbers, return a mapping of device id
53 * to a sequential id number. For example, if we have devices with id's 0 1 4 5 6 return a map
54 * where:
55 * 0 = 0
56 * 1 = 1
57 * 4 = 2
58 * 5 = 3
59 * 6 = 4
60 *
61 * which can help make post-processing easier
62 */
9f95a23c 63 std::map<int,int> get_collapsed_mapping();
7c673cae
FG
64
65 /*
66 * Essentially a re-implementation of CRUSH. Given a vector of devices
67 * check that the vector represents a valid placement for a given ruleno.
68 */
9f95a23c 69 bool check_valid_placement(int ruleno, std::vector<int> in, const std::vector<__u32>& weight);
7c673cae
FG
70
71 /*
72 * Generate a random selection of devices which satisfies ruleno. Essentially a
73 * monte-carlo simulator for CRUSH placements which can be used to compare the
74 * statistical distribution of the CRUSH algorithm to a random number generator
75 */
9f95a23c 76 int random_placement(int ruleno, std::vector<int>& out, int maxout, std::vector<__u32>& weight);
7c673cae
FG
77
78 // scaffolding to store data for off-line processing
79 struct tester_data_set {
9f95a23c
TL
80 std::vector<std::string> device_utilization;
81 std::vector<std::string> device_utilization_all;
82 std::vector<std::string> placement_information;
83 std::vector<std::string> batch_device_utilization_all;
84 std::vector<std::string> batch_device_expected_utilization_all;
85 std::map<int, float> proportional_weights;
86 std::map<int, float> proportional_weights_all;
87 std::map<int, float> absolute_weights;
7c673cae
FG
88 } ;
89
9f95a23c 90 void write_to_csv(std::ofstream& csv_file, std::vector<std::string>& payload)
7c673cae
FG
91 {
92 if (csv_file.good())
9f95a23c 93 for (std::vector<std::string>::iterator it = payload.begin(); it != payload.end(); ++it)
7c673cae
FG
94 csv_file << (*it);
95 }
96
9f95a23c 97 void write_to_csv(std::ofstream& csv_file, std::map<int, float>& payload)
7c673cae
FG
98 {
99 if (csv_file.good())
9f95a23c 100 for (std::map<int, float>::iterator it = payload.begin(); it != payload.end(); ++it)
7c673cae
FG
101 csv_file << (*it).first << ',' << (*it).second << std::endl;
102 }
103
9f95a23c 104 void write_data_set_to_csv(std::string user_tag, tester_data_set& tester_data)
7c673cae
FG
105 {
106
9f95a23c
TL
107 std::ofstream device_utilization_file((user_tag + (std::string)"-device_utilization.csv").c_str());
108 std::ofstream device_utilization_all_file((user_tag + (std::string)"-device_utilization_all.csv").c_str());
109 std::ofstream placement_information_file((user_tag + (std::string)"-placement_information.csv").c_str());
110 std::ofstream proportional_weights_file((user_tag + (std::string)"-proportional_weights.csv").c_str());
111 std::ofstream proportional_weights_all_file((user_tag + (std::string)"-proportional_weights_all.csv").c_str());
112 std::ofstream absolute_weights_file((user_tag + (std::string)"-absolute_weights.csv").c_str());
7c673cae
FG
113
114 // write the headers
115 device_utilization_file << "Device ID, Number of Objects Stored, Number of Objects Expected" << std::endl;
116 device_utilization_all_file << "Device ID, Number of Objects Stored, Number of Objects Expected" << std::endl;
117 proportional_weights_file << "Device ID, Proportional Weight" << std::endl;
118 proportional_weights_all_file << "Device ID, Proportional Weight" << std::endl;
119 absolute_weights_file << "Device ID, Absolute Weight" << std::endl;
120
121 placement_information_file << "Input";
122 for (int i = 0; i < max_rep; i++) {
123 placement_information_file << ", OSD" << i;
124 }
125 placement_information_file << std::endl;
126
127 write_to_csv(device_utilization_file, tester_data.device_utilization);
128 write_to_csv(device_utilization_all_file, tester_data.device_utilization_all);
129 write_to_csv(placement_information_file, tester_data.placement_information);
130 write_to_csv(proportional_weights_file, tester_data.proportional_weights);
131 write_to_csv(proportional_weights_all_file, tester_data.proportional_weights_all);
132 write_to_csv(absolute_weights_file, tester_data.absolute_weights);
133
134 device_utilization_file.close();
135 device_utilization_all_file.close();
136 placement_information_file.close();
137 proportional_weights_file.close();
138 absolute_weights_file.close();
139
140 if (num_batches > 1) {
9f95a23c
TL
141 std::ofstream batch_device_utilization_all_file ((user_tag + (std::string)"-batch_device_utilization_all.csv").c_str());
142 std::ofstream batch_device_expected_utilization_all_file ((user_tag + (std::string)"-batch_device_expected_utilization_all.csv").c_str());
7c673cae
FG
143
144 batch_device_utilization_all_file << "Batch Round";
145 for (unsigned i = 0; i < tester_data.device_utilization.size(); i++) {
146 batch_device_utilization_all_file << ", Objects Stored on OSD" << i;
147 }
148 batch_device_utilization_all_file << std::endl;
149
150 batch_device_expected_utilization_all_file << "Batch Round";
151 for (unsigned i = 0; i < tester_data.device_utilization.size(); i++) {
152 batch_device_expected_utilization_all_file << ", Objects Expected on OSD" << i;
153 }
154 batch_device_expected_utilization_all_file << std::endl;
155
156 write_to_csv(batch_device_utilization_all_file, tester_data.batch_device_utilization_all);
157 write_to_csv(batch_device_expected_utilization_all_file, tester_data.batch_device_expected_utilization_all);
158 batch_device_expected_utilization_all_file.close();
159 batch_device_utilization_all_file.close();
160 }
161 }
162
9f95a23c
TL
163 void write_integer_indexed_vector_data_string(std::vector<std::string> &dst, int index, std::vector<int> vector_data);
164 void write_integer_indexed_vector_data_string(std::vector<std::string> &dst, int index, std::vector<float> vector_data);
165 void write_integer_indexed_scalar_data_string(std::vector<std::string> &dst, int index, int scalar_data);
166 void write_integer_indexed_scalar_data_string(std::vector<std::string> &dst, int index, float scalar_data);
7c673cae
FG
167
168public:
9f95a23c 169 CrushTester(CrushWrapper& c, std::ostream& eo)
7c673cae
FG
170 : crush(c), err(eo),
171 min_rule(-1), max_rule(-1),
7c673cae
FG
172 min_x(-1), max_x(-1),
173 min_rep(-1), max_rep(-1),
174 pool_id(-1),
175 num_batches(1),
176 use_crush(true),
177 mark_down_device_ratio(0.0),
178 mark_down_bucket_ratio(1.0),
179 output_utilization(false),
180 output_utilization_all(false),
181 output_statistics(false),
182 output_mappings(false),
183 output_bad_mappings(false),
184 output_choose_tries(false),
185 output_data_file(false),
186 output_csv(false),
187 output_data_file_name("")
188
189 { }
190
9f95a23c 191 void set_output_data_file_name(std::string name) {
7c673cae
FG
192 output_data_file_name = name;
193 }
9f95a23c 194 std::string get_output_data_file_name() const {
7c673cae
FG
195 return output_data_file_name;
196 }
197
198 void set_output_data_file(bool b) {
199 output_data_file = b;
200 }
201 bool get_output_data_file() const {
202 return output_data_file;
203 }
204
205 void set_output_csv(bool b) {
206 output_csv = b;
207 }
208 bool get_output_csv() const {
209 return output_csv;
210 }
211
212 void set_output_utilization(bool b) {
213 output_utilization = b;
214 }
215 bool get_output_utilization() const {
216 return output_utilization;
217 }
218
219 void set_output_utilization_all(bool b) {
220 output_utilization_all = b;
221 }
222 bool get_output_utilization_all() const {
223 return output_utilization_all;
224 }
225
226 void set_output_statistics(bool b) {
227 output_statistics = b;
228 }
229 bool get_output_statistics() const {
230 return output_statistics;
231 }
232
233 void set_output_mappings(bool b) {
234 output_mappings = b;
235 }
236 bool get_output_mappings() const {
237 return output_mappings;
238 }
239
240 void set_output_bad_mappings(bool b) {
241 output_bad_mappings = b;
242 }
243 bool get_output_bad_mappings() const {
244 return output_bad_mappings;
245 }
246
247 void set_output_choose_tries(bool b) {
248 output_choose_tries = b;
249 }
250 bool get_output_choose_tries() const {
251 return output_choose_tries;
252 }
253
254 void set_batches(int b) {
255 num_batches = b;
256 }
257 int get_batches() const {
258 return num_batches;
259 }
260
261 void set_random_placement() {
262 use_crush = false;
263 }
264 bool get_random_placement() const {
265 return use_crush == false;
266 }
267
268 void set_bucket_down_ratio(float bucket_ratio) {
269 mark_down_bucket_ratio = bucket_ratio;
270 }
271 float get_bucket_down_ratio() const {
272 return mark_down_bucket_ratio;
273 }
274
275 void set_device_down_ratio(float device_ratio) {
276 mark_down_device_ratio = device_ratio;
277 }
278 float set_device_down_ratio() const {
279 return mark_down_device_ratio;
280 }
281
282 void set_device_weight(int dev, float f);
283
284 void set_min_rep(int r) {
285 min_rep = r;
286 }
287 int get_min_rep() const {
288 return min_rep;
289 }
290
291 void set_max_rep(int r) {
292 max_rep = r;
293 }
294 int get_max_rep() const {
295 return max_rep;
296 }
297
298 void set_num_rep(int r) {
299 min_rep = max_rep = r;
300 }
301
302 void set_min_x(int x) {
303 min_x = x;
304 }
305
306 void set_pool_id(int64_t x){
307 pool_id = x;
308 }
309
310 int get_min_x() const {
311 return min_x;
312 }
313
314 void set_max_x(int x) {
315 max_x = x;
316 }
317 int get_max_x() const {
318 return max_x;
319 }
320
321 void set_x(int x) {
322 min_x = max_x = x;
323 }
324
325 void set_min_rule(int rule) {
326 min_rule = rule;
327 }
328 int get_min_rule() const {
329 return min_rule;
330 }
331
332 void set_max_rule(int rule) {
333 max_rule = rule;
334 }
335 int get_max_rule() const {
336 return max_rule;
337 }
338
339 void set_rule(int rule) {
340 min_rule = max_rule = rule;
341 }
342
7c673cae
FG
343 /**
344 * check if any bucket/nodes is referencing an unknown name or type
345 * @param max_id rejects any non-bucket items with id less than this number,
346 * pass 0 to disable this check
347 * @return false if an dangling name/type is referenced or an item id is too
348 * large, true otherwise
349 */
350 bool check_name_maps(unsigned max_id = 0) const;
39ae355f
TL
351 int test(CephContext* cct);
352 int test_with_fork(CephContext* cct, int timeout);
f64942e4
AA
353
354 int compare(CrushWrapper& other);
7c673cae
FG
355};
356
357#endif