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