瀏覽代碼

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 18 年之前
父節點
當前提交
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);