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