diff options
30 files changed, 751 insertions, 127 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 731e600bc9..d9196795c5 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 @@ -30,8 +30,9 @@ public interface CDOProtocolConstants * @since 4.2 * @noreference This field is not intended to be referenced by clients. */ - public static final int PROTOCOL_VERSION = 27; // SIGNAL_OPENED_SESSION + public static final int PROTOCOL_VERSION = 28; // SIGNAL_RESET_TRANSACTION + // public static final int PROTOCOL_VERSION = 27; // SIGNAL_OPENED_SESSION // public static final int PROTOCOL_VERSION = 26; // Add prefetch depth in LockStateRequest/Indication // public static final int PROTOCOL_VERSION = 25; // OpenSessionResponse.repositoryAuthenticating // public static final int PROTOCOL_VERSION = 24; // SIGNAL_LOAD_OBJECT_LIFETIME @@ -306,6 +307,11 @@ public interface CDOProtocolConstants */ public static final short SIGNAL_OPENED_SESSION = 60; + /** + * @since 4.5 + */ + public static final short SIGNAL_RESET_TRANSACTION = 61; + // ////////////////////////////////////////////////////////////////////// // Session Refresh diff --git a/plugins/org.eclipse.emf.cdo.explorer.ui/src/org/eclipse/emf/cdo/explorer/ui/checkouts/CDOModelEditorOpener.java b/plugins/org.eclipse.emf.cdo.explorer.ui/src/org/eclipse/emf/cdo/explorer/ui/checkouts/CDOModelEditorOpener.java index 3e926bb4e4..7d9078720d 100644 --- a/plugins/org.eclipse.emf.cdo.explorer.ui/src/org/eclipse/emf/cdo/explorer/ui/checkouts/CDOModelEditorOpener.java +++ b/plugins/org.eclipse.emf.cdo.explorer.ui/src/org/eclipse/emf/cdo/explorer/ui/checkouts/CDOModelEditorOpener.java @@ -25,6 +25,7 @@ import org.eclipse.emf.internal.cdo.transaction.CDOHandlingConflictResolver; import org.eclipse.emf.common.util.URI; import org.eclipse.emf.spi.cdo.CDOMergingConflictResolver; +import org.eclipse.jface.dialogs.MessageDialog; import org.eclipse.ui.IEditorInput; import org.eclipse.ui.IEditorPart; import org.eclipse.ui.IEditorReference; @@ -48,6 +49,13 @@ public class CDOModelEditorOpener extends CDOEditorOpener.Default protected IEditorPart doOpenEditor(final IWorkbenchPage page, URI uri) { CDOCheckout checkout = CDOExplorerUtil.getCheckout(uri); + if (checkout == null) + { + MessageDialog.openError(page.getWorkbenchWindow().getShell(), "Error", + "The checkout for " + uri + " could not be found."); + return null; + } + final CDOView view = checkout.openView(); if (view instanceof CDOTransaction) diff --git a/plugins/org.eclipse.emf.cdo.explorer.ui/src/org/eclipse/emf/cdo/explorer/ui/checkouts/ResourceGroup.java b/plugins/org.eclipse.emf.cdo.explorer.ui/src/org/eclipse/emf/cdo/explorer/ui/checkouts/ResourceGroup.java index bde71d9f91..ee4aa2d47c 100644 --- a/plugins/org.eclipse.emf.cdo.explorer.ui/src/org/eclipse/emf/cdo/explorer/ui/checkouts/ResourceGroup.java +++ b/plugins/org.eclipse.emf.cdo.explorer.ui/src/org/eclipse/emf/cdo/explorer/ui/checkouts/ResourceGroup.java @@ -80,7 +80,9 @@ public class ResourceGroup extends CDOElement public void setName(final String name) { final String type = getType(); - new Job("Rename " + type.toLowerCase()) + final String title = "Rename " + type.toLowerCase(); + + new Job(title) { @Override protected IStatus run(IProgressMonitor monitor) @@ -118,7 +120,11 @@ public class ResourceGroup extends CDOElement if (commitInfo != null) { - checkout.getView().waitForUpdate(commitInfo.getTimeStamp()); + if (!checkout.getView().waitForUpdate(commitInfo.getTimeStamp(), 10000)) + { + OM.LOG.error(title + ": Did not receive an update"); + return Status.OK_STATUS; + } CDOCheckoutManagerImpl checkoutManager = (CDOCheckoutManagerImpl)CDOExplorerUtil.getCheckoutManager(); checkoutManager.fireElementChangedEvent(ElementsChangedEvent.StructuralImpact.PARENT, diff --git a/plugins/org.eclipse.emf.cdo.explorer.ui/src/org/eclipse/emf/cdo/explorer/ui/checkouts/wizards/NewWizard.java b/plugins/org.eclipse.emf.cdo.explorer.ui/src/org/eclipse/emf/cdo/explorer/ui/checkouts/wizards/NewWizard.java index b3691d5fe8..78dc864993 100644 --- a/plugins/org.eclipse.emf.cdo.explorer.ui/src/org/eclipse/emf/cdo/explorer/ui/checkouts/wizards/NewWizard.java +++ b/plugins/org.eclipse.emf.cdo.explorer.ui/src/org/eclipse/emf/cdo/explorer/ui/checkouts/wizards/NewWizard.java @@ -87,6 +87,7 @@ public abstract class NewWizard extends Wizard implements INewWizard { final Object parent = page.getParent(); final String name = page.getName(); + final String error = "An error occured while creating the " + title.toLowerCase() + "."; new Job(title) { @@ -139,8 +140,7 @@ public abstract class NewWizard extends Wizard implements INewWizard { public void run() { - ErrorDialog.openError(getShell(), "Error", - "An error occured while creating the " + title.toLowerCase() + ".", status); + ErrorDialog.openError(getShell(), "Error", error, status); } }); @@ -154,7 +154,11 @@ public abstract class NewWizard extends Wizard implements INewWizard if (commitInfo != null && contentProvider != null) { CDOView view = checkout.getView(); - view.waitForUpdate(commitInfo.getTimeStamp()); + if (!view.waitForUpdate(commitInfo.getTimeStamp(), 10000)) + { + OM.LOG.error(error + " Did not receive an update"); + return Status.OK_STATUS; + } CDOObject newObject = view.getObject(newID); contentProvider.selectObjects(newObject); diff --git a/plugins/org.eclipse.emf.cdo.explorer.ui/src/org/eclipse/emf/cdo/explorer/ui/properties/ExplorerUIAdapterFactory.java b/plugins/org.eclipse.emf.cdo.explorer.ui/src/org/eclipse/emf/cdo/explorer/ui/properties/ExplorerUIAdapterFactory.java index dbba91d79a..90be3ab992 100644 --- a/plugins/org.eclipse.emf.cdo.explorer.ui/src/org/eclipse/emf/cdo/explorer/ui/properties/ExplorerUIAdapterFactory.java +++ b/plugins/org.eclipse.emf.cdo.explorer.ui/src/org/eclipse/emf/cdo/explorer/ui/properties/ExplorerUIAdapterFactory.java @@ -194,7 +194,9 @@ public class ExplorerUIAdapterFactory implements IAdapterFactory public void setName(final String name) { - new Job("Rename " + getType().toLowerCase()) + final String title = "Rename " + getType().toLowerCase(); + + new Job(title) { @Override protected IStatus run(IProgressMonitor monitor) @@ -232,7 +234,11 @@ public class ExplorerUIAdapterFactory implements IAdapterFactory if (commitInfo != null && checkout != null) { - checkout.getView().waitForUpdate(commitInfo.getTimeStamp()); + if (!checkout.getView().waitForUpdate(commitInfo.getTimeStamp(), 10000)) + { + OM.LOG.error(title + ": Did not receive an update"); + return Status.OK_STATUS; + } CDOCheckoutManagerImpl checkoutManager = (CDOCheckoutManagerImpl)CDOExplorerUtil.getCheckoutManager(); checkoutManager.fireElementChangedEvent(ElementsChangedEvent.StructuralImpact.PARENT, resourceNode); diff --git a/plugins/org.eclipse.emf.cdo.net4j/src/org/eclipse/emf/cdo/internal/net4j/protocol/CDOClientProtocol.java b/plugins/org.eclipse.emf.cdo.net4j/src/org/eclipse/emf/cdo/internal/net4j/protocol/CDOClientProtocol.java index b4c17ddbe6..2e6f609394 100644 --- a/plugins/org.eclipse.emf.cdo.net4j/src/org/eclipse/emf/cdo/internal/net4j/protocol/CDOClientProtocol.java +++ b/plugins/org.eclipse.emf.cdo.net4j/src/org/eclipse/emf/cdo/internal/net4j/protocol/CDOClientProtocol.java @@ -21,6 +21,7 @@ import org.eclipse.emf.cdo.common.branch.CDOBranchPointRange; import org.eclipse.emf.cdo.common.branch.CDOBranchVersion; import org.eclipse.emf.cdo.common.commit.CDOChangeSetData; import org.eclipse.emf.cdo.common.commit.CDOCommitData; +import org.eclipse.emf.cdo.common.commit.CDOCommitInfo; import org.eclipse.emf.cdo.common.commit.CDOCommitInfoHandler; import org.eclipse.emf.cdo.common.id.CDOID; import org.eclipse.emf.cdo.common.id.CDOIDProvider; @@ -461,6 +462,11 @@ public class CDOClientProtocol extends AuthenticatingSignalProtocol<CDOSessionIm return send(new CommitXATransactionCancelRequest(this, xaContext), monitor); } + public CDOCommitInfo resetTransaction(int transactionID, int commitNumber) + { + return send(new ResetTransactionRequest(this, transactionID, commitNumber)); + } + public List<CDORemoteSession> getRemoteSessions(InternalCDORemoteSessionManager manager, boolean subscribe) { return send(new GetRemoteSessionsRequest(this, subscribe)); 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 25ef8f885c..a891df1530 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 @@ -38,7 +38,6 @@ import org.eclipse.emf.cdo.common.revision.delta.CDORevisionDelta; import org.eclipse.emf.cdo.common.security.CDOPermission; import org.eclipse.emf.cdo.internal.net4j.bundle.OM; import org.eclipse.emf.cdo.session.CDORepositoryInfo; -import org.eclipse.emf.cdo.transaction.CDOTransaction; import org.eclipse.emf.internal.cdo.object.CDOObjectReferenceImpl; import org.eclipse.emf.internal.cdo.view.AbstractCDOView; @@ -51,6 +50,8 @@ import org.eclipse.net4j.util.om.trace.ContextTracer; import org.eclipse.emf.ecore.EClass; import org.eclipse.emf.spi.cdo.CDOSessionProtocol.CommitTransactionResult; +import org.eclipse.emf.spi.cdo.InternalCDOSession.CommitToken; +import org.eclipse.emf.spi.cdo.InternalCDOTransaction; import org.eclipse.emf.spi.cdo.InternalCDOTransaction.InternalCDOCommitContext; import java.io.IOException; @@ -70,7 +71,9 @@ public class CommitTransactionRequest extends CDOClientRequestWithMonitoring<Com private CDOIDProvider idProvider; // CDOTransaction - private String comment; + private int commitNumber; + + private String commitComment; private boolean releaseLocks; @@ -85,7 +88,7 @@ public class CommitTransactionRequest extends CDOClientRequestWithMonitoring<Com /** * Is <code>null</code> in {@link CommitDelegationRequest}. */ - private CDOTransaction transaction; + private InternalCDOTransaction transaction; private boolean clearResourcePathCache; @@ -99,7 +102,13 @@ public class CommitTransactionRequest extends CDOClientRequestWithMonitoring<Com super(protocol, signalID); transaction = context.getTransaction(); - comment = context.getCommitComment(); + CommitToken commitToken = transaction.getCommitToken(); + if (commitToken != null) + { + commitNumber = commitToken.getCommitNumber(); + } + + commitComment = context.getCommitComment(); releaseLocks = context.isAutoReleaseLocks(); idProvider = context.getTransaction(); commitData = context.getCommitData(); @@ -142,7 +151,8 @@ public class CommitTransactionRequest extends CDOClientRequestWithMonitoring<Com out.writeLong(getLastUpdateTime()); out.writeBoolean(releaseLocks); - out.writeString(comment); + out.writeInt(commitNumber); + out.writeString(commitComment); out.writeInt(newPackageUnits.size()); out.writeInt(locksOnNewObjects.size()); out.writeInt(newObjects.size()); diff --git a/plugins/org.eclipse.emf.cdo.net4j/src/org/eclipse/emf/cdo/internal/net4j/protocol/ResetTransactionRequest.java b/plugins/org.eclipse.emf.cdo.net4j/src/org/eclipse/emf/cdo/internal/net4j/protocol/ResetTransactionRequest.java new file mode 100644 index 0000000000..140bd4c873 --- /dev/null +++ b/plugins/org.eclipse.emf.cdo.net4j/src/org/eclipse/emf/cdo/internal/net4j/protocol/ResetTransactionRequest.java @@ -0,0 +1,74 @@ +/* + * Copyright (c) 2016 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.internal.net4j.protocol; + +import org.eclipse.emf.cdo.common.commit.CDOCommitInfo; +import org.eclipse.emf.cdo.common.protocol.CDODataInput; +import org.eclipse.emf.cdo.common.protocol.CDODataOutput; +import org.eclipse.emf.cdo.common.protocol.CDOProtocolConstants; +import org.eclipse.emf.cdo.internal.net4j.bundle.OM; +import org.eclipse.emf.cdo.spi.common.commit.InternalCDOCommitInfoManager; + +import org.eclipse.net4j.util.om.trace.ContextTracer; + +import java.io.IOException; + +/** + * @author Eike Stepper + */ +public class ResetTransactionRequest extends CDOClientRequest<CDOCommitInfo> +{ + private static final ContextTracer TRACER = new ContextTracer(OM.DEBUG_PROTOCOL, ResetTransactionRequest.class); + + private int transactionID; + + private int commitNumber; + + public ResetTransactionRequest(CDOClientProtocol protocol, int transactionID, int commitNumber) + { + super(protocol, CDOProtocolConstants.SIGNAL_RESET_TRANSACTION); + this.transactionID = transactionID; + this.commitNumber = commitNumber; + } + + @Override + protected void requesting(CDODataOutput out) throws IOException + { + if (TRACER.isEnabled()) + { + TRACER.format("Writing transactionID: {0}", transactionID); //$NON-NLS-1$ + } + + out.writeInt(transactionID); + + if (TRACER.isEnabled()) + { + TRACER.format("Writing commitNumber: {0}", commitNumber); //$NON-NLS-1$ + } + + out.writeInt(commitNumber); + } + + @Override + protected CDOCommitInfo confirming(CDODataInput in) throws IOException + { + if (in.readBoolean()) + { + long timeStamp = in.readLong(); + long previousTimeStamp = in.readLong(); + + InternalCDOCommitInfoManager commitInfoManager = getSession().getCommitInfoManager(); + return commitInfoManager.createCommitInfo(null, timeStamp, previousTimeStamp, null, null, null); + } + + 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 941aeea198..abf8fb61a0 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 @@ -320,6 +320,10 @@ public class HibernateRawCommitContext implements InternalCommitContext { } + public void setCommitNumber(int commitNumber) + { + } + public void setCommitComment(String comment) { } diff --git a/plugins/org.eclipse.emf.cdo.server.net4j/src/org/eclipse/emf/cdo/server/internal/net4j/protocol/CDOServerProtocol.java b/plugins/org.eclipse.emf.cdo.server.net4j/src/org/eclipse/emf/cdo/server/internal/net4j/protocol/CDOServerProtocol.java index f51a2fb386..158ec41677 100644 --- a/plugins/org.eclipse.emf.cdo.server.net4j/src/org/eclipse/emf/cdo/server/internal/net4j/protocol/CDOServerProtocol.java +++ b/plugins/org.eclipse.emf.cdo.server.net4j/src/org/eclipse/emf/cdo/server/internal/net4j/protocol/CDOServerProtocol.java @@ -388,6 +388,9 @@ public class CDOServerProtocol extends SignalProtocol<InternalSession> implement case SIGNAL_OPENED_SESSION: return new OpenedSessionNotification(this); + case SIGNAL_RESET_TRANSACTION: + return new ResetTransactionIndication(this); + default: return super.createSignalReactor(signalID); } 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 ca070cc81d..8a1c87ca88 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 @@ -106,7 +106,11 @@ public class CommitTransactionIndication extends CDOServerIndicationWithMonitori } catch (Exception ex) { - OM.LOG.error(ex); + if (TRACER.isEnabled()) + { + TRACER.trace(ex); + } + throw WrappedException.wrap(ex); } finally @@ -123,6 +127,7 @@ public class CommitTransactionIndication extends CDOServerIndicationWithMonitori long lastUpdateTime = in.readLong(); boolean autoReleaseLocksEnabled = in.readBoolean(); + int commitNumber = in.readInt(); String commitComment = in.readString(); InternalCDOPackageUnit[] newPackageUnits = new InternalCDOPackageUnit[in.readInt()]; @@ -267,6 +272,7 @@ public class CommitTransactionIndication extends CDOServerIndicationWithMonitori detachedObjectTypes = null; } + commitContext.setCommitNumber(commitNumber); commitContext.setLastUpdateTime(lastUpdateTime); commitContext.setAutoReleaseLocksEnabled(autoReleaseLocksEnabled); commitContext.setClearResourcePathCache(clearResourcePathCache); diff --git a/plugins/org.eclipse.emf.cdo.server.net4j/src/org/eclipse/emf/cdo/server/internal/net4j/protocol/ResetTransactionIndication.java b/plugins/org.eclipse.emf.cdo.server.net4j/src/org/eclipse/emf/cdo/server/internal/net4j/protocol/ResetTransactionIndication.java new file mode 100644 index 0000000000..fa45694a26 --- /dev/null +++ b/plugins/org.eclipse.emf.cdo.server.net4j/src/org/eclipse/emf/cdo/server/internal/net4j/protocol/ResetTransactionIndication.java @@ -0,0 +1,74 @@ +/* + * Copyright (c) 2016 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.server.internal.net4j.protocol; + +import org.eclipse.emf.cdo.common.protocol.CDODataInput; +import org.eclipse.emf.cdo.common.protocol.CDODataOutput; +import org.eclipse.emf.cdo.common.protocol.CDOProtocolConstants; +import org.eclipse.emf.cdo.server.internal.net4j.bundle.OM; +import org.eclipse.emf.cdo.spi.server.InternalSession; +import org.eclipse.emf.cdo.spi.server.InternalTransaction; +import org.eclipse.emf.cdo.spi.server.InternalTransaction.CommitAttempt; + +import org.eclipse.net4j.util.om.trace.ContextTracer; + +import java.io.IOException; + +/** + * @author Eike Stepper + */ +public class ResetTransactionIndication extends CDOServerReadIndication +{ + private static final ContextTracer TRACER = new ContextTracer(OM.DEBUG_PROTOCOL, ResetTransactionIndication.class); + + private int transactionID; + + private int commitNumber; + + public ResetTransactionIndication(CDOServerProtocol protocol) + { + super(protocol, CDOProtocolConstants.SIGNAL_RESET_TRANSACTION); + } + + @Override + protected void indicating(CDODataInput in) throws IOException + { + transactionID = in.readInt(); + if (TRACER.isEnabled()) + { + TRACER.format("Read transactionID: {0}", transactionID); //$NON-NLS-1$ + } + + commitNumber = in.readInt(); + if (TRACER.isEnabled()) + { + TRACER.format("Read commitNumber: {0}", commitNumber); //$NON-NLS-1$ + } + } + + @Override + protected void responding(CDODataOutput out) throws IOException + { + InternalSession session = getSession(); + InternalTransaction transaction = (InternalTransaction)session.getView(transactionID); + CommitAttempt lastCommitSuccess = transaction.getLastCommitAttempt(); + if (lastCommitSuccess != null && lastCommitSuccess.getCommitNumber() == commitNumber) + { + out.writeBoolean(true); + out.writeLong(lastCommitSuccess.getTimeStamp()); + out.writeLong(lastCommitSuccess.getPreviousTimeStamp()); + } + else + { + out.writeBoolean(false); + } + } +} diff --git a/plugins/org.eclipse.emf.cdo.server.security/src/org/eclipse/emf/cdo/server/internal/security/SecurityManager.java b/plugins/org.eclipse.emf.cdo.server.security/src/org/eclipse/emf/cdo/server/internal/security/SecurityManager.java index 4ccb325c6a..b7dbe912c9 100644 --- a/plugins/org.eclipse.emf.cdo.server.security/src/org/eclipse/emf/cdo/server/internal/security/SecurityManager.java +++ b/plugins/org.eclipse.emf.cdo.server.security/src/org/eclipse/emf/cdo/server/internal/security/SecurityManager.java @@ -69,6 +69,7 @@ import org.eclipse.net4j.connector.IConnector; import org.eclipse.net4j.util.ArrayUtil; import org.eclipse.net4j.util.WrappedException; import org.eclipse.net4j.util.collection.HashBag; +import org.eclipse.net4j.util.concurrent.TimeoutRuntimeException; import org.eclipse.net4j.util.container.ContainerEventAdapter; import org.eclipse.net4j.util.container.IContainer; import org.eclipse.net4j.util.container.IManagedContainer; @@ -407,7 +408,10 @@ public class SecurityManager extends Lifecycle implements InternalSecurityManage if (waitUntilReadable) { - systemView.waitForUpdate(commit.getTimeStamp()); + if (!systemView.waitForUpdate(commit.getTimeStamp(), 10000)) + { + throw new TimeoutRuntimeException(); + } } } catch (CommitException ex) @@ -686,7 +690,11 @@ public class SecurityManager extends Lifecycle implements InternalSecurityManage { if (lastRealmModification != CDOBranchPoint.UNSPECIFIED_DATE) { - systemView.waitForUpdate(lastRealmModification); + if (!systemView.waitForUpdate(lastRealmModification, 10000L)) + { + throw new TimeoutRuntimeException(); + } + lastRealmModification = CDOBranchPoint.UNSPECIFIED_DATE; } diff --git a/plugins/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/internal/server/TimeStampAuthority.java b/plugins/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/internal/server/TimeStampAuthority.java index 6d3c997efb..a6af0e1ddd 100644 --- a/plugins/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/internal/server/TimeStampAuthority.java +++ b/plugins/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/internal/server/TimeStampAuthority.java @@ -72,6 +72,10 @@ class TimeStampAuthority this.repository = repository; } + /** + * @deprecated Not used anymore. + */ + @Deprecated synchronized long[] startCommit(OMMonitor monitor) { return startCommit(CDOBranchPoint.UNSPECIFIED_DATE, monitor); diff --git a/plugins/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/internal/server/Transaction.java b/plugins/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/internal/server/Transaction.java index 58d300a6d0..96e8c54b3e 100644 --- a/plugins/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/internal/server/Transaction.java +++ b/plugins/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/internal/server/Transaction.java @@ -26,6 +26,8 @@ import org.eclipse.net4j.util.om.monitor.OMMonitor; */ public class Transaction extends View implements InternalTransaction { + private CommitAttempt lastCommitAttempt; + public Transaction(InternalSession session, int viewID, CDOBranchPoint branchPoint) { super(session, viewID, branchPoint); @@ -73,6 +75,16 @@ public class Transaction extends View implements InternalTransaction }; } + public CommitAttempt getLastCommitAttempt() + { + return lastCommitAttempt; + } + + public void setLastCommitAttempt(CommitAttempt lastCommitAttempt) + { + this.lastCommitAttempt = lastCommitAttempt; + } + @Override protected void validateTimeStamp(long timeStamp) throws IllegalArgumentException { 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 3fbe135d4b..e87ac6a685 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 @@ -70,6 +70,7 @@ import org.eclipse.emf.cdo.spi.server.InternalCommitContext; import org.eclipse.emf.cdo.spi.server.InternalLockManager; import org.eclipse.emf.cdo.spi.server.InternalRepository; import org.eclipse.emf.cdo.spi.server.InternalTransaction; +import org.eclipse.emf.cdo.spi.server.InternalTransaction.CommitAttempt; import org.eclipse.net4j.util.CheckUtil; import org.eclipse.net4j.util.StringUtil; @@ -132,6 +133,8 @@ public class TransactionCommitContext implements InternalCommitContext private long previousTimeStamp = CDORevision.UNSPECIFIED_DATE; + private int commitNumber; + private String commitComment; private boolean usingEcore; @@ -216,6 +219,11 @@ public class TransactionCommitContext implements InternalCommitContext return transaction.getSession().getUserID(); } + public int getCommitNumber() + { + return commitNumber; + } + public String getCommitComment() { return commitComment; @@ -354,7 +362,7 @@ public class TransactionCommitContext implements InternalCommitContext return (InternalCDORevision)transaction.getRevision(id); } - private Map<CDOID, InternalCDORevision> cacheRevisions() + protected Map<CDOID, InternalCDORevision> cacheRevisions() { Map<CDOID, InternalCDORevision> cache = CDOIDUtil.createMap(); if (newObjects != null) @@ -432,7 +440,7 @@ public class TransactionCommitContext implements InternalCommitContext } } - private void applyIDMappings(InternalCDORevision[] revisions, OMMonitor monitor) + protected void applyIDMappings(InternalCDORevision[] revisions, OMMonitor monitor) { try { @@ -544,6 +552,11 @@ public class TransactionCommitContext implements InternalCommitContext autoReleaseLocksEnabled = on; } + public void setCommitNumber(int commitNumber) + { + this.commitNumber = commitNumber; + } + public void setCommitComment(String commitComment) { this.commitComment = commitComment; @@ -583,7 +596,7 @@ public class TransactionCommitContext implements InternalCommitContext return old; } - private InternalCDOPackageUnit[] lockPackageRegistry(InternalCDOPackageUnit[] packageUnits) + protected InternalCDOPackageUnit[] lockPackageRegistry(InternalCDOPackageUnit[] packageUnits) throws InterruptedException { if (!packageRegistryLocked) @@ -648,7 +661,7 @@ public class TransactionCommitContext implements InternalCommitContext monitor.worked(); detachObjects(monitor.fork()); - accessor.write(this, monitor.fork(100)); + writeAccessor(monitor.fork(100)); } catch (RollbackException ex) { @@ -702,7 +715,7 @@ public class TransactionCommitContext implements InternalCommitContext return postCommitLockStates; } - private void handleException(Throwable ex) + protected void handleException(Throwable ex) { try { @@ -742,7 +755,7 @@ public class TransactionCommitContext implements InternalCommitContext } } - private void finishMonitor(OMMonitor monitor) + protected void finishMonitor(OMMonitor monitor) { try { @@ -760,12 +773,14 @@ public class TransactionCommitContext implements InternalCommitContext } } - private void setTimeStamp(OMMonitor monitor) + protected void setTimeStamp(OMMonitor monitor) { long[] times = createTimeStamp(monitor); // Could throw an exception timeStamp = times[0]; previousTimeStamp = times[1]; CheckUtil.checkState(timeStamp != CDOBranchPoint.UNSPECIFIED_DATE, "Commit timestamp must not be 0"); + + transaction.setLastCommitAttempt(new CommitAttempt(commitNumber, timeStamp, previousTimeStamp)); } protected long[] createTimeStamp(OMMonitor monitor) @@ -791,9 +806,16 @@ public class TransactionCommitContext implements InternalCommitContext public void postCommit(boolean success) { - if (packageRegistryLocked) + try { - repository.getPackageRegistryCommitLock().release(); + if (packageRegistryLocked) + { + repository.getPackageRegistryCommitLock().release(); + } + } + catch (Throwable ex) + { + OM.LOG.warn("A problem occured while releasing the package registry commit lock", ex); } try @@ -804,7 +826,7 @@ public class TransactionCommitContext implements InternalCommitContext sendCommitNotifications(success); } } - catch (Exception ex) + catch (Throwable ex) { OM.LOG.warn("A problem occured while notifying other sessions", ex); } @@ -822,7 +844,7 @@ public class TransactionCommitContext implements InternalCommitContext } } - private void sendCommitNotifications(boolean success) + protected void sendCommitNotifications(boolean success) { commitNotificationInfo.setSender(transaction.getSession()); commitNotificationInfo.setRevisionProvider(this); @@ -853,7 +875,7 @@ public class TransactionCommitContext implements InternalCommitContext return new FailureCommitInfo(timeStamp, previousTimeStamp); } - private CDOCommitData createCommitData() + protected CDOCommitData createCommitData() { List<CDOPackageUnit> newPackageUnitsCollection = new IndexedList.ArrayBacked<CDOPackageUnit>() { @@ -1034,7 +1056,7 @@ public class TransactionCommitContext implements InternalCommitContext } } - private void lockTarget(Object value, Set<CDOID> newIDs, boolean supportingBranches) + protected void lockTarget(Object value, Set<CDOID> newIDs, boolean supportingBranches) { if (value instanceof CDOIDObject) { @@ -1069,7 +1091,7 @@ public class TransactionCommitContext implements InternalCommitContext } } - private synchronized void unlockObjects() + protected synchronized void unlockObjects() { // Unlock objects locked during commit if (!lockedObjects.isEmpty()) @@ -1113,7 +1135,7 @@ public class TransactionCommitContext implements InternalCommitContext } } - private void computeDirtyObjects(OMMonitor monitor) + protected void computeDirtyObjects(OMMonitor monitor) { try { @@ -1140,7 +1162,7 @@ public class TransactionCommitContext implements InternalCommitContext } } - private InternalCDORevision computeDirtyObject(InternalCDORevisionDelta delta) + protected InternalCDORevision computeDirtyObject(InternalCDORevisionDelta delta) { CDOID id = delta.getID(); @@ -1228,7 +1250,7 @@ public class TransactionCommitContext implements InternalCommitContext } } - private boolean isTheRootReachable(InternalCDORevision revision, Set<CDOID> objectsThatReachTheRoot, + protected boolean isTheRootReachable(InternalCDORevision revision, Set<CDOID> objectsThatReachTheRoot, Set<CDOID> visited) { CDOID id = revision.getID(); @@ -1305,7 +1327,7 @@ public class TransactionCommitContext implements InternalCommitContext return accessor; } - private void updateInfraStructure(OMMonitor monitor) + protected void updateInfraStructure(OMMonitor monitor) { try { @@ -1345,7 +1367,7 @@ public class TransactionCommitContext implements InternalCommitContext } } - private void applyLocksOnNewObjects() throws InterruptedException + protected void applyLocksOnNewObjects() throws InterruptedException { final CDOLockOwner owner = CDOLockUtil.createLockOwner(transaction); @@ -1373,7 +1395,7 @@ public class TransactionCommitContext implements InternalCommitContext } } - private void sendLockNotifications(List<LockState<Object, IView>> newLockStates) + protected void sendLockNotifications(List<LockState<Object, IView>> newLockStates) { CDOLockState[] newStates = Repository.toCDOLockStates(newLockStates); @@ -1384,7 +1406,7 @@ public class TransactionCommitContext implements InternalCommitContext repository.getSessionManager().sendLockNotification(transaction.getSession(), info); } - private void addNewPackageUnits(OMMonitor monitor) + protected void addNewPackageUnits(OMMonitor monitor) { InternalCDOPackageRegistry repositoryPackageRegistry = repository.getPackageRegistry(false); synchronized (repositoryPackageRegistry) @@ -1408,7 +1430,7 @@ public class TransactionCommitContext implements InternalCommitContext } } - private void addRevisions(CDORevision[] revisions, OMMonitor monitor) + protected void addRevisions(CDORevision[] revisions, OMMonitor monitor) { try { @@ -1431,7 +1453,7 @@ public class TransactionCommitContext implements InternalCommitContext } } - private void reviseDetachedObjects(OMMonitor monitor) + protected void reviseDetachedObjects(OMMonitor monitor) { try { @@ -1453,7 +1475,7 @@ public class TransactionCommitContext implements InternalCommitContext } } - private void detachObjects(OMMonitor monitor) + protected void detachObjects(OMMonitor monitor) { int size = detachedObjects.length; cachedDetachedRevisions = new InternalCDORevision[size]; @@ -1480,6 +1502,11 @@ public class TransactionCommitContext implements InternalCommitContext } } + protected void writeAccessor(OMMonitor monitor) + { + accessor.write(this, monitor); + } + @Override public String toString() { diff --git a/plugins/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/internal/server/embedded/EmbeddedClientSessionProtocol.java b/plugins/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/internal/server/embedded/EmbeddedClientSessionProtocol.java index a038d9c92c..75db50bbc4 100644 --- a/plugins/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/internal/server/embedded/EmbeddedClientSessionProtocol.java +++ b/plugins/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/internal/server/embedded/EmbeddedClientSessionProtocol.java @@ -21,6 +21,7 @@ import org.eclipse.emf.cdo.common.branch.CDOBranchPointRange; import org.eclipse.emf.cdo.common.branch.CDOBranchVersion; import org.eclipse.emf.cdo.common.commit.CDOChangeSetData; import org.eclipse.emf.cdo.common.commit.CDOCommitData; +import org.eclipse.emf.cdo.common.commit.CDOCommitInfo; import org.eclipse.emf.cdo.common.commit.CDOCommitInfoHandler; import org.eclipse.emf.cdo.common.id.CDOID; import org.eclipse.emf.cdo.common.id.CDOIDProvider; @@ -559,6 +560,11 @@ public class EmbeddedClientSessionProtocol extends Lifecycle implements CDOSessi throw new UnsupportedOperationException(); } + public CDOCommitInfo resetTransaction(int transactionID, int commitNumber) + { + throw new UnsupportedOperationException(); + } + public List<CDORemoteSession> getRemoteSessions(InternalCDORemoteSessionManager manager, boolean subscribe) { throw new UnsupportedOperationException(); diff --git a/plugins/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/internal/server/mem/MEMStoreAccessor.java b/plugins/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/internal/server/mem/MEMStoreAccessor.java index 657ca3b19e..8fc9fcd490 100644 --- a/plugins/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/internal/server/mem/MEMStoreAccessor.java +++ b/plugins/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/internal/server/mem/MEMStoreAccessor.java @@ -65,6 +65,8 @@ import java.util.Set; */ public class MEMStoreAccessor extends LongIDStoreAccessor implements Raw, DurableLocking2, BranchLoader3 { + private final MEMStore store; + private final IQueryHandler testQueryHandler = new IQueryHandler() { public void executeQuery(CDOQueryInfo info, IQueryContext queryContext) @@ -105,7 +107,7 @@ public class MEMStoreAccessor extends LongIDStoreAccessor implements Raw, Durabl } int i = 0; - for (InternalCDORevision revision : getStore().getCurrentRevisions()) + for (InternalCDORevision revision : store.getCurrentRevisions()) { if (sleep != null) { @@ -168,11 +170,12 @@ public class MEMStoreAccessor extends LongIDStoreAccessor implements Raw, Durabl } }; - private List<InternalCDORevision> newRevisions = new ArrayList<InternalCDORevision>(); + private List<InternalCDORevision> newRevisions; public MEMStoreAccessor(MEMStore store, ISession session) { super(store, session); + this.store = store; } /** @@ -181,12 +184,13 @@ public class MEMStoreAccessor extends LongIDStoreAccessor implements Raw, Durabl public MEMStoreAccessor(MEMStore store, ITransaction transaction) { super(store, transaction); + this.store = store; } @Override public MEMStore getStore() { - return (MEMStore)super.getStore(); + return store; } /** @@ -209,22 +213,22 @@ public class MEMStoreAccessor extends LongIDStoreAccessor implements Raw, Durabl public Pair<Integer, Long> createBranch(int branchID, BranchInfo branchInfo) { - return getStore().createBranch(branchID, branchInfo); + return store.createBranch(branchID, branchInfo); } public BranchInfo loadBranch(int branchID) { - return getStore().loadBranch(branchID); + return store.loadBranch(branchID); } public SubBranchInfo[] loadSubBranches(int branchID) { - return getStore().loadSubBranches(branchID); + return store.loadSubBranches(branchID); } public int loadBranches(int startID, int endID, CDOBranchHandler branchHandler) { - return getStore().loadBranches(startID, endID, branchHandler); + return store.loadBranches(startID, endID, branchHandler); } @Deprecated @@ -241,35 +245,35 @@ public class MEMStoreAccessor extends LongIDStoreAccessor implements Raw, Durabl public void renameBranch(int branchID, String oldName, String newName) { - getStore().renameBranch(branchID, oldName, newName); + store.renameBranch(branchID, oldName, newName); } public void loadCommitInfos(CDOBranch branch, long startTime, long endTime, CDOCommitInfoHandler handler) { - getStore().loadCommitInfos(branch, startTime, endTime, handler); + store.loadCommitInfos(branch, startTime, endTime, handler); } public Set<CDOID> readChangeSet(OMMonitor monitor, CDOChangeSetSegment... segments) { - return getStore().readChangeSet(segments); + return store.readChangeSet(segments); } public InternalCDORevision readRevision(CDOID id, CDOBranchPoint branchPoint, int listChunk, CDORevisionCacheAdder cache) { - return getStore().getRevision(id, branchPoint); + return store.getRevision(id, branchPoint); } public InternalCDORevision readRevisionByVersion(CDOID id, CDOBranchVersion branchVersion, int listChunk, CDORevisionCacheAdder cache) { - return getStore().getRevisionByVersion(id, branchVersion); + return store.getRevisionByVersion(id, branchVersion); } public void handleRevisions(EClass eClass, CDOBranch branch, long timeStamp, boolean exactTime, CDORevisionHandler handler) { - getStore().handleRevisions(eClass, branch, timeStamp, exactTime, handler); + store.handleRevisions(eClass, branch, timeStamp, exactTime, handler); } /** @@ -278,13 +282,12 @@ public class MEMStoreAccessor extends LongIDStoreAccessor implements Raw, Durabl @Override protected void doCommit(OMMonitor monitor) { - // Do nothing + newRevisions = null; } @Override public void doWrite(InternalCommitContext context, OMMonitor monitor) { - MEMStore store = getStore(); synchronized (store) { super.doWrite(context, monitor); @@ -295,18 +298,20 @@ public class MEMStoreAccessor extends LongIDStoreAccessor implements Raw, Durabl protected void writeCommitInfo(CDOBranch branch, long timeStamp, long previousTimeStamp, String userID, String comment, OMMonitor monitor) { - getStore().addCommitInfo(branch, timeStamp, previousTimeStamp, userID, comment); + store.addCommitInfo(branch, timeStamp, previousTimeStamp, userID, comment); } @Override protected void doRollback(CommitContext context) { - MEMStore store = getStore(); - synchronized (store) + if (newRevisions != null) { - for (InternalCDORevision revision : newRevisions) + synchronized (store) { - store.rollbackRevision(revision); + for (InternalCDORevision revision : newRevisions) + { + store.rollbackRevision(revision); + } } } } @@ -327,8 +332,13 @@ public class MEMStoreAccessor extends LongIDStoreAccessor implements Raw, Durabl protected void writeRevision(InternalCDORevision revision) { + if (newRevisions == null) + { + newRevisions = new ArrayList<InternalCDORevision>(); + } + newRevisions.add(revision); - getStore().addRevision(revision, false); + store.addRevision(revision, false); } /** @@ -350,7 +360,7 @@ public class MEMStoreAccessor extends LongIDStoreAccessor implements Raw, Durabl protected void writeRevisionDelta(InternalCDORevisionDelta revisionDelta, CDOBranch branch, long created) { CDOID id = revisionDelta.getID(); - InternalCDORevision revision = getStore().getRevisionByVersion(id, revisionDelta); + InternalCDORevision revision = store.getRevisionByVersion(id, revisionDelta); if (revision == null) { throw new ConcurrentModificationException("Trying to update object " + id //$NON-NLS-1$ @@ -378,7 +388,7 @@ public class MEMStoreAccessor extends LongIDStoreAccessor implements Raw, Durabl */ protected void detachObject(CDOID id, CDOBranch branch, long timeStamp) { - getStore().detachObject(id, branch, timeStamp); + store.detachObject(id, branch, timeStamp); } /** @@ -386,12 +396,12 @@ public class MEMStoreAccessor extends LongIDStoreAccessor implements Raw, Durabl */ public void queryResources(QueryResourcesContext context) { - getStore().queryResources(context); + store.queryResources(context); } public void queryXRefs(QueryXRefsContext context) { - getStore().queryXRefs(context); + store.queryXRefs(context); } public IQueryHandler getQueryHandler(CDOQueryInfo info) @@ -407,13 +417,13 @@ public class MEMStoreAccessor extends LongIDStoreAccessor implements Raw, Durabl public void rawExport(CDODataOutput out, int fromBranchID, int toBranchID, long fromCommitTime, long toCommitTime) throws IOException { - getStore().rawExport(out, fromBranchID, toBranchID, fromCommitTime, toCommitTime); + store.rawExport(out, fromBranchID, toBranchID, fromCommitTime, toCommitTime); } public void rawImport(CDODataInput in, int fromBranchID, int toBranchID, long fromCommitTime, long toCommitTime, OMMonitor monitor) throws IOException { - getStore().rawImport(in, fromBranchID, toBranchID, fromCommitTime, toCommitTime, monitor); + store.rawImport(in, fromBranchID, toBranchID, fromCommitTime, toCommitTime, monitor); } public void rawStore(InternalCDOPackageUnit[] packageUnits, OMMonitor monitor) @@ -423,7 +433,7 @@ public class MEMStoreAccessor extends LongIDStoreAccessor implements Raw, Durabl public void rawStore(InternalCDORevision revision, OMMonitor monitor) { - getStore().addRevision(revision, true); + store.addRevision(revision, true); } public void rawStore(byte[] id, long size, InputStream inputStream) throws IOException @@ -444,7 +454,7 @@ public class MEMStoreAccessor extends LongIDStoreAccessor implements Raw, Durabl public void rawDelete(CDOID id, int version, CDOBranch branch, EClass eClass, OMMonitor monitor) { - getStore().rawDelete(id, version, branch); + store.rawDelete(id, version, branch); } public void rawCommit(double commitWork, OMMonitor monitor) @@ -455,75 +465,75 @@ public class MEMStoreAccessor extends LongIDStoreAccessor implements Raw, Durabl public LockArea createLockArea(String userID, CDOBranchPoint branchPoint, boolean readOnly, Map<CDOID, LockGrade> locks) { - return getStore().createLockArea(userID, branchPoint, readOnly, locks); + return store.createLockArea(userID, branchPoint, readOnly, locks); } public LockArea createLockArea(String durableLockingID, String userID, CDOBranchPoint branchPoint, boolean readOnly, Map<CDOID, LockGrade> locks) { - return getStore().createLockArea(durableLockingID, userID, branchPoint, readOnly, locks); + return store.createLockArea(durableLockingID, userID, branchPoint, readOnly, locks); } public void updateLockArea(LockArea lockArea) { - getStore().updateLockArea(lockArea); + store.updateLockArea(lockArea); } public LockArea getLockArea(String durableLockingID) throws LockAreaNotFoundException { - return getStore().getLockArea(durableLockingID); + return store.getLockArea(durableLockingID); } public void getLockAreas(String userIDPrefix, Handler handler) { - getStore().getLockAreas(userIDPrefix, handler); + store.getLockAreas(userIDPrefix, handler); } public void deleteLockArea(String durableLockingID) { - getStore().deleteLockArea(durableLockingID); + store.deleteLockArea(durableLockingID); } public void lock(String durableLockingID, LockType type, Collection<? extends Object> objectsToLock) { - getStore().lock(durableLockingID, type, objectsToLock); + store.lock(durableLockingID, type, objectsToLock); } public void unlock(String durableLockingID, LockType type, Collection<? extends Object> objectsToUnlock) { - getStore().unlock(durableLockingID, type, objectsToUnlock); + store.unlock(durableLockingID, type, objectsToUnlock); } public void unlock(String durableLockingID) { - getStore().unlock(durableLockingID); + store.unlock(durableLockingID); } public void queryLobs(List<byte[]> ids) { - getStore().queryLobs(ids); + store.queryLobs(ids); } public void handleLobs(long fromTime, long toTime, CDOLobHandler handler) throws IOException { - getStore().handleLobs(fromTime, toTime, handler); + store.handleLobs(fromTime, toTime, handler); } public void loadLob(byte[] id, OutputStream out) throws IOException { - getStore().loadLob(id, out); + store.loadLob(id, out); } @Override protected void writeBlob(byte[] id, long size, InputStream inputStream) throws IOException { - getStore().writeBlob(id, size, inputStream); + store.writeBlob(id, size, inputStream); } @Override protected void writeClob(byte[] id, long size, Reader reader) throws IOException { - getStore().writeClob(id, size, reader); + store.writeClob(id, size, reader); } @Override @@ -535,7 +545,11 @@ public class MEMStoreAccessor extends LongIDStoreAccessor implements Raw, Durabl @Override protected void doDeactivate() throws Exception { - newRevisions.clear(); + if (newRevisions != null) + { + newRevisions.clear(); + newRevisions = null; + } } @Override diff --git a/plugins/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/internal/server/syncing/SynchronizableRepository.java b/plugins/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/internal/server/syncing/SynchronizableRepository.java index 8be293f5d4..791be4692f 100644 --- a/plugins/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/internal/server/syncing/SynchronizableRepository.java +++ b/plugins/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/internal/server/syncing/SynchronizableRepository.java @@ -72,6 +72,7 @@ import org.eclipse.emf.cdo.spi.server.SyncingUtil; import org.eclipse.net4j.util.WrappedException; import org.eclipse.net4j.util.collection.IndexedList; import org.eclipse.net4j.util.concurrent.IRWLockManager.LockType; +import org.eclipse.net4j.util.concurrent.TimeoutRuntimeException; import org.eclipse.net4j.util.lifecycle.LifecycleUtil; import org.eclipse.net4j.util.om.monitor.Monitor; import org.eclipse.net4j.util.om.monitor.OMMonitor; @@ -735,7 +736,10 @@ public abstract class SynchronizableRepository extends Repository.Default implem } long requiredTimestamp = masterLockingResult.getRequiredTimestamp(); - remoteSession.waitForUpdate(requiredTimestamp); + if (!remoteSession.waitForUpdate(requiredTimestamp, 10000)) + { + throw new TimeoutRuntimeException(); + } } return masterLockingResult; diff --git a/plugins/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/spi/server/InternalCommitContext.java b/plugins/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/spi/server/InternalCommitContext.java index 0f8824485d..d304a713df 100644 --- a/plugins/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/spi/server/InternalCommitContext.java +++ b/plugins/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/spi/server/InternalCommitContext.java @@ -49,20 +49,20 @@ public interface InternalCommitContext extends IStoreAccessor.CommitContext, CDO } }, // - new ProgressDistributable.Default<InternalCommitContext>() - { - public void runLoop(int index, InternalCommitContext commitContext, OMMonitor monitor) throws Exception - { - if (commitContext.getRollbackMessage() == null) - { - commitContext.commit(monitor.fork()); - } - else + new ProgressDistributable.Default<InternalCommitContext>() { - monitor.worked(); - } - } - }); + public void runLoop(int index, InternalCommitContext commitContext, OMMonitor monitor) throws Exception + { + if (commitContext.getRollbackMessage() == null) + { + commitContext.commit(monitor.fork()); + } + else + { + monitor.worked(); + } + } + }); public InternalTransaction getTransaction(); @@ -136,6 +136,11 @@ public interface InternalCommitContext extends IStoreAccessor.CommitContext, CDO public void setAutoReleaseLocksEnabled(boolean on); + /** + * @since 4.5 + */ + public void setCommitNumber(int commitNumber); + public void setCommitComment(String comment); /** diff --git a/plugins/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/spi/server/InternalTransaction.java b/plugins/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/spi/server/InternalTransaction.java index 0d8655e426..4488c03a06 100644 --- a/plugins/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/spi/server/InternalTransaction.java +++ b/plugins/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/spi/server/InternalTransaction.java @@ -23,4 +23,49 @@ import org.eclipse.emf.cdo.server.ITransaction; public interface InternalTransaction extends ITransaction, InternalView { public InternalCommitContext createCommitContext(); + + /** + * @since 4.5 + */ + public CommitAttempt getLastCommitAttempt(); + + /** + * @since 4.5 + */ + public void setLastCommitAttempt(CommitAttempt lastCommitAttempt); + + /** + * @author Eike Stepper + * @since 4.5 + */ + public static final class CommitAttempt + { + private final int commitNumber; + + private final long timeStamp; + + private final long previousTimeStamp; + + public CommitAttempt(int commitNumber, long timeStamp, long previousTimeStamp) + { + this.commitNumber = commitNumber; + this.timeStamp = timeStamp; + this.previousTimeStamp = previousTimeStamp; + } + + public int getCommitNumber() + { + return commitNumber; + } + + public long getTimeStamp() + { + return timeStamp; + } + + public long getPreviousTimeStamp() + { + return previousTimeStamp; + } + } } diff --git a/plugins/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/spi/server/StoreAccessorBase.java b/plugins/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/spi/server/StoreAccessorBase.java index adbd4024e2..0d3b4a823d 100644 --- a/plugins/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/spi/server/StoreAccessorBase.java +++ b/plugins/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/spi/server/StoreAccessorBase.java @@ -67,8 +67,6 @@ public abstract class StoreAccessorBase extends Lifecycle implements IStoreAcces { private static final ContextTracer TRACER = new ContextTracer(OM.DEBUG, StoreAccessorBase.class); - // private static int COUNT; - private Store store; private Object context; @@ -264,18 +262,6 @@ public abstract class StoreAccessorBase extends Lifecycle implements IStoreAcces protected abstract CDOID getNextCDOID(CDORevision revision); - // @Override - // protected void doActivate() throws Exception - // { - // System.out.println("Active accessors: " + ++COUNT); - // } - // - // @Override - // protected void doDeactivate() throws Exception - // { - // System.out.println("Active accessors: " + --COUNT); - // } - protected void doPassivate() throws Exception { } diff --git a/plugins/org.eclipse.emf.cdo.tests/src/org/eclipse/emf/cdo/tests/bugzilla/Bugzilla_485487_Test.java b/plugins/org.eclipse.emf.cdo.tests/src/org/eclipse/emf/cdo/tests/bugzilla/Bugzilla_485487_Test.java new file mode 100644 index 0000000000..d724ae69e9 --- /dev/null +++ b/plugins/org.eclipse.emf.cdo.tests/src/org/eclipse/emf/cdo/tests/bugzilla/Bugzilla_485487_Test.java @@ -0,0 +1,120 @@ +/* + * Copyright (c) 2016 Eike Stepper (Berlin, Germany) and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Eike Stepper - initial API and implementation + */ +package org.eclipse.emf.cdo.tests.bugzilla; + +import org.eclipse.emf.cdo.internal.server.Repository; +import org.eclipse.emf.cdo.internal.server.TransactionCommitContext; +import org.eclipse.emf.cdo.net4j.CDONet4jSession; +import org.eclipse.emf.cdo.spi.server.InternalCommitContext; +import org.eclipse.emf.cdo.spi.server.InternalRepository; +import org.eclipse.emf.cdo.spi.server.InternalTransaction; +import org.eclipse.emf.cdo.tests.AbstractCDOTest; +import org.eclipse.emf.cdo.tests.config.impl.RepositoryConfig; +import org.eclipse.emf.cdo.transaction.CDOTransaction; +import org.eclipse.emf.cdo.util.CommitException; + +import org.eclipse.net4j.util.concurrent.ConcurrencyUtil; +import org.eclipse.net4j.util.om.monitor.OMMonitor; + +import java.util.Map; + +/** + * Bug 485487. + * + * @author Eike Stepper + */ +public class Bugzilla_485487_Test extends AbstractCDOTest +{ + private static final String REPOSITORY_NAME = "repo1"; + + private Repository repository; + + private boolean forceTimeout; + + @Override + protected void doSetUp() throws Exception + { + createRepository(); + super.doSetUp(); + } + + private void createRepository() + { + repository = new Repository.Default() + { + @Override + public InternalCommitContext createCommitContext(InternalTransaction transaction) + { + return new TransactionCommitContext(transaction) + { + @Override + protected void writeAccessor(OMMonitor monitor) + { + super.writeAccessor(monitor); + + if (forceTimeout) + { + ConcurrencyUtil.sleep(2000); + } + } + }; + } + }; + + Map<String, String> props = getRepositoryProperties(); + ((InternalRepository)repository).setProperties(props); + + repository.setName(REPOSITORY_NAME); + + Map<String, Object> map = getTestProperties(); + map.put(RepositoryConfig.PROP_TEST_REPOSITORY, repository); + map.put(RepositoryConfig.PROP_TEST_ENABLE_SERVER_BROWSER, true); + } + + @CleanRepositoriesBefore(reason = "Isolated repository needed") + @CleanRepositoriesAfter(reason = "Isolated repository needed") + public void testTimeoutDuringCommit() throws Exception + { + disableConsole(); + + CDONet4jSession session = (CDONet4jSession)openSession(REPOSITORY_NAME); + session.options().setCommitTimeout(1); + + CDOTransaction transaction = session.openTransaction(); + transaction.options().setCommitInfoTimeout(1000); + transaction.createResource(getResourcePath("/test1")); + + msg("#### Commit-1"); + + try + { + forceTimeout = true; + transaction.setCommitComment("test1"); + transaction.commit(); + fail("CommitException expected"); + } + catch (CommitException expected) + { + assertEquals(true, expected.getMessage().contains("Timeout after")); + } + + msg("#### Rollback"); + + forceTimeout = false; + transaction.rollback(); + + transaction.createResource(getResourcePath("/test2")); + + msg("#### Commit-2"); + transaction.setCommitComment("test2"); + transaction.commit(); + } +} diff --git a/plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/cdo/transaction/CDOTransaction.java b/plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/cdo/transaction/CDOTransaction.java index 3becc9c982..4431348634 100644 --- a/plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/cdo/transaction/CDOTransaction.java +++ b/plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/cdo/transaction/CDOTransaction.java @@ -230,6 +230,11 @@ public interface CDOTransaction extends CDOView, CDOCommonTransaction, CDOUserTr public static final CDOUndoDetector DEFAULT_UNDO_DETECTOR = CDOUndoDetector.ALL_FEATURES; /** + * @since 4.5 + */ + public static final long DEFAULT_COMMIT_INFO_TIMEOUT = 10000; + + /** * Returns the {@link CDOTransaction transaction} of this options object. * * @since 4.0 @@ -305,6 +310,24 @@ public interface CDOTransaction extends CDOView, CDOCommonTransaction, CDOUserTr public void setAutoReleaseLocksEnabled(boolean on); /** + * Returns the number of milliseconds to wait for the transaction update when {@link CDOTransaction#commit()} is called. + * <p> + * Default value is 10000. + * + * @since 4.5 + */ + public long getCommitInfoTimeout(); + + /** + * Specifies the number of milliseconds to wait for the transaction update when {@link CDOTransaction#commit()} is called. + * <p> + * Default value is 10000. + * + * @since 4.5 + */ + public void setCommitInfoTimeout(long commitInfoTimeout); + + /** * An {@link IOptionsEvent options event} fired from transaction {@link CDOTransaction#options() options} when the * {@link Options#setUndoDetector(CDOUndoDetector) undo detector} option has changed. * @@ -354,5 +377,18 @@ public interface CDOTransaction extends CDOView, CDOCommonTransaction, CDOUserTr public interface AutoReleaseLocksEvent extends IOptionsEvent { } + + /** + * An {@link IOptionsEvent options event} fired from transaction {@link CDOTransaction#options() options} when the + * {@link Options#setCommitInfoTimeout(long) commit info timeout} option has changed. + * + * @author Eike Stepper + * @since 4.5 + * @noextend This interface is not intended to be extended by clients. + * @noimplement This interface is not intended to be implemented by clients. + */ + public interface CommitInfoTimeout extends IOptionsEvent + { + } } } 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 05654ab730..5643db22a1 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 @@ -1761,6 +1761,8 @@ public abstract class CDOSessionImpl extends CDOTransactionContainerImpl private boolean terminateIfSessionClosed; + private int lastCommitNumber; + public Invalidator() { } @@ -1772,15 +1774,12 @@ public abstract class CDOSessionImpl extends CDOTransactionContainerImpl return null; } - final String threadName = Thread.currentThread().getName(); - Object token = new Object() + CommitToken token = new CommitToken(++lastCommitNumber, Thread.currentThread().getName()); + + if (DEBUG) { - @Override - public String toString() - { - return threadName; - } - }; + IOUtil.OUT().println(CDOSessionImpl.this + " [" + getLastUpdateTime() % 10000 + "] startLocalCommit: " + token); + } unfinishedLocalCommits.add(token); return token; @@ -1788,6 +1787,11 @@ public abstract class CDOSessionImpl extends CDOTransactionContainerImpl public synchronized void endLocalCommit(Object token) { + if (DEBUG) + { + IOUtil.OUT().println(CDOSessionImpl.this + " [" + getLastUpdateTime() % 10000 + "] endLocalCommit: " + token); + } + unfinishedLocalCommits.remove(token); } diff --git a/plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/internal/cdo/session/DelegatingSessionProtocol.java b/plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/internal/cdo/session/DelegatingSessionProtocol.java index 7170faedd9..d616a5ad11 100644 --- a/plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/internal/cdo/session/DelegatingSessionProtocol.java +++ b/plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/internal/cdo/session/DelegatingSessionProtocol.java @@ -21,6 +21,7 @@ import org.eclipse.emf.cdo.common.branch.CDOBranchPointRange; import org.eclipse.emf.cdo.common.branch.CDOBranchVersion; import org.eclipse.emf.cdo.common.commit.CDOChangeSetData; import org.eclipse.emf.cdo.common.commit.CDOCommitData; +import org.eclipse.emf.cdo.common.commit.CDOCommitInfo; import org.eclipse.emf.cdo.common.commit.CDOCommitInfoHandler; import org.eclipse.emf.cdo.common.id.CDOID; import org.eclipse.emf.cdo.common.id.CDOIDProvider; @@ -396,6 +397,22 @@ public class DelegatingSessionProtocol extends Lifecycle implements CDOSessionPr } } + public CDOCommitInfo resetTransaction(int transactionID, int commitNumber) + { + int attempt = 0; + for (;;) + { + try + { + return delegate.resetTransaction(transactionID, commitNumber); + } + catch (Exception ex) + { + handleException(++attempt, ex); + } + } + } + public RepositoryTimeResult getRepositoryTime() { int attempt = 0; 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 bde1aa96ee..9aee7a2fd6 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 @@ -162,6 +162,7 @@ import org.eclipse.emf.spi.cdo.FSMUtil; import org.eclipse.emf.spi.cdo.InternalCDOObject; import org.eclipse.emf.spi.cdo.InternalCDOSavepoint; import org.eclipse.emf.spi.cdo.InternalCDOSession; +import org.eclipse.emf.spi.cdo.InternalCDOSession.CommitToken; import org.eclipse.emf.spi.cdo.InternalCDOSession.MergeData; import org.eclipse.emf.spi.cdo.InternalCDOTransaction; import org.eclipse.emf.spi.cdo.InternalCDOViewSet; @@ -231,6 +232,8 @@ public class CDOTransactionImpl extends CDOViewImpl implements InternalCDOTransa private String commitComment; + private CommitToken commitToken; + // Bug 283985 (Re-attachment) private final ThreadLocal<Boolean> providingCDOID = new InheritableThreadLocal<Boolean>() { @@ -1291,7 +1294,12 @@ public class CDOTransactionImpl extends CDOViewImpl implements InternalCDOTransa if (info != null) { long timeStamp = info.getTimeStamp(); - waitForUpdate(timeStamp, 10000); + long timeout = options().getCommitInfoTimeout(); + + if (!waitForUpdate(timeStamp, timeout)) + { + throw new TimeoutRuntimeException("Did not receive an update: " + this); + } } return info; @@ -1300,7 +1308,7 @@ public class CDOTransactionImpl extends CDOViewImpl implements InternalCDOTransa private synchronized CDOCommitInfo commitSynced(IProgressMonitor progressMonitor) throws DanglingIntegrityException, CommitException { - Object token = null; + InternalCDOSession session = getSession(); try { @@ -1310,7 +1318,7 @@ public class CDOTransactionImpl extends CDOViewImpl implements InternalCDOTransa throw new LocalCommitConflictException(Messages.getString("CDOTransactionImpl.2")); //$NON-NLS-1$ } - token = getSession().startLocalCommit(); + commitToken = (CommitToken)session.startLocalCommit(); CDOTransactionStrategy transactionStrategy = getTransactionStrategy(); CDOCommitInfo info = transactionStrategy.commit(this, progressMonitor); @@ -1331,21 +1339,53 @@ public class CDOTransactionImpl extends CDOViewImpl implements InternalCDOTransa } catch (Throwable t) { - if (t.getCause() instanceof MonitorCanceledException - && !(t.getCause().getCause() instanceof TimeoutRuntimeException)) + try + { + // The commit may have succeeded on the server, but after that fact network problems or timeouts have hit us. + // Let's see if we can recover... + CDOCommitInfo info = session.getSessionProtocol().resetTransaction(getViewID(), commitToken.getCommitNumber()); + if (info != null) + { + lastCommitTime = info.getTimeStamp(); + session.invalidate(info, this, true, CDOProtocol.CommitNotificationInfo.IMPACT_NONE, null); + + // At this point the session (invalidator) is recovered. + // Continue to rethrow the exception and let the client call rollback()... + } + } + catch (Throwable ex) + { + if (TRACER.isEnabled()) + { + TRACER.trace(ex); + } + } + + Throwable cause = t.getCause(); + if (cause instanceof MonitorCanceledException) { - throw new OperationCanceledException("CDOTransactionImpl.7");//$NON-NLS-1$ + if (!(cause.getCause() instanceof TimeoutRuntimeException)) + { + throw new OperationCanceledException("CDOTransactionImpl.7");//$NON-NLS-1$ + } } throw new CommitException(t); } finally { - getSession().endLocalCommit(token); + session.endLocalCommit(commitToken); + commitToken = null; + clearResourcePathCacheIfNecessary(null); } } + public CommitToken getCommitToken() + { + return commitToken; + } + /** * @since 2.0 */ @@ -3529,6 +3569,8 @@ public class CDOTransactionImpl extends CDOViewImpl implements InternalCDOTransa private boolean autoReleaseLocksEnabled = true; + private long commitInfoTimeout = DEFAULT_COMMIT_INFO_TIMEOUT; + public OptionsImpl() { } @@ -3710,6 +3752,28 @@ public class CDOTransactionImpl extends CDOViewImpl implements InternalCDOTransa fireEvent(event); } + public long getCommitInfoTimeout() + { + return commitInfoTimeout; + } + + public void setCommitInfoTimeout(long commitInfoTimeout) + { + checkActive(); + + IEvent event = null; + synchronized (CDOTransactionImpl.this) + { + if (this.commitInfoTimeout != commitInfoTimeout) + { + this.commitInfoTimeout = commitInfoTimeout; + event = new CommitInfoTimeoutImpl(); + } + } + + fireEvent(event); + } + /** * @author Eike Stepper */ @@ -3761,5 +3825,18 @@ public class CDOTransactionImpl extends CDOViewImpl implements InternalCDOTransa super(OptionsImpl.this); } } + + /** + * @author Eike Stepper + */ + private final class CommitInfoTimeoutImpl extends OptionsEvent implements CommitInfoTimeout + { + private static final long serialVersionUID = 1L; + + public CommitInfoTimeoutImpl() + { + super(OptionsImpl.this); + } + } } } 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 8ef89d8f25..ec58ab8fcd 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 @@ -22,6 +22,7 @@ import org.eclipse.emf.cdo.common.branch.CDOBranchPoint; import org.eclipse.emf.cdo.common.branch.CDOBranchPointRange; import org.eclipse.emf.cdo.common.commit.CDOChangeSetData; import org.eclipse.emf.cdo.common.commit.CDOCommitData; +import org.eclipse.emf.cdo.common.commit.CDOCommitInfo; import org.eclipse.emf.cdo.common.id.CDOID; import org.eclipse.emf.cdo.common.id.CDOID.ObjectType; import org.eclipse.emf.cdo.common.id.CDOIDProvider; @@ -257,6 +258,11 @@ public interface CDOSessionProtocol extends CDOProtocol, PackageLoader, BranchLo */ public CommitTransactionResult commitXATransactionCancel(InternalCDOXACommitContext xaContext, OMMonitor monitor); + /** + * @since 4.5 + */ + public CDOCommitInfo resetTransaction(int transactionID, int commitNumber); + public List<CDORemoteSession> getRemoteSessions(InternalCDORemoteSessionManager manager, boolean subscribe); /** diff --git a/plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/spi/cdo/InternalCDOSession.java b/plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/spi/cdo/InternalCDOSession.java index 520369d4d2..5741976f2a 100644 --- a/plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/spi/cdo/InternalCDOSession.java +++ b/plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/spi/cdo/InternalCDOSession.java @@ -312,6 +312,46 @@ public interface InternalCDOSession boolean computeChangeSets); /** + * @author Eike Stepper + * @since 4.5 + */ + public static final class CommitToken + { + private final int commitNumber; + + private final String threadName; + + public CommitToken(int commitNumber, String threadName) + { + this.commitNumber = commitNumber; + this.threadName = threadName; + } + + public int getCommitNumber() + { + return commitNumber; + } + + @Override + public boolean equals(Object obj) + { + return commitNumber == ((CommitToken)obj).commitNumber; + } + + @Override + public int hashCode() + { + return commitNumber; + } + + @Override + public String toString() + { + return "LocalCommit[" + getCommitNumber() + (threadName == null ? "" : ", " + threadName) + "]"; + } + } + + /** * A data structure that holds all input and output values of {@link InternalCDOSession#getMergeData(CDOBranchPoint, CDOBranchPoint, CDOBranchPoint, boolean) InternalCDOSession.getMergeData()}. * * @author Eike Stepper diff --git a/plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/spi/cdo/InternalCDOTransaction.java b/plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/spi/cdo/InternalCDOTransaction.java index 9aa0854d64..49f6fd206d 100644 --- a/plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/spi/cdo/InternalCDOTransaction.java +++ b/plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/spi/cdo/InternalCDOTransaction.java @@ -30,6 +30,7 @@ import org.eclipse.net4j.util.collection.Pair; import org.eclipse.emf.ecore.EObject; import org.eclipse.emf.spi.cdo.CDOSessionProtocol.CommitTransactionResult; +import org.eclipse.emf.spi.cdo.InternalCDOSession.CommitToken; import java.util.ArrayList; import java.util.List; @@ -48,6 +49,11 @@ public interface InternalCDOTransaction extends CDOTransaction, InternalCDOUserT public InternalCDOCommitContext createCommitContext(); /** + * @since 4.5 + */ + public CommitToken getCommitToken(); + + /** * @since 4.3 */ public boolean hasMultipleSavepoints(); |