From 50bee9f3450e4abf31b6704430c7bb81e9a4c134 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Pavel=20B=C5=99ezina?= <pbrezina@redhat.com>
Date: Fri, 21 Nov 2014 12:34:54 +0100
Subject: [PATCH] be_ptask: let backoff affect only period

---
 src/providers/dp_ptask.c         | 71 +++++++++++++++++++++++++---------------
 src/providers/dp_ptask_private.h |  4 +--
 2 files changed, 47 insertions(+), 28 deletions(-)

diff --git a/src/providers/dp_ptask.c b/src/providers/dp_ptask.c
index 3540579e83ccda6bb096099c05f5cbb5c56cd531..06bbd55a2562381b9a47220c993a75bdf26d3961 100644
--- a/src/providers/dp_ptask.c
+++ b/src/providers/dp_ptask.c
@@ -28,13 +28,21 @@
 #include "providers/dp_ptask_private.h"
 #include "providers/dp_ptask.h"
 
+#define is_backoff_allowed(ptask) (ptask->max_backoff != 0)
+
 enum be_ptask_schedule {
     BE_PTASK_SCHEDULE_FROM_NOW,
     BE_PTASK_SCHEDULE_FROM_LAST
 };
 
+enum be_ptask_delay {
+    BE_PTASK_FIRST_DELAY,
+    BE_PTASK_ENABLED_DELAY,
+    BE_PTASK_PERIOD
+};
+
 static void be_ptask_schedule(struct be_ptask *task,
-                              time_t delay,
+                              enum be_ptask_delay delay_type,
                               enum be_ptask_schedule from);
 
 static int be_ptask_destructor(void *pvt)
@@ -86,7 +94,7 @@ static void be_ptask_timeout(struct tevent_context *ev,
     DEBUG(SSSDBG_OP_FAILURE, "Task [%s]: timed out\n", task->name);
 
     talloc_zfree(task->req);
-    be_ptask_schedule(task, task->period, BE_PTASK_SCHEDULE_FROM_NOW);
+    be_ptask_schedule(task, BE_PTASK_PERIOD, BE_PTASK_SCHEDULE_FROM_NOW);
 }
 
 static void be_ptask_done(struct tevent_req *req);
@@ -106,7 +114,8 @@ static void be_ptask_execute(struct tevent_context *ev,
         DEBUG(SSSDBG_TRACE_FUNC, "Back end is offline\n");
         switch (task->offline) {
         case BE_PTASK_OFFLINE_SKIP:
-            be_ptask_schedule(task, task->period, BE_PTASK_SCHEDULE_FROM_NOW);
+            be_ptask_schedule(task, BE_PTASK_PERIOD,
+                              BE_PTASK_SCHEDULE_FROM_NOW);
             return;
         case BE_PTASK_OFFLINE_DISABLE:
             /* This case is normally handled by offline callback but we
@@ -131,7 +140,7 @@ static void be_ptask_execute(struct tevent_context *ev,
         DEBUG(SSSDBG_OP_FAILURE, "Task [%s]: failed to execute task, "
               "will try again later\n", task->name);
 
-        be_ptask_schedule(task, task->period, BE_PTASK_SCHEDULE_FROM_NOW);
+        be_ptask_schedule(task, BE_PTASK_PERIOD, BE_PTASK_SCHEDULE_FROM_NOW);
         return;
     }
 
@@ -150,7 +159,8 @@ static void be_ptask_execute(struct tevent_context *ev,
             DEBUG(SSSDBG_OP_FAILURE, "Task [%s]: failed to set timeout, "
                   "the task will be rescheduled\n", task->name);
 
-            be_ptask_schedule(task, task->period, BE_PTASK_SCHEDULE_FROM_NOW);
+            be_ptask_schedule(task, BE_PTASK_PERIOD,
+                              BE_PTASK_SCHEDULE_FROM_NOW);
         }
     }
 
@@ -172,39 +182,53 @@ static void be_ptask_done(struct tevent_req *req)
         DEBUG(SSSDBG_TRACE_FUNC, "Task [%s]: finished successfully\n",
                                   task->name);
 
-        be_ptask_schedule(task, task->period, BE_PTASK_SCHEDULE_FROM_LAST);
+        be_ptask_schedule(task, BE_PTASK_PERIOD, BE_PTASK_SCHEDULE_FROM_LAST);
         break;
     default:
         DEBUG(SSSDBG_OP_FAILURE, "Task [%s]: failed with [%d]: %s\n",
                                   task->name, ret, sss_strerror(ret));
 
-        be_ptask_schedule(task, task->period, BE_PTASK_SCHEDULE_FROM_NOW);
+        be_ptask_schedule(task, BE_PTASK_PERIOD, BE_PTASK_SCHEDULE_FROM_NOW);
         break;
     }
 }
 
 static void be_ptask_schedule(struct be_ptask *task,
-                              time_t delay,
+                              enum be_ptask_delay delay_type,
                               enum be_ptask_schedule from)
 {
     struct timeval tv;
+    time_t delay;
 
     if (!task->enabled) {
         DEBUG(SSSDBG_TRACE_FUNC, "Task [%s]: disabled\n", task->name);
         return;
     }
 
-    if (task->allow_backoff) {
+    switch (delay_type) {
+    case BE_PTASK_FIRST_DELAY:
+        delay = task->first_delay;
+        break;
+    case BE_PTASK_ENABLED_DELAY:
+        delay = task->enabled_delay;
+        break;
+    case BE_PTASK_PERIOD:
+        if (!is_backoff_allowed(task)) {
+            delay = task->period;
+            break;
+        }
+        /* compute backoff delay */
         if (task->backoff_delay == 0) {
             task->backoff_delay = task->period;
-        } else {
-            task->backoff_delay = (task->backoff_delay * 2 > task->max_backoff)
-                                  ? task->max_backoff
-                                  : task->backoff_delay * 2;
-            delay = task->backoff_delay;
-        }
+        } else if (task->backoff_delay * 2 <= task->max_backoff) {
+            task->backoff_delay = task->backoff_delay * 2;
+        } /* else do not change backoff delay */
+
+        delay = task->backoff_delay;
+        break;
     }
 
