From c03661cf0037f35d444d0ebe8c3d0129d96cfc0d Mon Sep 17 00:00:00 2001
From: Mark Reynolds <mreynolds@redhat.com>
Date: Thu, 13 Feb 2014 14:54:11 -0500
Subject: [PATCH] Ticket 525 - Replication retry time attributes cannot be added

Bug Description:  Trying to add nsds5ReplicaBackoffMin/nsds5ReplicaBackoffMax
                  to a replica entry results in an error 53.

Fix Description:  Allow the adding & deleting of these attributes.  Also changed
                  their type to slapi_counters so they can be safely updated.

https://fedorahosted.org/389/ticket/525

Reviewed by: ?
---
 ldap/servers/plugins/replication/repl5.h           |    8 +-
 ldap/servers/plugins/replication/repl5_replica.c   |   48 +++++++++++-----
 .../plugins/replication/repl5_replica_config.c     |   60 +++++++++++++++++--
 3 files changed, 90 insertions(+), 26 deletions(-)

diff --git a/ldap/servers/plugins/replication/repl5.h b/ldap/servers/plugins/replication/repl5.h
index 716da32..04d5a82 100644
--- a/ldap/servers/plugins/replication/repl5.h
+++ b/ldap/servers/plugins/replication/repl5.h
@@ -603,10 +603,10 @@ void replica_update_state (time_t when, void *arg);
 void replica_reset_csn_pl(Replica *r);
 PRUint64 replica_get_protocol_timeout(Replica *r);
 void replica_set_protocol_timeout(Replica *r, PRUint64 timeout);
-int replica_get_backoff_min(Replica *r);
-int replica_get_backoff_max(Replica *r);
-void replica_set_backoff_min(Replica *r, int min);
-void replica_set_backoff_max(Replica *r, int max);
+PRUint64 replica_get_backoff_min(Replica *r);
+PRUint64 replica_get_backoff_max(Replica *r);
+void replica_set_backoff_min(Replica *r, PRUint64 min);
+void replica_set_backoff_max(Replica *r, PRUint64 max);
 int replica_get_agmt_count(Replica *r);
 void replica_incr_agmt_count(Replica *r);
 void replica_decr_agmt_count(Replica *r);
diff --git a/ldap/servers/plugins/replication/repl5_replica.c b/ldap/servers/plugins/replication/repl5_replica.c
index ffa5adc..3eeb322 100644
--- a/ldap/servers/plugins/replication/repl5_replica.c
+++ b/ldap/servers/plugins/replication/repl5_replica.c
@@ -87,9 +87,9 @@ struct replica {
 	PRBool state_update_inprogress; /* replica state is being updated */
 	PRLock *agmt_lock;          	/* protects agreement creation, start and stop */
 	char *locking_purl;				/* supplier who has exclusive access */
-	Slapi_Counter *protocol_timeout;	/* protocol shutdown timeout */
-	PRUint64 backoff_min;			/* backoff retry minimum */
-	PRUint64 backoff_max;			/* backoff retry maximum */
+	Slapi_Counter *protocol_timeout;/* protocol shutdown timeout */
+	Slapi_Counter *backoff_min;		/* backoff retry minimum */
+	Slapi_Counter *backoff_max;		/* backoff retry maximum */
 	PRUint64 agmt_count;			/* Number of agmts */
 };
 
@@ -209,7 +209,11 @@ replica_new_from_entry (Slapi_Entry *e, char *errortext, PRBool is_add_operation
 		rc = -1;
 		goto done;
 	}
+
+	/* init the slapi_counter/atomic settings */
 	r->protocol_timeout = slapi_counter_new();
+	r->backoff_min = slapi_counter_new();
+	r->backoff_max = slapi_counter_new();
 
     /* read parameters from the replica config entry */
     rc = _replica_init_from_config (r, e, errortext);
@@ -406,6 +410,8 @@ replica_destroy(void **arg)
 	}
 
 	slapi_counter_destroy(&r->protocol_timeout);
+	slapi_counter_destroy(&r->backoff_min);
+	slapi_counter_destroy(&r->backoff_max);
 
 	slapi_ch_free((void **)arg);
 }
@@ -1771,11 +1777,11 @@ _replica_init_from_config (Replica *r, Slapi_Entry *e, char *errortext)
         slapi_log_error(SLAPI_LOG_FATAL, repl_plugin_name, "Backoff minimum (%d) can not be greater than "
             "the backoff maximum (%d).  Using default values: min (%d) max (%d)\n", backoff_min, backoff_max,
             PROTOCOL_BACKOFF_MINIMUM, PROTOCOL_BACKOFF_MAXIMUM);
-        r->backoff_min = PROTOCOL_BACKOFF_MINIMUM;
-        r->backoff_max = PROTOCOL_BACKOFF_MAXIMUM;
+        slapi_counter_set_value(r->backoff_min, PROTOCOL_BACKOFF_MINIMUM);
+        slapi_counter_set_value(r->backoff_max, PROTOCOL_BACKOFF_MAXIMUM);
     } else {
-        r->backoff_min = backoff_min;
-        r->backoff_max = backoff_max;
+        slapi_counter_set_value(r->backoff_min, backoff_min);
+        slapi_counter_set_value(r->backoff_max, backoff_max);
     }
 
     /* get the protocol timeout */
@@ -3930,28 +3936,40 @@ replica_get_attr ( Slapi_PBlock *pb, const char* type, void *value )
 	return rc;
 }
 
-int
+PRUint64
 replica_get_backoff_min(Replica *r)
 {
-	return (int)r->backoff_min;
+	if(r){
+		return slapi_counter_get_value(r->backoff_min);
+	} else {
+		return PROTOCOL_BACKOFF_MINIMUM;
+	}
 }
 
