bool ReplSetConfig::containsArbiter() const { for (MemberIterator mem = membersBegin(); mem != membersEnd(); mem++) { if (mem->isArbiter()) { return true; } } return false; }
int ReplicaSetConfig::_calculatePriorityRank(int priority) const { int count = 0; for (MemberIterator mem = membersBegin(); mem != membersEnd(); mem++) { if (mem->getPriority() > priority) { count++; } } return count; }
BSONObj ReplicaSetConfig::toBSON() const { BSONObjBuilder configBuilder; configBuilder.append(kIdFieldName, _replSetName); configBuilder.appendIntOrLL(kVersionFieldName, _version); if (_configServer) { // Only include "configsvr" field if true configBuilder.append(kConfigServerFieldName, _configServer); } if (_protocolVersion > 0) { configBuilder.append(kProtocolVersionFieldName, _protocolVersion); } 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(kHeartbeatIntervalFieldName, durationCount<Milliseconds>(_heartbeatInterval)); settingsBuilder.appendIntOrLL(kHeartbeatTimeoutFieldName, durationCount<Seconds>(_heartbeatTimeoutPeriod)); settingsBuilder.appendIntOrLL(kElectionTimeoutFieldName, durationCount<Milliseconds>(_electionTimeoutPeriod)); 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.done(); return configBuilder.obj(); }
int ReplicaSetConfig::getVoterPosition(int memberIdx) const { int pos = 0; int idx = 0; for (auto mem = membersBegin(); mem != membersEnd(); ++mem) { if (idx == memberIdx) { break; } if (mem->isVoter()) { pos++; } idx++; } return pos; }
Status ReplSetConfig::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 (_heartbeatInterval < Milliseconds(0)) { return Status(ErrorCodes::BadValue, str::stream() << kSettingsFieldName << '.' << kHeartbeatIntervalFieldName << " field value must be non-negative, " "but found " << durationCount<Milliseconds>(_heartbeatInterval)); } 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); } 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()); } 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 (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 (_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 != 1) { return Status(ErrorCodes::BadValue, str::stream() << kProtocolVersionFieldName << " field value of " << _protocolVersion << " is not 1 or 0"); } if (_configServer) { if (_protocolVersion == 0) { return Status(ErrorCodes::BadValue, "Config servers cannot run in protocolVersion 0"); } if (arbiterCount > 0) { return Status(ErrorCodes::BadValue, "Arbiters are not allowed in replica set configurations being used for " "config servers"); } for (MemberIterator mem = membersBegin(); mem != membersEnd(); mem++) { if (!mem->shouldBuildIndexes()) { return Status(ErrorCodes::BadValue, "Members in replica set configurations being used for config " "servers must build indexes"); } if (mem->getSlaveDelay() != Seconds(0)) { return Status(ErrorCodes::BadValue, "Members in replica set configurations being used for config " "servers cannot have a non-zero slaveDelay"); } } if (serverGlobalParams.clusterRole != ClusterRole::ConfigServer && !skipShardingConfigurationChecks) { return Status(ErrorCodes::BadValue, "Nodes being used for config servers must be started with the " "--configsvr flag"); } if (!_writeConcernMajorityJournalDefault) { return Status(ErrorCodes::BadValue, str::stream() << kWriteConcernMajorityJournalDefaultFieldName << " must be true in replica set configurations being " "used for config servers"); } } else if (serverGlobalParams.clusterRole == ClusterRole::ConfigServer) { return Status(ErrorCodes::BadValue, "Nodes started with the --configsvr flag must have configsvr:true in " "their config"); } if (!_connectionString.isValid()) { return Status(ErrorCodes::BadValue, "ReplSetConfig represented an invalid replica set ConnectionString"); } return Status::OK(); }