diff options
author | Andy Schwerin <schwerin@mongodb.com> | 2014-08-27 18:34:27 -0400 |
---|---|---|
committer | Andy Schwerin <schwerin@mongodb.com> | 2014-08-28 14:22:56 -0400 |
commit | 86be883456bddff9ce3c283c9d740e70d62eb22f (patch) | |
tree | 7f27d99ee087c8ce16955afc945b806fbcaafd75 /src/mongo/db/repl/repl_set_heartbeat_response.cpp | |
parent | ac6b4eac9d1fc33d357ee9264e4508f8a564d89d (diff) | |
download | mongo-86be883456bddff9ce3c283c9d740e70d62eb22f.tar.gz |
SERVER-14561 Parsing and accessor methods for ReplSetHeartbeatResponse.
Diffstat (limited to 'src/mongo/db/repl/repl_set_heartbeat_response.cpp')
-rw-r--r-- | src/mongo/db/repl/repl_set_heartbeat_response.cpp | 247 |
1 files changed, 227 insertions, 20 deletions
diff --git a/src/mongo/db/repl/repl_set_heartbeat_response.cpp b/src/mongo/db/repl/repl_set_heartbeat_response.cpp index de54954e44d..ebfd25bf93b 100644 --- a/src/mongo/db/repl/repl_set_heartbeat_response.cpp +++ b/src/mongo/db/repl/repl_set_heartbeat_response.cpp @@ -26,74 +26,281 @@ * it in the license file. */ +#define MONGO_LOG_DEFAULT_COMPONENT ::mongo::logger::LogComponent::kReplication + +#include "mongo/platform/basic.h" + #include "mongo/db/repl/repl_set_heartbeat_response.h" +#include <string> + +#include "mongo/base/status.h" #include "mongo/db/jsobj.h" +#include "mongo/util/assert_util.h" +#include "mongo/util/mongoutils/str.h" namespace mongo { namespace repl { +namespace { + + const std::string kOpTimeFieldName = "opTime"; + const std::string kTimeFieldName = "time"; + const std::string kElectionTimeFieldName = "electionTime"; + const std::string kConfigFieldName = "config"; + const std::string kIsElectableFieldName = "e"; + const std::string kMismatchFieldName = "mismatch"; + const std::string kIsReplSetFieldName = "rs"; + const std::string kHasStateDisagreementFieldName = "stateDisagreement"; + const std::string kMemberStateFieldName = "state"; + const std::string kConfigVersionFieldName = "v"; + const std::string kHbMessageFieldName = "hbmsg"; + const std::string kReplSetFieldName = "set"; + const std::string kSyncSourceFieldName = "syncingTo"; + +} // namespace ReplSetHeartbeatResponse::ReplSetHeartbeatResponse() : _electionTimeSet(false), _timeSet(false), + _time(0), _opTimeSet(false), _electableSet(false), _electable(false), _mismatch(false), _isReplSet(false), _stateDisagreement(false), - _state(-1), + _stateSet(false), _version(-1), - _setName(""), - _hbmsg(""), - _syncingTo("") + _configSet(false) {} void ReplSetHeartbeatResponse::addToBSON(BSONObjBuilder* builder) const { if (_opTimeSet) { - builder->appendDate("opTime", _opTime); + builder->appendDate(kOpTimeFieldName, _opTime.asDate()); } if (_timeSet) { - long long millis = _time.asInt64(); - *builder << "time" << millis; + *builder << kTimeFieldName << _time.total_seconds(); } if (_electionTimeSet) { - builder->appendDate("electionTime", _electionTime); + builder->appendDate(kElectionTimeFieldName, _electionTime.asDate()); } - if (_config.isInitialized()) { - *builder << "config" << _config.toBSON(); + if (_configSet) { + *builder << kConfigFieldName << _config.toBSON(); } if (_electableSet) { - *builder << "e" << _electable; + *builder << kIsElectableFieldName << _electable; } if (_mismatch) { - *builder << "mismatch" << _mismatch; + *builder << kMismatchFieldName << _mismatch; } if (_isReplSet) { *builder << "rs" << _isReplSet; } if (_stateDisagreement) { - *builder << "stateDisagreement" << _stateDisagreement; + *builder << kHasStateDisagreementFieldName << _stateDisagreement; } - if (_state != -1) { - *builder << "state" << _state; + if (_stateSet) { + builder->appendIntOrLL(kMemberStateFieldName, _state.s); } if (_version != -1) { - *builder << "v" << _version; + *builder << kConfigVersionFieldName << _version; } - *builder << "hbmsg" << _hbmsg; + *builder << kHbMessageFieldName << _hbmsg; if (!_setName.empty()) { - *builder << "set" << _setName; + *builder << kReplSetFieldName << _setName; } if (!_syncingTo.empty()) { - *builder << "syncingTo" << _syncingTo; + *builder << kSyncSourceFieldName << _syncingTo; } } BSONObj ReplSetHeartbeatResponse::toBSON() const { BSONObjBuilder builder; addToBSON(&builder); - return builder.done(); + return builder.obj(); + } + + Status ReplSetHeartbeatResponse::initialize(const BSONObj& doc) { + const BSONElement electionTimeElement = doc[kElectionTimeFieldName]; + if (electionTimeElement.eoo()) { + _electionTimeSet = false; + } + else if (electionTimeElement.type() == Timestamp) { + _electionTimeSet = true; + _electionTime = electionTimeElement._opTime(); + } + else if (electionTimeElement.type() == Date) { + _electionTime = true; + _electionTime = OpTime(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 reponse to replSetHeartbeat " + "command to have a numeric type, but found type " << + typeName(timeElement.type())); + } + + const BSONElement opTimeElement = doc[kOpTimeFieldName]; + if (opTimeElement.eoo()) { + _opTimeSet = false; + } + else if (opTimeElement.type() == Timestamp) { + _opTimeSet = true; + _opTime = opTimeElement._opTime(); + } + else if (opTimeElement.type() == Date) { + _opTimeSet = true; + _opTime = OpTime(opTimeElement.date()); + } + 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(); + } + + _mismatch = doc[kMismatchFieldName].trueValue(); + _isReplSet = doc[kIsReplSetFieldName].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); + } + _state = MemberState(static_cast<int>(stateInt)); + } + + _stateDisagreement = doc[kHasStateDisagreementFieldName].trueValue(); + + const BSONElement versionElement = doc[kConfigVersionFieldName]; + if (versionElement.eoo()) { + return Status(ErrorCodes::NoSuchKey, str::stream() << + "Response to replSetHeartbeat missing required \"" << + kConfigVersionFieldName << " field"); + } + if (versionElement.type() != NumberInt) { + return Status(ErrorCodes::TypeMismatch, str::stream() << "Expected \"" << + kConfigVersionFieldName << + "\" field in response to replSetHeartbeat to have " + "type NumberInt, but found " << typeName(versionElement.type())); + } + _version = versionElement.numberInt(); + + const BSONElement replSetNameElement = doc[kReplSetFieldName]; + if (replSetNameElement.eoo()) { + return Status(ErrorCodes::NoSuchKey, str::stream() << + "Response to replSetHeartbeat missing required \"" << + kReplSetFieldName << "\" field"); + } + 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())); + } + _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())); + } + _hbmsg = hbMsgElement.String(); + + const BSONElement syncingToElement = doc[kSyncSourceFieldName]; + if (syncingToElement.eoo()) { + _syncingTo.clear(); + } + 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())); + } + _syncingTo = syncingToElement.String(); + + const BSONElement rsConfigElement = doc[kConfigFieldName]; + if (rsConfigElement.eoo()) { + _configSet = false; + _config = ReplicaSetConfig(); + } + 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; + } + + OpTime ReplSetHeartbeatResponse::getElectionTime() const { + invariant(_electionTimeSet); + return _electionTime; + } + + bool ReplSetHeartbeatResponse::isElectable() const { + invariant(_electableSet); + return _electable; + } + + Seconds ReplSetHeartbeatResponse::getTime() const { + invariant(_timeSet); + return _time; + } + + OpTime ReplSetHeartbeatResponse::getOpTime() const { + invariant(_opTimeSet); + return _opTime; + } + + const ReplicaSetConfig& ReplSetHeartbeatResponse::getConfig() const { + invariant(_configSet); + return _config; } } // namespace repl |