diff options
author | ADAM David Alan Martin <adam.martin@10gen.com> | 2019-05-17 15:41:29 -0400 |
---|---|---|
committer | ADAM David Alan Martin <adam.martin@10gen.com> | 2019-05-17 15:41:29 -0400 |
commit | 6784f6568cc45fe25510e2d2393be57daffb5411 (patch) | |
tree | 1b3e93ce250ec2fbded3caea297e802b575c111f /src/mongo/db/repl/member_config.cpp | |
parent | 88efdbf5b5c3b2c30b5b971a9adcaaa0a9f51797 (diff) | |
download | mongo-6784f6568cc45fe25510e2d2393be57daffb5411.tar.gz |
SERVER-40156 Replica sets support Split Horizons
Replica sets can now respond to `isMaster` requests with
different hostnames and ports, if contacted via alternate
names using TLS. The `horizons` field in replica set
member configurations can be used to control which
`HostAndPort` to reply with for which "horizon view" of
a replica set.
Diffstat (limited to 'src/mongo/db/repl/member_config.cpp')
-rw-r--r-- | src/mongo/db/repl/member_config.cpp | 111 |
1 files changed, 55 insertions, 56 deletions
diff --git a/src/mongo/db/repl/member_config.cpp b/src/mongo/db/repl/member_config.cpp index 29907879a2e..6d5265a4b7f 100644 --- a/src/mongo/db/repl/member_config.cpp +++ b/src/mongo/db/repl/member_config.cpp @@ -50,6 +50,7 @@ const std::string MemberConfig::kSlaveDelayFieldName = "slaveDelay"; const std::string MemberConfig::kArbiterOnlyFieldName = "arbiterOnly"; const std::string MemberConfig::kBuildIndexesFieldName = "buildIndexes"; const std::string MemberConfig::kTagsFieldName = "tags"; +const std::string MemberConfig::kHorizonsFieldName = "horizons"; const std::string MemberConfig::kInternalVoterTagName = "$voter"; const std::string MemberConfig::kInternalElectableTagName = "$electable"; const std::string MemberConfig::kInternalAllTagName = "$all"; @@ -63,7 +64,8 @@ const std::string kLegalMemberConfigFieldNames[] = {MemberConfig::kIdFieldName, MemberConfig::kSlaveDelayFieldName, MemberConfig::kArbiterOnlyFieldName, MemberConfig::kBuildIndexesFieldName, - MemberConfig::kTagsFieldName}; + MemberConfig::kTagsFieldName, + MemberConfig::kHorizonsFieldName}; const int kVotesFieldDefault = 1; const double kPriorityFieldDefault = 1.0; @@ -76,40 +78,34 @@ const Seconds kMaxSlaveDelay(3600 * 24 * 366); } // namespace -Status MemberConfig::initialize(const BSONObj& mcfg, ReplSetTagConfig* tagConfig) { - Status status = bsonCheckOnlyHasFields( - "replica set member configuration", mcfg, kLegalMemberConfigFieldNames); - if (!status.isOK()) - return status; +MemberConfig::MemberConfig(const BSONObj& mcfg, ReplSetTagConfig* tagConfig) { + uassertStatusOK(bsonCheckOnlyHasFields( + "replica set member configuration", mcfg, kLegalMemberConfigFieldNames)); // // 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())); - } + if (idElement.eoo()) + uasserted(ErrorCodes::NoSuchKey, str::stream() << kIdFieldName << " field is missing"); + + if (!idElement.isNumber()) + uasserted(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; + uassertStatusOK(bsonExtractStringField(mcfg, kHostFieldName, &hostAndPortString)); boost::trim(hostAndPortString); - status = _host.initialize(hostAndPortString); - if (!status.isOK()) - return status; - if (!_host.hasPort()) { + HostAndPort host; + uassertStatusOK(host.initialize(hostAndPortString)); + if (!host.hasPort()) { // make port explicit even if default. - _host = HostAndPort(_host.host(), _host.port()); + host = HostAndPort(host.host(), host.port()); } // @@ -121,18 +117,16 @@ Status MemberConfig::initialize(const BSONObj& mcfg, ReplSetTagConfig* tagConfig } else if (votesElement.isNumber()) { _votes = votesElement.numberInt(); } else { - return Status(ErrorCodes::TypeMismatch, - str::stream() << kVotesFieldName << " field value has non-numeric type " - << typeName(votesElement.type())); + uasserted(ErrorCodes::TypeMismatch, + str::stream() << kVotesFieldName << " field value has non-numeric type " + << typeName(votesElement.type())); } // // Parse arbiterOnly field. // - status = bsonExtractBooleanFieldWithDefault( - mcfg, kArbiterOnlyFieldName, kArbiterOnlyFieldDefault, &_arbiterOnly); - if (!status.isOK()) - return status; + uassertStatusOK(bsonExtractBooleanFieldWithDefault( + mcfg, kArbiterOnlyFieldName, kArbiterOnlyFieldDefault, &_arbiterOnly)); // // Parse priority field. @@ -144,9 +138,9 @@ Status MemberConfig::initialize(const BSONObj& mcfg, ReplSetTagConfig* tagConfig } else if (priorityElement.isNumber()) { _priority = priorityElement.numberDouble(); } else { - return Status(ErrorCodes::TypeMismatch, - str::stream() << kPriorityFieldName << " field has non-numeric type " - << typeName(priorityElement.type())); + uasserted(ErrorCodes::TypeMismatch, + str::stream() << kPriorityFieldName << " field has non-numeric type " + << typeName(priorityElement.type())); } // @@ -158,47 +152,52 @@ Status MemberConfig::initialize(const BSONObj& mcfg, ReplSetTagConfig* tagConfig } 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())); + uasserted(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; + uassertStatusOK( + bsonExtractBooleanFieldWithDefault(mcfg, kHiddenFieldName, kHiddenFieldDefault, &_hidden)); // // Parse buildIndexes field. // - status = bsonExtractBooleanFieldWithDefault( - mcfg, kBuildIndexesFieldName, kBuildIndexesFieldDefault, &_buildIndexes); - if (!status.isOK()) - return status; + uassertStatusOK(bsonExtractBooleanFieldWithDefault( + mcfg, kBuildIndexesFieldName, kBuildIndexesFieldDefault, &_buildIndexes)); // // Parse "tags" field. // - _tags.clear(); - BSONElement tagsElement; - status = bsonExtractTypedField(mcfg, kTagsFieldName, Object, &tagsElement); - if (status.isOK()) { + try { + BSONElement tagsElement; + uassertStatusOK(bsonExtractTypedField(mcfg, kTagsFieldName, Object, &tagsElement)); for (auto&& tag : tagsElement.Obj()) { if (tag.type() != String) { - return Status(ErrorCodes::TypeMismatch, - str::stream() << "tags." << tag.fieldName() - << " field has non-string value of type " - << typeName(tag.type())); + uasserted(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; + } catch (const ExceptionFor<ErrorCodes::NoSuchKey>&) { + // No such key is okay in this case, everything else is a problem. } + const auto horizonsElement = [&]() -> boost::optional<BSONElement> { + const BSONElement result = mcfg[kHorizonsFieldName]; + if (result.eoo()) { + return boost::none; + } + return result; + }(); + + _splitHorizon = SplitHorizon(host, horizonsElement); + // // Add internal tags based on other member properties. // @@ -218,8 +217,6 @@ Status MemberConfig::initialize(const BSONObj& mcfg, ReplSetTagConfig* tagConfig if (!_arbiterOnly) { _tags.push_back(tagConfig->makeTag(kInternalAllTagName, id)); } - - return Status::OK(); } Status MemberConfig::validate() const { @@ -286,7 +283,7 @@ bool MemberConfig::hasTags(const ReplSetTagConfig& tagConfig) const { BSONObj MemberConfig::toBSON(const ReplSetTagConfig& tagConfig) const { BSONObjBuilder configBuilder; configBuilder.append("_id", _id); - configBuilder.append("host", _host.toString()); + configBuilder.append("host", _host().toString()); configBuilder.append("arbiterOnly", _arbiterOnly); configBuilder.append("buildIndexes", _buildIndexes); configBuilder.append("hidden", _hidden); @@ -303,6 +300,8 @@ BSONObj MemberConfig::toBSON(const ReplSetTagConfig& tagConfig) const { } tags.done(); + _splitHorizon.toBSON(configBuilder); + configBuilder.append("slaveDelay", durationCount<Seconds>(_slaveDelay)); configBuilder.append("votes", getNumVotes()); return configBuilder.obj(); |