andykimpe / rpms / 389-ds-base

Forked from rpms/389-ds-base 5 months ago
Clone
dc8c34
From 752242e11be84f3ed9ad24dd02f593ce2591af90 Mon Sep 17 00:00:00 2001
dc8c34
From: Ludwig Krispenz <lkrispen@redhat.com>
dc8c34
Date: Thu, 12 Jan 2017 10:20:08 +0100
dc8c34
Subject: [PATCH 426/427] Ticket 49020 - v1.2.11 do not treat missing csn as
dc8c34
 fatal
dc8c34
dc8c34
    This patch removes the automatic choice of an alternative csn when
dc8c34
    the calculated anchor csn is not found.
dc8c34
dc8c34
    In that case it does no longer go to fatal state but will retry later.
dc8c34
dc8c34
    It also adds a configuration parameter to thr replication agreement to
dc8c34
    allow to pick a "next best" anchorcsn if the original is not found to
dc8c34
    keep replicatio going.
dc8c34
dc8c34
    Reviewed by: Noriko, William
dc8c34
dc8c34
(cherry picked from commit 55aa091b4b7ae812aff1fb7378374c02fdf478b3)
dc8c34
---
dc8c34
 ldap/schema/01core389.ldif                         |   3 +-
dc8c34
 ldap/servers/plugins/replication/cl5_api.c         |  16 ++-
dc8c34
 ldap/servers/plugins/replication/cl5_clcache.c     |  43 ++++----
dc8c34
 ldap/servers/plugins/replication/cl5_clcache.h     |   2 +-
dc8c34
 ldap/servers/plugins/replication/repl5.h           |   4 +
dc8c34
 ldap/servers/plugins/replication/repl5_agmt.c      | 115 ++++++++++++++++++++-
dc8c34
 ldap/servers/plugins/replication/repl5_agmtlist.c  |  13 +++
dc8c34
 .../plugins/replication/repl5_inc_protocol.c       |   7 +-
dc8c34
 ldap/servers/plugins/replication/repl_globals.c    |   1 +
dc8c34
 9 files changed, 168 insertions(+), 36 deletions(-)
dc8c34
dc8c34
diff --git a/ldap/schema/01core389.ldif b/ldap/schema/01core389.ldif
dc8c34
index afa4ee6..94dd6c6 100644
dc8c34
--- a/ldap/schema/01core389.ldif
dc8c34
+++ b/ldap/schema/01core389.ldif
dc8c34
@@ -160,6 +160,7 @@ attributeTypes: ( 2.16.840.1.113730.3.1.2310 NAME 'nsds5ReplicaFlowControlWindow
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
 attributeTypes: ( 2.16.840.1.113730.3.1.2332 NAME 'allowWeakDHParam' DESC 'Netscape defined attribute type' SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 X-ORIGIN 'Netscape Directory Server' )
dc8c34
 attributeTypes: ( 2.16.840.1.113730.3.1.2333 NAME 'nsds5ReplicaReleaseTimeout' 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.2335 NAME 'nsds5ReplicaIgnoreMissingChange' DESC 'Netscape defined attribute type' SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 SINGLE-VALUE X-ORIGIN 'Netscape Directory Server' )
dc8c34
 #
dc8c34
 # objectclasses
dc8c34
 #
dc8c34
@@ -171,7 +172,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 $ nsds5ReplicaReleaseTimeout) 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  $ nsds5ReplicaFlowControlWindow $ nsds5ReplicaFlowControlPause ) 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 $ nsds5ReplicaIgnoreMissingChange ) 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/cl5_api.c b/ldap/servers/plugins/replication/cl5_api.c
dc8c34
index 9b2ef37..a97f626 100644
dc8c34
--- a/ldap/servers/plugins/replication/cl5_api.c
dc8c34
+++ b/ldap/servers/plugins/replication/cl5_api.c
dc8c34
@@ -337,7 +337,7 @@ static int _cl5WriteBervals (struct berval **bv, char** buff, unsigned int *size
dc8c34
 static PRBool _cl5ValidReplayIterator (const CL5ReplayIterator *iterator);
dc8c34
 #endif
dc8c34
 static int _cl5PositionCursorForReplay (ReplicaId consumerRID, const RUV *consumerRuv,
dc8c34
-			Object *replica, Object *fileObject, CL5ReplayIterator **iterator);
dc8c34
+		Object *replica, Object *fileObject, CL5ReplayIterator **iterator, int *continue_on_missing);
dc8c34
 static int _cl5CheckMissingCSN (const CSN *minCsn, const RUV *supplierRUV, CL5DBFile *file);
