Parcourir la source

Resolves #329951
Summary: MMR: Supplier does not respond anymore after many operations (deletes)
Description: introduce OP_FLAG_REPL_RUV. It's set in repl5_replica.c if the
entry is RUV. The operation should not be blocked at the backend SERIAL lock
(this is achieved by having OP_FLAG_REPL_FIXUP set in the operation flag).
But updating RUV has nothing to do with VLV, thus if the flag is set, it skips
the VLV indexing.

Noriko Hosoi il y a 18 ans
Parent
commit
8eb7f7d527

+ 18 - 18
ldap/servers/plugins/replication/repl5_plugins.c

@@ -846,39 +846,39 @@ multimaster_postop_modrdn (Slapi_PBlock *pb)
 static void
 copy_operation_parameters(Slapi_PBlock *pb)
 {
-	Slapi_Operation *op = NULL;
-	struct slapi_operation_parameters *op_params;
-	supplier_operation_extension *opext;
+    Slapi_Operation *op = NULL;
+    struct slapi_operation_parameters *op_params;
+    supplier_operation_extension *opext;
     Object *repl_obj;
     Replica *replica;
-	
+
     repl_obj = replica_get_replica_for_op (pb);
 
     /* we are only interested in the updates to replicas */
     if (repl_obj)
     {
         /* we only save the original operation parameters for replicated operations
-	       since client operations don't go through urp engine and pblock data can be logged */
-	    slapi_pblock_get( pb, SLAPI_OPERATION, &op );
-	    PR_ASSERT (op);
+           since client operations don't go through urp engine and pblock data can be logged */
+        slapi_pblock_get( pb, SLAPI_OPERATION, &op );
+        PR_ASSERT (op);
 
         replica = (Replica*)object_get_data (repl_obj);
-		PR_ASSERT (replica);
+        PR_ASSERT (replica);
 
         opext = (supplier_operation_extension*) repl_sup_get_ext (REPL_SUP_EXT_OP, op);
-	    if (operation_is_flag_set(op,OP_FLAG_REPLICATED) &&
+        if (operation_is_flag_set(op,OP_FLAG_REPLICATED) &&
             !operation_is_flag_set(op, OP_FLAG_REPL_FIXUP))
-	    {
-		    slapi_pblock_get (pb, SLAPI_OPERATION_PARAMETERS, &op_params);						  
-		    opext->operation_parameters= operation_parameters_dup(op_params);             
-        }       
-		   
-        /* this condition is needed to avoid re-entering lock when
-           ruv state is updated */
+        {
+            slapi_pblock_get (pb, SLAPI_OPERATION_PARAMETERS, &op_params);                          
+            opext->operation_parameters= operation_parameters_dup(op_params);             
+        }
+           
+        /* this condition is needed to avoid re-entering backend serial lock
+           when ruv state is updated */
         if (!operation_is_flag_set(op, OP_FLAG_REPL_FIXUP))
         {
-		    /* save replica generation in case it changes */
-		    opext->repl_gen = replica_get_generation (replica);
+            /* save replica generation in case it changes */
+            opext->repl_gen = replica_get_generation (replica);
         }
 
         object_release (repl_obj);                

+ 5 - 3
ldap/servers/plugins/replication/repl5_replica.c

@@ -2258,7 +2258,8 @@ replica_write_ruv (Replica *r)
 		RUV_STORAGE_ENTRY_UNIQUEID,
 		repl_get_plugin_identity (PLUGIN_MULTIMASTER_REPLICATION),
 		/* Add OP_FLAG_TOMBSTONE_ENTRY so that this doesn't get logged in the Retro ChangeLog */
-		OP_FLAG_REPLICATED | OP_FLAG_REPL_FIXUP | OP_FLAG_TOMBSTONE_ENTRY);
+        OP_FLAG_REPLICATED | OP_FLAG_REPL_FIXUP | OP_FLAG_TOMBSTONE_ENTRY |
+		OP_FLAG_REPL_RUV );
 	slapi_modify_internal_pb (pb);
 	slapi_pblock_get(pb, SLAPI_PLUGIN_INTOP_RESULT, &rc);
 
@@ -2732,7 +2733,8 @@ replica_create_ruv_tombstone(Replica *r)
 		e,
 		NULL /* controls */,
 		repl_get_plugin_identity(PLUGIN_MULTIMASTER_REPLICATION),
-		OP_FLAG_TOMBSTONE_ENTRY | OP_FLAG_REPLICATED | OP_FLAG_REPL_FIXUP);
+		OP_FLAG_TOMBSTONE_ENTRY | OP_FLAG_REPLICATED | OP_FLAG_REPL_FIXUP |
+		OP_FLAG_REPL_RUV);
 	slapi_add_internal_pb(pb);
 	slapi_pblock_get(pb, SLAPI_PLUGIN_INTOP_RESULT, &return_value);
     if (return_value == LDAP_SUCCESS)
@@ -3064,7 +3066,7 @@ replica_replace_ruv_tombstone(Replica *r)
         NULL, /* controls */
         RUV_STORAGE_ENTRY_UNIQUEID,
         repl_get_plugin_identity (PLUGIN_MULTIMASTER_REPLICATION),
-        OP_FLAG_REPLICATED | OP_FLAG_REPL_FIXUP);
+        OP_FLAG_REPLICATED | OP_FLAG_REPL_FIXUP | OP_FLAG_REPL_RUV);
 
     slapi_modify_internal_pb (pb);
 

+ 72 - 67
ldap/servers/slapd/back-ldbm/ldbm_add.c

