lib/events.c

説明を見る。
00001 /*
00002    Unix SMB/CIFS implementation.
00003    Timed event library.
00004    Copyright (C) Andrew Tridgell 1992-1998
00005    Copyright (C) Volker Lendecke 2005
00006 
00007    This program is free software; you can redistribute it and/or modify
00008    it under the terms of the GNU General Public License as published by
00009    the Free Software Foundation; either version 2 of the License, or
00010    (at your option) any later version.
00011 
00012    This program is distributed in the hope that it will be useful,
00013    but WITHOUT ANY WARRANTY; without even the implied warranty of
00014    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00015    GNU General Public License for more details.
00016 
00017    You should have received a copy of the GNU General Public License
00018    along with this program; if not, write to the Free Software
00019    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
00020 */
00021 
00022 #include "includes.h"
00023 
00024 struct timed_event {
00025         struct timed_event *next, *prev;
00026         struct event_context *event_ctx;
00027         struct timeval when;
00028         const char *event_name;
00029         void (*handler)(struct event_context *event_ctx,
00030                         struct timed_event *te,
00031                         const struct timeval *now,
00032                         void *private_data);
00033         void *private_data;
00034 };
00035 
00036 struct fd_event {
00037         struct fd_event *prev, *next;
00038         struct event_context *event_ctx;
00039         int fd;
00040         uint16_t flags; /* see EVENT_FD_* flags */
00041         void (*handler)(struct event_context *event_ctx,
00042                         struct fd_event *event,
00043                         uint16 flags,
00044                         void *private_data);
00045         void *private_data;
00046 };
00047 
00048 #define EVENT_FD_WRITEABLE(fde) \
00049         event_set_fd_flags(fde, event_get_fd_flags(fde) | EVENT_FD_WRITE)
00050 #define EVENT_FD_READABLE(fde) \
00051         event_set_fd_flags(fde, event_get_fd_flags(fde) | EVENT_FD_READ)
00052 
00053 #define EVENT_FD_NOT_WRITEABLE(fde) \
00054         event_set_fd_flags(fde, event_get_fd_flags(fde) & ~EVENT_FD_WRITE)
00055 #define EVENT_FD_NOT_READABLE(fde) \
00056         event_set_fd_flags(fde, event_get_fd_flags(fde) & ~EVENT_FD_READ)
00057 
00058 struct event_context {
00059         struct timed_event *timed_events;
00060         struct fd_event *fd_events;
00061 };
00062 
00063 static int timed_event_destructor(struct timed_event *te)
00064 {
00065         DEBUG(10, ("Destroying timed event %lx \"%s\"\n", (unsigned long)te,
00066                 te->event_name));
00067         DLIST_REMOVE(te->event_ctx->timed_events, te);
00068         return 0;
00069 }
00070 
00071 /****************************************************************************
00072  Add te by time.
00073 ****************************************************************************/
00074 
00075 static void add_event_by_time(struct timed_event *te)
00076 {
00077         struct event_context *ctx = te->event_ctx;
00078         struct timed_event *last_te, *cur_te;
00079 
00080         /* Keep the list ordered by time. We must preserve this. */
00081         last_te = NULL;
00082         for (cur_te = ctx->timed_events; cur_te; cur_te = cur_te->next) {
00083                 /* if the new event comes before the current one break */
00084                 if (!timeval_is_zero(&cur_te->when) &&
00085                                 timeval_compare(&te->when, &cur_te->when) < 0) {
00086                         break;
00087                 }
00088                 last_te = cur_te;
00089         }
00090 
00091         DLIST_ADD_AFTER(ctx->timed_events, te, last_te);
00092 }
00093 
00094 /****************************************************************************
00095  Schedule a function for future calling, cancel with TALLOC_FREE().
00096  It's the responsibility of the handler to call TALLOC_FREE() on the event
00097  handed to it.
00098 ****************************************************************************/
00099 
00100 struct timed_event *event_add_timed(struct event_context *event_ctx,
00101                                 TALLOC_CTX *mem_ctx,
00102                                 struct timeval when,
00103                                 const char *event_name,
00104                                 void (*handler)(struct event_context *event_ctx,
00105                                                 struct timed_event *te,
00106                                                 const struct timeval *now,
00107                                                 void *private_data),
00108                                 void *private_data)
00109 {
00110         struct timed_event *te;
00111 
00112         te = TALLOC_P(mem_ctx, struct timed_event);
00113         if (te == NULL) {
00114                 DEBUG(0, ("talloc failed\n"));
00115                 return NULL;
00116         }
00117 
00118         te->event_ctx = event_ctx;
00119         te->when = when;
00120         te->event_name = event_name;
00121         te->handler = handler;
00122         te->private_data = private_data;
00123 
00124         add_event_by_time(te);
00125 
00126         talloc_set_destructor(te, timed_event_destructor);
00127 
00128         DEBUG(10, ("Added timed event \"%s\": %lx\n", event_name,
00129                         (unsigned long)te));
00130         return te;
00131 }
00132 
00133 static int fd_event_destructor(struct fd_event *fde)
00134 {
00135         struct event_context *event_ctx = fde->event_ctx;
00136 
00137         DLIST_REMOVE(event_ctx->fd_events, fde);
00138         return 0;
00139 }
00140 
00141 struct fd_event *event_add_fd(struct event_context *event_ctx,
00142                               TALLOC_CTX *mem_ctx,
00143                               int fd, uint16_t flags,
00144                               void (*handler)(struct event_context *event_ctx,
00145                                               struct fd_event *event,
00146                                               uint16 flags,
00147                                               void *private_data),
00148                               void *private_data)
00149 {
00150         struct fd_event *fde;
00151 
00152         if (!(fde = TALLOC_P(mem_ctx, struct fd_event))) {
00153                 return NULL;
00154         }
00155 
00156         fde->event_ctx = event_ctx;
00157         fde->fd = fd;
00158         fde->flags = flags;
00159         fde->handler = handler;
00160         fde->private_data = private_data;
00161 
00162         DLIST_ADD(event_ctx->fd_events, fde);
00163 
00164         talloc_set_destructor(fde, fd_event_destructor);
00165         return fde;
00166 }
00167 
00168 void event_fd_set_writeable(struct fd_event *fde)
00169 {
00170         fde->flags |= EVENT_FD_WRITE;
00171 }
00172 
00173 void event_fd_set_not_writeable(struct fd_event *fde)
00174 {
00175         fde->flags &= ~EVENT_FD_WRITE;
00176 }
00177 
00178 void event_fd_set_readable(struct fd_event *fde)
00179 {
00180         fde->flags |= EVENT_FD_READ;
00181 }
00182 
00183 void event_fd_set_not_readable(struct fd_event *fde)
00184 {
00185         fde->flags &= ~EVENT_FD_READ;
00186 }
00187 
00188 void event_add_to_select_args(struct event_context *event_ctx,
00189                               const struct timeval *now,
00190                               fd_set *read_fds, fd_set *write_fds,
00191                               struct timeval *timeout, int *maxfd)
00192 {
00193         struct fd_event *fde;
00194         struct timeval diff;
00195 
00196         for (fde = event_ctx->fd_events; fde; fde = fde->next) {
00197                 if (fde->flags & EVENT_FD_READ) {
00198                         FD_SET(fde->fd, read_fds);
00199                 }
00200                 if (fde->flags & EVENT_FD_WRITE) {
00201                         FD_SET(fde->fd, write_fds);
00202                 }
00203 
00204                 if ((fde->flags & (EVENT_FD_READ|EVENT_FD_WRITE))
00205                     && (fde->fd > *maxfd)) {
00206                         *maxfd = fde->fd;
00207                 }
00208         }
00209 
00210         if (event_ctx->timed_events == NULL) {
00211                 return;
00212         }
00213 
00214         diff = timeval_until(now, &event_ctx->timed_events->when);
00215         *timeout = timeval_min(timeout, &diff);
00216 }
00217 
00218 BOOL run_events(struct event_context *event_ctx,
00219                 int selrtn, fd_set *read_fds, fd_set *write_fds)
00220 {
00221         BOOL fired = False;
00222         struct fd_event *fde, *next;
00223 
00224         /* Run all events that are pending, not just one (as we
00225            did previously. */
00226 
00227         while (event_ctx->timed_events) {
00228                 struct timeval now;
00229                 GetTimeOfDay(&now);
00230 
00231                 if (timeval_compare(
00232                             &now, &event_ctx->timed_events->when) < 0) {
00233                         /* Nothing to do yet */
00234                         DEBUG(11, ("run_events: Nothing to do\n"));
00235                         break;
00236                 }
00237 
00238                 DEBUG(10, ("Running event \"%s\" %lx\n",
00239                            event_ctx->timed_events->event_name,
00240                            (unsigned long)event_ctx->timed_events));
00241 
00242                 event_ctx->timed_events->handler(
00243                         event_ctx,
00244                         event_ctx->timed_events, &now,
00245                         event_ctx->timed_events->private_data);
00246 
00247                 fired = True;
00248         }
00249 
00250         if (fired) {
00251                 /*
00252                  * We might have changed the socket status during the timed
00253                  * events, return to run select again.
00254                  */
00255                 return True;
00256         }
00257 
00258         if (selrtn == 0) {
00259                 /*
00260                  * No fd ready
00261                  */
00262                 return fired;
00263         }
00264 
00265         for (fde = event_ctx->fd_events; fde; fde = next) {
00266                 uint16 flags = 0;
00267 
00268                 next = fde->next;
00269                 if (FD_ISSET(fde->fd, read_fds)) flags |= EVENT_FD_READ;
00270                 if (FD_ISSET(fde->fd, write_fds)) flags |= EVENT_FD_WRITE;
00271 
00272                 if (flags) {
00273                         fde->handler(event_ctx, fde, flags, fde->private_data);
00274                         fired = True;
00275                 }
00276         }
00277 
00278         return fired;
00279 }
00280 
00281 
00282 struct timeval *get_timed_events_timeout(struct event_context *event_ctx,
00283                                          struct timeval *to_ret)
00284 {
00285         struct timeval now;
00286 
00287         if (event_ctx->timed_events == NULL) {
00288                 return NULL;
00289         }
00290 
00291         now = timeval_current();
00292         *to_ret = timeval_until(&now, &event_ctx->timed_events->when);
00293 
00294         DEBUG(10, ("timed_events_timeout: %d/%d\n", (int)to_ret->tv_sec,
00295                 (int)to_ret->tv_usec));
00296 
00297         return to_ret;
00298 }
00299 
00300 struct event_context *event_context_init(TALLOC_CTX *mem_ctx)
00301 {
00302         return TALLOC_ZERO_P(NULL, struct event_context);
00303 }
00304 
00305 int set_event_dispatch_time(struct event_context *event_ctx,
00306                             const char *event_name, struct timeval when)
00307 {
00308         struct timed_event *te;
00309 
00310         for (te = event_ctx->timed_events; te; te = te->next) {
00311                 if (strcmp(event_name, te->event_name) == 0) {
00312                         DLIST_REMOVE(event_ctx->timed_events, te);
00313                         te->when = when;
00314                         add_event_by_time(te);
00315                         return 1;
00316                 }
00317         }
00318         return 0;
00319 }
00320 
00321 /* Returns 1 if event was found and cancelled, 0 otherwise. */
00322 
00323 int cancel_named_event(struct event_context *event_ctx,
00324                        const char *event_name)
00325 {
00326         struct timed_event *te;
00327 
00328         for (te = event_ctx->timed_events; te; te = te->next) {
00329                 if (strcmp(event_name, te->event_name) == 0) {
00330                         TALLOC_FREE(te);
00331                         return 1;
00332                 }
00333         }
00334         return 0;
00335 }

Sambaに対してSat Aug 29 21:22:58 2009に生成されました。  doxygen 1.4.7