]> git.apps.os.sepia.ceph.com Git - ceph.git/commitdiff
change CompatSet
authorGreg Farnum <gregf@hq.newdream.net>
Fri, 15 Jan 2010 21:16:46 +0000 (13:16 -0800)
committerGreg Farnum <gregf@hq.newdream.net>
Tue, 19 Jan 2010 22:03:20 +0000 (14:03 -0800)
src/include/CompatSet.h

index d728845ba35d611e5a4d793efb0ac642bf68adb9..4555bbc0842c3ee94307b9bb48763595bdbff237 100644 (file)
 #include <vector>
 
 struct CompatSet {
-  set<string> compat, ro_compat, incompat;
-  vector<set<string> *> all_features;
-  
-  CompatSet(const char **compat_a, int c_size,
-           const char **ro_compat_a, int ro_size,
-           const char **incompat_a, int inc_size) :
-    compat(), ro_compat(), incompat(){
-    for (int i = 0; i < c_size; ++i)
-      compat.insert(string(compat_a[i]));
-    for (int j = 0; j < ro_size; ++j)
-      ro_compat.insert(string(ro_compat_a[j]));
-    for (int k = 0; k < inc_size; ++k)
-      incompat.insert(string(incompat_a[k]));
-    all_features.push_back(&compat);
-    all_features.push_back(&ro_compat);
-    all_features.push_back(&incompat);
-  }
-  
-  CompatSet() : compat(), ro_compat(), incompat() {
-    all_features.push_back(&compat);
-    all_features.push_back(&ro_compat);
-    all_features.push_back(&incompat);
+
+  struct Feature {
+    __u64 id;
+    string name;
+
+    Feature(__u64 _id, const char *_name) : id(_id), name(_name) {}
+    Feature(__u64 _id, string& _name) : id(_id), name(_name) {}
+  };
+
+  struct FeatureSet {
+    __u64 mask;
+    map <__u64,string> names;
+    void insert(Feature f) {
+      mask |= f.id;
+      names[f.id] = f.name;
+    }
+
+    void encode(bufferlist& bl) const {
+      ::encode(mask, bl);
+      ::encode(names, bl);
+    }
+
+    void decode(bufferlist::iterator& bl) {
+      ::decode(mask, bl);
+      ::decode(names, bl);
+    }
+  };
+
+  FeatureSet compat, ro_compat, incompat;
+
+  CompatSet(FeatureSet& _compat, FeatureSet& _ro_compat, FeatureSet& _incompat) :
+    compat(_compat), ro_compat(_ro_compat), incompat(_incompat) {}
+
+  CompatSet(Feature _compat[], Feature _ro_compat[], Feature _incompat[]) :
+    compat(), ro_compat(), incompat()
+  {
+    for (int i = 0; _compat[i].id != 0; ++i) compat.insert(_compat[i]);
+    for (int j = 0; _ro_compat[j].id !=0; ++j) ro_compat.insert(_ro_compat[j]);
+    for (int k = 0; _incompat[k].id != 0; ++k) incompat.insert(_incompat[k]);
   }
-  
+
+  CompatSet() : compat(), ro_compat(), incompat() { }
+
+
   /* does this filesystem implementation have the
      features required to read the other? */
-  bool readable(CompatSet other) {
-    //make sure other's incompat string is a subset of ours
-    for ( set<string>::iterator i = other.incompat.begin();
-         i != other.incompat.end();
-         ++i) {
-      if (!incompat.count(*i)) return false; //we don't have that flag!
-    }
-    return true;
+  bool readable(CompatSet& other) {
+    return !((other.incompat.mask ^ incompat.mask) & other.incompat.mask);
   }
-  
+
   /* does this filesystem implementation have the
      features required to write the other? */
-  bool writeable(CompatSet other) {
-    if (!readable(other)) return false;
-    for (set<string>::iterator i = other.ro_compat.begin();
-        i != other.ro_compat.end();
-        ++i) {
-      if (!ro_compat.count(*i))        return false;
-    }
-    return true;
+  bool writeable(CompatSet& other) {
+    return readable(other) &&
+      !((other.ro_compat.mask ^ ro_compat.mask) & other.ro_compat.mask);
   }
-  
+
   /* Compare this CompatSet to another.
    * CAREFULLY NOTE: This operation is NOT commutative.
    * a > b DOES NOT imply that b < a.
@@ -75,119 +84,58 @@ struct CompatSet {
    * -1: This CompatSet is missing at least one feature
    *     described in the other. It may still have more features, though.
    */
-  int compare(CompatSet other) {
-    //check sizes, that's fast and easy
-    if (other.compat.size() > compat.size() ||
-       other.ro_compat.size() > ro_compat.size() ||
-       other.incompat.size() > incompat.size() ) {
-      return -1;
-    }
-    //well, we have at least as many features, let's compare them all
-    if (!writeable(other)) return -1; //compares ro_compat and incompat
-    for (set<string>::iterator i = other.compat.begin();
-        i != other.compat.end();
-        ++i) {
-      if (!compat.count(*i)) return -1;
-    }
-    //if we make it this far we have all the features other does
-    //do we have more?
-    if (other.compat.size() < compat.size() ||
-       other.ro_compat.size() < ro_compat.size() ||
-       other.incompat.size() < incompat.size() ) {
-      return 1;
-    }
-    //apparently we have the exact same feature set
-    return 0;
+  int compare(CompatSet& other) {
+    if ((other.compat.mask == compat.mask) &&
+       (other.ro_compat.mask == ro_compat.mask) &&
+       (other.incompat.mask == incompat.mask)) return 0;
+    //okay, they're not the same
+
+    //if we're writeable we have a superset of theirs on incompat and ro_compat
+    if (writeable(other) && !((other.compat.mask ^ compat.mask)
+                             & other.compat.mask)) return 1;
+    //if we make it here, we weren't writeable or had a difference compat set
+    return -1;
   }
-  
+
   /* Get the features supported by other CompatSet but not this one,
    * as a CompatSet.
    */
-  CompatSet unsupported(CompatSet other) {
-    CompatSet difference;
-    for (set<string>::iterator i = other.compat.begin();
-        i != other.compat.end();
-        ++i) {
-      if (!compat.count(*i)) difference.compat.insert(*i);
-    }
-    for (set<string>::iterator j = other.ro_compat.begin();
-        j != other.ro_compat.end();
-        ++j) {
-      if (!ro_compat.count(*j))        difference.ro_compat.insert(*j);
-    }
-    for (set<string>::iterator k = other.incompat.begin();
-        k != other.incompat.end();
-        ++k) {
-      if (!incompat.count(*k)) difference.incompat.insert(*k);
-    }
-    return difference;
-  }
-  
-  class iterator {
-  private:
-    friend class CompatSet;
-    CompatSet *cset;
-    vector<set<string> *>::iterator feature_it;
-    set<string>::iterator it;
-  public:
-    iterator(CompatSet *comset) : cset(comset){
-      feature_it = cset->all_features.begin();
-      it = (*feature_it)->begin();
-    }
-    
-    string operator*() {
-      //check that we actually have contents, here
-      if ( cset->all_features.end() != feature_it) { //if not at end
-       return (*it);
+  CompatSet unsupported(CompatSet& other) {
+    CompatSet diff;
+    __u64 other_compat =
+      ((other.compat.mask ^ compat.mask) & other.compat.mask);
+    __u64 other_ro_compat =
+      ((other.ro_compat.mask ^ ro_compat.mask) & other.ro_compat.mask);
+    __u64 other_incompat =
+      ((other.incompat.mask ^ incompat.mask) & other.incompat.mask);
+    for (int i = 0; i < 64; ++i) {
+      int mask = 1 << i;
+      if (mask & other_compat) {
+       diff.compat.insert( Feature(mask & other_compat,
+                                   other.compat.names[mask&other_compat]));
       }
-      return string();
-    }
-    
-    iterator& operator++() {
-      if (feature_it == cset->all_features.end()) return *this;//at end
-      if (it != (*feature_it)->end()) { //if not at end of cur stringset
-       if (++it != (*feature_it)->end()) return *this; //move along current set
+      if (mask & other_ro_compat) {
+       diff.ro_compat.insert(Feature(mask & other_ro_compat,
+                                     other.compat.names[mask&other_ro_compat]));
       }
-      if (++feature_it != cset->all_features.end()) { //move to next set
-       it = (*feature_it)->begin(); //start it over in new set
-       if ((*feature_it)->end() == it) return operator++(); //damn, keep moving
-       return *this; //yay, done
+      if (mask & other_incompat) {
+       diff.incompat.insert( Feature(mask & other_incompat,
+                                     other.incompat.names[mask&other_incompat]));
       }
-      return *this; //at full end now, returning end iterator
     }
-    
-    bool operator==(const iterator& other) const {
-      return (other.cset == cset
-             && other.feature_it == feature_it
-             && other.it == it);
-    }
-    
-    bool operator!=(const iterator& other) const { return !operator==(other);}
-  };
-  
-  iterator begin() {
-    iterator it(this);
-    if ((*it.feature_it)->end() == it.it) ++it;
-    return it;
-  }
-  
-  iterator end() {
-    iterator it(this);
-    it.feature_it = all_features.end();
-    it.it = all_features[2]->end();
-    return it;
+    return diff;
   }
   
   void encode(bufferlist& bl) const {
-    ::encode(compat, bl);
-    ::encode(ro_compat, bl);
-    ::encode(incompat, bl);
+    compat.encode(bl);
+    ro_compat.encode(bl);
+    incompat.encode(bl);
   }
   
   void decode(bufferlist::iterator& bl) {
-    ::decode(compat, bl);
-    ::decode(ro_compat, bl);
-    ::decode(incompat, bl);
+    compat.decode(bl);
+    ro_compat.decode(bl);
+    incompat.decode(bl);
   }
 };
 #endif