@@ -104,6 +104,7 @@ ldbm_back_add( Slapi_PBlock *pb )
 	int is_resurect_operation= 0;
 	int is_tombstone_operation= 0;
 	int is_fixup_operation= 0;
+	int is_ruv = 0;				 /* True if the current entry is RUV */
 	CSN *opcsn = NULL;
 	entry_address addr;
 
@@ -118,12 +119,13 @@ ldbm_back_add( Slapi_PBlock *pb )
 
 	is_resurect_operation= operation_is_flag_set(operation,OP_FLAG_RESURECT_ENTRY);
 	is_tombstone_operation= operation_is_flag_set(operation,OP_FLAG_TOMBSTONE_ENTRY);
-	is_fixup_operation = operation_is_flag_set(operation,OP_FLAG_REPL_FIXUP);
+	is_fixup_operation = operation_is_flag_set(operation, OP_FLAG_REPL_FIXUP);
+	is_ruv = operation_is_flag_set(operation, OP_FLAG_REPL_RUV);
 
 	inst = (ldbm_instance *) be->be_instance_info;
-        
-    slapi_sdn_init(&sdn);
-    slapi_sdn_init(&parentsdn);
+		
+	slapi_sdn_init(&sdn);
+	slapi_sdn_init(&parentsdn);
 	
 	/* Get rid of ldbm backend attributes that you are not allowed to specify yourself */
 	slapi_entry_delete_values( e, hassubordinates, NULL );
@@ -145,7 +147,7 @@ ldbm_back_add( Slapi_PBlock *pb )
 		dblock_acquired= 1;
 	}
 
-    rc= 0;
+	rc= 0;
 
 	/*
 	 * We are about to pass the last abandon test, so from now on we are
@@ -166,8 +168,8 @@ ldbm_back_add( Slapi_PBlock *pb )
 		rc= slapi_setbit_int(rc,SLAPI_RTN_BIT_FETCH_EXISTING_DN_ENTRY);
 	}
 	rc= slapi_setbit_int(rc,SLAPI_RTN_BIT_FETCH_EXISTING_UNIQUEID_ENTRY);
-    rc= slapi_setbit_int(rc,SLAPI_RTN_BIT_FETCH_PARENT_ENTRY);
-    while(rc!=0)
+	rc= slapi_setbit_int(rc,SLAPI_RTN_BIT_FETCH_PARENT_ENTRY);
+	while(rc!=0)
 	{
 		/* JCM - copying entries can be expensive... should optimize */
 		/* 
@@ -175,20 +177,20 @@ ldbm_back_add( Slapi_PBlock *pb )
 		 * backend pre-op plugin. To ensure a consistent snapshot of this state
 		 * we wrap the reading of the entry with the dblock.
 		 */
-	    if(slapi_isbitset_int(rc,SLAPI_RTN_BIT_FETCH_EXISTING_UNIQUEID_ENTRY))
+		if(slapi_isbitset_int(rc,SLAPI_RTN_BIT_FETCH_EXISTING_UNIQUEID_ENTRY))
 		{
-            /* Check if an entry with the intended uniqueid already exists. */
+			/* Check if an entry with the intended uniqueid already exists. */
 			done_with_pblock_entry(pb,SLAPI_ADD_EXISTING_UNIQUEID_ENTRY); /* Could be through this multiple times */
 			addr.dn = NULL;
 			addr.uniqueid = (char*)slapi_entry_get_uniqueid(e); /* jcm -  cast away const */
 			ldap_result_code= get_copy_of_entry(pb, &addr, &txn, SLAPI_ADD_EXISTING_UNIQUEID_ENTRY, !is_replicated_operation);
 		}
-	    if(slapi_isbitset_int(rc,SLAPI_RTN_BIT_FETCH_EXISTING_DN_ENTRY))
+		if(slapi_isbitset_int(rc,SLAPI_RTN_BIT_FETCH_EXISTING_DN_ENTRY))
 		{
 			slapi_pblock_get( pb, SLAPI_ADD_TARGET, &dn );
-            slapi_sdn_set_dn_byref(&sdn, dn);
+			slapi_sdn_set_dn_byref(&sdn, dn);
 			slapi_sdn_get_backend_parent(&sdn,&parentsdn,pb->pb_backend);
-            /* Check if an entry with the intended DN already exists. */
+			/* Check if an entry with the intended DN already exists. */
 			done_with_pblock_entry(pb,SLAPI_ADD_EXISTING_DN_ENTRY); /* Could be through this multiple times */
 			addr.dn = dn;
 			addr.uniqueid = NULL;
@@ -206,24 +208,24 @@ ldbm_back_add( Slapi_PBlock *pb )
 			/* need to set parentsdn or parentuniqueid if either is not set? */
 		}
 
-        /* Call the Backend Pre Add plugins */
+		/* Call the Backend Pre Add plugins */
 		slapi_pblock_set(pb, SLAPI_RESULT_CODE, &ldap_result_code);
-    	rc= plugin_call_plugins(pb, SLAPI_PLUGIN_BE_PRE_ADD_FN);
-    	if(rc==-1)
-    	{
+		rc= plugin_call_plugins(pb, SLAPI_PLUGIN_BE_PRE_ADD_FN);
+		if(rc==-1)
+		{
 			/* 
 			 * Plugin indicated some kind of failure,
 			 * or that this Operation became a No-Op.
 			 */
 			slapi_pblock_get(pb, SLAPI_RESULT_CODE, &ldap_result_code);
-    	    goto error_return;
-    	}
+			goto error_return;
+		}
 		/*
 		 * (rc!=-1 && rc!= 0) means that the plugin changed things, so we go around
 		 * the loop once again to get the new present state.
 		 */
 		/* JCMREPL - Warning: A Plugin could cause an infinite loop by always returning a result code that requires some action. */
