initial version
[ctdb.git] / lib / events / .svn / text-base / events_liboop.c.svn-base
1 /* 
2    Unix SMB/CIFS implementation.
3    main select loop and event handling
4    wrapper for http://liboop.org/
5
6    Copyright (C) Stefan Metzmacher 2005
7    
8    This program is free software; you can redistribute it and/or modify
9    it under the terms of the GNU General Public License as published by
10    the Free Software Foundation; either version 2 of the License, or
11    (at your option) any later version.
12    
13    This program is distributed in the hope that it will be useful,
14    but WITHOUT ANY WARRANTY; without even the implied warranty of
15    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16    GNU General Public License for more details.
17    
18    You should have received a copy of the GNU General Public License
19    along with this program; if not, write to the Free Software
20    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
21 */
22
23 #include "includes.h"
24 #include "lib/events/events.h"
25 #include "lib/events/events_internal.h"
26
27 #include <oop.h>
28
29 /*
30  !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! 
31
32  NOTE: this code compiles fine, but is completly *UNTESTED*
33        and is only commited as example
34
35  !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!   
36 */
37
38 static int oop_event_context_destructor(struct event_context *ev)
39 {
40         oop_source_sys *oop_sys = ev->additional_data;
41
42         oop_sys_delete(oop_sys);
43
44         return 0;
45 }
46
47 /*
48   create a oop_event_context structure.
49 */
50 static int oop_event_context_init(struct event_context *ev, void *private_data)
51 {
52         oop_source_sys *oop_sys = private_data;
53
54         if (!oop_sys) {
55                 oop_sys = oop_sys_new();
56                 if (!oop_sys) {
57                         return -1;
58                 }
59
60                 talloc_set_destructor(ev, oop_event_context_destructor);
61         }
62
63         ev->additional_data = oop_sys;
64
65         return 0;
66 }
67
68 static void *oop_event_fd_handler(oop_source *oop, int fd, oop_event oop_type, void *ptr)
69 {
70         struct fd_event *fde = ptr;
71
72         if (fd != fde->fd) return OOP_ERROR;
73
74         switch(oop_type) {
75                 case OOP_READ:
76                         fde->handler(fde->event_ctx, fde, EVENT_FD_READ, fde->private_data);
77                         return OOP_CONTINUE;
78                 case OOP_WRITE:
79                         fde->handler(fde->event_ctx, fde, EVENT_FD_WRITE, fde->private_data);
80                         return OOP_CONTINUE;                    
81                 case OOP_EXCEPTION:
82                         return OOP_ERROR;
83                 case OOP_NUM_EVENTS:
84                         return OOP_ERROR;
85         }
86
87         return OOP_ERROR;
88 }
89
90 /*
91   destroy an fd_event
92 */
93 static int oop_event_fd_destructor(struct fd_event *fde)
94 {
95         struct event_context *ev = fde->event_ctx;
96         oop_source_sys *oop_sys = ev->additional_data;
97         oop_source *oop = oop_sys_source(oop_sys);
98
99         if (fde->flags & EVENT_FD_READ)
100                 oop->cancel_fd(oop, fde->fd, OOP_READ);
101         if (fde->flags & EVENT_FD_WRITE)
102                 oop->cancel_fd(oop, fde->fd, OOP_WRITE);
103
104         return 0;
105 }
106
107 /*
108   add a fd based event
109   return NULL on failure (memory allocation error)
110 */
111 static struct fd_event *oop_event_add_fd(struct event_context *ev, TALLOC_CTX *mem_ctx,
112                                          int fd, uint16_t flags,
113                                          event_fd_handler_t handler,
114                                          void *private_data)
115 {
116         struct fd_event *fde;
117         oop_source_sys *oop_sys = ev->additional_data;
118         oop_source *oop = oop_sys_source(oop_sys);
119         
120         fde = talloc(mem_ctx?mem_ctx:ev, struct fd_event);
121         if (!fde) return NULL;
122
123         fde->event_ctx          = ev;
124         fde->fd                 = fd;
125         fde->flags              = flags;
126         fde->handler            = handler;
127         fde->private_data       = private_data;
128         fde->additional_flags   = 0;
129         fde->additional_data    = NULL;
130
131         if (fde->flags & EVENT_FD_READ)
132                 oop->on_fd(oop, fde->fd, OOP_READ, oop_event_fd_handler, fde);
133         if (fde->flags & EVENT_FD_WRITE)
134                 oop->on_fd(oop, fde->fd, OOP_WRITE, oop_event_fd_handler, fde);
135
136         talloc_set_destructor(fde, oop_event_fd_destructor);
137
138         return fde;
139 }
140
141 /*
142   return the fd event flags
143 */
144 static uint16_t oop_event_get_fd_flags(struct fd_event *fde)
145 {
146         return fde->flags;
147 }
148
149 /*
150   set the fd event flags
151 */
152 static void oop_event_set_fd_flags(struct fd_event *fde, uint16_t flags)
153 {
154         oop_source_sys *oop_sys;
155         oop_source *oop;
156
157         oop_sys = fde->event_ctx->additional_data;
158         oop = oop_sys_source(oop_sys);
159
160         if ((fde->flags & EVENT_FD_READ)&&(!(flags & EVENT_FD_READ)))
161                 oop->cancel_fd(oop, fde->fd, OOP_READ);
162
163         if ((!(fde->flags & EVENT_FD_READ))&&(flags & EVENT_FD_READ))
164                 oop->on_fd(oop, fde->fd, OOP_READ, oop_event_fd_handler, fde);
165
166         if ((fde->flags & EVENT_FD_WRITE)&&(!(flags & EVENT_FD_WRITE)))
167                 oop->cancel_fd(oop, fde->fd, OOP_WRITE);
168
169         if ((!(fde->flags & EVENT_FD_WRITE))&&(flags & EVENT_FD_WRITE))
170                 oop->on_fd(oop, fde->fd, OOP_WRITE, oop_event_fd_handler, fde);
171
172         fde->flags = flags;
173 }
174
175 static int oop_event_timed_destructor(struct timed_event *te);
176
177 static int oop_event_timed_deny_destructor(struct timed_event *te)
178 {
179         return -1;
180 }
181
182 static void *oop_event_timed_handler(oop_source *oop, struct timeval t, void *ptr)
183 {
184         struct timed_event *te = ptr;
185
186         /* deny the handler to free the event */
187         talloc_set_destructor(te, oop_event_timed_deny_destructor);
188         te->handler(te->event_ctx, te, t, te->private_data);
189
190         talloc_set_destructor(te, oop_event_timed_destructor);
191         talloc_free(te);
192
193         return OOP_CONTINUE;
194 }
195
196 /*
197   destroy a timed event
198 */
199 static int oop_event_timed_destructor(struct timed_event *te)
200 {
201         struct event_context *ev = te->event_ctx;
202         oop_source_sys *oop_sys = ev->additional_data;
203         oop_source *oop = oop_sys_source(oop_sys);
204
205         oop->cancel_time(oop, te->next_event, oop_event_timed_handler, te);
206
207         return 0;
208 }
209
210 /*
211   add a timed event
212   return NULL on failure (memory allocation error)
213 */
214 static struct timed_event *oop_event_add_timed(struct event_context *ev, TALLOC_CTX *mem_ctx,
215                                                struct timeval next_event, 
216                                                event_timed_handler_t handler, 
217                                                void *private_data) 
218 {
219         oop_source_sys *oop_sys = ev->additional_data;
220         oop_source *oop = oop_sys_source(oop_sys);
221         struct timed_event *te;
222
223         te = talloc(mem_ctx?mem_ctx:ev, struct timed_event);
224         if (te == NULL) return NULL;
225
226         te->event_ctx           = ev;
227         te->next_event          = next_event;
228         te->handler             = handler;
229         te->private_data        = private_data;
230         te->additional_data     = NULL;
231
232         oop->on_time(oop, te->next_event, oop_event_timed_handler, te);
233
234         talloc_set_destructor(te, oop_event_timed_destructor);
235
236         return te;
237 }
238
239 /*
240   do a single event loop using the events defined in ev 
241 */
242 static int oop_event_loop_once(struct event_context *ev)
243 {
244         void *oop_ret;
245         oop_source_sys *oop_sys = ev->additional_data;
246
247         oop_ret = oop_sys_run_once(oop_sys);
248         if (oop_ret == OOP_CONTINUE) {
249                 return 0;
250         }
251
252         return -1;
253 }
254
255 /*
256   return on failure or (with 0) if all fd events are removed
257 */
258 static int oop_event_loop_wait(struct event_context *ev)
259 {
260         void *oop_ret;
261         oop_source_sys *oop_sys = ev->additional_data;
262
263         oop_ret = oop_sys_run(oop_sys);
264         if (oop_ret == OOP_CONTINUE) {
265                 return 0;
266         }
267
268         return -1;
269 }
270
271 static const struct event_ops event_oop_ops = {
272         .context_init   = oop_event_context_init,
273         .add_fd         = oop_event_add_fd,
274         .get_fd_flags   = oop_event_get_fd_flags,
275         .set_fd_flags   = oop_event_set_fd_flags,
276         .add_timed      = oop_event_add_timed,
277         .loop_once      = oop_event_loop_once,
278         .loop_wait      = oop_event_loop_wait,
279 };
280
281 const struct event_ops *event_liboop_get_ops(void)
282 {
283         return &event_oop_ops;
284 }