>From 2f2ff5436c0087c52a50e1569ba4b0740ca13f98 Mon Sep 17 00:00:00 2001
From: Pavel Reichl <preichl@redhat.com>
Date: Mon, 10 Feb 2014 15:01:35 +0000
Subject: [PATCH] failover: Shorter retry time for failed SRV

Until now there was only one timeout used to re-resolve SRV queries.
This patch adds new (shorter) timeout that will be used for queries that
previously failed.

Resolves:
https://fedorahosted.org/sssd/ticket/1885
---
 src/providers/data_provider_fo.c |  1 +
 src/providers/fail_over.c        | 16 ++++++++++++++--
 src/providers/fail_over.h        |  4 ++++
 3 files changed, 19 insertions(+), 2 deletions(-)

diff --git a/src/providers/data_provider_fo.c b/src/providers/data_provider_fo.c
index 526ae58f145330c94d1c9fd158dcd085d756698d..974385758a00047968fa8f85b0b7d8abefa0cdc7 100644
--- a/src/providers/data_provider_fo.c
+++ b/src/providers/data_provider_fo.c
@@ -71,6 +71,7 @@ static int be_fo_get_options(struct be_ctx *ctx,
                                                   DP_RES_OPT_RESOLVER_TIMEOUT);
     opts->retry_timeout = 30;
     opts->srv_retry_timeout = 14400;
+    opts->srv_retry_timeout_prev_failed = 5;
     opts->family_order = ctx->be_res->family_order;
 
     return EOK;
diff --git a/src/providers/fail_over.c b/src/providers/fail_over.c
index c47e5f7309c0afd445a1ee35a84c14bbf43c7113..1b00ab26079acbaaf5ac5896e9b54669c66015d5 100644
--- a/src/providers/fail_over.c
+++ b/src/providers/fail_over.c
@@ -150,6 +150,8 @@ fo_context_init(TALLOC_CTX *mem_ctx, struct fo_options *opts)
     }
 
     ctx->opts->srv_retry_timeout = opts->srv_retry_timeout;
+    ctx->opts->srv_retry_timeout_prev_failed =
+        opts->srv_retry_timeout_prev_failed;
     ctx->opts->retry_timeout = opts->retry_timeout;
     ctx->opts->family_order  = opts->family_order;
     ctx->opts->service_resolv_timeout = opts->service_resolv_timeout;
@@ -265,9 +267,16 @@ get_srv_data_status(struct srv_data *data)
     struct timeval tv;
     time_t timeout;
 
-    timeout = data->meta->service->ctx->opts->srv_retry_timeout;
     gettimeofday(&tv, NULL);
 
+    /* Determine timeout value based on state of previous lookup. */
+    if (data->srv_lookup_status == SRV_RESOLVE_ERROR) {
+        timeout =
+            data->meta->service->ctx->opts->srv_retry_timeout_prev_failed;
+    } else {
+        timeout = data->meta->service->ctx->opts->srv_retry_timeout;
+    }
+
     if (timeout && STATUS_DIFF(data, tv) > timeout) {
         switch(data->srv_lookup_status) {
         case SRV_EXPIRED:
@@ -280,6 +289,9 @@ get_srv_data_status(struct srv_data *data)
         case SRV_RESOLVE_ERROR:
             data->srv_lookup_status = SRV_NEUTRAL;
             data->last_status_change.tv_sec = 0;
+            DEBUG(SSSDBG_TRACE_FUNC,
+                  "Changing state of SRV lookup from 'SRV_RESOLVE_ERROR' to "
+                  "'SRV_NEUTRAL'.\n.");
             break;
         default:
             DEBUG(SSSDBG_CRIT_FAILURE, "Unknown state for SRV server!\n");
@@ -1022,7 +1034,7 @@ fo_resolve_service_activate_timeout(struct tevent_req *req,
     tv = tevent_timeval_current();
     tv = tevent_timeval_add(&tv, timeout_seconds, 0);
     state->timeout_handler = tevent_add_timer(ev, state, tv,
-                                           fo_resolve_service_timeout, req);
+                                              fo_resolve_service_timeout, req);
     if (state->timeout_handler == NULL) {
         DEBUG(SSSDBG_CRIT_FAILURE, "tevent_add_timer failed.\n");
         return ENOMEM;
diff --git a/src/providers/fail_over.h b/src/providers/fail_over.h
index e4cc1b1cbc44a52cb11880be47823f36c37a473c..dba81a518e1b7eec46ed0d959e4546042f97d5d5 100644
--- a/src/providers/fail_over.h
+++ b/src/providers/fail_over.h
@@ -71,11 +71,15 @@ struct fo_server;
  * The 'srv_retry_timeout' member specifies how long a SRV lookup
  * is considered valid until we ask the server again.
  *
+ * The 'srv_retry_timeout_prev_failed' member specifies how long a SRV lookup
+ * waits before previously failed lookup is tried again.
+ *
  * The family_order member specifies the order of address families to
  * try when looking up the service.
  */
 struct fo_options {
     time_t srv_retry_timeout;
+    time_t srv_retry_timeout_prev_failed;
     time_t retry_timeout;
     int service_resolv_timeout;
     enum restrict_family family_order;
-- 
1.8.4.2

