diff options
author | Eike Stepper | 2008-12-13 21:29:44 +0000 |
---|---|---|
committer | Eike Stepper | 2008-12-13 21:29:44 +0000 |
commit | 9f42414414409ee0af9b16b53d63255f2c7a2a51 (patch) | |
tree | 53577f51a7680a68e18798ef06240133f8a9db65 /plugins/org.eclipse.emf.cdo | |
parent | 6b56bd26a06e71265f8e8434981c5f31f13e05e6 (diff) | |
download | cdo-9f42414414409ee0af9b16b53d63255f2c7a2a51.tar.gz cdo-9f42414414409ee0af9b16b53d63255f2c7a2a51.tar.xz cdo-9f42414414409ee0af9b16b53d63255f2c7a2a51.zip |
[257372] Handle conflict object without rollback the view completely
https://bugs.eclipse.org/bugs/show_bug.cgi?id=257372
Diffstat (limited to 'plugins/org.eclipse.emf.cdo')
7 files changed, 137 insertions, 68 deletions
diff --git a/plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/cdo/CDOConflictResolver.java b/plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/cdo/CDOConflictResolver.java index 61e032cabc..060e1f5028 100644 --- a/plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/cdo/CDOConflictResolver.java +++ b/plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/cdo/CDOConflictResolver.java @@ -35,9 +35,6 @@ public interface CDOConflictResolver * Resolves conflicts after remote invalidations arrived for objects that are locally dirty or detached. * <p> * The implementor might want to use/extend {@link ObjectConflictResolver}. - * <p> - * <b>Important:</b> Those conflicts that are resolved by the implementation of this method <b>must</b> be removed - * from the passed set of conflicts! */ public void resolveConflicts(CDOTransaction transaction, Set<CDOObject> conflicts); } diff --git a/plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/cdo/CDOTransaction.java b/plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/cdo/CDOTransaction.java index 1ad7af3165..5b5d8d3961 100644 --- a/plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/cdo/CDOTransaction.java +++ b/plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/cdo/CDOTransaction.java @@ -23,6 +23,7 @@ import org.eclipse.emf.ecore.EClass; import org.eclipse.emf.ecore.resource.ResourceSet; import java.util.Map; +import java.util.Set; /** * A read-write view to the <em>current</em> (i.e. latest) state of the object graph in the repository. @@ -53,6 +54,16 @@ public interface CDOTransaction extends CDOView, CDOUserTransaction public boolean hasConflict(); /** + * @since 2.0 + */ + public Set<CDOObject> getConflicts(); + + /** + * @since 2.0 + */ + public void resolveConflicts(CDOConflictResolver resolver); + + /** * @see ResourceSet#createResource(URI) */ public CDOResource createResource(String path); diff --git a/plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/internal/cdo/CDOTransactionImpl.java b/plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/internal/cdo/CDOTransactionImpl.java index e1e76d2d6d..b2782e5b2f 100644 --- a/plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/internal/cdo/CDOTransactionImpl.java +++ b/plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/internal/cdo/CDOTransactionImpl.java @@ -50,6 +50,7 @@ import org.eclipse.emf.internal.cdo.util.ModelUtil; import org.eclipse.net4j.util.ImplementationError; import org.eclipse.net4j.util.ObjectUtil; +import org.eclipse.net4j.util.WrappedException; import org.eclipse.net4j.util.event.Notifier; import org.eclipse.net4j.util.om.trace.ContextTracer; import org.eclipse.net4j.util.transaction.TransactionException; @@ -65,6 +66,7 @@ import java.util.ArrayList; import java.util.Collection; import java.util.Collections; import java.util.HashSet; +import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.Set; @@ -88,7 +90,7 @@ public class CDOTransactionImpl extends CDOViewImpl implements InternalCDOTransa private boolean dirty; - private boolean conflict; + private int conflict; private CDOConflictResolver conflictResolver; @@ -161,19 +163,53 @@ public class CDOTransactionImpl extends CDOViewImpl implements InternalCDOTransa public boolean hasConflict() { checkOpen(); - return conflict; + return conflict != 0; } public void setConflict(InternalCDOObject object) { - ConflictEvent event = new ConflictEvent(object, !conflict); - conflict = true; + ConflictEvent event = new ConflictEvent(object, conflict == 0); + ++conflict; fireEvent(event); } /** * @since 2.0 */ + public Set<CDOObject> getConflicts() + { + Set<CDOObject> conflicts = new HashSet<CDOObject>(); + for (CDOObject object : getDirtyObjects().values()) + { + if (FSMUtil.isConflict(object)) + { + conflicts.add(object); + } + } + + for (CDOObject object : getDetachedObjects().values()) + { + if (FSMUtil.isConflict(object)) + { + conflicts.add(object); + } + } + + return conflicts; + } + + /** + * @since 2.0 + */ + public void resolveConflicts(CDOConflictResolver resolver) + { + Set<CDOObject> conflicts = getConflicts(); + handleConflicts(conflicts, resolver); + } + + /** + * @since 2.0 + */ public synchronized CDOConflictResolver getConflictResolver() { if (conflictResolver == null) @@ -203,10 +239,42 @@ public class CDOTransactionImpl extends CDOViewImpl implements InternalCDOTransa @Override protected void handleConflicts(Set<CDOObject> conflicts) { - getConflictResolver().resolveConflicts(this, conflicts); - if (conflicts.isEmpty()) + handleConflicts(conflicts, getConflictResolver()); + } + + private void handleConflicts(Set<CDOObject> conflicts, CDOConflictResolver resolver) + { + List<CDOState> states = new ArrayList<CDOState>(conflicts.size()); + List<CDORevision> revisions = new ArrayList<CDORevision>(conflicts.size()); + for (CDOObject conflict : conflicts) + { + states.add(conflict.cdoState()); + revisions.add(conflict.cdoRevision()); + } + + try + { + resolver.resolveConflicts(this, Collections.unmodifiableSet(conflicts)); + } + catch (Exception ex) + { + Iterator<CDOState> state = states.iterator(); + Iterator<CDORevision> revision = revisions.iterator(); + for (CDOObject object : conflicts) + { + ((InternalCDOObject)object).cdoInternalSetState(state.next()); + ((InternalCDOObject)object).cdoInternalSetRevision(revision.next()); + } + + throw WrappedException.wrap(ex); + } + + for (CDOObject object : conflicts) { - conflict = false; + if (!FSMUtil.isConflict(object)) + { + --conflict; + } } } @@ -1030,7 +1098,7 @@ public class CDOTransactionImpl extends CDOViewImpl implements InternalCDOTransa firstSavepoint.setNextSavepoint(null); firstSavepoint.getSharedDetachedObjects().clear(); dirty = false; - conflict = false; + conflict = 0; lastTemporaryID = 0; } diff --git a/plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/internal/cdo/CDOViewImpl.java b/plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/internal/cdo/CDOViewImpl.java index 1797aa7044..8d01324b0e 100644 --- a/plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/internal/cdo/CDOViewImpl.java +++ b/plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/internal/cdo/CDOViewImpl.java @@ -1187,7 +1187,7 @@ public class CDOViewImpl extends org.eclipse.net4j.util.event.Notifier implement { CDOStateMachine.INSTANCE.invalidate(dirtyObject, dirtyOID.getVersion()); dirtyObjects.add(dirtyObject); - if (dirtyObject.cdoState() == CDOState.CONFLICT) + if (FSMUtil.isConflict(dirtyObject)) { if (conflicts == null) { @@ -1207,7 +1207,7 @@ public class CDOViewImpl extends org.eclipse.net4j.util.event.Notifier implement { CDOStateMachine.INSTANCE.detachRemote(detachedObject); detachedObjects.add(detachedObject); - if (detachedObject.cdoState() == CDOState.INVALID_CONFLICT) + if (FSMUtil.isConflict(detachedObject)) { if (conflicts == null) { 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 c51d3df97e..1e30fb82e4 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 @@ -57,6 +57,12 @@ public final class FSMUtil return state == CDOState.INVALID || state == CDOState.INVALID_CONFLICT; } + public static boolean isConflict(CDOObject object) + { + CDOState state = object.cdoState(); + return state == CDOState.CONFLICT || state == CDOState.INVALID_CONFLICT; + } + public static boolean isNew(CDOObject object) { CDOState state = object.cdoState(); diff --git a/plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/spi/cdo/ObjectConflictResolver.java b/plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/spi/cdo/ObjectConflictResolver.java index 885022c68c..ab32787473 100644 --- a/plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/spi/cdo/ObjectConflictResolver.java +++ b/plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/spi/cdo/ObjectConflictResolver.java @@ -14,13 +14,15 @@ import org.eclipse.emf.cdo.CDOConflictResolver; import org.eclipse.emf.cdo.CDOObject; import org.eclipse.emf.cdo.CDOTransaction; import org.eclipse.emf.cdo.common.id.CDOID; -import org.eclipse.emf.cdo.common.revision.delta.CDOFeatureDelta; import org.eclipse.emf.cdo.common.revision.delta.CDORevisionDelta; +import org.eclipse.emf.cdo.internal.common.revision.delta.CDORevisionMerger; +import org.eclipse.emf.cdo.spi.common.InternalCDORevision; +import org.eclipse.emf.cdo.spi.common.InternalCDORevisionDelta; +import org.eclipse.emf.internal.cdo.CDOObjectMerger; import org.eclipse.emf.internal.cdo.CDOStateMachine; import org.eclipse.emf.internal.cdo.InternalCDOObject; -import java.util.Iterator; import java.util.Map; import java.util.Set; @@ -30,6 +32,8 @@ import java.util.Set; */ public abstract class ObjectConflictResolver implements CDOConflictResolver { + public static final CDORevisionMerger REVISION_MERGER = new CDORevisionMerger(); + public ObjectConflictResolver() { } @@ -37,39 +41,59 @@ public abstract class ObjectConflictResolver implements CDOConflictResolver public void resolveConflicts(CDOTransaction transaction, Set<CDOObject> conflicts) { Map<CDOID, CDORevisionDelta> revisionDeltas = transaction.getRevisionDeltas(); - for (Iterator<CDOObject> it = conflicts.iterator(); it.hasNext();) + for (CDOObject conflict : conflicts) { - CDOObject conflict = it.next(); CDORevisionDelta revisionDelta = revisionDeltas.get(conflict.cdoID()); - if (resolveConflict(transaction, conflict, revisionDelta)) - { - it.remove(); - } + resolveConflict(transaction, conflict, revisionDelta); } } /** - * Resolves the conflict of a single object in the current transaction and returns <code>true</code> if successful, - * <code>false</code> otherwise. + * Resolves the conflict of a single object in the current transaction. */ - protected abstract boolean resolveConflict(CDOTransaction transaction, CDOObject conflict, - CDORevisionDelta revisionDelta); + protected abstract void resolveConflict(CDOTransaction transaction, CDOObject conflict, CDORevisionDelta revisionDelta); public static void rollbackObject(CDOObject object) { CDOStateMachine.INSTANCE.rollback((InternalCDOObject)object); } + /** + * TODO See {@link CDOObjectMerger}!!! + */ public static void changeObject(CDOObject object, CDORevisionDelta revisionDelta) { - for (CDOFeatureDelta featureDelta : revisionDelta.getFeatureDeltas()) - { - changeObject(object, featureDelta); - } + CDOStateMachine.INSTANCE.read((InternalCDOObject)object); + + InternalCDORevision revision = (InternalCDORevision)object.cdoRevision().copy(); + int originVersion = revision.getVersion(); + revision.setTransactional(); + + ((InternalCDORevisionDelta)revisionDelta).setOriginVersion(originVersion); + ((InternalCDORevisionDelta)revisionDelta).setDirtyVersion(revision.getVersion()); + + REVISION_MERGER.merge(revision, revisionDelta); + ((InternalCDOObject)object).cdoInternalSetRevision(revision); } - public static void changeObject(CDOObject object, CDOFeatureDelta featureDelta) + /** + * A conflict resolver implementation that takes all the new remote state of the conflicting objects and then applies + * the locally existing changes of the current transaction. + * + * @author Eike Stepper + * @since 2.0 + */ + public static class TakeRemoteChangesThenApplyLocalChanges extends ObjectConflictResolver { - CDOStateMachine.INSTANCE.write((InternalCDOObject)object, featureDelta); + public TakeRemoteChangesThenApplyLocalChanges() + { + } + + @Override + protected void resolveConflict(CDOTransaction transaction, CDOObject conflict, CDORevisionDelta revisionDelta) + { + rollbackObject(conflict); + changeObject(conflict, revisionDelta); + } } } diff --git a/plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/spi/cdo/TakeRemoteChangesAndReApplyLocalChangesConflictResolver.java b/plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/spi/cdo/TakeRemoteChangesAndReApplyLocalChangesConflictResolver.java deleted file mode 100644 index e7bfe7251d..0000000000 --- a/plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/spi/cdo/TakeRemoteChangesAndReApplyLocalChangesConflictResolver.java +++ /dev/null @@ -1,37 +0,0 @@ -/*************************************************************************** - * Copyright (c) 2004 - 2008 Eike Stepper, Germany. - * 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.CDOObject; -import org.eclipse.emf.cdo.CDOTransaction; -import org.eclipse.emf.cdo.common.revision.delta.CDORevisionDelta; - -/** - * A conflict resolver implementation that takes all the new remote state of the conflicting objects and then applies - * the locally existing changes of the current transaction. - * - * @author Eike Stepper - * @since 2.0 - */ -public class TakeRemoteChangesAndReApplyLocalChangesConflictResolver extends ObjectConflictResolver -{ - public TakeRemoteChangesAndReApplyLocalChangesConflictResolver() - { - } - - @Override - protected boolean resolveConflict(CDOTransaction transaction, CDOObject conflict, CDORevisionDelta revisionDelta) - { - rollbackObject(conflict); - changeObject(conflict, revisionDelta); - return true; - } -} |