diff options
26 files changed, 618 insertions, 146 deletions
diff --git a/plugins/org.eclipse.emf.cdo.common/src/org/eclipse/emf/cdo/common/protocol/CDOProtocolConstants.java b/plugins/org.eclipse.emf.cdo.common/src/org/eclipse/emf/cdo/common/protocol/CDOProtocolConstants.java index f7cd89d62b..ee540b9266 100644 --- a/plugins/org.eclipse.emf.cdo.common/src/org/eclipse/emf/cdo/common/protocol/CDOProtocolConstants.java +++ b/plugins/org.eclipse.emf.cdo.common/src/org/eclipse/emf/cdo/common/protocol/CDOProtocolConstants.java @@ -339,4 +339,29 @@ public interface CDOProtocolConstants * @since 4.1 */ public static final byte REPLICATE_LOCKAREA = 3; + + /** + * @since 4.2 + */ + public static final byte ROLLBACK_REASON_UNKNOWN = 0; + + /** + * @since 4.2 + */ + public static final byte ROLLBACK_REASON_IMPLICIT_LOCKING = 1; + + /** + * @since 4.2 + */ + public static final byte ROLLBACK_REASON_COMMIT_CONFLICT = 2; + + /** + * @since 4.2 + */ + public static final byte ROLLBACK_REASON_CONTAINMENT_CYCLE = 3; + + /** + * @since 4.2 + */ + public static final byte ROLLBACK_REASON_REFERENTIAL_INTEGRITY = 4; } diff --git a/plugins/org.eclipse.emf.cdo.net4j/src/org/eclipse/emf/cdo/internal/net4j/protocol/CommitTransactionRequest.java b/plugins/org.eclipse.emf.cdo.net4j/src/org/eclipse/emf/cdo/internal/net4j/protocol/CommitTransactionRequest.java index 6c8faade1d..d983875b3b 100644 --- a/plugins/org.eclipse.emf.cdo.net4j/src/org/eclipse/emf/cdo/internal/net4j/protocol/CommitTransactionRequest.java +++ b/plugins/org.eclipse.emf.cdo.net4j/src/org/eclipse/emf/cdo/internal/net4j/protocol/CommitTransactionRequest.java @@ -304,8 +304,8 @@ public class CommitTransactionRequest extends CDOClientRequestWithMonitoring<Com boolean success = in.readBoolean(); if (!success) { + byte rollbackReason = in.readByte(); String rollbackMessage = in.readString(); - OM.LOG.error(rollbackMessage); CDOBranchPoint branchPoint = in.readCDOBranchPoint(); long previousTimeStamp = in.readLong(); @@ -322,8 +322,8 @@ public class CommitTransactionRequest extends CDOClientRequestWithMonitoring<Com } } - return new CommitTransactionResult(idProvider, rollbackMessage, branchPoint, previousTimeStamp, xRefs, - clearResourcePathCache); + return new CommitTransactionResult(idProvider, rollbackReason, rollbackMessage, branchPoint, previousTimeStamp, + xRefs, clearResourcePathCache); } return null; diff --git a/plugins/org.eclipse.emf.cdo.server.hibernate/src/org/eclipse/emf/cdo/server/internal/hibernate/HibernateRawCommitContext.java b/plugins/org.eclipse.emf.cdo.server.hibernate/src/org/eclipse/emf/cdo/server/internal/hibernate/HibernateRawCommitContext.java index 0a0e4f6cd4..0b9dfadc51 100644 --- a/plugins/org.eclipse.emf.cdo.server.hibernate/src/org/eclipse/emf/cdo/server/internal/hibernate/HibernateRawCommitContext.java +++ b/plugins/org.eclipse.emf.cdo.server.hibernate/src/org/eclipse/emf/cdo/server/internal/hibernate/HibernateRawCommitContext.java @@ -18,6 +18,7 @@ import org.eclipse.emf.cdo.common.id.CDOID; import org.eclipse.emf.cdo.common.id.CDOIDReference; import org.eclipse.emf.cdo.common.id.CDOIDUtil; import org.eclipse.emf.cdo.common.lock.CDOLockState; +import org.eclipse.emf.cdo.common.protocol.CDOProtocolConstants; import org.eclipse.emf.cdo.common.revision.CDORevision; import org.eclipse.emf.cdo.server.IView; import org.eclipse.emf.cdo.spi.common.model.InternalCDOPackageRegistry; @@ -212,6 +213,11 @@ public class HibernateRawCommitContext implements InternalCommitContext return null; } + public byte getRollbackReason() + { + return CDOProtocolConstants.ROLLBACK_REASON_UNKNOWN; + } + public String getRollbackMessage() { return null; diff --git a/plugins/org.eclipse.emf.cdo.server.net4j/src/org/eclipse/emf/cdo/server/internal/net4j/protocol/CommitTransactionIndication.java b/plugins/org.eclipse.emf.cdo.server.net4j/src/org/eclipse/emf/cdo/server/internal/net4j/protocol/CommitTransactionIndication.java index 5f214fb169..b54ce5e022 100644 --- a/plugins/org.eclipse.emf.cdo.server.net4j/src/org/eclipse/emf/cdo/server/internal/net4j/protocol/CommitTransactionIndication.java +++ b/plugins/org.eclipse.emf.cdo.server.net4j/src/org/eclipse/emf/cdo/server/internal/net4j/protocol/CommitTransactionIndication.java @@ -322,7 +322,11 @@ public class CommitTransactionIndication extends CDOServerIndicationWithMonitori try { - success = respondingException(out, commitContext.getRollbackMessage(), commitContext.getXRefs()); + byte rollbackReason = commitContext.getRollbackReason(); + String rollbackMessage = commitContext.getRollbackMessage(); + List<CDOIDReference> xRefs = commitContext.getXRefs(); + + success = respondingException(out, rollbackReason, rollbackMessage, xRefs); if (success) { respondingResult(out); @@ -336,13 +340,14 @@ public class CommitTransactionIndication extends CDOServerIndicationWithMonitori } } - protected boolean respondingException(CDODataOutput out, String rollbackMessage, List<CDOIDReference> xRefs) - throws Exception + protected boolean respondingException(CDODataOutput out, byte rollbackReason, String rollbackMessage, + List<CDOIDReference> xRefs) throws Exception { boolean success = rollbackMessage == null; out.writeBoolean(success); if (!success) { + out.writeByte(rollbackReason); out.writeString(rollbackMessage); out.writeCDOBranchPoint(commitContext.getBranchPoint()); out.writeLong(commitContext.getPreviousTimeStamp()); diff --git a/plugins/org.eclipse.emf.cdo.server.net4j/src/org/eclipse/emf/cdo/server/internal/net4j/protocol/CommitXATransactionCancelIndication.java b/plugins/org.eclipse.emf.cdo.server.net4j/src/org/eclipse/emf/cdo/server/internal/net4j/protocol/CommitXATransactionCancelIndication.java index f05e687185..a1a30864f0 100644 --- a/plugins/org.eclipse.emf.cdo.server.net4j/src/org/eclipse/emf/cdo/server/internal/net4j/protocol/CommitXATransactionCancelIndication.java +++ b/plugins/org.eclipse.emf.cdo.server.net4j/src/org/eclipse/emf/cdo/server/internal/net4j/protocol/CommitXATransactionCancelIndication.java @@ -37,6 +37,7 @@ public class CommitXATransactionCancelIndication extends CommitTransactionIndica protected void responding(CDODataOutput out, OMMonitor monitor) throws Exception { String exceptionMessage = null; + try { if (commitContext != null) @@ -54,7 +55,7 @@ public class CommitXATransactionCancelIndication extends CommitTransactionIndica exceptionMessage = commitContext.getRollbackMessage(); } - respondingException(out, exceptionMessage, null); + respondingException(out, CDOProtocolConstants.ROLLBACK_REASON_UNKNOWN, exceptionMessage, null); } @Override diff --git a/plugins/org.eclipse.emf.cdo.server.net4j/src/org/eclipse/emf/cdo/server/internal/net4j/protocol/CommitXATransactionPhase1Indication.java b/plugins/org.eclipse.emf.cdo.server.net4j/src/org/eclipse/emf/cdo/server/internal/net4j/protocol/CommitXATransactionPhase1Indication.java index 817cd348c1..f70b26ced3 100644 --- a/plugins/org.eclipse.emf.cdo.server.net4j/src/org/eclipse/emf/cdo/server/internal/net4j/protocol/CommitXATransactionPhase1Indication.java +++ b/plugins/org.eclipse.emf.cdo.server.net4j/src/org/eclipse/emf/cdo/server/internal/net4j/protocol/CommitXATransactionPhase1Indication.java @@ -63,7 +63,7 @@ public class CommitXATransactionPhase1Indication extends CommitTransactionIndica exceptionMessage = commitContext.getRollbackMessage(); } - boolean success = respondingException(out, exceptionMessage, null); + boolean success = respondingException(out, CDOProtocolConstants.ROLLBACK_REASON_UNKNOWN, exceptionMessage, null); if (success) { respondingResult(out); diff --git a/plugins/org.eclipse.emf.cdo.server.net4j/src/org/eclipse/emf/cdo/server/internal/net4j/protocol/CommitXATransactionPhase2Indication.java b/plugins/org.eclipse.emf.cdo.server.net4j/src/org/eclipse/emf/cdo/server/internal/net4j/protocol/CommitXATransactionPhase2Indication.java index a0400b5c60..caaf0e7e84 100644 --- a/plugins/org.eclipse.emf.cdo.server.net4j/src/org/eclipse/emf/cdo/server/internal/net4j/protocol/CommitXATransactionPhase2Indication.java +++ b/plugins/org.eclipse.emf.cdo.server.net4j/src/org/eclipse/emf/cdo/server/internal/net4j/protocol/CommitXATransactionPhase2Indication.java @@ -86,7 +86,7 @@ public class CommitXATransactionPhase2Indication extends CommitTransactionIndica exceptionMessage = commitContext.getRollbackMessage(); } - respondingException(out, exceptionMessage, null); + respondingException(out, CDOProtocolConstants.ROLLBACK_REASON_UNKNOWN, exceptionMessage, null); } @Override diff --git a/plugins/org.eclipse.emf.cdo.server.net4j/src/org/eclipse/emf/cdo/server/internal/net4j/protocol/CommitXATransactionPhase3Indication.java b/plugins/org.eclipse.emf.cdo.server.net4j/src/org/eclipse/emf/cdo/server/internal/net4j/protocol/CommitXATransactionPhase3Indication.java index eed8b06f3c..1db1d6ade2 100644 --- a/plugins/org.eclipse.emf.cdo.server.net4j/src/org/eclipse/emf/cdo/server/internal/net4j/protocol/CommitXATransactionPhase3Indication.java +++ b/plugins/org.eclipse.emf.cdo.server.net4j/src/org/eclipse/emf/cdo/server/internal/net4j/protocol/CommitXATransactionPhase3Indication.java @@ -37,7 +37,8 @@ public class CommitXATransactionPhase3Indication extends CommitTransactionIndica protected void responding(CDODataOutput out, OMMonitor monitor) throws Exception { commitContext.commit(monitor); - boolean success = respondingException(out, commitContext.getRollbackMessage(), null); + boolean success = respondingException(out, CDOProtocolConstants.ROLLBACK_REASON_UNKNOWN, + commitContext.getRollbackMessage(), null); commitContext.postCommit(success); } diff --git a/plugins/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/internal/server/DelegatingCommitContext.java b/plugins/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/internal/server/DelegatingCommitContext.java index fa50bd97dc..0b7c6dc2f1 100644 --- a/plugins/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/internal/server/DelegatingCommitContext.java +++ b/plugins/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/internal/server/DelegatingCommitContext.java @@ -11,18 +11,27 @@ package org.eclipse.emf.cdo.internal.server; import org.eclipse.emf.cdo.common.branch.CDOBranchPoint; +import org.eclipse.emf.cdo.common.branch.CDOBranchVersion; +import org.eclipse.emf.cdo.common.commit.CDOCommitInfo; import org.eclipse.emf.cdo.common.id.CDOID; +import org.eclipse.emf.cdo.common.id.CDOIDReference; +import org.eclipse.emf.cdo.common.lock.CDOLockState; import org.eclipse.emf.cdo.common.revision.CDORevision; import org.eclipse.emf.cdo.server.IStoreAccessor; import org.eclipse.emf.cdo.server.IStoreAccessor.CommitContext; import org.eclipse.emf.cdo.server.ITransaction; +import org.eclipse.emf.cdo.server.IView; import org.eclipse.emf.cdo.spi.common.model.InternalCDOPackageRegistry; 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.net4j.util.concurrent.RWOLockManager.LockState; +import org.eclipse.net4j.util.io.ExtendedDataInputStream; + import org.eclipse.emf.ecore.EClass; +import java.util.List; import java.util.Map; /** @@ -102,8 +111,68 @@ public abstract class DelegatingCommitContext implements IStoreAccessor.CommitCo return getDelegate().getIDMappings(); } + public long getPreviousTimeStamp() + { + return getDelegate().getPreviousTimeStamp(); + } + + public long getLastUpdateTime() + { + return getDelegate().getLastUpdateTime(); + } + + public boolean isClearResourcePathCache() + { + return getDelegate().isClearResourcePathCache(); + } + + public boolean isUsingEcore() + { + return getDelegate().isUsingEcore(); + } + + public boolean isUsingEtypes() + { + return getDelegate().isUsingEtypes(); + } + + public CDOLockState[] getLocksOnNewObjects() + { + return getDelegate().getLocksOnNewObjects(); + } + + public CDOBranchVersion[] getDetachedObjectVersions() + { + return getDelegate().getDetachedObjectVersions(); + } + + public ExtendedDataInputStream getLobs() + { + return getDelegate().getLobs(); + } + + public CDOCommitInfo createCommitInfo() + { + return getDelegate().createCommitInfo(); + } + + public List<LockState<Object, IView>> getPostCommmitLockStates() + { + return getDelegate().getPostCommmitLockStates(); + } + + public byte getRollbackReason() + { + return getDelegate().getRollbackReason(); + } + public String getRollbackMessage() { return getDelegate().getRollbackMessage(); } + + public List<CDOIDReference> getXRefs() + { + return getDelegate().getXRefs(); + } } diff --git a/plugins/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/internal/server/TransactionCommitContext.java b/plugins/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/internal/server/TransactionCommitContext.java index 4663bf0f89..e89ce792fb 100644 --- a/plugins/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/internal/server/TransactionCommitContext.java +++ b/plugins/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/internal/server/TransactionCommitContext.java @@ -28,6 +28,7 @@ import org.eclipse.emf.cdo.common.lock.CDOLockOwner; import org.eclipse.emf.cdo.common.lock.CDOLockState; import org.eclipse.emf.cdo.common.lock.CDOLockUtil; import org.eclipse.emf.cdo.common.model.CDOPackageUnit; +import org.eclipse.emf.cdo.common.protocol.CDOProtocolConstants; import org.eclipse.emf.cdo.common.revision.CDOIDAndBranch; import org.eclipse.emf.cdo.common.revision.CDOIDAndVersion; import org.eclipse.emf.cdo.common.revision.CDORevision; @@ -44,7 +45,6 @@ import org.eclipse.emf.cdo.common.util.CDOQueryInfo; import org.eclipse.emf.cdo.internal.common.commit.FailureCommitInfo; import org.eclipse.emf.cdo.internal.common.model.CDOPackageRegistryImpl; import org.eclipse.emf.cdo.internal.server.bundle.OM; -import org.eclipse.emf.cdo.server.ContainmentCycleDetectedException; import org.eclipse.emf.cdo.server.IStoreAccessor; import org.eclipse.emf.cdo.server.IStoreAccessor.QueryXRefsContext; import org.eclipse.emf.cdo.server.IView; @@ -89,7 +89,6 @@ import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; import java.util.Collections; -import java.util.ConcurrentModificationException; import java.util.HashMap; import java.util.HashSet; import java.util.List; @@ -164,6 +163,8 @@ public class TransactionCommitContext implements InternalCommitContext private CDOReferenceAdjuster idMapper = new CDOIDMapper(idMappings); + private byte rollbackReason = CDOProtocolConstants.ROLLBACK_REASON_UNKNOWN; + private String rollbackMessage; private List<CDOIDReference> xRefs; @@ -223,6 +224,11 @@ public class TransactionCommitContext implements InternalCommitContext return autoReleaseLocksEnabled; } + public byte getRollbackReason() + { + return rollbackReason; + } + public String getRollbackMessage() { return rollbackMessage; @@ -414,6 +420,32 @@ public class TransactionCommitContext implements InternalCommitContext } } + private void applyIDMappings(InternalCDORevision[] revisions, OMMonitor monitor) + { + try + { + monitor.begin(revisions.length); + for (InternalCDORevision revision : revisions) + { + if (revision != null) + { + CDOID newID = idMappings.get(revision.getID()); + if (newID != null) + { + revision.setID(newID); + } + + revision.adjustReferences(idMapper); + monitor.worked(); + } + } + } + finally + { + monitor.done(); + } + } + protected void notifyBeforeCommitting(OMMonitor monitor) { repository.notifyWriteAccessHandlers(transaction, this, true, monitor.fork()); @@ -573,11 +605,13 @@ public class TransactionCommitContext implements InternalCommitContext checkXRefs(); monitor.worked(); - if (rollbackMessage == null) - { - detachObjects(monitor.fork()); - accessor.write(this, monitor.fork(100)); - } + detachObjects(monitor.fork()); + accessor.write(this, monitor.fork(100)); + } + catch (RollbackException ex) + { + rollbackReason = ex.getRollbackReason(); + rollback(ex.getRollbackMessage()); } catch (Throwable t) { @@ -890,9 +924,16 @@ public class TransactionCommitContext implements InternalCommitContext if (!lockedObjects.isEmpty()) { - // First lock all objects (incl. possible ref targets). - // This is a transient operation, it does not check for existance! - lockManager.lock2(LockType.WRITE, transaction, lockedObjects, 10000); + try + { + // First lock all objects (incl. possible ref targets). + // This is a transient operation, it does not check for existance! + lockManager.lock2(LockType.WRITE, transaction, lockedObjects, 10000); + } + catch (Exception ex) + { + throw new RollbackException(CDOProtocolConstants.ROLLBACK_REASON_IMPLICIT_LOCKING, ex); + } // If all locks could be acquired, check if locked targets do still exist if (lockedTargets != null) @@ -902,8 +943,8 @@ public class TransactionCommitContext implements InternalCommitContext CDORevision revision = transaction.getRevision(id); if (revision == null || revision instanceof DetachedCDORevision) { - throw new IllegalStateException("Object " + id - + " can not be referenced anymore because it has been detached"); + throw new RollbackException(CDOProtocolConstants.ROLLBACK_REASON_REFERENTIAL_INTEGRITY, "Attempt by " + + transaction + " to introduce a stale reference"); } } } @@ -952,86 +993,6 @@ public class TransactionCommitContext implements InternalCommitContext } } - protected void checkXRefs() - { - if (ensuringReferentialIntegrity && detachedObjectTypes != null) - { - XRefContext context = new XRefContext(); - xRefs = context.getXRefs(accessor); - if (!xRefs.isEmpty()) - { - rollbackMessage = "Referential integrity violated"; - } - } - } - - protected void checkContainmentCycles() - { - if (lastTreeRestructuringCommit == 0) - { - // If this was a tree-restructuring commit then lastTreeRestructuringCommit would be initialized. - return; - } - - if (lastUpdateTime == CDOBranchPoint.UNSPECIFIED_DATE) - { - // Happens during replication (see CommitDelegationRequest). Commits are checked in the master repo. - return; - } - - if (lastTreeRestructuringCommit <= lastUpdateTime) - { - // If this client's original state includes the state of the last tree-restructuring commit there's no danger. - return; - } - - Set<CDOID> objectsThatReachTheRoot = new HashSet<CDOID>(); - for (int i = 0; i < dirtyObjectDeltas.length; i++) - { - InternalCDORevisionDelta revisionDelta = dirtyObjectDeltas[i]; - CDOFeatureDelta containerDelta = revisionDelta.getFeatureDelta(CDOContainerFeatureDelta.CONTAINER_FEATURE); - if (containerDelta != null) - { - InternalCDORevision revision = dirtyObjects[i]; - if (!isTheRootReachable(revision, objectsThatReachTheRoot, new HashSet<CDOID>())) - { - throw new ContainmentCycleDetectedException("Attempt by " + transaction + " to introduce a containment cycle"); - } - } - } - } - - private boolean isTheRootReachable(InternalCDORevision revision, Set<CDOID> objectsThatReachTheRoot, - Set<CDOID> visited) - { - CDOID id = revision.getID(); - if (!visited.add(id)) - { - // Cycle detected on the way up to the root. - return false; - } - - if (!objectsThatReachTheRoot.add(id)) - { - // Has already been checked before. - return true; - } - - CDOID containerID = (CDOID)revision.getContainerID(); - if (CDOIDUtil.isNull(containerID)) - { - // The tree root has been reached. - return true; - } - - // Use this commit context as CDORevisionProvider for the container revisions. - // This is safe because Repository.commit() serializes all tree-restructuring commits. - InternalCDORevision containerRevision = getRevision(containerID); - - // Recurse Up - return isTheRootReachable(containerRevision, objectsThatReachTheRoot, visited); - } - private synchronized void unlockObjects() { if (!lockedObjects.isEmpty()) @@ -1117,8 +1078,8 @@ public class TransactionCommitContext implements InternalCommitContext if (oldRevision == null) { // If the object is logically locked (see lockObjects) but has a wrong (newer) version, someone else modified it - throw new ConcurrentModificationException("Attempt by " + transaction + " to modify historical revision: " - + delta); + throw new RollbackException(CDOProtocolConstants.ROLLBACK_REASON_COMMIT_CONFLICT, "Attempt by " + transaction + + " to modify historical revision: " + delta); } // Make sure all chunks are loaded @@ -1131,29 +1092,85 @@ public class TransactionCommitContext implements InternalCommitContext return newRevision; } - private void applyIDMappings(InternalCDORevision[] revisions, OMMonitor monitor) + protected void checkContainmentCycles() { - try + if (lastTreeRestructuringCommit == 0) { - monitor.begin(revisions.length); - for (InternalCDORevision revision : revisions) + // If this was a tree-restructuring commit then lastTreeRestructuringCommit would be initialized. + return; + } + + if (lastUpdateTime == CDOBranchPoint.UNSPECIFIED_DATE) + { + // Happens during replication (see CommitDelegationRequest). Commits are checked in the master repo. + return; + } + + if (lastTreeRestructuringCommit <= lastUpdateTime) + { + // If this client's original state includes the state of the last tree-restructuring commit there's no danger. + return; + } + + Set<CDOID> objectsThatReachTheRoot = new HashSet<CDOID>(); + for (int i = 0; i < dirtyObjectDeltas.length; i++) + { + InternalCDORevisionDelta revisionDelta = dirtyObjectDeltas[i]; + CDOFeatureDelta containerDelta = revisionDelta.getFeatureDelta(CDOContainerFeatureDelta.CONTAINER_FEATURE); + if (containerDelta != null) { - if (revision != null) + InternalCDORevision revision = dirtyObjects[i]; + if (!isTheRootReachable(revision, objectsThatReachTheRoot, new HashSet<CDOID>())) { - CDOID newID = idMappings.get(revision.getID()); - if (newID != null) - { - revision.setID(newID); - } - - revision.adjustReferences(idMapper); - monitor.worked(); + throw new RollbackException(CDOProtocolConstants.ROLLBACK_REASON_CONTAINMENT_CYCLE, "Attempt by " + + transaction + " to introduce a containment cycle"); } } } - finally + } + + private boolean isTheRootReachable(InternalCDORevision revision, Set<CDOID> objectsThatReachTheRoot, + Set<CDOID> visited) + { + CDOID id = revision.getID(); + if (!visited.add(id)) { - monitor.done(); + // Cycle detected on the way up to the root. + return false; + } + + if (!objectsThatReachTheRoot.add(id)) + { + // Has already been checked before. + return true; + } + + CDOID containerID = (CDOID)revision.getContainerID(); + if (CDOIDUtil.isNull(containerID)) + { + // The tree root has been reached. + return true; + } + + // Use this commit context as CDORevisionProvider for the container revisions. + // This is safe because Repository.commit() serializes all tree-restructuring commits. + InternalCDORevision containerRevision = getRevision(containerID); + + // Recurse Up + return isTheRootReachable(containerRevision, objectsThatReachTheRoot, visited); + } + + protected void checkXRefs() + { + if (ensuringReferentialIntegrity && detachedObjectTypes != null) + { + XRefContext context = new XRefContext(); + xRefs = context.getXRefs(accessor); + if (!xRefs.isEmpty()) + { + throw new RollbackException(CDOProtocolConstants.ROLLBACK_REASON_REFERENTIAL_INTEGRITY, "Attempt by " + + transaction + " to introduce a stale reference"); + } } } @@ -1438,6 +1455,41 @@ public class TransactionCommitContext implements InternalCommitContext /** * @author Eike Stepper */ + private static final class RollbackException extends RuntimeException + { + private static final long serialVersionUID = 1L; + + private final byte rollbackReason; + + private final String rollbackMessage; + + public RollbackException(byte rollbackReason, String rollbackMessage) + { + this.rollbackReason = rollbackReason; + this.rollbackMessage = rollbackMessage; + } + + public RollbackException(byte rollbackReason, Throwable cause) + { + super(cause); + this.rollbackReason = rollbackReason; + rollbackMessage = cause.getMessage(); + } + + public byte getRollbackReason() + { + return rollbackReason; + } + + public String getRollbackMessage() + { + return rollbackMessage; + } + } + + /** + * @author Eike Stepper + */ private final class XRefContext implements QueryXRefsContext { private Map<EClass, List<EReference>> sourceCandidates = new HashMap<EClass, List<EReference>>(); diff --git a/plugins/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/server/IStoreAccessor.java b/plugins/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/server/IStoreAccessor.java index d09083d7b0..4ae413fc9c 100644 --- a/plugins/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/server/IStoreAccessor.java +++ b/plugins/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/server/IStoreAccessor.java @@ -425,6 +425,12 @@ public interface IStoreAccessor extends IQueryHandlerProvider, BranchLoader, Com public CDOCommitInfo createCommitInfo(); /** + * @see CDOProtocolConstants + * @since 4.2 + */ + public byte getRollbackReason(); + + /** * @since 3.0 */ public String getRollbackMessage(); diff --git a/plugins/org.eclipse.emf.cdo.tests/src/org/eclipse/emf/cdo/tests/bugzilla/Bugzilla_409284_Test.java b/plugins/org.eclipse.emf.cdo.tests/src/org/eclipse/emf/cdo/tests/bugzilla/Bugzilla_409284_Test.java index d4fdb4a5f6..bb7ab7dd3a 100644 --- a/plugins/org.eclipse.emf.cdo.tests/src/org/eclipse/emf/cdo/tests/bugzilla/Bugzilla_409284_Test.java +++ b/plugins/org.eclipse.emf.cdo.tests/src/org/eclipse/emf/cdo/tests/bugzilla/Bugzilla_409284_Test.java @@ -16,7 +16,7 @@ import org.eclipse.emf.cdo.tests.AbstractCDOTest; import org.eclipse.emf.cdo.tests.model1.Category; import org.eclipse.emf.cdo.tests.model1.Company; import org.eclipse.emf.cdo.transaction.CDOTransaction; -import org.eclipse.emf.cdo.util.CommitException; +import org.eclipse.emf.cdo.util.ContainmentCycleException; import org.eclipse.emf.common.util.EList; @@ -77,12 +77,11 @@ public class Bugzilla_409284_Test extends AbstractCDOTest try { transaction2.commit(); - fail("CommitException expected"); + fail("ContainmentCycleException expected"); } - catch (CommitException expected) + catch (ContainmentCycleException expected) { - String message = expected.getMessage(); - assertEquals(true, message.contains("ContainmentCycleDetectedException")); + // SUCCESS } } diff --git a/plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/cdo/util/CommitConflictException.java b/plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/cdo/util/CommitConflictException.java new file mode 100644 index 0000000000..3b33842483 --- /dev/null +++ b/plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/cdo/util/CommitConflictException.java @@ -0,0 +1,27 @@ +/* + * Copyright (c) 2004-2013 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.util; + +/** + * @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 CommitConflictException extends ConcurrentAccessException +{ + private static final long serialVersionUID = 1L; + + public CommitConflictException(String message) + { + super(message); + } +} diff --git a/plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/cdo/util/CommitException.java b/plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/cdo/util/CommitException.java index 643e44ccca..ed1fc428fa 100644 --- a/plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/cdo/util/CommitException.java +++ b/plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/cdo/util/CommitException.java @@ -15,7 +15,7 @@ import org.eclipse.emf.cdo.transaction.CDOTransaction; /** * A checked exception being thrown from {@link CDOTransaction#commit()} in case of unrecoverable commit problems such * as commit conflicts. - * + * * @author Eike Stepper * @since 3.0 * @noextend This interface is not intended to be extended by clients. @@ -43,4 +43,20 @@ public class CommitException extends Exception { super(message, cause); } + + /** + * @since 4.2 + */ + public boolean isLocal() + { + return false; + } + + /** + * @since 4.2 + */ + public boolean isFatal() + { + return true; + } } diff --git a/plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/cdo/util/CommitIntegrityException.java b/plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/cdo/util/CommitIntegrityException.java index e5d07f06ed..121398a9d8 100644 --- a/plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/cdo/util/CommitIntegrityException.java +++ b/plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/cdo/util/CommitIntegrityException.java @@ -19,17 +19,17 @@ import java.util.Set; /** * A {@link CommitException commit exception} that indicates referential integrity problems with * {@link CDOTransaction#setCommittables(Set) partial commits} before the server is contacted. - * + * * @author Caspar De Groot * @since 4.0 * @noextend This interface is not intended to be extended by clients. * @noinstantiate This class is not intended to be instantiated by clients. */ -public class CommitIntegrityException extends CommitException +public class CommitIntegrityException extends DataIntegrityException { private static final long serialVersionUID = 1L; - private Set<? extends EObject> missingObjects; + private transient Set<? extends EObject> missingObjects; public CommitIntegrityException(String msg, Set<? extends EObject> missingObjects) { @@ -41,4 +41,10 @@ public class CommitIntegrityException extends CommitException { return missingObjects; } + + @Override + public boolean isLocal() + { + return true; + } } diff --git a/plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/cdo/util/ConcurrentAccessException.java b/plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/cdo/util/ConcurrentAccessException.java new file mode 100644 index 0000000000..c6cc6e767e --- /dev/null +++ b/plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/cdo/util/ConcurrentAccessException.java @@ -0,0 +1,47 @@ +/* + * Copyright (c) 2010-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: + * Caspar De Groot - initial API and implementation + */ +package org.eclipse.emf.cdo.util; + +/** + * @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 ConcurrentAccessException extends CommitException +{ + private static final long serialVersionUID = 1L; + + public ConcurrentAccessException() + { + } + + public ConcurrentAccessException(String message, Throwable cause) + { + super(message, cause); + } + + public ConcurrentAccessException(String message) + { + super(message); + } + + public ConcurrentAccessException(Throwable cause) + { + super(cause); + } + + @Override + public boolean isFatal() + { + return false; + } +} diff --git a/plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/cdo/util/ContainmentCycleException.java b/plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/cdo/util/ContainmentCycleException.java new file mode 100644 index 0000000000..efbb388258 --- /dev/null +++ b/plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/cdo/util/ContainmentCycleException.java @@ -0,0 +1,27 @@ +/* + * Copyright (c) 2004-2013 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.util; + +/** + * @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 ContainmentCycleException extends ConcurrentAccessException +{ + private static final long serialVersionUID = 1L; + + public ContainmentCycleException(String message) + { + super(message); + } +} diff --git a/plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/cdo/util/DanglingIntegrityException.java b/plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/cdo/util/DanglingIntegrityException.java new file mode 100644 index 0000000000..2f10f9d3c7 --- /dev/null +++ b/plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/cdo/util/DanglingIntegrityException.java @@ -0,0 +1,47 @@ +/* + * Copyright (c) 2008, 2009, 2011, 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: + * Simon McDuff - initial API and implementation + * Eike Stepper - maintenance + */ +package org.eclipse.emf.cdo.util; + +import org.eclipse.emf.ecore.EObject; + +/** + * @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 DanglingIntegrityException extends DataIntegrityException +{ + private static final long serialVersionUID = 1L; + + public DanglingIntegrityException(DanglingReferenceException cause) + { + super(cause.getMessage(), cause); + } + + @Override + public DanglingReferenceException getCause() + { + return (DanglingReferenceException)super.getCause(); + } + + public EObject getTarget() + { + return getCause().getTarget(); + } + + @Override + public boolean isLocal() + { + return true; + } +} diff --git a/plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/cdo/util/DanglingReferenceException.java b/plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/cdo/util/DanglingReferenceException.java index e5c5db0c4a..e44104a3ee 100644 --- a/plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/cdo/util/DanglingReferenceException.java +++ b/plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/cdo/util/DanglingReferenceException.java @@ -4,7 +4,7 @@ * 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: * Simon McDuff - initial API and implementation * Eike Stepper - maintenance @@ -26,7 +26,7 @@ import java.text.MessageFormat; * An unchecked exception being thrown from {@link CDOTransaction#commit()} if the commit {@link CDOCommitData change * set} is referencing {@link EObject objects} that are not contained by any {@link Resource resource} before the server * is contacted. - * + * * @author Simon McDuff * @since 2.0 * @noextend This interface is not intended to be extended by clients. @@ -36,7 +36,7 @@ public class DanglingReferenceException extends CDOException { private static final long serialVersionUID = 1L; - private EObject target; + private transient EObject target; public DanglingReferenceException(EObject object) { diff --git a/plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/cdo/util/DataIntegrityException.java b/plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/cdo/util/DataIntegrityException.java new file mode 100644 index 0000000000..4977b32d5c --- /dev/null +++ b/plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/cdo/util/DataIntegrityException.java @@ -0,0 +1,42 @@ +/* + * Copyright (c) 2010-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: + * Caspar De Groot - initial API and implementation + */ +package org.eclipse.emf.cdo.util; + + +/** + * @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 DataIntegrityException extends CommitException +{ + private static final long serialVersionUID = 1L; + + public DataIntegrityException() + { + } + + public DataIntegrityException(String message, Throwable cause) + { + super(message, cause); + } + + public DataIntegrityException(String message) + { + super(message); + } + + public DataIntegrityException(Throwable cause) + { + super(cause); + } +} diff --git a/plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/cdo/util/ImplicitLockingException.java b/plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/cdo/util/ImplicitLockingException.java new file mode 100644 index 0000000000..541b5e7f5c --- /dev/null +++ b/plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/cdo/util/ImplicitLockingException.java @@ -0,0 +1,27 @@ +/* + * Copyright (c) 2004-2013 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.util; + +/** + * @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 ImplicitLockingException extends ConcurrentAccessException +{ + private static final long serialVersionUID = 1L; + + public ImplicitLockingException(String message) + { + super(message); + } +} diff --git a/plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/cdo/util/LocalCommitConflictException.java b/plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/cdo/util/LocalCommitConflictException.java new file mode 100644 index 0000000000..5034a36d9a --- /dev/null +++ b/plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/cdo/util/LocalCommitConflictException.java @@ -0,0 +1,33 @@ +/* + * Copyright (c) 2004-2013 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.util; + +/** + * @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 LocalCommitConflictException extends CommitConflictException +{ + private static final long serialVersionUID = 1L; + + public LocalCommitConflictException(String message) + { + super(message); + } + + @Override + public boolean isLocal() + { + return true; + } +} diff --git a/plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/cdo/util/ReferentialIntegrityException.java b/plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/cdo/util/ReferentialIntegrityException.java index 01cd28b283..b8ae2e2fcb 100644 --- a/plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/cdo/util/ReferentialIntegrityException.java +++ b/plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/cdo/util/ReferentialIntegrityException.java @@ -16,17 +16,17 @@ import java.util.List; /** * A {@link CommitException commit exception} that indicates referential integrity problems detected by the server. - * + * * @author Eike Stepper * @since 4.0 * @noextend This interface is not intended to be extended by clients. * @noinstantiate This class is not intended to be instantiated by clients. */ -public class ReferentialIntegrityException extends CommitException +public class ReferentialIntegrityException extends DataIntegrityException { private static final long serialVersionUID = 1L; - private List<CDOObjectReference> xRefs; + private transient List<CDOObjectReference> xRefs; public ReferentialIntegrityException(String msg, List<CDOObjectReference> xRefs) { diff --git a/plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/internal/cdo/transaction/CDOSingleTransactionStrategyImpl.java b/plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/internal/cdo/transaction/CDOSingleTransactionStrategyImpl.java index 607d2472ee..be434cc9a2 100644 --- a/plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/internal/cdo/transaction/CDOSingleTransactionStrategyImpl.java +++ b/plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/internal/cdo/transaction/CDOSingleTransactionStrategyImpl.java @@ -10,12 +10,15 @@ */ package org.eclipse.emf.internal.cdo.transaction; -import org.eclipse.emf.cdo.CDOObjectReference; import org.eclipse.emf.cdo.common.branch.CDOBranch; import org.eclipse.emf.cdo.common.commit.CDOCommitData; import org.eclipse.emf.cdo.common.commit.CDOCommitInfo; +import org.eclipse.emf.cdo.common.protocol.CDOProtocolConstants; import org.eclipse.emf.cdo.spi.common.commit.InternalCDOCommitInfoManager; +import org.eclipse.emf.cdo.util.CommitConflictException; import org.eclipse.emf.cdo.util.CommitException; +import org.eclipse.emf.cdo.util.ContainmentCycleException; +import org.eclipse.emf.cdo.util.ImplicitLockingException; import org.eclipse.emf.cdo.util.ReferentialIntegrityException; import org.eclipse.emf.internal.cdo.bundle.OM; @@ -35,8 +38,6 @@ import org.eclipse.emf.spi.cdo.InternalCDOUserSavepoint; import org.eclipse.core.runtime.IProgressMonitor; -import java.util.List; - /** * @author Simon McDuff * @since 2.0 @@ -75,13 +76,27 @@ public class CDOSingleTransactionStrategyImpl implements CDOTransactionStrategy String rollbackMessage = result.getRollbackMessage(); if (rollbackMessage != null) { - List<CDOObjectReference> xRefs = result.getXRefs(); - if (xRefs != null) + byte rollbackReason = result.getRollbackReason(); + switch (rollbackReason) { - throw new ReferentialIntegrityException(rollbackMessage, xRefs); - } + case CDOProtocolConstants.ROLLBACK_REASON_IMPLICIT_LOCKING: + throw new ImplicitLockingException(rollbackMessage); + + case CDOProtocolConstants.ROLLBACK_REASON_COMMIT_CONFLICT: + throw new CommitConflictException(rollbackMessage); + + case CDOProtocolConstants.ROLLBACK_REASON_CONTAINMENT_CYCLE: + throw new ContainmentCycleException(rollbackMessage); - throw new CommitException(rollbackMessage); + case CDOProtocolConstants.ROLLBACK_REASON_REFERENTIAL_INTEGRITY: + throw new ReferentialIntegrityException(rollbackMessage, result.getXRefs()); + + case CDOProtocolConstants.ROLLBACK_REASON_UNKNOWN: + throw new CommitException(rollbackMessage); + + default: + throw new IllegalStateException("Invalid rollbackreason: " + rollbackReason); + } } transaction.setCommitComment(null); 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 a08f36cec9..da1927660c 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 @@ -100,6 +100,9 @@ import org.eclipse.emf.cdo.transaction.CDOUserSavepoint; import org.eclipse.emf.cdo.util.CDOURIUtil; import org.eclipse.emf.cdo.util.CDOUtil; import org.eclipse.emf.cdo.util.CommitException; +import org.eclipse.emf.cdo.util.DanglingIntegrityException; +import org.eclipse.emf.cdo.util.DanglingReferenceException; +import org.eclipse.emf.cdo.util.LocalCommitConflictException; import org.eclipse.emf.cdo.util.ObjectNotFoundException; import org.eclipse.emf.internal.cdo.CDOObjectImpl; @@ -1176,7 +1179,7 @@ public class CDOTransactionImpl extends CDOViewImpl implements InternalCDOTransa checkActive(); if (hasConflict()) { - throw new CommitException(Messages.getString("CDOTransactionImpl.2")); //$NON-NLS-1$ + throw new LocalCommitConflictException(Messages.getString("CDOTransactionImpl.2")); //$NON-NLS-1$ } if (progressMonitor == null) @@ -1193,6 +1196,10 @@ public class CDOTransactionImpl extends CDOViewImpl implements InternalCDOTransa return info; } + catch (DanglingReferenceException ex) + { + throw new DanglingIntegrityException(ex); + } catch (CommitException ex) { throw ex; diff --git a/plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/spi/cdo/CDOSessionProtocol.java b/plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/spi/cdo/CDOSessionProtocol.java index 222be34c16..9d4c2e5461 100644 --- a/plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/spi/cdo/CDOSessionProtocol.java +++ b/plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/spi/cdo/CDOSessionProtocol.java @@ -29,6 +29,7 @@ import org.eclipse.emf.cdo.common.lob.CDOLobInfo; import org.eclipse.emf.cdo.common.lock.CDOLockState; import org.eclipse.emf.cdo.common.model.CDOPackageUnit; import org.eclipse.emf.cdo.common.protocol.CDOProtocol; +import org.eclipse.emf.cdo.common.protocol.CDOProtocolConstants; import org.eclipse.emf.cdo.common.revision.CDOIDAndVersion; import org.eclipse.emf.cdo.common.revision.CDORevisionHandler; import org.eclipse.emf.cdo.common.revision.CDORevisionKey; @@ -675,6 +676,8 @@ public interface CDOSessionProtocol extends CDOProtocol, PackageLoader, BranchLo { private CDOIDProvider idProvider; + private byte rollbackReason; + private String rollbackMessage; private List<CDOObjectReference> xRefs; @@ -699,16 +702,19 @@ public interface CDOSessionProtocol extends CDOProtocol, PackageLoader, BranchLo public CommitTransactionResult(CDOIDProvider idProvider, String rollbackMessage, CDOBranchPoint branchPoint, long previousTimeStamp, List<CDOObjectReference> xRefs) { - this(idProvider, rollbackMessage, branchPoint, previousTimeStamp, xRefs, true); + this(idProvider, CDOProtocolConstants.ROLLBACK_REASON_UNKNOWN, rollbackMessage, branchPoint, previousTimeStamp, + xRefs, true); } /** * @since 4.2 */ - public CommitTransactionResult(CDOIDProvider idProvider, String rollbackMessage, CDOBranchPoint branchPoint, - long previousTimeStamp, List<CDOObjectReference> xRefs, boolean clearResourcePathCache) + public CommitTransactionResult(CDOIDProvider idProvider, byte rollbackReason, String rollbackMessage, + CDOBranchPoint branchPoint, long previousTimeStamp, List<CDOObjectReference> xRefs, + boolean clearResourcePathCache) { this.idProvider = idProvider; + this.rollbackReason = rollbackReason; this.rollbackMessage = rollbackMessage; this.branchPoint = branchPoint; this.previousTimeStamp = previousTimeStamp; @@ -759,6 +765,14 @@ public interface CDOSessionProtocol extends CDOProtocol, PackageLoader, BranchLo this.referenceAdjuster = referenceAdjuster; } + /** + * @since 4.2 + */ + public byte getRollbackReason() + { + return rollbackReason; + } + public String getRollbackMessage() { return rollbackMessage; |