andykimpe / rpms / 389-ds-base

Forked from rpms/389-ds-base 5 months ago
Clone
dc8c34
From 2ae48266c49d391664796bd3320319a06408acb8 Mon Sep 17 00:00:00 2001
dc8c34
From: Noriko Hosoi <nhosoi@redhat.com>
dc8c34
Date: Thu, 2 Apr 2015 13:09:12 -0700
dc8c34
Subject: [PATCH 310/319] Ticket #47942 - DS hangs during online total update
dc8c34
dc8c34
Backported the patch in the master branch to 389-ds-base-1.2.11
dc8c34
by Jatin Nansi (jnansi@redhat.com).
dc8c34
  commit fbafee54dc17e0673004d6d26d739ea1b19dd578
dc8c34
  Author: Thierry bordaz (tbordaz) <tbordaz@redhat.com>
dc8c34
  Date:   Mon Dec 15 15:12:35 2014 +0100
dc8c34
  Ticket 47942: DS hangs during online total update
dc8c34
dc8c34
Reviewed by tbordaz@redhat.com and nhosoi@redhat.com.
dc8c34
dc8c34
https://fedorahosted.org/389/ticket/47942
dc8c34
(cherry picked from commit 88ecf0c9b43060822e5bc9a3ba38b48438c296e6)
dc8c34
---
dc8c34
 ldap/schema/01core389.ldif                         |   4 +-
dc8c34
 ldap/servers/plugins/replication/repl5.h           |  11 ++
dc8c34
 ldap/servers/plugins/replication/repl5_agmt.c      | 160 ++++++++++++++++++++
dc8c34
 ldap/servers/plugins/replication/repl5_agmtlist.c  |  26 ++++
dc8c34
 .../servers/plugins/replication/repl5_connection.c | 165 ++++++++++++++++++++-
dc8c34
 .../plugins/replication/repl5_inc_protocol.c       |  32 +++-
dc8c34
 .../plugins/replication/repl5_prot_private.h       |   2 +
dc8c34
 .../plugins/replication/repl5_tot_protocol.c       |  52 ++++++-
dc8c34
 ldap/servers/plugins/replication/repl_globals.c    |   3 +
dc8c34
 9 files changed, 449 insertions(+), 6 deletions(-)
dc8c34
dc8c34
diff --git a/ldap/schema/01core389.ldif b/ldap/schema/01core389.ldif
dc8c34
index a1f993f..f8924fa 100644
dc8c34
--- a/ldap/schema/01core389.ldif
dc8c34
+++ b/ldap/schema/01core389.ldif
dc8c34
@@ -153,6 +153,8 @@ attributeTypes: ( 2.16.840.1.113730.3.1.2152 NAME 'nsds5ReplicaProtocolTimeout'
dc8c34
 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' )
dc8c34
 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' )
dc8c34
 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' )
dc8c34
+attributeTypes: ( 2.16.840.1.113730.3.1.2310 NAME 'nsds5ReplicaFlowControlWindow' DESC 'Netscape defined attribute type' SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 SINGLE-VALUE X-ORIGIN 'Netscape Directory Server' ) 
dc8c34
+attributeTypes: ( 2.16.840.1.113730.3.1.2311 NAME 'nsds5ReplicaFlowControlPause' DESC 'Netscape defined attribute type' SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 SINGLE-VALUE X-ORIGIN 'Netscape Directory Server' ) 
dc8c34
 #
dc8c34
 # objectclasses
dc8c34
 #
dc8c34
@@ -164,7 +166,7 @@ objectClasses: ( 2.16.840.1.113730.3.2.110 NAME 'nsMappingTree' DESC 'Netscape d
dc8c34
 objectClasses: ( 2.16.840.1.113730.3.2.104 NAME 'nsContainer' DESC 'Netscape defined objectclass' SUP top  MUST ( CN ) X-ORIGIN 'Netscape Directory Server' )
dc8c34
 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' )
dc8c34
 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' )
dc8c34
-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' )
dc8c34
+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  $ nsds5ReplicaFlowControlWindow $ nsds5ReplicaFlowControlPause ) X-ORIGIN 'Netscape Directory Server' )
dc8c34
 objectClasses: ( 2.16.840.1.113730.3.2.39 NAME 'nsslapdConfig' DESC 'Netscape defined objectclass' SUP top MAY ( cn ) X-ORIGIN 'Netscape Directory Server' )
dc8c34
 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' )
dc8c34
 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' )
dc8c34
diff --git a/ldap/servers/plugins/replication/repl5.h b/ldap/servers/plugins/replication/repl5.h
dc8c34
index a5761be..231daf5 100644
dc8c34
--- a/ldap/servers/plugins/replication/repl5.h
dc8c34
+++ b/ldap/servers/plugins/replication/repl5.h
dc8c34
@@ -168,6 +168,9 @@ extern const char *type_nsds5ReplicaSessionPauseTime;
dc8c34
 extern const char *type_nsds5ReplicaEnabled;
dc8c34
 extern const char *type_nsds5ReplicaStripAttrs;
dc8c34
 extern const char *type_nsds5ReplicaCleanRUVnotified;
dc8c34
+extern const char *type_nsds5ReplicaFlowControlWindow;
dc8c34
+extern const char *type_nsds5ReplicaFlowControlPause;
dc8c34
+
dc8c34
 
dc8c34
 /* Attribute names for windows replication agreements */
dc8c34
 extern const char *type_nsds7WindowsReplicaArea;
dc8c34
@@ -312,6 +315,8 @@ int agmt_get_auto_initialize(const Repl_Agmt *ra);
dc8c34
 long agmt_get_timeout(const Repl_Agmt *ra);
dc8c34
 long agmt_get_busywaittime(const Repl_Agmt *ra);
