|
|
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 |
|