|
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.
|