]> git.apps.os.sepia.ceph.com Git - ceph.git/commitdiff
*** empty log message ***
authorsage <sage@29311d96-e01e-0410-9327-a35deaab8ce9>
Thu, 15 Sep 2005 07:36:57 +0000 (07:36 +0000)
committersage <sage@29311d96-e01e-0410-9327-a35deaab8ce9>
Thu, 15 Sep 2005 07:36:57 +0000 (07:36 +0000)
git-svn-id: https://ceph.svn.sf.net/svnroot/ceph@494 29311d96-e01e-0410-9327-a35deaab8ce9

ceph/crush/BinaryTree.h [new file with mode: 0644]
ceph/crush/Bucket.h [new file with mode: 0644]

diff --git a/ceph/crush/BinaryTree.h b/ceph/crush/BinaryTree.h
new file mode 100644 (file)
index 0000000..870d6d1
--- /dev/null
@@ -0,0 +1,212 @@
+#ifndef __crush_BINARYTREE_H
+#define __crush_BINARYTREE_H
+
+#include <cassert>
+#include <iostream>
+#include <map>
+#include <set>
+using namespace std;
+
+namespace crush {
+
+  class BinaryTree {
+  private:
+       // tree def
+       int             root_node;       // 0 for empty tree.
+       map<int, int>   node_nested;     // all existing nodes in this map
+       map<int, float> node_weight;     // and this one
+       set<int>        node_complete;   // only nodes with all possible children
+       
+  public:
+       BinaryTree() : root_node(0) {}
+       
+       // accessors
+       bool  empty() { return root_node == 0; }
+       bool  exists(int n) { return node_nested.count(n); }
+       int   nested(int n) { return exists(n) ? node_nested[n]:0; }
+       float weight(int n) { return exists(n) ? node_weight[n]:0; }
+       bool  complete(int n) { return node_complete.count(n); }
+       int   root() { return root_node; }
+       
+       // tree navigation
+       bool terminal(int n) { return n & 1; }  // odd nodes are leaves.
+       int height(int n) {
+         assert(n);
+         int h = 0;
+         while ((n & 1) == 0) {
+               assert(n > 0);
+               h++; n = n >> 1;
+         }
+         return h;
+       }
+       int left(int n) { 
+         int h = height(n);
+         //cout << "left of " << n << " is " << (n - (1 << h)) << endl;
+         return n - (1 << (h-1));
+       }
+       int right(int n) {
+         int h = height(n);
+         //cout << "right of " << n << " is " << (n + (1 << h)) << endl;
+         return n + (1 << (h-1));
+       }
+       bool on_right(int n, int h = -1) { 
+         if (h < 0) h = height(n);
+         return n & (1 << (h+1)); 
+       }
+       bool on_left(int n) { return !on_right(n); }
+       int parent(int n) {
+         int h = height(n);
+         if (on_right(n, h))
+               return n - (1<<h);
+         else
+               return n + (1<<h);
+       }
+       
+       // modifiers
+       void remove_node(int n) {
+         assert(exists(n));
+         
+         // erase node
+         node_nested.erase(n);
+         node_weight.erase(n);
+
+         // adjust parents (!complete, -weight)
+         int p = n;
+         while (p != root_node) {
+               p = parent(p);
+
+               node_complete.erase(p);
+               node_weight[p] = weight(left(p)) + weight(right(p));
+               node_nested[p]--;
+
+               if (nested(p) == 0) {
+                 node_weight.erase(p);
+                 node_nested.erase(p);
+               }
+         }
+         
+         // hose root?
+         while (!terminal(root_node) &&
+                        (nested(left(root_node)) == 0 ||
+                        nested(right(root_node)) == 0)) {
+               // root now one child..
+               node_weight.erase(root_node);
+               node_nested.erase(root_node);
+               if (nested(left(root_node)) == 0)
+                 root_node = right(root_node);
+               else 
+                 root_node = left(root_node);
+         }
+
+         if (terminal(root_node) && 
+                 nested(root_node) == 0) {
+               // empty!
+               node_weight.erase(root_node);
+               node_nested.erase(root_node);
+               root_node = 0;
+         }
+
+       }
+       
+       int add_node(float w) {
+         int n;
+         if (!root_node) {
+               // empty tree!
+               root_node = n = 1;
+         } else {
+               // existing tree.
+               // expand tree?
+               if (complete(root_node)) {
+                 // add new root
+                 int newroot = parent(root_node);
+                 node_weight[newroot] = node_weight[root_node];
+                 node_nested[newroot] = nested(root_node);
+
+                 // go right or left?
+                 if (left(newroot) == root_node)
+                       n = right(newroot);
+                 else
+                       n = left(newroot);
+                 root_node = newroot;
+
+                 // then go left until terminal
+                 while (!terminal(n))
+                       n = left(n);
+               }
+               else {
+                 // tree isn't complete.
+                 n = root_node;
+                 while (!terminal(n)) {
+                       if (!exists(left(n)) || !complete(left(n))) {
+                         // left isn't complete
+                         n = left(n);
+                       } else {
+                         assert(!exists(right(n)) || !complete(right(n)));
+                         // right isn't complete
+                         n = right(n);
+                       }
+                 }
+               }
+         }
+         
+         // create at n
+         //cout << "creating " << n << endl;
+         node_weight[n] = w;
+         node_nested[n] = 1;
+         node_complete.insert(n);
+
+         // ancestors: create, adjust weight, complete as appropriate
+         int p = n;
+         while (p != root_node) {
+               p = parent(p);
+
+               // complete?
+               if (!complete(p) &&
+                       complete(left(p)) && 
+                       complete(right(p))) 
+                 node_complete.insert(p);
+               
+               // weight (and implicitly create)
+               node_weight[p] += w;
+               node_nested[p]++;
+         }
+
+         return n;
+       }
+       
+
+  };
+
+
+  // print it out
+  void print_node(ostream& out, BinaryTree& tree, int n, int i) {
+       for (int t=i; t>0; t--) out << "  ";
+       if (tree.root() == n)
+         out << "root  ";
+       else {
+         if (tree.on_left(n))
+               out << "left  ";
+         else
+               out << "right ";
+       }
+       out << n << " : nested " << tree.nested(n) << "   weight " << tree.weight(n);
+       if (tree.complete(n)) out << "  complete";
+       out << endl;
+       if (!tree.terminal(n)) {
+         if (tree.exists(tree.left(n)))
+               print_node(out, tree, tree.left(n), i+2);
+         if (tree.exists(tree.right(n)))
+               print_node(out, tree, tree.right(n), i+2);
+       }
+  }
+  
+  ostream& operator<<(ostream& out, BinaryTree& tree) {
+       if (tree.empty()) 
+         return out << "tree is empty";
+       print_node(out, tree, tree.root(), 0);  
+       return out;
+  }
+  
+}
+
+#endif
diff --git a/ceph/crush/Bucket.h b/ceph/crush/Bucket.h
new file mode 100644 (file)
index 0000000..5737a44
--- /dev/null
@@ -0,0 +1,127 @@
+#ifndef __crush_BUCKET_H
+#define __crush_BUCKET_H
+
+namespace crush {
+
+
+  class Bucket {
+  protected:
+       int         id;
+       int         type;
+       float       weight;
+       vector<int> items;
+
+  public:
+       Bucket(int _id) : id(_id), weight(0) { }
+
+       int         get_id() { return id; }
+       int         get_type() { return type; }
+       float       get_weight() { return weight; }
+       vector<int> get_items() { return items; }
+       int         get_size() { return items.size(); }
+
+       float       get_item_weight() = 0;
+       bool        is_uniform() = 0;
+       float       calc_weight() = 0;
+
+       
+       void choose_r(int r, int type, vector<int>& in, vector<int>& out) = 0;
+
+  };
+
+
+  class UniformBucket : public Bucket {        void choose_r(int r, int type, vector<int>& in, vector<int>& out) = 0;
+  protected:
+       float  item_weight;
+  public:
+       float       get_item_weight(int i) { return item_weight; }
+       bool        is_uniform() { return true; }
+
+       float calc_weight() {
+         if (item.empty())
+               weight = 0;
+         else 
+               weight = items.size() * get_item_weight(item[0]);
+         return weight;
+       }
+
+       int choose_r(pg_t x, int r, Hash& h) {
+         assert(type == get_type());
+         if (r >= get_size()) cour << "warning: r " << r << " >= " << get_size() << " uniformbucket.size" << endl;
+         
+         int v = h(x, r, get_id(), 1) * get_size();
+         int pmin = get_weight();
+         int p = 0; // choose a prime based on hash(x, r, get_id(), 2)
+         //int s = x + v + r *p(? % get_size())
+         //return get_item[s % get_size()];
+       }
+  };
+
+
+
+  // mixed bucket.. RUSH_T
+  
+
+  class MixedBucket : public Bucket {
+  protected:
+       vector<float>  item_weight;
+
+       BinaryTree     tree;
+       map<int,int>   node_map;     // node id -> item
+
+  public:
+       float       get_item_weight(int i) {
+         return item_weight[i];
+       }
+       bool        is_uniform() { return false; }
+
+       float calc_weight() {
+         weight = 0;
+         for (unsigned i=0; i<items.size(); i++) {
+               weight += get_item_weight(i);
+         }
+         return weight;
+       }
+
+
+       void make_new_tree(vector<int>& items) {
+         assert(tree.empty());
+         
+         for (unsigned i=0; i<items.size(); i++) {
+               int n = tree.add_node(item_weight[i]);
+               node_map[n] = items[i];
+         }
+       }
+
+       int choose_r(pg_t x, int r, Hash& h) {
+         int n = tree.root();
+         while (!tree.terminal(n)) {
+               float f = h(x, n, r, 0);
+               if (tree.weight(tree.left(n)) <= f)
+                 node = tree.left(n);
+               else
+                 node = tree.right(n);
+         }
+       
+         return node_map[n];
+       }
+
+
+  };
+
+
+
+
+
+
+}
+
+
+
+
+
+
+
+
+#endif