* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111, USA.
*
*/
-#include "config.h"
+#include "squid.h"
#if USE_SELECT
-#include "squid.h"
+#include "anyp/PortCfg.h"
+#include "comm/Connection.h"
#include "comm/Loops.h"
+#include "fde.h"
+#include "globals.h"
+#include "ICP.h"
#include "mgr/Registration.h"
#include "SquidTime.h"
+#include "StatCounters.h"
+#include "StatHist.h"
#include "Store.h"
-#include "fde.h"
+
+#if HAVE_SYS_STAT_H
+#include <sys/stat.h>
+#endif
+#if HAVE_ERRNO_H
+#include <errno.h>
+#endif
static int MAX_POLL_TIME = 1000; /* see also Comm::QuickPollRequired() */
/* STATIC */
static int examine_select(fd_set *, fd_set *);
-static int fdIsHttp(int fd);
-static int fdIsIcp(int fd);
+static int fdIsTcpListener(int fd);
+static int fdIsUdpListener(int fd);
static int fdIsDns(int fd);
static OBJH commIncomingStats;
static int comm_check_incoming_select_handlers(int nfds, int *fds);
static void commUpdateReadBits(int fd, PF * handler);
static void commUpdateWriteBits(int fd, PF * handler);
-
static struct timeval zero_tv;
static fd_set global_readfds;
static fd_set global_writefds;
* of incoming ICP, then we need to check these sockets more than
* if we just have HTTP.
*
- * The variables 'incoming_icp_interval' and 'incoming_http_interval'
+ * The variables 'incoming_udp_interval' and 'incoming_tcp_interval'
* determine how many normal I/O events to process before checking
* incoming sockets again. Note we store the incoming_interval
* multipled by a factor of (2^INCOMING_FACTOR) to have some
* pseudo-floating point precision.
*
- * The variable 'icp_io_events' and 'http_io_events' counts how many normal
+ * The variable 'udp_io_events' and 'tcp_io_events' counts how many normal
* I/O events have been processed since the last check on the incoming
* sockets. When io_events > incoming_interval, its time to check incoming
* sockets.
*
* incoming_interval = incoming_interval + target_average - number_of_events_processed
*
- * There are separate incoming_interval counters for both HTTP and ICP events
+ * There are separate incoming_interval counters for DNS, UDP and TCP events
*
* You can see the current values of the incoming_interval's, as well as
* a histogram of 'incoming_events' by asking the cache manager
#define MAX_INCOMING_INTEGER 256
#define INCOMING_FACTOR 5
#define MAX_INCOMING_INTERVAL (MAX_INCOMING_INTEGER << INCOMING_FACTOR)
-static int icp_io_events = 0;
+static int udp_io_events = 0;
static int dns_io_events = 0;
-static int http_io_events = 0;
-static int incoming_icp_interval = 16 << INCOMING_FACTOR;
+static int tcp_io_events = 0;
+static int incoming_udp_interval = 16 << INCOMING_FACTOR;
static int incoming_dns_interval = 16 << INCOMING_FACTOR;
-static int incoming_http_interval = 16 << INCOMING_FACTOR;
-#define commCheckICPIncoming (++icp_io_events > (incoming_icp_interval>> INCOMING_FACTOR))
-#define commCheckDNSIncoming (++dns_io_events > (incoming_dns_interval>> INCOMING_FACTOR))
-#define commCheckHTTPIncoming (++http_io_events > (incoming_http_interval>> INCOMING_FACTOR))
+static int incoming_tcp_interval = 16 << INCOMING_FACTOR;
+#define commCheckUdpIncoming (++udp_io_events > (incoming_udp_interval>> INCOMING_FACTOR))
+#define commCheckDnsIncoming (++dns_io_events > (incoming_dns_interval>> INCOMING_FACTOR))
+#define commCheckTcpIncoming (++tcp_io_events > (incoming_tcp_interval>> INCOMING_FACTOR))
void
Comm::SetSelect(int fd, unsigned int type, PF * handler, void *client_data, time_t timeout)
fde *F = &fd_table[fd];
assert(fd >= 0);
assert(F->flags.open);
- debugs(5, 5, HERE << "FD " << fd << " type " << type);
+ debugs(5, 5, HERE << "FD " << fd << ", type=" << type <<
+ ", handler=" << handler << ", client_data=" << client_data <<
+ ", timeout=" << timeout);
if (type & COMM_SELECT_READ) {
F->read_handler = handler;
}
static int
-fdIsIcp(int fd)
+fdIsUdpListener(int fd)
{
- if (fd == theInIcpConnection)
+ if (icpIncomingConn != NULL && fd == icpIncomingConn->fd)
return 1;
- if (fd == theOutIcpConnection)
+ if (icpOutgoingConn != NULL && fd == icpOutgoingConn->fd)
return 1;
return 0;
}
static int
-fdIsHttp(int fd)
+fdIsTcpListener(int fd)
{
- int j;
-
- for (j = 0; j < NHttpSockets; j++) {
- if (fd == HttpSockets[j])
+ for (const AnyP::PortCfg *s = Config.Sockaddr.http; s; s = s->next) {
+ if (s->listenConn != NULL && s->listenConn->fd == fd)
return 1;
}
FD_ZERO(&write_mask);
incoming_sockets_accepted = 0;
- for (i = 0; i < nfds; i++) {
+ for (i = 0; i < nfds; ++i) {
fd = fds[i];
if (fd_table[fd].read_handler) {
getCurrentTime();
- statCounter.syscalls.selects++;
+ ++ statCounter.syscalls.selects;
if (select(maxfd, &read_mask, &write_mask, NULL, &zero_tv) < 1)
return incoming_sockets_accepted;
- for (i = 0; i < nfds; i++) {
+ for (i = 0; i < nfds; ++i) {
fd = fds[i];
if (FD_ISSET(fd, &read_mask)) {
commUpdateReadBits(fd, NULL);
hdl(fd, fd_table[fd].read_data);
} else {
- debugs(5, 1, "comm_select_incoming: FD " << fd << " NULL read handler");
+ debugs(5, DBG_IMPORTANT, "comm_select_incoming: FD " << fd << " NULL read handler");
}
}
commUpdateWriteBits(fd, NULL);
hdl(fd, fd_table[fd].write_data);
} else {
- debugs(5, 1, "comm_select_incoming: FD " << fd << " NULL write handler");
+ debugs(5, DBG_IMPORTANT, "comm_select_incoming: FD " << fd << " NULL write handler");
}
}
}
}
static void
-comm_select_icp_incoming(void)
+comm_select_udp_incoming(void)
{
int nfds = 0;
int fds[2];
int nevents;
- icp_io_events = 0;
+ udp_io_events = 0;
- if (theInIcpConnection >= 0)
- fds[nfds++] = theInIcpConnection;
+ if (Comm::IsConnOpen(icpIncomingConn)) {
+ fds[nfds] = icpIncomingConn->fd;
+ ++nfds;
+ }
- if (theInIcpConnection != theOutIcpConnection)
- if (theOutIcpConnection >= 0)
- fds[nfds++] = theOutIcpConnection;
+ if (Comm::IsConnOpen(icpOutgoingConn) && icpIncomingConn != icpOutgoingConn) {
+ fds[nfds] = icpOutgoingConn->fd;
+ ++nfds;
+ }
if (nfds == 0)
return;
nevents = comm_check_incoming_select_handlers(nfds, fds);
- incoming_icp_interval += Config.comm_incoming.icp_average - nevents;
+ incoming_udp_interval += Config.comm_incoming.udp.average - nevents;
- if (incoming_icp_interval < 0)
- incoming_icp_interval = 0;
+ if (incoming_udp_interval < 0)
+ incoming_udp_interval = 0;
- if (incoming_icp_interval > MAX_INCOMING_INTERVAL)
- incoming_icp_interval = MAX_INCOMING_INTERVAL;
+ if (incoming_udp_interval > MAX_INCOMING_INTERVAL)
+ incoming_udp_interval = MAX_INCOMING_INTERVAL;
- if (nevents > INCOMING_ICP_MAX)
- nevents = INCOMING_ICP_MAX;
+ if (nevents > INCOMING_UDP_MAX)
+ nevents = INCOMING_UDP_MAX;
- statHistCount(&statCounter.comm_icp_incoming, nevents);
+ statCounter.comm_udp_incoming.count(nevents);
}
static void
-comm_select_http_incoming(void)
+comm_select_tcp_incoming(void)
{
int nfds = 0;
- int fds[MAXHTTPPORTS];
- int j;
+ int fds[MAXTCPLISTENPORTS];
int nevents;
- http_io_events = 0;
+ tcp_io_events = 0;
- for (j = 0; j < NHttpSockets; j++) {
- if (HttpSockets[j] < 0)
- continue;
+ // XXX: only poll sockets that won't be deferred. But how do we identify them?
- fds[nfds++] = HttpSockets[j];
+ for (const AnyP::PortCfg *s = Config.Sockaddr.http; s; s = s->next) {
+ if (Comm::IsConnOpen(s->listenConn)) {
+ fds[nfds] = s->listenConn->fd;
+ ++nfds;
+ }
}
nevents = comm_check_incoming_select_handlers(nfds, fds);
- incoming_http_interval += Config.comm_incoming.http_average - nevents;
+ incoming_tcp_interval += Config.comm_incoming.tcp.average - nevents;
- if (incoming_http_interval < 0)
- incoming_http_interval = 0;
+ if (incoming_tcp_interval < 0)
+ incoming_tcp_interval = 0;
- if (incoming_http_interval > MAX_INCOMING_INTERVAL)
- incoming_http_interval = MAX_INCOMING_INTERVAL;
+ if (incoming_tcp_interval > MAX_INCOMING_INTERVAL)
+ incoming_tcp_interval = MAX_INCOMING_INTERVAL;
- if (nevents > INCOMING_HTTP_MAX)
- nevents = INCOMING_HTTP_MAX;
+ if (nevents > INCOMING_TCP_MAX)
+ nevents = INCOMING_TCP_MAX;
- statHistCount(&statCounter.comm_http_incoming, nevents);
+ statCounter.comm_tcp_incoming.count(nevents);
}
#define DEBUG_FDBITS 0
int maxfd;
int num;
int pending;
- int callicp = 0, callhttp = 0;
- int calldns = 0;
+ int calldns = 0, calludp = 0, calltcp = 0;
int maxindex;
unsigned int k;
int j;
getCurrentTime();
start = current_dtime;
- if (commCheckICPIncoming)
- comm_select_icp_incoming();
+ if (commCheckUdpIncoming)
+ comm_select_udp_incoming();
- if (commCheckDNSIncoming)
+ if (commCheckDnsIncoming)
comm_select_dns_incoming();
- if (commCheckHTTPIncoming)
- comm_select_http_incoming();
+ if (commCheckTcpIncoming)
+ comm_select_tcp_incoming();
- callicp = calldns = callhttp = 0;
+ calldns = calludp = calltcp = 0;
maxfd = Biggest_FD + 1;
fdsp = (fd_mask *) & readfds;
- for (j = 0; j < maxindex; j++) {
+ for (j = 0; j < maxindex; ++j) {
if ((tmask = fdsp[j]) == 0)
continue; /* no bits here */
- for (k = 0; k < FD_MASK_BITS; k++) {
+ for (k = 0; k < FD_MASK_BITS; ++k) {
if (!EBIT_TEST(tmask, k))
continue;
if (FD_ISSET(fd, &readfds) && fd_table[fd].flags.read_pending) {
FD_SET(fd, &pendingfds);
- pending++;
+ ++pending;
}
}
}
#if DEBUG_FDBITS
- for (i = 0; i < maxfd; i++) {
+ for (i = 0; i < maxfd; ++i) {
/* Check each open socket for a handler. */
if (fd_table[i].read_handler) {
for (;;) {
poll_time.tv_sec = msec / 1000;
poll_time.tv_usec = (msec % 1000) * 1000;
- statCounter.syscalls.selects++;
+ ++ statCounter.syscalls.selects;
num = select(maxfd, &readfds, &writefds, NULL, &poll_time);
- ++statCounter.select_loops;
+ ++ statCounter.select_loops;
if (num >= 0 || pending > 0)
break;
if (ignoreErrno(errno))
break;
- debugs(5, 0, "comm_select: select failure: " << xstrerror());
+ debugs(5, DBG_CRITICAL, "comm_select: select failure: " << xstrerror());
examine_select(&readfds, &writefds);
debugs(5, num ? 5 : 8, "comm_select: " << num << "+" << pending << " FDs ready");
- statHistCount(&statCounter.select_fds_hist, num);
+ statCounter.select_fds_hist.count(num);
if (num == 0 && pending == 0)
continue;
maxindex = howmany(maxfd, FD_MASK_BITS);
- for (j = 0; j < maxindex; j++) {
+ for (j = 0; j < maxindex; ++j) {
if ((tmask = (fdsp[j] | pfdsp[j])) == 0)
continue; /* no bits here */
- for (k = 0; k < FD_MASK_BITS; k++) {
+ for (k = 0; k < FD_MASK_BITS; ++k) {
if (tmask == 0)
break; /* no more bits left */
#endif
- if (fdIsIcp(fd)) {
- callicp = 1;
+ if (fdIsUdpListener(fd)) {
+ calludp = 1;
continue;
}
continue;
}
- if (fdIsHttp(fd)) {
- callhttp = 1;
+ if (fdIsTcpListener(fd)) {
+ calltcp = 1;
continue;
}
F->flags.read_pending = 0;
commUpdateReadBits(fd, NULL);
hdl(fd, F->read_data);
- statCounter.select_fds++;
+ ++ statCounter.select_fds;
- if (commCheckICPIncoming)
- comm_select_icp_incoming();
+ if (commCheckUdpIncoming)
+ comm_select_udp_incoming();
- if (commCheckDNSIncoming)
+ if (commCheckDnsIncoming)
comm_select_dns_incoming();
- if (commCheckHTTPIncoming)
- comm_select_http_incoming();
+ if (commCheckTcpIncoming)
+ comm_select_tcp_incoming();
}
}
}
fdsp = (fd_mask *) & writefds;
- for (j = 0; j < maxindex; j++) {
+ for (j = 0; j < maxindex; ++j) {
if ((tmask = fdsp[j]) == 0)
continue; /* no bits here */
- for (k = 0; k < FD_MASK_BITS; k++) {
+ for (k = 0; k < FD_MASK_BITS; ++k) {
if (tmask == 0)
break; /* no more bits left */
#endif
- if (fdIsIcp(fd)) {
- callicp = 1;
+ if (fdIsUdpListener(fd)) {
+ calludp = 1;
continue;
}
continue;
}
- if (fdIsHttp(fd)) {
- callhttp = 1;
+ if (fdIsTcpListener(fd)) {
+ calltcp = 1;
continue;
}
F = &fd_table[fd];
- debugs(5, 5, "comm_select: FD " << fd << " ready for writing");
+ debugs(5, 6, "comm_select: FD " << fd << " ready for writing");
if ((hdl = F->write_handler)) {
F->write_handler = NULL;
commUpdateWriteBits(fd, NULL);
hdl(fd, F->write_data);
- statCounter.select_fds++;
+ ++ statCounter.select_fds;
- if (commCheckICPIncoming)
- comm_select_icp_incoming();
+ if (commCheckUdpIncoming)
+ comm_select_udp_incoming();
- if (commCheckDNSIncoming)
+ if (commCheckDnsIncoming)
comm_select_dns_incoming();
- if (commCheckHTTPIncoming)
- comm_select_http_incoming();
+ if (commCheckTcpIncoming)
+ comm_select_tcp_incoming();
}
}
}
- if (callicp)
- comm_select_icp_incoming();
+ if (calludp)
+ comm_select_udp_incoming();
if (calldns)
comm_select_dns_incoming();
- if (callhttp)
- comm_select_http_incoming();
+ if (calltcp)
+ comm_select_tcp_incoming();
getCurrentTime();
if (DnsSocketA < 0 && DnsSocketB < 0)
return;
- if (DnsSocketA >= 0)
- fds[nfds++] = DnsSocketA;
+ if (DnsSocketA >= 0) {
+ fds[nfds] = DnsSocketA;
+ ++nfds;
+ }
- if (DnsSocketB >= 0)
- fds[nfds++] = DnsSocketB;
+ if (DnsSocketB >= 0) {
+ fds[nfds] = DnsSocketB;
+ ++nfds;
+ }
nevents = comm_check_incoming_select_handlers(nfds, fds);
if (nevents < 0)
return;
- incoming_dns_interval += Config.comm_incoming.dns_average - nevents;
+ incoming_dns_interval += Config.comm_incoming.dns.average - nevents;
- if (incoming_dns_interval < Config.comm_incoming.dns_min_poll)
- incoming_dns_interval = Config.comm_incoming.dns_min_poll;
+ if (incoming_dns_interval < Config.comm_incoming.dns.min_poll)
+ incoming_dns_interval = Config.comm_incoming.dns.min_poll;
if (incoming_dns_interval > MAX_INCOMING_INTERVAL)
incoming_dns_interval = MAX_INCOMING_INTERVAL;
if (nevents > INCOMING_DNS_MAX)
nevents = INCOMING_DNS_MAX;
- statHistCount(&statCounter.comm_dns_incoming, nevents);
+ statCounter.comm_dns_incoming.count(nevents);
}
void
fde *F = NULL;
struct stat sb;
- debugs(5, 0, "examine_select: Examining open file descriptors...");
+ debugs(5, DBG_CRITICAL, "examine_select: Examining open file descriptors...");
- for (fd = 0; fd < Squid_MaxFD; fd++) {
+ for (fd = 0; fd < Squid_MaxFD; ++fd) {
FD_ZERO(&read_x);
FD_ZERO(&write_x);
tv.tv_sec = tv.tv_usec = 0;
else
continue;
- statCounter.syscalls.selects++;
+ ++ statCounter.syscalls.selects;
errno = 0;
if (!fstat(fd, &sb)) {
}
F = &fd_table[fd];
- debugs(5, 0, "FD " << fd << ": " << xstrerror());
- debugs(5, 0, "WARNING: FD " << fd << " has handlers, but it's invalid.");
- debugs(5, 0, "FD " << fd << " is a " << fdTypeStr[F->type] << " called '" << F->desc << "'");
- debugs(5, 0, "tmout:" << F->timeoutHandler << " read:" << F->read_handler << " write:" << F->write_handler);
+ debugs(5, DBG_CRITICAL, "FD " << fd << ": " << xstrerror());
+ debugs(5, DBG_CRITICAL, "WARNING: FD " << fd << " has handlers, but it's invalid.");
+ debugs(5, DBG_CRITICAL, "FD " << fd << " is a " << fdTypeStr[F->type] << " called '" << F->desc << "'");
+ debugs(5, DBG_CRITICAL, "tmout:" << F->timeoutHandler << " read:" << F->read_handler << " write:" << F->write_handler);
for (ch = F->closeHandler; ch != NULL; ch = ch->Next())
- debugs(5, 0, " close handler: " << ch);
+ debugs(5, DBG_CRITICAL, " close handler: " << ch);
if (F->closeHandler != NULL) {
commCallCloseHandlers(fd);
} else if (F->timeoutHandler != NULL) {
- debugs(5, 0, "examine_select: Calling Timeout Handler");
+ debugs(5, DBG_CRITICAL, "examine_select: Calling Timeout Handler");
ScheduleCallHere(F->timeoutHandler);
}
return 0;
}
-
static void
commIncomingStats(StoreEntry * sentry)
{
- StatCounters *f = &statCounter;
- storeAppendPrintf(sentry, "Current incoming_icp_interval: %d\n",
- incoming_icp_interval >> INCOMING_FACTOR);
+ storeAppendPrintf(sentry, "Current incoming_udp_interval: %d\n",
+ incoming_udp_interval >> INCOMING_FACTOR);
storeAppendPrintf(sentry, "Current incoming_dns_interval: %d\n",
incoming_dns_interval >> INCOMING_FACTOR);
- storeAppendPrintf(sentry, "Current incoming_http_interval: %d\n",
- incoming_http_interval >> INCOMING_FACTOR);
+ storeAppendPrintf(sentry, "Current incoming_tcp_interval: %d\n",
+ incoming_tcp_interval >> INCOMING_FACTOR);
storeAppendPrintf(sentry, "\n");
storeAppendPrintf(sentry, "Histogram of events per incoming socket type\n");
- storeAppendPrintf(sentry, "ICP Messages handled per comm_select_icp_incoming() call:\n");
- statHistDump(&f->comm_icp_incoming, sentry, statHistIntDumper);
+ storeAppendPrintf(sentry, "ICP Messages handled per comm_select_udp_incoming() call:\n");
+ statCounter.comm_udp_incoming.dump(sentry, statHistIntDumper);
storeAppendPrintf(sentry, "DNS Messages handled per comm_select_dns_incoming() call:\n");
- statHistDump(&f->comm_dns_incoming, sentry, statHistIntDumper);
- storeAppendPrintf(sentry, "HTTP Messages handled per comm_select_http_incoming() call:\n");
- statHistDump(&f->comm_http_incoming, sentry, statHistIntDumper);
+ statCounter.comm_dns_incoming.dump(sentry, statHistIntDumper);
+ storeAppendPrintf(sentry, "HTTP Messages handled per comm_select_tcp_incoming() call:\n");
+ statCounter.comm_tcp_incoming.dump(sentry, statHistIntDumper);
}
void
{
if (handler && !FD_ISSET(fd, &global_readfds)) {
FD_SET(fd, &global_readfds);
- nreadfds++;
+ ++nreadfds;
} else if (!handler && FD_ISSET(fd, &global_readfds)) {
FD_CLR(fd, &global_readfds);
- nreadfds--;
+ --nreadfds;
}
}
{
if (handler && !FD_ISSET(fd, &global_writefds)) {
FD_SET(fd, &global_writefds);
- nwritefds++;
+ ++nwritefds;
} else if (!handler && FD_ISSET(fd, &global_writefds)) {
FD_CLR(fd, &global_writefds);
- nwritefds--;
+ --nwritefds;
}
}