瀏覽代碼

Trac Ticket #499 - Handling URP results is not corrrect

https://fedorahosted.org/389/ticket/499

Bug description: When an urp resolution occurred as follows
  [] - urp_delete: Entry "nsuniqueid=<UNIQID>,uid=<UID>,o=<ORG>"
is already a Tombstone.
the operation should be skipped in the backend, but should return
SUCCESS to the supplier.  Otherwise, the supplier continues to
send the relay and the replication stops there.

Fix description: This patch introduced SLAPI_PLUGIN_NOOP (-2)
to the bepre and betxnpre plugin return value set (SLAPI_
PLUGIN_SUCCESS == 0; SLAPI_PLUGIN_FAILURE == -1).  If SLAPI_
PLUGIN_NOOP is returned, the backend code skips the operation,
but it returns SUCCESS.  Note that urp is only executed on the
replicated operation (not on the end user ones).
Noriko Hosoi 13 年之前
父節點
當前提交
d59f687e2a

+ 70 - 48
ldap/servers/plugins/replication/urp.c

@@ -53,10 +53,10 @@
 extern int slapi_log_urp;
 
 static int urp_add_resolve_parententry (Slapi_PBlock *pb, char *sessionid, Slapi_Entry *entry, Slapi_Entry *parententry, CSN *opcsn);
-static int urp_annotate_dn (char *sessionid, Slapi_Entry *entry, CSN *opcsn, const char *optype);
+static int urp_annotate_dn (char *sessionid, const Slapi_Entry *entry, CSN *opcsn, const char *optype);
 static int urp_naming_conflict_removal (Slapi_PBlock *pb, char *sessionid, CSN *opcsn, const char *optype);
 static int mod_namingconflict_attr (const char *uniqueid, const Slapi_DN *entrysdn, const Slapi_DN *conflictsdn, CSN *opcsn);
-static int del_replconflict_attr (Slapi_Entry *entry, CSN *opcsn, int opflags);
+static int del_replconflict_attr (const Slapi_Entry *entry, CSN *opcsn, int opflags);
 static char *get_dn_plus_uniqueid(char *sessionid,const char *olddn,const char *uniqueid);
 static char *get_rdn_plus_uniqueid(char *sessionid,const char *olddn,const char *uniqueid);
 static int is_suffix_entry (Slapi_PBlock *pb, Slapi_Entry *entry, Slapi_DN **parenddn);
@@ -69,19 +69,21 @@ urp_modify_operation( Slapi_PBlock *pb )
 {
 	Slapi_Entry *modifyentry= NULL;
 	int op_result= 0;
-    int rc= 0; /* OK */
+	int rc= 0; /* OK */
+	char sessionid[REPL_SESSION_ID_SIZE];
+	CSN *opcsn;
 
 	if ( slapi_op_abandoned(pb) )
 	{
 		return rc;
 	}
 
-   	slapi_pblock_get( pb, SLAPI_MODIFY_EXISTING_ENTRY, &modifyentry );
-
+	get_repl_session_id (pb, sessionid, &opcsn);
+	slapi_pblock_get( pb, SLAPI_MODIFY_EXISTING_ENTRY, &modifyentry );
 	if(modifyentry!=NULL)
 	{
-	    /*
-	     * The entry to be modified exists.
+		/*
+		 * The entry to be modified exists.
 		 * - the entry could be a tombstone... but that's OK.
 		 * - the entry could be glue... that may not be OK. JCMREPL
 		 */
@@ -90,12 +92,14 @@ urp_modify_operation( Slapi_PBlock *pb )
 	}
 	else
 	{
-	    /*
-	     * The entry to be modified could not be found.
-	     */ 
+		/*
+		 * The entry to be modified could not be found.
+		 */ 
 		op_result= LDAP_NO_SUCH_OBJECT;
 		slapi_pblock_set(pb, SLAPI_RESULT_CODE, &op_result);
-		rc= -1; /* Must discard this Modification */
+		rc = SLAPI_PLUGIN_NOOP; /* Must discard this Modification */
+		slapi_log_error (slapi_log_urp, sessionid,
+		                 "urp_modify: No such entry\n");
 		PROFILE_POINT; /* Modify Conflict; Entry Does Not Exist; Discard Modification */
 	}
 	return rc;
@@ -129,6 +133,7 @@ urp_add_operation( Slapi_PBlock *pb )
 		return rc;
 	}
 
