From c2a0888bf3bf03ef64d99f0d3de7b82e481192ba Mon Sep 17 00:00:00 2001
From: Quanah Gibson-Mount <quanah@openldap.org>
Date: Mon, 10 Nov 2008 23:03:12 +0000
Subject: [PATCH] ITS#5709

---
 CHANGES                              |  1 +
 servers/slapd/backend.c              |  3 +--
 servers/slapd/ctxcsn.c               | 24 ++++++++----------------
 servers/slapd/frontend.c             |  6 +-----
 servers/slapd/overlays/pcache.c      |  2 +-
 servers/slapd/overlays/syncprov.c    | 15 +++++++++------
 servers/slapd/overlays/translucent.c |  1 -
 servers/slapd/slap.h                 |  1 -
 8 files changed, 21 insertions(+), 32 deletions(-)

diff --git a/CHANGES b/CHANGES
index 42d76fb244..b34a506254 100644
--- a/CHANGES
+++ b/CHANGES
@@ -43,6 +43,7 @@ OpenLDAP 2.4.13 Engineering
 	Fixed slapo-rwm reusing freed filter (ITS#5732)
 	Fixed slapo-rwm entry get (ITS#5773)
 	Fixed slapo-syncprov runqueue removal (ITS#5776)
+	Fixed slapo-syncprov unreplicatable ops (ITS#5709)
 	Added slapo-translucent try local bind when remote fails (ITS#5656)
 	Added slapo-translucent support for PasswordModify exop (ITS#5656)
 	Fixed tools simple bind without SASL (ITS#5753)
diff --git a/servers/slapd/backend.c b/servers/slapd/backend.c
index ccbc938da5..459490b4ee 100644
--- a/servers/slapd/backend.c
+++ b/servers/slapd/backend.c
@@ -594,8 +594,7 @@ backend_db_init(
 	be->be_requires = frontendDB->be_requires;
 	be->be_ssf_set = frontendDB->be_ssf_set;
 
-	be->be_pcl_mutexp = &be->be_pcl_mutex;
-	ldap_pvt_thread_mutex_init( be->be_pcl_mutexp );
+	ldap_pvt_thread_mutex_init( &be->be_pcl_mutex );
 
  	/* assign a default depth limit for alias deref */
 	be->be_max_deref_depth = SLAPD_DEFAULT_MAXDEREFDEPTH; 
diff --git a/servers/slapd/ctxcsn.c b/servers/slapd/ctxcsn.c
index 772bfa17fb..ce6356ab42 100644
--- a/servers/slapd/ctxcsn.c
+++ b/servers/slapd/ctxcsn.c
@@ -43,7 +43,7 @@ slap_get_commit_csn(
 		BER_BVZERO( maxcsn );
 	}
 
-	ldap_pvt_thread_mutex_lock( be->be_pcl_mutexp );
+	ldap_pvt_thread_mutex_lock( &be->be_pcl_mutex );
 
 	LDAP_TAILQ_FOREACH( csne, be->be_pending_csn_list, ce_csn_link ) {
 		if ( csne->ce_opid == op->o_opid && csne->ce_connid == op->o_connid ) {
@@ -58,7 +58,7 @@ slap_get_commit_csn(
 	}
 
 	if ( committed_csne && maxcsn ) *maxcsn = committed_csne->ce_csn;
-	ldap_pvt_thread_mutex_unlock( be->be_pcl_mutexp );
+	ldap_pvt_thread_mutex_unlock( &be->be_pcl_mutex );
 }
 
 void
@@ -67,7 +67,7 @@ slap_rewind_commit_csn( Operation *op )
 	struct slap_csn_entry *csne;
 	BackendDB *be = op->o_bd->bd_self;
 
-	ldap_pvt_thread_mutex_lock( be->be_pcl_mutexp );
+	ldap_pvt_thread_mutex_lock( &be->be_pcl_mutex );
 
 	LDAP_TAILQ_FOREACH( csne, be->be_pending_csn_list, ce_csn_link ) {
 		if ( csne->ce_opid == op->o_opid && csne->ce_connid == op->o_connid ) {
@@ -76,7 +76,7 @@ slap_rewind_commit_csn( Operation *op )
 		}
 	}
 
-	ldap_pvt_thread_mutex_unlock( be->be_pcl_mutexp );
+	ldap_pvt_thread_mutex_unlock( &be->be_pcl_mutex );
 }
 
 void
@@ -89,15 +89,7 @@ slap_graduate_commit_csn( Operation *op )
 	if ( op->o_bd == NULL ) return;
 	be = op->o_bd->bd_self;
 
-#if 0
-	/* it is NULL when we get here from the frontendDB;
-	 * alternate fix: initialize frontendDB like all other backends */
-	assert( op->o_bd->be_pcl_mutexp != NULL );
-#endif
-	
-	if ( be->be_pcl_mutexp == NULL ) return;
-
-	ldap_pvt_thread_mutex_lock( be->be_pcl_mutexp );
+	ldap_pvt_thread_mutex_lock( &be->be_pcl_mutex );
 
 	LDAP_TAILQ_FOREACH( csne, be->be_pending_csn_list, ce_csn_link ) {
 		if ( csne->ce_opid == op->o_opid && csne->ce_connid == op->o_connid ) {
@@ -114,7 +106,7 @@ slap_graduate_commit_csn( Operation *op )
 		}
 	}
 
-	ldap_pvt_thread_mutex_unlock( be->be_pcl_mutexp );
+	ldap_pvt_thread_mutex_unlock( &be->be_pcl_mutex );
 
 	return;
 }
@@ -172,7 +164,7 @@ slap_queue_csn(
 
 	Debug( LDAP_DEBUG_SYNC, "slap_queue_csn: queing %p %s\n", csn->bv_val, csn->bv_val, 0 );
 
-	ldap_pvt_thread_mutex_lock( be->be_pcl_mutexp );
+	ldap_pvt_thread_mutex_lock( &be->be_pcl_mutex );
 
 	ber_dupbv( &pending->ce_csn, csn );
 	ber_bvreplace_x( &op->o_csn, &pending->ce_csn, op->o_tmpmemctx );
@@ -181,7 +173,7 @@ slap_queue_csn(
 	pending->ce_state = SLAP_CSN_PENDING;
 	LDAP_TAILQ_INSERT_TAIL( be->be_pending_csn_list,
 		pending, ce_csn_link );
-	ldap_pvt_thread_mutex_unlock( be->be_pcl_mutexp );
+	ldap_pvt_thread_mutex_unlock( &be->be_pcl_mutex );
 }
 
 int
diff --git a/servers/slapd/frontend.c b/servers/slapd/frontend.c
index caaf3b3900..342ae453cd 100644
--- a/servers/slapd/frontend.c
+++ b/servers/slapd/frontend.c
@@ -108,11 +108,7 @@ frontend_init( void )
 	frontendDB->be_def_limit.lms_s_pr_hide = 0;			/* don't hide number of entries left */
 	frontendDB->be_def_limit.lms_s_pr_total = 0;			/* number of total entries returned by pagedResults equal to hard limit */
 
-#if 0
-	/* FIXME: do we need this? */
-	frontendDB->be_pcl_mutexp = &frontendDB->be_pcl_mutex;
-	ldap_pvt_thread_mutex_init( frontendDB->be_pcl_mutexp );
-#endif
+	ldap_pvt_thread_mutex_init( &frontendDB->be_pcl_mutex );
 
 	/* suffix */
 	frontendDB->be_suffix = ch_calloc( 2, sizeof( struct berval ) );
diff --git a/servers/slapd/overlays/pcache.c b/servers/slapd/overlays/pcache.c
index d75ec06672..18da7fa413 100644
--- a/servers/slapd/overlays/pcache.c
+++ b/servers/slapd/overlays/pcache.c
@@ -3145,7 +3145,7 @@ pcache_db_init(
 	cm->db = *be;
 	SLAP_DBFLAGS(&cm->db) |= SLAP_DBFLAG_NO_SCHEMA_CHECK;
 	cm->db.be_private = NULL;
-	cm->db.be_pcl_mutexp = &cm->db.be_pcl_mutex;
+	cm->db.bd_self = &cm->db;
 	cm->qm = qm;
 	cm->numattrsets = 0;
 	cm->num_entries_limit = 5;
diff --git a/servers/slapd/overlays/syncprov.c b/servers/slapd/overlays/syncprov.c
index 7aaa5f9c67..a7cf44b74b 100644
--- a/servers/slapd/overlays/syncprov.c
+++ b/servers/slapd/overlays/syncprov.c
@@ -1604,12 +1604,12 @@ syncprov_op_response( Operation *op, SlapReply *rs )
 	{
 		struct berval maxcsn = BER_BVNULL;
 		char cbuf[LDAP_LUTIL_CSNSTR_BUFSIZE];
-		int do_check = 0, have_psearches;
+		int do_check = 0, have_psearches, foundit;
 
 		/* Update our context CSN */
 		cbuf[0] = '\0';
 		ldap_pvt_thread_rdwr_wlock( &si->si_csn_rwlock );
-		slap_get_commit_csn( op, &maxcsn );
+		slap_get_commit_csn( op, &maxcsn, &foundit );
 		if ( BER_BVISNULL( &maxcsn ) && SLAP_GLUE_SUBORDINATE( op->o_bd )) {
 			/* syncrepl queues the CSN values in the db where
 			 * it is configured , not where the changes are made.
@@ -1618,7 +1618,7 @@ syncprov_op_response( Operation *op, SlapReply *rs )
 			 */
 			BackendDB *be = op->o_bd;
 			op->o_bd = select_backend( &be->be_nsuffix[0], 1);
-			slap_get_commit_csn( op, &maxcsn );
+			slap_get_commit_csn( op, &maxcsn, &foundit );
 			op->o_bd = be;
 		}
 		if ( !BER_BVISNULL( &maxcsn ) ) {
@@ -1641,7 +1641,7 @@ syncprov_op_response( Operation *op, SlapReply *rs )
 					sizeof(int));
 				si->si_sids[i] = sid;
 			}
-		} else {
+		} else if ( !foundit ) {
 			/* internal ops that aren't meant to be replicated */
 			ldap_pvt_thread_rdwr_wunlock( &si->si_csn_rwlock );
 			return SLAP_CB_CONTINUE;
@@ -1678,8 +1678,11 @@ syncprov_op_response( Operation *op, SlapReply *rs )
 			ldap_pvt_thread_rdwr_runlock( &si->si_csn_rwlock );
 		}
 
-		opc->sctxcsn.bv_len = maxcsn.bv_len;
-		opc->sctxcsn.bv_val = cbuf;
+		/* only update consumer ctx if this is the greatest csn */
+		if ( bvmatch( &maxcsn, &op->o_csn )) {
+			opc->sctxcsn.bv_len = maxcsn.bv_len;
+			opc->sctxcsn.bv_val = cbuf;
+		}
 
 		/* Handle any persistent searches */
 		ldap_pvt_thread_mutex_lock( &si->si_ops_mutex );
diff --git a/servers/slapd/overlays/translucent.c b/servers/slapd/overlays/translucent.c
index e87cbe4632..66d090a26e 100644
--- a/servers/slapd/overlays/translucent.c
+++ b/servers/slapd/overlays/translucent.c
@@ -1268,7 +1268,6 @@ static int translucent_db_init(BackendDB *be, ConfigReply *cr) {
 	on->on_bi.bi_private = ov;
 	ov->db = *be;
 	ov->db.be_private = NULL;
-	ov->db.be_pcl_mutexp = &ov->db.be_pcl_mutex;
 	ov->defer_db_open = 1;
 
 	if ( !backend_db_init( "ldap", &ov->db, -1, NULL )) {
diff --git a/servers/slapd/slap.h b/servers/slapd/slap.h
index d9cdccf5bd..df29ec914d 100644
--- a/servers/slapd/slap.h
+++ b/servers/slapd/slap.h
@@ -1893,7 +1893,6 @@ struct BackendDB {
 	BerVarray	be_update_refs;	/* where to refer modifying clients to */
 	struct		be_pcl	*be_pending_csn_list;
 	ldap_pvt_thread_mutex_t					be_pcl_mutex;
-	ldap_pvt_thread_mutex_t					*be_pcl_mutexp;
 	struct syncinfo_s						*be_syncinfo; /* For syncrepl */
 
 	void    *be_pb;         /* Netscape plugin */
-- 
GitLab