From: <ale...@us...> - 2011-01-28 17:56:58
|
Revision: 52220 http://firebird.svn.sourceforge.net/firebird/?rev=52220&view=rev Author: alexpeshkoff Date: 2011-01-28 17:56:50 +0000 (Fri, 28 Jan 2011) Log Message: ----------- Frontported fix for CORE-3194: Number of connections to linux superclassic has limit equal 508 Modified Paths: -------------- firebird/trunk/configure.in firebird/trunk/src/remote/inet.cpp Modified: firebird/trunk/configure.in =================================================================== --- firebird/trunk/configure.in 2011-01-28 17:22:44 UTC (rev 52219) +++ firebird/trunk/configure.in 2011-01-28 17:56:50 UTC (rev 52220) @@ -667,6 +667,7 @@ AC_CHECK_HEADERS(float.h) AC_CHECK_HEADERS(atomic.h) AC_CHECK_HEADERS(atomic_ops.h) +AC_CHECK_HEADERS(poll.h) dnl check for ICU presence AC_CHECK_HEADER(unicode/ucnv.h,,AC_MSG_ERROR(ICU support not found - please install development ICU package)) @@ -790,6 +791,7 @@ AC_CHECK_FUNCS(fegetenv) AC_CHECK_FUNCS(strerror_r) AC_CHECK_FUNCS(fdatasync fsync) +AC_CHECK_FUNCS(poll) dnl AC_CHECK_FUNCS(AO_compare_and_swap_full) AC_COMPILE_IFELSE( [AC_LANG_PROGRAM([[#include <atomic_ops.h>]], [[AO_T x; AO_compare_and_swap_full(&x, 0, 0); return 0;]])], Modified: firebird/trunk/src/remote/inet.cpp =================================================================== --- firebird/trunk/src/remote/inet.cpp 2011-01-28 17:22:44 UTC (rev 52219) +++ firebird/trunk/src/remote/inet.cpp 2011-01-28 17:56:50 UTC (rev 52220) @@ -88,9 +88,13 @@ #include <netdb.h> #include <arpa/inet.h> #include <sys/wait.h> -#ifdef HAVE_SYS_SELECT_H + +#if defined(HAVE_POLL_H) +#include <poll.h> +#elif defined(HAVE_SYS_SELECT_H) #include <sys/select.h> #endif + #endif // !WIN_NT const int INET_RETRY_CALL = 5; @@ -229,12 +233,175 @@ const int SELECT_TIMEOUT = 60; // Dispatch thread select timeout (sec) -struct slct_t +class Select { +#ifdef HAVE_POLL +private: + static const int SEL_INIT_EVENTS = POLLIN; + static const int SEL_CHECK_MASK = POLLIN; + + pollfd* getPollFd(int n) + { + pollfd* const end = slct_poll.end(); + for (pollfd* pf = slct_poll.begin(); pf < end; ++pf) + { + if (n == pf->fd) + { + return pf; + } + } + + return NULL; + } + + static int compare(const void* a, const void* b) + { + // use C-cast here to be for sure compatible with libc + return ((pollfd*)a)->fd - ((pollfd*)b)->fd; + } +#endif + +public: +#ifdef HAVE_POLL + Select() + : slct_time(0), slct_count(0), slct_poll(*getDefaultMemoryPool()) + { } +#else + Select() + : slct_time(0), slct_count(0), slct_width(0) + { + memset(&slct_fdset, 0, sizeof slct_fdset); + } +#endif + + enum HandleState {SEL_BAD, SEL_DISCONNECTED, SEL_NO_DATA, SEL_READY}; + + HandleState ok(const rem_port* port) + { + SOCKET n = port->port_handle; +#if defined(WIN_NT) + return FD_ISSET(n, &slct_fdset) ? SEL_READY : SEL_NO_DATA; +#elif defined(HAVE_POLL) + const pollfd* pf = getPollFd(n); + if (pf) + { + return pf->events & SEL_CHECK_MASK ? SEL_READY : SEL_NO_DATA; + } + return (n < 0) ? (port->port_flags & PORT_disconnect ? SEL_DISCONNECTED : SEL_BAD) : SEL_NO_DATA; +#else + if (n < 0 || n >= FD_SETSIZE) + { + return port->port_flags & PORT_disconnect ? SEL_DISCONNECTED : SEL_BAD; + } + return (n < slct_width && FD_ISSET(n, &slct_fdset)) ? SEL_READY : SEL_NO_DATA; +#endif + } + + void unset(SOCKET handle) + { +#if defined(HAVE_POLL) + pollfd* pf = getPollFd(handle); + if (pf) + { + pf->events = 0; + } +#else + FD_CLR(handle, &slct_fdset); + --slct_count; +#endif + } + + void set(SOCKET handle) + { +#ifdef HAVE_POLL + pollfd* pf = getPollFd(handle); + if (pf) + { + pf->events = SEL_INIT_EVENTS; + return; + } + pollfd f; + f.fd = handle; + f.events = SEL_INIT_EVENTS; + slct_poll.push(f); +#else + FD_SET(handle, &slct_fdset); +#ifdef WIN_NT + ++slct_width; +#else + slct_width = MAX(slct_width, handle + 1); +#endif // WIN_NT +#endif // HAVE_POLL + } + + void clear() + { + slct_count = 0; +#if defined(HAVE_POLL) + slct_poll.clear(); +#else + slct_width = 0; + FD_ZERO(&slct_fdset); +#endif + } + + int select(timeval* timeout) + { + bool hasRequest = false; + +#ifdef HAVE_POLL + pollfd* const end = slct_poll.end(); + for (pollfd* pf = slct_poll.begin(); pf < end; ++pf) + { + pf->revents = pf->events; + if (pf->events & SEL_CHECK_MASK) + { + hasRequest = true; + } + } + + if (!hasRequest) + { + errno = NOTASOCKET; + return -1; + } + + int milliseconds = timeout ? timeout->tv_sec * 1000 + timeout->tv_usec / 1000 : -1; + slct_count = ::poll(slct_poll.begin(), slct_poll.getCount(), milliseconds); + + for (pollfd* pf = slct_poll.begin(); pf < end; ++pf) + { + pf->events = pf->revents; + } +#else +#ifdef WIN_NT + slct_count = ::select(FD_SETSIZE, &slct_fdset, NULL, NULL, timeout); +#else + + + slct_count = ::select(slct_width, &slct_fdset, NULL, NULL, timeout); +#endif // WIN_NT +#endif // HAVE_POLL + + + return slct_count; + } + + int getCount() + { + return slct_count; + } + + time_t slct_time; + +private: + int slct_count; +#ifdef HAVE_POLL + Firebird::HalfStaticArray<pollfd, 8> slct_poll; +#else int slct_width; - int slct_count; - time_t slct_time; fd_set slct_fdset; +#endif }; static bool accept_connection(rem_port*, const P_CNCT*); @@ -309,9 +476,9 @@ static rem_port* receive(rem_port*, PACKET *); static rem_port* select_accept(rem_port*); -static void select_port(rem_port*, slct_t*, RemPortPtr&); +static void select_port(rem_port*, Select*, RemPortPtr&); static bool select_multi(rem_port*, UCHAR* buffer, SSHORT bufsize, SSHORT* length, RemPortPtr&); -static bool select_wait(rem_port*, slct_t*); +static bool select_wait(rem_port*, Select*); static int send_full(rem_port*, PACKET *); static int send_partial(rem_port*, PACKET *); @@ -365,7 +532,7 @@ static Firebird::GlobalPtr<Firebird::Mutex> init_mutex; static volatile bool INET_initialized = false; static volatile bool INET_shutting_down = false; -static slct_t INET_select = { 0, 0, 0 }; +static Select INET_select; static rem_port* inet_async_receive = NULL; @@ -759,7 +926,7 @@ } if (! setNoNagleOption(port)) - { + { inet_error(true, port, "setsockopt TCP_NODELAY", isc_net_connect_listen_err, INET_ERRNO); } } @@ -1168,20 +1335,15 @@ timeout.tv_sec = port->port_connect_timeout; timeout.tv_usec = 0; - fd_set slct_fdset; - FD_ZERO(&slct_fdset); - FD_SET(port->port_channel, &slct_fdset); + Select slct; + slct.set(port->port_channel); int inetErrNo = 0; while (true) { - const int count = -#ifdef WIN_NT - select(FD_SETSIZE, &slct_fdset, NULL, NULL, &timeout); -#else - select(port->port_channel + 1, &slct_fdset, NULL, NULL, &timeout); -#endif + slct.select(&timeout); + const int count = slct.getCount(); inetErrNo = INET_ERRNO; if (count != -1 || !INTERRUPT_ERROR(inetErrNo)) @@ -1461,10 +1623,10 @@ #ifdef DEBUG if (INET_trace & TRACE_summary) { - fprintf(stdout, "INET_count_send = %lu packets\n", INET_count_send); - fprintf(stdout, "INET_bytes_send = %lu bytes\n", INET_bytes_send); - fprintf(stdout, "INET_count_recv = %lu packets\n", INET_count_recv); - fprintf(stdout, "INET_bytes_recv = %lu bytes\n", INET_bytes_recv); + fprintf(stdout, "INET_count_send = %u packets\n", INET_count_send); + fprintf(stdout, "INET_bytes_send = %u bytes\n", INET_bytes_send); + fprintf(stdout, "INET_count_recv = %u packets\n", INET_count_recv); + fprintf(stdout, "INET_bytes_recv = %u bytes\n", INET_bytes_recv); fflush(stdout); } #endif @@ -1826,7 +1988,7 @@ op_rec_count++; if (INET_trace & TRACE_operations) { - fprintf(stdout, "%04lu: OP Recd %5lu opcode %d\n", + fprintf(stdout, "%04u: OP Recd %5u opcode %d\n", inet_debug_timer(), op_rec_count, packet->p_operation); fflush(stdout); @@ -1949,7 +2111,7 @@ return 0; } -static void select_port(rem_port* main_port, slct_t* selct, RemPortPtr& port) +static void select_port(rem_port* main_port, Select* selct, RemPortPtr& port) { /************************************** * @@ -1971,33 +2133,36 @@ for (port = main_port; port; port = port->port_next) { - const SOCKET n = port->port_handle; -#ifdef WIN_NT - const int ok = FD_ISSET(n, &selct->slct_fdset); -#else - if (n < 0 || n >= FD_SETSIZE) + Select::HandleState result = selct->ok(port); + selct->unset(port->port_handle); + switch (result) { - if (port->port_flags & PORT_disconnect) + case Select::SEL_BAD: + if (port->port_state == rem_port::BROKEN) + { continue; + } + return; + case Select::SEL_DISCONNECTED: + continue; + + case Select::SEL_READY: + port->port_dummy_timeout = port->port_dummy_packet_interval; return; + + default: + break; } - const int ok = n < selct->slct_width && FD_ISSET(n, &selct->slct_fdset); -#endif - if (ok) + + if (port->port_dummy_timeout < 0) { - port->port_dummy_timeout = port->port_dummy_packet_interval; - FD_CLR(n, &selct->slct_fdset); - --selct->slct_count; return; } - if (port->port_dummy_timeout < 0) { - return; - } } } -static bool select_wait( rem_port* main_port, slct_t* selct) +static bool select_wait( rem_port* main_port, Select* selct) { /************************************** * @@ -2016,8 +2181,7 @@ for (;;) { - selct->slct_count = selct->slct_width = 0; - FD_ZERO(&selct->slct_fdset); + selct->clear(); bool found = false; // Use the time interval between select() calls to expire @@ -2075,16 +2239,10 @@ port->port_handle); // this will lead to receive() which will break bad connection - selct->slct_count = selct->slct_width = 0; - FD_ZERO(&selct->slct_fdset); + selct->clear(); if (!badSocket) { - FD_SET(port->port_handle, &selct->slct_fdset); -#ifdef WIN_NT - ++selct->slct_width; -#else - selct->slct_width = port->port_handle + 1; -#endif + selct->set(port->port_handle); } return true; } @@ -2094,12 +2252,7 @@ // if process is shuting down - don't listen on main port if (!INET_shutting_down || port != main_port) { - FD_SET(port->port_handle, &selct->slct_fdset); -#ifdef WIN_NT - ++selct->slct_width; -#else - selct->slct_width = MAX(selct->slct_width, port->port_handle + 1); -#endif + selct->set(port->port_handle); found = true; } } @@ -2130,30 +2283,26 @@ timeout.tv_sec = SELECT_TIMEOUT; timeout.tv_usec = 0; -#ifdef WIN_NT - selct->slct_count = select(FD_SETSIZE, &selct->slct_fdset, NULL, NULL, &timeout); -#else - selct->slct_count = select(selct->slct_width, &selct->slct_fdset, NULL, NULL, &timeout); -#endif + selct->select(&timeout); const int inetErrNo = INET_ERRNO; //if (INET_shutting_down) { // return false; //} - if (selct->slct_count != -1) + if (selct->getCount() != -1) { // if selct->slct_count is zero it means that we timed out of // select with nothing to read or accept, so clear the fd_set // bit as this value is undefined on some platforms (eg. HP-UX), // when the select call times out. Once these bits are cleared // they can be used in select_port() - if (selct->slct_count == 0) + if (selct->getCount() == 0) { Firebird::MutexLockGuard guard(port_mutex); for (rem_port* port = main_port; port; port = port->port_next) { - FD_CLR(port->port_handle, &selct->slct_fdset); + selct->unset(port->port_handle); } } return true; @@ -2197,7 +2346,7 @@ op_sent_count++; if (INET_trace & TRACE_operations) { - fprintf(stdout, "%05lu: OP Sent %5lu opcode %d\n", inet_debug_timer(), + fprintf(stdout, "%05u: OP Sent %5u opcode %d\n", inet_debug_timer(), op_sent_count, packet->p_operation); fflush(stdout); } @@ -2226,7 +2375,7 @@ op_sentp_count++; if (INET_trace & TRACE_operations) { - fprintf(stdout, "%05lu: OP Sent %5lu opcode %d (partial)\n", inet_debug_timer(), + fprintf(stdout, "%05u: OP Sent %5u opcode %d (partial)\n", inet_debug_timer(), op_sentp_count, packet->p_operation); fflush(stdout); } @@ -2802,7 +2951,7 @@ for (int l = length; l > 0; --l) sum += *packet++; - fprintf(stdout, "%05lu: PKT %s\t(%lu): length = %4d, checksum = %d\n", + fprintf(stdout, "%05u: PKT %s\t(%u): length = %4d, checksum = %d\n", inet_debug_timer(), string, counter, length, sum); fflush(stdout); } @@ -2875,18 +3024,14 @@ if ( !(port->port_flags & PORT_async) ) { - fd_set slct_fdset; - FD_ZERO(&slct_fdset); - FD_SET(ph, &slct_fdset); + Select slct; + slct.set(ph); int slct_count; for (;;) { -#if (defined WIN_NT) - slct_count = select(FD_SETSIZE, &slct_fdset, NULL, NULL, time_ptr); -#else - slct_count = select(port->port_handle + 1, &slct_fdset, NULL, NULL, time_ptr); -#endif + slct.select(time_ptr); + slct_count = slct.getCount(); inetErrNo = INET_ERRNO; // restore original timeout value FSG 3 MAY 2001 @@ -2916,7 +3061,7 @@ #ifdef DEBUG if (INET_trace & TRACE_operations) { - fprintf(stdout, "%05lu: OP Sent: op_dummy\n", inet_debug_timer()); + fprintf(stdout, "%05u: OP Sent: op_dummy\n", inet_debug_timer()); fflush(stdout); } #endif This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |