summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRandolph Tan <randolph@10gen.com>2012-09-24 13:58:00 -0400
committerEric Milkie <milkie@10gen.com>2012-11-06 15:41:16 -0500
commit67d9b0daa4f444661cf846d07f6a97dfbd03e012 (patch)
tree87709741d2e90684441962bc2cbe159fee664ab3
parentc5bfd792bd6b53ebb753784d3786a7afeb4ccfbb (diff)
downloadmongo-67d9b0daa4f444661cf846d07f6a97dfbd03e012.tar.gz
SERVER-7111 DBClientReplicaSet::connect should not assert if primary is down but secondaries are available
-rw-r--r--jstests/sharding/read_pref_rs_client.js5
-rw-r--r--src/mongo/client/dbclient_rs.cpp27
-rw-r--r--src/mongo/client/dbclient_rs.h16
3 files changed, 26 insertions, 22 deletions
diff --git a/jstests/sharding/read_pref_rs_client.js b/jstests/sharding/read_pref_rs_client.js
index df9a7ee1327..af7eac5d09a 100644
--- a/jstests/sharding/read_pref_rs_client.js
+++ b/jstests/sharding/read_pref_rs_client.js
@@ -180,12 +180,7 @@ function noPriSecOkTest() {
coll.find().readPref('primary').explain();
});
- // Needs to restart server, otherwise the js Mongo constructor
- // would throw because it can't find the primary
- replTest.start(0, {}, true);
- replTest.awaitSecondaryNodes();
replConn = new Mongo(replTest.getURL());
- replTest.stop(0);
coll = replConn.getDB('test').user;
var dest = coll.find().readPref('primaryPreferred').explain().server;
assert.eq(SEC_HOST, dest);
diff --git a/src/mongo/client/dbclient_rs.cpp b/src/mongo/client/dbclient_rs.cpp
index 8e00958403a..657731c40f0 100644
--- a/src/mongo/client/dbclient_rs.cpp
+++ b/src/mongo/client/dbclient_rs.cpp
@@ -1163,6 +1163,19 @@ namespace mongo {
_check(true);
}
+ bool ReplicaSetMonitor::isAnyNodeOk() const {
+ scoped_lock lock(_lock);
+
+ for (vector<Node>::const_iterator iter = _nodes.begin();
+ iter != _nodes.end(); ++iter) {
+ if (iter->ok) {
+ return true;
+ }
+ }
+
+ return false;
+ }
+
bool ReplicaSetMonitor::Node::matchesTag(const BSONObj& tag) const {
if (tag.isEmpty()) {
return true;
@@ -1347,19 +1360,7 @@ namespace mongo {
}
bool DBClientReplicaSet::connect() {
- try {
- checkMaster();
- }
- catch (AssertionException&) {
- // Can't use _getMonitor because that will create a new monitor from the cached seed if
- // the monitor doesn't exist.
- ReplicaSetMonitorPtr monitor = ReplicaSetMonitor::get(_setName);
- if (_master && monitor ) {
- monitor->notifyFailure(_masterHost);
- }
- return false;
- }
- return true;
+ return _getMonitor()->isAnyNodeOk();
}
bool DBClientReplicaSet::auth(const string &dbname, const string &username, const string &pwd, string& errmsg, bool digestPassword, Auth::Level * level) {
diff --git a/src/mongo/client/dbclient_rs.h b/src/mongo/client/dbclient_rs.h
index 213ee0dad25..79d604384d8 100644
--- a/src/mongo/client/dbclient_rs.h
+++ b/src/mongo/client/dbclient_rs.h
@@ -262,6 +262,14 @@ namespace mongo {
bool isHostCompatible(const HostAndPort& host, ReadPreference readPreference,
const TagSet* tagSet) const;
+ /**
+ * Performs a quick check if at least one node is up based on the cached
+ * view of the set.
+ *
+ * @return true if any node is ok
+ */
+ bool isAnyNodeOk() const;
+
private:
/**
* This populates a list of hosts from the list of seeds (discarding the
@@ -405,10 +413,10 @@ namespace mongo {
DBClientReplicaSet( const string& name , const vector<HostAndPort>& servers, double so_timeout=0 );
virtual ~DBClientReplicaSet();
- /** Returns false if nomember of the set were reachable, or neither is
- * master, although,
- * when false returned, you can still try to use this connection object, it will
- * try reconnects.
+ /**
+ * Returns false if no member of the set were reachable. This object
+ * can still be used even when false was returned as it will try to
+ * reconnect when you use it later.
*/
bool connect();