diff options
42 files changed, 1345 insertions, 552 deletions
diff --git a/features/org.eclipse.emf.cdo.examples-feature/feature.xml b/features/org.eclipse.emf.cdo.examples-feature/feature.xml index 734e1c8d69..55b8d45110 100644 --- a/features/org.eclipse.emf.cdo.examples-feature/feature.xml +++ b/features/org.eclipse.emf.cdo.examples-feature/feature.xml @@ -12,7 +12,7 @@ <feature id="org.eclipse.emf.cdo.examples" label="%featureName" - version="4.2.300.qualifier" + version="4.2.400.qualifier" provider-name="%providerName" image="eclipse_update_120.jpg" license-feature="org.eclipse.emf.cdo.license" diff --git a/features/org.eclipse.emf.cdo.examples.installer-feature/feature.xml b/features/org.eclipse.emf.cdo.examples.installer-feature/feature.xml index a13883a477..b26894d077 100644 --- a/features/org.eclipse.emf.cdo.examples.installer-feature/feature.xml +++ b/features/org.eclipse.emf.cdo.examples.installer-feature/feature.xml @@ -12,7 +12,7 @@ <feature id="org.eclipse.emf.cdo.examples.installer" label="%featureName" - version="4.2.300.qualifier" + version="4.2.400.qualifier" provider-name="%providerName" image="eclipse_update_120.jpg" license-feature="org.eclipse.emf.cdo.license" diff --git a/features/org.eclipse.net4j.db.h2-feature/feature.xml b/features/org.eclipse.net4j.db.h2-feature/feature.xml index 6129b9a70f..a4297b74bf 100644 --- a/features/org.eclipse.net4j.db.h2-feature/feature.xml +++ b/features/org.eclipse.net4j.db.h2-feature/feature.xml @@ -12,7 +12,7 @@ <feature id="org.eclipse.net4j.db.h2" label="%featureName" - version="4.2.300.qualifier" + version="4.3.0.qualifier" provider-name="%providerName" license-feature="org.eclipse.emf.cdo.license" license-feature-version="0.0.0"> diff --git a/plugins/org.eclipse.emf.cdo.common/src/org/eclipse/emf/cdo/common/lob/CDOLobInfo.java b/plugins/org.eclipse.emf.cdo.common/src/org/eclipse/emf/cdo/common/lob/CDOLobInfo.java index 7ca3d06d66..e143751438 100644 --- a/plugins/org.eclipse.emf.cdo.common/src/org/eclipse/emf/cdo/common/lob/CDOLobInfo.java +++ b/plugins/org.eclipse.emf.cdo.common/src/org/eclipse/emf/cdo/common/lob/CDOLobInfo.java @@ -19,7 +19,7 @@ import java.text.MessageFormat; * * @author Eike Stepper * @since 4.0 - * @noextend This interface is not intended to be extended by clients. + * @noextend This class is not intended to be subclassed by clients. * @noinstantiate This class is not intended to be instantiated by clients. */ public class CDOLobInfo @@ -46,6 +46,16 @@ public class CDOLobInfo return id; } + /** + * A string representation of the {@link #getID() identifier} of this large object. + * + * @since 4.6 + */ + public final String getIDString() + { + return HexUtil.bytesToHex(id); + } + public final long getSize() { return size; @@ -54,6 +64,6 @@ public class CDOLobInfo @Override public String toString() { - return MessageFormat.format("{0}[id={1}, size={2}]", getClass().getSimpleName(), HexUtil.bytesToHex(id), size); + return MessageFormat.format("{0}[id={1}, size={2}]", getClass().getSimpleName(), getIDString(), size); } } diff --git a/plugins/org.eclipse.emf.cdo.common/src/org/eclipse/emf/cdo/common/lock/CDOLockChangeInfo.java b/plugins/org.eclipse.emf.cdo.common/src/org/eclipse/emf/cdo/common/lock/CDOLockChangeInfo.java index 4f683adbf7..327626a62d 100644 --- a/plugins/org.eclipse.emf.cdo.common/src/org/eclipse/emf/cdo/common/lock/CDOLockChangeInfo.java +++ b/plugins/org.eclipse.emf.cdo.common/src/org/eclipse/emf/cdo/common/lock/CDOLockChangeInfo.java @@ -31,7 +31,7 @@ import org.eclipse.net4j.util.concurrent.IRWLockManager.LockType; public interface CDOLockChangeInfo extends CDOBranchPoint { /** - * @return <code>true</code> if this instance signals that all {@link CDOLockState lockstates} must be invalidated, + * @return <code>true</code> if this instance signals that all {@link CDOLockState lock states} must be invalidated, * <code>false</code> otherwise */ public boolean isInvalidateAll(); @@ -43,29 +43,29 @@ public interface CDOLockChangeInfo extends CDOBranchPoint /** * @return The repository time at which the lock changes took place. This is only an informal indication; no formal - * relation (e.g. an ordering) with commit timestamps is guaranteed. + * relation (e.g. an ordering) with commit time stamps is guaranteed. */ public long getTimeStamp(); /** - * @return The view, represented as a {@link CDOLockOwner}, that authored the lock changes. + * @return the type of lock operation that caused the lock changes */ - public CDOLockOwner getLockOwner(); + public Operation getOperation(); /** - * @return The new lock states of the objects that were affected by the change + * @return the type of locks that were affected by the lock operation */ - public CDOLockState[] getLockStates(); + public LockType getLockType(); /** - * @return the type of lock operation that caused the lock changes + * @return The view, represented as a {@link CDOLockOwner}, that authored the lock changes. */ - public Operation getOperation(); + public CDOLockOwner getLockOwner(); /** - * @return the type of locks that were affected by the lock operation + * @return The new lock states of the objects that were affected by the change */ - public LockType getLockType(); + public CDOLockState[] getLockStates(); /** * Enumerates the possible locking operations. diff --git a/plugins/org.eclipse.emf.cdo.common/src/org/eclipse/emf/cdo/common/protocol/CDOProtocol.java b/plugins/org.eclipse.emf.cdo.common/src/org/eclipse/emf/cdo/common/protocol/CDOProtocol.java index 66b5a51bf1..19184c2bb1 100644 --- a/plugins/org.eclipse.emf.cdo.common/src/org/eclipse/emf/cdo/common/protocol/CDOProtocol.java +++ b/plugins/org.eclipse.emf.cdo.common/src/org/eclipse/emf/cdo/common/protocol/CDOProtocol.java @@ -14,6 +14,7 @@ import org.eclipse.emf.cdo.common.CDOCommonSession; import org.eclipse.emf.cdo.common.commit.CDOCommitInfo; import org.eclipse.emf.cdo.common.id.CDOID; import org.eclipse.emf.cdo.common.id.CDOIDUtil; +import org.eclipse.emf.cdo.common.lock.CDOLockChangeInfo; import org.eclipse.emf.cdo.common.revision.CDORevisionProvider; import org.eclipse.emf.cdo.common.security.CDOPermission; @@ -41,6 +42,9 @@ public interface CDOProtocol extends CDOProtocolConstants * @author Eike Stepper * @since 4.3 */ + /** + * @author Eike Stepper + */ public static final class CommitNotificationInfo { public static final byte IMPACT_NONE = 0; @@ -65,6 +69,8 @@ public interface CDOProtocol extends CDOProtocolConstants private boolean clearResourcePathCache; + private CDOLockChangeInfo lockChangeInfo; + public CommitNotificationInfo() { } @@ -89,6 +95,11 @@ public interface CDOProtocol extends CDOProtocolConstants newPermissions.put(id, permission); } } + + if (in.readBoolean()) + { + lockChangeInfo = in.readCDOLockChangeInfo(); + } } public void write(CDODataOutput out) throws IOException @@ -117,6 +128,16 @@ public interface CDOProtocol extends CDOProtocolConstants out.writeByte(bits); } } + + if (lockChangeInfo != null) + { + out.writeBoolean(true); + out.writeCDOLockChangeInfo(lockChangeInfo); + } + else + { + out.writeBoolean(false); + } } public int getSenderID() @@ -194,5 +215,21 @@ public interface CDOProtocol extends CDOProtocolConstants { this.clearResourcePathCache = clearResourcePathCache; } + + /** + * @since 4.6 + */ + public CDOLockChangeInfo getLockChangeInfo() + { + return lockChangeInfo; + } + + /** + * @since 4.6 + */ + public void setLockChangeInfo(CDOLockChangeInfo lockChangeInfo) + { + this.lockChangeInfo = lockChangeInfo; + } } } diff --git a/plugins/org.eclipse.emf.cdo.common/src/org/eclipse/emf/cdo/internal/common/lock/CDOLockChangeInfoImpl.java b/plugins/org.eclipse.emf.cdo.common/src/org/eclipse/emf/cdo/internal/common/lock/CDOLockChangeInfoImpl.java index d936507305..5957eeadb0 100644 --- a/plugins/org.eclipse.emf.cdo.common/src/org/eclipse/emf/cdo/internal/common/lock/CDOLockChangeInfoImpl.java +++ b/plugins/org.eclipse.emf.cdo.common/src/org/eclipse/emf/cdo/internal/common/lock/CDOLockChangeInfoImpl.java @@ -20,21 +20,23 @@ import org.eclipse.emf.cdo.spi.common.branch.CDOBranchAdjustable; import org.eclipse.net4j.util.concurrent.IRWLockManager.LockType; +import java.util.Arrays; + /** * @author Caspar De Groot */ -public class CDOLockChangeInfoImpl implements CDOLockChangeInfo, CDOBranchAdjustable +public final class CDOLockChangeInfoImpl implements CDOLockChangeInfo, CDOBranchAdjustable { private CDOBranchPoint branchPoint; - private final CDOLockOwner lockOwner; - - private final CDOLockState[] lockStates; - private final Operation operation; private final LockType lockType; + private final CDOLockOwner lockOwner; + + private final CDOLockState[] lockStates; + private final boolean isInvalidateAll; public CDOLockChangeInfoImpl(CDOBranchPoint branchPoint, CDOLockOwner lockOwner, CDOLockState[] lockStates, @@ -80,28 +82,48 @@ public class CDOLockChangeInfoImpl implements CDOLockChangeInfo, CDOBranchAdjust return branchPoint == null ? CDOBranchPoint.UNSPECIFIED_DATE : branchPoint.getTimeStamp(); } - public CDOLockOwner getLockOwner() + public Operation getOperation() { - return lockOwner; + return operation; } - public CDOLockState[] getLockStates() + public LockType getLockType() { - return lockStates; + return lockType; } - public Operation getOperation() + public CDOLockOwner getLockOwner() { - return operation; + return lockOwner; } - public LockType getLockType() + public CDOLockState[] getLockStates() { - return lockType; + return lockStates; } public boolean isInvalidateAll() { return isInvalidateAll; } + + @Override + public String toString() + { + StringBuilder builder = new StringBuilder(); + builder.append("CDOLockChangeInfo[branchPoint="); + builder.append(branchPoint); + builder.append(", operation="); + builder.append(operation); + builder.append(", lockType="); + builder.append(lockType); + builder.append(", lockOwner="); + builder.append(lockOwner); + builder.append(", lockStates="); + builder.append(Arrays.toString(lockStates)); + builder.append(", invalidateAll="); + builder.append(isInvalidateAll); + builder.append("]"); + return builder.toString(); + } } diff --git a/plugins/org.eclipse.emf.cdo.common/src/org/eclipse/emf/cdo/internal/common/lock/CDOLockStateImpl.java b/plugins/org.eclipse.emf.cdo.common/src/org/eclipse/emf/cdo/internal/common/lock/CDOLockStateImpl.java index 4199f4245a..5cd0e2580b 100644 --- a/plugins/org.eclipse.emf.cdo.common/src/org/eclipse/emf/cdo/internal/common/lock/CDOLockStateImpl.java +++ b/plugins/org.eclipse.emf.cdo.common/src/org/eclipse/emf/cdo/internal/common/lock/CDOLockStateImpl.java @@ -300,10 +300,10 @@ public class CDOLockStateImpl implements InternalCDOLockState @Override public String toString() { - StringBuilder builder = new StringBuilder("CDOLockState\n lockedObject="); + StringBuilder builder = new StringBuilder("CDOLockState[lockedObject="); builder.append(lockedObject); - builder.append("\n readLockOwners="); + builder.append(", readLockOwners="); if (readLockOwners != null && readLockOwners.size() > 0) { boolean first = true; @@ -328,10 +328,10 @@ public class CDOLockStateImpl implements InternalCDOLockState builder.append("NONE"); } - builder.append("\n writeLockOwner="); + builder.append(", writeLockOwner="); builder.append(writeLockOwner != null ? writeLockOwner : "NONE"); - builder.append("\n writeOptionOwner="); + builder.append(", writeOptionOwner="); builder.append(writeOptionOwner != null ? writeOptionOwner : "NONE"); return builder.toString(); diff --git a/plugins/org.eclipse.emf.cdo.examples.installer/META-INF/MANIFEST.MF b/plugins/org.eclipse.emf.cdo.examples.installer/META-INF/MANIFEST.MF index 49ccba010b..78adcba70e 100644 --- a/plugins/org.eclipse.emf.cdo.examples.installer/META-INF/MANIFEST.MF +++ b/plugins/org.eclipse.emf.cdo.examples.installer/META-INF/MANIFEST.MF @@ -1,7 +1,7 @@ Manifest-Version: 1.0 Bundle-ManifestVersion: 2 Bundle-SymbolicName: org.eclipse.emf.cdo.examples.installer;singleton:=true -Bundle-Version: 4.1.400.qualifier +Bundle-Version: 4.1.500.qualifier Bundle-Name: %pluginName Bundle-Vendor: %providerName Bundle-ActivationPolicy: lazy diff --git a/plugins/org.eclipse.emf.cdo.examples.installer/examples/org.eclipse.emf.cdo.examples.master/META-INF/MANIFEST.MF b/plugins/org.eclipse.emf.cdo.examples.installer/examples/org.eclipse.emf.cdo.examples.master/META-INF/MANIFEST.MF index b4cb289830..39ce6b2b58 100644 --- a/plugins/org.eclipse.emf.cdo.examples.installer/examples/org.eclipse.emf.cdo.examples.master/META-INF/MANIFEST.MF +++ b/plugins/org.eclipse.emf.cdo.examples.installer/examples/org.eclipse.emf.cdo.examples.master/META-INF/MANIFEST.MF @@ -1,7 +1,7 @@ Manifest-Version: 1.0 Bundle-ManifestVersion: 2 Bundle-SymbolicName: org.eclipse.emf.cdo.examples.master;singleton:=true -Bundle-Version: 4.1.300.qualifier +Bundle-Version: 4.1.400.qualifier Bundle-Name: %pluginName Bundle-Vendor: %providerName Bundle-ActivationPolicy: lazy diff --git a/plugins/org.eclipse.emf.cdo.examples.installer/examples/org.eclipse.emf.cdo.examples.master/config/cdo-server.xml b/plugins/org.eclipse.emf.cdo.examples.installer/examples/org.eclipse.emf.cdo.examples.master/config/cdo-server.xml index 67d08a070d..f953dd6469 100644 --- a/plugins/org.eclipse.emf.cdo.examples.installer/examples/org.eclipse.emf.cdo.examples.master/config/cdo-server.xml +++ b/plugins/org.eclipse.emf.cdo.examples.installer/examples/org.eclipse.emf.cdo.examples.master/config/cdo-server.xml @@ -74,7 +74,7 @@ <dbAdapter name="h2"/> <dataSource class="org.h2.jdbcx.JdbcDataSource" - URL="jdbc:h2:/develop/cdo-master/h2/big"/> + URL="jdbc:h2:/develop/cdo-master/h2/big;LOCK_TIMEOUT=10000;TRACE_LEVEL_FILE=0"/> <!-- Example: <dbAdapter name="derby-embedded"/> diff --git a/plugins/org.eclipse.emf.cdo.examples.master/META-INF/MANIFEST.MF b/plugins/org.eclipse.emf.cdo.examples.master/META-INF/MANIFEST.MF index b4cb289830..39ce6b2b58 100644 --- a/plugins/org.eclipse.emf.cdo.examples.master/META-INF/MANIFEST.MF +++ b/plugins/org.eclipse.emf.cdo.examples.master/META-INF/MANIFEST.MF @@ -1,7 +1,7 @@ Manifest-Version: 1.0 Bundle-ManifestVersion: 2 Bundle-SymbolicName: org.eclipse.emf.cdo.examples.master;singleton:=true -Bundle-Version: 4.1.300.qualifier +Bundle-Version: 4.1.400.qualifier Bundle-Name: %pluginName Bundle-Vendor: %providerName Bundle-ActivationPolicy: lazy diff --git a/plugins/org.eclipse.emf.cdo.examples.master/config/cdo-server.xml b/plugins/org.eclipse.emf.cdo.examples.master/config/cdo-server.xml index 67d08a070d..f953dd6469 100644 --- a/plugins/org.eclipse.emf.cdo.examples.master/config/cdo-server.xml +++ b/plugins/org.eclipse.emf.cdo.examples.master/config/cdo-server.xml @@ -74,7 +74,7 @@ <dbAdapter name="h2"/> <dataSource class="org.h2.jdbcx.JdbcDataSource" - URL="jdbc:h2:/develop/cdo-master/h2/big"/> + URL="jdbc:h2:/develop/cdo-master/h2/big;LOCK_TIMEOUT=10000;TRACE_LEVEL_FILE=0"/> <!-- Example: <dbAdapter name="derby-embedded"/> diff --git a/plugins/org.eclipse.emf.cdo.server.product/META-INF/MANIFEST.MF b/plugins/org.eclipse.emf.cdo.server.product/META-INF/MANIFEST.MF index dd63b31d06..882bf761aa 100644 --- a/plugins/org.eclipse.emf.cdo.server.product/META-INF/MANIFEST.MF +++ b/plugins/org.eclipse.emf.cdo.server.product/META-INF/MANIFEST.MF @@ -1,7 +1,7 @@ Manifest-Version: 1.0 Bundle-ManifestVersion: 2 Bundle-SymbolicName: org.eclipse.emf.cdo.server.product;singleton:=true -Bundle-Version: 4.1.400.qualifier +Bundle-Version: 4.1.500.qualifier Bundle-Name: %pluginName Bundle-Vendor: %providerName Bundle-Localization: plugin diff --git a/plugins/org.eclipse.emf.cdo.server.product/config/cdo-server.xml b/plugins/org.eclipse.emf.cdo.server.product/config/cdo-server.xml index ac1d78fc63..7395e3c310 100644 --- a/plugins/org.eclipse.emf.cdo.server.product/config/cdo-server.xml +++ b/plugins/org.eclipse.emf.cdo.server.product/config/cdo-server.xml @@ -74,7 +74,7 @@ <dbAdapter name="h2"/> <dataSource class="org.h2.jdbcx.JdbcDataSource" - URL="jdbc:h2:/develop/cdo-master/h2/big"/> + URL="jdbc:h2:/develop/cdo-master/h2/big;LOCK_TIMEOUT=10000;TRACE_LEVEL_FILE=0"/> <!-- Example: <dbAdapter name="derby-embedded"/> diff --git a/plugins/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/internal/server/ServerCDOView.java b/plugins/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/internal/server/ServerCDOView.java index 6a0b132cf4..bae348f0f4 100644 --- a/plugins/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/internal/server/ServerCDOView.java +++ b/plugins/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/internal/server/ServerCDOView.java @@ -273,6 +273,7 @@ public class ServerCDOView extends AbstractCDOView implements org.eclipse.emf.cd throw new UnsupportedOperationException(); } + @Deprecated public void invalidate(CDOBranch branch, long lastUpdateTime, List<CDORevisionKey> allChangedObjects, List<CDOIDAndVersion> allDetachedObjects, Map<CDOID, InternalCDORevision> oldRevisions, boolean async, boolean clearResourcePathCache) @@ -280,6 +281,11 @@ public class ServerCDOView extends AbstractCDOView implements org.eclipse.emf.cd throw new UnsupportedOperationException(); } + public void invalidate(ViewInvalidationData invalidationData) + { + throw new UnsupportedOperationException(); + } + public void handleLockNotification(InternalCDOView sender, CDOLockChangeInfo lockChangeInfo) { // Do nothing @@ -1044,12 +1050,18 @@ public class ServerCDOView extends AbstractCDOView implements org.eclipse.emf.cd throw new UnsupportedOperationException(); } + @Deprecated public void invalidate(CDOCommitInfo commitInfo, InternalCDOTransaction sender, boolean clearResourcePathCache, byte securityImpact, Map<CDOID, CDOPermission> newPermissions) { throw new UnsupportedOperationException(); } + public void invalidate(InvalidationData invalidationData) + { + throw new UnsupportedOperationException(); + } + @Deprecated public void handleCommitNotification(CDOCommitInfo commitInfo) { diff --git a/plugins/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/internal/server/Session.java b/plugins/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/internal/server/Session.java index a230071147..b1e9b347e2 100644 --- a/plugins/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/internal/server/Session.java +++ b/plugins/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/internal/server/Session.java @@ -528,6 +528,16 @@ public class Session extends Container<IView> implements InternalSession sessionNotificationInfo.setNewPermissions(sessionCommitInfo.getNewPermissions()); sessionNotificationInfo.setSecurityImpact(securityImpact); + CDOLockChangeInfo lockChangeInfo = notificationInfo.getLockChangeInfo(); + if (lockChangeInfo != null) + { + Object lockNotificationRequired = isLockNotificationRequired(lockChangeInfo); + if (lockNotificationRequired != null) + { + sessionNotificationInfo.setLockChangeInfo(lockChangeInfo); + } + } + protocol.sendCommitNotification(sessionNotificationInfo); synchronized (lastUpdateTimeLock) @@ -541,40 +551,57 @@ public class Session extends Container<IView> implements InternalSession { if (protocol != null) { - if (options().getLockNotificationMode() == LockNotificationMode.ALWAYS) + Object lockNotificationRequired = isLockNotificationRequired(lockChangeInfo); + if (lockNotificationRequired == Boolean.TRUE) { protocol.sendLockNotification(lockChangeInfo); return; } - if (options().getLockNotificationMode() == LockNotificationMode.IF_REQUIRED_BY_VIEWS) + if (lockNotificationRequired instanceof InternalView) { - // If this session has one (or more) views configured for this branch, - // only then do we send the lockChangeInfo. - for (InternalView view : getViews()) + InternalView view = (InternalView)lockNotificationRequired; + + try { - try + protocol.sendLockNotification(lockChangeInfo); + } + catch (Exception ex) + { + if (!view.isClosed()) { - if (view.options().isLockNotificationEnabled()) - { - CDOBranch affectedBranch = lockChangeInfo.getBranch(); - if (view.getBranch() == affectedBranch || affectedBranch == null) - { - protocol.sendLockNotification(lockChangeInfo); - break; - } - } + OM.LOG.warn("A problem occured while notifying view " + view, ex); } - catch (Exception ex) + } + } + } + } + + private Object isLockNotificationRequired(CDOLockChangeInfo lockChangeInfo) + { + LockNotificationMode lockNotificationMode = options().getLockNotificationMode(); + if (lockNotificationMode == LockNotificationMode.ALWAYS) + { + return Boolean.TRUE; + } + + if (lockNotificationMode == LockNotificationMode.IF_REQUIRED_BY_VIEWS) + { + // We send the lockChangeInfo only if this session has one (or more) views configured for this branch. + for (InternalView view : getViews()) + { + if (view.options().isLockNotificationEnabled()) + { + CDOBranch affectedBranch = lockChangeInfo.getBranch(); + if (view.getBranch() == affectedBranch || affectedBranch == null) { - if (!view.isClosed()) - { - OM.LOG.warn("A problem occured while notifying view " + view, ex); - } + return view; } } } } + + return null; } private boolean isDeltaNeeded(CDOID id, InternalView[] views) 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 b20e5a377b..139fda152a 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 @@ -177,8 +177,6 @@ public class TransactionCommitContext implements InternalCommitContext private List<CDOIDReference> xRefs; - private final List<LockState<Object, IView>> postCommitLockStates = new ArrayList<LockState<Object, IView>>(); - private boolean hasChanges; private boolean serializingCommits; @@ -195,6 +193,10 @@ public class TransactionCommitContext implements InternalCommitContext private CommitNotificationInfo commitNotificationInfo = new CommitNotificationInfo(); + private CDOLockChangeInfo lockChangeInfo; + + private final List<LockState<Object, IView>> postCommitLockStates = new ArrayList<LockState<Object, IView>>(); + public TransactionCommitContext(InternalTransaction transaction) { this.transaction = transaction; @@ -875,6 +877,7 @@ public class TransactionCommitContext implements InternalCommitContext { commitNotificationInfo.setSender(transaction.getSession()); commitNotificationInfo.setRevisionProvider(this); + commitNotificationInfo.setLockChangeInfo(lockChangeInfo); if (success) { @@ -1353,9 +1356,7 @@ public class TransactionCommitContext implements InternalCommitContext if (!postCommitLockStates.isEmpty()) { - // TODO (CD) Does doing this here make sense? - // The commit notifications get sent later, from postCommit. - sendLockNotifications(postCommitLockStates); + lockChangeInfo = createLockChangeInfo(postCommitLockStates); } repository.notifyWriteAccessHandlers(transaction, this, false, monitor.fork()); @@ -1456,15 +1457,12 @@ public class TransactionCommitContext implements InternalCommitContext } } - protected void sendLockNotifications(List<LockState<Object, IView>> newLockStates) + protected CDOLockChangeInfo createLockChangeInfo(List<LockState<Object, IView>> newLockStates) { - CDOLockState[] newStates = Repository.toCDOLockStates(newLockStates); - long timeStamp = getTimeStamp(); - Operation unlock = Operation.UNLOCK; + CDOLockState[] newStates = Repository.toCDOLockStates(newLockStates); - CDOLockChangeInfo info = CDOLockUtil.createLockChangeInfo(timeStamp, transaction, branch, unlock, null, newStates); - repository.getSessionManager().sendLockNotification(transaction.getSession(), info); + return CDOLockUtil.createLockChangeInfo(timeStamp, transaction, branch, Operation.UNLOCK, null, newStates); } protected void addNewPackageUnits(OMMonitor monitor) diff --git a/plugins/org.eclipse.emf.cdo.tests.db/META-INF/MANIFEST.MF b/plugins/org.eclipse.emf.cdo.tests.db/META-INF/MANIFEST.MF index 47e8ff1d5d..c0db21b33b 100644 --- a/plugins/org.eclipse.emf.cdo.tests.db/META-INF/MANIFEST.MF +++ b/plugins/org.eclipse.emf.cdo.tests.db/META-INF/MANIFEST.MF @@ -1,7 +1,7 @@ Manifest-Version: 1.0 Bundle-ManifestVersion: 2 Bundle-SymbolicName: org.eclipse.emf.cdo.tests.db;singleton:=true -Bundle-Version: 4.0.500.qualifier +Bundle-Version: 4.0.600.qualifier Bundle-Name: %pluginName Bundle-Vendor: %providerName Bundle-Localization: plugin @@ -27,10 +27,10 @@ Import-Package: com.mysql.jdbc.jdbc2.optional;version="[5.0.0,6.0.0)", org.hsqldb.jdbc;version="[2.0.0,3.0.0)", org.postgresql.ds;version="[9.0.0,10.0.0)", org.postgresql.ds.common;version="[9.0.0,10.0.0)" -Export-Package: org.eclipse.emf.cdo.tests.db;version="4.0.500";x-friends:="org.eclipse.emf.cdo.tests.all", - org.eclipse.emf.cdo.tests.db.bundle;version="4.0.500";x-internal:=true, - org.eclipse.emf.cdo.tests.db.capabilities;version="4.0.500";x-friends:="org.eclipse.emf.cdo.tests.all", - org.eclipse.emf.cdo.tests.db.offline;version="4.0.500";x-friends:="org.eclipse.emf.cdo.tests.all", - org.eclipse.emf.cdo.tests.db.performance;version="4.0.500";x-friends:="org.eclipse.emf.cdo.tests.all", - org.eclipse.emf.cdo.tests.db.revisioncache;version="4.0.500";x-friends:="org.eclipse.emf.cdo.tests.all", - org.eclipse.emf.cdo.tests.db.verifier;version="4.0.500";x-friends:="org.eclipse.emf.cdo.tests.all" +Export-Package: org.eclipse.emf.cdo.tests.db;version="4.0.600";x-friends:="org.eclipse.emf.cdo.tests.all", + org.eclipse.emf.cdo.tests.db.bundle;version="4.0.600";x-internal:=true, + org.eclipse.emf.cdo.tests.db.capabilities;version="4.0.600";x-friends:="org.eclipse.emf.cdo.tests.all", + org.eclipse.emf.cdo.tests.db.offline;version="4.0.600";x-friends:="org.eclipse.emf.cdo.tests.all", + org.eclipse.emf.cdo.tests.db.performance;version="4.0.600";x-friends:="org.eclipse.emf.cdo.tests.all", + org.eclipse.emf.cdo.tests.db.revisioncache;version="4.0.600";x-friends:="org.eclipse.emf.cdo.tests.all", + org.eclipse.emf.cdo.tests.db.verifier;version="4.0.600";x-friends:="org.eclipse.emf.cdo.tests.all" diff --git a/plugins/org.eclipse.emf.cdo.tests.db/src/org/eclipse/emf/cdo/tests/db/H2Config.java b/plugins/org.eclipse.emf.cdo.tests.db/src/org/eclipse/emf/cdo/tests/db/H2Config.java index cf30e97a63..22e78832e5 100644 --- a/plugins/org.eclipse.emf.cdo.tests.db/src/org/eclipse/emf/cdo/tests/db/H2Config.java +++ b/plugins/org.eclipse.emf.cdo.tests.db/src/org/eclipse/emf/cdo/tests/db/H2Config.java @@ -15,6 +15,7 @@ import org.eclipse.emf.cdo.common.CDOCommonRepository.IDGenerationLocation; import org.eclipse.net4j.db.IDBAdapter; import org.eclipse.net4j.db.h2.H2Adapter; import org.eclipse.net4j.util.io.IOUtil; +import org.eclipse.net4j.util.io.TMPUtil; import org.h2.jdbcx.JdbcDataSource; @@ -62,21 +63,41 @@ public class H2Config extends DBConfig IOUtil.delete(reusableFolder); } + String url = "jdbc:h2:" + reusableFolder.getAbsolutePath() + "/h2test;LOCK_TIMEOUT=10000;TRACE_LEVEL_FILE=0"; + if (defaultDataSource == null) { defaultDataSource = new JdbcDataSource(); - defaultDataSource.setURL("jdbc:h2:" + reusableFolder.getAbsolutePath() + "/h2test;LOCK_TIMEOUT=10000"); + defaultDataSource.setURL(url); } H2Adapter.createSchema(defaultDataSource, repoName, !isRestarting()); JdbcDataSource dataSource = new JdbcDataSource(); - dataSource.setURL("jdbc:h2:" + reusableFolder.getAbsolutePath() + "/h2test;LOCK_TIMEOUT=10000;SCHEMA=" + repoName); + dataSource.setURL(url + ";SCHEMA=" + repoName); return dataSource; } protected File createDBFolder() { - return getCurrentTest().createTempFolder("h2_", "_test"); + return TMPUtil.createTempFolder("h2_", "_test"); + } + + @Override + public void mainSuiteFinished() throws Exception + { + deactivateRepositories(); + + // if (defaultDataSource != null) + // { + // H2Adapter.shutdown(defaultDataSource); + // defaultDataSource = null; + // } + + if (reusableFolder != null) + { + IOUtil.delete(reusableFolder); + reusableFolder = null; + } } } diff --git a/plugins/org.eclipse.emf.cdo.tests/src/org/eclipse/emf/cdo/tests/LockingNotificationsTest.java b/plugins/org.eclipse.emf.cdo.tests/src/org/eclipse/emf/cdo/tests/LockingNotificationsTest.java index c484fbc925..a680c7aade 100644 --- a/plugins/org.eclipse.emf.cdo.tests/src/org/eclipse/emf/cdo/tests/LockingNotificationsTest.java +++ b/plugins/org.eclipse.emf.cdo.tests/src/org/eclipse/emf/cdo/tests/LockingNotificationsTest.java @@ -39,13 +39,6 @@ import java.util.List; */ public class LockingNotificationsTest extends AbstractLockingTest { - private CDOView openViewWithLockNotifications(CDOSession session, CDOBranch branch) - { - CDOView view = branch != null ? session.openView(branch) : session.openView(); - view.options().setLockNotificationEnabled(true); - return view; - } - /** * FIXME Disabled until bug 358603 is addressed. */ @@ -59,24 +52,6 @@ public class LockingNotificationsTest extends AbstractLockingTest sameBranchDifferentSession(LockReleaseMode.AUTO); } - private void sameBranchDifferentSession(LockReleaseMode mode) throws CommitException - { - CDOSession session1 = openSession(); - CDOSession session2 = openSession(); - CDOView controlView = openViewWithLockNotifications(session2, null); - if (mode == LockReleaseMode.EXPLICIT) - { - withExplicitRelease(session1, controlView, true); - } - else if (mode == LockReleaseMode.AUTO) - { - withAutoRelease(session1, controlView, true); - } - - session1.close(); - session2.close(); - } - public void testSameBranchSameSession_explicitRelease() throws CommitException { sameBranchSameSession(LockReleaseMode.EXPLICIT); @@ -87,22 +62,6 @@ public class LockingNotificationsTest extends AbstractLockingTest sameBranchSameSession(LockReleaseMode.AUTO); } - private void sameBranchSameSession(LockReleaseMode mode) throws CommitException - { - CDOSession session1 = openSession(); - CDOView controlView = openViewWithLockNotifications(session1, null); - if (mode == LockReleaseMode.EXPLICIT) - { - withExplicitRelease(session1, controlView, true); - } - else if (mode == LockReleaseMode.AUTO) - { - withAutoRelease(session1, controlView, true); - } - - session1.close(); - } - @Requires(IRepositoryConfig.CAPABILITY_BRANCHING) public void testDifferentBranchDifferentSession() throws CommitException { @@ -115,52 +74,188 @@ public class LockingNotificationsTest extends AbstractLockingTest differentBranchDifferentSession(LockReleaseMode.AUTO); } - private void differentBranchDifferentSession(LockReleaseMode mode) throws CommitException + @Requires(IRepositoryConfig.CAPABILITY_BRANCHING) + public void testDifferentBranchSameSession() throws CommitException + { + differentBranchSameSession(LockReleaseMode.EXPLICIT); + } + + @Requires(IRepositoryConfig.CAPABILITY_BRANCHING) + public void testDifferentBranchSameSession_autoRelease() throws CommitException + { + differentBranchSameSession(LockReleaseMode.AUTO); + } + + public void testEnableDisableNotifications() throws CommitException + { + CDOSession session1 = openSession(); + CDOSession session2 = openSession(); + CDOView controlView = session2.openView(); + withExplicitRelease(session1, controlView, false); + + controlView.options().setLockNotificationEnabled(true); + withExplicitRelease(session1, controlView, true); + + controlView.options().setLockNotificationEnabled(false); + withExplicitRelease(session1, controlView, false); + + session1.close(); + session2.close(); + } + + public void testEnableDisableNotificationsSameSession() throws CommitException { CDOSession session1 = openSession(); - CDOBranch subBranch = session1.getBranchManager().getMainBranch().createBranch("sub1"); + CDOView controlView = session1.openView(); + withExplicitRelease(session1, controlView, false); + + controlView.options().setLockNotificationEnabled(true); + withExplicitRelease(session1, controlView, true); + + controlView.options().setLockNotificationEnabled(false); + withExplicitRelease(session1, controlView, false); + + session1.close(); + } + + public void testLockStateHeldByDurableView() throws CommitException + { + skipStoreWithoutDurableLocking(); + + { + CDOSession session1 = openSession(); + CDOTransaction tx1 = session1.openTransaction(); + tx1.enableDurableLocking(); + CDOResource res1 = tx1.createResource(getResourcePath("r1")); + Company company1 = getModel1Factory().createCompany(); + res1.getContents().add(company1); + tx1.commit(); + + CDOUtil.getCDOObject(company1).cdoWriteLock().lock(); + tx1.close(); + session1.close(); + } + CDOSession session2 = openSession(); - CDOView controlView = openViewWithLockNotifications(session2, subBranch); + CDOView controlView = session2.openView(); + CDOResource resource = controlView.getResource(getResourcePath("r1")); + Company company1 = (Company)resource.getContents().get(0); + CDOObject cdoObj = CDOUtil.getCDOObject(company1); + assertEquals(true, cdoObj.cdoWriteLock().isLockedByOthers()); + assertEquals(true, cdoObj.cdoLockState().getWriteLockOwner().isDurableView()); + session2.close(); + } + + public void testLockStateNewAndTransient() throws CommitException + { + Company company1 = getModel1Factory().createCompany(); + CDOObject cdoObj = CDOUtil.getCDOObject(company1); + assertTransient(cdoObj); + assertNull(cdoObj.cdoLockState()); + + CDOSession session1 = openSession(); + CDOTransaction tx1 = session1.openTransaction(); + CDOResource res1 = tx1.createResource(getResourcePath("r1")); + res1.getContents().add(company1); + assertNew(cdoObj, tx1); + assertNotNull(cdoObj.cdoLockState()); + + res1.getContents().remove(company1); + assertTransient(cdoObj); + assertNull(cdoObj.cdoLockState()); + + res1.getContents().add(company1); + tx1.commit(); + assertClean(cdoObj, tx1); + assertNotNull(cdoObj.cdoLockState()); + + res1.getContents().remove(company1); + assertTransient(cdoObj); + assertNull(cdoObj.cdoLockState()); + + session1.close(); + } + + private CDOView openViewWithLockNotifications(CDOSession session, CDOBranch branch) + { + CDOView view = branch != null ? session.openView(branch) : session.openView(); + view.options().setLockNotificationEnabled(true); + return view; + } + + private void sameBranchDifferentSession(LockReleaseMode mode) throws CommitException + { + CDOSession session = openSession(); + CDOSession controlSession = openSession(); + CDOView controlView = openViewWithLockNotifications(controlSession, null); + if (mode == LockReleaseMode.EXPLICIT) { - withExplicitRelease(session1, controlView, false); + withExplicitRelease(session, controlView, true); } else if (mode == LockReleaseMode.AUTO) { - withAutoRelease(session1, controlView, false); + withAutoRelease(session, controlView, true); } - session1.close(); - session2.close(); + controlSession.close(); + session.close(); } - @Requires(IRepositoryConfig.CAPABILITY_BRANCHING) - public void testDifferentBranchSameSession() throws CommitException + private void sameBranchSameSession(LockReleaseMode mode) throws CommitException { - differentBranchSameSession(LockReleaseMode.EXPLICIT); + CDOSession session = openSession(); + CDOView controlView = openViewWithLockNotifications(session, null); + + if (mode == LockReleaseMode.EXPLICIT) + { + withExplicitRelease(session, controlView, true); + } + else if (mode == LockReleaseMode.AUTO) + { + withAutoRelease(session, controlView, true); + } + + session.close(); } - @Requires(IRepositoryConfig.CAPABILITY_BRANCHING) - public void testDifferentBranchSameSession_autoRelease() throws CommitException + private void differentBranchDifferentSession(LockReleaseMode mode) throws CommitException { - differentBranchSameSession(LockReleaseMode.AUTO); + CDOSession session = openSession(); + CDOBranch subBranch = session.getBranchManager().getMainBranch().createBranch("sub1"); + + CDOSession controlSession = openSession(); + CDOView controlView = openViewWithLockNotifications(controlSession, subBranch); + + if (mode == LockReleaseMode.EXPLICIT) + { + withExplicitRelease(session, controlView, false); + } + else if (mode == LockReleaseMode.AUTO) + { + withAutoRelease(session, controlView, false); + } + + controlSession.close(); + session.close(); } private void differentBranchSameSession(LockReleaseMode mode) throws CommitException { - CDOSession session1 = openSession(); - CDOBranch subBranch = session1.getBranchManager().getMainBranch().createBranch("sub2"); - CDOView controlView = openViewWithLockNotifications(session1, subBranch); + CDOSession session = openSession(); + CDOBranch subBranch = session.getBranchManager().getMainBranch().createBranch("sub2"); + CDOView controlView = openViewWithLockNotifications(session, subBranch); + if (mode == LockReleaseMode.EXPLICIT) { - withExplicitRelease(session1, controlView, false); + withExplicitRelease(session, controlView, false); } else if (mode == LockReleaseMode.AUTO) { - withAutoRelease(session1, controlView, false); + withAutoRelease(session, controlView, false); } - session1.close(); + session.close(); } private void withExplicitRelease(CDOSession session1, CDOView controlView, boolean mustReceiveNotifications) @@ -179,7 +274,6 @@ public class LockingNotificationsTest extends AbstractLockingTest tx1.commit(); CDOObject cdoCompany = CDOUtil.getCDOObject(company); - CDOObject cdoCompanyInControlView = null; if (mustReceiveNotifications) { @@ -199,7 +293,7 @@ public class LockingNotificationsTest extends AbstractLockingTest CDOLockState[] lockStates = event.getLockStates(); assertEquals(1, lockStates.length); - assertLockedObject(cdoCompany, lockStates[0].getLockedObject()); + assertLockedObject(cdoCompany, lockStates[0]); assertLockOwner(tx1, lockStates[0].getWriteLockOwner()); assertEquals(cdoCompanyInControlView.cdoLockState(), lockStates[0]); } @@ -208,7 +302,6 @@ public class LockingNotificationsTest extends AbstractLockingTest if (mustReceiveNotifications) { controlViewListener.waitFor(2); - assertEquals(2, controlViewListener.getEvents().size()); CDOViewLocksChangedEvent event = (CDOViewLocksChangedEvent)controlViewListener.getEvents().get(1); @@ -216,7 +309,7 @@ public class LockingNotificationsTest extends AbstractLockingTest CDOLockState[] lockStates = event.getLockStates(); assertEquals(1, lockStates.length); - assertLockedObject(cdoCompany, lockStates[0].getLockedObject()); + assertLockedObject(cdoCompany, lockStates[0]); assertNull(lockStates[0].getWriteLockOwner()); assertEquals(cdoCompanyInControlView.cdoLockState(), lockStates[0]); } @@ -234,7 +327,7 @@ public class LockingNotificationsTest extends AbstractLockingTest CDOLockState[] lockStates = event.getLockStates(); assertEquals(1, lockStates.length); - assertLockedObject(cdoCompany, lockStates[0].getLockedObject()); + assertLockedObject(cdoCompany, lockStates[0]); assertEquals(1, lockStates[0].getReadLockOwners().size()); CDOLockOwner tx1Lo = CDOLockUtil.createLockOwner(tx1); assertEquals(true, lockStates[0].getReadLockOwners().contains(tx1Lo)); @@ -245,7 +338,6 @@ public class LockingNotificationsTest extends AbstractLockingTest if (mustReceiveNotifications) { controlViewListener.waitFor(4); - assertEquals(4, controlViewListener.getEvents().size()); CDOViewLocksChangedEvent event = (CDOViewLocksChangedEvent)controlViewListener.getEvents().get(3); @@ -270,7 +362,7 @@ public class LockingNotificationsTest extends AbstractLockingTest CDOLockState[] lockStates = event.getLockStates(); assertEquals(1, lockStates.length); - assertLockedObject(cdoCompany, lockStates[0].getLockedObject()); + assertLockedObject(cdoCompany, lockStates[0]); assertLockOwner(tx1, lockStates[0].getWriteOptionOwner()); assertEquals(cdoCompanyInControlView.cdoLockState(), lockStates[0]); } @@ -279,7 +371,6 @@ public class LockingNotificationsTest extends AbstractLockingTest if (mustReceiveNotifications) { controlViewListener.waitFor(6); - assertEquals(6, controlViewListener.getEvents().size()); CDOViewLocksChangedEvent event = (CDOViewLocksChangedEvent)controlViewListener.getEvents().get(5); @@ -287,7 +378,7 @@ public class LockingNotificationsTest extends AbstractLockingTest CDOLockState[] lockStates = event.getLockStates(); assertEquals(1, lockStates.length); - assertLockedObject(cdoCompany, lockStates[0].getLockedObject()); + assertLockedObject(cdoCompany, lockStates[0]); assertNull(lockStates[0].getWriteOptionOwner()); assertEquals(cdoCompanyInControlView.cdoLockState(), lockStates[0]); } @@ -301,153 +392,79 @@ public class LockingNotificationsTest extends AbstractLockingTest } } - private void withAutoRelease(CDOSession session1, CDOView controlView, boolean mustReceiveNotifications) + private void withAutoRelease(CDOSession session, CDOView controlView, boolean mustReceiveNotifications) throws CommitException { TestListener2 controlViewListener = new TestListener2(CDOViewLocksChangedEvent.class); controlView.addListener(controlViewListener); - CDOTransaction tx1 = session1.openTransaction(); - tx1.options().setAutoReleaseLocksEnabled(true); + CDOTransaction transaction = session.openTransaction(); + transaction.options().setAutoReleaseLocksEnabled(true); - CDOResource res1 = tx1.getOrCreateResource(getResourcePath("r1")); - res1.getContents().clear(); + CDOResource resource = transaction.getOrCreateResource(getResourcePath("r1")); + resource.getContents().clear(); Company company = getModel1Factory().createCompany(); - res1.getContents().add(company); - tx1.commit(); + resource.getContents().add(company); + transaction.commit(); - implicitRelease(company, LockType.WRITE, tx1, controlViewListener, mustReceiveNotifications); - implicitRelease(company, LockType.READ, tx1, controlViewListener, mustReceiveNotifications); - implicitRelease(company, LockType.OPTION, tx1, controlViewListener, mustReceiveNotifications); + implicitRelease(company, LockType.WRITE, transaction, controlViewListener, mustReceiveNotifications); + implicitRelease(company, LockType.READ, transaction, controlViewListener, mustReceiveNotifications); + implicitRelease(company, LockType.OPTION, transaction, controlViewListener, mustReceiveNotifications); } - private void implicitRelease(Company company, LockType type, CDOTransaction tx, TestListener2 controlViewListener, - boolean mustReceiveNotifications) throws CommitException + private void implicitRelease(Company company, LockType type, CDOTransaction transaction, + TestListener2 controlViewListener, boolean mustReceiveNotifications) throws CommitException { - CDOViewLocksChangedEvent e; + CDOViewLocksChangedEvent event; CDOObject cdoCompany = CDOUtil.getCDOObject(company); - company.setName(company.getName() + "x"); // Make name field dirty + company.setName(company.getName() + "x"); // Make object DIRTY. cdoCompany.cdoWriteLock().lock(); if (mustReceiveNotifications) { controlViewListener.waitFor(1); - e = (CDOViewLocksChangedEvent)controlViewListener.getEvents().get(0); - assertEquals(Operation.LOCK, e.getOperation()); - assertEquals(LockType.WRITE, e.getLockType()); + event = (CDOViewLocksChangedEvent)controlViewListener.getEvents().get(0); + assertEquals(Operation.LOCK, event.getOperation()); + assertEquals(LockType.WRITE, event.getLockType()); } - tx.commit(); + transaction.commit(); if (mustReceiveNotifications) { controlViewListener.waitFor(2); - e = (CDOViewLocksChangedEvent)controlViewListener.getEvents().get(1); - assertEquals(Operation.UNLOCK, e.getOperation()); - assertNull(e.getLockType()); + event = (CDOViewLocksChangedEvent)controlViewListener.getEvents().get(1); + assertEquals(Operation.UNLOCK, event.getOperation()); + assertNull(event.getLockType()); } - - if (!mustReceiveNotifications) + else { + sleep(1000); assertEquals(0, controlViewListener.getEvents().size()); } } - private void assertLockedObject(CDOObject obj, Object lockedObject) + public static void assertLockedObject(CDOObject expected, CDOLockState actual) { + Object lockedObject = actual.getLockedObject(); if (lockedObject instanceof CDOIDAndBranch) { CDOIDAndBranch idAndBranch = (CDOIDAndBranch)lockedObject; - assertEquals(obj.cdoID(), idAndBranch.getID()); - assertEquals(obj.cdoView().getBranch().getID(), idAndBranch.getBranch().getID()); + assertEquals(expected.cdoID(), idAndBranch.getID()); + assertEquals(expected.cdoView().getBranch().getID(), idAndBranch.getBranch().getID()); } else if (lockedObject instanceof CDOID) { - assertEquals(obj.cdoID(), lockedObject); + assertEquals(expected.cdoID(), lockedObject); } } - private void assertLockOwner(CDOView view, CDOLockOwner lockOwner) - { - CDOLockOwner lo = CDOLockUtil.createLockOwner(view); - assertEquals(lo, lockOwner); - } - - public void testEnableDisableNotifications() throws CommitException + public static void assertLockOwner(CDOView expected, CDOLockOwner actual) { - CDOSession session1 = openSession(); - CDOSession session2 = openSession(); - CDOView controlView = session2.openView(); - withExplicitRelease(session1, controlView, false); - - controlView.options().setLockNotificationEnabled(true); - withExplicitRelease(session1, controlView, true); - - controlView.options().setLockNotificationEnabled(false); - withExplicitRelease(session1, controlView, false); - - session1.close(); - session2.close(); - } - - public void testLockStateHeldByDurableView() throws CommitException - { - skipStoreWithoutDurableLocking(); - - { - CDOSession session1 = openSession(); - CDOTransaction tx1 = session1.openTransaction(); - tx1.enableDurableLocking(); - CDOResource res1 = tx1.createResource(getResourcePath("r1")); - Company company1 = getModel1Factory().createCompany(); - res1.getContents().add(company1); - tx1.commit(); - - CDOUtil.getCDOObject(company1).cdoWriteLock().lock(); - tx1.close(); - session1.close(); - } - - CDOSession session2 = openSession(); - CDOView controlView = session2.openView(); - CDOResource resource = controlView.getResource(getResourcePath("r1")); - Company company1 = (Company)resource.getContents().get(0); - CDOObject cdoObj = CDOUtil.getCDOObject(company1); - assertEquals(true, cdoObj.cdoWriteLock().isLockedByOthers()); - assertEquals(true, cdoObj.cdoLockState().getWriteLockOwner().isDurableView()); - session2.close(); - } - - public void testLockStateNewAndTransient() throws CommitException - { - Company company1 = getModel1Factory().createCompany(); - CDOObject cdoObj = CDOUtil.getCDOObject(company1); - assertTransient(cdoObj); - assertNull(cdoObj.cdoLockState()); - - CDOSession session1 = openSession(); - CDOTransaction tx1 = session1.openTransaction(); - CDOResource res1 = tx1.createResource(getResourcePath("r1")); - res1.getContents().add(company1); - assertNew(cdoObj, tx1); - assertNotNull(cdoObj.cdoLockState()); - - res1.getContents().remove(company1); - assertTransient(cdoObj); - assertNull(cdoObj.cdoLockState()); - - res1.getContents().add(company1); - tx1.commit(); - assertClean(cdoObj, tx1); - assertNotNull(cdoObj.cdoLockState()); - - res1.getContents().remove(company1); - assertTransient(cdoObj); - assertNull(cdoObj.cdoLockState()); - - session1.close(); + CDOLockOwner lockOwner = CDOLockUtil.createLockOwner(expected); + assertEquals(lockOwner, actual); } /** diff --git a/plugins/org.eclipse.emf.cdo.tests/src/org/eclipse/emf/cdo/tests/bugzilla/Bugzilla_387564_Test.java b/plugins/org.eclipse.emf.cdo.tests/src/org/eclipse/emf/cdo/tests/bugzilla/Bugzilla_387564_Test.java new file mode 100644 index 0000000000..94c70b95d6 --- /dev/null +++ b/plugins/org.eclipse.emf.cdo.tests/src/org/eclipse/emf/cdo/tests/bugzilla/Bugzilla_387564_Test.java @@ -0,0 +1,145 @@ +/* + * 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.eresource.CDOResource; +import org.eclipse.emf.cdo.internal.net4j.CDONet4jSessionConfigurationImpl; +import org.eclipse.emf.cdo.internal.net4j.CDONet4jSessionImpl; +import org.eclipse.emf.cdo.net4j.CDONet4jSessionConfiguration; +import org.eclipse.emf.cdo.session.CDOSession; +import org.eclipse.emf.cdo.session.CDOSessionInvalidationEvent; +import org.eclipse.emf.cdo.session.CDOSessionLocksChangedEvent; +import org.eclipse.emf.cdo.tests.AbstractCDOTest; +import org.eclipse.emf.cdo.tests.config.IRepositoryConfig; +import org.eclipse.emf.cdo.tests.config.impl.SessionConfig; +import org.eclipse.emf.cdo.tests.model1.Company; +import org.eclipse.emf.cdo.tests.util.TestListener2; +import org.eclipse.emf.cdo.transaction.CDOTransaction; +import org.eclipse.emf.cdo.util.CDOUtil; +import org.eclipse.emf.cdo.util.CommitException; +import org.eclipse.emf.cdo.util.ConcurrentAccessException; +import org.eclipse.emf.cdo.view.CDOView; +import org.eclipse.emf.cdo.view.CDOViewInvalidationEvent; +import org.eclipse.emf.cdo.view.CDOViewLocksChangedEvent; + +import org.eclipse.net4j.util.event.IEvent; +import org.eclipse.net4j.util.io.IOUtil; + +import org.eclipse.emf.spi.cdo.InternalCDOSession; + +import java.util.ArrayList; +import java.util.List; + +/** + * Bug 387564 - Ensure lock notification sending after invalidation for "lock/unlock objects on commit" + * + * @author Eike Stepper + */ +public class Bugzilla_387564_Test extends AbstractCDOTest +{ + private static final boolean DEBUG = true; + + public void testLockEventAfterInvalidationEventSameSession() throws Exception + { + CDOSession session = openSession(); + runTest(session, session); + } + + public void testLockEventAfterInvalidationEventDifferentSession() throws Exception + { + CDOSession session = openSession(); + CDOSession controlSession = openSession(); + runTest(session, controlSession); + } + + private void runTest(CDOSession session, CDOSession controlSession) throws ConcurrentAccessException, CommitException + { + Company company = getModel1Factory().createCompany(); + company.setName("Initial"); + + CDOTransaction transaction = session.openTransaction(); + CDOResource resource = transaction.createResource(getResourcePath("res1")); + resource.getContents().add(company); + transaction.commit(); + + CDOUtil.getCDOObject(company).cdoWriteLock().lock(); + company.setName("Changed"); + + CDONet4jSessionConfiguration template = (CDONet4jSessionConfiguration)((SessionConfig)getSessionConfig()) + .createSessionConfiguration(IRepositoryConfig.REPOSITORY_NAME); + + CDONet4jSessionConfiguration configuration = new CDONet4jSessionConfigurationImpl() + { + @Override + public InternalCDOSession createSession() + { + return new CDONet4jSessionImpl() + { + @Override + public void invalidate(InvalidationData invalidationData) + { + sleep(1000); // Delay the invalidation handling to give lock notifications a chance to overtake. + super.invalidate(invalidationData); + } + }; + } + }; + + configuration.setConnector(template.getConnector()); + configuration.setRepositoryName(template.getRepositoryName()); + configuration.setRevisionManager(template.getRevisionManager()); + getTestProperties().put(SessionConfig.PROP_TEST_SESSION_CONFIGURATION, configuration); + + TestListener2 controlSessionListener = createControlListener("SESSION"); + controlSession.addListener(controlSessionListener); + + TestListener2 controlViewListener = createControlListener("VIEW"); + CDOView controlView = controlSession.openView(); + controlView.options().setLockNotificationEnabled(true); + controlView.addListener(controlViewListener); + + // Load the company into the control view, so that the view emits invalidation events for it. + Company controlObject = controlView.getObject(company); + IOUtil.OUT().println(controlObject.getName()); + ((CDOTransaction)CDOUtil.getView(company)).commit(); + + controlSessionListener.waitFor(2); + assertInstanceOf(CDOSessionInvalidationEvent.class, controlSessionListener.getEvents().get(0)); + assertInstanceOf(CDOSessionLocksChangedEvent.class, controlSessionListener.getEvents().get(1)); + if (DEBUG) + { + IOUtil.OUT().println(controlSessionListener); + IOUtil.OUT().println(controlSessionListener.formatEvents(" ", "\n")); + } + + controlViewListener.waitFor(2); + assertInstanceOf(CDOViewInvalidationEvent.class, controlViewListener.getEvents().get(0)); + assertInstanceOf(CDOViewLocksChangedEvent.class, controlViewListener.getEvents().get(1)); + if (DEBUG) + { + IOUtil.OUT().println(controlViewListener); + IOUtil.OUT().println(controlViewListener.formatEvents(" ", "\n")); + } + + IOUtil.OUT().println(controlObject.getName()); + } + + private static TestListener2 createControlListener(String name) + { + List<Class<? extends IEvent>> eventClasses = new ArrayList<Class<? extends IEvent>>(); + eventClasses.add(CDOSessionInvalidationEvent.class); + eventClasses.add(CDOSessionLocksChangedEvent.class); + eventClasses.add(CDOViewInvalidationEvent.class); + eventClasses.add(CDOViewLocksChangedEvent.class); + + return new TestListener2(eventClasses, name); + } +} diff --git a/plugins/org.eclipse.emf.cdo.tests/src/org/eclipse/emf/cdo/tests/config/ITestLifecycle.java b/plugins/org.eclipse.emf.cdo.tests/src/org/eclipse/emf/cdo/tests/config/ITestLifecycle.java index 7cad3e1418..9b2e1edb72 100644 --- a/plugins/org.eclipse.emf.cdo.tests/src/org/eclipse/emf/cdo/tests/config/ITestLifecycle.java +++ b/plugins/org.eclipse.emf.cdo.tests/src/org/eclipse/emf/cdo/tests/config/ITestLifecycle.java @@ -24,4 +24,6 @@ public interface ITestLifecycle public void setUp() throws Exception; public void tearDown() throws Exception; + + public void mainSuiteFinished() throws Exception; } diff --git a/plugins/org.eclipse.emf.cdo.tests/src/org/eclipse/emf/cdo/tests/config/impl/Config.java b/plugins/org.eclipse.emf.cdo.tests/src/org/eclipse/emf/cdo/tests/config/impl/Config.java index 522a0892ac..63c29f0def 100644 --- a/plugins/org.eclipse.emf.cdo.tests/src/org/eclipse/emf/cdo/tests/config/impl/Config.java +++ b/plugins/org.eclipse.emf.cdo.tests/src/org/eclipse/emf/cdo/tests/config/impl/Config.java @@ -114,6 +114,10 @@ public abstract class Config implements IConfig { } + public void mainSuiteFinished() throws Exception + { + } + public static ExecutorService getExecutorService() { return executorService; diff --git a/plugins/org.eclipse.emf.cdo.tests/src/org/eclipse/emf/cdo/tests/config/impl/ConfigTestSuite.java b/plugins/org.eclipse.emf.cdo.tests/src/org/eclipse/emf/cdo/tests/config/impl/ConfigTestSuite.java index 5db839c026..833159d11c 100644 --- a/plugins/org.eclipse.emf.cdo.tests/src/org/eclipse/emf/cdo/tests/config/impl/ConfigTestSuite.java +++ b/plugins/org.eclipse.emf.cdo.tests/src/org/eclipse/emf/cdo/tests/config/impl/ConfigTestSuite.java @@ -15,6 +15,7 @@ import org.eclipse.emf.cdo.tests.config.IScenario; import org.eclipse.emf.cdo.tests.config.impl.ConfigTest.Requires; import org.eclipse.emf.cdo.tests.config.impl.ConfigTest.Skips; +import org.eclipse.net4j.util.io.IOUtil; import org.eclipse.net4j.util.om.OMBundle; import java.lang.reflect.AnnotatedElement; @@ -36,6 +37,8 @@ import junit.framework.TestSuite; */ public abstract class ConfigTestSuite implements IConstants { + private final List<IScenario> scenarios = new ArrayList<IScenario>(); + public ConfigTestSuite() { } @@ -62,7 +65,7 @@ public abstract class ConfigTestSuite implements IConstants if (scenario.isValid()) { - TestSuite suite = new TestSuite(scenario.toString()); + TestSuite scenarioSuite = new TestSuite(scenario.toString()); List<Class<? extends ConfigTest>> testClasses = new ArrayList<Class<? extends ConfigTest>>(); initTestClasses(testClasses, scenario); @@ -71,10 +74,10 @@ public abstract class ConfigTestSuite implements IConstants { try { - ScenarioSuite wrapper = new ScenarioSuite(testClass, scenario, this); - if (wrapper.testCount() != 0) + TestClassWrapper testClassWrapper = new TestClassWrapper(testClass, scenario, this); + if (testClassWrapper.testCount() != 0) { - suite.addTest(wrapper); + scenarioSuite.addTest(testClassWrapper); } } catch (ConstraintsViolatedException ex) @@ -83,7 +86,8 @@ public abstract class ConfigTestSuite implements IConstants } } - parent.addTest(suite); + parent.addTest(scenarioSuite); + scenarios.add(scenario); } } @@ -124,11 +128,19 @@ public abstract class ConfigTestSuite implements IConstants { } - /** - * Can be overridden by subclasses. - */ protected void mainSuiteFinished() { + for (IScenario scenario : scenarios) + { + try + { + scenario.mainSuiteFinished(); + } + catch (Exception ex) + { + IOUtil.print(ex); + } + } } /** @@ -152,28 +164,28 @@ public abstract class ConfigTestSuite implements IConstants /** * @author Eike Stepper */ - private static final class ScenarioSuite extends TestSuite + private static final class TestClassWrapper extends TestSuite { private IScenario scenario; - - public ScenarioSuite(Class<? extends ConfigTest> testClass, IScenario scenario, ConfigTestSuite suite) + + public TestClassWrapper(Class<? extends ConfigTest> testClass, IScenario scenario, ConfigTestSuite suite) throws ConstraintsViolatedException { // super(testClass, testClass.getName()); // Important for the UI to set the *qualified* class name! this.scenario = scenario; addTestsFromTestCase(testClass, suite); } - + @Override public void runTest(Test test, TestResult result) { if (test instanceof ConfigTest) { scenario.save(); - + ConfigTest configTest = (ConfigTest)test; configTest.setScenario(scenario); - + if (configTest.isValid()) { super.runTest(configTest, result); @@ -184,31 +196,31 @@ public abstract class ConfigTestSuite implements IConstants super.runTest(test, result); } } - + private void addTestsFromTestCase(final Class<?> theClass, ConfigTestSuite suite) throws ConstraintsViolatedException { setName(theClass.getName()); - + try { getTestConstructor(theClass); // Avoid generating multiple error messages } catch (NoSuchMethodException e) { - addTest(warning("Class " + theClass.getName() - + " has no public constructor TestCase(String name) or TestCase()")); + addTest( + warning("Class " + theClass.getName() + " has no public constructor TestCase(String name) or TestCase()")); return; } - + if (!Modifier.isPublic(theClass.getModifiers())) { addTest(warning("Class " + theClass.getName() + " is not public")); return; } - + Set<String> capabilities = scenario.getCapabilities(); - + Class<?> superClass = theClass; while (Test.class.isAssignableFrom(superClass)) { @@ -216,12 +228,12 @@ public abstract class ConfigTestSuite implements IConstants { throw new ConstraintsViolatedException(); } - + superClass = superClass.getSuperclass(); } - + List<String> names = new ArrayList<String>(); - + superClass = theClass; while (Test.class.isAssignableFrom(superClass)) { @@ -232,11 +244,11 @@ public abstract class ConfigTestSuite implements IConstants addTestMethod(method, names, theClass, suite); } } - + superClass = superClass.getSuperclass(); } } - + private boolean validateConstraints(AnnotatedElement element, Set<String> capabilities) { Requires requires = element.getAnnotation(Requires.class); @@ -250,7 +262,7 @@ public abstract class ConfigTestSuite implements IConstants } } } - + Skips skips = element.getAnnotation(Skips.class); if (skips != null) { @@ -262,10 +274,10 @@ public abstract class ConfigTestSuite implements IConstants } } } - + return true; } - + private void addTestMethod(Method m, List<String> names, Class<?> theClass, ConfigTestSuite suite) { String name = m.getName(); @@ -273,17 +285,17 @@ public abstract class ConfigTestSuite implements IConstants { return; } - + if (!isPublicTestMethod(m)) { if (isTestMethod(m)) { addTest(warning("Test method isn't public: " + m.getName() + "(" + theClass.getCanonicalName() + ")")); } - + return; } - + names.add(name); Test test = createTest(theClass, name); if (test instanceof ConfigTest) @@ -291,15 +303,15 @@ public abstract class ConfigTestSuite implements IConstants ConfigTest configTest = (ConfigTest)test; suite.prepareTest(configTest); } - + addTest(test); } - + private boolean isPublicTestMethod(Method m) { return isTestMethod(m) && Modifier.isPublic(m.getModifiers()); } - + private boolean isTestMethod(Method m) { return m.getParameterTypes().length == 0 && m.getName().startsWith("test") && m.getReturnType().equals(Void.TYPE); diff --git a/plugins/org.eclipse.emf.cdo.tests/src/org/eclipse/emf/cdo/tests/config/impl/RepositoryConfig.java b/plugins/org.eclipse.emf.cdo.tests/src/org/eclipse/emf/cdo/tests/config/impl/RepositoryConfig.java index eb9214209d..89cf325a30 100644 --- a/plugins/org.eclipse.emf.cdo.tests/src/org/eclipse/emf/cdo/tests/config/impl/RepositoryConfig.java +++ b/plugins/org.eclipse.emf.cdo.tests/src/org/eclipse/emf/cdo/tests/config/impl/RepositoryConfig.java @@ -513,8 +513,11 @@ public abstract class RepositoryConfig extends Config implements IRepositoryConf LifecycleUtil.deactivate(repository); } - repositories.clear(); - repositories = null; + if (repositories != null) + { + repositories.clear(); + repositories = null; + } StoreThreadLocal.release(); diff --git a/plugins/org.eclipse.emf.cdo.tests/src/org/eclipse/emf/cdo/tests/config/impl/Scenario.java b/plugins/org.eclipse.emf.cdo.tests/src/org/eclipse/emf/cdo/tests/config/impl/Scenario.java index e98e63cfcd..103438c247 100644 --- a/plugins/org.eclipse.emf.cdo.tests/src/org/eclipse/emf/cdo/tests/config/impl/Scenario.java +++ b/plugins/org.eclipse.emf.cdo.tests/src/org/eclipse/emf/cdo/tests/config/impl/Scenario.java @@ -236,6 +236,36 @@ public class Scenario implements IScenario } } + public void mainSuiteFinished() + { + try + { + getModelConfig().mainSuiteFinished(); + } + catch (Exception ex) + { + IOUtil.print(ex); + } + + try + { + getSessionConfig().mainSuiteFinished(); + } + catch (Exception ex) + { + IOUtil.print(ex); + } + + try + { + getRepositoryConfig().mainSuiteFinished(); + } + catch (Exception ex) + { + IOUtil.print(ex); + } + } + public void save() { File file = getStateFile(); diff --git a/plugins/org.eclipse.emf.cdo.tests/src/org/eclipse/emf/cdo/tests/config/impl/SessionConfig.java b/plugins/org.eclipse.emf.cdo.tests/src/org/eclipse/emf/cdo/tests/config/impl/SessionConfig.java index 9d3d20a481..bd913ec94b 100644 --- a/plugins/org.eclipse.emf.cdo.tests/src/org/eclipse/emf/cdo/tests/config/impl/SessionConfig.java +++ b/plugins/org.eclipse.emf.cdo.tests/src/org/eclipse/emf/cdo/tests/config/impl/SessionConfig.java @@ -272,9 +272,9 @@ public abstract class SessionConfig extends Config implements ISessionConfig return (CDOFetchRuleManager)getTestProperty(PROP_TEST_FETCH_RULE_MANAGER); } - protected abstract CDOSessionConfiguration createSessionConfiguration(String repositoryName); + public abstract CDOSessionConfiguration createSessionConfiguration(String repositoryName); - protected void configureSession(CDOSession session) + public void configureSession(CDOSession session) { final File lobCache = getCurrentTest().getTempName("lobs_" + new Date().getTime() + "_", ".tmp"); session.options().setLobCache(new CDOLobStoreImpl(lobCache)); @@ -347,7 +347,7 @@ public abstract class SessionConfig extends Config implements ISessionConfig } @Override - protected CDOSessionConfiguration createSessionConfiguration(String repositoryName) + public CDOSessionConfiguration createSessionConfiguration(String repositoryName) { IRepository repository = getCurrentTest().getRepository(repositoryName); @@ -434,7 +434,7 @@ public abstract class SessionConfig extends Config implements ISessionConfig } @Override - protected CDOSessionConfiguration createSessionConfiguration(String repositoryName) + public CDOSessionConfiguration createSessionConfiguration(String repositoryName) { CDONet4jSessionConfiguration configuration = CDONet4jUtil.createNet4jSessionConfiguration(); configuration.setConnector(getConnector()); @@ -444,13 +444,13 @@ public abstract class SessionConfig extends Config implements ISessionConfig } @Override - protected void configureSession(CDOSession session) + public void configureSession(CDOSession session) { super.configureSession(session); ((org.eclipse.emf.cdo.net4j.CDONet4jSession)session).options().getNet4jProtocol().setTimeout(-1); } - protected abstract CDOViewProvider createViewProvider(IManagedContainer container); + public abstract CDOViewProvider createViewProvider(IManagedContainer container); @Override public void setUp() throws Exception @@ -537,7 +537,7 @@ public abstract class SessionConfig extends Config implements ISessionConfig } @Override - protected CDOViewProvider createViewProvider(final IManagedContainer container) + public CDOViewProvider createViewProvider(final IManagedContainer container) { return new CDONet4jViewProvider.TCP() { @@ -605,7 +605,7 @@ public abstract class SessionConfig extends Config implements ISessionConfig } @Override - protected CDOViewProvider createViewProvider(final IManagedContainer container) + public CDOViewProvider createViewProvider(final IManagedContainer container) { return new CDONet4jViewProvider.SSL() { @@ -674,7 +674,7 @@ public abstract class SessionConfig extends Config implements ISessionConfig } @Override - protected CDOViewProvider createViewProvider(final IManagedContainer container) + public CDOViewProvider createViewProvider(final IManagedContainer container) { return new CDONet4jViewProvider.JVM() { diff --git a/plugins/org.eclipse.emf.cdo.tests/src/org/eclipse/emf/cdo/tests/util/TestListener2.java b/plugins/org.eclipse.emf.cdo.tests/src/org/eclipse/emf/cdo/tests/util/TestListener2.java index 712b4444d5..a871b5058a 100644 --- a/plugins/org.eclipse.emf.cdo.tests/src/org/eclipse/emf/cdo/tests/util/TestListener2.java +++ b/plugins/org.eclipse.emf.cdo.tests/src/org/eclipse/emf/cdo/tests/util/TestListener2.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: * Eike Stepper - initial API and implementation */ @@ -16,48 +16,116 @@ import org.eclipse.net4j.util.event.IListener; import org.junit.Assert; -import java.util.LinkedList; +import java.util.ArrayList; +import java.util.Collection; +import java.util.Collections; +import java.util.HashSet; +import java.util.LinkedHashMap; import java.util.List; +import java.util.Map; +import java.util.Map.Entry; +import java.util.Set; /** * @author Caspar De Groot */ public class TestListener2 implements IListener { - private final static long DEFAULT_TIMEOUT = 3000; // 3 seconds + public static final int NO_TIME_STAMP = 0; - private List<IEvent> events = new LinkedList<IEvent>(); + private static final Set<Class<? extends IEvent>> NO_EVENT_CLASSES = Collections.emptySet(); - private Class<? extends IEvent> eventClass; + private static final long DEFAULT_TIMEOUT = 3000; // 3 seconds + + private final Map<IEvent, Long> events = new LinkedHashMap<IEvent, Long>(); + + private final Collection<Class<? extends IEvent>> eventClasses; private long timeout; private String name; + public TestListener2(Collection<Class<? extends IEvent>> eventClasses) + { + this(eventClasses, null); + } + public TestListener2(Class<? extends IEvent> eventClass) { - this(eventClass, null); + this(singleton(eventClass)); } - public TestListener2(Class<? extends IEvent> eventClass, String name) + public TestListener2(Collection<Class<? extends IEvent>> eventClasses, String name) { - this.eventClass = eventClass; + this.eventClasses = eventClasses != null ? eventClasses : NO_EVENT_CLASSES; this.name = name; timeout = DEFAULT_TIMEOUT; } - public synchronized void notifyEvent(IEvent event) + public TestListener2(Class<? extends IEvent> eventClass, String name) + { + this(singleton(eventClass), name); + } + + public boolean isApplicable(IEvent event) { - if (eventClass == null || eventClass.isAssignableFrom(event.getClass())) + if (eventClasses.isEmpty()) + { + return true; + } + + Class<? extends IEvent> theClass = event.getClass(); + for (Class<? extends IEvent> eventClass : eventClasses) { - events.add(event); - notify(); + if (eventClass.isAssignableFrom(theClass)) + { + return true; + } + } + + return false; + } + + public void notifyEvent(IEvent event) + { + if (isApplicable(event)) + { + long timeStamp = System.currentTimeMillis(); + if (timeStamp == NO_TIME_STAMP) + { + throw new IllegalStateException("Regular time stamp is equal to NO_TIME_STAMP"); + } + + synchronized (this) + { + events.put(event, timeStamp); + notify(); + } } } public List<IEvent> getEvents() { - return events; + synchronized (this) + { + return new ArrayList<IEvent>(events.keySet()); + } + } + + public long getTimeStamp(IEvent event) + { + Long timeStamp; + synchronized (this) + { + timeStamp = events.get(event); + } + + if (timeStamp == null) + { + return NO_TIME_STAMP; + } + + return timeStamp; } public void setTimeout(long timeout) @@ -69,24 +137,27 @@ public class TestListener2 implements IListener { long t = 0; - while (events.size() < n) + synchronized (this) { - if (timeout <= 0) - { - Assert.fail("Timed out"); - } - - try - { - t = System.currentTimeMillis(); - wait(timeout); - } - catch (InterruptedException ex) + while (events.size() < n) { - throw WrappedException.wrap(ex); + if (timeout <= 0) + { + Assert.fail("Timed out"); + } + + try + { + t = System.currentTimeMillis(); + wait(timeout); + } + catch (InterruptedException ex) + { + throw WrappedException.wrap(ex); + } + + timeout -= System.currentTimeMillis() - t; } - - timeout -= System.currentTimeMillis() - t; } } @@ -95,11 +166,27 @@ public class TestListener2 implements IListener waitFor(i, timeout); } + public String formatEvents(String prefix, String suffix) + { + StringBuilder builder = new StringBuilder(); + + synchronized (this) + { + for (Entry<IEvent, Long> entry : events.entrySet()) + { + builder.append(prefix + entry.getValue() + ": " + entry.getKey() + suffix); + } + } + + return builder.toString(); + } + @Override public String toString() { StringBuilder builder = new StringBuilder(TestListener2.class.getSimpleName()); builder.append('['); + if (name != null) { builder.append("name=\""); @@ -107,17 +194,41 @@ public class TestListener2 implements IListener builder.append('\"'); } - if (eventClass != null) + if (!eventClasses.isEmpty()) { - if (builder.charAt(builder.length() - 1) != '[') + if (name != null) { - builder.append(';'); + builder.append(", "); } - builder.append("eventClass="); - builder.append(eventClass.getSimpleName()); + + builder.append("eventClasses=["); + boolean first = true; + + for (Class<? extends IEvent> eventClass : eventClasses) + { + if (first) + { + first = false; + } + else + { + builder.append(", "); + } + + builder.append(eventClass.getSimpleName()); + } + + builder.append(']'); } builder.append(']'); return builder.toString(); } + + private static Set<Class<? extends IEvent>> singleton(Class<? extends IEvent> eventClass) + { + Set<Class<? extends IEvent>> singleton = new HashSet<Class<? extends IEvent>>(); + singleton.add(eventClass); + return singleton; + } } diff --git a/plugins/org.eclipse.emf.cdo/.settings/.api_filters b/plugins/org.eclipse.emf.cdo/.settings/.api_filters index 9060fa7153..8b3ea3cdab 100644 --- a/plugins/org.eclipse.emf.cdo/.settings/.api_filters +++ b/plugins/org.eclipse.emf.cdo/.settings/.api_filters @@ -594,13 +594,6 @@ </filter> </resource> <resource path="src/org/eclipse/emf/internal/cdo/session/CDOSessionImpl.java" type="org.eclipse.emf.internal.cdo.session.CDOSessionImpl"> - <filter id="574660632"> - <message_arguments> - <message_argument value="InternalCDOSession"/> - <message_argument value="CDOCommonSession"/> - <message_argument value="CDOSessionImpl"/> - </message_arguments> - </filter> <filter id="574668824"> <message_arguments> <message_argument value="InternalCDOSession"/> @@ -610,13 +603,6 @@ </filter> </resource> <resource path="src/org/eclipse/emf/internal/cdo/session/CDOSessionImpl.java" type="org.eclipse.emf.internal.cdo.session.CDOSessionImpl$OptionsImpl"> - <filter id="574660632"> - <message_arguments> - <message_argument value="Options"/> - <message_argument value="Options"/> - <message_argument value="OptionsImpl"/> - </message_arguments> - </filter> <filter id="574668824"> <message_arguments> <message_argument value="Options"/> @@ -674,13 +660,6 @@ </filter> </resource> <resource path="src/org/eclipse/emf/internal/cdo/view/CDOViewImpl.java" type="org.eclipse.emf.internal.cdo.view.CDOViewImpl$OptionsImpl"> - <filter id="574660632"> - <message_arguments> - <message_argument value="Options"/> - <message_argument value="Options"/> - <message_argument value="OptionsImpl"/> - </message_arguments> - </filter> <filter id="574668824"> <message_arguments> <message_argument value="Options"/> 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 d375bf2a69..036dcc37e2 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 @@ -134,6 +134,7 @@ import org.eclipse.emf.spi.cdo.InternalCDOSession; import org.eclipse.emf.spi.cdo.InternalCDOSessionInvalidationEvent; import org.eclipse.emf.spi.cdo.InternalCDOTransaction; import org.eclipse.emf.spi.cdo.InternalCDOView; +import org.eclipse.emf.spi.cdo.InternalCDOView.ViewInvalidationData; import java.io.File; import java.io.FileNotFoundException; @@ -487,46 +488,16 @@ public abstract class CDOSessionImpl extends CDOTransactionContainerImpl private void loadBinary(final CDOLobInfo info) throws IOException { - final File file = getDelegate().getBinaryFile(info.getID()); - final FileOutputStream out = new FileOutputStream(file); - - loadLobAsync(info, new Runnable() - { - public void run() - { - try - { - getSessionProtocol().loadLob(info, out); - } - catch (Throwable t) - { - OM.LOG.error(t); - IOUtil.delete(file); - } - } - }); + File file = getDelegate().getBinaryFile(info.getID()); + FileOutputStream out = new FileOutputStream(file); + loadLobAsync(info, file, out); } private void loadCharacter(final CDOLobInfo info) throws IOException { - final File file = getDelegate().getCharacterFile(info.getID()); - final FileWriter out = new FileWriter(file); - - loadLobAsync(info, new Runnable() - { - public void run() - { - try - { - getSessionProtocol().loadLob(info, out); - } - catch (Throwable t) - { - OM.LOG.error(t); - IOUtil.delete(file); - } - } - }); + File file = getDelegate().getCharacterFile(info.getID()); + FileWriter out = new FileWriter(file); + loadLobAsync(info, file, out); } @Override @@ -537,9 +508,31 @@ public abstract class CDOSessionImpl extends CDOTransactionContainerImpl }; } - protected void loadLobAsync(CDOLobInfo info, Runnable runnable) + protected void loadLobAsync(final CDOLobInfo info, final File file, final Object outputStreamOrWriter) { - ConcurrencyUtil.execute(this, runnable); + ConcurrencyUtil.execute(this, new RunnableWithName() + { + @Override + public String getName() + { + return "CDOLobLoader-" + info.getIDString(); + } + + @Override + protected void doRun() + { + try + { + CDOSessionProtocol sessionProtocol = getSessionProtocol(); + sessionProtocol.loadLob(info, outputStreamOrWriter); + } + catch (Throwable t) + { + OM.LOG.error(t); + IOUtil.delete(file); + } + } + }); } public void close() @@ -706,8 +699,15 @@ public abstract class CDOSessionImpl extends CDOTransactionContainerImpl long lastUpdateTime = result.getLastUpdateTime(); for (InternalCDOView view : branchViews) { - CDOBranch viewBranch = view.getBranch(); - view.invalidate(viewBranch, lastUpdateTime, changedObjects, detachedObjects, oldRevisions, false, true); + ViewInvalidationData invalidationData = new ViewInvalidationData(); + invalidationData.setBranch(view.getBranch()); + invalidationData.setLastUpdateTime(lastUpdateTime); + invalidationData.setAllChangedObjects(changedObjects); + invalidationData.setAllDetachedObjects(detachedObjects); + invalidationData.setOldRevisions(oldRevisions); + invalidationData.setClearResourcePathCache(true); + + view.invalidate(invalidationData); } } @@ -957,11 +957,15 @@ public abstract class CDOSessionImpl extends CDOTransactionContainerImpl CDOCommitInfo commitInfo = info.getCommitInfo(); registerPackageUnits(commitInfo.getNewPackageUnits()); - boolean clearResourcePathCache = info.isClearResourcePathCache(); - byte securityImpact = info.getSecurityImpact(); - Map<CDOID, CDOPermission> newPermissions = info.getNewPermissions(); + InvalidationData invalidationData = new InvalidationData(); + invalidationData.setCommitInfo(commitInfo); + invalidationData.setSender(null); + invalidationData.setClearResourcePathCache(info.isClearResourcePathCache()); + invalidationData.setSecurityImpact(info.getSecurityImpact()); + invalidationData.setNewPermissions(info.getNewPermissions()); + invalidationData.setLockChangeInfo(info.getLockChangeInfo()); - invalidate(commitInfo, null, clearResourcePathCache, securityImpact, newPermissions); + invalidate(invalidationData); } catch (RuntimeException ex) { @@ -986,7 +990,7 @@ public abstract class CDOSessionImpl extends CDOTransactionContainerImpl } } - fireEvent(new LocksChangedEvent(sender, lockChangeInfo)); + fireEvent(new SessionLocksChangedEvent(sender, lockChangeInfo)); } private void registerPackageUnits(List<CDOPackageUnit> packageUnits) @@ -1094,10 +1098,16 @@ public abstract class CDOSessionImpl extends CDOTransactionContainerImpl throw new UnsupportedOperationException(); } + @Deprecated public void invalidate(CDOCommitInfo commitInfo, InternalCDOTransaction sender, boolean clearResourcePathCache, byte securityImpact, Map<CDOID, CDOPermission> newPermissions) { - invalidator.reorderInvalidations(commitInfo, sender, clearResourcePathCache, securityImpact, newPermissions); + throw new UnsupportedOperationException(); + } + + public void invalidate(InvalidationData invalidationData) + { + invalidator.reorderInvalidations(invalidationData); } public ILifecycle getInvalidator() @@ -1841,11 +1851,9 @@ public abstract class CDOSessionImpl extends CDOTransactionContainerImpl unfinishedLocalCommits.remove(token); } - public synchronized void reorderInvalidations(CDOCommitInfo commitInfo, InternalCDOTransaction sender, - boolean clearResourcePathCache, byte securityImpact, Map<CDOID, CDOPermission> newPermissions) + public synchronized void reorderInvalidations(InvalidationData invalidationData) { - Invalidation invalidation = new Invalidation(commitInfo, sender, clearResourcePathCache, securityImpact, - newPermissions); + Invalidation invalidation = new Invalidation(invalidationData); reorderQueue.add(invalidation); Collections.sort(reorderQueue); @@ -1854,7 +1862,7 @@ public abstract class CDOSessionImpl extends CDOTransactionContainerImpl { IOUtil.OUT() .println(CDOSessionImpl.this + " [" + getLastUpdateTime() % 10000 + "] " - + commitInfo.getPreviousTimeStamp() % 10000 + " --> " + commitInfo.getTimeStamp() % 10000 + + invalidation.getPreviousTimeStamp() % 10000 + " --> " + invalidation.getTimeStamp() % 10000 + " reorderQueue=" + reorderQueue + " unfinishedLocalCommits=" + unfinishedLocalCommits); } @@ -1904,24 +1912,14 @@ public abstract class CDOSessionImpl extends CDOTransactionContainerImpl */ private final class Invalidation extends RunnableWithName implements Comparable<Invalidation> { - private final CDOCommitInfo commitInfo; - - private final InternalCDOTransaction sender; - - private final boolean clearResourcePathCache; - - private final byte securityImpact; + private final InvalidationData invalidationData; - private final Map<CDOID, CDOPermission> newPermissions; + private final CDOCommitInfo commitInfo; - public Invalidation(CDOCommitInfo commitInfo, InternalCDOTransaction sender, boolean clearResourcePathCache, - byte securityImpact, Map<CDOID, CDOPermission> newPermissions) + public Invalidation(InvalidationData invalidationData) { - this.commitInfo = commitInfo; - this.sender = sender; - this.clearResourcePathCache = clearResourcePathCache; - this.securityImpact = securityImpact; - this.newPermissions = newPermissions; + this.invalidationData = invalidationData; + commitInfo = invalidationData.getCommitInfo(); } public long getTimeStamp() @@ -1942,7 +1940,7 @@ public abstract class CDOSessionImpl extends CDOTransactionContainerImpl @Override public String toString() { - return Long.toString(commitInfo.getTimeStamp() % 10000); + return Long.toString(getTimeStamp() % 10000); } @Override @@ -1954,7 +1952,7 @@ public abstract class CDOSessionImpl extends CDOTransactionContainerImpl @Override protected void doRun() { - long timeStamp = commitInfo.getTimeStamp(); + long timeStamp = getTimeStamp(); if (Invalidator.DEBUG) { @@ -1973,7 +1971,7 @@ public abstract class CDOSessionImpl extends CDOTransactionContainerImpl { oldRevisions = reviseRevisions(); - if (securityImpact != CommitNotificationInfo.IMPACT_NONE) + if (invalidationData.getSecurityImpact() != CommitNotificationInfo.IMPACT_NONE) { oldPermissions = updatePermissions(views); } @@ -1984,15 +1982,21 @@ public abstract class CDOSessionImpl extends CDOTransactionContainerImpl setLastUpdateTime(timeStamp); } + CDOLockChangeInfo lockChangeInfo = invalidationData.getLockChangeInfo(); + InternalCDOTransaction sender = invalidationData.getSender(); + if (success) { - CDOSessionImpl.this.fireEvent(new InvalidationEvent(sender, commitInfo, securityImpact, oldPermissions)); + fireEvent(new InvalidationEvent(sender, commitInfo, invalidationData.getSecurityImpact(), oldPermissions)); + fireEvent(new SessionLocksChangedEvent(sender, lockChangeInfo)); + commitInfoManager.notifyCommitInfoHandlers(commitInfo); } for (InternalCDOView view : views) { - invalidateView(commitInfo, view, sender, oldRevisions, clearResourcePathCache); + invalidateView(commitInfo, view, sender, oldRevisions, invalidationData.isClearResourcePathCache(), + lockChangeInfo); } } catch (RuntimeException ex) @@ -2069,7 +2073,7 @@ public abstract class CDOSessionImpl extends CDOTransactionContainerImpl { Map<CDOID, InternalCDORevision> oldRevisions = null; CDOBranch newBranch = commitInfo.getBranch(); - long timeStamp = commitInfo.getTimeStamp(); + long timeStamp = getTimeStamp(); // Cache new revisions for (CDOIDAndVersion key : commitInfo.getNewObjects()) @@ -2096,7 +2100,7 @@ public abstract class CDOSessionImpl extends CDOTransactionContainerImpl addOldValuesToDelta(oldRevision, revisionDelta); InternalCDORevision newRevision = oldRevision.copy(); - newRevision.adjustForCommit(commitInfo.getBranch(), commitInfo.getTimeStamp()); + newRevision.adjustForCommit(newBranch, timeStamp); CDORevisable target = revisionDelta.getTarget(); if (target != null) @@ -2147,6 +2151,7 @@ public abstract class CDOSessionImpl extends CDOTransactionContainerImpl private void addNewRevision(InternalCDORevision newRevision) { + Map<CDOID, CDOPermission> newPermissions = invalidationData.getNewPermissions(); if (newPermissions != null) { CDOPermission newPermission = newPermissions.get(newRevision.getID()); @@ -2160,26 +2165,27 @@ public abstract class CDOSessionImpl extends CDOTransactionContainerImpl } private void invalidateView(CDOCommitInfo commitInfo, InternalCDOView view, InternalCDOTransaction sender, - Map<CDOID, InternalCDORevision> oldRevisions, boolean clearResourcePathCache) + Map<CDOID, InternalCDORevision> oldRevisions, boolean clearResourcePathCache, CDOLockChangeInfo lockChangeInfo) { try { - long lastUpdateTime = commitInfo.getTimeStamp(); - if (view == sender) + ViewInvalidationData invalidationData = new ViewInvalidationData(); + invalidationData.setLastUpdateTime(getTimeStamp()); + invalidationData.setAsync(true); + + // The committing view (sender) is already valid, just the timestamp must be set "in sequence". + // Setting the sender's timestamp synchronously can lead to deadlock + if (view != sender) { - // The committing view (sender) is already valid, just the timestamp must be set "in sequence". - // Setting the sender's timestamp synchronously can lead to deadlock - view.invalidate(null, lastUpdateTime, null, null, null, true, false); + invalidationData.setBranch(commitInfo.getBranch()); + invalidationData.setAllChangedObjects(commitInfo.getChangedObjects()); + invalidationData.setAllDetachedObjects(commitInfo.getDetachedObjects()); + invalidationData.setOldRevisions(oldRevisions); + invalidationData.setClearResourcePathCache(clearResourcePathCache); + invalidationData.setLockChangeInfo(lockChangeInfo); } - else - { - CDOBranch branch = commitInfo.getBranch(); - List<CDORevisionKey> allChangedObjects = commitInfo.getChangedObjects(); - List<CDOIDAndVersion> allDetachedObjects = commitInfo.getDetachedObjects(); - view.invalidate(branch, lastUpdateTime, allChangedObjects, allDetachedObjects, oldRevisions, true, - clearResourcePathCache); - } + view.invalidate(invalidationData); } catch (RuntimeException ex) { @@ -2351,11 +2357,11 @@ public abstract class CDOSessionImpl extends CDOTransactionContainerImpl * @author Caspar De Groot * @since 4.1 */ - private final class LocksChangedEvent extends DefaultLocksChangedEvent implements CDOSessionLocksChangedEvent + private final class SessionLocksChangedEvent extends DefaultLocksChangedEvent implements CDOSessionLocksChangedEvent { private static final long serialVersionUID = 1L; - public LocksChangedEvent(InternalCDOView sender, CDOLockChangeInfo lockChangeInfo) + public SessionLocksChangedEvent(InternalCDOView sender, CDOLockChangeInfo lockChangeInfo) { super(CDOSessionImpl.this, sender, lockChangeInfo); } @@ -2365,5 +2371,11 @@ public abstract class CDOSessionImpl extends CDOTransactionContainerImpl { return (CDOSession)super.getSource(); } + + @Override + protected String formatEventName() + { + return "CDOSessionLocksChangedEvent"; + } } } 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 5108fdc34f..3d9ddd3f46 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 @@ -57,7 +57,6 @@ import org.eclipse.emf.cdo.common.revision.CDORevisionUtil; import org.eclipse.emf.cdo.common.revision.delta.CDOFeatureDelta; import org.eclipse.emf.cdo.common.revision.delta.CDOOriginSizeProvider; import org.eclipse.emf.cdo.common.revision.delta.CDORevisionDelta; -import org.eclipse.emf.cdo.common.security.CDOPermission; import org.eclipse.emf.cdo.common.util.CDOException; import org.eclipse.emf.cdo.eresource.CDOBinaryResource; import org.eclipse.emf.cdo.eresource.CDOFileResource; @@ -167,6 +166,7 @@ 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.InvalidationData; import org.eclipse.emf.spi.cdo.InternalCDOSession.MergeData; import org.eclipse.emf.spi.cdo.InternalCDOTransaction; import org.eclipse.emf.spi.cdo.InternalCDOViewSet; @@ -1630,15 +1630,23 @@ public class CDOTransactionImpl extends CDOViewImpl implements InternalCDOTransa { try { - // The commit may have succeeded on the server, but after that fact network problems or timeouts have hit - // us. + // The commit may have succeeded on the server, but after that 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); + + InvalidationData invalidationData = new InvalidationData(); + invalidationData.setCommitInfo(info); + invalidationData.setSender(this); + invalidationData.setClearResourcePathCache(true); + invalidationData.setSecurityImpact(CDOProtocol.CommitNotificationInfo.IMPACT_NONE); + invalidationData.setNewPermissions(null); + invalidationData.setLockChangeInfo(null); + + session.invalidate(invalidationData); // At this point the session (invalidator) is recovered. // Continue to rethrow the exception and let the client call rollback()... @@ -3939,8 +3947,16 @@ public class CDOTransactionImpl extends CDOViewImpl implements InternalCDOTransa if (result.getRollbackMessage() != null) { CDOCommitInfo commitInfo = new FailureCommitInfo(timeStamp, result.getPreviousTimeStamp()); - session.invalidate(commitInfo, transaction, clearResourcePathCache, - CDOProtocol.CommitNotificationInfo.IMPACT_NONE, null); + + InvalidationData invalidationData = new InvalidationData(); + invalidationData.setCommitInfo(commitInfo); + invalidationData.setSender(transaction); + invalidationData.setClearResourcePathCache(clearResourcePathCache); + invalidationData.setSecurityImpact(CDOProtocol.CommitNotificationInfo.IMPACT_NONE); + invalidationData.setNewPermissions(null); + invalidationData.setLockChangeInfo(null); + + session.invalidate(invalidationData); return; } @@ -3973,12 +3989,20 @@ public class CDOTransactionImpl extends CDOViewImpl implements InternalCDOTransa removeObject(id); } + CDOLockChangeInfo lockChangeInfo = makeUnlockChangeInfo(result); + CDOCommitInfo commitInfo = makeCommitInfo(timeStamp, result.getPreviousTimeStamp()); if (!commitInfo.isEmpty()) { - byte securityImpact = result.getSecurityImpact(); - Map<CDOID, CDOPermission> newPermissions = result.getNewPermissions(); - session.invalidate(commitInfo, transaction, clearResourcePathCache, securityImpact, newPermissions); + InvalidationData invalidationData = new InvalidationData(); + invalidationData.setCommitInfo(commitInfo); + invalidationData.setSender(transaction); + invalidationData.setClearResourcePathCache(clearResourcePathCache); + invalidationData.setSecurityImpact(result.getSecurityImpact()); + invalidationData.setNewPermissions(result.getNewPermissions()); + invalidationData.setLockChangeInfo(lockChangeInfo); + + session.invalidate(invalidationData); } // Bug 290032 - Sticky views @@ -4035,26 +4059,9 @@ public class CDOTransactionImpl extends CDOViewImpl implements InternalCDOTransa fireEvent(new FinishedEvent(idMappings), listeners); } - Map<CDOObject, CDOLockState> lockStates = getLockStates(); - if (!lockStates.isEmpty()) + if (lockChangeInfo != null && isActive()) { - List<CDOLockState> objectsToUnlock = new ArrayList<CDOLockState>(); - - for (Map.Entry<CDOObject, CDOLockState> entry : lockStates.entrySet()) - { - CDOObject object = entry.getKey(); - if (options().isEffectiveAutoReleaseLock(object)) - { - InternalCDOLockState lockState = (InternalCDOLockState)entry.getValue(); - lockState.updateFrom(InternalCDOLockState.UNLOCKED); - - objectsToUnlock.add(lockState); - } - } - - CDOLockState[] newLockStates = objectsToUnlock.toArray(new CDOLockState[objectsToUnlock.size()]); - notifyOtherViewsAboutLockChanges(CDOLockChangeInfo.Operation.UNLOCK, null, result.getTimeStamp(), - newLockStates); + fireLocksChangedEvent(CDOTransactionImpl.this, lockChangeInfo); } } catch (RuntimeException ex) @@ -4078,6 +4085,32 @@ public class CDOTransactionImpl extends CDOViewImpl implements InternalCDOTransa return commitInfoManager.createCommitInfo(branch, timeStamp, previousTimeStamp, userID, comment, commitData); } + private CDOLockChangeInfo makeUnlockChangeInfo(CommitTransactionResult result) + { + Map<CDOObject, CDOLockState> lockStates = getLockStates(); + if (lockStates.isEmpty()) + { + return null; + } + + List<CDOLockState> objectsToUnlock = new ArrayList<CDOLockState>(); + + for (Map.Entry<CDOObject, CDOLockState> entry : lockStates.entrySet()) + { + CDOObject object = entry.getKey(); + if (options().isEffectiveAutoReleaseLock(object)) + { + InternalCDOLockState lockState = (InternalCDOLockState)entry.getValue(); + lockState.updateFrom(InternalCDOLockState.UNLOCKED); + + objectsToUnlock.add(lockState); + } + } + + CDOLockState[] newLockStates = objectsToUnlock.toArray(new CDOLockState[objectsToUnlock.size()]); + return makeLockChangeInfo(CDOLockChangeInfo.Operation.UNLOCK, null, result.getTimeStamp(), newLockStates); + } + private void preCommit(Map<CDOID, CDOObject> objects, Map<ByteArrayWrapper, CDOLob<?>> lobs) { if (!objects.isEmpty()) diff --git a/plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/internal/cdo/util/DefaultLocksChangedEvent.java b/plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/internal/cdo/util/DefaultLocksChangedEvent.java index 99ba07f1c1..495d7a29f7 100644 --- a/plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/internal/cdo/util/DefaultLocksChangedEvent.java +++ b/plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/internal/cdo/util/DefaultLocksChangedEvent.java @@ -40,43 +40,54 @@ public class DefaultLocksChangedEvent extends Event implements CDOLockChangeInfo this.lockChangeInfo = lockChangeInfo; } - public InternalCDOView getSender() + public final InternalCDOView getSender() { return sender; } - public CDOBranch getBranch() + public final CDOBranch getBranch() { return lockChangeInfo.getBranch(); } - public long getTimeStamp() + public final long getTimeStamp() { return lockChangeInfo.getTimeStamp(); } - public CDOLockOwner getLockOwner() + public final Operation getOperation() + { + return lockChangeInfo.getOperation(); + } + + public final LockType getLockType() + { + return lockChangeInfo.getLockType(); + } + + public final CDOLockOwner getLockOwner() { return lockChangeInfo.getLockOwner(); } - public CDOLockState[] getLockStates() + public final CDOLockState[] getLockStates() { return lockChangeInfo.getLockStates(); } - public Operation getOperation() + public final boolean isInvalidateAll() { - return lockChangeInfo.getOperation(); + return lockChangeInfo.isInvalidateAll(); } - public LockType getLockType() + protected final CDOLockChangeInfo getLockChangeInfo() { - return lockChangeInfo.getLockType(); + return lockChangeInfo; } - public boolean isInvalidateAll() + @Override + protected String formatAdditionalParameters() { - return lockChangeInfo.isInvalidateAll(); + return "sender=" + getSender() + ", " + getLockChangeInfo(); } } diff --git a/plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/internal/cdo/view/AbstractCDOView.java b/plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/internal/cdo/view/AbstractCDOView.java index 64b46d5dff..6ae6b2ce76 100644 --- a/plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/internal/cdo/view/AbstractCDOView.java +++ b/plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/internal/cdo/view/AbstractCDOView.java @@ -2873,9 +2873,15 @@ public abstract class AbstractCDOView extends CDOCommitHistoryProviderImpl<CDOOb } @Override - public String toString() + protected String formatEventName() { - return "CDOViewAdaptersNotifiedEvent: " + timeStamp; //$NON-NLS-1$ + return "CDOViewAdaptersNotifiedEvent"; + } + + @Override + protected String formatAdditionalParameters() + { + return "timeStamp=" + timeStamp; } } @@ -2896,12 +2902,6 @@ public abstract class AbstractCDOView extends CDOCommitHistoryProviderImpl<CDOOb this.branchPoint = CDOBranchUtil.copyBranchPoint(branchPoint); } - @Override - public String toString() - { - return MessageFormat.format("CDOViewTargetChangedEvent: {0}", branchPoint); //$NON-NLS-1$ - } - public CDOBranchPoint getOldBranchPoint() { return oldBranchPoint; @@ -2911,6 +2911,18 @@ public abstract class AbstractCDOView extends CDOCommitHistoryProviderImpl<CDOOb { return branchPoint; } + + @Override + protected String formatEventName() + { + return "CDOViewTargetChangedEvent"; + } + + @Override + protected String formatAdditionalParameters() + { + return "oldBranchPoint=" + oldBranchPoint + ", branchPoint=" + branchPoint; + } } /** diff --git a/plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/internal/cdo/view/CDOViewImpl.java b/plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/internal/cdo/view/CDOViewImpl.java index 814dcf43a3..993216aefc 100644 --- a/plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/internal/cdo/view/CDOViewImpl.java +++ b/plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/internal/cdo/view/CDOViewImpl.java @@ -278,12 +278,20 @@ public class CDOViewImpl extends AbstractCDOView implements IExecutorServiceProv EclipseMonitor.convert(progressMonitor)); basicSetBranchPoint(branchPoint); - CDOBranch branch = branchPoint.getBranch(); try { CDOStateMachine.SWITCHING_TARGET.set(Boolean.TRUE); - doInvalidate(branch, UNSPECIFIED_DATE, allChangedObjects, allDetachedObjects, oldRevisions, true); + + ViewInvalidationData invalidationData = new ViewInvalidationData(); + invalidationData.setLastUpdateTime(UNSPECIFIED_DATE); + invalidationData.setBranch(branchPoint.getBranch()); + invalidationData.setAllChangedObjects(allChangedObjects); + invalidationData.setAllDetachedObjects(allDetachedObjects); + invalidationData.setOldRevisions(oldRevisions); + invalidationData.setClearResourcePathCache(true); + + doInvalidate(invalidationData); } finally { @@ -541,7 +549,7 @@ public class CDOViewImpl extends AbstractCDOView implements IExecutorServiceProv } } - private CDOLockChangeInfo makeLockChangeInfo(Operation op, LockType type, long timestamp, + protected final CDOLockChangeInfo makeLockChangeInfo(Operation op, LockType type, long timestamp, CDOLockState[] newLockStates) { return CDOLockUtil.createLockChangeInfo(timestamp, this, getBranch(), op, type, newLockStates); @@ -596,12 +604,12 @@ public class CDOViewImpl extends AbstractCDOView implements IExecutorServiceProv } } - private void fireLocksChangedEvent(InternalCDOView sender, CDOLockChangeInfo lockChangeInfo) + protected final void fireLocksChangedEvent(InternalCDOView sender, CDOLockChangeInfo lockChangeInfo) { IListener[] listeners = getListeners(); if (listeners != null) { - fireEvent(new LocksChangedEvent(sender, lockChangeInfo), listeners); + fireEvent(new ViewLocksChangedEvent(sender, lockChangeInfo), listeners); } } @@ -1148,38 +1156,38 @@ public class CDOViewImpl extends AbstractCDOView implements IExecutorServiceProv revisionManager.getRevision(id, this, initialChunkSize, depth, true); } - /* - * Must not by synchronized on the view! - */ @Deprecated - public/* synchronized */void invalidate(CDOBranch branch, long lastUpdateTime, List<CDORevisionKey> allChangedObjects, + public void invalidate(CDOBranch branch, long lastUpdateTime, List<CDORevisionKey> allChangedObjects, List<CDOIDAndVersion> allDetachedObjects, Map<CDOID, InternalCDORevision> oldRevisions, boolean async) { - invalidate(branch, lastUpdateTime, allChangedObjects, allDetachedObjects, oldRevisions, async, true); + throw new UnsupportedOperationException(); + } + + @Deprecated + public void invalidate(CDOBranch branch, long lastUpdateTime, List<CDORevisionKey> allChangedObjects, + List<CDOIDAndVersion> allDetachedObjects, Map<CDOID, InternalCDORevision> oldRevisions, boolean async, + boolean clearResourcePathCache) + { + throw new UnsupportedOperationException(); } /* * Must not by synchronized on the view! */ - public/* synchronized */void invalidate(CDOBranch branch, long lastUpdateTime, List<CDORevisionKey> allChangedObjects, - List<CDOIDAndVersion> allDetachedObjects, Map<CDOID, InternalCDORevision> oldRevisions, boolean async, - boolean clearResourcePathCache) + public /* synchronized */ void invalidate(ViewInvalidationData invalidationData) { - if (async) + if (invalidationData.isAsync()) { IWorkSerializer serializer = getInvalidationRunner(); - serializer.addWork(new InvalidationRunnable(branch, lastUpdateTime, allChangedObjects, allDetachedObjects, - oldRevisions, clearResourcePathCache)); + serializer.addWork(new InvalidationRunnable(invalidationData)); } else { - doInvalidate(branch, lastUpdateTime, allChangedObjects, allDetachedObjects, oldRevisions, clearResourcePathCache); + doInvalidate(invalidationData); } } - protected void doInvalidate(CDOBranch branch, long lastUpdateTime, List<CDORevisionKey> allChangedObjects, - List<CDOIDAndVersion> allDetachedObjects, Map<CDOID, InternalCDORevision> oldRevisions, - boolean clearResourcePathCache) + protected void doInvalidate(ViewInvalidationData invalidationData) { synchronized (getViewMonitor()) { @@ -1187,8 +1195,7 @@ public class CDOViewImpl extends AbstractCDOView implements IExecutorServiceProv try { - doInvalidateSynced(branch, lastUpdateTime, allChangedObjects, allDetachedObjects, oldRevisions, - clearResourcePathCache); + doInvalidateSynced(invalidationData); } finally { @@ -1197,9 +1204,7 @@ public class CDOViewImpl extends AbstractCDOView implements IExecutorServiceProv } } - private void doInvalidateSynced(CDOBranch branch, long lastUpdateTime, List<CDORevisionKey> allChangedObjects, - List<CDOIDAndVersion> allDetachedObjects, Map<CDOID, InternalCDORevision> oldRevisions, - boolean clearResourcePathCache) + private void doInvalidateSynced(ViewInvalidationData invalidationData) { if (getTimeStamp() != UNSPECIFIED_DATE && CDOStateMachine.SWITCHING_TARGET.get() != Boolean.TRUE) { @@ -1207,12 +1212,14 @@ public class CDOViewImpl extends AbstractCDOView implements IExecutorServiceProv return; } + long lastUpdateTime = invalidationData.getLastUpdateTime(); + try { // Also false for FailureCommitInfos (because of branch==null). Only setLastUpdateTime() is called below. - if (branch == getBranch()) + if (invalidationData.getBranch() == getBranch()) { - if (clearResourcePathCache) + if (invalidationData.isClearResourcePathCache()) { clearResourcePathCacheIfNecessary(null); } @@ -1221,8 +1228,9 @@ public class CDOViewImpl extends AbstractCDOView implements IExecutorServiceProv Map<CDOObject, CDORevisionDelta> revisionDeltas = new HashMap<CDOObject, CDORevisionDelta>(); Set<CDOObject> detachedObjects = new HashSet<CDOObject>(); - Map<CDOObject, Pair<CDORevision, CDORevisionDelta>> conflicts = invalidate(allChangedObjects, - allDetachedObjects, deltas, revisionDeltas, detachedObjects); + Map<CDOObject, Pair<CDORevision, CDORevisionDelta>> conflicts = invalidate( + invalidationData.getAllChangedObjects(), invalidationData.getAllDetachedObjects(), deltas, revisionDeltas, + detachedObjects); handleConflicts(lastUpdateTime, conflicts, deltas); sendInvalidationNotifications(revisionDeltas.keySet(), detachedObjects); @@ -1232,10 +1240,16 @@ public class CDOViewImpl extends AbstractCDOView implements IExecutorServiceProv // Then send the notifications. The deltas could have been modified by the conflict resolvers. if (!deltas.isEmpty() || !detachedObjects.isEmpty()) { - sendDeltaNotifications(deltas, detachedObjects, oldRevisions); + sendDeltaNotifications(deltas, detachedObjects, invalidationData.getOldRevisions()); } fireAdaptersNotifiedEvent(lastUpdateTime); + + CDOLockChangeInfo lockChangeInfo = invalidationData.getLockChangeInfo(); + if (lockChangeInfo != null) + { + fireLocksChangedEvent(null, lockChangeInfo); + } } } catch (RuntimeException ex) @@ -2759,28 +2773,11 @@ public class CDOViewImpl extends AbstractCDOView implements IExecutorServiceProv */ private final class InvalidationRunnable extends RunnableWithName { - private final CDOBranch branch; - - private final long lastUpdateTime; - - private final List<CDORevisionKey> allChangedObjects; - - private final List<CDOIDAndVersion> allDetachedObjects; - - private final Map<CDOID, InternalCDORevision> oldRevisions; - - private boolean clearResourcePathCache; + private final ViewInvalidationData invalidationData; - private InvalidationRunnable(CDOBranch branch, long lastUpdateTime, List<CDORevisionKey> allChangedObjects, - List<CDOIDAndVersion> allDetachedObjects, Map<CDOID, InternalCDORevision> oldRevisions, - boolean clearResourcePathCache) + public InvalidationRunnable(ViewInvalidationData invalidationData) { - this.branch = branch; - this.lastUpdateTime = lastUpdateTime; - this.allChangedObjects = allChangedObjects; - this.allDetachedObjects = allDetachedObjects; - this.oldRevisions = oldRevisions; - this.clearResourcePathCache = clearResourcePathCache; + this.invalidationData = invalidationData; } @Override @@ -2795,8 +2792,7 @@ public class CDOViewImpl extends AbstractCDOView implements IExecutorServiceProv try { invalidationRunnerActive = true; - doInvalidate(branch, lastUpdateTime, allChangedObjects, allDetachedObjects, oldRevisions, - clearResourcePathCache); + doInvalidate(invalidationData); } catch (Exception ex) { @@ -2854,9 +2850,16 @@ public class CDOViewImpl extends AbstractCDOView implements IExecutorServiceProv } @Override - public String toString() + protected String formatEventName() { - return "CDOViewInvalidationEvent" + revisionDeltas; //$NON-NLS-1$ + return "CDOViewInvalidationEvent"; + } + + @Override + protected String formatAdditionalParameters() + { + return "timeStamp=" + timeStamp + ", revisionDeltas=" + revisionDeltas + ", detachedObjects=" + detachedObjects + + "]"; } } @@ -2864,11 +2867,11 @@ public class CDOViewImpl extends AbstractCDOView implements IExecutorServiceProv * @author Caspar De Groot * @since 4.1 */ - private final class LocksChangedEvent extends DefaultLocksChangedEvent implements CDOViewLocksChangedEvent + private final class ViewLocksChangedEvent extends DefaultLocksChangedEvent implements CDOViewLocksChangedEvent { private static final long serialVersionUID = 1L; - public LocksChangedEvent(InternalCDOView sender, CDOLockChangeInfo lockChangeInfo) + public ViewLocksChangedEvent(InternalCDOView sender, CDOLockChangeInfo lockChangeInfo) { super(CDOViewImpl.this, sender, lockChangeInfo); } @@ -2916,6 +2919,12 @@ public class CDOViewImpl extends AbstractCDOView implements IExecutorServiceProv return objects.toArray(new EObject[objects.size()]); } + + @Override + protected String formatEventName() + { + return "CDOViewLocksChangedEvent"; + } } /** 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 a4eb51d95f..7794917985 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 @@ -256,11 +256,18 @@ public interface InternalCDOSession /** * @since 4.3 + * @deprecated As of 4.6 use {@link #invalidate(InvalidationData)}. */ + @Deprecated public void invalidate(CDOCommitInfo commitInfo, InternalCDOTransaction sender, boolean clearResourcePathCache, byte securityImpact, Map<CDOID, CDOPermission> newPermissions); /** + * @since 4.6 + */ + public void invalidate(InvalidationData invalidationData); + + /** * @since 3.0 */ public void processRefreshSessionResult(RefreshSessionResult result, CDOBranch branch, @@ -352,6 +359,111 @@ public interface InternalCDOSession } /** + * A data structure that holds all input values of {@link InternalCDOSession#invalidate(InvalidationData) InternalCDOSession#invalidate()}. + * + * @author Eike Stepper + * @since 4.6 + */ + public static final class InvalidationData + { + private CDOCommitInfo commitInfo; + + private InternalCDOTransaction sender; + + private boolean clearResourcePathCache; + + private byte securityImpact; + + private Map<CDOID, CDOPermission> newPermissions; + + private CDOLockChangeInfo lockChangeInfo; + + public InvalidationData() + { + } + + public CDOCommitInfo getCommitInfo() + { + return commitInfo; + } + + public void setCommitInfo(CDOCommitInfo commitInfo) + { + this.commitInfo = commitInfo; + } + + public InternalCDOTransaction getSender() + { + return sender; + } + + public void setSender(InternalCDOTransaction sender) + { + this.sender = sender; + } + + public boolean isClearResourcePathCache() + { + return clearResourcePathCache; + } + + public void setClearResourcePathCache(boolean clearResourcePathCache) + { + this.clearResourcePathCache = clearResourcePathCache; + } + + public byte getSecurityImpact() + { + return securityImpact; + } + + public void setSecurityImpact(byte securityImpact) + { + this.securityImpact = securityImpact; + } + + public Map<CDOID, CDOPermission> getNewPermissions() + { + return newPermissions; + } + + public void setNewPermissions(Map<CDOID, CDOPermission> newPermissions) + { + this.newPermissions = newPermissions; + } + + public CDOLockChangeInfo getLockChangeInfo() + { + return lockChangeInfo; + } + + public void setLockChangeInfo(CDOLockChangeInfo lockChangeInfo) + { + this.lockChangeInfo = lockChangeInfo; + } + + @Override + public String toString() + { + StringBuilder builder = new StringBuilder(); + builder.append("InvalidationData[commitInfo="); + builder.append(commitInfo); + builder.append(", sender="); + builder.append(sender); + builder.append(", clearResourcePathCache="); + builder.append(clearResourcePathCache); + builder.append(", securityImpact="); + builder.append(securityImpact); + builder.append(", newPermissions="); + builder.append(newPermissions); + builder.append(", lockChangeInfo="); + builder.append(lockChangeInfo); + builder.append("]"); + return builder.toString(); + } + } + + /** * 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/InternalCDOView.java b/plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/spi/cdo/InternalCDOView.java index 62110bd87c..ad471fbad1 100644 --- a/plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/spi/cdo/InternalCDOView.java +++ b/plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/spi/cdo/InternalCDOView.java @@ -117,12 +117,19 @@ public interface InternalCDOView extends CDOView, CDOIDProvider, ILifecycle /** * @since 4.2 + * @deprecated As of 4.6. use {@link #invalidate(ViewInvalidationData)} */ + @Deprecated public void invalidate(CDOBranch branch, long lastUpdateTime, List<CDORevisionKey> allChangedObjects, List<CDOIDAndVersion> allDetachedObjects, Map<CDOID, InternalCDORevision> oldRevisions, boolean async, boolean clearResourcePathCache); /** + * @since 4.6 + */ + public void invalidate(ViewInvalidationData invalidationData); + + /** * @since 3.0 */ public void setLastUpdateTime(long lastUpdateTime); @@ -272,4 +279,137 @@ public interface InternalCDOView extends CDOView, CDOIDProvider, ILifecycle return viewAndStates; } } + + /** + * A data structure that holds all input values of {@link InternalCDOView#invalidate(ViewInvalidationData) InternalCDOView#invalidate()}. + * + * @author Eike Stepper + * @since 4.6 + */ + public static final class ViewInvalidationData + { + private CDOBranch branch; + + private long lastUpdateTime; + + private List<CDORevisionKey> allChangedObjects; + + private List<CDOIDAndVersion> allDetachedObjects; + + private Map<CDOID, InternalCDORevision> oldRevisions; + + private boolean async; + + private boolean clearResourcePathCache; + + private CDOLockChangeInfo lockChangeInfo; + + public ViewInvalidationData() + { + } + + public CDOBranch getBranch() + { + return branch; + } + + public void setBranch(CDOBranch branch) + { + this.branch = branch; + } + + public long getLastUpdateTime() + { + return lastUpdateTime; + } + + public void setLastUpdateTime(long lastUpdateTime) + { + this.lastUpdateTime = lastUpdateTime; + } + + public List<CDORevisionKey> getAllChangedObjects() + { + return allChangedObjects; + } + + public void setAllChangedObjects(List<CDORevisionKey> allChangedObjects) + { + this.allChangedObjects = allChangedObjects; + } + + public List<CDOIDAndVersion> getAllDetachedObjects() + { + return allDetachedObjects; + } + + public void setAllDetachedObjects(List<CDOIDAndVersion> allDetachedObjects) + { + this.allDetachedObjects = allDetachedObjects; + } + + public Map<CDOID, InternalCDORevision> getOldRevisions() + { + return oldRevisions; + } + + public void setOldRevisions(Map<CDOID, InternalCDORevision> oldRevisions) + { + this.oldRevisions = oldRevisions; + } + + public boolean isAsync() + { + return async; + } + + public void setAsync(boolean async) + { + this.async = async; + } + + public boolean isClearResourcePathCache() + { + return clearResourcePathCache; + } + + public void setClearResourcePathCache(boolean clearResourcePathCache) + { + this.clearResourcePathCache = clearResourcePathCache; + } + + public CDOLockChangeInfo getLockChangeInfo() + { + return lockChangeInfo; + } + + public void setLockChangeInfo(CDOLockChangeInfo lockChangeInfo) + { + this.lockChangeInfo = lockChangeInfo; + } + + @Override + public String toString() + { + StringBuilder builder = new StringBuilder(); + builder.append("ViewInvalidationData[branch="); + builder.append(branch); + builder.append(", lastUpdateTime="); + builder.append(lastUpdateTime); + builder.append(", allChangedObjects="); + builder.append(allChangedObjects); + builder.append(", allDetachedObjects="); + builder.append(allDetachedObjects); + builder.append(", oldRevisions="); + builder.append(oldRevisions); + builder.append(", async="); + builder.append(async); + builder.append(", clearResourcePathCache="); + builder.append(clearResourcePathCache); + builder.append(", lockChangeInfo="); + builder.append(lockChangeInfo); + builder.append("]"); + return builder.toString(); + } + } } diff --git a/plugins/org.eclipse.net4j.db.h2/META-INF/MANIFEST.MF b/plugins/org.eclipse.net4j.db.h2/META-INF/MANIFEST.MF index 5362ed06e9..1b62110a7a 100644 --- a/plugins/org.eclipse.net4j.db.h2/META-INF/MANIFEST.MF +++ b/plugins/org.eclipse.net4j.db.h2/META-INF/MANIFEST.MF @@ -2,7 +2,7 @@ Manifest-Version: 1.0 Bundle-ManifestVersion: 2 Bundle-Name: %pluginName Bundle-SymbolicName: org.eclipse.net4j.db.h2;singleton:=true -Bundle-Version: 4.2.300.qualifier +Bundle-Version: 4.3.0.qualifier Bundle-Vendor: %providerName Bundle-Localization: plugin Bundle-ClassPath: . @@ -18,6 +18,6 @@ Import-Package: org.h2;version="[1.0.0,2.0.0)";resolution:=optional;x-installati org.h2.value;version="[1.0.0,2.0.0)";resolution:=optional;x-installation:=greedy Require-Bundle: org.eclipse.core.runtime;bundle-version="[3.5.0,4.0.0)", org.eclipse.net4j.db;bundle-version="[4.0.0,5.0.0)";visibility:=reexport -Export-Package: org.eclipse.net4j.db.h2;version="4.2.300", - org.eclipse.net4j.db.internal.h2.bundle;version="4.2.300";x-internal:=true +Export-Package: org.eclipse.net4j.db.h2;version="4.3.0", + org.eclipse.net4j.db.internal.h2.bundle;version="4.3.0";x-internal:=true Eclipse-RegisterBuddy: org.eclipse.net4j.db diff --git a/plugins/org.eclipse.net4j.db.h2/src/org/eclipse/net4j/db/h2/H2Adapter.java b/plugins/org.eclipse.net4j.db.h2/src/org/eclipse/net4j/db/h2/H2Adapter.java index 02ef7e0c81..a6d00bf0cb 100644 --- a/plugins/org.eclipse.net4j.db.h2/src/org/eclipse/net4j/db/h2/H2Adapter.java +++ b/plugins/org.eclipse.net4j.db.h2/src/org/eclipse/net4j/db/h2/H2Adapter.java @@ -115,4 +115,19 @@ public class H2Adapter extends DBAdapter } }); } + + /** + * @since 4.3 + */ + public static void shutdown(DataSource dataSource) + { + DBUtil.execute(DBUtil.createConnectionProvider(dataSource), new RunnableWithConnection<Object>() + { + public Object run(Connection connection) throws SQLException + { + DBUtil.execute(connection, "SHUTDOWN"); + return null; + } + }); + } } diff --git a/plugins/org.eclipse.net4j.tests/src/org/eclipse/net4j/util/tests/AbstractOMTest.java b/plugins/org.eclipse.net4j.tests/src/org/eclipse/net4j/util/tests/AbstractOMTest.java index 8420c88071..ec32e37ae4 100644 --- a/plugins/org.eclipse.net4j.tests/src/org/eclipse/net4j/util/tests/AbstractOMTest.java +++ b/plugins/org.eclipse.net4j.tests/src/org/eclipse/net4j/util/tests/AbstractOMTest.java @@ -443,6 +443,7 @@ public abstract class AbstractOMTest extends TestCase { IOUtil.delete(file); } + filesToDelete.clear(); } } diff --git a/plugins/org.eclipse.net4j.util/src/org/eclipse/net4j/util/concurrent/RunnableWithName.java b/plugins/org.eclipse.net4j.util/src/org/eclipse/net4j/util/concurrent/RunnableWithName.java index ef72c20d90..cce82fb489 100644 --- a/plugins/org.eclipse.net4j.util/src/org/eclipse/net4j/util/concurrent/RunnableWithName.java +++ b/plugins/org.eclipse.net4j.util/src/org/eclipse/net4j/util/concurrent/RunnableWithName.java @@ -11,6 +11,7 @@ package org.eclipse.net4j.util.concurrent; import org.eclipse.net4j.util.StringUtil; +import org.eclipse.net4j.util.om.OMPlatform; /** * @author Eike Stepper @@ -18,10 +19,17 @@ import org.eclipse.net4j.util.StringUtil; */ public abstract class RunnableWithName implements Runnable { - public abstract String getName(); + private static final boolean DISABLE_RUNNABLE_NAMES = Boolean.parseBoolean( + OMPlatform.INSTANCE.getProperty("org.eclipse.net4j.util.concurrent.DISABLE_RUNNABLE_NAMES", "false")); public final void run() { + if (DISABLE_RUNNABLE_NAMES) + { + doRun(); + return; + } + Thread thread = null; String oldName = null; @@ -54,5 +62,7 @@ public abstract class RunnableWithName implements Runnable } } + public abstract String getName(); + protected abstract void doRun(); } diff --git a/plugins/org.eclipse.net4j.util/src/org/eclipse/net4j/util/event/Event.java b/plugins/org.eclipse.net4j.util/src/org/eclipse/net4j/util/event/Event.java index b30c90f465..fa9197de6f 100644 --- a/plugins/org.eclipse.net4j.util/src/org/eclipse/net4j/util/event/Event.java +++ b/plugins/org.eclipse.net4j.util/src/org/eclipse/net4j/util/event/Event.java @@ -38,7 +38,15 @@ public class Event extends EventObject implements IEvent { String params = formatAdditionalParameters(); params = params == null ? "" : ", " + params; - return MessageFormat.format("{0}[source={1}{2}]", getClass().getSimpleName(), getSource(), params); + return MessageFormat.format("{0}[source={1}{2}]", formatEventName(), getSource(), params); + } + + /** + * @since 3.7 + */ + protected String formatEventName() + { + return getClass().getSimpleName(); } /** |