Skip to main content
summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--plugins/org.eclipse.emf.cdo.common/src/org/eclipse/emf/cdo/common/CDODataInput.java5
-rw-r--r--plugins/org.eclipse.emf.cdo.common/src/org/eclipse/emf/cdo/common/CDODataOutput.java5
-rw-r--r--plugins/org.eclipse.emf.cdo.common/src/org/eclipse/emf/cdo/common/CDOProtocolConstants.java23
-rw-r--r--plugins/org.eclipse.emf.cdo.common/src/org/eclipse/emf/cdo/internal/common/CDODataInputImpl.java6
-rw-r--r--plugins/org.eclipse.emf.cdo.common/src/org/eclipse/emf/cdo/internal/common/CDODataOutputImpl.java6
-rw-r--r--plugins/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/internal/server/LockManager.java93
-rw-r--r--plugins/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/internal/server/Repository.java35
-rw-r--r--plugins/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/internal/server/SessionManager.java12
-rw-r--r--plugins/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/internal/server/Transaction.java7
-rw-r--r--plugins/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/internal/server/TransactionCommitContextImpl.java58
-rw-r--r--plugins/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/internal/server/protocol/CDOServerProtocol.java9
-rw-r--r--plugins/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/internal/server/protocol/CommitTransactionIndication.java3
-rw-r--r--plugins/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/internal/server/protocol/LockObjectsIndication.java67
-rw-r--r--plugins/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/internal/server/protocol/ObjectLockedIndication.java51
-rw-r--r--plugins/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/internal/server/protocol/UnlockObjectsIndication.java65
-rw-r--r--plugins/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/server/ISessionManager.java5
-rw-r--r--plugins/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/server/ITransaction.java1
-rw-r--r--plugins/org.eclipse.emf.cdo.tests.hibernate/src/org/eclipse/emf/cdo/tests/hibernate/HbCDOAutomaticPackageRefTest.java26
-rw-r--r--plugins/org.eclipse.emf.cdo.tests.hibernate/src/org/eclipse/emf/cdo/tests/hibernate/HbCDOPackageRefTest.java8
-rw-r--r--plugins/org.eclipse.emf.cdo.tests/src/org/eclipse/emf/cdo/tests/AllTestsAllConfigs.java1
-rw-r--r--plugins/org.eclipse.emf.cdo.tests/src/org/eclipse/emf/cdo/tests/LockingManagerTest.java563
-rw-r--r--plugins/org.eclipse.emf.cdo.tests/src/org/eclipse/emf/cdo/tests/ResourceTest.java2
-rw-r--r--plugins/org.eclipse.emf.cdo.tests/src/org/eclipse/emf/cdo/tests/StateMachineTest.java6
-rw-r--r--plugins/org.eclipse.emf.cdo.tests/src/org/eclipse/emf/cdo/tests/TransactionTest.java5
-rw-r--r--plugins/org.eclipse.emf.cdo.tests/src/org/eclipse/emf/cdo/tests/bugzilla/Bugzilla_250757_Test.java9
-rw-r--r--plugins/org.eclipse.emf.cdo.ui/src/org/eclipse/emf/cdo/internal/ui/editor/CDOEditor.java2
-rw-r--r--plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/cdo/CDOLock.java33
-rw-r--r--plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/cdo/CDOObject.java14
-rw-r--r--plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/cdo/CDOTransaction.java22
-rw-r--r--plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/cdo/CDOView.java22
-rw-r--r--plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/internal/cdo/CDOObjectImpl.java124
-rw-r--r--plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/internal/cdo/CDOObjectWrapper.java17
-rw-r--r--plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/internal/cdo/CDOTransactionImpl.java39
-rw-r--r--plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/internal/cdo/CDOViewImpl.java89
-rw-r--r--plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/internal/cdo/NOOPLockImpl.java71
-rw-r--r--plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/internal/cdo/protocol/CommitTransactionRequest.java1
-rw-r--r--plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/internal/cdo/protocol/LockObjectsRequest.java83
-rw-r--r--plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/internal/cdo/protocol/ObjectLockedRequest.java66
-rw-r--r--plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/internal/cdo/protocol/UnlockObjectsRequest.java89
-rw-r--r--plugins/org.eclipse.net4j.http/src/org/eclipse/net4j/internal/http/HTTPConnectorFactory.java4
-rw-r--r--plugins/org.eclipse.net4j.jms.tests/src/org/eclipse/net4j/jms/tests/JMSSeparatedTest.java2
-rw-r--r--plugins/org.eclipse.net4j.jms.tests/src/org/eclipse/net4j/jms/tests/JMSTest.java2
-rw-r--r--plugins/org.eclipse.net4j.tests/src/org/eclipse/net4j/tests/ChannelTest.java6
-rw-r--r--plugins/org.eclipse.net4j.tests/src/org/eclipse/net4j/tests/Performance.java4
-rw-r--r--plugins/org.eclipse.net4j.tests/src/org/eclipse/net4j/tests/SignalTest.java2
-rw-r--r--plugins/org.eclipse.net4j.tests/src/org/eclipse/net4j/tests/TCPConnectorTest.java4
-rw-r--r--plugins/org.eclipse.net4j.tests/src/org/eclipse/net4j/tests/TransportTest.java19
-rw-r--r--plugins/org.eclipse.net4j.tests/src/org/eclipse/net4j/tests/bugzilla/Bugzilla241463_Test.java6
-rw-r--r--plugins/org.eclipse.net4j.tests/src/org/eclipse/net4j/util/tests/ExtendedIOTest.java8
-rw-r--r--plugins/org.eclipse.net4j.tests/src/org/eclipse/net4j/util/tests/ReferenceValueMapTest.java4
-rw-r--r--plugins/org.eclipse.net4j.tests/src/org/eclipse/net4j/util/tests/SynchronizingCorrelatorTest.java4
-rw-r--r--plugins/org.eclipse.net4j.tests/src/org/eclipse/net4j/util/tests/UTFTest.java2
-rw-r--r--plugins/org.eclipse.net4j.util/src/org/eclipse/net4j/util/concurrent/RWLockManager.java567
53 files changed, 2319 insertions, 58 deletions
diff --git a/plugins/org.eclipse.emf.cdo.common/src/org/eclipse/emf/cdo/common/CDODataInput.java b/plugins/org.eclipse.emf.cdo.common/src/org/eclipse/emf/cdo/common/CDODataInput.java
index 05e9789fbf..2c25147cb7 100644
--- a/plugins/org.eclipse.emf.cdo.common/src/org/eclipse/emf/cdo/common/CDODataInput.java
+++ b/plugins/org.eclipse.emf.cdo.common/src/org/eclipse/emf/cdo/common/CDODataInput.java
@@ -24,6 +24,7 @@ import org.eclipse.emf.cdo.common.revision.CDORevision;
import org.eclipse.emf.cdo.common.revision.delta.CDOFeatureDelta;
import org.eclipse.emf.cdo.common.revision.delta.CDORevisionDelta;
+import org.eclipse.net4j.util.concurrent.RWLockManager;
import org.eclipse.net4j.util.io.ExtendedDataInput;
import java.io.IOException;
@@ -79,4 +80,8 @@ public interface CDODataInput extends ExtendedDataInput
* Read either a CDORevision, a primitive value or a CDOClass.
*/
public Object readCDORevisionOrPrimitiveOrClass() throws IOException;
+
+ // /////////////////////////////////////////////////////////////////////////////////////////////////
+
+ public RWLockManager.LockType readCDOLockType() throws IOException;
}
diff --git a/plugins/org.eclipse.emf.cdo.common/src/org/eclipse/emf/cdo/common/CDODataOutput.java b/plugins/org.eclipse.emf.cdo.common/src/org/eclipse/emf/cdo/common/CDODataOutput.java
index df8e409b59..bf9754b973 100644
--- a/plugins/org.eclipse.emf.cdo.common/src/org/eclipse/emf/cdo/common/CDODataOutput.java
+++ b/plugins/org.eclipse.emf.cdo.common/src/org/eclipse/emf/cdo/common/CDODataOutput.java
@@ -25,6 +25,7 @@ import org.eclipse.emf.cdo.common.revision.CDORevision;
import org.eclipse.emf.cdo.common.revision.delta.CDOFeatureDelta;
import org.eclipse.emf.cdo.common.revision.delta.CDORevisionDelta;
+import org.eclipse.net4j.util.concurrent.RWLockManager;
import org.eclipse.net4j.util.io.ExtendedDataOutput;
import java.io.IOException;
@@ -80,4 +81,8 @@ public interface CDODataOutput extends ExtendedDataOutput
* Write either a CDORevision, a primitive value or a CDOClass.
*/
public void writeCDORevisionOrPrimitiveOrClass(Object value) throws IOException;
+
+ // /////////////////////////////////////////////////////////////////////////////////////////////////
+
+ public void writeCDOLockType(RWLockManager.LockType lockType) throws IOException;
}
diff --git a/plugins/org.eclipse.emf.cdo.common/src/org/eclipse/emf/cdo/common/CDOProtocolConstants.java b/plugins/org.eclipse.emf.cdo.common/src/org/eclipse/emf/cdo/common/CDOProtocolConstants.java
index a5dc508822..2f150171dc 100644
--- a/plugins/org.eclipse.emf.cdo.common/src/org/eclipse/emf/cdo/common/CDOProtocolConstants.java
+++ b/plugins/org.eclipse.emf.cdo.common/src/org/eclipse/emf/cdo/common/CDOProtocolConstants.java
@@ -106,6 +106,21 @@ public interface CDOProtocolConstants
*/
public static final short SIGNAL_REPOSITORY_TIME = 24;
+ /**
+ * @since 2.0
+ */
+ public static final short SIGNAL_LOCK_OBJECTS = 25;
+
+ /**
+ * @since 2.0
+ */
+ public static final short SIGNAL_UNLOCK_OBJECTS = 26;
+
+ /**
+ * @since 2.0
+ */
+ public static final short SIGNAL_OBJECT_LOCKED = 27;
+
// //////////////////////////////////////////////////////////////////////
// Session Management
@@ -141,4 +156,12 @@ public interface CDOProtocolConstants
* @since 2.0
*/
public static final String QUERY_LANGUAGE_RESOURCES_EXACT_MATCH = "exactMatch";
+
+ // //////////////////////////////////////////////////////////////////////
+ // Locking Objects
+
+ /**
+ * @since 2.0
+ */
+ public static final int RELEASE_ALL_LOCKS = -1;
}
diff --git a/plugins/org.eclipse.emf.cdo.common/src/org/eclipse/emf/cdo/internal/common/CDODataInputImpl.java b/plugins/org.eclipse.emf.cdo.common/src/org/eclipse/emf/cdo/internal/common/CDODataInputImpl.java
index 591c9934f4..7c638429d0 100644
--- a/plugins/org.eclipse.emf.cdo.common/src/org/eclipse/emf/cdo/internal/common/CDODataInputImpl.java
+++ b/plugins/org.eclipse.emf.cdo.common/src/org/eclipse/emf/cdo/internal/common/CDODataInputImpl.java
@@ -59,6 +59,7 @@ import org.eclipse.emf.cdo.spi.common.InternalCDOList;
import org.eclipse.emf.cdo.spi.common.InternalCDOPackage;
import org.eclipse.net4j.util.ImplementationError;
+import org.eclipse.net4j.util.concurrent.RWLockManager;
import org.eclipse.net4j.util.io.ExtendedDataInput;
import org.eclipse.net4j.util.io.ExtendedIOUtil.ClassResolver;
import org.eclipse.net4j.util.om.trace.ContextTracer;
@@ -407,6 +408,11 @@ public abstract class CDODataInputImpl implements CDODataInput
return readCDORevisionOrPrimitive();
}
+ public RWLockManager.LockType readCDOLockType() throws IOException
+ {
+ return readBoolean() ? RWLockManager.LockType.WRITE : RWLockManager.LockType.READ;
+ }
+
protected abstract CDOPackageManager getPackageManager();
protected abstract CDOPackageURICompressor getPackageURICompressor();
diff --git a/plugins/org.eclipse.emf.cdo.common/src/org/eclipse/emf/cdo/internal/common/CDODataOutputImpl.java b/plugins/org.eclipse.emf.cdo.common/src/org/eclipse/emf/cdo/internal/common/CDODataOutputImpl.java
index c63288ddde..a183be4dd6 100644
--- a/plugins/org.eclipse.emf.cdo.common/src/org/eclipse/emf/cdo/internal/common/CDODataOutputImpl.java
+++ b/plugins/org.eclipse.emf.cdo.common/src/org/eclipse/emf/cdo/internal/common/CDODataOutputImpl.java
@@ -38,6 +38,7 @@ import org.eclipse.emf.cdo.spi.common.InternalCDOClass;
import org.eclipse.emf.cdo.spi.common.InternalCDOFeature;
import org.eclipse.emf.cdo.spi.common.InternalCDOPackage;
+import org.eclipse.net4j.util.concurrent.RWLockManager;
import org.eclipse.net4j.util.io.ExtendedDataOutput;
import org.eclipse.net4j.util.om.trace.ContextTracer;
@@ -368,5 +369,10 @@ public abstract class CDODataOutputImpl implements CDODataOutput
}
}
+ public void writeCDOLockType(RWLockManager.LockType lockType) throws IOException
+ {
+ writeBoolean(lockType == RWLockManager.LockType.WRITE ? true : false);
+ }
+
protected abstract CDOPackageURICompressor getPackageURICompressor();
}
diff --git a/plugins/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/internal/server/LockManager.java b/plugins/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/internal/server/LockManager.java
new file mode 100644
index 0000000000..16048d5726
--- /dev/null
+++ b/plugins/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/internal/server/LockManager.java
@@ -0,0 +1,93 @@
+/***************************************************************************
+ * Copyright (c) 2004 - 2008 Eike Stepper, Germany.
+ * 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:
+ * Simon McDuff - initial API and implementation
+ **************************************************************************/
+package org.eclipse.emf.cdo.internal.server;
+
+import org.eclipse.emf.cdo.common.id.CDOID;
+import org.eclipse.emf.cdo.server.IRepository;
+import org.eclipse.emf.cdo.server.IRepositoryElement;
+import org.eclipse.emf.cdo.server.ISession;
+import org.eclipse.emf.cdo.server.ISessionManager;
+import org.eclipse.emf.cdo.server.IView;
+
+import org.eclipse.net4j.util.ReflectUtil.ExcludeFromDump;
+import org.eclipse.net4j.util.concurrent.RWLockManager;
+import org.eclipse.net4j.util.container.ContainerEventAdapter;
+import org.eclipse.net4j.util.container.IContainer;
+import org.eclipse.net4j.util.event.IListener;
+
+/**
+ * @author Simon McDuff
+ * @since 2.0
+ */
+public class LockManager extends RWLockManager<CDOID, IView> implements IRepositoryElement
+{
+ private IRepository repository;
+
+ @ExcludeFromDump
+ private transient IListener sessionListener = new ContainerEventAdapter<IView>()
+ {
+ @Override
+ protected void onRemoved(IContainer<IView> container, IView view)
+ {
+ unlock(view);
+ }
+ };
+
+ @ExcludeFromDump
+ private transient IListener sessionManagerListener = new ContainerEventAdapter<ISession>()
+ {
+ @Override
+ protected void onAdded(IContainer<ISession> container, ISession session)
+ {
+ session.addListener(sessionListener);
+ }
+
+ @Override
+ protected void onRemoved(IContainer<ISession> container, ISession session)
+ {
+ session.removeListener(sessionListener);
+ }
+ };
+
+ public LockManager()
+ {
+ }
+
+ public IRepository getRepository()
+ {
+ return repository;
+ }
+
+ public void setRepository(IRepository repository)
+ {
+ this.repository = repository;
+ }
+
+ @Override
+ protected void doActivate() throws Exception
+ {
+ super.doActivate();
+ getRepository().getSessionManager().addListener(sessionManagerListener);
+ }
+
+ @Override
+ protected void doDeactivate() throws Exception
+ {
+ ISessionManager sessionManager = getRepository().getSessionManager();
+ sessionManager.removeListener(sessionManagerListener);
+ for (ISession session : sessionManager.getSessions())
+ {
+ session.removeListener(sessionListener);
+ }
+
+ super.doDeactivate();
+ }
+}
diff --git a/plugins/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/internal/server/Repository.java b/plugins/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/internal/server/Repository.java
index d82bf41e4e..6b422a8d63 100644
--- a/plugins/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/internal/server/Repository.java
+++ b/plugins/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/internal/server/Repository.java
@@ -75,6 +75,8 @@ public class Repository extends Container<IRepositoryElement> implements IReposi
private CommitManager commitManager;
+ private LockManager lockManager;
+
private IQueryHandlerProvider queryHandlerProvider;
private List<ReadAccessHandler> readAccessHandlers = new ArrayList<ReadAccessHandler>();
@@ -255,6 +257,22 @@ public class Repository extends Container<IRepositoryElement> implements IReposi
/**
* @since 2.0
*/
+ public LockManager getLockManager()
+ {
+ return lockManager;
+ }
+
+ /**
+ * @since 2.0
+ */
+ public void setLockManager(LockManager lockManager)
+ {
+ this.lockManager = lockManager;
+ }
+
+ /**
+ * @since 2.0
+ */
public long createCommitTimeStamp()
{
long now = System.currentTimeMillis();
@@ -505,6 +523,7 @@ public class Repository extends Container<IRepositoryElement> implements IReposi
checkState(queryManager, "queryManager");
checkState(notificationManager, "notificationManager");
checkState(commitManager, "commitManager");
+ checkState(lockManager, "lockingManager");
packageManager.setRepository(this);
sessionManager.setRepository(this);
@@ -512,6 +531,7 @@ public class Repository extends Container<IRepositoryElement> implements IReposi
queryManager.setRepository(this);
notificationManager.setRepository(this);
commitManager.setRepository(this);
+ lockManager.setRepository(this);
checkState(store, "store");
supportingRevisionDeltas = store.getSupportedChangeFormats().contains(IStore.ChangeFormat.DELTA);
@@ -536,7 +556,7 @@ public class Repository extends Container<IRepositoryElement> implements IReposi
}
elements = new IRepositoryElement[] { packageManager, sessionManager, revisionManager, queryManager,
- notificationManager, commitManager, store };
+ notificationManager, commitManager, lockManager, store };
}
@Override
@@ -559,11 +579,14 @@ public class Repository extends Container<IRepositoryElement> implements IReposi
LifecycleUtil.activate(notificationManager);
LifecycleUtil.activate(commitManager);
LifecycleUtil.activate(queryHandlerProvider);
+ LifecycleUtil.activate(lockManager);
+
}
@Override
protected void doDeactivate() throws Exception
{
+ LifecycleUtil.deactivate(lockManager);
LifecycleUtil.deactivate(queryHandlerProvider);
LifecycleUtil.deactivate(commitManager);
LifecycleUtil.deactivate(notificationManager);
@@ -619,6 +642,11 @@ public class Repository extends Container<IRepositoryElement> implements IReposi
setCommitManager(createCommitManager());
}
+ if (getLockManager() == null)
+ {
+ setLockManager(createLockManager());
+ }
+
super.doBeforeActivate();
}
@@ -651,5 +679,10 @@ public class Repository extends Container<IRepositoryElement> implements IReposi
{
return new CommitManager();
}
+
+ protected LockManager createLockManager()
+ {
+ return new LockManager();
+ }
}
}
diff --git a/plugins/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/internal/server/SessionManager.java b/plugins/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/internal/server/SessionManager.java
index 4a1dd2d55c..7ca27c950d 100644
--- a/plugins/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/internal/server/SessionManager.java
+++ b/plugins/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/internal/server/SessionManager.java
@@ -74,6 +74,18 @@ public class SessionManager extends Container<ISession> implements ISessionManag
}
}
+ /**
+ * @since 2.0
+ */
+ public Session getSession(int sessionID)
+ {
+ checkActive();
+ synchronized (sessions)
+ {
+ return sessions.get(sessionID);
+ }
+ }
+
public ISession[] getElements()
{
return getSessions();
diff --git a/plugins/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/internal/server/Transaction.java b/plugins/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/internal/server/Transaction.java
index 1dc3bff8d9..ee14b178ce 100644
--- a/plugins/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/internal/server/Transaction.java
+++ b/plugins/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/internal/server/Transaction.java
@@ -31,6 +31,8 @@ import java.util.List;
*/
public class Transaction extends View implements ITransaction
{
+ private boolean autoReleaseLocksEnabled = true;
+
public Transaction(Session session, int viewID)
{
super(session, viewID);
@@ -117,5 +119,10 @@ public class Transaction extends View implements ITransaction
public void setDirtyObjectDeltas(CDORevisionDelta[] dirtyObjectDeltas);
public void setDetachedObjects(CDOID[] detachedObjects);
+
+ public boolean setAutoReleaseLocksEnabled(boolean on);
+
+ public boolean isAutoReleaseLocksEnabled();
}
+
}
diff --git a/plugins/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/internal/server/TransactionCommitContextImpl.java b/plugins/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/internal/server/TransactionCommitContextImpl.java
index 3181762b78..a2dc0c11da 100644
--- a/plugins/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/internal/server/TransactionCommitContextImpl.java
+++ b/plugins/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/internal/server/TransactionCommitContextImpl.java
@@ -33,6 +33,7 @@ import org.eclipse.emf.cdo.spi.common.InternalCDORevisionDelta;
import org.eclipse.net4j.util.ObjectUtil;
import org.eclipse.net4j.util.StringUtil;
+import org.eclipse.net4j.util.concurrent.RWLockManager;
import org.eclipse.net4j.util.event.IListener;
import org.eclipse.net4j.util.om.trace.ContextTracer;
@@ -66,6 +67,8 @@ public class TransactionCommitContextImpl implements IStoreAccessor.CommitContex
private CDOID[] detachedObjects;
+ private List<CDOID> lockedObjects = new ArrayList<CDOID>();
+
private List<InternalCDORevision> detachedRevisions = new ArrayList<InternalCDORevision>();;
private CDORevisionDelta[] dirtyObjectDeltas;
@@ -80,6 +83,8 @@ public class TransactionCommitContextImpl implements IStoreAccessor.CommitContex
private Transaction transaction;
+ private boolean autoReleaseLocksEnabled;
+
public TransactionCommitContextImpl(Transaction transaction)
{
this.transaction = transaction;
@@ -199,6 +204,23 @@ public class TransactionCommitContextImpl implements IStoreAccessor.CommitContex
this.detachedObjects = detachedObjects;
}
+ public boolean setAutoReleaseLocksEnabled(boolean on)
+ {
+ try
+ {
+ return autoReleaseLocksEnabled;
+ }
+ finally
+ {
+ autoReleaseLocksEnabled = on;
+ }
+ }
+
+ public boolean isAutoReleaseLocksEnabled()
+ {
+ return autoReleaseLocksEnabled;
+ }
+
public void commit()
{
try
@@ -232,6 +254,7 @@ public class TransactionCommitContextImpl implements IStoreAccessor.CommitContex
Repository repository = (Repository)transaction.getRepository();
computeDirtyObjects(!repository.isSupportingRevisionDeltas());
+ lockObjects();
repository.notifyWriteAccessHandlers(transaction, this);
detachObjects();
@@ -241,6 +264,10 @@ public class TransactionCommitContextImpl implements IStoreAccessor.CommitContex
{
handleException(ex);
}
+ catch (InterruptedException ex)
+ {
+ handleException(ex);
+ }
catch (Error ex)
{
handleException(ex);
@@ -331,6 +358,29 @@ public class TransactionCommitContextImpl implements IStoreAccessor.CommitContex
metaIDRanges.add(newRange);
}
+ private void lockObjects() throws InterruptedException
+ {
+ lockedObjects.clear();
+ for (int i = 0; i < dirtyObjectDeltas.length; i++)
+ {
+ lockedObjects.add(dirtyObjectDeltas[i].getID());
+ }
+
+ for (int i = 0; i < detachedObjects.length; i++)
+ {
+ lockedObjects.add(detachedObjects[i]);
+ }
+
+ LockManager lockManager = ((Repository)transaction.getRepository()).getLockManager();
+ lockManager.lock(RWLockManager.LockType.WRITE, transaction, lockedObjects, 1000);
+ }
+
+ private void unlockObjects()
+ {
+ LockManager lockManager = ((Repository)transaction.getRepository()).getLockManager();
+ lockManager.unlock(RWLockManager.LockType.WRITE, transaction, lockedObjects);
+ }
+
private void computeDirtyObjects(boolean failOnNull)
{
for (int i = 0; i < dirtyObjectDeltas.length; i++)
@@ -364,7 +414,6 @@ public class TransactionCommitContextImpl implements IStoreAccessor.CommitContex
private void applyIDMappings(CDORevision[] revisions)
{
-
for (CDORevision revision : revisions)
{
if (revision != null)
@@ -383,6 +432,7 @@ public class TransactionCommitContextImpl implements IStoreAccessor.CommitContex
protected void rollback()
{
+ unlockObjects();
if (accessor != null)
{
try
@@ -404,6 +454,12 @@ public class TransactionCommitContextImpl implements IStoreAccessor.CommitContex
addRevisions(newObjects);
addRevisions(dirtyObjects);
revisedDetachObjects();
+ unlockObjects();
+
+ if (isAutoReleaseLocksEnabled())
+ {
+ ((Repository)transaction.getRepository()).getLockManager().unlock(transaction);
+ }
}
catch (RuntimeException ex)
{
diff --git a/plugins/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/internal/server/protocol/CDOServerProtocol.java b/plugins/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/internal/server/protocol/CDOServerProtocol.java
index c608131120..7346e29f2e 100644
--- a/plugins/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/internal/server/protocol/CDOServerProtocol.java
+++ b/plugins/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/internal/server/protocol/CDOServerProtocol.java
@@ -115,6 +115,15 @@ public class CDOServerProtocol extends CDOProtocolImpl
case CDOProtocolConstants.SIGNAL_REPOSITORY_TIME:
return new RepositoryTimeIndication(this);
+ case CDOProtocolConstants.SIGNAL_LOCK_OBJECTS:
+ return new LockObjectsIndication(this);
+
+ case CDOProtocolConstants.SIGNAL_UNLOCK_OBJECTS:
+ return new UnlockObjectsIndication(this);
+
+ case CDOProtocolConstants.SIGNAL_OBJECT_LOCKED:
+ return new ObjectLockedIndication(this);
+
default:
return null;
}
diff --git a/plugins/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/internal/server/protocol/CommitTransactionIndication.java b/plugins/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/internal/server/protocol/CommitTransactionIndication.java
index 4d5ae47888..55046fd7c2 100644
--- a/plugins/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/internal/server/protocol/CommitTransactionIndication.java
+++ b/plugins/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/internal/server/protocol/CommitTransactionIndication.java
@@ -114,6 +114,9 @@ public class CommitTransactionIndication extends CDOServerIndication
indicationTransaction(in);
commitContext.preCommit();
+ boolean autoReleaseLocksEnabled = in.readBoolean();
+ commitContext.setAutoReleaseLocksEnabled(autoReleaseLocksEnabled);
+
TransactionPackageManager packageManager = commitContext.getPackageManager();
CDOPackage[] newPackages = new CDOPackage[in.readInt()];
CDORevision[] newObjects = new CDORevision[in.readInt()];
diff --git a/plugins/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/internal/server/protocol/LockObjectsIndication.java b/plugins/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/internal/server/protocol/LockObjectsIndication.java
new file mode 100644
index 0000000000..57824da787
--- /dev/null
+++ b/plugins/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/internal/server/protocol/LockObjectsIndication.java
@@ -0,0 +1,67 @@
+/***************************************************************************
+ * Copyright (c) 2004 - 2008 Eike Stepper, Germany.
+ * 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:
+ * Simon McDuff - initial API and implementation
+ **************************************************************************/
+package org.eclipse.emf.cdo.internal.server.protocol;
+
+import org.eclipse.emf.cdo.common.CDODataInput;
+import org.eclipse.emf.cdo.common.CDODataOutput;
+import org.eclipse.emf.cdo.common.CDOProtocolConstants;
+import org.eclipse.emf.cdo.common.id.CDOID;
+import org.eclipse.emf.cdo.server.IView;
+
+import org.eclipse.net4j.util.concurrent.RWLockManager;
+import org.eclipse.net4j.util.io.IORuntimeException;
+
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * @author Simon McDuff
+ */
+public class LockObjectsIndication extends CDOReadIndication
+{
+ public LockObjectsIndication(CDOServerProtocol protocol)
+ {
+ super(protocol, CDOProtocolConstants.SIGNAL_LOCK_OBJECTS);
+ }
+
+ @Override
+ protected void indicating(CDODataInput in) throws IOException
+ {
+ int viewID = in.readInt();
+ RWLockManager.LockType lockType = in.readCDOLockType();
+ long timeout = in.readLong();
+
+ int size = in.readInt();
+ List<CDOID> ids = new ArrayList<CDOID>(size);
+ for (int i = 0; i < size; i++)
+ {
+ CDOID id = in.readCDOID();
+ ids.add(id);
+ }
+
+ try
+ {
+ IView view = getSession().getView(viewID);
+ getRepository().getLockManager().lock(lockType, view, ids, timeout);
+ }
+ catch (InterruptedException ex)
+ {
+ throw new IORuntimeException(ex);
+ }
+ }
+
+ @Override
+ protected void responding(CDODataOutput out) throws IOException
+ {
+ out.writeBoolean(true);
+ }
+}
diff --git a/plugins/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/internal/server/protocol/ObjectLockedIndication.java b/plugins/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/internal/server/protocol/ObjectLockedIndication.java
new file mode 100644
index 0000000000..c85ce288f0
--- /dev/null
+++ b/plugins/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/internal/server/protocol/ObjectLockedIndication.java
@@ -0,0 +1,51 @@
+/***************************************************************************
+ * Copyright (c) 2004 - 2008 Eike Stepper, Germany.
+ * 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:
+ * Simon McDuff - initial API and implementation
+ **************************************************************************/
+package org.eclipse.emf.cdo.internal.server.protocol;
+
+import org.eclipse.emf.cdo.common.CDODataInput;
+import org.eclipse.emf.cdo.common.CDODataOutput;
+import org.eclipse.emf.cdo.common.CDOProtocolConstants;
+import org.eclipse.emf.cdo.common.id.CDOID;
+import org.eclipse.emf.cdo.server.IView;
+
+import org.eclipse.net4j.util.concurrent.RWLockManager;
+
+import java.io.IOException;
+
+/**
+ * @author Simon McDuff
+ */
+public class ObjectLockedIndication extends CDOReadIndication
+{
+ private boolean isLocked;
+
+ public ObjectLockedIndication(CDOServerProtocol protocol)
+ {
+ super(protocol, CDOProtocolConstants.SIGNAL_OBJECT_LOCKED);
+ }
+
+ @Override
+ protected void indicating(CDODataInput in) throws IOException
+ {
+ int viewID = in.readInt();
+ IView view = getSession().getView(viewID);
+
+ RWLockManager.LockType lockType = in.readCDOLockType();
+ CDOID id = in.readCDOID();
+ isLocked = getRepository().getLockManager().hasLock(lockType, view, id);
+ }
+
+ @Override
+ protected void responding(CDODataOutput out) throws IOException
+ {
+ out.writeBoolean(isLocked);
+ }
+}
diff --git a/plugins/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/internal/server/protocol/UnlockObjectsIndication.java b/plugins/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/internal/server/protocol/UnlockObjectsIndication.java
new file mode 100644
index 0000000000..418478c8f5
--- /dev/null
+++ b/plugins/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/internal/server/protocol/UnlockObjectsIndication.java
@@ -0,0 +1,65 @@
+/***************************************************************************
+ * Copyright (c) 2004 - 2008 Eike Stepper, Germany.
+ * 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:
+ * Simon McDuff - initial API and implementation
+ **************************************************************************/
+package org.eclipse.emf.cdo.internal.server.protocol;
+
+import org.eclipse.emf.cdo.common.CDODataInput;
+import org.eclipse.emf.cdo.common.CDODataOutput;
+import org.eclipse.emf.cdo.common.CDOProtocolConstants;
+import org.eclipse.emf.cdo.common.id.CDOID;
+import org.eclipse.emf.cdo.server.IView;
+
+import org.eclipse.net4j.util.concurrent.RWLockManager;
+
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * @author Simon McDuff
+ */
+public class UnlockObjectsIndication extends CDOReadIndication
+{
+ public UnlockObjectsIndication(CDOServerProtocol protocol)
+ {
+ super(protocol, CDOProtocolConstants.SIGNAL_UNLOCK_OBJECTS);
+ }
+
+ @Override
+ protected void indicating(CDODataInput in) throws IOException
+ {
+ int viewID = in.readInt();
+ RWLockManager.LockType lockType = in.readCDOLockType();
+ int size = in.readInt();
+
+ IView view = getSession().getView(viewID);
+ if (size == CDOProtocolConstants.RELEASE_ALL_LOCKS)
+ {
+ getRepository().getLockManager().unlock(view);
+ }
+ else
+ {
+ List<CDOID> ids = new ArrayList<CDOID>(size);
+ for (int i = 0; i < size; i++)
+ {
+ CDOID id = in.readCDOID();
+ ids.add(id);
+ }
+
+ getRepository().getLockManager().unlock(lockType, view, ids);
+ }
+ }
+
+ @Override
+ protected void responding(CDODataOutput out) throws IOException
+ {
+ out.writeBoolean(true);
+ }
+}
diff --git a/plugins/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/server/ISessionManager.java b/plugins/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/server/ISessionManager.java
index aa43b70ed1..24f513a4c7 100644
--- a/plugins/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/server/ISessionManager.java
+++ b/plugins/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/server/ISessionManager.java
@@ -23,6 +23,11 @@ public interface ISessionManager extends IRepositoryElement, IContainer<ISession
public ISession[] getSessions();
/**
+ * @since 2.0
+ */
+ public ISession getSession(int sessionID);
+
+ /**
* @return Never <code>null</code>
* @since 2.0
*/
diff --git a/plugins/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/server/ITransaction.java b/plugins/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/server/ITransaction.java
index 28cf794d7e..d5fdb3e453 100644
--- a/plugins/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/server/ITransaction.java
+++ b/plugins/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/server/ITransaction.java
@@ -23,4 +23,5 @@ public interface ITransaction extends IView
* Returns the ID of this transactional view. Same as {@link CDOProtocolView#getViewID() getViewID()}.
*/
public int getTransactionID();
+
}
diff --git a/plugins/org.eclipse.emf.cdo.tests.hibernate/src/org/eclipse/emf/cdo/tests/hibernate/HbCDOAutomaticPackageRefTest.java b/plugins/org.eclipse.emf.cdo.tests.hibernate/src/org/eclipse/emf/cdo/tests/hibernate/HbCDOAutomaticPackageRefTest.java
index cc537c682d..5f2083b113 100644
--- a/plugins/org.eclipse.emf.cdo.tests.hibernate/src/org/eclipse/emf/cdo/tests/hibernate/HbCDOAutomaticPackageRefTest.java
+++ b/plugins/org.eclipse.emf.cdo.tests.hibernate/src/org/eclipse/emf/cdo/tests/hibernate/HbCDOAutomaticPackageRefTest.java
@@ -6,6 +6,8 @@ import org.eclipse.emf.cdo.eresource.CDOResource;
import org.eclipse.emf.cdo.tests.AbstractCDOTest;
import org.eclipse.emf.cdo.tests.StoreRepositoryProvider;
+import org.eclipse.net4j.util.io.IOUtil;
+
import base.BaseFactory;
import base.BasePackage;
import derived.DerivedPackage;
@@ -35,10 +37,10 @@ public class HbCDOAutomaticPackageRefTest extends AbstractCDOTest
session.getPackageRegistry().putEPackage(DerivedPackage.eINSTANCE);
transaction.commit();
}
- catch (Exception e)
+ catch (Exception ex)
{
- e.printStackTrace();
- throw e;
+ IOUtil.print(ex);
+ throw ex;
}
}
@@ -56,10 +58,10 @@ public class HbCDOAutomaticPackageRefTest extends AbstractCDOTest
session.getPackageRegistry().putEPackage(DerivedPackage.eINSTANCE);
transaction.commit();
}
- catch (Exception e)
+ catch (Exception ex)
{
- e.printStackTrace();
- throw e;
+ IOUtil.print(ex);
+ throw ex;
}
}
@@ -76,10 +78,10 @@ public class HbCDOAutomaticPackageRefTest extends AbstractCDOTest
resource.getContents().add(BaseFactory.eINSTANCE.createBaseClass());
transaction.commit();
}
- catch (Exception e)
+ catch (Exception ex)
{
- e.printStackTrace();
- throw e;
+ IOUtil.print(ex);
+ throw ex;
}
}
@@ -96,10 +98,10 @@ public class HbCDOAutomaticPackageRefTest extends AbstractCDOTest
resource.getContents().add(ReferenceFactory.eINSTANCE.createReference());
transaction.commit();
}
- catch (Exception e)
+ catch (Exception ex)
{
- e.printStackTrace();
- throw e;
+ IOUtil.print(ex);
+ throw ex;
}
}
}
diff --git a/plugins/org.eclipse.emf.cdo.tests.hibernate/src/org/eclipse/emf/cdo/tests/hibernate/HbCDOPackageRefTest.java b/plugins/org.eclipse.emf.cdo.tests.hibernate/src/org/eclipse/emf/cdo/tests/hibernate/HbCDOPackageRefTest.java
index bfe54a1709..cc152607d4 100644
--- a/plugins/org.eclipse.emf.cdo.tests.hibernate/src/org/eclipse/emf/cdo/tests/hibernate/HbCDOPackageRefTest.java
+++ b/plugins/org.eclipse.emf.cdo.tests.hibernate/src/org/eclipse/emf/cdo/tests/hibernate/HbCDOPackageRefTest.java
@@ -6,6 +6,8 @@ import org.eclipse.emf.cdo.eresource.CDOResource;
import org.eclipse.emf.cdo.tests.AbstractCDOTest;
import org.eclipse.emf.cdo.tests.StoreRepositoryProvider;
+import org.eclipse.net4j.util.io.IOUtil;
+
import reference.ReferenceFactory;
import reference.ReferencePackage;
import interface_.InterfacePackage;
@@ -32,10 +34,10 @@ public class HbCDOPackageRefTest extends AbstractCDOTest
resource.getContents().add(ReferenceFactory.eINSTANCE.createReference());
transaction.commit();
}
- catch (Exception e)
+ catch (Exception ex)
{
- e.printStackTrace();
- throw e;
+ IOUtil.print(ex);
+ throw ex;
}
}
}
diff --git a/plugins/org.eclipse.emf.cdo.tests/src/org/eclipse/emf/cdo/tests/AllTestsAllConfigs.java b/plugins/org.eclipse.emf.cdo.tests/src/org/eclipse/emf/cdo/tests/AllTestsAllConfigs.java
index 5d6589233d..d4f84abfdc 100644
--- a/plugins/org.eclipse.emf.cdo.tests/src/org/eclipse/emf/cdo/tests/AllTestsAllConfigs.java
+++ b/plugins/org.eclipse.emf.cdo.tests/src/org/eclipse/emf/cdo/tests/AllTestsAllConfigs.java
@@ -73,6 +73,7 @@ public abstract class AllTestsAllConfigs extends ConfigTestSuite
testClasses.add(XATransactionTest.class);
testClasses.add(TransactionHandlerTest.class);
testClasses.add(RepositoryTest.class);
+ testClasses.add(LockingManagerTest.class);
// Specific for MEMStore
testClasses.add(MEMStoreQueryTest.class);
diff --git a/plugins/org.eclipse.emf.cdo.tests/src/org/eclipse/emf/cdo/tests/LockingManagerTest.java b/plugins/org.eclipse.emf.cdo.tests/src/org/eclipse/emf/cdo/tests/LockingManagerTest.java
new file mode 100644
index 0000000000..4e3e761101
--- /dev/null
+++ b/plugins/org.eclipse.emf.cdo.tests/src/org/eclipse/emf/cdo/tests/LockingManagerTest.java
@@ -0,0 +1,563 @@
+/***************************************************************************
+ * Copyright (c) 2004 - 2008 Eike Stepper() throws Exception{} Germany.
+ * 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() throws Exception{} and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Simon McDuff - initial API and implementation
+ **************************************************************************/
+package org.eclipse.emf.cdo.tests;
+
+import org.eclipse.emf.cdo.CDOLock;
+import org.eclipse.emf.cdo.CDOObject;
+import org.eclipse.emf.cdo.CDOSession;
+import org.eclipse.emf.cdo.CDOTransaction;
+import org.eclipse.emf.cdo.eresource.CDOResource;
+import org.eclipse.emf.cdo.internal.server.Repository;
+import org.eclipse.emf.cdo.server.IView;
+import org.eclipse.emf.cdo.tests.model1.Company;
+import org.eclipse.emf.cdo.util.CDOUtil;
+
+import org.eclipse.net4j.util.concurrent.RWLockManager;
+import org.eclipse.net4j.util.concurrent.TimeoutRuntimeException;
+import org.eclipse.net4j.util.io.IOUtil;
+import org.eclipse.net4j.util.transaction.TransactionException;
+
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.Set;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
+import java.util.concurrent.TimeUnit;
+
+/**
+ * @author Simon McDuff
+ */
+public class LockingManagerTest extends AbstractCDOTest
+{
+ public void testBasicUpgradeFromReadToWriteLock() throws Exception
+ {
+ final RWLockManager<Integer, Integer> lockingManager = new RWLockManager<Integer, Integer>();
+
+ Runnable step1 = new Runnable()
+ {
+ public void run()
+ {
+ Set<Integer> keys = new HashSet<Integer>();
+ keys.add(1);
+ try
+ {
+ lockingManager.lock(RWLockManager.LockType.WRITE, 1, keys, 50000);
+ }
+ catch (InterruptedException ex)
+ {
+ fail("Should not have exception");
+ }
+ }
+ };
+
+ ExecutorService executors = Executors.newFixedThreadPool(10);
+ Set<Integer> keys = new HashSet<Integer>();
+ keys.add(1);
+ keys.add(2);
+ keys.add(3);
+ keys.add(4);
+
+ msg("Context 1 have readlock 1,2,3,4");
+ lockingManager.lock(RWLockManager.LockType.READ, 1, keys, 1000);
+ assertEquals(true, lockingManager.hasLock(RWLockManager.LockType.READ, 1, 1));
+ assertEquals(true, lockingManager.hasLock(RWLockManager.LockType.READ, 1, 2));
+ assertEquals(true, lockingManager.hasLock(RWLockManager.LockType.READ, 1, 3));
+ assertEquals(true, lockingManager.hasLock(RWLockManager.LockType.READ, 1, 4));
+
+ keys.clear();
+ keys.add(1);
+ keys.add(2);
+ keys.add(3);
+ msg("Context 2 have readlock 1,2,3");
+ lockingManager.lock(RWLockManager.LockType.READ, 2, keys, 1000);
+ assertEquals(true, lockingManager.hasLock(RWLockManager.LockType.READ, 2, 1));
+ assertEquals(true, lockingManager.hasLock(RWLockManager.LockType.READ, 2, 2));
+ assertEquals(true, lockingManager.hasLock(RWLockManager.LockType.READ, 2, 3));
+
+ keys.clear();
+ keys.add(4);
+ msg("Context 1 have readlock 1,2,3,4 and writeLock 4");
+ lockingManager.lock(RWLockManager.LockType.WRITE, 1, keys, 1000);
+ assertEquals(true, lockingManager.hasLock(RWLockManager.LockType.READ, 1, 4));
+ assertEquals(true, lockingManager.hasLock(RWLockManager.LockType.WRITE, 1, 4));
+
+ keys.clear();
+ keys.add(1);
+ try
+ {
+ lockingManager.lock(RWLockManager.LockType.WRITE, 1, keys, 1000);
+ fail("Should not have exception");
+ }
+ catch (RuntimeException expected)
+ {
+ }
+
+ executors.execute(step1);
+ executors.execute(step1);
+
+ Thread.sleep(1000);
+
+ keys.clear();
+ keys.add(1);
+ keys.add(2);
+ keys.add(3);
+ lockingManager.unlock(RWLockManager.LockType.READ, 2, keys);
+ ITimeOuter timeOuter = new PollingTimeOuter(200, 100)
+ {
+ @Override
+ protected boolean successful()
+ {
+ return lockingManager.hasLock(RWLockManager.LockType.WRITE, 1, 1);
+ }
+ };
+
+ assertEquals(false, timeOuter.timedOut());
+ }
+
+ public void testBasicWrongUnlock() throws Exception
+ {
+ final RWLockManager<Integer, Integer> lockingManager = new RWLockManager<Integer, Integer>();
+ Set<Integer> keys = new HashSet<Integer>();
+ keys.add(1);
+ lockingManager.lock(RWLockManager.LockType.READ, 1, keys, 10000);
+ lockingManager.unlock(RWLockManager.LockType.READ, 1, keys);
+ try
+ {
+ lockingManager.unlock(RWLockManager.LockType.READ, 1, keys);
+ fail("Should have an exception");
+ }
+ catch (IllegalMonitorStateException exception)
+ {
+ }
+ }
+
+ public void testReadTimeout() throws Exception
+ {
+ Company company = getModel1Factory().createCompany();
+
+ CDOSession session = openModel1Session();
+ CDOTransaction transaction = session.openTransaction();
+ CDOResource res = transaction.createResource("/res1");
+ res.getContents().add(company);
+ transaction.commit();
+
+ CDOObject cdoCompany = CDOUtil.getCDOObject(company);
+ cdoCompany.cdoWriteLock().lock();
+
+ CDOTransaction transaction2 = session.openTransaction();
+ CDOObject company2 = transaction2.getObject(cdoCompany.cdoID());
+
+ long start = System.currentTimeMillis();
+ assertEquals(false, company2.cdoWriteLock().tryLock());
+ assertEquals(true, System.currentTimeMillis() - start < 300);
+
+ start = System.currentTimeMillis();
+ assertEquals(false, company2.cdoWriteLock().tryLock(2, TimeUnit.SECONDS));
+ assertEquals(true, System.currentTimeMillis() - start > 2000);
+ }
+
+ public void testWriteLock() throws Exception
+ {
+ Company company = getModel1Factory().createCompany();
+
+ CDOSession session = openModel1Session();
+ CDOTransaction transaction = session.openTransaction();
+ CDOResource res = transaction.createResource("/res1");
+ res.getContents().add(company);
+ transaction.commit();
+
+ CDOTransaction transaction2 = session.openTransaction();
+ Company company2 = (Company)transaction2.getResource("/res1").getContents().get(0);
+
+ CDOObject cdoCompany = CDOUtil.getCDOObject(company);
+ CDOObject cdoCompany2 = CDOUtil.getCDOObject(company2);
+
+ transaction.lockObjects(Collections.singletonList(cdoCompany), RWLockManager.LockType.WRITE, CDOLock.WAIT);
+
+ try
+ {
+ transaction2.lockObjects(Collections.singletonList(cdoCompany2), RWLockManager.LockType.WRITE, 1000);
+ fail("Should have an exception");
+ }
+ catch (TimeoutRuntimeException ex)
+ {
+ }
+ company2.setCity("Ottawa");
+ try
+ {
+ transaction2.commit();
+ fail("Should have an exception");
+ }
+ catch (TransactionException exception)
+ {
+ }
+ }
+
+ public void testWriteLockFromDifferenceTransaction() throws Exception
+ {
+ Company company = getModel1Factory().createCompany();
+
+ CDOSession session = openModel1Session();
+ CDOTransaction transaction = session.openTransaction();
+ CDOResource res = transaction.createResource("/res1");
+ res.getContents().add(company);
+ transaction.commit();
+
+ CDOTransaction transaction2 = session.openTransaction();
+ Company company2 = (Company)transaction2.getResource("/res1").getContents().get(0);
+
+ CDOObject cdoCompany = CDOUtil.getCDOObject(company);
+ CDOObject cdoCompany2 = CDOUtil.getCDOObject(company2);
+
+ transaction.lockObjects(Collections.singletonList(cdoCompany), RWLockManager.LockType.WRITE, CDOLock.WAIT);
+
+ try
+ {
+ transaction2.lockObjects(Collections.singletonList(cdoCompany2), RWLockManager.LockType.WRITE, 1000);
+ fail("Should have an exception");
+ }
+ catch (TimeoutRuntimeException ex)
+ {
+ }
+ }
+
+ public void testReadLockAndCommitFromDifferenceTransaction() throws Exception
+ {
+ Company company = getModel1Factory().createCompany();
+
+ CDOSession session = openModel1Session();
+ CDOTransaction transaction = session.openTransaction();
+ CDOResource res = transaction.createResource("/res1");
+ res.getContents().add(company);
+ transaction.commit();
+
+ CDOTransaction transaction2 = session.openTransaction();
+ Company company2 = (Company)transaction2.getResource("/res1").getContents().get(0);
+ CDOObject cdoCompany = CDOUtil.getCDOObject(company);
+
+ transaction.lockObjects(Collections.singletonList(cdoCompany), RWLockManager.LockType.READ, CDOLock.WAIT);
+ company2.setCity("Ottawa");
+
+ try
+ {
+ transaction2.commit();
+ fail("Should have an exception");
+ }
+ catch (TransactionException exception)
+ {
+ }
+ }
+
+ public void testWriteLockAndCommitFromDifferenceTransaction() throws Exception
+ {
+ Company company = getModel1Factory().createCompany();
+
+ CDOSession session = openModel1Session();
+ CDOTransaction transaction = session.openTransaction();
+ CDOResource res = transaction.createResource("/res1");
+ res.getContents().add(company);
+ transaction.commit();
+
+ CDOTransaction transaction2 = session.openTransaction();
+ Company company2 = (Company)transaction2.getResource("/res1").getContents().get(0);
+ CDOObject cdoCompany = CDOUtil.getCDOObject(company);
+
+ transaction.lockObjects(Collections.singletonList(cdoCompany), RWLockManager.LockType.WRITE, CDOLock.WAIT);
+ company2.setCity("Ottawa");
+
+ try
+ {
+ transaction2.commit();
+ fail("Should have an exception");
+ }
+ catch (TransactionException expected)
+ {
+ IOUtil.print(expected);
+ }
+ }
+
+ public void testReadLockAndCommitSameTransaction() throws Exception
+ {
+ Company company = getModel1Factory().createCompany();
+
+ CDOSession session = openModel1Session();
+ CDOTransaction transaction = session.openTransaction();
+ CDOResource res = transaction.createResource("/res1");
+ res.getContents().add(company);
+ transaction.commit();
+
+ CDOObject cdoCompany = CDOUtil.getCDOObject(company);
+ cdoCompany.cdoReadLock().lock();
+
+ company.setCity("Ottawa");
+ transaction.commit();
+ }
+
+ public void testWriteLockAndCommitSameTransaction() throws Exception
+ {
+ Company company = getModel1Factory().createCompany();
+
+ CDOSession session = openModel1Session();
+ CDOTransaction transaction = session.openTransaction();
+ CDOResource res = transaction.createResource("/res1");
+ res.getContents().add(company);
+ transaction.commit();
+
+ CDOObject cdoCompany = CDOUtil.getCDOObject(company);
+ cdoCompany.cdoWriteLock().lock();
+
+ company.setCity("Ottawa");
+ assertEquals(true, cdoCompany.cdoWriteLock().isLocked());
+ assertEquals(false, cdoCompany.cdoReadLock().isLocked());
+
+ transaction.commit();
+
+ assertEquals(false, cdoCompany.cdoWriteLock().isLocked());
+ assertEquals(false, cdoCompany.cdoReadLock().isLocked());
+ }
+
+ public void testWriteLockAndRollback() throws Exception
+ {
+ Company company = getModel1Factory().createCompany();
+
+ CDOSession session = openModel1Session();
+ CDOTransaction transaction = session.openTransaction();
+ CDOResource res = transaction.createResource("/res1");
+ res.getContents().add(company);
+ transaction.commit();
+
+ CDOObject cdoCompany = CDOUtil.getCDOObject(company);
+ cdoCompany.cdoWriteLock().lock();
+ company.setCity("Ottawa");
+
+ transaction.rollback();
+ assertEquals(false, cdoCompany.cdoWriteLock().isLocked());
+ }
+
+ public void testLockUnlock() throws Exception
+ {
+ Company company = getModel1Factory().createCompany();
+
+ CDOSession session = openModel1Session();
+ CDOTransaction transaction = session.openTransaction();
+ CDOResource res = transaction.createResource("/res1");
+ res.getContents().add(company);
+ transaction.commit();
+ CDOObject cdoCompany = CDOUtil.getCDOObject(company);
+
+ cdoCompany.cdoReadLock().lock();
+ assertEquals(true, cdoCompany.cdoReadLock().isLocked());
+ assertEquals(false, cdoCompany.cdoWriteLock().isLocked());
+
+ cdoCompany.cdoWriteLock().lock();
+ assertEquals(true, cdoCompany.cdoReadLock().isLocked());
+ assertEquals(true, cdoCompany.cdoWriteLock().isLocked());
+
+ cdoCompany.cdoReadLock().lock();
+ assertEquals(true, cdoCompany.cdoReadLock().isLocked());
+ assertEquals(true, cdoCompany.cdoWriteLock().isLocked());
+
+ cdoCompany.cdoWriteLock().lock();
+ assertEquals(true, cdoCompany.cdoReadLock().isLocked());
+ assertEquals(true, cdoCompany.cdoWriteLock().isLocked());
+
+ cdoCompany.cdoReadLock().unlock();
+ assertEquals(true, cdoCompany.cdoReadLock().isLocked());
+ assertEquals(true, cdoCompany.cdoWriteLock().isLocked());
+
+ cdoCompany.cdoReadLock().unlock();
+ assertEquals(false, cdoCompany.cdoReadLock().isLocked());
+ assertEquals(true, cdoCompany.cdoWriteLock().isLocked());
+
+ cdoCompany.cdoWriteLock().unlock();
+ assertEquals(false, cdoCompany.cdoReadLock().isLocked());
+ assertEquals(true, cdoCompany.cdoWriteLock().isLocked());
+
+ cdoCompany.cdoWriteLock().unlock();
+ assertEquals(false, cdoCompany.cdoReadLock().isLocked());
+ assertEquals(false, cdoCompany.cdoWriteLock().isLocked());
+
+ /********************/
+
+ cdoCompany.cdoReadLock().lock();
+ assertEquals(true, cdoCompany.cdoReadLock().isLocked());
+ assertEquals(false, cdoCompany.cdoWriteLock().isLocked());
+
+ cdoCompany.cdoWriteLock().lock();
+ assertEquals(true, cdoCompany.cdoReadLock().isLocked());
+ assertEquals(true, cdoCompany.cdoWriteLock().isLocked());
+
+ cdoCompany.cdoReadLock().lock();
+ assertEquals(true, cdoCompany.cdoReadLock().isLocked());
+ assertEquals(true, cdoCompany.cdoWriteLock().isLocked());
+
+ cdoCompany.cdoWriteLock().lock();
+ assertEquals(true, cdoCompany.cdoReadLock().isLocked());
+ assertEquals(true, cdoCompany.cdoWriteLock().isLocked());
+
+ cdoCompany.cdoWriteLock().unlock();
+ assertEquals(true, cdoCompany.cdoReadLock().isLocked());
+ assertEquals(true, cdoCompany.cdoWriteLock().isLocked());
+
+ cdoCompany.cdoWriteLock().unlock();
+ assertEquals(true, cdoCompany.cdoReadLock().isLocked());
+ assertEquals(false, cdoCompany.cdoWriteLock().isLocked());
+
+ cdoCompany.cdoReadLock().unlock();
+ assertEquals(true, cdoCompany.cdoReadLock().isLocked());
+ assertEquals(false, cdoCompany.cdoWriteLock().isLocked());
+
+ cdoCompany.cdoReadLock().unlock();
+ assertEquals(false, cdoCompany.cdoReadLock().isLocked());
+ assertEquals(false, cdoCompany.cdoWriteLock().isLocked());
+ }
+
+ public void testTransactionClose() throws Exception
+ {
+ Company company = getModel1Factory().createCompany();
+
+ Repository repo = (Repository)getRepository();
+ CDOSession session = openModel1Session();
+
+ CDOTransaction transaction = session.openTransaction();
+ IView view = repo.getSessionManager().getSession(session.getSessionID()).getView(transaction.getViewID());
+ CDOResource res = transaction.createResource("/res1");
+ res.getContents().add(company);
+ transaction.commit();
+
+ CDOObject cdoCompany = CDOUtil.getCDOObject(company);
+ cdoCompany.cdoReadLock().lock();
+ transaction.close();
+ assertEquals(false, repo.getLockManager().hasLock(RWLockManager.LockType.READ, view, cdoCompany.cdoID()));
+ }
+
+ public void testSessionClose() throws Exception
+ {
+ Company company = getModel1Factory().createCompany();
+
+ Repository repo = (Repository)getRepository();
+ CDOSession session = openModel1Session();
+
+ CDOTransaction transaction = session.openTransaction();
+ IView view = repo.getSessionManager().getSession(session.getSessionID()).getView(transaction.getViewID());
+ CDOResource res = transaction.createResource("/res1");
+ res.getContents().add(company);
+ transaction.commit();
+
+ CDOObject cdoCompany = CDOUtil.getCDOObject(company);
+ cdoCompany.cdoReadLock().lock();
+ session.close();
+ assertEquals(false, repo.getLockManager().hasLock(RWLockManager.LockType.READ, view, cdoCompany.cdoID()));
+ }
+
+ public void testAutoReleaseLockFalse_commit() throws Exception
+ {
+ Company company = getModel1Factory().createCompany();
+
+ CDOSession session = openModel1Session();
+ CDOTransaction transaction = session.openTransaction();
+ CDOResource res = transaction.createResource("/res1");
+ res.getContents().add(company);
+ transaction.commit();
+ transaction.setAutoReleaseLocksEnabled(false);
+
+ CDOObject cdoCompany = CDOUtil.getCDOObject(company);
+ cdoCompany.cdoWriteLock().lock();
+ cdoCompany.cdoReadLock().lock();
+
+ msg("Test with read/write lock");
+ assertEquals(true, cdoCompany.cdoWriteLock().isLocked());
+ assertEquals(true, cdoCompany.cdoReadLock().isLocked());
+
+ company.setCity("Ottawa");
+ transaction.commit();
+ assertEquals(true, cdoCompany.cdoWriteLock().isLocked());
+ assertEquals(true, cdoCompany.cdoReadLock().isLocked());
+
+ msg("Clean locks");
+ transaction.unlockObjects(null, null);
+
+ msg("Test with read lock");
+ cdoCompany.cdoReadLock().lock();
+ assertEquals(true, cdoCompany.cdoReadLock().isLocked());
+
+ company.setCity("Toronto");
+ transaction.commit();
+ assertEquals(true, cdoCompany.cdoReadLock().isLocked());
+
+ transaction.setAutoReleaseLocksEnabled(true);
+ transaction.commit();
+ assertEquals(false, cdoCompany.cdoReadLock().isLocked());
+ }
+
+ public void testAutoReleaseLockFalse_rollback() throws Exception
+ {
+ Company company = getModel1Factory().createCompany();
+
+ CDOSession session = openModel1Session();
+ CDOTransaction transaction = session.openTransaction();
+ CDOResource res = transaction.createResource("/res1");
+ res.getContents().add(company);
+ transaction.commit();
+ transaction.setAutoReleaseLocksEnabled(false);
+
+ CDOObject cdoCompany = CDOUtil.getCDOObject(company);
+ cdoCompany.cdoWriteLock().lock();
+ cdoCompany.cdoReadLock().lock();
+
+ msg("Test with read/write lock");
+ assertEquals(true, cdoCompany.cdoWriteLock().isLocked());
+ assertEquals(true, cdoCompany.cdoReadLock().isLocked());
+
+ company.setCity("Ottawa");
+ transaction.rollback();
+ assertEquals(true, cdoCompany.cdoWriteLock().isLocked());
+ assertEquals(true, cdoCompany.cdoReadLock().isLocked());
+
+ msg("Clean locks");
+ transaction.unlockObjects(null, null);
+
+ msg("Test with read lock");
+ cdoCompany.cdoReadLock().lock();
+ assertEquals(true, cdoCompany.cdoReadLock().isLocked());
+
+ company.setCity("Toronto");
+ transaction.rollback();
+ assertEquals(true, cdoCompany.cdoReadLock().isLocked());
+
+ transaction.setAutoReleaseLocksEnabled(true);
+ transaction.rollback();
+ assertEquals(false, cdoCompany.cdoReadLock().isLocked());
+ }
+
+ public void testWriteLockPerformance() throws Exception
+ {
+ final int ITERATION = 1000;
+ Company company = getModel1Factory().createCompany();
+
+ CDOSession session = openModel1Session();
+ CDOTransaction transaction = session.openTransaction();
+ CDOResource res = transaction.createResource("/res1");
+ res.getContents().add(company);
+ transaction.commit();
+
+ long start = System.currentTimeMillis();
+ CDOObject cdoCompany = CDOUtil.getCDOObject(company);
+
+ // 335-418 locks/sec
+ for (int i = 0; i < ITERATION; i++)
+ {
+ cdoCompany.cdoWriteLock().lock();
+ }
+
+ msg("Lock " + ITERATION / ((double)(System.currentTimeMillis() - start) / 1000) + " objects/sec");
+ }
+}
diff --git a/plugins/org.eclipse.emf.cdo.tests/src/org/eclipse/emf/cdo/tests/ResourceTest.java b/plugins/org.eclipse.emf.cdo.tests/src/org/eclipse/emf/cdo/tests/ResourceTest.java
index 135a047331..cd65ba6ec9 100644
--- a/plugins/org.eclipse.emf.cdo.tests/src/org/eclipse/emf/cdo/tests/ResourceTest.java
+++ b/plugins/org.eclipse.emf.cdo.tests/src/org/eclipse/emf/cdo/tests/ResourceTest.java
@@ -574,7 +574,7 @@ public class ResourceTest extends AbstractCDOTest
assertClean(order, transaction);
session.close();
}
-
+ clearCache(getRepository().getRevisionManager());
CDOSession session = openModel1Session();
CDOTransaction transaction = session.openTransaction();
diff --git a/plugins/org.eclipse.emf.cdo.tests/src/org/eclipse/emf/cdo/tests/StateMachineTest.java b/plugins/org.eclipse.emf.cdo.tests/src/org/eclipse/emf/cdo/tests/StateMachineTest.java
index 94374ac611..57d02cefb2 100644
--- a/plugins/org.eclipse.emf.cdo.tests/src/org/eclipse/emf/cdo/tests/StateMachineTest.java
+++ b/plugins/org.eclipse.emf.cdo.tests/src/org/eclipse/emf/cdo/tests/StateMachineTest.java
@@ -27,6 +27,8 @@ import org.eclipse.emf.internal.cdo.CDOStateMachine;
import org.eclipse.emf.internal.cdo.InternalCDOObject;
import org.eclipse.emf.internal.cdo.protocol.CommitTransactionResult;
+import org.eclipse.net4j.util.io.IOUtil;
+
import org.eclipse.emf.common.util.URI;
import org.eclipse.emf.ecore.EObject;
@@ -588,7 +590,7 @@ public class StateMachineTest extends AbstractCDOTest
private static void assertFailure(IllegalStateException ex)
{
- ex.printStackTrace();
+ IOUtil.print(ex);
assertTrue("Expected FAIL transition", ex.getMessage().startsWith("Failing event "));
}
@@ -693,7 +695,7 @@ public class StateMachineTest extends AbstractCDOTest
}
catch (Exception ex)
{
- ex.printStackTrace();
+ IOUtil.print(ex);
fail("Reflection problem: " + ex.getMessage());
}
finally
diff --git a/plugins/org.eclipse.emf.cdo.tests/src/org/eclipse/emf/cdo/tests/TransactionTest.java b/plugins/org.eclipse.emf.cdo.tests/src/org/eclipse/emf/cdo/tests/TransactionTest.java
index bcc10403b6..2ef5f5cc09 100644
--- a/plugins/org.eclipse.emf.cdo.tests/src/org/eclipse/emf/cdo/tests/TransactionTest.java
+++ b/plugins/org.eclipse.emf.cdo.tests/src/org/eclipse/emf/cdo/tests/TransactionTest.java
@@ -16,6 +16,7 @@ import org.eclipse.emf.cdo.CDOTransaction;
import org.eclipse.emf.cdo.eresource.CDOResource;
import org.eclipse.emf.cdo.tests.model1.Category;
+import org.eclipse.net4j.util.io.IOUtil;
import org.eclipse.net4j.util.om.OMPlatform;
import java.util.ArrayList;
@@ -144,11 +145,11 @@ public class TransactionTest extends AbstractCDOTest
boolean timedOut = !latch.await(TIMEOUT, TimeUnit.SECONDS);
- for (Exception exp : exceptions)
+ for (Exception ex : exceptions)
{
System.out.println();
System.out.println();
- exp.printStackTrace();
+ IOUtil.print(ex);
}
if (timedOut)
diff --git a/plugins/org.eclipse.emf.cdo.tests/src/org/eclipse/emf/cdo/tests/bugzilla/Bugzilla_250757_Test.java b/plugins/org.eclipse.emf.cdo.tests/src/org/eclipse/emf/cdo/tests/bugzilla/Bugzilla_250757_Test.java
index eb4d700a08..e045fb149f 100644
--- a/plugins/org.eclipse.emf.cdo.tests/src/org/eclipse/emf/cdo/tests/bugzilla/Bugzilla_250757_Test.java
+++ b/plugins/org.eclipse.emf.cdo.tests/src/org/eclipse/emf/cdo/tests/bugzilla/Bugzilla_250757_Test.java
@@ -19,6 +19,7 @@ import org.eclipse.emf.cdo.tests.AbstractCDOTest;
import org.eclipse.emf.cdo.tests.model1.PurchaseOrder;
import org.eclipse.emf.cdo.tests.model1.Supplier;
+import org.eclipse.net4j.util.io.IOUtil;
import org.eclipse.net4j.util.transaction.TransactionException;
import org.eclipse.emf.ecore.EObject;
@@ -123,9 +124,9 @@ public class Bugzilla_250757_Test extends AbstractCDOTest
{
transaction1.commit();
}
- catch (TransactionException e)
+ catch (TransactionException ex)
{
- e.printStackTrace();
+ IOUtil.print(ex);
fail("Should not have an exception");
}
}
@@ -155,9 +156,9 @@ public class Bugzilla_250757_Test extends AbstractCDOTest
{
transaction1.commit();
}
- catch (TransactionException e)
+ catch (TransactionException ex)
{
- e.printStackTrace();
+ IOUtil.print(ex);
fail("Should not have an exception");
}
}
diff --git a/plugins/org.eclipse.emf.cdo.ui/src/org/eclipse/emf/cdo/internal/ui/editor/CDOEditor.java b/plugins/org.eclipse.emf.cdo.ui/src/org/eclipse/emf/cdo/internal/ui/editor/CDOEditor.java
index e204332fad..9df82e344a 100644
--- a/plugins/org.eclipse.emf.cdo.ui/src/org/eclipse/emf/cdo/internal/ui/editor/CDOEditor.java
+++ b/plugins/org.eclipse.emf.cdo.ui/src/org/eclipse/emf/cdo/internal/ui/editor/CDOEditor.java
@@ -1044,7 +1044,7 @@ public class CDOEditor extends MultiPageEditorPart implements IEditingDomainProv
}
catch (RuntimeException ex)
{
- ex.printStackTrace();
+ OM.LOG.error(ex);
throw ex;
}
}
diff --git a/plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/cdo/CDOLock.java b/plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/cdo/CDOLock.java
new file mode 100644
index 0000000000..a02c8c95c4
--- /dev/null
+++ b/plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/cdo/CDOLock.java
@@ -0,0 +1,33 @@
+/***************************************************************************
+ * Copyright (c) 2004 - 2008 Eike Stepper, Germany.
+ * 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:
+ * Simon McDuff - initial API and implementation
+ **************************************************************************/
+package org.eclipse.emf.cdo;
+
+import org.eclipse.net4j.util.concurrent.RWLockManager;
+
+import java.util.concurrent.locks.Lock;
+
+/**
+ * @author Simon McDuff
+ * @since 2.0
+ */
+public interface CDOLock extends Lock
+{
+ public static final int WAIT = RWLockManager.WAIT;
+
+ public static final int NO_WAIT = RWLockManager.NO_WAIT;
+
+ /**
+ * Return true if it is currently lock.
+ */
+ public boolean isLocked();
+
+ public RWLockManager.LockType getType();
+}
diff --git a/plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/cdo/CDOObject.java b/plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/cdo/CDOObject.java
index 0f199e8b6e..91eabaa7d9 100644
--- a/plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/cdo/CDOObject.java
+++ b/plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/cdo/CDOObject.java
@@ -39,5 +39,19 @@ public interface CDOObject extends EObject
*/
public CDOResource cdoDirectResource();
+ /**
+ * Returns read lock associate with this object.
+ *
+ * @since 2.0
+ */
+ public CDOLock cdoReadLock();
+
+ /**
+ * Returns write lock associate with this object.
+ *
+ * @since 2.0
+ */
+ public CDOLock cdoWriteLock();
+
public void cdoReload();
}
diff --git a/plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/cdo/CDOTransaction.java b/plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/cdo/CDOTransaction.java
index dd17d2c8bc..d47cd76ff4 100644
--- a/plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/cdo/CDOTransaction.java
+++ b/plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/cdo/CDOTransaction.java
@@ -39,6 +39,28 @@ public interface CDOTransaction extends CDOView, CDOUserTransaction
public void setCommitTimeout(long timeout);
/**
+ * Specifies whether locks in this view will be removed when {@link CDOTransaction#commit()} or
+ * {@link CDOTransaction#rollback()} is called.
+ * <p>
+ * If false all locks are kept.
+ * <p>
+ * Default value is true.
+ *
+ * @since 2.0
+ */
+ public boolean setAutoReleaseLocksEnabled(boolean on);
+
+ /**
+ * Returns true if locks in this view will be removes when {@link CDOTransaction#commit()} or
+ * {@link CDOTransaction#rollback()} is called.
+ * <p>
+ * Default value is true.
+ *
+ * @since 2.0
+ */
+ public boolean isAutoReleaseLocksEnabled();
+
+ /**
* @since 2.0
*/
public long getLastCommitTime();
diff --git a/plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/cdo/CDOView.java b/plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/cdo/CDOView.java
index ae4e013213..5e8514b5dc 100644
--- a/plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/cdo/CDOView.java
+++ b/plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/cdo/CDOView.java
@@ -20,6 +20,7 @@ import org.eclipse.emf.cdo.eresource.CDOResourceNode;
import org.eclipse.emf.cdo.util.ReadOnlyException;
import org.eclipse.net4j.util.collection.CloseableIterator;
+import org.eclipse.net4j.util.concurrent.RWLockManager;
import org.eclipse.net4j.util.event.INotifier;
import org.eclipse.emf.common.util.URI;
@@ -27,6 +28,7 @@ import org.eclipse.emf.ecore.EObject;
import org.eclipse.emf.ecore.resource.ResourceSet;
import org.eclipse.emf.ecore.resource.URIHandler;
+import java.util.Collection;
import java.util.List;
import java.util.concurrent.locks.ReentrantLock;
@@ -337,5 +339,25 @@ public interface CDOView extends CDOProtocolView, INotifier
/**
* @since 2.0
*/
+ public void lockObjects(Collection<? extends CDOObject> objects, RWLockManager.LockType lockType, long timeout)
+ throws InterruptedException;
+
+ /**
+ * Unlocks the given locked objects of this view.
+ *
+ * @since 2.0
+ */
+ public void unlockObjects(Collection<? extends CDOObject> objects, RWLockManager.LockType lockType);
+
+ /**
+ * Unlocks all locked objects of this view.
+ *
+ * @since 2.0
+ */
+ public void unlockObjects();
+
+ /**
+ * @since 2.0
+ */
public CDOQuery createQuery(String language, String queryString);
}
diff --git a/plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/internal/cdo/CDOObjectImpl.java b/plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/internal/cdo/CDOObjectImpl.java
index bd266242e5..61b7e3a735 100644
--- a/plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/internal/cdo/CDOObjectImpl.java
+++ b/plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/internal/cdo/CDOObjectImpl.java
@@ -11,6 +11,7 @@
**************************************************************************/
package org.eclipse.emf.internal.cdo;
+import org.eclipse.emf.cdo.CDOLock;
import org.eclipse.emf.cdo.CDOState;
import org.eclipse.emf.cdo.CDOView;
import org.eclipse.emf.cdo.common.id.CDOID;
@@ -29,6 +30,9 @@ import org.eclipse.emf.internal.cdo.util.GenUtil;
import org.eclipse.emf.internal.cdo.util.ModelUtil;
import org.eclipse.net4j.util.ImplementationError;
+import org.eclipse.net4j.util.WrappedException;
+import org.eclipse.net4j.util.concurrent.RWLockManager;
+import org.eclipse.net4j.util.concurrent.TimeoutRuntimeException;
import org.eclipse.net4j.util.om.trace.ContextTracer;
import org.eclipse.emf.common.notify.Adapter;
@@ -58,9 +62,12 @@ import org.eclipse.emf.ecore.util.FeatureMap;
import org.eclipse.emf.ecore.util.InternalEList;
import java.util.Collection;
+import java.util.Collections;
import java.util.Iterator;
import java.util.List;
import java.util.ListIterator;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.locks.Condition;
/**
* @author Eike Stepper
@@ -78,7 +85,7 @@ public class CDOObjectImpl extends EStoreEObjectImpl implements InternalCDOObjec
private InternalCDORevision revision;
/**
- * CDO used this list instead of eSettings for transient objects. EMF used eSettings as cache. CDO deactivated the
+ * CDO used this list instead of eSettings for transient objects. EMF used eSettings as cache. CDO deactivates the
* cache but EMF still used eSettings to store list wrappers. CDO needs another place to store the real list with the
* actual data (transient mode) and accessible through EStore. This allows CDO to always use the same instance of the
* list wrapper.
@@ -297,6 +304,34 @@ public class CDOObjectImpl extends EStoreEObjectImpl implements InternalCDOObjec
cdoSettings = null;
}
+ /**
+ * @since 2.0
+ */
+ public CDOLock cdoReadLock()
+ {
+ if (FSMUtil.isTransient(this) || FSMUtil.isNew(this))
+ {
+ return NOOPLockImpl.INSTANCE;
+ }
+
+ // Should we cache the locks ?
+ return new CDOLockImpl(RWLockManager.LockType.READ);
+ }
+
+ /**
+ * @since 2.0
+ */
+ public CDOLock cdoWriteLock()
+ {
+ if (FSMUtil.isTransient(this) || FSMUtil.isNew(this))
+ {
+ return NOOPLockImpl.INSTANCE;
+ }
+
+ // Should we cache the locks ?
+ return new CDOLockImpl(RWLockManager.LockType.WRITE);
+ }
+
@SuppressWarnings("unchecked")
private void populateRevisionFeature(CDOViewImpl view, InternalCDORevision revision, EStructuralFeature eFeature,
Object[] eSettings, int i)
@@ -976,7 +1011,92 @@ public class CDOObjectImpl extends EStoreEObjectImpl implements InternalCDOObjec
}
/**
- * @author Eike Stepper
+ * @author Simon McDuff
+ * @since 2.0
+ */
+ private final class CDOLockImpl implements CDOLock
+ {
+ private RWLockManager.LockType type;
+
+ public CDOLockImpl(RWLockManager.LockType type)
+ {
+ this.type = type;
+ }
+
+ public RWLockManager.LockType getType()
+ {
+ return type;
+ }
+
+ public boolean isLocked()
+ {
+ return cdoView().isLocked(CDOObjectImpl.this, type);
+ }
+
+ public void lock()
+ {
+ try
+ {
+ cdoView().lockObjects(Collections.singletonList(CDOObjectImpl.this), type, CDOLock.WAIT);
+ }
+ catch (InterruptedException ex)
+ {
+ throw WrappedException.wrap(ex);
+ }
+ }
+
+ public void lockInterruptibly() throws InterruptedException
+ {
+ lock();
+ }
+
+ public Condition newCondition()
+ {
+ throw new UnsupportedOperationException();
+ }
+
+ public boolean tryLock()
+ {
+ try
+ {
+ cdoView().lockObjects(Collections.singletonList(CDOObjectImpl.this), type, CDOLock.NO_WAIT);
+ return true;
+ }
+ catch (TimeoutRuntimeException ex)
+ {
+ return false;
+ }
+ catch (InterruptedException ex)
+ {
+ return false;
+ }
+ }
+
+ /**
+ * @throws will
+ * throw an exception if timeout is reached.
+ */
+ public boolean tryLock(long time, TimeUnit unit) throws InterruptedException
+ {
+ try
+ {
+ cdoView().lockObjects(Collections.singletonList(CDOObjectImpl.this), type, unit.toMillis(time));
+ return true;
+ }
+ catch (TimeoutRuntimeException ex)
+ {
+ return false;
+ }
+ }
+
+ public void unlock()
+ {
+ cdoView().unlockObjects(Collections.singletonList(CDOObjectImpl.this), type);
+ }
+ }
+
+ /**
+ * @author Simon McDuff
* @since 2.0
*/
public static class CDOStoreSettingsImpl implements InternalEObject.EStore
diff --git a/plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/internal/cdo/CDOObjectWrapper.java b/plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/internal/cdo/CDOObjectWrapper.java
index 78441c6506..699451eac6 100644
--- a/plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/internal/cdo/CDOObjectWrapper.java
+++ b/plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/internal/cdo/CDOObjectWrapper.java
@@ -11,6 +11,7 @@
package org.eclipse.emf.internal.cdo;
import org.eclipse.emf.cdo.CDOView;
+import org.eclipse.emf.cdo.CDOLock;
import org.eclipse.emf.cdo.common.id.CDOID;
import org.eclipse.emf.cdo.eresource.impl.CDOResourceImpl;
@@ -125,6 +126,22 @@ public abstract class CDOObjectWrapper implements InternalCDOObject
/**
* @since 2.0
*/
+ public CDOLock cdoReadLock()
+ {
+ throw new UnsupportedOperationException();
+ }
+
+ /**
+ * @since 2.0
+ */
+ public CDOLock cdoWriteLock()
+ {
+ throw new UnsupportedOperationException();
+ }
+
+ /**
+ * @since 2.0
+ */
public void eFireRead(int featureID)
{
// Do nothing
diff --git a/plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/internal/cdo/CDOTransactionImpl.java b/plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/internal/cdo/CDOTransactionImpl.java
index fdf07f55f7..456e9f9f56 100644
--- a/plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/internal/cdo/CDOTransactionImpl.java
+++ b/plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/internal/cdo/CDOTransactionImpl.java
@@ -95,6 +95,8 @@ public class CDOTransactionImpl extends CDOViewImpl implements InternalCDOTransa
private CDOTransactionStrategy transactionStrategy;
+ private boolean autoReleaseLocksEnabled = true;
+
public CDOTransactionImpl(int id, CDOSessionImpl session)
{
super(session, id);
@@ -168,6 +170,29 @@ public class CDOTransactionImpl extends CDOViewImpl implements InternalCDOTransa
/**
* @since 2.0
*/
+ synchronized public boolean setAutoReleaseLocksEnabled(boolean on)
+ {
+ try
+ {
+ return autoReleaseLocksEnabled;
+ }
+ finally
+ {
+ autoReleaseLocksEnabled = on;
+ }
+ }
+
+ /**
+ * @since 2.0
+ */
+ public boolean isAutoReleaseLocksEnabled()
+ {
+ return autoReleaseLocksEnabled;
+ }
+
+ /**
+ * @since 2.0
+ */
public long getLastCommitTime()
{
return lastCommitTime;
@@ -718,6 +743,12 @@ public class CDOTransactionImpl extends CDOViewImpl implements InternalCDOTransa
// Load from first savepoint up to current savepoint
loadSavepoint(lastSavepoint, idsOfNewObjectWithDeltas);
+ if (lastSavepoint == firstSavepoint && isAutoReleaseLocksEnabled())
+ {
+ // Unlock all objects
+ unlockObjects(null, null);
+ }
+
Map<CDOIDTemp, CDOID> idMappings = Collections.emptyMap();
fireEvent(new FinishedEvent(CDOTransactionFinishedEvent.Type.ROLLED_BACK, idMappings));
for (CDOTransactionHandler handler : getHandlers())
@@ -1158,6 +1189,14 @@ public class CDOTransactionImpl extends CDOViewImpl implements InternalCDOTransa
throw new TransactionException(ex);
}
}
+ else
+ {
+ // Removes locks even if no one touch the transaction
+ if (isAutoReleaseLocksEnabled())
+ {
+ unlockObjects(null, null);
+ }
+ }
}
@SuppressWarnings("unchecked")
diff --git a/plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/internal/cdo/CDOViewImpl.java b/plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/internal/cdo/CDOViewImpl.java
index aaf101509d..01048a54eb 100644
--- a/plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/internal/cdo/CDOViewImpl.java
+++ b/plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/internal/cdo/CDOViewImpl.java
@@ -51,14 +51,20 @@ import org.eclipse.emf.cdo.util.ReadOnlyException;
import org.eclipse.emf.internal.cdo.bundle.OM;
import org.eclipse.emf.internal.cdo.protocol.ChangeSubscriptionRequest;
+import org.eclipse.emf.internal.cdo.protocol.LockObjectsRequest;
+import org.eclipse.emf.internal.cdo.protocol.ObjectLockedRequest;
+import org.eclipse.emf.internal.cdo.protocol.UnlockObjectsRequest;
import org.eclipse.emf.internal.cdo.query.CDOQueryImpl;
import org.eclipse.emf.internal.cdo.util.FSMUtil;
import org.eclipse.emf.internal.cdo.util.ModelUtil;
+import org.eclipse.net4j.signal.SignalRemoteException;
import org.eclipse.net4j.util.ImplementationError;
import org.eclipse.net4j.util.StringUtil;
+import org.eclipse.net4j.util.WrappedException;
import org.eclipse.net4j.util.ReflectUtil.ExcludeFromDump;
import org.eclipse.net4j.util.collection.CloseableIterator;
+import org.eclipse.net4j.util.concurrent.RWLockManager;
import org.eclipse.net4j.util.om.trace.ContextTracer;
import org.eclipse.net4j.util.ref.ReferenceValueMap;
import org.eclipse.net4j.util.transaction.TransactionException;
@@ -215,6 +221,89 @@ public class CDOViewImpl extends org.eclipse.net4j.util.event.Notifier implement
return lock;
}
+ /**
+ * @throws InterruptedException
+ * @since 2.0
+ */
+ public void lockObjects(Collection<? extends CDOObject> objects, RWLockManager.LockType lockType, long timeout)
+ throws InterruptedException
+ {
+ InterruptedException interruptedException = null;
+ RuntimeException runtimeException = null;
+
+ try
+ {
+ LockObjectsRequest request = new LockObjectsRequest(getSession().getProtocol(), this, objects, timeout, lockType);
+ getSession().getFailOverStrategy().send(request);
+ }
+ catch (SignalRemoteException ex)
+ {
+ if (ex.getCause() instanceof RuntimeException)
+ {
+ runtimeException = (RuntimeException)ex.getCause();
+ }
+ else if (ex.getCause() instanceof InterruptedException)
+ {
+ interruptedException = (InterruptedException)ex.getCause();
+ }
+ }
+ catch (Exception ex)
+ {
+ throw WrappedException.wrap(ex);
+ }
+
+ if (interruptedException != null)
+ {
+ throw interruptedException;
+ }
+
+ if (runtimeException != null)
+ {
+ throw runtimeException;
+ }
+ }
+
+ /**
+ * @since 2.0
+ */
+ public void unlockObjects(Collection<? extends CDOObject> objects, RWLockManager.LockType lockType)
+ {
+ try
+ {
+ UnlockObjectsRequest request = new UnlockObjectsRequest(getSession().getProtocol(), this, objects, lockType);
+ getSession().getFailOverStrategy().send(request);
+ }
+ catch (Exception ex)
+ {
+ throw WrappedException.wrap(ex);
+ }
+ }
+
+ /**
+ * @since 2.0
+ */
+ public void unlockObjects()
+ {
+ unlockObjects(null, null);
+ }
+
+ /**
+ * @throws InterruptedException
+ * @since 2.0
+ */
+ public boolean isLocked(CDOObject object, RWLockManager.LockType lockType)
+ {
+ try
+ {
+ ObjectLockedRequest request = new ObjectLockedRequest(getSession().getProtocol(), this, object, lockType);
+ return getSession().getFailOverStrategy().send(request);
+ }
+ catch (Exception ex)
+ {
+ throw WrappedException.wrap(ex);
+ }
+ }
+
public boolean isDirty()
{
return false;
diff --git a/plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/internal/cdo/NOOPLockImpl.java b/plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/internal/cdo/NOOPLockImpl.java
new file mode 100644
index 0000000000..4debb2dc0a
--- /dev/null
+++ b/plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/internal/cdo/NOOPLockImpl.java
@@ -0,0 +1,71 @@
+/***************************************************************************
+ * Copyright (c) 2004 - 2008 Eike Stepper, Germany.
+ * 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:
+ * Simon McDuff - initial API and implementation
+ **************************************************************************/
+package org.eclipse.emf.internal.cdo;
+
+import org.eclipse.emf.cdo.CDOLock;
+
+import org.eclipse.net4j.util.concurrent.RWLockManager;
+
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.locks.Condition;
+
+/**
+ * @author Simon McDuff
+ * @since 2.0
+ */
+public class NOOPLockImpl implements CDOLock
+{
+ public static final NOOPLockImpl INSTANCE = new NOOPLockImpl();
+
+ private NOOPLockImpl()
+ {
+ }
+
+ public boolean isLocked()
+ {
+ return false;
+ }
+
+ public void lock()
+ {
+ throw new UnsupportedOperationException();
+ }
+
+ public void lockInterruptibly() throws InterruptedException
+ {
+ throw new UnsupportedOperationException();
+ }
+
+ public Condition newCondition()
+ {
+ return null;
+ }
+
+ public boolean tryLock()
+ {
+ return false;
+ }
+
+ public boolean tryLock(long time, TimeUnit unit) throws InterruptedException
+ {
+ return false;
+ }
+
+ public void unlock()
+ {
+ throw new UnsupportedOperationException();
+ }
+
+ public RWLockManager.LockType getType()
+ {
+ return null;
+ }
+}
diff --git a/plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/internal/cdo/protocol/CommitTransactionRequest.java b/plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/internal/cdo/protocol/CommitTransactionRequest.java
index 7648b20f9d..45e51ae26e 100644
--- a/plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/internal/cdo/protocol/CommitTransactionRequest.java
+++ b/plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/internal/cdo/protocol/CommitTransactionRequest.java
@@ -106,6 +106,7 @@ public class CommitTransactionRequest extends CDOClientRequest<CommitTransaction
Collection<CDORevisionDelta> revisionDeltas = commitContext.getRevisionDeltas().values();
Collection<CDOID> detachedObjects = commitContext.getDetachedObjects().keySet();
+ out.writeBoolean(commitContext.getTransaction().isAutoReleaseLocksEnabled());
out.writeInt(newPackages.size());
out.writeInt(newResources.size() + newObjects.size());
out.writeInt(revisionDeltas.size());
diff --git a/plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/internal/cdo/protocol/LockObjectsRequest.java b/plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/internal/cdo/protocol/LockObjectsRequest.java
new file mode 100644
index 0000000000..a0fde6d651
--- /dev/null
+++ b/plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/internal/cdo/protocol/LockObjectsRequest.java
@@ -0,0 +1,83 @@
+/***************************************************************************
+ * Copyright (c) 2004 - 2008 Eike Stepper, Germany.
+ * 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:
+ * Simon McDuff - initial API and implementation
+ **************************************************************************/
+package org.eclipse.emf.internal.cdo.protocol;
+
+import org.eclipse.emf.cdo.CDOObject;
+import org.eclipse.emf.cdo.CDOView;
+import org.eclipse.emf.cdo.common.CDODataInput;
+import org.eclipse.emf.cdo.common.CDODataOutput;
+import org.eclipse.emf.cdo.common.CDOProtocolConstants;
+
+import org.eclipse.emf.internal.cdo.bundle.OM;
+
+import org.eclipse.net4j.util.concurrent.RWLockManager;
+import org.eclipse.net4j.util.om.trace.ContextTracer;
+
+import java.io.IOException;
+import java.util.Collection;
+
+/**
+ * @author Simon McDuff
+ */
+public class LockObjectsRequest extends CDOClientRequest<Object>
+{
+ private static final ContextTracer PROTOCOL_TRACER = new ContextTracer(OM.DEBUG_PROTOCOL, LockObjectsRequest.class);
+
+ private CDOView view;
+
+ private RWLockManager.LockType lockType;
+
+ private Collection<? extends CDOObject> objects;
+
+ private long timeout;
+
+ public LockObjectsRequest(CDOClientProtocol protocol, CDOView view, Collection<? extends CDOObject> objects,
+ long timeout, RWLockManager.LockType lockType)
+ {
+ super(protocol, CDOProtocolConstants.SIGNAL_LOCK_OBJECTS);
+ this.view = view;
+ this.objects = objects;
+ this.timeout = timeout;
+ this.lockType = lockType;
+ }
+
+ @Override
+ protected void requesting(CDODataOutput out) throws IOException
+ {
+ out.writeInt(view.getViewID());
+ out.writeCDOLockType(lockType);
+ out.writeLong(timeout);
+
+ if (PROTOCOL_TRACER.isEnabled())
+ {
+ PROTOCOL_TRACER.format("Locking of type {0} requested for view {1} with timeout {2}",
+ lockType == RWLockManager.LockType.READ ? "read" : "write", view.getViewID(), timeout);
+ }
+
+ out.writeInt(objects.size());
+ for (CDOObject object : objects)
+ {
+ if (PROTOCOL_TRACER.isEnabled())
+ {
+ PROTOCOL_TRACER.format("Locking requested for objects {0}", object.cdoID());
+ }
+
+ out.writeCDOID(object.cdoID());
+ }
+ }
+
+ @Override
+ protected Object confirming(CDODataInput in) throws IOException
+ {
+ in.readBoolean();
+ return null;
+ }
+}
diff --git a/plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/internal/cdo/protocol/ObjectLockedRequest.java b/plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/internal/cdo/protocol/ObjectLockedRequest.java
new file mode 100644
index 0000000000..7de2be3cf6
--- /dev/null
+++ b/plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/internal/cdo/protocol/ObjectLockedRequest.java
@@ -0,0 +1,66 @@
+/***************************************************************************
+ * Copyright (c) 2004 - 2008 Eike Stepper, Germany.
+ * 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:
+ * Simon McDuff - initial API and implementation
+ **************************************************************************/
+package org.eclipse.emf.internal.cdo.protocol;
+
+import org.eclipse.emf.cdo.CDOObject;
+import org.eclipse.emf.cdo.CDOView;
+import org.eclipse.emf.cdo.common.CDODataInput;
+import org.eclipse.emf.cdo.common.CDODataOutput;
+import org.eclipse.emf.cdo.common.CDOProtocolConstants;
+
+import org.eclipse.emf.internal.cdo.bundle.OM;
+
+import org.eclipse.net4j.util.concurrent.RWLockManager;
+import org.eclipse.net4j.util.om.trace.ContextTracer;
+
+import java.io.IOException;
+
+/**
+ * @author Simon McDuff
+ */
+public class ObjectLockedRequest extends CDOClientRequest<Boolean>
+{
+ private static final ContextTracer PROTOCOL_TRACER = new ContextTracer(OM.DEBUG_PROTOCOL, ObjectLockedRequest.class);
+
+ private CDOView view;
+
+ private CDOObject object;
+
+ private RWLockManager.LockType lockType;
+
+ public ObjectLockedRequest(CDOClientProtocol protocol, CDOView view, CDOObject object, RWLockManager.LockType lockType)
+ {
+ super(protocol, CDOProtocolConstants.SIGNAL_OBJECT_LOCKED);
+ this.view = view;
+ this.object = object;
+ this.lockType = lockType;
+ }
+
+ @Override
+ protected void requesting(CDODataOutput out) throws IOException
+ {
+ if (PROTOCOL_TRACER.isEnabled())
+ {
+ PROTOCOL_TRACER.format("Requesting if object {0} has of lock for object {1}", object.cdoID(),
+ lockType == RWLockManager.LockType.READ ? "read" : "write");
+ }
+
+ out.writeInt(view.getViewID());
+ out.writeCDOLockType(lockType);
+ out.writeCDOID(object.cdoID());
+ }
+
+ @Override
+ protected Boolean confirming(CDODataInput in) throws IOException
+ {
+ return in.readBoolean();
+ }
+}
diff --git a/plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/internal/cdo/protocol/UnlockObjectsRequest.java b/plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/internal/cdo/protocol/UnlockObjectsRequest.java
new file mode 100644
index 0000000000..294f8f229d
--- /dev/null
+++ b/plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/internal/cdo/protocol/UnlockObjectsRequest.java
@@ -0,0 +1,89 @@
+/***************************************************************************
+ * Copyright (c) 2004 - 2008 Eike Stepper, Germany.
+ * 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:
+ * Simon McDuff - initial API and implementation
+ **************************************************************************/
+package org.eclipse.emf.internal.cdo.protocol;
+
+import org.eclipse.emf.cdo.CDOObject;
+import org.eclipse.emf.cdo.CDOView;
+import org.eclipse.emf.cdo.common.CDODataInput;
+import org.eclipse.emf.cdo.common.CDODataOutput;
+import org.eclipse.emf.cdo.common.CDOProtocolConstants;
+
+import org.eclipse.emf.internal.cdo.bundle.OM;
+
+import org.eclipse.net4j.util.concurrent.RWLockManager;
+import org.eclipse.net4j.util.om.trace.ContextTracer;
+
+import java.io.IOException;
+import java.util.Collection;
+
+/**
+ * @author Simon McDuff
+ */
+public class UnlockObjectsRequest extends CDOClientRequest<Boolean>
+{
+ private static final ContextTracer PROTOCOL_TRACER = new ContextTracer(OM.DEBUG_PROTOCOL, UnlockObjectsRequest.class);
+
+ private CDOView view;
+
+ private Collection<? extends CDOObject> objects;
+
+ private RWLockManager.LockType lockType;
+
+ public UnlockObjectsRequest(CDOClientProtocol protocol, CDOView view, Collection<? extends CDOObject> objects,
+ RWLockManager.LockType lockType)
+ {
+ super(protocol, CDOProtocolConstants.SIGNAL_UNLOCK_OBJECTS);
+ this.view = view;
+ this.objects = objects;
+ this.lockType = lockType;
+ }
+
+ @Override
+ protected void requesting(CDODataOutput out) throws IOException
+ {
+ out.writeInt(view.getViewID());
+ out.writeCDOLockType(lockType);
+ if (objects == null)
+ {
+ if (PROTOCOL_TRACER.isEnabled())
+ {
+ PROTOCOL_TRACER.format("Unlocking all objects for view {0}", view.getViewID());
+ }
+
+ out.writeInt(CDOProtocolConstants.RELEASE_ALL_LOCKS);
+ }
+ else
+ {
+ if (PROTOCOL_TRACER.isEnabled())
+ {
+ PROTOCOL_TRACER.format("Unlocking of type {0} requested for view {1}",
+ lockType == RWLockManager.LockType.READ ? "read" : "write", view.getViewID());
+ }
+
+ out.writeInt(objects.size());
+ for (CDOObject object : objects)
+ {
+ if (PROTOCOL_TRACER.isEnabled())
+ {
+ PROTOCOL_TRACER.format("Unlocking requested for objects {0}", object.cdoID());
+ }
+
+ out.writeCDOID(object.cdoID());
+ }
+ }
+ }
+
+ @Override
+ protected Boolean confirming(CDODataInput in) throws IOException
+ {
+ return in.readBoolean();
+ }
+}
diff --git a/plugins/org.eclipse.net4j.http/src/org/eclipse/net4j/internal/http/HTTPConnectorFactory.java b/plugins/org.eclipse.net4j.http/src/org/eclipse/net4j/internal/http/HTTPConnectorFactory.java
index bf27e94845..02a1f5f7f7 100644
--- a/plugins/org.eclipse.net4j.http/src/org/eclipse/net4j/internal/http/HTTPConnectorFactory.java
+++ b/plugins/org.eclipse.net4j.http/src/org/eclipse/net4j/internal/http/HTTPConnectorFactory.java
@@ -10,6 +10,8 @@
**************************************************************************/
package org.eclipse.net4j.internal.http;
+import org.eclipse.net4j.http.internal.common.bundle.OM;
+
import org.eclipse.spi.net4j.ConnectorFactory;
import java.net.MalformedURLException;
@@ -44,7 +46,7 @@ public class HTTPConnectorFactory extends ConnectorFactory
}
catch (MalformedURLException ex)
{
- ex.printStackTrace();
+ OM.LOG.error(ex);
}
HTTPClientConnector connector = new HTTPClientConnector();
diff --git a/plugins/org.eclipse.net4j.jms.tests/src/org/eclipse/net4j/jms/tests/JMSSeparatedTest.java b/plugins/org.eclipse.net4j.jms.tests/src/org/eclipse/net4j/jms/tests/JMSSeparatedTest.java
index 15f2df9513..9699d8f8fb 100644
--- a/plugins/org.eclipse.net4j.jms.tests/src/org/eclipse/net4j/jms/tests/JMSSeparatedTest.java
+++ b/plugins/org.eclipse.net4j.jms.tests/src/org/eclipse/net4j/jms/tests/JMSSeparatedTest.java
@@ -140,7 +140,7 @@ public class JMSSeparatedTest
}
catch (JMSException ex)
{
- ex.printStackTrace();
+ IOUtil.print(ex);
}
}
}
diff --git a/plugins/org.eclipse.net4j.jms.tests/src/org/eclipse/net4j/jms/tests/JMSTest.java b/plugins/org.eclipse.net4j.jms.tests/src/org/eclipse/net4j/jms/tests/JMSTest.java
index 819fee4e74..918a5cf944 100644
--- a/plugins/org.eclipse.net4j.jms.tests/src/org/eclipse/net4j/jms/tests/JMSTest.java
+++ b/plugins/org.eclipse.net4j.jms.tests/src/org/eclipse/net4j/jms/tests/JMSTest.java
@@ -125,7 +125,7 @@ public class JMSTest
}
catch (JMSException ex)
{
- ex.printStackTrace();
+ IOUtil.print(ex);
}
}
}
diff --git a/plugins/org.eclipse.net4j.tests/src/org/eclipse/net4j/tests/ChannelTest.java b/plugins/org.eclipse.net4j.tests/src/org/eclipse/net4j/tests/ChannelTest.java
index c83e7ea536..4b7b75dc43 100644
--- a/plugins/org.eclipse.net4j.tests/src/org/eclipse/net4j/tests/ChannelTest.java
+++ b/plugins/org.eclipse.net4j.tests/src/org/eclipse/net4j/tests/ChannelTest.java
@@ -107,7 +107,7 @@ public abstract class ChannelTest extends AbstractProtocolTest
byte[] data = TinyData.getBytes();
byte[] result = new ArrayRequest(protocol, data).send();
- assertTrue(Arrays.equals(data, result));
+ assertEquals(true, Arrays.equals(data, result));
protocol.close();
assertInactive(protocol);
@@ -172,7 +172,7 @@ public abstract class ChannelTest extends AbstractProtocolTest
byte[] data = TinyData.getBytes();
byte[] result = new ArrayRequest(protocol, data).send();
- assertTrue(Arrays.equals(data, result));
+ assertEquals(true, Arrays.equals(data, result));
heartBeat();
protocol.close();
@@ -208,7 +208,7 @@ public abstract class ChannelTest extends AbstractProtocolTest
{
byte[] data = TinyData.getBytes();
byte[] result = new ArrayRequest(protocol, data).send();
- assertTrue(Arrays.equals(data, result));
+ assertEquals(true, Arrays.equals(data, result));
heartBeat();
ConcurrencyUtil.sleep(10L);
diff --git a/plugins/org.eclipse.net4j.tests/src/org/eclipse/net4j/tests/Performance.java b/plugins/org.eclipse.net4j.tests/src/org/eclipse/net4j/tests/Performance.java
index 6b3a4572b4..184827da56 100644
--- a/plugins/org.eclipse.net4j.tests/src/org/eclipse/net4j/tests/Performance.java
+++ b/plugins/org.eclipse.net4j.tests/src/org/eclipse/net4j/tests/Performance.java
@@ -1,5 +1,7 @@
package org.eclipse.net4j.tests;
+import org.eclipse.net4j.util.io.IOUtil;
+
import java.io.IOException;
import java.net.InetAddress;
import java.net.InetSocketAddress;
@@ -95,7 +97,7 @@ public class Performance
}
catch (IOException ex)
{
- ex.printStackTrace();
+ IOUtil.print(ex);
latch.countDown();
}
}
diff --git a/plugins/org.eclipse.net4j.tests/src/org/eclipse/net4j/tests/SignalTest.java b/plugins/org.eclipse.net4j.tests/src/org/eclipse/net4j/tests/SignalTest.java
index 6b2a36bf53..9607845ac6 100644
--- a/plugins/org.eclipse.net4j.tests/src/org/eclipse/net4j/tests/SignalTest.java
+++ b/plugins/org.eclipse.net4j.tests/src/org/eclipse/net4j/tests/SignalTest.java
@@ -60,7 +60,7 @@ public class SignalTest extends AbstractProtocolTest
protocol = new TestSignalProtocol(connector);
byte[] data = TinyData.getBytes();
byte[] result = new ArrayRequest(protocol, data).send();
- assertTrue(Arrays.equals(data, result));
+ assertEquals(true, Arrays.equals(data, result));
}
finally
{
diff --git a/plugins/org.eclipse.net4j.tests/src/org/eclipse/net4j/tests/TCPConnectorTest.java b/plugins/org.eclipse.net4j.tests/src/org/eclipse/net4j/tests/TCPConnectorTest.java
index 4a7cba1bb3..1485350e34 100644
--- a/plugins/org.eclipse.net4j.tests/src/org/eclipse/net4j/tests/TCPConnectorTest.java
+++ b/plugins/org.eclipse.net4j.tests/src/org/eclipse/net4j/tests/TCPConnectorTest.java
@@ -298,7 +298,7 @@ public class TCPConnectorTest extends AbstractOMTest
catch (ConnectorException ex)
{
OM.LOG.info("Expected ConnectorException:", ex);
- assertTrue(ex.getCause() instanceof NegotiationException);
+ assertEquals(true, ex.getCause() instanceof NegotiationException);
}
}
@@ -360,7 +360,7 @@ public class TCPConnectorTest extends AbstractOMTest
catch (ConnectorException ex)
{
OM.LOG.info("Expected ConnectorException:", ex);
- assertTrue(ex.getCause() instanceof NegotiationException);
+ assertEquals(true, ex.getCause() instanceof NegotiationException);
}
}
}
diff --git a/plugins/org.eclipse.net4j.tests/src/org/eclipse/net4j/tests/TransportTest.java b/plugins/org.eclipse.net4j.tests/src/org/eclipse/net4j/tests/TransportTest.java
index 6e22477f4b..24e4a308e4 100644
--- a/plugins/org.eclipse.net4j.tests/src/org/eclipse/net4j/tests/TransportTest.java
+++ b/plugins/org.eclipse.net4j.tests/src/org/eclipse/net4j/tests/TransportTest.java
@@ -21,6 +21,7 @@ import org.eclipse.net4j.util.container.IContainerDelta;
import org.eclipse.net4j.util.container.IContainerEvent;
import org.eclipse.net4j.util.event.IEvent;
import org.eclipse.net4j.util.event.IListener;
+import org.eclipse.net4j.util.io.IOUtil;
import java.io.BufferedReader;
import java.io.DataInputStream;
@@ -88,7 +89,7 @@ public abstract class TransportTest extends AbstractProtocolTest
sleep(50);
}
- assertTrue(counter.await(2, TimeUnit.SECONDS));
+ assertEquals(true, counter.await(2, TimeUnit.SECONDS));
}
public void testStreaming() throws Exception
@@ -124,7 +125,7 @@ public abstract class TransportTest extends AbstractProtocolTest
});
IChannel channel = getConnector().openChannel();
- assertTrue(counter.await(2, TimeUnit.SECONDS));
+ assertEquals(true, counter.await(2, TimeUnit.SECONDS));
assertNotNull(inputStream[0]);
ChannelOutputStream outputStream = new ChannelOutputStream(channel);
@@ -146,7 +147,7 @@ public abstract class TransportTest extends AbstractProtocolTest
}
catch (RuntimeException ex)
{
- ex.printStackTrace();
+ IOUtil.print(ex);
}
}
@@ -186,7 +187,7 @@ public abstract class TransportTest extends AbstractProtocolTest
});
IChannel channel = getConnector().openChannel();
- assertTrue(counter.await(2, TimeUnit.SECONDS));
+ assertEquals(true, counter.await(2, TimeUnit.SECONDS));
assertNotNull(inputStream[0]);
ChannelOutputStream outputStream = new ChannelOutputStream(channel);
@@ -215,7 +216,7 @@ public abstract class TransportTest extends AbstractProtocolTest
}
catch (RuntimeException ex)
{
- ex.printStackTrace();
+ IOUtil.print(ex);
}
}
@@ -252,7 +253,7 @@ public abstract class TransportTest extends AbstractProtocolTest
});
final IChannel channel = getConnector().openChannel();
- assertTrue(counter.await(2, TimeUnit.SECONDS));
+ assertEquals(true, counter.await(2, TimeUnit.SECONDS));
assertNotNull(inputStream[0]);
new Thread()
@@ -277,7 +278,7 @@ public abstract class TransportTest extends AbstractProtocolTest
}
catch (IOException ex)
{
- ex.printStackTrace();
+ IOUtil.print(ex);
fail(ex.getLocalizedMessage());
}
}
@@ -297,7 +298,7 @@ public abstract class TransportTest extends AbstractProtocolTest
}
catch (RuntimeException ex)
{
- ex.printStackTrace();
+ IOUtil.print(ex);
}
}
@@ -334,7 +335,7 @@ public abstract class TransportTest extends AbstractProtocolTest
});
IChannel channel = getConnector().openChannel();
- assertTrue(counter.await(2, TimeUnit.SECONDS));
+ assertEquals(true, counter.await(2, TimeUnit.SECONDS));
ChannelOutputStream outputStream = new ChannelOutputStream(channel);
DataOutputStream dataOutput = new DataOutputStream(outputStream);
diff --git a/plugins/org.eclipse.net4j.tests/src/org/eclipse/net4j/tests/bugzilla/Bugzilla241463_Test.java b/plugins/org.eclipse.net4j.tests/src/org/eclipse/net4j/tests/bugzilla/Bugzilla241463_Test.java
index 63d1080bbf..ac71a86745 100644
--- a/plugins/org.eclipse.net4j.tests/src/org/eclipse/net4j/tests/bugzilla/Bugzilla241463_Test.java
+++ b/plugins/org.eclipse.net4j.tests/src/org/eclipse/net4j/tests/bugzilla/Bugzilla241463_Test.java
@@ -26,6 +26,7 @@ import org.eclipse.net4j.util.ImplementationError;
import org.eclipse.net4j.util.concurrent.TimeoutRuntimeException;
import org.eclipse.net4j.util.container.IManagedContainer;
import org.eclipse.net4j.util.container.ManagedContainer;
+import org.eclipse.net4j.util.io.IOUtil;
import org.eclipse.net4j.util.security.RandomizerFactory;
import org.eclipse.internal.net4j.ExecutorServiceFactory;
@@ -76,13 +77,16 @@ public class Bugzilla241463_Test extends AbstractTransportTest
{
fail("TimeoutRuntimeException expected");
}
+
+ // Success
}
catch (TimeoutRuntimeException expected)
{
+ // Success
}
catch (Throwable wrongException)
{
- wrongException.printStackTrace();
+ IOUtil.print(wrongException);
fail("TimeoutRuntimeException expected");
}
}
diff --git a/plugins/org.eclipse.net4j.tests/src/org/eclipse/net4j/util/tests/ExtendedIOTest.java b/plugins/org.eclipse.net4j.tests/src/org/eclipse/net4j/util/tests/ExtendedIOTest.java
index f48fad416c..2f303a8c47 100644
--- a/plugins/org.eclipse.net4j.tests/src/org/eclipse/net4j/util/tests/ExtendedIOTest.java
+++ b/plugins/org.eclipse.net4j.tests/src/org/eclipse/net4j/util/tests/ExtendedIOTest.java
@@ -50,7 +50,7 @@ public class ExtendedIOTest extends AbstractOMTest
ByteArrayInputStream bais = new ByteArrayInputStream(baos.toByteArray());
ExtendedDataInputStream edis = new ExtendedDataInputStream(bais);
byte[] result = (byte[])edis.readObject();
- assertTrue(Arrays.equals(byteArray, result));
+ assertEquals(true, Arrays.equals(byteArray, result));
}
public void testObject2() throws Exception
@@ -64,7 +64,7 @@ public class ExtendedIOTest extends AbstractOMTest
ByteArrayInputStream bais = new ByteArrayInputStream(baos.toByteArray());
ExtendedDataInputStream edis = new ExtendedDataInputStream(bais);
byte[] result = (byte[])edis.readObject();
- assertTrue(Arrays.equals(byteArray, result));
+ assertEquals(true, Arrays.equals(byteArray, result));
}
public void testByteArray1() throws Exception
@@ -78,7 +78,7 @@ public class ExtendedIOTest extends AbstractOMTest
ByteArrayInputStream bais = new ByteArrayInputStream(baos.toByteArray());
ExtendedDataInputStream edis = new ExtendedDataInputStream(bais);
byte[] result = edis.readByteArray();
- assertTrue(Arrays.equals(byteArray, result));
+ assertEquals(true, Arrays.equals(byteArray, result));
}
public void testByteArray2() throws Exception
@@ -92,7 +92,7 @@ public class ExtendedIOTest extends AbstractOMTest
ByteArrayInputStream bais = new ByteArrayInputStream(baos.toByteArray());
ExtendedDataInputStream edis = new ExtendedDataInputStream(bais);
byte[] result = edis.readByteArray();
- assertTrue(Arrays.equals(byteArray, result));
+ assertEquals(true, Arrays.equals(byteArray, result));
}
private byte[] createByteArray1() throws IOException
diff --git a/plugins/org.eclipse.net4j.tests/src/org/eclipse/net4j/util/tests/ReferenceValueMapTest.java b/plugins/org.eclipse.net4j.tests/src/org/eclipse/net4j/util/tests/ReferenceValueMapTest.java
index 9dbb7419ad..3c13f556a0 100644
--- a/plugins/org.eclipse.net4j.tests/src/org/eclipse/net4j/util/tests/ReferenceValueMapTest.java
+++ b/plugins/org.eclipse.net4j.tests/src/org/eclipse/net4j/util/tests/ReferenceValueMapTest.java
@@ -25,7 +25,7 @@ public class ReferenceValueMapTest extends AbstractOMTest
map.put("SIMON", new Object());
System.gc();
map.put("SIMON", new Object());
- assertTrue(map.size() >= 0);
+ assertEquals(true, map.size() >= 0);
}
}
@@ -37,7 +37,7 @@ public class ReferenceValueMapTest extends AbstractOMTest
map.put("SIMON", new Object());
System.gc();
map.put("SIMON2", new Object());
- assertTrue(map.size() >= 1);
+ assertEquals(true, map.size() >= 1);
}
}
}
diff --git a/plugins/org.eclipse.net4j.tests/src/org/eclipse/net4j/util/tests/SynchronizingCorrelatorTest.java b/plugins/org.eclipse.net4j.tests/src/org/eclipse/net4j/util/tests/SynchronizingCorrelatorTest.java
index 47054dcec6..de85c293ae 100644
--- a/plugins/org.eclipse.net4j.tests/src/org/eclipse/net4j/util/tests/SynchronizingCorrelatorTest.java
+++ b/plugins/org.eclipse.net4j.tests/src/org/eclipse/net4j/util/tests/SynchronizingCorrelatorTest.java
@@ -69,7 +69,7 @@ public class SynchronizingCorrelatorTest extends AbstractOMTest
boolean consumed = correlator.put("eike", true, 1000);
msg("Consumed: " + consumed);
- assertTrue(consumed);
+ assertEquals(true, consumed);
consumer.join(1000);
assertEquals(Boolean.TRUE, result[0]);
@@ -121,7 +121,7 @@ public class SynchronizingCorrelatorTest extends AbstractOMTest
final SynchronizingCorrelator<String, Boolean> correlator = new SynchronizingCorrelator<String, Boolean>();
boolean consumed = correlator.put("eike", true, 50);
msg("Consumed: " + consumed);
- assertFalse(consumed);
+ assertEquals(false, consumed);
final Thread consumer = new Thread()
{
diff --git a/plugins/org.eclipse.net4j.tests/src/org/eclipse/net4j/util/tests/UTFTest.java b/plugins/org.eclipse.net4j.tests/src/org/eclipse/net4j/util/tests/UTFTest.java
index fd0375e551..507f2ce354 100644
--- a/plugins/org.eclipse.net4j.tests/src/org/eclipse/net4j/util/tests/UTFTest.java
+++ b/plugins/org.eclipse.net4j.tests/src/org/eclipse/net4j/util/tests/UTFTest.java
@@ -33,7 +33,7 @@ public class UTFTest extends AbstractOMTest
}
String str = builder.toString();
- assertTrue(str.length() > UNSIGNED_SHORT_MAX);
+ assertEquals(true, str.length() > UNSIGNED_SHORT_MAX);
ByteArrayOutputStream baos = new ByteArrayOutputStream();
DataOutputStream dos = new DataOutputStream(baos);
diff --git a/plugins/org.eclipse.net4j.util/src/org/eclipse/net4j/util/concurrent/RWLockManager.java b/plugins/org.eclipse.net4j.util/src/org/eclipse/net4j/util/concurrent/RWLockManager.java
new file mode 100644
index 0000000000..5dbe470f80
--- /dev/null
+++ b/plugins/org.eclipse.net4j.util/src/org/eclipse/net4j/util/concurrent/RWLockManager.java
@@ -0,0 +1,567 @@
+/***************************************************************************
+ * Copyright (c) 2004 - 2008 Eike Stepper, Germany.
+ * 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:
+ * Simon McDuff - initial API and implementation
+ **************************************************************************/
+package org.eclipse.net4j.util.concurrent;
+
+import org.eclipse.net4j.util.collection.HashBag;
+import org.eclipse.net4j.util.lifecycle.Lifecycle;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.Map.Entry;
+
+/**
+ * Support Multiple reads/no write and upgrade lock from read to write. Many context could request
+ * {@link LockType#WRITE write} lock at the same time. It will privileges first context that has already a
+ * {@link LockType#READ read} lock. If no one has any read lock, it's "first come first serve".
+ *
+ * @author Simon McDuff
+ * @since 2.0
+ */
+public class RWLockManager<K, V> extends Lifecycle
+{
+ public static final int WAIT = 0;
+
+ public static final int NO_WAIT = 1;
+
+ private LockStrategy<K, V> writeLockStrategy = new LockStrategy<K, V>()
+ {
+ public boolean canObtainLock(LockEntry<K, V> entry, V context)
+ {
+ return entry.canObtainWriteLock(context);
+ }
+
+ public LockEntry<K, V> lock(LockEntry<K, V> entry, V context)
+ {
+ return entry.writeLock(context);
+ }
+
+ public LockEntry<K, V> unlock(LockEntry<K, V> entry, V context)
+ {
+ return entry.writeUnlock(context);
+ }
+
+ public boolean isLocked(LockEntry<K, V> entry, V context)
+ {
+ return entry.isWriteLock(context);
+ }
+ };
+
+ private LockStrategy<K, V> readLockStrategy = new LockStrategy<K, V>()
+ {
+ public boolean canObtainLock(LockEntry<K, V> entry, V context)
+ {
+ return entry.canObtainReadLock(context);
+ }
+
+ public LockEntry<K, V> lock(LockEntry<K, V> entry, V context)
+ {
+ return entry.readLock(context);
+ }
+
+ public LockEntry<K, V> unlock(LockEntry<K, V> entry, V context)
+ {
+ return entry.readUnlock(context);
+ }
+
+ public boolean isLocked(LockEntry<K, V> entry, V context)
+ {
+ return entry.isReadLock(context);
+ }
+ };
+
+ private Map<K, LockEntry<K, V>> lockEntries = new HashMap<K, LockEntry<K, V>>();
+
+ private Object lockChanged = new Object();
+
+ public void lock(RWLockManager.LockType type, V context, Collection<K> objectsToLock, long timeout)
+ throws InterruptedException
+ {
+ lock(getLockingStrategy(type), context, objectsToLock, timeout);
+ }
+
+ public void lock(RWLockManager.LockType type, V context, K objectToLock, long timeout) throws InterruptedException
+ {
+ lock(type, context, Collections.singletonList(objectToLock), timeout);
+ }
+
+ /**
+ * Attempts to release for a given locktype, context and objects.
+ * <p>
+ * .
+ *
+ * @throws IllegalMonitorStateException
+ * Unlocking objects without lock.
+ */
+ public void unlock(RWLockManager.LockType type, V context, Collection<K> objectToLock)
+ {
+ unlock(getLockingStrategy(type), context, objectToLock);
+ }
+
+ /**
+ * Attempts to release all locks(read and write) for a given context.
+ */
+ public void unlock(V context)
+ {
+ synchronized (lockChanged)
+ {
+ List<LockEntry<K, V>> lockEntrysToRemove = new ArrayList<LockEntry<K, V>>();
+ List<LockEntry<K, V>> lockEntrysToAdd = new ArrayList<LockEntry<K, V>>();
+
+ for (Entry<K, LockEntry<K, V>> entry : lockEntries.entrySet())
+ {
+ LockEntry<K, V> newEntry = entry.getValue().clearLock(context);
+ if (newEntry == null)
+ {
+ lockEntrysToRemove.add(entry.getValue());
+ }
+ else if (newEntry != entry)
+ {
+ lockEntrysToAdd.add(newEntry);
+ }
+ }
+
+ for (LockEntry<K, V> lockEntry : lockEntrysToRemove)
+ {
+ lockEntries.remove(lockEntry.getKey());
+ }
+
+ for (LockEntry<K, V> lockEntry : lockEntrysToAdd)
+ {
+ lockEntries.put(lockEntry.getKey(), lockEntry);
+ }
+
+ lockChanged.notifyAll();
+ }
+ }
+
+ public boolean hasLock(RWLockManager.LockType type, V context, K objectToLock)
+ {
+ return hasLock(getLockingStrategy(type), context, objectToLock);
+ }
+
+ private LockStrategy<K, V> getLockingStrategy(RWLockManager.LockType type)
+ {
+ if (type == RWLockManager.LockType.READ)
+ {
+ return readLockStrategy;
+ }
+
+ if (type == RWLockManager.LockType.WRITE)
+ {
+ return writeLockStrategy;
+ }
+
+ throw new IllegalArgumentException(type.toString());
+ }
+
+ /**
+ * Attempts to release this lock.
+ * <p>
+ * If the number of context is now zero then the lock is made available for write lock attempts.
+ *
+ * @throws IllegalMonitorStateException
+ * Unlocking object not locked.
+ */
+ private void unlock(LockStrategy<K, V> lockingStrategy, V context, Collection<K> objectsToLock)
+ {
+ synchronized (lockChanged)
+ {
+ List<LockEntry<K, V>> lockEntrysToRemove = new ArrayList<LockEntry<K, V>>();
+ List<LockEntry<K, V>> lockEntrysToAdd = new ArrayList<LockEntry<K, V>>();
+ for (K objectToLock : objectsToLock)
+ {
+ LockEntry<K, V> entry = lockEntries.get(objectToLock);
+
+ if (entry == null)
+ {
+ throw new IllegalMonitorStateException();
+ }
+
+ LockEntry<K, V> newEntry = lockingStrategy.unlock(entry, context);
+
+ if (newEntry == null)
+ {
+ lockEntrysToRemove.add(entry);
+ }
+ else if (newEntry != entry)
+ {
+ lockEntrysToAdd.add(newEntry);
+ }
+ }
+
+ for (LockEntry<K, V> lockEntry : lockEntrysToRemove)
+ {
+ lockEntries.remove(lockEntry.getKey());
+ }
+
+ for (LockEntry<K, V> lockEntry : lockEntrysToAdd)
+ {
+ lockEntries.put(lockEntry.getKey(), lockEntry);
+ }
+
+ lockChanged.notifyAll();
+ }
+ }
+
+ private boolean hasLock(LockStrategy<K, V> lockingStrategy, V context, K objectToLock)
+ {
+ LockEntry<K, V> entry = getLockEntry(objectToLock);
+ return entry != null && lockingStrategy.isLocked(entry, context);
+ }
+
+ private void lock(LockStrategy<K, V> lockStrategy, V context, Collection<K> objectToLocks, long timeout)
+ throws InterruptedException
+ {
+ long startTime = System.currentTimeMillis();
+ while (true)
+ {
+ synchronized (lockChanged)
+ {
+ K conflict = obtainLock(lockStrategy, context, objectToLocks);
+ if (conflict == null)
+ {
+ lockChanged.notifyAll();
+ return;
+ }
+
+ long elapsedTime = System.currentTimeMillis() - startTime;
+ if (timeout != WAIT && elapsedTime > timeout)
+ {
+ throw new TimeoutRuntimeException("Conflict with " + conflict);
+ }
+
+ if (timeout == WAIT)
+ {
+ lockChanged.wait();
+ }
+ else
+ {
+ lockChanged.wait(Math.max(1, timeout - elapsedTime));
+ }
+ }
+ }
+ }
+
+ private K obtainLock(LockStrategy<K, V> lockingStrategy, V context, Collection<K> objectsToLock)
+ {
+ List<LockEntry<K, V>> lockEntrys = new ArrayList<LockEntry<K, V>>();
+ for (K objectToLock : objectsToLock)
+ {
+ LockEntry<K, V> entry = lockEntries.get(objectToLock);
+ if (entry == null)
+ {
+ entry = new NoLockEntry<K, V>(objectToLock);
+ }
+
+ if (lockingStrategy.canObtainLock(entry, context))
+ {
+ lockEntrys.add(entry);
+ }
+ else
+ {
+ return objectToLock;
+ }
+ }
+
+ for (LockEntry<K, V> lockEntry : lockEntrys)
+ {
+ lockEntries.put(lockEntry.getKey(), lockingStrategy.lock(lockEntry, context));
+ }
+
+ return null;
+ }
+
+ private LockEntry<K, V> getLockEntry(K objectToLock)
+ {
+ synchronized (lockChanged)
+ {
+ return lockEntries.get(objectToLock);
+ }
+ }
+
+ /**
+ * @author Simon McDuff
+ */
+ private interface LockStrategy<K, V>
+ {
+ public boolean isLocked(LockEntry<K, V> entry, V context);
+
+ public boolean canObtainLock(LockEntry<K, V> entry, V context);
+
+ public LockEntry<K, V> lock(LockEntry<K, V> entry, V context);
+
+ public LockEntry<K, V> unlock(LockEntry<K, V> entry, V context);
+ }
+
+ /**
+ * @author Simon McDuff
+ */
+ private interface LockEntry<K, V>
+ {
+ public K getKey();
+
+ public boolean isReadLock(V context);
+
+ public boolean isWriteLock(V context);
+
+ public boolean canObtainReadLock(V context);
+
+ public boolean canObtainWriteLock(V context);
+
+ public LockEntry<K, V> readLock(V context);
+
+ public LockEntry<K, V> writeLock(V context);
+
+ public LockEntry<K, V> readUnlock(V context);
+
+ public LockEntry<K, V> writeUnlock(V context);
+
+ public LockEntry<K, V> clearLock(V context);
+ }
+
+ /**
+ * @author Simon McDuff
+ */
+ private static final class ReadLockEntry<K, V> implements LockEntry<K, V>
+ {
+ private K id;
+
+ private Set<V> contexts = new HashBag<V>();
+
+ public ReadLockEntry(K objectToLock, V context)
+ {
+ this.id = objectToLock;
+ contexts.add(context);
+ }
+
+ public boolean canObtainReadLock(V context)
+ {
+ return true;
+ }
+
+ public boolean canObtainWriteLock(V context)
+ {
+ return contexts.size() == 1 && contexts.contains(context);
+ }
+
+ public LockEntry<K, V> readLock(V context)
+ {
+ contexts.add(context);
+ return this;
+ }
+
+ public LockEntry<K, V> writeLock(V context)
+ {
+ return new WriteLockEntry<K, V>(id, context, this);
+ }
+
+ public K getKey()
+ {
+ return id;
+ }
+
+ public LockEntry<K, V> readUnlock(V context)
+ {
+ contexts.remove(context);
+ return contexts.isEmpty() ? null : this;
+ }
+
+ public LockEntry<K, V> writeUnlock(V context)
+ {
+ throw new IllegalMonitorStateException();
+ }
+
+ public boolean isReadLock(V context)
+ {
+ return contexts.contains(context);
+ }
+
+ public boolean isWriteLock(V context)
+ {
+ return false;
+ }
+
+ public LockEntry<K, V> clearLock(V context)
+ {
+ return null;
+ }
+ }
+
+ /**
+ * @author Simon McDuff
+ */
+ private static final class WriteLockEntry<K, V> implements LockEntry<K, V>
+ {
+ private K objectToLock;
+
+ private V context;
+
+ private int count;
+
+ private ReadLockEntry<K, V> readLock;
+
+ public WriteLockEntry(K objectToLock, V context, ReadLockEntry<K, V> readLock)
+ {
+ this.objectToLock = objectToLock;
+ this.context = context;
+ this.readLock = readLock;
+ this.count = 1;
+ }
+
+ private ReadLockEntry<K, V> getReadLock()
+ {
+ if (readLock == null)
+ {
+ readLock = new ReadLockEntry<K, V>(objectToLock, context);
+ }
+
+ return readLock;
+ }
+
+ public boolean canObtainWriteLock(V context)
+ {
+ return context == this.context;
+ }
+
+ public boolean canObtainReadLock(V context)
+ {
+ return context == this.context;
+ }
+
+ public LockEntry<K, V> readLock(V context)
+ {
+ getReadLock().readLock(context);
+ return this;
+ }
+
+ public LockEntry<K, V> writeLock(V context)
+ {
+ count++;
+ return this;
+ }
+
+ public K getKey()
+ {
+ return objectToLock;
+ }
+
+ public LockEntry<K, V> readUnlock(V context)
+ {
+ if (readLock != null)
+ {
+ if (getReadLock().readUnlock(context) == null)
+ {
+ readLock = null;
+ }
+
+ return this;
+ }
+
+ throw new IllegalMonitorStateException();
+ }
+
+ public LockEntry<K, V> writeUnlock(V context)
+ {
+ return --count <= 0 ? readLock : this;
+ }
+
+ public boolean isReadLock(V context)
+ {
+ return readLock != null ? readLock.isReadLock(context) : false;
+ }
+
+ public boolean isWriteLock(V context)
+ {
+ return context == this.context;
+ }
+
+ public LockEntry<K, V> clearLock(V context)
+ {
+ return null;
+ }
+ }
+
+ /**
+ * @author Simon McDuff
+ */
+ private static final class NoLockEntry<K, V> implements LockEntry<K, V>
+ {
+ private K objectToLock;
+
+ public NoLockEntry(K objectToLock)
+ {
+ this.objectToLock = objectToLock;
+ }
+
+ public boolean canObtainWriteLock(V context)
+ {
+ return true;
+ }
+
+ public boolean canObtainReadLock(V context)
+ {
+ return true;
+ }
+
+ public LockEntry<K, V> readLock(V context)
+ {
+ return new ReadLockEntry<K, V>(objectToLock, context);
+ }
+
+ public LockEntry<K, V> writeLock(V context)
+ {
+ return new WriteLockEntry<K, V>(objectToLock, context, null);
+ }
+
+ public K getKey()
+ {
+ return objectToLock;
+ }
+
+ public LockEntry<K, V> readUnlock(V context)
+ {
+ throw new UnsupportedOperationException();
+ }
+
+ public LockEntry<K, V> writeUnlock(V context)
+ {
+ throw new UnsupportedOperationException();
+ }
+
+ public boolean isReadLock(V context)
+ {
+ throw new UnsupportedOperationException();
+ }
+
+ public boolean isWriteLock(V context)
+ {
+ throw new UnsupportedOperationException();
+ }
+
+ public LockEntry<K, V> clearLock(V context)
+ {
+ throw new UnsupportedOperationException();
+ }
+ }
+
+ /**
+ * @author Simon McDuff
+ */
+ public static enum LockType
+ {
+ WRITE, READ
+ }
+}

Back to the top