summaryrefslogtreecommitdiff
path: root/source4/lib
diff options
context:
space:
mode:
authorAndrew Tridgell <tridge@samba.org>2005-02-03 02:35:52 +0000
committerGerald (Jerry) Carter <jerry@samba.org>2007-10-10 13:09:29 -0500
commit66170ef8b36b499aa5b44ef10c1bd362a50f2636 (patch)
tree5bfb3d759ad397a6a42588b97802e237781c35e8 /source4/lib
parent1774b36c1464e1f04f982b83577e62fa31cbeef9 (diff)
downloadsamba-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.mk10
-rw-r--r--source4/lib/events.c185
-rw-r--r--source4/lib/messaging/messaging.c76
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);