summaryrefslogtreecommitdiff
path: root/src/mongo
diff options
context:
space:
mode:
authormatt dannenberg <matt.dannenberg@10gen.com>2013-09-04 14:47:46 -0400
committermatt dannenberg <matt.dannenberg@10gen.com>2013-09-04 16:50:47 -0400
commit607ae1384b26ebcb5e275a845f9806104852257f (patch)
tree8709e4befbd2d4e173e6438a4f7db55fc706ac75 /src/mongo
parentf51d5f797a89f7dbf152f74668c6b93065822bd2 (diff)
downloadmongo-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.cpp1
-rw-r--r--src/mongo/db/curop_test.cpp1
-rw-r--r--src/mongo/db/db.cpp3
-rw-r--r--src/mongo/db/dbwebserver.cpp1
-rw-r--r--src/mongo/tools/bridge.cpp1
-rw-r--r--src/mongo/util/net/listen.cpp64
-rw-r--r--src/mongo/util/net/listen.h14
-rw-r--r--src/mongo/util/net/message_server.h1
-rw-r--r--src/mongo/util/net/message_server_port.cpp4
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();
}