From 38ae40c28dd20dad301825235edab39f984799ef Mon Sep 17 00:00:00 2001
From: Noriko Hosoi <nhosoi@redhat.com>
Date: Thu, 13 Nov 2014 15:56:39 -0800
Subject: [PATCH] configurable WaitForAsyncResults

---
 ldap/schema/01core389.ldif                         |  3 +-
 ldap/servers/plugins/replication/repl5.h           |  5 ++++
 ldap/servers/plugins/replication/repl5_agmt.c      | 32 +++++++++++++++++++++-
 .../plugins/replication/repl5_inc_protocol.c       |  4 ++-
 ldap/servers/plugins/replication/repl_globals.c    |  1 +
 5 files changed, 42 insertions(+), 3 deletions(-)

diff --git a/ldap/schema/01core389.ldif b/ldap/schema/01core389.ldif
index a1f993f..49df40b 100644
--- a/ldap/schema/01core389.ldif
+++ b/ldap/schema/01core389.ldif
@@ -153,6 +153,7 @@ attributeTypes: ( 2.16.840.1.113730.3.1.2152 NAME 'nsds5ReplicaProtocolTimeout'
 attributeTypes: ( 2.16.840.1.113730.3.1.2154 NAME 'nsds5ReplicaBackoffMin' DESC 'Netscape defined attribute type' SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 SINGLE-VALUE X-ORIGIN 'Netscape Directory Server' )
 attributeTypes: ( 2.16.840.1.113730.3.1.2155 NAME 'nsds5ReplicaBackoffMax' DESC 'Netscape defined attribute type' SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 SINGLE-VALUE X-ORIGIN 'Netscape Directory Server' )
 attributeTypes: ( 2.16.840.1.113730.3.1.2156 NAME 'nsslapd-sasl-max-buffer-size' DESC 'Netscape defined attribute type' SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 SINGLE-VALUE X-ORIGIN 'Netscape Directory Server' )
+attributeTypes: ( 2.16.840.1.113730.3.1.2157 NAME 'nsDS5ReplicaWaitForAsyncResults' DESC 'Netscape defined attribute type' SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 SINGLE-VALUE X-ORIGIN 'Netscape Directory Server' )
 #
 # objectclasses
 #
@@ -164,7 +165,7 @@ objectClasses: ( 2.16.840.1.113730.3.2.110 NAME 'nsMappingTree' DESC 'Netscape d
 objectClasses: ( 2.16.840.1.113730.3.2.104 NAME 'nsContainer' DESC 'Netscape defined objectclass' SUP top  MUST ( CN ) X-ORIGIN 'Netscape Directory Server' )
 objectClasses: ( 2.16.840.1.113730.3.2.108 NAME 'nsDS5Replica' DESC 'Netscape defined objectclass' SUP top  MUST ( nsDS5ReplicaRoot $  nsDS5ReplicaId ) MAY (cn $ nsds5ReplicaCleanRUV $ nsds5ReplicaAbortCleanRUV $ nsDS5ReplicaType $ nsDS5ReplicaBindDN $ nsState $ nsDS5ReplicaName $ nsDS5Flags $ nsDS5Task $ nsDS5ReplicaReferral $ nsDS5ReplicaAutoReferral $ nsds5ReplicaPurgeDelay $ nsds5ReplicaTombstonePurgeInterval $ nsds5ReplicaChangeCount $ nsds5ReplicaLegacyConsumer) X-ORIGIN 'Netscape Directory Server' )
 objectClasses: ( 2.16.840.1.113730.3.2.113 NAME 'nsTombstone' DESC 'Netscape defined objectclass' SUP top MAY ( nsParentUniqueId $ nscpEntryDN ) X-ORIGIN 'Netscape Directory Server' )
-objectClasses: ( 2.16.840.1.113730.3.2.103 NAME 'nsDS5ReplicationAgreement' DESC 'Netscape defined objectclass' SUP top MUST ( cn ) MAY ( nsds5ReplicaCleanRUVNotified $ nsDS5ReplicaHost $ nsDS5ReplicaPort $ nsDS5ReplicaTransportInfo $ nsDS5ReplicaBindDN $ nsDS5ReplicaCredentials $ nsDS5ReplicaBindMethod $ nsDS5ReplicaRoot $ nsDS5ReplicatedAttributeList $ nsDS5ReplicatedAttributeListTotal $ nsDS5ReplicaUpdateSchedule $ nsds5BeginReplicaRefresh $ description $ nsds50ruv $ nsruvReplicaLastModified $ nsds5ReplicaTimeout $ nsds5replicaChangesSentSinceStartup $ nsds5replicaLastUpdateEnd $ nsds5replicaLastUpdateStart $ nsds5replicaLastUpdateStatus $ nsds5replicaUpdateInProgress $ nsds5replicaLastInitEnd $ nsds5ReplicaEnabled $ nsds5replicaLastInitStart $ nsds5replicaLastInitStatus $ nsds5debugreplicatimeout $ nsds5replicaBusyWaitTime $ nsds5ReplicaStripAttrs $ nsds5replicaSessionPauseTime ) X-ORIGIN 'Netscape Directory Server' )
+objectClasses: ( 2.16.840.1.113730.3.2.103 NAME 'nsDS5ReplicationAgreement' DESC 'Netscape defined objectclass' SUP top MUST ( cn ) MAY ( nsds5ReplicaCleanRUVNotified $ nsDS5ReplicaHost $ nsDS5ReplicaPort $ nsDS5ReplicaTransportInfo $ nsDS5ReplicaBindDN $ nsDS5ReplicaCredentials $ nsDS5ReplicaBindMethod $ nsDS5ReplicaRoot $ nsDS5ReplicatedAttributeList $ nsDS5ReplicatedAttributeListTotal $ nsDS5ReplicaUpdateSchedule $ nsds5BeginReplicaRefresh $ description $ nsds50ruv $ nsruvReplicaLastModified $ nsds5ReplicaTimeout $ nsds5replicaChangesSentSinceStartup $ nsds5replicaLastUpdateEnd $ nsds5replicaLastUpdateStart $ nsds5replicaLastUpdateStatus $ nsds5replicaUpdateInProgress $ nsds5replicaLastInitEnd $ nsds5ReplicaEnabled $ nsds5replicaLastInitStart $ nsds5replicaLastInitStatus $ nsds5debugreplicatimeout $ nsds5replicaBusyWaitTime $ nsds5ReplicaStripAttrs $ nsds5replicaSessionPauseTime $ nsDS5ReplicaWaitForAsyncResults ) X-ORIGIN 'Netscape Directory Server' )
 objectClasses: ( 2.16.840.1.113730.3.2.39 NAME 'nsslapdConfig' DESC 'Netscape defined objectclass' SUP top MAY ( cn ) X-ORIGIN 'Netscape Directory Server' )
 objectClasses: ( 2.16.840.1.113730.3.2.317 NAME 'nsSaslMapping' DESC 'Netscape defined objectclass' SUP top MUST ( cn $ nsSaslMapRegexString $ nsSaslMapBaseDNTemplate $ nsSaslMapFilterTemplate ) X-ORIGIN 'Netscape Directory Server' )
 objectClasses: ( 2.16.840.1.113730.3.2.43 NAME 'nsSNMP' DESC 'Netscape defined objectclass' SUP top MUST ( cn $ nsSNMPEnabled ) MAY ( nsSNMPOrganization $ nsSNMPLocation $ nsSNMPContact $ nsSNMPDescription $ nsSNMPName $ nsSNMPMasterHost $ nsSNMPMasterPort ) X-ORIGIN 'Netscape Directory Server' )
diff --git a/ldap/servers/plugins/replication/repl5.h b/ldap/servers/plugins/replication/repl5.h
index a5761be..b1549f6 100644
--- a/ldap/servers/plugins/replication/repl5.h
+++ b/ldap/servers/plugins/replication/repl5.h
@@ -183,6 +183,9 @@ extern const char *type_winsyncMoveAction;
 /* To Allow Consumer Initialisation when adding an agreement - */
 extern const char *type_nsds5BeginReplicaRefresh;
 
+/* For tuning replica release */
+extern const char *type_nsds5WaitForAsyncResults;
+
 /* replica related attributes */
 extern const char *attr_replicaId;
 extern const char *attr_replicaRoot;
@@ -686,6 +689,8 @@ void repl5_set_debug_timeout(const char *val);
 /* temp hack XXX */
 ReplicaId agmt_get_consumerRID(Repl_Agmt *ra);
 
+/* For replica release tuning */
+int agmt_get_WaitForAsyncResults(Repl_Agmt *ra);
 
 void windows_init_agreement_from_entry(Repl_Agmt *ra, Slapi_Entry *e);
 int windows_handle_modify_agreement(Repl_Agmt *ra, const char *type, Slapi_Entry *e);
diff --git a/ldap/servers/plugins/replication/repl5_agmt.c b/ldap/servers/plugins/replication/repl5_agmt.c
index 708966a..ca77dd0 100644
--- a/ldap/servers/plugins/replication/repl5_agmt.c
+++ b/ldap/servers/plugins/replication/repl5_agmt.c
@@ -142,6 +142,8 @@ typedef struct repl5agmt {
 	char **attrs_to_strip; /* for fractional replication, if a "mod" is empty, strip out these attributes:
 	                        * modifiersname, modifytimestamp, internalModifiersname, internalModifyTimestamp, etc */
 	int agreement_type;
+	int WaitForAsyncResults; /* Pass to DS_Sleep(PR_MillisecondsToInterval(WaitForAsyncResults))
+	                               * in repl5_inc_waitfor_async_results */
 } repl5agmt;
 
 /* Forward declarations */
@@ -295,7 +297,8 @@ agmt_new_from_entry(Slapi_Entry *e)
 	ra->port = slapi_entry_attr_get_int(e, type_nsds5ReplicaPort);
 	/* SSL, TLS, or other transport stuff */
 	ra->transport_flags = 0;
-	agmt_set_transportinfo_no_lock(ra, e);
+	(void) agmt_set_transportinfo_no_lock(ra, e);
+	(void) agmt_set_WaitForAsyncResults(ra, e);
 
 	/* DN to use when binding. May be empty if certain SASL auth is to be used e.g. EXTERNAL GSSAPI. */
 	ra->binddn = slapi_entry_attr_get_charptr(e, type_nsds5ReplicaBindDN);
@@ -1596,6 +1599,33 @@ agmt_set_transportinfo_no_lock(Repl_Agmt *ra, const Slapi_Entry *e)
 	return (rc);
 }
 
+int
+agmt_set_WaitForAsyncResults(Repl_Agmt *ra, const Slapi_Entry *e)
+{
+	char *tmpstr;
+	int wait = 0;
+	
+	tmpstr = slapi_entry_attr_get_charptr(e, type_nsds5WaitForAsyncResults);
+	if (tmpstr) {
+		wait = strtol(tmpstr, (char **)NULL, 10);
+		if (wait <= 0) {
+			ra->WaitForAsyncResults = 1000; /* 1 sec */
+		} else {
+			ra->WaitForAsyncResults = wait;
+		}
+		slapi_ch_free_string(&tmpstr);
+	} else {
+		ra->WaitForAsyncResults = 1000; /* 1 sec */
+	}
+	return 0;
+}
+
+int
+agmt_get_WaitForAsyncResults(Repl_Agmt *ra)
+{
+	return ra->WaitForAsyncResults;
+}
+
 int 
 agmt_set_transportinfo_from_entry(Repl_Agmt *ra, const Slapi_Entry *e) 
 {
diff --git a/ldap/servers/plugins/replication/repl5_inc_protocol.c b/ldap/servers/plugins/replication/repl5_inc_protocol.c
index 5d3e143..059fd14 100644
--- a/ldap/servers/plugins/replication/repl5_inc_protocol.c
+++ b/ldap/servers/plugins/replication/repl5_inc_protocol.c
@@ -109,6 +109,7 @@ typedef struct result_data
 	int last_message_id_sent;
 	int last_message_id_received;
 	int result; /* The UPDATE_TRANSIENT_ERROR etc */
+	int WaitForAsyncResults;
 } result_data;
 
 /* Various states the incremental protocol can pass through */
@@ -485,7 +486,7 @@ repl5_inc_waitfor_async_results(result_data *rd)
 		}
 		PR_Unlock(rd->lock);
 		/* If not then sleep a bit */