dc8c34
 long agmt_get_pausetime(const Repl_Agmt *ra);
dc8c34
+long agmt_get_flowcontrolwindow(const Repl_Agmt *ra);
dc8c34
+long agmt_get_flowcontrolpause(const Repl_Agmt *ra);
dc8c34
 int agmt_start(Repl_Agmt *ra);
dc8c34
 int windows_agmt_start(Repl_Agmt *ra); 
dc8c34
 int agmt_stop(Repl_Agmt *ra);
dc8c34
@@ -332,6 +337,8 @@ int agmt_replarea_matches(const Repl_Agmt *ra, const Slapi_DN *name);
dc8c34
 int agmt_schedule_in_window_now(const Repl_Agmt *ra);
dc8c34
 int agmt_set_schedule_from_entry( Repl_Agmt *ra, const Slapi_Entry *e );
dc8c34
 int agmt_set_timeout_from_entry( Repl_Agmt *ra, const Slapi_Entry *e );
dc8c34
+int agmt_set_flowcontrolwindow_from_entry(Repl_Agmt *ra, const Slapi_Entry *e);
dc8c34
+int agmt_set_flowcontrolpause_from_entry(Repl_Agmt *ra, const Slapi_Entry *e);
dc8c34
 int agmt_set_busywaittime_from_entry( Repl_Agmt *ra, const Slapi_Entry *e );
dc8c34
 int agmt_set_pausetime_from_entry( Repl_Agmt *ra, const Slapi_Entry *e );
dc8c34
 int agmt_set_credentials_from_entry( Repl_Agmt *ra, const Slapi_Entry *e );
dc8c34
@@ -463,6 +470,10 @@ void conn_lock(Repl_Connection *conn);
dc8c34
 void conn_unlock(Repl_Connection *conn);
dc8c34
 void conn_delete_internal_ext(Repl_Connection *conn);
dc8c34
 const char* conn_get_bindmethod(Repl_Connection *conn);
dc8c34
+void conn_set_tot_update_cb(Repl_Connection *conn, void *cb_data); 
dc8c34
+void conn_set_tot_update_cb_nolock(Repl_Connection *conn, void *cb_data); 
dc8c34
+void conn_get_tot_update_cb(Repl_Connection *conn, void **cb_data); 
dc8c34
+void conn_get_tot_update_cb_nolock(Repl_Connection *conn, void **cb_data); 
dc8c34
 
dc8c34
 /* In repl5_protocol.c */
dc8c34
 typedef struct repl_protocol Repl_Protocol;
dc8c34
diff --git a/ldap/servers/plugins/replication/repl5_agmt.c b/ldap/servers/plugins/replication/repl5_agmt.c
dc8c34
index 708966a..41a81ca 100644
dc8c34
--- a/ldap/servers/plugins/replication/repl5_agmt.c
dc8c34
+++ b/ldap/servers/plugins/replication/repl5_agmt.c
dc8c34
@@ -87,6 +87,8 @@
dc8c34
 #include "slapi-plugin.h"
dc8c34
 
dc8c34
 #define DEFAULT_TIMEOUT 600 /* (seconds) default outbound LDAP connection */
dc8c34
+#define DEFAULT_FLOWCONTROL_WINDOW 1000 /* #entries sent without acknowledgment */
dc8c34
+#define DEFAULT_FLOWCONTROL_PAUSE 2000 /* msec of pause when #entries sent witout acknowledgment */
dc8c34
 #define STATUS_LEN 1024
dc8c34
 
dc8c34
 struct changecounter {
dc8c34
@@ -142,6 +144,12 @@ typedef struct repl5agmt {
dc8c34
 	char **attrs_to_strip; /* for fractional replication, if a "mod" is empty, strip out these attributes:
dc8c34
 	                        * modifiersname, modifytimestamp, internalModifiersname, internalModifyTimestamp, etc */
dc8c34
 	int agreement_type;
dc8c34
+	long flowControlWindow; /* This is the maximum number of entries 
dc8c34
+	                         * sent without acknowledgment
dc8c34
+	                         */
dc8c34
+	long flowControlPause; /* When nb of not acknowledged entries overpass totalUpdateWindow
dc8c34
+	                        * This is the duration (in msec) that the RA will pause before sending the next entry
dc8c34
+	                        */
dc8c34
 } repl5agmt;
dc8c34
 
dc8c34
 /* Forward declarations */
dc8c34
@@ -332,6 +340,27 @@ agmt_new_from_entry(Slapi_Entry *e)
dc8c34
 			ra->timeout = slapi_value_get_long(sval);
dc8c34
 		}
dc8c34
 	}
dc8c34
+	/* flow control update window. */
dc8c34
+	ra->flowControlWindow = DEFAULT_FLOWCONTROL_WINDOW;
dc8c34
+	if (slapi_entry_attr_find(e, type_nsds5ReplicaFlowControlWindow, &sattr) == 0)
dc8c34
+	{
dc8c34
+		Slapi_Value *sval;
dc8c34
+		if (slapi_attr_first_value(sattr, &sval) == 0)
dc8c34
+		{
dc8c34
+			ra->flowControlWindow = slapi_value_get_long(sval);
dc8c34
+		}
dc8c34
+	}
dc8c34
+
dc8c34
+	/* flow control update pause. */
dc8c34
+	ra->flowControlPause = DEFAULT_FLOWCONTROL_PAUSE;
dc8c34
+	if (slapi_entry_attr_find(e, type_nsds5ReplicaFlowControlPause, &sattr) == 0)
dc8c34
+	{
dc8c34
+		Slapi_Value *sval;
dc8c34
+		if (slapi_attr_first_value(sattr, &sval) == 0)
dc8c34
+		{
dc8c34
+			ra->flowControlPause = slapi_value_get_long(sval);
dc8c34
+		}
dc8c34
+	}
dc8c34
 
