diff options
Diffstat (limited to 'src/mongo/db/repl/replica_set_config.cpp')
-rw-r--r-- | src/mongo/db/repl/replica_set_config.cpp | 919 |
1 files changed, 449 insertions, 470 deletions
diff --git a/src/mongo/db/repl/replica_set_config.cpp b/src/mongo/db/repl/replica_set_config.cpp index ab901fe5886..eef500a2328 100644 --- a/src/mongo/db/repl/replica_set_config.cpp +++ b/src/mongo/db/repl/replica_set_config.cpp @@ -41,542 +41,521 @@ namespace mongo { namespace repl { #ifndef _MSC_VER - const size_t ReplicaSetConfig::kMaxMembers; - const size_t ReplicaSetConfig::kMaxVotingMembers; +const size_t ReplicaSetConfig::kMaxMembers; +const size_t ReplicaSetConfig::kMaxVotingMembers; #endif - const std::string ReplicaSetConfig::kVersionFieldName = "version"; - const std::string ReplicaSetConfig::kMajorityWriteConcernModeName = "$majority"; - const Seconds ReplicaSetConfig::kDefaultHeartbeatTimeoutPeriod(10); +const std::string ReplicaSetConfig::kVersionFieldName = "version"; +const std::string ReplicaSetConfig::kMajorityWriteConcernModeName = "$majority"; +const Seconds ReplicaSetConfig::kDefaultHeartbeatTimeoutPeriod(10); namespace { - const std::string kIdFieldName = "_id"; - const std::string kMembersFieldName = "members"; - const std::string kSettingsFieldName = "settings"; - const std::string kStepDownCheckWriteConcernModeName = "$stepDownCheck"; - const std::string kProtocolVersionFieldName = "protocolVersion"; - - const std::string kLegalConfigTopFieldNames[] = { - kIdFieldName, - ReplicaSetConfig::kVersionFieldName, - kMembersFieldName, - kSettingsFieldName, - kProtocolVersionFieldName - }; - - const std::string kHeartbeatTimeoutFieldName = "heartbeatTimeoutSecs"; - const std::string kChainingAllowedFieldName = "chainingAllowed"; - const std::string kGetLastErrorDefaultsFieldName = "getLastErrorDefaults"; - const std::string kGetLastErrorModesFieldName = "getLastErrorModes"; +const std::string kIdFieldName = "_id"; +const std::string kMembersFieldName = "members"; +const std::string kSettingsFieldName = "settings"; +const std::string kStepDownCheckWriteConcernModeName = "$stepDownCheck"; +const std::string kProtocolVersionFieldName = "protocolVersion"; -} // namespace - - ReplicaSetConfig::ReplicaSetConfig() : _isInitialized(false), - _heartbeatTimeoutPeriod(0), - _protocolVersion(0) {} - - Status ReplicaSetConfig::initialize(const BSONObj& cfg) { - _isInitialized = false; - _members.clear(); - Status status = bsonCheckOnlyHasFields( - "replica set configuration", cfg, kLegalConfigTopFieldNames); - if (!status.isOK()) - return status; - - // - // Parse replSetName - // - status = bsonExtractStringField(cfg, kIdFieldName, &_replSetName); - if (!status.isOK()) - return status; +const std::string kLegalConfigTopFieldNames[] = {kIdFieldName, + ReplicaSetConfig::kVersionFieldName, + kMembersFieldName, + kSettingsFieldName, + kProtocolVersionFieldName}; - // - // Parse version - // - status = bsonExtractIntegerField(cfg, kVersionFieldName, &_version); - if (!status.isOK()) - return status; +const std::string kHeartbeatTimeoutFieldName = "heartbeatTimeoutSecs"; +const std::string kChainingAllowedFieldName = "chainingAllowed"; +const std::string kGetLastErrorDefaultsFieldName = "getLastErrorDefaults"; +const std::string kGetLastErrorModesFieldName = "getLastErrorModes"; - // - // Parse members - // - BSONElement membersElement; - status = bsonExtractTypedField(cfg, kMembersFieldName, Array, &membersElement); - if (!status.isOK()) - return status; - - for (BSONObj::iterator membersIterator(membersElement.Obj()); membersIterator.more();) { - BSONElement memberElement = membersIterator.next(); - if (memberElement.type() != Object) { - return Status(ErrorCodes::TypeMismatch, str::stream() << - "Expected type of " << kMembersFieldName << "." << - memberElement.fieldName() << " to be Object, but found " << - typeName(memberElement.type())); - } - _members.resize(_members.size() + 1); - status = _members.back().initialize(memberElement.Obj(), &_tagConfig); - if (!status.isOK()) - return status; - } +} // namespace - // - // Parse settings - // - BSONElement settingsElement; - status = bsonExtractTypedField(cfg, kSettingsFieldName, Object, &settingsElement); - BSONObj settings; - if (status.isOK()) { - settings = settingsElement.Obj(); - } - else if (status != ErrorCodes::NoSuchKey) { - return status; - } - status = _parseSettingsSubdocument(settings); +ReplicaSetConfig::ReplicaSetConfig() + : _isInitialized(false), _heartbeatTimeoutPeriod(0), _protocolVersion(0) {} + +Status ReplicaSetConfig::initialize(const BSONObj& cfg) { + _isInitialized = false; + _members.clear(); + Status status = + bsonCheckOnlyHasFields("replica set configuration", cfg, kLegalConfigTopFieldNames); + if (!status.isOK()) + return status; + + // + // Parse replSetName + // + status = bsonExtractStringField(cfg, kIdFieldName, &_replSetName); + if (!status.isOK()) + return status; + + // + // Parse version + // + status = bsonExtractIntegerField(cfg, kVersionFieldName, &_version); + if (!status.isOK()) + return status; + + // + // Parse members + // + BSONElement membersElement; + status = bsonExtractTypedField(cfg, kMembersFieldName, Array, &membersElement); + if (!status.isOK()) + return status; + + for (BSONObj::iterator membersIterator(membersElement.Obj()); membersIterator.more();) { + BSONElement memberElement = membersIterator.next(); + if (memberElement.type() != Object) { + return Status(ErrorCodes::TypeMismatch, + str::stream() << "Expected type of " << kMembersFieldName << "." + << memberElement.fieldName() << " to be Object, but found " + << typeName(memberElement.type())); + } + _members.resize(_members.size() + 1); + status = _members.back().initialize(memberElement.Obj(), &_tagConfig); if (!status.isOK()) return status; + } - // - // Parse protocol version - // - BSONElement protocolVersionElement; - status = bsonExtractIntegerField(cfg, kProtocolVersionFieldName, &_protocolVersion); - if (!status.isOK() && status != ErrorCodes::NoSuchKey) { - return status; - } - - _calculateMajorities(); - _addInternalWriteConcernModes(); - _isInitialized = true; - return Status::OK(); + // + // Parse settings + // + BSONElement settingsElement; + status = bsonExtractTypedField(cfg, kSettingsFieldName, Object, &settingsElement); + BSONObj settings; + if (status.isOK()) { + settings = settingsElement.Obj(); + } else if (status != ErrorCodes::NoSuchKey) { + return status; + } + status = _parseSettingsSubdocument(settings); + if (!status.isOK()) + return status; + + // + // Parse protocol version + // + BSONElement protocolVersionElement; + status = bsonExtractIntegerField(cfg, kProtocolVersionFieldName, &_protocolVersion); + if (!status.isOK() && status != ErrorCodes::NoSuchKey) { + return status; } - Status ReplicaSetConfig::_parseSettingsSubdocument(const BSONObj& settings) { - // - // Parse heartbeatTimeoutSecs - // - BSONElement hbTimeoutSecsElement = settings[kHeartbeatTimeoutFieldName]; - if (hbTimeoutSecsElement.eoo()) { - _heartbeatTimeoutPeriod = Seconds(kDefaultHeartbeatTimeoutPeriod); - } - else if (hbTimeoutSecsElement.isNumber()) { - _heartbeatTimeoutPeriod = Seconds(hbTimeoutSecsElement.numberInt()); - } - else { - return Status(ErrorCodes::TypeMismatch, str::stream() << "Expected type of " << - kSettingsFieldName << "." << kHeartbeatTimeoutFieldName << - " to be a number, but found a value of type " << - typeName(hbTimeoutSecsElement.type())); - } + _calculateMajorities(); + _addInternalWriteConcernModes(); + _isInitialized = true; + return Status::OK(); +} + +Status ReplicaSetConfig::_parseSettingsSubdocument(const BSONObj& settings) { + // + // Parse heartbeatTimeoutSecs + // + BSONElement hbTimeoutSecsElement = settings[kHeartbeatTimeoutFieldName]; + if (hbTimeoutSecsElement.eoo()) { + _heartbeatTimeoutPeriod = Seconds(kDefaultHeartbeatTimeoutPeriod); + } else if (hbTimeoutSecsElement.isNumber()) { + _heartbeatTimeoutPeriod = Seconds(hbTimeoutSecsElement.numberInt()); + } else { + return Status(ErrorCodes::TypeMismatch, + str::stream() << "Expected type of " << kSettingsFieldName << "." + << kHeartbeatTimeoutFieldName + << " to be a number, but found a value of type " + << typeName(hbTimeoutSecsElement.type())); + } - // - // Parse chainingAllowed - // - Status status = bsonExtractBooleanFieldWithDefault(settings, - kChainingAllowedFieldName, - true, - &_chainingAllowed); + // + // Parse chainingAllowed + // + Status status = bsonExtractBooleanFieldWithDefault( + settings, kChainingAllowedFieldName, true, &_chainingAllowed); + if (!status.isOK()) + return status; + + // + // Parse getLastErrorDefaults + // + BSONElement gleDefaultsElement; + status = bsonExtractTypedField( + settings, kGetLastErrorDefaultsFieldName, Object, &gleDefaultsElement); + if (status.isOK()) { + status = _defaultWriteConcern.parse(gleDefaultsElement.Obj()); if (!status.isOK()) return status; + } else if (status == ErrorCodes::NoSuchKey) { + // Default write concern is w: 1. + _defaultWriteConcern.reset(); + _defaultWriteConcern.wNumNodes = 1; + } else { + return status; + } - // - // Parse getLastErrorDefaults - // - BSONElement gleDefaultsElement; - status = bsonExtractTypedField(settings, - kGetLastErrorDefaultsFieldName, - Object, - &gleDefaultsElement); - if (status.isOK()) { - status = _defaultWriteConcern.parse(gleDefaultsElement.Obj()); - if (!status.isOK()) - return status; - } - else if (status == ErrorCodes::NoSuchKey) { - // Default write concern is w: 1. - _defaultWriteConcern.reset(); - _defaultWriteConcern.wNumNodes = 1; - } - else { - return status; - } + // + // Parse getLastErrorModes + // + BSONElement gleModesElement; + status = bsonExtractTypedField(settings, kGetLastErrorModesFieldName, Object, &gleModesElement); + BSONObj gleModes; + if (status.isOK()) { + gleModes = gleModesElement.Obj(); + } else if (status != ErrorCodes::NoSuchKey) { + return status; + } - // - // Parse getLastErrorModes - // - BSONElement gleModesElement; - status = bsonExtractTypedField(settings, - kGetLastErrorModesFieldName, - Object, - &gleModesElement); - BSONObj gleModes; - if (status.isOK()) { - gleModes = gleModesElement.Obj(); - } - else if (status != ErrorCodes::NoSuchKey) { - return status; + for (BSONObj::iterator gleModeIter(gleModes); gleModeIter.more();) { + const BSONElement modeElement = gleModeIter.next(); + if (_customWriteConcernModes.find(modeElement.fieldNameStringData()) != + _customWriteConcernModes.end()) { + return Status(ErrorCodes::DuplicateKey, + str::stream() << kSettingsFieldName << '.' << kGetLastErrorModesFieldName + << " contains multiple fields named " + << modeElement.fieldName()); + } + if (modeElement.type() != Object) { + return Status(ErrorCodes::TypeMismatch, + str::stream() << "Expected " << kSettingsFieldName << '.' + << kGetLastErrorModesFieldName << '.' + << modeElement.fieldName() << " to be an Object, not " + << typeName(modeElement.type())); } - - for (BSONObj::iterator gleModeIter(gleModes); gleModeIter.more();) { - const BSONElement modeElement = gleModeIter.next(); - if (_customWriteConcernModes.find(modeElement.fieldNameStringData()) != - _customWriteConcernModes.end()) { - - return Status(ErrorCodes::DuplicateKey, str::stream() << kSettingsFieldName << - '.' << kGetLastErrorModesFieldName << - " contains multiple fields named " << modeElement.fieldName()); + ReplicaSetTagPattern pattern = _tagConfig.makePattern(); + for (BSONObj::iterator constraintIter(modeElement.Obj()); constraintIter.more();) { + const BSONElement constraintElement = constraintIter.next(); + if (!constraintElement.isNumber()) { + return Status(ErrorCodes::TypeMismatch, + str::stream() + << "Expected " << kSettingsFieldName << '.' + << kGetLastErrorModesFieldName << '.' << modeElement.fieldName() + << '.' << constraintElement.fieldName() << " to be a number, not " + << typeName(constraintElement.type())); } - if (modeElement.type() != Object) { - return Status(ErrorCodes::TypeMismatch, str::stream() << "Expected " << - kSettingsFieldName << '.' << kGetLastErrorModesFieldName << '.' << - modeElement.fieldName() << " to be an Object, not " << - typeName(modeElement.type())); + const int minCount = constraintElement.numberInt(); + if (minCount <= 0) { + return Status(ErrorCodes::BadValue, + str::stream() << "Value of " << kSettingsFieldName << '.' + << kGetLastErrorModesFieldName << '.' + << modeElement.fieldName() << '.' + << constraintElement.fieldName() + << " must be positive, but found " << minCount); } - ReplicaSetTagPattern pattern = _tagConfig.makePattern(); - for (BSONObj::iterator constraintIter(modeElement.Obj()); constraintIter.more();) { - const BSONElement constraintElement = constraintIter.next(); - if (!constraintElement.isNumber()) { - return Status(ErrorCodes::TypeMismatch, str::stream() << "Expected " << - kSettingsFieldName << '.' << kGetLastErrorModesFieldName << '.' << - modeElement.fieldName() << '.' << constraintElement.fieldName() << - " to be a number, not " << typeName(constraintElement.type())); - } - const int minCount = constraintElement.numberInt(); - if (minCount <= 0) { - return Status(ErrorCodes::BadValue, str::stream() << "Value of " << - kSettingsFieldName << '.' << kGetLastErrorModesFieldName << '.' << - modeElement.fieldName() << '.' << constraintElement.fieldName() << - " must be positive, but found " << minCount); - } - status = _tagConfig.addTagCountConstraintToPattern( - &pattern, - constraintElement.fieldNameStringData(), - minCount); - if (!status.isOK()) { - return status; - } + status = _tagConfig.addTagCountConstraintToPattern( + &pattern, constraintElement.fieldNameStringData(), minCount); + if (!status.isOK()) { + return status; } - _customWriteConcernModes[modeElement.fieldNameStringData()] = pattern; } - return Status::OK(); + _customWriteConcernModes[modeElement.fieldNameStringData()] = pattern; + } + return Status::OK(); +} + +Status ReplicaSetConfig::validate() const { + if (_version <= 0 || _version > std::numeric_limits<int>::max()) { + return Status(ErrorCodes::BadValue, + str::stream() << kVersionFieldName << " field value of " << _version + << " is out of range"); + } + if (_replSetName.empty()) { + return Status(ErrorCodes::BadValue, + str::stream() << "Replica set configuration must have non-empty " + << kIdFieldName << " field"); + } + if (_heartbeatTimeoutPeriod < Seconds(0)) { + return Status(ErrorCodes::BadValue, + str::stream() << kSettingsFieldName << '.' << kHeartbeatTimeoutFieldName + << " field value must be non-negative, " + "but found " << _heartbeatTimeoutPeriod.count()); + } + if (_members.size() > kMaxMembers || _members.empty()) { + return Status(ErrorCodes::BadValue, + str::stream() << "Replica set configuration contains " << _members.size() + << " members, but must have at least 1 and no more than " + << kMaxMembers); } - Status ReplicaSetConfig::validate() const { - if (_version <= 0 || _version > std::numeric_limits<int>::max()) { - return Status(ErrorCodes::BadValue, str::stream() << kVersionFieldName << - " field value of " << _version << " is out of range"); - } - if (_replSetName.empty()) { - return Status(ErrorCodes::BadValue, str::stream() << - "Replica set configuration must have non-empty " << kIdFieldName << - " field"); + size_t localhostCount = 0; + size_t voterCount = 0; + size_t arbiterCount = 0; + size_t electableCount = 0; + for (size_t i = 0; i < _members.size(); ++i) { + const MemberConfig& memberI = _members[i]; + Status status = memberI.validate(); + if (!status.isOK()) + return status; + if (memberI.getHostAndPort().isLocalHost()) { + ++localhostCount; } - if (_heartbeatTimeoutPeriod < Seconds(0)) { - return Status(ErrorCodes::BadValue, str::stream() << kSettingsFieldName << '.' << - kHeartbeatTimeoutFieldName << " field value must be non-negative, " - "but found " << _heartbeatTimeoutPeriod.count()); + if (memberI.isVoter()) { + ++voterCount; } - if (_members.size() > kMaxMembers || _members.empty()) { - return Status(ErrorCodes::BadValue, str::stream() << - "Replica set configuration contains " << _members.size() << - " members, but must have at least 1 and no more than " << kMaxMembers); + // Nodes may be arbiters or electable, or neither, but never both. + if (memberI.isArbiter()) { + ++arbiterCount; + } else if (memberI.getPriority() > 0) { + ++electableCount; } - - size_t localhostCount = 0; - size_t voterCount = 0; - size_t arbiterCount = 0; - size_t electableCount = 0; - for (size_t i = 0; i < _members.size(); ++i) { - const MemberConfig& memberI = _members[i]; - Status status = memberI.validate(); - if (!status.isOK()) - return status; - if (memberI.getHostAndPort().isLocalHost()) { - ++localhostCount; - } - if (memberI.isVoter()) { - ++voterCount; - } - // Nodes may be arbiters or electable, or neither, but never both. - if (memberI.isArbiter()) { - ++arbiterCount; - } - else if (memberI.getPriority() > 0) { - ++electableCount; + for (size_t j = 0; j < _members.size(); ++j) { + if (i == j) + continue; + const MemberConfig& memberJ = _members[j]; + if (memberI.getId() == memberJ.getId()) { + return Status(ErrorCodes::BadValue, + str::stream() + << "Found two member configurations with same " + << MemberConfig::kIdFieldName << " field, " << kMembersFieldName + << "." << i << "." << MemberConfig::kIdFieldName + << " == " << kMembersFieldName << "." << j << "." + << MemberConfig::kIdFieldName << " == " << memberI.getId()); } - for (size_t j = 0; j < _members.size(); ++j) { - if (i == j) - continue; - const MemberConfig& memberJ = _members[j]; - if (memberI.getId() == memberJ.getId()) { - return Status( - ErrorCodes::BadValue, str::stream() << - "Found two member configurations with same " << - MemberConfig::kIdFieldName << " field, " << - kMembersFieldName << "." << i << "." << MemberConfig::kIdFieldName << - " == " << - kMembersFieldName << "." << j << "." << MemberConfig::kIdFieldName << - " == " << memberI.getId()); - } - if (memberI.getHostAndPort() == memberJ.getHostAndPort()) { - return Status( - ErrorCodes::BadValue, str::stream() << - "Found two member configurations with same " << - MemberConfig::kHostFieldName << " field, " << - kMembersFieldName << "." << i << "." << MemberConfig::kHostFieldName << - " == " << - kMembersFieldName << "." << j << "." << MemberConfig::kHostFieldName << - " == " << memberI.getHostAndPort().toString()); - } + if (memberI.getHostAndPort() == memberJ.getHostAndPort()) { + return Status(ErrorCodes::BadValue, + str::stream() << "Found two member configurations with same " + << MemberConfig::kHostFieldName << " field, " + << kMembersFieldName << "." << i << "." + << MemberConfig::kHostFieldName + << " == " << kMembersFieldName << "." << j << "." + << MemberConfig::kHostFieldName + << " == " << memberI.getHostAndPort().toString()); } } + } - if (localhostCount != 0 && localhostCount != _members.size()) { - return Status(ErrorCodes::BadValue, str::stream() << - "Either all host names in a replica set configuration must be localhost " - "references, or none must be; found " << localhostCount << " out of " << - _members.size()); - } + if (localhostCount != 0 && localhostCount != _members.size()) { + return Status( + ErrorCodes::BadValue, + str::stream() + << "Either all host names in a replica set configuration must be localhost " + "references, or none must be; found " << localhostCount << " out of " + << _members.size()); + } - if (voterCount > kMaxVotingMembers || voterCount == 0) { - return Status(ErrorCodes::BadValue, str::stream() << - "Replica set configuration contains " << voterCount << - " voting members, but must be at least 1 and no more than " << - kMaxVotingMembers); - } + if (voterCount > kMaxVotingMembers || voterCount == 0) { + return Status(ErrorCodes::BadValue, + str::stream() << "Replica set configuration contains " << voterCount + << " voting members, but must be at least 1 and no more than " + << kMaxVotingMembers); + } - if (electableCount == 0) { - return Status(ErrorCodes::BadValue, "Replica set configuration must contain at least " - "one non-arbiter member with priority > 0"); - } + if (electableCount == 0) { + return Status(ErrorCodes::BadValue, + "Replica set configuration must contain at least " + "one non-arbiter member with priority > 0"); + } - // TODO(schwerin): Validate satisfiability of write modes? Omitting for backwards - // compatibility. - if (_defaultWriteConcern.wMode.empty()) { - if (_defaultWriteConcern.wNumNodes == 0) { - return Status(ErrorCodes::BadValue, - "Default write concern mode must wait for at least 1 member"); - } + // TODO(schwerin): Validate satisfiability of write modes? Omitting for backwards + // compatibility. + if (_defaultWriteConcern.wMode.empty()) { + if (_defaultWriteConcern.wNumNodes == 0) { + return Status(ErrorCodes::BadValue, + "Default write concern mode must wait for at least 1 member"); } - else { - if (WriteConcernOptions::kMajority != _defaultWriteConcern.wMode && - !findCustomWriteMode(_defaultWriteConcern.wMode).isOK()) { - return Status(ErrorCodes::BadValue, str::stream() << - "Default write concern requires undefined write mode " << - _defaultWriteConcern.wMode); - } - } - - if (_protocolVersion < 0 || _protocolVersion > std::numeric_limits<int>::max()) { - return Status(ErrorCodes::BadValue, str::stream() << kProtocolVersionFieldName << - " field value of " << _protocolVersion << " is out of range"); + } else { + if (WriteConcernOptions::kMajority != _defaultWriteConcern.wMode && + !findCustomWriteMode(_defaultWriteConcern.wMode).isOK()) { + return Status(ErrorCodes::BadValue, + str::stream() << "Default write concern requires undefined write mode " + << _defaultWriteConcern.wMode); } - - return Status::OK(); } - Status ReplicaSetConfig::checkIfWriteConcernCanBeSatisfied( - const WriteConcernOptions& writeConcern) const { - if (!writeConcern.wMode.empty() && writeConcern.wMode != WriteConcernOptions::kMajority) { - StatusWith<ReplicaSetTagPattern> tagPatternStatus = - findCustomWriteMode(writeConcern.wMode); - if (!tagPatternStatus.isOK()) { - return tagPatternStatus.getStatus(); - } + if (_protocolVersion < 0 || _protocolVersion > std::numeric_limits<int>::max()) { + return Status(ErrorCodes::BadValue, + str::stream() << kProtocolVersionFieldName << " field value of " + << _protocolVersion << " is out of range"); + } - ReplicaSetTagMatch matcher(tagPatternStatus.getValue()); - for (size_t j = 0; j < _members.size(); ++j) { - const MemberConfig& memberConfig = _members[j]; - for (MemberConfig::TagIterator it = memberConfig.tagsBegin(); - it != memberConfig.tagsEnd(); ++it) { - if (matcher.update(*it)) { - return Status::OK(); - } + return Status::OK(); +} + +Status ReplicaSetConfig::checkIfWriteConcernCanBeSatisfied( + const WriteConcernOptions& writeConcern) const { + if (!writeConcern.wMode.empty() && writeConcern.wMode != WriteConcernOptions::kMajority) { + StatusWith<ReplicaSetTagPattern> tagPatternStatus = findCustomWriteMode(writeConcern.wMode); + if (!tagPatternStatus.isOK()) { + return tagPatternStatus.getStatus(); + } + + ReplicaSetTagMatch matcher(tagPatternStatus.getValue()); + for (size_t j = 0; j < _members.size(); ++j) { + const MemberConfig& memberConfig = _members[j]; + for (MemberConfig::TagIterator it = memberConfig.tagsBegin(); + it != memberConfig.tagsEnd(); + ++it) { + if (matcher.update(*it)) { + return Status::OK(); } } - // Even if all the nodes in the set had a given write it still would not satisfy this - // write concern mode. - return Status(ErrorCodes::CannotSatisfyWriteConcern, - str::stream() << "Not enough nodes match write concern mode \"" - << writeConcern.wMode << "\""); } - else { - int nodesRemaining = writeConcern.wNumNodes; - for (size_t j = 0; j < _members.size(); ++j) { - if (!_members[j].isArbiter()) { // Only count data-bearing nodes - --nodesRemaining; - if (nodesRemaining <= 0) { - return Status::OK(); - } + // Even if all the nodes in the set had a given write it still would not satisfy this + // write concern mode. + return Status(ErrorCodes::CannotSatisfyWriteConcern, + str::stream() << "Not enough nodes match write concern mode \"" + << writeConcern.wMode << "\""); + } else { + int nodesRemaining = writeConcern.wNumNodes; + for (size_t j = 0; j < _members.size(); ++j) { + if (!_members[j].isArbiter()) { // Only count data-bearing nodes + --nodesRemaining; + if (nodesRemaining <= 0) { + return Status::OK(); } } - return Status(ErrorCodes::CannotSatisfyWriteConcern, "Not enough data-bearing nodes"); } + return Status(ErrorCodes::CannotSatisfyWriteConcern, "Not enough data-bearing nodes"); } +} - const MemberConfig& ReplicaSetConfig::getMemberAt(size_t i) const { - invariant(i < _members.size()); - return _members[i]; - } +const MemberConfig& ReplicaSetConfig::getMemberAt(size_t i) const { + invariant(i < _members.size()); + return _members[i]; +} - const MemberConfig* ReplicaSetConfig::findMemberByID(int id) const { - for (std::vector<MemberConfig>::const_iterator it = _members.begin(); - it != _members.end(); ++it) { - if (it->getId() == id) { - return &(*it); - } +const MemberConfig* ReplicaSetConfig::findMemberByID(int id) const { + for (std::vector<MemberConfig>::const_iterator it = _members.begin(); it != _members.end(); + ++it) { + if (it->getId() == id) { + return &(*it); } - return NULL; } + return NULL; +} - const int ReplicaSetConfig::findMemberIndexByHostAndPort(const HostAndPort& hap) const { - int x = 0; - for (std::vector<MemberConfig>::const_iterator it = _members.begin(); - it != _members.end(); ++it) { - - if (it->getHostAndPort() == hap) { - return x; - } - ++x; +const int ReplicaSetConfig::findMemberIndexByHostAndPort(const HostAndPort& hap) const { + int x = 0; + for (std::vector<MemberConfig>::const_iterator it = _members.begin(); it != _members.end(); + ++it) { + if (it->getHostAndPort() == hap) { + return x; } - return -1; + ++x; } + return -1; +} - const int ReplicaSetConfig::findMemberIndexByConfigId(long long configId) const { - int x = 0; - for (const auto& member : _members) { - - if (member.getId() == configId) { - return x; - } - ++x; +const int ReplicaSetConfig::findMemberIndexByConfigId(long long configId) const { + int x = 0; + for (const auto& member : _members) { + if (member.getId() == configId) { + return x; } - return -1; + ++x; } - - const MemberConfig* ReplicaSetConfig::findMemberByHostAndPort(const HostAndPort& hap) const { - int idx = findMemberIndexByHostAndPort(hap); - return idx != -1 ? &getMemberAt(idx) : NULL; + return -1; +} + +const MemberConfig* ReplicaSetConfig::findMemberByHostAndPort(const HostAndPort& hap) const { + int idx = findMemberIndexByHostAndPort(hap); + return idx != -1 ? &getMemberAt(idx) : NULL; +} + +ReplicaSetTag ReplicaSetConfig::findTag(StringData key, StringData value) const { + return _tagConfig.findTag(key, value); +} + +StatusWith<ReplicaSetTagPattern> ReplicaSetConfig::findCustomWriteMode( + StringData patternName) const { + const StringMap<ReplicaSetTagPattern>::const_iterator iter = + _customWriteConcernModes.find(patternName); + if (iter == _customWriteConcernModes.end()) { + return StatusWith<ReplicaSetTagPattern>( + ErrorCodes::UnknownReplWriteConcern, + str::stream() << "No write concern mode named '" << escape(patternName.toString()) + << "' found in replica set configuration"); } - - ReplicaSetTag ReplicaSetConfig::findTag(StringData key, StringData value) const { - return _tagConfig.findTag(key, value); + return StatusWith<ReplicaSetTagPattern>(iter->second); +} + +void ReplicaSetConfig::_calculateMajorities() { + const int voters = std::count_if(_members.begin(), + _members.end(), + stdx::bind(&MemberConfig::isVoter, stdx::placeholders::_1)); + const int arbiters = + std::count_if(_members.begin(), + _members.end(), + stdx::bind(&MemberConfig::isArbiter, stdx::placeholders::_1)); + _totalVotingMembers = voters; + _majorityVoteCount = voters / 2 + 1; + _writeMajority = std::min(_majorityVoteCount, voters - arbiters); +} + +void ReplicaSetConfig::_addInternalWriteConcernModes() { + // $majority: the majority of voting nodes or all non-arbiter voting nodes if + // the majority of voting nodes are arbiters. + ReplicaSetTagPattern pattern = _tagConfig.makePattern(); + + Status status = _tagConfig.addTagCountConstraintToPattern( + &pattern, MemberConfig::kInternalVoterTagName, _writeMajority); + + if (status.isOK()) { + _customWriteConcernModes[kMajorityWriteConcernModeName] = pattern; + } else if (status != ErrorCodes::NoSuchKey) { + // NoSuchKey means we have no $voter-tagged nodes in this config; + // other errors are unexpected. + fassert(28693, status); } - StatusWith<ReplicaSetTagPattern> ReplicaSetConfig::findCustomWriteMode( - StringData patternName) const { - - const StringMap<ReplicaSetTagPattern>::const_iterator iter = _customWriteConcernModes.find( - patternName); - if (iter == _customWriteConcernModes.end()) { - return StatusWith<ReplicaSetTagPattern>( - ErrorCodes::UnknownReplWriteConcern, - str::stream() << - "No write concern mode named '" << escape(patternName.toString()) << - "' found in replica set configuration"); - } - return StatusWith<ReplicaSetTagPattern>(iter->second); + // $stepDownCheck: one electable node plus ourselves + pattern = _tagConfig.makePattern(); + status = _tagConfig.addTagCountConstraintToPattern( + &pattern, MemberConfig::kInternalElectableTagName, 2); + if (status.isOK()) { + _customWriteConcernModes[kStepDownCheckWriteConcernModeName] = pattern; + } else if (status != ErrorCodes::NoSuchKey) { + // NoSuchKey means we have no $electable-tagged nodes in this config; + // other errors are unexpected + fassert(28694, status); } +} - void ReplicaSetConfig::_calculateMajorities() { - const int voters = std::count_if( - _members.begin(), - _members.end(), - stdx::bind(&MemberConfig::isVoter, stdx::placeholders::_1)); - const int arbiters = std::count_if( - _members.begin(), - _members.end(), - stdx::bind(&MemberConfig::isArbiter, stdx::placeholders::_1)); - _totalVotingMembers = voters; - _majorityVoteCount = voters / 2 + 1; - _writeMajority = std::min(_majorityVoteCount, voters - arbiters); - } - - void ReplicaSetConfig::_addInternalWriteConcernModes() { - // $majority: the majority of voting nodes or all non-arbiter voting nodes if - // the majority of voting nodes are arbiters. - ReplicaSetTagPattern pattern = _tagConfig.makePattern(); - - Status status = _tagConfig.addTagCountConstraintToPattern( - &pattern, - MemberConfig::kInternalVoterTagName, - _writeMajority); - - if (status.isOK()) { - _customWriteConcernModes[kMajorityWriteConcernModeName] = pattern; - } - else if (status != ErrorCodes::NoSuchKey) { - // NoSuchKey means we have no $voter-tagged nodes in this config; - // other errors are unexpected. - fassert(28693, status); - } +BSONObj ReplicaSetConfig::toBSON() const { + BSONObjBuilder configBuilder; + configBuilder.append(kIdFieldName, _replSetName); + configBuilder.appendIntOrLL(kVersionFieldName, _version); - // $stepDownCheck: one electable node plus ourselves - pattern = _tagConfig.makePattern(); - status = _tagConfig.addTagCountConstraintToPattern(&pattern, - MemberConfig::kInternalElectableTagName, - 2); - if (status.isOK()) { - _customWriteConcernModes[kStepDownCheckWriteConcernModeName] = pattern; - } - else if (status != ErrorCodes::NoSuchKey) { - // NoSuchKey means we have no $electable-tagged nodes in this config; - // other errors are unexpected - fassert(28694, status); - } + BSONArrayBuilder members(configBuilder.subarrayStart(kMembersFieldName)); + for (MemberIterator mem = membersBegin(); mem != membersEnd(); mem++) { + members.append(mem->toBSON(getTagConfig())); } - - BSONObj ReplicaSetConfig::toBSON() const { - BSONObjBuilder configBuilder; - configBuilder.append(kIdFieldName, _replSetName); - configBuilder.appendIntOrLL(kVersionFieldName, _version); - - BSONArrayBuilder members(configBuilder.subarrayStart(kMembersFieldName)); - for (MemberIterator mem = membersBegin(); mem != membersEnd(); mem++) { - members.append(mem->toBSON(getTagConfig())); - } - members.done(); - - BSONObjBuilder settingsBuilder(configBuilder.subobjStart(kSettingsFieldName)); - settingsBuilder.append(kChainingAllowedFieldName, _chainingAllowed); - settingsBuilder.appendIntOrLL(kHeartbeatTimeoutFieldName, _heartbeatTimeoutPeriod.count()); - - BSONObjBuilder gleModes(settingsBuilder.subobjStart(kGetLastErrorModesFieldName)); - for (StringMap<ReplicaSetTagPattern>::const_iterator mode = - _customWriteConcernModes.begin(); - mode != _customWriteConcernModes.end(); - ++mode) { - if (mode->first[0] == '$') { - // Filter out internal modes - continue; - } - BSONObjBuilder modeBuilder(gleModes.subobjStart(mode->first)); - for (ReplicaSetTagPattern::ConstraintIterator itr = mode->second.constraintsBegin(); - itr != mode->second.constraintsEnd(); - itr++) { - modeBuilder.append(_tagConfig.getTagKey(ReplicaSetTag(itr->getKeyIndex(), 0)), - itr->getMinCount()); - } - modeBuilder.done(); - } - gleModes.done(); - - settingsBuilder.append(kGetLastErrorDefaultsFieldName, _defaultWriteConcern.toBSON()); - settingsBuilder.append(kProtocolVersionFieldName, _protocolVersion); - settingsBuilder.done(); - return configBuilder.obj(); + members.done(); + + BSONObjBuilder settingsBuilder(configBuilder.subobjStart(kSettingsFieldName)); + settingsBuilder.append(kChainingAllowedFieldName, _chainingAllowed); + settingsBuilder.appendIntOrLL(kHeartbeatTimeoutFieldName, _heartbeatTimeoutPeriod.count()); + + BSONObjBuilder gleModes(settingsBuilder.subobjStart(kGetLastErrorModesFieldName)); + for (StringMap<ReplicaSetTagPattern>::const_iterator mode = _customWriteConcernModes.begin(); + mode != _customWriteConcernModes.end(); + ++mode) { + if (mode->first[0] == '$') { + // Filter out internal modes + continue; + } + BSONObjBuilder modeBuilder(gleModes.subobjStart(mode->first)); + for (ReplicaSetTagPattern::ConstraintIterator itr = mode->second.constraintsBegin(); + itr != mode->second.constraintsEnd(); + itr++) { + modeBuilder.append(_tagConfig.getTagKey(ReplicaSetTag(itr->getKeyIndex(), 0)), + itr->getMinCount()); + } + modeBuilder.done(); } - - std::vector<std::string> ReplicaSetConfig::getWriteConcernNames() const { - std::vector<std::string> names; - for (StringMap<ReplicaSetTagPattern>::const_iterator mode = - _customWriteConcernModes.begin(); - mode != _customWriteConcernModes.end(); - ++mode) { - names.push_back(mode->first); - } - return names; - } + gleModes.done(); + + settingsBuilder.append(kGetLastErrorDefaultsFieldName, _defaultWriteConcern.toBSON()); + settingsBuilder.append(kProtocolVersionFieldName, _protocolVersion); + settingsBuilder.done(); + return configBuilder.obj(); +} + +std::vector<std::string> ReplicaSetConfig::getWriteConcernNames() const { + std::vector<std::string> names; + for (StringMap<ReplicaSetTagPattern>::const_iterator mode = _customWriteConcernModes.begin(); + mode != _customWriteConcernModes.end(); + ++mode) { + names.push_back(mode->first); + } + return names; +} } // namespace repl } // namespace mongo |