Skip to main content
aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/internal/cdo/CDOStateMachine.java47
-rw-r--r--plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/internal/cdo/transaction/CDOSavepointImpl.java31
-rw-r--r--plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/internal/cdo/transaction/CDOTransactionImpl.java54
-rw-r--r--plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/internal/cdo/util/FSMUtil.java49
-rw-r--r--plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/internal/cdo/view/CDOViewImpl.java2
-rw-r--r--plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/spi/cdo/InternalCDOTransaction.java7
6 files changed, 112 insertions, 78 deletions
diff --git a/plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/internal/cdo/CDOStateMachine.java b/plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/internal/cdo/CDOStateMachine.java
index 4266d65bfb..2779fcc32d 100644
--- a/plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/internal/cdo/CDOStateMachine.java
+++ b/plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/internal/cdo/CDOStateMachine.java
@@ -28,7 +28,6 @@ import org.eclipse.emf.cdo.view.CDOView;
import org.eclipse.emf.internal.cdo.bundle.OM;
import org.eclipse.emf.internal.cdo.transaction.CDOSavepointImpl;
-import org.eclipse.emf.internal.cdo.transaction.CDOTransactionImpl;
import org.eclipse.emf.internal.cdo.util.FSMUtil;
import org.eclipse.net4j.util.collection.Pair;
@@ -213,7 +212,7 @@ public final class CDOStateMachine extends FiniteStateMachine<CDOState, CDOEvent
private void attachOrReattach(InternalCDOObject object, InternalCDOTransaction transaction)
{
// Bug 283985 (Re-attachment): Special case: re-attachment
- if (((CDOTransactionImpl)transaction).getFormerRevisions().containsKey(object))
+ if (transaction.getFormerRevisions().containsKey(object))
{
reattachObject(object, transaction);
}
@@ -631,42 +630,42 @@ public final class CDOStateMachine extends FiniteStateMachine<CDOState, CDOEvent
InternalCDOTransaction transaction = transactionAndContents.getElement1();
List<InternalCDOObject> contents = transactionAndContents.getElement2();
- Map<InternalCDOObject, InternalCDORevision> formerRevisionMap = ((CDOTransactionImpl)transaction)
- .getFormerRevisions();
+ Map<InternalCDOObject, InternalCDORevision> formerRevisionMap = transaction.getFormerRevisions();
boolean reattaching = formerRevisionMap.containsKey(object);
if (!reattaching)
{
- // Prepare object
- CDOID id = transaction.getNextTemporaryID();
- object.cdoInternalSetID(id);
- object.cdoInternalSetView(transaction);
- changeState(object, CDOState.PREPARED);
-
- // Create new revision
- EClass eClass = object.eClass();
- CDORevisionFactory factory = transaction.getSession().getRevisionManager().getFactory();
- InternalCDORevision revision = (InternalCDORevision)factory.createRevision(eClass);
- revision.setID(id);
- revision.setVersion(-1);
+ // Prepare object
+ CDOID id = transaction.getNextTemporaryID();
+ object.cdoInternalSetID(id);
+ object.cdoInternalSetView(transaction);
+ changeState(object, CDOState.PREPARED);
+
+ // Create new revision
+ EClass eClass = object.eClass();
+ CDORevisionFactory factory = transaction.getSession().getRevisionManager().getFactory();
+ InternalCDORevision revision = (InternalCDORevision)factory.createRevision(eClass);
+ revision.setID(id);
+ revision.setVersion(-1);
- object.cdoInternalSetRevision(revision);
+ object.cdoInternalSetRevision(revision);
- // Register object
- transaction.registerObject(object);
- transaction.registerNew(object);
+ // Register object
+ transaction.registerObject(object);
+ transaction.registerNew(object);
}
// Prepare content tree
- for (Iterator<InternalCDOObject> it = getProperContents(object,transaction); it.hasNext();)
+ for (Iterator<InternalCDOObject> it = getProperContents(object, transaction); it.hasNext();)
{
InternalCDOObject content = it.next();
contents.add(content);
INSTANCE.process(content, CDOEvent.PREPARE, transactionAndContents);
}
}
-
- private Iterator<InternalCDOObject> getProperContents(final InternalCDOObject object, final CDOTransaction transaction)
+
+ private Iterator<InternalCDOObject> getProperContents(final InternalCDOObject object,
+ final CDOTransaction transaction)
{
final boolean isResource = object instanceof Resource;
final Iterator<EObject> delegate = object.eContents().iterator();
@@ -746,7 +745,7 @@ public final class CDOStateMachine extends FiniteStateMachine<CDOState, CDOEvent
public void execute(InternalCDOObject object, CDOState state, CDOEvent event, InternalCDOTransaction transaction)
{
InternalCDORevisionManager revisionManager = transaction.getSession().getRevisionManager();
- InternalCDORevision formerRevision = ((CDOTransactionImpl)transaction).getFormerRevisions().get(object);
+ InternalCDORevision formerRevision = transaction.getFormerRevisions().get(object);
CDOID id = formerRevision.getID();
object.cdoInternalSetID(id);
diff --git a/plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/internal/cdo/transaction/CDOSavepointImpl.java b/plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/internal/cdo/transaction/CDOSavepointImpl.java
index 3460edf310..e6535985e6 100644
--- a/plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/internal/cdo/transaction/CDOSavepointImpl.java
+++ b/plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/internal/cdo/transaction/CDOSavepointImpl.java
@@ -66,6 +66,8 @@ public class CDOSavepointImpl extends AbstractSavepoint
}
};
+ private Map<CDOID, CDOObject> reattachedObjects = new HashMap<CDOID, CDOObject>();
+
private ConcurrentMap<CDOID, CDORevisionDelta> revisionDeltas = new ConcurrentHashMap<CDOID, CDORevisionDelta>();
/**
@@ -80,7 +82,7 @@ public class CDOSavepointImpl extends AbstractSavepoint
{
super(transaction, lastSavepoint);
isDirty = transaction.isDirty();
- if (getPreviousSavepoint() == null)
+ if (lastSavepoint == null)
{
sharedDetachedObjects = new HashSet<CDOID>();
}
@@ -295,17 +297,34 @@ public class CDOSavepointImpl extends AbstractSavepoint
{
if (getPreviousSavepoint() == null)
{
- return Collections.unmodifiableMap(getDetachedObjects());
+ Map<CDOID, CDOObject> detachedObjects = getDetachedObjects();
+
+ // Bug 283985 (Re-attachment):
+ // Object is only included if it was not reattached in a later savepoint
+ for (CDOID id : getReattachedObjects().keySet())
+ {
+ detachedObjects.remove(id);
+ }
+
+ return Collections.unmodifiableMap(detachedObjects);
}
Map<CDOID, CDOObject> detachedObjects = new HashMap<CDOID, CDOObject>();
+ Set<CDOID> reattachedObjectIDs = new HashSet<CDOID>(); // Bug 283985 (Re-attachment)
for (CDOSavepointImpl savepoint = this; savepoint != null; savepoint = savepoint.getPreviousSavepoint())
{
+ reattachedObjectIDs.addAll(savepoint.getReattachedObjects().keySet());
+
for (Entry<CDOID, CDOObject> entry : savepoint.getDetachedObjects().entrySet())
{
if (!entry.getKey().isTemporary())
{
- detachedObjects.put(entry.getKey(), entry.getValue());
+ // Bug 283985 (Re-attachment):
+ // Object is only included if it was not reattached in a later savepoint
+ if (!reattachedObjectIDs.contains(entry.getKey()))
+ {
+ detachedObjects.put(entry.getKey(), entry.getValue());
+ }
}
}
}
@@ -313,6 +332,12 @@ public class CDOSavepointImpl extends AbstractSavepoint
return detachedObjects;
}
+ // Bug 283985 (Re-attachment)
+ public Map<CDOID, CDOObject> getReattachedObjects()
+ {
+ return reattachedObjects;
+ }
+
public void recalculateSharedDetachedObjects()
{
sharedDetachedObjects.clear();
diff --git a/plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/internal/cdo/transaction/CDOTransactionImpl.java b/plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/internal/cdo/transaction/CDOTransactionImpl.java
index ecdf2c7616..81d5ca2a3b 100644
--- a/plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/internal/cdo/transaction/CDOTransactionImpl.java
+++ b/plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/internal/cdo/transaction/CDOTransactionImpl.java
@@ -34,6 +34,7 @@ import org.eclipse.emf.cdo.eresource.EresourceFactory;
import org.eclipse.emf.cdo.eresource.impl.CDOResourceImpl;
import org.eclipse.emf.cdo.eresource.impl.CDOResourceNodeImpl;
import org.eclipse.emf.cdo.spi.common.model.InternalCDOPackageUnit;
+import org.eclipse.emf.cdo.spi.common.revision.InternalCDORevision;
import org.eclipse.emf.cdo.spi.common.revision.InternalCDORevisionDelta;
import org.eclipse.emf.cdo.transaction.CDOConflictResolver;
import org.eclipse.emf.cdo.transaction.CDOSavepoint;
@@ -83,6 +84,7 @@ import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
+import java.util.WeakHashMap;
import java.util.Map.Entry;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.locks.ReentrantLock;
@@ -117,6 +119,9 @@ public class CDOTransactionImpl extends CDOViewImpl implements InternalCDOTransa
private CDOTransactionStrategy transactionStrategy;
+ // Bug 283985 (Re-attachment)
+ private WeakHashMap<InternalCDOObject, InternalCDORevision> formerRevisions = new WeakHashMap<InternalCDOObject, InternalCDORevision>();
+
/**
* @since 2.0
*/
@@ -733,6 +738,10 @@ public class CDOTransactionImpl extends CDOViewImpl implements InternalCDOTransa
removeObjects(itrSavepoint.getNewResources().values());
removeObjects(itrSavepoint.getNewObjects().values());
+ // Bug 283985 (Re-attachment): Objects that were reattached must also be removed
+ Collection<CDOObject> reattachedObjects = itrSavepoint.getReattachedObjects().values();
+ removeObjects(reattachedObjects);
+
Map<CDOID, CDORevisionDelta> revisionDeltas = itrSavepoint.getRevisionDeltas();
if (!revisionDeltas.isEmpty())
{
@@ -769,7 +778,13 @@ public class CDOTransactionImpl extends CDOViewImpl implements InternalCDOTransa
if (!entryDirtyObject.getKey().isTemporary())
{
InternalCDOObject internalDirtyObject = (InternalCDOObject)entryDirtyObject.getValue();
- CDOStateMachine.INSTANCE.rollback(internalDirtyObject);
+
+ // Bug 283985 (Re-attachment): Skip objects that were reattached, because
+ // they were already reset to TRANSIENT earlier in this method
+ if (!reattachedObjects.contains(internalDirtyObject))
+ {
+ CDOStateMachine.INSTANCE.rollback(internalDirtyObject);
+ }
}
}
@@ -907,6 +922,15 @@ public class CDOTransactionImpl extends CDOViewImpl implements InternalCDOTransa
else
{
getLastSavepoint().getDetachedObjects().put(object.cdoID(), object);
+
+ if (!formerRevisions.containsKey(object))
+ {
+ formerRevisions.put(object, object.cdoRevision());
+ }
+
+ // Object may have been reattached previously, in which case it must
+ // here be removed from the collection of reattached objects
+ lastSavepoint.getReattachedObjects().remove(object.cdoID());
}
if (!dirty)
@@ -1305,6 +1329,34 @@ public class CDOTransactionImpl extends CDOViewImpl implements InternalCDOTransa
return lastSavepoint.getAllDetachedObjects();
}
+ public Map<InternalCDOObject, InternalCDORevision> getFormerRevisions()
+ {
+ return formerRevisions;
+ }
+
+ @Override
+ protected CDOID getID(InternalCDOObject object, boolean onlyPersistedID)
+ {
+ // Bug 283985 (Re-attachment): We consult the formerRevision map before delegating
+ // to the super implementation. Note that we *abuse* the onlyPersistedID
+ // argument to determine if we should disregard the formerRevision map. We need
+ // to disregard it when this gets called during commit, and it just so happens
+ // that only during commit it is being called with onlyPersistedID = false. So
+ // this code exploits a regularity in the calling code, rather than interpreting
+ // the onlyPersistedID argument in accordance with its intended meaning. Indeed
+ // this is a very fragile hack...
+ if (onlyPersistedID)
+ {
+ CDORevision formerRevision = formerRevisions.get(object);
+ if (formerRevision != null)
+ {
+ return formerRevision.getID();
+ }
+ }
+
+ return super.getID(object, onlyPersistedID);
+ }
+
/**
* @since 2.0
*/
diff --git a/plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/internal/cdo/util/FSMUtil.java b/plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/internal/cdo/util/FSMUtil.java
index a9c7b449fd..103fa4b4af 100644
--- a/plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/internal/cdo/util/FSMUtil.java
+++ b/plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/internal/cdo/util/FSMUtil.java
@@ -14,7 +14,6 @@ package org.eclipse.emf.internal.cdo.util;
import org.eclipse.emf.cdo.CDOObject;
import org.eclipse.emf.cdo.CDOState;
import org.eclipse.emf.cdo.common.id.CDOID;
-import org.eclipse.emf.cdo.common.model.EMFUtil;
import org.eclipse.emf.cdo.common.revision.CDORevision;
import org.eclipse.emf.cdo.spi.common.model.InternalCDOPackageRegistry;
import org.eclipse.emf.cdo.util.InvalidObjectException;
@@ -34,11 +33,9 @@ import org.eclipse.emf.ecore.EGenericType;
import org.eclipse.emf.ecore.EModelElement;
import org.eclipse.emf.ecore.EObject;
import org.eclipse.emf.ecore.EPackage;
-import org.eclipse.emf.ecore.EStructuralFeature;
import org.eclipse.emf.ecore.EcorePackage;
import org.eclipse.emf.ecore.InternalEObject;
import org.eclipse.emf.ecore.impl.DynamicEObjectImpl;
-import org.eclipse.emf.ecore.resource.Resource;
import org.eclipse.emf.ecore.util.EcoreUtil;
import org.eclipse.emf.spi.cdo.InternalCDOObject;
import org.eclipse.emf.spi.cdo.InternalCDOView;
@@ -253,52 +250,6 @@ public final class FSMUtil
}
}
- /**
- * Similar to {@link EcoreUtil#getAllProperContents(Resource, boolean)} except gives only one depth
- */
- public static Iterator<InternalCDOObject> getProperContents(final InternalCDOObject object)
- {
- final boolean isResource = object instanceof Resource;
- final CDOView cdoView = object.cdoView();
- final Iterator<EObject> delegate = object.eContents().iterator();
-
- return new Iterator<InternalCDOObject>()
- {
- private Object next;
-
- public boolean hasNext()
- {
- while (delegate.hasNext())
- {
- InternalEObject eObject = (InternalEObject)delegate.next();
-
- EStructuralFeature eContainingFeature = eObject.eContainingFeature();
- if (isResource || eObject.eDirectResource() == null
- && (eContainingFeature == null || EMFUtil.isPersistent(eContainingFeature)))
- {
- next = adapt(eObject, cdoView);
- if (next instanceof InternalCDOObject)
- {
- return true;
- }
- }
- }
-
- return false;
- }
-
- public InternalCDOObject next()
- {
- return (InternalCDOObject)next;
- }
-
- public void remove()
- {
- throw new UnsupportedOperationException();
- }
- };
- }
-
public static Iterator<InternalCDOObject> iterator(final Iterator<?> delegate, final InternalCDOView view)
{
return new Iterator<InternalCDOObject>()
diff --git a/plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/internal/cdo/view/CDOViewImpl.java b/plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/internal/cdo/view/CDOViewImpl.java
index 07f9f86845..b7293c1b4b 100644
--- a/plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/internal/cdo/view/CDOViewImpl.java
+++ b/plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/internal/cdo/view/CDOViewImpl.java
@@ -1032,7 +1032,7 @@ public class CDOViewImpl extends Lifecycle implements InternalCDOView
// throw new IllegalStateException("Dangling objects not possible outside of a transaction");
// }
- private CDOID getID(InternalCDOObject object, boolean onlyPersistedID)
+ protected CDOID getID(InternalCDOObject object, boolean onlyPersistedID)
{
if (onlyPersistedID)
{
diff --git a/plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/spi/cdo/InternalCDOTransaction.java b/plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/spi/cdo/InternalCDOTransaction.java
index a1b38ac82e..9a3af12727 100644
--- a/plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/spi/cdo/InternalCDOTransaction.java
+++ b/plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/spi/cdo/InternalCDOTransaction.java
@@ -16,6 +16,7 @@ import org.eclipse.emf.cdo.common.id.CDOIDTemp;
import org.eclipse.emf.cdo.common.revision.delta.CDOFeatureDelta;
import org.eclipse.emf.cdo.common.revision.delta.CDORevisionDelta;
import org.eclipse.emf.cdo.eresource.CDOResourceFolder;
+import org.eclipse.emf.cdo.spi.common.revision.InternalCDORevision;
import org.eclipse.emf.cdo.transaction.CDOCommitContext;
import org.eclipse.emf.cdo.transaction.CDOSavepoint;
import org.eclipse.emf.cdo.transaction.CDOTransaction;
@@ -23,6 +24,7 @@ import org.eclipse.emf.cdo.transaction.CDOTransaction;
import org.eclipse.emf.spi.cdo.CDOSessionProtocol.CommitTransactionResult;
import java.util.List;
+import java.util.Map;
import java.util.Set;
/**
@@ -63,6 +65,11 @@ public interface InternalCDOTransaction extends CDOTransaction, InternalCDOView
public void handleConflicts(Set<CDOObject> conflicts);
/**
+ * @since 3.0
+ */
+ public Map<InternalCDOObject, InternalCDORevision> getFormerRevisions();
+
+ /**
* Provides a context for a commit operation.
*
* @author Simon McDuff

Back to the top