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 MemberConfig::validate() const { if (_id < 0 || _id > 255) { return Status(ErrorCodes::BadValue, str::stream() << kIdFieldName << " field value of " << _id << " is out of range."); } if (_priority < 0 || _priority > 1000) { return Status(ErrorCodes::BadValue, str::stream() << kPriorityFieldName << " field value of " << _priority << " is out of range"); } if (_votes != 0 && _votes != 1) { return Status(ErrorCodes::BadValue, str::stream() << kVotesFieldName << " field value is " << _votes << " but must be 0 or 1"); } if (_arbiterOnly) { if (!_tags.empty()) { return Status(ErrorCodes::BadValue, "Cannot set tags on arbiters."); } if (!isVoter()) { return Status(ErrorCodes::BadValue, "Arbiter must vote (cannot have 0 votes)"); } } if (_slaveDelay < Seconds(0) || _slaveDelay > kMaxSlaveDelay) { return Status(ErrorCodes::BadValue, str::stream() << kSlaveDelayFieldName << " field value of " << durationCount<Seconds>(_slaveDelay) << " seconds is out of range"); } // Check for additional electable requirements, when priority is non zero if (_priority != 0) { if (_votes == 0) { return Status(ErrorCodes::BadValue, "priority must be 0 when non-voting (votes:0)"); } if (_slaveDelay > Seconds(0)) { return Status(ErrorCodes::BadValue, "priority must be 0 when slaveDelay is used"); } if (_hidden) { return Status(ErrorCodes::BadValue, "priority must be 0 when hidden=true"); } if (!_buildIndexes) { return Status(ErrorCodes::BadValue, "priority must be 0 when buildIndexes=false"); } } return Status::OK(); }
VoteRequester::Algorithm::Algorithm(const ReplicaSetConfig& rsConfig, long long candidateId, long long term, OpTime lastOplogEntry) : _rsConfig(rsConfig), _candidateId(candidateId), _term(term), _lastOplogEntry(lastOplogEntry) { // populate targets with all voting members that aren't this node for (auto member = _rsConfig.membersBegin(); member != _rsConfig.membersEnd(); member++) { if (member->isVoter() && member->getId() != candidateId) { _targets.push_back(member->getHostAndPort()); } } }
Status MemberConfig::initialize(const BSONObj& mcfg, ReplicaSetTagConfig* tagConfig) { Status status = bsonCheckOnlyHasFields( "replica set member configuration", mcfg, kLegalMemberConfigFieldNames); if (!status.isOK()) return status; // // Parse _id field. // BSONElement idElement = mcfg[kIdFieldName]; if (idElement.eoo()) { return Status(ErrorCodes::NoSuchKey, str::stream() << kIdFieldName << " field is missing"); } if (!idElement.isNumber()) { return Status(ErrorCodes::TypeMismatch, str::stream() << kIdFieldName << " field has non-numeric type " << typeName(idElement.type())); } _id = idElement.numberInt(); // // Parse h field. // std::string hostAndPortString; status = bsonExtractStringField(mcfg, kHostFieldName, &hostAndPortString); if (!status.isOK()) return status; boost::trim(hostAndPortString); status = _host.initialize(hostAndPortString); if (!status.isOK()) return status; if (!_host.hasPort()) { // make port explicit even if default. _host = HostAndPort(_host.host(), _host.port()); } // // Parse votes field. // BSONElement votesElement = mcfg[kVotesFieldName]; if (votesElement.eoo()) { _votes = kVotesFieldDefault; } else if (votesElement.isNumber()) { _votes = votesElement.numberInt(); } else { return Status(ErrorCodes::TypeMismatch, str::stream() << kVotesFieldName << " field value has non-numeric type " << typeName(votesElement.type())); } // // Parse priority field. // BSONElement priorityElement = mcfg[kPriorityFieldName]; if (priorityElement.eoo()) { _priority = kPriorityFieldDefault; } else if (priorityElement.isNumber()) { _priority = priorityElement.numberDouble(); } else { return Status(ErrorCodes::TypeMismatch, str::stream() << kPriorityFieldName << " field has non-numeric type " << typeName(priorityElement.type())); } // // Parse arbiterOnly field. // status = bsonExtractBooleanFieldWithDefault( mcfg, kArbiterOnlyFieldName, kArbiterOnlyFieldDefault, &_arbiterOnly); if (!status.isOK()) return status; // // Parse slaveDelay field. // BSONElement slaveDelayElement = mcfg[kSlaveDelayFieldName]; if (slaveDelayElement.eoo()) { _slaveDelay = kSlaveDelayFieldDefault; } else if (slaveDelayElement.isNumber()) { _slaveDelay = Seconds(slaveDelayElement.numberInt()); } else { return Status(ErrorCodes::TypeMismatch, str::stream() << kSlaveDelayFieldName << " field value has non-numeric type " << typeName(slaveDelayElement.type())); } // // Parse hidden field. // status = bsonExtractBooleanFieldWithDefault(mcfg, kHiddenFieldName, kHiddenFieldDefault, &_hidden); if (!status.isOK()) return status; // // Parse buildIndexes field. // status = bsonExtractBooleanFieldWithDefault( mcfg, kBuildIndexesFieldName, kBuildIndexesFieldDefault, &_buildIndexes); if (!status.isOK()) return status; // // Parse "tags" field. // _tags.clear(); BSONElement tagsElement; status = bsonExtractTypedField(mcfg, kTagsFieldName, Object, &tagsElement); if (status.isOK()) { for (BSONObj::iterator tagIter(tagsElement.Obj()); tagIter.more();) { const BSONElement& tag = tagIter.next(); if (tag.type() != String) { return Status(ErrorCodes::TypeMismatch, str::stream() << "tags." << tag.fieldName() << " field has non-string value of type " << typeName(tag.type())); } _tags.push_back(tagConfig->makeTag(tag.fieldNameStringData(), tag.valueStringData())); } } else if (ErrorCodes::NoSuchKey != status) { return status; } // // Add internal tags based on other member properties. // // Add a voter tag if this non-arbiter member votes; use _id for uniquity. const std::string id = str::stream() << _id; if (isVoter() && !_arbiterOnly) { _tags.push_back(tagConfig->makeTag(kInternalVoterTagName, id)); } // Add an electable tag if this member is electable. if (isElectable()) { _tags.push_back(tagConfig->makeTag(kInternalElectableTagName, id)); } // Add a tag for generic counting of this node. if (!_arbiterOnly) { _tags.push_back(tagConfig->makeTag(kInternalAllTagName, id)); } return Status::OK(); }