diff options
author | Eike Stepper | 2009-11-07 09:37:20 +0000 |
---|---|---|
committer | Eike Stepper | 2009-11-07 09:37:20 +0000 |
commit | b9d57f215e8203f11d09991a20bcbcdfa7127ad4 (patch) | |
tree | ecabc5c258a238ce8fcda21b36937d5c937b2f64 /plugins/org.eclipse.emf.cdo/src/org/eclipse/emf | |
parent | c1ccd51148da5a6e14d5e65002e0737dc6ce7592 (diff) | |
download | cdo-b9d57f215e8203f11d09991a20bcbcdfa7127ad4.tar.gz cdo-b9d57f215e8203f11d09991a20bcbcdfa7127ad4.tar.xz cdo-b9d57f215e8203f11d09991a20bcbcdfa7127ad4.zip |
[294528] Preserve CDOID for re-attached CDOObjects
https://bugs.eclipse.org/bugs/show_bug.cgi?id=294528
Diffstat (limited to 'plugins/org.eclipse.emf.cdo/src/org/eclipse/emf')
-rw-r--r-- | plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/internal/cdo/CDOStateMachine.java | 158 |
1 files changed, 154 insertions, 4 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 ca9147b8ee..4266d65bfb 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 @@ -14,9 +14,12 @@ package org.eclipse.emf.internal.cdo; import org.eclipse.emf.cdo.CDOState; import org.eclipse.emf.cdo.common.id.CDOID; import org.eclipse.emf.cdo.common.id.CDOIDTemp; +import org.eclipse.emf.cdo.common.model.EMFUtil; import org.eclipse.emf.cdo.common.revision.CDORevision; import org.eclipse.emf.cdo.common.revision.CDORevisionFactory; import org.eclipse.emf.cdo.common.revision.delta.CDOFeatureDelta; +import org.eclipse.emf.cdo.common.revision.delta.CDORevisionDelta; +import org.eclipse.emf.cdo.common.revision.delta.CDORevisionDeltaUtil; import org.eclipse.emf.cdo.spi.common.revision.InternalCDORevision; import org.eclipse.emf.cdo.spi.common.revision.InternalCDORevisionManager; import org.eclipse.emf.cdo.transaction.CDOTransaction; @@ -24,6 +27,8 @@ import org.eclipse.emf.cdo.util.InvalidObjectException; 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; @@ -33,6 +38,7 @@ import org.eclipse.net4j.util.om.trace.ContextTracer; import org.eclipse.emf.ecore.EClass; import org.eclipse.emf.ecore.EObject; +import org.eclipse.emf.ecore.EStructuralFeature; import org.eclipse.emf.ecore.InternalEObject; import org.eclipse.emf.ecore.impl.EStoreEObjectImpl; import org.eclipse.emf.ecore.resource.Resource; @@ -78,6 +84,7 @@ public final class CDOStateMachine extends FiniteStateMachine<CDOState, CDOEvent init(CDOState.TRANSIENT, CDOEvent.RELOAD, IGNORE); init(CDOState.TRANSIENT, CDOEvent.COMMIT, FAIL); init(CDOState.TRANSIENT, CDOEvent.ROLLBACK, FAIL); + init(CDOState.TRANSIENT, CDOEvent.REATTACH, new ReattachTransition()); init(CDOState.PREPARED, CDOEvent.PREPARE, FAIL); init(CDOState.PREPARED, CDOEvent.ATTACH, new AttachTransition()); @@ -89,6 +96,7 @@ public final class CDOStateMachine extends FiniteStateMachine<CDOState, CDOEvent init(CDOState.PREPARED, CDOEvent.RELOAD, FAIL); init(CDOState.PREPARED, CDOEvent.COMMIT, FAIL); init(CDOState.PREPARED, CDOEvent.ROLLBACK, FAIL); + init(CDOState.PREPARED, CDOEvent.REATTACH, FAIL); init(CDOState.NEW, CDOEvent.PREPARE, FAIL); init(CDOState.NEW, CDOEvent.ATTACH, FAIL); @@ -100,6 +108,7 @@ public final class CDOStateMachine extends FiniteStateMachine<CDOState, CDOEvent init(CDOState.NEW, CDOEvent.RELOAD, FAIL); init(CDOState.NEW, CDOEvent.COMMIT, new CommitTransition(false)); init(CDOState.NEW, CDOEvent.ROLLBACK, FAIL); + init(CDOState.NEW, CDOEvent.REATTACH, FAIL); init(CDOState.CLEAN, CDOEvent.PREPARE, FAIL); init(CDOState.CLEAN, CDOEvent.ATTACH, FAIL); @@ -111,6 +120,7 @@ public final class CDOStateMachine extends FiniteStateMachine<CDOState, CDOEvent init(CDOState.CLEAN, CDOEvent.RELOAD, new ReloadTransition()); init(CDOState.CLEAN, CDOEvent.COMMIT, FAIL); init(CDOState.CLEAN, CDOEvent.ROLLBACK, FAIL); + init(CDOState.CLEAN, CDOEvent.REATTACH, FAIL); init(CDOState.DIRTY, CDOEvent.PREPARE, FAIL); init(CDOState.DIRTY, CDOEvent.ATTACH, FAIL); @@ -122,6 +132,7 @@ public final class CDOStateMachine extends FiniteStateMachine<CDOState, CDOEvent init(CDOState.DIRTY, CDOEvent.RELOAD, new ReloadTransition()); init(CDOState.DIRTY, CDOEvent.COMMIT, new CommitTransition(true)); init(CDOState.DIRTY, CDOEvent.ROLLBACK, new RollbackTransition()); + init(CDOState.DIRTY, CDOEvent.REATTACH, FAIL); init(CDOState.PROXY, CDOEvent.PREPARE, FAIL); init(CDOState.PROXY, CDOEvent.ATTACH, FAIL); @@ -133,6 +144,7 @@ public final class CDOStateMachine extends FiniteStateMachine<CDOState, CDOEvent init(CDOState.PROXY, CDOEvent.RELOAD, new ReloadTransition()); init(CDOState.PROXY, CDOEvent.COMMIT, FAIL); init(CDOState.PROXY, CDOEvent.ROLLBACK, FAIL); + init(CDOState.PROXY, CDOEvent.REATTACH, FAIL); // Bug 283985 (Re-attachment) - Not sure about this one init(CDOState.CONFLICT, CDOEvent.PREPARE, FAIL); init(CDOState.CONFLICT, CDOEvent.ATTACH, IGNORE); @@ -144,6 +156,7 @@ public final class CDOStateMachine extends FiniteStateMachine<CDOState, CDOEvent init(CDOState.CONFLICT, CDOEvent.RELOAD, FAIL); init(CDOState.CONFLICT, CDOEvent.COMMIT, IGNORE); init(CDOState.CONFLICT, CDOEvent.ROLLBACK, new RollbackTransition()); + init(CDOState.CONFLICT, CDOEvent.REATTACH, FAIL); // Bug 283985 (Re-attachment) Not sure about this one init(CDOState.INVALID, CDOEvent.PREPARE, InvalidTransition.INSTANCE); init(CDOState.INVALID, CDOEvent.ATTACH, InvalidTransition.INSTANCE); @@ -155,6 +168,7 @@ public final class CDOStateMachine extends FiniteStateMachine<CDOState, CDOEvent init(CDOState.INVALID, CDOEvent.RELOAD, InvalidTransition.INSTANCE); init(CDOState.INVALID, CDOEvent.COMMIT, InvalidTransition.INSTANCE); init(CDOState.INVALID, CDOEvent.ROLLBACK, InvalidTransition.INSTANCE); + init(CDOState.INVALID, CDOEvent.REATTACH, FAIL); // Bug 283985 (Re-attachment) Not sure about this one init(CDOState.INVALID_CONFLICT, CDOEvent.PREPARE, InvalidTransition.INSTANCE); init(CDOState.INVALID_CONFLICT, CDOEvent.ATTACH, InvalidTransition.INSTANCE); @@ -166,6 +180,7 @@ public final class CDOStateMachine extends FiniteStateMachine<CDOState, CDOEvent init(CDOState.INVALID_CONFLICT, CDOEvent.RELOAD, InvalidTransition.INSTANCE); init(CDOState.INVALID_CONFLICT, CDOEvent.COMMIT, InvalidTransition.INSTANCE); init(CDOState.INVALID_CONFLICT, CDOEvent.ROLLBACK, DetachRemoteTransition.INSTANCE); + init(CDOState.INVALID_CONFLICT, CDOEvent.REATTACH, FAIL); // Bug 283985 (Re-attachment) Not sure about this one } /** @@ -182,11 +197,11 @@ public final class CDOStateMachine extends FiniteStateMachine<CDOState, CDOEvent { List<InternalCDOObject> contents = new ArrayList<InternalCDOObject>(); prepare(object, new Pair<InternalCDOTransaction, List<InternalCDOObject>>(transaction, contents)); - attachObject(object); + attachOrReattach(object, transaction); for (InternalCDOObject content : contents) { - attachObject(content); + attachOrReattach(content, transaction); } } finally @@ -195,6 +210,19 @@ 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)) + { + reattachObject(object, transaction); + } + else + { + attachObject(object); + } + } + /** * Phase 1: TRANSIENT --> PREPARED */ @@ -222,6 +250,16 @@ public final class CDOStateMachine extends FiniteStateMachine<CDOState, CDOEvent process(object, CDOEvent.ATTACH, null); } + private void reattachObject(InternalCDOObject object, InternalCDOTransaction transaction) + { + if (TRACER.isEnabled()) + { + TRACER.format("REATTACH: {0}", object); + } + + process(object, CDOEvent.REATTACH, transaction); + } + /** * @since 2.0 */ @@ -593,6 +631,12 @@ public final class CDOStateMachine extends FiniteStateMachine<CDOState, CDOEvent InternalCDOTransaction transaction = transactionAndContents.getElement1(); List<InternalCDOObject> contents = transactionAndContents.getElement2(); + Map<InternalCDOObject, InternalCDORevision> formerRevisionMap = ((CDOTransactionImpl)transaction) + .getFormerRevisions(); + boolean reattaching = formerRevisionMap.containsKey(object); + + if (!reattaching) + { // Prepare object CDOID id = transaction.getNextTemporaryID(); object.cdoInternalSetID(id); @@ -611,15 +655,57 @@ public final class CDOStateMachine extends FiniteStateMachine<CDOState, CDOEvent // Register object transaction.registerObject(object); transaction.registerNew(object); + } // Prepare content tree - for (Iterator<InternalCDOObject> it = FSMUtil.getProperContents(object); 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) + { + final boolean isResource = object instanceof Resource; + 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 = FSMUtil.adapt(eObject, transaction); + if (next instanceof InternalCDOObject) + { + return true; + } + } + } + + return false; + } + + public InternalCDOObject next() + { + return (InternalCDOObject)next; + } + + public void remove() + { + throw new UnsupportedOperationException(); + } + }; + } } /** @@ -650,6 +736,67 @@ public final class CDOStateMachine extends FiniteStateMachine<CDOState, CDOEvent } /** + * Bug 283985 (Re-attachment) + * + * @author Caspar De Groot + */ + private final class ReattachTransition implements + ITransition<CDOState, CDOEvent, InternalCDOObject, InternalCDOTransaction> + { + public void execute(InternalCDOObject object, CDOState state, CDOEvent event, InternalCDOTransaction transaction) + { + InternalCDORevisionManager revisionManager = transaction.getSession().getRevisionManager(); + InternalCDORevision formerRevision = ((CDOTransactionImpl)transaction).getFormerRevisions().get(object); + CDOID id = formerRevision.getID(); + + object.cdoInternalSetID(id); + object.cdoInternalSetView(transaction); + + // Construct a new revision if the old one is not transactional + InternalCDORevision revision; + EClass eClass = object.eClass(); + if (!formerRevision.isTransactional()) + { + CDORevisionFactory factory = revisionManager.getFactory(); + revision = (InternalCDORevision)factory.createRevision(eClass); + revision.setID(id); + revision.setVersion(formerRevision.getVersion()); + revision.setTransactional(); + } + else + { + // This branch only gets taken if the object that is being re-attached, + // was already DIRTY when it was first detached. + // + revision = formerRevision; + for (int i = 0; i < eClass.getFeatureCount(); i++) + { + EStructuralFeature eFeature = object.cdoInternalDynamicFeature(i); + if (!eFeature.isTransient()) + { + revision.clear(eFeature); + } + } + } + + // Populate the revision based on the values in the CDOObject + object.cdoInternalSetRevision(revision); + object.cdoInternalPostAttach(); + + // Compute a revision delta and register it with the tx + CDORevision originalRevision = revisionManager.getRevisionByVersion(id, -1, CDORevision.DEPTH_NONE, revision + .getVersion() - 1); + CDORevisionDelta revisionDelta = CDORevisionDeltaUtil.create(originalRevision, revision); + transaction.registerRevisionDelta(revisionDelta); + transaction.registerDirty(object, null); + changeState(object, CDOState.DIRTY); + + // Add the object to the set of reattached objects + ((CDOSavepointImpl)transaction.getLastSavepoint()).getReattachedObjects().put(id, object); + } + } + + /** * @author Eike Stepper */ private final class DetachTransition implements @@ -916,5 +1063,8 @@ public final class CDOStateMachine extends FiniteStateMachine<CDOState, CDOEvent */ enum CDOEvent { - PREPARE, ATTACH, DETACH, READ, WRITE, INVALIDATE, DETACH_REMOTE, RELOAD, COMMIT, ROLLBACK + PREPARE, ATTACH, DETACH, READ, WRITE, INVALIDATE, DETACH_REMOTE, RELOAD, COMMIT, ROLLBACK, + + // Bug 283985 (Re-attachment) + REATTACH } |