diff options
author | Egidijus Vaisnora | 2012-01-04 14:59:40 +0000 |
---|---|---|
committer | Egidijus Vaisnora | 2012-01-04 14:59:40 +0000 |
commit | 4e1ba595bab91ce57475455e513399fcd42d6e16 (patch) | |
tree | a7c573069a209f6d22b9aeacba724e90f86fc9ec | |
parent | c4d77b54ea1984b36ed152f69e920f9d0fade919 (diff) | |
download | cdo-4e1ba595bab91ce57475455e513399fcd42d6e16.tar.gz cdo-4e1ba595bab91ce57475455e513399fcd42d6e16.tar.xz cdo-4e1ba595bab91ce57475455e513399fcd42d6e16.zip |
Patch applied from the
https://bugs.eclipse.org/bugs/show_bug.cgi?id=350120
12 files changed, 274 insertions, 29 deletions
diff --git a/plugins/org.eclipse.emf.cdo.tests/src/org/eclipse/emf/cdo/tests/AbstractCDOTest.java b/plugins/org.eclipse.emf.cdo.tests/src/org/eclipse/emf/cdo/tests/AbstractCDOTest.java index f5a7173cef..0bc31c92cf 100644 --- a/plugins/org.eclipse.emf.cdo.tests/src/org/eclipse/emf/cdo/tests/AbstractCDOTest.java +++ b/plugins/org.eclipse.emf.cdo.tests/src/org/eclipse/emf/cdo/tests/AbstractCDOTest.java @@ -74,7 +74,6 @@ public abstract class AbstractCDOTest extends ConfigTest assertEquals(true, FSMUtil.isTransient(object)); assertNull(object.cdoID()); assertNull(object.cdoRevision()); - assertNull(object.cdoView()); } } diff --git a/plugins/org.eclipse.emf.cdo.tests/src/org/eclipse/emf/cdo/tests/StateMachineTest.java b/plugins/org.eclipse.emf.cdo.tests/src/org/eclipse/emf/cdo/tests/StateMachineTest.java index 18f2d5e9ff..96ab935174 100644 --- a/plugins/org.eclipse.emf.cdo.tests/src/org/eclipse/emf/cdo/tests/StateMachineTest.java +++ b/plugins/org.eclipse.emf.cdo.tests/src/org/eclipse/emf/cdo/tests/StateMachineTest.java @@ -25,6 +25,7 @@ import org.eclipse.emf.cdo.tests.model1.Product1; import org.eclipse.emf.cdo.tests.model1.Supplier; import org.eclipse.emf.cdo.transaction.CDOTransaction; import org.eclipse.emf.cdo.util.CDOUtil; +import org.eclipse.emf.cdo.view.CDOView; import org.eclipse.emf.internal.cdo.view.CDOStateMachine; @@ -137,8 +138,13 @@ public class StateMachineTest extends AbstractCDOTest Supplier supplier = getModel1Factory().createSupplier(); supplier.setName("Stepper"); assertTransient(supplier); - invalidate(supplier); - assertTransient(supplier); + + CDOSession session = openSession(); + CDOTransaction transaction = session.openTransaction(); + invalidate(supplier, transaction); + CDOObject object = CDOUtil.getCDOObject(supplier); + assertEquals(CDOState.CONFLICT, object.cdoState()); + session.close(); } public void test_TRANSIENT_with_COMMIT() throws Exception @@ -255,7 +261,7 @@ public class StateMachineTest extends AbstractCDOTest try { - invalidate(supplier); + invalidate(supplier, CDOUtil.getCDOObject(supplier).cdoView()); fail("IllegalStateException expected"); } catch (IllegalStateException expected) @@ -455,12 +461,12 @@ public class StateMachineTest extends AbstractCDOTest } } - private static void invalidate(EObject object) + private static void invalidate(EObject object, CDOView view) { CDOObject cdoObject = CDOUtil.getCDOObject(object); if (cdoObject != null) { - CDOStateMachine.INSTANCE.invalidate((InternalCDOObject)cdoObject, null, CDOBranchPoint.UNSPECIFIED_DATE); + CDOStateMachine.INSTANCE.invalidate((InternalCDOObject)cdoObject, null, CDOBranchPoint.UNSPECIFIED_DATE, view); } } diff --git a/plugins/org.eclipse.emf.cdo.tests/src/org/eclipse/emf/cdo/tests/bugzilla/Bugzilla_252214_Test.java b/plugins/org.eclipse.emf.cdo.tests/src/org/eclipse/emf/cdo/tests/bugzilla/Bugzilla_252214_Test.java index ee8969584f..0f0b334b1b 100644 --- a/plugins/org.eclipse.emf.cdo.tests/src/org/eclipse/emf/cdo/tests/bugzilla/Bugzilla_252214_Test.java +++ b/plugins/org.eclipse.emf.cdo.tests/src/org/eclipse/emf/cdo/tests/bugzilla/Bugzilla_252214_Test.java @@ -76,7 +76,8 @@ public class Bugzilla_252214_Test extends AbstractCDOTest CDOResource auditResource = audit.getResource(getResourcePath("/res1")); Company auditCompany = (Company)auditResource.getContents().get(0); CDOObject cdoAuditCompany = CDOUtil.getCDOObject(auditCompany); - CDOStateMachine.INSTANCE.invalidate((InternalCDOObject)cdoAuditCompany, null, CDOBranchPoint.UNSPECIFIED_DATE); + CDOStateMachine.INSTANCE.invalidate((InternalCDOObject)cdoAuditCompany, null, CDOBranchPoint.UNSPECIFIED_DATE, + cdoAuditCompany.cdoView()); } audit.setTimeStamp(commitTime2); diff --git a/plugins/org.eclipse.emf.cdo.tests/src/org/eclipse/emf/cdo/tests/bugzilla/Bugzilla_350120_Test.java b/plugins/org.eclipse.emf.cdo.tests/src/org/eclipse/emf/cdo/tests/bugzilla/Bugzilla_350120_Test.java new file mode 100644 index 0000000000..e8d9f7eca6 --- /dev/null +++ b/plugins/org.eclipse.emf.cdo.tests/src/org/eclipse/emf/cdo/tests/bugzilla/Bugzilla_350120_Test.java @@ -0,0 +1,165 @@ +/** + * Copyright (c) 2004 - 2011 Eike Stepper (Berlin, Germany) and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Eike Stepper - initial API and implementation + */ +package org.eclipse.emf.cdo.tests.bugzilla; + +import org.eclipse.emf.cdo.CDOObject; +import org.eclipse.emf.cdo.CDOState; +import org.eclipse.emf.cdo.common.revision.CDORevision; +import org.eclipse.emf.cdo.common.revision.delta.CDORevisionDelta; +import org.eclipse.emf.cdo.eresource.CDOResource; +import org.eclipse.emf.cdo.session.CDOSession; +import org.eclipse.emf.cdo.tests.AbstractCDOTest; +import org.eclipse.emf.cdo.tests.model1.Category; +import org.eclipse.emf.cdo.transaction.CDOTransaction; +import org.eclipse.emf.cdo.util.CDOUtil; +import org.eclipse.emf.cdo.util.CommitException; + +import org.eclipse.emf.ecore.util.EcoreUtil; +import org.eclipse.emf.spi.cdo.AbstractObjectConflictResolver; + +import java.util.List; + +/** + * @author Egidijus Vaisnora + */ +public class Bugzilla_350120_Test extends AbstractCDOTest +{ + public void testConflict() throws CommitException + { + CDOSession user1Session = openSession(); + user1Session.options().setPassiveUpdateEnabled(false); + + CDOTransaction user1Transaction = user1Session.openTransaction(); + CDOResource createResource = user1Transaction.createResource(getResourcePath("test")); + Category user1RootCategory = getModel1Factory().createCategory(); + createResource.getContents().add(user1RootCategory); + user1Transaction.commit(); + + // User 2 + CDOSession user2Session = openSession(); + user2Session.options().setPassiveUpdateEnabled(false); + CDOTransaction user2Transaction = user2Session.openTransaction(); + CDOObject user2RootCatecory = user2Transaction.getObject(CDOUtil.getCDOObject(user1RootCategory).cdoID()); + + // User 1 + Category user1ChildCategory = getModel1Factory().createCategory(); + user1RootCategory.getCategories().add(user1ChildCategory); + user1Transaction.commit(); + + // User 2 + EcoreUtil.delete(user2RootCatecory); + assertEquals(CDOState.TRANSIENT, user2RootCatecory.cdoState()); + user2Transaction.options().addConflictResolver(new AbstractObjectConflictResolver() + { + + @Override + protected void resolveConflict(CDOObject conflict, CDORevision oldRemoteRevision, CDORevisionDelta localDelta, + CDORevisionDelta remoteDelta, List<CDORevisionDelta> allRemoteDeltas) + { + // do nothing. It just test AbstractObjectConflictResolver from NPE + } + + }); + user2Session.refresh(); + + boolean expected = true; + if (expected) + { + assertEquals(CDOState.CONFLICT, user2RootCatecory.cdoState()); + } + else + { + // current flow + assertEquals(CDOState.TRANSIENT, user2RootCatecory.cdoState()); + CDOObject user2ChildCategory = user2Transaction.getObject(CDOUtil.getCDOObject(user1ChildCategory).cdoID()); + assertEquals(CDOState.CLEAN, user2ChildCategory.cdoState()); + user2Transaction.commit(); + + // User 1 + user1Session.refresh(); + assertEquals(CDOState.CLEAN, CDOUtil.getCDOObject(user1ChildCategory).cdoState()); + } + + user2Session.close(); + user1Session.close(); + } + + public void testMoveToOtherRepository() throws CommitException + { + CDOSession user1Session = openSession(); + user1Session.options().setPassiveUpdateEnabled(false); + + CDOTransaction user1Transaction = user1Session.openTransaction(); + CDOResource createResource = user1Transaction.createResource(getResourcePath("test")); + Category user1RootCategory = getModel1Factory().createCategory(); + createResource.getContents().add(user1RootCategory); + user1Transaction.commit(); + + // User 2 + CDOSession user2Session = openSession(); + user2Session.options().setPassiveUpdateEnabled(false); + CDOTransaction user2Transaction = user2Session.openTransaction(); + CDOObject user2RootCatecory = user2Transaction.getObject(CDOUtil.getCDOObject(user1RootCategory).cdoID()); + + // User 1 + Category user1ChildCategory = getModel1Factory().createCategory(); + user1RootCategory.getCategories().add(user1ChildCategory); + user1Transaction.commit(); + + // User 2 + EcoreUtil.delete(user2RootCatecory); + assertEquals(CDOState.TRANSIENT, user2RootCatecory.cdoState()); + + getRepository("repo2"); + CDOSession repo2Session = openSession("repo2"); + CDOTransaction user3Repo2Transaction = repo2Session.openTransaction(); + CDOResource repo2Resource = user3Repo2Transaction.createResource(getResourcePath("repo2Res")); + repo2Resource.getContents().add(user2RootCatecory); + assertEquals(CDOState.NEW, user2RootCatecory.cdoState()); + + user3Repo2Transaction.commit(); + assertEquals(CDOState.CLEAN, user2RootCatecory.cdoState()); + + user2Session.refresh(); + + boolean expected = true; + if (expected) + { + assertEquals(CDOState.CLEAN, user2RootCatecory.cdoState()); + assertEquals(user3Repo2Transaction, user2RootCatecory.cdoView()); + + } + else + { + // current flow - object was invalidated updating another session + assertEquals(CDOState.PROXY, user2RootCatecory.cdoState()); + assertEquals(user3Repo2Transaction, user2RootCatecory.cdoView()); + } + + // make rollback + user2Transaction.rollback(); + if (expected) + { + assertEquals(CDOState.CLEAN, user2RootCatecory.cdoState()); + assertEquals(user3Repo2Transaction, user2RootCatecory.cdoView()); + + } + else + { + // current flow - object switched transaction + assertEquals(CDOState.CLEAN, user2RootCatecory.cdoState()); + assertEquals(user2Transaction, user2RootCatecory.cdoView()); + } + + user2Session.close(); + user1Session.close(); + } +} diff --git a/plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/internal/cdo/CDOObjectImpl.java b/plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/internal/cdo/CDOObjectImpl.java index 586571863d..bf872f04d5 100644 --- a/plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/internal/cdo/CDOObjectImpl.java +++ b/plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/internal/cdo/CDOObjectImpl.java @@ -653,7 +653,7 @@ public class CDOObjectImpl extends EStoreEObjectImpl implements InternalCDOObjec CDOView newView = newResource != null && newResource instanceof CDOResource ? ((CDOResource)newResource).cdoView() : null; - boolean moved = oldView != null && oldView == newView; + boolean moved = oldView != null && oldView == newView && cdoState() != CDOState.TRANSIENT; if (!moved && oldResource != null && !isResourceRoot) { oldResource.detached(this); diff --git a/plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/internal/cdo/object/CDOLegacyAdapter.java b/plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/internal/cdo/object/CDOLegacyAdapter.java index 9f9740a163..91885be501 100644 --- a/plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/internal/cdo/object/CDOLegacyAdapter.java +++ b/plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/internal/cdo/object/CDOLegacyAdapter.java @@ -12,6 +12,7 @@ package org.eclipse.emf.internal.cdo.object; import org.eclipse.emf.cdo.CDONotification; +import org.eclipse.emf.cdo.CDOState; import org.eclipse.emf.cdo.common.model.EMFUtil; import org.eclipse.emf.cdo.transaction.CDOTransaction; @@ -80,7 +81,7 @@ public class CDOLegacyAdapter extends CDOLegacyWrapper implements Adapter.Intern } EStructuralFeature feature = (EStructuralFeature)msg.getFeature(); - if (view == null || feature == null || !(view instanceof CDOTransaction)) + if (view == null || feature == null || !(view instanceof CDOTransaction) || cdoState() == CDOState.TRANSIENT) { return; } 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 f8d18c7e8b..42de90fe81 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 @@ -2179,7 +2179,8 @@ public class CDOTransactionImpl extends CDOViewImpl implements InternalCDOTransa @Override protected Map<CDOObject, Pair<CDORevision, CDORevisionDelta>> invalidate(long lastUpdateTime, List<CDORevisionKey> allChangedObjects, List<CDOIDAndVersion> allDetachedObjects, List<CDORevisionDelta> deltas, - Map<CDOObject, CDORevisionDelta> revisionDeltas, Set<CDOObject> detachedObjects) + Map<CDOObject, CDORevisionDelta> revisionDeltas, Set<CDOObject> detachedObjects, + Map<CDOID, InternalCDORevision> oldRevisions) { if (!allDetachedObjects.isEmpty()) { @@ -2204,7 +2205,7 @@ public class CDOTransactionImpl extends CDOViewImpl implements InternalCDOTransa } return super.invalidate(lastUpdateTime, allChangedObjects, allDetachedObjects, deltas, revisionDeltas, - detachedObjects); + detachedObjects, oldRevisions); } private void removeCrossReferences(Collection<CDOObject> referencers, Set<CDOID> referencedOIDs) @@ -2326,7 +2327,7 @@ public class CDOTransactionImpl extends CDOViewImpl implements InternalCDOTransa InternalCDORevision rev = super.getViewedRevision(object); // Bug 336590: If we have a clean revision for this object, return that instead - if (rev != null) + if (rev != null || object.cdoState() == CDOState.TRANSIENT) { InternalCDORevision cleanRev = cleanRevisions.get(object); if (cleanRev != null) diff --git a/plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/internal/cdo/view/AbstractCDOView.java b/plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/internal/cdo/view/AbstractCDOView.java index acad1f21d4..dc0374a315 100644 --- a/plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/internal/cdo/view/AbstractCDOView.java +++ b/plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/internal/cdo/view/AbstractCDOView.java @@ -1125,7 +1125,17 @@ public abstract class AbstractCDOView extends Lifecycle implements InternalCDOVi TRACER.format("Deregistering {0}", object); //$NON-NLS-1$ } - removeObject(object.cdoID()); + deregisterObject(object.cdoID()); + } + + public synchronized void deregisterObject(CDOID id) + { + if (TRACER.isEnabled()) + { + TRACER.format("Deregistering {0}", id); //$NON-NLS-1$ + } + + removeObject(id); } public synchronized void remapObject(CDOID oldID) @@ -1178,7 +1188,8 @@ public abstract class AbstractCDOView extends Lifecycle implements InternalCDOVi */ protected Map<CDOObject, Pair<CDORevision, CDORevisionDelta>> invalidate(long lastUpdateTime, List<CDORevisionKey> allChangedObjects, List<CDOIDAndVersion> allDetachedObjects, List<CDORevisionDelta> deltas, - Map<CDOObject, CDORevisionDelta> revisionDeltas, Set<CDOObject> detachedObjects) + Map<CDOObject, CDORevisionDelta> revisionDeltas, Set<CDOObject> detachedObjects, + Map<CDOID, InternalCDORevision> oldRevisions) { Map<CDOObject, Pair<CDORevision, CDORevisionDelta>> conflicts = null; for (CDORevisionKey key : allChangedObjects) @@ -1200,11 +1211,20 @@ public abstract class AbstractCDOView extends Lifecycle implements InternalCDOVi if (changedObject != null) { - Pair<CDORevision, CDORevisionDelta> oldInfo = new Pair<CDORevision, CDORevisionDelta>( - changedObject.cdoRevision(), delta); + CDOID cdoID = key.getID(); + Pair<CDORevision, CDORevisionDelta> oldInfo; + if (changedObject.cdoState() == CDOState.TRANSIENT) + { + oldInfo = new Pair<CDORevision, CDORevisionDelta>(oldRevisions.get(cdoID), delta); + } + else + { + oldInfo = new Pair<CDORevision, CDORevisionDelta>(changedObject.cdoRevision(), delta); + } + // if (!isLocked(changedObject)) { - CDOStateMachine.INSTANCE.invalidate((InternalCDOObject)changedObject, key, lastUpdateTime); + CDOStateMachine.INSTANCE.invalidate((InternalCDOObject)changedObject, key, lastUpdateTime, this); } revisionDeltas.put(changedObject, delta); @@ -1391,12 +1411,13 @@ public abstract class AbstractCDOView extends Lifecycle implements InternalCDOVi for (InternalCDOObject object : objects.values()) { CDOState state = object.cdoState(); - if (state != CDOState.CLEAN && state != CDOState.DIRTY && state != CDOState.CONFLICT) + if (state != CDOState.CLEAN && state != CDOState.DIRTY && state != CDOState.CONFLICT + && state != CDOState.TRANSIENT) { continue; } - CDOID id = object.cdoID(); + CDOID id = getID(object, true); if (revisions.containsKey(id)) { continue; diff --git a/plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/internal/cdo/view/CDOStateMachine.java b/plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/internal/cdo/view/CDOStateMachine.java index 80ea51a1a4..47b12d224d 100644 --- a/plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/internal/cdo/view/CDOStateMachine.java +++ b/plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/internal/cdo/view/CDOStateMachine.java @@ -35,6 +35,7 @@ import org.eclipse.emf.internal.cdo.CDOObjectImpl; import org.eclipse.emf.internal.cdo.bundle.OM; import org.eclipse.net4j.util.collection.Pair; +import org.eclipse.net4j.util.collection.Triplet; import org.eclipse.net4j.util.fsm.FiniteStateMachine; import org.eclipse.net4j.util.fsm.ITransition; import org.eclipse.net4j.util.om.trace.ContextTracer; @@ -49,6 +50,7 @@ import org.eclipse.emf.ecore.resource.Resource; import org.eclipse.emf.spi.cdo.CDOSessionProtocol.CommitTransactionResult; import org.eclipse.emf.spi.cdo.FSMUtil; import org.eclipse.emf.spi.cdo.InternalCDOObject; +import org.eclipse.emf.spi.cdo.InternalCDOSavepoint; import org.eclipse.emf.spi.cdo.InternalCDOSession; import org.eclipse.emf.spi.cdo.InternalCDOTransaction; import org.eclipse.emf.spi.cdo.InternalCDOView; @@ -86,7 +88,7 @@ public final class CDOStateMachine extends FiniteStateMachine<CDOState, CDOEvent init(CDOState.TRANSIENT, CDOEvent.REATTACH, new ReattachTransition()); init(CDOState.TRANSIENT, CDOEvent.READ, IGNORE); init(CDOState.TRANSIENT, CDOEvent.WRITE, IGNORE); - init(CDOState.TRANSIENT, CDOEvent.INVALIDATE, IGNORE); + init(CDOState.TRANSIENT, CDOEvent.INVALIDATE, new TransientConflictTransition()); init(CDOState.TRANSIENT, CDOEvent.DETACH_REMOTE, IGNORE); init(CDOState.TRANSIENT, CDOEvent.COMMIT, FAIL); init(CDOState.TRANSIENT, CDOEvent.ROLLBACK, FAIL); @@ -286,7 +288,6 @@ public final class CDOStateMachine extends FiniteStateMachine<CDOState, CDOEvent transaction.detachObject(content); content.cdoInternalSetState(CDOState.TRANSIENT); - content.cdoInternalSetView(null); content.cdoInternalSetID(null); content.cdoInternalSetRevision(null); } @@ -391,7 +392,7 @@ public final class CDOStateMachine extends FiniteStateMachine<CDOState, CDOEvent /** * @since 3.0 */ - public void invalidate(InternalCDOObject object, CDORevisionKey key, long lastUpdateTime) + public void invalidate(InternalCDOObject object, CDORevisionKey key, long lastUpdateTime, CDOView view) { synchronized (getMonitor(object)) { @@ -400,7 +401,7 @@ public final class CDOStateMachine extends FiniteStateMachine<CDOState, CDOEvent trace(object, CDOEvent.INVALIDATE); } - process(object, CDOEvent.INVALIDATE, new Pair<CDORevisionKey, Long>(key, lastUpdateTime)); + process(object, CDOEvent.INVALIDATE, new Triplet<CDORevisionKey, Long, CDOView>(key, lastUpdateTime, view)); } } @@ -528,6 +529,25 @@ public final class CDOStateMachine extends FiniteStateMachine<CDOState, CDOEvent if (!reattaching) { + InternalCDOView oldView = object.cdoView(); + if (oldView != null && oldView != transaction && object.cdoState() == CDOState.TRANSIENT) + { + // transfer to another transaction, make cleanup in old view + InternalCDOTransaction oldTransaction = oldView.toTransaction(); + CDORevisionKey revKey = oldTransaction.getCleanRevisions().get(object); + if (revKey != null) + { + InternalCDOSavepoint lastSavepoint = oldTransaction.getLastSavepoint(); + for (InternalCDOSavepoint savepoint = lastSavepoint; savepoint != null; savepoint = savepoint + .getPreviousSavepoint()) + { + savepoint.getDetachedObjects().remove(revKey.getID()); + } + + oldTransaction.deregisterObject(revKey.getID()); + } + } + // Prepare object CDOID id = transaction.createIDForNewObject(object.cdoInternalInstance()); object.cdoInternalSetID(id); @@ -841,9 +861,10 @@ public final class CDOStateMachine extends FiniteStateMachine<CDOState, CDOEvent * @author Eike Stepper */ private class InvalidateTransition implements - ITransition<CDOState, CDOEvent, InternalCDOObject, Pair<CDORevisionKey, Long>> + ITransition<CDOState, CDOEvent, InternalCDOObject, Triplet<CDORevisionKey, Long, InternalCDOView>> { - public void execute(InternalCDOObject object, CDOState state, CDOEvent event, Pair<CDORevisionKey, Long> keyAndTime) + public void execute(InternalCDOObject object, CDOState state, CDOEvent event, + Triplet<CDORevisionKey, Long, InternalCDOView> keyAndTime) { CDORevisionKey key = keyAndTime.getElement1(); InternalCDORevision oldRevision = object.cdoRevision(); @@ -905,10 +926,12 @@ public final class CDOStateMachine extends FiniteStateMachine<CDOState, CDOEvent private class ConflictTransition extends InvalidateTransition { @Override - public void execute(InternalCDOObject object, CDOState state, CDOEvent event, Pair<CDORevisionKey, Long> keyAndTime) + public void execute(InternalCDOObject object, CDOState state, CDOEvent event, + Triplet<CDORevisionKey, Long, InternalCDOView> keyAndTime) { CDORevisionKey key = keyAndTime.getElement1(); InternalCDORevision oldRevision = object.cdoRevision(); + if (key == null || key.getVersion() >= oldRevision.getVersion() - 1) { changeState(object, CDOState.CONFLICT); @@ -919,12 +942,29 @@ public final class CDOStateMachine extends FiniteStateMachine<CDOState, CDOEvent } /** + * @author Eike Stepper + * @since 2.0 + */ + private class TransientConflictTransition extends InvalidateTransition + { + @Override + public void execute(InternalCDOObject object, CDOState state, CDOEvent event, + Triplet<CDORevisionKey, Long, InternalCDOView> keyAndTime) + { + InternalCDOTransaction transaction = keyAndTime.getElement3().toTransaction(); + changeState(object, CDOState.CONFLICT); + transaction.setConflict(object); + } + } + + /** * @author Simon McDuff */ private final class InvalidConflictTransition extends ConflictTransition { @Override - public void execute(InternalCDOObject object, CDOState state, CDOEvent event, Pair<CDORevisionKey, Long> UNUSED) + public void execute(InternalCDOObject object, CDOState state, CDOEvent event, + Triplet<CDORevisionKey, Long, InternalCDOView> UNUSED) { changeState(object, CDOState.INVALID_CONFLICT); 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 3524857769..83bf125f66 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 @@ -805,7 +805,7 @@ public class CDOViewImpl extends AbstractCDOView Set<CDOObject> detachedObjects = new HashSet<CDOObject>(); conflicts = invalidate(lastUpdateTime, allChangedObjects, allDetachedObjects, deltas, revisionDeltas, - detachedObjects); + detachedObjects, oldRevisions); sendInvalidationNotifications(revisionDeltas.keySet(), detachedObjects); fireInvalidationEvent(lastUpdateTime, Collections.unmodifiableMap(revisionDeltas), diff --git a/plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/spi/cdo/AbstractObjectConflictResolver.java b/plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/spi/cdo/AbstractObjectConflictResolver.java index b23d07fb19..4992409d1e 100644 --- a/plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/spi/cdo/AbstractObjectConflictResolver.java +++ b/plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/spi/cdo/AbstractObjectConflictResolver.java @@ -95,7 +95,13 @@ public abstract class AbstractObjectConflictResolver extends AbstractConflictRes CDOObject conflict = entry.getKey(); CDORevision oldRevision = entry.getValue().getElement1(); CDORevisionDelta remoteDelta = entry.getValue().getElement2(); - CDORevisionDelta localDelta = localDeltas.get(conflict.cdoID()); + CDOID cdoID = conflict.cdoID(); + if (cdoID == null) + { + // we have detached object in CONFLICT state. But ID we can obtain from old revision + cdoID = oldRevision.getID(); + } + CDORevisionDelta localDelta = localDeltas.get(cdoID); try { diff --git a/plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/spi/cdo/InternalCDOView.java b/plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/spi/cdo/InternalCDOView.java index 0d694c11a7..50e9bca9f0 100644 --- a/plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/spi/cdo/InternalCDOView.java +++ b/plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/spi/cdo/InternalCDOView.java @@ -103,6 +103,11 @@ public interface InternalCDOView extends CDOView, CDOIDProvider, ILifecycle public void deregisterObject(InternalCDOObject object); + /** + * @since 4.1 + */ + public void deregisterObject(CDOID object); + public InternalCDORevision getRevision(CDOID id, boolean loadOnDemand); /** |