+	get_repl_session_id (pb, sessionid, &opcsn);
 	slapi_pblock_get( pb, SLAPI_ADD_EXISTING_UNIQUEID_ENTRY, &existing_uniqueid_entry );
 	if (existing_uniqueid_entry!=NULL)
 	{
@@ -149,12 +154,11 @@ urp_add_operation( Slapi_PBlock *pb )
 		          slapi_entry_get_dn_const(existing_uniqueid_entry));
 		op_result= LDAP_UNWILLING_TO_PERFORM;
 		slapi_pblock_set(pb, SLAPI_RESULT_CODE, &op_result);
-		rc= -1; /* Ignore this Operation */
+		rc = SLAPI_PLUGIN_NOOP; /* Ignore this Operation */
 		PROFILE_POINT; /* Add Conflict; UniqueID Exists;  Ignore */
 		goto bailout;
 	}
 
-	get_repl_session_id (pb, sessionid, &opcsn);
 	slapi_pblock_get( pb, SLAPI_ADD_ENTRY, &addentry );
 	slapi_pblock_get( pb, SLAPI_ADD_EXISTING_DN_ENTRY, &existing_dn_entry );
 	if (existing_dn_entry==NULL) /* The target DN does not exist */
@@ -185,7 +189,10 @@ urp_add_operation( Slapi_PBlock *pb )
 		{
 			op_result= LDAP_OPERATIONS_ERROR;
 			slapi_pblock_set(pb, SLAPI_RESULT_CODE, &op_result);
-			rc= -1; /* Abort this Operation */
+			rc = SLAPI_PLUGIN_NOOP; /* Abort this Operation */
+			slapi_log_error(slapi_log_urp, sessionid,
+			      "urp_add (%s): Add conflict; Unique ID (%s) already in RDN\n",
+			      basedn, adduniqueid);
 			PROFILE_POINT; /* Add Conflict; Entry Exists; Unique ID already in RDN - Abort this update. */
 		}
 		else
@@ -200,7 +207,8 @@ urp_add_operation( Slapi_PBlock *pb )
 			if (slapi_entry_attr_find (addentry, ATTR_NSDS5_REPLCONFLICT, &attr) == 0)
 			{
 				/* ATTR_NSDS5_REPLCONFLICT exists */
-				slapi_log_error (SLAPI_LOG_FATAL, sessionid, "New entry has nsds5ReplConflict already\n");
+				slapi_log_error(SLAPI_LOG_FATAL, sessionid,
+				          "urp_add: New entry has nsds5ReplConflict already\n");
 				vals = attr_get_present_values (attr); /* this returns a pointer to the contents */
 			}
 			if ( vals == NULL || *vals == NULL )
@@ -227,7 +235,8 @@ urp_add_operation( Slapi_PBlock *pb )
 
 			rdn = slapi_rdn_new_sdn ( slapi_entry_get_sdn_const(addentry) );
 			slapi_log_error (slapi_log_urp, sessionid,
-					"Naming conflict ADD. Add %s instead\n", slapi_rdn_get_rdn(rdn) );
+			                 "urp_add: Naming conflict ADD. Add %s instead\n",
+			                 slapi_rdn_get_rdn(rdn));
 			slapi_rdn_free(&rdn);
 
 			rc= slapi_setbit_int(rc,SLAPI_RTN_BIT_FETCH_EXISTING_DN_ENTRY);
@@ -241,7 +250,10 @@ urp_add_operation( Slapi_PBlock *pb )
 		{
 			op_result= LDAP_OPERATIONS_ERROR;
 			slapi_pblock_set(pb, SLAPI_RESULT_CODE, &op_result);
-			rc= -1; /* Ignore this Operation */
+			slapi_log_error(slapi_log_urp, sessionid,
+			                "urp_add (%s): Entry to be added is a loser; "
+			                "urp_annotate_dn failed.\n", basedn);
+			rc = SLAPI_PLUGIN_NOOP; /* Ignore this Operation */
 		}
 		else
 		{
@@ -271,12 +283,12 @@ urp_add_operation( Slapi_PBlock *pb )
 		slapi_entry_get_dn_const(existing_dn_entry));
 		op_result= LDAP_UNWILLING_TO_PERFORM;
 		slapi_pblock_set(pb, SLAPI_RESULT_CODE, &op_result);
-		rc= -1; /* Ignore this Operation */
+		rc = SLAPI_PLUGIN_NOOP; /* Ignore this Operation */
 		PROFILE_POINT; /* Add Conflict; Entry Exists; Same CSN */
 	}
 
 bailout:
-    return rc;
+	return rc;
 }
 
 /*
@@ -289,11 +301,11 @@ urp_modrdn_operation( Slapi_PBlock *pb )
 {
 	slapi_operation_parameters *op_params = NULL;
 	Slapi_Entry *parent_entry;
-    Slapi_Entry *new_parent_entry;
+	Slapi_Entry *new_parent_entry;
 	Slapi_DN *newsuperior = NULL;
 	Slapi_DN *parentdn = NULL;
-	Slapi_Entry *target_entry;
-    Slapi_Entry *existing_entry;
+	const Slapi_Entry *target_entry;
+	Slapi_Entry *existing_entry;
 	const CSN *target_entry_dncsn;
 	CSN *opcsn= NULL;
 	char *op_uniqueid = NULL;
@@ -304,7 +316,7 @@ urp_modrdn_operation( Slapi_PBlock *pb )
 	char sessionid[REPL_SESSION_ID_SIZE];
 	int r;
 	int op_result= 0;
-    int rc= 0; /* OK */
+	int rc= 0; /* OK */
 	int del_old_replconflict_attr = 0;
 
 	if ( slapi_op_abandoned(pb) )
@@ -312,7 +324,7 @@ urp_modrdn_operation( Slapi_PBlock *pb )
 		return rc;
 	}
 
-   	slapi_pblock_get (pb, SLAPI_MODRDN_TARGET_ENTRY, &target_entry);
+	slapi_pblock_get (pb, SLAPI_MODRDN_TARGET_ENTRY, &target_entry);
 	if(target_entry==NULL)
 	{
 		/* An entry can't be found for the Unique Identifier */
@@ -323,7 +335,7 @@ urp_modrdn_operation( Slapi_PBlock *pb )
 		goto bailout;
 	}
 
-   	get_repl_session_id (pb, sessionid, &opcsn);
+	get_repl_session_id (pb, sessionid, &opcsn);
 	target_entry_dncsn = entry_get_dncsn (target_entry);
 	if ( csn_compare (target_entry_dncsn, opcsn) >= 0 )
 	{
@@ -343,7 +355,7 @@ urp_modrdn_operation( Slapi_PBlock *pb )
 		           slapi_entry_get_dn_const(target_entry));
 		op_result= LDAP_UNWILLING_TO_PERFORM;
 		slapi_pblock_set(pb, SLAPI_RESULT_CODE, &op_result);
-		rc= -1; /* Ignore the modrdn */
+		rc = SLAPI_PLUGIN_NOOP; /* Ignore the modrdn */
 		PROFILE_POINT; /* ModRDN Conflict; Entry with Target DN Exists; OPCSN is not newer. */
 		goto bailout;
 	}
@@ -385,7 +397,10 @@ urp_modrdn_operation( Slapi_PBlock *pb )
 		}
 		else
 		{
-			rc = -1;
+			slapi_log_error(slapi_log_urp, sessionid,
+			                "urp_modrdn (%s): target entry is a tombstone.\n",
+			                slapi_entry_get_dn_const(target_entry));
+			rc = SLAPI_PLUGIN_NOOP; /* Ignore the modrdn */
 		}
 		PROFILE_POINT; /* ModRDN Conflict; Entry with Target DN Exists; OPCSN is not newer. */
 		goto bailout;
@@ -426,12 +441,12 @@ urp_modrdn_operation( Slapi_PBlock *pb )
 			 * but the uniqueids are not.
 			 * There might be two replicas with the same ReplicaID.
 			 */
-			slapi_log_error(SLAPI_LOG_FATAL, sessionid,
-				"Duplicated CSN for different uniqueids [%s][%s]",
+			slapi_log_error(slapi_log_urp, sessionid,
+				"urp_modrdn: Duplicated CSN for different uniqueids [%s][%s]",
 				existing_uniqueid, op_uniqueid);
 			op_result= LDAP_OPERATIONS_ERROR;
 			slapi_pblock_set(pb, SLAPI_RESULT_CODE, &op_result);
-			rc= -1; /* Abort */
+			rc = SLAPI_PLUGIN_NOOP; /* Ignore this Operation */
 			PROFILE_POINT; /* ModRDN Conflict; Duplicated CSN for Different Entries */
 			goto bailout;
 		}