dc8c34
 	/* DN of entry at root of replicated area */
dc8c34
 	tmpstr = slapi_entry_attr_get_charptr(e, type_nsds5ReplicaRoot);
dc8c34
@@ -963,6 +992,26 @@ agmt_get_pausetime(const Repl_Agmt *ra)
dc8c34
 	return return_value;
dc8c34
 }
dc8c34
 
dc8c34
+long
dc8c34
+agmt_get_flowcontrolwindow(const Repl_Agmt *ra)
dc8c34
+{
dc8c34
+	long return_value;
dc8c34
+	PR_ASSERT(NULL != ra);
dc8c34
+	PR_Lock(ra->lock);
dc8c34
+	return_value = ra->flowControlWindow;
dc8c34
+	PR_Unlock(ra->lock);
dc8c34
+	return return_value;
dc8c34
+}
dc8c34
+long
dc8c34
+agmt_get_flowcontrolpause(const Repl_Agmt *ra)
dc8c34
+{
dc8c34
+	long return_value;
dc8c34
+	PR_ASSERT(NULL != ra);
dc8c34
+	PR_Lock(ra->lock);
dc8c34
+	return_value = ra->flowControlPause;
dc8c34
+	PR_Unlock(ra->lock);
dc8c34
+	return return_value;
dc8c34
+}
dc8c34
 /*
dc8c34
  * Warning - reference to the long name of the agreement is returned.
dc8c34
  * The long name of an agreement is the DN of the agreement entry,
dc8c34
@@ -1694,6 +1743,90 @@ agmt_set_timeout_from_entry(Repl_Agmt *ra, const Slapi_Entry *e)
dc8c34
 	return return_value;
dc8c34
 }
dc8c34
 
dc8c34
+/*
dc8c34
+ * Set or reset the windows of entries sent without acknowledgment.
dc8c34
+ * The window is used during update to determine the number of
dc8c34
+ * entries will be send by the replica agreement without acknowledgment from the consumer
dc8c34
+ *
dc8c34
+ * Returns 0 if window set, or -1 if an error occurred.
dc8c34
+ */
dc8c34
+int
dc8c34
+agmt_set_flowcontrolwindow_from_entry(Repl_Agmt *ra, const Slapi_Entry *e)
dc8c34
+{
dc8c34
+	Slapi_Attr *sattr = NULL;
dc8c34
+	int return_value = -1;
dc8c34
+
dc8c34
+	PR_ASSERT(NULL != ra);
dc8c34
+	PR_Lock(ra->lock);
dc8c34
+	if (ra->stop_in_progress)
dc8c34
+	{
dc8c34
+		PR_Unlock(ra->lock);
dc8c34
+		return return_value;
dc8c34
+	}
dc8c34
+
dc8c34
+	slapi_entry_attr_find(e, type_nsds5ReplicaFlowControlWindow, &sattr);
dc8c34
+	if (NULL != sattr)
dc8c34
+	{
dc8c34
+		Slapi_Value *sval = NULL;
dc8c34
+		slapi_attr_first_value(sattr, &sval);
dc8c34
+		if (NULL != sval)
dc8c34
+		{
dc8c34
+			long tmpval = slapi_value_get_long(sval);
dc8c34
+			if (tmpval >= 0) {
dc8c34
+				ra->flowControlWindow = tmpval;
dc8c34
+				return_value = 0; /* success! */
dc8c34
+			}
dc8c34
+		}
dc8c34
+	}
dc8c34
+	PR_Unlock(ra->lock);
dc8c34
+	if (return_value == 0)
dc8c34
+	{
dc8c34
+		prot_notify_agmt_changed(ra->protocol, ra->long_name);
dc8c34
+	}
dc8c34
+	return return_value;
dc8c34
+}
dc8c34
+
dc8c34
+/*
dc8c34
+ * Set or reset the pause duration when #entries sent without acknowledgment overpass flow control window
dc8c34
+ *
dc8c34
+ * Returns 0 if pause set, or -1 if an error occurred.
dc8c34
+ */
dc8c34
+int
dc8c34
+agmt_set_flowcontrolpause_from_entry(Repl_Agmt *ra, const Slapi_Entry *e)
dc8c34
+{
dc8c34
+	Slapi_Attr *sattr = NULL;
dc8c34
+	int return_value = -1;
dc8c34
+
dc8c34
+	PR_ASSERT(NULL != ra);
dc8c34
+	PR_Lock(ra->lock);
dc8c34
+	if (ra->stop_in_progress)
dc8c34
+	{
dc8c34
+		PR_Unlock(ra->lock);
dc8c34
+		return return_value;
dc8c34
+	}
dc8c34
+
dc8c34
+	slapi_entry_attr_find(e, type_nsds5ReplicaFlowControlPause, &sattr);
dc8c34
+	if (NULL != sattr)
dc8c34
+	{
dc8c34
+		Slapi_Value *sval = NULL;
dc8c34
+		slapi_attr_first_value(sattr, &sval);
dc8c34
+		if (NULL != sval)
dc8c34
+		{
dc8c34
+			long tmpval = slapi_value_get_long(sval);
dc8c34
+			if (tmpval >= 0) {
dc8c34
+				ra->flowControlPause = tmpval;
dc8c34
+				return_value = 0; /* success! */
dc8c34
+			}
dc8c34
+		}
dc8c34
+	}
dc8c34
+	PR_Unlock(ra->lock);
dc8c34
+	if (return_value == 0)
dc8c34
+	{
dc8c34
+		prot_notify_agmt_changed(ra->protocol, ra->long_name);
dc8c34
+	}
dc8c34
+	return return_value;
dc8c34
+}
dc8c34
+
dc8c34
 int
