summaryrefslogtreecommitdiffstats
path: root/src/providers
diff options
context:
space:
mode:
authorStephen Gallagher <sgallagh@redhat.com>2010-04-27 14:57:37 -0400
committerStephen Gallagher <sgallagh@redhat.com>2010-05-07 17:14:32 -0400
commitdd025b4cbd501e2f34461f9d8359a829b81f5c2f (patch)
treeb04795563e7072d0b66ad28383d00624656363fa /src/providers
parent96a6aa73a6ea0982b349ac10b82aaf86d03ec5f5 (diff)
downloadsssd-dd025b4cbd501e2f34461f9d8359a829b81f5c2f.tar.gz
sssd-dd025b4cbd501e2f34461f9d8359a829b81f5c2f.tar.xz
sssd-dd025b4cbd501e2f34461f9d8359a829b81f5c2f.zip
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.
Diffstat (limited to 'src/providers')
-rw-r--r--src/providers/data_provider_be.c138
-rw-r--r--src/providers/dp_backend.h17
-rw-r--r--src/providers/ldap/sdap_async_connection.c9
-rw-r--r--src/providers/proxy.c10
4 files changed, 174 insertions, 0 deletions
diff --git a/src/providers/data_provider_be.c b/src/providers/data_provider_be.c
index e5a5ff7b0..27a4571a7 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 d657af18b..496c80700 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;
@@ -126,6 +136,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 17cd55863..bd8d4e960 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;
@@ -851,6 +852,7 @@ struct tevent_req *sdap_cli_connect_send(TALLOC_CTX *memctx,
state->service = service;
state->be = be;
state->srv = NULL;
+ state->be = be;
if (rootdse) {
state->use_rootdse = true;
@@ -1123,6 +1125,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;
@@ -1137,6 +1141,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 c7aef3086..ac5cf7fe9 100644
--- a/src/providers/proxy.c
+++ b/src/providers/proxy.c
@@ -277,6 +277,16 @@ static void proxy_pam_handler(struct be_req *req) {
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);
}