summaryrefslogtreecommitdiff
path: root/src/mongo
diff options
context:
space:
mode:
authormatt dannenberg <matt.dannenberg@10gen.com>2014-07-17 10:34:50 -0400
committermatt dannenberg <matt.dannenberg@10gen.com>2014-07-21 08:05:07 -0400
commitb3712d70b80c2b5ba936a4d74c6def5ca150682d (patch)
tree8e28dc2f3ad13688033363c395774b6294d38bf3 /src/mongo
parent6870e3e7494a8209070cf952cde5a6d5748b5381 (diff)
downloadmongo-b3712d70b80c2b5ba936a4d74c6def5ca150682d.tar.gz
SERVER-14586 add toBSON() methods to ReplicaSetConfig and MemberConfig classes
Diffstat (limited to 'src/mongo')
-rw-r--r--src/mongo/db/repl/member_config.cpp21
-rw-r--r--src/mongo/db/repl/member_config.h5
-rw-r--r--src/mongo/db/repl/replica_set_config.cpp47
-rw-r--r--src/mongo/db/repl/replica_set_config.h11
-rw-r--r--src/mongo/db/repl/replica_set_config_test.cpp156
-rw-r--r--src/mongo/util/unordered_fast_key_table.h2
6 files changed, 242 insertions, 0 deletions
diff --git a/src/mongo/db/repl/member_config.cpp b/src/mongo/db/repl/member_config.cpp
index 118ea72d3a6..4b59c7a7b0c 100644
--- a/src/mongo/db/repl/member_config.cpp
+++ b/src/mongo/db/repl/member_config.cpp
@@ -252,6 +252,27 @@ namespace {
return Status::OK();
}
+ BSONObj MemberConfig::toBSON(const ReplicaSetTagConfig& tagConfig) const {
+ BSONObjBuilder configBuilder;
+ configBuilder.append("_id", _id);
+ configBuilder.append("host", _host.toString());
+ configBuilder.append("arbiterOnly", _arbiterOnly);
+ configBuilder.append("buildIndexes", _buildIndexes);
+ configBuilder.append("hidden", _hidden);
+ configBuilder.append("priority", _priority);
+
+ BSONObjBuilder tags(configBuilder.subobjStart("tags"));
+ for (std::vector<ReplicaSetTag>::const_iterator tag = _tags.begin();
+ tag != _tags.end();
+ tag++) {
+ tags.append(tagConfig.getTagKey(*tag), tagConfig.getTagValue(*tag));
+ }
+ tags.done();
+
+ configBuilder.append("slaveDelay", _slaveDelay.total_seconds());
+ configBuilder.append("votes", _isVoter? 1 : 0);
+ return configBuilder.obj();
+ }
} // namespace repl
} // namespace mongo
diff --git a/src/mongo/db/repl/member_config.h b/src/mongo/db/repl/member_config.h
index 02a5bcec733..2c07a0d22ad 100644
--- a/src/mongo/db/repl/member_config.h
+++ b/src/mongo/db/repl/member_config.h
@@ -139,6 +139,11 @@ namespace repl {
*/
TagIterator tagsEnd() const { return _tags.end(); }
+ /**
+ * Returns the member config as a BSONObj, using "tagConfig" to generate the tag subdoc.
+ */
+ BSONObj toBSON(const ReplicaSetTagConfig& tagConfig) const;
+
private:
int _id;
diff --git a/src/mongo/db/repl/replica_set_config.cpp b/src/mongo/db/repl/replica_set_config.cpp
index a48a52b96d2..a67a1f00fcb 100644
--- a/src/mongo/db/repl/replica_set_config.cpp
+++ b/src/mongo/db/repl/replica_set_config.cpp
@@ -384,5 +384,52 @@ namespace {
_majorityNumber = (strictMajority > nonArbiters) ? nonArbiters : strictMajority;
}
+ BSONObj ReplicaSetConfig::toBSON() const {
+ BSONObjBuilder configBuilder;
+ configBuilder.append("_id", _replSetName);
+ configBuilder.append("version", _version);
+
+ BSONArrayBuilder members(configBuilder.subarrayStart("members"));
+ for (MemberIterator mem = membersBegin(); mem != membersEnd(); mem++) {
+ members.append(mem->toBSON(getTagConfig()));
+ }
+ members.done();
+
+ BSONObjBuilder settingsBuilder(configBuilder.subobjStart("settings"));
+ settingsBuilder.append("chainingAllowed", _chainingAllowed);
+ settingsBuilder.append("heartbeatTimeoutSecs", _heartbeatTimeoutPeriod.total_seconds());
+
+ BSONObjBuilder gleModes(settingsBuilder.subobjStart("getLastErrorModes"));
+ for (StringMap<ReplicaSetTagPattern>::const_iterator mode =
+ _customWriteConcernModes.begin();
+ mode != _customWriteConcernModes.end();
+ ++mode) {
+ 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("getLastErrorDefaults", _defaultWriteConcern.toBSON());
+ settingsBuilder.done();
+ return configBuilder.obj();
+ }
+
+ std::vector<std::string> ReplicaSetConfig::getWriteConcernNames() const {
+ std::vector<std::string> names;
+ for (StringMap<ReplicaSetTagPattern>::const_iterator mode =
+ _customWriteConcernModes.begin();
+ mode != _customWriteConcernModes.end();
+ ++mode) {
+ names.push_back(mode->first);
+ }
+ return names;
+ }
+
} // namespace repl
} // namespace mongo
diff --git a/src/mongo/db/repl/replica_set_config.h b/src/mongo/db/repl/replica_set_config.h
index f3e979759eb..31b14cc8438 100644
--- a/src/mongo/db/repl/replica_set_config.h
+++ b/src/mongo/db/repl/replica_set_config.h
@@ -143,6 +143,17 @@ namespace repl {
*/
const ReplicaSetTagConfig& getTagConfig() const { return _tagConfig; }
+ /**
+ * Returns the config as a BSONObj.
+ */
+ BSONObj toBSON() const;
+
+ /**
+ * Returns a vector of strings which are the names of the WriteConcernModes.
+ * Currently used in unit tests to compare two configs.
+ */
+ std::vector<std::string> getWriteConcernNames() const;
+
private:
/**
* Parses the "settings" subdocument of a replica set configuration.
diff --git a/src/mongo/db/repl/replica_set_config_test.cpp b/src/mongo/db/repl/replica_set_config_test.cpp
index 520e11fd95e..7a7c22f2780 100644
--- a/src/mongo/db/repl/replica_set_config_test.cpp
+++ b/src/mongo/db/repl/replica_set_config_test.cpp
@@ -368,6 +368,162 @@ namespace {
ASSERT_OK(config.findCustomWriteMode("frim").getStatus());
}
+ bool operator==(const MemberConfig& a, const MemberConfig& b) {
+ // do tag comparisons
+ for (MemberConfig::TagIterator itrA = a.tagsBegin(); itrA != a.tagsEnd(); ++itrA) {
+ if (std::find(b.tagsBegin(), b.tagsEnd(), *itrA) == b.tagsEnd()) {
+ return false;
+ }
+ }
+ return a.getId() == b.getId() &&
+ a.getHostAndPort() == b.getHostAndPort() &&
+ a.getPriority() == b.getPriority() &&
+ a.getSlaveDelay() == b.getSlaveDelay() &&
+ a.isVoter() == b.isVoter() &&
+ a.isArbiter() == b.isArbiter() &&
+ a.isHidden() == b.isHidden() &&
+ a.shouldBuildIndexes() == b.shouldBuildIndexes() &&
+ a.getNumTags() == b.getNumTags();
+ }
+
+ bool operator==(const ReplicaSetConfig& a, const ReplicaSetConfig& b) {
+ // compare WriteConcernModes
+ std::vector<std::string> modeNames = a.getWriteConcernNames();
+ for (std::vector<std::string>::iterator it = modeNames.begin();
+ it != modeNames.end();
+ it++) {
+ ReplicaSetTagPattern patternA = a.findCustomWriteMode(*it).getValue();
+ ReplicaSetTagPattern patternB = b.findCustomWriteMode(*it).getValue();
+ for (ReplicaSetTagPattern::ConstraintIterator itrA = patternA.constraintsBegin();
+ itrA != patternA.constraintsEnd();
+ itrA++) {
+ bool same = false;
+ for (ReplicaSetTagPattern::ConstraintIterator itrB = patternB.constraintsBegin();
+ itrB != patternB.constraintsEnd();
+ itrB++) {
+ if (itrA->getKeyIndex() == itrB->getKeyIndex() &&
+ itrA->getMinCount() == itrB->getMinCount()) {
+ same = true;
+ break;
+ }
+ }
+ if (!same) {
+ return false;
+ }
+ }
+ }
+
+ // compare the members
+ for (ReplicaSetConfig::MemberIterator memA = a.membersBegin();
+ memA != a.membersEnd();
+ memA++) {
+ bool same = false;
+ for (ReplicaSetConfig::MemberIterator memB = b.membersBegin();
+ memB != b.membersEnd();
+ memB++) {
+ if (*memA == *memB) {
+ same = true;
+ break;
+ }
+ }
+ if (!same) {
+ return false;
+ }
+ }
+
+ // simple comparisons
+ return a.getReplSetName() == b.getReplSetName() &&
+ a.getConfigVersion() == b.getConfigVersion() &&
+ a.getNumMembers() == b.getNumMembers() &&
+ a.getHeartbeatTimeoutPeriod() == b.getHeartbeatTimeoutPeriod() &&
+ a.getMajorityNumber() == b.getMajorityNumber() &&
+ a.isChainingAllowed() == b.isChainingAllowed() &&
+ a.getDefaultWriteConcern().wNumNodes == b.getDefaultWriteConcern().wNumNodes &&
+ a.getDefaultWriteConcern().wMode == b.getDefaultWriteConcern().wMode;
+ }
+
+ TEST(ReplicaSetConfig, toBSONRoundTripAbility) {
+ ReplicaSetConfig configA;
+ ReplicaSetConfig configB;
+ ASSERT_OK(configA.initialize(
+ BSON("_id" << "rs0" <<
+ "version" << 1 <<
+ "members" << BSON_ARRAY(BSON("_id" << 0 <<
+ "host" << "localhost:12345")) <<
+ "settings" << BSON("heartbeatTimeoutSecs" << 20))));
+ ASSERT_OK(configB.initialize(configA.toBSON()));
+ ASSERT_TRUE(configA == configB);
+ }
+
+ TEST(ReplicaSetConfig, toBSONRoundTripAbilityLarge) {
+ ReplicaSetConfig configA;
+ ReplicaSetConfig configB;
+ ASSERT_OK(configA.initialize(
+ BSON("_id" << "asdf"
+ << "version" << 9
+ << "members" << BSON_ARRAY(
+ BSON("_id" << 0
+ << "host" << "localhost:12345"
+ << "arbiterOnly" << true
+ << "votes" << 1
+ ) <<
+ BSON("_id" << 3
+ << "host" << "localhost:3828"
+ << "arbiterOnly" << false
+ << "hidden" << true
+ << "buildIndexes" << false
+ << "priority" << 0
+ << "slaveDelay" << 17
+ << "votes" << 0
+ << "tags" << BSON("coast" << "east" << "ssd" << "true")
+ ) <<
+ BSON("_id" << 2
+ << "host" << "foo.com:3828"
+ << "priority" << 9
+ << "votes" << 0
+ << "tags" << BSON("coast" << "west" << "hdd" << "true")
+ ))
+ << "settings" << BSON("heartbeatTimeoutSecs" << 20
+ << "chainingAllowd" << true
+ << "getLastErrorDefaults" << BSON("w" << "majority")
+ << "getLastErrorModes" << BSON(
+ "disks" << BSON("ssd" << 1 << "hdd" << 1)
+ << "coasts" << BSON("coast" << 2)))
+ )));
+ ASSERT_OK(configB.initialize(configA.toBSON()));
+ ASSERT_TRUE(configA == configB);
+ }
+
+ TEST(ReplicaSetConfig, toBSONRoundTripAbilityInvalid) {
+ ReplicaSetConfig configA;
+ ReplicaSetConfig configB;
+ ASSERT_OK(configA.initialize(
+ BSON("_id" << ""
+ << "version" << -3
+ << "members" << BSON_ARRAY(
+ BSON("_id" << 0
+ << "host" << "localhost:12345"
+ << "arbiterOnly" << true
+ << "votes" << 0
+ ) <<
+ BSON("_id" << 0
+ << "host" << "localhost:3828"
+ << "arbiterOnly" << false
+ << "buildIndexes" << false
+ << "priority" << 2
+ ) <<
+ BSON("_id" << 2
+ << "host" << "localhost:3828"
+ << "priority" << 9
+ << "votes" << 0
+ ))
+ << "settings" << BSON("heartbeatTimeoutSecs" << -20))));
+ ASSERT_OK(configB.initialize(configA.toBSON()));
+ ASSERT_NOT_OK(configA.validate());
+ ASSERT_NOT_OK(configB.validate());
+ ASSERT_TRUE(configA == configB);
+ }
+
} // namespace
} // namespace repl
} // namespace mongo
diff --git a/src/mongo/util/unordered_fast_key_table.h b/src/mongo/util/unordered_fast_key_table.h
index 47b0a81552d..e7d670cc24d 100644
--- a/src/mongo/util/unordered_fast_key_table.h
+++ b/src/mongo/util/unordered_fast_key_table.h
@@ -149,6 +149,8 @@ namespace mongo {
const value_type* operator->() const { return &_area->_entries[_position].data; }
+ const value_type& operator*() const { return _area->_entries[_position].data; }
+
const_iterator operator++() {
if ( _position < 0 )
return *this;