]> git.ipfire.org Git - thirdparty/squid.git/blob - src/comm_select_win32.cc
Bug #2150: Connection hangs on automatic retry
[thirdparty/squid.git] / src / comm_select_win32.cc
1
2 /*
3 * $Id: comm_select_win32.cc,v 1.5 2008/01/07 16:22:06 hno Exp $
4 *
5 * DEBUG: section 5 Socket Functions
6 *
7 * SQUID Web Proxy Cache http://www.squid-cache.org/
8 * ----------------------------------------------------------
9 *
10 * Squid is the result of efforts by numerous individuals from
11 * the Internet community; see the CONTRIBUTORS file for full
12 * details. Many organizations have provided support for Squid's
13 * development; see the SPONSORS file for full details. Squid is
14 * Copyrighted (C) 2001 by the Regents of the University of
15 * California; see the COPYRIGHT file for full details. Squid
16 * incorporates software developed and/or copyrighted by other
17 * sources; see the CREDITS file for full details.
18 *
19 * This program is free software; you can redistribute it and/or modify
20 * it under the terms of the GNU General Public License as published by
21 * the Free Software Foundation; either version 2 of the License, or
22 * (at your option) any later version.
23 *
24 * This program is distributed in the hope that it will be useful,
25 * but WITHOUT ANY WARRANTY; without even the implied warranty of
26 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
27 * GNU General Public License for more details.
28 *
29 * You should have received a copy of the GNU General Public License
30 * along with this program; if not, write to the Free Software
31 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111, USA.
32 *
33 */
34
35 #include "squid.h"
36 #include "comm_select.h"
37 #include "CacheManager.h"
38 #include "SquidTime.h"
39
40 #ifdef USE_SELECT_WIN32
41 #include "Store.h"
42 #include "fde.h"
43
44 static int MAX_POLL_TIME = 1000; /* see also comm_quick_poll_required() */
45
46 #ifndef howmany
47 #define howmany(x, y) (((x)+((y)-1))/(y))
48 #endif
49 #ifndef NBBY
50 #define NBBY 8
51 #endif
52 #define FD_MASK_BYTES sizeof(fd_mask)
53 #define FD_MASK_BITS (FD_MASK_BYTES*NBBY)
54
55 /* STATIC */
56 static int examine_select(fd_set *, fd_set *);
57 static int fdIsHttp(int fd);
58 static int fdIsIcp(int fd);
59 static int fdIsDns(int fd);
60 static OBJH commIncomingStats;
61 static int comm_check_incoming_select_handlers(int nfds, int *fds);
62 static void comm_select_dns_incoming(void);
63 static void commUpdateReadBits(int fd, PF * handler);
64 static void commUpdateWriteBits(int fd, PF * handler);
65
66
67 static struct timeval zero_tv;
68 static fd_set global_readfds;
69 static fd_set global_writefds;
70 static int nreadfds;
71 static int nwritefds;
72
73 /*
74 * Automatic tuning for incoming requests:
75 *
76 * INCOMING sockets are the ICP and HTTP ports. We need to check these
77 * fairly regularly, but how often? When the load increases, we
78 * want to check the incoming sockets more often. If we have a lot
79 * of incoming ICP, then we need to check these sockets more than
80 * if we just have HTTP.
81 *
82 * The variables 'incoming_icp_interval' and 'incoming_http_interval'
83 * determine how many normal I/O events to process before checking
84 * incoming sockets again. Note we store the incoming_interval
85 * multipled by a factor of (2^INCOMING_FACTOR) to have some
86 * pseudo-floating point precision.
87 *
88 * The variable 'icp_io_events' and 'http_io_events' counts how many normal
89 * I/O events have been processed since the last check on the incoming
90 * sockets. When io_events > incoming_interval, its time to check incoming
91 * sockets.
92 *
93 * Every time we check incoming sockets, we count how many new messages
94 * or connections were processed. This is used to adjust the
95 * incoming_interval for the next iteration. The new incoming_interval
96 * is calculated as the current incoming_interval plus what we would
97 * like to see as an average number of events minus the number of
98 * events just processed.
99 *
100 * incoming_interval = incoming_interval + target_average - number_of_events_processed
101 *
102 * There are separate incoming_interval counters for both HTTP and ICP events
103 *
104 * You can see the current values of the incoming_interval's, as well as
105 * a histogram of 'incoming_events' by asking the cache manager
106 * for 'comm_incoming', e.g.:
107 *
108 * % ./client mgr:comm_incoming
109 *
110 * Caveats:
111 *
112 * - We have MAX_INCOMING_INTEGER as a magic upper limit on
113 * incoming_interval for both types of sockets. At the
114 * largest value the cache will effectively be idling.
115 *
116 * - The higher the INCOMING_FACTOR, the slower the algorithm will
117 * respond to load spikes/increases/decreases in demand. A value
118 * between 3 and 8 is recommended.
119 */
120
121 #define MAX_INCOMING_INTEGER 256
122 #define INCOMING_FACTOR 5
123 #define MAX_INCOMING_INTERVAL (MAX_INCOMING_INTEGER << INCOMING_FACTOR)
124 static int icp_io_events = 0;
125 static int dns_io_events = 0;
126 static int http_io_events = 0;
127 static int incoming_icp_interval = 16 << INCOMING_FACTOR;
128 static int incoming_dns_interval = 16 << INCOMING_FACTOR;
129 static int incoming_http_interval = 16 << INCOMING_FACTOR;
130 #define commCheckICPIncoming (++icp_io_events > (incoming_icp_interval>> INCOMING_FACTOR))
131 #define commCheckDNSIncoming (++dns_io_events > (incoming_dns_interval>> INCOMING_FACTOR))
132 #define commCheckHTTPIncoming (++http_io_events > (incoming_http_interval>> INCOMING_FACTOR))
133
134 void
135 commSetSelect(int fd, unsigned int type, PF * handler, void *client_data,
136 time_t timeout)
137 {
138 fde *F = &fd_table[fd];
139 assert(fd >= 0);
140 assert(F->flags.open);
141 debugs(5, 5, "commSetSelect: FD " << fd << " type " << type);
142
143 if (type & COMM_SELECT_READ) {
144 F->read_handler = handler;
145 F->read_data = client_data;
146 commUpdateReadBits(fd, handler);
147 }
148
149 if (type & COMM_SELECT_WRITE) {
150 F->write_handler = handler;
151 F->write_data = client_data;
152 commUpdateWriteBits(fd, handler);
153 }
154
155 if (timeout)
156 F->timeout = squid_curtime + timeout;
157 }
158
159 void
160 commResetSelect(int fd)
161 {
162 }
163
164
165 static int
166 fdIsIcp(int fd)
167 {
168 if (fd == theInIcpConnection)
169 return 1;
170
171 if (fd == theOutIcpConnection)
172 return 1;
173
174 return 0;
175 }
176
177 static int
178 fdIsDns(int fd)
179 {
180 if (fd == DnsSocket)
181 return 1;
182
183 return 0;
184 }
185
186 static int
187 fdIsHttp(int fd)
188 {
189 int j;
190
191 for (j = 0; j < NHttpSockets; j++) {
192 if (fd == HttpSockets[j])
193 return 1;
194 }
195
196 return 0;
197 }
198
199 #if DELAY_POOLS
200 static int slowfdcnt = 0;
201 static int slowfdarr[SQUID_MAXFD];
202
203 static void
204 commAddSlowFd(int fd)
205 {
206 assert(slowfdcnt < SQUID_MAXFD);
207 slowfdarr[slowfdcnt++] = fd;
208 }
209
210 static int
211 commGetSlowFd(void)
212 {
213 int whichfd, retfd;
214
215 if (!slowfdcnt)
216 return -1;
217
218 whichfd = squid_random() % slowfdcnt;
219
220 retfd = slowfdarr[whichfd];
221
222 slowfdarr[whichfd] = slowfdarr[--slowfdcnt];
223
224 return retfd;
225 }
226
227 #endif
228
229 static int
230 comm_check_incoming_select_handlers(int nfds, int *fds)
231 {
232 int i;
233 int fd;
234 int maxfd = 0;
235 PF *hdl = NULL;
236 fd_set read_mask;
237 fd_set write_mask;
238 fd_set errfds;
239 FD_ZERO(&errfds);
240 FD_ZERO(&read_mask);
241 FD_ZERO(&write_mask);
242 incoming_sockets_accepted = 0;
243
244 for (i = 0; i < nfds; i++) {
245 fd = fds[i];
246
247 if (fd_table[fd].read_handler) {
248 FD_SET(fd, &read_mask);
249
250 if (fd > maxfd)
251 maxfd = fd;
252 }
253
254 if (fd_table[fd].write_handler) {
255 FD_SET(fd, &write_mask);
256
257 if (fd > maxfd)
258 maxfd = fd;
259 }
260 }
261
262 if (maxfd++ == 0)
263 return -1;
264
265 getCurrentTime();
266
267 statCounter.syscalls.selects++;
268
269 if (select(maxfd, &read_mask, &write_mask, &errfds, &zero_tv) < 1)
270
271 return incoming_sockets_accepted;
272
273 for (i = 0; i < nfds; i++) {
274 fd = fds[i];
275
276 if (FD_ISSET(fd, &read_mask)) {
277 if ((hdl = fd_table[fd].read_handler) != NULL) {
278 fd_table[fd].read_handler = NULL;
279 commUpdateReadBits(fd, NULL);
280 hdl(fd, fd_table[fd].read_data);
281 } else {
282 debugs(5, 1, "comm_select_incoming: FD " << fd << " NULL read handler");
283 }
284 }
285
286 if (FD_ISSET(fd, &write_mask)) {
287 if ((hdl = fd_table[fd].write_handler) != NULL) {
288 fd_table[fd].write_handler = NULL;
289 commUpdateWriteBits(fd, NULL);
290 hdl(fd, fd_table[fd].write_data);
291 } else {
292 debugs(5, 1, "comm_select_incoming: FD " << fd << " NULL write handler");
293 }
294 }
295 }
296
297 return incoming_sockets_accepted;
298 }
299
300 static void
301 comm_select_icp_incoming(void)
302 {
303 int nfds = 0;
304 int fds[2];
305 int nevents;
306 icp_io_events = 0;
307
308 if (theInIcpConnection >= 0)
309 fds[nfds++] = theInIcpConnection;
310
311 if (theInIcpConnection != theOutIcpConnection)
312 if (theOutIcpConnection >= 0)
313 fds[nfds++] = theOutIcpConnection;
314
315 if (nfds == 0)
316 return;
317
318 nevents = comm_check_incoming_select_handlers(nfds, fds);
319
320 incoming_icp_interval += Config.comm_incoming.icp_average - nevents;
321
322 if (incoming_icp_interval < 0)
323 incoming_icp_interval = 0;
324
325 if (incoming_icp_interval > MAX_INCOMING_INTERVAL)
326 incoming_icp_interval = MAX_INCOMING_INTERVAL;
327
328 if (nevents > INCOMING_ICP_MAX)
329 nevents = INCOMING_ICP_MAX;
330
331 statHistCount(&statCounter.comm_icp_incoming, nevents);
332 }
333
334 static void
335 comm_select_http_incoming(void)
336 {
337 int nfds = 0;
338 int fds[MAXHTTPPORTS];
339 int j;
340 int nevents;
341 http_io_events = 0;
342
343 for (j = 0; j < NHttpSockets; j++) {
344 if (HttpSockets[j] < 0)
345 continue;
346
347 fds[nfds++] = HttpSockets[j];
348 }
349
350 nevents = comm_check_incoming_select_handlers(nfds, fds);
351 incoming_http_interval += Config.comm_incoming.http_average - nevents;
352
353 if (incoming_http_interval < 0)
354 incoming_http_interval = 0;
355
356 if (incoming_http_interval > MAX_INCOMING_INTERVAL)
357 incoming_http_interval = MAX_INCOMING_INTERVAL;
358
359 if (nevents > INCOMING_HTTP_MAX)
360 nevents = INCOMING_HTTP_MAX;
361
362 statHistCount(&statCounter.comm_http_incoming, nevents);
363 }
364
365 #define DEBUG_FDBITS 0
366 /* Select on all sockets; call handlers for those that are ready. */
367 comm_err_t
368 comm_select(int msec)
369 {
370 fd_set readfds;
371 fd_set pendingfds;
372 fd_set writefds;
373 #if DELAY_POOLS
374
375 fd_set slowfds;
376 #endif
377
378 PF *hdl = NULL;
379 int fd;
380 int maxfd;
381 int num;
382 int pending;
383 int callicp = 0, callhttp = 0;
384 int calldns = 0;
385 int j;
386 #if DEBUG_FDBITS
387
388 int i;
389 #endif
390 struct timeval poll_time;
391 double timeout = current_dtime + (msec / 1000.0);
392 fde *F;
393
394 int no_bits;
395 fd_set errfds;
396 FD_ZERO(&errfds);
397
398 do {
399 double start;
400 getCurrentTime();
401 start = current_dtime;
402 #if DELAY_POOLS
403
404 FD_ZERO(&slowfds);
405 #endif
406
407 if (commCheckICPIncoming)
408 comm_select_icp_incoming();
409
410 if (commCheckDNSIncoming)
411 comm_select_dns_incoming();
412
413 if (commCheckHTTPIncoming)
414 comm_select_http_incoming();
415
416 callicp = calldns = callhttp = 0;
417
418 maxfd = Biggest_FD + 1;
419
420 xmemcpy(&readfds, &global_readfds, sizeof(global_readfds));
421
422 xmemcpy(&writefds, &global_writefds, sizeof(global_writefds));
423
424 xmemcpy(&errfds, &global_writefds, sizeof(global_writefds));
425
426 /* remove stalled FDs, and deal with pending descriptors */
427 pending = 0;
428
429 FD_ZERO(&pendingfds);
430
431 for (j = 0; j < (int) readfds.fd_count; j++) {
432 register int readfds_handle = readfds.fd_array[j];
433 no_bits = 1;
434
435 for ( fd = Biggest_FD; fd; fd-- ) {
436 if ( fd_table[fd].win32.handle == readfds_handle ) {
437 if (fd_table[fd].flags.open) {
438 no_bits = 0;
439 break;
440 }
441 }
442 }
443
444 if (no_bits)
445 continue;
446
447 if (FD_ISSET(fd, &readfds) && fd_table[fd].flags.read_pending) {
448 FD_SET(fd, &pendingfds);
449 pending++;
450 }
451 }
452
453 #if DEBUG_FDBITS
454 for (i = 0; i < maxfd; i++) {
455 /* Check each open socket for a handler. */
456
457 if (fd_table[i].read_handler) {
458 assert(FD_ISSET(i, &readfds));
459 }
460
461 if (fd_table[i].write_handler) {
462 assert(FD_ISSET(i, &writefds));
463 }
464 }
465
466 #endif
467 if (nreadfds + nwritefds == 0) {
468 assert(shutting_down);
469 return COMM_SHUTDOWN;
470 }
471
472 if (msec > MAX_POLL_TIME)
473 msec = MAX_POLL_TIME;
474
475 if (comm_iocallbackpending())
476 pending++;
477
478 if (pending)
479 msec = 0;
480
481 for (;;) {
482 poll_time.tv_sec = msec / 1000;
483 poll_time.tv_usec = (msec % 1000) * 1000;
484 statCounter.syscalls.selects++;
485 num = select(maxfd, &readfds, &writefds, &errfds, &poll_time);
486 statCounter.select_loops++;
487
488 if (num >= 0 || pending > 0)
489 break;
490
491 if (ignoreErrno(errno))
492 break;
493
494 debugs(5, 0, "comm_select: select failure: " << xstrerror());
495
496 examine_select(&readfds, &writefds);
497
498 return COMM_ERROR;
499
500 /* NOTREACHED */
501 }
502
503 if (num < 0 && !pending)
504 continue;
505
506 getCurrentTime();
507
508 debugs(5, num ? 5 : 8, "comm_select: " << num << "+" << pending << " FDs ready\n");
509
510 statHistCount(&statCounter.select_fds_hist, num);
511
512 if (num == 0 && pending == 0)
513 continue;
514
515 /* Scan return fd masks for ready descriptors */
516
517 assert(readfds.fd_count <= (unsigned int) Biggest_FD);
518
519 assert(pendingfds.fd_count <= (unsigned int) Biggest_FD);
520
521 for (j = 0; j < (int) readfds.fd_count; j++) {
522 register int readfds_handle = readfds.fd_array[j];
523 register int pendingfds_handle = pendingfds.fd_array[j];
524 register int osfhandle;
525 no_bits = 1;
526
527 for ( fd = Biggest_FD; fd; fd-- ) {
528 osfhandle = fd_table[fd].win32.handle;
529
530 if (( osfhandle == readfds_handle ) ||
531 ( osfhandle == pendingfds_handle )) {
532 if (fd_table[fd].flags.open) {
533 no_bits = 0;
534 break;
535 }
536 }
537 }
538
539 if (no_bits)
540 continue;
541
542 #if DEBUG_FDBITS
543
544 debugs(5, 9, "FD " << fd << " bit set for reading");
545
546 assert(FD_ISSET(fd, &readfds));
547
548 #endif
549
550 if (fdIsIcp(fd)) {
551 callicp = 1;
552 continue;
553 }
554
555 if (fdIsDns(fd)) {
556 calldns = 1;
557 continue;
558 }
559
560 if (fdIsHttp(fd)) {
561 callhttp = 1;
562 continue;
563 }
564
565 F = &fd_table[fd];
566 debugs(5, 6, "comm_select: FD " << fd << " ready for reading");
567
568 if (NULL == (hdl = F->read_handler))
569 (void) 0;
570
571 #if DELAY_POOLS
572
573 else if (FD_ISSET(fd, &slowfds))
574 commAddSlowFd(fd);
575
576 #endif
577
578 else {
579 F->read_handler = NULL;
580 commUpdateReadBits(fd, NULL);
581 hdl(fd, F->read_data);
582 statCounter.select_fds++;
583
584 if (commCheckICPIncoming)
585 comm_select_icp_incoming();
586
587 if (commCheckDNSIncoming)
588 comm_select_dns_incoming();
589
590 if (commCheckHTTPIncoming)
591 comm_select_http_incoming();
592 }
593 }
594
595 assert(errfds.fd_count <= (unsigned int) Biggest_FD);
596
597 for (j = 0; j < (int) errfds.fd_count; j++) {
598 register int errfds_handle = errfds.fd_array[j];
599
600 for ( fd = Biggest_FD; fd; fd-- ) {
601 if ( fd_table[fd].win32.handle == errfds_handle )
602 break;
603 }
604
605 if (fd_table[fd].flags.open) {
606 F = &fd_table[fd];
607
608 if ((hdl = F->write_handler)) {
609 F->write_handler = NULL;
610 commUpdateWriteBits(fd, NULL);
611 hdl(fd, F->write_data);
612 statCounter.select_fds++;
613 }
614 }
615 }
616
617 assert(writefds.fd_count <= (unsigned int) Biggest_FD);
618
619 for (j = 0; j < (int) writefds.fd_count; j++) {
620 register int writefds_handle = writefds.fd_array[j];
621 no_bits = 1;
622
623 for ( fd = Biggest_FD; fd; fd-- ) {
624 if ( fd_table[fd].win32.handle == writefds_handle ) {
625 if (fd_table[fd].flags.open) {
626 no_bits = 0;
627 break;
628 }
629 }
630 }
631
632 if (no_bits)
633 continue;
634
635 #if DEBUG_FDBITS
636
637 debugs(5, 9, "FD " << fd << " bit set for writing");
638
639 assert(FD_ISSET(fd, &writefds));
640
641 #endif
642
643 if (fdIsIcp(fd)) {
644 callicp = 1;
645 continue;
646 }
647
648 if (fdIsDns(fd)) {
649 calldns = 1;
650 continue;
651 }
652
653 if (fdIsHttp(fd)) {
654 callhttp = 1;
655 continue;
656 }
657
658 F = &fd_table[fd];
659 debugs(5, 5, "comm_select: FD " << fd << " ready for writing");
660
661 if ((hdl = F->write_handler)) {
662 F->write_handler = NULL;
663 commUpdateWriteBits(fd, NULL);
664 hdl(fd, F->write_data);
665 statCounter.select_fds++;
666
667 if (commCheckICPIncoming)
668 comm_select_icp_incoming();
669
670 if (commCheckDNSIncoming)
671 comm_select_dns_incoming();
672
673 if (commCheckHTTPIncoming)
674 comm_select_http_incoming();
675
676
677 }
678 }
679
680 if (callicp)
681 comm_select_icp_incoming();
682
683 if (calldns)
684 comm_select_dns_incoming();
685
686 if (callhttp)
687 comm_select_http_incoming();
688
689 #if DELAY_POOLS
690
691 while ((fd = commGetSlowFd()) != -1) {
692 F = &fd_table[fd];
693 debugs(5, 6, "comm_select: slow FD " << fd << " selected for reading");
694
695 if ((hdl = F->read_handler)) {
696 F->read_handler = NULL;
697 commUpdateReadBits(fd, NULL);
698 hdl(fd, F->read_data);
699 statCounter.select_fds++;
700
701 if (commCheckICPIncoming)
702 comm_select_icp_incoming();
703
704 if (commCheckDNSIncoming)
705 comm_select_dns_incoming();
706
707 if (commCheckHTTPIncoming)
708 comm_select_http_incoming();
709 }
710 }
711
712 #endif
713 getCurrentTime();
714
715 statCounter.select_time += (current_dtime - start);
716
717 return COMM_OK;
718 } while (timeout > current_dtime)
719
720 ;
721 debugs(5, 8, "comm_select: time out: " << squid_curtime);
722
723 return COMM_TIMEOUT;
724 }
725
726 static void
727 comm_select_dns_incoming(void)
728 {
729 int nfds = 0;
730 int fds[2];
731 int nevents;
732 dns_io_events = 0;
733
734 if (DnsSocket < 0)
735 return;
736
737 fds[nfds++] = DnsSocket;
738
739 nevents = comm_check_incoming_select_handlers(nfds, fds);
740
741 if (nevents < 0)
742 return;
743
744 incoming_dns_interval += Config.comm_incoming.dns_average - nevents;
745
746 if (incoming_dns_interval < Config.comm_incoming.dns_min_poll)
747 incoming_dns_interval = Config.comm_incoming.dns_min_poll;
748
749 if (incoming_dns_interval > MAX_INCOMING_INTERVAL)
750 incoming_dns_interval = MAX_INCOMING_INTERVAL;
751
752 if (nevents > INCOMING_DNS_MAX)
753 nevents = INCOMING_DNS_MAX;
754
755 statHistCount(&statCounter.comm_dns_incoming, nevents);
756 }
757
758 void
759 comm_select_init(void)
760 {
761 zero_tv.tv_sec = 0;
762 zero_tv.tv_usec = 0;
763 FD_ZERO(&global_readfds);
764 FD_ZERO(&global_writefds);
765 nreadfds = nwritefds = 0;
766 }
767
768 void
769 commSelectRegisterWithCacheManager(CacheManager & manager)
770 {
771 manager.registerAction("comm_select_incoming",
772 "comm_incoming() stats",
773 commIncomingStats, 0, 1);
774 }
775
776 /*
777 * examine_select - debug routine.
778 *
779 * I spend the day chasing this core dump that occurs when both the client
780 * and the server side of a cache fetch simultaneoulsy abort the
781 * connection. While I haven't really studied the code to figure out how
782 * it happens, the snippet below may prevent the cache from exitting:
783 *
784 * Call this from where the select loop fails.
785 */
786 static int
787 examine_select(fd_set * readfds, fd_set * writefds)
788 {
789 int fd = 0;
790 fd_set read_x;
791 fd_set write_x;
792
793 struct timeval tv;
794 close_handler *ch = NULL;
795 fde *F = NULL;
796
797 struct stat sb;
798 debugs(5, 0, "examine_select: Examining open file descriptors...");
799
800 for (fd = 0; fd < Squid_MaxFD; fd++) {
801 FD_ZERO(&read_x);
802 FD_ZERO(&write_x);
803 tv.tv_sec = tv.tv_usec = 0;
804
805 if (FD_ISSET(fd, readfds))
806 FD_SET(fd, &read_x);
807 else if (FD_ISSET(fd, writefds))
808 FD_SET(fd, &write_x);
809 else
810 continue;
811
812 statCounter.syscalls.selects++;
813
814 errno = 0;
815
816 if (!fstat(fd, &sb)) {
817 debugs(5, 5, "FD " << fd << " is valid.");
818 continue;
819 }
820
821 F = &fd_table[fd];
822 debugs(5, 0, "FD " << fd << ": " << xstrerror());
823 debugs(5, 0, "WARNING: FD " << fd << " has handlers, but it's invalid.");
824 debugs(5, 0, "FD " << fd << " is a " << fdTypeStr[F->type] << " called '" << F->desc << "'");
825 debugs(5, 0, "tmout:" << F->timeout_handler << " read:" << F->read_handler << " write:" << F->write_handler);
826
827 for (ch = F->closeHandler; ch; ch = ch->next)
828 debugs(5, 0, " close handler: " << ch->handler);
829
830 if (F->closeHandler) {
831 commCallCloseHandlers(fd);
832 } else if (F->timeout_handler) {
833 debugs(5, 0, "examine_select: Calling Timeout Handler");
834 F->timeout_handler(fd, F->timeout_data);
835 }
836
837 F->closeHandler = NULL;
838 F->timeout_handler = NULL;
839 F->read_handler = NULL;
840 F->write_handler = NULL;
841 FD_CLR(fd, readfds);
842 FD_CLR(fd, writefds);
843 }
844
845 return 0;
846 }
847
848
849 static void
850 commIncomingStats(StoreEntry * sentry)
851 {
852 StatCounters *f = &statCounter;
853 storeAppendPrintf(sentry, "Current incoming_icp_interval: %d\n",
854 incoming_icp_interval >> INCOMING_FACTOR);
855 storeAppendPrintf(sentry, "Current incoming_dns_interval: %d\n",
856 incoming_dns_interval >> INCOMING_FACTOR);
857 storeAppendPrintf(sentry, "Current incoming_http_interval: %d\n",
858 incoming_http_interval >> INCOMING_FACTOR);
859 storeAppendPrintf(sentry, "\n");
860 storeAppendPrintf(sentry, "Histogram of events per incoming socket type\n");
861 storeAppendPrintf(sentry, "ICP Messages handled per comm_select_icp_incoming() call:\n");
862 statHistDump(&f->comm_icp_incoming, sentry, statHistIntDumper);
863 storeAppendPrintf(sentry, "DNS Messages handled per comm_select_dns_incoming() call:\n");
864 statHistDump(&f->comm_dns_incoming, sentry, statHistIntDumper);
865 storeAppendPrintf(sentry, "HTTP Messages handled per comm_select_http_incoming() call:\n");
866 statHistDump(&f->comm_http_incoming, sentry, statHistIntDumper);
867 }
868
869 void
870 commUpdateReadBits(int fd, PF * handler)
871 {
872 if (handler && !FD_ISSET(fd, &global_readfds)) {
873 FD_SET(fd, &global_readfds);
874 nreadfds++;
875 } else if (!handler && FD_ISSET(fd, &global_readfds)) {
876 FD_CLR(fd, &global_readfds);
877 nreadfds--;
878 }
879 }
880
881 void
882 commUpdateWriteBits(int fd, PF * handler)
883 {
884 if (handler && !FD_ISSET(fd, &global_writefds)) {
885 FD_SET(fd, &global_writefds);
886 nwritefds++;
887 } else if (!handler && FD_ISSET(fd, &global_writefds)) {
888 FD_CLR(fd, &global_writefds);
889 nwritefds--;
890 }
891 }
892
893 /* Called by async-io or diskd to speed up the polling */
894 void
895 comm_quick_poll_required(void)
896 {
897 MAX_POLL_TIME = 10;
898 }
899
900 #endif /* USE_SELECT_WIN32 */