Skip to main content
aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorEike Stepper2013-04-08 06:49:15 -0400
committerEike Stepper2013-04-08 06:49:15 -0400
commit5aece33dc40ccff8d08a52cc242d5ff261c4600c (patch)
tree5d4d8f53c67f85066bbb8595978090e065a3fc92
parent1d0c2afa773ccd0f241e6b2c9d288b3fd9e0f07b (diff)
downloadcdo-5aece33dc40ccff8d08a52cc242d5ff261c4600c.tar.gz
cdo-5aece33dc40ccff8d08a52cc242d5ff261c4600c.tar.xz
cdo-5aece33dc40ccff8d08a52cc242d5ff261c4600c.zip
[402142] LockState unsychronized after lock/unlock
https://bugs.eclipse.org/bugs/show_bug.cgi?id=402142
-rw-r--r--plugins/org.eclipse.emf.cdo.common/src/org/eclipse/emf/cdo/internal/common/lock/CDOLockStateImpl.java97
-rw-r--r--plugins/org.eclipse.emf.cdo.common/src/org/eclipse/emf/cdo/spi/common/lock/InternalCDOLockState.java10
-rw-r--r--plugins/org.eclipse.emf.cdo.tests/src/org/eclipse/emf/cdo/tests/LockingNotificationsTest.java18
-rw-r--r--plugins/org.eclipse.emf.cdo.tests/src/org/eclipse/emf/cdo/tests/bugzilla/Bugzilla_402142_Test.java170
-rw-r--r--plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/internal/cdo/transaction/CDOTransactionImpl.java45
-rw-r--r--plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/internal/cdo/view/CDOViewImpl.java56
6 files changed, 352 insertions, 44 deletions
diff --git a/plugins/org.eclipse.emf.cdo.common/src/org/eclipse/emf/cdo/internal/common/lock/CDOLockStateImpl.java b/plugins/org.eclipse.emf.cdo.common/src/org/eclipse/emf/cdo/internal/common/lock/CDOLockStateImpl.java
index 7f7d2eb83a..b0a6994c26 100644
--- a/plugins/org.eclipse.emf.cdo.common/src/org/eclipse/emf/cdo/internal/common/lock/CDOLockStateImpl.java
+++ b/plugins/org.eclipse.emf.cdo.common/src/org/eclipse/emf/cdo/internal/common/lock/CDOLockStateImpl.java
@@ -4,7 +4,7 @@
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
- *
+ *
* Contributors:
* Caspar De Groot - initial API and implementation
*/
@@ -12,6 +12,7 @@ package org.eclipse.emf.cdo.internal.common.lock;
import org.eclipse.emf.cdo.common.id.CDOID;
import org.eclipse.emf.cdo.common.lock.CDOLockOwner;
+import org.eclipse.emf.cdo.common.lock.CDOLockState;
import org.eclipse.emf.cdo.common.revision.CDOIDAndBranch;
import org.eclipse.emf.cdo.spi.common.lock.InternalCDOLockState;
@@ -27,9 +28,9 @@ import java.util.Set;
*/
public class CDOLockStateImpl implements InternalCDOLockState
{
- private final Object lockedObject;
+ private Object lockedObject;
- private final Set<CDOLockOwner> readLockOwners = new HashSet<CDOLockOwner>();
+ private Set<CDOLockOwner> readLockOwners = new HashSet<CDOLockOwner>();
private CDOLockOwner writeLockOwner;
@@ -45,6 +46,7 @@ public class CDOLockStateImpl implements InternalCDOLockState
public CDOLockStateImpl copy()
{
+ checkDisposed();
CDOLockStateImpl newLockState = new CDOLockStateImpl(lockedObject);
for (CDOLockOwner owner : readLockOwners)
{
@@ -56,8 +58,21 @@ public class CDOLockStateImpl implements InternalCDOLockState
return newLockState;
}
+ public void updateFrom(Object object, CDOLockState source)
+ {
+ lockedObject = object;
+ readLockOwners = source.getReadLockOwners();
+ writeLockOwner = source.getWriteLockOwner();
+ writeOptionOwner = source.getWriteOptionOwner();
+ }
+
public boolean isLocked(LockType lockType, CDOLockOwner lockOwner, boolean others)
{
+ if (lockedObject == null)
+ {
+ return false;
+ }
+
switch (lockType)
{
case READ:
@@ -111,16 +126,23 @@ public class CDOLockStateImpl implements InternalCDOLockState
public Set<CDOLockOwner> getReadLockOwners()
{
+ if (lockedObject == null)
+ {
+ return Collections.emptySet();
+ }
+
return Collections.unmodifiableSet(readLockOwners);
}
public void addReadLockOwner(CDOLockOwner lockOwner)
{
+ checkDisposed();
readLockOwners.add(lockOwner);
}
public boolean removeReadLockOwner(CDOLockOwner lockOwner)
{
+ checkDisposed();
return readLockOwners.remove(lockOwner);
}
@@ -131,6 +153,7 @@ public class CDOLockStateImpl implements InternalCDOLockState
public void setWriteLockOwner(CDOLockOwner lockOwner)
{
+ checkDisposed();
writeLockOwner = lockOwner;
}
@@ -141,6 +164,7 @@ public class CDOLockStateImpl implements InternalCDOLockState
public void setWriteOptionOwner(CDOLockOwner lockOwner)
{
+ checkDisposed();
writeOptionOwner = lockOwner;
}
@@ -150,12 +174,55 @@ public class CDOLockStateImpl implements InternalCDOLockState
}
@Override
+ public int hashCode()
+ {
+ final int prime = 31;
+ int result = 1;
+ result = prime * result + (lockedObject == null ? 0 : lockedObject.hashCode());
+ return result;
+ }
+
+ @Override
+ public boolean equals(Object obj)
+ {
+ if (this == obj)
+ {
+ return true;
+ }
+
+ if (obj == null)
+ {
+ return false;
+ }
+
+ if (!(obj instanceof CDOLockStateImpl))
+ {
+ return false;
+ }
+
+ CDOLockStateImpl other = (CDOLockStateImpl)obj;
+ if (lockedObject == null)
+ {
+ if (other.lockedObject != null)
+ {
+ return false;
+ }
+ }
+ else if (!lockedObject.equals(other.lockedObject))
+ {
+ return false;
+ }
+
+ return true;
+ }
+
+ @Override
public String toString()
{
- StringBuilder builder = new StringBuilder("CDOLockState\nlockedObject=");
+ StringBuilder builder = new StringBuilder("CDOLockState\n lockedObject=");
builder.append(lockedObject);
- builder.append("\nreadLockOwners=");
+ builder.append("\n readLockOwners=");
if (readLockOwners.size() > 0)
{
boolean first = true;
@@ -180,12 +247,28 @@ public class CDOLockStateImpl implements InternalCDOLockState
builder.append("NONE");
}
- builder.append("\nwriteLockOwner=");
+ builder.append("\n writeLockOwner=");
builder.append(writeLockOwner != null ? writeLockOwner : "NONE");
- builder.append("\nwriteOptionOwner=");
+ builder.append("\n writeOptionOwner=");
builder.append(writeOptionOwner != null ? writeOptionOwner : "NONE");
return builder.toString();
}
+
+ public void dispose()
+ {
+ lockedObject = null;
+ readLockOwners = null;
+ writeLockOwner = null;
+ writeOptionOwner = null;
+ }
+
+ private void checkDisposed()
+ {
+ if (lockedObject == null)
+ {
+ throw new IllegalStateException("Lock state is disposed");
+ }
+ }
}
diff --git a/plugins/org.eclipse.emf.cdo.common/src/org/eclipse/emf/cdo/spi/common/lock/InternalCDOLockState.java b/plugins/org.eclipse.emf.cdo.common/src/org/eclipse/emf/cdo/spi/common/lock/InternalCDOLockState.java
index 0058f5cb0d..ab72382b35 100644
--- a/plugins/org.eclipse.emf.cdo.common/src/org/eclipse/emf/cdo/spi/common/lock/InternalCDOLockState.java
+++ b/plugins/org.eclipse.emf.cdo.common/src/org/eclipse/emf/cdo/spi/common/lock/InternalCDOLockState.java
@@ -30,4 +30,14 @@ public interface InternalCDOLockState extends CDOLockState
public void setWriteLockOwner(CDOLockOwner lockOwner);
public void setWriteOptionOwner(CDOLockOwner lockOwner);
+
+ /**
+ * @since 4.2
+ */
+ public void updateFrom(Object object, CDOLockState source);
+
+ /**
+ * @since 4.2
+ */
+ public void dispose();
}
diff --git a/plugins/org.eclipse.emf.cdo.tests/src/org/eclipse/emf/cdo/tests/LockingNotificationsTest.java b/plugins/org.eclipse.emf.cdo.tests/src/org/eclipse/emf/cdo/tests/LockingNotificationsTest.java
index 0cc850c892..6b136da9aa 100644
--- a/plugins/org.eclipse.emf.cdo.tests/src/org/eclipse/emf/cdo/tests/LockingNotificationsTest.java
+++ b/plugins/org.eclipse.emf.cdo.tests/src/org/eclipse/emf/cdo/tests/LockingNotificationsTest.java
@@ -198,7 +198,7 @@ public class LockingNotificationsTest extends AbstractLockingTest
assertEquals(1, lockStates.length);
assertLockedObject(cdoCompany, lockStates[0].getLockedObject());
assertLockOwner(tx1, lockStates[0].getWriteLockOwner());
- assertSame(cdoCompanyInControlView.cdoLockState(), lockStates[0]);
+ assertEquals(cdoCompanyInControlView.cdoLockState(), lockStates[0]);
}
cdoCompany.cdoWriteLock().unlock();
@@ -215,7 +215,7 @@ public class LockingNotificationsTest extends AbstractLockingTest
assertEquals(1, lockStates.length);
assertLockedObject(cdoCompany, lockStates[0].getLockedObject());
assertNull(lockStates[0].getWriteLockOwner());
- assertSame(cdoCompanyInControlView.cdoLockState(), lockStates[0]);
+ assertEquals(cdoCompanyInControlView.cdoLockState(), lockStates[0]);
}
/* Test read lock */
@@ -235,7 +235,7 @@ public class LockingNotificationsTest extends AbstractLockingTest
assertEquals(1, lockStates[0].getReadLockOwners().size());
CDOLockOwner tx1Lo = CDOLockUtil.createLockOwner(tx1);
assertEquals(true, lockStates[0].getReadLockOwners().contains(tx1Lo));
- assertSame(cdoCompanyInControlView.cdoLockState(), lockStates[0]);
+ assertEquals(cdoCompanyInControlView.cdoLockState(), lockStates[0]);
}
cdoCompany.cdoReadLock().unlock();
@@ -251,7 +251,7 @@ public class LockingNotificationsTest extends AbstractLockingTest
CDOLockState[] lockStates = event.getLockStates();
assertEquals(1, lockStates.length);
assertEquals(0, lockStates[0].getReadLockOwners().size());
- assertSame(cdoCompanyInControlView.cdoLockState(), lockStates[0]);
+ assertEquals(cdoCompanyInControlView.cdoLockState(), lockStates[0]);
}
/* Test write option */
@@ -269,7 +269,7 @@ public class LockingNotificationsTest extends AbstractLockingTest
assertEquals(1, lockStates.length);
assertLockedObject(cdoCompany, lockStates[0].getLockedObject());
assertLockOwner(tx1, lockStates[0].getWriteOptionOwner());
- assertSame(cdoCompanyInControlView.cdoLockState(), lockStates[0]);
+ assertEquals(cdoCompanyInControlView.cdoLockState(), lockStates[0]);
}
cdoCompany.cdoWriteOption().unlock();
@@ -286,7 +286,7 @@ public class LockingNotificationsTest extends AbstractLockingTest
assertEquals(1, lockStates.length);
assertLockedObject(cdoCompany, lockStates[0].getLockedObject());
assertNull(lockStates[0].getWriteOptionOwner());
- assertSame(cdoCompanyInControlView.cdoLockState(), lockStates[0]);
+ assertEquals(cdoCompanyInControlView.cdoLockState(), lockStates[0]);
}
assertEquals(0, transactionListener.getEvents().size());
@@ -329,8 +329,8 @@ public class LockingNotificationsTest extends AbstractLockingTest
{
controlViewListener.waitFor(1);
e = (CDOViewLocksChangedEvent)controlViewListener.getEvents().get(0);
- assertSame(Operation.LOCK, e.getOperation());
- assertSame(LockType.WRITE, e.getLockType());
+ assertEquals(Operation.LOCK, e.getOperation());
+ assertEquals(LockType.WRITE, e.getLockType());
}
tx.commit();
@@ -339,7 +339,7 @@ public class LockingNotificationsTest extends AbstractLockingTest
{
controlViewListener.waitFor(2);
e = (CDOViewLocksChangedEvent)controlViewListener.getEvents().get(1);
- assertSame(Operation.UNLOCK, e.getOperation());
+ assertEquals(Operation.UNLOCK, e.getOperation());
assertNull(e.getLockType());
}
diff --git a/plugins/org.eclipse.emf.cdo.tests/src/org/eclipse/emf/cdo/tests/bugzilla/Bugzilla_402142_Test.java b/plugins/org.eclipse.emf.cdo.tests/src/org/eclipse/emf/cdo/tests/bugzilla/Bugzilla_402142_Test.java
new file mode 100644
index 0000000000..aa41715a22
--- /dev/null
+++ b/plugins/org.eclipse.emf.cdo.tests/src/org/eclipse/emf/cdo/tests/bugzilla/Bugzilla_402142_Test.java
@@ -0,0 +1,170 @@
+/*
+ * Copyright (c) 2004 - 2013 Eike Stepper (Berlin, Germany) and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Steve Monnier - initial API and implementation
+ */
+package org.eclipse.emf.cdo.tests.bugzilla;
+
+import org.eclipse.emf.cdo.CDOLock;
+import org.eclipse.emf.cdo.CDOObject;
+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.tests.model1.Customer;
+import org.eclipse.emf.cdo.transaction.CDOTransaction;
+import org.eclipse.emf.cdo.util.CDOUtil;
+
+import org.eclipse.net4j.util.concurrent.IRWLockManager.LockType;
+
+import org.eclipse.emf.common.util.URI;
+import org.eclipse.emf.ecore.resource.Resource;
+import org.eclipse.emf.ecore.resource.ResourceSet;
+import org.eclipse.emf.ecore.xmi.impl.XMLResourceFactoryImpl;
+
+import java.util.ArrayList;
+
+/**
+ * Bug 385268.
+ *
+ * @author Steve Monnier
+ */
+public class Bugzilla_402142_Test extends AbstractCDOTest
+{
+ /**
+ * Scenario #1
+ * <ol>
+ * <li>User A : Create a CDOResource and add a Company root and commit
+ * <li>User B : Lock the Company element
+ * <li>User A : Ask if Company element is lockedByOther -> OK, it's locked
+ * </ol>
+ */
+ public void testCheckLockByOther() throws Exception
+ {
+ CDOSession session = openSession();
+ CDOTransaction transaction = session.openTransaction();
+ transaction.options().setLockNotificationEnabled(true);
+
+ CDOResource resource = transaction.createResource(getResourcePath("/my/resource"));
+ Company company = getModel1Factory().createCompany();
+ resource.getContents().add(company);
+ transaction.commit();
+
+ final CDOLock writeLock = CDOUtil.getCDOObject(company).cdoWriteLock();
+ assertEquals(false, writeLock.isLockedByOthers());
+
+ lockCompanyRemotely();
+ new PollingTimeOuter()
+ {
+ @Override
+ protected boolean successful()
+ {
+ return writeLock.isLockedByOthers();
+ }
+ }.assertNoTimeOut();
+
+ transaction.commit();
+ }
+
+ /**
+ * Scenario #2
+ * <ol>
+ * <li>User A : Create a CDOResource and add a Company root and commit
+ * <li>User A : Lock and Unlock the Company element
+ * <li>User B : Lock the Company element
+ * <li>User A : Ask if Company element is lockedByOther -> OK, it's locked
+ * </ol>
+ */
+ public void testCheckLockByOtherAfterLockUnlock() throws Exception
+ {
+ CDOSession session = openSession();
+ CDOTransaction transaction = session.openTransaction();
+ transaction.options().setLockNotificationEnabled(true);
+
+ CDOResource resource = transaction.createResource(getResourcePath("/my/resource"));
+ Company company = getModel1Factory().createCompany();
+ resource.getContents().add(company);
+ transaction.commit();
+
+ final CDOLock writeLock = CDOUtil.getCDOObject(company).cdoWriteLock();
+ writeLock.lock(DEFAULT_TIMEOUT);
+ writeLock.unlock();
+ assertEquals(false, writeLock.isLockedByOthers());
+
+ lockCompanyRemotely();
+ new PollingTimeOuter()
+ {
+ @Override
+ protected boolean successful()
+ {
+ return writeLock.isLockedByOthers();
+ }
+ }.assertNoTimeOut();
+
+ transaction.commit();
+ }
+
+ /**
+ * Scenario #3
+ * <ol>
+ * <li>Create a local resource and a CDOResource
+ * <li>Add an element "company1" to CDOResource
+ * <li>Add an element "company2" to the local resource
+ * <li>Add a Customer to "comapny1" commit
+ * <li>Move the customer to the local resource
+ * <li>Lock "company1" and customer (to avoid conflict from a distant user)
+ * <li>Commit
+ * <li>Move back the customer to "company1"
+ * <li>Add lock to customer (lock on new object)
+ * <li>Commit -> The new object should not have the lockstate of the former one
+ * </ol>
+ */
+ public void testLockUnlockOnElementMovedBetweenResources() throws Exception
+ {
+ CDOSession session = openSession();
+ CDOTransaction transaction = session.openTransaction();
+ transaction.options().setLockNotificationEnabled(true);
+
+ CDOResource resource = transaction.createResource(getResourcePath("/my/resource"));
+ Company company = getModel1Factory().createCompany();
+ resource.getContents().add(company);
+ Customer customer = getModel1Factory().createCustomer();
+ company.getCustomers().add(customer);
+ transaction.commit();
+
+ ResourceSet resourceSet = transaction.getResourceSet();
+ resourceSet.getResourceFactoryRegistry().getExtensionToFactoryMap().put("model1", new XMLResourceFactoryImpl());
+ URI localURI = URI.createFileURI(createTempFile("resource", ".model1").getCanonicalPath());
+ Resource resource2 = resourceSet.createResource(localURI);
+ Company company2 = getModel1Factory().createCompany();
+ resource2.getContents().add(company2);
+ company2.getCustomers().add(customer); // Move the customer to the local resource (detach)
+
+ ArrayList<CDOObject> objectsToLock = new ArrayList<CDOObject>();
+ objectsToLock.add(CDOUtil.getCDOObject(company));
+ objectsToLock.add(CDOUtil.getCDOObject(customer));
+ transaction.lockObjects(objectsToLock, LockType.WRITE, DEFAULT_TIMEOUT);
+
+ transaction.commit();
+
+ company.getCustomers().add(customer); // Move the customer to the CDO resource (attach new)
+ objectsToLock.add(CDOUtil.getCDOObject(customer)); // New object
+ transaction.lockObjects(objectsToLock, LockType.WRITE, DEFAULT_TIMEOUT);
+
+ transaction.commit();
+ }
+
+ private void lockCompanyRemotely() throws Exception
+ {
+ CDOSession session = openSession();
+ CDOTransaction transaction = session.openTransaction();
+ CDOResource resource = transaction.getResource(getResourcePath("/my/resource"));
+ CDOLock writeLock = CDOUtil.getCDOObject(resource.getContents().get(0)).cdoWriteLock();
+ writeLock.lock(DEFAULT_TIMEOUT);
+ }
+}
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 5ac10bb9f9..f1d0b7f106 100644
--- a/plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/internal/cdo/transaction/CDOTransactionImpl.java
+++ b/plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/internal/cdo/transaction/CDOTransactionImpl.java
@@ -100,7 +100,6 @@ import org.eclipse.emf.cdo.util.CDOURIUtil;
import org.eclipse.emf.cdo.util.CDOUtil;
import org.eclipse.emf.cdo.util.CommitException;
import org.eclipse.emf.cdo.util.ObjectNotFoundException;
-import org.eclipse.emf.cdo.view.CDOView;
import org.eclipse.emf.internal.cdo.CDOObjectImpl;
import org.eclipse.emf.internal.cdo.bundle.OM;
@@ -1458,7 +1457,7 @@ public class CDOTransactionImpl extends CDOViewImpl implements InternalCDOTransa
CDOID id = object.cdoID();
if (object.cdoState() == CDOState.NEW)
{
- Map<CDOID, CDOObject> map = getLastSavepoint().getNewObjects();
+ Map<CDOID, CDOObject> map = lastSavepoint.getNewObjects();
// Determine if we added object
if (map.containsKey(id))
@@ -1467,7 +1466,7 @@ public class CDOTransactionImpl extends CDOViewImpl implements InternalCDOTransa
}
else
{
- getLastSavepoint().getDetachedObjects().put(id, object);
+ lastSavepoint.getDetachedObjects().put(id, object);
}
// deregister object
@@ -1475,13 +1474,13 @@ public class CDOTransactionImpl extends CDOViewImpl implements InternalCDOTransa
}
else
{
- getLastSavepoint().getDetachedObjects().put(id, object);
-
if (!cleanRevisions.containsKey(object))
{
cleanRevisions.put(object, object.cdoRevision());
}
+ lastSavepoint.getDetachedObjects().put(id, object);
+
// Object may have been reattached previously, in which case it must
// here be removed from the collection of reattached objects
lastSavepoint.getReattachedObjects().remove(id);
@@ -1862,6 +1861,14 @@ public class CDOTransactionImpl extends CDOViewImpl implements InternalCDOTransa
{
if (commitContext == null || !commitContext.isPartialCommit())
{
+ if (commitContext != null)
+ {
+ for (CDOObject object : commitContext.getDetachedObjects().values())
+ {
+ cleanUpLockState(object);
+ }
+ }
+
lastSavepoint = firstSavepoint;
firstSavepoint.clear();
firstSavepoint.setNextSavepoint(null);
@@ -1878,6 +1885,7 @@ public class CDOTransactionImpl extends CDOViewImpl implements InternalCDOTransa
for (CDOObject object : commitContext.getDetachedObjects().values())
{
cleanRevisions.remove(object);
+ cleanUpLockState(object);
}
for (CDOObject object : commitContext.getDirtyObjects().values())
@@ -1890,6 +1898,15 @@ public class CDOTransactionImpl extends CDOViewImpl implements InternalCDOTransa
committables = null;
}
+ private void cleanUpLockState(CDOObject object)
+ {
+ InternalCDOLockState lockState = (InternalCDOLockState)removeLockState(object);
+ if (lockState != null)
+ {
+ lockState.dispose();
+ }
+ }
+
private void collapseSavepoints(CDOCommitContext commitContext)
{
InternalCDOSavepoint newSavepoint = createSavepoint(null);
@@ -2557,24 +2574,6 @@ public class CDOTransactionImpl extends CDOViewImpl implements InternalCDOTransa
return locksOnNewObjects;
}
- private static Object getLockTarget(CDOObject object)
- {
- CDOView view = object.cdoView();
- if (view == null)
- {
- return null;
- }
-
- CDOID id = object.cdoID();
- boolean branching = view.getSession().getRepositoryInfo().isSupportingBranches();
- if (branching)
- {
- return CDOIDUtil.createIDAndBranch(id, view.getBranch());
- }
-
- return id;
- }
-
private final class ResolvingRevisionMap extends HashMap<InternalCDOObject, InternalCDORevision>
{
private static final long serialVersionUID = 1L;
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 dab8f49d48..c5e9b89447 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
@@ -276,6 +276,16 @@ public class CDOViewImpl extends AbstractCDOView
return result;
}
+ private Set<? extends CDOObject> getSet(Collection<? extends CDOObject> objects)
+ {
+ if (objects instanceof Set)
+ {
+ return (Set<? extends CDOObject>)objects;
+ }
+
+ return new HashSet<CDOObject>(objects);
+ }
+
/**
* @throws InterruptedException
* @since 2.0
@@ -292,9 +302,13 @@ public class CDOViewImpl extends AbstractCDOView
checkActive();
checkState(getTimeStamp() == CDOBranchPoint.UNSPECIFIED_DATE, "Locking not supported for historial views");
- List<CDORevisionKey> revisionKeys = new LinkedList<CDORevisionKey>();
- List<CDOLockState> locksOnNewObjects = new LinkedList<CDOLockState>();
- for (CDOObject object : objects)
+ Set<? extends CDOObject> uniqueObjects = getSet(objects);
+ int size = uniqueObjects.size();
+
+ List<CDORevisionKey> revisionKeys = new ArrayList<CDORevisionKey>(size);
+ List<CDOLockState> locksOnNewObjects = new ArrayList<CDOLockState>(size);
+
+ for (CDOObject object : uniqueObjects)
{
if (FSMUtil.isNew(object))
{
@@ -392,7 +406,16 @@ public class CDOViewImpl extends AbstractCDOView
InternalCDOObject object = getObject(id, false);
if (object != null)
{
- lockStates.put(object, lockState);
+ InternalCDOLockState existingLockState = (InternalCDOLockState)lockStates.get(object);
+ if (existingLockState != null)
+ {
+ Object lockTarget = getLockTarget(object);
+ existingLockState.updateFrom(lockTarget, lockState);
+ }
+ else
+ {
+ lockStates.put(object, lockState);
+ }
}
}
}
@@ -511,7 +534,7 @@ public class CDOViewImpl extends AbstractCDOView
{
objectIDs = new ArrayList<CDOID>();
- for (CDOObject object : objects)
+ for (CDOObject object : getSet(objects))
{
if (FSMUtil.isNew(object))
{
@@ -750,6 +773,11 @@ public class CDOViewImpl extends AbstractCDOView
return lockStates.toArray(new CDOLockState[lockStates.size()]);
}
+ protected CDOLockState removeLockState(CDOObject object)
+ {
+ return lockStates.remove(object);
+ }
+
protected CDOLockState getLockState(CDOObject object)
{
return lockStates.get(object);
@@ -1229,6 +1257,24 @@ public class CDOViewImpl extends AbstractCDOView
}
}
+ protected static Object getLockTarget(CDOObject object)
+ {
+ CDOView view = object.cdoView();
+ if (view == null)
+ {
+ return null;
+ }
+
+ CDOID id = object.cdoID();
+ boolean branching = view.getSession().getRepositoryInfo().isSupportingBranches();
+ if (branching)
+ {
+ return CDOIDUtil.createIDAndBranch(id, view.getBranch());
+ }
+
+ return id;
+ }
+
/**
* @author Simon McDuff
* @since 2.0

Back to the top