]> git.apps.os.sepia.ceph.com Git - ceph.git/commitdiff
*** empty log message ***
authorsage <sage@29311d96-e01e-0410-9327-a35deaab8ce9>
Fri, 16 Sep 2005 22:58:10 +0000 (22:58 +0000)
committersage <sage@29311d96-e01e-0410-9327-a35deaab8ce9>
Fri, 16 Sep 2005 22:58:10 +0000 (22:58 +0000)
git-svn-id: https://ceph.svn.sf.net/svnroot/ceph@497 29311d96-e01e-0410-9327-a35deaab8ce9

ceph/TODO
ceph/crush/Bucket.h
ceph/crush/crush.h
ceph/test/testcrush.cc

index 86dbe8a94616c4a70650af3106aae4b42f972a5c..820c58e295917c6f8e1de11695a7488583df4a33 100644 (file)
--- a/ceph/TODO
+++ b/ceph/TODO
@@ -101,6 +101,7 @@ give each bucket "type" has a numerical id, whatever you want.  eg
 3 row
 4 room
 
+mirror(4)
 take(root)
 choose(2, room)
 take_vert
@@ -109,6 +110,63 @@ take_vert
 choose(1, disk)
 
 
+=> 0
+takeb root
+choose_r 0 room -> w[2]
+takew 2
+choose_r 0 cab -> w[1]
+takew 1
+choose_r 0 disk -> 0
+
+=> 1
+takeb root
+choose_r 0 room -> w[2]
+takew 2
+choose_r 1 cab -> w[1]
+takew 1
+choose_r 0 disk -> 0
+
+=> 2
+takeb root
+choose_r 1 room -> w[2]
+takew 2
+choose_r 0 cab -> w[1]
+takew 1
+choose_r 0 disk -> 0
+
+=> 3
+takeb root
+choose_r 1 room -> w[2]
+takew 2
+choose_r 1 cab -> w[1]
+takew 1
+choose_r 0 disk -> 0
+
+
+mirror(3)
+choose(1, room, root)
+choose(3, cab, _)
+vert(_)
+choose(1, disk, _)
+
+=> 0
+takeb root
+choose_r 0/3 cab
+choose_r 0/1 disk
+
+=> 1
+takeb root
+choose_r 1/3 cab
+choose_r 0/1 disk
+
+=> 2
+takeb root
+choose_r 2/3 cab
+choose_r 0/1 disk
+
+
+
+
 mirror(2):
 choose(1, room, root)       -> [ room1 ]
 choose(2, cabinet, _)       -> [ cab3 cab2 ]
