--- /dev/null
+
+#include "CrushTester.h"
+
+void CrushTester::set_device_weight(int dev, float f)
+{
+ int w = (int)(f * 0x10000);
+ if (w < 0)
+ w = 0;
+ if (w > 0x10000)
+ w = 0x10000;
+ device_weight[dev] = w;
+}
+
+int CrushTester::test()
+{
+ if (min_rule < 0 || max_rule < 0) {
+ min_rule = 0;
+ max_rule = crush.get_max_rules() - 1;
+ }
+ if (min_x < 0 || max_x < 0) {
+ min_x = 0;
+ max_x = 1023;
+ }
+
+ // all osds in
+ vector<__u32> weight;
+ for (int o = 0; o < crush.get_max_devices(); o++)
+ if (device_weight.count(o))
+ weight.push_back(device_weight[o]);
+ else
+ weight.push_back(0x10000);
+ if (verbose>1)
+ err << "devices weights (hex): " << hex << weight << dec << std::endl;
+
+ for (int r = min_rule; r < crush.get_max_rules() && r <= max_rule; r++) {
+ if (!crush.rule_exists(r)) {
+ if (verbose>0)
+ err << "rule " << r << " dne" << std::endl;
+ continue;
+ }
+ int minr = min_rep, maxr = max_rep;
+ if (min_rep < 0 || max_rep < 0) {
+ minr = crush.get_rule_mask_min_size(r);
+ maxr = crush.get_rule_mask_max_size(r);
+ }
+
+ if (verbose>0)
+ err << "rule " << r << " (" << crush.get_rule_name(r)
+ << "), x = " << min_x << ".." << max_x
+ << ", numrep = " << minr << ".." << maxr
+ << std::endl;
+ for (int nr = minr; nr <= maxr; nr++) {
+ vector<int> per(crush.get_max_devices());
+ map<int,int> sizes;
+ for (int x = min_x; x <= max_x; x++) {
+ vector<int> out;
+ crush.do_rule(r, x, out, nr, force, weight);
+ if (verbose)
+ if (verbose>1)
+ err << " rule " << r << " x " << x << " " << out << std::endl;
+ for (unsigned i = 0; i < out.size(); i++)
+ per[out[i]]++;
+ sizes[out.size()]++;
+ }
+ for (unsigned i = 0; i < per.size(); i++)
+ if (verbose>1)
+ err << " device " << i << ":\t" << per[i] << std::endl;
+ for (map<int,int>::iterator p = sizes.begin(); p != sizes.end(); p++)
+ if (verbose>0 || p->first != nr)
+ err << "rule " << r << " (" << crush.get_rule_name(r) << ") num_rep " << nr
+ << " result size == " << p->first << ":\t"
+ << p->second << "/" << (max_x-min_x+1) << std::endl;
+ }
+ }
+ return 0;
+}
--- /dev/null
+// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
+// vim: ts=8 sw=2 smarttab
+
+#ifndef CEPH_CRUSH_TESTER_H
+#define CEPH_CRUSH_TESTER_H
+
+#include "crush/CrushWrapper.h"
+
+class CrushTester {
+ CrushWrapper& crush;
+ ostream& err;
+ int verbose;
+
+ map<int, int> device_weight;
+ int min_rule, max_rule;
+ int min_x, max_x;
+ int min_rep, max_rep;
+ int force;
+
+public:
+ CrushTester(CrushWrapper& c, ostream& eo, int verbosity=0)
+ : crush(c), err(eo), verbose(verbosity),
+ min_rule(-1), max_rule(-1),
+ min_x(-1), max_x(-1),
+ min_rep(-1), max_rep(-1),
+ force(-1)
+ { }
+
+ void set_verbosity(int v) {
+ verbose = v;
+ }
+ void set_device_weight(int dev, float f);
+
+ void set_min_rep(int r) {
+ min_rep = r;
+ }
+ void set_max_rep(int r) {
+ max_rep = r;
+ }
+ void set_num_rep(int r) {
+ min_rep = max_rep = r;
+ }
+
+ void set_min_x(int x) {
+ min_x = x;
+ }
+ void set_max_x(int x) {
+ max_x = x;
+ }
+ void set_x(int x) {
+ min_x = max_x = x;
+ }
+
+ void set_min_rule(int rule) {
+ min_rule = rule;
+ }
+ void set_max_rule(int rule) {
+ max_rule = rule;
+ }
+ void set_rule(int rule) {
+ min_rule = max_rule = rule;
+ }
+
+ void set_force(int x) {
+ force = x;
+ }
+
+ int test();
+};
+
+#endif
#include "global/global_init.h"
#include "crush/CrushWrapper.h"
#include "crush/CrushCompiler.h"
+#include "crush/CrushTester.h"
#include <fstream>
int build = 0;
int num_osds =0;
vector<layer_t> layers;
- int num_rep = 2;
- int min_x = 0, max_x = 10000-1;
- int min_rule = 0, max_rule = 1000;
- int force = -1;
- map<int, int> device_weight;
+
+ CrushWrapper crush;
+
+ CrushTester tester(crush, cerr, 1);
vector<const char *> empty_args; // we use -c, don't confuse the generic arg parsing
global_init(empty_args, CEPH_ENTITY_TYPE_CLIENT, CODE_ENVIRONMENT_UTILITY,
CINIT_FLAG_NO_DEFAULT_CONFIG_FILE);
common_init_finish(g_ceph_context);
+ int x;
+
std::string val;
std::ostringstream err;
int tmp;
outfn = val;
} else if (ceph_argparse_flag(args, i, "-v", "--verbose", (char*)NULL)) {
verbose = true;
+ tester.set_verbosity(2);
} else if (ceph_argparse_witharg(args, i, &val, "-c", "--compile", (char*)NULL)) {
srcfn = val;
compile = true;
cerr << err.str() << std::endl;
exit(EXIT_FAILURE);
}
- } else if (ceph_argparse_withint(args, i, &num_rep, &err, "--num_rep", (char*)NULL)) {
+ } else if (ceph_argparse_withint(args, i, &x, &err, "--num_rep", (char*)NULL)) {
if (!err.str().empty()) {
cerr << err.str() << std::endl;
exit(EXIT_FAILURE);
}
- } else if (ceph_argparse_withint(args, i, &max_x, &err, "--max_x", (char*)NULL)) {
+ tester.set_num_rep(x);
+ } else if (ceph_argparse_withint(args, i, &x, &err, "--max_x", (char*)NULL)) {
if (!err.str().empty()) {
cerr << err.str() << std::endl;
exit(EXIT_FAILURE);
}
- } else if (ceph_argparse_withint(args, i, &min_x, &err, "--min_x", (char*)NULL)) {
+ tester.set_max_x(x);
+ } else if (ceph_argparse_withint(args, i, &x, &err, "--min_x", (char*)NULL)) {
if (!err.str().empty()) {
cerr << err.str() << std::endl;
exit(EXIT_FAILURE);
}
- } else if (ceph_argparse_withint(args, i, &min_x, &err, "--x", (char*)NULL)) {
+ tester.set_min_x(x);
+ } else if (ceph_argparse_withint(args, i, &x, &err, "--x", (char*)NULL)) {
if (!err.str().empty()) {
cerr << err.str() << std::endl;
exit(EXIT_FAILURE);
}
- max_x = min_x;
- } else if (ceph_argparse_withint(args, i, &force, &err, "--force", (char*)NULL)) {
+ tester.set_x(x);
+ } else if (ceph_argparse_withint(args, i, &x, &err, "--force", (char*)NULL)) {
if (!err.str().empty()) {
cerr << err.str() << std::endl;
exit(EXIT_FAILURE);
}
- } else if (ceph_argparse_withint(args, i, &max_rule, &err, "--max_rule", (char*)NULL)) {
+ tester.set_force(x);
+ } else if (ceph_argparse_withint(args, i, &x, &err, "--max_rule", (char*)NULL)) {
if (!err.str().empty()) {
cerr << err.str() << std::endl;
exit(EXIT_FAILURE);
}
- } else if (ceph_argparse_withint(args, i, &min_rule, &err, "--min_rule", (char*)NULL)) {
+ tester.set_max_rule(x);
+ } else if (ceph_argparse_withint(args, i, &x, &err, "--min_rule", (char*)NULL)) {
if (!err.str().empty()) {
cerr << err.str() << std::endl;
exit(EXIT_FAILURE);
}
- } else if (ceph_argparse_withint(args, i, &min_rule, &err, "--rule", (char*)NULL)) {
+ tester.set_min_rule(x);
+ } else if (ceph_argparse_withint(args, i, &x, &err, "--rule", (char*)NULL)) {
if (!err.str().empty()) {
cerr << err.str() << std::endl;
exit(EXIT_FAILURE);
}
- max_rule = min_rule;
+ tester.set_rule(x);
} else if (ceph_argparse_withint(args, i, &tmp, &err, "--weight", (char*)NULL)) {
if (!err.str().empty()) {
cerr << err.str() << std::endl;
usage();
float f = atof(*i);
i = args.erase(i);
- int w = (int)(f * 0x10000);
- if (w < 0)
- w = 0;
- if (w > 0x10000)
- w = 0x10000;
- device_weight[dev] = w;
+ tester.set_device_weight(dev, f);
}
else {
++i;
if (dinfn) cout << "dinfn " << dinfn << std::endl;
*/
- CrushWrapper crush;
bool modified = false;
if (!infn.empty()) {
}
if (test) {
-
- // all osds in
- vector<__u32> weight;
- for (int o = 0; o < crush.get_max_devices(); o++)
- if (device_weight.count(o))
- weight.push_back(device_weight[o]);
- else
- weight.push_back(0x10000);
- cout << "devices weights (hex): " << hex << weight << dec << std::endl;
-
- for (int r = min_rule; r < crush.get_max_rules() && r <= max_rule; r++) {
- if (!crush.rule_exists(r)) {
- cout << "rule " << r << " dne" << std::endl;
- continue;
- }
- cout << "rule " << r << " (" << crush.get_rule_name(r) << "), x = " << min_x << ".." << max_x << std::endl;
- vector<int> per(crush.get_max_devices());
- map<int,int> sizes;
- for (int x = min_x; x <= max_x; x++) {
- vector<int> out;
- crush.do_rule(r, x, out, num_rep, force, weight);
- if (verbose)
- cout << "rule " << r << " x " << x << " " << out << std::endl;
- for (unsigned i = 0; i < out.size(); i++)
- per[out[i]]++;
- sizes[out.size()]++;
- }
- for (unsigned i = 0; i < per.size(); i++)
- cout << " device " << i << ":\t" << per[i] << std::endl;
- for (map<int,int>::iterator p = sizes.begin(); p != sizes.end(); p++)
- cout << " result size " << p->first << "x:\t" << p->second << std::endl;
- }
+ int r = tester.test();
+ if (r < 0)
+ exit(1);
}
return 0;