diff options
author | Andrew Tridgell <tridge@samba.org> | 2005-02-03 02:35:52 +0000 |
---|---|---|
committer | Gerald (Jerry) Carter <jerry@samba.org> | 2007-10-10 13:09:29 -0500 |
commit | 66170ef8b36b499aa5b44ef10c1bd362a50f2636 (patch) | |
tree | 5bfb3d759ad397a6a42588b97802e237781c35e8 /source4/lib | |
parent | 1774b36c1464e1f04f982b83577e62fa31cbeef9 (diff) | |
download | samba-66170ef8b36b499aa5b44ef10c1bd362a50f2636.tar.gz samba-66170ef8b36b499aa5b44ef10c1bd362a50f2636.tar.bz2 samba-66170ef8b36b499aa5b44ef10c1bd362a50f2636.zip |
r5185: make all the events data structures private to events.c. This will
make it possible to add optimisations to the events code such as
keeping the next timed event in a sorted list, and using epoll for
file descriptor events.
I also removed the loop events code, as it wasn't being used anywhere,
and changed timed events to always be one-shot (as adding a new timed
event in the event handler is so easy to do if needed)
(This used to be commit d7b4b6de51342a65bf46fce772d313f92f8d73d3)
Diffstat (limited to 'source4/lib')
-rw-r--r-- | source4/lib/basic.mk | 10 | ||||
-rw-r--r-- | source4/lib/events.c | 185 | ||||
-rw-r--r-- | source4/lib/messaging/messaging.c | 76 |
3 files changed, 128 insertions, 143 deletions
diff --git a/source4/lib/basic.mk b/source4/lib/basic.mk index af1420c685..dda79f50ad 100644 --- a/source4/lib/basic.mk +++ b/source4/lib/basic.mk @@ -33,6 +33,15 @@ ADD_OBJ_FILES = \ ############################## ############################## +# Start SUBSYSTEM LIBEVENTS +[SUBSYSTEM::LIBEVENTS] +NOPROTO = YES +INIT_OBJ_FILES = lib/events.o +REQUIRED_SUBSYSTEMS = LIBTALLOC +# End SUBSYSTEM LIBEVENTS +############################## + +############################## # Start SUBSYSTEM LIBBASIC [SUBSYSTEM::LIBBASIC] INIT_OBJ_FILES = lib/version.o @@ -62,7 +71,6 @@ ADD_OBJ_FILES = \ lib/pam_errors.o \ intl/lang_tdb.o \ lib/mutex.o \ - lib/events.o \ lib/server_mutex.o \ lib/idtree.o \ lib/unix_privs.o \ diff --git a/source4/lib/events.c b/source4/lib/events.c index ebfa164885..b2e0404e34 100644 --- a/source4/lib/events.c +++ b/source4/lib/events.c @@ -26,7 +26,7 @@ register one of the possible event types and implement that event somewhere else. - There are 4 types of event handling that are handled in this module: + There are 2 types of event handling that are handled in this module: 1) a file descriptor becoming readable or writeable. This is mostly used for network sockets, but can be used for any type of file @@ -41,15 +41,6 @@ like. When they are called the handler can choose to set the time for the next event. If next_event is not set then the event is removed. - 3) an event that happens every time through the select loop. These - sorts of events should be very fast, as they will occur a - lot. Mostly used for things like destroying a talloc context or - checking a signal flag. - - 4) an event triggered by a signal. These can be one shot or - repeated. You can have more than one handler registered for a - single signal if you want to. - To setup a set of events you first need to create a event_context structure using the function event_context_init(); This returns a 'struct event_context' that you use in all subsequent calls. @@ -59,8 +50,7 @@ Finally, you call event_loop_wait() to block waiting for one of the events to occor. In normal operation event_loop_wait() will loop - forever, unless you call event_loop_exit() from inside one of your - handler functions. + forever. */ @@ -70,6 +60,46 @@ #include "dlinklist.h" #include "events.h" + +/* + please read the comments in events.c before modifying +*/ + + +struct event_context { + /* list of filedescriptor events */ + struct fd_event { + struct event_context *event_ctx; + struct fd_event *next, *prev; + int fd; + uint16_t flags; /* see EVENT_FD_* flags */ + event_fd_handler_t handler; + void *private; + } *fd_events; + + /* list of timed events */ + struct timed_event { + struct event_context *event_ctx; + struct timed_event *next, *prev; + struct timeval next_event; + event_timed_handler_t handler; + void *private; + } *timed_events; + + /* the maximum file descriptor number in fd_events */ + int maxfd; + + /* information for exiting from the event loop */ + int exit_code; + + /* this is changed by the destructors for any event type. It + is used to detect event destruction by event handlers, + which means the code that is calling all event handles + needs to assume that the linked list is no longer valid + */ + uint32_t destruction_count; +}; + /* create a event_context structure. This must be the first events call, and all subsequent calls pass this event_context as the first @@ -82,21 +112,10 @@ struct event_context *event_context_init(TALLOC_CTX *mem_ctx) ev = talloc_zero(mem_ctx, struct event_context); if (!ev) return NULL; - ev->events = talloc_new(ev); - return ev; } /* - destroy an events context, also destroying any remaining events -*/ -void event_context_destroy(struct event_context *ev) -{ - talloc_free(ev); -} - - -/* recalculate the maxfd */ static void calc_maxfd(struct event_context *ev) @@ -131,17 +150,25 @@ static int event_fd_destructor(void *ptr) add a fd based event return NULL on failure (memory allocation error) */ -struct fd_event *event_add_fd(struct event_context *ev, struct fd_event *e0, - TALLOC_CTX *mem_ctx) +struct fd_event *event_add_fd(struct event_context *ev, TALLOC_CTX *mem_ctx, + int fd, uint16_t flags, event_fd_handler_t handler, + void *private) { - struct fd_event *e = talloc(ev->events, struct fd_event); + struct fd_event *e = talloc(ev, struct fd_event); if (!e) return NULL; - *e = *e0; - DLIST_ADD(ev->fd_events, e); + e->event_ctx = ev; + e->fd = fd; + e->flags = flags; + e->handler = handler; + e->private = private; + + DLIST_ADD(ev->fd_events, e); + if (e->fd > ev->maxfd) { ev->maxfd = e->fd; } + talloc_set_destructor(e, event_fd_destructor); if (mem_ctx) { talloc_steal(mem_ctx, e); @@ -150,54 +177,52 @@ struct fd_event *event_add_fd(struct event_context *ev, struct fd_event *e0, } -static int event_timed_destructor(void *ptr) +/* + return the fd event flags +*/ +uint16_t event_fd_flags(struct fd_event *fde) { - struct timed_event *te = talloc_get_type(ptr, struct timed_event); - DLIST_REMOVE(te->event_ctx->timed_events, te); - te->event_ctx->destruction_count++; - return 0; + return fde->flags; } /* - add a timed event - return NULL on failure (memory allocation error) + set the fd event flags */ -struct timed_event *event_add_timed(struct event_context *ev, struct timed_event *e0, - TALLOC_CTX *mem_ctx) +void event_fd_setflags(struct fd_event *fde, uint16_t flags) { - struct timed_event *e = talloc(ev->events, struct timed_event); - if (!e) return NULL; - *e = *e0; - e->event_ctx = ev; - DLIST_ADD(ev->timed_events, e); - talloc_set_destructor(e, event_timed_destructor); - if (mem_ctx) { - talloc_steal(mem_ctx, e); - } - return e; + fde->flags = flags; } -static int event_loop_destructor(void *ptr) +/* + destroy a timed event +*/ +static int event_timed_destructor(void *ptr) { - struct loop_event *le = talloc_get_type(ptr, struct loop_event); - DLIST_REMOVE(le->event_ctx->loop_events, le); - le->event_ctx->destruction_count++; + struct timed_event *te = talloc_get_type(ptr, struct timed_event); + DLIST_REMOVE(te->event_ctx->timed_events, te); + te->event_ctx->destruction_count++; return 0; } /* - add a loop event + add a timed event return NULL on failure (memory allocation error) */ -struct loop_event *event_add_loop(struct event_context *ev, struct loop_event *e0, - TALLOC_CTX *mem_ctx) +struct timed_event *event_add_timed(struct event_context *ev, TALLOC_CTX *mem_ctx, + struct timeval next_event, + event_timed_handler_t handler, + void *private) { - struct loop_event *e = talloc(ev->events, struct loop_event); + struct timed_event *e = talloc(ev, struct timed_event); if (!e) return NULL; - *e = *e0; - e->event_ctx = ev; - DLIST_ADD(ev->loop_events, e); - talloc_set_destructor(e, event_loop_destructor); + + e->event_ctx = ev; + e->next_event = next_event; + e->handler = handler; + e->private = private; + + DLIST_ADD(ev->timed_events, e); + talloc_set_destructor(e, event_timed_destructor); if (mem_ctx) { talloc_steal(mem_ctx, e); } @@ -205,38 +230,17 @@ struct loop_event *event_add_loop(struct event_context *ev, struct loop_event *e } /* - tell the event loop to exit with the specified code -*/ -void event_loop_exit(struct event_context *ev, int code) -{ - ev->exit.exit_now = True; - ev->exit.code = code; -} - -/* do a single event loop using the events defined in ev this function */ int event_loop_once(struct event_context *ev) { fd_set r_fds, w_fds; struct fd_event *fe; - struct loop_event *le; struct timed_event *te, *te_next; int selrtn; - struct timeval tval, t, *tvalp=NULL; + struct timeval tval, t, *tvalp; uint32_t destruction_count = ev->destruction_count; - t = timeval_current(); - - /* the loop events are called on each loop. Be careful to allow the - event to remove itself */ - for (le=ev->loop_events;le;) { - struct loop_event *next = le->next; - le->handler(ev, le, t); - if (destruction_count != ev->destruction_count) break; - le = next; - } - FD_ZERO(&r_fds); FD_ZERO(&w_fds); @@ -252,9 +256,8 @@ int event_loop_once(struct event_context *ev) fe = next; } - /* start with a reasonable max timeout */ - tval.tv_sec = 0; - tval.tv_usec = 0; + tvalp = NULL; + t = timeval_current(); /* work out the right timeout for all timed events */ for (te=ev->timed_events;te;te=te_next) { @@ -301,7 +304,7 @@ int event_loop_once(struct event_context *ev) the event, so this must be a bug. This is a fatal error. */ DEBUG(0,("EBADF on event_loop_once - exiting\n")); - ev->exit.code = EBADF; + ev->exit_code = EBADF; return -1; } @@ -314,7 +317,7 @@ int event_loop_once(struct event_context *ev) if (FD_ISSET(fe->fd, &r_fds)) flags |= EVENT_FD_READ; if (FD_ISSET(fe->fd, &w_fds)) flags |= EVENT_FD_WRITE; if (flags) { - fe->handler(ev, fe, t, flags); + fe->handler(ev, fe, t, flags, fe->private); if (destruction_count != ev->destruction_count) { break; } @@ -328,7 +331,7 @@ int event_loop_once(struct event_context *ev) struct timed_event *next = te->next; if (timeval_compare(&te->next_event, &t) >= 0) { te->next_event = timeval_zero(); - te->handler(ev, te, t); + te->handler(ev, te, t, te->private); if (destruction_count != ev->destruction_count) { break; } @@ -348,16 +351,14 @@ int event_loop_once(struct event_context *ev) */ int event_loop_wait(struct event_context *ev) { - ZERO_STRUCT(ev->exit); + ev->exit_code = 0; ev->maxfd = EVENT_INVALID_MAXFD; - ev->exit.exit_now = False; - - while (ev->fd_events && !ev->exit.exit_now) { + while (ev->fd_events && ev->exit_code == 0) { if (event_loop_once(ev) != 0) { break; } } - return ev->exit.code; + return ev->exit_code; } diff --git a/source4/lib/messaging/messaging.c b/source4/lib/messaging/messaging.c index 09d30027b0..53b6f434f0 100644 --- a/source4/lib/messaging/messaging.c +++ b/source4/lib/messaging/messaging.c @@ -122,9 +122,9 @@ static void messaging_dispatch(struct messaging_context *msg, struct messaging_r handle IO for a single message */ static void messaging_recv_handler(struct event_context *ev, struct fd_event *fde, - struct timeval t, uint16_t flags) + struct timeval t, uint16_t flags, void *private) { - struct messaging_rec *rec = fde->private; + struct messaging_rec *rec = talloc_get_type(private, struct messaging_rec); struct messaging_context *msg = rec->msg; NTSTATUS status; @@ -192,12 +192,12 @@ static void messaging_recv_handler(struct event_context *ev, struct fd_event *fd handle a new incoming connection */ static void messaging_listen_handler(struct event_context *ev, struct fd_event *fde, - struct timeval t, uint16_t flags) + struct timeval t, uint16_t flags, void *private) { - struct messaging_context *msg = fde->private; + struct messaging_context *msg = talloc_get_type(private, + struct messaging_context); struct messaging_rec *rec; NTSTATUS status; - struct fd_event fde2; rec = talloc(msg, struct messaging_rec); if (rec == NULL) { @@ -210,17 +210,12 @@ static void messaging_listen_handler(struct event_context *ev, struct fd_event * } talloc_steal(rec, rec->sock); - rec->msg = msg; - rec->ndone = 0; + rec->msg = msg; + rec->ndone = 0; rec->header.length = 0; - rec->path = msg->path; - - fde2.private = rec; - fde2.fd = socket_get_fd(rec->sock); - fde2.flags = EVENT_FD_READ; - fde2.handler = messaging_recv_handler; - - rec->fde = event_add_fd(msg->event.ev, &fde2, rec); + rec->path = msg->path; + rec->fde = event_add_fd(msg->event.ev, rec, socket_get_fd(rec->sock), + EVENT_FD_READ, messaging_recv_handler, rec); } /* @@ -262,9 +257,9 @@ void messaging_deregister(struct messaging_context *msg, uint32_t msg_type, void handle IO for sending a message */ static void messaging_send_handler(struct event_context *ev, struct fd_event *fde, - struct timeval t, uint16_t flags) + struct timeval t, uint16_t flags, void *private) { - struct messaging_rec *rec = fde->private; + struct messaging_rec *rec = talloc_get_type(private, struct messaging_rec); NTSTATUS status; if (rec->ndone < sizeof(rec->header)) { @@ -330,17 +325,18 @@ static NTSTATUS try_connect(struct messaging_rec *rec) when the servers listen queue is full we use this to backoff the message */ static void messaging_backoff_handler(struct event_context *ev, struct timed_event *te, - struct timeval t) + struct timeval t, void *private) { - struct messaging_rec *rec = te->private; + struct messaging_rec *rec = talloc_get_type(private, struct messaging_rec); struct messaging_context *msg = rec->msg; NTSTATUS status; - struct fd_event fde; status = try_connect(rec); if (NT_STATUS_EQUAL(status, STATUS_MORE_ENTRIES)) { /* backoff again */ - te->next_event = timeval_add(&t, 0, MESSAGING_BACKOFF); + event_add_timed(msg->event.ev, rec, + timeval_add(&t, 0, MESSAGING_BACKOFF), + messaging_backoff_handler, rec); return; } @@ -351,14 +347,8 @@ static void messaging_backoff_handler(struct event_context *ev, struct timed_eve return; } - fde.private = rec; - fde.fd = socket_get_fd(rec->sock); - fde.flags = EVENT_FD_WRITE; - fde.handler = messaging_send_handler; - - rec->fde = event_add_fd(msg->event.ev, &fde, rec); - - messaging_send_handler(msg->event.ev, rec->fde, timeval_zero(), EVENT_FD_WRITE); + rec->fde = event_add_fd(msg->event.ev, rec, socket_get_fd(rec->sock), + EVENT_FD_WRITE, messaging_send_handler, rec); } @@ -369,7 +359,6 @@ NTSTATUS messaging_send(struct messaging_context *msg, uint32_t server, uint32_t { struct messaging_rec *rec; NTSTATUS status; - struct fd_event fde; rec = talloc(msg, struct messaging_rec); if (rec == NULL) { @@ -401,11 +390,9 @@ NTSTATUS messaging_send(struct messaging_context *msg, uint32_t server, uint32_t status = try_connect(rec); if (NT_STATUS_EQUAL(status, STATUS_MORE_ENTRIES)) { /* backoff on this message - the servers listen queue is full */ - struct timed_event te; - te.next_event = timeval_current_ofs(0, MESSAGING_BACKOFF); - te.handler = messaging_backoff_handler; - te.private = rec; - event_add_timed(msg->event.ev, &te, rec); + event_add_timed(msg->event.ev, rec, + timeval_current_ofs(0, MESSAGING_BACKOFF), + messaging_backoff_handler, rec); return NT_STATUS_OK; } @@ -414,14 +401,8 @@ NTSTATUS messaging_send(struct messaging_context *msg, uint32_t server, uint32_t return status; } - fde.private = rec; - fde.fd = socket_get_fd(rec->sock); - fde.flags = EVENT_FD_WRITE; - fde.handler = messaging_send_handler; - - rec->fde = event_add_fd(msg->event.ev, &fde, rec); - - messaging_send_handler(msg->event.ev, rec->fde, timeval_zero(), EVENT_FD_WRITE); + rec->fde = event_add_fd(msg->event.ev, rec, socket_get_fd(rec->sock), + EVENT_FD_WRITE, messaging_send_handler, rec); return NT_STATUS_OK; } @@ -458,7 +439,6 @@ struct messaging_context *messaging_init(TALLOC_CTX *mem_ctx, uint32_t server_id { struct messaging_context *msg; NTSTATUS status; - struct fd_event fde; msg = talloc(mem_ctx, struct messaging_context); if (msg == NULL) { @@ -491,13 +471,9 @@ struct messaging_context *messaging_init(TALLOC_CTX *mem_ctx, uint32_t server_id return NULL; } - fde.private = msg; - fde.fd = socket_get_fd(msg->sock); - fde.flags = EVENT_FD_READ; - fde.handler = messaging_listen_handler; - msg->event.ev = talloc_reference(msg, ev); - msg->event.fde = event_add_fd(ev, &fde, msg); + msg->event.fde = event_add_fd(ev, msg, socket_get_fd(msg->sock), + EVENT_FD_READ, messaging_listen_handler, msg); talloc_set_destructor(msg, messaging_destructor); |