diff options
author | Randolph Tan <randolph@10gen.com> | 2013-03-29 16:00:59 -0400 |
---|---|---|
committer | Randolph Tan <randolph@10gen.com> | 2013-04-01 19:17:36 -0400 |
commit | 0502e6aadada1ce1bf5187a44c367714e8c142b2 (patch) | |
tree | 69153262cb8d3abc507db27ab298964ead07370a | |
parent | f1017ee04454faace5997a3604527d3fd6bccda9 (diff) | |
download | mongo-0502e6aadada1ce1bf5187a44c367714e8c142b2.tar.gz |
SERVER-9174 Race condition on read_pref_rs_client.js after reconfig
Replaced js test with cpp unit test that does not rely on reconfig.
-rw-r--r-- | jstests/sharding/read_pref_rs_client.js | 220 | ||||
-rw-r--r-- | src/mongo/client/dbclient_rs_test.cpp | 405 | ||||
-rw-r--r-- | src/mongo/dbtests/mock/mock_remote_db_server.cpp | 2 | ||||
-rw-r--r-- | src/mongo/dbtests/mock/mock_remote_db_server.h | 10 |
4 files changed, 385 insertions, 252 deletions
diff --git a/jstests/sharding/read_pref_rs_client.js b/jstests/sharding/read_pref_rs_client.js deleted file mode 100644 index 8a458101aa2..00000000000 --- a/jstests/sharding/read_pref_rs_client.js +++ /dev/null @@ -1,220 +0,0 @@ -/** - * Testing read preference on DBClientReplicaSets, specifically on the auto-retry - * and automatic failover selection - */ -// NOTE: this test is skipped when running smoke.py with --auth because of SERVER-6972 - -function basicTest() { - var replTest = new ReplSetTest({ name: 'basic', nodes: 2, useHostName: true }); - replTest.startSet({ oplogSize: 1 }); - replTest.initiate(); - replTest.awaitSecondaryNodes(); - - var PRI_HOST = replTest.getPrimary().host; - var SEC_HOST = replTest.getSecondary().host; - - var replConn = new Mongo(replTest.getURL()); - var coll = replConn.getDB('test').user; - var dest = coll.find().readPref('primary').explain().server; - assert.eq(PRI_HOST, dest); - - // Create brand new connection to make sure that the last cached is not used - replConn = new Mongo(replTest.getURL()); - coll = replConn.getDB('test').user; - dest = coll.find().readPref('secondary').explain().server; - assert.eq(SEC_HOST, dest); - - replConn = new Mongo(replTest.getURL()); - coll = replConn.getDB('test').user; - dest = coll.find().readPref('primaryPreferred').explain().server; - assert.eq(PRI_HOST, dest); - - replConn = new Mongo(replTest.getURL()); - coll = replConn.getDB('test').user; - dest = coll.find().readPref('secondaryPreferred').explain().server; - assert.eq(SEC_HOST, dest); - - replConn = new Mongo(replTest.getURL()); - coll = replConn.getDB('test').user; - // just make sure that it doesn't throw - coll.find().readPref('nearest').explain(); - - replTest.stopSet(); -} - -function noPriNoSecTest() { - var replTest = new ReplSetTest({ name: 'noPriNoSec', useHostName: true, - nodes: [{}, { arbiter: true }, { arbiter: true }]}); - replTest.startSet({ oplogSize: 1 }); - replTest.initiate(); - replTest.awaitSecondaryNodes(); - - var replConn = new Mongo(replTest.getURL()); - var coll = replConn.getDB('test').user; - - replTest.stop(0); - - assert.throws(function() { - coll.find().readPref('primary').explain(); - }); - - // Make sure that it still fails even when trying to refresh - assert.throws(function() { - coll.find().readPref('primary').explain(); - }); - - // Don't need to create new connection because failed connections - // would never be reused, and also becasue the js Mongo contructor - // will throw when it can't connect to a primary - assert.throws(function() { - coll.find().readPref('secondary').explain(); - }); - - assert.throws(function() { - coll.find().readPref('secondary').explain(); - }); - - assert.throws(function() { - coll.find().readPref('primaryPreferred').explain(); - }); - - assert.throws(function() { - coll.find().readPref('primaryPreferred').explain(); - }); - - assert.throws(function() { - coll.find().readPref('secondaryPreferred').explain(); - }); - - assert.throws(function() { - coll.find().readPref('secondaryPreferred').explain(); - }); - - assert.throws(function() { - coll.find().readPref('neareset').explain(); - }); - - assert.throws(function() { - coll.find().readPref('nearest').explain(); - }); - - replTest.stopSet(); -} - -function priOkNoSecTest() { - var replTest = new ReplSetTest({ name: 'priOkNoSec', useHostName: true, - nodes: [{}, { arbiter: true }, {}]}); - replTest.startSet({ oplogSize: 1 }); - replTest.initiate(); - replTest.awaitSecondaryNodes(); - - var replConn = new Mongo(replTest.getURL()); - var coll = replConn.getDB('test').user; - - replTest.stop(2); - - var PRI_HOST = replTest.getPrimary().host; - - var dest = coll.find().readPref('primary').explain().server; - assert.eq(PRI_HOST, dest); - - replConn = new Mongo(replTest.getURL()); - coll = replConn.getDB('test').user; - dest = coll.find().readPref('primaryPreferred').explain().server; - assert.eq(PRI_HOST, dest); - - replConn = new Mongo(replTest.getURL()); - coll = replConn.getDB('test').user; - assert.throws(function() { - coll.find().readPref('secondary').explain(); - }); - - assert.throws(function() { - coll.find().readPref('secondary').explain(); - }); - - replConn = new Mongo(replTest.getURL()); - coll = replConn.getDB('test').user; - dest = coll.find().readPref('secondaryPreferred').explain().server; - assert.eq(PRI_HOST, dest); - - replConn = new Mongo(replTest.getURL()); - coll = replConn.getDB('test').user; - dest = coll.find().readPref('nearest').explain().server; - assert.eq(PRI_HOST, dest); - - replTest.stopSet(); -} - -function noPriSecOkTest() { - var replTest = new ReplSetTest({ name: 'noPriSecOk', useHostName: true, - nodes: [{ }, { arbiter: true }, { }]}); - replTest.startSet({ oplogSize: 1 }); - replTest.initiate(); - replTest.awaitSecondaryNodes(); - - var priConn = replTest.getPrimary(); - var conf = priConn.getDB('local').system.replset.findOne(); - conf.version++; - conf.members[0].priority = 99; - conf.members[2].priority = 0; - - var SEC_HOST = replTest.nodes[2].host; - - try { - priConn.getDB('admin').runCommand({ replSetReconfig: conf }); - } catch (x) { - print('Exception from reconfig: ' + x); - } - - var replConn = new Mongo(replTest.getURL()); - var coll = replConn.getDB('test').user; - - replTest.stop(0); - - assert.throws(function() { - coll.find().readPref('primary').explain(); - }); - - // Make sure that it still fails even when trying to refresh - assert.throws(function() { - coll.find().readPref('primary').explain(); - }); - - replConn = new Mongo(replTest.getURL()); - coll = replConn.getDB('test').user; - var dest = coll.find().readPref('primaryPreferred').explain().server; - assert.eq(SEC_HOST, dest); - - replTest.start(0, {}, true); - replTest.awaitSecondaryNodes(); - replConn = new Mongo(replTest.getURL()); - replTest.stop(0); - coll = replConn.getDB('test').user; - dest = coll.find().readPref('secondary').explain().server; - assert.eq(SEC_HOST, dest); - - replTest.start(0, {}, true); - replTest.awaitSecondaryNodes(); - replConn = new Mongo(replTest.getURL()); - replTest.stop(0); - coll = replConn.getDB('test').user; - dest = coll.find().readPref('secondaryPreferred').explain().server; - assert.eq(SEC_HOST, dest); - - replTest.start(0, {}, true); - replTest.awaitSecondaryNodes(); - replConn = new Mongo(replTest.getURL()); - replTest.stop(0); - coll = replConn.getDB('test').user; - dest = coll.find().readPref('nearest').explain().server; - assert.eq(SEC_HOST, dest); - - replTest.stopSet(); -} - -basicTest(); -noPriNoSecTest(); -priOkNoSecTest(); -noPriSecOkTest(); - diff --git a/src/mongo/client/dbclient_rs_test.cpp b/src/mongo/client/dbclient_rs_test.cpp index 19e94a0fc9f..ccb7b71063e 100644 --- a/src/mongo/client/dbclient_rs_test.cpp +++ b/src/mongo/client/dbclient_rs_test.cpp @@ -15,7 +15,8 @@ */ /** - * This file contains tests for DBClientReplicaSet. + * This file contains tests for DBClientReplicaSet. The tests mocks the servers + * the DBClientReplicaSet talks to, so the tests only covers the client side logic. */ #include "mongo/bson/bson_field.h" @@ -25,35 +26,13 @@ #include "mongo/dbtests/mock/mock_conn_registry.h" #include "mongo/dbtests/mock/mock_replica_set.h" #include "mongo/unittest/unittest.h" +#include "mongo/util/assert_util.h" #include <map> #include <memory> #include <string> #include <vector> -using std::auto_ptr; -using std::map; -using std::make_pair; -using std::pair; -using std::string; -using std::vector; -using boost::scoped_ptr; - -using mongo::BSONField; -using mongo::BSONObj; -using mongo::BSONArray; -using mongo::BSONElement; -using mongo::ConnectionString; -using mongo::DBClientCursor; -using mongo::DBClientReplicaSet; -using mongo::HostAndPort; -using mongo::MockReplicaSet; -using mongo::Query; -using mongo::ReadPreference; -using mongo::ReplicaSetMonitor; -using mongo::ScopedDbConnection; -using mongo::TagSet; - namespace mongo { // Symbols defined to build the binary correctly. CmdLine cmdLine; @@ -73,16 +52,373 @@ namespace mongo { } } -namespace mongo_test { +namespace { + using boost::scoped_ptr; + using std::auto_ptr; + using std::map; + using std::make_pair; + using std::pair; + using std::string; + using std::vector; + + using mongo::AssertionException; + using mongo::BSONArray; + using mongo::BSONElement; + using mongo::BSONField; + using mongo::BSONObj; + using mongo::ConnectionString; + using mongo::DBClientCursor; + using mongo::DBClientReplicaSet; + using mongo::HostAndPort; + using mongo::HostField; + using mongo::IdentityNS; + using mongo::MockReplicaSet; + using mongo::Query; + using mongo::ReadPreference; + using mongo::ReplicaSetMonitor; + using mongo::ScopedDbConnection; + using mongo::TagSet; + + /** + * Basic fixture with one primary and one secondary. + */ + class BasicRS: public mongo::unittest::Test { + protected: + void setUp() { + _replSet.reset(new MockReplicaSet("test", 2)); + ConnectionString::setConnectionHook( + mongo::MockConnRegistry::get()->getConnStrHook()); + } + + void tearDown() { + ReplicaSetMonitor::remove(_replSet->getSetName(), true); + _replSet.reset(); + + // TODO: remove this after we remove replSetGetStatus from ReplicaSetMonitor. + mongo::ScopedDbConnection::clearPool(); + } + + MockReplicaSet* getReplSet() { + return _replSet.get(); + } + + private: + boost::scoped_ptr<MockReplicaSet> _replSet; + }; + + TEST_F(BasicRS, ReadFromPrimary) { + MockReplicaSet* replSet = getReplSet(); + DBClientReplicaSet replConn(replSet->getSetName(), replSet->getHosts()); + + Query query; + query.readPref(mongo::ReadPreference_PrimaryOnly, BSONArray()); + + // Note: IdentityNS contains the name of the server. + auto_ptr<DBClientCursor> cursor = replConn.query(IdentityNS, query); + BSONObj doc = cursor->next(); + ASSERT_EQUALS(replSet->getPrimary(), doc[HostField.name()].str()); + } + + TEST_F(BasicRS, SecondaryOnly) { + MockReplicaSet* replSet = getReplSet(); + DBClientReplicaSet replConn(replSet->getSetName(), replSet->getHosts()); + + Query query; + query.readPref(mongo::ReadPreference_SecondaryOnly, BSONArray()); + + // Note: IdentityNS contains the name of the server. + auto_ptr<DBClientCursor> cursor = replConn.query(IdentityNS, query); + BSONObj doc = cursor->next(); + ASSERT_EQUALS(replSet->getSecondaries().front(), doc[HostField.name()].str()); + } + + TEST_F(BasicRS, PrimaryPreferred) { + MockReplicaSet* replSet = getReplSet(); + DBClientReplicaSet replConn(replSet->getSetName(), replSet->getHosts()); + + Query query; + query.readPref(mongo::ReadPreference_PrimaryPreferred, BSONArray()); + + // Note: IdentityNS contains the name of the server. + auto_ptr<DBClientCursor> cursor = replConn.query(IdentityNS, query); + BSONObj doc = cursor->next(); + ASSERT_EQUALS(replSet->getPrimary(), doc[HostField.name()].str()); + } + + TEST_F(BasicRS, SecondaryPreferred) { + MockReplicaSet* replSet = getReplSet(); + DBClientReplicaSet replConn(replSet->getSetName(), replSet->getHosts()); + + Query query; + query.readPref(mongo::ReadPreference_SecondaryPreferred, BSONArray()); + + // Note: IdentityNS contains the name of the server. + auto_ptr<DBClientCursor> cursor = replConn.query(IdentityNS, query); + BSONObj doc = cursor->next(); + ASSERT_EQUALS(replSet->getSecondaries().front(), doc[HostField.name()].str()); + } + + /** + * Setup for 2 member replica set will all of the nodes down. + */ + class AllNodesDown: public mongo::unittest::Test { + protected: + void setUp() { + _replSet.reset(new MockReplicaSet("test", 2)); + ConnectionString::setConnectionHook( + mongo::MockConnRegistry::get()->getConnStrHook()); + + vector<HostAndPort> hostList(_replSet->getHosts()); + for (vector<HostAndPort>::const_iterator iter = hostList.begin(); + iter != hostList.end(); ++iter) { + _replSet->kill(iter->toString(true)); + } + } + + void tearDown() { + ReplicaSetMonitor::remove(_replSet->getSetName(), true); + _replSet.reset(); + + // TODO: remove this after we remove replSetGetStatus from ReplicaSetMonitor. + mongo::ScopedDbConnection::clearPool(); + } + + MockReplicaSet* getReplSet() { + return _replSet.get(); + } + + private: + boost::scoped_ptr<MockReplicaSet> _replSet; + }; + + TEST_F(AllNodesDown, ReadFromPrimary) { + MockReplicaSet* replSet = getReplSet(); + DBClientReplicaSet replConn(replSet->getSetName(), replSet->getHosts()); + + Query query; + query.readPref(mongo::ReadPreference_PrimaryOnly, BSONArray()); + ASSERT_THROWS(replConn.query(IdentityNS, query), AssertionException); + } + + TEST_F(AllNodesDown, SecondaryOnly) { + MockReplicaSet* replSet = getReplSet(); + DBClientReplicaSet replConn(replSet->getSetName(), replSet->getHosts()); + + Query query; + query.readPref(mongo::ReadPreference_SecondaryOnly, BSONArray()); + ASSERT_THROWS(replConn.query(IdentityNS, query), AssertionException); + } + + TEST_F(AllNodesDown, PrimaryPreferred) { + MockReplicaSet* replSet = getReplSet(); + DBClientReplicaSet replConn(replSet->getSetName(), replSet->getHosts()); + + Query query; + query.readPref(mongo::ReadPreference_PrimaryPreferred, BSONArray()); + ASSERT_THROWS(replConn.query(IdentityNS, query), AssertionException); + } + + TEST_F(AllNodesDown, SecondaryPreferred) { + MockReplicaSet* replSet = getReplSet(); + DBClientReplicaSet replConn(replSet->getSetName(), replSet->getHosts()); + + Query query; + query.readPref(mongo::ReadPreference_SecondaryPreferred, BSONArray()); + ASSERT_THROWS(replConn.query(IdentityNS, query), AssertionException); + } + + TEST_F(AllNodesDown, Nearest) { + MockReplicaSet* replSet = getReplSet(); + DBClientReplicaSet replConn(replSet->getSetName(), replSet->getHosts()); + + Query query; + query.readPref(mongo::ReadPreference_Nearest, BSONArray()); + ASSERT_THROWS(replConn.query(IdentityNS, query), AssertionException); + } + + /** + * Setup for 2 member replica set with the primary down. + */ + class PrimaryDown: public mongo::unittest::Test { + protected: + void setUp() { + _replSet.reset(new MockReplicaSet("test", 2)); + ConnectionString::setConnectionHook( + mongo::MockConnRegistry::get()->getConnStrHook()); + _replSet->kill(_replSet->getPrimary()); + } + + void tearDown() { + ReplicaSetMonitor::remove(_replSet->getSetName(), true); + _replSet.reset(); + + // TODO: remove this after we remove replSetGetStatus from ReplicaSetMonitor. + mongo::ScopedDbConnection::clearPool(); + } + + MockReplicaSet* getReplSet() { + return _replSet.get(); + } + + private: + boost::scoped_ptr<MockReplicaSet> _replSet; + }; + + TEST_F(PrimaryDown, ReadFromPrimary) { + MockReplicaSet* replSet = getReplSet(); + DBClientReplicaSet replConn(replSet->getSetName(), replSet->getHosts()); + + Query query; + query.readPref(mongo::ReadPreference_PrimaryOnly, BSONArray()); + ASSERT_THROWS(replConn.query(IdentityNS, query), AssertionException); + } + + TEST_F(PrimaryDown, SecondaryOnly) { + MockReplicaSet* replSet = getReplSet(); + DBClientReplicaSet replConn(replSet->getSetName(), replSet->getHosts()); + + Query query; + query.readPref(mongo::ReadPreference_SecondaryOnly, BSONArray()); + + // Note: IdentityNS contains the name of the server. + auto_ptr<DBClientCursor> cursor = replConn.query(IdentityNS, query); + BSONObj doc = cursor->next(); + ASSERT_EQUALS(replSet->getSecondaries().front(), doc[HostField.name()].str()); + } + + TEST_F(PrimaryDown, PrimaryPreferred) { + MockReplicaSet* replSet = getReplSet(); + DBClientReplicaSet replConn(replSet->getSetName(), replSet->getHosts()); + + Query query; + query.readPref(mongo::ReadPreference_PrimaryPreferred, BSONArray()); + + // Note: IdentityNS contains the name of the server. + auto_ptr<DBClientCursor> cursor = replConn.query(IdentityNS, query); + BSONObj doc = cursor->next(); + ASSERT_EQUALS(replSet->getSecondaries().front(), doc[HostField.name()].str()); + } + + TEST_F(PrimaryDown, SecondaryPreferred) { + MockReplicaSet* replSet = getReplSet(); + DBClientReplicaSet replConn(replSet->getSetName(), replSet->getHosts()); + + Query query; + query.readPref(mongo::ReadPreference_SecondaryPreferred, BSONArray()); + + // Note: IdentityNS contains the name of the server. + auto_ptr<DBClientCursor> cursor = replConn.query(IdentityNS, query); + BSONObj doc = cursor->next(); + ASSERT_EQUALS(replSet->getSecondaries().front(), doc[HostField.name()].str()); + } + + TEST_F(PrimaryDown, Nearest) { + MockReplicaSet* replSet = getReplSet(); + DBClientReplicaSet replConn(replSet->getSetName(), replSet->getHosts()); + + Query query; + query.readPref(mongo::ReadPreference_Nearest, BSONArray()); + auto_ptr<DBClientCursor> cursor = replConn.query(IdentityNS, query); + BSONObj doc = cursor->next(); + ASSERT_EQUALS(replSet->getSecondaries().front(), doc[HostField.name()].str()); + } + + /** + * Setup for 2 member replica set with the secondary down. + */ + class SecondaryDown: public mongo::unittest::Test { + protected: + void setUp() { + _replSet.reset(new MockReplicaSet("test", 2)); + ConnectionString::setConnectionHook( + mongo::MockConnRegistry::get()->getConnStrHook()); + + _replSet->kill(_replSet->getSecondaries().front()); + } + + void tearDown() { + ReplicaSetMonitor::remove(_replSet->getSetName(), true); + _replSet.reset(); + + // TODO: remove this after we remove replSetGetStatus from ReplicaSetMonitor. + mongo::ScopedDbConnection::clearPool(); + } + + MockReplicaSet* getReplSet() { + return _replSet.get(); + } + + private: + boost::scoped_ptr<MockReplicaSet> _replSet; + }; + + TEST_F(SecondaryDown, ReadFromPrimary) { + MockReplicaSet* replSet = getReplSet(); + DBClientReplicaSet replConn(replSet->getSetName(), replSet->getHosts()); + + Query query; + query.readPref(mongo::ReadPreference_PrimaryOnly, BSONArray()); + + // Note: IdentityNS contains the name of the server. + auto_ptr<DBClientCursor> cursor = replConn.query(IdentityNS, query); + BSONObj doc = cursor->next(); + ASSERT_EQUALS(replSet->getPrimary(), doc[HostField.name()].str()); + } + + TEST_F(SecondaryDown, SecondaryOnly) { + MockReplicaSet* replSet = getReplSet(); + DBClientReplicaSet replConn(replSet->getSetName(), replSet->getHosts()); + + Query query; + query.readPref(mongo::ReadPreference_SecondaryOnly, BSONArray()); + ASSERT_THROWS(replConn.query(IdentityNS, query), AssertionException); + } + + TEST_F(SecondaryDown, PrimaryPreferred) { + MockReplicaSet* replSet = getReplSet(); + DBClientReplicaSet replConn(replSet->getSetName(), replSet->getHosts()); + + Query query; + query.readPref(mongo::ReadPreference_PrimaryPreferred, BSONArray()); + + // Note: IdentityNS contains the name of the server. + auto_ptr<DBClientCursor> cursor = replConn.query(IdentityNS, query); + BSONObj doc = cursor->next(); + ASSERT_EQUALS(replSet->getPrimary(), doc[HostField.name()].str()); + } + + TEST_F(SecondaryDown, SecondaryPreferred) { + MockReplicaSet* replSet = getReplSet(); + DBClientReplicaSet replConn(replSet->getSetName(), replSet->getHosts()); + + Query query; + query.readPref(mongo::ReadPreference_SecondaryPreferred, BSONArray()); + + // Note: IdentityNS contains the name of the server. + auto_ptr<DBClientCursor> cursor = replConn.query(IdentityNS, query); + BSONObj doc = cursor->next(); + ASSERT_EQUALS(replSet->getPrimary(), doc[HostField.name()].str()); + } + + TEST_F(SecondaryDown, Nearest) { + MockReplicaSet* replSet = getReplSet(); + DBClientReplicaSet replConn(replSet->getSetName(), replSet->getHosts()); + + Query query; + query.readPref(mongo::ReadPreference_Nearest, BSONArray()); + + // Note: IdentityNS contains the name of the server. + auto_ptr<DBClientCursor> cursor = replConn.query(IdentityNS, query); + BSONObj doc = cursor->next(); + ASSERT_EQUALS(replSet->getPrimary(), doc[HostField.name()].str()); + } + /** * Warning: Tests running this fixture cannot be run in parallel with other tests * that uses ConnectionString::setConnectionHook */ class TaggedFiveMemberRS: public mongo::unittest::Test { protected: - static const string IdentityNS; - static const BSONField<string> HostField; - void setUp() { _replSet.reset(new MockReplicaSet("test", 5)); _originalConnectionHook = ConnectionString::getConnectionHook(); @@ -153,6 +489,8 @@ namespace mongo_test { ConnectionString::setConnectionHook(_originalConnectionHook); ReplicaSetMonitor::remove(_replSet->getSetName(), true); _replSet.reset(); + + // TODO: remove this after we remove replSetGetStatus from ReplicaSetMonitor. mongo::ScopedDbConnection::clearPool(); } @@ -165,9 +503,6 @@ namespace mongo_test { boost::scoped_ptr<MockReplicaSet> _replSet; }; - const string TaggedFiveMemberRS::IdentityNS("local.me"); - const BSONField<string> TaggedFiveMemberRS::HostField("host", "bad"); - TEST_F(TaggedFiveMemberRS, ConnShouldPinIfSameSettings) { MockReplicaSet* replSet = getReplSet(); vector<HostAndPort> seedList; @@ -179,6 +514,8 @@ namespace mongo_test { { Query query; query.readPref(mongo::ReadPreference_PrimaryPreferred, BSONArray()); + + // Note: IdentityNS contains the name of the server. auto_ptr<DBClientCursor> cursor = replConn.query(IdentityNS, query); BSONObj doc = cursor->next(); dest = doc[HostField.name()].str(); @@ -205,6 +542,8 @@ namespace mongo_test { { Query query; query.readPref(mongo::ReadPreference_SecondaryPreferred, BSONArray()); + + // Note: IdentityNS contains the name of the server. auto_ptr<DBClientCursor> cursor = replConn.query(IdentityNS, query); BSONObj doc = cursor->next(); dest = doc[HostField.name()].str(); @@ -233,6 +572,8 @@ namespace mongo_test { Query query; query.readPref(mongo::ReadPreference_SecondaryPreferred, BSON_ARRAY(BSON("dc" << "sf"))); + + // Note: IdentityNS contains the name of the server. auto_ptr<DBClientCursor> cursor = replConn.query(IdentityNS, query); BSONObj doc = cursor->next(); dest = doc[HostField.name()].str(); @@ -261,6 +602,8 @@ namespace mongo_test { string dest; mongo::DBClientConnection& secConn = replConn.slaveConn(); + + // Note: IdentityNS contains the name of the server. auto_ptr<DBClientCursor> cursor = secConn.query(IdentityNS, Query()); BSONObj doc = cursor->next(); dest = doc[HostField.name()].str(); diff --git a/src/mongo/dbtests/mock/mock_remote_db_server.cpp b/src/mongo/dbtests/mock/mock_remote_db_server.cpp index e78d245c70c..9d8506b37ba 100644 --- a/src/mongo/dbtests/mock/mock_remote_db_server.cpp +++ b/src/mongo/dbtests/mock/mock_remote_db_server.cpp @@ -24,6 +24,7 @@ using std::string; using std::vector; namespace mongo { + MockRemoteDBServer::CircularBSONIterator::CircularBSONIterator( const vector<BSONObj>& replyVector) { for (std::vector<mongo::BSONObj>::const_iterator iter = replyVector.begin(); @@ -54,6 +55,7 @@ namespace mongo { _cmdCount(0), _queryCount(0), _instanceID(0) { + insert(IdentityNS, BSON(HostField(hostAndPort)), 0); } MockRemoteDBServer::~MockRemoteDBServer() { diff --git a/src/mongo/dbtests/mock/mock_remote_db_server.h b/src/mongo/dbtests/mock/mock_remote_db_server.h index 6aaba91113c..0455e755d07 100644 --- a/src/mongo/dbtests/mock/mock_remote_db_server.h +++ b/src/mongo/dbtests/mock/mock_remote_db_server.h @@ -19,12 +19,17 @@ #include <string> #include <vector> +#include "mongo/bson/bson_field.h" #include "mongo/bson/bsonobjbuilder.h" #include "mongo/client/dbclientinterface.h" #include "mongo/platform/unordered_map.h" #include "mongo/util/concurrency/spin_lock.h" namespace mongo { + + const std::string IdentityNS("local.me"); + const BSONField<string> HostField("host"); + /** * A very simple mock that acts like a database server. Every object keeps track of its own * InstanceID, which initially starts at zero and increments every time it is restarted. @@ -51,6 +56,9 @@ namespace mongo { * 1. hostAndPort of this server should start with $. * 2. No other instance has the same hostAndPort as this. * + * This server will also contain the hostAndPort inside the IdentityNS + * collection. This is convenient for testing query routing. + * * @param hostAndPort the host name with port for this server. * * @see MockConnRegistry @@ -70,7 +78,7 @@ namespace mongo { /** * Shuts down this server. Any operations on this server with an InstanceID * less than or equal to the current one will throw a mongo::SocketException. - * To bring the server up again, use the #reboot method. + * To bring the server up again, use the reboot method. */ void shutdown(); |