~clint-fewbar/ubuntu/precise/squid3/ignore-sighup-early

« back to all changes in this revision

Viewing changes to src/comm_kqueue.cc

  • Committer: Bazaar Package Importer
  • Author(s): Luigi Gangitano
  • Date: 2006-11-11 10:32:06 UTC
  • Revision ID: james.westby@ubuntu.com-20061111103206-f3p0r9g0vq44rp3r
Tags: upstream-3.0.PRE5
ImportĀ upstreamĀ versionĀ 3.0.PRE5

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
 
 
2
/*
 
3
 * $Id: comm_kqueue.cc,v 1.12 2006/09/02 10:43:10 adrian 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
/*
 
36
 * This code was originally written by Benno Rice and hacked on quite
 
37
 * a bit by Adrian. Adrian then took it to the hybrid-ircd project to use
 
38
 * in their new IO subsystem. After a year of modifications and some
 
39
 * rather interesting changes (event aggregation) its back in squid.
 
40
 * Thanks to the ircd-hybrid guys.
 
41
 */
 
42
 
 
43
/*
 
44
 * XXX Currently not implemented / supported by this module XXX
 
45
 *
 
46
 * - delay pools
 
47
 * - deferred reads
 
48
 *
 
49
 * So, its not entirely useful in a production setup since if a read
 
50
 * is meant to be deferred it isn't (we're not even throwing the event
 
51
 * away here). Eventually the rest of the code will be rewritten
 
52
 * so deferred reads aren't required.
 
53
 *  -- adrian
 
54
 */
 
55
 
 
56
#include "squid.h"
 
57
#include "comm_kqueue.h"
 
58
#include "CacheManager.h"
 
59
#include "Store.h"
 
60
#include "fde.h"
 
61
#include "SquidTime.h"
 
62
 
 
63
#ifdef USE_KQUEUE
 
64
 
 
65
#include <sys/event.h>
 
66
 
 
67
 
 
68
#define KE_LENGTH        128
 
69
 
 
70
/* jlemon goofed up and didn't add EV_SET until fbsd 4.3 */
 
71
 
 
72
#ifndef EV_SET
 
73
#define EV_SET(kevp, a, b, c, d, e, f) do {     \
 
74
        (kevp)->ident = (a);                    \
 
75
        (kevp)->filter = (b);                   \
 
76
        (kevp)->flags = (c);                    \
 
77
        (kevp)->fflags = (d);                   \
 
78
        (kevp)->data = (e);                     \
 
79
        (kevp)->udata = (f);                    \
 
80
} while(0)
 
81
#endif
 
82
 
 
83
static void kq_update_events(int, short, PF *);
 
84
static int kq;
 
85
 
 
86
static struct timespec zero_timespec;
 
87
 
 
88
static struct kevent *kqlst;        /* kevent buffer */
 
89
static int kqmax;                /* max structs to buffer */
 
90
static int kqoff;                /* offset into the buffer */
 
91
static int max_poll_time = 1000;
 
92
 
 
93
 
 
94
/* XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX */
 
95
/* Private functions */
 
96
 
 
97
void
 
98
kq_update_events(int fd, short filter, PF * handler)
 
99
{
 
100
    PF *cur_handler;
 
101
    int kep_flags;
 
102
 
 
103
#if 0
 
104
 
 
105
    int retval;
 
106
#endif
 
107
 
 
108
    switch (filter) {
 
109
 
 
110
    case EVFILT_READ:
 
111
        cur_handler = fd_table[fd].read_handler;
 
112
        break;
 
113
 
 
114
    case EVFILT_WRITE:
 
115
        cur_handler = fd_table[fd].write_handler;
 
116
        break;
 
117
 
 
118
    default:
 
119
        /* XXX bad! -- adrian */
 
120
        return;
 
121
        break;
 
122
    }
 
123
 
 
124
    if ((cur_handler == NULL && handler != NULL)
 
125
            || (cur_handler != NULL && handler == NULL)) {
 
126
 
 
127
        struct kevent *kep;
 
128
 
 
129
        kep = kqlst + kqoff;
 
130
 
 
131
        if (handler != NULL) {
 
132
            kep_flags = (EV_ADD | EV_ONESHOT);
 
133
        } else {
 
134
            kep_flags = EV_DELETE;
 
135
        }
 
136
 
 
137
        EV_SET(kep, (uintptr_t) fd, filter, kep_flags, 0, 0, 0);
 
138
 
 
139
        if (kqoff == kqmax) {
 
140
            int ret;
 
141
 
 
142
            ret = kevent(kq, kqlst, kqoff, NULL, 0, &zero_timespec);
 
143
            /* jdc -- someone needs to do error checking... */
 
144
 
 
145
            if (ret == -1) {
 
146
                perror("kq_update_events(): kevent()");
 
147
                return;
 
148
            }
 
149
 
 
150
            kqoff = 0;
 
151
        } else {
 
152
            kqoff++;
 
153
        }
 
154
 
 
155
#if 0
 
156
        if (retval < 0) {
 
157
            /* Error! */
 
158
 
 
159
            if (ke.flags & EV_ERROR) {
 
160
                errno = ke.data;
 
161
            }
 
162
        }
 
163
 
 
164
#endif
 
165
 
 
166
    }
 
167
}
 
168
 
 
169
 
 
170
 
 
171
/* XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX */
 
172
/* Public functions */
 
173
 
 
174
 
 
175
/*
 
176
 * comm_select_init
 
177
 *
 
178
 * This is a needed exported function which will be called to initialise
 
179
 * the network loop code.
 
180
 */
 
