summaryrefslogtreecommitdiff
path: root/src/mongo/db/repl/repl_set_heartbeat_response.cpp
diff options
context:
space:
mode:
authorAndy Schwerin <schwerin@mongodb.com>2014-08-27 18:34:27 -0400
committerAndy Schwerin <schwerin@mongodb.com>2014-08-28 14:22:56 -0400
commit86be883456bddff9ce3c283c9d740e70d62eb22f (patch)
tree7f27d99ee087c8ce16955afc945b806fbcaafd75 /src/mongo/db/repl/repl_set_heartbeat_response.cpp
parentac6b4eac9d1fc33d357ee9264e4508f8a564d89d (diff)
downloadmongo-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.cpp247
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