r9702: r9680@blu: tridge | 2005-08-27 18:45:08 +1000
[bbaumbach/samba-autobuild/.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-2005
5    Copyright (C) Stefan Metzmacher      2005
6    
7    This program is free software; you can redistribute it and/or modify
8    it under the terms of the GNU General Public License as published by
9    the Free Software Foundation; either version 2 of the License, or
10    (at your option) any later version.
11    
12    This program is distributed in the hope that it will be useful,
13    but WITHOUT ANY WARRANTY; without even the implied warranty of
14    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15    GNU General Public License for more details.
16    
17    You should have received a copy of the GNU General Public License
18    along with this program; if not, write to the Free Software
19    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
20 */
21
22 /*
23   This is SAMBA's default event loop code
24
25   - we try to use epoll if configure detected support for it
26     otherwise we use select()
27   - if epoll is broken on the system or the kernel doesn't support it
28     at runtime we fallback to select()
29 */
30
31 #include "includes.h"
32 #include "system/filesys.h"
33 #include "dlinklist.h"
34 #include "lib/events/events.h"
35 #include "lib/events/events_internal.h"
36
37 /* use epoll if it is available */
38 #if defined(HAVE_EPOLL_CREATE) && defined(HAVE_SYS_EPOLL_H)
39 #define WITH_EPOLL 1
40 #endif
41
42 #if WITH_EPOLL
43 #include <sys/epoll.h>
44 #endif
45
46 struct std_event_context {
47         /* list of filedescriptor events */
48         struct fd_event *fd_events;
49
50         /* list of timed events */
51         struct timed_event *timed_events;
52
53         /* the maximum file descriptor number in fd_events */
54         int maxfd;
55
56         /* information for exiting from the event loop */
57         int exit_code;
58
59         /* this is changed by the destructors for the fd event
60            type. It is used to detect event destruction by event
61            handlers, which means the code that is calling the event
62            handler needs to assume that the linked list is no longer
63            valid
64         */
65         uint32_t destruction_count;
66
67 #if WITH_EPOLL
68         /* when using epoll this is the handle from epoll_create */
69         int epoll_fd;
70 #endif
71 };
72
73 /*
74   destroy an event context
75 */
76 static int std_event_context_destructor(void *ptr)
77 {
78 #if WITH_EPOLL
79         struct event_context *ev = talloc_get_type(ptr, struct event_context);
80         struct std_event_context *std_ev = talloc_get_type(ev->additional_data,
81                                                            struct std_event_context);
82         if (std_ev->epoll_fd != -1) {
83                 close(std_ev->epoll_fd);
84                 std_ev->epoll_fd = -1;
85         }
86 #endif
87         return 0;
88 }
89
90 /*
91   create a std_event_context structure.
92 */
93 static int std_event_context_init(struct event_context *ev, void *privata_data)
94 {
95         struct std_event_context *std_ev;
96
97         std_ev = talloc_zero(ev, struct std_event_context);
98         if (!std_ev) return -1;
99
100 #if WITH_EPOLL
101         std_ev->epoll_fd = epoll_create(64);
102 #endif
103
104         ev->additional_data = std_ev;
105
106         talloc_set_destructor(ev, std_event_context_destructor);
107
108         return 0;
109 }
110
111 /*
112   recalculate the maxfd
113 */
114 static void calc_maxfd(struct event_context *ev)
115 {
116         struct std_event_context *std_ev = talloc_get_type(ev->additional_data,
117                                                            struct std_event_context);
118         struct fd_event *fde;
119
120         std_ev->maxfd = 0;
121         for (fde = std_ev->fd_events; fde; fde = fde->next) {
122                 if (fde->fd > std_ev->maxfd) {
123                         std_ev->maxfd = fde->fd;
124                 }
125         }
126 }
127
128
129 /* to mark the ev->maxfd invalid
130  * this means we need to recalculate it
131  */
132 #define EVENT_INVALID_MAXFD (-1)
133
134
135 #if WITH_EPOLL
136 /*
137   called when a epoll call fails, and we should fallback
138   to using select
139 */
140 static void epoll_fallback_to_select(struct event_context *ev, const char *reason)
141 {
142         struct std_event_context *std_ev = talloc_get_type(ev->additional_data,
143                                                            struct std_event_context);
144         DEBUG(0,("%s (%s) - falling back to select()\n", reason, strerror(errno)));
145         close(std_ev->epoll_fd);
146         std_ev->epoll_fd = -1;
147 }
148 #endif
149
150
151 #if WITH_EPOLL
152 /*
153   map from EVENT_FD_* to EPOLLIN/EPOLLOUT
154 */
155 static uint32_t epoll_map_flags(uint16_t flags)
156 {
157         uint32_t ret = 0;
158         if (flags & EVENT_FD_READ) ret |= EPOLLIN;
159         if (flags & EVENT_FD_WRITE) ret |= EPOLLOUT;
160         return ret;
161 }
162 #endif
163
164 /*
165   destroy an fd_event
166 */
167 static int std_event_fd_destructor(void *ptr)
168 {
169         struct fd_event *fde = talloc_get_type(ptr, struct fd_event);
170         struct event_context *ev = fde->event_ctx;
171         struct std_event_context *std_ev = talloc_get_type(ev->additional_data,
172                                                            struct std_event_context);
173
174         if (std_ev->maxfd == fde->fd) {
175                 std_ev->maxfd = EVENT_INVALID_MAXFD;
176         }
177         DLIST_REMOVE(std_ev->fd_events, fde);
178         std_ev->destruction_count++;
179 #if WITH_EPOLL
180         if (std_ev->epoll_fd != -1) {
181                 struct epoll_event event;
182                 ZERO_STRUCT(event);
183                 event.events = epoll_map_flags(fde->flags);
184                 event.data.ptr = fde;
185                 epoll_ctl(std_ev->epoll_fd, EPOLL_CTL_DEL, fde->fd, &event);
186         }
187 #endif
188         return 0;
189 }
190
191 /*
192   add a fd based event
193   return NULL on failure (memory allocation error)
194 */
195 static struct fd_event *std_event_add_fd(struct event_context *ev, TALLOC_CTX *mem_ctx,
196                                          int fd, uint16_t flags,
197                                          event_fd_handler_t handler,
198                                          void *private_data)
199 {
200         struct std_event_context *std_ev = talloc_get_type(ev->additional_data,
201                                                            struct std_event_context);
202         struct fd_event *fde;
203
204         fde = talloc(mem_ctx?mem_ctx:ev, struct fd_event);
205         if (!fde) return NULL;
206
207         fde->event_ctx          = ev;
208         fde->fd                 = fd;
209         fde->flags              = flags;
210         fde->handler            = handler;
211         fde->private_data       = private_data;
212         fde->additional_data    = NULL;
213
214         DLIST_ADD(std_ev->fd_events, fde);
215
216         if (fde->fd > std_ev->maxfd) {
217                 std_ev->maxfd = fde->fd;
218         }
219
220         talloc_set_destructor(fde, std_event_fd_destructor);
221
222 #if WITH_EPOLL
223         if (std_ev->epoll_fd != -1) {
224                 struct epoll_event event;
225                 ZERO_STRUCT(event);
226                 event.events = epoll_map_flags(flags);
227                 event.data.ptr = fde;
228                 if (epoll_ctl(std_ev->epoll_fd, EPOLL_CTL_ADD, fde->fd, &event) != 0) {
229                         epoll_fallback_to_select(ev, "EPOLL_CTL_ADD failed");
230                 }
231         }
232 #endif
233
234         return fde;
235 }
236
237
238 /*
239   return the fd event flags
240 */
241 static uint16_t std_event_get_fd_flags(struct fd_event *fde)
242 {
243         return fde?fde->flags:0;
244 }
245
246 /*
247   set the fd event flags
248 */
249 static void std_event_set_fd_flags(struct fd_event *fde, uint16_t flags)
250 {
251 #if WITH_EPOLL
252         struct event_context *ev;
253         struct std_event_context *std_ev;
254         if (fde == NULL || 
255             fde->flags == flags) {
256                 return;
257         }
258         ev = fde->event_ctx;
259         std_ev = talloc_get_type(ev->additional_data, struct std_event_context);
260         if (std_ev->epoll_fd != -1) {
261                 struct epoll_event event;
262                 ZERO_STRUCT(event);
263                 event.events = epoll_map_flags(flags);
264                 event.data.ptr = fde;
265                 if (epoll_ctl(std_ev->epoll_fd, EPOLL_CTL_MOD, fde->fd, &event) != 0) {
266                         epoll_fallback_to_select(ev, "EPOLL_CTL_MOD failed");
267                 }
268         }
269 #endif
270         if (fde) {
271                 fde->flags = flags;
272         }
273 }
274
275 /*
276   destroy a timed event
277 */
278 static int std_event_timed_destructor(void *ptr)
279 {
280         struct timed_event *te = talloc_get_type(ptr, struct timed_event);
281         struct std_event_context *std_ev = talloc_get_type(te->event_ctx->additional_data,
282                                                            struct std_event_context);
283         DLIST_REMOVE(std_ev->timed_events, te);
284         return 0;
285 }
286
287 /*
288   add a timed event
289   return NULL on failure (memory allocation error)
290 */
291 static struct timed_event *std_event_add_timed(struct event_context *ev, TALLOC_CTX *mem_ctx,
292                                                struct timeval next_event, 
293                                                event_timed_handler_t handler, 
294                                                void *private_data) 
295 {
296         struct std_event_context *std_ev = talloc_get_type(ev->additional_data,
297                                                            struct std_event_context);
298         struct timed_event *te, *last_te, *cur_te;
299
300         te = talloc(mem_ctx?mem_ctx:ev, struct timed_event);
301         if (te == NULL) return NULL;
302
303         te->event_ctx           = ev;
304         te->next_event          = next_event;
305         te->handler             = handler;
306         te->private_data        = private_data;
307         te->additional_data     = NULL;
308
309         /* keep the list ordered */
310         last_te = NULL;
311         for (cur_te = std_ev->timed_events; cur_te; cur_te = cur_te->next) {
312                 /* if the new event comes before the current one break */
313                 if (!timeval_is_zero(&cur_te->next_event) &&
314                     timeval_compare(&te->next_event,
315                                     &cur_te->next_event) < 0) {
316                         break;
317                 }
318
319                 last_te = cur_te;
320         }
321
322         DLIST_ADD_AFTER(std_ev->timed_events, te, last_te);
323
324         talloc_set_destructor(te, std_event_timed_destructor);
325
326         return te;
327 }
328
329 /*
330   a timer has gone off - call it
331 */
332 static void std_event_loop_timer(struct event_context *ev)
333 {
334         struct std_event_context *std_ev = talloc_get_type(ev->additional_data,
335                                                            struct std_event_context);
336         struct timeval t = timeval_current();
337         struct timed_event *te = std_ev->timed_events;
338
339         if (te == NULL) {
340                 return;
341         }
342
343         te->next_event = timeval_zero();
344
345         te->handler(ev, te, t, te->private_data);
346
347         /* note the care taken to prevent referencing a event
348            that could have been freed by the handler */
349         if (std_ev->timed_events) {
350                 if (timeval_is_zero(&std_ev->timed_events->next_event)) {
351                         talloc_free(te);
352                 }
353         }
354 }
355
356 #if WITH_EPOLL
357 /*
358   event loop handling using epoll
359 */
360 static int std_event_loop_epoll(struct event_context *ev, struct timeval *tvalp)
361 {
362         struct std_event_context *std_ev = talloc_get_type(ev->additional_data,
363                                                            struct std_event_context);
364         int ret, i;
365 #define MAXEVENTS 8
366         struct epoll_event events[MAXEVENTS];
367         uint32_t destruction_count = std_ev->destruction_count;
368         int timeout = -1;
369
370         if (tvalp) {
371                 /* it's better to trigger timed events a bit later than to early */
372                 timeout = ((tvalp->tv_usec+999) / 1000) + (tvalp->tv_sec*1000);
373         }
374
375         ret = epoll_wait(std_ev->epoll_fd, events, MAXEVENTS, timeout);
376
377         if (ret == -1 && errno != EINTR) {
378                 epoll_fallback_to_select(ev, "epoll_wait() failed");
379                 return -1;
380         }
381
382         if (ret == 0 && tvalp) {
383                 std_event_loop_timer(ev);
384                 return 0;
385         }
386
387         for (i=0;i<ret;i++) {
388                 struct fd_event *fde = talloc_get_type(events[i].data.ptr, 
389                                                        struct fd_event);
390                 uint16_t flags = 0;
391
392                 if (fde == NULL) {
393                         epoll_fallback_to_select(ev, "epoll_wait() gave bad data");
394                         return -1;
395                 }
396                 if (events[i].events & (EPOLLIN|EPOLLHUP|EPOLLERR)) 
397                         flags |= EVENT_FD_READ;
398                 if (events[i].events & EPOLLOUT) flags |= EVENT_FD_WRITE;
399                 if (flags) {
400                         fde->handler(ev, fde, flags, fde->private_data);
401                         if (destruction_count != std_ev->destruction_count) {
402                                 break;
403                         }
404                 }
405         }
406
407         return 0;
408 }               
409 #endif
410
411 /*
412   event loop handling using select()
413 */
414 static int std_event_loop_select(struct event_context *ev, struct timeval *tvalp)
415 {
416         struct std_event_context *std_ev = talloc_get_type(ev->additional_data,
417                                                            struct std_event_context);
418         fd_set r_fds, w_fds;
419         struct fd_event *fde;
420         int selrtn;
421         uint32_t destruction_count = std_ev->destruction_count;
422
423         /* we maybe need to recalculate the maxfd */
424         if (std_ev->maxfd == EVENT_INVALID_MAXFD) {
425                 calc_maxfd(ev);
426         }
427
428         FD_ZERO(&r_fds);
429         FD_ZERO(&w_fds);
430
431         /* setup any fd events */
432         for (fde = std_ev->fd_events; fde; fde = fde->next) {
433                 if (fde->flags & EVENT_FD_READ) {
434                         FD_SET(fde->fd, &r_fds);
435                 }
436                 if (fde->flags & EVENT_FD_WRITE) {
437                         FD_SET(fde->fd, &w_fds);
438                 }
439         }
440
441         selrtn = select(std_ev->maxfd+1, &r_fds, &w_fds, NULL, tvalp);
442
443         if (selrtn == -1 && errno == EBADF) {
444                 /* the socket is dead! this should never
445                    happen as the socket should have first been
446                    made readable and that should have removed
447                    the event, so this must be a bug. This is a
448                    fatal error. */
449                 DEBUG(0,("ERROR: EBADF on std_event_loop_once\n"));
450                 std_ev->exit_code = EBADF;
451                 return -1;
452         }
453
454         if (selrtn == 0 && tvalp) {
455                 std_event_loop_timer(ev);
456                 return 0;
457         }
458
459         if (selrtn > 0) {
460                 /* at least one file descriptor is ready - check
461                    which ones and call the handler, being careful to allow
462                    the handler to remove itself when called */
463                 for (fde = std_ev->fd_events; fde; fde = fde->next) {
464                         uint16_t flags = 0;
465
466                         if (FD_ISSET(fde->fd, &r_fds)) flags |= EVENT_FD_READ;
467                         if (FD_ISSET(fde->fd, &w_fds)) flags |= EVENT_FD_WRITE;
468                         if (flags) {
469                                 fde->handler(ev, fde, flags, fde->private_data);
470                                 if (destruction_count != std_ev->destruction_count) {
471                                         break;
472                                 }
473                         }
474                 }
475         }
476
477         return 0;
478 }               
479
480 /*
481   do a single event loop using the events defined in ev 
482 */
483 static int std_event_loop_once(struct event_context *ev)
484 {
485         struct std_event_context *std_ev = talloc_get_type(ev->additional_data,
486                                                            struct std_event_context);
487         struct timeval tval;
488
489         /* work out the right timeout for all timed events */
490         if (std_ev->timed_events) {
491                 struct timeval t = timeval_current();
492                 tval = timeval_until(&t, &std_ev->timed_events->next_event);
493                 if (timeval_is_zero(&tval)) {
494                         std_event_loop_timer(ev);
495                         return 0;
496                 }
497         } else {
498                 /* have a default tick time of 30 seconds. This guarantees
499                    that code that uses its own timeout checking will be
500                    able to proceeed eventually */
501                 tval = timeval_set(30, 0);
502         }
503
504 #if WITH_EPOLL
505         if (std_ev->epoll_fd != -1) {
506                 if (std_event_loop_epoll(ev, &tval) == 0) {
507                         return 0;
508                 }
509         }
510 #endif
511
512         return std_event_loop_select(ev, &tval);
513 }
514
515 /*
516   return on failure or (with 0) if all fd events are removed
517 */
518 static int std_event_loop_wait(struct event_context *ev)
519 {
520         struct std_event_context *std_ev = talloc_get_type(ev->additional_data,
521                                                            struct std_event_context);
522         std_ev->exit_code = 0;
523
524         while (std_ev->fd_events && std_ev->exit_code == 0) {
525                 if (std_event_loop_once(ev) != 0) {
526                         break;
527                 }
528         }
529
530         return std_ev->exit_code;
531 }
532
533 static const struct event_ops std_event_ops = {
534         .context_init   = std_event_context_init,
535         .add_fd         = std_event_add_fd,
536         .get_fd_flags   = std_event_get_fd_flags,
537         .set_fd_flags   = std_event_set_fd_flags,
538         .add_timed      = std_event_add_timed,
539         .loop_once      = std_event_loop_once,
540         .loop_wait      = std_event_loop_wait,
541 };
542
543 const struct event_ops *event_standard_get_ops(void)
544 {
545         return &std_event_ops;
546 }