-    }	
+	}	
 
 	/*
 	 * Originally (in the U-M LDAP 3.3 code), there was a comment near this
@@ -237,7 +239,7 @@ ldbm_back_add( Slapi_PBlock *pb )
 	/* 
 	 * Fetch the parent entry and acquire the cache lock.
 	 */
-    if(have_parent_address(&parentsdn, operation->o_params.p.p_add.parentuniqueid))
+	if(have_parent_address(&parentsdn, operation->o_params.p.p_add.parentuniqueid))
 	{
 		addr.dn = (char*)slapi_sdn_get_dn (&parentsdn);
 		addr.uniqueid = operation->o_params.p.p_add.parentuniqueid;
@@ -255,13 +257,13 @@ ldbm_back_add( Slapi_PBlock *pb )
 		modify_init(&parent_modify_c,parententry);
 	}
 
-    /* Check if the entry we have been asked to add already exists */
+	/* Check if the entry we have been asked to add already exists */
 	{
 		Slapi_Entry *entry;
 		slapi_pblock_get( pb, SLAPI_ADD_EXISTING_DN_ENTRY, &entry);
 		if ( entry != NULL )
 		{
-		    /* The entry already exists */ 
+			/* The entry already exists */ 
 			ldap_result_code= LDAP_ALREADY_EXISTS;
 			goto error_return;
 		} 
@@ -283,7 +285,7 @@ ldbm_back_add( Slapi_PBlock *pb )
 				if ( ancestorentry != NULL )
 				{
 					int sentreferral= check_entry_for_referral(pb, ancestorentry->ep_entry, backentry_get_ndn(ancestorentry), "ldbm_back_add");
-				    cache_return( &inst->inst_cache, &ancestorentry );
+					cache_return( &inst->inst_cache, &ancestorentry );
 					if(sentreferral)
 					{
 						ldap_result_code= -1; /* The result was sent by check_entry_for_referral */
@@ -316,7 +318,7 @@ ldbm_back_add( Slapi_PBlock *pb )
 		tombstoneentry = find_entry2modify( pb, be, &addr, NULL );
 		if ( tombstoneentry==NULL )
 		{
-		    ldap_result_code= -1;
+			ldap_result_code= -1;
 			goto error_return;	  /* error result sent by find_entry2modify() */
 		}
 		tombstone_in_cache = 1;
@@ -324,7 +326,7 @@ ldbm_back_add( Slapi_PBlock *pb )
 		addingentry = backentry_dup( tombstoneentry );
 		if ( addingentry==NULL )
 		{
-	       	ldap_result_code= LDAP_OPERATIONS_ERROR;
+		   	ldap_result_code= LDAP_OPERATIONS_ERROR;
 			goto error_return;
 		}
 		/*
@@ -405,8 +407,8 @@ ldbm_back_add( Slapi_PBlock *pb )
 		addingentry = backentry_init( e );
 		if ( ( addingentry->ep_id = next_id( be ) ) >= MAXID ) {
 		  LDAPDebug( LDAP_DEBUG_ANY,
-			     "add: maximum ID reached, cannot add entry to "
-			     "backend '%s'", be->be_name, 0, 0 );
+				 "add: maximum ID reached, cannot add entry to "
+				 "backend '%s'", be->be_name, 0, 0 );
 		  ldap_result_code = LDAP_OPERATIONS_ERROR;
 		  goto error_return;
 		}
@@ -436,11 +438,11 @@ ldbm_back_add( Slapi_PBlock *pb )
 			/* Directly add the entry as a tombstone */
 			/*
 			 * 1) If the entry has an existing DN, change it to be
-			 *    "nsuniqueid=<uniqueid>, <old dn>"
+			 *	"nsuniqueid=<uniqueid>, <old dn>"
 			 * 2) Add the objectclass value "tombstone" and arrange for only
-			 *    that value to be indexed. 
+			 *	that value to be indexed. 
 			 * 3) If the parent entry was found, set the nsparentuniqueid
-			 *    attribute to be the unique id of that parent.
+			 *	attribute to be the unique id of that parent.
 			 */
 			char *untombstoned_dn = slapi_entry_get_dn(e);
 			if (NULL == untombstoned_dn)
@@ -476,13 +478,13 @@ ldbm_back_add( Slapi_PBlock *pb )
 			struct backentry *ancestorentry;
 
 			LDAPDebug( LDAP_DEBUG_TRACE,
-			    "parent does not exist, pdn = %s\n",
-			    slapi_sdn_get_dn(&parentsdn), 0, 0 );
+				"parent does not exist, pdn = %s\n",
+				slapi_sdn_get_dn(&parentsdn), 0, 0 );
 
 			ancestorentry = dn2ancestor(be, &parentsdn, &ancestordn, &txn, &err );
 			cache_return( &inst->inst_cache, &ancestorentry );
 
-    		ldap_result_code= LDAP_NO_SUCH_OBJECT;
+			ldap_result_code= LDAP_NO_SUCH_OBJECT;
 			ldap_result_matcheddn= slapi_ch_strdup((char *)slapi_sdn_get_dn(&ancestordn)); /* jcm - cast away const. */
 			slapi_sdn_done(&ancestordn);
 			goto error_return;
@@ -502,8 +504,8 @@ ldbm_back_add( Slapi_PBlock *pb )
 		if ( !isroot && !is_replicated_operation)
 		{
 			LDAPDebug( LDAP_DEBUG_TRACE, "no parent & not root\n",
-			    0, 0, 0 );
-    		ldap_result_code= LDAP_INSUFFICIENT_ACCESS;
+				0, 0, 0 );
+			ldap_result_code= LDAP_INSUFFICIENT_ACCESS;
 			goto error_return;
 		}
 		parententry = NULL;
@@ -527,7 +529,7 @@ ldbm_back_add( Slapi_PBlock *pb )
 		/*
 		 * add the parentid, entryid and entrydn operational attributes
 		 */
-	    add_update_entry_operational_attributes(addingentry, pid);
+		add_update_entry_operational_attributes(addingentry, pid);
 	}
 
 	/* Tentatively add the entry to the cache.  We do this after adding any
@@ -560,7 +562,7 @@ ldbm_back_add( Slapi_PBlock *pb )
 		retval = parent_update_on_childchange(&parent_modify_c,1,NULL); /* 1==add */\
 		/* The modify context now contains info needed later */
 		if (0 != retval) {
-       		ldap_result_code= LDAP_OPERATIONS_ERROR;
+	   		ldap_result_code= LDAP_OPERATIONS_ERROR;
 			goto error_return;
 		}
 		parent_found = 1;
