[SSSD] [PATCH] Add callback when the ID provider switches from offline to online

Sumit Bose sbose at redhat.com
Tue May 4 17:27:40 UTC 2010


On Mon, May 03, 2010 at 03:41:18PM -0400, Stephen Gallagher wrote:
> On 04/29/2010 07:41 AM, Stephen Gallagher wrote:
> >On 04/29/2010 05:52 AM, Sumit Bose wrote:
> >>>+
> >>>+static int online_cb_destructor(TALLOC_CTX *ptr);
> >>>+int be_add_online_cb(TALLOC_CTX *mem_ctx,
> >>>+ struct be_ctx *ctx,
> >>>+ be_conn_online_callback_t cb,
> >>>+ void *pvt,
> >>>+ struct be_conn_online_cb **online_cb)
> >>>+{
> >>>+ struct be_conn_online_cb *on_cb;
> >>>+
> >>>+ if (!ctx || !cb) {
> >>>+ return EINVAL;
> >>>+ }
> >>>+
> >>>+ on_cb = talloc(mem_ctx, struct be_conn_online_cb);
> >>>+ if (!online_cb) {
> >>if (!on_cb) ??
> >>
> >>bye,
> >>Sumit
> >Thanks for catching that. When I added the **online_cb return, I changed
> >the name of the internal struct to be on_cb, but I missed that use of
> >it. That would have been a bug, since it would have returned on error if
> >called without expecting a returned struct.
> >
> >New patch attached.
> >
> 
> Rebased to current sssd-1-2.

ACK

bye,
Sumit

> 
> -- 
> Stephen Gallagher
> RHCE 804006346421761
> 
> Delivering value year after year.
> Red Hat ranks #1 in value among software vendors.
> http://www.redhat.com/promo/vendor/

> From 5aaf82cdf4838105dab6e7601ead134a5309f89f Mon Sep 17 00:00:00 2001
> From: Stephen Gallagher <sgallagh at redhat.com>
> Date: Tue, 27 Apr 2010 14:57:37 -0400
> Subject: [PATCH 1/3] Add callback when the ID provider switches from offline to online
> 
> Allow backends to set a callback in the be_ctx that should be
> invoked when the ID provider goes online.
> 
> This can be used to perform regular maintenance tasks that are
> valid only when going online.
> ---
>  src/providers/data_provider_be.c           |  138 ++++++++++++++++++++++++++++
>  src/providers/dp_backend.h                 |   17 ++++
>  src/providers/ldap/sdap_async_connection.c |    9 ++
>  src/providers/proxy.c                      |   10 ++
>  4 files changed, 174 insertions(+), 0 deletions(-)
> 
> diff --git a/src/providers/data_provider_be.c b/src/providers/data_provider_be.c
> index 22f18024858a73da8788ad93dcc863a1c3222069..320821ae41daf1f7a64ba69aac0e8f0d91c3e5f1 100644
> --- a/src/providers/data_provider_be.c
> +++ b/src/providers/data_provider_be.c
> @@ -166,8 +166,146 @@ void be_mark_offline(struct be_ctx *ctx)
>  
>      ctx->offstat.went_offline = time(NULL);
>      ctx->offstat.offline = true;
> +    ctx->run_online_cb = true;
>  }
>  
> +
> +struct be_conn_online_cb {
> +    struct be_conn_online_cb *prev;
> +    struct be_conn_online_cb *next;
> +
> +    be_conn_online_callback_t cb;
> +    void *pvt;
> +
> +    struct be_ctx *be;
> +};
> +
> +static int online_cb_destructor(TALLOC_CTX *ptr);
> +int be_add_online_cb(TALLOC_CTX *mem_ctx,
> +                     struct be_ctx *ctx,
> +                     be_conn_online_callback_t cb,
> +                     void *pvt,
> +                     struct be_conn_online_cb **online_cb)
> +{
> +    struct be_conn_online_cb *on_cb;
> +
> +    if (!ctx || !cb) {
> +        return EINVAL;
> +    }
> +
> +    on_cb = talloc(mem_ctx, struct be_conn_online_cb);
> +    if (!on_cb) {
> +        return ENOMEM;
> +    }
> +
> +    on_cb->cb = cb;
> +    on_cb->pvt = pvt;
> +    on_cb->be = ctx;
> +
> +    DLIST_ADD(ctx->online_cb_list, on_cb);
> +
> +    talloc_set_destructor((TALLOC_CTX *)on_cb, online_cb_destructor);
> +
> +    /* Make sure we run the callback for the first
> +     * connection after startup.
> +     */
> +    ctx->run_online_cb = true;
> +
> +    if (online_cb) {
> +        *online_cb = on_cb;
> +    }
> +
> +    return EOK;
> +}
> +
> +static int online_cb_destructor(TALLOC_CTX *ptr)
> +{
> +    struct be_conn_online_cb *cb =
> +            talloc_get_type(ptr, struct be_conn_online_cb);
> +    DLIST_REMOVE(cb->be->online_cb_list, cb);
> +    return 0;
> +}
> +
> +
> +struct be_online_cb_ctx {
> +    struct be_ctx *be;
> +    struct be_conn_online_cb *callback;
> +};
> +
> +static void be_run_online_cb_step(struct tevent_context *ev,
> +                                  struct tevent_timer *te,
> +                                  struct timeval current_time,
> +                                  void *pvt);
> +void be_run_online_cb(struct be_ctx *be) {
> +    struct timeval soon;
> +    struct tevent_timer *te;
> +    struct be_online_cb_ctx *cb_ctx;
> +
> +    if (be->run_online_cb && be->online_cb_list) {
> +        /* Reset the flag. We only want to run these
> +         * callbacks when transitioning to online
> +         */
> +        be->run_online_cb = false;
> +
> +        DEBUG(3, ("Going online. Running callbacks.\n"));
> +
> +        cb_ctx = talloc(be, struct be_online_cb_ctx);
> +        if (!cb_ctx) {
> +            DEBUG(0, ("Out of memory. Could not invoke callbacks\n"));
> +            return;
> +        }
> +        cb_ctx->be = be;
> +        cb_ctx->callback = be->online_cb_list;
> +
> +        /* Delay 30ms so we don't block any other events */
> +        soon = tevent_timeval_current_ofs(0, 30000);
> +        te = tevent_add_timer(be->ev, cb_ctx, soon,
> +                              be_run_online_cb_step,
> +                              cb_ctx);
> +        if (!te) {
> +            DEBUG(0, ("Out of memory. Could not invoke callbacks\n"));
> +            talloc_free(cb_ctx);
> +        }
> +    }
> +}
> +
> +static void be_run_online_cb_step(struct tevent_context *ev,
> +                                  struct tevent_timer *te,
> +                                  struct timeval current_time,
> +                                  void *pvt)
> +{
> +    struct be_online_cb_ctx *cb_ctx =
> +            talloc_get_type(pvt, struct be_online_cb_ctx);
> +    struct tevent_timer *tev;
> +    struct timeval soon;
> +
> +    /* Call the callback */
> +    cb_ctx->callback->cb(cb_ctx->callback->pvt);
> +
> +    if (cb_ctx->callback->next) {
> +        cb_ctx->callback = cb_ctx->callback->next;
> +
> +        /* Delay 30ms so we don't block any other events */
> +        soon = tevent_timeval_current_ofs(0, 30000);
> +        tev = tevent_add_timer(cb_ctx->be->ev, cb_ctx, soon,
> +                               be_run_online_cb_step,
> +                               cb_ctx);
> +        if (!te) {
> +            DEBUG(0, ("Out of memory. Could not invoke callbacks\n"));
> +            goto final;
> +        }
> +        return;
> +    }
> +
> +final:
> +    /* Steal the timer event onto the be_ctx so it doesn't
> +     * get freed with the cb_ctx
> +     */
> +    talloc_steal(cb_ctx->be, te);
> +    talloc_free(cb_ctx);
> +}
> +
> +
>  static int be_check_online(DBusMessage *message, struct sbus_connection *conn)
>  {
>      struct be_client *becli;
> diff --git a/src/providers/dp_backend.h b/src/providers/dp_backend.h
> index f1069d0db313ca278e6125908668e2aad2c25b76..330f0f03b7b107cfbe272c92afed83e687f32d70 100644
> --- a/src/providers/dp_backend.h
> +++ b/src/providers/dp_backend.h
> @@ -35,6 +35,8 @@ typedef void (*be_shutdown_fn)(void *);
>  typedef void (*be_req_fn_t)(struct be_req *);
>  typedef void (*be_async_callback_t)(struct be_req *, int, int, const char *);
>  
> +typedef void (*be_conn_online_callback_t)(void *);
> +
>  enum bet_type {
>      BET_NULL = 0,
>      BET_ID,
> @@ -76,6 +78,8 @@ struct be_client {
>  
>  struct be_failover_ctx;
>  
> +struct be_conn_online_cb;
> +
>  struct be_ctx {
>      struct tevent_context *ev;
>      struct confdb_ctx *cdb;
> @@ -85,6 +89,12 @@ struct be_ctx {
>      const char *conf_path;
>      struct be_failover_ctx *be_fo;
>  
> +    /* Functions to be invoked when the
> +     * backend goes online
> +     */
> +    struct be_conn_online_cb *online_cb_list;
> +    bool run_online_cb;
> +
>      struct be_offline_status offstat;
>  
>      struct sbus_connection *mon_conn;
> @@ -122,6 +132,13 @@ struct be_acct_req {
>  bool be_is_offline(struct be_ctx *ctx);
>  void be_mark_offline(struct be_ctx *ctx);
>  
> +int be_add_online_cb(TALLOC_CTX *mem_ctx,
> +                     struct be_ctx *ctx,
> +                     be_conn_online_callback_t cb,
> +                     void *pvt,
> +                     struct be_conn_online_cb **online_cb);
> +void be_run_online_cb(struct be_ctx *be);
> +
>  /* from data_provider_fo.c */
>  typedef void (be_svc_callback_fn_t)(void *, struct fo_server *);
>  
> diff --git a/src/providers/ldap/sdap_async_connection.c b/src/providers/ldap/sdap_async_connection.c
> index 9871dc2109d2c0eac00f95401ba5dae2d16486ce..214c58efb63d71580f64dce95c8a9a1bec302581 100644
> --- a/src/providers/ldap/sdap_async_connection.c
> +++ b/src/providers/ldap/sdap_async_connection.c
> @@ -813,6 +813,7 @@ struct sdap_cli_connect_state {
>      struct tevent_context *ev;
>      struct sdap_options *opts;
>      struct sdap_service *service;
> +    struct be_ctx *be;
>  
>      bool use_rootdse;
>      struct sysdb_attrs *rootdse;
> @@ -848,6 +849,7 @@ struct tevent_req *sdap_cli_connect_send(TALLOC_CTX *memctx,
>      state->opts = opts;
>      state->service = service;
>      state->srv = NULL;
> +    state->be = be;
>  
>      if (rootdse) {
>          state->use_rootdse = true;
> @@ -1077,6 +1079,8 @@ static void sdap_cli_auth_done(struct tevent_req *subreq)
>  {
>      struct tevent_req *req = tevent_req_callback_data(subreq,
>                                                        struct tevent_req);
> +    struct sdap_cli_connect_state *state = tevent_req_data(req,
> +                                             struct sdap_cli_connect_state);
>      enum sdap_result result;
>      int ret;
>  
> @@ -1091,6 +1095,11 @@ static void sdap_cli_auth_done(struct tevent_req *subreq)
>          return;
>      }
>  
> +    /* Reconnection succeeded
> +     * Run any post-connection routines
> +     */
> +    be_run_online_cb(state->be);
> +
>      tevent_req_done(req);
>  }
>  
> diff --git a/src/providers/proxy.c b/src/providers/proxy.c
> index 09a2555c5c509ee837019c69ad2c2ddd9f9d01d5..d3ec7ef35361300fb6e7d708e1f91d9b230eeb4a 100644
> --- a/src/providers/proxy.c
> +++ b/src/providers/proxy.c
> @@ -296,6 +296,16 @@ static void proxy_pam_handler_cache_done(struct tevent_req *subreq)
>  static void proxy_reply(struct be_req *req, int dp_err,
>                          int error, const char *errstr)
>  {
> +    if (!req->be_ctx->offstat.offline) {
> +        /* This action took place online.
> +         * Fire any online callbacks if necessary.
> +         * Note: we're checking the offline value directly,
> +         * because if the activity took a long time to
> +         * complete, calling be_is_offline() might report false
> +         * incorrectly.
> +         */
> +        be_run_online_cb(req->be_ctx);
> +    }
>      return req->fn(req, dp_err, error, errstr);
>  }
>  
> -- 
> 1.7.0.1
> 

> _______________________________________________
> sssd-devel mailing list
> sssd-devel at lists.fedorahosted.org
> https://fedorahosted.org/mailman/listinfo/sssd-devel




More information about the sssd-devel mailing list