+    /* add random offset */
     if (task->random_offset != 0) {
         delay = delay + (rand_r(&task->ro_seed) % task->random_offset);
     }
@@ -274,9 +298,11 @@ errno_t be_ptask_create(TALLOC_CTX *mem_ctx,
     task->ev = be_ctx->ev;
     task->be_ctx = be_ctx;
     task->period = period;
+    task->first_delay = first_delay;
     task->enabled_delay = enabled_delay;
     task->random_offset = random_offset;
     task->ro_seed = time(NULL) * getpid();
+    task->max_backoff = max_backoff;
     task->timeout = timeout;
     task->offline = offline;
     task->send_fn = send_fn;
@@ -288,11 +314,7 @@ errno_t be_ptask_create(TALLOC_CTX *mem_ctx,
         goto done;
     }
 
-    if (max_backoff != 0) {
-        task->max_backoff = max_backoff;
-        task->allow_backoff = true;
-    }
-
+    task->backoff_delay = 0;
     task->enabled = true;
 
     talloc_set_destructor((TALLOC_CTX*)task, be_ptask_destructor);
@@ -316,7 +338,7 @@ errno_t be_ptask_create(TALLOC_CTX *mem_ctx,
 
     DEBUG(SSSDBG_TRACE_FUNC, "Periodic task [%s] was created\n", task->name);
 
-    be_ptask_schedule(task, first_delay, BE_PTASK_SCHEDULE_FROM_NOW);
+    be_ptask_schedule(task, BE_PTASK_FIRST_DELAY, BE_PTASK_SCHEDULE_FROM_NOW);
 
     if (_task != NULL) {
         *_task = task;
@@ -343,7 +365,7 @@ void be_ptask_enable(struct be_ptask *task)
     DEBUG(SSSDBG_TRACE_FUNC, "Task [%s]: enabling task\n", task->name);
 
     task->enabled = true;
-    be_ptask_schedule(task, task->enabled_delay, BE_PTASK_SCHEDULE_FROM_NOW);
+    be_ptask_schedule(task, BE_PTASK_ENABLED_DELAY, BE_PTASK_SCHEDULE_FROM_NOW);
 }
 
 /* Disable the task, but if a request already in progress, let it finish. */
@@ -353,10 +375,7 @@ void be_ptask_disable(struct be_ptask *task)
 
     talloc_zfree(task->timer);
     task->enabled = false;
-
-    if (task->allow_backoff) {
-        task->backoff_delay = 0;
-    }
+    task->backoff_delay = 0;
 }
 
 void be_ptask_destroy(struct be_ptask **task)
diff --git a/src/providers/dp_ptask_private.h b/src/providers/dp_ptask_private.h
index 9c97fae7b8cf7e062c2767037e30148432408023..1d5415cc4474163156ebf299fc5cc4fa6e0a6c67 100644
--- a/src/providers/dp_ptask_private.h
+++ b/src/providers/dp_ptask_private.h
@@ -25,19 +25,19 @@ struct be_ptask {
     struct tevent_context *ev;
     struct be_ctx *be_ctx;
     time_t period;
+    time_t first_delay;
     time_t enabled_delay;
     time_t random_offset;
     unsigned int ro_seed;
     time_t timeout;
-    bool allow_backoff;
     time_t max_backoff;
-    time_t backoff_delay;
     enum be_ptask_offline offline;
     be_ptask_send_t send_fn;
     be_ptask_recv_t recv_fn;
     void *pvt;
     const char *name;
 
+    time_t backoff_delay; /* computed backoff */
     time_t next_execution;  /* next time when the task is scheduled */
     time_t last_execution;  /* last time when send was called */
     struct tevent_req *req; /* active tevent request */
-- 
1.7.11.7