@@ -577,10 +579,10 @@ ldbm_back_add( Slapi_PBlock *pb )
 			/* We're re-trying */
 			LDAPDebug( LDAP_DEBUG_TRACE, "Add Retrying Transaction\n", 0, 0, 0 );
 #ifndef LDBM_NO_BACKOFF_DELAY
-            {
-    	        PRIntervalTime interval;
-    			interval = PR_MillisecondsToInterval(slapi_rand() % 100);
-    			DS_Sleep(interval);
+			{
+				PRIntervalTime interval;
+				interval = PR_MillisecondsToInterval(slapi_rand() % 100);
+				DS_Sleep(interval);
 			}
 #endif
 		}
@@ -682,7 +684,7 @@ ldbm_back_add( Slapi_PBlock *pb )
 		}
 		if (retval != 0) {
 			LDAPDebug( LDAP_DEBUG_ANY, "add: attempt to index %lu failed\n",
-                                   (u_long)addingentry->ep_id, 0, 0 );
+								   (u_long)addingentry->ep_id, 0, 0 );
 			if (LDBM_OS_ERR_IS_DISKFULL(retval)) {
 				disk_full = 1;
 				ldap_result_code= LDAP_OPERATIONS_ERROR;
@@ -705,38 +707,41 @@ ldbm_back_add( Slapi_PBlock *pb )
 					   retval, (msg = dblayer_strerror( retval )) ? msg : "", 0 );
 				if (LDBM_OS_ERR_IS_DISKFULL(retval)) {
 					disk_full = 1;
-            		ldap_result_code= LDAP_OPERATIONS_ERROR;
+					ldap_result_code= LDAP_OPERATIONS_ERROR;
 					goto diskfull_return;
 				}
-            	ldap_result_code= LDAP_OPERATIONS_ERROR;
+				ldap_result_code= LDAP_OPERATIONS_ERROR;
 				goto error_return; 
 			}
 		}