dc8c34
 
dc8c34
 /* changelog trimming */
dc8c34
@@ -1544,7 +1544,7 @@ int cl5CreateReplayIteratorEx (Private_Repl_Protocol *prp, const RUV *consumerRu
dc8c34
     	/* iterate through the ruv in csn order to find first master for which 
dc8c34
 	       we can replay changes */		    
dc8c34
 		
dc8c34
-		rc = _cl5PositionCursorForReplay (consumerRID, consumerRuv, replica, obj, iterator);
dc8c34
+		rc = _cl5PositionCursorForReplay (consumerRID, consumerRuv, replica, obj, iterator, NULL);
dc8c34
 	}
dc8c34
 	else
dc8c34
 	{
dc8c34
@@ -1605,7 +1605,13 @@ int cl5CreateReplayIterator (Private_Repl_Protocol *prp, const RUV *consumerRuv,
dc8c34
     	/* iterate through the ruv in csn order to find first master for which 
dc8c34
 	       we can replay changes */		    
dc8c34
 		ReplicaId consumerRID = agmt_get_consumer_rid ( prp->agmt, prp->conn );
dc8c34
-		rc = _cl5PositionCursorForReplay (consumerRID, consumerRuv, replica, obj, iterator);
dc8c34
+		int continue_on_missing = agmt_get_ignoremissing ( prp->agmt);
dc8c34
+		int save_cont_miss = continue_on_missing;
dc8c34
+		rc = _cl5PositionCursorForReplay (consumerRID, consumerRuv, replica, obj, iterator, &continue_on_missing);
dc8c34
+		if (save_cont_miss == 1 && continue_on_missing ==0) {
dc8c34
+			/* the option to continue once on a missing csn was used, rest */
dc8c34
+			agmt_set_ignoremissing ( prp->agmt, 0);
dc8c34
+		}
dc8c34
 	}
dc8c34
 	else
dc8c34
 	{
dc8c34
@@ -5445,7 +5451,7 @@ struct replica_hash_entry
dc8c34
 
dc8c34
 
dc8c34
 static int _cl5PositionCursorForReplay (ReplicaId consumerRID, const RUV *consumerRuv,
dc8c34
-		Object *replica, Object *fileObj, CL5ReplayIterator **iterator)
dc8c34
+		Object *replica, Object *fileObj, CL5ReplayIterator **iterator, int *continue_on_missing)
dc8c34
 {
dc8c34
 	CLC_Buffer *clcache = NULL;
dc8c34
 	CL5DBFile *file;
dc8c34
@@ -5489,7 +5495,7 @@ static int _cl5PositionCursorForReplay (ReplicaId consumerRID, const RUV *consum
dc8c34
 	rc = clcache_get_buffer ( &clcache, file->db, consumerRID, consumerRuv, supplierRuv );
dc8c34
 	if ( rc != 0 ) goto done;
dc8c34
 
dc8c34
-	rc = clcache_load_buffer (clcache, &startCSN);
dc8c34
+	rc = clcache_load_buffer (clcache, &startCSN, continue_on_missing);
dc8c34
 
dc8c34
         if (rc == 0) {
dc8c34
 		haveChanges = PR_TRUE;
dc8c34
diff --git a/ldap/servers/plugins/replication/cl5_clcache.c b/ldap/servers/plugins/replication/cl5_clcache.c
dc8c34
index f6c56a9..44b2817 100644
dc8c34
--- a/ldap/servers/plugins/replication/cl5_clcache.c
dc8c34
+++ b/ldap/servers/plugins/replication/cl5_clcache.c
dc8c34
@@ -354,7 +354,7 @@ clcache_return_buffer ( CLC_Buffer **buf )
dc8c34
  *		       historic reason.
dc8c34
  */
dc8c34
 int
dc8c34
-clcache_load_buffer ( CLC_Buffer *buf, CSN **anchorCSN )
dc8c34
+clcache_load_buffer ( CLC_Buffer *buf, CSN **anchorCSN, int *continue_on_miss )
dc8c34
 {
dc8c34
 	int rc = 0;
dc8c34
         int flag = DB_NEXT;
dc8c34
@@ -375,6 +375,22 @@ clcache_load_buffer ( CLC_Buffer *buf, CSN **anchorCSN )
dc8c34
 		if (anchorCSN) *anchorCSN = buf->buf_current_csn;
dc8c34
 		rc = clcache_load_buffer_bulk ( buf, flag );
dc8c34
 
dc8c34
+		if (rc == DB_NOTFOUND && continue_on_miss && *continue_on_miss) {
dc8c34
+			/* make replication going using next best startcsn */
dc8c34
+			slapi_log_error(SLAPI_LOG_FATAL, buf->buf_agmt_name,
dc8c34
+					"clcache_load_buffer - Can't load changelog buffer starting at CSN %s with flag(%s). "
dc8c34
+					"Trying to use an alterantive start CSN.\n",
dc8c34
+					(char*)buf->buf_key.data,
dc8c34
+					flag==DB_NEXT?"DB_NEXT":"DB_SET" );
dc8c34
+			rc = clcache_load_buffer_bulk ( buf, DB_SET_RANGE );
dc8c34
+			if (rc == 0) {
dc8c34
+				slapi_log_error(SLAPI_LOG_FATAL, buf->buf_agmt_name,
dc8c34
+					"clcache_load_buffer - Using alternative start iteration csn: %s \n",
dc8c34
+					(char*)buf->buf_key.data);
dc8c34
+			}
dc8c34
+			/* the use of alternative start csns can be limited, record its usage */
dc8c34
+			(*continue_on_miss)--;
dc8c34
+		}
dc8c34
 		/* Reset some flag variables */
dc8c34
 		if ( rc == 0 ) {
dc8c34
 			int i;
dc8c34
@@ -437,23 +453,6 @@ retry:
dc8c34
 								 & buf->buf_key,
dc8c34
 								 & buf->buf_data,
dc8c34
 								 DB_SET );
dc8c34
-			if (rc == DB_NOTFOUND) {
dc8c34
-				/* the start position in the changelog is not found
dc8c34
-				 * 1. log an error
dc8c34
-				 * 2. try to find another starting position as close
dc8c34
-				 *    as possible
dc8c34
-				 */
dc8c34
-				slapi_log_error ( SLAPI_LOG_FATAL, "clcache_load_buffer_bulk",
dc8c34
-							"changelog record with csn (%s) not found for DB_NEXT\n",
dc8c34
-							(char *)buf->buf_key.data );
dc8c34
-				rc = cursor->c_get ( cursor, & buf->buf_key, & buf->buf_data,
dc8c34
-							 DB_SET_RANGE );
dc8c34
-				/* this moves the cursor ahead of the tageted csn,
dc8c34
-				 * so we achieved what was intended with DB_SET/DB_NEXT
dc8c34
-				 * continute at this csn.
dc8c34
-				 */
dc8c34
-				use_flag = DB_CURRENT;
dc8c34
-			}
dc8c34
 		}
dc8c34
 
dc8c34
 		/*
dc8c34
@@ -462,12 +461,6 @@ retry:
dc8c34
 		 */
dc8c34
 		if ( 0 == rc || DB_BUFFER_SMALL == rc ) {
dc8c34
 			rc = clcache_cursor_get ( cursor, buf, use_flag );
dc8c34
-			if ( rc == DB_NOTFOUND && use_flag == DB_SET) {
dc8c34
-				slapi_log_error ( SLAPI_LOG_FATAL, "clcache_load_buffer_bulk",
dc8c34
-							"changelog record with csn (%s) not found for DB_SET\n",
dc8c34
-							(char *)buf->buf_key.data );
dc8c34
-				rc = clcache_cursor_get ( cursor, buf, DB_SET_RANGE );
dc8c34
-			}
dc8c34
 		}
dc8c34
 
dc8c34
 	}
dc8c34
@@ -541,7 +534,7 @@ clcache_get_next_change ( CLC_Buffer *buf, void **key, size_t *keylen, void **da
dc8c34
 		 * We're done with the current buffer. Now load the next chunk.
dc8c34
 		 */
dc8c34
 		if ( NULL == *key && CLC_STATE_READY == buf->buf_state ) {
dc8c34
-			rc = clcache_load_buffer ( buf, NULL );
dc8c34
+			rc = clcache_load_buffer ( buf, NULL, NULL );
dc8c34
 			if ( 0 == rc && buf->buf_record_ptr ) {
dc8c34
 				DB_MULTIPLE_KEY_NEXT ( buf->buf_record_ptr, &buf->buf_data,
dc8c34
 								   *key, *keylen, *data, *datalen );
dc8c34
diff --git a/ldap/servers/plugins/replication/cl5_clcache.h b/ldap/servers/plugins/replication/cl5_clcache.h
dc8c34
index 5cab3cb..3ce210b 100644
dc8c34
--- a/ldap/servers/plugins/replication/cl5_clcache.h
dc8c34
+++ b/ldap/servers/plugins/replication/cl5_clcache.h
dc8c34
@@ -52,7 +52,7 @@ typedef struct clc_buffer CLC_Buffer;
dc8c34
 int	 clcache_init ( DB_ENV **dbenv );
dc8c34
 void clcache_set_config ();
dc8c34
 int	 clcache_get_buffer ( CLC_Buffer **buf, DB *db, ReplicaId consumer_rid, const RUV *consumer_ruv, const RUV *local_ruv );
dc8c34
-int	 clcache_load_buffer ( CLC_Buffer *buf, CSN **anchorCSN );
dc8c34
+int	 clcache_load_buffer ( CLC_Buffer *buf, CSN **anchorCSN, int *continue_on_miss );
dc8c34
 void clcache_return_buffer ( CLC_Buffer **buf );
dc8c34
 int	 clcache_get_next_change ( CLC_Buffer *buf, void **key, size_t *keylen, void **data, size_t *datalen, CSN **csn );
dc8c34
 void clcache_destroy ();
dc8c34
diff --git a/ldap/servers/plugins/replication/repl5.h b/ldap/servers/plugins/replication/repl5.h
dc8c34
index 0db632e..80ef757 100644
dc8c34
--- a/ldap/servers/plugins/replication/repl5.h
dc8c34
+++ b/ldap/servers/plugins/replication/repl5.h
dc8c34
@@ -175,6 +175,7 @@ extern const char *type_nsds5ReplicaCleanRUVnotified;
dc8c34
 extern const char *type_nsds5ReplicaFlowControlWindow;
dc8c34
 extern const char *type_nsds5ReplicaFlowControlPause;
dc8c34
 extern const char *type_replicaReleaseTimeout;
dc8c34
+extern const char *type_replicaIgnoreMissingChange;
dc8c34
 
dc8c34
 /* Attribute names for windows replication agreements */
dc8c34
 extern const char *type_nsds7WindowsReplicaArea;
dc8c34
@@ -321,6 +322,7 @@ 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
+long agmt_get_ignoremissing(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
@@ -343,6 +345,7 @@ 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_ignoremissing_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
@@ -388,6 +391,7 @@ int agmt_set_enabled_from_entry(Repl_Agmt *ra, Slapi_Entry *e, char *returntext)
dc8c34
 char **agmt_get_attrs_to_strip(Repl_Agmt *ra);
dc8c34
 int agmt_set_attrs_to_strip(Repl_Agmt *ra, Slapi_Entry *e);
dc8c34
 int agmt_set_timeout(Repl_Agmt *ra, long timeout);
dc8c34
+int agmt_set_ignoremissing(Repl_Agmt *ra, long ignoremissing);
dc8c34
 void agmt_update_done(Repl_Agmt *ra, int is_total);
dc8c34
 
dc8c34
 typedef struct replica Replica;
dc8c34
diff --git a/ldap/servers/plugins/replication/repl5_agmt.c b/ldap/servers/plugins/replication/repl5_agmt.c
dc8c34
index 41a81ca..4c67e57 100644
dc8c34
--- a/ldap/servers/plugins/replication/repl5_agmt.c
dc8c34
+++ b/ldap/servers/plugins/replication/repl5_agmt.c
dc8c34
@@ -150,6 +150,7 @@ typedef struct repl5agmt {
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
+	long ignoreMissingChange;	/* if set replication will try to continue even if change cannot be found in changelog */
dc8c34
 } repl5agmt;
dc8c34
 
dc8c34
 /* Forward declarations */
dc8c34
@@ -159,7 +160,7 @@ static int get_agmt_status(Slapi_PBlock *pb, Slapi_Entry* e,
dc8c34
 	Slapi_Entry* entryAfter, int *returncode, char *returntext, void *arg);
dc8c34
 static int agmt_set_bind_method_no_lock(Repl_Agmt *ra, const Slapi_Entry *e);
dc8c34
 static int agmt_set_transportinfo_no_lock(Repl_Agmt *ra, const Slapi_Entry *e);
dc8c34
-
dc8c34
+static void agmt_replica_reset_ignoremissing (const Repl_Agmt *agmt);
dc8c34
 
dc8c34
 /*
dc8c34
 Schema for replication agreement:
dc8c34
@@ -362,6 +363,21 @@ agmt_new_from_entry(Slapi_Entry *e)
dc8c34
 		}
dc8c34
 	}
dc8c34
 
dc8c34
+	/* continue on missing change ? */
dc8c34
+	ra->ignoreMissingChange = 0;
dc8c34
+	tmpstr = slapi_entry_attr_get_charptr(e, type_replicaIgnoreMissingChange);
dc8c34
+	if (NULL != tmpstr)
dc8c34
+	{
dc8c34
+		if (strcasecmp(tmpstr,"off") == 0 || strcasecmp(tmpstr,"never") == 0) {
dc8c34
+			ra->ignoreMissingChange = 0;
dc8c34
+		} else if (strcasecmp(tmpstr,"on") == 0 || strcasecmp(tmpstr,"once") == 0) {
dc8c34
+			ra->ignoreMissingChange = 1;
dc8c34
+		} else if (strcasecmp(tmpstr,"always") == 0) {
dc8c34
+			ra->ignoreMissingChange = -1;
dc8c34
+		}
dc8c34
+		slapi_ch_free_string(&tmpstr);
dc8c34
+	}
dc8c34
+
dc8c34
 	/* DN of entry at root of replicated area */
dc8c34
 	tmpstr = slapi_entry_attr_get_charptr(e, type_nsds5ReplicaRoot);
dc8c34
 	if (NULL != tmpstr)
dc8c34
@@ -1012,6 +1028,16 @@ agmt_get_flowcontrolpause(const Repl_Agmt *ra)
dc8c34
 	PR_Unlock(ra->lock);
dc8c34
 	return return_value;
dc8c34
 }
dc8c34
+long
dc8c34
+agmt_get_ignoremissing(const Repl_Agmt *ra)
dc8c34
+{
dc8c34
+	long return_value;
dc8c34
+	PR_ASSERT(NULL != ra);
dc8c34
+	PR_Lock(ra->lock);
dc8c34
+	return_value = ra->ignoreMissingChange;
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
@@ -1826,6 +1852,48 @@ agmt_set_flowcontrolpause_from_entry(Repl_Agmt *ra, const Slapi_Entry *e)
dc8c34
 	}
dc8c34
 	return return_value;
dc8c34
 }
dc8c34
+/* add comment here */
dc8c34
+int
dc8c34
+agmt_set_ignoremissing_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_replicaIgnoreMissingChange, &sattr);
dc8c34
+	if (NULL != sattr)
dc8c34
+	{
dc8c34
+		Slapi_Value *sval = NULL;
dc8c34
+		slapi_attr_first_value(sattr, &sval);
dc8c34
+		if (NULL != sval)
dc8c34
+		{
dc8c34
+			const char *tmpval = slapi_value_get_string(sval);
dc8c34
+			if (strcasecmp(tmpval,"off") == 0 || strcasecmp(tmpval,"never") == 0) {
dc8c34
+				ra->ignoreMissingChange = 0;
dc8c34
+				return_value = 0;
dc8c34
+			} else if (strcasecmp(tmpval,"on") == 0 || strcasecmp(tmpval,"once") == 0) {
dc8c34
+				ra->ignoreMissingChange = 1;
dc8c34
+				return_value = 0;
dc8c34
+			} else if (strcasecmp(tmpval,"always") == 0) {
dc8c34
+				ra->ignoreMissingChange = -1;
dc8c34
+				return_value = 0;
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
@@ -1867,6 +1935,20 @@ agmt_set_flowcontrolpause(Repl_Agmt *ra, long pause)
dc8c34
 
dc8c34
     return 0;
dc8c34
 }
dc8c34
+int
dc8c34
+agmt_set_ignoremissing(Repl_Agmt *ra, long ignoremissing)
dc8c34
+{
dc8c34
+    PR_Lock(ra->lock);
dc8c34
+    if (ra->stop_in_progress){
dc8c34
+        PR_Unlock(ra->lock);
dc8c34
+        return -1;
dc8c34
+    }
dc8c34
+    ra->ignoreMissingChange = ignoremissing;
dc8c34
+    PR_Unlock(ra->lock);
dc8c34
+    /* if reset to 0 update the entry */
dc8c34
+    agmt_replica_reset_ignoremissing(ra);
dc8c34
+    return 0;
dc8c34
+}
dc8c34
 
dc8c34
 /*
dc8c34
  * Set or reset the busywaittime
dc8c34
@@ -2101,6 +2183,37 @@ agmt_replica_init_done (const Repl_Agmt *agmt)
dc8c34
     slapi_pblock_destroy (pb);
dc8c34
 }
dc8c34
 
dc8c34
+
dc8c34
+/* delete nsds5replicaIgnoreMissingChange attribute */
dc8c34
+static void
dc8c34
+agmt_replica_reset_ignoremissing (const Repl_Agmt *agmt)
dc8c34
+{
dc8c34
+    int rc;
dc8c34
+    Slapi_PBlock *pb = slapi_pblock_new ();
dc8c34
+    LDAPMod *mods [2];
dc8c34
+    LDAPMod mod;
dc8c34
+
dc8c34
+    mods[0] = &mod;
dc8c34
+    mods[1] = NULL;
dc8c34
+    mod.mod_op = LDAP_MOD_DELETE | LDAP_MOD_BVALUES;
dc8c34
+    mod.mod_type = (char*)type_replicaIgnoreMissingChange;
dc8c34
+    mod.mod_bvalues = NULL;
dc8c34
+
dc8c34
+    slapi_modify_internal_set_pb_ext(pb, agmt->dn, mods, NULL/* controls */,
dc8c34
+          NULL/* uniqueid */, repl_get_plugin_identity (PLUGIN_MULTIMASTER_REPLICATION), 0/* flags */);
dc8c34
+    slapi_modify_internal_pb (pb);
dc8c34
+
dc8c34
+    slapi_pblock_get(pb, SLAPI_PLUGIN_INTOP_RESULT, &rc);
dc8c34
+    if (rc != LDAP_SUCCESS && rc != LDAP_NO_SUCH_ATTRIBUTE)
dc8c34
+    {
dc8c34
+        slapi_log_error(SLAPI_LOG_FATAL, repl_plugin_name, "agmt_replica_ignoremissing: "
dc8c34
+                        "failed to remove (%s) attribute from (%s) entry; LDAP error - %d\n",
dc8c34
+                        type_replicaIgnoreMissingChange, slapi_sdn_get_ndn (agmt->dn), rc);
dc8c34
+    }
dc8c34
+
dc8c34
+    slapi_pblock_destroy (pb);
dc8c34
+}
dc8c34
+
dc8c34
 /* Agreement object is acquired on behalf of the caller.
dc8c34
    The caller is responsible for releasing the object
dc8c34
    when it is no longer used */
dc8c34
diff --git a/ldap/servers/plugins/replication/repl5_agmtlist.c b/ldap/servers/plugins/replication/repl5_agmtlist.c
dc8c34
index caa41af..7789c3f 100644
dc8c34
--- a/ldap/servers/plugins/replication/repl5_agmtlist.c
dc8c34
+++ b/ldap/servers/plugins/replication/repl5_agmtlist.c
dc8c34
@@ -371,6 +371,19 @@ 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_replicaIgnoreMissingChange))
dc8c34
+		{
dc8c34
+			/* New replica timeout */
dc8c34
+			if (agmt_set_ignoremissing_from_entry(agmt, e) != 0)
dc8c34
+			{
dc8c34
+				slapi_log_error(SLAPI_LOG_FATAL, repl_plugin_name, "agmtlist_modify_callback - "
dc8c34
+						"Failed to update the ignorMissingChange attribute 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_inc_protocol.c b/ldap/servers/plugins/replication/repl5_inc_protocol.c
dc8c34
index e6920e8..8cf72a1 100644
dc8c34
--- a/ldap/servers/plugins/replication/repl5_inc_protocol.c
dc8c34
+++ b/ldap/servers/plugins/replication/repl5_inc_protocol.c
dc8c34
@@ -1709,13 +1709,14 @@ send_updates(Private_Repl_Protocol *prp, RUV *remote_update_vector, PRUint32 *nu
dc8c34
 				"%s: Data required to update replica has been purged. "
dc8c34
 				"The replica must be reinitialized.\n",
dc8c34
 				agmt_get_long_name(prp->agmt));
dc8c34
-			return_value = UPDATE_FATAL_ERROR;
dc8c34
+			return_value = UPDATE_TRANSIENT_ERROR;
dc8c34
 			break;
dc8c34
 		case CL5_MISSING_DATA:   /* data should be in the changelog, but is missing */
dc8c34
 			slapi_log_error(SLAPI_LOG_FATAL, repl_plugin_name,
dc8c34
-				"%s: Missing data encountered\n",
dc8c34
+				"send_updates - %s: Missing data encountered. "
dc8c34
+				"If the error persists the replica must be reinitialized.\n",
dc8c34
 				agmt_get_long_name(prp->agmt));
dc8c34
-			return_value = UPDATE_FATAL_ERROR;
dc8c34
+			return_value = UPDATE_TRANSIENT_ERROR;
dc8c34
 			break;
dc8c34
 		case CL5_UNKNOWN_ERROR:   /* unclassified error */
dc8c34
 			slapi_log_error(SLAPI_LOG_FATAL, repl_plugin_name,
dc8c34
diff --git a/ldap/servers/plugins/replication/repl_globals.c b/ldap/servers/plugins/replication/repl_globals.c
dc8c34
index 1d35241..4c9f274 100644
dc8c34
--- a/ldap/servers/plugins/replication/repl_globals.c
dc8c34
+++ b/ldap/servers/plugins/replication/repl_globals.c
dc8c34
@@ -135,6 +135,7 @@ const char *type_nsds5ReplicaCleanRUVnotified = "nsds5ReplicaCleanRUVNotified";
dc8c34
 const char* type_nsds5ReplicaFlowControlWindow = "nsds5ReplicaFlowControlWindow";
dc8c34
 const char* type_nsds5ReplicaFlowControlPause = "nsds5ReplicaFlowControlPause";
dc8c34
 
dc8c34
+const char* type_replicaIgnoreMissingChange = "nsds5ReplicaIgnoreMissingChange";
dc8c34
 
dc8c34
 /* windows sync specific attributes */
dc8c34
 const char *type_nsds7WindowsReplicaArea = "nsds7WindowsReplicaSubtree";
dc8c34
-- 
dc8c34
2.9.3
dc8c34