diff options
21 files changed, 1146 insertions, 218 deletions
diff --git a/plugins/org.eclipse.emf.cdo.net4j/src/org/eclipse/emf/cdo/internal/net4j/protocol/CommitTransactionRequest.java b/plugins/org.eclipse.emf.cdo.net4j/src/org/eclipse/emf/cdo/internal/net4j/protocol/CommitTransactionRequest.java index acf0b462c9..60ae48f28d 100644 --- a/plugins/org.eclipse.emf.cdo.net4j/src/org/eclipse/emf/cdo/internal/net4j/protocol/CommitTransactionRequest.java +++ b/plugins/org.eclipse.emf.cdo.net4j/src/org/eclipse/emf/cdo/internal/net4j/protocol/CommitTransactionRequest.java @@ -69,26 +69,24 @@ public class CommitTransactionRequest extends CDOClientRequestWithMonitoring<Com private static long sleepMillisForTesting = 0L; - private CDOIDProvider idProvider; // CDOTransaction + private final int commitNumber; - private int commitNumber; + private final String commitComment; - private String commitComment; + private final CDOCommitData commitData; - private boolean releaseLocks; + private final Collection<CDOLob<?>> lobs; - private CDOCommitData commitData; + private final Collection<CDOLockState> locksOnNewObjects; - private Collection<CDOLob<?>> lobs; + private final Collection<CDOID> unlocksOnChangedObjects; - private Collection<CDOLockState> locksOnNewObjects; - - private int viewID; + private final int viewID; /** * Is <code>null</code> in {@link CommitDelegationRequest}. */ - private InternalCDOTransaction transaction; + private final InternalCDOTransaction transaction; private boolean clearResourcePathCache; @@ -100,20 +98,23 @@ public class CommitTransactionRequest extends CDOClientRequestWithMonitoring<Com public CommitTransactionRequest(CDOClientProtocol protocol, short signalID, InternalCDOCommitContext context) { super(protocol, signalID); - transaction = context.getTransaction(); + CommitToken commitToken = transaction.getCommitToken(); if (commitToken != null) { commitNumber = commitToken.getCommitNumber(); } + else + { + commitNumber = 0; + } commitComment = context.getCommitComment(); - releaseLocks = context.isAutoReleaseLocks(); - idProvider = context.getTransaction(); commitData = context.getCommitData(); lobs = context.getLobs(); locksOnNewObjects = context.getLocksOnNewObjects(); + unlocksOnChangedObjects = context.getUnlocksOnChangedObjects(); viewID = context.getViewID(); } @@ -127,7 +128,7 @@ public class CommitTransactionRequest extends CDOClientRequestWithMonitoring<Com @Override protected CDOIDProvider getIDProvider() { - return idProvider; + return transaction; } @Override @@ -150,33 +151,43 @@ public class CommitTransactionRequest extends CDOClientRequestWithMonitoring<Com List<CDOIDAndVersion> detachedObjects = commitData.getDetachedObjects(); out.writeLong(getLastUpdateTime()); - out.writeBoolean(releaseLocks); out.writeInt(commitNumber); out.writeString(commitComment); - out.writeInt(newPackageUnits.size()); out.writeInt(locksOnNewObjects.size()); + out.writeInt(unlocksOnChangedObjects.size()); + out.writeInt(newPackageUnits.size()); out.writeInt(newObjects.size()); out.writeInt(changedObjects.size()); out.writeInt(detachedObjects.size()); if (TRACER.isEnabled()) { - TRACER.format("Writing {0} new package units", newPackageUnits.size()); //$NON-NLS-1$ + TRACER.format("Writing {0} locks on new objects", locksOnNewObjects.size()); //$NON-NLS-1$ } - for (CDOPackageUnit newPackageUnit : newPackageUnits) + for (CDOLockState lockState : locksOnNewObjects) { - out.writeCDOPackageUnit(newPackageUnit, true); + out.writeCDOLockState(lockState); } if (TRACER.isEnabled()) { - TRACER.format("Writing {0} locks on new objects", locksOnNewObjects.size()); //$NON-NLS-1$ + TRACER.format("Writing {0} unlocks on changed objects", unlocksOnChangedObjects.size()); //$NON-NLS-1$ } - for (CDOLockState lockState : locksOnNewObjects) + for (CDOID id : unlocksOnChangedObjects) { - out.writeCDOLockState(lockState); + out.writeCDOID(id); + } + + if (TRACER.isEnabled()) + { + TRACER.format("Writing {0} new package units", newPackageUnits.size()); //$NON-NLS-1$ + } + + for (CDOPackageUnit newPackageUnit : newPackageUnits) + { + out.writeCDOPackageUnit(newPackageUnit, true); } if (TRACER.isEnabled()) @@ -319,7 +330,7 @@ public class CommitTransactionRequest extends CDOClientRequestWithMonitoring<Com } CommitTransactionResult result = new CommitTransactionResult(); - result.setIDProvider(idProvider); + result.setIDProvider(transaction); result.setClearResourcePathCache(clearResourcePathCache); result.setRollbackReason(in.readByte()); result.setRollbackMessage(in.readString()); @@ -345,7 +356,7 @@ public class CommitTransactionRequest extends CDOClientRequestWithMonitoring<Com protected CommitTransactionResult confirmingResult(CDODataInput in) throws IOException { CommitTransactionResult result = new CommitTransactionResult(); - result.setIDProvider(idProvider); + result.setIDProvider(transaction); result.setClearResourcePathCache(clearResourcePathCache); result.setBranchPoint(in.readCDOBranchPoint()); result.setPreviousTimeStamp(in.readLong()); diff --git a/plugins/org.eclipse.emf.cdo.net4j/src/org/eclipse/emf/cdo/internal/net4j/protocol/UnlockObjectsRequest.java b/plugins/org.eclipse.emf.cdo.net4j/src/org/eclipse/emf/cdo/internal/net4j/protocol/UnlockObjectsRequest.java index 914e8bdd86..a90d1d99a2 100644 --- a/plugins/org.eclipse.emf.cdo.net4j/src/org/eclipse/emf/cdo/internal/net4j/protocol/UnlockObjectsRequest.java +++ b/plugins/org.eclipse.emf.cdo.net4j/src/org/eclipse/emf/cdo/internal/net4j/protocol/UnlockObjectsRequest.java @@ -62,6 +62,7 @@ public class UnlockObjectsRequest extends CDOClientRequest<UnlockObjectsResult> out.writeInt(viewID); out.writeCDOLockType(lockType); out.writeBoolean(recursive); + if (objectIDs == null) { if (TRACER.isEnabled()) @@ -97,11 +98,13 @@ public class UnlockObjectsRequest extends CDOClientRequest<UnlockObjectsResult> { long timestamp = in.readLong(); int n = in.readInt(); + CDOLockState[] newLockStates = new CDOLockState[n]; for (int i = 0; i < n; i++) { newLockStates[i] = in.readCDOLockState(); } + return new UnlockObjectsResult(newLockStates, timestamp); } } diff --git a/plugins/org.eclipse.emf.cdo.server.hibernate/src/org/eclipse/emf/cdo/server/internal/hibernate/HibernateRawCommitContext.java b/plugins/org.eclipse.emf.cdo.server.hibernate/src/org/eclipse/emf/cdo/server/internal/hibernate/HibernateRawCommitContext.java index ee8b86b579..5b0e2ef301 100644 --- a/plugins/org.eclipse.emf.cdo.server.hibernate/src/org/eclipse/emf/cdo/server/internal/hibernate/HibernateRawCommitContext.java +++ b/plugins/org.eclipse.emf.cdo.server.hibernate/src/org/eclipse/emf/cdo/server/internal/hibernate/HibernateRawCommitContext.java @@ -125,6 +125,7 @@ public class HibernateRawCommitContext implements InternalCommitContext { } + @Deprecated public boolean isAutoReleaseLocksEnabled() { return false; @@ -160,6 +161,11 @@ public class HibernateRawCommitContext implements InternalCommitContext return null; } + public CDOID[] getUnlocksOnChangedObjects() + { + return null; + } + public InternalCDORevision[] getNewObjects() { return newObjects.toArray(new InternalCDORevision[0]); @@ -303,6 +309,10 @@ public class HibernateRawCommitContext implements InternalCommitContext { } + public void setUnlocksOnChangedObjects(CDOID[] unlocksOnChangedObjects) + { + } + public void setNewObjects(InternalCDORevision[] newObjects) { } @@ -327,6 +337,7 @@ public class HibernateRawCommitContext implements InternalCommitContext { } + @Deprecated public void setAutoReleaseLocksEnabled(boolean on) { } diff --git a/plugins/org.eclipse.emf.cdo.server.net4j/src/org/eclipse/emf/cdo/server/internal/net4j/protocol/CommitTransactionIndication.java b/plugins/org.eclipse.emf.cdo.server.net4j/src/org/eclipse/emf/cdo/server/internal/net4j/protocol/CommitTransactionIndication.java index 0b38c4471c..779b757afe 100644 --- a/plugins/org.eclipse.emf.cdo.server.net4j/src/org/eclipse/emf/cdo/server/internal/net4j/protocol/CommitTransactionIndication.java +++ b/plugins/org.eclipse.emf.cdo.server.net4j/src/org/eclipse/emf/cdo/server/internal/net4j/protocol/CommitTransactionIndication.java @@ -126,19 +126,44 @@ public class CommitTransactionIndication extends CDOServerIndicationWithMonitori commitContext.preWrite(); long lastUpdateTime = in.readLong(); - boolean autoReleaseLocksEnabled = in.readBoolean(); int commitNumber = in.readInt(); String commitComment = in.readString(); - InternalCDOPackageUnit[] newPackageUnits = new InternalCDOPackageUnit[in.readInt()]; CDOLockState[] locksOnNewObjects = new CDOLockState[in.readInt()]; + CDOID[] unlocksOnChangedObjects = new CDOID[in.readInt()]; + InternalCDOPackageUnit[] newPackageUnits = new InternalCDOPackageUnit[in.readInt()]; InternalCDORevision[] newObjects = new InternalCDORevision[in.readInt()]; InternalCDORevisionDelta[] dirtyObjectDeltas = new InternalCDORevisionDelta[in.readInt()]; CDOID[] detachedObjects = new CDOID[in.readInt()]; - monitor.begin(newPackageUnits.length + newObjects.length + dirtyObjectDeltas.length + detachedObjects.length); + monitor.begin(locksOnNewObjects.length + unlocksOnChangedObjects.length + newPackageUnits.length + newObjects.length + + dirtyObjectDeltas.length + detachedObjects.length); try { + // Locks on new objects + if (TRACER.isEnabled()) + { + TRACER.format("Reading {0} locks on new objects", locksOnNewObjects.length); //$NON-NLS-1$ + } + + for (int i = 0; i < locksOnNewObjects.length; i++) + { + locksOnNewObjects[i] = in.readCDOLockState(); + monitor.worked(); + } + + // Unlocks on changed objects + if (TRACER.isEnabled()) + { + TRACER.format("Reading {0} unlocks on changed objects", unlocksOnChangedObjects.length); //$NON-NLS-1$ + } + + for (int i = 0; i < unlocksOnChangedObjects.length; i++) + { + unlocksOnChangedObjects[i] = in.readCDOID(); + monitor.worked(); + } + // New package units if (TRACER.isEnabled()) { @@ -161,18 +186,6 @@ public class CommitTransactionIndication extends CDOServerIndicationWithMonitori EMFUtil.safeResolveAll(resourceSet); } - // Locks on new objects - if (TRACER.isEnabled()) - { - TRACER.format("Reading {0} locks on new objects", locksOnNewObjects.length); //$NON-NLS-1$ - } - - for (int i = 0; i < locksOnNewObjects.length; i++) - { - locksOnNewObjects[i] = in.readCDOLockState(); - monitor.worked(); - } - // New objects if (TRACER.isEnabled()) { @@ -274,7 +287,6 @@ public class CommitTransactionIndication extends CDOServerIndicationWithMonitori commitContext.setCommitNumber(commitNumber); commitContext.setLastUpdateTime(lastUpdateTime); - commitContext.setAutoReleaseLocksEnabled(autoReleaseLocksEnabled); commitContext.setClearResourcePathCache(clearResourcePathCache); commitContext.setUsingEcore(usingEcore); commitContext.setUsingEtypes(usingEtypes); @@ -287,6 +299,8 @@ public class CommitTransactionIndication extends CDOServerIndicationWithMonitori commitContext.setDetachedObjectVersions(detachedObjectVersions); commitContext.setCommitComment(commitComment); commitContext.setLobs(getIndicationStream()); + commitContext.setLocksOnNewObjects(locksOnNewObjects); + commitContext.setUnlocksOnChangedObjects(unlocksOnChangedObjects); } finally { diff --git a/plugins/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/internal/server/DelegatingCommitContext.java b/plugins/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/internal/server/DelegatingCommitContext.java index a6872ffee7..6066e867f4 100644 --- a/plugins/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/internal/server/DelegatingCommitContext.java +++ b/plugins/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/internal/server/DelegatingCommitContext.java @@ -61,11 +61,6 @@ public abstract class DelegatingCommitContext implements IStoreAccessor.CommitCo return getDelegate().getCommitComment(); } - public boolean isAutoReleaseLocksEnabled() - { - return getDelegate().isAutoReleaseLocksEnabled(); - } - public InternalCDOPackageRegistry getPackageRegistry() { return getDelegate().getPackageRegistry(); @@ -136,11 +131,22 @@ public abstract class DelegatingCommitContext implements IStoreAccessor.CommitCo return getDelegate().isUsingEtypes(); } + @Deprecated + public boolean isAutoReleaseLocksEnabled() + { + return getDelegate().isAutoReleaseLocksEnabled(); + } + public CDOLockState[] getLocksOnNewObjects() { return getDelegate().getLocksOnNewObjects(); } + public CDOID[] getUnlocksOnChangedObjects() + { + return getDelegate().getUnlocksOnChangedObjects(); + } + public CDOBranchVersion[] getDetachedObjectVersions() { return getDelegate().getDetachedObjectVersions(); 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 5163a45593..eaa557f409 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 @@ -147,8 +147,6 @@ public class TransactionCommitContext implements InternalCommitContext private InternalCDOPackageUnit[] newPackageUnits = new InternalCDOPackageUnit[0]; - private CDOLockState[] locksOnNewObjects = new CDOLockState[0]; - private InternalCDORevision[] newObjects = new InternalCDORevision[0]; private InternalCDORevisionDelta[] dirtyObjectDeltas = new InternalCDORevisionDelta[0]; @@ -179,7 +177,7 @@ public class TransactionCommitContext implements InternalCommitContext private List<CDOIDReference> xRefs; - private List<LockState<Object, IView>> postCommitLockStates; + private final List<LockState<Object, IView>> postCommitLockStates = new ArrayList<LockState<Object, IView>>(); private boolean hasChanges; @@ -187,10 +185,12 @@ public class TransactionCommitContext implements InternalCommitContext private boolean ensuringReferentialIntegrity; - private boolean autoReleaseLocksEnabled; - private ExtendedDataInputStream lobs; + private CDOLockState[] locksOnNewObjects = new CDOLockState[0]; + + private CDOID[] unlocksOnChangedObjects = new CDOID[0]; + private Map<Object, Object> data; private CommitNotificationInfo commitNotificationInfo = new CommitNotificationInfo(); @@ -238,11 +238,6 @@ public class TransactionCommitContext implements InternalCommitContext return lastUpdateTime; } - public boolean isAutoReleaseLocksEnabled() - { - return autoReleaseLocksEnabled; - } - public byte getRollbackReason() { return rollbackReason; @@ -294,11 +289,6 @@ public class TransactionCommitContext implements InternalCommitContext return newPackageUnits; } - public CDOLockState[] getLocksOnNewObjects() - { - return locksOnNewObjects; - } - public InternalCDORevision[] getNewObjects() { return newObjects; @@ -526,11 +516,6 @@ public class TransactionCommitContext implements InternalCommitContext this.newPackageUnits = newPackageUnits; } - public void setLocksOnNewObjects(CDOLockState[] locksOnNewObjects) - { - this.locksOnNewObjects = locksOnNewObjects; - } - public void setNewObjects(InternalCDORevision[] newObjects) { this.newObjects = newObjects; @@ -561,11 +546,6 @@ public class TransactionCommitContext implements InternalCommitContext this.lastUpdateTime = lastUpdateTime; } - public void setAutoReleaseLocksEnabled(boolean on) - { - autoReleaseLocksEnabled = on; - } - public void setCommitNumber(int commitNumber) { this.commitNumber = commitNumber; @@ -586,6 +566,38 @@ public class TransactionCommitContext implements InternalCommitContext lobs = in; } + @Deprecated + public boolean isAutoReleaseLocksEnabled() + { + return false; + } + + @Deprecated + public void setAutoReleaseLocksEnabled(boolean on) + { + // Do nothing. + } + + public CDOLockState[] getLocksOnNewObjects() + { + return locksOnNewObjects; + } + + public void setLocksOnNewObjects(CDOLockState[] locksOnNewObjects) + { + this.locksOnNewObjects = locksOnNewObjects; + } + + public CDOID[] getUnlocksOnChangedObjects() + { + return unlocksOnChangedObjects; + } + + public void setUnlocksOnChangedObjects(CDOID[] unlocksOnChangedObjects) + { + this.unlocksOnChangedObjects = unlocksOnChangedObjects; + } + public <T> T getData(Object key) { if (data == null) @@ -1380,18 +1392,17 @@ public class TransactionCommitContext implements InternalCommitContext applyLocksOnNewObjects(); monitor.worked(); - if (autoReleaseLocksEnabled) + applyUnlocksOnChangedObjects(); + monitor.worked(); + + if (!postCommitLockStates.isEmpty()) { - postCommitLockStates = lockManager.unlock2(true, transaction); - if (!postCommitLockStates.isEmpty()) - { - // TODO (CD) Does doing this here make sense? - // The commit notifications get sent later, from postCommit. - sendLockNotifications(postCommitLockStates); - } + int xxx; + // TODO (CD) Does doing this here make sense? + // The commit notifications get sent later, from postCommit. + sendLockNotifications(postCommitLockStates); } - monitor.worked(); repository.notifyWriteAccessHandlers(transaction, this, false, monitor.fork()); } catch (Throwable t) @@ -1407,12 +1418,13 @@ public class TransactionCommitContext implements InternalCommitContext protected void applyLocksOnNewObjects() throws InterruptedException { final CDOLockOwner owner = CDOLockUtil.createLockOwner(transaction); + final boolean mapIDs = transaction.getRepository().getIDGenerationLocation() == IDGenerationLocation.STORE; for (CDOLockState lockState : locksOnNewObjects) { Object target = lockState.getLockedObject(); - if (transaction.getRepository().getIDGenerationLocation() == IDGenerationLocation.STORE) + if (mapIDs) { CDOIDAndBranch idAndBranch = target instanceof CDOIDAndBranch ? (CDOIDAndBranch)target : null; CDOID id = idAndBranch != null ? ((CDOIDAndBranch)target).getID() : (CDOID)target; @@ -1422,13 +1434,38 @@ public class TransactionCommitContext implements InternalCommitContext target = idAndBranch != null ? CDOIDUtil.createIDAndBranch(newID, idAndBranch.getBranch()) : newID; } + LockState<Object, IView> postCommitLockState = null; for (LockType type : LockType.values()) { if (lockState.isLocked(type, owner, false)) { - lockManager.lock2(type, transaction, Collections.singleton(target), 0); + List<LockState<Object, IView>> lockStates = lockManager.lock2(type, transaction, + Collections.singleton(target), 0); + postCommitLockState = lockStates.get(0); } } + + if (postCommitLockState != null) + { + postCommitLockStates.add(postCommitLockState); + } + } + } + + protected void applyUnlocksOnChangedObjects() throws InterruptedException + { + List<Object> targets = new ArrayList<Object>(); + + for (CDOID id : unlocksOnChangedObjects) + { + Object target = lockManager.getLockKey(id, branch); + targets.add(target); + } + + List<LockState<Object, IView>> lockStates = lockManager.unlock2(transaction, targets); + if (lockStates != null) + { + postCommitLockStates.addAll(lockStates); } } diff --git a/plugins/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/internal/server/syncing/SynchronizableRepository.java b/plugins/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/internal/server/syncing/SynchronizableRepository.java index 0151075080..8554b14aaa 100644 --- a/plugins/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/internal/server/syncing/SynchronizableRepository.java +++ b/plugins/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/internal/server/syncing/SynchronizableRepository.java @@ -1022,13 +1022,6 @@ public abstract class SynchronizableRepository extends Repository.Default implem throw new UnsupportedOperationException(); } - public Collection<CDOLockState> getLocksOnNewObjects() - { - CDOLockState[] locksOnNewObjectsArr = WriteThroughCommitContext.this.getLocksOnNewObjects(); - Collection<CDOLockState> locksOnNewObjects = Arrays.asList(locksOnNewObjectsArr); - return locksOnNewObjects; - } - public Collection<CDOLob<?>> getLobs() { return Collections.emptySet(); // TODO (CD) Did we forget to support this earlier? @@ -1074,11 +1067,24 @@ public abstract class SynchronizableRepository extends Repository.Default implem return WriteThroughCommitContext.this.getUserID(); } + @Deprecated public boolean isAutoReleaseLocks() { return WriteThroughCommitContext.this.isAutoReleaseLocksEnabled(); } + public Collection<CDOLockState> getLocksOnNewObjects() + { + CDOLockState[] locksOnNewObjectsArray = WriteThroughCommitContext.this.getLocksOnNewObjects(); + return Arrays.asList(locksOnNewObjectsArray); + } + + public Collection<CDOID> getUnlocksOnChangedObjects() + { + CDOID[] unlocksOnChangedObjectsArray = WriteThroughCommitContext.this.getUnlocksOnChangedObjects(); + return Arrays.asList(unlocksOnChangedObjectsArray); + } + public String getCommitComment() { return WriteThroughCommitContext.this.getCommitComment(); diff --git a/plugins/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/server/IStoreAccessor.java b/plugins/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/server/IStoreAccessor.java index 332a01f1da..230bb7ec2e 100644 --- a/plugins/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/server/IStoreAccessor.java +++ b/plugins/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/server/IStoreAccessor.java @@ -312,11 +312,6 @@ public interface IStoreAccessor extends IQueryHandlerProvider, BranchLoader, Com public long getLastUpdateTime(); /** - * @since 3.0 - */ - public boolean isAutoReleaseLocksEnabled(); - - /** * Returns the temporary, transactional package manager associated with the commit operation represented by this * <code>CommitContext</code>. In addition to the packages registered with the session this package manager also * contains the new packages that are part of this commit operation. @@ -350,14 +345,6 @@ public interface IStoreAccessor extends IQueryHandlerProvider, BranchLoader, Com public InternalCDOPackageUnit[] getNewPackageUnits(); /** - * Returns an array of the locks on the new objects that are part of the commit operation represented by this - * <code>CommitContext</code>. - * - * @since 4.1 - */ - public CDOLockState[] getLocksOnNewObjects(); - - /** * Returns an array of the new objects that are part of the commit operation represented by this * <code>CommitContext</code>. */ @@ -420,6 +407,27 @@ public interface IStoreAccessor extends IQueryHandlerProvider, BranchLoader, Com public ExtendedDataInputStream getLobs(); /** + * + * @since 3.0 + * @deprecated As of 4.5 no longer supported. See {@link #getUnlocksOnChangedObjects()}. + */ + @Deprecated + public boolean isAutoReleaseLocksEnabled(); + + /** + * Returns an array of the locks on the new objects that are part of the commit operation represented by this + * <code>CommitContext</code>. + * + * @since 4.1 + */ + public CDOLockState[] getLocksOnNewObjects(); + + /** + * @since 4.5 + */ + public CDOID[] getUnlocksOnChangedObjects(); + + /** * Returns an unmodifiable map from all temporary IDs to their persistent counter parts. */ public Map<CDOID, CDOID> getIDMappings(); diff --git a/plugins/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/spi/server/InternalCommitContext.java b/plugins/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/spi/server/InternalCommitContext.java index 786f3af1e3..5daa013f62 100644 --- a/plugins/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/spi/server/InternalCommitContext.java +++ b/plugins/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/spi/server/InternalCommitContext.java @@ -118,11 +118,6 @@ public interface InternalCommitContext extends IStoreAccessor.CommitContext, CDO public void setNewPackageUnits(InternalCDOPackageUnit[] newPackageUnits); - /** - * @since 4.1 - */ - public void setLocksOnNewObjects(CDOLockState[] locksOnNewObjects); - public void setNewObjects(InternalCDORevision[] newObjects); public void setDirtyObjectDeltas(InternalCDORevisionDelta[] dirtyObjectDeltas); @@ -144,9 +139,23 @@ public interface InternalCommitContext extends IStoreAccessor.CommitContext, CDO */ public void setLastUpdateTime(long lastUpdateTime); + /** + * @deprecated As of 4.5 no longer supported. See {@link #setUnlocksOnChangedObjects(CDOID[])}. + */ + @Deprecated public void setAutoReleaseLocksEnabled(boolean on); /** + * @since 4.1 + */ + public void setLocksOnNewObjects(CDOLockState[] locksOnNewObjects); + + /** + * @since 4.5 + */ + public void setUnlocksOnChangedObjects(CDOID[] unlocksOnChangedObjects); + + /** * @since 4.5 */ public void setCommitNumber(int commitNumber); diff --git a/plugins/org.eclipse.emf.cdo.tests/src/org/eclipse/emf/cdo/tests/SessionTest.java b/plugins/org.eclipse.emf.cdo.tests/src/org/eclipse/emf/cdo/tests/SessionTest.java index bdebdba5b6..6721079c85 100644 --- a/plugins/org.eclipse.emf.cdo.tests/src/org/eclipse/emf/cdo/tests/SessionTest.java +++ b/plugins/org.eclipse.emf.cdo.tests/src/org/eclipse/emf/cdo/tests/SessionTest.java @@ -63,6 +63,14 @@ public class SessionTest extends AbstractCDOTest private static final char[] PASSWORD2 = "invalid".toCharArray(); //$NON-NLS-1$ + @Override + public void setUp() throws Exception + { + super.setUp(); + enableConsole(); + + } + public void testIsSupportingAudits() throws Exception { CDOSession session = openSession(); diff --git a/plugins/org.eclipse.emf.cdo.tests/src/org/eclipse/emf/cdo/tests/bugzilla/Bugzilla_355045_Test.java b/plugins/org.eclipse.emf.cdo.tests/src/org/eclipse/emf/cdo/tests/bugzilla/Bugzilla_355045_Test.java new file mode 100644 index 0000000000..5dc2a66c74 --- /dev/null +++ b/plugins/org.eclipse.emf.cdo.tests/src/org/eclipse/emf/cdo/tests/bugzilla/Bugzilla_355045_Test.java @@ -0,0 +1,204 @@ +/* + * Copyright (c) 2004 - 2012 Eike Stepper (Berlin, Germany) and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Esteban Dugueperoux - initial API and implementation + */ +package org.eclipse.emf.cdo.tests.bugzilla; + +import org.eclipse.emf.cdo.CDOObject; +import org.eclipse.emf.cdo.CDOState; +import org.eclipse.emf.cdo.common.CDOCommonSession.Options.LockNotificationMode; +import org.eclipse.emf.cdo.common.lock.CDOLockState; +import org.eclipse.emf.cdo.eresource.CDOResource; +import org.eclipse.emf.cdo.session.CDOSession; +import org.eclipse.emf.cdo.tests.AbstractCDOTest; +import org.eclipse.emf.cdo.tests.model1.Category; +import org.eclipse.emf.cdo.tests.model1.Company; +import org.eclipse.emf.cdo.transaction.CDOTransaction; +import org.eclipse.emf.cdo.util.CDOUtil; + +import org.eclipse.net4j.util.concurrent.IRWLockManager.LockType; + +import org.junit.Assert; + +import java.util.Collections; + +/** + * @author Esteban Dugueperoux + */ +public class Bugzilla_355045_Test extends AbstractCDOTest +{ + private static final String RESOURCE_PATH = "/test1"; + + private CDOTransaction transaction; + + private Company company; + + private Category category1; + + @Override + public void setUp() throws Exception + { + super.setUp(); + CDOSession cdoSession = openSession(); + cdoSession.options().setLockNotificationMode(LockNotificationMode.ALWAYS); + transaction = cdoSession.openTransaction(); + // cdoTransaction.options().setAutoReleaseLocksEnabled(false); + CDOResource cdoResource = transaction.createResource(getResourcePath(RESOURCE_PATH)); + + company = getModel1Factory().createCompany(); + category1 = getModel1Factory().createCategory(); + company.getCategories().add(category1); + + cdoResource.getContents().add(company); + cdoResource.save(Collections.emptyMap()); + } + + public void testLockOnCommitOfSingleNewObject() throws Exception + { + Category category2 = getModel1Factory().createCategory(); + category2.setName("category2"); + category1.getCategories().add(category2); + + transaction.lockObjects(CDOUtil.getCDOObjects(category2), LockType.WRITE, DEFAULT_TIMEOUT); + assertLockStatus(category2, true, false); + + transaction.commit(); + assertEquals(CDOState.CLEAN, CDOUtil.getCDOObject(category2).cdoState()); + assertLockStatus(category2, true, false); + } + + public void testRecursiveLockOnCommitOfNewObjectsTree() throws Exception + { + Category category2 = getModel1Factory().createCategory(); + category2.setName("category2"); + Category category4 = getModel1Factory().createCategory(); + category4.setName("category4"); + Category category5 = getModel1Factory().createCategory(); + category5.setName("category5"); + Category category6 = getModel1Factory().createCategory(); + category6.setName("category6"); + Category category7 = getModel1Factory().createCategory(); + category7.setName("category7"); + + category2.getCategories().add(category4); + category2.getCategories().add(category5); + category4.getCategories().add(category6); + category5.getCategories().add(category7); + category1.getCategories().add(category2); + + Category category3 = getModel1Factory().createCategory(); + category3.setName("category3"); + Category category8 = getModel1Factory().createCategory(); + category8.setName("category8"); + Category category9 = getModel1Factory().createCategory(); + category9.setName("category9"); + Category category10 = getModel1Factory().createCategory(); + category10.setName("category10"); + Category category11 = getModel1Factory().createCategory(); + category11.setName("category11"); + + category3.getCategories().add(category8); + category3.getCategories().add(category9); + category8.getCategories().add(category10); + category9.getCategories().add(category11); + category1.getCategories().add(category3); + + transaction.lockObjects(CDOUtil.getCDOObjects(category2), LockType.WRITE, DEFAULT_TIMEOUT, true); + transaction.options().addAutoReleaseLocksExemptions(true, category2); + + assertLockStatus(category1, false, false); + assertLockStatus(category2, true, true); + assertLockStatus(category3, false, true); + + transaction.lockObjects(CDOUtil.getCDOObjects(category3), LockType.WRITE, DEFAULT_TIMEOUT, true); + transaction.options().addAutoReleaseLocksExemptions(true, category3); + + assertLockStatus(category1, false, false); + assertLockStatus(category2, true, true); + assertLockStatus(category3, true, true); + + transaction.unlockObjects(CDOUtil.getCDOObjects(category3), LockType.WRITE); + + assertLockStatus(category1, false, false); + assertLockStatus(category2, true, true); + assertLockStatus(category3, false, false); + assertLockStatus(category8, true, true); + assertLockStatus(category9, true, true); + + transaction.commit(); + + assertLockStatus(category1, false, false); + assertLockStatus(category2, true, true); + assertLockStatus(category3, false, false); + assertLockStatus(category8, true, true); + assertLockStatus(category9, true, true); + } + + public void testRecursiveLockOfObjectsTreeContainingASubTreeOfNewObjects() throws Exception + { + Category category2 = getModel1Factory().createCategory(); + category2.setName("category2"); + Category category4 = getModel1Factory().createCategory(); + category4.setName("category4"); + Category category5 = getModel1Factory().createCategory(); + category5.setName("category5"); + Category category6 = getModel1Factory().createCategory(); + category6.setName("category6"); + Category category7 = getModel1Factory().createCategory(); + category7.setName("category7"); + + category2.getCategories().add(category4); + category2.getCategories().add(category5); + category4.getCategories().add(category6); + category5.getCategories().add(category7); + category1.getCategories().add(category2); + + Category category3 = getModel1Factory().createCategory(); + category3.setName("category3"); + Category category8 = getModel1Factory().createCategory(); + category8.setName("category8"); + Category category9 = getModel1Factory().createCategory(); + category9.setName("category9"); + Category category10 = getModel1Factory().createCategory(); + category10.setName("category10"); + Category category11 = getModel1Factory().createCategory(); + category11.setName("category11"); + + category3.getCategories().add(category8); + category3.getCategories().add(category9); + category8.getCategories().add(category10); + category9.getCategories().add(category11); + category1.getCategories().add(category3); + + transaction.lockObjects(CDOUtil.getCDOObjects(category1), LockType.WRITE, DEFAULT_TIMEOUT, true); + transaction.options().addAutoReleaseLocksExemptions(false, category1); + assertLockStatus(category1, true, false); + + transaction.commit(); + assertLockStatus(category1, true, false); + } + + private void assertLockStatus(Category category, boolean lockedByMe, boolean recursive) + { + CDOObject categoryCDOObject = CDOUtil.getCDOObject(category); + CDOLockState cdoLockState = categoryCDOObject.cdoLockState(); + Assert.assertEquals( + "new object " + category.getName() + + (lockedByMe ? " should be locally locked" : " shouldn't be locally locked"), + lockedByMe, cdoLockState.isLocked(LockType.WRITE, transaction, false)); + + if (recursive) + { + for (Category subCategory : category.getCategories()) + { + assertLockStatus(subCategory, lockedByMe, recursive); + } + } + } +} diff --git a/plugins/org.eclipse.emf.cdo.tests/src/org/eclipse/emf/cdo/tests/bugzilla/Bugzilla_387563_Test.java b/plugins/org.eclipse.emf.cdo.tests/src/org/eclipse/emf/cdo/tests/bugzilla/Bugzilla_387563_Test.java new file mode 100644 index 0000000000..638c3292c6 --- /dev/null +++ b/plugins/org.eclipse.emf.cdo.tests/src/org/eclipse/emf/cdo/tests/bugzilla/Bugzilla_387563_Test.java @@ -0,0 +1,179 @@ +/* + * Copyright (c) 2004 - 2012 Eike Stepper (Berlin, Germany) and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Esteban Dugueperoux - initial API and implementation + */ +package org.eclipse.emf.cdo.tests.bugzilla; + +import org.eclipse.emf.cdo.CDOObject; +import org.eclipse.emf.cdo.common.CDOCommonSession.Options.LockNotificationMode; +import org.eclipse.emf.cdo.common.lock.CDOLockState; +import org.eclipse.emf.cdo.eresource.CDOResource; +import org.eclipse.emf.cdo.session.CDOSession; +import org.eclipse.emf.cdo.tests.AbstractCDOTest; +import org.eclipse.emf.cdo.tests.model1.Category; +import org.eclipse.emf.cdo.tests.model1.Company; +import org.eclipse.emf.cdo.transaction.CDOTransaction; +import org.eclipse.emf.cdo.util.CDOUtil; + +import org.eclipse.net4j.util.concurrent.IRWLockManager.LockType; + +/** + * @author Esteban Dugueperoux + */ +public class Bugzilla_387563_Test extends AbstractCDOTest +{ + private CDOTransaction transaction; + + private Company company; + + private Category category1; + + private Category category2; + + private Category category3; + + private Category category4; + + private Category category5; + + @Override + protected void doSetUp() throws Exception + { + super.doSetUp(); + + CDOSession session = openSession(); + session.options().setLockNotificationMode(LockNotificationMode.ALWAYS); + + transaction = session.openTransaction(); + // transaction.options().setAutoReleaseLocksEnabled(false); + + CDOResource resource = transaction.createResource(getResourcePath("test1")); + + category1 = getModel1Factory().createCategory(); + category1.setName("category1"); + + category2 = getModel1Factory().createCategory(); + category2.setName("category2"); + + category3 = getModel1Factory().createCategory(); + category3.setName("category3"); + + category4 = getModel1Factory().createCategory(); + category4.setName("category4"); + + category5 = getModel1Factory().createCategory(); + category5.setName("category5"); + + Category category6 = getModel1Factory().createCategory(); + category6.setName("category6"); + + Category category7 = getModel1Factory().createCategory(); + category7.setName("category7"); + + Category category8 = getModel1Factory().createCategory(); + category8.setName("category8"); + + Category category9 = getModel1Factory().createCategory(); + category9.setName("category9"); + + Category category10 = getModel1Factory().createCategory(); + category10.setName("category10"); + + Category category11 = getModel1Factory().createCategory(); + category11.setName("category11"); + + category1.getCategories().add(category2); + category1.getCategories().add(category3); + category2.getCategories().add(category4); + category2.getCategories().add(category5); + category3.getCategories().add(category8); + category3.getCategories().add(category9); + category4.getCategories().add(category6); + category5.getCategories().add(category7); + category8.getCategories().add(category10); + category9.getCategories().add(category11); + + company = getModel1Factory().createCompany(); + company.getCategories().add(category1); + + resource.getContents().add(company); + } + + public void testPartialLockOnCommit() throws Exception + { + // Mark all objects to be locked on commit + transaction.lockObjects(CDOUtil.getCDOObjects(category1), LockType.WRITE, DEFAULT_TIMEOUT, true); + transaction.options().addAutoReleaseLocksExemptions(true, category1); + assertLockStatus(category1, true, true); + + // Mark category2 to be unlocked on commit + transaction.options().removeAutoReleaseLocksExemptions(false, category2); + + assertLockStatus(category1, true, false); + + LOCAL LOCK NOT RELEASED! + assertLockStatus(category2, false, false); + + assertLockStatus(category4, true, true); + assertLockStatus(category5, true, true); + assertLockStatus(category3, true, true); + + // Mark category3 and its descendants to be unlocked on commit + transaction.options().removeAutoReleaseLocksExemptions(true, category3); + + assertLockStatus(category1, true, false); + assertLockStatus(category2, false, false); + assertLockStatus(category4, true, true); + assertLockStatus(category5, true, true); + assertLockStatus(category3, false, true); + + transaction.commit(); + + assertLockStatus(category1, true, false); + assertLockStatus(category2, false, false); + assertLockStatus(category4, true, true); + assertLockStatus(category5, true, true); + assertLockStatus(category3, false, true); + } + + public void testPartialUnlockOnCommit() throws Exception + { + // Mark category1 as locked and all contained new category as to be locked on commit + transaction.lockObjects(CDOUtil.getCDOObjects(category1), LockType.WRITE, DEFAULT_TIMEOUT, true); + transaction.options().addAutoReleaseLocksExemptions(true, category1); + assertLockStatus(category1, true, true); + + transaction.unlockObjects(CDOUtil.getCDOObjects(category3), LockType.WRITE, true); + assertLockStatus(category3, false, true); + + transaction.commit(); + + assertLockStatus(category1, true, false); + assertLockStatus(category2, true, true); + assertLockStatus(category3, false, true); + } + + private static void assertLockStatus(Category category, boolean expected, boolean recursive) + { + CDOObject cdoObject = CDOUtil.getCDOObject(category); + CDOLockState lockState = cdoObject.cdoLockState(); + + assertEquals( + "new object " + category.getName() + (expected ? " should be locally locked" : " shouldn't be locally locked"), + expected, lockState.isLocked(LockType.WRITE, cdoObject.cdoView(), false)); + + if (recursive) + { + for (Category subCategory : category.getCategories()) + { + assertLockStatus(subCategory, expected, recursive); + } + } + } +} diff --git a/plugins/org.eclipse.emf.cdo.tests/src/org/eclipse/emf/cdo/tests/bugzilla/Bugzilla_387563b_Test.java b/plugins/org.eclipse.emf.cdo.tests/src/org/eclipse/emf/cdo/tests/bugzilla/Bugzilla_387563b_Test.java new file mode 100644 index 0000000000..9efc07f4ec --- /dev/null +++ b/plugins/org.eclipse.emf.cdo.tests/src/org/eclipse/emf/cdo/tests/bugzilla/Bugzilla_387563b_Test.java @@ -0,0 +1,85 @@ +/* + * 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.CDOObject; +import org.eclipse.emf.cdo.common.lock.CDOLockState; +import org.eclipse.emf.cdo.eresource.CDOResource; +import org.eclipse.emf.cdo.session.CDOSession; +import org.eclipse.emf.cdo.tests.AbstractCDOTest; +import org.eclipse.emf.cdo.tests.model1.Company; +import org.eclipse.emf.cdo.transaction.CDOTransaction; +import org.eclipse.emf.cdo.util.CDOUtil; + +import org.eclipse.emf.internal.cdo.view.CDOViewImpl; + +import org.eclipse.net4j.util.ReflectUtil; + +import org.eclipse.emf.ecore.EObject; + +import java.lang.reflect.Method; + +/** + * @author Eike Stepper + */ +public class Bugzilla_387563b_Test extends AbstractCDOTest +{ + private static final Method GET_LOCK_STATE_METHOD = ReflectUtil.getMethod(CDOViewImpl.class, "getLockState", + CDOObject.class); + + public void testNoImplicitLockingOfNewObject() throws Exception + { + Company company = getModel1Factory().createCompany(); + + CDOSession session = openSession(); + CDOTransaction transaction = session.openTransaction(); + transaction.options().setAutoReleaseLocksEnabled(true); + + CDOResource resource = transaction.createResource(getResourcePath("test1")); + resource.getContents().add(company); + + CDOObject cdoObject = CDOUtil.getCDOObject(company); + CDOLockState lockState = cdoObject.cdoLockState(); + assertNull(lockState.getWriteLockOwner()); + + transaction.commit(); + assertNull(getLockState(cdoObject)); + } + + public void testExplicitLockingOfNewObject() throws Exception + { + Company company = getModel1Factory().createCompany(); + + CDOSession session = openSession(); + CDOTransaction transaction = session.openTransaction(); + transaction.options().setAutoReleaseLocksEnabled(true); + + CDOResource resource = transaction.createResource(getResourcePath("test1")); + resource.getContents().add(company); + + CDOObject cdoObject = CDOUtil.getCDOObject(company); + cdoObject.cdoWriteLock().lock(); + + CDOLockState lockState = cdoObject.cdoLockState(); + assertEquals(transaction, lockState.getWriteLockOwner()); + + transaction.commit(); + assertNull(getLockState(cdoObject)); + } + + private static CDOLockState getLockState(EObject object) + { + CDOObject cdoObject = CDOUtil.getCDOObject(object); + CDOViewImpl view = (CDOViewImpl)cdoObject.cdoView(); + + return (CDOLockState)ReflectUtil.invokeMethod(GET_LOCK_STATE_METHOD, view, cdoObject); + } +} diff --git a/plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/cdo/transaction/CDOCommitContext.java b/plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/cdo/transaction/CDOCommitContext.java index 4905d74085..4620ed9218 100644 --- a/plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/cdo/transaction/CDOCommitContext.java +++ b/plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/cdo/transaction/CDOCommitContext.java @@ -55,11 +55,6 @@ public interface CDOCommitContext public CDOTransaction getTransaction(); /** - * @since 4.1 - */ - public boolean isAutoReleaseLocks(); - - /** * @since 4.0 */ public boolean isPartialCommit(); @@ -80,11 +75,6 @@ public interface CDOCommitContext public List<CDOPackageUnit> getNewPackageUnits(); /** - * @since 4.1 - */ - public Collection<CDOLockState> getLocksOnNewObjects(); - - /** * Returns a map of the new {@link CDOObject objects} that are to be committed with this commit context. */ public Map<CDOID, CDOObject> getNewObjects(); @@ -108,4 +98,21 @@ public interface CDOCommitContext * @since 4.0 */ public Collection<CDOLob<?>> getLobs(); + + /** + * @since 4.1 + * @deprecated As of 4.5 no longer supported. See {@link #getUnlocksOnChangedObjects()}. + */ + @Deprecated + public boolean isAutoReleaseLocks(); + + /** + * @since 4.1 + */ + public Collection<CDOLockState> getLocksOnNewObjects(); + + /** + * @since 4.5 + */ + public Collection<CDOID> getUnlocksOnChangedObjects(); } diff --git a/plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/cdo/transaction/CDOTransaction.java b/plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/cdo/transaction/CDOTransaction.java index 95d4460e3a..a29c90e108 100644 --- a/plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/cdo/transaction/CDOTransaction.java +++ b/plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/cdo/transaction/CDOTransaction.java @@ -292,24 +292,84 @@ public interface CDOTransaction extends CDOView, CDOCommonTransaction, CDOUserTr public void setStaleReferenceCleaner(CDOStaleReferenceCleaner staleReferenceCleaner); /** - * Returns true if locks in this view will be removes when {@link CDOTransaction#commit()} or - * {@link CDOTransaction#rollback()} is called. + * Returns <code>true</code> if locks in this transaction will be released when {@link CDOTransaction#commit()} or + * {@link CDOTransaction#rollback()} are called, <code>false</code> otherwise. * <p> - * Default value is true. + * The default value is <code>true</code>. + * + * @see #getAutoReleaseLocksExemptions() */ public boolean isAutoReleaseLocksEnabled(); /** - * Specifies whether locks in this view will be removed when {@link CDOTransaction#commit()} or - * {@link CDOTransaction#rollback()} is called. + * Specifies whether locks in this transaction will be released when {@link CDOTransaction#commit()} or + * {@link CDOTransaction#rollback()} are called. * <p> - * If false all locks are kept. + * If set to <code>false</code> all locks will be kept when {@link CDOTransaction#commit()} or + * {@link CDOTransaction#rollback()} are called. * <p> - * Default value is true. + * The default value is <code>true</code>. + * + * @see #getAutoReleaseLocksExemptions() */ public void setAutoReleaseLocksEnabled(boolean on); /** + * Returns the set of {@link EObject objects} that are to be treated as exemptions to the {@link #isAutoReleaseLocksEnabled()} option. + * <p> + * That means: + * <p> + * <ul> + * <li> If {@link #isAutoReleaseLocksEnabled()} returns <code>true</code>, the locks on the objects in this set are <b>not</b> released + * when {@link CDOTransaction#commit()} or {@link CDOTransaction#rollback()} are called. + * <li> If {@link #isAutoReleaseLocksEnabled()} returns <code>false</code>, the locks on the objects in this set <b>are</b> released nevertheless + * when {@link CDOTransaction#commit()} or {@link CDOTransaction#rollback()} are called. + * </ul> + * <p> + * The returned set is unmodifiable. To modify the set use the {@link #clearAutoReleaseLocksExemptions() clearAutoReleaseLocksExemptions()}, + * {@link #addAutoReleaseLocksExemptions(boolean, EObject...) addAutoReleaseLocksExemption()}, + * and {@link #removeAutoReleaseLocksExemptions(boolean, EObject...) removeAutoReleaseLocksExemption()} methods. + * <p> + * <b>Implementation note</b>: This set stores weak references to the contained objects. + * + * @see #clearAutoReleaseLocksExemptions() + * @see #addAutoReleaseLocksExemptions(boolean, EObject...) + * @see #removeAutoReleaseLocksExemptions(boolean, EObject...) + * @since 4.5 + */ + public Set<? extends EObject> getAutoReleaseLocksExemptions(); + + /** + * Clears the set of {@link EObject objects} that are to be treated as exemptions to the {@link #isAutoReleaseLocksEnabled()} option. + * + * @see #getAutoReleaseLocksExemptions() + * @see #addAutoReleaseLocksExemptions(boolean, EObject...) + * @see #removeAutoReleaseLocksExemptions(boolean, EObject...) + * @since 4.5 + */ + public void clearAutoReleaseLocksExemptions(); + + /** + * Adds the given {@link EObject object} to the set of objects that are to be treated as exemptions to the {@link #isAutoReleaseLocksEnabled()} option. + * + * @see #getAutoReleaseLocksExemptions() + * @see #clearAutoReleaseLocksExemptions() + * @see #removeAutoReleaseLocksExemptions(boolean, EObject...) + * @since 4.5 + */ + public void addAutoReleaseLocksExemptions(boolean recursive, EObject... objects); + + /** + * Removes the given {@link EObject object} from the set of objects that are to be treated as exemptions to the {@link #isAutoReleaseLocksEnabled()} option. + * + * @see #getAutoReleaseLocksExemptions() + * @see #clearAutoReleaseLocksExemptions() + * @see #addAutoReleaseLocksExemptions(boolean, EObject...) + * @since 4.5 + */ + public void removeAutoReleaseLocksExemptions(boolean recursive, EObject... objects); + + /** * Returns the number of milliseconds to wait for the transaction update when {@link CDOTransaction#commit()} is called. * <p> * Default value is 10000. @@ -367,7 +427,8 @@ public interface CDOTransaction extends CDOView, CDOCommonTransaction, CDOUserTr /** * An {@link IOptionsEvent options event} fired from transaction {@link CDOTransaction#options() options} when the - * {@link Options#setAutoReleaseLocksEnabled(boolean) auto release locks} option has changed. + * {@link Options#setAutoReleaseLocksEnabled(boolean) auto release locks enabled} or + * {@link Options#getAutoReleaseLocksExemptions() auto release locks exemptions} options have changed. * * @author Eike Stepper * @since 3.0 @@ -376,6 +437,31 @@ public interface CDOTransaction extends CDOView, CDOCommonTransaction, CDOUserTr */ public interface AutoReleaseLocksEvent extends IOptionsEvent { + /** + * An {@link AutoReleaseLocksEvent auto release locks options event} fired from transaction {@link CDOTransaction#options() options} when the + * {@link Options#setAutoReleaseLocksEnabled(boolean) auto release locks enabled} option has changed. + * + * @author Eike Stepper + * @since 4.5 + * @noextend This interface is not intended to be extended by clients. + * @noimplement This interface is not intended to be implemented by clients. + */ + public interface AutoReleaseLocksEnabledEvent extends AutoReleaseLocksEvent + { + } + + /** + * An {@link AutoReleaseLocksEvent auto release locks options event} fired from transaction {@link CDOTransaction#options() options} when the + * {@link Options#getAutoReleaseLocksExemptions() auto release locks exemptions} option has changed. + * + * @author Eike Stepper + * @since 4.5 + * @noextend This interface is not intended to be extended by clients. + * @noimplement This interface is not intended to be implemented by clients. + */ + public interface AutoReleaseLocksExemptionsEvent extends AutoReleaseLocksEvent + { + } } /** diff --git a/plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/cdo/util/CDOUtil.java b/plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/cdo/util/CDOUtil.java index 41cd6b114b..6e7ce0a636 100644 --- a/plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/cdo/util/CDOUtil.java +++ b/plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/cdo/util/CDOUtil.java @@ -88,8 +88,10 @@ import org.eclipse.emf.spi.cdo.FSMUtil; import org.eclipse.emf.spi.cdo.InternalCDOObject; import org.eclipse.emf.spi.cdo.InternalCDOView; +import java.util.ArrayList; import java.util.Collection; import java.util.Iterator; +import java.util.List; import java.util.Map; import java.util.concurrent.locks.Lock; @@ -592,6 +594,20 @@ public final class CDOUtil } /** + * @since 4.5 + */ + public static List<? extends CDOObject> getCDOObjects(EObject... objects) + { + List<CDOObject> result = new ArrayList<CDOObject>(); + for (EObject object : objects) + { + result.add(getCDOObject(object)); + } + + return result; + } + + /** * @since 4.4 */ public static boolean isCDOObject(EObject object) 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 c80de5cabe..41d3c6c0dc 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 @@ -96,6 +96,8 @@ import org.eclipse.emf.cdo.transaction.CDOMerger; import org.eclipse.emf.cdo.transaction.CDOSavepoint; import org.eclipse.emf.cdo.transaction.CDOStaleReferenceCleaner; import org.eclipse.emf.cdo.transaction.CDOTransaction; +import org.eclipse.emf.cdo.transaction.CDOTransaction.Options.AutoReleaseLocksEvent.AutoReleaseLocksEnabledEvent; +import org.eclipse.emf.cdo.transaction.CDOTransaction.Options.AutoReleaseLocksEvent.AutoReleaseLocksExemptionsEvent; import org.eclipse.emf.cdo.transaction.CDOTransactionConflictEvent; import org.eclipse.emf.cdo.transaction.CDOTransactionFinishedEvent; import org.eclipse.emf.cdo.transaction.CDOTransactionHandler; @@ -146,6 +148,7 @@ import org.eclipse.net4j.util.transaction.TransactionException; import org.eclipse.emf.common.notify.NotificationChain; import org.eclipse.emf.common.util.EList; +import org.eclipse.emf.common.util.TreeIterator; import org.eclipse.emf.common.util.URI; import org.eclipse.emf.ecore.EObject; import org.eclipse.emf.ecore.EPackage; @@ -176,7 +179,6 @@ import java.io.InputStream; import java.io.OutputStream; import java.text.MessageFormat; import java.util.ArrayList; -import java.util.Arrays; import java.util.Collection; import java.util.Collections; import java.util.HashMap; @@ -187,6 +189,7 @@ import java.util.List; import java.util.Map; import java.util.Map.Entry; import java.util.Set; +import java.util.WeakHashMap; import java.util.concurrent.Callable; import java.util.concurrent.atomic.AtomicInteger; @@ -3640,8 +3643,6 @@ public class CDOTransactionImpl extends CDOViewImpl implements InternalCDOTransa private CDOCommitData commitData; - private Collection<CDOLockState> locksOnNewObjects; - private Map<CDOID, CDOObject> newObjects; private Map<CDOID, CDOObject> detachedObjects; @@ -3652,6 +3653,10 @@ public class CDOTransactionImpl extends CDOViewImpl implements InternalCDOTransa private Map<ByteArrayWrapper, CDOLob<?>> lobs = new HashMap<ByteArrayWrapper, CDOLob<?>>(); + private List<CDOLockState> locksOnNewObjects = new ArrayList<CDOLockState>(); + + private List<CDOID> unlocksOnChangedObjects = new ArrayList<CDOID>(); + public CDOCommitContextImpl(InternalCDOTransaction transaction) { this.transaction = transaction; @@ -3660,6 +3665,8 @@ public class CDOTransactionImpl extends CDOViewImpl implements InternalCDOTransa private void calculateCommitData() { + OptionsImpl options = (OptionsImpl)transaction.options(); + List<CDOPackageUnit> newPackageUnits = analyzeNewPackages(); newObjects = filterCommittables(transaction.getNewObjects()); @@ -3667,6 +3674,15 @@ public class CDOTransactionImpl extends CDOViewImpl implements InternalCDOTransa for (CDOObject newObject : newObjects.values()) { revisions.add(newObject.cdoRevision()); + + CDOLockState lockState = getLockState(newObject); + if (lockState != null) + { + if (!options.isEffectiveAutoReleaseLock(newObject)) + { + locksOnNewObjects.add(lockState); + } + } } revisionDeltas = filterCommittables(transaction.getRevisionDeltas()); @@ -3699,9 +3715,17 @@ public class CDOTransactionImpl extends CDOViewImpl implements InternalCDOTransa } dirtyObjects = filterCommittables(transaction.getDirtyObjects()); - - CDOLockState[] locksOnNewObjectsArray = getLockStates(newObjects.keySet(), false); - locksOnNewObjects = Arrays.asList(locksOnNewObjectsArray); + for (CDOObject dirtyObject : dirtyObjects.values()) + { + CDOLockState lockState = getLockState(dirtyObject); + if (lockState != null) + { + if (options.isEffectiveAutoReleaseLock(dirtyObject)) + { + unlocksOnChangedObjects.add(dirtyObject.cdoID()); + } + } + } commitData = CDOCommitInfoUtil.createCommitData(newPackageUnits, revisions, deltas, detached); } @@ -3757,11 +3781,6 @@ public class CDOTransactionImpl extends CDOViewImpl implements InternalCDOTransa return isPartialCommit; } - public boolean isAutoReleaseLocks() - { - return transaction.options().isAutoReleaseLocksEnabled(); - } - public String getCommitComment() { return transaction.getCommitComment(); @@ -3787,11 +3806,6 @@ public class CDOTransactionImpl extends CDOViewImpl implements InternalCDOTransa return commitData.getNewPackageUnits(); } - public Collection<CDOLockState> getLocksOnNewObjects() - { - return locksOnNewObjects; - } - public Map<CDOID, CDOObject> getDetachedObjects() { return detachedObjects; @@ -3807,6 +3821,22 @@ public class CDOTransactionImpl extends CDOViewImpl implements InternalCDOTransa return lobs.values(); } + @Deprecated + public boolean isAutoReleaseLocks() + { + return transaction.options().isAutoReleaseLocksEnabled(); + } + + public Collection<CDOLockState> getLocksOnNewObjects() + { + return locksOnNewObjects; + } + + public List<CDOID> getUnlocksOnChangedObjects() + { + return unlocksOnChangedObjects; + } + public void preCommit() { if (isDirty()) @@ -3991,6 +4021,8 @@ public class CDOTransactionImpl extends CDOViewImpl implements InternalCDOTransa fireEvent(new FinishedEvent(idMappings), listeners); } + unlock new objects, if needed! + CDOLockState[] newLockStates = result.getNewLockStates(); if (newLockStates != null) { @@ -4175,12 +4207,14 @@ public class CDOTransactionImpl extends CDOViewImpl implements InternalCDOTransa { private CDOUndoDetector undoDetector = DEFAULT_UNDO_DETECTOR; - private List<CDOConflictResolver> conflictResolvers = new ArrayList<CDOConflictResolver>(); + private final List<CDOConflictResolver> conflictResolvers = new ArrayList<CDOConflictResolver>(); private CDOStaleReferenceCleaner staleReferenceCleaner = CDOStaleReferenceCleaner.DEFAULT; private boolean autoReleaseLocksEnabled = true; + private final Map<EObject, Boolean> autoReleaseLocksExemptions = new WeakHashMap<EObject, Boolean>(); + private long commitInfoTimeout = DEFAULT_COMMIT_INFO_TIMEOUT; public OptionsImpl() @@ -4414,7 +4448,50 @@ public class CDOTransactionImpl extends CDOViewImpl implements InternalCDOTransa if (autoReleaseLocksEnabled != on) { autoReleaseLocksEnabled = on; - event = new AutoReleaseLocksEventImpl(); + event = new AutoReleaseLocksEnabledEventImpl(); + } + } + finally + { + unlockView(); + } + } + + fireEvent(event); + } + + public Set<? extends EObject> getAutoReleaseLocksExemptions() + { + synchronized (getViewMonitor()) + { + lockView(); + + try + { + return new HashSet<EObject>(autoReleaseLocksExemptions.keySet()); + } + finally + { + unlockView(); + } + } + } + + public void clearAutoReleaseLocksExemptions() + { + checkActive(); + + IEvent event = null; + synchronized (getViewMonitor()) + { + lockView(); + + try + { + if (!autoReleaseLocksExemptions.isEmpty()) + { + autoReleaseLocksExemptions.clear(); + event = new AutoReleaseLocksExemptionsEventImpl(); } } finally @@ -4426,6 +4503,97 @@ public class CDOTransactionImpl extends CDOViewImpl implements InternalCDOTransa fireEvent(event); } + public void addAutoReleaseLocksExemptions(boolean recursive, EObject... objects) + { + checkActive(); + + IEvent event = null; + synchronized (getViewMonitor()) + { + lockView(); + + try + { + for (EObject object : objects) + { + if (autoReleaseLocksExemptions.put(object, Boolean.TRUE) == null) + { + event = new AutoReleaseLocksExemptionsEventImpl(); + } + + if (recursive) + { + for (TreeIterator<EObject> it = object.eAllContents(); it.hasNext();) + { + EObject child = it.next(); + if (autoReleaseLocksExemptions.put(child, Boolean.TRUE) == null && event == null) + { + event = new AutoReleaseLocksExemptionsEventImpl(); + } + } + } + } + } + finally + { + unlockView(); + } + } + + fireEvent(event); + } + + public void removeAutoReleaseLocksExemptions(boolean recursive, EObject... objects) + { + checkActive(); + + IEvent event = null; + synchronized (getViewMonitor()) + { + lockView(); + + try + { + for (EObject object : objects) + { + if (autoReleaseLocksExemptions.remove(object) != null) + { + event = new AutoReleaseLocksExemptionsEventImpl(); + } + + if (recursive) + { + for (TreeIterator<EObject> it = object.eAllContents(); it.hasNext();) + { + EObject child = it.next(); + if (autoReleaseLocksExemptions.put(child, Boolean.TRUE) == null && event == null) + { + event = new AutoReleaseLocksExemptionsEventImpl(); + } + } + } + } + } + finally + { + unlockView(); + } + } + + fireEvent(event); + } + + public boolean isEffectiveAutoReleaseLock(CDOObject newObject) + { + boolean effectiveAutoReleaseLock = autoReleaseLocksEnabled; + if (autoReleaseLocksExemptions.containsKey(newObject)) + { + effectiveAutoReleaseLock = !effectiveAutoReleaseLock; + } + + return effectiveAutoReleaseLock; + } + public long getCommitInfoTimeout() { return commitInfoTimeout; @@ -4499,11 +4667,25 @@ public class CDOTransactionImpl extends CDOViewImpl implements InternalCDOTransa /** * @author Eike Stepper */ - private final class AutoReleaseLocksEventImpl extends OptionsEvent implements AutoReleaseLocksEvent + private final class AutoReleaseLocksEnabledEventImpl extends OptionsEvent implements AutoReleaseLocksEnabledEvent + { + private static final long serialVersionUID = 1L; + + public AutoReleaseLocksEnabledEventImpl() + { + super(OptionsImpl.this); + } + } + + /** + * @author Eike Stepper + */ + private final class AutoReleaseLocksExemptionsEventImpl extends OptionsEvent + implements AutoReleaseLocksExemptionsEvent { private static final long serialVersionUID = 1L; - public AutoReleaseLocksEventImpl() + public AutoReleaseLocksExemptionsEventImpl() { super(OptionsImpl.this); } diff --git a/plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/internal/cdo/transaction/CDOUndoDetectorImpl.java b/plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/internal/cdo/transaction/CDOUndoDetectorImpl.java index 681dbc538d..1a9aa4d135 100644 --- a/plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/internal/cdo/transaction/CDOUndoDetectorImpl.java +++ b/plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/internal/cdo/transaction/CDOUndoDetectorImpl.java @@ -94,7 +94,7 @@ public class CDOUndoDetectorImpl implements CDOUndoDetector } /** - * @deprecated As of CDO 4.5 {@link #detectUndo(CDOTransaction, CDORevision, CDORevision, CDOFeatureDelta)} is called. + * @deprecated As of 4.5 {@link #detectUndo(CDOTransaction, CDORevision, CDORevision, CDOFeatureDelta)} is called. */ @Deprecated protected boolean detectUndoContainer(InternalCDORevision cleanRevision, InternalCDORevision currentRevision) diff --git a/plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/internal/cdo/transaction/CDOXACommitContextImpl.java b/plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/internal/cdo/transaction/CDOXACommitContextImpl.java index e475279359..a7b3dfc306 100644 --- a/plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/internal/cdo/transaction/CDOXACommitContextImpl.java +++ b/plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/internal/cdo/transaction/CDOXACommitContextImpl.java @@ -119,11 +119,6 @@ public class CDOXACommitContextImpl implements InternalCDOXACommitContext return delegateCommitContext.getTransaction(); } - public boolean isAutoReleaseLocks() - { - return delegateCommitContext.isAutoReleaseLocks(); - } - public boolean isPartialCommit() { return delegateCommitContext.isPartialCommit(); @@ -159,11 +154,6 @@ public class CDOXACommitContextImpl implements InternalCDOXACommitContext return delegateCommitContext.getNewPackageUnits(); } - public Collection<CDOLockState> getLocksOnNewObjects() - { - return delegateCommitContext.getLocksOnNewObjects(); - } - public Map<CDOID, CDOObject> getDetachedObjects() { return delegateCommitContext.getDetachedObjects(); @@ -179,6 +169,22 @@ public class CDOXACommitContextImpl implements InternalCDOXACommitContext return delegateCommitContext.getLobs(); } + @Deprecated + public boolean isAutoReleaseLocks() + { + return delegateCommitContext.isAutoReleaseLocks(); + } + + public Collection<CDOLockState> getLocksOnNewObjects() + { + return delegateCommitContext.getLocksOnNewObjects(); + } + + public Collection<CDOID> getUnlocksOnChangedObjects() + { + return delegateCommitContext.getUnlocksOnChangedObjects(); + } + public Object call() throws Exception { state.handle(this, progressMonitor); 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 694efefc37..27081656b1 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 @@ -99,6 +99,7 @@ import org.eclipse.net4j.util.ref.ReferenceValueMap; import org.eclipse.emf.common.notify.Adapter; import org.eclipse.emf.common.notify.NotificationChain; +import org.eclipse.emf.common.util.TreeIterator; import org.eclipse.emf.ecore.EObject; import org.eclipse.emf.ecore.InternalEObject; import org.eclipse.emf.ecore.util.EcoreUtil; @@ -121,6 +122,7 @@ import java.util.Collections; import java.util.HashMap; import java.util.HashSet; import java.util.Iterator; +import java.util.LinkedHashSet; import java.util.LinkedList; import java.util.List; import java.util.Map; @@ -361,6 +363,16 @@ public class CDOViewImpl extends AbstractCDOView implements IExecutorServiceProv { CDOLockState lockState = createUpdatedLockStateForNewObject(object, lockType, true); locksOnNewObjects.add(lockState); + + if (recursive) + { + for (TreeIterator<EObject> it = object.eAllContents(); it.hasNext();) + { + CDOObject child = CDOUtil.getCDOObject(it.next()); + lockState = createUpdatedLockStateForNewObject(child, lockType, true); + locksOnNewObjects.add(lockState); + } + } } else { @@ -429,8 +441,12 @@ public class CDOViewImpl extends AbstractCDOView implements IExecutorServiceProv } } - CDOLockState[] locksOnNewObjectsArray = locksOnNewObjects.toArray(new CDOLockState[locksOnNewObjects.size()]); - updateLockStates(locksOnNewObjectsArray); + int locksOnNewObjectsCount = locksOnNewObjects.size(); + if (locksOnNewObjectsCount != 0) + { + CDOLockState[] locksOnNewObjectsArray = locksOnNewObjects.toArray(new CDOLockState[locksOnNewObjectsCount]); + updateLockStates(locksOnNewObjectsArray); + } if (result != null) { @@ -637,6 +653,16 @@ public class CDOViewImpl extends AbstractCDOView implements IExecutorServiceProv { CDOLockState lockState = createUpdatedLockStateForNewObject(object, lockType, false); locksOnNewObjects.add(lockState); + + if (recursive) + { + for (TreeIterator<EObject> it = object.eAllContents(); it.hasNext();) + { + CDOObject child = CDOUtil.getCDOObject(it.next()); + lockState = createUpdatedLockStateForNewObject(child, lockType, false); + locksOnNewObjects.add(lockState); + } + } } else { @@ -984,83 +1010,80 @@ public class CDOViewImpl extends AbstractCDOView implements IExecutorServiceProv try { - List<CDOID> missing = new LinkedList<CDOID>(); - List<CDOLockState> lockStates = new LinkedList<CDOLockState>(); - List<CDOLockState> locksOnNewObjects = new ArrayList<CDOLockState>(ids.size()); + Set<CDOID> missingIDs = new LinkedHashSet<CDOID>(); + List<CDOLockState> result = new LinkedList<CDOLockState>(); for (CDOID id : ids) { - CDOLockState lockState = null; InternalCDOObject object = getObject(id, false); if (object != null) { - lockState = this.lockStates.get(object); - } - - if (lockState != null) - { - lockStates.add(lockState); - } - else if (loadOnDemand && object != null && FSMUtil.isNew(object)) - { - Object lockedObject = getLockTarget(object); // CDOID or CDOIDAndBranch - CDOLockState defaultLockState = CDOLockUtil.createLockState(lockedObject); - locksOnNewObjects.add(defaultLockState); - lockStates.add(defaultLockState); - } - else - { - missing.add(id); + CDOLockState lockState = lockStates.get(object); + if (lockState != null) + { + result.add(lockState); + } + else if (loadOnDemand) + { + missingIDs.add(id); + } } } - if (loadOnDemand && (missing.size() > 0 || ids.isEmpty())) + if (loadOnDemand && (!missingIDs.isEmpty() || ids.isEmpty())) { CDOSessionProtocol sessionProtocol = session.getSessionProtocol(); - CDOLockState[] loadedLockStates = sessionProtocol.getLockStates(viewID, missing, CDOLockState.DEPTH_NONE); - List<CDOLockState> newLockStateForCache = new ArrayList<CDOLockState>( - loadedLockStates.length + missing.size()); + CDOLockState[] loadedLockStates = sessionProtocol.getLockStates(viewID, missingIDs, CDOLockState.DEPTH_NONE); + + List<CDOLockState> lockStatesToUpdate = options().isLockNotificationEnabled() + ? new ArrayList<CDOLockState>(loadedLockStates.length) : null; + for (CDOLockState loadedLockState : loadedLockStates) { - lockStates.add(loadedLockState); - newLockStateForCache.add(loadedLockState); + result.add(loadedLockState); - CDOID cdoID = CDOIDUtil.getCDOID(loadedLockState.getLockedObject()); - if (cdoID != null) + if (lockStatesToUpdate != null) { - missing.remove(cdoID); + lockStatesToUpdate.add(loadedLockState); + } + + CDOID id = CDOIDUtil.getCDOID(loadedLockState.getLockedObject()); + if (id != null) + { + missingIDs.remove(id); } } - for (CDOID missingLockStateForCDOID : missing) + for (CDOID missingLockStateForCDOID : missingIDs) { - Object target; + Object lockTarget; InternalCDOObject object = getObject(missingLockStateForCDOID, false); if (object != null) { - target = getLockTarget(object); // CDOID or CDOIDAndBranch + lockTarget = getLockTarget(object); // CDOID or CDOIDAndBranch } else { - target = missingLockStateForCDOID; + lockTarget = missingLockStateForCDOID; } - CDOLockState defaultLockState = CDOLockUtil.createLockState(target); - lockStates.add(defaultLockState); - newLockStateForCache.add(defaultLockState); + CDOLockState defaultLockState = CDOLockUtil.createLockState(lockTarget); + result.add(defaultLockState); + + if (lockStatesToUpdate != null) + { + lockStatesToUpdate.add(defaultLockState); + } } - if (options().isLockNotificationEnabled()) + if (lockStatesToUpdate != null && !lockStatesToUpdate.isEmpty()) { - updateLockStates(newLockStateForCache.toArray(new CDOLockState[newLockStateForCache.size()])); + updateLockStates(lockStatesToUpdate.toArray(new CDOLockState[lockStatesToUpdate.size()])); } } - CDOLockState[] locksOnNewObjectsArray = locksOnNewObjects.toArray(new CDOLockState[locksOnNewObjects.size()]); - updateLockStates(locksOnNewObjectsArray); - - return lockStates.toArray(new CDOLockState[lockStates.size()]); + return result.toArray(new CDOLockState[result.size()]); } finally { diff --git a/plugins/org.eclipse.net4j.util/src/org/eclipse/net4j/util/concurrent/RWOLockManager.java b/plugins/org.eclipse.net4j.util/src/org/eclipse/net4j/util/concurrent/RWOLockManager.java index 437445d636..23d9519481 100644 --- a/plugins/org.eclipse.net4j.util/src/org/eclipse/net4j/util/concurrent/RWOLockManager.java +++ b/plugins/org.eclipse.net4j.util/src/org/eclipse/net4j/util/concurrent/RWOLockManager.java @@ -482,8 +482,7 @@ public class RWOLockManager<OBJECT, CONTEXT> extends Lifecycle implements IRWOLo return lockedObject; } - public boolean hasLock(org.eclipse.net4j.util.concurrent.IRWLockManager.LockType type, CONTEXT view, - boolean byOthers) + public boolean hasLock(LockType type, CONTEXT view, boolean byOthers) { CheckUtil.checkArg(view, "view"); @@ -517,7 +516,7 @@ public class RWOLockManager<OBJECT, CONTEXT> extends Lifecycle implements IRWOLo return false; } - public boolean hasLock(org.eclipse.net4j.util.concurrent.IRWLockManager.LockType type) + public boolean hasLock(LockType type) { switch (type) { @@ -534,6 +533,49 @@ public class RWOLockManager<OBJECT, CONTEXT> extends Lifecycle implements IRWOLo return false; } + public Set<CONTEXT> getReadLockOwners() + { + return Collections.unmodifiableSet(readLockOwners); + } + + public CONTEXT getWriteLockOwner() + { + return writeLockOwner; + } + + public CONTEXT getWriteOptionOwner() + { + return writeOptionOwner; + } + + @Override + public int hashCode() + { + return lockedObject.hashCode(); + } + + @Override + public boolean equals(Object obj) + { + if (this == obj) + { + return true; + } + + if (obj == null) + { + return false; + } + + if (!(obj instanceof LockState)) + { + return false; + } + + LockState<?, ?> other = (LockState<?, ?>)obj; + return lockedObject.equals(other.lockedObject); + } + @Override public String toString() { @@ -808,20 +850,5 @@ public class RWOLockManager<OBJECT, CONTEXT> extends Lifecycle implements IRWOLo { writeOptionOwner = null; } - - public Set<CONTEXT> getReadLockOwners() - { - return Collections.unmodifiableSet(readLockOwners); - } - - public CONTEXT getWriteLockOwner() - { - return writeLockOwner; - } - - public CONTEXT getWriteOptionOwner() - { - return writeOptionOwner; - } } } |