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