dc8c34
 agmt_set_timeout(Repl_Agmt *ra, long timeout)
dc8c34
 {
dc8c34
@@ -1708,6 +1841,33 @@ agmt_set_timeout(Repl_Agmt *ra, long timeout)
dc8c34
     return 0;
dc8c34
 }
dc8c34
 
dc8c34
+int
dc8c34
+agmt_set_flowcontrolwindow(Repl_Agmt *ra, long window)
dc8c34
+{
dc8c34
+    PR_Lock(ra->lock);
dc8c34
+    if (ra->stop_in_progress){
dc8c34
+        PR_Unlock(ra->lock);
dc8c34
+        return -1;
dc8c34
+    }
dc8c34
+    ra->flowControlWindow = window;
dc8c34
+    PR_Unlock(ra->lock);
dc8c34
+
dc8c34
+    return 0;
dc8c34
+}
dc8c34
+int
dc8c34
+agmt_set_flowcontrolpause(Repl_Agmt *ra, long pause)
dc8c34
+{
dc8c34
+    PR_Lock(ra->lock);
dc8c34
+    if (ra->stop_in_progress){
dc8c34
+        PR_Unlock(ra->lock);
dc8c34
+        return -1;
dc8c34
+    }
dc8c34
+    ra->flowControlPause = pause;
dc8c34
+    PR_Unlock(ra->lock);
dc8c34
+
dc8c34
+    return 0;
dc8c34
+}
dc8c34
+
dc8c34
 /*
dc8c34
  * Set or reset the busywaittime
dc8c34
  *
dc8c34
diff --git a/ldap/servers/plugins/replication/repl5_agmtlist.c b/ldap/servers/plugins/replication/repl5_agmtlist.c
dc8c34
index d37704d..caa41af 100644
dc8c34
--- a/ldap/servers/plugins/replication/repl5_agmtlist.c
dc8c34
+++ b/ldap/servers/plugins/replication/repl5_agmtlist.c
dc8c34
@@ -345,6 +345,32 @@ agmtlist_modify_callback(Slapi_PBlock *pb, Slapi_Entry *entryBefore, Slapi_Entry
dc8c34
             }
dc8c34
 		}
dc8c34
 		else if (slapi_attr_types_equivalent(mods[i]->mod_type,
dc8c34
+					type_nsds5ReplicaFlowControlWindow))
dc8c34
+		{
dc8c34
+			/* New replica timeout */
dc8c34
+			if (agmt_set_flowcontrolwindow_from_entry(agmt, e) != 0)
dc8c34
+			{
dc8c34
+				slapi_log_error(SLAPI_LOG_REPL, repl_plugin_name, "agmtlist_modify_callback: " 
dc8c34
+						"failed to update the flow control window for agreement %s\n",
dc8c34
+						agmt_get_long_name(agmt));	
dc8c34
+				*returncode = LDAP_OPERATIONS_ERROR;
dc8c34
+				rc = SLAPI_DSE_CALLBACK_ERROR;
dc8c34
+			}
dc8c34
+		}
dc8c34
+		else if (slapi_attr_types_equivalent(mods[i]->mod_type,
dc8c34
+					type_nsds5ReplicaFlowControlPause))
dc8c34
+		{
dc8c34
+			/* New replica timeout */
dc8c34
+			if (agmt_set_flowcontrolpause_from_entry(agmt, e) != 0)
dc8c34
+			{
dc8c34
+				slapi_log_error(SLAPI_LOG_REPL, repl_plugin_name, "agmtlist_modify_callback: " 
dc8c34
+						"failed to update the flow control pause for agreement %s\n",
dc8c34
+						agmt_get_long_name(agmt));	
dc8c34
+				*returncode = LDAP_OPERATIONS_ERROR;
dc8c34
+				rc = SLAPI_DSE_CALLBACK_ERROR;
dc8c34
+			}
dc8c34
+		}
dc8c34
+		else if (slapi_attr_types_equivalent(mods[i]->mod_type,
dc8c34
 					type_nsds5ReplicaBusyWaitTime))
dc8c34
 		{
dc8c34
 			/* New replica busywaittime */
dc8c34
diff --git a/ldap/servers/plugins/replication/repl5_connection.c b/ldap/servers/plugins/replication/repl5_connection.c
dc8c34
index 5efd0e6..e080a3f 100644
dc8c34
--- a/ldap/servers/plugins/replication/repl5_connection.c
dc8c34
+++ b/ldap/servers/plugins/replication/repl5_connection.c
dc8c34
@@ -52,6 +52,7 @@ replica locked. Seems like right thing to do.
dc8c34
 */
dc8c34
 
dc8c34
 #include "repl5.h"
dc8c34
+#include "repl5_prot_private.h"
dc8c34
 #if defined(USE_OPENLDAP)
dc8c34
 #include "ldap.h"
dc8c34
 #else
dc8c34
@@ -90,6 +91,7 @@ typedef struct repl_connection
dc8c34
 	struct timeval timeout;
dc8c34
 	int flag_agmt_changed;
dc8c34
 	char *plain;
dc8c34
+	void *tot_init_callback; /* Used during total update to do flow control */
dc8c34
 } repl_connection;
dc8c34
 
dc8c34
 /* #define DEFAULT_LINGER_TIME (5 * 60) */ /* 5 minutes */
dc8c34
@@ -277,6 +279,32 @@ conn_get_error(Repl_Connection *conn, int *operation, int *error)
dc8c34
 	PR_Unlock(conn->lock);
dc8c34
 }
dc8c34
 
