DBClientConnection * DBClientReplicaSet::checkMaster() { ReplicaSetMonitorPtr monitor = _getMonitor(); HostAndPort h = monitor->getMasterOrUassert(); if ( h == _masterHost && _master ) { // a master is selected. let's just make sure connection didn't die if ( ! _master->isFailed() ) return _master.get(); monitor->failedHost( _masterHost ); h = monitor->getMasterOrUassert(); // old master failed, try again. } _masterHost = h; ConnectionString connStr(_masterHost); string errmsg; DBClientConnection* newConn = NULL; try { // Needs to perform a dynamic_cast because we need to set the replSet // callback. We should eventually not need this after we remove the // callback. newConn = dynamic_cast<DBClientConnection*>( connStr.connect(errmsg, _so_timeout)); } catch (const AssertionException& ex) { errmsg = ex.toString(); } if (newConn == NULL || !errmsg.empty()) { monitor->failedHost(_masterHost); uasserted(13639, str::stream() << "can't connect to new replica set master [" << _masterHost.toString() << "]" << (errmsg.empty()? "" : ", err: ") << errmsg); } _master.reset(newConn); _master->setReplSetClientCallback(this); _master->setRunCommandHook(_runCommandHook); _master->setPostRunCommandHook(_postRunCommandHook); _auth( _master.get() ); return _master.get(); }
void DBClientReplicaSet::isntMaster() { log() << "got not master for: " << _masterHost << endl; // 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 ( monitor ) { monitor->failedHost( _masterHost ); } _master.reset(); }
void DBClientConnection::handleNotMasterResponse(const BSONObj& replyBody, StringData errorMsgFieldName) { const BSONElement errorMsgElem = replyBody[errorMsgFieldName]; const BSONElement codeElem = replyBody["code"]; if (!isNotMasterErrorString(errorMsgElem) && !ErrorCodes::isNotMasterError(ErrorCodes::Error(codeElem.numberInt()))) { return; } ReplicaSetMonitorPtr monitor = ReplicaSetMonitor::get(_parentReplSetName); if (monitor) { monitor->failedHost(_serverAddress, {ErrorCodes::NotMaster, str::stream() << "got not master from: " << _serverAddress << " of repl set: " << _parentReplSetName}); } _markFailed(kSetFlag); }
// Ensure nothing breaks when out-of-band failedHost is called during scan TEST(ReplicaSetMonitorTests, OutOfBandFailedHost) { SetStatePtr state = boost::make_shared<SetState>("name", basicSeedsSet); ReplicaSetMonitorPtr rsm = boost::make_shared<ReplicaSetMonitor>(state); Refresher refresher = rsm->startOrContinueRefresh(); for (size_t i = 0; i != basicSeeds.size(); ++i) { NextStep ns = refresher.getNextStep(); } for (size_t i = 0; i != basicSeeds.size(); ++i) { bool primary = (i == 0); refresher.receivedIsMaster(basicSeeds[i], -1, BSON( "setName" << "name" << "ismaster" << primary << "secondary" << !primary << "hosts" << BSON_ARRAY("a" << "b" << "c") << "ok" << true )); if (i >= 1) { HostAndPort a("a"); rsm->failedHost(a); Node* node = state->findNode(a); ASSERT(node); ASSERT(!node->isUp); ASSERT(!node->isMaster); } else { Node* node = state->findNode(HostAndPort("a")); ASSERT(node); ASSERT(node->isUp); ASSERT(node->isMaster); } } }