summaryrefslogtreecommitdiff
path: root/src/mongo/dbtests/replica_set_monitor_test.cpp
diff options
context:
space:
mode:
authorRandolph Tan <randolph@10gen.com>2013-06-24 17:35:57 -0400
committerRandolph Tan <randolph@10gen.com>2013-06-25 09:56:37 -0400
commit6d27da0887b286c421751afc5e5cf573101c1eb8 (patch)
treebe443774406b383f1ba41716deae945ae6665840 /src/mongo/dbtests/replica_set_monitor_test.cpp
parent76803bccc0206503b1641fe4222c90bcb82331d0 (diff)
downloadmongo-6d27da0887b286c421751afc5e5cf573101c1eb8.tar.gz
SERVER-10006 Secondary read pref with tag can end up selecting no nodes on retry
Reset the TagSet iterator to point to initial position before attempting to retry node selection logic.
Diffstat (limited to 'src/mongo/dbtests/replica_set_monitor_test.cpp')
-rw-r--r--src/mongo/dbtests/replica_set_monitor_test.cpp114
1 files changed, 114 insertions, 0 deletions
diff --git a/src/mongo/dbtests/replica_set_monitor_test.cpp b/src/mongo/dbtests/replica_set_monitor_test.cpp
index ac1b37849d7..77eed10e7ff 100644
--- a/src/mongo/dbtests/replica_set_monitor_test.cpp
+++ b/src/mongo/dbtests/replica_set_monitor_test.cpp
@@ -28,6 +28,7 @@
#include <vector>
+using std::map;
using std::vector;
using std::string;
using boost::scoped_ptr;
@@ -1514,6 +1515,20 @@ namespace mongo_test {
#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")));
+ }
+
// TODO: Port these existing tests here: replmonitor_bad_seed.js, repl_monitor_refresh.js
/**
@@ -1615,4 +1630,103 @@ namespace mongo_test {
ConnectionString::setConnectionHook(originalConnHook);
mongo::ScopedDbConnection::clearPool();
}
+
+ /**
+ * Warning: Tests running this fixture cannot be run in parallel with other tests
+ * that use ConnectionString::setConnectionHook.
+ */
+ class TwoNodeWithTags: public mongo::unittest::Test {
+ protected:
+ void setUp() {
+ _replSet.reset(new MockReplicaSet("test", 2));
+ _originalConnectionHook = ConnectionString::getConnectionHook();
+ ConnectionString::setConnectionHook(
+ mongo::MockConnRegistry::get()->getConnStrHook());
+
+ mongo::MockReplicaSet::ReplConfigMap config = _replSet->getReplConfig();
+
+ {
+ const string host(_replSet->getPrimary());
+ map<string, string>& tag = config[host].tags;
+ tag.clear();
+ tag["dc"] = "ny";
+ tag["num"] = "1";
+ }
+
+ {
+ const string host(_replSet->getSecondaries().front());
+ map<string, string>& tag = config[host].tags;
+ tag.clear();
+ tag["dc"] = "ny";
+ tag["num"] = "2";
+ }
+
+ _replSet->setConfig(config);
+
+ }
+
+ void tearDown() {
+ ConnectionString::setConnectionHook(_originalConnectionHook);
+ ReplicaSetMonitor::remove(_replSet->getSetName(), true);
+ _replSet.reset();
+ }
+
+ MockReplicaSet* getReplSet() {
+ return _replSet.get();
+ }
+
+ private:
+ ConnectionString::ConnectionHook* _originalConnectionHook;
+ boost::scoped_ptr<MockReplicaSet> _replSet;
+ };
+
+ // Tests the node selection retry logic when the connection went bad.
+ TEST_F(TwoNodeWithTags, SecDownRetryNoTag) {
+ MockReplicaSet* replSet = getReplSet();
+
+ vector<HostAndPort> seedList;
+ seedList.push_back(HostAndPort(replSet->getPrimary()));
+ ReplicaSetMonitor::createIfNeeded(replSet->getSetName(), seedList);
+
+ const string secHost(replSet->getSecondaries().front());
+ replSet->kill(secHost);
+
+ ReplicaSetMonitorPtr monitor = ReplicaSetMonitor::get(replSet->getSetName());
+ // Make sure monitor sees the dead secondary
+ monitor->check();
+
+ replSet->restore(secHost);
+
+ TagSet tags(BSON_ARRAY(BSONObj()));
+ bool isPrimary;
+ HostAndPort node = monitor->selectAndCheckNode(mongo::ReadPreference_SecondaryOnly,
+ &tags, &isPrimary);
+ ASSERT_FALSE(isPrimary);
+ ASSERT_EQUALS(secHost, node.toString(true));
+ }
+
+ // Tests the node selection retry logic with tags when the connection went bad.
+ TEST_F(TwoNodeWithTags, SecDownRetryWithTag) {
+ MockReplicaSet* replSet = getReplSet();
+
+ vector<HostAndPort> seedList;
+ seedList.push_back(HostAndPort(replSet->getPrimary()));
+ ReplicaSetMonitor::createIfNeeded(replSet->getSetName(), seedList);
+
+ const string secHost(replSet->getSecondaries().front());
+ replSet->kill(secHost);
+
+ ReplicaSetMonitorPtr monitor = ReplicaSetMonitor::get(replSet->getSetName());
+ // Make sure monitor sees the dead secondary
+ monitor->check();
+
+ replSet->restore(secHost);
+
+ TagSet tags(BSON_ARRAY(BSON("dc" << "ny")));
+ bool isPrimary;
+ HostAndPort node = monitor->selectAndCheckNode(mongo::ReadPreference_SecondaryOnly,
+ &tags, &isPrimary);
+ ASSERT_FALSE(isPrimary);
+ ASSERT_EQUALS(secHost, node.toString(true));
+ }
}