181
void
 
182
comm_select_init(void)
 
183
{
 
184
    kq = kqueue();
 
185
 
 
186
    if (kq < 0) {
 
187
        fatal("comm_select_init: Couldn't open kqueue fd!\n");
 
188
    }
 
189
 
 
190
    kqmax = getdtablesize();
 
191
 
 
192
    kqlst = (struct kevent *)xmalloc(sizeof(*kqlst) * kqmax);
 
193
    zero_timespec.tv_sec = 0;
 
194
    zero_timespec.tv_nsec = 0;
 
195
}
 
196
 
 
197
/*
 
198
 * comm_setselect
 
199
 *
 
200
 * This is a needed exported function which will be called to register
 
201
 * and deregister interest in a pending IO state for a given FD.
 
202
 */
 
203
void
 
204
commSetSelect(int fd, unsigned int type, PF * handler,
 
205
              void *client_data, time_t timeout)
 
206
{
 
207
    fde *F = &fd_table[fd];
 
208
    assert(fd >= 0);
 
209
    assert(F->flags.open);
 
210
 
 
211
    if (type & COMM_SELECT_READ) {
 
212
        kq_update_events(fd, EVFILT_READ, handler);
 
213
        F->read_handler = handler;
 
214
        F->read_data = client_data;
 
215
    }
 
216
 
 
217
    if (type & COMM_SELECT_WRITE) {
 
218
        kq_update_events(fd, EVFILT_WRITE, handler);
 
219
        F->write_handler = handler;
 
220
        F->write_data = client_data;
 
221
    }
 
222
 
 
223
    if (timeout)
 
224
        F->timeout = squid_curtime + timeout;
 
225
 
 
226
}
 
227
 
 
228
/*
 
229
 * Check all connections for new connections and input data that is to be
 
230
 * processed. Also check for connections with data queued and whether we can
 
231
 * write it out.
 
232
 */
 
233
 
 
234
/*
 
235
 * comm_select
 
236
 *
 
237
 * Called to do the new-style IO, courtesy of of squid (like most of this
 
238
 * new IO code). This routine handles the stuff we've hidden in
 
239
 * comm_setselect and fd_table[] and calls callbacks for IO ready
 
240
 * events.
 
241
 */
 
242
 
 
243
comm_err_t
 
244
comm_select(int msec)
 
245
{
 
246
    int num, i;
 
247
 
 
248
    static struct kevent ke[KE_LENGTH];
 
249
 
 
250
    struct timespec poll_time;
 
251
 
 
252
    /*
 
253
     * remember we are doing NANOseconds here, not micro/milli. God knows
 
254
     * why jlemon used a timespec, but hey, he wrote the interface, not I
 
255
     *   -- Adrian
 
256
     */
 
257
 
 
258
    if (msec > max_poll_time)
 
259
        msec = max_poll_time;
 
260
 
 
261
    poll_time.tv_sec = msec / 1000;
 
262
 
 
263
    poll_time.tv_nsec = (msec % 1000) * 1000000;
 
264
 
 
265
    for (;;) {
 
266
        num = kevent(kq, kqlst, kqoff, ke, KE_LENGTH, &poll_time);
 
267
        statCounter.select_loops++;
 
268
        kqoff = 0;
 
269
 
 
270
        if (num >= 0)
 
271
            break;
 
272
 
 
273
        if (ignoreErrno(errno))
 
274
            break;
 
275
 
 
276
        getCurrentTime();
 
277
 
 
278
        return COMM_ERROR;
 
279
 
 
280
        /* NOTREACHED */
 
281
    }
 
282
 
 
283
    getCurrentTime();
 
284
 
 
285
    if (num == 0)
 
286
        return COMM_OK;         /* No error.. */
 
287
 
 
288
    for (i = 0; i < num; i++) {
 
289
        int fd = (int) ke[i].ident;
 
290
        PF *hdl = NULL;
 
291
        fde *F = &fd_table[fd];
 
292
 
 
293
        if (ke[i].flags & EV_ERROR) {
 
294
            errno = ke[i].data;
 
295
            /* XXX error == bad! -- adrian */
 
296
            continue;        /* XXX! */
 
297
        }
 
298
 
 
299
        switch (ke[i].filter) {
 
300
 
 
301
        case EVFILT_READ:
 
302
 
 
303
            if ((hdl = F->read_handler) != NULL) {
 
304
                F->read_handler = NULL;
 
305
                hdl(fd, F->read_data);
 
306
            }
 
307
 
 
308
            break;
 
309
 
 
310
        case EVFILT_WRITE:
 
311
 
 
312
            if ((hdl = F->write_handler) != NULL) {
 
313
                F->write_handler = NULL;
 
314
                hdl(fd, F->write_data);
 
315
            }
 
316
 
 
317
            break;
 
318
 
 
319
        default:
 
320
            /* Bad! -- adrian */
 
321
            debug(5, 1) ("comm_select: kevent returned %d!\n", ke[i].filter);
 
322
            break;
 
323
        }
 
324
    }
 
325
 
 
326
    return COMM_OK;
 
327
}
 
328
 
 
329
void
 
330
comm_quick_poll_required(void)
 
331
{
 
332
    max_poll_time = 100;
 
333
}
 
334
 
 
335
void
 
336
commKQueueRegisterWithCacheManager(CacheManager & manager)
 
337
{
 
338
}
 
339
 
 
340
#endif /* USE_KQUEUE */