]> git.ipfire.org Git - thirdparty/squid.git/blame - src/comm_select_win32.cc
Adding a comment that tests/testUfs will fail when 'heap' is the only
[thirdparty/squid.git] / src / comm_select_win32.cc
CommitLineData
663c0a38 1
2/*
fa3f745b 3 * $Id: comm_select_win32.cc,v 1.2 2006/09/02 10:39:53 adrian Exp $
663c0a38 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
44static 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 */
56static int examine_select(fd_set *, fd_set *);
57static int fdIsHttp(int fd);
58static int fdIsIcp(int fd);
59static int fdIsDns(int fd);
60static OBJH commIncomingStats;
61static int comm_check_incoming_select_handlers(int nfds, int *fds);
62static void comm_select_dns_incoming(void);
63static void commUpdateReadBits(int fd, PF * handler);
64static void commUpdateWriteBits(int fd, PF * handler);
65
66
67static struct timeval zero_tv;
68static fd_set global_readfds;
69static fd_set global_writefds;
70static int nreadfds;
71static 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)
124static int icp_io_events = 0;
125static int dns_io_events = 0;
126static int http_io_events = 0;
127static int incoming_icp_interval = 16 << INCOMING_FACTOR;
128static int incoming_dns_interval = 16 << INCOMING_FACTOR;
129static 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
134void
135commSetSelect(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 debug(5, 5) ("commSetSelect: FD %d type %d\n", fd, 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
160static int
161fdIsIcp(int fd)
162{
163 if (fd == theInIcpConnection)
164 return 1;
165
166 if (fd == theOutIcpConnection)
167 return 1;
168
169 return 0;
170}
171
172static int
173fdIsDns(int fd)
174{
175 if (fd == DnsSocket)
176 return 1;
177
178 return 0;
179}
180
181static int
182fdIsHttp(int fd)
183{
184 int j;
185
186 for (j = 0; j < NHttpSockets; j++) {
187 if (fd == HttpSockets[j])
188 return 1;
189 }
190
191 return 0;
192}
193
194#if DELAY_POOLS
195static int slowfdcnt = 0;
196static int slowfdarr[SQUID_MAXFD];
197
198static void
199commAddSlowFd(int fd)
200{
201 assert(slowfdcnt < SQUID_MAXFD);
202 slowfdarr[slowfdcnt++] = fd;
203}
204
205static int
206commGetSlowFd(void)
207{
208 int whichfd, retfd;
209
210 if (!slowfdcnt)
211 return -1;
212
213 whichfd = squid_random() % slowfdcnt;
214
215 retfd = slowfdarr[whichfd];
216
217 slowfdarr[whichfd] = slowfdarr[--slowfdcnt];
218
219 return retfd;
220}
221
222#endif
223
224static int
225comm_check_incoming_select_handlers(int nfds, int *fds)
226{
227 int i;
228 int fd;
229 int maxfd = 0;
230 PF *hdl = NULL;
231 fd_set read_mask;
232 fd_set write_mask;
233 fd_set errfds;
234 FD_ZERO(&errfds);
235 FD_ZERO(&read_mask);
236 FD_ZERO(&write_mask);
237 incoming_sockets_accepted = 0;
238
239 for (i = 0; i < nfds; i++) {
240 fd = fds[i];
241
242 if (fd_table[fd].read_handler) {
243 FD_SET(fd, &read_mask);
244
245 if (fd > maxfd)
246 maxfd = fd;
247 }
248
249 if (fd_table[fd].write_handler) {
250 FD_SET(fd, &write_mask);
251
252 if (fd > maxfd)
253 maxfd = fd;
254 }
255 }
256
257 if (maxfd++ == 0)
258 return -1;
259
260 getCurrentTime();
261
262 statCounter.syscalls.selects++;
263
264 if (select(maxfd, &read_mask, &write_mask, &errfds, &zero_tv) < 1)
265
266 return incoming_sockets_accepted;
267
268 for (i = 0; i < nfds; i++) {
269 fd = fds[i];
270
271 if (FD_ISSET(fd, &read_mask)) {
272 if ((hdl = fd_table[fd].read_handler) != NULL) {
273 fd_table[fd].read_handler = NULL;
274 commUpdateReadBits(fd, NULL);
275 hdl(fd, fd_table[fd].read_data);
276 } else {
277 debug(5, 1) ("comm_select_incoming: FD %d NULL read handler\n",
278 fd);
279 }
280 }
281
282 if (FD_ISSET(fd, &write_mask)) {
283 if ((hdl = fd_table[fd].write_handler) != NULL) {
284 fd_table[fd].write_handler = NULL;
285 commUpdateWriteBits(fd, NULL);
286 hdl(fd, fd_table[fd].write_data);
287 } else {
288 debug(5, 1) ("comm_select_incoming: FD %d NULL write handler\n",
289 fd);
290 }
291 }
292 }
293
294 return incoming_sockets_accepted;
295}
296
297static void
298comm_select_icp_incoming(void)
299{
300 int nfds = 0;
301 int fds[2];
302 int nevents;
303 icp_io_events = 0;
304
305 if (theInIcpConnection >= 0)
306 fds[nfds++] = theInIcpConnection;
307
308 if (theInIcpConnection != theOutIcpConnection)
309 if (theOutIcpConnection >= 0)
310 fds[nfds++] = theOutIcpConnection;
311
312 if (nfds == 0)
313 return;
314
315 nevents = comm_check_incoming_select_handlers(nfds, fds);
316
317 incoming_icp_interval += Config.comm_incoming.icp_average - nevents;
318
319 if (incoming_icp_interval < 0)
320 incoming_icp_interval = 0;
321
322 if (incoming_icp_interval > MAX_INCOMING_INTERVAL)
323 incoming_icp_interval = MAX_INCOMING_INTERVAL;
324
325 if (nevents > INCOMING_ICP_MAX)
326 nevents = INCOMING_ICP_MAX;
327
328 statHistCount(&statCounter.comm_icp_incoming, nevents);
329}
330
331static void
332comm_select_http_incoming(void)
333{
334 int nfds = 0;
335 int fds[MAXHTTPPORTS];
336 int j;
337 int nevents;
338 http_io_events = 0;
339
340 for (j = 0; j < NHttpSockets; j++) {
341 if (HttpSockets[j] < 0)
342 continue;
343
344 fds[nfds++] = HttpSockets[j];
345 }
346
347 nevents = comm_check_incoming_select_handlers(nfds, fds);
348 incoming_http_interval += Config.comm_incoming.http_average - nevents;
349
350 if (incoming_http_interval < 0)
351 incoming_http_interval = 0;
352
353 if (incoming_http_interval > MAX_INCOMING_INTERVAL)
354 incoming_http_interval = MAX_INCOMING_INTERVAL;
355
356 if (nevents > INCOMING_HTTP_MAX)
357 nevents = INCOMING_HTTP_MAX;
358
359 statHistCount(&statCounter.comm_http_incoming, nevents);
360}
361
362#define DEBUG_FDBITS 0
363/* Select on all sockets; call handlers for those that are ready. */
364comm_err_t
365comm_select(int msec)
366{
367 fd_set readfds;
368 fd_set pendingfds;
369 fd_set writefds;
370#if DELAY_POOLS
371
372 fd_set slowfds;
373#endif
374
375 PF *hdl = NULL;
376 int fd;
377 int maxfd;
378 int num;
379 int pending;
380 int callicp = 0, callhttp = 0;
381 int calldns = 0;
382 int j;
383#if DEBUG_FDBITS
384
385 int i;
386#endif
663c0a38 387 struct timeval poll_time;
388 double timeout = current_dtime + (msec / 1000.0);
389 fde *F;
390
391 int no_bits;
392 fd_set errfds;
393 FD_ZERO(&errfds);
394
395 do {
396 double start;
397 getCurrentTime();
398 start = current_dtime;
399#if DELAY_POOLS
400
401 FD_ZERO(&slowfds);
402#endif
403
404 if (commCheckICPIncoming)
405 comm_select_icp_incoming();
406
407 if (commCheckDNSIncoming)
408 comm_select_dns_incoming();
409
410 if (commCheckHTTPIncoming)
411 comm_select_http_incoming();
412
413 callicp = calldns = callhttp = 0;
414
415 maxfd = Biggest_FD + 1;
416
417 xmemcpy(&readfds, &global_readfds, sizeof(global_readfds));
418
419 xmemcpy(&writefds, &global_writefds, sizeof(global_writefds));
420
421 xmemcpy(&errfds, &global_writefds, sizeof(global_writefds));
422
423 /* remove stalled FDs, and deal with pending descriptors */
424 pending = 0;
425
426 FD_ZERO(&pendingfds);
427
428 for (j = 0; j < (int) readfds.fd_count; j++) {
429 register int readfds_handle = readfds.fd_array[j];
430 no_bits = 1;
431
432 for ( fd = Biggest_FD; fd; fd-- ) {
433 if ( fd_table[fd].win32.handle == readfds_handle ) {
434 if (fd_table[fd].flags.open) {
435 no_bits = 0;
436 break;
437 }
438 }
439 }
440
441 if (no_bits)
442 continue;
443
444 if (FD_ISSET(fd, &readfds) && fd_table[fd].flags.read_pending) {
445 FD_SET(fd, &pendingfds);
446 pending++;
447 }
448 }
449
450#if DEBUG_FDBITS
451 for (i = 0; i < maxfd; i++) {
452 /* Check each open socket for a handler. */
453
454 if (fd_table[i].read_handler) {
455 assert(FD_ISSET(i, &readfds));
456 }
457
458 if (fd_table[i].write_handler) {
459 assert(FD_ISSET(i, &writefds));
460 }
461 }
462
463#endif
464 if (nreadfds + nwritefds == 0) {
465 assert(shutting_down);
466 return COMM_SHUTDOWN;
467 }
468
469 if (msec > MAX_POLL_TIME)
470 msec = MAX_POLL_TIME;
471
472 if (comm_iocallbackpending())
473 pending++;
474
475 if (pending)
476 msec = 0;
477
478 for (;;) {
479 poll_time.tv_sec = msec / 1000;
480 poll_time.tv_usec = (msec % 1000) * 1000;
481 statCounter.syscalls.selects++;
482 num = select(maxfd, &readfds, &writefds, &errfds, &poll_time);
483 statCounter.select_loops++;
484
485 if (num >= 0 || pending > 0)
486 break;
487
488 if (ignoreErrno(errno))
489 break;
490
491 debug(5, 0) ("comm_select: select failure: %s\n",
492 xstrerror());
493
494 examine_select(&readfds, &writefds);
495
496 return COMM_ERROR;
497
498 /* NOTREACHED */
499 }
500
501 if (num < 0 && !pending)
502 continue;
503
504 getCurrentTime();
505
506 debug(5, num ? 5 : 8) ("comm_select: %d+%d FDs ready\n",
507 num, pending);
508
509 statHistCount(&statCounter.select_fds_hist, num);
510
663c0a38 511 if (num == 0 && pending == 0)
512 continue;
513
514 /* Scan return fd masks for ready descriptors */
515
516 assert(readfds.fd_count <= (unsigned int) Biggest_FD);
517
518 assert(pendingfds.fd_count <= (unsigned int) Biggest_FD);
519
520 for (j = 0; j < (int) readfds.fd_count; j++) {
521 register int readfds_handle = readfds.fd_array[j];
522 register int pendingfds_handle = pendingfds.fd_array[j];
523 register int osfhandle;
524 no_bits = 1;
525
526 for ( fd = Biggest_FD; fd; fd-- ) {
527 osfhandle = fd_table[fd].win32.handle;
528
529 if (( osfhandle == readfds_handle ) ||
530 ( osfhandle == pendingfds_handle )) {
531 if (fd_table[fd].flags.open) {
532 no_bits = 0;
533 break;
534 }
535 }
536 }
537
538 if (no_bits)
539 continue;
540
541#if DEBUG_FDBITS
542
543 debug(5, 9) ("FD %d bit set for reading\n", fd);
544
545 assert(FD_ISSET(fd, &readfds));
546
547#endif
548
549 if (fdIsIcp(fd)) {
550 callicp = 1;
551 continue;
552 }
553
554 if (fdIsDns(fd)) {
555 calldns = 1;
556 continue;
557 }
558
559 if (fdIsHttp(fd)) {
560 callhttp = 1;
561 continue;
562 }
563
564 F = &fd_table[fd];
565 debug(5, 6) ("comm_select: FD %d ready for reading\n", fd);
566
567 if (NULL == (hdl = F->read_handler))
568 (void) 0;
569
570#if DELAY_POOLS
571
572 else if (FD_ISSET(fd, &slowfds))
573 commAddSlowFd(fd);
574
575#endif
576
577 else {
578 F->read_handler = NULL;
579 commUpdateReadBits(fd, NULL);
580 hdl(fd, F->read_data);
581 statCounter.select_fds++;
582
583 if (commCheckICPIncoming)
584 comm_select_icp_incoming();
585
586 if (commCheckDNSIncoming)
587 comm_select_dns_incoming();
588
589 if (commCheckHTTPIncoming)
590 comm_select_http_incoming();
591 }
592 }
593
594 assert(errfds.fd_count <= (unsigned int) Biggest_FD);
595
596 for (j = 0; j < (int) errfds.fd_count; j++) {
597 register int errfds_handle = errfds.fd_array[j];
598
599 for ( fd = Biggest_FD; fd; fd-- ) {
600 if ( fd_table[fd].win32.handle == errfds_handle )
601 break;
602 }
603
604 if (fd_table[fd].flags.open) {
605 F = &fd_table[fd];
606
607 if ((hdl = F->write_handler)) {
608 F->write_handler = NULL;
609 commUpdateWriteBits(fd, NULL);
610 hdl(fd, F->write_data);
611 statCounter.select_fds++;
612 }
613 }
614 }
615
616 assert(writefds.fd_count <= (unsigned int) Biggest_FD);
617
618 for (j = 0; j < (int) writefds.fd_count; j++) {
619 register int writefds_handle = writefds.fd_array[j];
620 no_bits = 1;
621
622 for ( fd = Biggest_FD; fd; fd-- ) {
623 if ( fd_table[fd].win32.handle == writefds_handle ) {
624 if (fd_table[fd].flags.open) {
625 no_bits = 0;
626 break;
627 }
628 }
629 }
630
631 if (no_bits)
632 continue;
633
634#if DEBUG_FDBITS
635
636 debug(5, 9) ("FD %d bit set for writing\n", fd);
637
638 assert(FD_ISSET(fd, &writefds));
639
640#endif
641
642 if (fdIsIcp(fd)) {
643 callicp = 1;
644 continue;
645 }
646
647 if (fdIsDns(fd)) {
648 calldns = 1;
649 continue;
650 }
651
652 if (fdIsHttp(fd)) {
653 callhttp = 1;
654 continue;
655 }
656
657 F = &fd_table[fd];
658 debug(5, 5) ("comm_select: FD %d ready for writing\n", fd);
659
660 if ((hdl = F->write_handler)) {
661 F->write_handler = NULL;
662 commUpdateWriteBits(fd, NULL);
663 hdl(fd, F->write_data);
664 statCounter.select_fds++;
665
666 if (commCheckICPIncoming)
667 comm_select_icp_incoming();
668
669 if (commCheckDNSIncoming)
670 comm_select_dns_incoming();
671
672 if (commCheckHTTPIncoming)
673 comm_select_http_incoming();
674
675
676 }
677 }
678
679 if (callicp)
680 comm_select_icp_incoming();
681
682 if (calldns)
683 comm_select_dns_incoming();
684
685 if (callhttp)
686 comm_select_http_incoming();
687
688#if DELAY_POOLS
689
690 while ((fd = commGetSlowFd()) != -1) {
691 F = &fd_table[fd];
692 debug(5, 6) ("comm_select: slow FD %d selected for reading\n", fd);
693
694 if ((hdl = F->read_handler)) {
695 F->read_handler = NULL;
696 commUpdateReadBits(fd, NULL);
697 hdl(fd, F->read_data);
698 statCounter.select_fds++;
699
700 if (commCheckICPIncoming)
701 comm_select_icp_incoming();
702
703 if (commCheckDNSIncoming)
704 comm_select_dns_incoming();
705
706 if (commCheckHTTPIncoming)
707 comm_select_http_incoming();
708 }
709 }
710
711#endif
712 getCurrentTime();
713
714 statCounter.select_time += (current_dtime - start);
715
716 return COMM_OK;
717 } while (timeout > current_dtime)
718
719 ;
720 debug(5, 8) ("comm_select: time out: %d\n", (int) squid_curtime);
721
722 return COMM_TIMEOUT;
723}
724
725static void
726comm_select_dns_incoming(void)
727{
728 int nfds = 0;
729 int fds[2];
730 int nevents;
731 dns_io_events = 0;
732
733 if (DnsSocket < 0)
734 return;
735
736 fds[nfds++] = DnsSocket;
737
738 nevents = comm_check_incoming_select_handlers(nfds, fds);
739
740 if (nevents < 0)
741 return;
742
743 incoming_dns_interval += Config.comm_incoming.dns_average - nevents;
744
745 if (incoming_dns_interval < Config.comm_incoming.dns_min_poll)
746 incoming_dns_interval = Config.comm_incoming.dns_min_poll;
747
748 if (incoming_dns_interval > MAX_INCOMING_INTERVAL)
749 incoming_dns_interval = MAX_INCOMING_INTERVAL;
750
751 if (nevents > INCOMING_DNS_MAX)
752 nevents = INCOMING_DNS_MAX;
753
754 statHistCount(&statCounter.comm_dns_incoming, nevents);
755}
756
757void
758comm_select_init(void)
759{
760 zero_tv.tv_sec = 0;
761 zero_tv.tv_usec = 0;
762 FD_ZERO(&global_readfds);
763 FD_ZERO(&global_writefds);
764 nreadfds = nwritefds = 0;
765}
766
767void
768commSelectRegisterWithCacheManager(CacheManager & manager)
769{
770 manager.registerAction("comm_select_incoming",
771 "comm_incoming() stats",
772 commIncomingStats, 0, 1);
773}
774
775/*
776 * examine_select - debug routine.
777 *
778 * I spend the day chasing this core dump that occurs when both the client
779 * and the server side of a cache fetch simultaneoulsy abort the
780 * connection. While I haven't really studied the code to figure out how
781 * it happens, the snippet below may prevent the cache from exitting:
782 *
783 * Call this from where the select loop fails.
784 */
785static int
786examine_select(fd_set * readfds, fd_set * writefds)
787{
788 int fd = 0;
789 fd_set read_x;
790 fd_set write_x;
791
792 struct timeval tv;
793 close_handler *ch = NULL;
794 fde *F = NULL;
795
796 struct stat sb;
797 debug(5, 0) ("examine_select: Examining open file descriptors...\n");
798
799 for (fd = 0; fd < Squid_MaxFD; fd++) {
800 FD_ZERO(&read_x);
801 FD_ZERO(&write_x);
802 tv.tv_sec = tv.tv_usec = 0;
803
804 if (FD_ISSET(fd, readfds))
805 FD_SET(fd, &read_x);
806 else if (FD_ISSET(fd, writefds))
807 FD_SET(fd, &write_x);
808 else
809 continue;
810
811 statCounter.syscalls.selects++;
812
813 errno = 0;
814
815 if (!fstat(fd, &sb)) {
816 debug(5, 5) ("FD %d is valid.\n", fd);
817 continue;
818 }
819
820 F = &fd_table[fd];
821 debug(5, 0) ("FD %d: %s\n", fd, xstrerror());
822 debug(5, 0) ("WARNING: FD %d has handlers, but it's invalid.\n", fd);
823 debug(5, 0) ("FD %d is a %s called '%s'\n",
824 fd,
825 fdTypeStr[F->type],
826 F->desc);
827 debug(5, 0) ("tmout:%p read:%p write:%p\n",
828 F->timeout_handler,
829 F->read_handler,
830 F->write_handler);
831
832 for (ch = F->closeHandler; ch; ch = ch->next)
833 debug(5, 0) (" close handler: %p\n", ch->handler);
834
835 if (F->closeHandler) {
836 commCallCloseHandlers(fd);
837 } else if (F->timeout_handler) {
838 debug(5, 0) ("examine_select: Calling Timeout Handler\n");
839 F->timeout_handler(fd, F->timeout_data);
840 }
841
842 F->closeHandler = NULL;
843 F->timeout_handler = NULL;
844 F->read_handler = NULL;
845 F->write_handler = NULL;
846 FD_CLR(fd, readfds);
847 FD_CLR(fd, writefds);
848 }
849
850 return 0;
851}
852
853
854static void
855commIncomingStats(StoreEntry * sentry)
856{
857 StatCounters *f = &statCounter;
858 storeAppendPrintf(sentry, "Current incoming_icp_interval: %d\n",
859 incoming_icp_interval >> INCOMING_FACTOR);
860 storeAppendPrintf(sentry, "Current incoming_dns_interval: %d\n",
861 incoming_dns_interval >> INCOMING_FACTOR);
862 storeAppendPrintf(sentry, "Current incoming_http_interval: %d\n",
863 incoming_http_interval >> INCOMING_FACTOR);
864 storeAppendPrintf(sentry, "\n");
865 storeAppendPrintf(sentry, "Histogram of events per incoming socket type\n");
866 storeAppendPrintf(sentry, "ICP Messages handled per comm_select_icp_incoming() call:\n");
867 statHistDump(&f->comm_icp_incoming, sentry, statHistIntDumper);
868 storeAppendPrintf(sentry, "DNS Messages handled per comm_select_dns_incoming() call:\n");
869 statHistDump(&f->comm_dns_incoming, sentry, statHistIntDumper);
870 storeAppendPrintf(sentry, "HTTP Messages handled per comm_select_http_incoming() call:\n");
871 statHistDump(&f->comm_http_incoming, sentry, statHistIntDumper);
872}
873
874void
875commUpdateReadBits(int fd, PF * handler)
876{
877 if (handler && !FD_ISSET(fd, &global_readfds)) {
878 FD_SET(fd, &global_readfds);
879 nreadfds++;
880 } else if (!handler && FD_ISSET(fd, &global_readfds)) {
881 FD_CLR(fd, &global_readfds);
882 nreadfds--;
883 }
884}
885
886void
887commUpdateWriteBits(int fd, PF * handler)
888{
889 if (handler && !FD_ISSET(fd, &global_writefds)) {
890 FD_SET(fd, &global_writefds);
891 nwritefds++;
892 } else if (!handler && FD_ISSET(fd, &global_writefds)) {
893 FD_CLR(fd, &global_writefds);
894 nwritefds--;
895 }
896}
897
898/* Called by async-io or diskd to speed up the polling */
899void
900comm_quick_poll_required(void)
901{
902 MAX_POLL_TIME = 10;
903}
904
905#endif /* USE_SELECT_WIN32 */