]>
Commit | Line | Data |
---|---|---|
1b3db6d9 | 1 | /* |
262a0e14 | 2 | * $Id$ |
1b3db6d9 | 3 | * |
b510f3a1 | 4 | * DEBUG: section 05 Socket Functions |
1b3db6d9 | 5 | * |
6 | * SQUID Web Proxy Cache http://www.squid-cache.org/ | |
7 | * ---------------------------------------------------------- | |
8 | * | |
9 | * Squid is the result of efforts by numerous individuals from | |
10 | * the Internet community; see the CONTRIBUTORS file for full | |
11 | * details. Many organizations have provided support for Squid's | |
12 | * development; see the SPONSORS file for full details. Squid is | |
13 | * Copyrighted (C) 2001 by the Regents of the University of | |
14 | * California; see the COPYRIGHT file for full details. Squid | |
15 | * incorporates software developed and/or copyrighted by other | |
16 | * sources; see the CREDITS file for full details. | |
17 | * | |
18 | * This program is free software; you can redistribute it and/or modify | |
19 | * it under the terms of the GNU General Public License as published by | |
20 | * the Free Software Foundation; either version 2 of the License, or | |
21 | * (at your option) any later version. | |
26ac0430 | 22 | * |
1b3db6d9 | 23 | * This program is distributed in the hope that it will be useful, |
24 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
25 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
26 | * GNU General Public License for more details. | |
26ac0430 | 27 | * |
1b3db6d9 | 28 | * You should have received a copy of the GNU General Public License |
29 | * along with this program; if not, write to the Free Software | |
30 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111, USA. | |
31 | * | |
32 | */ | |
f7f3304a | 33 | #include "squid.h" |
d841c88d AJ |
34 | |
35 | #if USE_POLL | |
1b3db6d9 | 36 | |
f7f3304a | 37 | #include "squid-old.h" |
65d448bc | 38 | #include "anyp/PortCfg.h" |
1b76e6c1 | 39 | #include "comm/Connection.h" |
d841c88d AJ |
40 | #include "comm/Loops.h" |
41 | #include "fde.h" | |
1b76e6c1 | 42 | #include "ICP.h" |
8822ebee | 43 | #include "mgr/Registration.h" |
985c86bc | 44 | #include "SquidTime.h" |
e4f1fdae | 45 | #include "StatCounters.h" |
e6ccf245 | 46 | #include "Store.h" |
1b3db6d9 | 47 | |
dc47f531 AJ |
48 | #if HAVE_POLL_H |
49 | #include <poll.h> | |
50 | #endif | |
51 | ||
52 | /* Needed for poll() on Linux at least */ | |
53 | #if USE_POLL | |
54 | #ifndef POLLRDNORM | |
55 | #define POLLRDNORM POLLIN | |
56 | #endif | |
57 | #ifndef POLLWRNORM | |
58 | #define POLLWRNORM POLLOUT | |
59 | #endif | |
60 | #endif | |
61 | ||
d841c88d | 62 | static int MAX_POLL_TIME = 1000; /* see also Comm::QuickPollRequired() */ |
1b3db6d9 | 63 | |
64 | #ifndef howmany | |
65 | #define howmany(x, y) (((x)+((y)-1))/(y)) | |
66 | #endif | |
67 | #ifndef NBBY | |
68 | #define NBBY 8 | |
69 | #endif | |
70 | #define FD_MASK_BYTES sizeof(fd_mask) | |
71 | #define FD_MASK_BITS (FD_MASK_BYTES*NBBY) | |
72 | ||
73 | /* STATIC */ | |
65d448bc AJ |
74 | static int fdIsTcpListen(int fd); |
75 | static int fdIsUdpListen(int fd); | |
1b3db6d9 | 76 | static int fdIsDns(int fd); |
77 | static OBJH commIncomingStats; | |
78 | static int comm_check_incoming_poll_handlers(int nfds, int *fds); | |
79 | static void comm_poll_dns_incoming(void); | |
1b3db6d9 | 80 | |
81 | /* | |
82 | * Automatic tuning for incoming requests: | |
83 | * | |
84 | * INCOMING sockets are the ICP and HTTP ports. We need to check these | |
85 | * fairly regularly, but how often? When the load increases, we | |
86 | * want to check the incoming sockets more often. If we have a lot | |
87 | * of incoming ICP, then we need to check these sockets more than | |
88 | * if we just have HTTP. | |
89 | * | |
26ac0430 | 90 | * The variables 'incoming_icp_interval' and 'incoming_http_interval' |
1b3db6d9 | 91 | * determine how many normal I/O events to process before checking |
92 | * incoming sockets again. Note we store the incoming_interval | |
93 | * multipled by a factor of (2^INCOMING_FACTOR) to have some | |
94 | * pseudo-floating point precision. | |
95 | * | |
65d448bc | 96 | * The variable 'udp_io_events' and 'tcp_io_events' counts how many normal |
1b3db6d9 | 97 | * I/O events have been processed since the last check on the incoming |
98 | * sockets. When io_events > incoming_interval, its time to check incoming | |
99 | * sockets. | |
100 | * | |
101 | * Every time we check incoming sockets, we count how many new messages | |
102 | * or connections were processed. This is used to adjust the | |
103 | * incoming_interval for the next iteration. The new incoming_interval | |
104 | * is calculated as the current incoming_interval plus what we would | |
105 | * like to see as an average number of events minus the number of | |
106 | * events just processed. | |
107 | * | |
108 | * incoming_interval = incoming_interval + target_average - number_of_events_processed | |
109 | * | |
65d448bc | 110 | * There are separate incoming_interval counters for TCP-based, UDP-based, and DNS events |
26ac0430 | 111 | * |
1b3db6d9 | 112 | * You can see the current values of the incoming_interval's, as well as |
113 | * a histogram of 'incoming_events' by asking the cache manager | |
114 | * for 'comm_incoming', e.g.: | |
115 | * | |
62ee09ca | 116 | * % ./client mgr:comm_poll_incoming |
1b3db6d9 | 117 | * |
118 | * Caveats: | |
119 | * | |
120 | * - We have MAX_INCOMING_INTEGER as a magic upper limit on | |
121 | * incoming_interval for both types of sockets. At the | |
122 | * largest value the cache will effectively be idling. | |
123 | * | |
124 | * - The higher the INCOMING_FACTOR, the slower the algorithm will | |
125 | * respond to load spikes/increases/decreases in demand. A value | |
126 | * between 3 and 8 is recommended. | |
127 | */ | |
128 | ||
129 | #define MAX_INCOMING_INTEGER 256 | |
130 | #define INCOMING_FACTOR 5 | |
131 | #define MAX_INCOMING_INTERVAL (MAX_INCOMING_INTEGER << INCOMING_FACTOR) | |
65d448bc AJ |
132 | static int udp_io_events = 0; ///< I/O events passed since last UDP receiver socket poll |
133 | static int dns_io_events = 0; ///< I/O events passed since last DNS socket poll | |
134 | static int tcp_io_events = 0; ///< I/O events passed since last TCP listening socket poll | |
135 | static int incoming_udp_interval = 16 << INCOMING_FACTOR; | |
1b3db6d9 | 136 | static int incoming_dns_interval = 16 << INCOMING_FACTOR; |
65d448bc AJ |
137 | static int incoming_tcp_interval = 16 << INCOMING_FACTOR; |
138 | #define commCheckUdpIncoming (++udp_io_events > (incoming_udp_interval>> INCOMING_FACTOR)) | |
139 | #define commCheckDnsIncoming (++dns_io_events > (incoming_dns_interval>> INCOMING_FACTOR)) | |
140 | #define commCheckTcpIncoming (++tcp_io_events > (incoming_tcp_interval>> INCOMING_FACTOR)) | |
1b3db6d9 | 141 | |
142 | ||
143 | void | |
d841c88d | 144 | Comm::SetSelect(int fd, unsigned int type, PF * handler, void *client_data, time_t timeout) |
1b3db6d9 | 145 | { |
146 | fde *F = &fd_table[fd]; | |
147 | assert(fd >= 0); | |
148 | assert(F->flags.open); | |
48e7baac AJ |
149 | debugs(5, 5, HERE << "FD " << fd << ", type=" << type << |
150 | ", handler=" << handler << ", client_data=" << client_data << | |
151 | ", timeout=" << timeout); | |
62e76326 | 152 | |
1b3db6d9 | 153 | if (type & COMM_SELECT_READ) { |
62e76326 | 154 | F->read_handler = handler; |
155 | F->read_data = client_data; | |
1b3db6d9 | 156 | } |
62e76326 | 157 | |
1b3db6d9 | 158 | if (type & COMM_SELECT_WRITE) { |
62e76326 | 159 | F->write_handler = handler; |
160 | F->write_data = client_data; | |
1b3db6d9 | 161 | } |
62e76326 | 162 | |
1b3db6d9 | 163 | if (timeout) |
62e76326 | 164 | F->timeout = squid_curtime + timeout; |
1b3db6d9 | 165 | } |
166 | ||
3a5a4930 | 167 | void |
d841c88d | 168 | Comm::ResetSelect(int fd) |
3a5a4930 | 169 | { |
170 | } | |
171 | ||
1b3db6d9 | 172 | static int |
65d448bc | 173 | fdIsUdpListen(int fd) |
1b3db6d9 | 174 | { |
1b76e6c1 | 175 | if (icpIncomingConn != NULL && icpIncomingConn->fd == fd) |
62e76326 | 176 | return 1; |
177 | ||
1b76e6c1 | 178 | if (icpOutgoingConn != NULL && icpOutgoingConn->fd == fd) |
62e76326 | 179 | return 1; |
180 | ||
1b3db6d9 | 181 | return 0; |
182 | } | |
183 | ||
184 | static int | |
185 | fdIsDns(int fd) | |
186 | { | |
4d6c8504 AJ |
187 | if (fd == DnsSocketA) |
188 | return 1; | |
189 | ||
190 | if (fd == DnsSocketB) | |
62e76326 | 191 | return 1; |
192 | ||
1b3db6d9 | 193 | return 0; |
194 | } | |
195 | ||
196 | static int | |
65d448bc | 197 | fdIsTcpListen(int fd) |
1b3db6d9 | 198 | { |
65d448bc AJ |
199 | for (const AnyP::PortCfg *s = Config.Sockaddr.http; s; s = s->next) { |
200 | if (s->listenConn != NULL && s->listenConn->fd == fd) | |
62e76326 | 201 | return 1; |
1b3db6d9 | 202 | } |
62e76326 | 203 | |
1b3db6d9 | 204 | return 0; |
205 | } | |
206 | ||
1b3db6d9 | 207 | static int |
208 | comm_check_incoming_poll_handlers(int nfds, int *fds) | |
209 | { | |
210 | int i; | |
211 | int fd; | |
212 | PF *hdl = NULL; | |
213 | int npfds; | |
62e76326 | 214 | |
65d448bc | 215 | struct pollfd pfds[3 + MAXTCPLISTENPORTS]; |
88bfe092 | 216 | PROF_start(comm_check_incoming); |
1b3db6d9 | 217 | incoming_sockets_accepted = 0; |
62e76326 | 218 | |
098346fd | 219 | for (i = npfds = 0; i < nfds; ++i) { |
62e76326 | 220 | int events; |
221 | fd = fds[i]; | |
222 | events = 0; | |
223 | ||
224 | if (fd_table[fd].read_handler) | |
225 | events |= POLLRDNORM; | |
226 | ||
227 | if (fd_table[fd].write_handler) | |
228 | events |= POLLWRNORM; | |
229 | ||
230 | if (events) { | |
231 | pfds[npfds].fd = fd; | |
232 | pfds[npfds].events = events; | |
233 | pfds[npfds].revents = 0; | |
cbebe602 | 234 | ++npfds; |
62e76326 | 235 | } |
1b3db6d9 | 236 | } |
62e76326 | 237 | |
88bfe092 | 238 | if (!nfds) { |
62e76326 | 239 | PROF_stop(comm_check_incoming); |
240 | return -1; | |
88bfe092 | 241 | } |
62e76326 | 242 | |
1b3db6d9 | 243 | getCurrentTime(); |
098346fd | 244 | ++ statCounter.syscalls.selects; |
62e76326 | 245 | |
88bfe092 | 246 | if (poll(pfds, npfds, 0) < 1) { |
62e76326 | 247 | PROF_stop(comm_check_incoming); |
248 | return incoming_sockets_accepted; | |
88bfe092 | 249 | } |
62e76326 | 250 | |
cbebe602 | 251 | for (i = 0; i < npfds; ++i) { |
62e76326 | 252 | int revents; |
253 | ||
254 | if (((revents = pfds[i].revents) == 0) || ((fd = pfds[i].fd) == -1)) | |
255 | continue; | |
256 | ||
257 | if (revents & (POLLRDNORM | POLLIN | POLLHUP | POLLERR)) { | |
258 | if ((hdl = fd_table[fd].read_handler)) { | |
259 | fd_table[fd].read_handler = NULL; | |
260 | hdl(fd, fd_table[fd].read_data); | |
261 | } else if (pfds[i].events & POLLRDNORM) | |
e0236918 | 262 | debugs(5, DBG_IMPORTANT, "comm_poll_incoming: FD " << fd << " NULL read handler"); |
62e76326 | 263 | } |
264 | ||
265 | if (revents & (POLLWRNORM | POLLOUT | POLLHUP | POLLERR)) { | |
266 | if ((hdl = fd_table[fd].write_handler)) { | |
267 | fd_table[fd].write_handler = NULL; | |
268 | hdl(fd, fd_table[fd].write_data); | |
269 | } else if (pfds[i].events & POLLWRNORM) | |
e0236918 | 270 | debugs(5, DBG_IMPORTANT, "comm_poll_incoming: FD " << fd << " NULL write_handler"); |
62e76326 | 271 | } |
1b3db6d9 | 272 | } |
62e76326 | 273 | |
88bfe092 | 274 | PROF_stop(comm_check_incoming); |
1b3db6d9 | 275 | return incoming_sockets_accepted; |
276 | } | |
277 | ||
278 | static void | |
65d448bc | 279 | comm_poll_udp_incoming(void) |
1b3db6d9 | 280 | { |
281 | int nfds = 0; | |
282 | int fds[2]; | |
283 | int nevents; | |
65d448bc | 284 | udp_io_events = 0; |
62e76326 | 285 | |
098346fd FC |
286 | if (Comm::IsConnOpen(icpIncomingConn)) { |
287 | fds[nfds] = icpIncomingConn->fd; | |
288 | ++nfds; | |
289 | } | |
62e76326 | 290 | |
098346fd FC |
291 | if (icpIncomingConn != icpOutgoingConn && Comm::IsConnOpen(icpOutgoingConn)) { |
292 | fds[nfds] = icpOutgoingConn->fd; | |
293 | ++nfds; | |
294 | } | |
62e76326 | 295 | |
1b3db6d9 | 296 | if (nfds == 0) |
62e76326 | 297 | return; |
298 | ||
1b3db6d9 | 299 | nevents = comm_check_incoming_poll_handlers(nfds, fds); |
62e76326 | 300 | |
65d448bc | 301 | incoming_udp_interval += Config.comm_incoming.udp.average - nevents; |
62e76326 | 302 | |
65d448bc AJ |
303 | if (incoming_udp_interval < Config.comm_incoming.udp.min_poll) |
304 | incoming_udp_interval = Config.comm_incoming.udp.min_poll; | |
62e76326 | 305 | |
65d448bc AJ |
306 | if (incoming_udp_interval > MAX_INCOMING_INTERVAL) |
307 | incoming_udp_interval = MAX_INCOMING_INTERVAL; | |
62e76326 | 308 | |
65d448bc AJ |
309 | if (nevents > INCOMING_UDP_MAX) |
310 | nevents = INCOMING_UDP_MAX; | |
62e76326 | 311 | |
65d448bc | 312 | statCounter.comm_udp_incoming.count(nevents); |
1b3db6d9 | 313 | } |
314 | ||
315 | static void | |
65d448bc | 316 | comm_poll_tcp_incoming(void) |
1b3db6d9 | 317 | { |
318 | int nfds = 0; | |
65d448bc | 319 | int fds[MAXTCPLISTENPORTS]; |
1b3db6d9 | 320 | int j; |
321 | int nevents; | |
65d448bc | 322 | tcp_io_events = 0; |
62e76326 | 323 | |
65d448bc | 324 | // XXX: only poll sockets that won't be deferred. But how do we identify them? |
a46d2c0e | 325 | |
098346fd | 326 | for (j = 0; j < NHttpSockets; ++j) { |
62e76326 | 327 | if (HttpSockets[j] < 0) |
328 | continue; | |
329 | ||
098346fd FC |
330 | fds[nfds] = HttpSockets[j]; |
331 | ++nfds; | |
1b3db6d9 | 332 | } |
62e76326 | 333 | |
1b3db6d9 | 334 | nevents = comm_check_incoming_poll_handlers(nfds, fds); |
65d448bc | 335 | incoming_tcp_interval = incoming_tcp_interval |
04401ab0 | 336 | + Config.comm_incoming.tcp.average - nevents; |
62e76326 | 337 | |
65d448bc AJ |
338 | if (incoming_tcp_interval < Config.comm_incoming.tcp.min_poll) |
339 | incoming_tcp_interval = Config.comm_incoming.tcp.min_poll; | |
62e76326 | 340 | |
65d448bc AJ |
341 | if (incoming_tcp_interval > MAX_INCOMING_INTERVAL) |
342 | incoming_tcp_interval = MAX_INCOMING_INTERVAL; | |
62e76326 | 343 | |
65d448bc AJ |
344 | if (nevents > INCOMING_TCP_MAX) |
345 | nevents = INCOMING_TCP_MAX; | |
62e76326 | 346 | |
65d448bc | 347 | statCounter.comm_tcp_incoming.count(nevents); |
1b3db6d9 | 348 | } |
349 | ||
350 | /* poll all sockets; call handlers for those that are ready. */ | |
3d7e9d7c | 351 | comm_err_t |
d841c88d | 352 | Comm::DoSelect(int msec) |
1b3db6d9 | 353 | { |
354 | struct pollfd pfds[SQUID_MAXFD]; | |
62e76326 | 355 | |
1b3db6d9 | 356 | PF *hdl = NULL; |
357 | int fd; | |
1b3db6d9 | 358 | int maxfd; |
359 | unsigned long nfds; | |
360 | unsigned long npending; | |
361 | int num; | |
65d448bc | 362 | int calldns = 0, calludp = 0, calltcp = 0; |
1b3db6d9 | 363 | double timeout = current_dtime + (msec / 1000.0); |
62e76326 | 364 | |
1b3db6d9 | 365 | do { |
62e76326 | 366 | double start; |
367 | getCurrentTime(); | |
368 | start = current_dtime; | |
62e76326 | 369 | |
65d448bc AJ |
370 | if (commCheckUdpIncoming) |
371 | comm_poll_udp_incoming(); | |
62e76326 | 372 | |
65d448bc | 373 | if (commCheckDnsIncoming) |
62e76326 | 374 | comm_poll_dns_incoming(); |
375 | ||
65d448bc AJ |
376 | if (commCheckTcpIncoming) |
377 | comm_poll_tcp_incoming(); | |
62e76326 | 378 | |
379 | PROF_start(comm_poll_prep_pfds); | |
380 | ||
65d448bc | 381 | calldns = calludp = calltcp = 0; |
62e76326 | 382 | |
383 | nfds = 0; | |
384 | ||
385 | npending = 0; | |
386 | ||
387 | maxfd = Biggest_FD + 1; | |
388 | ||
098346fd | 389 | for (int i = 0; i < maxfd; ++i) { |
62e76326 | 390 | int events; |
391 | events = 0; | |
392 | /* Check each open socket for a handler. */ | |
393 | ||
a46d2c0e | 394 | if (fd_table[i].read_handler) |
395 | events |= POLLRDNORM; | |
62e76326 | 396 | |
397 | if (fd_table[i].write_handler) | |
398 | events |= POLLWRNORM; | |
399 | ||
400 | if (events) { | |
401 | pfds[nfds].fd = i; | |
402 | pfds[nfds].events = events; | |
403 | pfds[nfds].revents = 0; | |
cbebe602 | 404 | ++nfds; |
62e76326 | 405 | |
406 | if ((events & POLLRDNORM) && fd_table[i].flags.read_pending) | |
cbebe602 | 407 | ++npending; |
62e76326 | 408 | } |
409 | } | |
410 | ||
411 | PROF_stop(comm_poll_prep_pfds); | |
412 | ||
62e76326 | 413 | if (npending) |
414 | msec = 0; | |
415 | ||
416 | if (msec > MAX_POLL_TIME) | |
417 | msec = MAX_POLL_TIME; | |
418 | ||
8ff3fa2e | 419 | /* nothing to do |
420 | * | |
421 | * Note that this will only ever trigger when there are no log files | |
422 | * and stdout/err/in are all closed too. | |
423 | */ | |
425e3a42 | 424 | if (nfds == 0 && npending == 0) { |
a553a5a3 | 425 | if (shutting_down) |
426 | return COMM_SHUTDOWN; | |
427 | else | |
428 | return COMM_IDLE; | |
429 | } | |
430 | ||
62e76326 | 431 | for (;;) { |
432 | PROF_start(comm_poll_normal); | |
098346fd | 433 | ++ statCounter.syscalls.selects; |
62e76326 | 434 | num = poll(pfds, nfds, msec); |
098346fd | 435 | ++ statCounter.select_loops; |
62e76326 | 436 | PROF_stop(comm_poll_normal); |
437 | ||
425e3a42 | 438 | if (num >= 0 || npending > 0) |
62e76326 | 439 | break; |
440 | ||
441 | if (ignoreErrno(errno)) | |
442 | continue; | |
443 | ||
bf8fe701 | 444 | debugs(5, 0, "comm_poll: poll failure: " << xstrerror()); |
62e76326 | 445 | |
446 | assert(errno != EINVAL); | |
447 | ||
448 | return COMM_ERROR; | |
449 | ||
450 | /* NOTREACHED */ | |
451 | } | |
452 | ||
40a77eef | 453 | getCurrentTime(); |
454 | ||
bf8fe701 | 455 | debugs(5, num ? 5 : 8, "comm_poll: " << num << "+" << npending << " FDs ready"); |
f30f7998 | 456 | statCounter.select_fds_hist.count(num); |
62e76326 | 457 | |
458 | if (num == 0 && npending == 0) | |
459 | continue; | |
460 | ||
461 | /* scan each socket but the accept socket. Poll this | |
26ac0430 | 462 | * more frequently to minimize losses due to the 5 connect |
62e76326 | 463 | * limit in SunOS */ |
464 | PROF_start(comm_handle_ready_fd); | |
465 | ||
098346fd | 466 | for (size_t loopIndex = 0; loopIndex < nfds; ++loopIndex) { |
62e76326 | 467 | fde *F; |
468 | int revents = pfds[loopIndex].revents; | |
469 | fd = pfds[loopIndex].fd; | |
470 | ||
471 | if (fd == -1) | |
472 | continue; | |
473 | ||
474 | if (fd_table[fd].flags.read_pending) | |
475 | revents |= POLLIN; | |
476 | ||
477 | if (revents == 0) | |
478 | continue; | |
479 | ||
65d448bc AJ |
480 | if (fdIsUdpListen(fd)) { |
481 | calludp = 1; | |
62e76326 | 482 | continue; |
483 | } | |
484 | ||
485 | if (fdIsDns(fd)) { | |
486 | calldns = 1; | |
487 | continue; | |
488 | } | |
489 | ||
65d448bc AJ |
490 | if (fdIsTcpListen(fd)) { |
491 | calltcp = 1; | |
62e76326 | 492 | continue; |
493 | } | |
494 | ||
495 | F = &fd_table[fd]; | |
496 | ||
497 | if (revents & (POLLRDNORM | POLLIN | POLLHUP | POLLERR)) { | |
bf8fe701 | 498 | debugs(5, 6, "comm_poll: FD " << fd << " ready for reading"); |
62e76326 | 499 | |
65d448bc | 500 | if ((hdl = F->read_handler)) { |
62e76326 | 501 | PROF_start(comm_read_handler); |
502 | F->read_handler = NULL; | |
26ac0430 | 503 | F->flags.read_pending = 0; |
62e76326 | 504 | hdl(fd, F->read_data); |
505 | PROF_stop(comm_read_handler); | |
098346fd | 506 | ++ statCounter.select_fds; |
62e76326 | 507 | |
65d448bc AJ |
508 | if (commCheckUdpIncoming) |
509 | comm_poll_udp_incoming(); | |
62e76326 | 510 | |
65d448bc | 511 | if (commCheckDnsIncoming) |
62e76326 | 512 | comm_poll_dns_incoming(); |
513 | ||
65d448bc AJ |
514 | if (commCheckTcpIncoming) |
515 | comm_poll_tcp_incoming(); | |
62e76326 | 516 | } |
517 | } | |
518 | ||
519 | if (revents & (POLLWRNORM | POLLOUT | POLLHUP | POLLERR)) { | |
48e7baac | 520 | debugs(5, 6, "comm_poll: FD " << fd << " ready for writing"); |
62e76326 | 521 | |
522 | if ((hdl = F->write_handler)) { | |
523 | PROF_start(comm_write_handler); | |
524 | F->write_handler = NULL; | |
525 | hdl(fd, F->write_data); | |
526 | PROF_stop(comm_write_handler); | |
098346fd | 527 | ++ statCounter.select_fds; |
62e76326 | 528 | |
65d448bc AJ |
529 | if (commCheckUdpIncoming) |
530 | comm_poll_udp_incoming(); | |
62e76326 | 531 | |
65d448bc | 532 | if (commCheckDnsIncoming) |
62e76326 | 533 | comm_poll_dns_incoming(); |
534 | ||
65d448bc AJ |
535 | if (commCheckTcpIncoming) |
536 | comm_poll_tcp_incoming(); | |
62e76326 | 537 | } |
538 | } | |
539 | ||
540 | if (revents & POLLNVAL) { | |
6d527e0a | 541 | AsyncCall::Pointer ch; |
bf8fe701 | 542 | debugs(5, 0, "WARNING: FD " << fd << " has handlers, but it's invalid."); |
543 | debugs(5, 0, "FD " << fd << " is a " << fdTypeStr[F->type]); | |
544 | debugs(5, 0, "--> " << F->desc); | |
26ac0430 | 545 | debugs(5, 0, "tmout:" << F->timeoutHandler << "read:" << |
bf8fe701 | 546 | F->read_handler << " write:" << F->write_handler); |
62e76326 | 547 | |
6d527e0a | 548 | for (ch = F->closeHandler; ch != NULL; ch = ch->Next()) |
549 | debugs(5, 0, " close handler: " << ch); | |
62e76326 | 550 | |
6d527e0a | 551 | if (F->closeHandler != NULL) { |
62e76326 | 552 | commCallCloseHandlers(fd); |
6d527e0a | 553 | } else if (F->timeoutHandler != NULL) { |
bf8fe701 | 554 | debugs(5, 0, "comm_poll: Calling Timeout Handler"); |
26ac0430 | 555 | ScheduleCallHere(F->timeoutHandler); |
62e76326 | 556 | } |
557 | ||
558 | F->closeHandler = NULL; | |
6d527e0a | 559 | F->timeoutHandler = NULL; |
62e76326 | 560 | F->read_handler = NULL; |
561 | F->write_handler = NULL; | |
562 | ||
563 | if (F->flags.open) | |
564 | fd_close(fd); | |
565 | } | |
566 | } | |
567 | ||
568 | PROF_stop(comm_handle_ready_fd); | |
569 | ||
65d448bc AJ |
570 | if (calludp) |
571 | comm_poll_udp_incoming(); | |
62e76326 | 572 | |
573 | if (calldns) | |
574 | comm_poll_dns_incoming(); | |
575 | ||
65d448bc AJ |
576 | if (calltcp) |
577 | comm_poll_tcp_incoming(); | |
62e76326 | 578 | |
62e76326 | 579 | getCurrentTime(); |
580 | ||
581 | statCounter.select_time += (current_dtime - start); | |
582 | ||
583 | return COMM_OK; | |
584 | } while (timeout > current_dtime); | |
585 | ||
4a7a3d56 | 586 | debugs(5, 8, "comm_poll: time out: " << squid_curtime << "."); |
62e76326 | 587 | |
1b3db6d9 | 588 | return COMM_TIMEOUT; |
589 | } | |
590 | ||
591 | ||
592 | static void | |
593 | comm_poll_dns_incoming(void) | |
594 | { | |
595 | int nfds = 0; | |
596 | int fds[2]; | |
597 | int nevents; | |
598 | dns_io_events = 0; | |
62e76326 | 599 | |
055421ee | 600 | if (DnsSocketA < 0 && DnsSocketB < 0) |
62e76326 | 601 | return; |
602 | ||
098346fd FC |
603 | if (DnsSocketA >= 0) { |
604 | fds[nfds] = DnsSocketA; | |
605 | ++nfds; | |
606 | } | |
4d6c8504 | 607 | |
098346fd FC |
608 | if (DnsSocketB >= 0) { |
609 | fds[nfds] = DnsSocketB; | |
610 | ++nfds; | |
611 | } | |
62e76326 | 612 | |
1b3db6d9 | 613 | nevents = comm_check_incoming_poll_handlers(nfds, fds); |
62e76326 | 614 | |
1b3db6d9 | 615 | if (nevents < 0) |
62e76326 | 616 | return; |
617 | ||
65d448bc | 618 | incoming_dns_interval += Config.comm_incoming.dns.average - nevents; |
62e76326 | 619 | |
65d448bc AJ |
620 | if (incoming_dns_interval < Config.comm_incoming.dns.min_poll) |
621 | incoming_dns_interval = Config.comm_incoming.dns.min_poll; | |
62e76326 | 622 | |
1b3db6d9 | 623 | if (incoming_dns_interval > MAX_INCOMING_INTERVAL) |
62e76326 | 624 | incoming_dns_interval = MAX_INCOMING_INTERVAL; |
625 | ||
1b3db6d9 | 626 | if (nevents > INCOMING_DNS_MAX) |
62e76326 | 627 | nevents = INCOMING_DNS_MAX; |
628 | ||
f30f7998 | 629 | statCounter.comm_dns_incoming.count(nevents); |
1b3db6d9 | 630 | } |
631 | ||
62ee09ca | 632 | |
5acc9f37 | 633 | static void |
edfab338 | 634 | commPollRegisterWithCacheManager(void) |
1b3db6d9 | 635 | { |
8822ebee | 636 | Mgr::RegisterAction("comm_poll_incoming", |
d9fc6862 A |
637 | "comm_incoming() stats", |
638 | commIncomingStats, 0, 1); | |
1b3db6d9 | 639 | } |
640 | ||
5acc9f37 | 641 | void |
d841c88d | 642 | Comm::SelectLoopInit(void) |
5acc9f37 FC |
643 | { |
644 | commPollRegisterWithCacheManager(); | |
645 | } | |
1b3db6d9 | 646 | |
647 | static void | |
648 | commIncomingStats(StoreEntry * sentry) | |
649 | { | |
65d448bc AJ |
650 | storeAppendPrintf(sentry, "Current incoming_udp_interval: %d\n", |
651 | incoming_udp_interval >> INCOMING_FACTOR); | |
1b3db6d9 | 652 | storeAppendPrintf(sentry, "Current incoming_dns_interval: %d\n", |
62e76326 | 653 | incoming_dns_interval >> INCOMING_FACTOR); |
65d448bc AJ |
654 | storeAppendPrintf(sentry, "Current incoming_tcp_interval: %d\n", |
655 | incoming_tcp_interval >> INCOMING_FACTOR); | |
1b3db6d9 | 656 | storeAppendPrintf(sentry, "\n"); |
657 | storeAppendPrintf(sentry, "Histogram of events per incoming socket type\n"); | |
65d448bc AJ |
658 | storeAppendPrintf(sentry, "ICP Messages handled per comm_poll_udp_incoming() call:\n"); |
659 | statCounter.comm_udp_incoming.dump(sentry, statHistIntDumper); | |
1b3db6d9 | 660 | storeAppendPrintf(sentry, "DNS Messages handled per comm_poll_dns_incoming() call:\n"); |
82146cc8 | 661 | statCounter.comm_dns_incoming.dump(sentry, statHistIntDumper); |
65d448bc AJ |
662 | storeAppendPrintf(sentry, "HTTP Messages handled per comm_poll_tcp_incoming() call:\n"); |
663 | statCounter.comm_tcp_incoming.dump(sentry, statHistIntDumper); | |
1b3db6d9 | 664 | } |
665 | ||
1b3db6d9 | 666 | /* Called by async-io or diskd to speed up the polling */ |
667 | void | |
d841c88d | 668 | Comm::QuickPollRequired(void) |
1b3db6d9 | 669 | { |
670 | MAX_POLL_TIME = 10; | |
671 | } | |
672 | ||
673 | #endif /* USE_POLL */ |