-		DS_Sleep(PR_SecondsToInterval(1));
+		DS_Sleep(PR_MillisecondsToInterval(rd->WaitForAsyncResults));
 		loops++;
 		/* If we sleep forever then we can conclude that something bad happened, and bail... */
 		/* Arbitrary 30 second delay : basically we should only expect to wait as long as it takes to process a few operations, which should be on the order of a second at most */
@@ -1881,6 +1882,7 @@ send_updates(Private_Repl_Protocol *prp, RUV *remote_update_vector, PRUint32 *nu
 		{
 			/* We need to ensure that we wait until all the responses have been received from our operations */
 			if (return_value != UPDATE_CONNECTION_LOST) {
+				rd->WaitForAsyncResults = agmt_get_WaitForAsyncResults(prp->agmt);
 				/* if connection was lost/closed, there will be nothing to read */
 				repl5_inc_waitfor_async_results(rd);
 			}
diff --git a/ldap/servers/plugins/replication/repl_globals.c b/ldap/servers/plugins/replication/repl_globals.c
index f31a476..140a3dd 100644
--- a/ldap/servers/plugins/replication/repl_globals.c
+++ b/ldap/servers/plugins/replication/repl_globals.c
@@ -131,6 +131,7 @@ const char *type_nsds5ReplicaSessionPauseTime = "nsds5ReplicaSessionPauseTime";
 const char *type_nsds5ReplicaEnabled = "nsds5ReplicaEnabled";
 const char *type_nsds5ReplicaStripAttrs = "nsds5ReplicaStripAttrs";
 const char *type_nsds5ReplicaCleanRUVnotified = "nsds5ReplicaCleanRUVNotified";
+const char *type_nsds5WaitForAsyncResults = "nsds5ReplicaWaitForAsyncResults";
 
 /* windows sync specific attributes */
 const char *type_nsds7WindowsReplicaArea = "nsds7WindowsReplicaSubtree";
-- 
1.9.3