dc8c34
+void
dc8c34
+conn_set_tot_update_cb_nolock(Repl_Connection *conn, void *cb_data)
dc8c34
+{
dc8c34
+    conn->tot_init_callback = (void *) cb_data;
dc8c34
+}
dc8c34
+void
dc8c34
+conn_set_tot_update_cb(Repl_Connection *conn, void *cb_data)
dc8c34
+{
dc8c34
+	PR_Lock(conn->lock);
dc8c34
+	conn_set_tot_update_cb_nolock(conn, cb_data);
dc8c34
+	PR_Unlock(conn->lock);
dc8c34
+}
dc8c34
+
dc8c34
+void
dc8c34
+conn_get_tot_update_cb_nolock(Repl_Connection *conn, void **cb_data)
dc8c34
+{
dc8c34
+    *cb_data = (void *) conn->tot_init_callback;
dc8c34
+}
dc8c34
+void
dc8c34
+conn_get_tot_update_cb(Repl_Connection *conn, void **cb_data)
dc8c34
+{
dc8c34
+	PR_Lock(conn->lock);
dc8c34
+	conn_get_tot_update_cb_nolock(conn, cb_data);
dc8c34
+	PR_Unlock(conn->lock);
dc8c34
+}
dc8c34
+
dc8c34
 /*
dc8c34
  * Return the last operation type processed by the connection
dc8c34
  * object, and the LDAP error encountered.
dc8c34
@@ -629,6 +657,133 @@ see_if_write_available(Repl_Connection *conn, PRIntervalTime timeout)
dc8c34
 }
dc8c34
 #endif /* ! USE_OPENLDAP */
dc8c34
 
