]> git.apps.os.sepia.ceph.com Git - ceph.git/commitdiff
crush: add move_bucket() method
authorCaleb Miles <caselim@gmail.com>
Fri, 29 Jun 2012 17:54:16 +0000 (10:54 -0700)
committerSage Weil <sage@inktank.com>
Fri, 29 Jun 2012 19:32:33 +0000 (12:32 -0700)
Move an existing bucket to a new location in the hierarchy.

Signed-off-by: Caleb Miles <caselim@gmail.com>
src/crush/CrushWrapper.cc
src/crush/CrushWrapper.h

index 63a3374696682f70cd555380f4b3e282fce18145..9c6deba32a18b2a87063c1910744ce89da10d132 100644 (file)
@@ -186,6 +186,31 @@ int CrushWrapper::insert_item(CephContext *cct, int item, float weight, string n
   return -EINVAL;
 }
 
+int CrushWrapper::move_bucket(CephContext *cct, int id, map<string,string>& loc)
+{
+  // sorry this only works for buckets
+  if (id >= 0)
+    return -EINVAL;
+
+  if (!item_exists(id))
+    return -ENOENT;
+
+  // get the name of the bucket we are trying to move for later
+  string id_name = get_item_name(id);
+
+  // detach the bucket
+  int bucket_weight = detach_bucket(cct, id);
+
+  // un-set the device name so we can use add_item later
+  build_rmap(name_map, name_rmap);
+  name_map.erase(id);
+  name_rmap.erase(id_name);
+
+  // insert the bucket back into the hierarchy
+  return insert_item(cct, id, bucket_weight / (float)0x10000, id_name, loc);
+}
+
+
 int CrushWrapper::update_item(CephContext *cct, int item, float weight, string name,
                              map<string,string>& loc)  // typename -> bucketname
 {
index 6f86a2d919d6832d9c932f7b530f00dac9735046..84757416563067a8d386a330c6d247385711003d 100644 (file)
@@ -252,6 +252,19 @@ public:
    */
   int insert_item(CephContext *cct, int id, float weight, string name, map<string,string>& loc);
 
+  /**
+   * move a bucket in the hierarchy to the given location
+   *
+   * This has the same location and ancestor creation behavior as
+   * insert_item(), but will relocate the specified existing bucket.
+   *
+   * @param cct cct
+   * @param id bucket id
+   * @param loc location (map of type to bucket names)
+   * @return 0 for success, negative on error
+   */
+  int move_bucket(CephContext *cct, int id, map<string,string>& loc);
+
   /**
    * add or update an item's position in the map
    *
@@ -423,6 +436,51 @@ private:
       return (crush_bucket *)(-ENOENT);
     return ret;
   }
+  /**
+   * detach a bucket from its parent and adjust the parent weight
+   *
+   * returns the weight of the detached bucket
+   **/
+  int detach_bucket(CephContext *cct, int item){
+    if (!crush)
+      return (-EINVAL);
+
+    if (item > 0)
+      return (-EINVAL);
+
+    // check that the bucket that we want to detach exists
+    assert( get_bucket(item) );
+
+    // get the bucket's weight
+    crush_bucket *b = get_bucket(item);
+    unsigned bucket_weight = b->weight;
+
+    // zero out the bucket weight
+    adjust_item_weight(cct, item, 0);
+
+    // get where the bucket is located
+    pair<string, string> bucket_location = get_immediate_parent(item);
+
+    // get the id of the parent bucket
+    int parent_id = get_item_id( (bucket_location.second).c_str() );
+
+    // get the parent bucket
+    crush_bucket *parent_bucket = get_bucket(parent_id);
+
+    // remove the bucket from the parent
+    crush_bucket_remove_item(parent_bucket, item);
+
+    // check that we're happy
+    int test_weight = 0;
+    map<string,string> test_location;
+    test_location[ bucket_location.first ] = (bucket_location.second);
+
+    bool successful_detach = !(check_item_loc(cct, item, test_location, &test_weight));
+    assert(successful_detach);
+    assert(test_weight == 0);
+
+    return bucket_weight;
+  }
 
 public:
   int get_max_buckets() const {