@@ -454,8 +469,8 @@ urp_modrdn_operation( Slapi_PBlock *pb )
 			mod_namingconflict_attr (op_uniqueid, target_sdn, existing_sdn, opcsn);
 			slapi_pblock_set(pb, SLAPI_MODRDN_NEWRDN, newrdn_with_uniqueid); 
 			slapi_log_error(slapi_log_urp, sessionid,
-					"Naming conflict MODRDN. Rename target entry to %s\n",
-					newrdn_with_uniqueid );
+			  "urp_modrdn: Naming conflict MODRDN. Rename target entry to %s\n",
+			  newrdn_with_uniqueid );
 
 			rc= slapi_setbit_int(rc,SLAPI_RTN_BIT_FETCH_EXISTING_DN_ENTRY);
 			PROFILE_POINT; /* ModRDN Conflict; Entry with Target DN Exists; Rename Operation Entry */
@@ -559,11 +574,11 @@ urp_modrdn_operation( Slapi_PBlock *pb )
 			 * admin intercession
 			 */
 			slapi_log_error( SLAPI_LOG_FATAL, sessionid,
-				 "Parent %s couldn't be found, nor recreated as a glue entry\n",
+				 "urp_modrdn: Parent %s couldn't be found, nor recreated as a glue entry\n",
 				 slapi_sdn_get_dn(newsuperior) );
 			op_result= LDAP_OPERATIONS_ERROR;
 			slapi_pblock_set(pb, SLAPI_RESULT_CODE, &op_result);
-			rc = -1;
+			rc = SLAPI_PLUGIN_FAILURE; /* Ignore this Operation */
 			PROFILE_POINT;
 			goto bailout;
 		}
@@ -590,24 +605,25 @@ bailout:
 int 
 urp_delete_operation( Slapi_PBlock *pb )
 {
-  	Slapi_Entry *deleteentry;
+	const Slapi_Entry *deleteentry;
 	CSN *opcsn= NULL;
 	char sessionid[REPL_SESSION_ID_SIZE];
 	int op_result= 0;
-    int rc= 0; /* OK */
+    int rc = SLAPI_PLUGIN_SUCCESS; /* OK */
 
 	if ( slapi_op_abandoned(pb) )
 	{
 		return rc;
 	}
 
-   	slapi_pblock_get(pb, SLAPI_DELETE_EXISTING_ENTRY, &deleteentry);
+	slapi_pblock_get(pb, SLAPI_DELETE_EXISTING_ENTRY, &deleteentry);
 
+	get_repl_session_id (pb, sessionid, &opcsn);
 	if(deleteentry==NULL) /* uniqueid can't be found */
 	{
 		op_result= LDAP_NO_SUCH_OBJECT;
 		slapi_pblock_set(pb, SLAPI_RESULT_CODE, &op_result);
-		rc= -1; /* Don't apply the Delete */
+		rc = SLAPI_PLUGIN_FAILURE; /* Don't apply the Delete */
 		PROFILE_POINT; /* Delete Operation; Entry not exist. */
 	}
 	else if(is_tombstone_entry(deleteentry))
@@ -615,7 +631,10 @@ urp_delete_operation( Slapi_PBlock *pb )
 		/* The entry is already a Tombstone, ignore this delete. */
 		op_result= LDAP_SUCCESS;
 		slapi_pblock_set(pb, SLAPI_RESULT_CODE, &op_result);
-		rc = -1; /* Don't apply the Delete */
+		rc = SLAPI_PLUGIN_NOOP; /* Don't apply the Delete */
+		slapi_log_error(slapi_log_urp, sessionid,
+		                "urp_delete: Entry \"%s\" is already a Tombstone.\n",
+		                slapi_entry_get_dn_const(deleteentry));
 		PROFILE_POINT; /* Delete Operation; Already a Tombstone. */
 	}
 	else /* The entry to be deleted exists and is not a tombstone */
@@ -627,7 +646,7 @@ urp_delete_operation( Slapi_PBlock *pb )
 		{
 			/* Remove possible conflict attributes */
 			del_replconflict_attr (deleteentry, opcsn, 0);
-			rc= 0; /* OK, to delete the entry */
+			rc = SLAPI_PLUGIN_SUCCESS; /* OK, to delete the entry */
 			PROFILE_POINT; /* Delete Operation; OK. */
 		}
 		else
@@ -638,8 +657,11 @@ urp_delete_operation( Slapi_PBlock *pb )
 			/* Turn the Delete into a No-Op */
 			op_result= LDAP_SUCCESS;
 			slapi_pblock_set(pb, SLAPI_RESULT_CODE, &op_result);
