change CompatSet

This commit is contained in:
Greg Farnum 2010-01-15 13:16:46 -08:00
parent b826611cae
commit 80979bbe92

View File

@ -18,54 +18,63 @@
#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);
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() {
all_features.push_back(&compat);
all_features.push_back(&ro_compat);
all_features.push_back(&incompat);
}
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