From f826cd7518a78bd5a922296dbd4d5cee6c58cf5d Mon Sep 17 00:00:00 2001
From: Stephen Gallagher <sgallagh@redhat.com>
Date: Tue, 27 Apr 2010 14:57:37 -0400
Subject: [PATCH] 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           |   43 ++++++++++++++++++++++++++++
 src/providers/dp_backend.h                 |   21 +++++++++++++
 src/providers/ldap/sdap_async_connection.c |   20 +++++++++++++
 3 files changed, 84 insertions(+), 0 deletions(-)

diff --git a/src/providers/data_provider_be.c b/src/providers/data_provider_be.c
index 69aba6cebf03b9922e5d843763eace3117e7d1fb..ba08f577ead07fe61cc545f5541ebd66efe54beb 100644
--- a/src/providers/data_provider_be.c
+++ b/src/providers/data_provider_be.c
@@ -168,6 +168,49 @@ void be_mark_offline(struct be_ctx *ctx)
     ctx->offstat.offline = true;
 }
 
+int be_add_online_cb(struct be_ctx *ctx,
+                     be_conn_online_callback_t cb,
+                     void *pvt)
+{
+    struct be_conn_online_cb *online_cb;
+
+    if (!ctx || !cb) {
+        return EINVAL;
+    }
+
+    online_cb = talloc(ctx, struct be_conn_online_cb);
+    if(!online_cb) {
+        return ENOMEM;
+    }
+
+    online_cb->cb = cb;
+    online_cb->pvt = pvt;
+
+    DLIST_ADD(ctx->online_cb_list, online_cb);
+    return EOK;
+}
+
+int be_remove_online_cb(struct be_ctx *ctx,
+                        be_conn_online_callback_t cb)
+{
+    int ret;
+    struct be_conn_online_cb *callback;
+
+    DLIST_FOR_EACH(callback, ctx->online_cb_list) {
+        if (callback->cb == cb) {
+            DLIST_REMOVE(ctx->online_cb_list, callback);
+            ret = talloc_free(callback);
+            if (ret == -1) {
+                return EIO;
+            }
+            return EOK;
+        }
+    }
+
+    /* Not found */
+    return ENOENT;
+}
+
 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..516f609515239c2e79b4e7379fbfcbcb89ddfc34 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 int (*be_conn_online_callback_t)(void *);
+
 enum bet_type {
     BET_NULL = 0,
     BET_ID,
@@ -76,6 +78,14 @@ struct be_client {
 
 struct be_failover_ctx;
 
+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 {
     struct tevent_context *ev;
     struct confdb_ctx *cdb;
@@ -85,6 +95,11 @@ 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;
+
     struct be_offline_status offstat;
 
     struct sbus_connection *mon_conn;
@@ -122,6 +137,12 @@ 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(struct be_ctx *ctx,
+                     be_conn_online_callback_t cb,
+                     void *pvt);
+int be_remove_online_cb(struct be_ctx *ctx,
+                        be_conn_online_callback_t cb);
+
 /* 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..af8c659c92ef8f9916c17ac3978dfe902dcd4d0e 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,8 +1079,11 @@ 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;
+    struct be_conn_online_cb *callback;
 
     ret = sdap_auth_recv(subreq, NULL, &result, NULL);
     talloc_zfree(subreq);
@@ -1091,6 +1096,21 @@ static void sdap_cli_auth_done(struct tevent_req *subreq)
         return;
     }
 
+    /* Reconnection succeeded
+     * Run any post-connection routines
+     */
+    if (state->be->online_cb_list) {
+        DLIST_FOR_EACH(callback, state->be->online_cb_list) {
+            ret = callback->cb(callback->pvt);
+            if (ret != EOK) {
+                DEBUG(0, ("Post-connection callback returned [%d][%s]",
+                          ret, strerror(ret)));
+                tevent_req_error(req, ret);
+                break;
+            }
+        }
+    }
+
     tevent_req_done(req);
 }
 
-- 
1.7.0.1

