]> git-server-git.apps.pok.os.sepia.ceph.com Git - ceph.git/commitdiff
crush: move crushtool --test into CrushTester
authorSage Weil <sage.weil@dreamhost.com>
Sun, 19 Feb 2012 22:48:05 +0000 (14:48 -0800)
committerSage Weil <sage.weil@dreamhost.com>
Sun, 19 Feb 2012 22:48:05 +0000 (14:48 -0800)
Signed-off-by: Sage Weil <sage.weil@dreamhost.com>
src/Makefile.am
src/crush/CrushTester.cc [new file with mode: 0644]
src/crush/CrushTester.h [new file with mode: 0644]
src/crushtool.cc

index 085507e22aee86e8e6f08cca2f55552ba4f0a1c7..7d3509cb557716d141e050bd754797598dd7d8ed 100644 (file)
@@ -860,7 +860,8 @@ crush_files = \
        crush/crush.c \
        crush/hash.c \
        crush/CrushWrapper.cc \
-       crush/CrushCompiler.cc
+       crush/CrushCompiler.cc \
+       crush/CrushTester.cc
 
 # this list ommits the ceph_ver.c file
 libcommon_files = \
@@ -1146,6 +1147,7 @@ noinst_HEADERS = \
        common/strtol.h\
        common/static_assert.h\
        crush/CrushCompiler.h\
+       crush/CrushTester.h\
         crush/CrushWrapper.h\
         crush/CrushWrapper.i\
         crush/builder.h\
diff --git a/src/crush/CrushTester.cc b/src/crush/CrushTester.cc
new file mode 100644 (file)
index 0000000..6aaf90d
--- /dev/null
@@ -0,0 +1,76 @@
+
+#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;
+}
diff --git a/src/crush/CrushTester.h b/src/crush/CrushTester.h
new file mode 100644 (file)
index 0000000..897290a
--- /dev/null
@@ -0,0 +1,71 @@
+// -*- 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
index d3d972e151262d1ccd01b48e69860e41c12abbbf..0849b636a647354d20a8f49fa171b7c05a8ad6e4 100644 (file)
@@ -28,6 +28,7 @@
 #include "global/global_init.h"
 #include "crush/CrushWrapper.h"
 #include "crush/CrushCompiler.h"
+#include "crush/CrushTester.h"
 
 #include <fstream>
 
@@ -108,17 +109,18 @@ int main(int argc, const char **argv)
   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;
@@ -134,6 +136,7 @@ int main(int argc, const char **argv)
       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;
@@ -176,48 +179,54 @@ int main(int argc, const char **argv)
        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;
@@ -228,12 +237,7 @@ int main(int argc, const char **argv)
        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;
@@ -272,7 +276,6 @@ int main(int argc, const char **argv)
   if (dinfn) cout << "dinfn " << dinfn << std::endl;
   */
 
-  CrushWrapper crush;
   bool modified = false;
 
   if (!infn.empty()) {
@@ -498,38 +501,9 @@ int main(int argc, const char **argv)
   }
 
   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;