*
* @param msg The UpdateMsg to be replayed.
*/
public void replay(LDAPUpdateMsg msg)
{
Operation op = null;
boolean done = false;
boolean dependency = false;
ChangeNumber changeNumber = null;
int retryCount = 10;
// Try replay the operation, then flush (replaying) any pending operation
// whose dependency has been replayed until no more left.
do
{
String replayErrorMsg = null;
try
{
op = msg.createOperation(conn);
dependency = remotePendingChanges.checkDependencies(op, msg);
while ((!dependency) && (!done) && (retryCount-- > 0))
{
// Try replay the operation
op.setInternalOperation(true);
op.setSynchronizationOperation(true);
changeNumber = OperationContext.getChangeNumber(op);
((AbstractOperation) op).run();
ResultCode result = op.getResultCode();
if (result != ResultCode.SUCCESS)
{
if (op instanceof ModifyOperation)
{
ModifyOperation newOp = (ModifyOperation) op;
dependency = remotePendingChanges.checkDependencies(newOp);
ModifyMsg modifyMsg = (ModifyMsg) msg;
done = solveNamingConflict(newOp, modifyMsg);
} else if (op instanceof DeleteOperation)
{
DeleteOperation newOp = (DeleteOperation) op;
dependency = remotePendingChanges.checkDependencies(newOp);
done = solveNamingConflict(newOp, msg);
} else if (op instanceof AddOperation)
{
AddOperation newOp = (AddOperation) op;
AddMsg addMsg = (AddMsg) msg;
dependency = remotePendingChanges.checkDependencies(newOp);
done = solveNamingConflict(newOp, addMsg);
} else if (op instanceof ModifyDNOperationBasis)
{
ModifyDNOperationBasis newOp = (ModifyDNOperationBasis) op;
done = solveNamingConflict(newOp, msg);
} else
{
done = true; // unknown type of operation ?!
}
if (done)
{
// the update became a dummy update and the result
// of the conflict resolution phase is to do nothing.
// however we still need to push this change to the serverState
updateError(changeNumber);
}
else
{
/*
* Create a new operation as the ConflictResolution
* different operation.
* Note: When msg is a DeleteMsg, the DeleteOperation is properly
* created with subtreeDelete request control when needed.
*/
op = msg.createOperation(conn);
}
}
else
{
done = true;
}
}
if (!done && !dependency)
{
// Continue with the next change but the servers could now become
// inconsistent.
// Let the repair tool know about this.
Message message = ERR_LOOP_REPLAYING_OPERATION.get(op.toString(),
op.getErrorMessage().toString());
logError(message);
numUnresolvedNamingConflicts.incrementAndGet();
replayErrorMsg = message.toString();
updateError(changeNumber);
}
} catch (ASN1Exception e)
{
Message message = ERR_EXCEPTION_DECODING_OPERATION.get(
String.valueOf(msg) + stackTraceToSingleLineString(e));
logError(message);
replayErrorMsg = message.toString();
} catch (LDAPException e)
{
Message message = ERR_EXCEPTION_DECODING_OPERATION.get(
String.valueOf(msg) + stackTraceToSingleLineString(e));
logError(message);
replayErrorMsg = message.toString();
} catch (DataFormatException e)
{
Message message = ERR_EXCEPTION_DECODING_OPERATION.get(
String.valueOf(msg) + stackTraceToSingleLineString(e));
logError(message);
replayErrorMsg = message.toString();
} catch (Exception e)
{
if (changeNumber != null)
{
/*
* An Exception happened during the replay process.
* Continue with the next change but the servers will now start
* to be inconsistent.
* Let the repair tool know about this.
*/
Message message = ERR_EXCEPTION_REPLAYING_OPERATION.get(
stackTraceToSingleLineString(e), op.toString());
logError(message);
replayErrorMsg = message.toString();
updateError(changeNumber);
} else
{