dc8c34
+/* 
dc8c34
+ * During a total update, this function checks how much entries
dc8c34
+ * have been sent to the consumer without having received their acknowledgment.
dc8c34
+ * Basically it checks how late is the consumer.
dc8c34
+ * 
dc8c34
+ * If the consumer is too late, it pause the RA.sender (releasing the lock) to
dc8c34
+ * let the consumer to catch up and RA.reader to receive the acknowledgments.
dc8c34
+ * 
dc8c34
+ * Caller must hold conn->lock
dc8c34
+ */
dc8c34
+static void
dc8c34
+check_flow_control_tot_init(Repl_Connection *conn, int optype, const char *extop_oid, int sent_msgid)
dc8c34
+{
dc8c34
+    int rcv_msgid;
dc8c34
+    int once;
dc8c34
+    
dc8c34
+    if ((sent_msgid != 0) && (optype == CONN_EXTENDED_OPERATION) && (strcmp(extop_oid, REPL_NSDS50_REPLICATION_ENTRY_REQUEST_OID) == 0)) {
dc8c34
+        /* We are sending entries part of the total update of a consumer
dc8c34
+         * Wait a bit if the consumer needs to catchup from the current sent entries
dc8c34
+         */
dc8c34
+        rcv_msgid = repl5_tot_last_rcv_msgid(conn);
dc8c34
+        if (rcv_msgid == -1) {
dc8c34
+            slapi_log_error(SLAPI_LOG_FATAL, repl_plugin_name,
dc8c34
+                            "%s: check_flow_control_tot_init no callback data [ msgid sent: %d]\n",
dc8c34
+                            agmt_get_long_name(conn->agmt),
dc8c34
+                            sent_msgid);
dc8c34
+        } else if (sent_msgid < rcv_msgid) {
dc8c34
+            slapi_log_error(SLAPI_LOG_REPL, repl_plugin_name,
dc8c34
+                            "%s: check_flow_control_tot_init invalid message ids [ msgid sent: %d, rcv: %d]\n",
dc8c34
+                            agmt_get_long_name(conn->agmt),
dc8c34
+                            sent_msgid,
dc8c34
+                            rcv_msgid);
dc8c34
+        } else if ((sent_msgid - rcv_msgid) > agmt_get_flowcontrolwindow(conn->agmt)) {
dc8c34
+            int totalUpdatePause;
dc8c34
+
dc8c34
+            totalUpdatePause = agmt_get_flowcontrolpause(conn->agmt);
dc8c34
+            if (totalUpdatePause) {
dc8c34
+                /* The consumer is late. Last sent entry compare to last acknowledged entry 
dc8c34
+                 * overpass the allowed limit (flowcontrolwindow)
dc8c34
+                 * Give some time to the consumer to catch up
dc8c34
+                 */
dc8c34
+                once = repl5_tot_flowcontrol_detection(conn, 1);
dc8c34
+                PR_Unlock(conn->lock);
dc8c34
+                if (once == 1) {
dc8c34
+                    /* This is the first time we hit total update flow control.
dc8c34
+                     * Log it at least once to inform administrator there is
dc8c34
+                     * a potential configuration issue here
dc8c34
+                     */
dc8c34
+                    slapi_log_error(SLAPI_LOG_FATAL, repl_plugin_name,
dc8c34
+                            "%s: Total update flow control gives time (%d msec) to the consumer before sending more entries [ msgid sent: %d, rcv: %d])\n"
dc8c34
+                            "If total update fails you can try to increase %s and/or decrease %s in the replica agreement configuration\n",
dc8c34
+                            agmt_get_long_name(conn->agmt),
dc8c34
+                            totalUpdatePause,
dc8c34
+                            sent_msgid,
dc8c34
+                            rcv_msgid,
dc8c34
+                            type_nsds5ReplicaFlowControlPause,
dc8c34
+                            type_nsds5ReplicaFlowControlWindow);
dc8c34
+                }
dc8c34
+                DS_Sleep(PR_MillisecondsToInterval(totalUpdatePause));
dc8c34
+                PR_Lock(conn->lock);
dc8c34
+            }
dc8c34
+        }
dc8c34
+    }
dc8c34
+    
dc8c34
+}
dc8c34
+/* 
dc8c34
+ * Test if the connection is available to do a write.
dc8c34
+ * This function is doing a periodic polling of the connection.
dc8c34
+ * If the polling times out:
dc8c34
+ *  - it releases the connection lock (to let other thread ,i.e. 
dc8c34
+ *    replication result thread, the opportunity to use the connection)
dc8c34
+ *  - Sleeps for a short period (100ms)
dc8c34
+ *  - acquires the connection lock
dc8c34
+ * 
dc8c34
+ * It loops until
dc8c34
+ *  - it is available
dc8c34
+ *  - exceeds RA complete timeout
dc8c34
+ *  - server is shutdown
dc8c34
+ *  - connection is disconnected (Disable, stop, delete the RA
dc8c34
+ *    'terminate' the replication protocol and disconnect the connection)
dc8c34
+ * 
dc8c34
+ * Return:
dc8c34
+ *   - CONN_OPERATION_SUCCESS if the connection is available
dc8c34
+ *   - CONN_TIMEOUT if the overall polling/sleeping delay exceeds RA timeout
dc8c34
+ *   - CONN_NOT_CONNECTED if the replication connection state is disconnected
dc8c34
+ *   - other ConnResult
dc8c34
+ *
dc8c34
+ * Caller must hold conn->Lock. At the exit, conn->lock is held
dc8c34
+ */
dc8c34
+static ConnResult
dc8c34
+conn_is_available(Repl_Connection *conn)
dc8c34
+{
dc8c34
+    time_t poll_timeout_sec = 1; /* Polling for 1sec */
dc8c34
+    time_t yield_delay_msec = 100; /* Delay to wait */
dc8c34
+    time_t start_time = time( NULL );
dc8c34
+    time_t time_now;
dc8c34
+    ConnResult return_value = CONN_OPERATION_SUCCESS;
dc8c34
+    
dc8c34
+    while (!slapi_is_shutting_down() && (conn->state != STATE_DISCONNECTED)) {
dc8c34
+        return_value = see_if_write_available(conn, PR_SecondsToInterval(poll_timeout_sec));
dc8c34
+        if (return_value == CONN_TIMEOUT) {
dc8c34
+            /* in case of timeout we return CONN_TIMEOUT only
dc8c34
+             * if the RA.timeout is exceeded
dc8c34
+             */
dc8c34
+            time_now = time(NULL);
dc8c34
+            if (conn->timeout.tv_sec <= (time_now - start_time)) {
dc8c34
+                break;
dc8c34
+            } else {
dc8c34
+                /* Else give connection to others threads */
dc8c34
+                PR_Unlock(conn->lock);
dc8c34
+                slapi_log_error(SLAPI_LOG_REPL, repl_plugin_name,
dc8c34
+                        "%s: perform_operation transient timeout. retry)\n",
dc8c34
+                        agmt_get_long_name(conn->agmt));
dc8c34
+                DS_Sleep(PR_MillisecondsToInterval(yield_delay_msec));
dc8c34
+                PR_Lock(conn->lock);
dc8c34
+            }
dc8c34
+        } else {
dc8c34
+            break;
dc8c34
+        }
dc8c34
+    }
dc8c34
+    if (conn->state == STATE_DISCONNECTED) {
dc8c34
+        return_value = CONN_NOT_CONNECTED;
dc8c34
+    }
dc8c34
+    return return_value;
dc8c34
+}
dc8c34
+
dc8c34
+
dc8c34
 /*
dc8c34
  * Common code to send an LDAPv3 operation and collect the result.
dc8c34
  * Return values:
dc8c34
@@ -670,10 +825,13 @@ perform_operation(Repl_Connection *conn, int optype, const char *dn,
dc8c34
 
dc8c34
 		Slapi_Eq_Context eqctx = repl5_start_debug_timeout(&setlevel);
dc8c34
 
dc8c34
-		return_value = see_if_write_available(
dc8c34
-			conn, PR_SecondsToInterval(conn->timeout.tv_sec));
dc8c34
+                return_value = conn_is_available(conn);
dc8c34
 		if (return_value != CONN_OPERATION_SUCCESS) {
dc8c34
 			PR_Unlock(conn->lock);
dc8c34
+			slapi_log_error(SLAPI_LOG_FATAL, repl_plugin_name,
dc8c34
+							"%s: perform_operation connection is not available (%d)\n",
dc8c34
+							agmt_get_long_name(conn->agmt),
dc8c34
+							return_value);
dc8c34
 			return return_value;
dc8c34
 		}
dc8c34
 		conn->last_operation = optype;
dc8c34
@@ -745,6 +903,9 @@ perform_operation(Repl_Connection *conn, int optype, const char *dn,
dc8c34
 		 */
dc8c34
 		return_value = CONN_NOT_CONNECTED;
dc8c34
 	}
dc8c34
+    
dc8c34
+	check_flow_control_tot_init(conn, optype, extop_oid, msgid);
dc8c34
+
dc8c34
 	PR_Unlock(conn->lock); /* release the lock */
dc8c34
 	if (message_id)
dc8c34
 	{
dc8c34
diff --git a/ldap/servers/plugins/replication/repl5_inc_protocol.c b/ldap/servers/plugins/replication/repl5_inc_protocol.c
dc8c34
index ae26380..f5516a3 100644
dc8c34
--- a/ldap/servers/plugins/replication/repl5_inc_protocol.c
dc8c34
+++ b/ldap/servers/plugins/replication/repl5_inc_protocol.c
dc8c34
@@ -108,6 +108,7 @@ typedef struct result_data
dc8c34
 	int stop_result_thread; /* Flag used to tell the result thread to exit */
dc8c34
 	int last_message_id_sent;
dc8c34
 	int last_message_id_received;
dc8c34
+	int flowcontrol_detection;
dc8c34
 	int result; /* The UPDATE_TRANSIENT_ERROR etc */
dc8c34
 } result_data;
