void SyncClusterConnection::_connect(const std::string& hostStr) { log() << "SyncClusterConnection connecting to [" << hostStr << "]" << endl; const HostAndPort host(hostStr); DBClientConnection* c; if (connectionHook) { c = new DBClientConnection( true, // auto reconnect 0, // socket timeout [this, host](const executor::RemoteCommandResponse& isMasterReply) { return connectionHook(host, isMasterReply); }); } else { c = new DBClientConnection(true); } c->setRequestMetadataWriter(getRequestMetadataWriter()); c->setReplyMetadataReader(getReplyMetadataReader()); c->setSoTimeout(_socketTimeout); Status status = c->connect(host); if (!status.isOK()) { log() << "SyncClusterConnection connect fail to: " << hostStr << causedBy(status); if (status == ErrorCodes::IncompatibleCatalogManager) { // Make sure to propagate IncompatibleCatalogManager errors to trigger catalog manager // swapping. uassertStatusOK(status); } } _connAddresses.push_back(hostStr); _conns.push_back(c); }
bool isSelf(const HostAndPort& hostAndPort, ServiceContext* const ctx) { // Fastpath: check if the host&port in question is bound to one // of the interfaces on this machine. // No need for ip match if the ports do not match if (hostAndPort.port() == serverGlobalParams.port) { std::vector<std::string> myAddrs = serverGlobalParams.bind_ips; // If any of the bound addresses is the default route (0.0.0.0 on IPv4) it means we are // listening on all network interfaces and need to check against any of them. if (myAddrs.empty() || std::any_of(myAddrs.cbegin(), myAddrs.cend(), [](std::string const& addrStr) { return HostAndPort(addrStr, serverGlobalParams.port).isDefaultRoute(); })) { myAddrs = getBoundAddrs(IPv6Enabled()); } const std::vector<std::string> hostAddrs = getAddrsForHost(hostAndPort.host(), hostAndPort.port(), IPv6Enabled()); for (std::vector<std::string>::const_iterator i = myAddrs.begin(); i != myAddrs.end(); ++i) { for (std::vector<std::string>::const_iterator j = hostAddrs.begin(); j != hostAddrs.end(); ++j) { if (*i == *j) { return true; } } } } ctx->waitForStartupComplete(); try { DBClientConnection conn; conn.setSoTimeout(30); // 30 second timeout // We need to avoid the isMaster call triggered by a normal connect, which would // cause a deadlock. 'isSelf' is called by the Replication Coordinator when validating // a replica set configuration document, but the 'isMaster' command requires a lock on the // replication coordinator to execute. As such we call we call 'connectSocketOnly', which // does not call 'isMaster'. if (!conn.connectSocketOnly(hostAndPort).isOK()) { return false; } if (auth::isInternalAuthSet() && !conn.authenticateInternalUser().isOK()) { return false; } BSONObj out; bool ok = conn.simpleCommand("admin", &out, "_isSelf"); bool me = ok && out["id"].type() == jstOID && instanceId == out["id"].OID(); return me; } catch (const std::exception& e) { warning() << "couldn't check isSelf (" << hostAndPort << ") " << e.what() << std::endl; } return false; }
void SyncClusterConnection::_connect( const std::string& host ) { log() << "SyncClusterConnection connecting to [" << host << "]" << endl; DBClientConnection * c = new DBClientConnection( true ); c->setSoTimeout( _socketTimeout ); string errmsg; if ( ! c->connect( host , errmsg ) ) log() << "SyncClusterConnection connect fail to: " << host << " errmsg: " << errmsg << endl; _connAddresses.push_back( host ); _conns.push_back( c ); }
void SyncClusterConnection::_connect(const std::string& host) { log() << "SyncClusterConnection connecting to [" << host << "]" << endl; DBClientConnection* c = new DBClientConnection(true); c->setRequestMetadataWriter(getRequestMetadataWriter()); c->setReplyMetadataReader(getReplyMetadataReader()); c->setSoTimeout(_socketTimeout); string errmsg; if (!c->connect(HostAndPort(host), errmsg)) log() << "SyncClusterConnection connect fail to: " << host << " errmsg: " << errmsg << endl; _connAddresses.push_back(host); _conns.push_back(c); }
DBClientBase* ConnectionString::connect( string& errmsg, double socketTimeout ) const { switch ( _type ) { case MASTER: { DBClientConnection * c = new DBClientConnection(true); c->setSoTimeout( socketTimeout ); log(1) << "creating new connection to:" << _servers[0] << endl; if ( ! c->connect( _servers[0] , errmsg ) ) { delete c; return 0; } log(1) << "connected connection!" << endl; return c; } case PAIR: case SET: { DBClientReplicaSet * set = new DBClientReplicaSet( _setName , _servers , socketTimeout ); if( ! set->connect() ) { delete set; errmsg = "connect failed to set "; errmsg += toString(); return 0; } return set; } case SYNC: { // TODO , don't copy list<HostAndPort> l; for ( unsigned i=0; i<_servers.size(); i++ ) l.push_back( _servers[i] ); SyncClusterConnection* c = new SyncClusterConnection( l, socketTimeout ); return c; } case INVALID: throw UserException( 13421 , "trying to connect to invalid ConnectionString" ); break; } assert( 0 ); return 0; }
bool isSelf(const HostAndPort& hostAndPort) { // Fastpath: check if the host&port in question is bound to one // of the interfaces on this machine. // No need for ip match if the ports do not match if (hostAndPort.port() == serverGlobalParams.port) { std::vector<std::string> myAddrs = serverGlobalParams.bind_ip.empty() ? getBoundAddrs(IPv6Enabled()) : std::vector<std::string>(); if (!serverGlobalParams.bind_ip.empty()) { boost::split(myAddrs, serverGlobalParams.bind_ip, boost::is_any_of(", ")); } const std::vector<std::string> hostAddrs = getAddrsForHost(hostAndPort.host(), hostAndPort.port(), IPv6Enabled()); for (std::vector<std::string>::const_iterator i = myAddrs.begin(); i != myAddrs.end(); ++i) { for (std::vector<std::string>::const_iterator j = hostAddrs.begin(); j != hostAddrs.end(); ++j) { if (*i == *j) { return true; } } } } // Ensure that the server is up and ready to accept incoming network requests. const Listener* listener = Listener::getTimeTracker(); if (!listener) { return false; } listener->waitUntilListening(); try { DBClientConnection conn; std::string errmsg; conn.setSoTimeout(30); // 30 second timeout if (!conn.connect(hostAndPort, errmsg)) { return false; } if (getGlobalAuthorizationManager()->isAuthEnabled() && isInternalAuthSet()) { if (!authenticateInternalUser(&conn)) { return false; } } BSONObj out; bool ok = conn.simpleCommand("admin" , &out, "_isSelf"); bool me = ok && out["id"].type() == jstOID && instanceId == out["id"].OID(); return me; } catch (const std::exception& e) { warning() << "could't check isSelf (" << hostAndPort << ") " << e.what() << std::endl; } return false; }
DBClientBase* ConnectionString::connect( std::string& errmsg, double socketTimeout ) const { switch ( _type ) { case MASTER: { DBClientConnection * c = new DBClientConnection(true); c->setSoTimeout( socketTimeout ); LOG(1) << "creating new connection to:" << _servers[0]; if ( ! c->connect( _servers[0] , errmsg ) ) { delete c; return 0; } LOG(1) << "connected connection!"; return c; } case PAIR: case SET: { DBClientReplicaSet * set = new DBClientReplicaSet( _setName , _servers , socketTimeout ); if( ! set->connect() ) { delete set; errmsg = "connect failed to replica set "; errmsg += toString(); return 0; } return set; } case SYNC: { // TODO , don't copy std::list<HostAndPort> l; for ( unsigned i=0; i<_servers.size(); i++ ) l.push_back( _servers[i] ); SyncClusterConnection* c = new SyncClusterConnection( l, socketTimeout ); return c; } case CUSTOM: { // Lock in case other things are modifying this at the same time boost::lock_guard<boost::mutex> lk( _connectHookMutex ); // Allow the replacement of connections with other connections - useful for testing. uassert( 16335, "custom connection to " + this->toString() + " specified with no connection hook", _connectHook ); // Double-checked lock, since this will never be active during normal operation DBClientBase* replacementConn = _connectHook->connect( *this, errmsg, socketTimeout ); log() << "replacing connection to " << this->toString() << " with " << ( replacementConn ? replacementConn->getServerAddress() : "(empty)" ); return replacementConn; } case INVALID: throw UserException( 13421 , "trying to connect to invalid ConnectionString" ); break; } verify( 0 ); return 0; }
bool isSelf(const HostAndPort& hostAndPort) { // Fastpath: check if the host&port in question is bound to one // of the interfaces on this machine. // No need for ip match if the ports do not match if (hostAndPort.port() == serverGlobalParams.port) { std::vector<std::string> myAddrs = serverGlobalParams.bind_ip.empty() ? getBoundAddrs(IPv6Enabled()) : std::vector<std::string>(); if (!serverGlobalParams.bind_ip.empty()) { boost::split(myAddrs, serverGlobalParams.bind_ip, boost::is_any_of(", ")); } const std::vector<std::string> hostAddrs = getAddrsForHost(hostAndPort.host(), hostAndPort.port(), IPv6Enabled()); for (std::vector<std::string>::const_iterator i = myAddrs.begin(); i != myAddrs.end(); ++i) { for (std::vector<std::string>::const_iterator j = hostAddrs.begin(); j != hostAddrs.end(); ++j) { if (*i == *j) { return true; } } } } // Ensure that the server is up and ready to accept incoming network requests. const Listener* listener = Listener::getTimeTracker(); if (!listener) { return false; } listener->waitUntilListening(); try { DBClientConnection conn; conn.setSoTimeout(30); // 30 second timeout // We need to avoid the isMaster call triggered by a normal connect, which would // cause a deadlock. 'isSelf' is called by the Replication Coordinator when validating // a replica set configuration document, but the 'isMaster' command requires a lock on the // replication coordinator to execute. As such we call we call 'connectSocketOnly', which // does not call 'isMaster'. if (!conn.connectSocketOnly(hostAndPort).isOK()) { return false; } if (getGlobalAuthorizationManager()->isAuthEnabled() && isInternalAuthSet()) { if (!conn.authenticateInternalUser()) { return false; } } BSONObj out; bool ok = conn.simpleCommand("admin", &out, "_isSelf"); bool me = ok && out["id"].type() == jstOID && instanceId == out["id"].OID(); return me; } catch (const std::exception& e) { warning() << "couldn't check isSelf (" << hostAndPort << ") " << e.what() << std::endl; } return false; }