lib/events: use mem_context given to event_context_init().
[tprouty/samba.git] / source / lib / events.c
index ab38a85a53ee767bd3f0fe882aef9f5dfa1dac94..8134a7ac1c2a9503f4696a5df21a873077f3903a 100644 (file)
@@ -6,7 +6,7 @@
 
    This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
-   the Free Software Foundation; either version 2 of the License, or
+   the Free Software Foundation; either version 3 of the License, or
    (at your option) any later version.
 
    This program is distributed in the hope that it will be useful,
@@ -15,8 +15,7 @@
    GNU General Public License for more details.
 
    You should have received a copy of the GNU General Public License
-   along with this program; if not, write to the Free Software
-   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */
 
 #include "includes.h"
@@ -74,11 +73,12 @@ static int timed_event_destructor(struct timed_event *te)
 
 static void add_event_by_time(struct timed_event *te)
 {
+       struct event_context *ctx = te->event_ctx;
        struct timed_event *last_te, *cur_te;
 
        /* Keep the list ordered by time. We must preserve this. */
        last_te = NULL;
-       for (cur_te = timed_events; cur_te; cur_te = cur_te->next) {
+       for (cur_te = ctx->timed_events; cur_te; cur_te = cur_te->next) {
                /* if the new event comes before the current one break */
                if (!timeval_is_zero(&cur_te->when) &&
                                timeval_compare(&te->when, &cur_te->when) < 0) {
@@ -87,7 +87,7 @@ static void add_event_by_time(struct timed_event *te)
                last_te = cur_te;
        }
 
-       DLIST_ADD_AFTER(timed_events, te, last_te);
+       DLIST_ADD_AFTER(ctx->timed_events, te, last_te);
 }
 
 /****************************************************************************
@@ -184,20 +184,27 @@ void event_fd_set_not_readable(struct fd_event *fde)
        fde->flags &= ~EVENT_FD_READ;
 }
 
-void event_add_to_select_args(struct event_context *event_ctx,
+/*
+ * Return if there's something in the queue
+ */
+
+bool event_add_to_select_args(struct event_context *event_ctx,
                              const struct timeval *now,
                              fd_set *read_fds, fd_set *write_fds,
                              struct timeval *timeout, int *maxfd)
 {
        struct fd_event *fde;
        struct timeval diff;
+       bool ret = False;
 
        for (fde = event_ctx->fd_events; fde; fde = fde->next) {
                if (fde->flags & EVENT_FD_READ) {
                        FD_SET(fde->fd, read_fds);
+                       ret = True;
                }
                if (fde->flags & EVENT_FD_WRITE) {
                        FD_SET(fde->fd, write_fds);
+                       ret = True;
                }
 
                if ((fde->flags & (EVENT_FD_READ|EVENT_FD_WRITE))
@@ -207,17 +214,34 @@ void event_add_to_select_args(struct event_context *event_ctx,
        }
 
        if (event_ctx->timed_events == NULL) {
-               return;
+               return ret;
        }
 
        diff = timeval_until(now, &event_ctx->timed_events->when);
        *timeout = timeval_min(timeout, &diff);
+
+       return True;
+}
+
+bool events_pending(struct event_context *event_ctx)
+{
+       struct fd_event *fde;
+
+       if (event_ctx->timed_events != NULL) {
+               return True;
+       }
+       for (fde = event_ctx->fd_events; fde; fde = fde->next) {
+               if (fde->flags & (EVENT_FD_READ|EVENT_FD_WRITE)) {
+                       return True;
+               }
+       }
+       return False;
 }
 
-BOOL run_events(struct event_context *event_ctx,
+bool run_events(struct event_context *event_ctx,
                int selrtn, fd_set *read_fds, fd_set *write_fds)
 {
-       BOOL fired = False;
+       bool fired = False;
        struct fd_event *fde, *next;
 
        /* Run all events that are pending, not just one (as we
@@ -268,7 +292,7 @@ BOOL run_events(struct event_context *event_ctx,
                if (FD_ISSET(fde->fd, read_fds)) flags |= EVENT_FD_READ;
                if (FD_ISSET(fde->fd, write_fds)) flags |= EVENT_FD_WRITE;
 
-               if (flags) {
+               if (flags & fde->flags) {
                        fde->handler(event_ctx, fde, flags, fde->private_data);
                        fired = True;
                }
@@ -296,9 +320,43 @@ struct timeval *get_timed_events_timeout(struct event_context *event_ctx,
        return to_ret;
 }
 
+int event_loop_once(struct event_context *ev)
+{
+       struct timeval now, to;
+       fd_set r_fds, w_fds;
+       int maxfd = 0;
+       int ret;
+
+       FD_ZERO(&r_fds);
+       FD_ZERO(&w_fds);
+
+       to.tv_sec = 9999;       /* Max timeout */
+       to.tv_usec = 0;
+
+       GetTimeOfDay(&now);
+
+       if (!event_add_to_select_args(ev, &now, &r_fds, &w_fds, &to, &maxfd)) {
+               return -1;
+       }
+
+       if (timeval_is_zero(&to)) {
+               run_events(ev, 0, NULL, NULL);
+               return 0;
+       }
+
+       ret = sys_select(maxfd, &r_fds, &w_fds, NULL, &to);
+
+       if (ret == -1 && errno != EINTR) {
+               return -1;
+       }
+
+       run_events(ev, ret, &r_fds, &w_fds);
+       return 0;
+}
+
 struct event_context *event_context_init(TALLOC_CTX *mem_ctx)
 {
-       return TALLOC_ZERO_P(NULL, struct event_context);
+       return TALLOC_ZERO_P(mem_ctx, struct event_context);
 }
 
 int set_event_dispatch_time(struct event_context *event_ctx,
@@ -308,7 +366,7 @@ int set_event_dispatch_time(struct event_context *event_ctx,
 
        for (te = event_ctx->timed_events; te; te = te->next) {
                if (strcmp(event_name, te->event_name) == 0) {
-                       DLIST_REMOVE(timed_events, te);
+                       DLIST_REMOVE(event_ctx->timed_events, te);
                        te->when = when;
                        add_event_by_time(te);
                        return 1;
@@ -332,3 +390,37 @@ int cancel_named_event(struct event_context *event_ctx,
        }
        return 0;
 }
+
+void dump_event_list(struct event_context *event_ctx)
+{
+       struct timed_event *te;
+       struct fd_event *fe;
+       struct timeval evt, now;
+
+       if (!event_ctx) {
+               return;
+       }
+
+       now = timeval_current();
+
+       DEBUG(10,("dump_event_list:\n"));
+
+       for (te = event_ctx->timed_events; te; te = te->next) {
+
+               evt = timeval_until(&now, &te->when);
+
+               DEBUGADD(10,("Timed Event \"%s\" %lx handled in %d seconds (at %s)\n",
+                          te->event_name,
+                          (unsigned long)te,
+                          (int)evt.tv_sec,
+                          http_timestring(te->when.tv_sec)));
+       }
+
+       for (fe = event_ctx->fd_events; fe; fe = fe->next) {
+
+               DEBUGADD(10,("FD Event %d %lx, flags: 0x%04x\n",
+                          fe->fd,
+                          (unsigned long)fe,
+                          fe->flags));
+       }
+}