dc8c34
 
dc8c34
@@ -460,6 +461,23 @@ repl5_inc_destroy_async_result_thread(result_data *rd)
dc8c34
 	return retval;
dc8c34
 }
dc8c34
 
dc8c34
+/* The interest of this routine is to give time to the consumer
dc8c34
+ * to apply the sent updates and return the acks.
dc8c34
+ * So the caller should not hold the replication connection lock
dc8c34
+ * to let the RA.reader receives the acks.
dc8c34
+ */
dc8c34
+static void
dc8c34
+repl5_inc_flow_control_results(Repl_Agmt *agmt, result_data *rd)
dc8c34
+{
dc8c34
+    PR_Lock(rd->lock);
dc8c34
+    if ((rd->last_message_id_received <= rd->last_message_id_sent) &&
dc8c34
+        ((rd->last_message_id_sent - rd->last_message_id_received) >= agmt_get_flowcontrolwindow(agmt))) {
dc8c34
+        rd->flowcontrol_detection++;
dc8c34
+        DS_Sleep(PR_MillisecondsToInterval(agmt_get_flowcontrolpause(agmt)));
dc8c34
+    }
dc8c34
+    PR_Unlock(rd->lock);
dc8c34
+}
dc8c34
+
dc8c34
 static void
dc8c34
 repl5_inc_waitfor_async_results(result_data *rd)
