summaryrefslogtreecommitdiffstats
path: root/src/providers/data_provider_be.c
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 16:38:23 -0400
commit8af798967f76df5cc96952a11d425e6ba9f10864 (patch)
tree2fce6ee54545064bc071d8cfacb4ef4a3dfede0c /src/providers/data_provider_be.c
parent63b072f1c9b78b8a1877b32acc02b61bd1f04f12 (diff)
downloadsssd-8af798967f76df5cc96952a11d425e6ba9f10864.tar.gz
sssd-8af798967f76df5cc96952a11d425e6ba9f10864.tar.xz
sssd-8af798967f76df5cc96952a11d425e6ba9f10864.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/data_provider_be.c')
-rw-r--r--src/providers/data_provider_be.c138
1 files changed, 138 insertions, 0 deletions
diff --git a/src/providers/data_provider_be.c b/src/providers/data_provider_be.c
index 6dc6f9bea..9ef436e93 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;