diff options
author | matt dannenberg <matt.dannenberg@10gen.com> | 2013-09-04 14:47:46 -0400 |
---|---|---|
committer | matt dannenberg <matt.dannenberg@10gen.com> | 2013-09-04 16:50:47 -0400 |
commit | 607ae1384b26ebcb5e275a845f9806104852257f (patch) | |
tree | 8709e4befbd2d4e173e6438a4f7db55fc706ac75 /src/mongo | |
parent | f51d5f797a89f7dbf152f74668c6b93065822bd2 (diff) | |
download | mongo-607ae1384b26ebcb5e275a845f9806104852257f.tar.gz |
SERVER-9818 allocate socket file descriptors before opening datafiles
Diffstat (limited to 'src/mongo')
-rw-r--r-- | src/mongo/client/scoped_db_conn_test.cpp | 1 | ||||
-rw-r--r-- | src/mongo/db/curop_test.cpp | 1 | ||||
-rw-r--r-- | src/mongo/db/db.cpp | 3 | ||||
-rw-r--r-- | src/mongo/db/dbwebserver.cpp | 1 | ||||
-rw-r--r-- | src/mongo/tools/bridge.cpp | 1 | ||||
-rw-r--r-- | src/mongo/util/net/listen.cpp | 64 | ||||
-rw-r--r-- | src/mongo/util/net/listen.h | 14 | ||||
-rw-r--r-- | src/mongo/util/net/message_server.h | 1 | ||||
-rw-r--r-- | src/mongo/util/net/message_server_port.cpp | 4 |
9 files changed, 50 insertions, 40 deletions
diff --git a/src/mongo/client/scoped_db_conn_test.cpp b/src/mongo/client/scoped_db_conn_test.cpp index 2c9600fb35a..f7ed76ddca8 100644 --- a/src/mongo/client/scoped_db_conn_test.cpp +++ b/src/mongo/client/scoped_db_conn_test.cpp @@ -139,6 +139,7 @@ namespace mongo_test { } _server = mongo::createServer(options, messsageHandler); + _server->setupSockets(); _serverThread = boost::thread(runServer, _server); } diff --git a/src/mongo/db/curop_test.cpp b/src/mongo/db/curop_test.cpp index 8435b7b88d2..a6e6c1dbb10 100644 --- a/src/mongo/db/curop_test.cpp +++ b/src/mongo/db/curop_test.cpp @@ -43,6 +43,7 @@ namespace mongo { void timeTrackerSetup() { TestListener listener; listener.setAsTimeTracker(); + listener.setupSockets(); listener.initAndListen(); } diff --git a/src/mongo/db/db.cpp b/src/mongo/db/db.cpp index 97ef6a696ed..42d5049c333 100644 --- a/src/mongo/db/db.cpp +++ b/src/mongo/db/db.cpp @@ -282,6 +282,9 @@ namespace mongo { MessageServer * server = createServer( options , new MyMessageHandler() ); server->setAsTimeTracker(); + // we must setupSockets prior to logStartup() to avoid getting too high + // a file descriptor for our calls to select() + server->setupSockets(); logStartup(); startReplication(); diff --git a/src/mongo/db/dbwebserver.cpp b/src/mongo/db/dbwebserver.cpp index d4598fed49e..1fa1f50f608 100644 --- a/src/mongo/db/dbwebserver.cpp +++ b/src/mongo/db/dbwebserver.cpp @@ -555,6 +555,7 @@ namespace mongo { Client::initThread("websvr"); const int p = cmdLine.port + 1000; DbWebServer mini(cmdLine.bind_ip, p, adminAccessPtr.get()); + mini.setupSockets(); mini.initAndListen(); cc().shutdown(); } diff --git a/src/mongo/tools/bridge.cpp b/src/mongo/tools/bridge.cpp index ece13adf589..b211dcdc5b0 100644 --- a/src/mongo/tools/bridge.cpp +++ b/src/mongo/tools/bridge.cpp @@ -181,6 +181,7 @@ int toolMain( int argc, char **argv, char** envp ) { check( port != 0 && !destUri.empty() ); listener.reset( new MyListener( port ) ); + listener->setupSockets(); listener->initAndListen(); return 0; diff --git a/src/mongo/util/net/listen.cpp b/src/mongo/util/net/listen.cpp index 6ab0219e835..da51a2b6543 100644 --- a/src/mongo/util/net/listen.cpp +++ b/src/mongo/util/net/listen.cpp @@ -98,7 +98,8 @@ namespace mongo { } Listener::Listener(const string& name, const string &ip, int port, bool logConnect ) - : _port(port), _name(name), _ip(ip), _logConnect(logConnect), _elapsedTime(0) { + : _port(port), _name(name), _ip(ip), _setupSocketsSuccessful(false), + _logConnect(logConnect), _elapsedTime(0) { #ifdef MONGO_SSL _ssl = getSSLManager(); #endif @@ -109,8 +110,11 @@ namespace mongo { _timeTracker = 0; } - bool Listener::_setupSockets( const vector<SockAddr>& mine , vector<SOCKET>& socks ) { - for (vector<SockAddr>::const_iterator it=mine.begin(), end=mine.end(); it != end; ++it) { + void Listener::setupSockets() { + checkTicketNumbers(); + _mine = ipToAddrs(_ip.c_str(), _port, (!cmdLine.noUnixSocket && useUnixSockets())); + + for (vector<SockAddr>::const_iterator it=_mine.begin(), end=_mine.end(); it != end; ++it) { const SockAddr& me = *it; SOCKET sock = ::socket(me.getType(), SOCK_STREAM, 0); @@ -148,7 +152,7 @@ namespace mongo { if ( x == EADDRINUSE ) error() << " addr already in use" << endl; closesocket(sock); - return false; + return; } #if !defined(_WIN32) @@ -163,33 +167,28 @@ namespace mongo { if ( ::listen(sock, 128) != 0 ) { error() << "listen(): listen() failed " << errnoWithDescription() << endl; closesocket(sock); - return false; + return; } ListeningSockets::get()->add( sock ); - socks.push_back(sock); + _socks.push_back(sock); } - return true; + _setupSocketsSuccessful = true; } #if !defined(_WIN32) void Listener::initAndListen() { - checkTicketNumbers(); - vector<SOCKET> socks; - - { - vector<SockAddr> mine = ipToAddrs(_ip.c_str(), _port, (!cmdLine.noUnixSocket && useUnixSockets())); - if ( ! _setupSockets( mine , socks ) ) - return; + if (!_setupSocketsSuccessful) { + return; } SOCKET maxfd = 0; // needed for select() - for ( unsigned i=0; i<socks.size(); i++ ) { - if ( socks[i] > maxfd ) - maxfd = socks[i]; + for ( unsigned i=0; i<_socks.size(); i++ ) { + if ( _socks[i] > maxfd ) + maxfd = _socks[i]; } if ( maxfd >= FD_SETSIZE ) { @@ -209,7 +208,7 @@ namespace mongo { fd_set fds[1]; FD_ZERO(fds); - for (vector<SOCKET>::iterator it=socks.begin(), end=socks.end(); it != end; ++it) { + for (vector<SOCKET>::iterator it=_socks.begin(), end=_socks.end(); it != end; ++it) { FD_SET(*it, fds); } @@ -245,7 +244,7 @@ namespace mongo { _elapsedTime += ret; // assume 1ms to grab connection. very rough #endif - for (vector<SOCKET>::iterator it=socks.begin(), end=socks.end(); it != end; ++it) { + for (vector<SOCKET>::iterator it=_socks.begin(), end=_socks.end(); it != end; ++it) { if (! (FD_ISSET(*it, fds))) continue; SockAddr from; @@ -349,13 +348,8 @@ namespace mongo { }; void Listener::initAndListen() { - checkTicketNumbers(); - vector<SOCKET> socks; - - { - vector<SockAddr> mine = ipToAddrs(_ip.c_str(), _port, false); - if ( ! _setupSockets( mine , socks ) ) - return; + if (!_setupSocketsSuccessful) { + return; } #ifdef MONGO_SSL @@ -365,11 +359,11 @@ namespace mongo { #endif OwnedPointerVector<EventHolder> eventHolders; - boost::scoped_array<WSAEVENT> events(new WSAEVENT[socks.size()]); + boost::scoped_array<WSAEVENT> events(new WSAEVENT[_socks.size()]); // Populate events array with an event for each socket we are watching - for (size_t count = 0; count < socks.size(); ++count) { + for (size_t count = 0; count < _socks.size(); ++count) { EventHolder* ev(new EventHolder); eventHolders.mutableVector().push_back(ev); events[count] = ev->get(); @@ -377,8 +371,8 @@ namespace mongo { while ( ! inShutdown() ) { // Turn on listening for accept-ready sockets - for (size_t count = 0; count < socks.size(); ++count) { - int status = WSAEventSelect(socks[count], events[count], FD_ACCEPT | FD_CLOSE); + for (size_t count = 0; count < _socks.size(); ++count) { + int status = WSAEventSelect(_socks[count], events[count], FD_ACCEPT | FD_CLOSE); if (status == SOCKET_ERROR) { const int mongo_errno = WSAGetLastError(); error() << "Windows WSAEventSelect returned " @@ -388,7 +382,7 @@ namespace mongo { } // Wait till one of them goes active, or we time out - DWORD result = WSAWaitForMultipleEvents(socks.size(), + DWORD result = WSAWaitForMultipleEvents(_socks.size(), events.get(), FALSE, // don't wait for all the events 10, // timeout, in ms @@ -410,7 +404,7 @@ namespace mongo { DWORD eventIndex = result - WSA_WAIT_EVENT_0; WSANETWORKEVENTS networkEvents; // Extract event details, and clear event for next pass - int status = WSAEnumNetworkEvents(socks[eventIndex], + int status = WSAEnumNetworkEvents(_socks[eventIndex], events[eventIndex], &networkEvents); if (status == SOCKET_ERROR) { @@ -437,7 +431,7 @@ namespace mongo { continue; } - status = WSAEventSelect(socks[eventIndex], NULL, 0); + status = WSAEventSelect(_socks[eventIndex], NULL, 0); if (status == SOCKET_ERROR) { const int mongo_errno = WSAGetLastError(); error() << "Windows WSAEventSelect returned " @@ -445,10 +439,10 @@ namespace mongo { continue; } - disableNonblockingMode(socks[eventIndex]); + disableNonblockingMode(_socks[eventIndex]); SockAddr from; - int s = accept(socks[eventIndex], from.raw(), &from.addressSize); + int s = accept(_socks[eventIndex], from.raw(), &from.addressSize); if ( s < 0 ) { int x = errno; // so no global issues if ( x == ECONNABORTED || x == EBADF ) { diff --git a/src/mongo/util/net/listen.h b/src/mongo/util/net/listen.h index 01f2a4e9fd4..da3a99170e7 100644 --- a/src/mongo/util/net/listen.h +++ b/src/mongo/util/net/listen.h @@ -52,6 +52,12 @@ namespace mongo { */ long long getMyElapsedTimeMillis() const { return _elapsedTime; } + /** + * Allocate sockets for the listener and set _setupSocketsSuccessful to true + * iff the process was successful. + */ + void setupSockets(); + void setAsTimeTracker() { _timeTracker = this; } @@ -69,8 +75,11 @@ namespace mongo { } private: + std::vector<SockAddr> _mine; + std::vector<SOCKET> _socks; std::string _name; std::string _ip; + bool _setupSocketsSuccessful; bool _logConnect; long long _elapsedTime; @@ -78,11 +87,6 @@ namespace mongo { SSLManagerInterface* _ssl; #endif - /** - * @return true iff everything went ok - */ - bool _setupSockets( const std::vector<SockAddr>& mine , std::vector<SOCKET>& socks ); - void _logListen( int port , bool ssl ); static const Listener* _timeTracker; diff --git a/src/mongo/util/net/message_server.h b/src/mongo/util/net/message_server.h index a33014641b2..ed6cf96de44 100644 --- a/src/mongo/util/net/message_server.h +++ b/src/mongo/util/net/message_server.h @@ -61,6 +61,7 @@ namespace mongo { virtual ~MessageServer() {} virtual void run() = 0; virtual void setAsTimeTracker() = 0; + virtual void setupSockets() = 0; }; // TODO use a factory here to decide between port and asio variations diff --git a/src/mongo/util/net/message_server_port.cpp b/src/mongo/util/net/message_server_port.cpp index eeec3cc3263..00bed7f7443 100644 --- a/src/mongo/util/net/message_server_port.cpp +++ b/src/mongo/util/net/message_server_port.cpp @@ -126,6 +126,10 @@ namespace mongo { Listener::setAsTimeTracker(); } + virtual void setupSockets() { + Listener::setupSockets(); + } + void run() { initAndListen(); } |