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