-int
+PRUint64
 replica_get_backoff_max(Replica *r)
 {
-	return (int)r->backoff_max;
+	if(r){
+		return slapi_counter_get_value(r->backoff_max);
+	} else {
+		return PROTOCOL_BACKOFF_MAXIMUM;
+	}
 }
 
 void
-replica_set_backoff_min(Replica *r, int min)
+replica_set_backoff_min(Replica *r, PRUint64 min)
 {
-	r->backoff_min = min;
+	if(r){
+		slapi_counter_set_value(r->backoff_min, min);
+	}
 }
 
 void
-replica_set_backoff_max(Replica *r, int max)
+replica_set_backoff_max(Replica *r, PRUint64 max)
 {
-	r->backoff_max = max;
+	if(r){
+		slapi_counter_set_value(r->backoff_max, max);
+	}
 }
 
 int
diff --git a/ldap/servers/plugins/replication/repl5_replica_config.c b/ldap/servers/plugins/replication/repl5_replica_config.c
index dfe898a..b1c700e 100644
--- a/ldap/servers/plugins/replication/repl5_replica_config.c
+++ b/ldap/servers/plugins/replication/repl5_replica_config.c
@@ -374,8 +374,10 @@ replica_config_modify (Slapi_PBlock *pb, Slapi_Entry* entryBefore, Slapi_Entry*
             else if ((mods[i]->mod_op & LDAP_MOD_DELETE) || mods[i]->mod_bvalues == NULL
                      || mods[i]->mod_bvalues[0]->bv_val == NULL)
             {
-                /* currently, you can only remove referral,
-				   legacy consumer or bind dn attribute */
+                /*
+                 *  Where possible/allowed return replica config settings to their
+                 *  default values.
+                 */
                 if (strcasecmp (config_attr, attr_replicaBindDn) == 0)
                 {
 				    *returncode = replica_config_change_updatedn (r, mods[i], errortext, apply_mods);
@@ -398,14 +400,24 @@ replica_config_modify (Slapi_PBlock *pb, Slapi_Entry* entryBefore, Slapi_Entry*
                          strcasecmp (config_attr, type_replicaAbortCleanRUV) == 0)
                 {
                     /*
-                     * Only allow the deletion of the cleanAllRUV config attributes, and the
-                     * protocol timeout.
+                     * Nothing to do in this case, allow it, and continue.
                      */
                     continue;
                 }
                 else if (strcasecmp (config_attr, type_replicaProtocolTimeout) == 0 )
                 {
-                	replica_set_protocol_timeout(r, DEFAULT_PROTOCOL_TIMEOUT);
+                    if (apply_mods)
+                        replica_set_protocol_timeout(r, DEFAULT_PROTOCOL_TIMEOUT);
+                }
+                else if(strcasecmp (config_attr, type_replicaBackoffMin) == 0 )
+                {
+                    if (apply_mods)
+                        replica_set_backoff_min(r, PROTOCOL_BACKOFF_MINIMUM);
+                }
+                else if (strcasecmp (config_attr, type_replicaBackoffMax) == 0 )
+                {
+                    if (apply_mods)
+                        replica_set_backoff_max(r, PROTOCOL_BACKOFF_MAXIMUM);
                 }
                 else
                 {
@@ -498,10 +510,10 @@ replica_config_modify (Slapi_PBlock *pb, Slapi_Entry* entryBefore, Slapi_Entry*
                 else if (strcasecmp (config_attr, type_replicaProtocolTimeout) == 0 ){
                     if (apply_mods)
                     {
-                        long ptimeout = 0;
+                        PRUint64 ptimeout = 0;
 
                         if(config_attr_value){
-                            ptimeout = atol(config_attr_value);
+                            ptimeout = atoll(config_attr_value);
                         }
 
                         if(ptimeout <= 0){
@@ -515,6 +527,40 @@ replica_config_modify (Slapi_PBlock *pb, Slapi_Entry* entryBefore, Slapi_Entry*
                         replica_set_protocol_timeout(r, ptimeout);
                     }
                 }
+                else if(strcasecmp (config_attr, type_replicaBackoffMin) == 0 )
+                {
+                    if (apply_mods)
+                    {
+                        PRUint64 val = atoll(config_attr_value);
+
+                        if(val <= 0){
+                            *returncode = LDAP_UNWILLING_TO_PERFORM;
+                            PR_snprintf (errortext, SLAPI_DSE_RETURNTEXT_SIZE,
+                                    "attribute %s value (%s) is invalid, must be a number greater than zero.\n",
+                                    config_attr, config_attr_value ? config_attr_value : "");
+                            slapi_log_error(SLAPI_LOG_FATAL, repl_plugin_name, "replica_config_modify: %s\n", errortext);
+                            break;
+                        }
+                        replica_set_backoff_min(r, val);
+                    }
+                }
+                else if (strcasecmp (config_attr, type_replicaBackoffMax) == 0 )
+                {
+                    if (apply_mods)
+                    {
+                        PRUint64 val = atoll(config_attr_value);
+
+                        if(val <= 0){
+                            *returncode = LDAP_UNWILLING_TO_PERFORM;
+                            PR_snprintf (errortext, SLAPI_DSE_RETURNTEXT_SIZE,
+                                    "attribute %s value (%s) is invalid, must be a number greater than zero.\n",
+                                    config_attr, config_attr_value ? config_attr_value : "");
+                            slapi_log_error(SLAPI_LOG_FATAL, repl_plugin_name, "replica_config_modify: %s\n", errortext);
+                            break;
+                        }
+                        replica_set_backoff_max(r, val);
+                    }
+                }
                 else
                 {
                     *returncode = LDAP_UNWILLING_TO_PERFORM;
-- 
1.7.1

