r5298: - got rid of pstring.h from includes.h. This at least makes it a bit
[bbaumbach/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 "system/filesys.h"
61 #include "dlinklist.h"
62 #include "lib/events/events.h"
63
64 /* use epoll if it is available */
65 #if defined(HAVE_EPOLL_CREATE) && defined(HAVE_SYS_EPOLL_H)
66 #define WITH_EPOLL 1
67 #endif
68
69 #if WITH_EPOLL
70 #include <sys/epoll.h>
71 #endif
72
73 struct event_context {  
74         /* list of filedescriptor events */
75         struct fd_event {
76                 struct event_context *event_ctx;
77                 struct fd_event *next, *prev;
78                 int fd;
79                 uint16_t flags; /* see EVENT_FD_* flags */
80                 event_fd_handler_t handler;
81                 void *private;
82         } *fd_events;
83
84         /* list of timed events */
85         struct timed_event {
86                 struct event_context *event_ctx;
87                 struct timed_event *next, *prev;
88                 struct timeval next_event;
89                 event_timed_handler_t handler;
90                 void *private;
91         } *timed_events;
92
93         /* the maximum file descriptor number in fd_events */
94         int maxfd;
95
96         /* information for exiting from the event loop */
97         int exit_code;
98
99         /* this is changed by the destructors for the fd event
100            type. It is used to detect event destruction by event
101            handlers, which means the code that is calling the event
102            handler needs to assume that the linked list is no longer
103            valid
104         */
105         uint32_t destruction_count;
106
107 #if WITH_EPOLL
108         /* when using epoll this is the handle from epoll_create */
109         int epoll_fd;
110 #endif
111 };
112
113
114 /*
115   destroy an event context
116 */
117 static int event_context_destructor(void *ptr)
118 {
119 #if WITH_EPOLL
120         struct event_context *ev = talloc_get_type(ptr, struct event_context);
121         if (ev->epoll_fd != -1) {
122                 close(ev->epoll_fd);
123                 ev->epoll_fd = -1;
124         }
125 #endif
126         return 0;
127 }
128
129 /*
130   create a event_context structure. This must be the first events
131   call, and all subsequent calls pass this event_context as the first
132   element. Event handlers also receive this as their first argument.
133 */
134 struct event_context *event_context_init(TALLOC_CTX *mem_ctx)
135 {
136         struct event_context *ev;
137
138         ev = talloc_zero(mem_ctx, struct event_context);
139         if (!ev) return NULL;
140
141 #if WITH_EPOLL
142         ev->epoll_fd = epoll_create(64);
143 #endif
144
145         talloc_set_destructor(ev, event_context_destructor);
146
147         return ev;
148 }
149
150
151 /*
152   recalculate the maxfd
153 */
154 static void calc_maxfd(struct event_context *ev)
155 {
156         struct fd_event *e;
157         ev->maxfd = 0;
158         for (e=ev->fd_events; e; e=e->next) {
159                 if (e->fd > ev->maxfd) {
160                         ev->maxfd = e->fd;
161                 }
162         }
163 }
164
165
166 /* to mark the ev->maxfd invalid
167  * this means we need to recalculate it
168  */
169 #define EVENT_INVALID_MAXFD (-1)
170
171
172 #if WITH_EPOLL
173 /*
174   called when a epoll call fails, and we should fallback
175   to using select
176 */
177 static void epoll_fallback_to_select(struct event_context *ev, const char *reason)
178 {
179         DEBUG(0,("%s (%s) - falling back to select()\n", reason, strerror(errno)));
180         close(ev->epoll_fd);
181         ev->epoll_fd = -1;
182 }
183 #endif
184
185
186 #if WITH_EPOLL
187 /*
188   map from EVENT_FD_* to EPOLLIN/EPOLLOUT
189 */
190 static uint32_t epoll_map_flags(uint16_t flags)
191 {
192         uint32_t ret = 0;
193         if (flags & EVENT_FD_READ) ret |= EPOLLIN;
194         if (flags & EVENT_FD_WRITE) ret |= EPOLLOUT;
195         return ret;
196 }
197 #endif
198
199 /*
200   destroy an fd_event
201 */
202 static int event_fd_destructor(void *ptr)
203 {
204         struct fd_event *fde = talloc_get_type(ptr, struct fd_event);
205         struct event_context *ev = fde->event_ctx;
206
207         if (ev->maxfd == fde->fd) {
208                 ev->maxfd = EVENT_INVALID_MAXFD;
209         }
210         DLIST_REMOVE(ev->fd_events, fde);
211         ev->destruction_count++;
212 #if WITH_EPOLL
213         if (ev->epoll_fd != -1) {
214                 struct epoll_event event;
215                 ZERO_STRUCT(event);
216                 event.events = epoll_map_flags(fde->flags);
217                 event.data.ptr = fde;
218                 epoll_ctl(ev->epoll_fd, EPOLL_CTL_DEL, fde->fd, &event);
219         }
220 #endif
221         return 0;
222 }
223
224 /*
225   add a fd based event
226   return NULL on failure (memory allocation error)
227 */
228 struct fd_event *event_add_fd(struct event_context *ev, TALLOC_CTX *mem_ctx,
229                               int fd, uint16_t flags, event_fd_handler_t handler,
230                               void *private)
231 {
232         struct fd_event *e = talloc(ev, struct fd_event);
233         if (!e) return NULL;
234
235         e->event_ctx = ev;
236         e->fd        = fd;
237         e->flags     = flags;
238         e->handler   = handler;
239         e->private   = private;
240
241         DLIST_ADD(ev->fd_events, e);
242
243         if (e->fd > ev->maxfd) {
244                 ev->maxfd = e->fd;
245         }
246
247         talloc_set_destructor(e, event_fd_destructor);
248         if (mem_ctx) {
249                 talloc_steal(mem_ctx, e);
250         }
251
252 #if WITH_EPOLL
253         if (ev->epoll_fd != -1) {
254                 struct epoll_event event;
255                 ZERO_STRUCT(event);
256                 event.events = epoll_map_flags(flags);
257                 event.data.ptr = e;
258                 if (epoll_ctl(ev->epoll_fd, EPOLL_CTL_ADD, e->fd, &event) != 0) {
259                         epoll_fallback_to_select(ev, "EPOLL_CTL_ADD failed");
260                 }
261         }
262 #endif
263
264         return e;
265 }
266
267
268 /*
269   return the fd event flags
270 */
271 uint16_t event_fd_flags(struct fd_event *fde)
272 {
273         return fde?fde->flags:0;
274 }
275
276 /*
277   set the fd event flags
278 */
279 void event_fd_setflags(struct fd_event *fde, uint16_t flags)
280 {
281 #if WITH_EPOLL
282         struct event_context *ev;
283         if (fde == NULL || 
284             fde->flags == flags) {
285                 return;
286         }
287         ev = fde->event_ctx;
288         if (ev->epoll_fd != -1) {
289                 struct epoll_event event;
290                 ZERO_STRUCT(event);
291                 event.events = epoll_map_flags(flags);
292                 event.data.ptr = fde;
293                 if (epoll_ctl(ev->epoll_fd, EPOLL_CTL_MOD, fde->fd, &event) != 0) {
294                         epoll_fallback_to_select(ev, "EPOLL_CTL_MOD failed");
295                 }
296         }
297 #endif
298         if (fde) {
299                 fde->flags = flags;
300         }
301 }
302
303 /*
304   destroy a timed event
305 */
306 static int event_timed_destructor(void *ptr)
307 {
308         struct timed_event *te = talloc_get_type(ptr, struct timed_event);
309         DLIST_REMOVE(te->event_ctx->timed_events, te);
310         return 0;
311 }
312
313 /*
314   add a timed event
315   return NULL on failure (memory allocation error)
316 */
317 struct timed_event *event_add_timed(struct event_context *ev, TALLOC_CTX *mem_ctx,
318                                     struct timeval next_event, 
319                                     event_timed_handler_t handler, 
320                                     void *private) 
321 {
322         struct timed_event *te, *e;
323
324         e = talloc(mem_ctx?mem_ctx:ev, struct timed_event);
325         if (e == NULL) return NULL;
326
327         e->event_ctx  = ev;
328         e->next_event = next_event;
329         e->handler    = handler;
330         e->private    = private;
331
332         /* keep the list ordered */
333         if (ev->timed_events == NULL || 
334             timeval_compare(&e->next_event, &ev->timed_events->next_event) > 0) {
335                 DLIST_ADD(ev->timed_events, e);
336         } else {
337                 for (te=ev->timed_events;te && te->next;te=te->next) {
338                         if (!timeval_is_zero(&te->next->next_event) &&
339                             timeval_compare(&te->next->next_event, &e->next_event) < 0) {
340                                 break;
341                         }
342                 }
343                 DLIST_ADD_AFTER(ev->timed_events, e, te);
344         }
345
346         talloc_set_destructor(e, event_timed_destructor);
347
348         return e;
349 }
350
351 /*
352   a timer has gone off - call it
353 */
354 static void event_loop_timer(struct event_context *ev)
355 {
356         struct timeval t = timeval_current();
357         struct timed_event *te = ev->timed_events;
358
359         te->next_event = timeval_zero();
360
361         te->handler(ev, te, t, te->private);
362
363         /* note the care taken to prevent referencing a event
364            that could have been freed by the handler */
365         if (ev->timed_events && timeval_is_zero(&ev->timed_events->next_event)) {
366                 talloc_free(ev->timed_events);
367         }
368 }
369
370 #if WITH_EPOLL
371 /*
372   event loop handling using epoll
373 */
374 static int event_loop_epoll(struct event_context *ev, struct timeval *tvalp)
375 {
376         int ret, i;
377         const int maxevents = 8;
378         struct epoll_event events[maxevents];
379         uint32_t destruction_count = ev->destruction_count;
380         int timeout = -1;
381
382         if (tvalp) {
383                 timeout = (tvalp->tv_usec / 1000) + (tvalp->tv_sec*1000);
384         }
385
386         ret = epoll_wait(ev->epoll_fd, events, maxevents, timeout);
387
388         if (ret == -1 && errno != EINTR) {
389                 epoll_fallback_to_select(ev, "epoll_wait() failed");
390                 return -1;
391         }
392
393         if (ret == 0 && tvalp) {
394                 event_loop_timer(ev);
395                 return 0;
396         }
397
398         for (i=0;i<ret;i++) {
399                 struct fd_event *fde = talloc_get_type(events[i].data.ptr, 
400                                                        struct fd_event);
401                 uint16_t flags = 0;
402
403                 if (fde == NULL) {
404                         epoll_fallback_to_select(ev, "epoll_wait() gave bad data");
405                         return -1;
406                 }
407                 if (events[i].events & EPOLLIN) flags |= EVENT_FD_READ;
408                 if (events[i].events & EPOLLOUT) flags |= EVENT_FD_WRITE;
409                 if (flags) {
410                         fde->handler(ev, fde, flags, fde->private);
411                         if (destruction_count != ev->destruction_count) {
412                                 break;
413                         }
414                 }
415         }
416
417         return 0;
418 }               
419 #endif
420
421 /*
422   event loop handling using select()
423 */
424 static int event_loop_select(struct event_context *ev, struct timeval *tvalp)
425 {
426         fd_set r_fds, w_fds;
427         int selrtn;
428         uint32_t destruction_count = ev->destruction_count;
429         struct fd_event *fe;
430
431         /* we maybe need to recalculate the maxfd */
432         if (ev->maxfd == EVENT_INVALID_MAXFD) {
433                 calc_maxfd(ev);
434         }
435                 
436         FD_ZERO(&r_fds);
437         FD_ZERO(&w_fds);
438
439         /* setup any fd events */
440         for (fe=ev->fd_events; fe; ) {
441                 struct fd_event *next = fe->next;
442                 if (fe->flags & EVENT_FD_READ) {
443                         FD_SET(fe->fd, &r_fds);
444                 }
445                 if (fe->flags & EVENT_FD_WRITE) {
446                         FD_SET(fe->fd, &w_fds);
447                 }
448                 fe = next;
449         }
450
451         selrtn = select(ev->maxfd+1, &r_fds, &w_fds, NULL, tvalp);
452                 
453         if (selrtn == -1 && errno == EBADF) {
454                 /* the socket is dead! this should never
455                    happen as the socket should have first been
456                    made readable and that should have removed
457                    the event, so this must be a bug. This is a
458                    fatal error. */
459                 DEBUG(0,("ERROR: EBADF on event_loop_once\n"));
460                 ev->exit_code = EBADF;
461                 return -1;
462         }
463
464         if (selrtn == 0 && tvalp) {
465                 event_loop_timer(ev);
466                 return 0;
467         }
468
469         if (selrtn > 0) {
470                 /* at least one file descriptor is ready - check
471                    which ones and call the handler, being careful to allow
472                    the handler to remove itself when called */
473                 for (fe=ev->fd_events; fe; fe=fe->next) {
474                         uint16_t flags = 0;
475                         if (FD_ISSET(fe->fd, &r_fds)) flags |= EVENT_FD_READ;
476                         if (FD_ISSET(fe->fd, &w_fds)) flags |= EVENT_FD_WRITE;
477                         if (flags) {
478                                 fe->handler(ev, fe, flags, fe->private);
479                                 if (destruction_count != ev->destruction_count) {
480                                         break;
481                                 }
482                         }
483                 }
484         }
485
486         return 0;
487 }               
488
489 /*
490   do a single event loop using the events defined in ev 
491 */
492 int event_loop_once(struct event_context *ev)
493 {
494         struct timeval tval, *tvalp;
495
496         tvalp = NULL;
497                 
498         /* work out the right timeout for all timed events */
499         if (ev->timed_events) {
500                 struct timeval t = timeval_current();
501                 tval = timeval_diff(&ev->timed_events->next_event, &t);
502                 tvalp = &tval;
503                 if (timeval_is_zero(tvalp)) {
504                         event_loop_timer(ev);
505                         return 0;
506                 }
507         }
508
509 #if WITH_EPOLL
510         if (ev->epoll_fd != -1) {
511                 if (event_loop_epoll(ev, tvalp) == 0) {
512                         return 0;
513                 }
514         }
515 #endif
516
517         return event_loop_select(ev, tvalp);
518 }
519
520 /*
521   go into an event loop using the events defined in ev this function
522   will return with the specified code if one of the handlers calls
523   event_loop_exit()
524
525   also return (with code 0) if all fd events are removed
526 */
527 int event_loop_wait(struct event_context *ev)
528 {
529         ev->exit_code = 0;
530         ev->maxfd = EVENT_INVALID_MAXFD;
531
532         while (ev->fd_events && ev->exit_code == 0) {
533                 if (event_loop_once(ev) != 0) {
534                         break;
535                 }
536         }
537
538         return ev->exit_code;
539 }