Skip to main content
summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--plugins/org.eclipse.emf.cdo.tests/src/org/eclipse/emf/cdo/tests/Bugzilla_396804_Test.java139
-rw-r--r--plugins/org.eclipse.emf.cdo.tests/src/org/eclipse/emf/cdo/tests/ConflictResolverExtendedTest.java4
-rw-r--r--plugins/org.eclipse.emf.cdo.tests/src/org/eclipse/emf/cdo/tests/ConflictResolverMergingTest.java36
-rw-r--r--plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/internal/cdo/session/CDOSessionImpl.java178
-rw-r--r--plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/spi/cdo/AbstractChangeSetsConflictResolver.java46
-rw-r--r--plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/spi/cdo/CDOMergingConflictResolver.java85
-rw-r--r--plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/spi/cdo/CDOSessionInvalidationAggregator.java72
-rw-r--r--plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/spi/cdo/CDOSessionInvalidationEventQueue.java93
8 files changed, 415 insertions, 238 deletions
diff --git a/plugins/org.eclipse.emf.cdo.tests/src/org/eclipse/emf/cdo/tests/Bugzilla_396804_Test.java b/plugins/org.eclipse.emf.cdo.tests/src/org/eclipse/emf/cdo/tests/Bugzilla_396804_Test.java
new file mode 100644
index 0000000000..0768d7523f
--- /dev/null
+++ b/plugins/org.eclipse.emf.cdo.tests/src/org/eclipse/emf/cdo/tests/Bugzilla_396804_Test.java
@@ -0,0 +1,139 @@
+/*
+ * Copyright (c) 2004 - 2012 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:
+ * Erdal Karaca - initial API and implementation
+ */
+package org.eclipse.emf.cdo.tests;
+
+import org.eclipse.emf.cdo.eresource.CDOResource;
+import org.eclipse.emf.cdo.session.CDOSession;
+import org.eclipse.emf.cdo.tests.model1.Model1Factory;
+import org.eclipse.emf.cdo.tests.model1.Order;
+import org.eclipse.emf.cdo.tests.model1.OrderDetail;
+import org.eclipse.emf.cdo.transaction.CDOTransaction;
+
+import org.eclipse.emf.common.util.EList;
+import org.eclipse.emf.ecore.EObject;
+import org.eclipse.emf.spi.cdo.CDOMergingConflictResolver;
+import org.eclipse.emf.spi.cdo.DefaultCDOMerger;
+
+/**
+ * Test cases for CDOMergingConflictResolver. See bug 396804.
+ *
+ * @author Erdal Karaca
+ */
+public class Bugzilla_396804_Test extends AbstractCDOTest
+{
+ public void testParallelADD() throws Exception
+ {
+ String path = getResourcePath("/res1");
+
+ {
+ CDOSession session = openSession();
+ CDOTransaction transaction = session.openTransaction();
+ transaction.createResource(path);
+ transaction.commit();
+ session.close();
+ }
+
+ CDOSession session1 = openSession();
+ CDOTransaction transaction1 = session1.openTransaction();
+ transaction1.options().addConflictResolver(createConflictResolver());
+
+ CDOResource resource1 = transaction1.getResource(path);
+ transaction1.commit();
+
+ resource1.getContents().add(Model1Factory.eINSTANCE.createSalesOrder());
+
+ CDOSession session2 = openSession();
+ CDOTransaction transaction2 = session2.openTransaction();
+
+ CDOResource resource2 = transaction2.getResource(path);
+ OrderDetail orderDetail = Model1Factory.eINSTANCE.createOrderDetail();
+ resource2.getContents().add(orderDetail);
+ commitAndSync(transaction2, transaction1);
+
+ transaction1.commit();
+ }
+
+ public void testParallelRemoveYieldsUnexpectedObjectState() throws Exception
+ {
+ String path = getResourcePath("/res1");
+
+ {
+ CDOSession session = openSession();
+ CDOTransaction transaction = session.openTransaction();
+
+ EList<EObject> contents = transaction.createResource(path).getContents();
+ contents.add(Model1Factory.eINSTANCE.createOrderDetail());
+ contents.add(Model1Factory.eINSTANCE.createOrderDetail());
+
+ transaction.commit();
+ session.close();
+ }
+
+ CDOSession session1 = openSession();
+ CDOTransaction transaction1 = session1.openTransaction();
+ transaction1.options().addConflictResolver(createConflictResolver());
+
+ EList<EObject> contents1 = transaction1.getResource(path).getContents();
+ OrderDetail firstOrderDetail1 = (OrderDetail)contents1.get(0);
+ Order order = Model1Factory.eINSTANCE.createSalesOrder();
+ order.getOrderDetails().add(firstOrderDetail1); // change2: contents1.remove(0)
+ contents1.add(order); // change3
+
+ CDOSession session2 = openSession();
+ CDOTransaction transaction2 = session2.openTransaction();
+
+ EList<EObject> contents2 = transaction2.getResource(path).getContents();
+ contents2.remove(1); // change1: lastOrderDetail2
+ commitAndSync(transaction2, transaction1);
+
+ transaction1.commit();
+ }
+
+ public void testParallelRemoveThrowsIOOBE() throws Exception
+ {
+ String path = getResourcePath("/res1");
+
+ {
+ CDOSession session = openSession();
+ CDOTransaction transaction = session.openTransaction();
+ CDOResource resource = transaction.createResource(path);
+
+ resource.getContents().add(Model1Factory.eINSTANCE.createOrderDetail());
+ resource.getContents().add(Model1Factory.eINSTANCE.createOrderDetail());
+
+ transaction.commit();
+ session.close();
+ }
+
+ CDOSession session1 = openSession();
+ CDOTransaction transaction1 = session1.openTransaction();
+ transaction1.options().addConflictResolver(createConflictResolver());
+
+ CDOResource resource1 = transaction1.getResource(path);
+ Order order = Model1Factory.eINSTANCE.createSalesOrder();
+ resource1.getContents().add(order);
+
+ CDOSession session2 = openSession();
+ CDOTransaction transaction2 = session2.openTransaction();
+
+ CDOResource resource2 = transaction2.getResource(path);
+ OrderDetail lastOrderDetail = (OrderDetail)resource2.getContents().get(resource2.getContents().size() - 1);
+ resource2.getContents().remove(lastOrderDetail);
+ commitAndSync(transaction2, transaction1);
+
+ transaction1.commit();
+ }
+
+ private CDOMergingConflictResolver createConflictResolver()
+ {
+ return new CDOMergingConflictResolver(new DefaultCDOMerger.PerFeature.ManyValued());
+ }
+}
diff --git a/plugins/org.eclipse.emf.cdo.tests/src/org/eclipse/emf/cdo/tests/ConflictResolverExtendedTest.java b/plugins/org.eclipse.emf.cdo.tests/src/org/eclipse/emf/cdo/tests/ConflictResolverExtendedTest.java
index 255a8aefbf..01f65bc853 100644
--- a/plugins/org.eclipse.emf.cdo.tests/src/org/eclipse/emf/cdo/tests/ConflictResolverExtendedTest.java
+++ b/plugins/org.eclipse.emf.cdo.tests/src/org/eclipse/emf/cdo/tests/ConflictResolverExtendedTest.java
@@ -25,6 +25,7 @@ import org.eclipse.emf.cdo.util.CommitException;
import org.eclipse.emf.common.notify.Notification;
import org.eclipse.emf.common.notify.impl.AdapterImpl;
import org.eclipse.emf.common.util.EList;
+import org.eclipse.emf.spi.cdo.CDOMergingConflictResolver;
import java.util.List;
@@ -35,8 +36,7 @@ public class ConflictResolverExtendedTest extends AbstractCDOTest
{
private static final String TEST_RESOURCE_NAME = "/test1";
- @SuppressWarnings("deprecation")
- private CDOConflictResolver conflictResolver = new org.eclipse.emf.spi.cdo.CDOMergingConflictResolver();
+ private CDOConflictResolver conflictResolver = new CDOMergingConflictResolver();
// --- initialize model ----------------------------------------------------
diff --git a/plugins/org.eclipse.emf.cdo.tests/src/org/eclipse/emf/cdo/tests/ConflictResolverMergingTest.java b/plugins/org.eclipse.emf.cdo.tests/src/org/eclipse/emf/cdo/tests/ConflictResolverMergingTest.java
index 175cf70bf9..fd00cd1f1c 100644
--- a/plugins/org.eclipse.emf.cdo.tests/src/org/eclipse/emf/cdo/tests/ConflictResolverMergingTest.java
+++ b/plugins/org.eclipse.emf.cdo.tests/src/org/eclipse/emf/cdo/tests/ConflictResolverMergingTest.java
@@ -20,6 +20,7 @@ import org.eclipse.emf.cdo.util.CDOUtil;
import org.eclipse.emf.common.util.EList;
import org.eclipse.emf.ecore.EObject;
+import org.eclipse.emf.spi.cdo.CDOMergingConflictResolver;
/**
* @author Simon McDuff
@@ -102,40 +103,47 @@ public class ConflictResolverMergingTest extends ConflictResolverTest
msg("Opening session");
CDOSession session = openSession();
+ // CLIENT-1 creates sales order
CDOTransaction transaction1 = session.openTransaction();
transaction1.options().addConflictResolver(createConflictResolver());
EList<EObject> contents1 = transaction1.getOrCreateResource(getResourcePath("/res1")).getContents();
- SalesOrder c1 = getModel1Factory().createSalesOrder();
- contents1.add(c1);
+ SalesOrder salesOrder1 = getModel1Factory().createSalesOrder();
+ EList<OrderDetail> orderDetails1 = salesOrder1.getOrderDetails();
+
+ contents1.add(salesOrder1);
transaction1.commit();
+ // CLIENT-2 loads sales order
CDOTransaction transaction2 = session.openTransaction();
transaction2.options().addConflictResolver(createConflictResolver());
EList<EObject> contents2 = transaction2.getOrCreateResource(getResourcePath("/res1")).getContents();
- SalesOrder c2 = (SalesOrder)contents2.get(0);
+ SalesOrder salesOrder2 = (SalesOrder)contents2.get(0);
+ EList<OrderDetail> orderDetails2 = salesOrder2.getOrderDetails();
- OrderDetail s1 = getModel1Factory().createOrderDetail();
- c1.getOrderDetails().add(s1);
+ // CLIENT-1 adds order detail
+ OrderDetail orderDetail1 = getModel1Factory().createOrderDetail();
+ orderDetails1.add(orderDetail1);
- OrderDetail s2 = getModel1Factory().createOrderDetail();
- c2.getOrderDetails().add(s2);
+ // CLIENT-2 adds order detail
+ OrderDetail orderDetail2 = getModel1Factory().createOrderDetail();
+ orderDetails2.add(orderDetail2);
+ // CLIENT-1 commits and waits for CLIENT-2's conflict resolver
commitAndSync(transaction1, transaction2);
+
+ // CLIENT-2 commits and waits for CLIENT-1's conflict resolver (nothing to do there)
commitAndSync(transaction2, transaction1);
- EList<OrderDetail> list = c1.getOrderDetails();
- System.out.println(list);
- assertEquals(2, list.size());
- assertEquals(CDOUtil.getCDOObject(s2).cdoID(), CDOUtil.getCDOObject(list.get(0)).cdoID());
- assertEquals(CDOUtil.getCDOObject(s1).cdoID(), CDOUtil.getCDOObject(list.get(1)).cdoID());
+ assertEquals(2, orderDetails1.size());
+ assertEquals(CDOUtil.getCDOObject(orderDetail2).cdoID(), CDOUtil.getCDOObject(orderDetails1.get(0)).cdoID());
+ assertEquals(CDOUtil.getCDOObject(orderDetail1).cdoID(), CDOUtil.getCDOObject(orderDetails1.get(1)).cdoID());
}
- @SuppressWarnings("deprecation")
@Override
protected CDOConflictResolver createConflictResolver()
{
- return new org.eclipse.emf.spi.cdo.CDOMergingConflictResolver();
+ return new CDOMergingConflictResolver();
}
}
diff --git a/plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/internal/cdo/session/CDOSessionImpl.java b/plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/internal/cdo/session/CDOSessionImpl.java
index a6b38604a7..bf7ce48068 100644
--- a/plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/internal/cdo/session/CDOSessionImpl.java
+++ b/plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/internal/cdo/session/CDOSessionImpl.java
@@ -91,7 +91,6 @@ import org.eclipse.emf.internal.cdo.util.DefaultLocksChangedEvent;
import org.eclipse.net4j.util.ObjectUtil;
import org.eclipse.net4j.util.ReflectUtil.ExcludeFromDump;
import org.eclipse.net4j.util.WrappedException;
-import org.eclipse.net4j.util.collection.Pair;
import org.eclipse.net4j.util.concurrent.IRWLockManager;
import org.eclipse.net4j.util.concurrent.IRWLockManager.LockType;
import org.eclipse.net4j.util.concurrent.IRWOLockManager;
@@ -909,7 +908,6 @@ public abstract class CDOSessionImpl extends CDOTransactionContainerImpl impleme
Map<CDOID, InternalCDORevision> oldRevisions = null;
CDOBranch newBranch = commitInfo.getBranch();
long timeStamp = commitInfo.getTimeStamp();
- InternalCDORevisionManager revisionManager = getRevisionManager();
// Cache new revisions
for (CDOIDAndVersion key : commitInfo.getNewObjects())
@@ -924,96 +922,37 @@ public abstract class CDOSessionImpl extends CDOTransactionContainerImpl impleme
// Apply deltas and cache the resulting new revisions, if possible...
for (CDORevisionKey key : commitInfo.getChangedObjects())
{
- // Add old values to revision deltas.
+ CDOID id = key.getID();
if (key instanceof CDORevisionDelta)
{
- final CDORevisionDelta revisionDelta = (CDORevisionDelta)key;
- final CDORevision oldRevision = revisionManager.getRevisionByVersion(revisionDelta.getID(), revisionDelta,
- CDORevision.UNCHUNKED, false);
+ CDORevisionDelta revisionDelta = (CDORevisionDelta)key;
+ InternalCDORevision oldRevision = revisionManager.getRevisionByVersion(id, revisionDelta,
+ CDORevision.UNCHUNKED, false);
if (oldRevision != null)
{
- CDOFeatureDeltaVisitor visitor = new CDOFeatureDeltaVisitorImpl()
- {
- private List<Object> workList;
-
- @Override
- public void visit(CDOAddFeatureDelta delta)
- {
- workList.add(delta.getIndex(), delta.getValue());
- }
-
- @Override
- public void visit(CDOClearFeatureDelta delta)
- {
- workList.clear();
- }
-
- @Override
- public void visit(CDOListFeatureDelta deltas)
- {
- @SuppressWarnings("unchecked")
- List<Object> list = (List<Object>)((InternalCDORevision)oldRevision).getValue(deltas.getFeature());
- if (list != null)
- {
- workList = new ArrayList<Object>(list);
- super.visit(deltas);
- }
- }
-
- @Override
- public void visit(CDOMoveFeatureDelta delta)
- {
- Object value = workList.get(delta.getOldPosition());
- ((CDOMoveFeatureDeltaImpl)delta).setValue(value);
- ECollections.move(workList, delta.getNewPosition(), delta.getOldPosition());
- }
+ addOldValuesToDelta(oldRevision, revisionDelta);
- @Override
- public void visit(CDORemoveFeatureDelta delta)
- {
- Object oldValue = workList.remove(delta.getIndex());
- ((CDOSingleValueFeatureDeltaImpl)delta).setValue(oldValue);
- }
+ InternalCDORevision newRevision = oldRevision.copy();
+ newRevision.adjustForCommit(commitInfo.getBranch(), commitInfo.getTimeStamp());
- @Override
- public void visit(CDOSetFeatureDelta delta)
- {
- EStructuralFeature feature = delta.getFeature();
- Object value = null;
- if (feature.isMany())
- {
- value = workList.set(delta.getIndex(), delta.getValue());
- }
- else
- {
- value = ((InternalCDORevision)oldRevision).getValue(feature);
- }
+ CDORevisable target = revisionDelta.getTarget();
+ if (target != null)
+ {
+ newRevision.setVersion(target.getVersion());
+ }
- ((CDOSetFeatureDeltaImpl)delta).setOldValue(value);
- }
- };
+ revisionDelta.apply(newRevision);
+ newRevision.freeze();
- for (CDOFeatureDelta featureDelta : revisionDelta.getFeatureDeltas())
+ revisionManager.addRevision(newRevision);
+ if (oldRevisions == null)
{
- featureDelta.accept(visitor);
+ oldRevisions = new HashMap<CDOID, InternalCDORevision>();
}
- }
- }
- CDOID id = key.getID();
- Pair<InternalCDORevision, InternalCDORevision> pair = createNewRevision(key, commitInfo);
- if (pair != null)
- {
- InternalCDORevision newRevision = pair.getElement2();
- revisionManager.addRevision(newRevision);
- if (oldRevisions == null)
- {
- oldRevisions = new HashMap<CDOID, InternalCDORevision>();
+ oldRevisions.put(id, oldRevision);
}
-
- InternalCDORevision oldRevision = pair.getElement1();
- oldRevisions.put(id, oldRevision);
}
else
{
@@ -1035,35 +974,78 @@ public abstract class CDOSessionImpl extends CDOTransactionContainerImpl impleme
return oldRevisions;
}
- private Pair<InternalCDORevision, InternalCDORevision> createNewRevision(CDORevisionKey potentialDelta,
- CDOCommitInfo commitInfo)
+ /**
+ * Computes/adjusts CDOMoveFeatureDelta.value, CDORemoveFeatureDelta.value and CDOSetFeatureDelta.oldValue.
+ * <p>
+ * Implicitely adjusts the underlying CDORevisionDelta.
+ */
+ private void addOldValuesToDelta(final CDORevision oldRevision, CDORevisionDelta revisionDelta)
{
- if (potentialDelta instanceof CDORevisionDelta)
+ CDOFeatureDeltaVisitor visitor = new CDOFeatureDeltaVisitorImpl()
{
- CDORevisionDelta delta = (CDORevisionDelta)potentialDelta;
- CDOID id = delta.getID();
+ private List<Object> workList;
- InternalCDORevisionManager revisionManager = getRevisionManager();
- InternalCDORevision oldRevision = revisionManager.getRevisionByVersion(id, potentialDelta, CDORevision.UNCHUNKED,
- false);
- if (oldRevision != null)
+ @Override
+ public void visit(CDOAddFeatureDelta delta)
{
- InternalCDORevision newRevision = oldRevision.copy();
- newRevision.adjustForCommit(commitInfo.getBranch(), commitInfo.getTimeStamp());
+ workList.add(delta.getIndex(), delta.getValue());
+ }
- CDORevisable target = delta.getTarget();
- if (target != null)
+ @Override
+ public void visit(CDOClearFeatureDelta delta)
+ {
+ workList.clear();
+ }
+
+ @Override
+ public void visit(CDOListFeatureDelta deltas)
+ {
+ @SuppressWarnings("unchecked")
+ List<Object> list = (List<Object>)((InternalCDORevision)oldRevision).getValue(deltas.getFeature());
+ if (list != null)
{
- newRevision.setVersion(target.getVersion());
+ workList = new ArrayList<Object>(list);
+ super.visit(deltas);
}
+ }
- delta.apply(newRevision);
- newRevision.freeze();
- return new Pair<InternalCDORevision, InternalCDORevision>(oldRevision, newRevision);
+ @Override
+ public void visit(CDOMoveFeatureDelta delta)
+ {
+ Object value = workList.get(delta.getOldPosition());
+ ((CDOMoveFeatureDeltaImpl)delta).setValue(value); // Adjust delta
+ ECollections.move(workList, delta.getNewPosition(), delta.getOldPosition());
}
- }
- return null;
+ @Override
+ public void visit(CDORemoveFeatureDelta delta)
+ {
+ Object oldValue = workList.remove(delta.getIndex());
+ ((CDOSingleValueFeatureDeltaImpl)delta).setValue(oldValue); // Adjust delta
+ }
+
+ @Override
+ public void visit(CDOSetFeatureDelta delta)
+ {
+ EStructuralFeature feature = delta.getFeature();
+ Object value = null;
+ if (feature.isMany())
+ {
+ value = workList.set(delta.getIndex(), delta.getValue());
+ }
+ else
+ {
+ value = ((InternalCDORevision)oldRevision).getValue(feature);
+ }
+
+ ((CDOSetFeatureDeltaImpl)delta).setOldValue(value); // Adjust delta
+ }
+ };
+
+ for (CDOFeatureDelta featureDelta : revisionDelta.getFeatureDeltas())
+ {
+ featureDelta.accept(visitor);
+ }
}
@Deprecated
diff --git a/plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/spi/cdo/AbstractChangeSetsConflictResolver.java b/plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/spi/cdo/AbstractChangeSetsConflictResolver.java
index 0da5bcdc0d..20f38f0f32 100644
--- a/plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/spi/cdo/AbstractChangeSetsConflictResolver.java
+++ b/plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/spi/cdo/AbstractChangeSetsConflictResolver.java
@@ -46,7 +46,7 @@ public abstract class AbstractChangeSetsConflictResolver extends AbstractConflic
if (getTransaction() == transaction)
{
adapter.reset();
- aggregator.reset();
+ remoteInvalidationEvents.reset();
}
}
@@ -57,14 +57,14 @@ public abstract class AbstractChangeSetsConflictResolver extends AbstractConflic
if (getTransaction() == transaction && transaction.getLastSavepoint().getPreviousSavepoint() == null)
{
adapter.reset();
- aggregator.reset();
+ remoteInvalidationEvents.reset();
}
}
};
private CDOChangeSubscriptionAdapter adapter;
- private RemoteAggregator aggregator;
+ private RemoteInvalidationEventQueue remoteInvalidationEvents;
public AbstractChangeSetsConflictResolver()
{
@@ -77,19 +77,19 @@ public abstract class AbstractChangeSetsConflictResolver extends AbstractConflic
public CDOChangeSet getLocalChangeSet()
{
- CDOTransaction transaction = getTransaction();
- return CDORevisionUtil.createChangeSet(transaction, transaction, getLocalChangeSetData());
+ CDOChangeSetData changeSetData = getLocalChangeSetData();
+ return createChangeSet(changeSetData);
}
public CDOChangeSetData getRemoteChangeSetData()
{
- return aggregator.getChangeSetData();
+ return remoteInvalidationEvents.getChangeSetData();
}
public CDOChangeSet getRemoteChangeSet()
{
- CDOTransaction transaction = getTransaction();
- return CDORevisionUtil.createChangeSet(transaction, transaction, getRemoteChangeSetData());
+ CDOChangeSetData changeSetData = remoteInvalidationEvents.getChangeSetData();
+ return createChangeSet(changeSetData);
}
@Override
@@ -97,14 +97,14 @@ public abstract class AbstractChangeSetsConflictResolver extends AbstractConflic
{
transaction.addTransactionHandler(handler);
adapter = new CDOChangeSubscriptionAdapter(getTransaction());
- aggregator = new RemoteAggregator();
+ remoteInvalidationEvents = new RemoteInvalidationEventQueue();
}
@Override
protected void unhookTransaction(CDOTransaction transaction)
{
- aggregator.dispose();
- aggregator = null;
+ remoteInvalidationEvents.dispose();
+ remoteInvalidationEvents = null;
adapter.dispose();
adapter = null;
@@ -112,12 +112,18 @@ public abstract class AbstractChangeSetsConflictResolver extends AbstractConflic
transaction.removeTransactionHandler(handler);
}
+ private CDOChangeSet createChangeSet(CDOChangeSetData changeSetData)
+ {
+ CDOTransaction transaction = getTransaction();
+ return CDORevisionUtil.createChangeSet(transaction, transaction, changeSetData);
+ }
+
/**
* @author Eike Stepper
*/
- private final class RemoteAggregator extends CDOSessionInvalidationAggregator
+ private final class RemoteInvalidationEventQueue extends CDOSessionInvalidationEventQueue
{
- public RemoteAggregator()
+ public RemoteInvalidationEventQueue()
{
super(getTransaction().getSession());
}
@@ -125,10 +131,20 @@ public abstract class AbstractChangeSetsConflictResolver extends AbstractConflic
@Override
protected void handleEvent(CDOSessionInvalidationEvent event) throws Exception
{
- if (event.getBranch() == getTransaction().getBranch())
+ CDOTransaction transaction = getTransaction();
+ if (event.getLocalTransaction() == transaction)
{
- super.handleEvent(event);
+ // Don't handle own changes
+ return;
}
+
+ if (event.getBranch() != transaction.getBranch())
+ {
+ // Don't handle changes in other branches
+ return;
+ }
+
+ super.handleEvent(event);
}
}
}
diff --git a/plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/spi/cdo/CDOMergingConflictResolver.java b/plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/spi/cdo/CDOMergingConflictResolver.java
index 27964731b0..c7d3022a9b 100644
--- a/plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/spi/cdo/CDOMergingConflictResolver.java
+++ b/plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/spi/cdo/CDOMergingConflictResolver.java
@@ -15,17 +15,14 @@ import org.eclipse.emf.cdo.CDOState;
import org.eclipse.emf.cdo.common.commit.CDOChangeSet;
import org.eclipse.emf.cdo.common.commit.CDOChangeSetData;
import org.eclipse.emf.cdo.common.id.CDOID;
-import org.eclipse.emf.cdo.common.revision.CDORevision;
import org.eclipse.emf.cdo.common.revision.CDORevisionKey;
import org.eclipse.emf.cdo.common.revision.delta.CDORevisionDelta;
import org.eclipse.emf.cdo.spi.common.revision.InternalCDORevision;
import org.eclipse.emf.cdo.spi.common.revision.InternalCDORevisionDelta;
-import org.eclipse.emf.cdo.spi.common.revision.InternalCDORevisionManager;
import org.eclipse.emf.cdo.transaction.CDOMerger;
import org.eclipse.emf.cdo.transaction.CDOMerger.ConflictException;
-import org.eclipse.net4j.util.CheckUtil;
-
+import java.util.HashMap;
import java.util.Map;
import java.util.Set;
@@ -34,9 +31,7 @@ import java.util.Set;
*
* @author Eike Stepper
* @since 4.0
- * @deprecated This conflict resolver is still under development. It's not safe to use it.
*/
-@Deprecated
public class CDOMergingConflictResolver extends AbstractChangeSetsConflictResolver
{
private CDOMerger merger;
@@ -58,14 +53,13 @@ public class CDOMergingConflictResolver extends AbstractChangeSetsConflictResolv
public void resolveConflicts(Set<CDOObject> conflicts)
{
+ CDOChangeSet localChangeSet = getLocalChangeSet();
+ CDOChangeSet remoteChangeSet = getRemoteChangeSet();
CDOChangeSetData result;
try
{
- CDOChangeSet target = getLocalChangeSet();
- CDOChangeSet source = getRemoteChangeSet();
-
- result = merger.merge(target, source);
+ result = merger.merge(localChangeSet, remoteChangeSet);
}
catch (ConflictException ex)
{
@@ -73,45 +67,54 @@ public class CDOMergingConflictResolver extends AbstractChangeSetsConflictResolv
}
InternalCDOTransaction transaction = (InternalCDOTransaction)getTransaction();
- InternalCDORevisionManager revisionManager = transaction.getSession().getRevisionManager();
+ Map<InternalCDOObject, InternalCDORevision> cleanRevisions = transaction.getCleanRevisions();
+
Map<CDOID, CDORevisionDelta> localDeltas = transaction.getLastSavepoint().getRevisionDeltas2();
+ Map<CDOID, CDORevisionDelta> remoteDeltas = getRemoteDeltas(remoteChangeSet);
for (CDORevisionKey key : result.getChangedObjects())
{
- InternalCDORevisionDelta delta = (InternalCDORevisionDelta)key;
- CDOID id = delta.getID();
+ InternalCDORevisionDelta resultDelta = (InternalCDORevisionDelta)key;
+ CDOID id = resultDelta.getID();
InternalCDOObject object = (InternalCDOObject)transaction.getObject(id, false);
if (object != null)
{
- CDOState state = object.cdoState();
- if (state == CDOState.CLEAN || state == CDOState.PROXY)
- {
- InternalCDORevision revision = revisionManager.getRevision(id, transaction, CDORevision.UNCHUNKED,
- CDORevision.DEPTH_NONE, false);
- CheckUtil.checkState(revision, "revision");
-
- object.cdoInternalSetRevision(revision);
- object.cdoInternalSetState(CDOState.CLEAN);
- }
- else if (state == CDOState.CONFLICT)
- {
- int newVersion = delta.getVersion() + 1;
-
- InternalCDORevision revision = transaction.getCleanRevisions().get(object).copy();
- revision.setVersion(newVersion);
- delta.apply(revision);
-
- object.cdoInternalSetRevision(revision);
- object.cdoInternalSetState(CDOState.DIRTY);
-
- InternalCDORevisionDelta localDelta = (InternalCDORevisionDelta)localDeltas.get(id);
- localDelta.setVersion(newVersion);
- }
- else
- {
- throw new IllegalStateException("Unexpected objects state: " + state);
- }
+ // Compute new version
+ InternalCDORevision localRevision = object.cdoRevision();
+ int newVersion = localRevision.getVersion() + 1;
+
+ // Compute new local revision
+ InternalCDORevision cleanRevision = cleanRevisions.get(object);
+ InternalCDORevision newLocalRevision = cleanRevision.copy();
+ newLocalRevision.setVersion(newVersion);
+ resultDelta.apply(newLocalRevision);
+
+ object.cdoInternalSetRevision(newLocalRevision);
+ object.cdoInternalSetState(CDOState.DIRTY);
+
+ // Compute new clean revision
+ CDORevisionDelta remoteDelta = remoteDeltas.get(id);
+ InternalCDORevision newCleanRevision = cleanRevision.copy();
+ newCleanRevision.setVersion(newVersion);
+ remoteDelta.apply(newCleanRevision);
+ cleanRevisions.put(object, newCleanRevision);
+
+ // Compute new local delta
+ InternalCDORevisionDelta newLocalDelta = newLocalRevision.compare(newCleanRevision);
+ newLocalDelta.setTarget(null);
+ localDeltas.put(id, newLocalDelta);
}
}
}
+
+ private Map<CDOID, CDORevisionDelta> getRemoteDeltas(CDOChangeSet remoteChangeSet)
+ {
+ Map<CDOID, CDORevisionDelta> remoteDeltas = new HashMap<CDOID, CDORevisionDelta>();
+ for (CDORevisionKey key : remoteChangeSet.getChangedObjects())
+ {
+ remoteDeltas.put(key.getID(), (CDORevisionDelta)key);
+ }
+
+ return remoteDeltas;
+ }
}
diff --git a/plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/spi/cdo/CDOSessionInvalidationAggregator.java b/plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/spi/cdo/CDOSessionInvalidationAggregator.java
index 5be7dd7967..70c701c560 100644
--- a/plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/spi/cdo/CDOSessionInvalidationAggregator.java
+++ b/plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/spi/cdo/CDOSessionInvalidationAggregator.java
@@ -10,86 +10,22 @@
*/
package org.eclipse.emf.spi.cdo;
-import org.eclipse.emf.cdo.common.commit.CDOChangeSetData;
import org.eclipse.emf.cdo.session.CDOSession;
-import org.eclipse.emf.cdo.session.CDOSessionInvalidationEvent;
-
-import org.eclipse.emf.internal.cdo.bundle.OM;
-
-import org.eclipse.net4j.util.event.IEvent;
-import org.eclipse.net4j.util.event.IListener;
/**
* If the meaning of this type isn't clear, there really should be more of a description here...
*
* @author Eike Stepper
* @since 4.0
+ * @deprecated As of 4.2 use {@link CDOSessionInvalidationEventQueue}.
* @noextend This interface is not intended to be extended by clients.
* @noinstantiate This class is not intended to be instantiated by clients.
*/
-public class CDOSessionInvalidationAggregator
+@Deprecated
+public class CDOSessionInvalidationAggregator extends CDOSessionInvalidationEventQueue
{
- private CDOSession session;
-
- private IListener sessionListener = new IListener()
- {
- public void notifyEvent(IEvent event)
- {
- try
- {
- if (event instanceof CDOSessionInvalidationEvent)
- {
- CDOSessionInvalidationEvent e = (CDOSessionInvalidationEvent)event;
- handleEvent(e);
- }
- }
- catch (Exception ex)
- {
- OM.LOG.error(ex);
- }
- }
- };
-
- private CDOChangeSetData changeSetData;
-
public CDOSessionInvalidationAggregator(CDOSession session)
{
- this.session = session;
- session.addListener(sessionListener);
- }
-
- public void dispose()
- {
- reset();
- session.removeListener(sessionListener);
- session = null;
- }
-
- public CDOSession getSession()
- {
- return session;
- }
-
- public CDOChangeSetData getChangeSetData()
- {
- return changeSetData;
- }
-
- public void reset()
- {
- changeSetData = null;
- }
-
- protected void handleEvent(CDOSessionInvalidationEvent event) throws Exception
- {
- CDOChangeSetData copy = event.copy();
- if (changeSetData == null)
- {
- changeSetData = copy;
- }
- else
- {
- changeSetData.merge(copy);
- }
+ super(session);
}
}
diff --git a/plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/spi/cdo/CDOSessionInvalidationEventQueue.java b/plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/spi/cdo/CDOSessionInvalidationEventQueue.java
new file mode 100644
index 0000000000..2690bd9c64
--- /dev/null
+++ b/plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/spi/cdo/CDOSessionInvalidationEventQueue.java
@@ -0,0 +1,93 @@
+/*
+ * Copyright (c) 2004 - 2012 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.spi.cdo;
+
+import org.eclipse.emf.cdo.common.commit.CDOChangeSetData;
+import org.eclipse.emf.cdo.session.CDOSession;
+import org.eclipse.emf.cdo.session.CDOSessionInvalidationEvent;
+
+import org.eclipse.emf.internal.cdo.bundle.OM;
+
+import org.eclipse.net4j.util.event.IEvent;
+import org.eclipse.net4j.util.event.IListener;
+
+import java.util.Queue;
+import java.util.concurrent.ConcurrentLinkedQueue;
+
+/**
+ * If the meaning of this type isn't clear, there really should be more of a description here...
+ *
+ * @author Eike Stepper
+ * @since 4.2
+ * @noextend This interface is not intended to be extended by clients.
+ * @noinstantiate This class is not intended to be instantiated by clients.
+ */
+public class CDOSessionInvalidationEventQueue
+{
+ private CDOSession session;
+
+ private IListener sessionListener = new IListener()
+ {
+ public void notifyEvent(IEvent event)
+ {
+ try
+ {
+ if (event instanceof CDOSessionInvalidationEvent)
+ {
+ CDOSessionInvalidationEvent e = (CDOSessionInvalidationEvent)event;
+ handleEvent(e);
+ }
+ }
+ catch (Exception ex)
+ {
+ OM.LOG.error(ex);
+ }
+ }
+ };
+
+ private Queue<CDOChangeSetData> queue = new ConcurrentLinkedQueue<CDOChangeSetData>();
+
+ public CDOSessionInvalidationEventQueue(CDOSession session)
+ {
+ this.session = session;
+ session.addListener(sessionListener);
+ }
+
+ public void dispose()
+ {
+ reset();
+ session.removeListener(sessionListener);
+ session = null;
+ }
+
+ public CDOSession getSession()
+ {
+ return session;
+ }
+
+ /**
+ * Removes and returns the first event from this queue.
+ */
+ public CDOChangeSetData getChangeSetData()
+ {
+ return queue.poll();
+ }
+
+ public void reset()
+ {
+ queue.clear();
+ }
+
+ protected void handleEvent(CDOSessionInvalidationEvent event) throws Exception
+ {
+ queue.offer(event);
+ }
+}

Back to the top