From 0d566a1779183a479c33447ac6b0224b705a33c9 Mon Sep 17 00:00:00 2001
From: gbellato <gbellato@localhost>
Date: Mon, 18 Jun 2007 06:50:18 +0000
Subject: [PATCH] Fix for 1797 : dead locks during replication testing
---
opends/src/server/org/opends/server/replication/plugin/PendingChanges.java | 373 +---------------------------------------------------
1 files changed, 10 insertions(+), 363 deletions(-)
diff --git a/opends/src/server/org/opends/server/replication/plugin/PendingChanges.java b/opends/src/server/org/opends/server/replication/plugin/PendingChanges.java
index 02f24c2..7d181f0 100644
--- a/opends/src/server/org/opends/server/replication/plugin/PendingChanges.java
+++ b/opends/src/server/org/opends/server/replication/plugin/PendingChanges.java
@@ -28,28 +28,23 @@
import java.util.NoSuchElementException;
import java.util.SortedMap;
-import java.util.SortedSet;
import java.util.TreeMap;
-import java.util.TreeSet;
-import org.opends.server.core.AddOperation;
-import org.opends.server.core.DeleteOperation;
-import org.opends.server.core.ModifyOperation;
import org.opends.server.replication.common.ChangeNumber;
import org.opends.server.replication.common.ChangeNumberGenerator;
import org.opends.server.replication.common.ServerState;
-import org.opends.server.replication.protocol.AddMsg;
-import org.opends.server.replication.protocol.DeleteMsg;
-import org.opends.server.replication.protocol.ModifyDNMsg;
-import org.opends.server.replication.protocol.OperationContext;
import org.opends.server.replication.protocol.UpdateMessage;
-import org.opends.server.types.DN;
import org.opends.server.types.Operation;
/**
- *
- * This class is use to store the list of operations currently
+ * This class is use to store the list of local operations currently
* in progress and not yet committed in the database.
+ *
+ * It is used to make sure that operations are sent to the Replication
+ * Server in the order defined by their ChangeNumber.
+ * It is also used to update the ServerState at the appropriate time.
+ *
+ * On object of this class is instanciated for each ReplicationDomain.
*/
public class PendingChanges
{
@@ -60,14 +55,6 @@
new TreeMap<ChangeNumber, PendingChange>();
/**
- * A sorted set containing the list of PendingChanges that have
- * not been replayed correctly because they are dependent on
- * another change to be completed.
- */
- private SortedSet<PendingChange> dependentChanges =
- new TreeSet<PendingChange>();
-
- /**
* The ChangeNumberGenerator to use to create new unique ChangeNumbers
* for each operation done on the replication domain.
*/
@@ -129,13 +116,10 @@
*
* @param changeNumber The ChangeNumber of the update message that must be
* set as committed.
- * @param op The Operation associated of the update when the
- * update is a local update.
- * @param msg The message associated to the update when the update
- * was received from a replication server.
+ * @param msg The message associated to the update.
*/
public synchronized void commit(ChangeNumber changeNumber,
- Operation op, UpdateMessage msg)
+ UpdateMessage msg)
{
PendingChange curChange = pendingChanges.get(changeNumber);
if (curChange == null)
@@ -144,10 +128,7 @@
}
curChange.setCommitted(true);
- if (op.isSynchronizationOperation())
- curChange.setOp(op);
- else
- curChange.setMsg(msg);
+ curChange.setMsg(msg);
}
/**
@@ -186,21 +167,6 @@
}
/**
- * Add a new UpdateMessage that was received from the replication server
- * to the pendingList.
- *
- * @param update The UpdateMessage that was received from the replication
- * server and that will be added to the pending list.
- */
- public synchronized void putRemoteUpdate(UpdateMessage update)
- {
- ChangeNumber changeNumber = update.getChangeNumber();
- changeNumberGenerator.adjust(changeNumber);
- pendingChanges.put(changeNumber, new PendingChange(changeNumber, null,
- update));
- }
-
- /**
* Push all committed local changes to the replicationServer service.
*
* @return The number of pushed updates.
@@ -237,323 +203,4 @@
}
return numSentUpdates;
}
-
- /**
- * Get the first update in the list that have some dependencies cleared.
- *
- * @return The UpdateMessage to be handled.
- */
- public synchronized UpdateMessage getNextUpdate()
- {
- /*
- * Parse the list of Update with dependencies and check if the dependencies
- * are now cleared until an Update withour dependencies is found.
- */
- for (PendingChange change : dependentChanges)
- {
- if (change.dependenciesIsCovered(state))
- {
- dependentChanges.remove(change);
- return change.getMsg();
- }
- }
- return null;
- }
-
-
- /**
- * Check if the given AddOperation has some dependencies on any
- * currently running previous operation.
- * Update the dependency list in the associated PendingChange if
- * there are some dependencies.
- * AddOperation depends on
- *
- * - DeleteOperation done on the same DN
- * - ModifyDnOperation with the same target DN as the ADD DN
- * - ModifyDnOperation with new DN equals to the ADD DN parent
- * - AddOperation done on the parent DN of the ADD DN
- *
- * @param op The AddOperation to be checked.
- *
- * @return A boolean indicating if this operation has some dependencies.
- */
- public synchronized boolean checkDependencies(AddOperation op)
- {
- boolean hasDependencies = false;
- DN targetDn = op.getEntryDN();
- ChangeNumber changeNumber = OperationContext.getChangeNumber(op);
- PendingChange change = pendingChanges.get(changeNumber);
- if (change == null)
- return false;
-
- for (PendingChange pendingChange : pendingChanges.values())
- {
- if (pendingChange.getChangeNumber().older(changeNumber))
- {
- UpdateMessage pendingMsg = pendingChange.getMsg();
- if (pendingMsg != null)
- {
- if (pendingMsg instanceof DeleteMsg)
- {
- /*
- * Check is the operation to be run is a deleteOperation on the
- * same DN.
- */
- if (pendingChange.getTargetDN().equals(targetDn))
- {
- hasDependencies = true;
- addDependency(change, pendingChange);
- }
- }
- else if (pendingMsg instanceof AddMsg)
- {
- /*
- * Check if the operation to be run is an addOperation on a
- * parent of the current AddOperation.
- */
- if (pendingChange.getTargetDN().isAncestorOf(targetDn))
- {
- hasDependencies = true;
- addDependency(change, pendingChange);
- }
- }
- else if (pendingMsg instanceof ModifyDNMsg)
- {
- /*
- * Check if the operation to be run is ModifyDnOperation with
- * the same target DN as the ADD DN
- * or a ModifyDnOperation with new DN equals to the ADD DN parent
- */
- if (pendingChange.getTargetDN().equals(targetDn))
- {
- hasDependencies = true;
- addDependency(change, pendingChange);
- }
- else
- {
- ModifyDNMsg pendingModDn = (ModifyDNMsg) pendingChange.getMsg();
- if (pendingModDn.newDNIsParent(targetDn))
- {
- hasDependencies = true;
- addDependency(change, pendingChange);
- }
- }
- }
- }
- }
- }
- return hasDependencies;
- }
-
- /**
- * Check if the given ModifyOperation has some dependencies on any
- * currently running previous operation.
- * Update the dependency list in the associated PendingChange if
- * there are some dependencies.
- *
- * ModifyOperation depends on
- * - AddOperation done on the same DN
- *
- * @param op The ModifyOperation to be checked.
- *
- * @return A boolean indicating if this operation has some dependencies.
- */
- public synchronized boolean checkDependencies(ModifyOperation op)
- {
- boolean hasDependencies = false;
- DN targetDn = op.getEntryDN();
- ChangeNumber changeNumber = OperationContext.getChangeNumber(op);
- PendingChange change = pendingChanges.get(changeNumber);
- if (change == null)
- return false;
-
- for (PendingChange pendingChange : pendingChanges.values())
- {
- if (pendingChange.getChangeNumber().older(changeNumber))
- {
- UpdateMessage pendingMsg = pendingChange.getMsg();
- if (pendingMsg != null)
- {
- if (pendingMsg instanceof AddMsg)
- {
- /*
- * Check if the operation to be run is an addOperation on a
- * same DN.
- */
- if (pendingChange.getTargetDN().equals(targetDn))
- {
- hasDependencies = true;
- addDependency(change, pendingChange);
- }
- }
- }
- }
- }
- return hasDependencies;
- }
-
- /**
- * Mark the first pendingChange as dependent on the second PendingChange.
- * @param dependentChange The PendingChange that depend on the second
- * PendingChange.
- * @param pendingChange The PendingChange on which the first PendingChange
- * is dependent.
- */
- private void addDependency(
- PendingChange dependentChange, PendingChange pendingChange)
- {
- dependentChange.addDependency(pendingChange.getChangeNumber());
- dependentChanges.add(dependentChange);
- }
-
- /**
- * Check if the given ModifyDNMsg has some dependencies on any
- * currently running previous operation.
- * Update the dependency list in the associated PendingChange if
- * there are some dependencies.
- *
- * Modify DN Operation depends on
- * - AddOperation done on the same DN as the target DN of the MODDN operation
- * - AddOperation done on the new parent of the MODDN operation
- * - DeleteOperation done on the new DN of the MODDN operation
- * - ModifyDNOperation done from the new DN of the MODDN operation
- *
- * @param msg The ModifyDNMsg to be checked.
- *
- * @return A boolean indicating if this operation has some dependencies.
- */
- public synchronized boolean checkDependencies(ModifyDNMsg msg)
- {
- boolean hasDependencies = false;
- ChangeNumber changeNumber = msg.getChangeNumber();
- PendingChange change = pendingChanges.get(changeNumber);
- if (change == null)
- return false;
-
- DN targetDn = change.getTargetDN();
-
-
- for (PendingChange pendingChange : pendingChanges.values())
- {
- if (pendingChange.getChangeNumber().older(changeNumber))
- {
- UpdateMessage pendingMsg = pendingChange.getMsg();
- if (pendingMsg != null)
- {
- if (pendingMsg instanceof DeleteMsg)
- {
- // Check if the target of the Delete is the same
- // as the new DN of this ModifyDN
- if (msg.newDNIsEqual(pendingChange.getTargetDN()))
- {
- hasDependencies = true;
- addDependency(change, pendingChange);
- }
- }
- else if (pendingMsg instanceof AddMsg)
- {
- // Check if the Add Operation was done on the new parent of
- // the MODDN operation
- if (msg.newParentIsEqual(pendingChange.getTargetDN()))
- {
- hasDependencies = true;
- addDependency(change, pendingChange);
- }
- // Check if the AddOperation was done on the same DN as the
- // target DN of the MODDN operation
- if (pendingChange.getTargetDN().equals(targetDn))
- {
- hasDependencies = true;
- addDependency(change, pendingChange);
- }
- }
- else if (pendingMsg instanceof ModifyDNMsg)
- {
- // Check if the ModifyDNOperation was done from the new DN of
- // the MODDN operation
- if (msg.newDNIsEqual(pendingChange.getTargetDN()))
- {
- hasDependencies = true;
- addDependency(change, pendingChange);
- }
- }
- }
- }
- }
- return hasDependencies;
- }
-
- /**
- * Check if the given DeleteOperation has some dependencies on any
- * currently running previous operation.
- * Update the dependency list in the associated PendingChange if
- * there are some dependencies.
- *
- * DeleteOperation depends on
- * - DeleteOperation done on children DN
- * - ModifyDnOperation with target DN that are children of the DEL DN
- * - AddOperation done on the same DN
- *
- *
- * @param op The DeleteOperation to be checked.
- *
- * @return A boolean indicating if this operation has some dependencies.
- */
- public synchronized boolean checkDependencies(DeleteOperation op)
- {
- boolean hasDependencies = false;
- DN targetDn = op.getEntryDN();
- ChangeNumber changeNumber = OperationContext.getChangeNumber(op);
- PendingChange change = pendingChanges.get(changeNumber);
- if (change == null)
- return false;
-
- for (PendingChange pendingChange : pendingChanges.values())
- {
- if (pendingChange.getChangeNumber().older(changeNumber))
- {
- UpdateMessage pendingMsg = pendingChange.getMsg();
- if (pendingMsg != null)
- {
- if (pendingMsg instanceof DeleteMsg)
- {
- /*
- * Check if the operation to be run is a deleteOperation on a
- * children of the current DeleteOperation.
- */
- if (pendingChange.getTargetDN().isDescendantOf(targetDn))
- {
- hasDependencies = true;
- addDependency(change, pendingChange);
- }
- }
- else if (pendingMsg instanceof AddMsg)
- {
- /*
- * Check if the operation to be run is an addOperation on a
- * parent of the current DeleteOperation.
- */
- if (pendingChange.getTargetDN().equals(targetDn))
- {
- hasDependencies = true;
- addDependency(change, pendingChange);
- }
- }
- else if (pendingMsg instanceof ModifyDNMsg)
- {
- /*
- * Check if the operation to be run is an ModifyDNOperation
- * on a children of the current DeleteOperation
- */
- if (pendingChange.getTargetDN().isDescendantOf(targetDn))
- {
- hasDependencies = true;
- addDependency(change, pendingChange);
- }
- }
- }
- }
- }
- return hasDependencies;
- }
}
--
Gitblit v1.10.0