>From 46b77fa70588c55b35627558cb99395586df5366 Mon Sep 17 00:00:00 2001
From: Michal Zidek <mzidek@redhat.com>
Date: Thu, 3 Jul 2014 12:49:20 +0200
Subject: [PATCH] Exit offline mode only if server is available.

This patch adds periodic check to test if
backend can exit offline mode and only
marks backend as not offline if server
for the service is available.

Prior to this patch we marked backend as not
offline if the offline_timeout was reached
without checking for the server availability
and when the next request failed again
we switched back to the offline mode.
This caused significant slowdowns in some
edge cases.

Fixes:
https://fedorahosted.org/sssd/ticket/2355
---
 src/providers/data_provider_be.c | 50 ++++++++++++++++++++++++++++++++++------
 src/providers/dp_backend.h       |  5 ++++
 2 files changed, 48 insertions(+), 7 deletions(-)

diff --git a/src/providers/data_provider_be.c b/src/providers/data_provider_be.c
index 240f603..22f0dc5 100644
--- a/src/providers/data_provider_be.c
+++ b/src/providers/data_provider_be.c
@@ -449,24 +449,59 @@ static void be_queue_next_request(struct be_req *be_req, enum bet_type type)
 
 bool be_is_offline(struct be_ctx *ctx)
 {
-    time_t now = time(NULL);
+    return ctx->offstat.offline;
+}
 
-    /* check if we are past the offline blackout timeout */
-    /* FIXME: get offline_timeout from configuration */
-    if (ctx->offstat.went_offline + 60 < now) {
-        ctx->offstat.offline = false;
-    }
+static void check_if_online(struct be_ctx *ctx);
 
-    return ctx->offstat.offline;
+errno_t
+try_to_go_online(TALLOC_CTX *mem_ctx,
+                 struct tevent_context *ev,
+                 struct be_ctx *be_ctx,
+                 struct be_ptask *be_ptask,
+                 void *be_ctx_void)
+{
+    struct be_ctx *ctx = (struct be_ctx*) be_ctx_void;
+
+    check_if_online(ctx);
+    return EOK;
 }
 
 void be_mark_offline(struct be_ctx *ctx)
 {
+    int offline_timeout = 60;
     DEBUG(SSSDBG_TRACE_INTERNAL, "Going offline!\n");
 
     ctx->offstat.went_offline = time(NULL);
     ctx->offstat.offline = true;
     ctx->run_online_cb = true;
+    errno_t ret;
+
+    if (ctx->online_check_ptask_initialized == false) {
+        /* This is the first time we go offline - create a periodic task
+         * to check if we can switch to online. */
+        DEBUG(SSSDBG_TRACE_INTERNAL, "Initialize check_if_online_ptask.\n");
+
+        ret = be_ptask_create_sync(ctx, ctx,
+                                   offline_timeout, offline_timeout,
+                                   offline_timeout, offline_timeout,
+                                   BE_PTASK_OFFLINE_EXECUTE,
+                                   try_to_go_online,
+                                   ctx, "Check if online (periodic)",
+                                   &ctx->check_if_online_ptask);
+        if (ret == EOK) {
+            ctx->online_check_ptask_initialized = true;
+        } else {
+            DEBUG(SSSDBG_FATAL_FAILURE,
+                  "be_ptask_create_sync failed [%d]: %s\n",
+                  ret, sss_strerror(ret));
+        }
+    } else {
+        /* Periodic task was already created. Just enable it. */
+        DEBUG(SSSDBG_TRACE_INTERNAL, "Enable check_if_online_ptask.\n");
+        be_ptask_enable(ctx->check_if_online_ptask);
+    }
+
     be_run_offline_cb(ctx);
 }
 
@@ -474,6 +509,7 @@ static void be_reset_offline(struct be_ctx *ctx)
 {
     ctx->offstat.went_offline = 0;
     ctx->offstat.offline = false;
+    be_ptask_disable(ctx->check_if_online_ptask);
     be_run_online_cb(ctx);
 }
 
diff --git a/src/providers/dp_backend.h b/src/providers/dp_backend.h
index 8e3a68a..330ee99 100644
--- a/src/providers/dp_backend.h
+++ b/src/providers/dp_backend.h
@@ -133,6 +133,11 @@ struct be_ctx {
     struct be_cb *unconditional_online_cb_list;
 
     struct be_offline_status offstat;
+    /* Periodicly check if we can go online. */
+    struct be_ptask *check_if_online_ptask;
+    /* Initial value is 'false' because be_ctx is allocated with
+     * talloc_zero. */
+    bool online_check_ptask_initialized;
 
     struct sbus_connection *mon_conn;
     struct sbus_connection *sbus_srv;
-- 
1.8.5.3

