ReplicaSetTag ReplicaSetTagConfig::findTag(StringData key, StringData value) const { int32_t keyIndex = _findKeyIndex(key); if (size_t(keyIndex) == _tagData.size()) return ReplicaSetTag(-1, -1); const ValueVector& values = _tagData[keyIndex].second; for (size_t valueIndex = 0; valueIndex < values.size(); ++valueIndex) { if (values[valueIndex] == value) { return ReplicaSetTag(keyIndex, int32_t(valueIndex)); } } return ReplicaSetTag(-1, -1); }
ReplicaSetTag ReplicaSetTagConfig::makeTag(StringData key, StringData value) { int32_t keyIndex = _findKeyIndex(key); if (size_t(keyIndex) == _tagData.size()) { _tagData.push_back(make_pair(key.toString(), ValueVector())); } ValueVector& values = _tagData[keyIndex].second; for (size_t valueIndex = 0; valueIndex < values.size(); ++valueIndex) { if (values[valueIndex] != value) continue; return ReplicaSetTag(keyIndex, int32_t(valueIndex)); } values.push_back(value.toString()); return ReplicaSetTag(keyIndex, int32_t(values.size()) - 1); }
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(); }
Status MemberConfig::initialize(const BSONObj& mcfg) { 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]; int votes; 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())); } if (votes != 0 && votes != 1) { return Status(ErrorCodes::BadValue, str::stream() << kVotesFieldName << " field value is " << votesElement.numberInt() << " but must be 0 or 1"); } _isVoter = bool(votes); // // 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(ReplicaSetTag(tag.fieldName(), tag.String())); } } else if (ErrorCodes::NoSuchKey != status) { return status; } return Status::OK(); }