index b83a3f382f9c7f4444c41500eea2b85498bcf1d9..a28f49a93ee8b5d04e7357b6baad40948ef94392 100644 (file)
@@ -31,7 +31,7 @@ namespace crush {
        float        get_weight() const { return weight; }
        virtual int  get_size() const = 0;
 
-       void        set_weight(float w)  { weight = w; }
+       void         set_weight(float w)  { weight = w; }
 
        virtual bool is_uniform() const = 0;
        virtual int choose_r(int x, int r, Hash& h) const = 0;
@@ -85,6 +85,7 @@ namespace crush {
        }
 
        int choose_r(int x, int r, Hash& h) const {
+         //cout << "uniformbucket.choose_r(" << x << ", " << r << ")" << endl;
          //if (r >= get_size()) cout << "warning: r " << r << " >= " << get_size() << " uniformbucket.size" << endl;
          
          int v = (h(x, get_id(), 1) % get_size()) * get_size();
@@ -147,6 +148,7 @@ namespace crush {
        }
 
        int choose_r(int x, int r, Hash& h) const {
+         //cout << "mixedbucket.choose_r(" << x << ", " << r << ")" << endl;
          int n = tree.root();
          while (!tree.terminal(n)) {
                // pick a point in [0,w)
index 83e1dff037029e77b0fd107c0830b384b548547a..c061dd8be5d0d12d89e5b2ca9a6ea3cffd1436ed 100644 (file)
@@ -10,11 +10,6 @@ namespace crush {
 
   // *** RULES ***
 
-  // rule commands
-  const int CRUSH_RULE_TAKE = 0;
-  const int CRUSH_RULE_CHOOSE = 1;
-  const int CRUSH_RULE_VERT = 2;
-
   class RuleStep {
   public:
        int         cmd;
@@ -28,13 +23,37 @@ namespace crush {
          args.push_back(a);
          args.push_back(b);
        }
+       RuleStep(int o, int a, int b, int c) : cmd(o) {
+         args.push_back(a);
+         args.push_back(b);
+         args.push_back(c);
+       }
   };
 
+
+  // Rule
+  const int CRUSH_RULE_TAKE = 0;
+  const int CRUSH_RULE_CHOOSE = 1;
+  const int CRUSH_RULE_VERT = 2;
+
   class Rule {
   public:
        vector< RuleStep > steps;
   };
 
+  // CRule
+  const int CRULE_TAKEB = 1;
+  const int CRULE_CHOOSER = 2;
+
+  class CRule {
+  public:
+       vector< vector<RuleStep> > steps;
+       int nchoose;
+       int nrep;
+
+       CRule() {}
+       CRule(int nr) : steps(nr), nrep(nr) {}
+  };
 
 
   // *** CRUSH ***
@@ -43,8 +62,11 @@ namespace crush {
   protected:
        map<int, Bucket*>  buckets;
        map<int, Rule>     rules;
+       map<int, CRule>     crules;
        Hash h;
 
+       set<int>           failed;
+
   public:
        Crush(int seed=123) : h(seed) {}
 
@@ -54,6 +76,102 @@ namespace crush {
        void add_rule( int id, Rule& r ) {
          rules[id] = r;
        }
+       void add_crule( int id, CRule& r ) {
+         crules[id] = r;
+       }
+
+       void crule_choose(int ruleno, int x, vector<int>& result) {
+         CRule& rule = crules[ruleno];
+         
+         // input
+         Bucket *in = 0;
+         int out = -1;
+         
+         // for replicas
+         for (int rep=0; rep<rule.nrep; rep++) {
+               // initially zero
+               vector<int> add_r(rule.nchoose);
+               
+               for (int attempt=0; ; attempt++) {
+                 
+                 // steps
+                 int nchoose = 0;
+                 for (int pc=0; pc<rule.steps[rep].size(); pc++) {
+                       switch (rule.steps[rep][pc].cmd) {
+                       case CRULE_TAKEB:
+                         {
+                               const int arg = rule.steps[rep][pc].args[0];
+                               assert(buckets.count(arg));
+                               in = buckets[arg];
+                         }
+                         break;
+                         
+                       case CRULE_CHOOSER:
+                         {
+                               int r = rule.steps[rep][pc].args[0];
+                               const int rperiod = rule.steps[rep][pc].args[1];
+                               const int type = rule.steps[rep][pc].args[2];
+                               
+                               // adjust to skip unusable
+                               r += rperiod * add_r[nchoose];
+                               nchoose++;
+                               
+                               //cout << "choose_r " << r << " type " << type << endl;
+                               
+                               // choose through any intervening buckets
+                               while (1) {
+                                 // choose in this bucket
+                                 out = in->choose_r(x, r, h);
+
+                                 if (in->is_uniform() && 
+                                         ((UniformBucket*)in)->get_item_type() == type)
+                                       break;
+
+                                 int itemtype = 0;  // 0 is a terminal type
+                                 if (buckets.count(out)) {
+                                       in = buckets[out];
+                                       itemtype = in->get_type();
+                                 } 
+                                 if (itemtype == type) break;  // this is what we want!
+                               }                               
+                               
+                               if (type != 0) {  // translate back into a bucket
+                                 assert(buckets.count(out));
+                                 in = buckets[out];
+                               }
+                         }
+                         break;
+                         
+                       default:
+                         assert(0);
+                       }
+                 }
+
+                 // disk failed?
+                 bool bad = false;
+                 if (failed.count(out)) 
+                       bad = true;
+                 
+                 for (int prep=0; prep<rep; prep++) {
+                       if (result[prep] == out) 
+                         bad = true;
+                 }
+
+                 if (bad) {
+                       // bump an 'r'
+                       //cout << "failed|repeat " << attempt << endl;
+                       add_r[ rule.nchoose - 1 - ((attempt/2)%rule.nchoose) ]++;
+                       continue;
+                 }
+
+                 break;                  // disk is fine.
+               }
+               
+               // ok!
+               result[rep] = out;
+         }
+       }
+
 
        void choose(int rno, int x, vector<int>& result) {
          assert(rules.count(rno));
index 420059c5f4fd6536fb0039b77e6cca0c288efd74..3563c7f4a5932f02e9320ed7527339bf02db5ccb 100644 (file)
@@ -33,7 +33,7 @@ void make_disks(int n, int& no, vector<int>& d)
 int main() 
 {
   Hash h(73);
-  int numrep = 3;
+  int numrep = 5;
 
 
   // buckets
@@ -50,7 +50,7 @@ int main()
   ub2.make_primes(h);  
   cout << "ub2 primes are " << ub2.primes << endl;
 
-  make_disks(21, ndisks, disks);
+  make_disks(4, ndisks, disks);
   UniformBucket ub3(3, 1, 0, 30, disks);
   ub3.make_primes(h);  
   cout << "ub3 primes are " << ub3.primes << endl;
@@ -63,7 +63,14 @@ int main()
   // rule
   Rule rule;
   rule.steps.push_back(RuleStep(CRUSH_RULE_TAKE, 100));
-  rule.steps.push_back(RuleStep(CRUSH_RULE_CHOOSE, 3, 0));
+  rule.steps.push_back(RuleStep(CRUSH_RULE_CHOOSE, numrep, 0));
+  CRule crule(numrep);
+  crule.nchoose = 2;
+  for (int j=0; j<numrep; j++) {
+       crule.steps[j].push_back(RuleStep(CRULE_TAKEB, 100));
+       crule.steps[j].push_back(RuleStep(CRULE_CHOOSER, j, numrep, 1));
+       crule.steps[j].push_back(RuleStep(CRULE_CHOOSER, j, numrep, 0));
+  }
 
   // crush
   Crush c;
@@ -72,6 +79,7 @@ int main()
   c.add_bucket(&ub3);
   c.add_bucket(&b);
   c.add_rule(numrep, rule);
+  c.add_crule(numrep, crule);
 
 
   
@@ -82,14 +90,22 @@ int main()
   cout << "placing " << numo << " logical,  " << numo*numrep << " total" << endl;
   for (int x=1; x<numo; x++) {
        //cout << H(x) << "\t" << h(x) << endl;
-       v.clear();
-       c.choose(numrep, x, v);
+       c.crule_choose(numrep, x, v);
+       //cout << "v = " << v << endl;// " " << v[0] << " " << v[1] << "  " << v[2] << endl;
 
+       bool bad = false;
        for (int i=0; i<numrep; i++) {
          //int d = b.choose_r(x, i, h);
          //v[i] = d;
          ocount[v[i]]++;
+         for (int j=i+1; j<numrep; j++) {
+               if (v[i] == v[j]) 
+                 bad = true;
+         }
        }
+       if (bad)
+         cout << "bad set " << x << ": " << v << endl;
+         
        //cout << v << "\t" << ocount << endl;
   }