Skip to main content
aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorEike Stepper2016-06-07 08:13:23 -0400
committerEike Stepper2016-06-07 08:13:23 -0400
commitaff2821728bdc3c510f45e81846243dbfc6dcb02 (patch)
tree57c1e087d86400373e1933f71012c758d6755c8e
parent192a73ba2a787f9361d49826b87c76af85b14ac6 (diff)
downloadcdo-bugs/387563.tar.gz
cdo-bugs/387563.tar.xz
cdo-bugs/387563.zip
[387563] Generalize the "lock of new objects on commit" feature to the "lock/unlock objects on commit" bugs/387563
https://bugs.eclipse.org/bugs/show_bug.cgi?id=387563
-rw-r--r--plugins/org.eclipse.emf.cdo.net4j/src/org/eclipse/emf/cdo/internal/net4j/protocol/CommitTransactionRequest.java59
-rw-r--r--plugins/org.eclipse.emf.cdo.net4j/src/org/eclipse/emf/cdo/internal/net4j/protocol/UnlockObjectsRequest.java3
-rw-r--r--plugins/org.eclipse.emf.cdo.server.hibernate/src/org/eclipse/emf/cdo/server/internal/hibernate/HibernateRawCommitContext.java11
-rw-r--r--plugins/org.eclipse.emf.cdo.server.net4j/src/org/eclipse/emf/cdo/server/internal/net4j/protocol/CommitTransactionIndication.java46
-rw-r--r--plugins/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/internal/server/DelegatingCommitContext.java16
-rw-r--r--plugins/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/internal/server/TransactionCommitContext.java109
-rw-r--r--plugins/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/internal/server/syncing/SynchronizableRepository.java20
-rw-r--r--plugins/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/server/IStoreAccessor.java34
-rw-r--r--plugins/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/spi/server/InternalCommitContext.java19
-rw-r--r--plugins/org.eclipse.emf.cdo.tests/src/org/eclipse/emf/cdo/tests/SessionTest.java8
-rw-r--r--plugins/org.eclipse.emf.cdo.tests/src/org/eclipse/emf/cdo/tests/bugzilla/Bugzilla_355045_Test.java204
-rw-r--r--plugins/org.eclipse.emf.cdo.tests/src/org/eclipse/emf/cdo/tests/bugzilla/Bugzilla_387563_Test.java179
-rw-r--r--plugins/org.eclipse.emf.cdo.tests/src/org/eclipse/emf/cdo/tests/bugzilla/Bugzilla_387563b_Test.java85
-rw-r--r--plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/cdo/transaction/CDOCommitContext.java27
-rw-r--r--plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/cdo/transaction/CDOTransaction.java102
-rw-r--r--plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/cdo/util/CDOUtil.java16
-rw-r--r--plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/internal/cdo/transaction/CDOTransactionImpl.java222
-rw-r--r--plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/internal/cdo/transaction/CDOUndoDetectorImpl.java2
-rw-r--r--plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/internal/cdo/transaction/CDOXACommitContextImpl.java26
-rw-r--r--plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/internal/cdo/view/CDOViewImpl.java113
-rw-r--r--plugins/org.eclipse.net4j.util/src/org/eclipse/net4j/util/concurrent/RWOLockManager.java63
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;
- }
}
}

Back to the top