2 Unix SMB/CIFS implementation.
4 Copyright (C) Andrew Tridgell 1992-1998
5 Copyright (C) Volker Lendecke 2005
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 3 of the License, or
10 (at your option) any later version.
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.
17 You should have received a copy of the GNU General Public License
18 along with this program. If not, see <http://www.gnu.org/licenses/>.
24 struct timed_event
*next
, *prev
;
25 struct event_context
*event_ctx
;
27 const char *event_name
;
28 void (*handler
)(struct event_context
*event_ctx
,
29 struct timed_event
*te
,
30 const struct timeval
*now
,
36 struct fd_event
*prev
, *next
;
37 struct event_context
*event_ctx
;
39 uint16_t flags
; /* see EVENT_FD_* flags */
40 void (*handler
)(struct event_context
*event_ctx
,
41 struct fd_event
*event
,
47 #define EVENT_FD_WRITEABLE(fde) \
48 event_set_fd_flags(fde, event_get_fd_flags(fde) | EVENT_FD_WRITE)
49 #define EVENT_FD_READABLE(fde) \
50 event_set_fd_flags(fde, event_get_fd_flags(fde) | EVENT_FD_READ)
52 #define EVENT_FD_NOT_WRITEABLE(fde) \
53 event_set_fd_flags(fde, event_get_fd_flags(fde) & ~EVENT_FD_WRITE)
54 #define EVENT_FD_NOT_READABLE(fde) \
55 event_set_fd_flags(fde, event_get_fd_flags(fde) & ~EVENT_FD_READ)
57 struct event_context
{
58 struct timed_event
*timed_events
;
59 struct fd_event
*fd_events
;
62 static int timed_event_destructor(struct timed_event
*te
)
64 DEBUG(10, ("Destroying timed event %lx \"%s\"\n", (unsigned long)te
,
66 if (te
->event_ctx
!= NULL
) {
67 DLIST_REMOVE(te
->event_ctx
->timed_events
, te
);
72 /****************************************************************************
74 ****************************************************************************/
76 static void add_event_by_time(struct timed_event
*te
)
78 struct event_context
*ctx
= te
->event_ctx
;
79 struct timed_event
*last_te
, *cur_te
;
81 /* Keep the list ordered by time. We must preserve this. */
83 for (cur_te
= ctx
->timed_events
; cur_te
; cur_te
= cur_te
->next
) {
84 /* if the new event comes before the current one break */
85 if (!timeval_is_zero(&cur_te
->when
) &&
86 timeval_compare(&te
->when
, &cur_te
->when
) < 0) {
92 DLIST_ADD_AFTER(ctx
->timed_events
, te
, last_te
);
95 /****************************************************************************
96 Schedule a function for future calling, cancel with TALLOC_FREE().
97 It's the responsibility of the handler to call TALLOC_FREE() on the event
99 ****************************************************************************/
101 struct timed_event
*event_add_timed(struct event_context
*event_ctx
,
104 const char *event_name
,
105 void (*handler
)(struct event_context
*event_ctx
,
106 struct timed_event
*te
,
107 const struct timeval
*now
,
111 struct timed_event
*te
;
113 te
= TALLOC_P(mem_ctx
, struct timed_event
);
115 DEBUG(0, ("talloc failed\n"));
119 te
->event_ctx
= event_ctx
;
121 te
->event_name
= event_name
;
122 te
->handler
= handler
;
123 te
->private_data
= private_data
;
125 add_event_by_time(te
);
127 talloc_set_destructor(te
, timed_event_destructor
);
129 DEBUG(10, ("Added timed event \"%s\": %lx\n", event_name
,
134 static int fd_event_destructor(struct fd_event
*fde
)
136 if (fde
->event_ctx
!= NULL
) {
137 DLIST_REMOVE(fde
->event_ctx
->fd_events
, fde
);
142 struct fd_event
*event_add_fd(struct event_context
*event_ctx
,
144 int fd
, uint16_t flags
,
145 void (*handler
)(struct event_context
*event_ctx
,
146 struct fd_event
*event
,
151 struct fd_event
*fde
;
153 if (!(fde
= TALLOC_P(mem_ctx
, struct fd_event
))) {
157 fde
->event_ctx
= event_ctx
;
160 fde
->handler
= handler
;
161 fde
->private_data
= private_data
;
163 DLIST_ADD(event_ctx
->fd_events
, fde
);
165 talloc_set_destructor(fde
, fd_event_destructor
);
169 void event_fd_set_writeable(struct fd_event
*fde
)
171 fde
->flags
|= EVENT_FD_WRITE
;
174 void event_fd_set_not_writeable(struct fd_event
*fde
)
176 fde
->flags
&= ~EVENT_FD_WRITE
;
179 void event_fd_set_readable(struct fd_event
*fde
)
181 fde
->flags
|= EVENT_FD_READ
;
184 void event_fd_set_not_readable(struct fd_event
*fde
)
186 fde
->flags
&= ~EVENT_FD_READ
;
190 * Return if there's something in the queue
193 bool event_add_to_select_args(struct event_context
*event_ctx
,
194 const struct timeval
*now
,
195 fd_set
*read_fds
, fd_set
*write_fds
,
196 struct timeval
*timeout
, int *maxfd
)
198 struct fd_event
*fde
;
202 for (fde
= event_ctx
->fd_events
; fde
; fde
= fde
->next
) {
203 if (fde
->flags
& EVENT_FD_READ
) {
204 FD_SET(fde
->fd
, read_fds
);
207 if (fde
->flags
& EVENT_FD_WRITE
) {
208 FD_SET(fde
->fd
, write_fds
);
212 if ((fde
->flags
& (EVENT_FD_READ
|EVENT_FD_WRITE
))
213 && (fde
->fd
> *maxfd
)) {
218 if (event_ctx
->timed_events
== NULL
) {
222 diff
= timeval_until(now
, &event_ctx
->timed_events
->when
);
223 *timeout
= timeval_min(timeout
, &diff
);
228 bool events_pending(struct event_context
*event_ctx
)
230 struct fd_event
*fde
;
232 if (event_ctx
->timed_events
!= NULL
) {
235 for (fde
= event_ctx
->fd_events
; fde
; fde
= fde
->next
) {
236 if (fde
->flags
& (EVENT_FD_READ
|EVENT_FD_WRITE
)) {
243 bool run_events(struct event_context
*event_ctx
,
244 int selrtn
, fd_set
*read_fds
, fd_set
*write_fds
)
247 struct fd_event
*fde
, *next
;
249 /* Run all events that are pending, not just one (as we
252 while (event_ctx
->timed_events
) {
257 &now
, &event_ctx
->timed_events
->when
) < 0) {
258 /* Nothing to do yet */
259 DEBUG(11, ("run_events: Nothing to do\n"));
263 DEBUG(10, ("Running event \"%s\" %lx\n",
264 event_ctx
->timed_events
->event_name
,
265 (unsigned long)event_ctx
->timed_events
));
267 event_ctx
->timed_events
->handler(
269 event_ctx
->timed_events
, &now
,
270 event_ctx
->timed_events
->private_data
);
277 * We might have changed the socket status during the timed
278 * events, return to run select again.
290 for (fde
= event_ctx
->fd_events
; fde
; fde
= next
) {
294 if (FD_ISSET(fde
->fd
, read_fds
)) flags
|= EVENT_FD_READ
;
295 if (FD_ISSET(fde
->fd
, write_fds
)) flags
|= EVENT_FD_WRITE
;
297 if (flags
& fde
->flags
) {
298 fde
->handler(event_ctx
, fde
, flags
, fde
->private_data
);
307 struct timeval
*get_timed_events_timeout(struct event_context
*event_ctx
,
308 struct timeval
*to_ret
)
312 if (event_ctx
->timed_events
== NULL
) {
316 now
= timeval_current();
317 *to_ret
= timeval_until(&now
, &event_ctx
->timed_events
->when
);
319 DEBUG(10, ("timed_events_timeout: %d/%d\n", (int)to_ret
->tv_sec
,
320 (int)to_ret
->tv_usec
));
325 int event_loop_once(struct event_context
*ev
)
327 struct timeval now
, to
;
335 to
.tv_sec
= 9999; /* Max timeout */
340 if (!event_add_to_select_args(ev
, &now
, &r_fds
, &w_fds
, &to
, &maxfd
)) {
344 if (timeval_is_zero(&to
)) {
345 run_events(ev
, 0, NULL
, NULL
);
349 ret
= sys_select(maxfd
+1, &r_fds
, &w_fds
, NULL
, &to
);
351 if (ret
== -1 && errno
!= EINTR
) {
355 run_events(ev
, ret
, &r_fds
, &w_fds
);
359 static int event_context_destructor(struct event_context
*ev
)
361 while (ev
->fd_events
!= NULL
) {
362 ev
->fd_events
->event_ctx
= NULL
;
363 DLIST_REMOVE(ev
->fd_events
, ev
->fd_events
);
365 while (ev
->timed_events
!= NULL
) {
366 ev
->timed_events
->event_ctx
= NULL
;
367 DLIST_REMOVE(ev
->timed_events
, ev
->timed_events
);
372 struct event_context
*event_context_init(TALLOC_CTX
*mem_ctx
)
374 struct event_context
*result
;
376 result
= TALLOC_ZERO_P(mem_ctx
, struct event_context
);
377 if (result
== NULL
) {
381 talloc_set_destructor(result
, event_context_destructor
);
385 int set_event_dispatch_time(struct event_context
*event_ctx
,
386 const char *event_name
, struct timeval when
)
388 struct timed_event
*te
;
390 for (te
= event_ctx
->timed_events
; te
; te
= te
->next
) {
391 if (strcmp(event_name
, te
->event_name
) == 0) {
392 DLIST_REMOVE(event_ctx
->timed_events
, te
);
394 add_event_by_time(te
);
401 /* Returns 1 if event was found and cancelled, 0 otherwise. */
403 int cancel_named_event(struct event_context
*event_ctx
,
404 const char *event_name
)
406 struct timed_event
*te
;
408 for (te
= event_ctx
->timed_events
; te
; te
= te
->next
) {
409 if (strcmp(event_name
, te
->event_name
) == 0) {
417 void dump_event_list(struct event_context
*event_ctx
)
419 struct timed_event
*te
;
421 struct timeval evt
, now
;
427 now
= timeval_current();
429 DEBUG(10,("dump_event_list:\n"));
431 for (te
= event_ctx
->timed_events
; te
; te
= te
->next
) {
433 evt
= timeval_until(&now
, &te
->when
);
435 DEBUGADD(10,("Timed Event \"%s\" %lx handled in %d seconds (at %s)\n",
439 http_timestring(te
->when
.tv_sec
)));
442 for (fe
= event_ctx
->fd_events
; fe
; fe
= fe
->next
) {
444 DEBUGADD(10,("FD Event %d %lx, flags: 0x%04x\n",