r5284: this is needed on my server
[kai/samba-autobuild/.git] / source4 / lib / events / events.c
1 /* 
2    Unix SMB/CIFS implementation.
3    main select loop and event handling
4    Copyright (C) Andrew Tridgell 2003
5    
6    This program is free software; you can redistribute it and/or modify
7    it under the terms of the GNU General Public License as published by
8    the Free Software Foundation; either version 2 of the License, or
9    (at your option) any later version.
10    
11    This program is distributed in the hope that it will be useful,
12    but WITHOUT ANY WARRANTY; without even the implied warranty of
13    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14    GNU General Public License for more details.
15    
16    You should have received a copy of the GNU General Public License
17    along with this program; if not, write to the Free Software
18    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
19 */
20
21 /*
22   PLEASE READ THIS BEFORE MODIFYING!
23
24   This module is a general abstraction for the main select loop and
25   event handling. Do not ever put any localised hacks in here, instead
26   register one of the possible event types and implement that event
27   somewhere else.
28
29   There are 2 types of event handling that are handled in this module:
30
31   1) a file descriptor becoming readable or writeable. This is mostly
32      used for network sockets, but can be used for any type of file
33      descriptor. You may only register one handler for each file
34      descriptor/io combination or you will get unpredictable results
35      (this means that you can have a handler for read events, and a
36      separate handler for write events, but not two handlers that are
37      both handling read events)
38
39   2) a timed event. You can register an event that happens at a
40      specific time.  You can register as many of these as you
41      like. They are single shot - add a new timed event in the event
42      handler to get another event.
43
44   To setup a set of events you first need to create a event_context
45   structure using the function event_context_init(); This returns a
46   'struct event_context' that you use in all subsequent calls.
47
48   After that you can add/remove events that you are interested in
49   using event_add_*() and talloc_free()
50
51   Finally, you call event_loop_wait() to block waiting for one of the
52   events to occor. In normal operation event_loop_wait() will loop
53   forever.
54
55 */
56
57 #include "includes.h"
58 #include "system/time.h"
59 #include "system/select.h"
60 #include "dlinklist.h"
61 #include "lib/events/events.h"
62
63 /* use epoll if it is available */
64 #if defined(HAVE_EPOLL_CREATE) && defined(HAVE_SYS_EPOLL_H)
65 #define WITH_EPOLL 1
66 #endif
67
68 #if WITH_EPOLL
69 /* this #undef is needed on my SuSE 9.2 Box with glibc-devel-2.3.3-118 */
70 #undef u32
71 #include <sys/epoll.h>
72 #endif
73
74 struct event_context {  
75         /* list of filedescriptor events */
76         struct fd_event {
77                 struct event_context *event_ctx;
78                 struct fd_event *next, *prev;
79                 int fd;
80                 uint16_t flags; /* see EVENT_FD_* flags */
81                 event_fd_handler_t handler;
82                 void *private;
83         } *fd_events;
84
85         /* list of timed events */
86         struct timed_event {
87                 struct event_context *event_ctx;
88                 struct timed_event *next, *prev;
89                 struct timeval next_event;
90                 event_timed_handler_t handler;
91                 void *private;
92         } *timed_events;
93
94         /* the maximum file descriptor number in fd_events */
95         int maxfd;
96
97         /* information for exiting from the event loop */
98         int exit_code;
99
100         /* this is changed by the destructors for the fd event
101            type. It is used to detect event destruction by event
102            handlers, which means the code that is calling the event
103            handler needs to assume that the linked list is no longer
104            valid
105         */
106         uint32_t destruction_count;
107
108 #if WITH_EPOLL
109         /* when using epoll this is the handle from epoll_create */
110         int epoll_fd;
111 #endif
112 };
113
114
115 /*
116   create a event_context structure. This must be the first events
117   call, and all subsequent calls pass this event_context as the first
118   element. Event handlers also receive this as their first argument.
119 */
120 struct event_context *event_context_init(TALLOC_CTX *mem_ctx)
121 {
122         struct event_context *ev;
123
124         ev = talloc_zero(mem_ctx, struct event_context);
125         if (!ev) return NULL;
126
127 #if WITH_EPOLL
128         ev->epoll_fd = epoll_create(64);
129 #endif
130
131         return ev;
132 }
133
134
135 /*
136   recalculate the maxfd
137 */
138 static void calc_maxfd(struct event_context *ev)
139 {
140         struct fd_event *e;
141         ev->maxfd = 0;
142         for (e=ev->fd_events; e; e=e->next) {
143                 if (e->fd > ev->maxfd) {
144                         ev->maxfd = e->fd;
145                 }
146         }
147 }
148
149
150 /* to mark the ev->maxfd invalid
151  * this means we need to recalculate it
152  */
153 #define EVENT_INVALID_MAXFD (-1)
154
155
156 #if WITH_EPOLL
157 /*
158   called when a epoll call fails, and we should fallback
159   to using select
160 */
161 static void epoll_fallback_to_select(struct event_context *ev, const char *reason)
162 {
163         DEBUG(0,("%s (%s) - falling back to select()\n", reason, strerror(errno)));
164         close(ev->epoll_fd);
165         ev->epoll_fd = -1;
166 }
167 #endif
168
169
170 #if WITH_EPOLL
171 /*
172   map from EVENT_FD_* to EPOLLIN/EPOLLOUT
173 */
174 static uint32_t epoll_map_flags(uint16_t flags)
175 {
176         uint32_t ret = 0;
177         if (flags & EVENT_FD_READ) ret |= EPOLLIN;
178         if (flags & EVENT_FD_WRITE) ret |= EPOLLOUT;
179         return ret;
180 }
181 #endif
182
183 /*
184   destroy an fd_event
185 */
186 static int event_fd_destructor(void *ptr)
187 {
188         struct fd_event *fde = talloc_get_type(ptr, struct fd_event);
189         struct event_context *ev = fde->event_ctx;
190
191         if (ev->maxfd == fde->fd) {
192                 ev->maxfd = EVENT_INVALID_MAXFD;
193         }
194         DLIST_REMOVE(ev->fd_events, fde);
195         ev->destruction_count++;
196 #if WITH_EPOLL
197         if (ev->epoll_fd != -1) {
198                 struct epoll_event event;
199                 ZERO_STRUCT(event);
200                 event.events = epoll_map_flags(fde->flags);
201                 event.data.ptr = fde;
202                 epoll_ctl(ev->epoll_fd, EPOLL_CTL_DEL, fde->fd, &event);
203         }
204 #endif
205         return 0;
206 }
207
208 /*
209   add a fd based event
210   return NULL on failure (memory allocation error)
211 */
212 struct fd_event *event_add_fd(struct event_context *ev, TALLOC_CTX *mem_ctx,
213                               int fd, uint16_t flags, event_fd_handler_t handler,
214                               void *private)
215 {
216         struct fd_event *e = talloc(ev, struct fd_event);
217         if (!e) return NULL;
218
219         e->event_ctx = ev;
220         e->fd        = fd;
221         e->flags     = flags;
222         e->handler   = handler;
223         e->private   = private;
224
225         DLIST_ADD(ev->fd_events, e);
226
227         if (e->fd > ev->maxfd) {
228                 ev->maxfd = e->fd;
229         }
230
231         talloc_set_destructor(e, event_fd_destructor);
232         if (mem_ctx) {
233                 talloc_steal(mem_ctx, e);
234         }
235
236 #if WITH_EPOLL
237         if (ev->epoll_fd != -1) {
238                 struct epoll_event event;
239                 ZERO_STRUCT(event);
240                 event.events = epoll_map_flags(flags);
241                 event.data.ptr = e;
242                 if (epoll_ctl(ev->epoll_fd, EPOLL_CTL_ADD, e->fd, &event) != 0) {
243                         epoll_fallback_to_select(ev, "EPOLL_CTL_ADD failed");
244                 }
245         }
246 #endif
247
248         return e;
249 }
250
251
252 /*
253   return the fd event flags
254 */
255 uint16_t event_fd_flags(struct fd_event *fde)
256 {
257         return fde?fde->flags:0;
258 }
259
260 /*
261   set the fd event flags
262 */
263 void event_fd_setflags(struct fd_event *fde, uint16_t flags)
264 {
265 #if WITH_EPOLL
266         struct event_context *ev;
267         if (fde == NULL || 
268             fde->flags == flags) {
269                 return;
270         }
271         ev = fde->event_ctx;
272         if (ev->epoll_fd != -1) {
273                 struct epoll_event event;
274                 ZERO_STRUCT(event);
275                 event.events = epoll_map_flags(flags);
276                 event.data.ptr = fde;
277                 if (epoll_ctl(ev->epoll_fd, EPOLL_CTL_MOD, fde->fd, &event) != 0) {
278                         epoll_fallback_to_select(ev, "EPOLL_CTL_MOD failed");
279                 }
280         }
281 #endif
282         if (fde) {
283                 fde->flags = flags;
284         }
285 }
286
287 /*
288   destroy a timed event
289 */
290 static int event_timed_destructor(void *ptr)
291 {
292         struct timed_event *te = talloc_get_type(ptr, struct timed_event);
293         DLIST_REMOVE(te->event_ctx->timed_events, te);
294         return 0;
295 }
296
297 /*
298   add a timed event
299   return NULL on failure (memory allocation error)
300 */
301 struct timed_event *event_add_timed(struct event_context *ev, TALLOC_CTX *mem_ctx,
302                                     struct timeval next_event, 
303                                     event_timed_handler_t handler, 
304                                     void *private) 
305 {
306         struct timed_event *te, *e;
307
308         e = talloc(mem_ctx?mem_ctx:ev, struct timed_event);
309         if (e == NULL) return NULL;
310
311         e->event_ctx  = ev;
312         e->next_event = next_event;
313         e->handler    = handler;
314         e->private    = private;
315
316         /* keep the list ordered */
317         if (ev->timed_events == NULL || 
318             timeval_compare(&e->next_event, &ev->timed_events->next_event) > 0) {
319                 DLIST_ADD(ev->timed_events, e);
320         } else {
321                 for (te=ev->timed_events;te && te->next;te=te->next) {
322                         if (!timeval_is_zero(&te->next->next_event) &&
323                             timeval_compare(&te->next->next_event, &e->next_event) < 0) {
324                                 break;
325                         }
326                 }
327                 DLIST_ADD_AFTER(ev->timed_events, e, te);
328         }
329
330         talloc_set_destructor(e, event_timed_destructor);
331
332         return e;
333 }
334
335 /*
336   a timer has gone off - call it
337 */
338 static void event_loop_timer(struct event_context *ev)
339 {
340         struct timeval t = timeval_current();
341         struct timed_event *te = ev->timed_events;
342
343         te->next_event = timeval_zero();
344
345         te->handler(ev, te, t, te->private);
346
347         /* note the care taken to prevent referencing a event
348            that could have been freed by the handler */
349         if (ev->timed_events && timeval_is_zero(&ev->timed_events->next_event)) {
350                 talloc_free(ev->timed_events);
351         }
352 }
353
354 #if WITH_EPOLL
355 /*
356   event loop handling using epoll
357 */
358 static int event_loop_epoll(struct event_context *ev, struct timeval *tvalp)
359 {
360         int ret, i;
361         const int maxevents = 8;
362         struct epoll_event events[maxevents];
363         uint32_t destruction_count = ev->destruction_count;
364         int timeout = -1;
365
366         if (tvalp) {
367                 timeout = (tvalp->tv_usec / 1000) + (tvalp->tv_sec*1000);
368         }
369
370         ret = epoll_wait(ev->epoll_fd, events, maxevents, timeout);
371
372         if (ret == -1 && errno != EINTR) {
373                 epoll_fallback_to_select(ev, "epoll_wait() failed");
374                 return -1;
375         }
376
377         if (ret == 0 && tvalp) {
378                 event_loop_timer(ev);
379                 return 0;
380         }
381
382         for (i=0;i<ret;i++) {
383                 struct fd_event *fde = talloc_get_type(events[i].data.ptr, 
384                                                        struct fd_event);
385                 uint16_t flags = 0;
386
387                 if (fde == NULL) {
388                         epoll_fallback_to_select(ev, "epoll_wait() gave bad data");
389                         return -1;
390                 }
391                 if (events[i].events & EPOLLIN) flags |= EVENT_FD_READ;
392                 if (events[i].events & EPOLLOUT) flags |= EVENT_FD_WRITE;
393                 if (flags) {
394                         fde->handler(ev, fde, flags, fde->private);
395                         if (destruction_count != ev->destruction_count) {
396                                 break;
397                         }
398                 }
399         }
400
401         return 0;
402 }               
403 #endif
404
405 /*
406   event loop handling using select()
407 */
408 static int event_loop_select(struct event_context *ev, struct timeval *tvalp)
409 {
410         fd_set r_fds, w_fds;
411         int selrtn;
412         uint32_t destruction_count = ev->destruction_count;
413         struct fd_event *fe;
414
415         /* we maybe need to recalculate the maxfd */
416         if (ev->maxfd == EVENT_INVALID_MAXFD) {
417                 calc_maxfd(ev);
418         }
419                 
420         FD_ZERO(&r_fds);
421         FD_ZERO(&w_fds);
422
423         /* setup any fd events */
424         for (fe=ev->fd_events; fe; ) {
425                 struct fd_event *next = fe->next;
426                 if (fe->flags & EVENT_FD_READ) {
427                         FD_SET(fe->fd, &r_fds);
428                 }
429                 if (fe->flags & EVENT_FD_WRITE) {
430                         FD_SET(fe->fd, &w_fds);
431                 }
432                 fe = next;
433         }
434
435         selrtn = select(ev->maxfd+1, &r_fds, &w_fds, NULL, tvalp);
436                 
437         if (selrtn == -1 && errno == EBADF) {
438                 /* the socket is dead! this should never
439                    happen as the socket should have first been
440                    made readable and that should have removed
441                    the event, so this must be a bug. This is a
442                    fatal error. */
443                 DEBUG(0,("ERROR: EBADF on event_loop_once\n"));
444                 ev->exit_code = EBADF;
445                 return -1;
446         }
447
448         if (selrtn == 0 && tvalp) {
449                 event_loop_timer(ev);
450                 return 0;
451         }
452
453         if (selrtn > 0) {
454                 /* at least one file descriptor is ready - check
455                    which ones and call the handler, being careful to allow
456                    the handler to remove itself when called */
457                 for (fe=ev->fd_events; fe; fe=fe->next) {
458                         uint16_t flags = 0;
459                         if (FD_ISSET(fe->fd, &r_fds)) flags |= EVENT_FD_READ;
460                         if (FD_ISSET(fe->fd, &w_fds)) flags |= EVENT_FD_WRITE;
461                         if (flags) {
462                                 fe->handler(ev, fe, flags, fe->private);
463                                 if (destruction_count != ev->destruction_count) {
464                                         break;
465                                 }
466                         }
467                 }
468         }
469
470         return 0;
471 }               
472
473 /*
474   do a single event loop using the events defined in ev 
475 */
476 int event_loop_once(struct event_context *ev)
477 {
478         struct timeval tval, *tvalp;
479
480         tvalp = NULL;
481                 
482         /* work out the right timeout for all timed events */
483         if (ev->timed_events) {
484                 struct timeval t = timeval_current();
485                 tval = timeval_diff(&ev->timed_events->next_event, &t);
486                 tvalp = &tval;
487                 if (timeval_is_zero(tvalp)) {
488                         event_loop_timer(ev);
489                         return 0;
490                 }
491         }
492
493 #if WITH_EPOLL
494         if (ev->epoll_fd != -1) {
495                 if (event_loop_epoll(ev, tvalp) == 0) {
496                         return 0;
497                 }
498         }
499 #endif
500
501         return event_loop_select(ev, tvalp);
502 }
503
504 /*
505   go into an event loop using the events defined in ev this function
506   will return with the specified code if one of the handlers calls
507   event_loop_exit()
508
509   also return (with code 0) if all fd events are removed
510 */
511 int event_loop_wait(struct event_context *ev)
512 {
513         ev->exit_code = 0;
514         ev->maxfd = EVENT_INVALID_MAXFD;
515
516         while (ev->fd_events && ev->exit_code == 0) {
517                 if (event_loop_once(ev) != 0) {
518                         break;
519                 }
520         }
521
522         return ev->exit_code;
523 }