diff options
author | matt dannenberg <matt.dannenberg@10gen.com> | 2014-07-17 10:34:50 -0400 |
---|---|---|
committer | matt dannenberg <matt.dannenberg@10gen.com> | 2014-07-21 08:05:07 -0400 |
commit | b3712d70b80c2b5ba936a4d74c6def5ca150682d (patch) | |
tree | 8e28dc2f3ad13688033363c395774b6294d38bf3 /src/mongo | |
parent | 6870e3e7494a8209070cf952cde5a6d5748b5381 (diff) | |
download | mongo-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.cpp | 21 | ||||
-rw-r--r-- | src/mongo/db/repl/member_config.h | 5 | ||||
-rw-r--r-- | src/mongo/db/repl/replica_set_config.cpp | 47 | ||||
-rw-r--r-- | src/mongo/db/repl/replica_set_config.h | 11 | ||||
-rw-r--r-- | src/mongo/db/repl/replica_set_config_test.cpp | 156 | ||||
-rw-r--r-- | src/mongo/util/unordered_fast_key_table.h | 2 |
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; |