summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSage Weil <sage@newdream.net>2012-05-02 12:08:26 -0700
committerSage Weil <sage@newdream.net>2012-05-02 14:55:53 -0700
commitbfa7635162566ccbf3a3ab326a71024836a146f6 (patch)
tree9cf26496e8c4aa075036230719aa22162c99c4b9
parenteca7eac34af0468fe6d8c7db0f87d04c18dc51eb (diff)
downloadceph-bfa7635162566ccbf3a3ab326a71024836a146f6.tar.gz
crush: add check_item_loc
The check_item_loc() method will take an item and position and tell you if it matches the items current location. The matching is identical to that used for insert_item, in that a specific location constraint match means success, even if a less specific one does not match (e.g., rack=wrongrack, host=correcthost will return true). Signed-off-by: Sage Weil <sage@newdream.net>
-rw-r--r--src/crush/CrushWrapper.cc53
-rw-r--r--src/crush/CrushWrapper.h1
2 files changed, 54 insertions, 0 deletions
diff --git a/src/crush/CrushWrapper.cc b/src/crush/CrushWrapper.cc
index 13351d54d04..5473e60a85d 100644
--- a/src/crush/CrushWrapper.cc
+++ b/src/crush/CrushWrapper.cc
@@ -65,6 +65,59 @@ int CrushWrapper::remove_item(CephContext *cct, int item)
return ret;
}
+/**
+ * see if item is located where we think it is
+ *
+ * @param cct cct
+ * @param item item id
+ * @param loc location to check (map of type to bucket names)
+ */
+bool CrushWrapper::check_item_loc(CephContext *cct, int item, map<string,string>& loc,
+ float *weight) // typename -> bucketname
+{
+ ldout(cct, 5) << "check_item_loc item " << item << " loc " << loc << dendl;
+
+ int cur = item;
+ for (map<int,string>::const_iterator p = type_map.begin(); p != type_map.end(); p++) {
+ if (p->first == 0)
+ continue;
+
+ if (loc.count(p->second) == 0) {
+ ldout(cct, 2) << "warning: did not specify location for '" << p->second << "' level (levels are "
+ << type_map << ")" << dendl;
+ continue;
+ }
+
+ int id = get_item_id(loc[p->second].c_str());
+ if (!id) {
+ ldout(cct, 5) << "check_item_loc bucket " << loc[p->second] << " of type " << p->second << " dne" << dendl;
+ return false;
+ }
+
+ if (id >= 0) {
+ ldout(cct, 5) << "check_item_loc requested " << loc[p->second] << " for type " << p->second
+ << " is a device, not bucket" << dendl;
+ return false;
+ }
+
+ crush_bucket *b = get_bucket(id);
+ assert(b);
+
+ // make sure the item doesn't already exist in this bucket
+ for (unsigned j=0; j<b->size; j++)
+ if (b->items[j] == cur) {
+ ldout(cct, 2) << "check_item_loc " << cur << " exists in bucket " << b->id << dendl;
+ if (weight)
+ *weight = (float)crush_get_bucket_item_weight(b, j) / (float)0x10000;
+ return true;
+ }
+ return false;
+ }
+
+ ldout(cct, 1) << "check_item_loc item " << item << " loc " << loc << dendl;
+ return false;
+}
+
int CrushWrapper::insert_item(CephContext *cct, int item, float weight, string name,
map<string,string>& loc) // typename -> bucketname
{
diff --git a/src/crush/CrushWrapper.h b/src/crush/CrushWrapper.h
index 5376a78ffc9..25ada59d12e 100644
--- a/src/crush/CrushWrapper.h
+++ b/src/crush/CrushWrapper.h
@@ -164,6 +164,7 @@ public:
void find_roots(set<int>& roots) const;
+ bool check_item_loc(CephContext *cct, int item, map<string,string>& loc, float *weight);
int insert_item(CephContext *cct, int id, float weight, string name, map<string,string>& loc);
int remove_item(CephContext *cct, int id);
int adjust_item_weight(CephContext *cct, int id, int weight);