dc8c34
 {
dc8c34
@@ -1669,7 +1687,7 @@ send_updates(Private_Repl_Protocol *prp, RUV *remote_update_vector, PRUint32 *nu
dc8c34
 	{
dc8c34
 		int finished = 0;
dc8c34
 		ConnResult replay_crc;
dc8c34
-        char csn_str[CSN_STRSIZE];
dc8c34
+		char csn_str[CSN_STRSIZE];
dc8c34
 
dc8c34
 		/* Start the results reading thread */
dc8c34
 		rd = repl5_inc_rd_new(prp);
dc8c34
@@ -1804,6 +1822,7 @@ send_updates(Private_Repl_Protocol *prp, RUV *remote_update_vector, PRUint32 *nu
dc8c34
 						sop->replica_id = replica_id;
dc8c34
 						PL_strncpyz(sop->uniqueid, uniqueid, sizeof(sop->uniqueid));
dc8c34
 						repl5_int_push_operation(rd,sop);
dc8c34
+						repl5_inc_flow_control_results(prp->agmt, rd);
dc8c34
 					} else {
dc8c34
 						slapi_log_error(SLAPI_LOG_REPL, repl_plugin_name,
dc8c34
 							"%s: Skipping update operation with no message_id (uniqueid %s, CSN %s):\n",
dc8c34
@@ -1892,6 +1911,17 @@ send_updates(Private_Repl_Protocol *prp, RUV *remote_update_vector, PRUint32 *nu
dc8c34
 			}
dc8c34
 			*num_changes_sent = rd->num_changes_sent;
dc8c34
 		}
dc8c34
+		PR_Lock(rd->lock);
dc8c34
+		if (rd->flowcontrol_detection) {
dc8c34
+			slapi_log_error(SLAPI_LOG_REPL, repl_plugin_name,
dc8c34
+					"%s: Incremental update flow control triggered %d times\n"
dc8c34
+					"You may increase %s and/or decrease %s in the replica agreement configuration\n",
dc8c34
+					agmt_get_long_name(prp->agmt),
dc8c34
+					rd->flowcontrol_detection,
dc8c34
+					type_nsds5ReplicaFlowControlPause,
dc8c34
+					type_nsds5ReplicaFlowControlWindow);             
dc8c34
+		}
dc8c34
+		PR_Unlock(rd->lock);
dc8c34
 		repl5_inc_rd_destroy(&rd);
dc8c34
 
dc8c34
 		cl5_operation_parameters_done ( entry.op );
dc8c34
diff --git a/ldap/servers/plugins/replication/repl5_prot_private.h b/ldap/servers/plugins/replication/repl5_prot_private.h
dc8c34
index 10aa02b..7ca31ca 100644
dc8c34
--- a/ldap/servers/plugins/replication/repl5_prot_private.h
dc8c34
+++ b/ldap/servers/plugins/replication/repl5_prot_private.h
dc8c34
@@ -79,6 +79,8 @@ typedef struct private_repl_protocol
dc8c34
 
dc8c34
 extern Private_Repl_Protocol *Repl_5_Inc_Protocol_new();
dc8c34
 extern Private_Repl_Protocol *Repl_5_Tot_Protocol_new();
dc8c34
+extern int repl5_tot_last_rcv_msgid(Repl_Connection *conn);
dc8c34
+extern int repl5_tot_flowcontrol_detection(Repl_Connection *conn, int increment);
dc8c34
 extern Private_Repl_Protocol *Windows_Inc_Protocol_new();
dc8c34
 extern Private_Repl_Protocol *Windows_Tot_Protocol_new();
dc8c34
 
dc8c34
diff --git a/ldap/servers/plugins/replication/repl5_tot_protocol.c b/ldap/servers/plugins/replication/repl5_tot_protocol.c
dc8c34
index 9829984..e514dc6 100644
dc8c34
--- a/ldap/servers/plugins/replication/repl5_tot_protocol.c
dc8c34
+++ b/ldap/servers/plugins/replication/repl5_tot_protocol.c
dc8c34
@@ -82,6 +82,7 @@ typedef struct callback_data
dc8c34
 	int stop_result_thread; /* Flag used to tell the result thread to exit */
dc8c34
 	int last_message_id_sent;
dc8c34
 	int last_message_id_received;
dc8c34
+	int flowcontrol_detection;
dc8c34
 } callback_data;
dc8c34
 
dc8c34
 /* 
dc8c34
@@ -416,12 +417,17 @@ repl5_tot_run(Private_Repl_Protocol *prp)
dc8c34
                                   LDAP_SCOPE_SUBTREE, "(|(objectclass=ldapsubentry)(objectclass=nstombstone)(nsuniqueid=*))", NULL, 0, ctrls, NULL, 
dc8c34
                                   repl_get_plugin_identity (PLUGIN_MULTIMASTER_REPLICATION), 0);
dc8c34
 
dc8c34
-    cb_data.prp = prp;
dc8c34
-    cb_data.rc = 0;
dc8c34
+	cb_data.prp = prp;
dc8c34
+	cb_data.rc = 0;
dc8c34
 	cb_data.num_entries = 0UL;
dc8c34
 	cb_data.sleep_on_busy = 0UL;
dc8c34
 	cb_data.last_busy = current_time ();
dc8c34
+	cb_data.flowcontrol_detection = 0;
dc8c34
 	cb_data.lock = PR_NewLock();
dc8c34
+	/* This allows during perform_operation to check the callback data
dc8c34
+	 * especially to do flow contol on delta send msgid / recv msgid
dc8c34
+	 */
dc8c34
+	conn_set_tot_update_cb(prp->conn, (void *) &cb_data);
dc8c34
 
dc8c34
 	/* Before we get started on sending entries to the replica, we need to 
dc8c34
 	 * setup things for async propagation: 
dc8c34
@@ -492,6 +498,17 @@ repl5_tot_run(Private_Repl_Protocol *prp)
dc8c34
 done:
dc8c34
 	slapi_sdn_free(&area_sdn);
dc8c34
 	slapi_ch_free_string(&hostname);
dc8c34
+	if (cb_data.flowcontrol_detection > 1)
dc8c34
+	{
dc8c34
+		slapi_log_error(SLAPI_LOG_FATAL, repl_plugin_name,
dc8c34
+			"%s: Total update flow control triggered %d times\n"
dc8c34
+			"You may increase %s and/or decrease %s in the replica agreement configuration\n",
dc8c34
+			agmt_get_long_name(prp->agmt),
dc8c34
+			cb_data.flowcontrol_detection,
dc8c34
+			type_nsds5ReplicaFlowControlPause,
dc8c34
+			type_nsds5ReplicaFlowControlWindow);
dc8c34
+	}
dc8c34
+	conn_set_tot_update_cb(prp->conn, NULL);
dc8c34
 	if (cb_data.lock) 
dc8c34
 	{
dc8c34
 		PR_DestroyLock(cb_data.lock);
dc8c34
@@ -619,6 +636,37 @@ void get_result (int rc, void *cb_data)
dc8c34
     ((callback_data*)cb_data)->rc = rc;
dc8c34
 }
dc8c34
 
dc8c34
+/* Call must hold the connection lock */
dc8c34
+int
dc8c34
+repl5_tot_last_rcv_msgid(Repl_Connection *conn) 
dc8c34
+{
dc8c34
+    struct callback_data *cb_data;
dc8c34
+    
dc8c34
+    conn_get_tot_update_cb_nolock(conn, (void **) &cb_data);
dc8c34
+    if (cb_data == NULL) {
dc8c34
+        return -1;
dc8c34
+    } else {
dc8c34
+        return cb_data->last_message_id_received;
dc8c34
+    }
dc8c34
+}
dc8c34
+
dc8c34
+/* Increase the flowcontrol counter
dc8c34
+ * Call must hold the connection lock
dc8c34
+ */
dc8c34
+int
dc8c34
+repl5_tot_flowcontrol_detection(Repl_Connection *conn, int increment) 
dc8c34
+{
dc8c34
+    struct callback_data *cb_data;
dc8c34
+    
dc8c34
+    conn_get_tot_update_cb_nolock(conn, (void **) &cb_data);
dc8c34
+    if (cb_data == NULL) {
dc8c34
+        return -1;
dc8c34
+    } else {
dc8c34
+        cb_data->flowcontrol_detection += increment;
dc8c34
+        return cb_data->flowcontrol_detection;
dc8c34
+    }
dc8c34
+}
dc8c34
+
dc8c34
 static 
dc8c34
 int send_entry (Slapi_Entry *e, void *cb_data)
dc8c34
 {
dc8c34
diff --git a/ldap/servers/plugins/replication/repl_globals.c b/ldap/servers/plugins/replication/repl_globals.c
dc8c34
index f31a476..bfcff03 100644
dc8c34
--- a/ldap/servers/plugins/replication/repl_globals.c
dc8c34
+++ b/ldap/servers/plugins/replication/repl_globals.c
dc8c34
@@ -131,6 +131,9 @@ const char *type_nsds5ReplicaSessionPauseTime = "nsds5ReplicaSessionPauseTime";
dc8c34
 const char *type_nsds5ReplicaEnabled = "nsds5ReplicaEnabled";
dc8c34
 const char *type_nsds5ReplicaStripAttrs = "nsds5ReplicaStripAttrs";
dc8c34
 const char *type_nsds5ReplicaCleanRUVnotified = "nsds5ReplicaCleanRUVNotified";
dc8c34
+const char* type_nsds5ReplicaFlowControlWindow = "nsds5ReplicaFlowControlWindow";
dc8c34
+const char* type_nsds5ReplicaFlowControlPause = "nsds5ReplicaFlowControlPause";
dc8c34
+
dc8c34
 
dc8c34
 /* windows sync specific attributes */
dc8c34
 const char *type_nsds7WindowsReplicaArea = "nsds7WindowsReplicaSubtree";
dc8c34
-- 
dc8c34
1.9.3
dc8c34