summaryrefslogtreecommitdiff
path: root/src/mongo/db/repl/repl_set_heartbeat_response.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/mongo/db/repl/repl_set_heartbeat_response.cpp')
-rw-r--r--src/mongo/db/repl/repl_set_heartbeat_response.cpp618
1 files changed, 304 insertions, 314 deletions
diff --git a/src/mongo/db/repl/repl_set_heartbeat_response.cpp b/src/mongo/db/repl/repl_set_heartbeat_response.cpp
index 43b62a43f48..d2a77c58a5f 100644
--- a/src/mongo/db/repl/repl_set_heartbeat_response.cpp
+++ b/src/mongo/db/repl/repl_set_heartbeat_response.cpp
@@ -45,345 +45,335 @@ namespace mongo {
namespace repl {
namespace {
- const std::string kConfigFieldName = "config";
- const std::string kConfigVersionFieldName = "v";
- const std::string kElectionTimeFieldName = "electionTime";
- const std::string kErrMsgFieldName = "errmsg";
- const std::string kErrorCodeFieldName = "code";
- const std::string kHasDataFieldName = "hasData";
- const std::string kHasStateDisagreementFieldName = "stateDisagreement";
- const std::string kHbMessageFieldName = "hbmsg";
- const std::string kIsElectableFieldName = "e";
- const std::string kIsReplSetFieldName = "rs";
- const std::string kMemberStateFieldName = "state";
- const std::string kMismatchFieldName = "mismatch";
- const std::string kOkFieldName = "ok";
- const std::string kOpTimeFieldName = "opTime";
- const std::string kPrimaryIdFieldName = "primaryId";
- const std::string kReplSetFieldName = "set";
- const std::string kSyncSourceFieldName = "syncingTo";
- const std::string kTermFieldName = "term";
- const std::string kTimeFieldName = "time";
- const std::string kTimestampFieldName = "ts";
+const std::string kConfigFieldName = "config";
+const std::string kConfigVersionFieldName = "v";
+const std::string kElectionTimeFieldName = "electionTime";
+const std::string kErrMsgFieldName = "errmsg";
+const std::string kErrorCodeFieldName = "code";
+const std::string kHasDataFieldName = "hasData";
+const std::string kHasStateDisagreementFieldName = "stateDisagreement";
+const std::string kHbMessageFieldName = "hbmsg";
+const std::string kIsElectableFieldName = "e";
+const std::string kIsReplSetFieldName = "rs";
+const std::string kMemberStateFieldName = "state";
+const std::string kMismatchFieldName = "mismatch";
+const std::string kOkFieldName = "ok";
+const std::string kOpTimeFieldName = "opTime";
+const std::string kPrimaryIdFieldName = "primaryId";
+const std::string kReplSetFieldName = "set";
+const std::string kSyncSourceFieldName = "syncingTo";
+const std::string kTermFieldName = "term";
+const std::string kTimeFieldName = "time";
+const std::string kTimestampFieldName = "ts";
} // namespace
- void ReplSetHeartbeatResponse::addToBSON(BSONObjBuilder* builder,
- bool isProtocolVersionV1) const {
- if (_mismatch) {
- *builder << kOkFieldName << 0.0;
- *builder << kMismatchFieldName << _mismatch;
- return;
- }
-
- builder->append(kOkFieldName, 1.0);
- if (_timeSet) {
- *builder << kTimeFieldName << durationCount<Seconds>(_time);
- }
- if (_electionTimeSet) {
- builder->appendDate(kElectionTimeFieldName,
- Date_t::fromMillisSinceEpoch(_electionTime.asLL()));
- }
- if (_configSet) {
- *builder << kConfigFieldName << _config.toBSON();
- }
- if (_electableSet) {
- *builder << kIsElectableFieldName << _electable;
- }
- if (_isReplSet) {
- *builder << "rs" << _isReplSet;
- }
- if (_stateDisagreement) {
- *builder << kHasStateDisagreementFieldName << _stateDisagreement;
- }
- if (_stateSet) {
- builder->appendIntOrLL(kMemberStateFieldName, _state.s);
- }
- if (_configVersion != -1) {
- *builder << kConfigVersionFieldName << _configVersion;
- }
- *builder << kHbMessageFieldName << _hbmsg;
- if (!_setName.empty()) {
- *builder << kReplSetFieldName << _setName;
- }
- if (!_syncingTo.empty()) {
- *builder << kSyncSourceFieldName << _syncingTo.toString();
- }
- if (_hasDataSet) {
- builder->append(kHasDataFieldName, _hasData);
- }
- if (_term != -1) {
- builder->append(kTermFieldName, _term);
- }
- if (_primaryIdSet) {
- builder->append(kPrimaryIdFieldName, _primaryId);
- }
- if (_opTimeSet) {
- if (isProtocolVersionV1) {
- BSONObjBuilder opTime(builder->subobjStart(kOpTimeFieldName));
- opTime.append(kTimestampFieldName, _opTime.getTimestamp());
- opTime.append(kTermFieldName, _opTime.getTerm());
- opTime.done();
- }
- else {
- builder->appendDate(kOpTimeFieldName,
- Date_t::fromMillisSinceEpoch(_opTime.getTimestamp().asLL()));
- }
- }
-
+void ReplSetHeartbeatResponse::addToBSON(BSONObjBuilder* builder, bool isProtocolVersionV1) const {
+ if (_mismatch) {
+ *builder << kOkFieldName << 0.0;
+ *builder << kMismatchFieldName << _mismatch;
+ return;
}
- BSONObj ReplSetHeartbeatResponse::toBSON(bool isProtocolVersionV1) const {
- BSONObjBuilder builder;
- addToBSON(&builder, isProtocolVersionV1);
- return builder.obj();
+ builder->append(kOkFieldName, 1.0);
+ if (_timeSet) {
+ *builder << kTimeFieldName << durationCount<Seconds>(_time);
}
-
- Status ReplSetHeartbeatResponse::initialize(const BSONObj& doc, long long term) {
-
- // Old versions set this even though they returned not "ok"
- _mismatch = doc[kMismatchFieldName].trueValue();
- if (_mismatch)
- return Status(ErrorCodes::InconsistentReplicaSetNames,
- "replica set name doesn't match.");
-
- // Old versions sometimes set the replica set name ("set") but ok:0
- const BSONElement replSetNameElement = doc[kReplSetFieldName];
- if (replSetNameElement.eoo()) {
- _setName.clear();
- }
- else if (replSetNameElement.type() != String) {
- return Status(ErrorCodes::TypeMismatch, str::stream() << "Expected \"" <<
- kReplSetFieldName << "\" field in response to replSetHeartbeat to have "
- "type String, but found " << typeName(replSetNameElement.type()));
- }
- else {
- _setName = replSetNameElement.String();
- }
-
- if (_setName.empty() && !doc[kOkFieldName].trueValue()) {
- std::string errMsg = doc[kErrMsgFieldName].str();
-
- BSONElement errCodeElem = doc[kErrorCodeFieldName];
- if (errCodeElem.ok()) {
- if (!errCodeElem.isNumber())
- return Status(ErrorCodes::BadValue, "Error code is not a number!");
-
- int errorCode = errCodeElem.numberInt();
- return Status(ErrorCodes::Error(errorCode), errMsg);
- }
- return Status(ErrorCodes::UnknownError, errMsg);
- }
-
- const BSONElement hasDataElement = doc[kHasDataFieldName];
- _hasDataSet = !hasDataElement.eoo();
- _hasData = hasDataElement.trueValue();
-
- const BSONElement electionTimeElement = doc[kElectionTimeFieldName];
- if (electionTimeElement.eoo()) {
- _electionTimeSet = false;
- }
- else if (electionTimeElement.type() == bsonTimestamp) {
- _electionTimeSet = true;
- _electionTime = electionTimeElement.timestamp();
- }
- else if (electionTimeElement.type() == Date) {
- _electionTimeSet = true;
- _electionTime = Timestamp(electionTimeElement.date());
- }
- else {
- return Status(ErrorCodes::TypeMismatch, str::stream() << "Expected \"" <<
- kElectionTimeFieldName << "\" field in response to replSetHeartbeat "
- "command to have type Date or Timestamp, but found type " <<
- typeName(electionTimeElement.type()));
- }
-
- const BSONElement timeElement = doc[kTimeFieldName];
- if (timeElement.eoo()) {
- _timeSet = false;
- }
- else if (timeElement.isNumber()) {
- _timeSet = true;
- _time = Seconds(timeElement.numberLong());
- }
- else {
- return Status(ErrorCodes::TypeMismatch, str::stream() << "Expected \"" <<
- kTimeFieldName << "\" field in response to replSetHeartbeat "
- "command to have a numeric type, but found type " <<
- typeName(timeElement.type()));
- }
-
- _isReplSet = doc[kIsReplSetFieldName].trueValue();
-
- // In order to support both the 3.0(V0) and 3.2(V1) heartbeats we must parse the OpTime
- // field based on its type. If it is a Date, we parse it as the timestamp and use
- // initialize's term argument to complete the OpTime type. If it is an Object, then it's
- // V1 and we construct an OpTime out of its nested fields.
- const BSONElement opTimeElement = doc[kOpTimeFieldName];
- if (opTimeElement.eoo()) {
- _opTimeSet = false;
- }
- else if (opTimeElement.type() == bsonTimestamp) {
- _opTimeSet = true;
- _opTime = OpTime(opTimeElement.timestamp(), term);
- }
- else if (opTimeElement.type() == Date) {
- _opTimeSet = true;
- _opTime = OpTime(Timestamp(opTimeElement.date()), term);
- }
- else if (opTimeElement.type() == Object) {
- BSONObj opTime = opTimeElement.Obj();
- Timestamp ts;
- Status status = bsonExtractTimestampField(opTime, kTimestampFieldName, &ts);
- if (!status.isOK())
- return status;
- long long extractedTerm;
- status = bsonExtractIntegerField(opTime, kTermFieldName, &extractedTerm);
- if (!status.isOK())
- return status;
-
- _opTimeSet = true;
- _opTime = OpTime(ts, extractedTerm);
- // since a v1 OpTime was in the response, the member must be part of a replset
- _isReplSet = true;
- }
- else {
- return Status(ErrorCodes::TypeMismatch, str::stream() << "Expected \"" <<
- kOpTimeFieldName << "\" field in response to replSetHeartbeat "
- "command to have type Date or Timestamp, but found type " <<
- typeName(opTimeElement.type()));
- }
-
- const BSONElement electableElement = doc[kIsElectableFieldName];
- if (electableElement.eoo()) {
- _electableSet = false;
- }
- else {
- _electableSet = true;
- _electable = electableElement.trueValue();
- }
-
- const BSONElement memberStateElement = doc[kMemberStateFieldName];
- if (memberStateElement.eoo()) {
- _stateSet = false;
- }
- else if (memberStateElement.type() != NumberInt &&
- memberStateElement.type() != NumberLong) {
- return Status(ErrorCodes::TypeMismatch, str::stream() << "Expected \"" <<
- kMemberStateFieldName << "\" field in response to replSetHeartbeat "
- "command to have type NumberInt or NumberLong, but found type " <<
- typeName(memberStateElement.type()));
- }
- else {
- long long stateInt = memberStateElement.numberLong();
- if (stateInt < 0 || stateInt > MemberState::RS_MAX) {
- return Status(ErrorCodes::BadValue, str::stream() << "Value for \"" <<
- kMemberStateFieldName << "\" in response to replSetHeartbeat is "
- "out of range; legal values are non-negative and no more than " <<
- MemberState::RS_MAX);
- }
- _stateSet = true;
- _state = MemberState(static_cast<int>(stateInt));
- }
-
- _stateDisagreement = doc[kHasStateDisagreementFieldName].trueValue();
-
-
- // Not required for the case of uninitialized members -- they have no config
- const BSONElement configVersionElement = doc[kConfigVersionFieldName];
-
- // If we have an optime then we must have a configVersion
- if (_opTimeSet && configVersionElement.eoo()) {
- return Status(ErrorCodes::NoSuchKey, str::stream() <<
- "Response to replSetHeartbeat missing required \"" <<
- kConfigVersionFieldName << "\" field even though initialized");
- }
-
- // If there is a "v" (config version) then it must be an int.
- if (!configVersionElement.eoo() && configVersionElement.type() != NumberInt) {
- return Status(ErrorCodes::TypeMismatch, str::stream() << "Expected \"" <<
- kConfigVersionFieldName <<
- "\" field in response to replSetHeartbeat to have "
- "type NumberInt, but found " << typeName(configVersionElement.type()));
+ if (_electionTimeSet) {
+ builder->appendDate(kElectionTimeFieldName,
+ Date_t::fromMillisSinceEpoch(_electionTime.asLL()));
+ }
+ if (_configSet) {
+ *builder << kConfigFieldName << _config.toBSON();
+ }
+ if (_electableSet) {
+ *builder << kIsElectableFieldName << _electable;
+ }
+ if (_isReplSet) {
+ *builder << "rs" << _isReplSet;
+ }
+ if (_stateDisagreement) {
+ *builder << kHasStateDisagreementFieldName << _stateDisagreement;
+ }
+ if (_stateSet) {
+ builder->appendIntOrLL(kMemberStateFieldName, _state.s);
+ }
+ if (_configVersion != -1) {
+ *builder << kConfigVersionFieldName << _configVersion;
+ }
+ *builder << kHbMessageFieldName << _hbmsg;
+ if (!_setName.empty()) {
+ *builder << kReplSetFieldName << _setName;
+ }
+ if (!_syncingTo.empty()) {
+ *builder << kSyncSourceFieldName << _syncingTo.toString();
+ }
+ if (_hasDataSet) {
+ builder->append(kHasDataFieldName, _hasData);
+ }
+ if (_term != -1) {
+ builder->append(kTermFieldName, _term);
+ }
+ if (_primaryIdSet) {
+ builder->append(kPrimaryIdFieldName, _primaryId);
+ }
+ if (_opTimeSet) {
+ if (isProtocolVersionV1) {
+ BSONObjBuilder opTime(builder->subobjStart(kOpTimeFieldName));
+ opTime.append(kTimestampFieldName, _opTime.getTimestamp());
+ opTime.append(kTermFieldName, _opTime.getTerm());
+ opTime.done();
+ } else {
+ builder->appendDate(kOpTimeFieldName,
+ Date_t::fromMillisSinceEpoch(_opTime.getTimestamp().asLL()));
}
- _configVersion = configVersionElement.numberInt();
+ }
+}
+
+BSONObj ReplSetHeartbeatResponse::toBSON(bool isProtocolVersionV1) const {
+ BSONObjBuilder builder;
+ addToBSON(&builder, isProtocolVersionV1);
+ return builder.obj();
+}
+
+Status ReplSetHeartbeatResponse::initialize(const BSONObj& doc, long long term) {
+ // Old versions set this even though they returned not "ok"
+ _mismatch = doc[kMismatchFieldName].trueValue();
+ if (_mismatch)
+ return Status(ErrorCodes::InconsistentReplicaSetNames, "replica set name doesn't match.");
+
+ // Old versions sometimes set the replica set name ("set") but ok:0
+ const BSONElement replSetNameElement = doc[kReplSetFieldName];
+ if (replSetNameElement.eoo()) {
+ _setName.clear();
+ } else if (replSetNameElement.type() != String) {
+ return Status(ErrorCodes::TypeMismatch,
+ str::stream() << "Expected \"" << kReplSetFieldName
+ << "\" field in response to replSetHeartbeat to have "
+ "type String, but found "
+ << typeName(replSetNameElement.type()));
+ } else {
+ _setName = replSetNameElement.String();
+ }
- const BSONElement hbMsgElement = doc[kHbMessageFieldName];
- if (hbMsgElement.eoo()) {
- _hbmsg.clear();
- }
- else if (hbMsgElement.type() != String) {
- return Status(ErrorCodes::TypeMismatch, str::stream() << "Expected \"" <<
- kHbMessageFieldName << "\" field in response to replSetHeartbeat to have "
- "type String, but found " << typeName(hbMsgElement.type()));
- }
- else {
- _hbmsg = hbMsgElement.String();
- }
+ if (_setName.empty() && !doc[kOkFieldName].trueValue()) {
+ std::string errMsg = doc[kErrMsgFieldName].str();
- const BSONElement syncingToElement = doc[kSyncSourceFieldName];
- if (syncingToElement.eoo()) {
- _syncingTo = HostAndPort();
- }
- else if (syncingToElement.type() != String) {
- return Status(ErrorCodes::TypeMismatch, str::stream() << "Expected \"" <<
- kSyncSourceFieldName << "\" field in response to replSetHeartbeat to "
- "have type String, but found " << typeName(syncingToElement.type()));
- }
- else {
- _syncingTo = HostAndPort(syncingToElement.String());
- }
+ BSONElement errCodeElem = doc[kErrorCodeFieldName];
+ if (errCodeElem.ok()) {
+ if (!errCodeElem.isNumber())
+ return Status(ErrorCodes::BadValue, "Error code is not a number!");
- const BSONElement rsConfigElement = doc[kConfigFieldName];
- if (rsConfigElement.eoo()) {
- _configSet = false;
- _config = ReplicaSetConfig();
- return Status::OK();
+ int errorCode = errCodeElem.numberInt();
+ return Status(ErrorCodes::Error(errorCode), errMsg);
}
- else if (rsConfigElement.type() != Object) {
- return Status(ErrorCodes::TypeMismatch, str::stream() << "Expected \"" <<
- kConfigFieldName << "\" in response to replSetHeartbeat to have type "
- "Object, but found " << typeName(rsConfigElement.type()));
- }
- _configSet = true;
+ return Status(ErrorCodes::UnknownError, errMsg);
+ }
- return _config.initialize(rsConfigElement.Obj());
+ const BSONElement hasDataElement = doc[kHasDataFieldName];
+ _hasDataSet = !hasDataElement.eoo();
+ _hasData = hasDataElement.trueValue();
+
+ const BSONElement electionTimeElement = doc[kElectionTimeFieldName];
+ if (electionTimeElement.eoo()) {
+ _electionTimeSet = false;
+ } else if (electionTimeElement.type() == bsonTimestamp) {
+ _electionTimeSet = true;
+ _electionTime = electionTimeElement.timestamp();
+ } else if (electionTimeElement.type() == Date) {
+ _electionTimeSet = true;
+ _electionTime = Timestamp(electionTimeElement.date());
+ } else {
+ return Status(ErrorCodes::TypeMismatch,
+ str::stream() << "Expected \"" << kElectionTimeFieldName
+ << "\" field in response to replSetHeartbeat "
+ "command to have type Date or Timestamp, but found type "
+ << typeName(electionTimeElement.type()));
}
- MemberState ReplSetHeartbeatResponse::getState() const {
- invariant(_stateSet);
- return _state;
+ const BSONElement timeElement = doc[kTimeFieldName];
+ if (timeElement.eoo()) {
+ _timeSet = false;
+ } else if (timeElement.isNumber()) {
+ _timeSet = true;
+ _time = Seconds(timeElement.numberLong());
+ } else {
+ return Status(ErrorCodes::TypeMismatch,
+ str::stream() << "Expected \"" << kTimeFieldName
+ << "\" field in response to replSetHeartbeat "
+ "command to have a numeric type, but found type "
+ << typeName(timeElement.type()));
}
- Timestamp ReplSetHeartbeatResponse::getElectionTime() const {
- invariant(_electionTimeSet);
- return _electionTime;
+ _isReplSet = doc[kIsReplSetFieldName].trueValue();
+
+ // In order to support both the 3.0(V0) and 3.2(V1) heartbeats we must parse the OpTime
+ // field based on its type. If it is a Date, we parse it as the timestamp and use
+ // initialize's term argument to complete the OpTime type. If it is an Object, then it's
+ // V1 and we construct an OpTime out of its nested fields.
+ const BSONElement opTimeElement = doc[kOpTimeFieldName];
+ if (opTimeElement.eoo()) {
+ _opTimeSet = false;
+ } else if (opTimeElement.type() == bsonTimestamp) {
+ _opTimeSet = true;
+ _opTime = OpTime(opTimeElement.timestamp(), term);
+ } else if (opTimeElement.type() == Date) {
+ _opTimeSet = true;
+ _opTime = OpTime(Timestamp(opTimeElement.date()), term);
+ } else if (opTimeElement.type() == Object) {
+ BSONObj opTime = opTimeElement.Obj();
+ Timestamp ts;
+ Status status = bsonExtractTimestampField(opTime, kTimestampFieldName, &ts);
+ if (!status.isOK())
+ return status;
+ long long extractedTerm;
+ status = bsonExtractIntegerField(opTime, kTermFieldName, &extractedTerm);
+ if (!status.isOK())
+ return status;
+
+ _opTimeSet = true;
+ _opTime = OpTime(ts, extractedTerm);
+ // since a v1 OpTime was in the response, the member must be part of a replset
+ _isReplSet = true;
+ } else {
+ return Status(ErrorCodes::TypeMismatch,
+ str::stream() << "Expected \"" << kOpTimeFieldName
+ << "\" field in response to replSetHeartbeat "
+ "command to have type Date or Timestamp, but found type "
+ << typeName(opTimeElement.type()));
}
- bool ReplSetHeartbeatResponse::isElectable() const {
- invariant(_electableSet);
- return _electable;
+ const BSONElement electableElement = doc[kIsElectableFieldName];
+ if (electableElement.eoo()) {
+ _electableSet = false;
+ } else {
+ _electableSet = true;
+ _electable = electableElement.trueValue();
}
- Seconds ReplSetHeartbeatResponse::getTime() const {
- invariant(_timeSet);
- return _time;
+ const BSONElement memberStateElement = doc[kMemberStateFieldName];
+ if (memberStateElement.eoo()) {
+ _stateSet = false;
+ } else if (memberStateElement.type() != NumberInt && memberStateElement.type() != NumberLong) {
+ return Status(ErrorCodes::TypeMismatch,
+ str::stream()
+ << "Expected \"" << kMemberStateFieldName
+ << "\" field in response to replSetHeartbeat "
+ "command to have type NumberInt or NumberLong, but found type "
+ << typeName(memberStateElement.type()));
+ } else {
+ long long stateInt = memberStateElement.numberLong();
+ if (stateInt < 0 || stateInt > MemberState::RS_MAX) {
+ return Status(ErrorCodes::BadValue,
+ str::stream()
+ << "Value for \"" << kMemberStateFieldName
+ << "\" in response to replSetHeartbeat is "
+ "out of range; legal values are non-negative and no more than "
+ << MemberState::RS_MAX);
+ }
+ _stateSet = true;
+ _state = MemberState(static_cast<int>(stateInt));
}
- const ReplicaSetConfig& ReplSetHeartbeatResponse::getConfig() const {
- invariant(_configSet);
- return _config;
+ _stateDisagreement = doc[kHasStateDisagreementFieldName].trueValue();
+
+
+ // Not required for the case of uninitialized members -- they have no config
+ const BSONElement configVersionElement = doc[kConfigVersionFieldName];
+
+ // If we have an optime then we must have a configVersion
+ if (_opTimeSet && configVersionElement.eoo()) {
+ return Status(ErrorCodes::NoSuchKey,
+ str::stream() << "Response to replSetHeartbeat missing required \""
+ << kConfigVersionFieldName
+ << "\" field even though initialized");
}
- long long ReplSetHeartbeatResponse::getPrimaryId() const {
- invariant(_primaryIdSet);
- return _primaryId;
+ // If there is a "v" (config version) then it must be an int.
+ if (!configVersionElement.eoo() && configVersionElement.type() != NumberInt) {
+ return Status(ErrorCodes::TypeMismatch,
+ str::stream() << "Expected \"" << kConfigVersionFieldName
+ << "\" field in response to replSetHeartbeat to have "
+ "type NumberInt, but found "
+ << typeName(configVersionElement.type()));
+ }
+ _configVersion = configVersionElement.numberInt();
+
+ const BSONElement hbMsgElement = doc[kHbMessageFieldName];
+ if (hbMsgElement.eoo()) {
+ _hbmsg.clear();
+ } else if (hbMsgElement.type() != String) {
+ return Status(ErrorCodes::TypeMismatch,
+ str::stream() << "Expected \"" << kHbMessageFieldName
+ << "\" field in response to replSetHeartbeat to have "
+ "type String, but found " << typeName(hbMsgElement.type()));
+ } else {
+ _hbmsg = hbMsgElement.String();
}
- OpTime ReplSetHeartbeatResponse::getOpTime() const {
- invariant(_opTimeSet);
- return _opTime;
+ const BSONElement syncingToElement = doc[kSyncSourceFieldName];
+ if (syncingToElement.eoo()) {
+ _syncingTo = HostAndPort();
+ } else if (syncingToElement.type() != String) {
+ return Status(ErrorCodes::TypeMismatch,
+ str::stream() << "Expected \"" << kSyncSourceFieldName
+ << "\" field in response to replSetHeartbeat to "
+ "have type String, but found "
+ << typeName(syncingToElement.type()));
+ } else {
+ _syncingTo = HostAndPort(syncingToElement.String());
}
-} // namespace repl
-} // namespace mongo
+ const BSONElement rsConfigElement = doc[kConfigFieldName];
+ if (rsConfigElement.eoo()) {
+ _configSet = false;
+ _config = ReplicaSetConfig();
+ return Status::OK();
+ } else if (rsConfigElement.type() != Object) {
+ return Status(ErrorCodes::TypeMismatch,
+ str::stream() << "Expected \"" << kConfigFieldName
+ << "\" in response to replSetHeartbeat to have type "
+ "Object, but found " << typeName(rsConfigElement.type()));
+ }
+ _configSet = true;
+
+ return _config.initialize(rsConfigElement.Obj());
+}
+
+MemberState ReplSetHeartbeatResponse::getState() const {
+ invariant(_stateSet);
+ return _state;
+}
+
+Timestamp ReplSetHeartbeatResponse::getElectionTime() const {
+ invariant(_electionTimeSet);
+ return _electionTime;
+}
+
+bool ReplSetHeartbeatResponse::isElectable() const {
+ invariant(_electableSet);
+ return _electable;
+}
+
+Seconds ReplSetHeartbeatResponse::getTime() const {
+ invariant(_timeSet);
+ return _time;
+}
+
+const ReplicaSetConfig& ReplSetHeartbeatResponse::getConfig() const {
+ invariant(_configSet);
+ return _config;
+}
+
+long long ReplSetHeartbeatResponse::getPrimaryId() const {
+ invariant(_primaryIdSet);
+ return _primaryId;
+}
+
+OpTime ReplSetHeartbeatResponse::getOpTime() const {
+ invariant(_opTimeSet);
+ return _opTime;
+}
+
+} // namespace repl
+} // namespace mongo