diff options
-rw-r--r-- | src/mongo/client/dbclient_rs.cpp | 76 | ||||
-rw-r--r-- | src/mongo/client/dbclient_rs.h | 69 | ||||
-rw-r--r-- | src/mongo/client/replica_set_monitor.cpp | 3 | ||||
-rw-r--r-- | src/mongo/client/replica_set_monitor_test.cpp | 3 | ||||
-rw-r--r-- | src/mongo/dbtests/replica_set_monitor_test.cpp | 106 |
5 files changed, 26 insertions, 231 deletions
diff --git a/src/mongo/client/dbclient_rs.cpp b/src/mongo/client/dbclient_rs.cpp index 12ab70de79a..f4a15b59af1 100644 --- a/src/mongo/client/dbclient_rs.cpp +++ b/src/mongo/client/dbclient_rs.cpp @@ -119,25 +119,23 @@ namespace { tagsElem.type() == mongo::Array); TagSet tags(BSONArray(tagsElem.Obj().getOwned())); - if (pref == mongo::ReadPreference_PrimaryOnly && !tags.isExhausted()) { + if (pref == mongo::ReadPreference_PrimaryOnly && !tags.getTagBSON().isEmpty()) { uassert(16384, "Only empty tags are allowed with primary read preference", - tags.getCurrentTag().isEmpty()); + tags.getTagBSON().firstElement().Obj().isEmpty()); } return new ReadPreferenceSetting(pref, tags); } else { - TagSet tags(BSON_ARRAY(BSONObj())); - return new ReadPreferenceSetting(pref, tags); + return new ReadPreferenceSetting(pref, TagSet()); } } // Default read pref is primary only or secondary preferred with slaveOK - TagSet tags(BSON_ARRAY(BSONObj())); ReadPreference pref = queryOptions & QueryOption_SlaveOk ? mongo::ReadPreference_SecondaryPreferred : mongo::ReadPreference_PrimaryOnly; - return new ReadPreferenceSetting(pref, tags); + return new ReadPreferenceSetting(pref, TagSet()); } } // namespace @@ -337,10 +335,8 @@ namespace { } DBClientConnection& DBClientReplicaSet::slaveConn() { - BSONArray emptyArray(BSON_ARRAY(BSONObj())); - TagSet tags(emptyArray); shared_ptr<ReadPreferenceSetting> readPref( - new ReadPreferenceSetting(ReadPreference_SecondaryPreferred, tags)); + new ReadPreferenceSetting(ReadPreference_SecondaryPreferred, TagSet())); DBClientConnection* conn = selectNodeUsingTags(readPref); uassert( 16369, str::stream() << "No good nodes available for set: " @@ -363,9 +359,8 @@ namespace { // We prefer to authenticate against a primary, but otherwise a secondary is ok too // Empty tag matches every secondary - TagSet tags(BSON_ARRAY(BSONObj())); shared_ptr<ReadPreferenceSetting> readPref( - new ReadPreferenceSetting( ReadPreference_PrimaryPreferred, tags ) ); + new ReadPreferenceSetting( ReadPreference_PrimaryPreferred, TagSet() ) ); LOG(3) << "dbclient_rs authentication of " << _getMonitor()->getName() << endl; @@ -959,62 +954,9 @@ namespace { _lastSlaveOkConn.reset(); } - TagSet::TagSet(): - _isExhausted(true), - _tagIterator(new BSONArrayIteratorSorted(_tags)) { - } - - TagSet::TagSet(const TagSet& other) : - _isExhausted(false), - _tags(other._tags.getOwned()), - _tagIterator(new BSONArrayIteratorSorted(_tags)) { - next(); - } - - TagSet::TagSet(const BSONArray& tags) : - _isExhausted(false), - _tags(tags.getOwned()), - _tagIterator(new BSONArrayIteratorSorted(_tags)) { - next(); - } - - void TagSet::next() { - if (_tagIterator->more()) { - const BSONElement& nextTag = _tagIterator->next(); - uassert(16357, "Tags should be a BSON object", nextTag.isABSONObj()); - _currentTag = nextTag.Obj(); - } - else { - _isExhausted = true; - } - } - - void TagSet::reset() { - _isExhausted = false; - _tagIterator.reset(new BSONArrayIteratorSorted(_tags)); - next(); - } - - const BSONObj& TagSet::getCurrentTag() const { - verify(!_isExhausted); - return _currentTag; - } - - bool TagSet::isExhausted() const { - return _isExhausted; - } - - BSONObjIterator* TagSet::getIterator() const { - return new BSONObjIterator(_tags); - } - - bool TagSet::equals(const TagSet& other) const { - return _tags.equal(other._tags); - } - - const BSONArray& TagSet::getTagBSON() const { - return _tags; - } + // trying to optimize for the common dont-care-about-tags case. + static const BSONArray tagsMatchesAll = BSON_ARRAY(BSONObj()); + TagSet::TagSet() : _tags(tagsMatchesAll) {} string readPrefToString( ReadPreference pref ) { switch ( pref ) { diff --git a/src/mongo/client/dbclient_rs.h b/src/mongo/client/dbclient_rs.h index b7c805c6450..7cc23ea386d 100644 --- a/src/mongo/client/dbclient_rs.h +++ b/src/mongo/client/dbclient_rs.h @@ -255,84 +255,35 @@ namespace mongo { }; /** - * A simple object for representing the list of tags. The initial state will - * have a valid current tag as long as the list is not empty. + * A simple object for representing the list of tags requested by a $readPreference. */ class MONGO_CLIENT_API TagSet { public: /** - * Creates an empty tag list that is initially exhausted. + * Creates a TagSet that matches any nodes. + * + * Do not call during static init. */ TagSet(); /** - * Creates a copy of the given TagSet. The new copy will have the - * iterator pointing at the initial position. - */ - explicit TagSet(const TagSet& other); - - /** - * Creates a tag set object that lazily iterates over the tag list. + * Creates a TagSet from a BSONArray of tags. * * @param tags the list of tags associated with this option. This object * will get a shared copy of the list. Therefore, it is important * for the the given tag to live longer than the created tag set. */ - explicit TagSet(const BSONArray& tags); - - /** - * Advance to the next tag. - * - * @throws AssertionException if iterator is exhausted before this is called. - */ - void next(); - - /** - * Rests the iterator to point to the first element (if there is a tag). - */ - void reset(); - - // - // Getters - // - - /** - * @return the current tag. Returned tag is invalid if isExhausted is true. - */ - const BSONObj& getCurrentTag() const; - - /** - * @return true if the iterator has been exhausted. - */ - bool isExhausted() const; + explicit TagSet(const BSONArray& tags) : _tags(tags) {} /** - * @return an unordered iterator to the tag list. The caller is responsible for - * destroying the returned iterator. + * Returns the BSONArray listing all tags that should be accepted. */ - BSONObjIterator* getIterator() const; + const BSONArray& getTagBSON() const { return _tags; } - /** - * @returns true if the other TagSet has the same tag set specification with - * this tag set, disregarding where the current iterator is pointing to. - */ - bool equals(const TagSet& other) const; - - const BSONArray& getTagBSON() const; + bool operator==(const TagSet& other) const { return _tags == other._tags; } private: - /** - * This is purposely undefined as the semantics for assignment can be - * confusing. This is because BSONArrayIteratorSorted shouldn't be - * copied (because of how it manages internal buffer). - */ - TagSet& operator=(const TagSet& other); - BSONObj _currentTag; - bool _isExhausted; - - // Important: do not re-order _tags & _tagIterator BSONArray _tags; - scoped_ptr<BSONArrayIteratorSorted> _tagIterator; }; struct MONGO_CLIENT_API ReadPreferenceSetting { @@ -348,7 +299,7 @@ namespace mongo { } inline bool equals(const ReadPreferenceSetting& other) const { - return pref == other.pref && tags.equals(other.tags); + return pref == other.pref && tags == other.tags; } BSONObj toBSON() const; diff --git a/src/mongo/client/replica_set_monitor.cpp b/src/mongo/client/replica_set_monitor.cpp index ab312fd8ef6..8288617f494 100644 --- a/src/mongo/client/replica_set_monitor.cpp +++ b/src/mongo/client/replica_set_monitor.cpp @@ -279,8 +279,7 @@ namespace { } HostAndPort ReplicaSetMonitor::getMasterOrUassert() { - const TagSet matchAnything(BSON_ARRAY(BSONObj())); - const ReadPreferenceSetting masterOnly(ReadPreference_PrimaryOnly, matchAnything); + const ReadPreferenceSetting masterOnly(ReadPreference_PrimaryOnly, TagSet()); HostAndPort master = getHostOrRefresh(masterOnly); uassert(10009, str::stream() << "ReplicaSetMonitor no master found for set: " << getName(), !master.empty()); diff --git a/src/mongo/client/replica_set_monitor_test.cpp b/src/mongo/client/replica_set_monitor_test.cpp index 1a9b298bbd9..bd5e4b21c03 100644 --- a/src/mongo/client/replica_set_monitor_test.cpp +++ b/src/mongo/client/replica_set_monitor_test.cpp @@ -327,8 +327,7 @@ TEST(ReplicaSetMonitorTests, SlavesUsableEvenIfNoMaster) { SetStatePtr state = boost::make_shared<SetState>("name", seeds); Refresher refresher(state); - const TagSet any(BSON_ARRAY(BSONObj())); - const ReadPreferenceSetting secondary(ReadPreference_SecondaryOnly, any); + const ReadPreferenceSetting secondary(ReadPreference_SecondaryOnly, TagSet()); // Mock a reply from the only host we know about and have it claim to not be master or know // about any other hosts. This leaves the scan with no more hosts to scan, but all hosts are diff --git a/src/mongo/dbtests/replica_set_monitor_test.cpp b/src/mongo/dbtests/replica_set_monitor_test.cpp index b4332299d37..0393ffdd721 100644 --- a/src/mongo/dbtests/replica_set_monitor_test.cpp +++ b/src/mongo/dbtests/replica_set_monitor_test.cpp @@ -1358,34 +1358,7 @@ namespace mongo_test { ASSERT_EQUALS("b", host.host()); } - TEST(TagSet, CopyConstructor) { - TagSet* copy; - - { - BSONArrayBuilder builder; - builder.append(BSON("dc" << "nyc")); - builder.append(BSON("priority" << "1")); - TagSet original(builder.arr()); - - original.next(); - - copy = new TagSet(original); - } - - ASSERT_FALSE(copy->isExhausted()); - ASSERT(copy->getCurrentTag().equal(BSON("dc" << "nyc"))); - copy->next(); - - ASSERT_FALSE(copy->isExhausted()); - ASSERT(copy->getCurrentTag().equal(BSON("priority" << "1"))); - copy->next(); - - ASSERT(copy->isExhausted()); - - delete copy; - } - - TEST(TagSet, NearestMultiTagsNoMatch) { + TEST(MultiTags, NearestMultiTagsNoMatch) { vector<Node> nodes = NodeSetFixtures::getThreeMemberWithTags(); TagSet tags(TagSetFixtures::getMultiNoMatchTag()); @@ -1398,77 +1371,9 @@ namespace mongo_test { ASSERT(host.empty()); } - TEST(TagSet, SingleTagSet) { - BSONArrayBuilder builder; - builder.append(BSON("dc" << "nyc")); - - TagSet tags(BSONArray(builder.done())); - - ASSERT(!tags.isExhausted()); - ASSERT(tags.getCurrentTag().equal(BSON("dc" << "nyc"))); - - ASSERT(!tags.isExhausted()); - tags.next(); - - ASSERT(tags.isExhausted()); -#if !(defined(_DEBUG) || defined(_DURABLEDEFAULTON) || defined(_DURABLEDEFAULTOFF)) - // TODO: remove this guard once SERVER-6317 is fixed - ASSERT_THROWS(tags.getCurrentTag(), mongo::AssertionException); -#endif - } - - TEST(TagSet, MultiTagSet) { - BSONArrayBuilder builder; - builder.append(BSON("dc" << "nyc")); - builder.append(BSON("dc" << "sf")); - builder.append(BSON("dc" << "ma")); - - TagSet tags(BSONArray(builder.done())); - - ASSERT(!tags.isExhausted()); - ASSERT(tags.getCurrentTag().equal(BSON("dc" << "nyc"))); - - ASSERT(!tags.isExhausted()); - tags.next(); - ASSERT(tags.getCurrentTag().equal(BSON("dc" << "sf"))); - - ASSERT(!tags.isExhausted()); - tags.next(); - ASSERT(tags.getCurrentTag().equal(BSON("dc" << "ma"))); - - ASSERT(!tags.isExhausted()); - tags.next(); - - ASSERT(tags.isExhausted()); -#if !(defined(_DEBUG) || defined(_DURABLEDEFAULTON) || defined(_DURABLEDEFAULTOFF)) - // TODO: remove this guard once SERVER-6317 is fixed - ASSERT_THROWS(tags.getCurrentTag(), mongo::AssertionException); -#endif - } - - TEST(TagSet, EmptyArrayTags) { - BSONArray emptyArray; - TagSet tags(emptyArray); - - ASSERT(tags.isExhausted()); -#if !(defined(_DEBUG) || defined(_DURABLEDEFAULTON) || defined(_DURABLEDEFAULTOFF)) - // TODO: remove this guard once SERVER-6317 is fixed - ASSERT_THROWS(tags.getCurrentTag(), mongo::AssertionException); -#endif - } - - TEST(TagSet, Reset) { - BSONArrayBuilder builder; - builder.append(BSON("dc" << "nyc")); - - TagSet tags(BSONArray(builder.done())); - tags.next(); - ASSERT(tags.isExhausted()); - - tags.reset(); - - ASSERT(!tags.isExhausted()); - ASSERT(tags.getCurrentTag().equal(BSON("dc" << "nyc"))); + TEST(TagSet, DefaultConstructorMatchesAll) { + TagSet tags; + ASSERT_EQUALS(tags.getTagBSON(), BSON_ARRAY(BSONObj())); } @@ -1645,9 +1550,8 @@ namespace mongo_test { replSet->restore(secHost); - TagSet tags(BSON_ARRAY(BSONObj())); HostAndPort node = monitor->getHostOrRefresh( - ReadPreferenceSetting(mongo::ReadPreference_SecondaryOnly, tags)); + ReadPreferenceSetting(mongo::ReadPreference_SecondaryOnly, TagSet())); ASSERT_FALSE(monitor->isPrimary(node)); ASSERT_EQUALS(secHost, node.toString(true)); |