summaryrefslogtreecommitdiff
path: root/cpp/src/qpid/cluster/InitialStatusMap.cpp
diff options
context:
space:
mode:
authorAlan Conway <aconway@apache.org>2010-01-27 20:56:31 +0000
committerAlan Conway <aconway@apache.org>2010-01-27 20:56:31 +0000
commitd1c4af32b27b6d242d2b15e4dc91152a6d3e4a5a (patch)
tree68ae4c033fcf4f36c19966bf474c9ebdafd40fdf /cpp/src/qpid/cluster/InitialStatusMap.cpp
parent1e24432f3f0333890334648d808410fb3e9535cd (diff)
downloadqpid-python-d1c4af32b27b6d242d2b15e4dc91152a6d3e4a5a.tar.gz
Fix cluster elder calculation to ensure unique elder.
Race condition in the previous algorithm allowed several cluster members to consider themselves the elder. git-svn-id: https://svn.apache.org/repos/asf/qpid/trunk/qpid@903826 13f79535-47bb-0310-9956-ffa450edef68
Diffstat (limited to 'cpp/src/qpid/cluster/InitialStatusMap.cpp')
-rw-r--r--cpp/src/qpid/cluster/InitialStatusMap.cpp25
1 files changed, 20 insertions, 5 deletions
diff --git a/cpp/src/qpid/cluster/InitialStatusMap.cpp b/cpp/src/qpid/cluster/InitialStatusMap.cpp
index c6de488a40..a1a1456618 100644
--- a/cpp/src/qpid/cluster/InitialStatusMap.cpp
+++ b/cpp/src/qpid/cluster/InitialStatusMap.cpp
@@ -45,6 +45,7 @@ void InitialStatusMap::configChange(const MemberSet& members) {
Map::iterator j = map.begin();
while (i != members.end() || j != map.end()) {
if (i == members.end()) { // j not in members, member left
+ firstConfig.erase(j->first);
Map::iterator k = j++;
map.erase(k);
}
@@ -59,6 +60,7 @@ void InitialStatusMap::configChange(const MemberSet& members) {
++i;
}
else if (*i > j->first) { // j not in members, member left
+ firstConfig.erase(j->first);
Map::iterator k = j++;
map.erase(k);
}
@@ -83,7 +85,7 @@ bool InitialStatusMap::notInitialized(const Map::value_type& v) {
return !v.second;
}
-bool InitialStatusMap::isComplete() {
+bool InitialStatusMap::isComplete() const {
return !map.empty() && find_if(map.begin(), map.end(), &notInitialized) == map.end()
&& (map.size() >= size);
}
@@ -128,12 +130,21 @@ bool InitialStatusMap::isUpdateNeeded() {
return false;
}
-MemberSet InitialStatusMap::getElders() {
+MemberSet InitialStatusMap::getElders() const {
assert(isComplete());
MemberSet elders;
- // Elders are from first config change, active or higher node-id.
- for (MemberSet::iterator i = firstConfig.begin(); i != firstConfig.end(); ++i) {
- if (map.find(*i) != map.end() && (map[*i]->getActive() || *i > self))
+ for (MemberSet::const_iterator i = firstConfig.begin(); i != firstConfig.end(); ++i) {
+ // *i is in my first config, so a potential elder.
+ if (*i == self) continue; // Not my own elder
+ Map::const_iterator j = map.find(*i);
+ assert(j != map.end());
+ assert(j->second);
+ const Status& s = *j->second;
+ // If I'm not in i's first config then i is older than me.
+ // Otherwise we were born in the same configuration so use
+ // member ID to break the tie.
+ MemberSet iFirstConfig = decodeMemberSet(s.getFirstConfig());
+ if (iFirstConfig.find(self) == iFirstConfig.end() || *i > self)
elders.insert(*i);
}
return elders;
@@ -197,5 +208,9 @@ void InitialStatusMap::checkConsistent() {
throw Exception("Cannot recover, no clean store.");
}
+std::string InitialStatusMap::getFirstConfigStr() const {
+ assert(!firstConfig.empty());
+ return encodeMemberSet(firstConfig);
+}
}} // namespace qpid::cluster