r5393: trigger timed events not to early, better do it a bit to late
[samba.git] / source4 / lib / events / events_standard.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                 /* it's better to trigger timed events a bit later than to early */
384                 timeout = ((tvalp->tv_usec+999) / 1000) + (tvalp->tv_sec*1000);
385         }
386
387         ret = epoll_wait(ev->epoll_fd, events, maxevents, timeout);
388
389         if (ret == -1 && errno != EINTR) {
390                 epoll_fallback_to_select(ev, "epoll_wait() failed");
391                 return -1;
392         }
393
394         if (ret == 0 && tvalp) {
395                 event_loop_timer(ev);
396                 return 0;
397         }
398
399         for (i=0;i<ret;i++) {
400                 struct fd_event *fde = talloc_get_type(events[i].data.ptr, 
401                                                        struct fd_event);
402                 uint16_t flags = 0;
403
404                 if (fde == NULL) {
405                         epoll_fallback_to_select(ev, "epoll_wait() gave bad data");
406                         return -1;
407                 }
408                 if (events[i].events & (EPOLLIN|EPOLLHUP|EPOLLERR)) 
409                         flags |= EVENT_FD_READ;
410                 if (events[i].events & EPOLLOUT) flags |= EVENT_FD_WRITE;
411                 if (flags) {
412                         fde->handler(ev, fde, flags, fde->private);
413                         if (destruction_count != ev->destruction_count) {
414                                 break;
415                         }
416                 }
417         }
418
419         return 0;
420 }               
421 #endif
422
423 /*
424   event loop handling using select()
425 */
426 static int event_loop_select(struct event_context *ev, struct timeval *tvalp)
427 {
428         fd_set r_fds, w_fds;
429         int selrtn;
430         uint32_t destruction_count = ev->destruction_count;
431         struct fd_event *fe;
432
433         /* we maybe need to recalculate the maxfd */
434         if (ev->maxfd == EVENT_INVALID_MAXFD) {
435                 calc_maxfd(ev);
436         }
437                 
438         FD_ZERO(&r_fds);
439         FD_ZERO(&w_fds);
440
441         /* setup any fd events */
442         for (fe=ev->fd_events; fe; ) {
443                 struct fd_event *next = fe->next;
444                 if (fe->flags & EVENT_FD_READ) {
445                         FD_SET(fe->fd, &r_fds);
446                 }
447                 if (fe->flags & EVENT_FD_WRITE) {
448                         FD_SET(fe->fd, &w_fds);
449                 }
450                 fe = next;
451         }
452
453         selrtn = select(ev->maxfd+1, &r_fds, &w_fds, NULL, tvalp);
454                 
455         if (selrtn == -1 && errno == EBADF) {
456                 /* the socket is dead! this should never
457                    happen as the socket should have first been
458                    made readable and that should have removed
459                    the event, so this must be a bug. This is a
460                    fatal error. */
461                 DEBUG(0,("ERROR: EBADF on event_loop_once\n"));
462                 ev->exit_code = EBADF;
463                 return -1;
464         }
465
466         if (selrtn == 0 && tvalp) {
467                 event_loop_timer(ev);
468                 return 0;
469         }
470
471         if (selrtn > 0) {
472                 /* at least one file descriptor is ready - check
473                    which ones and call the handler, being careful to allow
474                    the handler to remove itself when called */
475                 for (fe=ev->fd_events; fe; fe=fe->next) {
476                         uint16_t flags = 0;
477                         if (FD_ISSET(fe->fd, &r_fds)) flags |= EVENT_FD_READ;
478                         if (FD_ISSET(fe->fd, &w_fds)) flags |= EVENT_FD_WRITE;
479                         if (flags) {
480                                 fe->handler(ev, fe, flags, fe->private);
481                                 if (destruction_count != ev->destruction_count) {
482                                         break;
483                                 }
484                         }
485                 }
486         }
487
488         return 0;
489 }               
490
491 /*
492   do a single event loop using the events defined in ev 
493 */
494 int event_loop_once(struct event_context *ev)
495 {
496         struct timeval tval, *tvalp;
497
498         tvalp = NULL;
499                 
500         /* work out the right timeout for all timed events */
501         if (ev->timed_events) {
502                 struct timeval t = timeval_current();
503                 tval = timeval_diff(&ev->timed_events->next_event, &t);
504                 tvalp = &tval;
505                 if (timeval_is_zero(tvalp)) {
506                         event_loop_timer(ev);
507                         return 0;
508                 }
509         }
510
511 #if WITH_EPOLL
512         if (ev->epoll_fd != -1) {
513                 if (event_loop_epoll(ev, tvalp) == 0) {
514                         return 0;
515                 }
516         }
517 #endif
518
519         return event_loop_select(ev, tvalp);
520 }
521
522 /*
523   go into an event loop using the events defined in ev this function
524   will return with the specified code if one of the handlers calls
525   event_loop_exit()
526
527   also return (with code 0) if all fd events are removed
528 */
529 int event_loop_wait(struct event_context *ev)
530 {
531         ev->exit_code = 0;
532         ev->maxfd = EVENT_INVALID_MAXFD;
533
534         while (ev->fd_events && ev->exit_code == 0) {
535                 if (event_loop_once(ev) != 0) {
536                         break;
537                 }
538         }
539
540         return ev->exit_code;
541 }