]> git.ipfire.org Git - thirdparty/squid.git/blame - src/comm_epoll.cc
Bug #822: cache_peer originserver connects to wrong port
[thirdparty/squid.git] / src / comm_epoll.cc
CommitLineData
6039b729 1
2/*
0dc60cb3 3 * $Id: comm_epoll.cc,v 1.4 2003/08/03 21:38:15 robertc Exp $
6039b729 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/*
36 * The idea for this came from these two websites:
37 * http://www.xmailserver.org/linux-patches/nio-improve.html
38 * http://www.kegel.com/c10k.html
39 *
40 * This is to support the epoll sysctl being added to the linux 2.5
41 * kernel tree. The new sys_epoll is an event based poller without
42 * most of the fuss of rtsignals.
43 *
44 * -- David Nicklay <dnicklay@web.turner.com>
45 */
46
47/*
48 * XXX Currently not implemented / supported by this module XXX
49 *
50 * - delay pools
51 * - deferred reads
52 *
53 */
54
55#include "squid.h"
56#include "Store.h"
1287b9e1 57#include "fde.h"
6039b729 58
6039b729 59#define DEBUG_EPOLL 0
60
61#include <sys/epoll.h>
62
63static int kdpfd;
64static int max_poll_time = 1000;
65
66static struct epoll_event *pevents;
67
68
69
70/* XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX */
71/* Public functions */
72
73
74/*
75 * comm_select_init
76 *
77 * This is a needed exported function which will be called to initialise
78 * the network loop code.
79 */
80void
81comm_select_init(void)
82{
83
84 pevents = (struct epoll_event *) xmalloc(SQUID_MAXFD * sizeof(struct epoll_event));
85
86 if (!pevents) {
87 fatalf("comm_select_init: xmalloc() failed: %s\n",xstrerror());
88 }
89
90 kdpfd = epoll_create(SQUID_MAXFD);
91
92 if (kdpfd < 0) {
93 fatalf("comm_select_init: epoll_create(): %s\n",xstrerror());
94 }
95}
96
97/*
98 * comm_setselect
99 *
100 * This is a needed exported function which will be called to register
101 * and deregister interest in a pending IO state for a given FD.
102 *
103 */
104void
105commSetSelect(int fd, unsigned int type, PF * handler,
106 void *client_data, time_t timeout)
107{
108 fde *F = &fd_table[fd];
109 int change = 0;
110 int events = 0;
111 int pollin = 0;
112 int pollout = 0;
113
114 struct epoll_event ev;
115 assert(fd >= 0);
116 assert(F->flags.open);
117 debug(5, DEBUG_EPOLL ? 0 : 8) ("commSetSelect(fd=%d,type=%u,handler=%p,client_data=%p,timeout=%ld)\n",
118 fd,type,handler,client_data,timeout);
119
120 if(F->read_handler != NULL)
121 pollin = 1;
122
123 if(F->write_handler != NULL)
124 pollout = 1;
125
126 if (type & COMM_SELECT_READ) {
127 if(F->read_handler != handler)
128 change = 1;
129
130 if(handler == NULL)
131 pollin = 0;
132 else
133 pollin = 1;
134
135 F->read_handler = handler;
136
137 F->read_data = client_data;
138 }
139
140 if (type & COMM_SELECT_WRITE) {
141 if(F->write_handler != handler)
142 change = 1;
143
144 if(handler == NULL)
145 pollout = 0;
146 else
147 pollout = 1;
148
149 F->write_handler = handler;
150
151 F->write_data = client_data;
152 }
153
154 if(pollin)
155 events |= EPOLLIN;
156
157 if(pollout)
158 events |= EPOLLOUT;
159
160 if(events)
161 events |= EPOLLHUP | EPOLLERR;
162
163 ev.data.fd = fd;
164
165 ev.events = events;
166
167 if(events) {
168 if (epoll_ctl(kdpfd, EPOLL_CTL_MOD, fd, &ev) < 0) {
169 if(errno == ENOENT) {
170 debug(5,4) ("commSetSelect: epoll_ctl(,EPOLL_CTL_MOD,,) failed on fd=%d: entry does not exist\n",fd);
171
172 if (epoll_ctl(kdpfd, EPOLL_CTL_ADD, fd, &ev) < 0)
173 debug(5,1) ("commSetSelect: cpoll_ctl(,EPOLL_CTL_ADD,,) failed on fd=%d!: %s\n",fd,xstrerror());
174 } else {
175 debug(5,1) ("commSetSelect: cpoll_ctl(,EPOLL_CTL_MOD,,) failed on fd=%d!: %s\n",fd,xstrerror());
176 }
177 }
178 } else if(change) {
179 if(epoll_ctl(kdpfd,EPOLL_CTL_DEL,fd,&ev) < 0) {
180 if(errno != ENOENT)
181 debug(5,1) ("commSetSelect: cpoll_ctl(,EPOLL_CTL_DEL,,) failed on fd=%d!: %s\n",fd,xstrerror());
182 else
183 debug(5,4) ("commSetSelect: epoll_ctl(,EPOLL_CTL_DEL,,) failed on fd=%d: entry does not exist\n",fd);
184 }
185 }
186
187 if (timeout)
188 F->timeout = squid_curtime + timeout;
189}
190
191/*
192 * Check all connections for new connections and input data that is to be
193 * processed. Also check for connections with data queued and whether we can
194 * write it out.
195 */
196
197/*
198 * comm_select
199 *
200 * Called to do the new-style IO, courtesy of of squid (like most of this
201 * new IO code). This routine handles the stuff we've hidden in
202 * comm_setselect and fd_table[] and calls callbacks for IO ready
203 * events.
204 */
205
206comm_err_t
207comm_select(int msec)
208{
209 int num, i,fd;
210 fde *F;
211 PF *hdl;
212
213 struct epoll_event *cevents;
214 static time_t last_timeout = 0;
215
216 if (squid_curtime > last_timeout) {
217 last_timeout = squid_curtime;
218 checkTimeouts();
219 }
220
221 if (msec > max_poll_time)
222 msec = max_poll_time;
223
224 for (;;) {
225 num = epoll_wait(kdpfd, pevents, SQUID_MAXFD, msec);
226 statCounter.select_loops++;
227
228 if (num >= 0)
229 break;
230
231 if (ignoreErrno(errno))
232 break;
233
234 getCurrentTime();
235
236 return COMM_ERROR;
237 }
238
239 getCurrentTime();
240
241 if (num == 0)
242 return COMM_OK; /* No error.. */
243
244 for (i = 0, cevents = pevents; i < num; i++, cevents++) {
245 fd = cevents->data.fd;
246 F = &fd_table[fd];
247 debug(5, DEBUG_EPOLL ? 0 : 8) ("comm_select(): got fd=%d events=%d F->read_handler=%p F->write_handler=%p\n",
248 fd,cevents->events,F->read_handler,F->write_handler);
249
250 if(cevents->events & (EPOLLIN|EPOLLHUP|EPOLLERR)) {
251 if((hdl = F->read_handler) != NULL) {
252 debug(5, DEBUG_EPOLL ? 0 : 8) ("comm_select(): Calling read handler on fd=%d\n",fd);
253 F->read_handler = NULL;
254 hdl(fd, F->read_data);
255 }
256 }
257
258 if(cevents->events & (EPOLLOUT|EPOLLHUP|EPOLLERR)) {
259 if((hdl = F->write_handler) != NULL) {
260 debug(5, DEBUG_EPOLL ? 0 : 8) ("comm_select(): Calling write handler on fd=%d\n",fd);
261 F->write_handler = NULL;
262 hdl(fd, F->write_data);
263 }
264 }
265 }
266
267 return COMM_OK;
268}
269
270void
271comm_quick_poll_required(void)
272{
273 max_poll_time = 100;
274}
275