6809ca117c3c61c1f9a364014d72dfce42ea417e
[debian/amanda] / common-src / event.c
1 /*
2  * Amanda, The Advanced Maryland Automatic Network Disk Archiver
3  * Copyright (c) 1999 University of Maryland at College Park
4  * All Rights Reserved.
5  *
6  * Permission to use, copy, modify, distribute, and sell this software and its
7  * documentation for any purpose is hereby granted without fee, provided that
8  * the above copyright notice appear in all copies and that both that
9  * copyright notice and this permission notice appear in supporting
10  * documentation, and that the name of U.M. not be used in advertising or
11  * publicity pertaining to distribution of the software without specific,
12  * written prior permission.  U.M. makes no representations about the
13  * suitability of this software for any purpose.  It is provided "as is"
14  * without express or implied warranty.
15  *
16  * U.M. DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL
17  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL U.M.
18  * BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
19  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
20  * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
21  * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
22  *
23  * Authors: the Amanda Development Team.  Its members are listed in a
24  * file named AUTHORS, in the root directory of this distribution.
25  */
26 /*
27  * $Id: event.c,v 1.20 2005/10/02 15:31:07 martinea Exp $
28  *
29  * Event handler.  Serializes different kinds of events to allow for
30  * a uniform interface, central state storage, and centralized
31  * interdependency logic.
32  */
33
34 /*#define       EVENT_DEBUG*/
35
36 #ifdef EVENT_DEBUG
37 #define eventprintf(x)    dbprintf(x)
38 #else
39 #define eventprintf(x)
40 #endif
41
42 #include "amanda.h"
43 #include "event.h"
44 #include "queue.h"
45
46 /*
47  * The opaque handle passed back to the caller.  This is typedefed to
48  * event_handle_t in our header file.
49  */
50 struct event_handle {
51     event_fn_t fn;              /* function to call when this fires */
52     void *arg;                  /* argument to pass to previous function */
53     event_type_t type;          /* type of event */
54     event_id_t data;            /* type data */
55     time_t lastfired;           /* timestamp of last fired (EV_TIME only) */
56     LIST_ENTRY(event_handle) le; /* queue handle */
57 };
58
59 /*
60  * eventq is a queue of currently active events.
61  * cache is a queue of unused handles.  We keep a few around to avoid
62  * malloc overhead when doing a lot of register/releases.
63  */
64 static struct {
65     LIST_HEAD(, event_handle) listhead;
66     int qlength;
67 } eventq = {
68     LIST_HEAD_INITIALIZER(eventq.listhead), 0
69 }, cache = {
70     LIST_HEAD_INITIALIZER(eventq.listhead), 0
71 };
72 #define eventq_first(q)         LIST_FIRST(&q.listhead)
73 #define eventq_next(eh)         LIST_NEXT(eh, le)
74 #define eventq_add(q, eh)       LIST_INSERT_HEAD(&q.listhead, eh, le);
75 #define eventq_remove(eh)       LIST_REMOVE(eh, le);
76
77 /*
78  * How many items we can have in the handle cache before we start
79  * freeing.
80  */
81 #define CACHEDEPTH      10
82
83 /*
84  * A table of currently set signal handlers.
85  */
86 static struct sigtabent {
87     event_handle_t *handle;     /* handle for this signal */
88     int score;                  /* number of signals recvd since last checked */
89     void (*oldhandler) P((int));/* old handler (for unsetting) */
90 } sigtable[NSIG];
91
92 #ifdef EVENT_DEBUG
93 static const char *event_type2str P((event_type_t));
94 #endif
95 #define fire(eh)        (*(eh)->fn)((eh)->arg)
96 static void signal_handler P((int));
97 static event_handle_t *gethandle P((void));
98 static void puthandle P((event_handle_t *));
99
100 /*
101  * Add a new event.  See the comment in event.h for what the arguments
102  * mean.
103  */
104 event_handle_t *
105 event_register(data, type, fn, arg)
106     event_id_t data;
107     event_type_t type;
108     event_fn_t fn;
109     void *arg;
110 {
111     event_handle_t *handle;
112
113     switch (type) {
114     case EV_READFD:
115     case EV_WRITEFD:
116         /* make sure we aren't given a high fd that will overflow a fd_set */
117         assert(data < FD_SETSIZE);
118         break;
119
120     case EV_SIG:
121         /* make sure signals are within range */
122         assert(data < NSIG);
123         /* make sure we don't double-register a signal */
124         assert(sigtable[data].handle == NULL);
125         break;
126
127     case EV_TIME:
128     case EV_WAIT:
129         break;
130
131     case EV_DEAD:
132     default:
133         /* callers can't register EV_DEAD */
134         assert(0);
135         break;
136     }
137
138     handle = gethandle();
139     handle->fn = fn;
140     handle->arg = arg;
141     handle->type = type;
142     handle->data = data;
143     handle->lastfired = -1;
144     eventq_add(eventq, handle);
145     eventq.qlength++;
146
147     eventprintf(("%s: event: register: %X data=%lu, type=%s\n", debug_prefix_time(NULL), (int)handle,
148                  handle->data, event_type2str(handle->type)));
149     return (handle);
150 }
151
152 /*
153  * Mark an event to be released.  Because we may be traversing the queue
154  * when this is called, we must wait until later to actually remove
155  * the event.
156  */
157 void
158 event_release(handle)
159     event_handle_t *handle;
160 {
161
162     assert(handle != NULL);
163
164     eventprintf(("%s: event: release (mark): %X data=%lu, type=%s\n", debug_prefix_time(NULL),
165         (int)handle, handle->data, event_type2str(handle->type)));
166     assert(handle->type != EV_DEAD);
167
168     /*
169      * For signal events, we need to specially remove then from the
170      * signal event table.
171      */
172     if (handle->type == EV_SIG) {
173         struct sigtabent *se = &sigtable[handle->data];
174
175         assert(se->handle == handle);
176         signal(handle->data, se->oldhandler);
177         se->handle = NULL;
178         se->score = 0;
179     }
180
181     /*
182      * Decrement the qlength now since this is no longer a real
183      * event.
184      */
185     eventq.qlength--;
186
187     /*
188      * Mark it as dead and leave it for the loop to remove.
189      */
190     handle->type = EV_DEAD;
191 }
192
193 /*
194  * Fire all EV_WAIT events waiting on the specified id.
195  */
196 int
197 event_wakeup(id)
198     event_id_t id;
199 {
200     event_handle_t *eh;
201     int nwaken = 0;
202
203     eventprintf(("%s: event: wakeup: enter (%lu)\n", debug_prefix_time(NULL), id));
204
205     assert(id >= 0);
206
207     for (eh = eventq_first(eventq); eh != NULL; eh = eventq_next(eh)) {
208
209         if (eh->type == EV_WAIT && eh->data == id) {
210             eventprintf(("%s: event: wakeup: %X id=%lu\n", debug_prefix_time(NULL), (int)eh, id));
211             fire(eh);
212             nwaken++;
213         }
214     }
215     return (nwaken);
216 }
217
218
219 /*
220  * The event loop.  We need to be specially careful here with adds and
221  * deletes.  Since adds and deletes will often happen while this is running,
222  * we need to make sure we don't end up referencing a dead event handle.
223  */
224 void
225 event_loop(dontblock)
226     const int dontblock;
227 {
228 #ifdef ASSERTIONS
229     static int entry = 0;
230 #endif
231     fd_set readfds, writefds, errfds, werrfds;
232     struct timeval timeout, *tvptr;
233     int ntries, maxfd, rc, interval;
234     time_t curtime;
235     event_handle_t *eh, *nexteh;
236     struct sigtabent *se;
237
238     eventprintf(("%s: event: loop: enter: dontblock=%d, qlength=%d\n", debug_prefix_time(NULL),
239                  dontblock, eventq.qlength));
240
241     /*
242      * If we have no events, we have nothing to do
243      */
244     if (eventq.qlength == 0)
245         return;
246
247     /*
248      * We must not be entered twice
249      */
250     assert(++entry == 1);
251
252     ntries = 0;
253
254     /*
255      * Save a copy of the current time once, to reduce syscall load
256      * slightly.
257      */
258     curtime = time(NULL);
259
260     do {
261 #ifdef EVENT_DEBUG
262         eventprintf(("%s: event: loop: dontblock=%d, qlength=%d\n", debug_prefix_time(NULL), dontblock,
263             eventq.qlength));
264         for (eh = eventq_first(eventq); eh != NULL; eh = eventq_next(eh)) {
265             eventprintf(("%s: %X: %s data=%lu fn=0x%x arg=0x%x\n", debug_prefix_time(NULL), (int)eh,
266                 event_type2str(eh->type), eh->data, (int)eh->fn, (int)eh->arg));
267         }
268 #endif
269         /*
270          * Set ourselves up with no timeout initially.
271          */
272         timeout.tv_sec = 0;
273         timeout.tv_usec = 0;
274
275         /*
276          * If we can block, initially set the tvptr to NULL.  If
277          * we come across timeout events in the loop below, they
278          * will set it to an appropriate buffer.  If we don't
279          * see any timeout events, then tvptr will remain NULL
280          * and the select will properly block indefinately.
281          *
282          * If we can't block, set it to point to the timeout buf above.
283          */
284         if (dontblock)
285             tvptr = &timeout;
286         else
287             tvptr = NULL;
288
289         /*
290          * Rebuild the select bitmasks each time.
291          */
292         FD_ZERO(&readfds);
293         FD_ZERO(&writefds);
294         FD_ZERO(&errfds);
295         maxfd = 0;
296
297         /*
298          * Run through each event handle and setup the events.
299          * We save our next pointer early in case we GC some dead
300          * events.
301          */
302         for (eh = eventq_first(eventq); eh != NULL; eh = nexteh) {
303             nexteh = eventq_next(eh);
304
305             switch (eh->type) {
306
307             /*
308              * Read fds just get set into the select bitmask
309              */
310             case EV_READFD:
311                 FD_SET(eh->data, &readfds);
312                 FD_SET(eh->data, &errfds);
313                 maxfd = max(maxfd, eh->data);
314                 break;
315
316             /*
317              * Likewise with write fds
318              */
319             case EV_WRITEFD:
320                 FD_SET(eh->data, &writefds);
321                 FD_SET(eh->data, &errfds);
322                 maxfd = max(maxfd, eh->data);
323                 break;
324
325             /*
326              * Only set signals that aren't already set to avoid unnecessary
327              * syscall overhead.
328              */
329             case EV_SIG:
330                 se = &sigtable[eh->data];
331
332                 if (se->handle == eh)
333                     break;
334
335                 /* no previous handle */
336                 assert(se->handle == NULL);
337                 se->handle = eh;
338                 se->score = 0;
339                 se->oldhandler = signal(eh->data, signal_handler);
340                 break;
341
342             /*
343              * Compute the timeout for this select
344              */
345             case EV_TIME:
346                 /* if we're not supposed to block, then leave it at 0 */
347                 if (dontblock)
348                     break;
349
350                 if (eh->lastfired == -1)
351                     eh->lastfired = curtime;
352
353                 interval = eh->data - (curtime - eh->lastfired);
354                 if (interval < 0)
355                     interval = 0;
356
357                 if (tvptr != NULL)
358                     timeout.tv_sec = min(timeout.tv_sec, interval);
359                 else {
360                     /* this is the first timeout */
361                     tvptr = &timeout;
362                     timeout.tv_sec = interval;
363                 }
364                 break;
365
366             /*
367              * Wait events are processed immediately by event_wakeup()
368              */
369             case EV_WAIT:
370                 break;
371
372             /*
373              * Prune dead events
374              */
375             case EV_DEAD:
376                 eventq_remove(eh);
377                 puthandle(eh);
378                 break;
379
380             default:
381                 assert(0);
382                 break;
383             }
384         }
385
386         /*
387          * Let 'er rip
388          */
389         eventprintf(("%s: event: select: dontblock=%d, maxfd=%d, timeout=%ld\n", debug_prefix_time(NULL),
390             dontblock, maxfd, tvptr != NULL ? timeout.tv_sec : -1));
391         rc = select(maxfd + 1, &readfds, &writefds, &errfds, tvptr);
392         eventprintf(("%s: event: select returns %d\n", debug_prefix_time(NULL), rc));
393
394         /*
395          * Select errors can mean many things.  Interrupted events should
396          * not be fatal, since they could be delivered signals which still
397          * need to have their events fired.
398          */
399         if (rc < 0) {
400             if (errno != EINTR) {
401                 if (++ntries > 5)
402                     error("select failed: %s", strerror(errno));
403                 continue;
404             }
405             /* proceed if errno == EINTR, we may have caught a signal */
406
407             /* contents cannot be trusted */
408             FD_ZERO(&readfds);
409             FD_ZERO(&writefds);
410             FD_ZERO(&errfds);
411         }
412
413         /*
414          * Grab the current time again for use in timed events.
415          */
416         curtime = time(NULL);
417
418         /*
419          * We need to copy the errfds into werrfds, so file descriptors
420          * that are being polled for both reading and writing have
421          * both of their poll events 'see' the error.
422          */
423         memcpy(&werrfds, &errfds, sizeof(werrfds));
424
425         /*
426          * Now run through the events and fire the ones that are ready.
427          * Don't handle file descriptor events if the select failed.
428          */
429         for (eh = eventq_first(eventq); eh != NULL; eh = eventq_next(eh)) {
430             switch (eh->type) {
431
432             /*
433              * Read fds: just fire the event if set in the bitmask
434              */
435             case EV_READFD:
436                 if (FD_ISSET(eh->data, &readfds) ||
437                     FD_ISSET(eh->data, &errfds)) {
438                     FD_CLR(eh->data, &readfds);
439                     FD_CLR(eh->data, &errfds);
440                     fire(eh);
441                 }
442                 break;
443
444             /*
445              * Write fds: same as Read fds
446              */
447             case EV_WRITEFD:
448                 if (FD_ISSET(eh->data, &writefds) ||
449                     FD_ISSET(eh->data, &werrfds)) {
450                     FD_CLR(eh->data, &writefds);
451                     FD_CLR(eh->data, &werrfds);
452                     fire(eh);
453                 }
454                 break;
455
456             /*
457              * Signal events: check the score for fires, and run the
458              * event if we got one.
459              */
460             case EV_SIG:
461                 se = &sigtable[eh->data];
462                 if (se->score > 0) {
463                     assert(se->handle == eh);
464                     se->score = 0;
465                     fire(eh);
466                 }
467                 break;
468
469             /*
470              * Timed events: check the interval elapsed since last fired,
471              * and set it off if greater or equal to requested interval.
472              */
473             case EV_TIME:
474                 if (eh->lastfired == -1)
475                     eh->lastfired = curtime;
476                 if (curtime - eh->lastfired >= eh->data) {
477                     eh->lastfired = curtime;
478                     fire(eh);
479                 }
480                 break;
481
482             /*
483              * Wait events are handled immediately by event_wakeup()
484              * Dead events are handled by the pre-select loop.
485              */
486             case EV_WAIT:
487             case EV_DEAD:
488                 break;
489
490             default:
491                 assert(0);
492                 break;
493             }
494         }
495     } while (!dontblock && eventq.qlength > 0);
496
497     assert(--entry == 0);
498 }
499
500 /*
501  * Generic signal handler.  Used to count caught signals for the event
502  * loop.
503  */
504 static void
505 signal_handler(signo)
506     int signo;
507 {
508
509     assert(signo >= 0 && signo < sizeof(sigtable) / sizeof(sigtable[0]));
510     sigtable[signo].score++;
511 }
512
513 /*
514  * Return a new handle.  Take from the handle cache if not empty.  Otherwise,
515  * alloc a new one.
516  */
517 static event_handle_t *
518 gethandle()
519 {
520     event_handle_t *eh;
521
522     if ((eh = eventq_first(cache)) != NULL) {
523         assert(cache.qlength > 0);
524         eventq_remove(eh);
525         cache.qlength--;
526         return (eh);
527     }
528     assert(cache.qlength == 0);
529     return (alloc(sizeof(*eh)));
530 }
531
532 /*
533  * Free a handle.  If there's space in the handle cache, put it there.
534  * Otherwise, free it.
535  */
536 static void
537 puthandle(eh)
538     event_handle_t *eh;
539 {
540
541     if (cache.qlength > CACHEDEPTH) {
542         amfree(eh);
543         return;
544     }
545     eventq_add(cache, eh);
546     cache.qlength++;
547 }
548
549 #ifdef EVENT_DEBUG
550 /*
551  * Convert an event type into a string
552  */
553 static const char *
554 event_type2str(type)
555     event_type_t type;
556 {
557     static const struct {
558         event_type_t type;
559         const char name[12];
560     } event_types[] = {
561 #define X(s)    { s, stringize(s) }
562         X(EV_READFD),
563         X(EV_WRITEFD),
564         X(EV_SIG),
565         X(EV_TIME),
566         X(EV_WAIT),
567         X(EV_DEAD),
568 #undef X
569     };
570     int i;
571
572     for (i = 0; i < sizeof(event_types) / sizeof(event_types[0]); i++)
573         if (type == event_types[i].type)
574             return (event_types[i].name);
575     return ("BOGUS EVENT TYPE");
576 }
577 #endif  /* EVENT_DEBUG */