summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/mongo/client/dbclient_rs.cpp76
-rw-r--r--src/mongo/client/dbclient_rs.h69
-rw-r--r--src/mongo/client/replica_set_monitor.cpp3
-rw-r--r--src/mongo/client/replica_set_monitor_test.cpp3
-rw-r--r--src/mongo/dbtests/replica_set_monitor_test.cpp106
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));