-        /*
-         * Update the Virtual List View indexes
-         */
-        retval= vlv_update_all_indexes(&txn, be, pb, NULL, addingentry);
-		if (DB_LOCK_DEADLOCK == retval)
+		/*
+		 * Update the Virtual List View indexes
+		 */
+		if (!is_ruv)
 		{
-			LDAPDebug( LDAP_DEBUG_ARGS, "add DEADLOCK vlv_update_index\n", 0, 0, 0 );
-			/* Retry txn */
-			continue;
-		}
-		if (0 != retval) {
-			LDAPDebug( LDAP_DEBUG_TRACE, "vlv_update_index failed, err=%d %s\n",
-				   retval, (msg = dblayer_strerror( retval )) ? msg : "", 0 );
-			if (LDBM_OS_ERR_IS_DISKFULL(retval)) {
-				disk_full = 1;
+			retval= vlv_update_all_indexes(&txn, be, pb, NULL, addingentry);
+			if (DB_LOCK_DEADLOCK == retval) {
+				LDAPDebug( LDAP_DEBUG_ARGS,
+								"add DEADLOCK vlv_update_index\n", 0, 0, 0 );
+				/* Retry txn */
+				continue;
+			}
+			if (0 != retval) {
+				LDAPDebug( LDAP_DEBUG_TRACE,
+					"vlv_update_index failed, err=%d %s\n",
+				   	retval, (msg = dblayer_strerror( retval )) ? msg : "", 0 );
+				if (LDBM_OS_ERR_IS_DISKFULL(retval)) {
+					disk_full = 1;
+					ldap_result_code= LDAP_OPERATIONS_ERROR;
+					goto diskfull_return;
+				}
 				ldap_result_code= LDAP_OPERATIONS_ERROR;
-				goto diskfull_return;
+				goto error_return; 
 			}
-			ldap_result_code= LDAP_OPERATIONS_ERROR;
-			goto error_return; 
 		}
-		if (retval  == 0 ) {
+		if (retval == 0) {
 			break;
 		}
-
 	}
 	if (retry_count == RETRY_TIMES) {
 		/* Failed */
@@ -760,9 +765,9 @@ ldbm_back_add( Slapi_PBlock *pb )
 		if (cache_replace( &inst->inst_cache, tombstoneentry, addingentry ) != 0 )
 		{
 			/* This happens if the dn of addingentry already exists */
-		    ldap_result_code= LDAP_ALREADY_EXISTS;
+			ldap_result_code= LDAP_ALREADY_EXISTS;
 			cache_unlock_entry( &inst->inst_cache, tombstoneentry );
-		    goto error_return;
+			goto error_return;
 		}
 		/*
 		 * The tombstone was locked down in the cache... we can
@@ -844,9 +849,9 @@ common_return:
 	{
 		dblayer_unlock_backend(be);
 	}
-    if(ldap_result_code!=-1)
+	if(ldap_result_code!=-1)
 	{
-        slapi_send_ldap_result( pb, ldap_result_code, ldap_result_matcheddn, ldap_result_message, 0, NULL );
+		slapi_send_ldap_result( pb, ldap_result_code, ldap_result_matcheddn, ldap_result_message, 0, NULL );
 	}
 	slapi_sdn_done(&sdn);
 	slapi_sdn_done(&parentsdn);

+ 22 - 20
ldap/servers/slapd/back-ldbm/ldbm_delete.c

@@ -73,6 +73,7 @@ ldbm_back_delete( Slapi_PBlock *pb )
 	Slapi_Operation *operation;
 	CSN *opcsn = NULL;
 	int is_fixup_operation = 0;
+	int is_ruv = 0;                 /* True if the current entry is RUV */
 	int is_replicated_operation= 0;
 	int	is_tombstone_entry = 0;		/* True if the current entry is alreday a tombstone		*/
 	int delete_tombstone_entry = 0;	/* We must remove the given tombstone entry from the DB	*/
@@ -95,7 +96,8 @@ ldbm_back_delete( Slapi_PBlock *pb )
 		slapi_log_error (SLAPI_LOG_TRACE, "ldbm_back_delete", "enter conn=%d op=%d\n", pb->pb_conn->c_connid, operation->o_opid);
 	}
 
-	is_fixup_operation = operation_is_flag_set(operation,OP_FLAG_REPL_FIXUP);
+	is_fixup_operation = operation_is_flag_set(operation, OP_FLAG_REPL_FIXUP);
+	is_ruv = operation_is_flag_set(operation, OP_FLAG_REPL_RUV);
 	delete_tombstone_entry = operation_is_flag_set(operation, OP_FLAG_TOMBSTONE_ENTRY);
 	
 	inst = (ldbm_instance *) be->be_instance_info;
@@ -469,7 +471,8 @@ ldbm_back_delete( Slapi_PBlock *pb )
     			ldap_result_code= LDAP_OPERATIONS_ERROR;
 				goto error_return;
 			}
-		} else if (delete_tombstone_entry)
+		} /* create_tombstone_entry */
+		else if (delete_tombstone_entry)
 		{
 			/* 
 			 * We need to remove the Tombstone entry from the remaining indexes:
@@ -521,7 +524,7 @@ ldbm_back_delete( Slapi_PBlock *pb )
 					goto error_return;
 				}
 			}
-		}
+		} /* delete_tombstone_entry */
 		
 		if (parent_found) {
 			/* Push out the db modifications from the parent entry */
@@ -536,32 +539,31 @@ ldbm_back_delete( Slapi_PBlock *pb )
 				LDAPDebug( LDAP_DEBUG_TRACE, "delete 3 BAD, err=%d %s\n",
 					   retval, (msg = dblayer_strerror( retval )) ? msg : "", 0 );
 				if (LDBM_OS_ERR_IS_DISKFULL(retval)) disk_full = 1;
-    			ldap_result_code= LDAP_OPERATIONS_ERROR;
+				ldap_result_code= LDAP_OPERATIONS_ERROR;
 				goto error_return;
 			}
 		}
 		/* 
 		 * first check if searchentry needs to be removed
          * Remove the entry from the Virtual List View indexes.
-		 * 
 		 */
