*/
private boolean solveNamingConflict(ModifyDNOperation op,
LDAPUpdateMsg msg) throws Exception
{
ResultCode result = op.getResultCode();
ModifyDnContext ctx = (ModifyDnContext) op.getAttachment(SYNCHROCONTEXT);
String entryUid = ctx.getEntryUid();
String newSuperiorID = ctx.getNewParentId();
/*
* four possible cases :
* - the modified entry has been renamed
* - the new parent has been renamed
* - the operation is replayed for the second time.
* - the entry has been deleted
* action :
* - change the target dn and the new parent dn and
* restart the operation,
* - don't do anything if the operation is replayed.
*/
// get the current DN of this entry in the database.
DN currentDN = findEntryDN(entryUid);
// Construct the new DN to use for the entry.
DN entryDN = op.getEntryDN();
DN newSuperior = null;
RDN newRDN = op.getNewRDN();
if (newSuperiorID != null)
{
newSuperior = findEntryDN(newSuperiorID);
}
else
{
newSuperior = entryDN.getParent();
}
//If we could not find the new parent entry, we missed this entry
// earlier or it has disappeared from the database
// Log this information for the repair tool and mark the entry
// as conflicting.
// stop the processing.
if (newSuperior == null)
{
markConflictEntry(op, currentDN, currentDN.getParent().concat(newRDN));
numUnresolvedNamingConflicts.incrementAndGet();
return true;
}
DN newDN = newSuperior.concat(newRDN);
if (currentDN == null)
{
// The entry targeted by the Modify DN is not in the database
// anymore.
// This is a conflict between a delete and this modify DN.
// The entry has been deleted, we can safely assume
// that the operation is completed.
numResolvedNamingConflicts.incrementAndGet();
return true;
}
// if the newDN and the current DN match then the operation
// is a no-op (this was probably a second replay)
// don't do anything.
if (newDN.equals(currentDN))
{
numResolvedNamingConflicts.incrementAndGet();
return true;
}
if ((result == ResultCode.NO_SUCH_OBJECT) ||
(result == ResultCode.UNWILLING_TO_PERFORM) ||
(result == ResultCode.OBJECTCLASS_VIOLATION))
{
/*
* The entry or it's new parent has not been found
* reconstruct the operation with the DN we just built
*/
ModifyDNMsg modifyDnMsg = (ModifyDNMsg) msg;
msg.setDn(currentDN.toString());
modifyDnMsg.setNewSuperior(newSuperior.toString());
numResolvedNamingConflicts.incrementAndGet();
return false;
}
else if (result == ResultCode.ENTRY_ALREADY_EXISTS)
{
/*
* This may happen when two modifyDn operation
* are done on different servers but with the same target DN
* add the conflict object class to the entry
* and rename it using its entryuuid.
*/
ModifyDNMsg modifyDnMsg = (ModifyDNMsg) msg;
markConflictEntry(op, op.getEntryDN(), newDN);
modifyDnMsg.setNewRDN(generateConflictRDN(entryUid,
modifyDnMsg.getNewRDN()));
modifyDnMsg.setNewSuperior(newSuperior.toString());
numUnresolvedNamingConflicts.incrementAndGet();
return false;
}
else
{
// The other type of errors can not be caused by naming conflicts.
// Log a message for the repair tool.
Message message = ERR_ERROR_REPLAYING_OPERATION.get(
op.toString(), ctx.getChangeNumber().toString(),
result.toString(), op.getErrorMessage().toString());
logError(message);
return true;
}
}