-			rc = -1; /* Don't apply the Delete */
-		    PROFILE_POINT; /* Delete Operation; Entry has children. */
+			rc = SLAPI_PLUGIN_NOOP; /* Don't apply the Delete */
+			slapi_log_error(slapi_log_urp, sessionid,
+			 "urp_delete: Turn entry \"%s\" into a glue_absent_parent entry.\n",
+		     slapi_entry_get_dn_const(deleteentry));
+			PROFILE_POINT; /* Delete Operation; Entry has children. */
 		}
 	}
 	return rc;
@@ -785,7 +807,7 @@ urp_fixup_add_entry (Slapi_Entry *e, const char *target_uniqueid, const char *pa
 }
 
 int
-urp_fixup_rename_entry (Slapi_Entry *entry, const char *newrdn, int opflags)
+urp_fixup_rename_entry (const Slapi_Entry *entry, const char *newrdn, int opflags)
 {
 	Slapi_PBlock *newpb;
     Slapi_Operation *op;
@@ -996,7 +1018,7 @@ bailout:
  * a new entry (the operation entry) see urp_add_operation.
  */
 static int
-urp_annotate_dn (char *sessionid, Slapi_Entry *entry, CSN *opcsn, const char *optype)
+urp_annotate_dn (char *sessionid, const Slapi_Entry *entry, CSN *opcsn, const char *optype)
 {
 	int rc = 0; /* Fail */
 	int op_result;
@@ -1179,7 +1201,7 @@ urp_naming_conflict_removal ( Slapi_PBlock *pb, char *sessionid, CSN *opcsn, con
 
 	/* Step 1: Restore the entry's original DN */
 
-	oldrdn = slapi_rdn_new_sdn ( slapi_entry_get_sdn (min_naming_conflict_entry) );
+	oldrdn = slapi_rdn_new_sdn(slapi_entry_get_sdn_const(min_naming_conflict_entry));
 	oldrdnstr = slapi_rdn_get_rdn ( oldrdn );
 
 	/* newrdnstr is the old rdn of the entry minus the nsuniqueid part */
@@ -1192,7 +1214,7 @@ urp_naming_conflict_removal ( Slapi_PBlock *pb, char *sessionid, CSN *opcsn, con
 	 * is done after DB lock was released. The backend modrdn
 	 * will acquire the DB lock if it sees this flag.
 	 */
-	op_result = urp_fixup_rename_entry (min_naming_conflict_entry, newrdnstr, OP_FLAG_ACTION_INVOKE_FOR_REPLOP);
+	op_result = urp_fixup_rename_entry((const Slapi_Entry *)min_naming_conflict_entry, newrdnstr, OP_FLAG_ACTION_INVOKE_FOR_REPLOP);
 	if ( op_result != LDAP_SUCCESS )
 	{
 	    slapi_log_error (slapi_log_urp, sessionid,
@@ -1215,7 +1237,7 @@ urp_naming_conflict_removal ( Slapi_PBlock *pb, char *sessionid, CSN *opcsn, con
 	}
 
 bailout:
-	slapi_entry_free (min_naming_conflict_entry);
+	slapi_entry_free(min_naming_conflict_entry);
 	slapi_rdn_free(&oldrdn);
 	slapi_rdn_free(&newrdn);
 	return op_result;
@@ -1347,7 +1369,7 @@ mod_namingconflict_attr (const char *uniqueid, const Slapi_DN *entrysdn,
 }
 
 static int
-del_replconflict_attr (Slapi_Entry *entry, CSN *opcsn, int opflags)
+del_replconflict_attr (const Slapi_Entry *entry, CSN *opcsn, int opflags)
 {
 	Slapi_Attr *attr;
 	int op_result = 0;

+ 1 - 1
ldap/servers/plugins/replication/urp.h

@@ -59,7 +59,7 @@ int urp_post_modrdn_operation( Slapi_PBlock *pb );
 /* urp internal ops */
 int urp_fixup_add_entry (Slapi_Entry *e, const char *target_uniqueid, const char *parentuniqueid, CSN *opcsn, int opflags);
 int urp_fixup_delete_entry (const char *uniqueid, const char *dn, CSN *opcsn, int opflags);
-int urp_fixup_rename_entry (Slapi_Entry *entry, const char *newrdn, int opflags);
+int urp_fixup_rename_entry (const Slapi_Entry *entry, const char *newrdn, int opflags);
 int urp_fixup_modify_entry (const char *uniqueid, const Slapi_DN *sdn, CSN *opcsn, Slapi_Mods *smods, int opflags);
 
 int is_suffix_dn (Slapi_PBlock *pb, const Slapi_DN *dn, Slapi_DN **parenddn);

+ 20 - 4
ldap/servers/slapd/back-ldbm/ldbm_add.c

@@ -116,6 +116,7 @@ ldbm_back_add( Slapi_PBlock *pb )
 	int is_ruv = 0;				 /* True if the current entry is RUV */
 	CSN *opcsn = NULL;
 	entry_address addr = {0};
+	int not_an_error = 0;
 
 	slapi_pblock_get( pb, SLAPI_PLUGIN_PRIVATE, &li );
 	slapi_pblock_get( pb, SLAPI_ADD_ENTRY, &e );
@@ -266,9 +267,12 @@ ldbm_back_add( Slapi_PBlock *pb )
 		/* 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)
-		{
+		if (rc) {
 			int opreturn = 0;
+			if (SLAPI_PLUGIN_NOOP == rc) {
+				not_an_error = 1;
+				rc = LDAP_SUCCESS;
+			}
 			/* 
 			 * Plugin indicated some kind of failure,
 			 * or that this Operation became a No-Op.
@@ -776,8 +780,13 @@ ldbm_back_add( Slapi_PBlock *pb )
 
 		/* call the transaction pre add plugins just after the to-be-added entry
 		 * is prepared. */
-		if ((retval = plugin_call_plugins(pb, SLAPI_PLUGIN_BE_TXN_PRE_ADD_FN))) {
+		retval = plugin_call_plugins(pb, SLAPI_PLUGIN_BE_TXN_PRE_ADD_FN);
+		if (retval) {
 			int opreturn = 0;
+			if (SLAPI_PLUGIN_NOOP == retval) {
+				not_an_error = 1;
+				rc = retval = LDAP_SUCCESS;
+			}
 			LDAPDebug1Arg( LDAP_DEBUG_TRACE, "SLAPI_PLUGIN_BE_TXN_PRE_ADD_FN plugin "
 				       "returned error code %d\n", retval );
 			if (!ldap_result_code) {
@@ -1120,7 +1129,9 @@ diskfull_return:
 			/* txn is no longer valid - reset the txn pointer to the parent */
 			slapi_pblock_set(pb, SLAPI_TXN, parent_txn);
 		}
-		rc= SLAPI_FAIL_GENERAL;
+		if (!not_an_error) {
+			rc = SLAPI_FAIL_GENERAL;
+		}
 	}
 	
 common_return:
@@ -1166,6 +1177,11 @@ common_return:
 	done_with_pblock_entry(pb,SLAPI_ADD_PARENT_ENTRY);
 	if(ldap_result_code!=-1)
 	{
+		if (not_an_error) {
+			/* This is mainly used by urp.  Solved conflict is not an error.
+			 * And we don't want the supplier to halt sending the updates. */
+			ldap_result_code = LDAP_SUCCESS;
+		}
 		slapi_send_ldap_result( pb, ldap_result_code, ldap_result_matcheddn, ldap_result_message, 0, NULL );
 	}
 	backentry_free(&originalentry);

+ 14 - 3
ldap/servers/slapd/back-ldbm/ldbm_delete.c

@@ -97,6 +97,7 @@ ldbm_back_delete( Slapi_PBlock *pb )
 	Slapi_DN parentsdn;
 	int opreturn = 0;
 	int free_delete_existing_entry = 0;
+	int not_an_error = 0;
 
 	slapi_pblock_get( pb, SLAPI_BACKEND, &be);
 	slapi_pblock_get( pb, SLAPI_PLUGIN_PRIVATE, &li );
@@ -300,8 +301,11 @@ ldbm_back_delete( Slapi_PBlock *pb )
 				slapi_pblock_set(pb, SLAPI_RESULT_CODE, &ldap_result_code);
 		
 				rc = plugin_call_plugins(pb, SLAPI_PLUGIN_BE_PRE_DELETE_FN);
-				if (rc == -1)
+				if (rc)
 				{
+					if (SLAPI_PLUGIN_NOOP == rc) {
+						not_an_error = 1;
+					}
 					/* 
 					 * Plugin indicated some kind of failure,
 					 * or that this Operation became a No-Op.
@@ -569,6 +573,9 @@ ldbm_back_delete( Slapi_PBlock *pb )
 			   instead, have them modify a copy of the entry */
 			retval = plugin_call_plugins(pb, SLAPI_PLUGIN_BE_TXN_PRE_DELETE_FN);
 			if (retval) {
+				if (SLAPI_PLUGIN_NOOP == retval) {
+					not_an_error = 1;
+				}
 				LDAPDebug1Arg( LDAP_DEBUG_TRACE,
 				               "SLAPI_PLUGIN_BE_TXN_PRE_DELETE_FN plugin "
 				               "returned error code %d\n", retval );
@@ -1223,8 +1230,12 @@ common_return:
 	}
 
 diskfull_return:
-    if(ldap_result_code!=-1)
-	{
+	if(ldap_result_code!=-1) {
+		if (not_an_error) {
+			/* This is mainly used by urp.  Solved conflict is not an error.
+			 * And we don't want the supplier to halt sending the updates. */
+			ldap_result_code = LDAP_SUCCESS;
+		}
 		slapi_send_ldap_result( pb, ldap_result_code, NULL, ldap_result_message, 0, NULL );
 	}
 	modify_term(&parent_modify_c,be);

+ 22 - 4
ldap/servers/slapd/back-ldbm/ldbm_modify.c

@@ -340,6 +340,7 @@ ldbm_back_modify( Slapi_PBlock *pb )
 	int repl_op;
 	int opreturn = 0;
 	int mod_count = 0;
+	int not_an_error = 0;
 
 	slapi_pblock_get( pb, SLAPI_BACKEND, &be);
 	slapi_pblock_get( pb, SLAPI_PLUGIN_PRIVATE, &li );
@@ -511,7 +512,8 @@ ldbm_back_modify( Slapi_PBlock *pb )
 			slapi_pblock_set( pb, SLAPI_MODIFY_EXISTING_ENTRY, ec->ep_entry );
 			slapi_pblock_set(pb, SLAPI_RESULT_CODE, &ldap_result_code);
 		
-			if ((opreturn = plugin_call_plugins(pb, SLAPI_PLUGIN_BE_PRE_MODIFY_FN)) ||
+			opreturn = plugin_call_plugins(pb, SLAPI_PLUGIN_BE_PRE_MODIFY_FN);
+			if (opreturn ||
 				(slapi_pblock_get(pb, SLAPI_RESULT_CODE, &ldap_result_code) && ldap_result_code) ||
 				(slapi_pblock_get(pb, SLAPI_PLUGIN_OPRETURN, &opreturn) && opreturn)) {
 				slapi_pblock_get(pb, SLAPI_RESULT_CODE, &ldap_result_code);
@@ -521,7 +523,11 @@ ldbm_back_modify( Slapi_PBlock *pb )
 						       "returned error but did not set SLAPI_RESULT_CODE\n");
 					ldap_result_code = LDAP_OPERATIONS_ERROR;
 				}
-				if (!opreturn) {
+				if (SLAPI_PLUGIN_NOOP == opreturn) {
+					not_an_error = 1;
+					rc = opreturn = LDAP_SUCCESS;
+					goto error_return;
+				} else if (!opreturn) {
 					opreturn = -1;
 					slapi_pblock_set(pb, SLAPI_PLUGIN_OPRETURN, &opreturn);
 				}
@@ -563,11 +569,16 @@ ldbm_back_modify( Slapi_PBlock *pb )
 		} /* if (0 == retry_count) just once */
 
 		/* call the transaction pre modify plugins just after creating the transaction */
-		if ((retval = plugin_call_plugins(pb, SLAPI_PLUGIN_BE_TXN_PRE_MODIFY_FN))) {
+		retval = plugin_call_plugins(pb, SLAPI_PLUGIN_BE_TXN_PRE_MODIFY_FN);
+		if (retval) {
 			LDAPDebug1Arg( LDAP_DEBUG_TRACE, "SLAPI_PLUGIN_BE_TXN_PRE_MODIFY_FN plugin "
 						   "returned error code %d\n", retval );
 			slapi_pblock_get(pb, SLAPI_RESULT_CODE, &ldap_result_code);
 			slapi_pblock_get(pb, SLAPI_PLUGIN_OPRETURN, &opreturn);
+			if (SLAPI_PLUGIN_NOOP == retval) {
+				not_an_error = 1;
+				rc = retval = LDAP_SUCCESS;
+			}
 			if (!opreturn) {
 				slapi_pblock_set(pb, SLAPI_PLUGIN_OPRETURN, ldap_result_code ? &ldap_result_code : &retval);
 			}
@@ -796,7 +807,9 @@ error_return:
 			/* txn is no longer valid - reset the txn pointer to the parent */
 			slapi_pblock_set(pb, SLAPI_TXN, parent_txn);
 		}
-	    rc= SLAPI_FAIL_GENERAL;
+		if (!not_an_error) {
+			rc = SLAPI_FAIL_GENERAL;
+		}
 	}
 
 	/* if ec is in cache, remove it, then add back e if we still have it */
@@ -845,6 +858,11 @@ common_return:
 
 	if(ldap_result_code!=-1)
 	{
+		if (not_an_error) {
+			/* This is mainly used by urp.  Solved conflict is not an error.
+			 * And we don't want the supplier to halt sending the updates. */
+			ldap_result_code = LDAP_SUCCESS;
+		}
 		slapi_send_ldap_result( pb, ldap_result_code, NULL, ldap_result_message, 0, NULL );
 	}
 

+ 20 - 4
ldap/servers/slapd/back-ldbm/ldbm_modrdn.c

@@ -120,6 +120,7 @@ ldbm_back_modrdn( Slapi_PBlock *pb )
     char *newrdn = NULL;
     int opreturn = 0;
     int free_modrdn_existing_entry = 0;
+    int not_an_error = 0;
 
     /* sdn & parentsdn need to be initialized before "goto *_return" */
     slapi_sdn_init(&dn_newdn);
@@ -441,8 +442,11 @@ ldbm_back_modrdn( Slapi_PBlock *pb )
                 /* Call the Backend Pre ModRDN plugins */
                 slapi_pblock_set(pb, SLAPI_RESULT_CODE, &ldap_result_code);
                 rc= plugin_call_plugins(pb, SLAPI_PLUGIN_BE_PRE_MODRDN_FN);
-                if(rc==-1)
-                {
+                if (rc) {
+                    if (SLAPI_PLUGIN_NOOP == rc) {
+                        not_an_error = 1;
+                        rc = LDAP_SUCCESS;
+                    }
                     /* 
                      * Plugin indicated some kind of failure,
                      * or that this Operation became a No-Op.
@@ -869,9 +873,14 @@ ldbm_back_modrdn( Slapi_PBlock *pb )
         } /* if (0 == retry_count) just once */
 
         /* call the transaction pre modrdn plugins just after creating the transaction */
-        if ((retval = plugin_call_plugins(pb, SLAPI_PLUGIN_BE_TXN_PRE_MODRDN_FN))) {
+        retval = plugin_call_plugins(pb, SLAPI_PLUGIN_BE_TXN_PRE_MODRDN_FN);
+        if (retval) {
             LDAPDebug1Arg( LDAP_DEBUG_TRACE, "SLAPI_PLUGIN_BE_TXN_PRE_MODRDN_FN plugin "
                            "returned error code %d\n", retval );
+            if (SLAPI_PLUGIN_NOOP == retval) {
+                not_an_error = 1;
+                rc = retval = LDAP_SUCCESS;
+            }
             if (!ldap_result_code) {
                 slapi_pblock_get(pb, SLAPI_RESULT_CODE, &ldap_result_code);
             }
@@ -1267,7 +1276,9 @@ error_return:
             /* txn is no longer valid - reset the txn pointer to the parent */
             slapi_pblock_set(pb, SLAPI_TXN, parent_txn);
         }
-        retval= SLAPI_FAIL_GENERAL;
+        if (!not_an_error) {
+            retval = SLAPI_FAIL_GENERAL;
+        }
     }
 
 common_return:
@@ -1314,6 +1325,11 @@ common_return:
 
     if (ldap_result_code!=-1)
     {
+		if (not_an_error) {
+			/* This is mainly used by urp.  Solved conflict is not an error.
+			 * And we don't want the supplier to halt sending the updates. */
+			ldap_result_code = LDAP_SUCCESS;
+		}
         slapi_send_ldap_result( pb, ldap_result_code, ldap_result_matcheddn,
                     ldap_result_message, 0,NULL );
     }

+ 10 - 0
ldap/servers/slapd/slapi-plugin.h

@@ -6326,6 +6326,16 @@ time_t slapi_current_time( void );
 #define SLAPI_PLUGIN_EXTENDED_SENT_RESULT	-1
 #define SLAPI_PLUGIN_EXTENDED_NOT_HANDLED	-2
 
+/*
+ * Return values of plugins:
+ */
+#define SLAPI_PLUGIN_SUCCESS  0  /* 0 is treated as success implicitely */
+#define SLAPI_PLUGIN_FAILURE -1  /* common failure */
+#define SLAPI_PLUGIN_NOOP    -2  /* Special in be_pre_op/be_txn_pre_op.
+                                  * Treat as SUCCESS, but skip the backend op.
+                                  * Also, return SUCCESS to the client/supplier.
+                                  * Necessary for the replication conflicts. */
+
 /*
  * the following can be used as the second argument to the
  * slapi_pblock_get() and slapi_pblock_set() calls.