diff options
| author | Alan Conway <aconway@apache.org> | 2010-01-27 20:56:31 +0000 |
|---|---|---|
| committer | Alan Conway <aconway@apache.org> | 2010-01-27 20:56:31 +0000 |
| commit | d1c4af32b27b6d242d2b15e4dc91152a6d3e4a5a (patch) | |
| tree | 68ae4c033fcf4f36c19966bf474c9ebdafd40fdf /cpp/src/qpid/cluster/InitialStatusMap.cpp | |
| parent | 1e24432f3f0333890334648d808410fb3e9535cd (diff) | |
| download | qpid-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.cpp | 25 |
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(), ¬Initialized) == 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 |
