summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDavid Zafman <david.zafman@inktank.com>2013-09-17 17:04:54 -0700
committerDavid Zafman <david.zafman@inktank.com>2013-09-26 11:29:04 -0700
commit793ba9f1d551f66f1aefa4e2f78ef5592a74b7e0 (patch)
tree729347adb04994f2afd7e49e8782ab453453456c
parentc6b83180f9f769de27ca7890f5f8ec507ee743ca (diff)
downloadceph-793ba9f1d551f66f1aefa4e2f78ef5592a74b7e0.tar.gz
include, test: Add CompatSet::merge() operation
New func merge() adds missing features from specified CompatSet Add merge testing to unittest Signed-off-by: David Zafman <david.zafman@inktank.com>
-rw-r--r--src/include/CompatSet.h27
-rw-r--r--src/test/ceph_compatset.cc34
2 files changed, 61 insertions, 0 deletions
diff --git a/src/include/CompatSet.h b/src/include/CompatSet.h
index 31246e186b2..b23883093ac 100644
--- a/src/include/CompatSet.h
+++ b/src/include/CompatSet.h
@@ -171,6 +171,33 @@ struct CompatSet {
return diff;
}
+ /* Merge features supported by other CompatSet into this one.
+ * Return: true if some features were merged
+ */
+ bool merge(CompatSet& other) {
+ uint64_t other_compat =
+ ((other.compat.mask ^ compat.mask) & other.compat.mask);
+ uint64_t other_ro_compat =
+ ((other.ro_compat.mask ^ ro_compat.mask) & other.ro_compat.mask);
+ uint64_t other_incompat =
+ ((other.incompat.mask ^ incompat.mask) & other.incompat.mask);
+ if (!other_compat && !other_ro_compat && !other_incompat)
+ return false;
+ for (int id = 1; id < 64; ++id) {
+ uint64_t mask = (uint64_t)1 << id;
+ if (mask & other_compat) {
+ compat.insert( Feature(id, other.compat.names[id]));
+ }
+ if (mask & other_ro_compat) {
+ ro_compat.insert(Feature(id, other.ro_compat.names[id]));
+ }
+ if (mask & other_incompat) {
+ incompat.insert( Feature(id, other.incompat.names[id]));
+ }
+ }
+ return true;
+ }
+
void encode(bufferlist& bl) const {
compat.encode(bl);
ro_compat.encode(bl);
diff --git a/src/test/ceph_compatset.cc b/src/test/ceph_compatset.cc
index 50909ed0538..2b57db01ab9 100644
--- a/src/test/ceph_compatset.cc
+++ b/src/test/ceph_compatset.cc
@@ -128,3 +128,37 @@ TEST(CephCompatSet, other) {
EXPECT_EQ(diff.ro_compat.mask, (uint64_t)1);
EXPECT_EQ(diff.incompat.mask, (uint64_t)1<<4 | 1);
}
+
+TEST(CephCompatSet, merge) {
+ CompatSet s1, s2, s1dup, s2dup;
+
+ s1.compat.insert(CompatSet::Feature(1, "c1"));
+ s1.compat.insert(CompatSet::Feature(2, "c2"));
+ s1.compat.insert(CompatSet::Feature(32, "c32"));
+ s1.ro_compat.insert(CompatSet::Feature(63, "r63"));
+ s1.incompat.insert(CompatSet::Feature(1, "i1"));
+
+ s1dup = s1;
+
+ s2.compat.insert(CompatSet::Feature(1, "c1"));
+ s2.compat.insert(CompatSet::Feature(32, "c32"));
+ s2.ro_compat.insert(CompatSet::Feature(1, "r1"));
+ s2.ro_compat.insert(CompatSet::Feature(63, "r63"));
+ s2.incompat.insert(CompatSet::Feature(1, "i1"));
+
+ s2dup = s2;
+
+ //Nothing to merge if they are the same
+ EXPECT_FALSE(s1.merge(s1dup));
+ EXPECT_FALSE(s2.merge(s2dup));
+
+ EXPECT_TRUE(s1.merge(s2));
+ EXPECT_EQ(s1.compat.mask, (uint64_t)1<<1 | (uint64_t)1<<2 | (uint64_t)1<<32 | 1);
+ EXPECT_EQ(s1.ro_compat.mask, (uint64_t)1<<1 | (uint64_t)1<<63 | 1);
+ EXPECT_EQ(s1.incompat.mask, (uint64_t)1<<1 | 1);
+
+ EXPECT_TRUE(s2.merge(s1dup));
+ EXPECT_EQ(s2.compat.mask, (uint64_t)1<<1 | (uint64_t)1<<2 | (uint64_t)1<<32 | 1);
+ EXPECT_EQ(s2.ro_compat.mask, (uint64_t)1<<1 | (uint64_t)1<<63 | 1);
+ EXPECT_EQ(s2.incompat.mask, (uint64_t)1<<1 | 1);
+}