From 111a920fdb92ccef32f89b2f992bdd3051e5ac54 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Thu, 8 Dec 2005 01:13:45 +0000 Subject: r12116: got rid of composite_trigger_done() and composite_trigger_error(), and instead make the normal composite_done() and composite_error() functions automatically trigger a delayed callback if the caller has had no opportunity to setup a async callback this removes one of the common mistakes in writing a composite function (This used to be commit f9413ce792ded682e05134b66d433eeec293e6f1) --- source4/libcli/composite/composite.c | 65 +++++++++++++++++------------------- source4/libcli/composite/composite.h | 2 ++ source4/libcli/ldap/ldap_client.c | 2 +- source4/libcli/resolve/resolve.c | 2 +- source4/libcli/smb2/connect.c | 2 +- source4/libcli/smb2/session.c | 2 +- 6 files changed, 37 insertions(+), 38 deletions(-) (limited to 'source4/libcli') diff --git a/source4/libcli/composite/composite.c b/source4/libcli/composite/composite.c index 3842ddfe9f..c9cc20e923 100644 --- a/source4/libcli/composite/composite.c +++ b/source4/libcli/composite/composite.c @@ -35,6 +35,8 @@ NTSTATUS composite_wait(struct composite_context *c) { if (c == NULL) return NT_STATUS_NO_MEMORY; + c->used_wait = True; + while (c->state < COMPOSITE_STATE_DONE) { if (event_loop_once(c->event_ctx) != 0) { return NT_STATUS_UNSUCCESSFUL; @@ -45,44 +47,10 @@ NTSTATUS composite_wait(struct composite_context *c) } -/* - callback from composite_trigger_done() and composite_trigger_error() -*/ -static void composite_trigger(struct event_context *ev, struct timed_event *te, - struct timeval t, void *ptr) -{ - struct composite_context *c = talloc_get_type(ptr, struct composite_context); - if (c->async.fn) { - c->async.fn(c); - } -} - - -/* - trigger an immediate 'done' event on a composite context - this is used when the composite code works out that the call - can be completed without waiting for any external event -*/ -void composite_trigger_done(struct composite_context *c) -{ - c->state = COMPOSITE_STATE_DONE; - /* a zero timeout means immediate */ - event_add_timed(c->event_ctx, c, timeval_zero(), composite_trigger, c); -} - -void composite_trigger_error(struct composite_context *c) -{ - c->state = COMPOSITE_STATE_ERROR; - /* a zero timeout means immediate */ - event_add_timed(c->event_ctx, c, timeval_zero(), composite_trigger, c); -} - - /* * Some composite helpers that are handy if you write larger composite * functions. */ - BOOL composite_is_ok(struct composite_context *ctx) { if (NT_STATUS_IS_OK(ctx->status)) { @@ -95,8 +63,34 @@ BOOL composite_is_ok(struct composite_context *ctx) return False; } +/* + callback from composite_done() and composite_error() + + this is used to allow for a composite function to complete without + going through any state transitions. When that happens the caller + has had no opportunity to fill in the async callback fields + (ctx->async.fn and ctx->async.private) which means the usual way of + dealing with composite functions doesn't work. To cope with this, + we trigger a timer event that will happen then the event loop is + re-entered. This gives the caller a chance to setup the callback, + and allows the caller to ignore the fact that the composite + function completed early +*/ +static void composite_trigger(struct event_context *ev, struct timed_event *te, + struct timeval t, void *ptr) +{ + struct composite_context *c = talloc_get_type(ptr, struct composite_context); + if (c->async.fn) { + c->async.fn(c); + } +} + + void composite_error(struct composite_context *ctx, NTSTATUS status) { + if (!ctx->used_wait && !ctx->async.fn) { + event_add_timed(ctx->event_ctx, ctx, timeval_zero(), composite_trigger, ctx); + } ctx->status = status; SMB_ASSERT(!composite_is_ok(ctx)); } @@ -112,6 +106,9 @@ BOOL composite_nomem(const void *p, struct composite_context *ctx) void composite_done(struct composite_context *ctx) { + if (!ctx->used_wait && !ctx->async.fn) { + event_add_timed(ctx->event_ctx, ctx, timeval_zero(), composite_trigger, ctx); + } ctx->state = COMPOSITE_STATE_DONE; if (ctx->async.fn != NULL) { ctx->async.fn(ctx); diff --git a/source4/libcli/composite/composite.h b/source4/libcli/composite/composite.h index 1e6e9f5dc8..26490f1c4a 100644 --- a/source4/libcli/composite/composite.h +++ b/source4/libcli/composite/composite.h @@ -57,4 +57,6 @@ struct composite_context { void (*fn)(struct composite_context *); void *private_data; } async; + + BOOL used_wait; }; diff --git a/source4/libcli/ldap/ldap_client.c b/source4/libcli/ldap/ldap_client.c index a5f647939f..0a787bbf57 100644 --- a/source4/libcli/ldap/ldap_client.c +++ b/source4/libcli/ldap/ldap_client.c @@ -341,7 +341,7 @@ struct composite_context *ldap_connect_send(struct ldap_connection *conn, state->ctx->status = ldap_parse_basic_url(conn, url, &conn->host, &conn->port, &conn->ldaps); if (!NT_STATUS_IS_OK(state->ctx->status)) { - composite_trigger_error(state->ctx); + composite_error(state->ctx, state->ctx->status); return result; } diff --git a/source4/libcli/resolve/resolve.c b/source4/libcli/resolve/resolve.c index db5aefeaeb..bbed931eed 100644 --- a/source4/libcli/resolve/resolve.c +++ b/source4/libcli/resolve/resolve.c @@ -153,7 +153,7 @@ struct composite_context *resolve_name_send(struct nbt_name *name, struct event_ struct ipv4_addr ip = interpret_addr2(state->name.name); state->reply_addr = talloc_strdup(state, sys_inet_ntoa(ip)); if (!state->reply_addr) goto failed; - composite_trigger_done(c); + composite_done(c); return c; } diff --git a/source4/libcli/smb2/connect.c b/source4/libcli/smb2/connect.c index 7ed3f97bf3..d15f370feb 100644 --- a/source4/libcli/smb2/connect.c +++ b/source4/libcli/smb2/connect.c @@ -201,7 +201,7 @@ struct composite_context *smb2_connect_send(TALLOC_CTX *mem_ctx, return c; failed: - composite_trigger_error(c); + composite_error(c, c->status); return c; } diff --git a/source4/libcli/smb2/session.c b/source4/libcli/smb2/session.c index 07970747c4..208e2a94de 100644 --- a/source4/libcli/smb2/session.c +++ b/source4/libcli/smb2/session.c @@ -253,7 +253,7 @@ struct composite_context *smb2_session_setup_spnego_send(struct smb2_session *se return c; failed: - composite_trigger_error(c); + composite_error(c, c->status); return c; } -- cgit