r23792: convert Samba4 to GPLv3
[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 3 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, see <http://www.gnu.org/licenses/>.
18 */
19
20 /*
21   PLEASE READ THIS BEFORE MODIFYING!
22
23   This module is a general abstraction for the main select loop and
24   event handling. Do not ever put any localised hacks in here, instead
25   register one of the possible event types and implement that event
26   somewhere else.
27
28   There are 2 types of event handling that are handled in this module:
29
30   1) a file descriptor becoming readable or writeable. This is mostly
31      used for network sockets, but can be used for any type of file
32      descriptor. You may only register one handler for each file
33      descriptor/io combination or you will get unpredictable results
34      (this means that you can have a handler for read events, and a
35      separate handler for write events, but not two handlers that are
36      both handling read events)
37
38   2) a timed event. You can register an event that happens at a
39      specific time.  You can register as many of these as you
40      like. They are single shot - add a new timed event in the event
41      handler to get another event.
42
43   To setup a set of events you first need to create a event_context
44   structure using the function event_context_init(); This returns a
45   'struct event_context' that you use in all subsequent calls.
46
47   After that you can add/remove events that you are interested in
48   using event_add_*() and talloc_free()
49
50   Finally, you call event_loop_wait_once() to block waiting for one of the
51   events to occor or event_loop_wait() which will loop
52   forever.
53
54 */
55
56 #include "includes.h"
57 #include "lib/events/events.h"
58 #include "lib/events/events_internal.h"
59 #include "lib/util/dlinklist.h"
60 #if _SAMBA_BUILD_
61 #include "build.h"
62 #endif
63
64 struct event_ops_list {
65         struct event_ops_list *next, *prev;
66         const char *name;
67         const struct event_ops *ops;
68 };
69
70 /* list of registered event backends */
71 static struct event_ops_list *event_backends;
72
73 static char *event_default_backend = NULL;
74
75 /*
76   register an events backend
77 */
78 bool event_register_backend(const char *name, const struct event_ops *ops)
79 {
80         struct event_ops_list *e;
81         e = talloc(talloc_autofree_context(), struct event_ops_list);
82         if (e == NULL) return False;
83         e->name = name;
84         e->ops = ops;
85         DLIST_ADD(event_backends, e);
86         return True;
87 }
88
89 /*
90   set the default event backend
91  */
92 void event_set_default_backend(const char *backend)
93 {
94         if (event_default_backend) free(event_default_backend);
95         event_default_backend = strdup(backend);
96 }
97
98 /*
99   initialise backends if not already done
100 */
101 static void event_backend_init(void)
102 {
103 #if _SAMBA_BUILD_
104         init_module_fn static_init[] = STATIC_LIBEVENTS_MODULES;
105         init_module_fn *shared_init;
106         if (event_backends) return;
107         shared_init = load_samba_modules(NULL, "LIBEVENTS");
108         run_init_functions(static_init);
109         run_init_functions(shared_init);
110 #else
111         bool events_standard_init(void);
112         bool events_select_init(void);
113         events_select_init();
114         events_standard_init();
115 #if HAVE_EVENTS_EPOLL
116         {
117                 bool events_epoll_init(void);
118                 events_epoll_init();
119         }
120 #endif
121 #endif
122 }
123
124 /*
125   list available backends
126 */
127 const char **event_backend_list(TALLOC_CTX *mem_ctx)
128 {
129         const char **list = NULL;
130         struct event_ops_list *e;
131
132         event_backend_init();
133
134         for (e=event_backends;e;e=e->next) {
135                 list = str_list_add(list, e->name);
136         }
137
138         talloc_steal(mem_ctx, list);
139
140         return list;
141 }
142
143 /*
144   create a event_context structure for a specific implemementation.
145   This must be the first events call, and all subsequent calls pass
146   this event_context as the first element. Event handlers also
147   receive this as their first argument.
148
149   This function is for allowing third-party-applications to hook in gluecode
150   to their own event loop code, so that they can make async usage of our client libs
151
152   NOTE: use event_context_init() inside of samba!
153 */
154 static struct event_context *event_context_init_ops(TALLOC_CTX *mem_ctx, 
155                                                     const struct event_ops *ops)
156 {
157         struct event_context *ev;
158         int ret;
159
160         ev = talloc_zero(mem_ctx, struct event_context);
161         if (!ev) return NULL;
162
163         ev->ops = ops;
164
165         ret = ev->ops->context_init(ev);
166         if (ret != 0) {
167                 talloc_free(ev);
168                 return NULL;
169         }
170
171         return ev;
172 }
173
174 /*
175   create a event_context structure. This must be the first events
176   call, and all subsequent calls pass this event_context as the first
177   element. Event handlers also receive this as their first argument.
178 */
179 struct event_context *event_context_init_byname(TALLOC_CTX *mem_ctx, const char *name)
180 {
181         struct event_ops_list *e;
182
183         event_backend_init();
184
185 #if _SAMBA_BUILD_
186         if (name == NULL) {
187                 name = lp_parm_string(-1, "event", "backend");
188         }
189 #endif
190         if (name == NULL) {
191                 name = event_default_backend;
192         }
193         if (name == NULL) {
194                 name = "standard";
195         }
196
197         for (e=event_backends;e;e=e->next) {
198                 if (strcmp(name, e->name) == 0) {
199                         return event_context_init_ops(mem_ctx, e->ops);
200                 }
201         }
202         return NULL;
203 }
204
205
206 /*
207   create a event_context structure. This must be the first events
208   call, and all subsequent calls pass this event_context as the first
209   element. Event handlers also receive this as their first argument.
210 */
211 struct event_context *event_context_init(TALLOC_CTX *mem_ctx)
212 {
213         return event_context_init_byname(mem_ctx, NULL);
214 }
215
216 /*
217   add a fd based event
218   return NULL on failure (memory allocation error)
219
220   if flags contains EVENT_FD_AUTOCLOSE then the fd will be closed when
221   the returned fd_event context is freed
222 */
223 struct fd_event *event_add_fd(struct event_context *ev, TALLOC_CTX *mem_ctx,
224                               int fd, uint16_t flags, event_fd_handler_t handler,
225                               void *private_data)
226 {
227         return ev->ops->add_fd(ev, mem_ctx, fd, flags, handler, private_data);
228 }
229
230 /*
231   add a disk aio event
232 */
233 struct aio_event *event_add_aio(struct event_context *ev,
234                                 TALLOC_CTX *mem_ctx,
235                                 struct iocb *iocb,
236                                 event_aio_handler_t handler,
237                                 void *private_data)
238 {
239         if (ev->ops->add_aio == NULL) return NULL;
240         return ev->ops->add_aio(ev, mem_ctx, iocb, handler, private_data);
241 }
242
243 /*
244   return the fd event flags
245 */
246 uint16_t event_get_fd_flags(struct fd_event *fde)
247 {
248         if (!fde) return 0;
249         return fde->event_ctx->ops->get_fd_flags(fde);
250 }
251
252 /*
253   set the fd event flags
254 */
255 void event_set_fd_flags(struct fd_event *fde, uint16_t flags)
256 {
257         if (!fde) return;
258         fde->event_ctx->ops->set_fd_flags(fde, flags);
259 }
260
261 /*
262   add a timed event
263   return NULL on failure
264 */
265 struct timed_event *event_add_timed(struct event_context *ev, TALLOC_CTX *mem_ctx,
266                                     struct timeval next_event, 
267                                     event_timed_handler_t handler, 
268                                     void *private_data)
269 {
270         return ev->ops->add_timed(ev, mem_ctx, next_event, handler, private_data);
271 }
272
273 /*
274   add a signal event
275
276   sa_flags are flags to sigaction(2)
277
278   return NULL on failure
279 */
280 struct signal_event *event_add_signal(struct event_context *ev, TALLOC_CTX *mem_ctx,
281                                       int signum,
282                                       int sa_flags,
283                                       event_signal_handler_t handler, 
284                                       void *private_data)
285 {
286         return ev->ops->add_signal(ev, mem_ctx, signum, sa_flags, handler, private_data);
287 }
288
289 /*
290   do a single event loop using the events defined in ev 
291 */
292 _PUBLIC_ int event_loop_once(struct event_context *ev)
293 {
294         return ev->ops->loop_once(ev);
295 }
296
297 /*
298   return on failure or (with 0) if all fd events are removed
299 */
300 int event_loop_wait(struct event_context *ev)
301 {
302         return ev->ops->loop_wait(ev);
303 }
304
305 /*
306   find an event context that is a parent of the given memory context,
307   or create a new event context as a child of the given context if
308   none is found
309
310   This should be used in preference to event_context_init() in places
311   where you would prefer to use the existing event context if possible
312   (which is most situations)
313 */
314 struct event_context *event_context_find(TALLOC_CTX *mem_ctx)
315 {
316         struct event_context *ev = talloc_find_parent_bytype(mem_ctx, struct event_context);
317         if (ev == NULL) {               
318                 ev = event_context_init(mem_ctx);
319         }
320         return ev;
321 }