>From 79f5b5f1af27dd4da77ec9af212cca515910b041 Mon Sep 17 00:00:00 2001
From: Michal Zidek <mzidek@redhat.com>
Date: Mon, 7 Jul 2014 17:45:45 +0200
Subject: [PATCH 2/3] ptask: Add backoff feature to the ptask api.

---
 src/providers/data_provider_be.c     |  2 +-
 src/providers/dp_ptask.c             | 27 ++++++++++++++++++++++++++-
 src/providers/dp_ptask.h             |  8 ++++++++
 src/providers/ldap/ldap_id_cleanup.c |  2 +-
 src/providers/ldap/ldap_id_enum.c    |  1 +
 5 files changed, 37 insertions(+), 3 deletions(-)

diff --git a/src/providers/data_provider_be.c b/src/providers/data_provider_be.c
index a01bb06..5e7c2a4 100644
--- a/src/providers/data_provider_be.c
+++ b/src/providers/data_provider_be.c
@@ -2581,7 +2581,7 @@ int be_process_init(TALLOC_CTX *mem_ctx,
     if (ctx->domain->refresh_expired_interval > 0) {
         ret = be_ptask_create(ctx, ctx, ctx->domain->refresh_expired_interval,
                               30, 5, 0, ctx->domain->refresh_expired_interval,
-                              BE_PTASK_OFFLINE_SKIP,
+                              BE_PTASK_OFFLINE_SKIP, 0,
                               be_refresh_send, be_refresh_recv,
                               ctx->refresh_ctx, "Refresh Records", NULL);
         if (ret != EOK) {
diff --git a/src/providers/dp_ptask.c b/src/providers/dp_ptask.c
index 4d0fec4..255ad3f 100644
--- a/src/providers/dp_ptask.c
+++ b/src/providers/dp_ptask.c
@@ -40,6 +40,9 @@ struct be_ptask {
     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;
@@ -210,6 +213,17 @@ static void be_ptask_schedule(struct be_ptask *task,
         return;
     }
 
+    if (task->allow_backoff) {
+        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;
+        }
+    }
+
     if (task->random_offset != 0) {
         delay = delay + (rand_r(&task->ro_seed) % task->random_offset);
     }
@@ -253,6 +267,7 @@ errno_t be_ptask_create(TALLOC_CTX *mem_ctx,
                         time_t random_offset,
                         time_t timeout,
                         enum be_ptask_offline offline,
+                        time_t max_backoff,
                         be_ptask_send_t send_fn,
                         be_ptask_recv_t recv_fn,
                         void *pvt,
@@ -290,6 +305,11 @@ 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->enabled = true;
 
     talloc_set_destructor((TALLOC_CTX*)task, be_ptask_destructor);
@@ -350,6 +370,10 @@ void be_ptask_disable(struct be_ptask *task)
 
     talloc_zfree(task->timer);
     task->enabled = false;
+
+    if (task->allow_backoff) {
+        task->backoff_delay = 0;
+    }
 }
 
 void be_ptask_destroy(struct be_ptask **task)
@@ -418,6 +442,7 @@ errno_t be_ptask_create_sync(TALLOC_CTX *mem_ctx,
                              time_t random_offset,
                              time_t timeout,
                              enum be_ptask_offline offline,
+                             time_t max_backoff,
                              be_ptask_sync_t fn,
                              void *pvt,
                              const char *name,
@@ -437,7 +462,7 @@ errno_t be_ptask_create_sync(TALLOC_CTX *mem_ctx,
 
     ret = be_ptask_create(mem_ctx, be_ctx, period, first_delay,
                           enabled_delay, random_offset, timeout, offline,
-                          be_ptask_sync_send, be_ptask_sync_recv,
+                          max_backoff, be_ptask_sync_send, be_ptask_sync_recv,
                           ctx, name, _task);
     if (ret != EOK) {
         goto done;
diff --git a/src/providers/dp_ptask.h b/src/providers/dp_ptask.h
index 0f98738..1b93101 100644
--- a/src/providers/dp_ptask.h
+++ b/src/providers/dp_ptask.h
@@ -83,6 +83,12 @@ typedef errno_t
  *
  * The random_offset is maximum number of seconds added to the
  * expected delay. Set to 0 if no randomization is needed.
+
+ * If max_backoff is not 0 then the period is doubled
+ * every time the task is scheduled. The maximum value of
+ * period is max_backoff. The value of period will be reset to
+ * original value when the task is disabled. With max_backoff
+ * set to zero, this feature is disabled.
  *
  * If an internal error occurred, the task is automatically disabled.
  */
@@ -94,6 +100,7 @@ errno_t be_ptask_create(TALLOC_CTX *mem_ctx,
                         time_t random_offset,
                         time_t timeout,
                         enum be_ptask_offline offline,
+                        time_t max_backoff,
                         be_ptask_send_t send_fn,
                         be_ptask_recv_t recv_fn,
                         void *pvt,
@@ -108,6 +115,7 @@ errno_t be_ptask_create_sync(TALLOC_CTX *mem_ctx,
                              time_t random_offset,
                              time_t timeout,
                              enum be_ptask_offline offline,
+                             time_t max_backoff,
                              be_ptask_sync_t fn,
                              void *pvt,
                              const char *name,
diff --git a/src/providers/ldap/ldap_id_cleanup.c b/src/providers/ldap/ldap_id_cleanup.c
index 0c473da..f78d4b4 100644
--- a/src/providers/ldap/ldap_id_cleanup.c
+++ b/src/providers/ldap/ldap_id_cleanup.c
@@ -87,7 +87,7 @@ errno_t ldap_setup_cleanup(struct sdap_id_ctx *id_ctx,
 
     ret = be_ptask_create_sync(sdom, id_ctx->be, period, first_delay,
                                5 /* enabled delay */, 0 /* random offset */,
-                               period /* timeout */, BE_PTASK_OFFLINE_SKIP,
+                               period /* timeout */, BE_PTASK_OFFLINE_SKIP, 0,
                                ldap_cleanup_task, cleanup_ctx, name,
                                &sdom->cleanup_task);
     if (ret != EOK) {
diff --git a/src/providers/ldap/ldap_id_enum.c b/src/providers/ldap/ldap_id_enum.c
index 25ee5f6..9ffa3e5 100644
--- a/src/providers/ldap/ldap_id_enum.c
+++ b/src/providers/ldap/ldap_id_enum.c
@@ -77,6 +77,7 @@ errno_t ldap_setup_enumeration(struct be_ctx *be_ctx,
                           0,                        /* random offset */
                           period,                   /* timeout */
                           BE_PTASK_OFFLINE_SKIP,
+                          0,                        /* max_backoff */
                           send_fn, recv_fn,
                           ectx, "enumeration", &sdom->enum_task);
     if (ret != EOK) {
-- 
1.9.3