-		if(!delete_tombstone_entry && 
-		   !vlv_delete_search_entry(pb,e->ep_entry,inst)) {
+		if (!delete_tombstone_entry && !is_ruv &&
+		    !vlv_delete_search_entry(pb,e->ep_entry,inst)) {
 			retval = vlv_update_all_indexes(&txn, be, pb, e, NULL);
+
+			if (DB_LOCK_DEADLOCK == retval)
+			{
+				LDAPDebug( LDAP_DEBUG_ARGS, "delete DEADLOCK vlv_update_index\n", 0, 0, 0 );
+				/* Retry txn */
+				continue;
+			}
+			if (retval  != 0 ) {
+				if (LDBM_OS_ERR_IS_DISKFULL(retval)) disk_full = 1;
+				ldap_result_code= LDAP_OPERATIONS_ERROR;
+				goto error_return;
+			}
 		}
-	
-		if (DB_LOCK_DEADLOCK == retval)
-		{
-			LDAPDebug( LDAP_DEBUG_ARGS, "delete DEADLOCK vlv_update_index\n", 0, 0, 0 );
-			/* Retry txn */
-			continue;
-		}
-		if (retval  != 0 ) {
-			if (LDBM_OS_ERR_IS_DISKFULL(retval)) disk_full = 1;
-			ldap_result_code= LDAP_OPERATIONS_ERROR;
-			goto error_return;
-		}
-		if (retval  == 0 ) {
+		if (retval == 0 ) {
 			break;
 		}
 	}

+ 55 - 44
ldap/servers/slapd/back-ldbm/ldbm_modify.c

@@ -131,12 +131,18 @@ int modify_update_all(backend *be, Slapi_PBlock *pb,
 					  back_txn *txn)
 {
 	static char *function_name = "modify_update_all";
+	Slapi_Operation *operation;
+	int is_ruv = 0;				 /* True if the current entry is RUV */
 	int retval = 0;
 
-    /*
-     * Update the ID to Entry index. 
-     * Note that id2entry_add replaces the entry, so the Entry ID stays the same.
-     */
+	if (pb) { /* pb could be NULL if it's called from import */
+		slapi_pblock_get( pb, SLAPI_OPERATION, &operation );
+		is_ruv = operation_is_flag_set(operation, OP_FLAG_REPL_RUV);
+	}
+	/*
+	 * Update the ID to Entry index. 
+	 * Note that id2entry_add replaces the entry, so the Entry ID stays the same.
+	 */
 	retval = id2entry_add( be, mc->new_entry, txn );
 	if ( 0 != retval ) {
 		if (DB_LOCK_DEADLOCK != retval)
@@ -153,13 +159,13 @@ int modify_update_all(backend *be, Slapi_PBlock *pb,
 		}
 		goto error;
 	}
-    /*
-     * Remove the old entry from the Virtual List View indexes.
-     * Add the new entry to the Virtual List View indexes.
+	/*
+	 * Remove the old entry from the Virtual List View indexes.
+	 * Add the new entry to the Virtual List View indexes.
 	 * Because the VLV code calls slapi_filter_test(), which requires a pb (why?),
 	 * we allow the caller sans pb to get everything except vlv indexing.
-     */
-	if (NULL != pb) {
+	 */
+	if (NULL != pb && !is_ruv) {
 		retval= vlv_update_all_indexes(txn, be, pb, mc->old_entry, mc->new_entry);
 		if ( 0 != retval ) {
 			if (DB_LOCK_DEADLOCK != retval)
@@ -189,7 +195,7 @@ ldbm_back_modify( Slapi_PBlock *pb )
 	char			*errbuf = NULL;
 	int retry_count = 0;
 	int disk_full = 0;
-    int ldap_result_code= LDAP_SUCCESS;
+	int ldap_result_code= LDAP_SUCCESS;
 	char *ldap_result_message= NULL;
 	int rc = 0;
 	Slapi_Operation *operation;
@@ -198,6 +204,7 @@ ldbm_back_modify( Slapi_PBlock *pb )
 	int change_entry = 0;
 	int ec_in_cache = 0;
 	int is_fixup_operation= 0;
+	int is_ruv = 0;                 /* True if the current entry is RUV */
 	CSN *opcsn = NULL;
 	int repl_op;
 
@@ -208,7 +215,8 @@ ldbm_back_modify( Slapi_PBlock *pb )
 	slapi_pblock_get( pb, SLAPI_PARENT_TXN, (void**)&parent_txn );
 	slapi_pblock_get( pb, SLAPI_OPERATION, &operation );
 	slapi_pblock_get (pb, SLAPI_IS_REPLICATED_OPERATION, &repl_op);	
-	is_fixup_operation = operation_is_flag_set(operation,OP_FLAG_REPL_FIXUP);
+	is_fixup_operation = operation_is_flag_set(operation, OP_FLAG_REPL_FIXUP);
+	is_ruv = operation_is_flag_set(operation, OP_FLAG_REPL_RUV);
 	inst = (ldbm_instance *) be->be_instance_info;
 
 	dblayer_txn_init(li,&txn);
@@ -221,15 +229,14 @@ ldbm_back_modify( Slapi_PBlock *pb )
 	 * operations that the URP code in the Replication
 	 * plugin generates.
 	 */
-	if(SERIALLOCK(li) && !operation_is_flag_set(operation,OP_FLAG_REPL_FIXUP))
-	{
+	if(SERIALLOCK(li) && !operation_is_flag_set(operation,OP_FLAG_REPL_FIXUP)) {
 		dblayer_lock_backend(be);
 		dblock_acquired= 1;
 	}
 
 	/* find and lock the entry we are about to modify */
 	if ( (e = find_entry2modify( pb, be, addr, NULL )) == NULL ) {
-	    ldap_result_code= -1;
+		ldap_result_code= -1;
 		goto error_return;	  /* error result sent by find_entry2modify() */
 	}
 
@@ -260,7 +267,7 @@ ldbm_back_modify( Slapi_PBlock *pb )
 
 	/* create a copy of the entry and apply the changes to it */
 	if ( (ec = backentry_dup( e )) == NULL ) {
-       	ldap_result_code= LDAP_OPERATIONS_ERROR;
+		ldap_result_code= LDAP_OPERATIONS_ERROR;
 		goto error_return;
 	}
 
@@ -276,10 +283,10 @@ ldbm_back_modify( Slapi_PBlock *pb )
 
 	{
 		Slapi_Mods smods;
-        CSN *csn = operation_get_csn(operation);
+		CSN *csn = operation_get_csn(operation);
 		slapi_mods_init_byref(&smods,mods);
 		if ( (change_entry = mods_have_effect (ec->ep_entry, &smods)) ) {
-	    	ldap_result_code = entry_apply_mods_wsi(ec->ep_entry, &smods, csn, operation_is_flag_set(operation,OP_FLAG_REPLICATED));
+			ldap_result_code = entry_apply_mods_wsi(ec->ep_entry, &smods, csn, operation_is_flag_set(operation,OP_FLAG_REPLICATED));
 			/*
 			 * XXXmcs: it would be nice to get back an error message from
 			 * the above call so we could pass it along to the client, e.g.,
@@ -356,8 +363,8 @@ ldbm_back_modify( Slapi_PBlock *pb )
 			dblayer_txn_abort(li,&txn);
 			LDAPDebug( LDAP_DEBUG_TRACE, "Modify Retrying Transaction\n", 0, 0, 0 );
 #ifndef LDBM_NO_BACKOFF_DELAY
-            {
-	        PRIntervalTime interval;
+			{
+			PRIntervalTime interval;
 			interval = PR_MillisecondsToInterval(slapi_rand() % 100);
 			DS_Sleep(interval);
 			}
@@ -373,10 +380,10 @@ ldbm_back_modify( Slapi_PBlock *pb )
 			goto error_return;
 		}
 
-        /*
-         * Update the ID to Entry index. 
-         * Note that id2entry_add replaces the entry, so the Entry ID stays the same.
-         */
+		/*
+		 * Update the ID to Entry index. 
+		 * Note that id2entry_add replaces the entry, so the Entry ID stays the same.
+		 */
 		retval = id2entry_add( be, ec, &txn ); 
 		if (DB_LOCK_DEADLOCK == retval)
 		{
@@ -404,37 +411,41 @@ ldbm_back_modify( Slapi_PBlock *pb )
 			ldap_result_code= LDAP_OPERATIONS_ERROR;
 			goto error_return;
 		}
-        /*
-         * Remove the old entry from the Virtual List View indexes.
-         * Add the new entry to the Virtual List View indexes.
-         */
-        retval= vlv_update_all_indexes(&txn, be, pb, e, ec);
-		if (DB_LOCK_DEADLOCK == retval)
-		{
-			/* Abort and re-try */
-			continue;
-		}
-		if (0 != retval) {
-			LDAPDebug( LDAP_DEBUG_ANY, "vlv_update_index failed, err=%d %s\n",
-				  retval, (msg = dblayer_strerror( retval )) ? msg : "", 0 );
-			if (LDBM_OS_ERR_IS_DISKFULL(retval)) disk_full = 1;
-			ldap_result_code= LDAP_OPERATIONS_ERROR;
-			goto error_return;
-		}
+		/*
+		 * Remove the old entry from the Virtual List View indexes.
+		 * Add the new entry to the Virtual List View indexes.
+		 * If the entry is ruv, no need to update vlv.
+		 */
+		if (!is_ruv) {
+			retval= vlv_update_all_indexes(&txn, be, pb, e, ec);
+			if (DB_LOCK_DEADLOCK == retval)
+			{
+				/* Abort and re-try */
+				continue;
+			}
+			if (0 != retval) {
+				LDAPDebug( LDAP_DEBUG_ANY, 
+					"vlv_update_index failed, err=%d %s\n",
+					retval, (msg = dblayer_strerror( retval )) ? msg : "", 0 );
+				if (LDBM_OS_ERR_IS_DISKFULL(retval)) disk_full = 1;
+				ldap_result_code= LDAP_OPERATIONS_ERROR;
+				goto error_return;
+			}
 
+		}
 		if (0 == retval) {
 			break;
 		}
 	}
 	if (retry_count == RETRY_TIMES) {
 		LDAPDebug( LDAP_DEBUG_ANY, "Retry count exceeded in modify\n", 0, 0, 0 );
-    	ldap_result_code= LDAP_OPERATIONS_ERROR;
+	   	ldap_result_code= LDAP_OPERATIONS_ERROR;
 		goto error_return;
 	}
 	
 	if (cache_replace( &inst->inst_cache, e, ec ) != 0 ) {
-	    ldap_result_code= LDAP_OPERATIONS_ERROR;
-	    goto error_return;
+		ldap_result_code= LDAP_OPERATIONS_ERROR;
+		goto error_return;
 	}
 
 	postentry = slapi_entry_dup( ec->ep_entry );
@@ -473,7 +484,7 @@ error_return:
 	}
 	else
 	{
-        backentry_free(&ec);
+		backentry_free(&ec);
 	}
 	if ( postentry != NULL ) 
 	{

+ 19 - 11
ldap/servers/slapd/back-ldbm/ldbm_modrdn.c

@@ -113,7 +113,7 @@ ldbm_back_modrdn( Slapi_PBlock *pb )
 	slapi_pblock_get( pb, SLAPI_REQUESTOR_ISROOT, &isroot );
 	slapi_pblock_get( pb, SLAPI_OPERATION, &operation );
 	slapi_pblock_get( pb, SLAPI_IS_REPLICATED_OPERATION, &is_replicated_operation );
-	is_fixup_operation = operation_is_flag_set(operation,OP_FLAG_REPL_FIXUP);
+	is_fixup_operation = operation_is_flag_set(operation, OP_FLAG_REPL_FIXUP);
 
 	if (pb->pb_conn)
 	{
@@ -1127,8 +1127,12 @@ modrdn_rename_entry_update_indexes(back_txn *ptxn, Slapi_PBlock *pb, struct ldbm
 	ldbm_instance *inst;
 	int retval= 0;
 	char *msg;
+	Slapi_Operation *operation;
+	int is_ruv = 0;                 /* True if the current entry is RUV */
 
-	slapi_pblock_get( pb, SLAPI_BACKEND, &be);
+	slapi_pblock_get( pb, SLAPI_BACKEND, &be );
+	slapi_pblock_get( pb, SLAPI_OPERATION, &operation );
+	is_ruv = operation_is_flag_set(operation, OP_FLAG_REPL_RUV);
 	inst = (ldbm_instance *) be->be_instance_info;
 
 	/*
@@ -1206,17 +1210,21 @@ modrdn_rename_entry_update_indexes(back_txn *ptxn, Slapi_PBlock *pb, struct ldbm
 	/*
 	 * Remove the old entry from the Virtual List View indexes.
 	 * Add the new entry to the Virtual List View indexes.
+	 * If ruv, we don't have to update vlv.
 	 */
-	retval= vlv_update_all_indexes(ptxn, be, pb, e, ec);
-	if (DB_LOCK_DEADLOCK == retval)
+	if (!is_ruv)
 	{
-		/* Abort and re-try */
-		goto error_return;
-	}
-	if (retval != 0)
-	{
-		LDAPDebug( LDAP_DEBUG_TRACE, "vlv_update_all_indexes failed, err=%d %s\n", retval, (msg = dblayer_strerror( retval )) ? msg : "", 0 );
-		goto error_return;
+		retval= vlv_update_all_indexes(ptxn, be, pb, e, ec);
+		if (DB_LOCK_DEADLOCK == retval)
+		{
+			/* Abort and re-try */
+			goto error_return;
+		}
+		if (retval != 0)
+		{
+			LDAPDebug( LDAP_DEBUG_TRACE, "vlv_update_all_indexes failed, err=%d %s\n", retval, (msg = dblayer_strerror( retval )) ? msg : "", 0 );
+			goto error_return;
+		}
 	}
 	if (cache_replace( &inst->inst_cache, e, ec ) != 0 ) {
 		retval= -1;

+ 37 - 21
ldap/servers/slapd/slapi-private.h

@@ -382,27 +382,43 @@ slapi_filter_to_string_internal( const struct slapi_filter *f, char *buf, size_t
 
 /* operation.c */
 
-#define	OP_FLAG_PS				0x00001
-#define	OP_FLAG_PS_CHANGESONLY			0x00002
-#define OP_FLAG_GET_EFFECTIVE_RIGHTS		0x00004  
-#define OP_FLAG_REPLICATED			0x00008 /* A Replicated Operation */
-#define OP_FLAG_REPL_FIXUP			0x00010 /* A Fixup Operation, generated as a
-							 * consequence of a Replicated Operation. */
-#define OP_FLAG_INTERNAL			0x00020 /* An operation generated by the core
-							 * server or a plugin. */ 
-#define OP_FLAG_ACTION_LOG_ACCESS		0x00040
-#define OP_FLAG_ACTION_LOG_AUDIT		0x00080
-#define OP_FLAG_ACTION_SCHEMA_CHECK		0x00100
-#define OP_FLAG_ACTION_LOG_CHANGES		0x00200
-#define OP_FLAG_ACTION_INVOKE_FOR_REPLOP	0x00400
-#define OP_FLAG_NEVER_CHAIN 			SLAPI_OP_FLAG_NEVER_CHAIN  /* 0x0800 */
-#define OP_FLAG_TOMBSTONE_ENTRY			0x01000
-#define OP_FLAG_RESURECT_ENTRY			0x02000
-#define OP_FLAG_LEGACY_REPLICATION_DN		0x04000 /* Operation done by legacy replication DN */
-#define OP_FLAG_ACTION_NOLOG			0x08000 /* Do not log the entry in audit log or
-							 * change log */
-#define OP_FLAG_SKIP_MODIFIED_ATTRS		0x10000 /* Do not update the modifiersname,
-							 * modifiedtimestamp, etc. attributes */
+#define OP_FLAG_PS                       0x00001
+#define OP_FLAG_PS_CHANGESONLY           0x00002
+#define OP_FLAG_GET_EFFECTIVE_RIGHTS     0x00004  
+#define OP_FLAG_REPLICATED               0x00008 /* A Replicated Operation */
+#define OP_FLAG_REPL_FIXUP               0x00010 /* A Fixup Operation, 
+                                                  * generated as a consequence
+                                                  * of a Replicated Operation.
+                                                  */
+#define OP_FLAG_INTERNAL                 0x00020 /* An operation generated by 
+                                                  * the core server or a plugin.
+                                                  */ 
+#define OP_FLAG_ACTION_LOG_ACCESS        0x00040
+#define OP_FLAG_ACTION_LOG_AUDIT         0x00080
+#define OP_FLAG_ACTION_SCHEMA_CHECK      0x00100
+#define OP_FLAG_ACTION_LOG_CHANGES       0x00200
+#define OP_FLAG_ACTION_INVOKE_FOR_REPLOP 0x00400
+#define OP_FLAG_NEVER_CHAIN              SLAPI_OP_FLAG_NEVER_CHAIN  /* 0x0800 */
+#define OP_FLAG_TOMBSTONE_ENTRY          0x01000
+#define OP_FLAG_RESURECT_ENTRY           0x02000
+#define OP_FLAG_LEGACY_REPLICATION_DN    0x04000 /* Operation done by legacy 
+                                                  * replication DN
+                                                  */
+#define OP_FLAG_ACTION_NOLOG             0x08000 /* Do not log the entry in 
+                                                  * audit log or change log
+                                                  */
+#define OP_FLAG_SKIP_MODIFIED_ATTRS      0x10000 /* Do not update the 
+                                                  * modifiersname,
+                                                  * modifiedtimestamp, etc.
+                                                  * attributes
+                                                  */
+#define OP_FLAG_REPL_RUV                 0x20000 /* Flag to tell to the backend
+                                                  * that the entry to be added/
+                                                  * modified is RUV. This info
+                                                  * is used to skip VLV op.
+                                                  * (see #329951)
+                                                  */
+
 
 CSN *operation_get_csn(Slapi_Operation *op);
 void operation_set_csn(Slapi_Operation *op,CSN *csn);