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