[infinispan-commits] Infinispan SVN: r2386 - in trunk: cachestore/remote/src/test/java/org/infinispan/loaders/remote and 40 other directories.
infinispan-commits at lists.jboss.org
infinispan-commits at lists.jboss.org
Wed Sep 15 15:09:41 EDT 2010
Author: mircea.markus
Date: 2010-09-15 15:09:38 -0400 (Wed, 15 Sep 2010)
New Revision: 2386
Added:
trunk/core/src/main/java/org/infinispan/transaction/xa/DldGlobalTransaction.java
trunk/core/src/test/java/org/infinispan/lock/EagerLockingSingleLockTest.java
trunk/core/src/test/java/org/infinispan/tx/dld/
trunk/core/src/test/java/org/infinispan/tx/dld/AsyncDeadlockDetectionTest.java
trunk/core/src/test/java/org/infinispan/tx/dld/BaseDldEagerLockingTest.java
trunk/core/src/test/java/org/infinispan/tx/dld/BaseDldLazyLockingTest.java
trunk/core/src/test/java/org/infinispan/tx/dld/BaseDldTest.java
trunk/core/src/test/java/org/infinispan/tx/dld/ControlledRpcManager.java
trunk/core/src/test/java/org/infinispan/tx/dld/DldEagerLockingDistributedTest.java
trunk/core/src/test/java/org/infinispan/tx/dld/DldEagerLockingReplicationTest.java
trunk/core/src/test/java/org/infinispan/tx/dld/DldLazyLockingDistributionTest.java
trunk/core/src/test/java/org/infinispan/tx/dld/DldLazyLockingReplicationTest.java
trunk/core/src/test/java/org/infinispan/tx/dld/LocalDeadlockDetectionTest.java
trunk/core/src/test/java/org/infinispan/tx/exception/
trunk/core/src/test/java/org/infinispan/tx/exception/CustomInterceptorException.java
trunk/core/src/test/java/org/infinispan/tx/exception/ExplicitLockingAndTimeoutTest.java
trunk/core/src/test/java/org/infinispan/tx/exception/ReplicationExceptionTest.java
trunk/core/src/test/java/org/infinispan/tx/exception/TxAndInvalidationTimeoutTest.java
trunk/core/src/test/java/org/infinispan/tx/exception/TxAndRemoteTimeoutExceptionTest.java
trunk/core/src/test/java/org/infinispan/tx/exception/TxAndTimeoutExceptionTest.java
trunk/core/src/test/java/org/infinispan/tx/timeout/
Removed:
trunk/core/src/main/java/org/infinispan/factories/context/
trunk/core/src/main/java/org/infinispan/transaction/xa/DeadlockDetectingGlobalTransaction.java
trunk/core/src/test/java/org/infinispan/distribution/DeadlockDetectionDistributionTest.java
trunk/core/src/test/java/org/infinispan/lock/EagerLockingDisabledTest.java
trunk/core/src/test/java/org/infinispan/tx/AsyncDeadlockDetectionTest.java
trunk/core/src/test/java/org/infinispan/tx/LocalDeadlockDetectionTest.java
trunk/core/src/test/java/org/infinispan/tx/ReplDeadlockDetectionTest.java
trunk/core/src/test/java/org/infinispan/tx/dld/AsyncDeadlockDetectionTest.java
trunk/core/src/test/java/org/infinispan/tx/dld/BaseDldEagerLockingTest.java
trunk/core/src/test/java/org/infinispan/tx/dld/BaseDldLazyLockingTest.java
trunk/core/src/test/java/org/infinispan/tx/dld/BaseDldTest.java
trunk/core/src/test/java/org/infinispan/tx/dld/ControlledRpcManager.java
trunk/core/src/test/java/org/infinispan/tx/dld/DldEagerLockingDistributedTest.java
trunk/core/src/test/java/org/infinispan/tx/dld/DldEagerLockingReplicationTest.java
trunk/core/src/test/java/org/infinispan/tx/dld/DldLazyLockingDistributionTest.java
trunk/core/src/test/java/org/infinispan/tx/dld/DldLazyLockingReplicationTest.java
trunk/core/src/test/java/org/infinispan/tx/dld/LocalDeadlockDetectionTest.java
trunk/core/src/test/java/org/infinispan/tx/exception/CustomInterceptorException.java
trunk/core/src/test/java/org/infinispan/tx/exception/ExplicitLockingAndTimeoutTest.java
trunk/core/src/test/java/org/infinispan/tx/exception/ReplicationExceptionTest.java
trunk/core/src/test/java/org/infinispan/tx/exception/TxAndInvalidationTimeoutTest.java
trunk/core/src/test/java/org/infinispan/tx/exception/TxAndRemoteTimeoutExceptionTest.java
trunk/core/src/test/java/org/infinispan/tx/exception/TxAndTimeoutExceptionTest.java
trunk/query/src/main/java/org/infinispan/query/config/
trunk/server/websocket/src/main/java/org/infinispan/websocket/
Modified:
trunk/cachestore/jdbc/src/main/java/org/infinispan/loaders/jdbc/stringbased/JdbcStringBasedCacheStore.java
trunk/cachestore/remote/src/test/java/org/infinispan/loaders/remote/RemoteCacheStoreFunctionalTest.java
trunk/cachestore/remote/src/test/java/org/infinispan/loaders/remote/RemoteCacheStoreTest.java
trunk/core/
trunk/core/src/main/java/org/infinispan/CacheDelegate.java
trunk/core/src/main/java/org/infinispan/CacheException.java
trunk/core/src/main/java/org/infinispan/affinity/KeyAffinityServiceImpl.java
trunk/core/src/main/java/org/infinispan/commands/CommandsFactory.java
trunk/core/src/main/java/org/infinispan/commands/CommandsFactoryImpl.java
trunk/core/src/main/java/org/infinispan/commands/RemoteCommandsFactory.java
trunk/core/src/main/java/org/infinispan/commands/control/LockControlCommand.java
trunk/core/src/main/java/org/infinispan/commands/control/RehashControlCommand.java
trunk/core/src/main/java/org/infinispan/commands/tx/AbstractTransactionBoundaryCommand.java
trunk/core/src/main/java/org/infinispan/commands/tx/PrepareCommand.java
trunk/core/src/main/java/org/infinispan/commands/tx/TransactionBoundaryCommand.java
trunk/core/src/main/java/org/infinispan/config/Configuration.java
trunk/core/src/main/java/org/infinispan/config/ConfigurationValidatingVisitor.java
trunk/core/src/main/java/org/infinispan/context/InvocationContext.java
trunk/core/src/main/java/org/infinispan/context/impl/AbstractInvocationContext.java
trunk/core/src/main/java/org/infinispan/context/impl/AbstractTxInvocationContext.java
trunk/core/src/main/java/org/infinispan/context/impl/LocalTxInvocationContext.java
trunk/core/src/main/java/org/infinispan/context/impl/NonTxInvocationContext.java
trunk/core/src/main/java/org/infinispan/context/impl/RemoteTxInvocationContext.java
trunk/core/src/main/java/org/infinispan/context/impl/TxInvocationContext.java
trunk/core/src/main/java/org/infinispan/distribution/DistributionManager.java
trunk/core/src/main/java/org/infinispan/distribution/DistributionManagerImpl.java
trunk/core/src/main/java/org/infinispan/interceptors/CallInterceptor.java
trunk/core/src/main/java/org/infinispan/interceptors/DeadlockDetectingInterceptor.java
trunk/core/src/main/java/org/infinispan/interceptors/DistributionInterceptor.java
trunk/core/src/main/java/org/infinispan/interceptors/ImplicitEagerLockingInterceptor.java
trunk/core/src/main/java/org/infinispan/interceptors/InvalidationInterceptor.java
trunk/core/src/main/java/org/infinispan/interceptors/InvocationContextInterceptor.java
trunk/core/src/main/java/org/infinispan/interceptors/LockingInterceptor.java
trunk/core/src/main/java/org/infinispan/interceptors/TxInterceptor.java
trunk/core/src/main/java/org/infinispan/interceptors/base/BaseRpcInterceptor.java
trunk/core/src/main/java/org/infinispan/marshall/Ids.java
trunk/core/src/main/java/org/infinispan/marshall/jboss/ConstantObjectTable.java
trunk/core/src/main/java/org/infinispan/remoting/InboundInvocationHandlerImpl.java
trunk/core/src/main/java/org/infinispan/statetransfer/StateTransferManagerImpl.java
trunk/core/src/main/java/org/infinispan/transaction/xa/GlobalTransaction.java
trunk/core/src/main/java/org/infinispan/transaction/xa/GlobalTransactionFactory.java
trunk/core/src/main/java/org/infinispan/transaction/xa/RemoteTransaction.java
trunk/core/src/main/java/org/infinispan/transaction/xa/TransactionTable.java
trunk/core/src/main/java/org/infinispan/transaction/xa/TransactionXaAdapter.java
trunk/core/src/main/java/org/infinispan/util/concurrent/TimeoutException.java
trunk/core/src/main/java/org/infinispan/util/concurrent/locks/DeadlockDetectedException.java
trunk/core/src/main/java/org/infinispan/util/concurrent/locks/DeadlockDetectingLockManager.java
trunk/core/src/main/resources/config-samples/all.xml
trunk/core/src/test/java/org/infinispan/api/mvcc/LockTestBase.java
trunk/core/src/test/java/org/infinispan/config/parsing/XmlFileParsingTest.java
trunk/core/src/test/java/org/infinispan/loaders/dummy/DummyInMemoryCacheStore.java
trunk/core/src/test/java/org/infinispan/notifications/cachelistener/CacheNotifierTest.java
trunk/core/src/test/java/org/infinispan/statetransfer/StateTransferReplicationQueueTest.java
trunk/core/src/test/java/org/infinispan/test/AbstractInfinispanTest.java
trunk/core/src/test/java/org/infinispan/test/MultipleCacheManagersTest.java
trunk/core/src/test/java/org/infinispan/test/PerCacheExecutorThread.java
trunk/core/src/test/java/org/infinispan/test/TestingUtil.java
trunk/core/src/test/java/org/infinispan/test/fwk/TestCacheManagerFactory.java
trunk/core/src/test/java/org/infinispan/util/DeadlockDetectingLockManagerTest.java
trunk/core/src/test/resources/configs/named-cache-test.xml
trunk/core/src/test/resources/log4j.xml
trunk/lucene-directory/src/main/java/org/infinispan/lucene/readlocks/DistributedSegmentReadLocker.java
trunk/tree/
Log:
r2274 through r2385 from 4.2.x to trunk
Modified: trunk/cachestore/jdbc/src/main/java/org/infinispan/loaders/jdbc/stringbased/JdbcStringBasedCacheStore.java
===================================================================
--- trunk/cachestore/jdbc/src/main/java/org/infinispan/loaders/jdbc/stringbased/JdbcStringBasedCacheStore.java 2010-09-15 16:19:59 UTC (rev 2385)
+++ trunk/cachestore/jdbc/src/main/java/org/infinispan/loaders/jdbc/stringbased/JdbcStringBasedCacheStore.java 2010-09-15 19:09:38 UTC (rev 2386)
@@ -195,16 +195,16 @@
log.trace("Running sql '" + sql + "' on " + ed + ". Key string is '" + lockingKey + "'");
Connection connection = null;
PreparedStatement ps = null;
+ ByteBuffer byteBuffer = JdbcUtil.marshall(getMarshaller(), ed.toInternalCacheValue());
try {
connection = connectionFactory.getConnection();
ps = connection.prepareStatement(sql);
- ByteBuffer byteBuffer = JdbcUtil.marshall(getMarshaller(), ed.toInternalCacheValue());
ps.setBinaryStream(1, byteBuffer.getStream(), byteBuffer.getLength());
ps.setLong(2, ed.getExpiryTime());
ps.setString(3, lockingKey);
ps.executeUpdate();
} catch (SQLException ex) {
- logAndThrow(ex, "Error while storing string keys to database");
+ logAndThrow(ex, "Error while storing string key to database; key: '"+lockingKey+"', buffer size of value: " + byteBuffer.getLength() + " bytes");
} finally {
JdbcUtil.safeClose(ps);
connectionFactory.releaseConnection(connection);
Modified: trunk/cachestore/remote/src/test/java/org/infinispan/loaders/remote/RemoteCacheStoreFunctionalTest.java
===================================================================
--- trunk/cachestore/remote/src/test/java/org/infinispan/loaders/remote/RemoteCacheStoreFunctionalTest.java 2010-09-15 16:19:59 UTC (rev 2385)
+++ trunk/cachestore/remote/src/test/java/org/infinispan/loaders/remote/RemoteCacheStoreFunctionalTest.java 2010-09-15 19:09:38 UTC (rev 2386)
@@ -6,7 +6,10 @@
import org.infinispan.manager.CacheContainer;
import org.infinispan.manager.EmbeddedCacheManager;
import org.infinispan.server.hotrod.HotRodServer;
+import org.infinispan.test.TestingUtil;
import org.infinispan.test.fwk.TestCacheManagerFactory;
+import org.testng.annotations.AfterClass;
+import org.testng.annotations.AfterMethod;
import org.testng.annotations.AfterTest;
import org.testng.annotations.Test;
@@ -35,10 +38,10 @@
return remoteCacheStoreConfig;
}
- @AfterTest
+ @AfterMethod(alwaysRun = true)
public void tearDown() {
hrServer.stop();
- localCacheManager.stop();
+ TestingUtil.killCacheManagers(localCacheManager);
}
@Override
Modified: trunk/cachestore/remote/src/test/java/org/infinispan/loaders/remote/RemoteCacheStoreTest.java
===================================================================
--- trunk/cachestore/remote/src/test/java/org/infinispan/loaders/remote/RemoteCacheStoreTest.java 2010-09-15 16:19:59 UTC (rev 2385)
+++ trunk/cachestore/remote/src/test/java/org/infinispan/loaders/remote/RemoteCacheStoreTest.java 2010-09-15 19:09:38 UTC (rev 2386)
@@ -9,6 +9,7 @@
import org.infinispan.manager.EmbeddedCacheManager;
import org.infinispan.server.hotrod.HotRodServer;
import org.infinispan.test.fwk.TestCacheManagerFactory;
+import org.testng.annotations.AfterMethod;
import org.testng.annotations.AfterTest;
import org.testng.annotations.Test;
@@ -45,7 +46,7 @@
return remoteCacheStore;
}
- @AfterTest(alwaysRun = true)
+ @AfterMethod(alwaysRun = true)
public void tearDown() {
hrServer.stop();
localCacheManager.stop();
@@ -77,3 +78,5 @@
public void testLoadKeys() throws CacheLoaderException {
}
}
+
+
Property changes on: trunk/core
___________________________________________________________________
Name: svn:ignore
- target
.settings
eclipse-output
test-output
output
.classpath
.project
temp-testng-customsuite.xml
Infinispan-FileCacheStore
*.iml
*.log
+ target
.settings
eclipse-output
test-output
output
.classpath
.project
temp-testng-customsuite.xml
Infinispan-FileCacheStore
*.iml
*.log
PutObjectStoreDirHere
Modified: trunk/core/src/main/java/org/infinispan/CacheDelegate.java
===================================================================
--- trunk/core/src/main/java/org/infinispan/CacheDelegate.java 2010-09-15 16:19:59 UTC (rev 2385)
+++ trunk/core/src/main/java/org/infinispan/CacheDelegate.java 2010-09-15 19:09:38 UTC (rev 2386)
@@ -287,8 +287,6 @@
public void lock(K key) {
assertKeyNotNull(key);
- //this will be removed with https://jira.jboss.org/browse/ISPN-598
- ConfigurationValidatingVisitor.checkEagerLockingAndDld(config, true);
lock(Collections.singletonList(key));
}
Modified: trunk/core/src/main/java/org/infinispan/CacheException.java
===================================================================
--- trunk/core/src/main/java/org/infinispan/CacheException.java 2010-09-15 16:19:59 UTC (rev 2385)
+++ trunk/core/src/main/java/org/infinispan/CacheException.java 2010-09-15 19:09:38 UTC (rev 2386)
@@ -26,9 +26,13 @@
* <p/>
* Specific subclasses such as {@link org.infinispan.util.concurrent.TimeoutException} and {@link
* org.infinispan.config.ConfigurationException} have more specific uses.
+ * <p/>
+ * Transactions: if a CacheException (including any subclasses) is thrown for an operation on a JTA transaction, then
+ * the transaction is marked for rollback.
*
* @author <a href="mailto:bela at jboss.org">Bela Ban</a>
* @author <a href="mailto:manik at jboss.org">Manik Surtani</a>
+ * @author Mircea.Markus at jboss.com
* @since 4.0
*/
public class CacheException extends RuntimeException {
Modified: trunk/core/src/main/java/org/infinispan/affinity/KeyAffinityServiceImpl.java
===================================================================
--- trunk/core/src/main/java/org/infinispan/affinity/KeyAffinityServiceImpl.java 2010-09-15 16:19:59 UTC (rev 2385)
+++ trunk/core/src/main/java/org/infinispan/affinity/KeyAffinityServiceImpl.java 2010-09-15 19:09:38 UTC (rev 2386)
@@ -94,6 +94,8 @@
if (!started) {
throw new IllegalStateException("You have to start the service first!");
}
+ if (address == null)
+ throw new NullPointerException("Null address not supported!");
BlockingQueue queue = address2key.get(address);
try {
maxNumberInvariant.readLock().lock();
Modified: trunk/core/src/main/java/org/infinispan/commands/CommandsFactory.java
===================================================================
--- trunk/core/src/main/java/org/infinispan/commands/CommandsFactory.java 2010-09-15 16:19:59 UTC (rev 2385)
+++ trunk/core/src/main/java/org/infinispan/commands/CommandsFactory.java 2010-09-15 19:09:38 UTC (rev 2386)
@@ -196,8 +196,9 @@
* <p/>
*
* @param command command to initialize. Cannot be null.
+ * @param isRemote
*/
- void initializeReplicableCommand(ReplicableCommand command);
+ void initializeReplicableCommand(ReplicableCommand command, boolean isRemote);
/**
* Builds an RpcCommand "envelope" containing multiple ReplicableCommands
@@ -283,14 +284,6 @@
/**
* Builds a RehashControlCommand for coordinating a rehash event. This particular variation of RehashControlCommand
* coordinates rehashing of nodes when a node join or leaves
- *
- * @param subtype
- * @param sender
- * @param state
- * @param oldCH
- * @param leaversHandled
- * @param newCH
- * @return
*/
RehashControlCommand buildRehashControlCommand(RehashControlCommand.Type subtype,
Address sender, Map<Object, InternalCacheValue> state, ConsistentHash oldCH,
Modified: trunk/core/src/main/java/org/infinispan/commands/CommandsFactoryImpl.java
===================================================================
--- trunk/core/src/main/java/org/infinispan/commands/CommandsFactoryImpl.java 2010-09-15 16:19:59 UTC (rev 2385)
+++ trunk/core/src/main/java/org/infinispan/commands/CommandsFactoryImpl.java 2010-09-15 19:09:38 UTC (rev 2386)
@@ -59,7 +59,9 @@
import org.infinispan.interceptors.InterceptorChain;
import org.infinispan.notifications.cachelistener.CacheNotifier;
import org.infinispan.remoting.transport.Address;
+import org.infinispan.transaction.xa.DldGlobalTransaction;
import org.infinispan.transaction.xa.GlobalTransaction;
+import org.infinispan.transaction.xa.RemoteTransaction;
import org.infinispan.transaction.xa.TransactionTable;
import org.infinispan.util.logging.Log;
import org.infinispan.util.logging.LogFactory;
@@ -67,6 +69,7 @@
import java.util.Collection;
import java.util.List;
import java.util.Map;
+import java.util.Set;
/**
* @author Mircea.Markus at jboss.com
@@ -213,7 +216,10 @@
return new ClusteredGetCommand(key, cacheName);
}
- public void initializeReplicableCommand(ReplicableCommand c) {
+ /**
+ * @param isRemote true if the command is deserialized and is executed remote.
+ */
+ public void initializeReplicableCommand(ReplicableCommand c, boolean isRemote) {
if (c == null) return;
switch (c.getCommandId()) {
case PutKeyValueCommand.COMMAND_ID:
@@ -230,14 +236,14 @@
rc.init(interceptorChain, icc);
if (rc.getCommands() != null)
for (ReplicableCommand nested : rc.getCommands()) {
- initializeReplicableCommand(nested);
+ initializeReplicableCommand(nested, false);
}
break;
case SingleRpcCommand.COMMAND_ID:
SingleRpcCommand src = (SingleRpcCommand) c;
src.init(interceptorChain, icc);
if (src.getCommand() != null)
- initializeReplicableCommand(src.getCommand());
+ initializeReplicableCommand(src.getCommand(), false);
break;
case InvalidateCommand.COMMAND_ID:
@@ -253,15 +259,24 @@
pc.init(interceptorChain, icc, txTable);
pc.initialize(notifier);
if (pc.getModifications() != null)
- for (ReplicableCommand nested : pc.getModifications()) initializeReplicableCommand(nested);
+ for (ReplicableCommand nested : pc.getModifications()) {
+ initializeReplicableCommand(nested, false);
+ }
+ pc.markTransactionAsRemote(isRemote);
+ if (configuration.isEnableDeadlockDetection() && isRemote) {
+ DldGlobalTransaction transaction = (DldGlobalTransaction) pc.getGlobalTransaction();
+ transaction.setLocksHeldAtOrigin(pc.getAffectedKeys());
+ }
break;
case CommitCommand.COMMAND_ID:
CommitCommand commitCommand = (CommitCommand) c;
commitCommand.init(interceptorChain, icc, txTable);
+ commitCommand.markTransactionAsRemote(isRemote);
break;
case RollbackCommand.COMMAND_ID:
RollbackCommand rollbackCommand = (RollbackCommand) c;
rollbackCommand.init(interceptorChain, icc, txTable);
+ rollbackCommand.markTransactionAsRemote(isRemote);
break;
case ClearCommand.COMMAND_ID:
ClearCommand cc = (ClearCommand) c;
@@ -274,6 +289,22 @@
case LockControlCommand.COMMAND_ID:
LockControlCommand lcc = (LockControlCommand) c;
lcc.init(interceptorChain, icc, txTable);
+ lcc.markTransactionAsRemote(isRemote);
+ if (configuration.isEnableDeadlockDetection() && isRemote) {
+ DldGlobalTransaction gtx = (DldGlobalTransaction) lcc.getGlobalTransaction();
+ RemoteTransaction transaction = txTable.getRemoteTransaction(gtx);
+ if (transaction != null) {
+ if (!configuration.getCacheMode().isDistributed()) {
+ Set<Object> keys = txTable.getLockedKeysForRemoteTransaction(gtx);
+ GlobalTransaction gtx2 = transaction.getGlobalTransaction();
+ ((DldGlobalTransaction) gtx2).setLocksHeldAtOrigin(keys);
+ gtx.setLocksHeldAtOrigin(keys);
+ } else {
+ GlobalTransaction gtx2 = transaction.getGlobalTransaction();
+ ((DldGlobalTransaction) gtx2).setLocksHeldAtOrigin(gtx.getLocksHeldAtOrigin());
+ }
+ }
+ }
break;
case RehashControlCommand.COMMAND_ID:
RehashControlCommand rcc = (RehashControlCommand) c;
Modified: trunk/core/src/main/java/org/infinispan/commands/RemoteCommandsFactory.java
===================================================================
--- trunk/core/src/main/java/org/infinispan/commands/RemoteCommandsFactory.java 2010-09-15 16:19:59 UTC (rev 2385)
+++ trunk/core/src/main/java/org/infinispan/commands/RemoteCommandsFactory.java 2010-09-15 19:09:38 UTC (rev 2386)
@@ -29,10 +29,11 @@
* cache-specific components into it.
* <p />
* Usually a second step to unmarshalling a command from a byte stream (after
- * creating an un-initialized version using this factory) is to pass the command though {@link org.infinispan.commands.CommandsFactory#initializeReplicableCommand(ReplicableCommand)}.
+ * creating an un-initialized version using this factory) is to pass the command though {@link CommandsFactory#initializeReplicableCommand(ReplicableCommand,boolean)}.
*
- * @see org.infinispan.commands.CommandsFactory#initializeReplicableCommand(ReplicableCommand)
+ * @see CommandsFactory#initializeReplicableCommand(ReplicableCommand,boolean)
* @author Manik Surtani
+ * @author Mircea.Markus at jboss.com
* @since 4.0
*/
@Scope(Scopes.GLOBAL)
@@ -48,7 +49,7 @@
* Creates an un-initialized command. Un-initialized in the sense that parameters will be set, but any components
* specific to the cache in question will not be set.
* <p/>
- * You would typically set these parameters using {@link org.infinispan.commands.CommandsFactory#initializeReplicableCommand(ReplicableCommand)}
+ * You would typically set these parameters using {@link CommandsFactory#initializeReplicableCommand(ReplicableCommand,boolean)}
* <p/>
*
* @param id id of the command
Modified: trunk/core/src/main/java/org/infinispan/commands/control/LockControlCommand.java
===================================================================
--- trunk/core/src/main/java/org/infinispan/commands/control/LockControlCommand.java 2010-09-15 16:19:59 UTC (rev 2385)
+++ trunk/core/src/main/java/org/infinispan/commands/control/LockControlCommand.java 2010-09-15 19:09:38 UTC (rev 2386)
@@ -32,6 +32,8 @@
import org.infinispan.transaction.xa.GlobalTransaction;
import org.infinispan.transaction.xa.RemoteTransaction;
import org.infinispan.util.Util;
+import org.infinispan.util.logging.Log;
+import org.infinispan.util.logging.LogFactory;
import java.util.Collection;
import java.util.Collections;
@@ -45,14 +47,19 @@
* For more details refer to: https://jira.jboss.org/jira/browse/ISPN-70 https://jira.jboss.org/jira/browse/ISPN-48
*
* @author Vladimir Blagojevic (<a href="mailto:vblagoje at redhat.com">vblagoje at redhat.com</a>)
+ * @author Mircea.Markus at jboss.com
* @since 4.0
*/
@Marshallable(externalizer = ReplicableCommandExternalizer.class, id = Ids.LOCK_CONTROL_COMMAND)
public class LockControlCommand extends AbstractTransactionBoundaryCommand {
+
+ private static Log log = LogFactory.getLog(LockControlCommand.class);
+
public static final int COMMAND_ID = 3;
private Set<Object> keys;
private Object singleKey;
private boolean implicit = false;
+ private boolean unlock = false;
public LockControlCommand() {
}
@@ -143,8 +150,13 @@
RemoteTxInvocationContext ctxt = icc.createRemoteTxInvocationContext();
RemoteTransaction transaction = txTable.getRemoteTransaction(globalTx);
- boolean remoteTxinitiated = transaction != null;
- if (!remoteTxinitiated) {
+ if (transaction == null) {
+ if (unlock) {
+ if (log.isTraceEnabled()) {
+ log.trace("Unlock for in-existing transaction: " + globalTx + ". Not doing anything.");
+ }
+ return null;
+ }
//create a remote tx without any modifications (we do not know modifications ahead of time)
transaction = txTable.createRemoteTransaction(globalTx);
}
@@ -159,11 +171,11 @@
public Object[] getParameters() {
if (keys == null || keys.isEmpty()) {
if (singleKey == null)
- return new Object[]{globalTx, cacheName, (byte) 1};
+ return new Object[]{globalTx, cacheName, unlock, (byte) 1};
else
- return new Object[]{globalTx, cacheName, (byte) 2, singleKey};
+ return new Object[]{globalTx, cacheName, unlock, (byte) 2, singleKey};
}
- return new Object[]{globalTx, cacheName, (byte) 3, keys};
+ return new Object[]{globalTx, cacheName, unlock, (byte) 3, keys};
}
@SuppressWarnings("unchecked")
@@ -172,22 +184,31 @@
throw new IllegalStateException("Unusupported command id:" + commandId);
globalTx = (GlobalTransaction) args[0];
cacheName = (String) args[1];
+ unlock = (Boolean)args[2];
keys = null;
singleKey = null;
- byte mode = (Byte) args[2];
+ byte mode = (Byte) args[3];
switch (mode) {
case 1:
break; // do nothing
case 2:
- singleKey = args[3];
+ singleKey = args[4];
break;
case 3:
- keys = (Set<Object>) args[3];
+ keys = (Set<Object>) args[4];
break;
}
}
+ public boolean isUnlock() {
+ return unlock;
+ }
+
+ public void setUnlock(boolean unlock) {
+ this.unlock = unlock;
+ }
+
public boolean equals(Object o) {
if (this == o)
return true;
@@ -197,7 +218,7 @@
LockControlCommand that = (LockControlCommand) o;
if (!super.equals(that))
return false;
- return keys.equals(that.keys) && Util.safeEquals(singleKey, that.singleKey);
+ return keys.equals(that.keys) && Util.safeEquals(singleKey, that.singleKey) && (unlock == that.unlock);
}
public int hashCode() {
@@ -213,6 +234,7 @@
", cacheName='" + cacheName +
", implicit='" + implicit +
", keys=" + keys +
+ ", unlock=" + unlock +
", singleKey=" + singleKey + '}';
}
}
Modified: trunk/core/src/main/java/org/infinispan/commands/control/RehashControlCommand.java
===================================================================
--- trunk/core/src/main/java/org/infinispan/commands/control/RehashControlCommand.java 2010-09-15 16:19:59 UTC (rev 2385)
+++ trunk/core/src/main/java/org/infinispan/commands/control/RehashControlCommand.java 2010-09-15 19:09:38 UTC (rev 2386)
@@ -105,7 +105,7 @@
// we need to "fix" these command lists - essentially propagate the init. TODO think of a nicer way to do this!!
for (List<? extends ReplicableCommand> commandList : Arrays.asList(txLogCommands, pendingPrepares)) {
if (commandList != null) {
- for (ReplicableCommand cmd : commandList) commandsFactory.initializeReplicableCommand(cmd);
+ for (ReplicableCommand cmd : commandList) commandsFactory.initializeReplicableCommand(cmd, false);
}
}
}
Modified: trunk/core/src/main/java/org/infinispan/commands/tx/AbstractTransactionBoundaryCommand.java
===================================================================
--- trunk/core/src/main/java/org/infinispan/commands/tx/AbstractTransactionBoundaryCommand.java 2010-09-15 16:19:59 UTC (rev 2385)
+++ trunk/core/src/main/java/org/infinispan/commands/tx/AbstractTransactionBoundaryCommand.java 2010-09-15 19:09:38 UTC (rev 2386)
@@ -68,8 +68,13 @@
return globalTx;
}
+ public void markTransactionAsRemote(boolean isRemote) {
+ globalTx.setRemote(isRemote);
+ }
+
public Object perform(InvocationContext ctx) throws Throwable {
if (ctx != null) throw new IllegalStateException("Expected null context!");
+ markGtxAsRemote();
RemoteTransaction transaction = txTable.getRemoteTransaction(globalTx);
if (transaction == null) {
if (trace) log.info("Not found RemoteTransaction for tx id: " + globalTx);
@@ -112,9 +117,12 @@
@Override
public String toString() {
- return getClass().getSimpleName() + "{" +
- "gtx=" + globalTx +
+ return ", gtx=" + globalTx +
", cacheName='" + cacheName + '\'' +
'}';
}
+
+ private void markGtxAsRemote() {
+ globalTx.setRemote(true);
+ }
}
Modified: trunk/core/src/main/java/org/infinispan/commands/tx/PrepareCommand.java
===================================================================
--- trunk/core/src/main/java/org/infinispan/commands/tx/PrepareCommand.java 2010-09-15 16:19:59 UTC (rev 2385)
+++ trunk/core/src/main/java/org/infinispan/commands/tx/PrepareCommand.java 2010-09-15 19:09:38 UTC (rev 2386)
@@ -105,7 +105,7 @@
ctx.setRemoteTransaction(remoteTransaction);
if (trace)
- log.trace("Invoking remotly orginated prepare: " + this);
+ log.trace("Invoking remotely originated prepare: " + this + " with invocation context: " + ctx);
notifier.notifyTransactionRegistered(ctx.getGlobalTransaction(), ctx);
try {
return invoker.invoke(ctx, this);
Modified: trunk/core/src/main/java/org/infinispan/commands/tx/TransactionBoundaryCommand.java
===================================================================
--- trunk/core/src/main/java/org/infinispan/commands/tx/TransactionBoundaryCommand.java 2010-09-15 16:19:59 UTC (rev 2385)
+++ trunk/core/src/main/java/org/infinispan/commands/tx/TransactionBoundaryCommand.java 2010-09-15 19:09:38 UTC (rev 2386)
@@ -30,9 +30,12 @@
* {@link org.infinispan.transaction.xa.GlobalTransaction}
*
* @author Manik Surtani (<a href="mailto:manik at jboss.org">manik at jboss.org</a>)
+ * @author Mircea.Markus at jboss.com
* @since 4.0
*/
public interface TransactionBoundaryCommand extends VisitableCommand, CacheRpcCommand {
GlobalTransaction getGlobalTransaction();
+
+ void markTransactionAsRemote(boolean remote);
}
Modified: trunk/core/src/main/java/org/infinispan/config/Configuration.java
===================================================================
--- trunk/core/src/main/java/org/infinispan/config/Configuration.java 2010-09-15 16:19:59 UTC (rev 2385)
+++ trunk/core/src/main/java/org/infinispan/config/Configuration.java 2010-09-15 19:09:38 UTC (rev 2386)
@@ -438,6 +438,10 @@
this.transaction.setUseEagerLocking(useEagerLocking);
}
+ public void setEagerLockSingleNode(boolean eagerLockSingleNode) {
+ this.transaction.setEagerLockSingleNode(eagerLockSingleNode);
+ }
+
public void setUseReplQueue(boolean useReplQueue) {
this.clustering.async.setUseReplQueue(useReplQueue);
}
@@ -616,6 +620,10 @@
return transaction.useEagerLocking;
}
+ public boolean isEagerLockSingleNode() {
+ return transaction.eagerLockSingleNode;
+ }
+
public long getStateRetrievalTimeout() {
return clustering.stateRetrieval.timeout;
}
@@ -847,6 +855,17 @@
* */
@Dynamic
protected Boolean useEagerLocking = false;
+
+ /**
+ * @configRef desc="Only has effect for DIST mode and when useEagerLocking is set to true. When this is enabled, then only one node
+ * is locked in the cluster, disregarding numOwners config. On the opposite, if this is false, then on all cache.lock() calls
+ * numOwners RPCs are being performed. The node that gets locked is the main data owner, i.e. the node where data
+ * would reside if numOwners==1. If the node where the lock resides crashes, then the transaction is marked for rollback -
+ * data is in a consistent state, no fault tolerance."
+ */
+ @Dynamic
+ protected Boolean eagerLockSingleNode = false;
+
public TransactionType(String transactionManagerLookupClass) {
this.transactionManagerLookupClass = transactionManagerLookupClass;
@@ -882,8 +901,15 @@
public void setUseEagerLocking(Boolean useEagerLocking) {
testImmutability("useEagerLocking");
this.useEagerLocking = useEagerLocking;
+
}
+ @XmlAttribute
+ public void setEagerLockSingleNode(Boolean eagerLockSingleNode) {
+ testImmutability("useEagerLocking");
+ this.eagerLockSingleNode = eagerLockSingleNode;
+ }
+
@Override
public boolean equals(Object o) {
if (this == o) return true;
Modified: trunk/core/src/main/java/org/infinispan/config/ConfigurationValidatingVisitor.java
===================================================================
--- trunk/core/src/main/java/org/infinispan/config/ConfigurationValidatingVisitor.java 2010-09-15 16:19:59 UTC (rev 2385)
+++ trunk/core/src/main/java/org/infinispan/config/ConfigurationValidatingVisitor.java 2010-09-15 19:09:38 UTC (rev 2386)
@@ -48,18 +48,5 @@
@Override
public void visitConfiguration(Configuration bean) {
- checkEagerLockingAndDld(bean);
}
-
- private void checkEagerLockingAndDld(Configuration bean) {
- boolean isEagerLocking = bean.isUseEagerLocking();
- checkEagerLockingAndDld(bean, isEagerLocking);
- }
-
- public static void checkEagerLockingAndDld(Configuration bean, boolean eagerLocking) {
- boolean isDealLockDetection = bean.isEnableDeadlockDetection();
- if (isDealLockDetection && eagerLocking) {
- throw new ConfigurationException("Deadlock detection cannot be used with eager locking until ISPN-596 is fixed. See https://jira.jboss.org/browse/ISPN-596");
- }
- }
}
Modified: trunk/core/src/main/java/org/infinispan/context/InvocationContext.java
===================================================================
--- trunk/core/src/main/java/org/infinispan/context/InvocationContext.java 2010-09-15 16:19:59 UTC (rev 2385)
+++ trunk/core/src/main/java/org/infinispan/context/InvocationContext.java 2010-09-15 19:09:38 UTC (rev 2386)
@@ -48,11 +48,6 @@
*/
Object getLockOwner();
- /**
- * Returns true if the context has any locked entries associated with it.
- */
- boolean hasLockedEntries();
-
boolean isUseFutureReturnType();
void setUseFutureReturnType(boolean useFutureReturnType);
@@ -60,10 +55,8 @@
InvocationContext clone();
/**
- * Retrieves a set of keys added to the context within the scope of the current invocation up to the current point
- * in time. This is usually all of the keys added to the context, unless transactions are used in which case it is
- * a subset of all the keys added to the context.
- * @return a Set of keys, which may be an empty set.
+ * Returns the set of keys that are locked for writing.
*/
- Set<Object> getKeysAddedInCurrentInvocation();
+ public Set getLockedKeys();
+
}
Modified: trunk/core/src/main/java/org/infinispan/context/impl/AbstractInvocationContext.java
===================================================================
--- trunk/core/src/main/java/org/infinispan/context/impl/AbstractInvocationContext.java 2010-09-15 16:19:59 UTC (rev 2385)
+++ trunk/core/src/main/java/org/infinispan/context/impl/AbstractInvocationContext.java 2010-09-15 19:09:38 UTC (rev 2386)
@@ -3,11 +3,9 @@
import org.infinispan.container.entries.CacheEntry;
import org.infinispan.context.Flag;
import org.infinispan.context.InvocationContext;
-import org.infinispan.util.BidirectionalMap;
import java.util.Arrays;
import java.util.Collection;
-import java.util.Collections;
import java.util.EnumSet;
import java.util.HashSet;
import java.util.Set;
@@ -22,7 +20,6 @@
public abstract class AbstractInvocationContext implements InvocationContext {
protected volatile EnumSet<Flag> flags;
- protected Set<Object> keysAddedInCurrentInvocation;
// since this is finite, small, and strictly an internal API, it is cheaper/quicker to use bitmasking rather than
// an EnumSet.
@@ -111,7 +108,6 @@
public void reset() {
flags = null;
contextFlags = 0;
- keysAddedInCurrentInvocation = null;
}
public boolean isFlagsUninitialized() {
@@ -127,18 +123,7 @@
}
}
- public boolean hasLockedEntries() {
- BidirectionalMap<Object, CacheEntry> lookedUpEntries = getLookedUpEntries();
- boolean result = false;
- for (CacheEntry e : lookedUpEntries.values()) {
- if (e.isChanged()) {
- result = true;
- }
- }
- return result;
- }
-
public boolean isUseFutureReturnType() {
return isContextFlagSet(ContextFlag.USE_FUTURE_RETURN_TYPE);
}
@@ -147,34 +132,26 @@
setContextFlag(ContextFlag.USE_FUTURE_RETURN_TYPE, useFutureReturnType);
}
- /**
- * Records that a key has been added. This method should be called by all implementations of {@link org.infinispan.context.InvocationContext#putLookedUpEntry(Object, org.infinispan.container.entries.CacheEntry)}
- * and {@link org.infinispan.context.InvocationContext#putLookedUpEntries(java.util.Map)} for each key added.
- *
- * @param key key to record
- */
- protected void keyAddedInCurrentInvocation(Object key) {
- if (keysAddedInCurrentInvocation == null) keysAddedInCurrentInvocation = new HashSet<Object>(4);
- keysAddedInCurrentInvocation.add(key);
- }
-
- public Set<Object> getKeysAddedInCurrentInvocation() {
- if (keysAddedInCurrentInvocation == null) return Collections.emptySet();
- return keysAddedInCurrentInvocation;
- }
-
@Override
public AbstractInvocationContext clone() {
try {
AbstractInvocationContext dolly = (AbstractInvocationContext) super.clone();
if (flags != null) dolly.flags = flags.clone();
- dolly.keysAddedInCurrentInvocation = null;
return dolly;
} catch (CloneNotSupportedException e) {
throw new IllegalStateException("Impossible!");
}
}
+ public Set getLockedKeys() {
+ Set result = new HashSet();
+ for (Object key : getLookedUpEntries().keySet()) {
+ if (hasLockedKey(key))
+ result.add(key);
+ }
+ return result;
+ }
+
@Override
public String toString() {
return getClass().getSimpleName() + "{" +
Modified: trunk/core/src/main/java/org/infinispan/context/impl/AbstractTxInvocationContext.java
===================================================================
--- trunk/core/src/main/java/org/infinispan/context/impl/AbstractTxInvocationContext.java 2010-09-15 16:19:59 UTC (rev 2385)
+++ trunk/core/src/main/java/org/infinispan/context/impl/AbstractTxInvocationContext.java 2010-09-15 19:09:38 UTC (rev 2386)
@@ -28,10 +28,6 @@
return affectedKeys == null ? Collections.EMPTY_SET : affectedKeys;
}
- public boolean isValidRunningTx() {
- return isValid(getRunningTransaction());
- }
-
public void addAffectedKeys(Object... keys) {
if (affectedKeys == null) {
affectedKeys = new HashSet<Object>();
@@ -39,60 +35,6 @@
affectedKeys.addAll(Arrays.asList(keys));
}
-
- /**
- * Return s true of tx's status is ACTIVE or PREPARING
- *
- * @param tx
- * @return true if the tx is active or preparing
- */
- public static boolean isValid(Transaction tx) {
- return isActive(tx) || isPreparing(tx);
- }
-
- /**
- * Returns true if transaction is ACTIVE, false otherwise
- */
- public static boolean isActive(Transaction tx) {
- if (tx == null) return false;
- int status;
- try {
- status = tx.getStatus();
- return status == Status.STATUS_ACTIVE;
- }
- catch (SystemException e) {
- return false;
- }
- }
-
- /**
- * Returns true if transaction is PREPARING, false otherwise
- */
- public static boolean isPreparing(Transaction tx) {
- if (tx == null) return false;
- int status;
- try {
- status = tx.getStatus();
- return status == Status.STATUS_PREPARING;
- }
- catch (SystemException e) {
- return false;
- }
- }
-
- /**
- * Tests whether the caller is in a valid transaction. If not, will throw a CacheException.
- */
- public static void assertTransactionValid(TxInvocationContext ctx) {
- Transaction tx = ctx.getRunningTransaction();
- if (!isValid(tx)) try {
- throw new CacheException("Invalid transaction " + tx + ", status = " + (tx == null ? null : tx.getStatus()));
- }
- catch (SystemException e) {
- throw new CacheException("Exception trying to analyse status of transaction " + tx, e);
- }
- }
-
@Override
public AbstractTxInvocationContext clone() {
AbstractTxInvocationContext dolly = (AbstractTxInvocationContext) super.clone();
Modified: trunk/core/src/main/java/org/infinispan/context/impl/LocalTxInvocationContext.java
===================================================================
--- trunk/core/src/main/java/org/infinispan/context/impl/LocalTxInvocationContext.java 2010-09-15 16:19:59 UTC (rev 2385)
+++ trunk/core/src/main/java/org/infinispan/context/impl/LocalTxInvocationContext.java 2010-09-15 19:09:38 UTC (rev 2386)
@@ -2,11 +2,13 @@
import org.infinispan.commands.write.WriteCommand;
import org.infinispan.container.entries.CacheEntry;
+import org.infinispan.remoting.transport.Address;
import org.infinispan.transaction.xa.GlobalTransaction;
import org.infinispan.transaction.xa.TransactionXaAdapter;
import org.infinispan.util.BidirectionalMap;
import javax.transaction.Transaction;
+import java.util.Collection;
import java.util.List;
import java.util.Map;
@@ -57,13 +59,11 @@
}
public void putLookedUpEntry(Object key, CacheEntry e) {
- keyAddedInCurrentInvocation(key);
xaAdapter.putLookedUpEntry(key, e);
}
public void putLookedUpEntries(Map<Object, CacheEntry> lookedUpEntries) {
for (Map.Entry<Object, CacheEntry> ce: lookedUpEntries.entrySet()) {
- keyAddedInCurrentInvocation(ce.getKey());
xaAdapter.putLookedUpEntry(ce.getKey(), ce.getValue());
}
}
@@ -80,4 +80,8 @@
public boolean hasLockedKey(Object key) {
return xaAdapter != null && super.hasLockedKey(key);
}
+
+ public void remoteLocksAcquired(Collection<Address> nodes) {
+ xaAdapter.locksAcquired(nodes);
+ }
}
Modified: trunk/core/src/main/java/org/infinispan/context/impl/NonTxInvocationContext.java
===================================================================
--- trunk/core/src/main/java/org/infinispan/context/impl/NonTxInvocationContext.java 2010-09-15 16:19:59 UTC (rev 2385)
+++ trunk/core/src/main/java/org/infinispan/context/impl/NonTxInvocationContext.java 2010-09-15 19:09:38 UTC (rev 2386)
@@ -27,14 +27,12 @@
public void putLookedUpEntry(Object key, CacheEntry e) {
initLookedUpEntries();
- keyAddedInCurrentInvocation(key);
lookedUpEntries.put(key, e);
}
public void putLookedUpEntries(Map<Object, CacheEntry> lookedUpEntries) {
initLookedUpEntries();
for (Map.Entry<Object, CacheEntry> ce: lookedUpEntries.entrySet()) {
- keyAddedInCurrentInvocation(ce.getKey());
lookedUpEntries.put(ce.getKey(), ce.getValue());
}
}
Modified: trunk/core/src/main/java/org/infinispan/context/impl/RemoteTxInvocationContext.java
===================================================================
--- trunk/core/src/main/java/org/infinispan/context/impl/RemoteTxInvocationContext.java 2010-09-15 16:19:59 UTC (rev 2385)
+++ trunk/core/src/main/java/org/infinispan/context/impl/RemoteTxInvocationContext.java 2010-09-15 19:09:38 UTC (rev 2386)
@@ -62,7 +62,6 @@
}
public void putLookedUpEntry(Object key, CacheEntry e) {
- keyAddedInCurrentInvocation(key);
remoteTransaction.putLookedUpEntry(key, e);
}
@@ -76,7 +75,6 @@
public void putLookedUpEntries(Map<Object, CacheEntry> lookedUpEntries) {
for (Map.Entry<Object, CacheEntry> ce: lookedUpEntries.entrySet()) {
- keyAddedInCurrentInvocation(ce.getKey());
remoteTransaction.putLookedUpEntry(ce.getKey(), ce.getValue());
}
}
Modified: trunk/core/src/main/java/org/infinispan/context/impl/TxInvocationContext.java
===================================================================
--- trunk/core/src/main/java/org/infinispan/context/impl/TxInvocationContext.java 2010-09-15 16:19:59 UTC (rev 2385)
+++ trunk/core/src/main/java/org/infinispan/context/impl/TxInvocationContext.java 2010-09-15 19:09:38 UTC (rev 2386)
@@ -46,11 +46,6 @@
Transaction getRunningTransaction();
/**
- * Returns true if the current tx is either ACTIVE or PREPARING, false otherwise.
- */
- boolean isValidRunningTx();
-
- /**
* Registers a new participant with the transaction.
*/
void addAffectedKeys(Object... keys);
Modified: trunk/core/src/main/java/org/infinispan/distribution/DistributionManager.java
===================================================================
--- trunk/core/src/main/java/org/infinispan/distribution/DistributionManager.java 2010-09-15 16:19:59 UTC (rev 2385)
+++ trunk/core/src/main/java/org/infinispan/distribution/DistributionManager.java 2010-09-15 19:09:38 UTC (rev 2386)
@@ -18,6 +18,7 @@
* A component that manages the distribution of elements across a cache cluster
*
* @author Manik Surtani
+ * @author Mircea.Markus at jboss.com
* @since 4.0
*/
@Scope(Scopes.NAMED_CACHE)
@@ -46,6 +47,11 @@
Map<Object, List<Address>> locateAll(Collection<Object> keys);
/**
+ * Same as {@link #locateAll(java.util.Collection)}, but the list of addresses only contains numOwners owners.
+ */
+ Map<Object, List<Address>> locateAll(Collection<Object> keys, int numOwners);
+
+ /**
* Transforms a cache entry so it is marked for L1 rather than the primary cache data structure. This should be done
* if it is deemed that the entry is targeted for L1 storage rather than storage in the primary data container.
*
Modified: trunk/core/src/main/java/org/infinispan/distribution/DistributionManagerImpl.java
===================================================================
--- trunk/core/src/main/java/org/infinispan/distribution/DistributionManagerImpl.java 2010-09-15 16:19:59 UTC (rev 2385)
+++ trunk/core/src/main/java/org/infinispan/distribution/DistributionManagerImpl.java 2010-09-15 19:09:38 UTC (rev 2386)
@@ -259,13 +259,17 @@
}
public Map<Object, List<Address>> locateAll(Collection<Object> keys) {
+ return locateAll(keys, replCount);
+ }
+
+ public Map<Object, List<Address>> locateAll(Collection<Object> keys, int numOwners) {
if (consistentHash == null) {
Map<Object, List<Address>> m = new HashMap<Object, List<Address>>(keys.size());
List<Address> selfList = Collections.singletonList(self);
for (Object k : keys) m.put(k, selfList);
return m;
}
- return consistentHash.locateAll(keys, replCount);
+ return consistentHash.locateAll(keys, numOwners);
}
public void transformForL1(CacheEntry entry) {
Modified: trunk/core/src/main/java/org/infinispan/interceptors/CallInterceptor.java
===================================================================
--- trunk/core/src/main/java/org/infinispan/interceptors/CallInterceptor.java 2010-09-15 16:19:59 UTC (rev 2385)
+++ trunk/core/src/main/java/org/infinispan/interceptors/CallInterceptor.java 2010-09-15 19:09:38 UTC (rev 2386)
@@ -37,6 +37,7 @@
* transaction.
*
* @author Bela Ban
+ * @author Mircea.Markus at jboss.com
* @since 4.0
*/
public class CallInterceptor extends CommandInterceptor {
@@ -67,19 +68,6 @@
@Override
final public Object handleDefault(InvocationContext ctx, VisitableCommand command) throws Throwable {
if (trace) log.trace("Executing command: " + command + ".");
- Object retval;
- try {
- retval = command.perform(ctx);
- }
- catch (Throwable t) {
- if (ctx.isInTxScope()) {
- TxInvocationContext txContext = (TxInvocationContext) ctx;
- if (txContext.isValidRunningTx()) {
- txContext.getRunningTransaction().setRollbackOnly();
- }
- }
- throw t;
- }
- return retval;
+ return command.perform(ctx);
}
}
\ No newline at end of file
Modified: trunk/core/src/main/java/org/infinispan/interceptors/DeadlockDetectingInterceptor.java
===================================================================
--- trunk/core/src/main/java/org/infinispan/interceptors/DeadlockDetectingInterceptor.java 2010-09-15 16:19:59 UTC (rev 2385)
+++ trunk/core/src/main/java/org/infinispan/interceptors/DeadlockDetectingInterceptor.java 2010-09-15 19:09:38 UTC (rev 2386)
@@ -1,29 +1,26 @@
package org.infinispan.interceptors;
-import org.infinispan.commands.DataCommand;
+import org.infinispan.commands.VisitableCommand;
+import org.infinispan.commands.control.LockControlCommand;
import org.infinispan.commands.tx.PrepareCommand;
-import org.infinispan.commands.tx.RollbackCommand;
import org.infinispan.commands.write.PutKeyValueCommand;
import org.infinispan.commands.write.RemoveCommand;
import org.infinispan.commands.write.ReplaceCommand;
import org.infinispan.context.InvocationContext;
import org.infinispan.context.impl.TxInvocationContext;
-import org.infinispan.distribution.DistributionManager;
import org.infinispan.factories.annotations.Inject;
import org.infinispan.factories.annotations.Start;
import org.infinispan.interceptors.base.CommandInterceptor;
-import org.infinispan.remoting.transport.Address;
-import org.infinispan.transaction.xa.DeadlockDetectingGlobalTransaction;
+import org.infinispan.transaction.xa.DldGlobalTransaction;
+import org.infinispan.transaction.xa.GlobalTransaction;
+import org.infinispan.transaction.xa.RemoteTransaction;
import org.infinispan.transaction.xa.TransactionTable;
-import org.infinispan.util.concurrent.locks.DeadlockDetectedException;
-import org.infinispan.util.concurrent.locks.LockManager;
-import javax.transaction.Transaction;
-import javax.transaction.TransactionManager;
-import java.util.HashSet;
+import java.util.Collections;
+import java.util.Set;
/**
- * This interceptor populates the {@link org.infinispan.transaction.xa.DeadlockDetectingGlobalTransaction} with
+ * This interceptor populates the {@link org.infinispan.transaction.xa.DldGlobalTransaction} with
* appropriate information needed in order to accomplish deadlock detection. It MUST process populate data before the
* replication takes place, so it will do all the tasks before calling {@link org.infinispan.interceptors.base.CommandInterceptor#invokeNextInterceptor(org.infinispan.context.InvocationContext,
* org.infinispan.commands.VisitableCommand)}.
@@ -35,21 +32,6 @@
*/
public class DeadlockDetectingInterceptor extends CommandInterceptor {
- private TransactionTable txTable;
- private LockManager lockManager;
- private TransactionManager txManager;
- private DistributionManager distributionManager;
-
- @Inject
- public void init(TransactionTable txTable, LockManager lockManager, TransactionManager txManager,
- DistributionManager distributionManager) {
- this.txTable = txTable;
- this.lockManager = lockManager;
- this.txManager = txManager;
- this.distributionManager = distributionManager;
- }
-
-
/**
* Only does a sanity check.
*/
@@ -60,43 +42,6 @@
}
}
- private Object handleDataCommand(InvocationContext ctx, DataCommand command) throws Throwable {
- if (ctx.isInTxScope()) {
- DeadlockDetectingGlobalTransaction gtx = (DeadlockDetectingGlobalTransaction) ctx.getLockOwner();
- gtx.setLockIntention(command.getKey());
- gtx.setProcessingThread(Thread.currentThread());
- }
- try {
- return invokeNextInterceptor(ctx, command);
- } catch (InterruptedException ie) {
- if (ctx.isInTxScope()) {
- lockManager.releaseLocks(ctx);
- if (ctx.isOriginLocal()) {
- Transaction transaction = txManager.getTransaction();
- if (trace)
- log.trace("Marking the transaction for rollback! : " + transaction);
- if (transaction == null) {
- throw new IllegalStateException("We're running in a local transaction, there MUST be one " +
- "associated witht the local thread but none found! (null)");
- }
- transaction.setRollbackOnly();
- txTable.removeLocalTransaction(transaction);
- throw new DeadlockDetectedException("Deadlock request was detected for locally originated tx " + transaction +
- "; it was marked for rollback");
- } else {
- DeadlockDetectingGlobalTransaction gtx = (DeadlockDetectingGlobalTransaction) ctx.getLockOwner();
- gtx.setMarkedForRollback(true);
- throw new DeadlockDetectedException("Deadlock request was detected for remotely originated tx " + gtx +
- "; it was marked for rollback");
- }
- } else {
- if (trace)
- log.trace("Received an interrupt request, but we're not running within the scope of a transaction, so passing it up the stack", ie);
- throw ie;
- }
- }
- }
-
@Override
public Object visitPutKeyValueCommand(InvocationContext ctx, PutKeyValueCommand command) throws Throwable {
return handleDataCommand(ctx, command);
@@ -113,46 +58,34 @@
}
@Override
- public Object visitPrepareCommand(TxInvocationContext ctx, PrepareCommand command) throws Throwable {
- DeadlockDetectingGlobalTransaction globalTransaction = (DeadlockDetectingGlobalTransaction) ctx.getGlobalTransaction();
- globalTransaction.setProcessingThread(Thread.currentThread());
+ public Object visitLockControlCommand(TxInvocationContext ctx, LockControlCommand command) throws Throwable {
+ DldGlobalTransaction globalTransaction = (DldGlobalTransaction) ctx.getGlobalTransaction();
if (ctx.isOriginLocal()) {
+ globalTransaction.setRemoteLockIntention(command.getKeys());
+ //in the case of DIST we need to propagate the list of keys. In all other situations in can be determined
+ // based on the actual command
if (configuration.getCacheMode().isDistributed()) {
- globalTransaction.setReplicatingTo(new HashSet<Address>(distributionManager.getAffectedNodes(ctx.getAffectedKeys())));
- } else {
- globalTransaction.setReplicatingTo(null);
+ ((DldGlobalTransaction) ctx.getGlobalTransaction()).setLocksHeldAtOrigin(ctx.getLockedKeys());
}
- if (trace) log.trace("Deadlock detection information was added to " + globalTransaction);
}
- try {
- return invokeNextInterceptor(ctx, command);
- } catch (Throwable dde) {
- if (ctx.isOriginLocal()) {
- globalTransaction.setMarkedForRollback(true);
- boolean wasInterrupted = Thread.interrupted();
- if (trace)
- log.trace("Deadlock was detected on the remote side, marking the tx for rollback. Was this thread interrupted? " + wasInterrupted);
- }
- throw dde;
- } finally {
- if (!ctx.isOriginLocal()) {
- if (!txTable.containRemoteTx(ctx.getGlobalTransaction())) {
- if (trace) {
- log.trace("While returning from prepare we determined that remote tx is no longer in the txTable. " +
- "This means that a rollback was executed in between; releasing locks");
- }
- lockManager.releaseLocks(ctx);
- }
- }
- }
+ return handleDataCommand(ctx, command);
}
@Override
- public Object visitRollbackCommand(TxInvocationContext ctx, RollbackCommand command) throws Throwable {
- if (!ctx.isOriginLocal()) {
- DeadlockDetectingGlobalTransaction globalTransaction = (DeadlockDetectingGlobalTransaction) ctx.getGlobalTransaction();
- globalTransaction.interruptProcessingThread();
+ public Object visitPrepareCommand(TxInvocationContext ctx, PrepareCommand command) throws Throwable {
+ DldGlobalTransaction globalTransaction = (DldGlobalTransaction) ctx.getGlobalTransaction();
+ if (ctx.isOriginLocal()) {
+ globalTransaction.setRemoteLockIntention(command.getAffectedKeys());
}
+ Object result = invokeNextInterceptor(ctx, command);
+ if (ctx.isOriginLocal()) {
+ globalTransaction.setRemoteLockIntention(Collections.EMPTY_SET);
+ }
+ return result;
+ }
+
+
+ private Object handleDataCommand(InvocationContext ctx, VisitableCommand command) throws Throwable {
return invokeNextInterceptor(ctx, command);
}
}
Modified: trunk/core/src/main/java/org/infinispan/interceptors/DistributionInterceptor.java
===================================================================
--- trunk/core/src/main/java/org/infinispan/interceptors/DistributionInterceptor.java 2010-09-15 16:19:59 UTC (rev 2385)
+++ trunk/core/src/main/java/org/infinispan/interceptors/DistributionInterceptor.java 2010-09-15 19:09:38 UTC (rev 2386)
@@ -19,6 +19,7 @@
import org.infinispan.container.entries.InternalCacheEntry;
import org.infinispan.context.Flag;
import org.infinispan.context.InvocationContext;
+import org.infinispan.context.impl.LocalTxInvocationContext;
import org.infinispan.context.impl.TxInvocationContext;
import org.infinispan.distribution.DistributionManager;
import org.infinispan.factories.annotations.Inject;
@@ -30,6 +31,7 @@
import org.infinispan.util.concurrent.NotifyingFutureImpl;
import org.infinispan.util.concurrent.NotifyingNotifiableFuture;
+import java.util.ArrayList;
import java.util.Collection;
import java.util.HashSet;
import java.util.LinkedList;
@@ -41,6 +43,7 @@
* The interceptor that handles distribution of entries across a cluster, as well as transparent lookup
*
* @author Manik Surtani
+ * @author Mircea.Markus at jboss.com
* @since 4.0
*/
public class DistributionInterceptor extends BaseRpcInterceptor {
@@ -189,8 +192,28 @@
@Override
public Object visitLockControlCommand(TxInvocationContext ctx, LockControlCommand command) throws Throwable {
- if (ctx.isOriginLocal())
- rpcManager.invokeRemotely(dm.getAffectedNodes(command.getKeys()), command, true, true);
+ if (ctx.isOriginLocal()) {
+ if (configuration.isEagerLockSingleNode()) {
+ //only main data owner is locked, see: https://jira.jboss.org/browse/ISPN-615
+ Map<Object, List<Address>> toMulticast = dm.locateAll(command.getKeys(), 1);
+
+ //now compile address reunion
+ List<Address> where;
+ if (toMulticast.size() == 1) {//avoid building an extra array, as most often this will be a single key
+ where = toMulticast.values().iterator().next();
+ rpcManager.invokeRemotely(where, command, true, true);
+ } else {
+ where = new ArrayList<Address>();
+ for (List<Address> values: toMulticast.values()) {
+ where.addAll(values);
+ }
+ rpcManager.invokeRemotely(where, command, true, true);
+ }
+ ((LocalTxInvocationContext)ctx).remoteLocksAcquired(where);
+ } else {
+ rpcManager.invokeRemotely(dm.getAffectedNodes(command.getKeys()), command, true, true);
+ }
+ }
return invokeNextInterceptor(ctx, command);
}
Modified: trunk/core/src/main/java/org/infinispan/interceptors/ImplicitEagerLockingInterceptor.java
===================================================================
--- trunk/core/src/main/java/org/infinispan/interceptors/ImplicitEagerLockingInterceptor.java 2010-09-15 16:19:59 UTC (rev 2385)
+++ trunk/core/src/main/java/org/infinispan/interceptors/ImplicitEagerLockingInterceptor.java 2010-09-15 19:09:38 UTC (rev 2386)
@@ -8,6 +8,7 @@
import org.infinispan.commands.write.PutMapCommand;
import org.infinispan.commands.write.RemoveCommand;
import org.infinispan.commands.write.ReplaceCommand;
+import org.infinispan.context.Flag;
import org.infinispan.context.InvocationContext;
import org.infinispan.factories.annotations.Inject;
import org.infinispan.interceptors.base.CommandInterceptor;
@@ -23,6 +24,7 @@
* For more details refer to: https://jira.jboss.org/jira/browse/ISPN-70 https://jira.jboss.org/jira/browse/ISPN-48
*
* @author <a href="mailto:vblagoje at redhat.com">Vladimir Blagojevic (vblagoje at redhat.com)</a>
+ * @author Mircea.Markus at jboss.com
* @since 4.0
*/
public class ImplicitEagerLockingInterceptor extends CommandInterceptor {
@@ -35,10 +37,8 @@
}
@Override
- public Object visitPutKeyValueCommand(InvocationContext ctx, PutKeyValueCommand command)
- throws Throwable {
- boolean localTxScope = ctx.isInTxScope() & ctx.isOriginLocal();
- if (localTxScope) {
+ public Object visitPutKeyValueCommand(InvocationContext ctx, PutKeyValueCommand command) throws Throwable {
+ if (shouldAcquireRemoteLock(ctx)) {
lockEagerly(ctx, Collections.singleton(command.getKey()));
}
return invokeNextInterceptor(ctx, command);
@@ -46,8 +46,7 @@
@Override
public Object visitRemoveCommand(InvocationContext ctx, RemoveCommand command) throws Throwable {
- boolean localTxScope = ctx.isInTxScope() & ctx.isOriginLocal();
- if (localTxScope) {
+ if (shouldAcquireRemoteLock(ctx)) {
lockEagerly(ctx, Collections.singleton(command.getKey()));
}
return invokeNextInterceptor(ctx, command);
@@ -56,8 +55,7 @@
@Override
public Object visitReplaceCommand(InvocationContext ctx, ReplaceCommand command)
throws Throwable {
- boolean localTxScope = ctx.isInTxScope() & ctx.isOriginLocal();
- if (localTxScope) {
+ if (shouldAcquireRemoteLock(ctx)) {
lockEagerly(ctx, Collections.singleton(command.getKey()));
}
return invokeNextInterceptor(ctx, command);
@@ -65,8 +63,7 @@
@Override
public Object visitPutMapCommand(InvocationContext ctx, PutMapCommand command) throws Throwable {
- boolean localTxScope = ctx.isInTxScope() & ctx.isOriginLocal();
- if (localTxScope) {
+ if (shouldAcquireRemoteLock(ctx)) {
lockEagerly(ctx, new HashSet<Object>(command.getMap().keySet()));
}
return invokeNextInterceptor(ctx, command);
@@ -74,8 +71,7 @@
@Override
public Object visitEvictCommand(InvocationContext ctx, EvictCommand command) throws Throwable {
- boolean localTxScope = ctx.isInTxScope() & ctx.isOriginLocal();
- if (localTxScope) {
+ if (shouldAcquireRemoteLock(ctx)) {
lockEagerly(ctx, Collections.singleton(command.getKey()));
}
return invokeNextInterceptor(ctx, command);
@@ -84,8 +80,7 @@
@Override
public Object visitInvalidateCommand(InvocationContext ctx, InvalidateCommand command)
throws Throwable {
- boolean localTxScope = ctx.isInTxScope() & ctx.isOriginLocal();
- if (localTxScope) {
+ if (shouldAcquireRemoteLock(ctx)) {
lockEagerly(ctx, Collections.singleton(command.getKey()));
}
return invokeNextInterceptor(ctx, command);
@@ -95,4 +90,8 @@
LockControlCommand lcc = cf.buildLockControlCommand(keys, true);
return invokeNextInterceptor(ctx, lcc);
}
+
+ private boolean shouldAcquireRemoteLock(InvocationContext ctx) {
+ return ctx.isInTxScope() & ctx.isOriginLocal() && !ctx.hasFlag(Flag.CACHE_MODE_LOCAL);
+ }
}
Modified: trunk/core/src/main/java/org/infinispan/interceptors/InvalidationInterceptor.java
===================================================================
--- trunk/core/src/main/java/org/infinispan/interceptors/InvalidationInterceptor.java 2010-09-15 16:19:59 UTC (rev 2385)
+++ trunk/core/src/main/java/org/infinispan/interceptors/InvalidationInterceptor.java 2010-09-15 19:09:38 UTC (rev 2386)
@@ -52,6 +52,7 @@
import javax.transaction.SystemException;
import javax.transaction.Transaction;
+import java.sql.ResultSet;
import java.util.Arrays;
import java.util.HashSet;
import java.util.List;
@@ -70,6 +71,7 @@
*
* @author Manik Surtani
* @author Galder Zamarreño
+ * @author Mircea.Markus at jboss.com
* @since 4.0
*/
@MBean(objectName = "Invalidation", description = "Component responsible for invalidating entries on remote caches when entries are written to locally.")
@@ -164,12 +166,6 @@
}
catch (Throwable t) {
log.warn("Unable to broadcast evicts as a part of the prepare phase. Rolling back.", t);
- try {
- tx.setRollbackOnly();
- }
- catch (SystemException se) {
- throw new RuntimeException("setting tx rollback failed ", se);
- }
if (t instanceof RuntimeException)
throw (RuntimeException) t;
else
@@ -198,6 +194,12 @@
result.add(command.getKey());
return null;
}
+
+ @Override
+ public Object visitPutMapCommand(InvocationContext ctx, PutMapCommand command) throws Throwable {
+ result.addAll(command.getAffectedKeys());
+ return null;
+ }
}
Modified: trunk/core/src/main/java/org/infinispan/interceptors/InvocationContextInterceptor.java
===================================================================
--- trunk/core/src/main/java/org/infinispan/interceptors/InvocationContextInterceptor.java 2010-09-15 16:19:59 UTC (rev 2385)
+++ trunk/core/src/main/java/org/infinispan/interceptors/InvocationContextInterceptor.java 2010-09-15 19:09:38 UTC (rev 2386)
@@ -22,27 +22,35 @@
package org.infinispan.interceptors;
+import org.infinispan.CacheException;
import org.infinispan.commands.VisitableCommand;
import org.infinispan.context.Flag;
import org.infinispan.context.InvocationContext;
import org.infinispan.factories.annotations.Inject;
import org.infinispan.interceptors.base.CommandInterceptor;
-import org.infinispan.util.concurrent.locks.LockManager;
+import javax.transaction.Status;
+import javax.transaction.SystemException;
+import javax.transaction.Transaction;
+import javax.transaction.TransactionManager;
+
+/**
+ * @author Mircea.Markus at jboss.com
+ */
public class InvocationContextInterceptor extends CommandInterceptor {
- LockManager lockManager;
+ private TransactionManager tm;
+ @Inject
+ public void init(TransactionManager tm) {
+ this.tm = tm;
+ }
+
@Override
public Object handleDefault(InvocationContext ctx, VisitableCommand command) throws Throwable {
return handleAll(ctx, command);
}
- @Inject
- public void injectLockManager(LockManager lockManager) {
- this.lockManager = lockManager;
- }
-
private Object handleAll(InvocationContext ctx, VisitableCommand command) throws Throwable {
boolean suppressExceptions = false;
@@ -57,30 +65,41 @@
return invokeNextInterceptor(ctx, command);
}
catch (Throwable th) {
- // make sure we release locks for all keys locked in this invocation!
- for (Object key: ctx.getKeysAddedInCurrentInvocation()) {
- if (ctx.hasLockedKey(key)) {
- if (suppressExceptions) {
- if (log.isDebugEnabled()) log.debug("Caught exception, Releasing lock on key " + key + " acquired during the current invocation!");
- } else {
- if (log.isInfoEnabled()) log.info("Caught exception, Releasing lock on key " + key + " acquired during the current invocation!");
- }
- // unlock key!
- lockManager.unlock(key);
- ctx.removeLookedUpEntry(key);
- }
- }
-
if (suppressExceptions) {
log.trace("Exception while executing code, failing silently...", th);
return null;
} else {
+ if (ctx.isInTxScope() && ctx.isOriginLocal()) {
+ if (trace) log.trace("Transaction marked for rollback as exception was received.");
+ markTxForRollbackAndRethrow(ctx, th);
+ throw new IllegalStateException("This should not be reached");
+ }
log.error("Execution error: ", th);
-
throw th;
}
} finally {
ctx.reset();
}
}
+
+ private Object markTxForRollbackAndRethrow(InvocationContext ctx, Throwable te) throws Throwable {
+ if (ctx.isOriginLocal() && ctx.isInTxScope()) {
+ Transaction transaction = tm.getTransaction();
+ if (transaction != null && isValidRunningTx(transaction)) {
+ transaction.setRollbackOnly();
+ }
+ }
+ throw te;
+ }
+
+ public boolean isValidRunningTx(Transaction tx) throws Exception {
+ int status;
+ try {
+ status = tx.getStatus();
+ }
+ catch (SystemException e) {
+ throw new CacheException("Unexpected!", e);
+ }
+ return status == Status.STATUS_ACTIVE || status == Status.STATUS_PREPARING;
+ }
}
\ No newline at end of file
Modified: trunk/core/src/main/java/org/infinispan/interceptors/LockingInterceptor.java
===================================================================
--- trunk/core/src/main/java/org/infinispan/interceptors/LockingInterceptor.java 2010-09-15 16:19:59 UTC (rev 2385)
+++ trunk/core/src/main/java/org/infinispan/interceptors/LockingInterceptor.java 2010-09-15 19:09:38 UTC (rev 2386)
@@ -58,6 +58,7 @@
* Interceptor to implement <a href="http://wiki.jboss.org/wiki/JBossCacheMVCC">MVCC</a> functionality.
*
* @author Manik Surtani (<a href="mailto:manik at jboss.org">manik at jboss.org</a>)
+ * @author Mircea.Markus at jboss.com
* @see <a href="http://wiki.jboss.org/wiki/JBossCacheMVCC">MVCC designs</a>
* @since 4.0
*/
@@ -138,17 +139,41 @@
if (localTxScope) {
c.attachGlobalTransaction((GlobalTransaction) ctx.getLockOwner());
}
+
+ if (c.isUnlock()) {
+ lockManager.releaseLocks(ctx);
+ if (log.isTraceEnabled()) log.trace("Lock released for: " + ctx.getLockOwner());
+ return null;
+ }
+
for (Object key : c.getKeys()) {
if (c.isImplicit() && localTxScope && !lockManager.ownsLock(key, ctx.getLockOwner())) {
- //if even one key is unlocked we need to invoke this lock command cluster wide...
+ //if even one key is unlocked we need to invoke this lock command cluster wide...
shouldInvokeOnCluster = true;
+ break;
}
- entryFactory.wrapEntryForWriting(ctx, key, true, false, false, false, false);
}
- if (shouldInvokeOnCluster || c.isExplicit())
- return invokeNextInterceptor(ctx, c);
- else
- return null;
+ boolean goRemoteFirst = configuration.isEnableDeadlockDetection() && localTxScope;
+ if (goRemoteFirst) {
+ Object result = invokeNextInterceptor(ctx, c);
+ try {
+ lockKeysForRemoteTx(ctx, c);
+ } catch (Throwable e) {
+ //if anything happen during locking then unlock remote
+ c.setUnlock(true);
+ invokeNextInterceptor(ctx, c);
+ throw e;
+ }
+ return result;
+ } else {
+ lockKeysForRemoteTx(ctx, c);
+ if (shouldInvokeOnCluster || c.isExplicit())
+ return invokeNextInterceptor(ctx, c);
+ else
+ return null;
+ }
+ } catch (Throwable te) {
+ return cleanLocksAndRethrow(ctx, te);
} finally {
if (ctx.isInTxScope()) {
doAfterCall(ctx);
@@ -158,6 +183,12 @@
}
}
+ private void lockKeysForRemoteTx(TxInvocationContext ctx, LockControlCommand c) throws InterruptedException {
+ for (Object key : c.getKeys()) {
+ entryFactory.wrapEntryForWriting(ctx, key, true, false, false, false, false);
+ }
+ }
+
// write commands
@Override
@@ -167,6 +198,8 @@
for (InternalCacheEntry entry : dataContainer.entrySet())
entryFactory.wrapEntryForWriting(ctx, entry, false, false, false, false, false);
return invokeNextInterceptor(ctx, command);
+ } catch (Throwable te) {
+ return cleanLocksAndRethrow(ctx, te);
} finally {
doAfterCall(ctx);
}
@@ -183,10 +216,14 @@
public Object visitInvalidateCommand(InvocationContext ctx, InvalidateCommand command) throws Throwable {
try {
if (command.getKeys() != null) {
- for (Object key : command.getKeys()) entryFactory.wrapEntryForWriting(ctx, key, false, true, false, false, false);
+ for (Object key : command.getKeys())
+ entryFactory.wrapEntryForWriting(ctx, key, false, true, false, false, false);
}
return invokeNextInterceptor(ctx, command);
- } finally {
+ } catch (Throwable te) {
+ return cleanLocksAndRethrow(ctx, te);
+ }
+ finally {
doAfterCall(ctx);
}
}
@@ -196,7 +233,10 @@
try {
entryFactory.wrapEntryForWriting(ctx, command.getKey(), true, false, false, false, !command.isPutIfAbsent());
return invokeNextInterceptor(ctx, command);
- } finally {
+ } catch (Throwable te) {
+ return cleanLocksAndRethrow(ctx, te);
+ }
+ finally {
doAfterCall(ctx);
}
}
@@ -208,6 +248,8 @@
entryFactory.wrapEntryForWriting(ctx, key, true, false, false, false, true);
}
return invokeNextInterceptor(ctx, command);
+ } catch (Throwable te) {
+ return cleanLocksAndRethrow(ctx, te);
}
finally {
doAfterCall(ctx);
@@ -219,6 +261,8 @@
try {
entryFactory.wrapEntryForWriting(ctx, command.getKey(), false, true, false, true, false);
return invokeNextInterceptor(ctx, command);
+ } catch (Throwable te) {
+ return cleanLocksAndRethrow(ctx, te);
}
finally {
doAfterCall(ctx);
@@ -230,6 +274,8 @@
try {
entryFactory.wrapEntryForWriting(ctx, command.getKey(), false, true, false, false, false);
return invokeNextInterceptor(ctx, command);
+ } catch (Throwable te) {
+ return cleanLocksAndRethrow(ctx, te);
}
finally {
doAfterCall(ctx);
@@ -294,6 +340,11 @@
}
}
+ private Object cleanLocksAndRethrow(InvocationContext ctx, Throwable te) throws Throwable {
+ cleanupLocks(ctx, false);
+ throw te;
+ }
+
protected void commitEntry(CacheEntry entry) {
entry.commit(dataContainer);
}
Modified: trunk/core/src/main/java/org/infinispan/interceptors/TxInterceptor.java
===================================================================
--- trunk/core/src/main/java/org/infinispan/interceptors/TxInterceptor.java 2010-09-15 16:19:59 UTC (rev 2385)
+++ trunk/core/src/main/java/org/infinispan/interceptors/TxInterceptor.java 2010-09-15 19:09:38 UTC (rev 2386)
@@ -112,21 +112,9 @@
@Override
public Object visitLockControlCommand(TxInvocationContext ctx, LockControlCommand command) throws Throwable {
- return enlistReadAndInvokeNext(ctx, command);
+ return enlistReadAndInvokeNext(ctx, command);
}
- /**
- * Designed to be overridden. Returns a VisitableCommand fit for replaying locally, based on the modification passed
- * in. If a null value is returned, this means that the command should not be replayed.
- *
- * @param modification modification in a prepare call
- * @return a VisitableCommand representing this modification, fit for replaying, or null if the command should not be
- * replayed.
- */
- protected VisitableCommand getCommandToReplay(VisitableCommand modification) {
- return modification;
- }
-
@Override
public Object visitPutKeyValueCommand(InvocationContext ctx, PutKeyValueCommand command) throws Throwable {
return enlistWriteAndInvokeNext(ctx, command);
@@ -180,7 +168,8 @@
if (localModeNotForced(ctx)) shouldAddMod = true;
localTxContext.setXaCache(xaAdapter);
}
- Object rv = invokeNextInterceptor(ctx, command);
+ Object rv;
+ rv = invokeNextInterceptor(ctx, command);
if (!ctx.isInTxScope())
transactionLog.logNoTxWrite(command);
if (command.isSuccessful() && shouldAddMod) xaAdapter.addModification(command);
@@ -247,4 +236,16 @@
public long getRollbacks() {
return rollbacks.get();
}
+
+ /**
+ * Designed to be overridden. Returns a VisitableCommand fit for replaying locally, based on the modification passed
+ * in. If a null value is returned, this means that the command should not be replayed.
+ *
+ * @param modification modification in a prepare call
+ * @return a VisitableCommand representing this modification, fit for replaying, or null if the command should not be
+ * replayed.
+ */
+ protected VisitableCommand getCommandToReplay(VisitableCommand modification) {
+ return modification;
+ }
}
Modified: trunk/core/src/main/java/org/infinispan/interceptors/base/BaseRpcInterceptor.java
===================================================================
--- trunk/core/src/main/java/org/infinispan/interceptors/base/BaseRpcInterceptor.java 2010-09-15 16:19:59 UTC (rev 2385)
+++ trunk/core/src/main/java/org/infinispan/interceptors/base/BaseRpcInterceptor.java 2010-09-15 19:09:38 UTC (rev 2386)
@@ -56,12 +56,13 @@
public Object visitLockControlCommand(TxInvocationContext ctx, LockControlCommand command) throws Throwable {
Object retVal = invokeNextInterceptor(ctx, command);
if (ctx.isOriginLocal()) {
- rpcManager.broadcastRpcCommand(command, true, false);
+ //unlock will happen async as it is a best effort
+ boolean sync = !command.isUnlock();
+ rpcManager.broadcastRpcCommand(command, sync, false);
}
return retVal;
}
-
protected final boolean isSynchronous(InvocationContext ctx) {
if (ctx.hasFlag(Flag.FORCE_SYNCHRONOUS))
return true;
Modified: trunk/core/src/main/java/org/infinispan/marshall/Ids.java
===================================================================
--- trunk/core/src/main/java/org/infinispan/marshall/Ids.java 2010-09-15 16:19:59 UTC (rev 2385)
+++ trunk/core/src/main/java/org/infinispan/marshall/Ids.java 2010-09-15 19:09:38 UTC (rev 2386)
@@ -83,39 +83,38 @@
static final byte INVALIDATE_L1_COMMAND = 35;
static final byte LOCK_CONTROL_COMMAND = 36;
static final byte EVICT_COMMAND = 37;
-
// others
+
static final byte GLOBAL_TRANSACTION = 38;
static final byte JGROUPS_ADDRESS = 39;
static final byte MARSHALLED_VALUE = 40;
static final byte TRANSACTION_LOG_ENTRY = 41;
static final byte BUCKET = 42;
static final byte DEADLOCK_DETECTING_GLOBAL_TRANSACTION = 43;
-
/**
* ids for infinispan tree classes *
*/
static final byte NODE_KEY = 44;
- static final byte FQN = 45;
+ static final byte FQN = 45;
static final byte ATOMIC_HASH_MAP_DELTA = 46;
+
static final byte ATOMIC_PUT_OPERATION = 47;
static final byte ATOMIC_REMOVE_OPERATION = 48;
static final byte ATOMIC_CLEAR_OPERATION = 49;
-
static final byte REHASH_CONTROL_COMMAND = 50;
+
static final byte DEFAULT_CONSISTENT_HASH = 51;
static final byte UNION_CONSISTENT_HASH = 52;
static final byte JOIN_COMPLETE_COMMAND = 53;
-
/*
* ids for server modules
*/
+
static final byte SERVER_CACHE_VALUE = 55;
static final byte MEMCACHED_CACHE_VALUE = 56;
static final byte BYTE_ARRAY_KEY = 57;
static final byte TOPOLOGY_ADDRESS = 58;
static final byte TOPOLOGY_VIEW = 59;
-
}
Modified: trunk/core/src/main/java/org/infinispan/marshall/jboss/ConstantObjectTable.java
===================================================================
--- trunk/core/src/main/java/org/infinispan/marshall/jboss/ConstantObjectTable.java 2010-09-15 16:19:59 UTC (rev 2385)
+++ trunk/core/src/main/java/org/infinispan/marshall/jboss/ConstantObjectTable.java 2010-09-15 19:09:38 UTC (rev 2386)
@@ -73,7 +73,7 @@
import org.infinispan.remoting.responses.UnsuccessfulResponse;
import org.infinispan.remoting.responses.UnsureResponse;
import org.infinispan.remoting.transport.jgroups.JGroupsAddress;
-import org.infinispan.transaction.xa.DeadlockDetectingGlobalTransaction;
+import org.infinispan.transaction.xa.DldGlobalTransaction;
import org.infinispan.transaction.xa.GlobalTransaction;
import org.infinispan.util.ByteArrayKey;
import org.infinispan.util.FastCopyHashMap;
@@ -119,7 +119,7 @@
JDK_EXTERNALIZERS.put("java.util.Collections$SingletonList", SingletonListExternalizer.class.getName());
MARSHALLABLES.add(GlobalTransaction.class.getName());
- MARSHALLABLES.add(DeadlockDetectingGlobalTransaction.class.getName());
+ MARSHALLABLES.add(DldGlobalTransaction.class.getName());
MARSHALLABLES.add(JGroupsAddress.class.getName());
MARSHALLABLES.add("org.infinispan.util.Immutables$ImmutableMapWrapper");
MARSHALLABLES.add(MarshalledValue.class.getName());
Modified: trunk/core/src/main/java/org/infinispan/remoting/InboundInvocationHandlerImpl.java
===================================================================
--- trunk/core/src/main/java/org/infinispan/remoting/InboundInvocationHandlerImpl.java 2010-09-15 16:19:59 UTC (rev 2385)
+++ trunk/core/src/main/java/org/infinispan/remoting/InboundInvocationHandlerImpl.java 2010-09-15 19:09:38 UTC (rev 2386)
@@ -86,7 +86,7 @@
CommandsFactory commandsFactory = cr.getLocalComponent(CommandsFactory.class);
// initialize this command with components specific to the intended cache instance
- commandsFactory.initializeReplicableCommand(cmd);
+ commandsFactory.initializeReplicableCommand(cmd, true);
try {
log.trace("Calling perform() on {0}", cmd);
Modified: trunk/core/src/main/java/org/infinispan/statetransfer/StateTransferManagerImpl.java
===================================================================
--- trunk/core/src/main/java/org/infinispan/statetransfer/StateTransferManagerImpl.java 2010-09-15 16:19:59 UTC (rev 2385)
+++ trunk/core/src/main/java/org/infinispan/statetransfer/StateTransferManagerImpl.java 2010-09-15 19:09:38 UTC (rev 2386)
@@ -232,7 +232,7 @@
WriteCommand[] mods = logEntry.getModifications();
if (trace) log.trace("Mods = {0}", Arrays.toString(mods));
for (WriteCommand mod : mods) {
- commandsFactory.initializeReplicableCommand(mod);
+ commandsFactory.initializeReplicableCommand(mod, false);
ctx.setFlags(CACHE_MODE_LOCAL, Flag.SKIP_CACHE_STATUS_CHECK);
interceptorChain.invoke(ctx, mod);
}
@@ -265,7 +265,7 @@
if (!transactionLog.hasPendingPrepare(command)) {
if (trace) log.trace("Applying pending prepare {0}", command);
- commandsFactory.initializeReplicableCommand(command);
+ commandsFactory.initializeReplicableCommand(command, false);
RemoteTxInvocationContext ctx = invocationContextContainer.createRemoteTxInvocationContext();
RemoteTransaction transaction = txTable.createRemoteTransaction(command.getGlobalTransaction(), command.getModifications());
ctx.setRemoteTransaction(transaction);
Deleted: trunk/core/src/main/java/org/infinispan/transaction/xa/DeadlockDetectingGlobalTransaction.java
===================================================================
--- trunk/core/src/main/java/org/infinispan/transaction/xa/DeadlockDetectingGlobalTransaction.java 2010-09-15 16:19:59 UTC (rev 2385)
+++ trunk/core/src/main/java/org/infinispan/transaction/xa/DeadlockDetectingGlobalTransaction.java 2010-09-15 19:09:38 UTC (rev 2386)
@@ -1,191 +0,0 @@
-package org.infinispan.transaction.xa;
-
-import org.infinispan.marshall.Ids;
-import org.infinispan.marshall.Marshallable;
-import org.infinispan.remoting.transport.Address;
-import org.infinispan.util.logging.Log;
-import org.infinispan.util.logging.LogFactory;
-
-import java.io.IOException;
-import java.io.ObjectInput;
-import java.io.ObjectOutput;
-import java.util.Collections;
-import java.util.Set;
-
-/**
- * This class is used when deadlock detection is enabled.
- *
- * @author Mircea.Markus at jboss.com
- */
- at Marshallable(externalizer = DeadlockDetectingGlobalTransaction.Externalizer.class, id = Ids.DEADLOCK_DETECTING_GLOBAL_TRANSACTION)
-public class DeadlockDetectingGlobalTransaction extends GlobalTransaction {
-
- private static final Log log = LogFactory.getLog(DeadlockDetectingGlobalTransaction.class);
-
- public static final boolean trace = log.isTraceEnabled();
-
- private Set<Address> replicatingTo = Collections.EMPTY_SET;
-
- private volatile transient Thread processingThread;
-
- private volatile long coinToss;
-
- private volatile boolean isMarkedForRollback;
-
- private transient volatile Object lockIntention;
-
-
- public DeadlockDetectingGlobalTransaction() {
- }
-
- DeadlockDetectingGlobalTransaction(Address addr, boolean remote) {
- super(addr, remote);
- }
-
- DeadlockDetectingGlobalTransaction(boolean remote) {
- super(null, remote);
- }
-
- /**
- * Is this global transaction replicating to the given address?
- */
- public boolean isReplicatingTo(Address address) {
- if (this.replicatingTo == null) {
- return true;
- } else {
- return this.replicatingTo.contains(address);
- }
- }
-
- /**
- * On a node, this will set the thread that handles replicatin on the given node.
- */
- public void setProcessingThread(Thread replicationThread) {
- if (trace) log.trace("Setting thread " + Thread.currentThread() + "on tx [" + this + "]");
- this.processingThread = replicationThread;
- }
-
- /**
- * Tries to interrupt the processing thread.
- */
- public synchronized void interruptProcessingThread() {
- if (isMarkedForRollback) {
- if (trace) log.trace("Not interrupting as tx is marked for rollback");
- return;
- }
- if (processingThread == null) {
- if(trace) log.trace("Processing thread is null, nothing to interrupt");
- return;
- }
- if (trace) {
- StackTraceElement[] stackTraceElements = processingThread.getStackTrace();
- StringBuilder builder = new StringBuilder();
- for (StackTraceElement stackTraceElement : stackTraceElements) {
- builder.append(" ").append(stackTraceElement).append('\n');
- }
- log.trace("About to interrupt thread: " + processingThread + ". Thread's stack trace is: \n" + builder.toString());
- }
- this.processingThread.interrupt();
- }
-
- /**
- * Sets the set og <b>Address</b> objects this node is replicating to.
- */
- public void setReplicatingTo(Set<Address> targets) {
- this.replicatingTo = targets;
- }
-
- /**
- * Based on the coin toss, determine whether this tx will continue working or this thread will be stopped.
- */
- public boolean thisWillInterrupt(DeadlockDetectingGlobalTransaction globalTransaction) {
- return this.coinToss > globalTransaction.coinToss;
- }
-
- /**
- * Sets the reandom number that defines the coin toss.
- */
- public void setCoinToss(long coinToss) {
- this.coinToss = coinToss;
- }
-
- public long getCoinToss() {
- return coinToss;
- }
-
- @Override
- public boolean equals(Object o) {
- if (this == o) return true;
- if (!(o instanceof DeadlockDetectingGlobalTransaction)) return false;
- if (!super.equals(o)) return false;
-
- DeadlockDetectingGlobalTransaction that = (DeadlockDetectingGlobalTransaction) o;
-
- if (coinToss != that.coinToss) return false;
- if (replicatingTo != null ? !replicatingTo.equals(that.replicatingTo) : that.replicatingTo != null) return false;
-
- return true;
- }
-
- @Override
- public int hashCode() {
- int result = super.hashCode();
- result = 31 * result + (replicatingTo != null ? replicatingTo.hashCode() : 0);
- result = 31 * result + (int) (coinToss ^ (coinToss >>> 32));
- return result;
- }
-
- @Override
- public String toString() {
- return "DeadlockDetectingGlobalTransaction{" +
- "replicatingTo=" + replicatingTo +
- ", replicationThread=" + processingThread +
- ", coinToss=" + coinToss +
- "} " + super.toString();
- }
-
- /**
- * Once marked for rollback, the call to {@link #interruptProcessingThread()} will be ignored.
- */
- public synchronized boolean isMarkedForRollback() {
- return isMarkedForRollback;
- }
-
- public synchronized void setMarkedForRollback(boolean markedForRollback) {
- isMarkedForRollback = markedForRollback;
- }
-
- /**
- * Returns the key this transaction intends to lock.
- */
- public Object getLockIntention() {
- return lockIntention;
- }
-
- /**
- * Sets the lock this transaction intends to lock.
- */
- public void setLockIntention(Object lockIntention) {
- this.lockIntention = lockIntention;
- }
-
- public static class Externalizer extends GlobalTransaction.Externalizer {
- public Externalizer() {
- gtxFactory = new GlobalTransactionFactory(true);
- }
-
- @Override
- public void writeObject(ObjectOutput output, Object subject) throws IOException {
- super.writeObject(output, subject);
- DeadlockDetectingGlobalTransaction ddGt = (DeadlockDetectingGlobalTransaction) subject;
- output.writeLong(ddGt.getCoinToss());
- }
-
- @Override
- public Object readObject(ObjectInput input) throws IOException, ClassNotFoundException {
- DeadlockDetectingGlobalTransaction ddGt = (DeadlockDetectingGlobalTransaction) super.readObject(input);
- ddGt.setCoinToss(input.readLong());
- return ddGt;
- }
- }
-}
Copied: trunk/core/src/main/java/org/infinispan/transaction/xa/DldGlobalTransaction.java (from rev 2385, branches/4.2.x/core/src/main/java/org/infinispan/transaction/xa/DldGlobalTransaction.java)
===================================================================
--- trunk/core/src/main/java/org/infinispan/transaction/xa/DldGlobalTransaction.java (rev 0)
+++ trunk/core/src/main/java/org/infinispan/transaction/xa/DldGlobalTransaction.java 2010-09-15 19:09:38 UTC (rev 2386)
@@ -0,0 +1,175 @@
+package org.infinispan.transaction.xa;
+
+import org.infinispan.marshall.Ids;
+import org.infinispan.marshall.Marshallable;
+import org.infinispan.remoting.transport.Address;
+import org.infinispan.util.logging.Log;
+import org.infinispan.util.logging.LogFactory;
+
+import java.io.IOException;
+import java.io.ObjectInput;
+import java.io.ObjectOutput;
+import java.util.Collections;
+import java.util.Set;
+
+/**
+ * This class is used when deadlock detection is enabled.
+ *
+ * @author Mircea.Markus at jboss.com
+ */
+ at Marshallable(externalizer = DldGlobalTransaction.Externalizer.class, id = Ids.DEADLOCK_DETECTING_GLOBAL_TRANSACTION)
+public class DldGlobalTransaction extends GlobalTransaction {
+
+ private static Log log = LogFactory.getLog(DldGlobalTransaction.class);
+
+ public static final boolean trace = log.isTraceEnabled();
+
+ private volatile long coinToss;
+
+ private volatile boolean isMarkedForRollback;
+
+ private transient volatile Object localLockIntention;
+
+ protected volatile Set<Object> remoteLockIntention = Collections.EMPTY_SET;
+
+ private volatile Set<Object> locksAtOrigin = Collections.EMPTY_SET;
+
+ public DldGlobalTransaction() {
+ }
+
+ DldGlobalTransaction(Address addr, boolean remote) {
+ super(addr, remote);
+ }
+
+
+ /**
+ * Sets the reandom number that defines the coin toss.
+ */
+ public void setCoinToss(long coinToss) {
+ this.coinToss = coinToss;
+ }
+
+ public long getCoinToss() {
+ return coinToss;
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) return true;
+ if (!(o instanceof DldGlobalTransaction)) return false;
+ if (!super.equals(o)) return false;
+
+ DldGlobalTransaction that = (DldGlobalTransaction) o;
+
+ if (coinToss != that.coinToss) return false;
+ return true;
+ }
+
+ @Override
+ public int hashCode() {
+ int result = super.hashCode();
+ result = 31 * result + (int) (coinToss ^ (coinToss >>> 32));
+ return result;
+ }
+
+ @Override
+ public String toString() {
+ return "DldGlobalTransaction{" +
+ "coinToss=" + coinToss +
+ ", isMarkedForRollback=" + isMarkedForRollback +
+ ", lockIntention=" + localLockIntention +
+ ", affectedKeys=" + remoteLockIntention +
+ ", locksAtOrigin=" + locksAtOrigin +
+ "} " + super.toString();
+ }
+
+ public synchronized boolean isMarkedForRollback() {
+ return isMarkedForRollback;
+ }
+
+ public synchronized void setMarkedForRollback(boolean markedForRollback) {
+ isMarkedForRollback = markedForRollback;
+ }
+
+ /**
+ * Returns the key this transaction intends to lock.
+ */
+ public Object getLockIntention() {
+ return localLockIntention;
+ }
+
+ public void setLockIntention(Object lockIntention) {
+ this.localLockIntention = lockIntention;
+ }
+
+ public boolean wouldLose(DldGlobalTransaction other) {
+ return this.coinToss < other.coinToss;
+ }
+
+ public boolean isAcquiringRemoteLock(Object key, Address address) {
+ boolean contains = remoteLockIntention.contains(key);
+ if (trace) log.trace("Intention check: does " + remoteLockIntention + " contain " + key + "? " + contains);
+ return contains; //this works for replication
+ }
+
+ public void setRemoteLockIntention(Set<Object> remoteLockIntention) {
+ if (trace) {
+ log.trace("Setting the remote lock intention: " + remoteLockIntention);
+ }
+ this.remoteLockIntention = remoteLockIntention;
+ }
+
+ public Set<Object> getRemoteLockIntention() {
+ return remoteLockIntention;
+ }
+
+ public boolean hasLockAtOrigin(Set<Object> remoteLockIntention) {
+ if (log.isTraceEnabled()) log.trace("Our(" + this + ") locks at origin are: " + locksAtOrigin + ". Others remote lock intention is: " + remoteLockIntention);
+ for (Object key : remoteLockIntention) {
+ if (this.locksAtOrigin.contains(key)) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ public void setLocksHeldAtOrigin(Set<Object> locksAtOrigin) {
+ if (trace) log.trace("Setting locks at origin for (" + this + ") to " + locksAtOrigin);
+ this.locksAtOrigin = locksAtOrigin;
+ }
+
+ public Set<Object> getLocksHeldAtOrigin() {
+ return this.locksAtOrigin;
+ }
+
+ public static class Externalizer extends GlobalTransaction.Externalizer {
+ public Externalizer() {
+ gtxFactory = new GlobalTransactionFactory(true);
+ }
+
+ @Override
+ public void writeObject(ObjectOutput output, Object subject) throws IOException {
+ super.writeObject(output, subject);
+ DldGlobalTransaction ddGt = (DldGlobalTransaction) subject;
+ output.writeLong(ddGt.getCoinToss());
+ if (ddGt.locksAtOrigin.isEmpty()) {
+ output.writeObject(null);
+ } else {
+ output.writeObject(ddGt.locksAtOrigin);
+ }
+ }
+
+ @Override
+ public Object readObject(ObjectInput input) throws IOException, ClassNotFoundException {
+ DldGlobalTransaction ddGt = (DldGlobalTransaction) super.readObject(input);
+ ddGt.setCoinToss(input.readLong());
+ Object locksAtOriginObj = input.readObject();
+ if (locksAtOriginObj == null) {
+ ddGt.setLocksHeldAtOrigin(Collections.EMPTY_SET);
+ } else {
+ ddGt.setLocksHeldAtOrigin((Set<Object>) locksAtOriginObj);
+ }
+ return ddGt;
+ }
+ }
+}
Modified: trunk/core/src/main/java/org/infinispan/transaction/xa/GlobalTransaction.java
===================================================================
--- trunk/core/src/main/java/org/infinispan/transaction/xa/GlobalTransaction.java 2010-09-15 16:19:59 UTC (rev 2385)
+++ trunk/core/src/main/java/org/infinispan/transaction/xa/GlobalTransaction.java 2010-09-15 19:09:38 UTC (rev 2386)
@@ -106,7 +106,7 @@
@Override
public String toString() {
StringBuilder sb = new StringBuilder();
- sb.append("GlobalTransaction:<").append(addr).append(">:").append(id);
+ sb.append("GlobalTransaction:<").append(addr).append(">:").append(id).append(isRemote() ? ":remote" : ":local");
return sb.toString();
}
Modified: trunk/core/src/main/java/org/infinispan/transaction/xa/GlobalTransactionFactory.java
===================================================================
--- trunk/core/src/main/java/org/infinispan/transaction/xa/GlobalTransactionFactory.java 2010-09-15 16:19:59 UTC (rev 2385)
+++ trunk/core/src/main/java/org/infinispan/transaction/xa/GlobalTransactionFactory.java 2010-09-15 19:09:38 UTC (rev 2386)
@@ -1,6 +1,7 @@
package org.infinispan.transaction.xa;
import org.infinispan.config.Configuration;
+import org.infinispan.distribution.DistributionManager;
import org.infinispan.factories.annotations.Inject;
import org.infinispan.factories.annotations.Start;
import org.infinispan.remoting.transport.Address;
@@ -8,7 +9,7 @@
import java.util.Random;
/**
- * Factory for GlobalTransaction/DadlockDetectingGlobalTransaction.
+ * Factory for GlobalTransaction/DeadlockDetectingGlobalTransaction.
*
* @author Mircea.Markus at jboss.com
*/
@@ -16,6 +17,16 @@
private boolean isEddEnabled = false;
+ private DistributionManager distributionManager;
+
+ private Configuration configuration;
+
+ @Inject
+ public void init(DistributionManager distributionManager, Configuration configuration) {
+ this.distributionManager = distributionManager;
+ this.configuration = configuration;
+ }
+
/** this class is internally synchronized, so it can be shared between instances */
private final Random rnd = new Random();
@@ -43,7 +54,7 @@
public GlobalTransaction instantiateGlobalTransaction() {
if (isEddEnabled) {
- return new DeadlockDetectingGlobalTransaction();
+ return new DldGlobalTransaction();
} else {
return new GlobalTransaction();
}
@@ -52,13 +63,13 @@
public GlobalTransaction newGlobalTransaction(Address addr, boolean remote) {
GlobalTransaction gtx;
if (isEddEnabled) {
- DeadlockDetectingGlobalTransaction globalTransaction = new DeadlockDetectingGlobalTransaction(addr, remote);
+ DldGlobalTransaction globalTransaction;
+ globalTransaction = new DldGlobalTransaction(addr, remote);
globalTransaction.setCoinToss(generateRandomId());
gtx = globalTransaction;
} else {
gtx = new GlobalTransaction(addr, remote);
}
-
return gtx;
}
}
Modified: trunk/core/src/main/java/org/infinispan/transaction/xa/RemoteTransaction.java
===================================================================
--- trunk/core/src/main/java/org/infinispan/transaction/xa/RemoteTransaction.java 2010-09-15 16:19:59 UTC (rev 2385)
+++ trunk/core/src/main/java/org/infinispan/transaction/xa/RemoteTransaction.java 2010-09-15 19:09:38 UTC (rev 2386)
@@ -4,11 +4,15 @@
import org.infinispan.container.entries.CacheEntry;
import org.infinispan.util.BidirectionalLinkedHashMap;
import org.infinispan.util.BidirectionalMap;
+import org.infinispan.util.logging.Log;
+import org.infinispan.util.logging.LogFactory;
import java.util.ArrayList;
import java.util.Arrays;
+import java.util.HashSet;
import java.util.LinkedList;
import java.util.List;
+import java.util.Set;
/**
* Defines the state of a remotely originated transaction.
@@ -18,6 +22,8 @@
*/
public class RemoteTransaction implements CacheTransaction, Cloneable {
+ private static Log log = LogFactory.getLog(RemoteTransaction.class);
+
private List<WriteCommand> modifications;
private BidirectionalLinkedHashMap<Object, CacheEntry> lookedUpEntries;
@@ -58,6 +64,9 @@
}
public void putLookedUpEntry(Object key, CacheEntry e) {
+ if (log.isTraceEnabled()) {
+ log.trace("Adding key " + key + " to tx " + getGlobalTransaction());
+ }
lookedUpEntries.put(key, e);
}
@@ -103,4 +112,14 @@
", tx=" + tx +
'}';
}
+
+ public Set<Object> getLockedKeys() {
+ Set<Object> result = new HashSet<Object>();
+ for (Object key : getLookedUpEntries().keySet()) {
+ result.add(key);
+ }
+ if (lookedUpEntries.entrySet().size() != result.size())
+ throw new IllegalStateException("Different sizes!");
+ return result;
+ }
}
Modified: trunk/core/src/main/java/org/infinispan/transaction/xa/TransactionTable.java
===================================================================
--- trunk/core/src/main/java/org/infinispan/transaction/xa/TransactionTable.java 2010-09-15 16:19:59 UTC (rev 2385)
+++ trunk/core/src/main/java/org/infinispan/transaction/xa/TransactionTable.java 2010-09-15 19:09:38 UTC (rev 2386)
@@ -23,11 +23,12 @@
import org.infinispan.util.logging.LogFactory;
import javax.transaction.Transaction;
-import java.util.HashMap;
+import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
+import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.RejectedExecutionException;
@@ -44,9 +45,9 @@
private static final Log log = LogFactory.getLog(TransactionTable.class);
private static boolean trace = log.isTraceEnabled();
- private final Map<Transaction, TransactionXaAdapter> localTransactions = new HashMap<Transaction, TransactionXaAdapter>();
+ private final Map<Transaction, TransactionXaAdapter> localTransactions = new ConcurrentHashMap<Transaction, TransactionXaAdapter>();
- private final Map<GlobalTransaction, RemoteTransaction> remoteTransactions = new HashMap<GlobalTransaction, RemoteTransaction>();
+ private final Map<GlobalTransaction, RemoteTransaction> remoteTransactions = new ConcurrentHashMap<GlobalTransaction, RemoteTransaction>();
private CommandsFactory commandsFactory;
private Configuration configuration;
@@ -82,6 +83,12 @@
lockBreakingService.shutdownNow();
}
+ public Set<Object> getLockedKeysForRemoteTransaction(GlobalTransaction gtx) {
+ RemoteTransaction transaction = remoteTransactions.get(gtx);
+ if (transaction == null) return Collections.EMPTY_SET;
+ return transaction.getLockedKeys();
+ }
+
@Listener
public class StaleTransactionCleanup {
@ViewChanged
@@ -89,35 +96,47 @@
final List<Address> leavers = MembershipArithmetic.getMembersLeft(vce.getOldMembers(), vce.getNewMembers());
if (!leavers.isEmpty()) {
if (trace) log.trace("Saw {0} leavers - kicking off a lock breaking task", leavers.size());
- try {
- lockBreakingService.submit(new Runnable() {
- public void run() {
- Set<GlobalTransaction> toKill = new HashSet<GlobalTransaction>();
- for (GlobalTransaction gt : remoteTransactions.keySet()) {
- if (leavers.contains(gt.getAddress())) toKill.add(gt);
- }
+ cleanTxForWhichTheOwnerLeft(leavers);
+ if (configuration.isUseEagerLocking() && configuration.isEagerLockSingleNode() && configuration.getCacheMode().isDistributed()) {
+ for (TransactionXaAdapter xaAdapter : localTransactions.values()) {
+ if (xaAdapter.hasRemoteLocksAcquired(leavers)) {
+ xaAdapter.markForRollback();
+ }
+ }
+ }
+ }
+ }
- if (trace)
- log.trace("Global transactions {0} pertain to leavers list {1} and need to be killed", toKill, leavers);
+ private void cleanTxForWhichTheOwnerLeft(final List<Address> leavers) {
+ try {
+ lockBreakingService.submit(new Runnable() {
+ public void run() {
+ Set<GlobalTransaction> toKill = new HashSet<GlobalTransaction>();
+ for (GlobalTransaction gt : remoteTransactions.keySet()) {
+ if (leavers.contains(gt.getAddress())) toKill.add(gt);
+ }
- for (GlobalTransaction gtx : toKill) {
- if (trace) log.trace("Killing {0}", gtx);
- RollbackCommand rc = new RollbackCommand(gtx);
- rc.init(invoker, icc, TransactionTable.this);
- try {
- rc.perform(null);
- } catch (Throwable e) {
- log.warn("Unable to roll back gtx " + gtx, e);
- } finally {
- removeRemoteTransaction(gtx);
- }
+ if (trace)
+ log.trace("Global transactions {0} pertain to leavers list {1} and need to be killed", toKill, leavers);
+
+ for (GlobalTransaction gtx : toKill) {
+ if (trace) log.trace("Killing {0}", gtx);
+ RollbackCommand rc = new RollbackCommand(gtx);
+ rc.init(invoker, icc, TransactionTable.this);
+ try {
+ rc.perform(null);
+ } catch (Throwable e) {
+ log.warn("Unable to roll back gtx " + gtx, e);
+ } finally {
+ removeRemoteTransaction(gtx);
}
}
- });
- } catch (RejectedExecutionException ree) {
- log.debug("Unable to submit task to executor", ree);
- }
+ }
+ });
+ } catch (RejectedExecutionException ree) {
+ log.debug("Unable to submit task to executor", ree);
}
+
}
}
Modified: trunk/core/src/main/java/org/infinispan/transaction/xa/TransactionXaAdapter.java
===================================================================
--- trunk/core/src/main/java/org/infinispan/transaction/xa/TransactionXaAdapter.java 2010-09-15 16:19:59 UTC (rev 2385)
+++ trunk/core/src/main/java/org/infinispan/transaction/xa/TransactionXaAdapter.java 2010-09-15 19:09:38 UTC (rev 2386)
@@ -10,6 +10,7 @@
import org.infinispan.context.InvocationContextContainer;
import org.infinispan.context.impl.LocalTxInvocationContext;
import org.infinispan.interceptors.InterceptorChain;
+import org.infinispan.remoting.transport.Address;
import org.infinispan.util.BidirectionalLinkedHashMap;
import org.infinispan.util.BidirectionalMap;
import org.infinispan.util.InfinispanCollections;
@@ -21,7 +22,11 @@
import javax.transaction.xa.XAResource;
import javax.transaction.xa.Xid;
import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.HashSet;
import java.util.List;
+import java.util.Set;
/**
* This acts both as an local {@link org.infinispan.transaction.xa.CacheTransaction} and implementor of an {@link
@@ -50,6 +55,10 @@
private TransactionTable txTable;
private Transaction transaction;
+ private Set<Address> remoteLockedNodes;
+ private boolean isMarkedForRollback;
+
+
public TransactionXaAdapter(GlobalTransaction globalTx, InvocationContextContainer icc, InterceptorChain invoker,
CommandsFactory commandsFactory, Configuration configuration, TransactionTable txTable,
Transaction transaction) {
@@ -71,6 +80,7 @@
}
public int prepare(Xid xid) throws XAException {
+ checkMarkedForRollback();
if (configuration.isOnePhaseCommit()) {
if (trace)
log.trace("Received prepare for tx: " + xid + " . Skipping call as 1PC will be used.");
@@ -99,6 +109,7 @@
LocalTxInvocationContext ctx = icc.createTxInvocationContext();
ctx.setXaCache(this);
if (configuration.isOnePhaseCommit()) {
+ checkMarkedForRollback();
if (trace) log.trace("Doing an 1PC prepare call on the interceptor chain");
PrepareCommand command = commandsFactory.buildPrepareCommand(globalTx, modifications, true);
try {
@@ -243,4 +254,24 @@
", txTimeout=" + txTimeout +
'}';
}
+
+ public boolean hasRemoteLocksAcquired(List<Address> leavers) {
+ if (log.isTraceEnabled()) {
+ log.trace("My remote locks: " + remoteLockedNodes + ", leavers are:" + leavers);
+ }
+ return (remoteLockedNodes != null) && !Collections.disjoint(remoteLockedNodes, leavers);
+ }
+
+ public void locksAcquired(Collection<Address> nodes) {
+ if (remoteLockedNodes == null) remoteLockedNodes = new HashSet<Address>();
+ remoteLockedNodes.addAll(nodes);
+ }
+
+ public void markForRollback() {
+ isMarkedForRollback = true;
+ }
+
+ private void checkMarkedForRollback() throws XAException {
+ if (isMarkedForRollback) throw new XAException(XAException.XA_RBOTHER);
+ }
}
Modified: trunk/core/src/main/java/org/infinispan/util/concurrent/TimeoutException.java
===================================================================
--- trunk/core/src/main/java/org/infinispan/util/concurrent/TimeoutException.java 2010-09-15 16:19:59 UTC (rev 2385)
+++ trunk/core/src/main/java/org/infinispan/util/concurrent/TimeoutException.java 2010-09-15 19:09:38 UTC (rev 2386)
@@ -29,11 +29,7 @@
* from all members.
*
* @author <a href="mailto:bela at jboss.org">Bela Ban</a>.
- * <p/>
- * <p/>
- * <p><b>Revisions:</b>
- * <p/>
- * <p>Dec 28 2002 Bela Ban: first implementation
+ * @author Mircea.Markus at jboss.com
* @since 4.0
*/
public class TimeoutException extends CacheException {
Modified: trunk/core/src/main/java/org/infinispan/util/concurrent/locks/DeadlockDetectedException.java
===================================================================
--- trunk/core/src/main/java/org/infinispan/util/concurrent/locks/DeadlockDetectedException.java 2010-09-15 16:19:59 UTC (rev 2385)
+++ trunk/core/src/main/java/org/infinispan/util/concurrent/locks/DeadlockDetectedException.java 2010-09-15 19:09:38 UTC (rev 2386)
@@ -1,6 +1,7 @@
package org.infinispan.util.concurrent.locks;
import org.infinispan.CacheException;
+import org.infinispan.util.concurrent.TimeoutException;
/**
* Exception signaling detected deadlocks.
Modified: trunk/core/src/main/java/org/infinispan/util/concurrent/locks/DeadlockDetectingLockManager.java
===================================================================
--- trunk/core/src/main/java/org/infinispan/util/concurrent/locks/DeadlockDetectingLockManager.java 2010-09-15 16:19:59 UTC (rev 2385)
+++ trunk/core/src/main/java/org/infinispan/util/concurrent/locks/DeadlockDetectingLockManager.java 2010-09-15 19:09:38 UTC (rev 2386)
@@ -1,13 +1,11 @@
package org.infinispan.util.concurrent.locks;
import org.infinispan.context.InvocationContext;
-import org.infinispan.context.impl.TxInvocationContext;
import org.infinispan.factories.annotations.Start;
import org.infinispan.jmx.annotations.MBean;
import org.infinispan.jmx.annotations.ManagedAttribute;
import org.infinispan.jmx.annotations.ManagedOperation;
-import org.infinispan.remoting.transport.Address;
-import org.infinispan.transaction.xa.DeadlockDetectingGlobalTransaction;
+import org.infinispan.transaction.xa.DldGlobalTransaction;
import org.infinispan.util.logging.Log;
import org.infinispan.util.logging.LogFactory;
import org.rhq.helpers.pluginAnnotations.agent.MeasurementType;
@@ -15,10 +13,21 @@
import org.rhq.helpers.pluginAnnotations.agent.Operation;
import static java.util.concurrent.TimeUnit.MILLISECONDS;
+
import java.util.concurrent.atomic.AtomicLong;
/**
* Lock manager in charge with processing deadlock detections.
+ * Implementation notes: if a deadlock is detected, then one of the transactions has to rollback. The transaction that
+ * rollbacks is determined by comparing the coin toss from {@link org.infinispan.transaction.xa.DldGlobalTransaction}.
+ * A thread calling {@link DeadlockDetectingLockManager#lockAndRecord(Object, org.infinispan.context.InvocationContext)}
+ * would run the deadlock detection algorithm only if all of the following take place:
+ * - the call is made in the scope of a transaction (either locally originated or remotely originated)
+ * - it cannot acquire lock on the given key and the lock owner is another transaction
+ * - when comparing coin toss, this thread would loose against the other one - so it's always the potential loser that runs DLD.
+ * If deadlock is detected then {@link #lockAndRecord(Object, org.infinispan.context.InvocationContext)} would throw an
+ * {@link org.infinispan.util.concurrent.locks.DeadlockDetectedException}. This is subsequently handled in
+ * in the interceptor chain - locsk owned by this tx are released.
*
* @author Mircea.Markus at jboss.com
*/
@@ -31,52 +40,49 @@
protected volatile boolean exposeJmxStats;
- private volatile boolean isSync;
+ private AtomicLong localTxStopped = new AtomicLong(0);
- private AtomicLong detectedRemoteDeadlocks = new AtomicLong(0);
+ private AtomicLong remoteTxStopped = new AtomicLong(0);
- private AtomicLong detectedLocalDeadlocks = new AtomicLong(0);
+ private AtomicLong cannotRunDld = new AtomicLong(0);
- private AtomicLong locallyInterruptedTransactions = new AtomicLong(0);
-
- private AtomicLong overlapWithNotDeadlockAwareLockOwners = new AtomicLong(0);
-
@Start
public void init() {
spinDuration = configuration.getDeadlockDetectionSpinDuration();
exposeJmxStats = configuration.isExposeJmxStatistics();
- isSync = configuration.getCacheMode().isSynchronous();
}
public boolean lockAndRecord(Object key, InvocationContext ctx) throws InterruptedException {
long lockTimeout = getLockAcquisitionTimeout(ctx);
if (trace) log.trace("Attempting to lock {0} with acquisition timeout of {1} millis", key, lockTimeout);
+
if (ctx.isInTxScope()) {
if (trace) log.trace("Using early dead lock detection");
final long start = System.currentTimeMillis();
- long now;
- while ((now = System.currentTimeMillis()) < (start + lockTimeout)) {
+ DldGlobalTransaction thisTx = (DldGlobalTransaction) ctx.getLockOwner();
+ thisTx.setLockIntention(key);
+ if (trace) log.trace("Setting lock intention to: " + key);
+
+ while (System.currentTimeMillis() < (start + lockTimeout)) {
if (lockContainer.acquireLock(key, spinDuration, MILLISECONDS) != null) {
+ thisTx.setLockIntention(null); //clear lock intention
if (trace) log.trace("successfully acquired lock on " + key + ", returning ...");
return true;
} else {
- if (trace)
- log.trace("Could not acquire lock on '" + key + "' as it is locked by '" + getOwner(key) + "', check for dead locks");
Object owner = getOwner(key);
- if (!(owner instanceof DeadlockDetectingGlobalTransaction)) {
- if (trace)
- log.trace("Owner is not instance of DeadlockDetectingGlobalTransaction: " + owner + ", continuing ...");
- if (exposeJmxStats) overlapWithNotDeadlockAwareLockOwners.incrementAndGet();
- continue; //try to acquire lock again, for the rest of the time
+ if (!(owner instanceof DldGlobalTransaction)) {
+ if (trace) log.trace("Not running DLD as lock owner( " + owner + ") is not a transaction");
+ cannotRunDld.incrementAndGet();
+ continue;
}
- DeadlockDetectingGlobalTransaction lockOwnerTx = (DeadlockDetectingGlobalTransaction) owner;
- if (isSync && !ctx.isOriginLocal() && !lockOwnerTx.isRemote()) {
- return remoteVsRemoteDld(key, ctx, lockTimeout, start, now, lockOwnerTx);
+ DldGlobalTransaction lockOwnerTx = (DldGlobalTransaction) owner;
+ if (isDeadlockAndIAmLoosing(lockOwnerTx, thisTx, key)) {
+ updateStats(thisTx);
+ String message = "Deadlock found and we " + thisTx + " shall not continue. Other tx is " + lockOwnerTx;
+ if (trace) log.trace(message);
+ throw new DeadlockDetectedException(message);
}
- if ((ctx.isOriginLocal() && !lockOwnerTx.isRemote()) || (!isSync && !ctx.isOriginLocal() && !lockOwnerTx.isRemote())) {
- localVsLocalDld(ctx, lockOwnerTx);
- }
}
}
} else {
@@ -88,100 +94,95 @@
return false;
}
- private void localVsLocalDld(InvocationContext ctx, DeadlockDetectingGlobalTransaction lockOwnerTx) {
- if (trace) log.trace("Looking for local vs local deadlocks");
- DeadlockDetectingGlobalTransaction thisThreadsTx = (DeadlockDetectingGlobalTransaction) ctx.getLockOwner();
- boolean weOwnLock = ownsLock(lockOwnerTx.getLockIntention(), thisThreadsTx);
- if (trace) {
- log.trace("Other owner's intention is " + lockOwnerTx.getLockIntention() + ". Do we(" + thisThreadsTx + ") own lock for it? " + weOwnLock + ". Lock owner is " + getOwner(lockOwnerTx.getLockIntention()));
+ private boolean isDeadlockAndIAmLoosing(DldGlobalTransaction lockOwnerTx, DldGlobalTransaction thisTx, Object key) {
+ //run the lose check first as it is cheaper
+ boolean wouldWeLoose = thisTx.wouldLose(lockOwnerTx);
+ if (!wouldWeLoose) {
+ if (trace) log.trace("We (" + thisTx + ") wouldn't lose against the other(" + lockOwnerTx + ") transaction, so no point running rest of DLD");
+ return false;
}
- if (weOwnLock) {
- boolean iShouldInterrupt = thisThreadsTx.thisWillInterrupt(lockOwnerTx);
- if (trace)
- log.trace("deadlock situation detected. Shall I interrupt?" + iShouldInterrupt );
- if (iShouldInterrupt) {
- lockOwnerTx.interruptProcessingThread();
- if (exposeJmxStats) detectedLocalDeadlocks.incrementAndGet();
- }
- }
+ //do we have lock on what other tx intends to acquire?
+ return ownsLocalIntention(thisTx, lockOwnerTx.getLockIntention()) || ownsRemoteIntention(lockOwnerTx, thisTx, key);
}
- private boolean remoteVsRemoteDld(Object key, InvocationContext ctx, long lockTimeout, long start, long now, DeadlockDetectingGlobalTransaction lockOwnerTx) throws InterruptedException {
- TxInvocationContext remoteTxContext = (TxInvocationContext) ctx;
- Address origin = remoteTxContext.getGlobalTransaction().getAddress();
- DeadlockDetectingGlobalTransaction remoteGlobalTransaction = (DeadlockDetectingGlobalTransaction) ctx.getLockOwner();
- boolean thisShouldInterrupt = remoteGlobalTransaction.thisWillInterrupt(lockOwnerTx);
- if (trace) log.trace("Should I interrupt other transaction ? " + thisShouldInterrupt);
- boolean isDeadLock = (configuration.getCacheMode().isReplicated() || lockOwnerTx.isReplicatingTo(origin)) && !lockOwnerTx.isRemote();
- if (thisShouldInterrupt && isDeadLock) {
- lockOwnerTx.interruptProcessingThread();
- if (exposeJmxStats) {
- detectedRemoteDeadlocks.incrementAndGet();
- locallyInterruptedTransactions.incrementAndGet();
+ /**
+ * This happens with two nodes replicating same tx at the same time.
+ */
+ private boolean ownsRemoteIntention(DldGlobalTransaction lockOwnerTx, DldGlobalTransaction thisTx, Object key) {
+ if (!lockOwnerTx.isRemote()) {
+ // I've already acquired lock on this key before replicating here, so this mean we are in deadlock. This assumes the fact that
+ // if trying to acquire a remote lock, a tx first acquires a local lock.
+ if (thisTx.hasLockAtOrigin(lockOwnerTx.getRemoteLockIntention())) {
+ if (trace)
+ log.trace("Same key deadlock detected: lock owner tries to acquire lock remotely on " + key + " but we have it!");
+ return true;
}
- return lockForTheRemainingTime(key, lockTimeout, start, now);
- } else if (!isDeadLock) {
- return lockForTheRemainingTime(key, lockTimeout, start, now);
} else {
- if (trace)
- log.trace("Not trying to acquire lock anymore, as we're in deadlock and this will be rollback at origin");
- if (exposeJmxStats) {
- detectedRemoteDeadlocks.incrementAndGet();
- }
- remoteGlobalTransaction.setMarkedForRollback(true);
- throw new DeadlockDetectedException("Deadlock situation detected on tx: " + remoteTxContext.getLockOwner());
+ if (trace) log.trace("Lock owner is remote: " + lockOwnerTx);
}
+ return false;
}
- private boolean lockForTheRemainingTime(Object key, long lockTimeout, long start, long now) throws InterruptedException {
- long remainingLockingTime = (start + lockTimeout) - now;
- if (remainingLockingTime < 0)
- throw new IllegalStateException("No remaining time!!! The outer while condition MUST make sure this always stands true!");
- if (trace) log.trace("trying to lock for the remaining time: " + remainingLockingTime + " millis ");
- return lockContainer.acquireLock(key, remainingLockingTime, MILLISECONDS) != null;
+ private boolean ownsLocalIntention(DldGlobalTransaction thisTx, Object intention) {
+ boolean result = intention != null && ownsLock(intention, thisTx);
+ if (trace) log.trace("Local intention is '" + intention + "'. Do we own lock for it? " + result + " We == " + thisTx);
+ return result;
}
public void setExposeJmxStats(boolean exposeJmxStats) {
this.exposeJmxStats = exposeJmxStats;
}
- @ManagedAttribute(description = "Number of situtations when we try to determine a deadlock and the other lock owner is e.g. a local tx. In this scenario we cannot run the deadlock detection mechanism")
- @Metric(displayName = "Number of unsolvable deadlock situations", measurementType = MeasurementType.TRENDSUP)
- public long getOverlapWithNotDeadlockAwareLockOwners() {
- return overlapWithNotDeadlockAwareLockOwners.get();
+
+ @ManagedAttribute (description = "Total number of local detected deadlocks")
+ @Metric(displayName = "Number of total detected deadlocks", measurementType = MeasurementType.TRENDSUP)
+ public long getTotalNumberOfDetectedDeadlocks() {
+ return localTxStopped.get() + remoteTxStopped.get();
}
- @ManagedAttribute(description = "Number of locally originated transactions that were interrupted as a deadlock situation was detected")
- @Metric(displayName = "Number of interrupted local transactions", measurementType = MeasurementType.TRENDSUP)
- public long getLocallyInterruptedTransactions() {
- return locallyInterruptedTransactions.get();
+ @ManagedOperation(description = "Resets statistics gathered by this component")
+ @Operation(displayName = "Reset statistics")
+ public void resetStatistics() {
+ localTxStopped.set(0);
+ remoteTxStopped.set(0);
+ cannotRunDld.set(0);
}
- @ManagedAttribute(description = "Number of remote deadlocks detected")
- @Metric(displayName = "Number of detected remote deadlocks", measurementType = MeasurementType.TRENDSUP)
+ @ManagedAttribute(description = "Number of remote transaction that were roll backed due to deadlocks")
+ @Metric(displayName = "Number of remote transaction that were roll backed due to deadlocks", measurementType = MeasurementType.TRENDSUP)
public long getDetectedRemoteDeadlocks() {
- return detectedRemoteDeadlocks.get();
+ return remoteTxStopped.get();
}
- @ManagedAttribute (description = "Number of local detected deadlocks")
- @Metric(displayName = "Number of detected local deadlocks", measurementType = MeasurementType.TRENDSUP)
+ @ManagedAttribute (description = "Number of local transaction that were roll backed due to deadlocks")
+ @Metric(displayName = "Number of local transaction that were roll backed due to deadlocks", measurementType = MeasurementType.TRENDSUP)
public long getDetectedLocalDeadlocks() {
- return detectedLocalDeadlocks.get();
+ return localTxStopped.get();
}
- @ManagedAttribute (description = "Total number of local detected deadlocks")
- @Metric(displayName = "Number of total detected deadlocks", measurementType = MeasurementType.TRENDSUP)
- public long getTotalNumberOfDetectedDeadlocks() {
- return detectedRemoteDeadlocks.get() + detectedLocalDeadlocks.get();
+ @ManagedAttribute(description = "Number of situtations when we try to determine a deadlock and the other lock owner is NOT a transaction. In this scenario we cannot run the deadlock detection mechanism")
+ @Metric(displayName = "Number of unsolvable deadlock situations", measurementType = MeasurementType.TRENDSUP)
+ public long getOverlapWithNotDeadlockAwareLockOwners() {
+ return cannotRunDld.get();
}
- @ManagedOperation(description = "Resets statistics gathered by this component")
- @Operation(displayName = "Reset statistics")
- public void resetStatistics() {
- overlapWithNotDeadlockAwareLockOwners.set(0);
- locallyInterruptedTransactions.set(0);
- detectedRemoteDeadlocks.set(0);
- detectedLocalDeadlocks.set(0);
+
+
+ private void updateStats(DldGlobalTransaction tx) {
+ if (exposeJmxStats) {
+ if (tx.isRemote())
+ remoteTxStopped.incrementAndGet();
+ else
+ localTxStopped.incrementAndGet();
+ }
}
+
+ @ManagedAttribute(description = "Number of locally originated transactions that were interrupted as a deadlock situation was detected")
+ @Metric(displayName = "Number of interrupted local transactions", measurementType = MeasurementType.TRENDSUP)
+ @Deprecated
+ public long getLocallyInterruptedTransactions() {
+ return -1;
+ }
+
}
Modified: trunk/core/src/main/resources/config-samples/all.xml
===================================================================
--- trunk/core/src/main/resources/config-samples/all.xml 2010-09-15 16:19:59 UTC (rev 2385)
+++ trunk/core/src/main/resources/config-samples/all.xml 2010-09-15 19:09:38 UTC (rev 2386)
@@ -81,7 +81,7 @@
transactionManagerLookupClass="org.infinispan.transaction.lookup.GenericTransactionManagerLookup"
syncRollbackPhase="false"
syncCommitPhase="false"
- useEagerLocking="false"/>
+ useEagerLocking="true" eagerLockSingleNode="true"/>
<!--
Used to register JMX statistics in any available MBean server
Modified: trunk/core/src/test/java/org/infinispan/api/mvcc/LockTestBase.java
===================================================================
--- trunk/core/src/test/java/org/infinispan/api/mvcc/LockTestBase.java 2010-09-15 16:19:59 UTC (rev 2385)
+++ trunk/core/src/test/java/org/infinispan/api/mvcc/LockTestBase.java 2010-09-15 19:09:38 UTC (rev 2386)
@@ -270,7 +270,7 @@
catch (TimeoutException expected) {
// expected.printStackTrace(); // for debugging
}
- tm.commit();
+ tm.rollback();
tm.resume(t1);
tm.commit();
assertNoLocks();
Modified: trunk/core/src/test/java/org/infinispan/config/parsing/XmlFileParsingTest.java
===================================================================
--- trunk/core/src/test/java/org/infinispan/config/parsing/XmlFileParsingTest.java 2010-09-15 16:19:59 UTC (rev 2385)
+++ trunk/core/src/test/java/org/infinispan/config/parsing/XmlFileParsingTest.java 2010-09-15 19:09:38 UTC (rev 2386)
@@ -18,6 +18,8 @@
import org.testng.annotations.Test;
import java.io.ByteArrayInputStream;
+import java.io.File;
+import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.Map;
@@ -160,6 +162,7 @@
assert c.getTransactionManagerLookupClass().equals("org.infinispan.transaction.lookup.GenericTransactionManagerLookup");
assert c.isUseEagerLocking();
+ assert c.isEagerLockSingleNode();
assert !c.isSyncRollbackPhase();
c = namedCaches.get("syncRepl");
Deleted: trunk/core/src/test/java/org/infinispan/distribution/DeadlockDetectionDistributionTest.java
===================================================================
--- trunk/core/src/test/java/org/infinispan/distribution/DeadlockDetectionDistributionTest.java 2010-09-15 16:19:59 UTC (rev 2385)
+++ trunk/core/src/test/java/org/infinispan/distribution/DeadlockDetectionDistributionTest.java 2010-09-15 19:09:38 UTC (rev 2386)
@@ -1,42 +0,0 @@
-package org.infinispan.distribution;
-
-import org.infinispan.config.Configuration;
-import org.infinispan.tx.ReplDeadlockDetectionTest;
-import static org.testng.Assert.fail;
-import org.testng.annotations.Test;
-
-/**
- * Test deadlock detection when cache is configured for distribution.
- *
- * @author Mircea.Markus at jboss.com
- */
- at Test(groups = "functional", enabled = false, testName = "distribution.DeadlockDetectionDistributionTest")
-public class DeadlockDetectionDistributionTest extends ReplDeadlockDetectionTest {
-
- public DeadlockDetectionDistributionTest() {
- cacheMode = Configuration.CacheMode.DIST_SYNC;
- }
-
-
- public void testDeadlockDetectedTwoTransactions() throws Exception {
- fail("This test should be updated to make sure tx replicate on opposite nodes");
- }
-
-
- //following methods are overridden as TestNG will otherwise run them even if I mark the class as enabled = false
-
- @Override
- public void testExpectedInnerStructure() {
- throw new IllegalStateException("TODO - please implement me!!!"); //todo implement!!!
- }
-
- @Override
- public void testDeadlockDetectedOneTx() throws Exception {
- throw new IllegalStateException("TODO - please implement me!!!"); //todo implement!!!
- }
-
- @Override
- public void testLockReleasedWhileTryingToAcquire() throws Exception {
- throw new IllegalStateException("TODO - please implement me!!!"); //todo implement!!!
- }
-}
Modified: trunk/core/src/test/java/org/infinispan/loaders/dummy/DummyInMemoryCacheStore.java
===================================================================
--- trunk/core/src/test/java/org/infinispan/loaders/dummy/DummyInMemoryCacheStore.java 2010-09-15 16:19:59 UTC (rev 2385)
+++ trunk/core/src/test/java/org/infinispan/loaders/dummy/DummyInMemoryCacheStore.java 2010-09-15 19:09:38 UTC (rev 2386)
@@ -31,6 +31,7 @@
public void store(InternalCacheEntry ed) {
if (ed != null) {
if (trace) log.trace("Store {0} in dummy map store@{1}", ed, Integer.toHexString(System.identityHashCode(store)));
+ config.failIfNeeded(ed.getKey());
store.put(ed.getKey(), ed);
}
}
@@ -158,6 +159,7 @@
boolean debug;
String store = "__DEFAULT_STORE__";
boolean cleanBetweenRestarts = true;
+ private Object failKey;
public Cfg() {
setCacheLoaderClassName(DummyInMemoryCacheStore.class.getName());
@@ -197,5 +199,13 @@
public boolean isCleanBetweenRestarts() {
return cleanBetweenRestarts;
}
+
+ public void setFailKey(Object failKey) {
+ this.failKey = failKey;
+ }
+
+ public void failIfNeeded(Object key) {
+ if(failKey != null && failKey.equals(key)) throw new RuntimeException("Induced failure on key:" + key);
+ }
}
}
Deleted: trunk/core/src/test/java/org/infinispan/lock/EagerLockingDisabledTest.java
===================================================================
--- trunk/core/src/test/java/org/infinispan/lock/EagerLockingDisabledTest.java 2010-09-15 16:19:59 UTC (rev 2385)
+++ trunk/core/src/test/java/org/infinispan/lock/EagerLockingDisabledTest.java 2010-09-15 19:09:38 UTC (rev 2386)
@@ -1,50 +0,0 @@
-package org.infinispan.lock;
-
-import org.infinispan.Cache;
-import org.infinispan.config.Configuration;
-import org.infinispan.config.ConfigurationException;
-import org.infinispan.manager.EmbeddedCacheManager;
-import org.infinispan.test.TestingUtil;
-import org.infinispan.test.fwk.TestCacheManagerFactory;
-import org.testng.annotations.Test;
-
-/**
- * Tester for https://jira.jboss.org/browse/ISPN-596
- *
- * @author Mircea.Markus at jboss.com
- * @since 4.1
- */
- at Test (groups = "functional", testName = "lock.EagerLockingDisabledTest")
-public class EagerLockingDisabledTest {
-
- public void testImplicitEagerLockingAndDld() {
- Configuration configuration = TestCacheManagerFactory.getDefaultConfiguration(false);
- configuration.setEnableDeadlockDetection(true);
- configuration.setUseEagerLocking(true);
- EmbeddedCacheManager cm = null;
- try {
- cm = TestCacheManagerFactory.createCacheManager(configuration);
- assert false : "expecting configuration exception";
- } catch (ConfigurationException ce) {
- //expected
- }
- finally {
- TestingUtil.killCacheManagers(cm);
- }
- }
-
- public void testExplicitEagerLockingAndDld() {
- Configuration configuration = TestCacheManagerFactory.getDefaultConfiguration(false);
- configuration.setEnableDeadlockDetection(true);
- EmbeddedCacheManager cm = TestCacheManagerFactory.createCacheManager(configuration);
- Cache c = cm.getCache();
- try {
- c.getAdvancedCache().lock("k");
- } catch (ConfigurationException ce) {
- //expected
- }
- finally {
- TestingUtil.killCacheManagers(cm);
- }
- }
-}
Copied: trunk/core/src/test/java/org/infinispan/lock/EagerLockingSingleLockTest.java (from rev 2385, branches/4.2.x/core/src/test/java/org/infinispan/lock/EagerLockingSingleLockTest.java)
===================================================================
--- trunk/core/src/test/java/org/infinispan/lock/EagerLockingSingleLockTest.java (rev 0)
+++ trunk/core/src/test/java/org/infinispan/lock/EagerLockingSingleLockTest.java 2010-09-15 19:09:38 UTC (rev 2386)
@@ -0,0 +1,164 @@
+package org.infinispan.lock;
+
+import org.infinispan.affinity.KeyAffinityService;
+import org.infinispan.affinity.KeyAffinityServiceFactory;
+import org.infinispan.affinity.RndKeyGenerator;
+import org.infinispan.config.Configuration;
+import org.infinispan.distribution.BaseDistFunctionalTest;
+import org.infinispan.test.MultipleCacheManagersTest;
+import org.infinispan.test.TestingUtil;
+import org.infinispan.util.concurrent.TimeoutException;
+import org.infinispan.util.logging.Log;
+import org.infinispan.util.logging.LogFactory;
+import org.testng.annotations.AfterClass;
+import org.testng.annotations.Test;
+
+import javax.transaction.RollbackException;
+import javax.transaction.Status;
+import javax.transaction.Transaction;
+import javax.transaction.TransactionManager;
+import java.util.concurrent.ArrayBlockingQueue;
+import java.util.concurrent.ThreadPoolExecutor;
+import java.util.concurrent.TimeUnit;
+
+import static org.testng.Assert.assertEquals;
+
+/**
+ * Tester for https://jira.jboss.org/browse/ISPN-615.
+ *
+ * @author Mircea.Markus at jboss.com
+ * @since 4.2
+ */
+ at Test(groups = "functional", testName = "lock.EagerLockingSingleLockTest")
+public class EagerLockingSingleLockTest extends MultipleCacheManagersTest {
+ private KeyAffinityService kaf;
+ private ThreadPoolExecutor poolExecutor;
+
+ private static Log log = LogFactory.getLog(EagerLockingSingleLockTest.class);
+
+ @Override
+ protected void createCacheManagers() throws Throwable {
+ Configuration config = getDefaultClusteredConfig(Configuration.CacheMode.DIST_SYNC, true);
+ config.setEagerLockSingleNode(true);
+ config.setNumOwners(2);
+ config.setLockAcquisitionTimeout(2000);
+ config.setUseEagerLocking(true);
+ config.setL1CacheEnabled(false);
+ createClusteredCaches(4, config);
+ TestingUtil.blockUntilViewReceived(cache(0), 4, 10000);
+ BaseDistFunctionalTest.RehashWaiter.waitForInitRehashToComplete(cache(0), cache(1), cache(2), cache(3));
+ poolExecutor = new ThreadPoolExecutor(1, 1, 1000, TimeUnit.MILLISECONDS, new ArrayBlockingQueue<Runnable>(10));
+ kaf = KeyAffinityServiceFactory.newKeyAffinityService(cache(0), poolExecutor, new RndKeyGenerator(), 10, true);
+ }
+
+ @AfterClass
+ public void cleanUp() {
+ kaf.stop();
+ poolExecutor.shutdownNow();
+ }
+
+ public void testSingleLockAcquiredRemotely() throws Exception {
+ log.trace("0 -> " + address(0));
+ log.trace("1 -> " + address(1));
+ log.trace("2 -> " + address(2));
+ log.trace("3 -> " + address(3));
+
+ Object k = kaf.getKeyForAddress(address(3));
+ cache(1).put(k, "1stValue");
+ TransactionManager tm = cache(0).getAdvancedCache().getTransactionManager();
+ tm.begin();
+ cache(1).put(k, "2ndValue");
+ assert !TestingUtil.extractLockManager(cache(0)).isLocked(k);
+ assert TestingUtil.extractLockManager(cache(1)).isLocked(k);
+ assert !TestingUtil.extractLockManager(cache(2)).isLocked(k);
+ assert TestingUtil.extractLockManager(cache(3)).isLocked(k);
+
+ Transaction lockOwnerTx = tm.suspend();
+
+ //now make sure other transactions won't be able to acquire locks
+ tm.begin();
+ try {
+ cache(2).put(k, "3rdValue");
+ assert false;
+ } catch (TimeoutException e) {
+ assertEquals(tm.getStatus(), Status.STATUS_MARKED_ROLLBACK);
+ }
+ tm.rollback();
+
+ //now check that the only node that has a remote lock is cache(3)
+ assert !TestingUtil.extractLockManager(cache(0)).isLocked(k);
+ assert !TestingUtil.extractLockManager(cache(2)).isLocked(k);
+ assert TestingUtil.extractLockManager(cache(3)).isLocked(k);
+
+ tm.resume(lockOwnerTx);
+ tm.commit();
+
+ //no locks are being held now
+ assert !TestingUtil.extractLockManager(cache(0)).isLocked(k);
+ assert !TestingUtil.extractLockManager(cache(1)).isLocked(k);
+ assert !TestingUtil.extractLockManager(cache(2)).isLocked(k);
+ assert !TestingUtil.extractLockManager(cache(3)).isLocked(k);
+
+ assertEquals(cache(0).get(k), "2ndValue");
+ }
+
+ @Test(dependsOnMethods = "testSingleLockAcquiredRemotely")
+ public void testSingleLockAcquiredLocally() throws Exception {
+ Object k = kaf.getKeyForAddress(address(1));
+ cache(1).put(k, "1stValue");
+ TransactionManager tm = cache(0).getAdvancedCache().getTransactionManager();
+
+ tm.begin();
+ cache(1).put(k, "2ndValue");//this acquires a local cache only
+
+ //now check that the only node that has a remote lock is cache(3)
+ assert !TestingUtil.extractLockManager(cache(0)).isLocked(k);
+ assert TestingUtil.extractLockManager(cache(1)).isLocked(k);
+ assert !TestingUtil.extractLockManager(cache(2)).isLocked(k);
+ assert !TestingUtil.extractLockManager(cache(3)).isLocked(k);
+
+ tm.commit();
+
+ //no locks are being held now
+ assert !TestingUtil.extractLockManager(cache(0)).isLocked(k);
+ assert !TestingUtil.extractLockManager(cache(1)).isLocked(k);
+ assert !TestingUtil.extractLockManager(cache(2)).isLocked(k);
+ assert !TestingUtil.extractLockManager(cache(3)).isLocked(k);
+
+ assertEquals(cache(0).get(k), "2ndValue");
+ }
+
+ @Test(dependsOnMethods = "testSingleLockAcquiredLocally")
+ public void testLockOwnerFailure() throws Exception {
+ Object k = kaf.getKeyForAddress(address(3));
+ cache(1).put(k, "1stValue");
+ final TransactionManager tm = cache(0).getAdvancedCache().getTransactionManager();
+
+ tm.begin();
+ cache(1).put(k, "2ndValue");
+
+ //now check that the only node that has a remote lock is cache(3)
+ assert !TestingUtil.extractLockManager(cache(0)).isLocked(k);
+ assert !TestingUtil.extractLockManager(cache(2)).isLocked(k);
+ assert TestingUtil.extractLockManager(cache(3)).isLocked(k);
+
+ manager(3).stop();
+ TestingUtil.blockUntilViewReceived(cache(0), 3, 10000);
+ BaseDistFunctionalTest.RehashWaiter.waitForInitRehashToComplete(cache(0), cache(1), cache(2));
+
+ try {
+ log.trace("here it begins");
+ tm.commit();
+ assert false;
+ } catch (RollbackException re) {
+ //expected
+ }
+
+ //no locks are being held now
+ assert !TestingUtil.extractLockManager(cache(0)).isLocked(k);
+ assert !TestingUtil.extractLockManager(cache(1)).isLocked(k);
+ assert !TestingUtil.extractLockManager(cache(2)).isLocked(k);
+
+ assertEquals(cache(0).get(k), "1stValue");
+ }
+}
Modified: trunk/core/src/test/java/org/infinispan/notifications/cachelistener/CacheNotifierTest.java
===================================================================
--- trunk/core/src/test/java/org/infinispan/notifications/cachelistener/CacheNotifierTest.java 2010-09-15 16:19:59 UTC (rev 2385)
+++ trunk/core/src/test/java/org/infinispan/notifications/cachelistener/CacheNotifierTest.java 2010-09-15 19:09:38 UTC (rev 2386)
@@ -26,13 +26,14 @@
private TransactionManager tm;
private CacheNotifier mockNotifier;
private CacheNotifier origNotifier;
+ private CacheContainer cm;
@BeforeMethod(alwaysRun = true)
public void setUp() throws Exception {
Configuration c = new Configuration();
c.setCacheMode(Configuration.CacheMode.LOCAL);
c.setIsolationLevel(IsolationLevel.REPEATABLE_READ);
- CacheContainer cm = TestCacheManagerFactory.createCacheManager(c, true);
+ cm = TestCacheManagerFactory.createCacheManager(c, true);
cache = cm.getCache();
tm = TestingUtil.getTransactionManager(cache);
@@ -44,6 +45,7 @@
public void tearDown() throws Exception {
TestingUtil.replaceComponent(cache, CacheNotifier.class, origNotifier, true);
TestingUtil.killCaches(cache);
+ cm.stop();
}
@AfterClass
Modified: trunk/core/src/test/java/org/infinispan/statetransfer/StateTransferReplicationQueueTest.java
===================================================================
--- trunk/core/src/test/java/org/infinispan/statetransfer/StateTransferReplicationQueueTest.java 2010-09-15 16:19:59 UTC (rev 2385)
+++ trunk/core/src/test/java/org/infinispan/statetransfer/StateTransferReplicationQueueTest.java 2010-09-15 19:09:38 UTC (rev 2386)
@@ -17,13 +17,11 @@
import java.io.ObjectOutput;
import java.lang.reflect.Method;
import java.util.Properties;
-import java.util.concurrent.ExecutorService;
-import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicBoolean;
/**
- * State transfer and replication queue test veryfying that the interaction between them two works in fine.
+ * State transfer and replication queue test verifying that the interaction between them two works in fine.
*
* @author Galder Zamarre�o
* @since 4.1
Modified: trunk/core/src/test/java/org/infinispan/test/AbstractInfinispanTest.java
===================================================================
--- trunk/core/src/test/java/org/infinispan/test/AbstractInfinispanTest.java 2010-09-15 16:19:59 UTC (rev 2385)
+++ trunk/core/src/test/java/org/infinispan/test/AbstractInfinispanTest.java 2010-09-15 19:09:38 UTC (rev 2386)
@@ -21,31 +21,57 @@
*/
package org.infinispan.test;
+import org.testng.annotations.AfterTest;
+
import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
-import org.testng.annotations.AfterTest;
+import static org.testng.Assert.assertEquals;
/**
- * AbstractInfinispanTest is a superclass of all Infinispan tests.
- *
+ * AbstractInfinispanTest is a superclass of all Infinispan tests.
+ *
* @author Vladimir Blagojevic
+ * @author Mircea.Markus at jboss.com
* @since 4.0
*/
public class AbstractInfinispanTest {
-
- @AfterTest(alwaysRun=true)
+
+ @AfterTest(alwaysRun = true)
protected void nullifyInstanceFields() {
- for(Class<?> current = this.getClass();current.getSuperclass() != null; current = current.getSuperclass()) {
+ for (Class<?> current = this.getClass(); current.getSuperclass() != null; current = current.getSuperclass()) {
Field[] fields = current.getDeclaredFields();
- for(Field f:fields) {
- try {
- if(!Modifier.isStatic(f.getModifiers()) && !f.getDeclaringClass().isPrimitive()) {
+ for (Field f : fields) {
+ try {
+ if (!Modifier.isStatic(f.getModifiers()) && !f.getDeclaringClass().isPrimitive()) {
f.setAccessible(true);
f.set(this, null);
}
- } catch (Exception e) {}
- }
- }
+ } catch (Exception e) {}
+ }
+ }
}
+
+ public void eventually(Condition ec, long timeout) {
+ int loops = 10;
+ long sleepDuration = timeout / loops;
+ try {
+ for (int i = 0; i < loops; i++) {
+
+ if (ec.isSatisfied()) break;
+ Thread.sleep(sleepDuration);
+ }
+ assertEquals(true, ec.isSatisfied());
+ } catch (Exception e) {
+ throw new RuntimeException("Unexpected!", e);
+ }
+ }
+
+ public void eventually(Condition ec) {
+ eventually(ec, 10000);
+ }
+
+ public interface Condition {
+ public boolean isSatisfied() throws Exception;
+ }
}
Modified: trunk/core/src/test/java/org/infinispan/test/MultipleCacheManagersTest.java
===================================================================
--- trunk/core/src/test/java/org/infinispan/test/MultipleCacheManagersTest.java 2010-09-15 16:19:59 UTC (rev 2385)
+++ trunk/core/src/test/java/org/infinispan/test/MultipleCacheManagersTest.java 2010-09-15 19:09:38 UTC (rev 2386)
@@ -4,6 +4,7 @@
import org.infinispan.config.Configuration;
import org.infinispan.manager.CacheContainer;
import org.infinispan.manager.EmbeddedCacheManager;
+import org.infinispan.remoting.transport.Address;
import org.infinispan.test.fwk.TestCacheManagerFactory;
import org.testng.annotations.AfterClass;
import org.testng.annotations.AfterMethod;
@@ -211,4 +212,8 @@
* {@link #addClusterEnabledCacheManager()}
*/
protected abstract void createCacheManagers() throws Throwable;
+
+ public Address address(int cacheIndex) {
+ return cache(cacheIndex).getAdvancedCache().getRpcManager().getAddress();
+ }
}
Modified: trunk/core/src/test/java/org/infinispan/test/PerCacheExecutorThread.java
===================================================================
--- trunk/core/src/test/java/org/infinispan/test/PerCacheExecutorThread.java 2010-09-15 16:19:59 UTC (rev 2385)
+++ trunk/core/src/test/java/org/infinispan/test/PerCacheExecutorThread.java 2010-09-15 19:09:38 UTC (rev 2386)
@@ -4,6 +4,7 @@
import org.infinispan.util.logging.Log;
import org.infinispan.util.logging.LogFactory;
+import javax.transaction.Transaction;
import javax.transaction.TransactionManager;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.BlockingQueue;
@@ -24,6 +25,7 @@
private BlockingQueue<Object> toExecute = new ArrayBlockingQueue<Object>(1);
private volatile Object response;
private CountDownLatch responseLatch = new CountDownLatch(1);
+ private volatile Transaction ongoingTransaction;
private volatile Object key, value;
@@ -75,6 +77,7 @@
TransactionManager txManager = TestingUtil.getTransactionManager(cache);
try {
txManager.begin();
+ ongoingTransaction = txManager.getTransaction();
setResponse(OperationsResult.BEGGIN_TX_OK);
} catch (Exception e) {
log.trace("Failure on beggining tx", e);
@@ -86,6 +89,7 @@
TransactionManager txManager = TestingUtil.getTransactionManager(cache);
try {
txManager.commit();
+ ongoingTransaction = null;
setResponse(OperationsResult.COMMIT_TX_OK);
} catch (Exception e) {
log.trace("Exception while committing tx", e);
@@ -210,6 +214,9 @@
*/
public static enum OperationsResult {
BEGGIN_TX_OK, COMMIT_TX_OK, PUT_KEY_VALUE_OK, REMOVE_KEY_OK, REPLACE_KEY_VALUE_OK, STOP_THREAD_OK
+ }
+ public Transaction getOngoingTransaction() {
+ return ongoingTransaction;
}
}
Modified: trunk/core/src/test/java/org/infinispan/test/TestingUtil.java
===================================================================
--- trunk/core/src/test/java/org/infinispan/test/TestingUtil.java 2010-09-15 16:19:59 UTC (rev 2385)
+++ trunk/core/src/test/java/org/infinispan/test/TestingUtil.java 2010-09-15 19:09:38 UTC (rev 2386)
@@ -30,6 +30,7 @@
import org.infinispan.remoting.transport.Address;
import org.infinispan.remoting.transport.Transport;
import org.infinispan.remoting.transport.jgroups.JGroupsTransport;
+import org.infinispan.transaction.xa.TransactionTable;
import org.infinispan.util.concurrent.locks.LockManager;
import org.infinispan.util.logging.Log;
import org.infinispan.util.logging.LogFactory;
@@ -837,4 +838,8 @@
public static Object v(Method method) {
return v(method, "");
}
+
+ public static TransactionTable getTransactionTable(Cache<Object, Object> cache) {
+ return cache.getAdvancedCache().getComponentRegistry().getComponent(TransactionTable.class);
+ }
}
Modified: trunk/core/src/test/java/org/infinispan/test/fwk/TestCacheManagerFactory.java
===================================================================
--- trunk/core/src/test/java/org/infinispan/test/fwk/TestCacheManagerFactory.java 2010-09-15 16:19:59 UTC (rev 2385)
+++ trunk/core/src/test/java/org/infinispan/test/fwk/TestCacheManagerFactory.java 2010-09-15 19:09:38 UTC (rev 2386)
@@ -16,13 +16,15 @@
import java.io.IOException;
import java.io.InputStream;
import java.util.HashMap;
+import java.util.HashSet;
import java.util.Map;
import java.util.Properties;
+import java.util.Set;
import java.util.concurrent.atomic.AtomicInteger;
/**
- * CacheManagers in unit tests should be created with this factory, in order to avoid resource clashes.
- * See http://community.jboss.org/wiki/ParallelTestSuite for more details.
+ * CacheManagers in unit tests should be created with this factory, in order to avoid resource clashes. See
+ * http://community.jboss.org/wiki/ParallelTestSuite for more details.
*
* @author Mircea.Markus at jboss.com
* @author Galder Zamarreño
@@ -51,9 +53,9 @@
public static EmbeddedCacheManager fromXml(String xmlFile, boolean allowDupeDomains) throws IOException {
InfinispanConfiguration parser = InfinispanConfiguration.newInfinispanConfiguration(
- xmlFile,
- InfinispanConfiguration.resolveSchemaPath(),
- new ConfigurationValidatingVisitor());
+ xmlFile,
+ InfinispanConfiguration.resolveSchemaPath(),
+ new ConfigurationValidatingVisitor());
return fromConfigFileParser(parser, allowDupeDomains);
}
@@ -67,8 +69,8 @@
public static EmbeddedCacheManager fromStream(InputStream is, boolean allowDupeDomains) throws IOException {
InfinispanConfiguration parser = InfinispanConfiguration.newInfinispanConfiguration(
- is, InfinispanConfiguration.findSchemaInputStream(),
- new ConfigurationValidatingVisitor());
+ is, InfinispanConfiguration.findSchemaInputStream(),
+ new ConfigurationValidatingVisitor());
return fromConfigFileParser(parser, allowDupeDomains);
}
@@ -81,7 +83,7 @@
minimizeThreads(gc);
EmbeddedCacheManager cm = newDefaultCacheManager(true, gc, c, false);
- for (Map.Entry<String, Configuration> e: named.entrySet()) cm.defineConfiguration(e.getKey(), e.getValue());
+ for (Map.Entry<String, Configuration> e : named.entrySet()) cm.defineConfiguration(e.getKey(), e.getValue());
cm.start();
return cm;
}
@@ -126,9 +128,7 @@
globalConfiguration.setTransportNodeName(perThreadCacheManagers.get().getNextCacheName());
amendMarshaller(globalConfiguration);
minimizeThreads(globalConfiguration);
- Properties newTransportProps = new Properties();
- newTransportProps.put(JGroupsTransport.CONFIGURATION_STRING, JGroupsConfigBuilder.getJGroupsConfig());
- globalConfiguration.setTransportProperties(newTransportProps);
+ amendTransport(globalConfiguration);
return newDefaultCacheManager(true, globalConfiguration, defaultCacheConfig, false);
}
@@ -145,9 +145,10 @@
}
/**
- * Creates a cache manager that won't try to modify the configured jmx domain name: {@link org.infinispan.config.GlobalConfiguration#getJmxDomain()}}.
- * This method must be used with care, and one should make sure that no domain name collision happens when the parallel suite executes.
- * An approach to ensure this, is to set the domain name to the name of the test class that instantiates the CacheManager.
+ * Creates a cache manager that won't try to modify the configured jmx domain name: {@link
+ * org.infinispan.config.GlobalConfiguration#getJmxDomain()}}. This method must be used with care, and one should
+ * make sure that no domain name collision happens when the parallel suite executes. An approach to ensure this, is
+ * to set the domain name to the name of the test class that instantiates the CacheManager.
*/
public static EmbeddedCacheManager createCacheManagerEnforceJmxDomain(GlobalConfiguration configuration) {
return internalCreateJmxDomain(true, configuration, true);
@@ -183,10 +184,13 @@
public static EmbeddedCacheManager createCacheManager(Configuration defaultCacheConfig, boolean transactional) {
GlobalConfiguration globalConfiguration;
- if (defaultCacheConfig.getCacheMode().isClustered())
+ if (defaultCacheConfig.getCacheMode().isClustered()) {
globalConfiguration = GlobalConfiguration.getClusteredDefault();
- else
+ amendTransport(globalConfiguration);
+ }
+ else {
globalConfiguration = GlobalConfiguration.getNonClusteredDefault();
+ }
amendMarshaller(globalConfiguration);
minimizeThreads(globalConfiguration);
if (transactional) amendJTA(defaultCacheConfig);
@@ -247,7 +251,7 @@
if (configuration.getTransportClass() != null) { //this is local
Properties newTransportProps = new Properties();
Properties previousSettings = configuration.getTransportProperties();
- if (previousSettings!=null) {
+ if (previousSettings != null) {
newTransportProps.putAll(previousSettings);
}
newTransportProps.put(JGroupsTransport.CONFIGURATION_STRING, JGroupsConfigBuilder.getJGroupsConfig());
@@ -276,6 +280,7 @@
DefaultCacheManager defaultCacheManager = new DefaultCacheManager(gc, c, start);
PerThreadCacheManagers threadCacheManagers = perThreadCacheManagers.get();
String methodName = extractMethodName();
+ log.trace("Adding DCM (" + defaultCacheManager.getAddress() + ") for method: '" + methodName + "'");
threadCacheManagers.add(methodName, defaultCacheManager);
return defaultCacheManager;
}
@@ -283,8 +288,7 @@
private static String extractMethodName() {
StackTraceElement[] stack = Thread.currentThread().getStackTrace();
if (stack.length == 0) return null;
- for (int i = stack.length - 1; i > 0; i--)
- {
+ for (int i = stack.length - 1; i > 0; i--) {
StackTraceElement e = stack[i];
String className = e.getClassName();
if ((className.indexOf("org.infinispan") != -1) && className.indexOf("org.infinispan.test") < 0)
@@ -298,17 +302,16 @@
}
private static class PerThreadCacheManagers {
- HashMap<String, EmbeddedCacheManager> cacheManagers = new HashMap<String, EmbeddedCacheManager>();
+ HashMap<EmbeddedCacheManager, String> cacheManagers = new HashMap<EmbeddedCacheManager, String>();
public void checkManagersClosed(String testName) {
- for (String cmName : cacheManagers.keySet()) {
- EmbeddedCacheManager cm = cacheManagers.get(cmName);
- if (cm.getStatus().allowInvocations()) {
+ for (Map.Entry<EmbeddedCacheManager, String> cmEntry : cacheManagers.entrySet()) {
+ if (cmEntry.getKey().getStatus().allowInvocations()) {
String thName = Thread.currentThread().getName();
String errorMessage = '\n' +
"!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n" +
"!!!!!! (" + thName + ") Exiting because " + testName + " has NOT shut down all the cache managers it has started !!!!!!!\n" +
- "!!!!!! (" + thName + ") The still-running cacheManager was created here: " + cmName + " !!!!!!!\n" +
+ "!!!!!! (" + thName + ") The still-running cacheManager was created here: " + cmEntry.getValue() + " !!!!!!!\n" +
"!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n";
log.error(errorMessage);
System.err.println(errorMessage);
@@ -319,13 +322,13 @@
}
public String getNextCacheName() {
- int index = cacheManagers.keySet().size();
- char name = (char) ((int)'A' + index);
+ int index = cacheManagers.size();
+ char name = (char) ((int) 'A' + index);
return "Node" + name;
}
public void add(String methodName, DefaultCacheManager cm) {
- cacheManagers.put(methodName, cm);
+ cacheManagers.put(cm, methodName);
}
}
}
Deleted: trunk/core/src/test/java/org/infinispan/tx/AsyncDeadlockDetectionTest.java
===================================================================
--- trunk/core/src/test/java/org/infinispan/tx/AsyncDeadlockDetectionTest.java 2010-09-15 16:19:59 UTC (rev 2385)
+++ trunk/core/src/test/java/org/infinispan/tx/AsyncDeadlockDetectionTest.java 2010-09-15 19:09:38 UTC (rev 2386)
@@ -1,183 +0,0 @@
-package org.infinispan.tx;
-
-import org.infinispan.Cache;
-import org.infinispan.commands.VisitableCommand;
-import org.infinispan.commands.write.PutKeyValueCommand;
-import org.infinispan.config.Configuration;
-import org.infinispan.context.InvocationContext;
-import org.infinispan.interceptors.base.CommandInterceptor;
-import org.infinispan.test.MultipleCacheManagersTest;
-import org.infinispan.test.PerCacheExecutorThread;
-import org.infinispan.test.TestingUtil;
-import org.infinispan.transaction.xa.TransactionTable;
-import org.infinispan.util.concurrent.locks.DeadlockDetectedException;
-import org.infinispan.util.concurrent.locks.DeadlockDetectingLockManager;
-import org.infinispan.util.concurrent.locks.LockManager;
-import static org.testng.Assert.assertEquals;
-import static org.testng.Assert.assertFalse;
-import org.testng.annotations.AfterMethod;
-import org.testng.annotations.BeforeMethod;
-import org.testng.annotations.Test;
-
-/**
- * Tests deadlock detection for async caches.
- *
- * @author Mircea.Markus at jboss.com
- */
- at Test(groups = "functional", testName = "tx.AsyncDeadlockDetectionTest")
-public class AsyncDeadlockDetectionTest extends MultipleCacheManagersTest {
- private PerCacheExecutorThread t0;
- private PerCacheExecutorThread t1;
- private RemoteReplicationInterceptor remoteReplicationInterceptor;
-
-
- protected void createCacheManagers() throws Throwable {
- Configuration config = getDefaultClusteredConfig(Configuration.CacheMode.REPL_ASYNC, true);
- config.setEnableDeadlockDetection(true);
- config.setSyncCommitPhase(true);
- config.setSyncRollbackPhase(true);
- config.setUseLockStriping(false);
- assert config.isEnableDeadlockDetection();
- createClusteredCaches(2, "test", config);
- assert config.isEnableDeadlockDetection();
-
-
- remoteReplicationInterceptor = new RemoteReplicationInterceptor();
- Cache cache0 = cache(0, "test");
- Cache cache1 = cache(1, "test");
- cache1.getAdvancedCache().addInterceptor(remoteReplicationInterceptor, 0);
- assert cache0.getConfiguration().isEnableDeadlockDetection();
- assert cache1.getConfiguration().isEnableDeadlockDetection();
- assert !cache0.getConfiguration().isExposeJmxStatistics();
- assert !cache1.getConfiguration().isExposeJmxStatistics();
-
- ((DeadlockDetectingLockManager) TestingUtil.extractLockManager(cache0)).setExposeJmxStats(true);
- ((DeadlockDetectingLockManager) TestingUtil.extractLockManager(cache1)).setExposeJmxStats(true);
- }
-
- @BeforeMethod
- public void beforeMethod() {
- Cache cache0 = cache(0, "test");
- Cache cache1 = cache(1, "test");
- t0 = new PerCacheExecutorThread(cache0, 0);
- t1 = new PerCacheExecutorThread(cache1, 1);
- }
-
- @AfterMethod
- public void afterMethod() {
- Cache cache0 = cache(0, "test");
- Cache cache1 = cache(1, "test");
- t0.stopThread();
- t1.stopThread();
- ((DeadlockDetectingLockManager) TestingUtil.extractLockManager(cache0)).resetStatistics();
- ((DeadlockDetectingLockManager) TestingUtil.extractLockManager(cache1)).resetStatistics();
- remoteReplicationInterceptor.executionResponse = null;
- remoteReplicationInterceptor = null;
- t0 = null;
- t1 = null;
- }
-
- public void testRemoteTxVsLocal() throws Exception {
- Cache cache0 = cache(0, "test");
- Cache cache1 = cache(1, "test");
- assertEquals(PerCacheExecutorThread.OperationsResult.BEGGIN_TX_OK, t0.execute(PerCacheExecutorThread.Operations.BEGGIN_TX));
- t0.setKeyValue("k1", "v1_t0");
- assertEquals(PerCacheExecutorThread.OperationsResult.PUT_KEY_VALUE_OK, t0.execute(PerCacheExecutorThread.Operations.PUT_KEY_VALUE));
- t0.setKeyValue("k2", "v2_t0");
- assertEquals(PerCacheExecutorThread.OperationsResult.PUT_KEY_VALUE_OK, t0.execute(PerCacheExecutorThread.Operations.PUT_KEY_VALUE));
-
- assertEquals(PerCacheExecutorThread.OperationsResult.BEGGIN_TX_OK, t1.execute(PerCacheExecutorThread.Operations.BEGGIN_TX));
- t1.setKeyValue("k2", "v2_t1");
- assertEquals(PerCacheExecutorThread.OperationsResult.PUT_KEY_VALUE_OK, t1.execute(PerCacheExecutorThread.Operations.PUT_KEY_VALUE));
-
- t0.execute(PerCacheExecutorThread.Operations.COMMIT_TX);
-
- LockManager lockManager = TestingUtil.extractLockManager(cache1);
- while (!lockManager.isLocked("k1")) {
- Thread.sleep(50);
- }
- System.out.println("successful replication !");
-
-
- t1.setKeyValue("k1", "v1_t1");
- t1.executeNoResponse(PerCacheExecutorThread.Operations.PUT_KEY_VALUE);
-
-
- Object t1Response = t1.waitForResponse();
- Object t0Response = remoteReplicationInterceptor.getResponse();
-
- System.out.println("t0Response = " + t0Response);
- System.out.println("t1Response = " + t1Response);
-
- assert xor(t1Response instanceof DeadlockDetectedException, t0Response instanceof DeadlockDetectedException);
-
- if (t0Response instanceof DeadlockDetectedException) {
- replListener(cache0).expectWithTx(PutKeyValueCommand.class, PutKeyValueCommand.class);
- assertEquals(t1.execute(PerCacheExecutorThread.Operations.COMMIT_TX), PerCacheExecutorThread.OperationsResult.COMMIT_TX_OK);
- replListener(cache0).waitForRpc();
- }
-
- DeadlockDetectingLockManager ddLm0 = (DeadlockDetectingLockManager) TestingUtil.extractLockManager(cache0);
- DeadlockDetectingLockManager ddLm1 = (DeadlockDetectingLockManager) TestingUtil.extractLockManager(cache1);
-
- assertFalse(ddLm0.isLocked("k1"));
- assertFalse(ddLm1.isLocked("k1"));
- assertFalse(ddLm0.isLocked("k2"));
- assertFalse(ddLm1.isLocked("k2"));
- TransactionTable transactionTable0 = TestingUtil.extractComponent(cache0, TransactionTable.class);
- assertEquals(transactionTable0.getLocalTxCount(), 0);
- for (int i = 0; i < 20; i++) {
- if (!(transactionTable0.getRemoteTxCount() == 0)) Thread.sleep(50);
- }
-
- assertEquals(transactionTable0.getRemoteTxCount(), 0);
-
- TransactionTable transactionTable1 = TestingUtil.extractComponent(cache1, TransactionTable.class);
- assertEquals(transactionTable1.getLocalTxCount(), 0);
- for (int i = 0; i < 20; i++) {
- if (!(transactionTable1.getRemoteTxCount() == 0)) Thread.sleep(50);
- }
- assertEquals(transactionTable1.getRemoteTxCount(), 0);
-
- if (t1Response instanceof DeadlockDetectedException) {
- assertEquals(cache0.get("k1"), "v1_t0");
- assertEquals(cache0.get("k2"), "v2_t0");
- assertEquals(cache1.get("k1"), "v1_t0");
- assertEquals(cache1.get("k2"), "v2_t0");
- } else {
- assertEquals(cache0.get("k1"), "v1_t1");
- assertEquals(cache0.get("k2"), "v2_t1");
- assertEquals(cache1.get("k1"), "v1_t1");
- assertEquals(cache1.get("k2"), "v2_t1");
- }
- }
-
-
- public static class RemoteReplicationInterceptor extends CommandInterceptor {
-
- public volatile Object executionResponse;
-
- @Override
- protected Object handleDefault(InvocationContext ctx, VisitableCommand command) throws Throwable {
- try {
- return invokeNextInterceptor(ctx, command);
- } catch (Throwable throwable) {
- if (!ctx.isOriginLocal()) {
- log.trace("Setting thrownExceptionForRemoteTx to " + throwable);
- executionResponse = throwable;
- } else {
- log.trace("Ignoring throwable " + throwable);
- executionResponse = "NONE";
- }
- throw throwable;
- }
- }
-
- public Object getResponse() throws Exception {
- while (executionResponse == null) {
- Thread.sleep(50);
- }
- return executionResponse;
- }
- }
-}
Deleted: trunk/core/src/test/java/org/infinispan/tx/LocalDeadlockDetectionTest.java
===================================================================
--- trunk/core/src/test/java/org/infinispan/tx/LocalDeadlockDetectionTest.java 2010-09-15 16:19:59 UTC (rev 2385)
+++ trunk/core/src/test/java/org/infinispan/tx/LocalDeadlockDetectionTest.java 2010-09-15 19:09:38 UTC (rev 2386)
@@ -1,191 +0,0 @@
-package org.infinispan.tx;
-
-import org.infinispan.config.Configuration;
-import org.infinispan.manager.EmbeddedCacheManager;
-import org.infinispan.test.PerCacheExecutorThread;
-import org.infinispan.test.SingleCacheManagerTest;
-import org.infinispan.test.TestingUtil;
-import org.infinispan.test.fwk.TestCacheManagerFactory;
-import org.infinispan.util.concurrent.locks.DeadlockDetectedException;
-import org.infinispan.util.concurrent.locks.DeadlockDetectingLockManager;
-import static org.testng.Assert.assertEquals;
-
-import org.testng.annotations.AfterMethod;
-import org.testng.annotations.BeforeMethod;
-import org.testng.annotations.Test;
-
-import javax.transaction.RollbackException;
-
-/**
- * Tests deadlock detection functionality for local caches.
- *
- * @author Mircea.Markus at jboss.com
- */
- at Test(groups = "functional", testName = "tx.LocalDeadlockDetectionTest")
-public class LocalDeadlockDetectionTest extends SingleCacheManagerTest {
-
- private PerCacheExecutorThread t1;
- private PerCacheExecutorThread t2;
- private DeadlockDetectingLockManager lockManager;
- private Object response1;
- private Object response2;
-
- protected EmbeddedCacheManager createCacheManager() throws Exception {
- cacheManager = TestCacheManagerFactory.createLocalCacheManager();
- Configuration configuration = getDefaultStandaloneConfig(true);
- configuration.setEnableDeadlockDetection(true);
- configuration.setUseLockStriping(false);
- configuration.setExposeJmxStatistics(true);
- cacheManager.defineConfiguration("test", configuration);
- cache = cacheManager.getCache("test");
- lockManager = (DeadlockDetectingLockManager) TestingUtil.extractLockManager(cache);
- return cacheManager;
- }
-
- @BeforeMethod
- public void startExecutors() {
- t1 = new PerCacheExecutorThread(cache, 0);
- t2 = new PerCacheExecutorThread(cache, 1);
- lockManager.resetStatistics();
- }
-
-
- @AfterMethod
- public void stopExecutors() {
- t1.stopThread();
- t2.stopThread();
- }
-
- public void testDldPutAndPut() {
- testLocalVsLocalTxDeadlock(PerCacheExecutorThread.Operations.PUT_KEY_VALUE,
- PerCacheExecutorThread.Operations.PUT_KEY_VALUE);
- if (response1 instanceof Exception) {
- assertEquals("value_1_t2", cache.get("k1"));
- assertEquals("value_2_t2", cache.get("k2"));
- } else {
- assertEquals("value_1_t1", cache.get("k1"));
- assertEquals("value_2_t1", cache.get("k2"));
- }
- }
-
- public void testDldPutAndRemove() {
- testLocalVsLocalTxDeadlock(PerCacheExecutorThread.Operations.PUT_KEY_VALUE,
- PerCacheExecutorThread.Operations.REMOVE_KEY);
- if (response1 instanceof Exception) {
- assertEquals(cache.get("k1"), null);
- assertEquals("value_2_t2", cache.get("k2"));
- } else {
- assertEquals("value_1_t1", cache.get("k1"));
- assertEquals(null, cache.get("k2"));
- }
- }
-
- public void testDldRemoveAndPut() {
- testLocalVsLocalTxDeadlock(PerCacheExecutorThread.Operations.REMOVE_KEY,
- PerCacheExecutorThread.Operations.PUT_KEY_VALUE);
- if (response1 instanceof Exception) {
- System.out.println("t1 failure");
- assertEquals(cache.get("k1"), "value_1_t2");
- assertEquals(cache.get("k2"), null);
- } else {
- System.out.println("t2 failure");
- assertEquals(cache.get("k1"), null);
- assertEquals(cache.get("k2"), "value_2_t1");
- }
- }
-
- public void testDldRemoveAndRemove() {
- testLocalVsLocalTxDeadlock(PerCacheExecutorThread.Operations.REMOVE_KEY,
- PerCacheExecutorThread.Operations.REMOVE_KEY);
- if (response1 instanceof Exception) {
- System.out.println("t1 failure");
- assertEquals(cache.get("k1"), null);
- assertEquals(cache.get("k2"), null);
- } else {
- System.out.println("t2 failure");
- assertEquals(cache.get("k1"), null);
- assertEquals(cache.get("k2"), null);
- }
- }
-
- public void testDldPutAndReplace() {
-
- cache.put("k1", "initial_1");
- cache.put("k2", "initial_2");
-
- testLocalVsLocalTxDeadlock(PerCacheExecutorThread.Operations.PUT_KEY_VALUE,
- PerCacheExecutorThread.Operations.REPLACE_KEY_VALUE);
- if (response1 instanceof Exception) {
- System.out.println("t1 failure");
- assertEquals(cache.get("k1"), "value_1_t2");
- assertEquals(cache.get("k2"), "value_2_t2");
- } else {
- System.out.println("t2 failure");
- assertEquals(cache.get("k1"), "value_1_t1");
- assertEquals(cache.get("k2"), "value_2_t1");
- }
- }
-
- public void testDldReplaceAndPut() {
-
- cache.put("k1", "initial_1");
- cache.put("k2", "initial_2");
-
- testLocalVsLocalTxDeadlock(PerCacheExecutorThread.Operations.REPLACE_KEY_VALUE,
- PerCacheExecutorThread.Operations.PUT_KEY_VALUE);
- if (response1 instanceof Exception) {
- System.out.println("t1 failure");
- assertEquals(cache.get("k1"), "value_1_t2");
- assertEquals(cache.get("k2"), "value_2_t2");
- } else {
- System.out.println("t2 failure");
- assertEquals(cache.get("k1"), "value_1_t1");
- assertEquals(cache.get("k2"), "value_2_t1");
- }
- }
-
-
- private void testLocalVsLocalTxDeadlock(PerCacheExecutorThread.Operations firstOperation, PerCacheExecutorThread.Operations secondOperation) {
-
- assert PerCacheExecutorThread.OperationsResult.BEGGIN_TX_OK == t1.execute(PerCacheExecutorThread.Operations.BEGGIN_TX);
- assert PerCacheExecutorThread.OperationsResult.BEGGIN_TX_OK == t2.execute(PerCacheExecutorThread.Operations.BEGGIN_TX);
- System.out.println("After beggin");
-
- t1.setKeyValue("k1", "value_1_t1");
- t2.setKeyValue("k2", "value_2_t2");
-
- assert firstOperation.getCorrespondingOkResult() == t1.execute(firstOperation);
- assert firstOperation.getCorrespondingOkResult() == t2.execute(firstOperation);
-
- System.out.println("After first PUT");
- assert lockManager.isLocked("k1");
- assert lockManager.isLocked("k2");
-
-
- t1.setKeyValue("k2", "value_2_t1");
- t2.setKeyValue("k1", "value_1_t2");
- t1.executeNoResponse(secondOperation);
- t2.executeNoResponse(secondOperation);
-
- response1 = t1.waitForResponse();
- response2 = t2.waitForResponse();
-
- assert xor(response1 instanceof DeadlockDetectedException, response2 instanceof DeadlockDetectedException) : "expected one and only one exception: " + response1 + ", " + response2;
- assert xor(response1 == secondOperation.getCorrespondingOkResult(), response2 == secondOperation.getCorrespondingOkResult()) : "expected one and only one exception: " + response1 + ", " + response2;
-
- assert lockManager.isLocked("k1");
- assert lockManager.isLocked("k2");
- assert lockManager.getOwner("k1") == lockManager.getOwner("k2");
-
- if (response1 instanceof Exception) {
- assert PerCacheExecutorThread.OperationsResult.COMMIT_TX_OK == t2.execute(PerCacheExecutorThread.Operations.COMMIT_TX);
- assert t1.execute(PerCacheExecutorThread.Operations.COMMIT_TX) instanceof RollbackException;
- } else {
- assert PerCacheExecutorThread.OperationsResult.COMMIT_TX_OK == t1.execute(PerCacheExecutorThread.Operations.COMMIT_TX);
- assert t2.execute(PerCacheExecutorThread.Operations.COMMIT_TX) instanceof RollbackException;
- }
- assert lockManager.getNumberOfLocksHeld() == 0;
- assertEquals(lockManager.getDetectedLocalDeadlocks(), 1);
- }
-
-}
Deleted: trunk/core/src/test/java/org/infinispan/tx/ReplDeadlockDetectionTest.java
===================================================================
--- trunk/core/src/test/java/org/infinispan/tx/ReplDeadlockDetectionTest.java 2010-09-15 16:19:59 UTC (rev 2385)
+++ trunk/core/src/test/java/org/infinispan/tx/ReplDeadlockDetectionTest.java 2010-09-15 19:09:38 UTC (rev 2386)
@@ -1,319 +0,0 @@
-package org.infinispan.tx;
-
-import org.infinispan.api.mvcc.LockAssert;
-import org.infinispan.commands.ReplicableCommand;
-import org.infinispan.config.Configuration;
-import org.infinispan.context.impl.NonTxInvocationContext;
-import org.infinispan.interceptors.DeadlockDetectingInterceptor;
-import org.infinispan.interceptors.InterceptorChain;
-import org.infinispan.remoting.ReplicationException;
-import org.infinispan.remoting.responses.Response;
-import org.infinispan.remoting.rpc.ResponseFilter;
-import org.infinispan.remoting.rpc.ResponseMode;
-import org.infinispan.remoting.rpc.RpcManager;
-import org.infinispan.remoting.transport.Address;
-import org.infinispan.remoting.transport.Transport;
-import org.infinispan.statetransfer.StateTransferException;
-import org.infinispan.test.MultipleCacheManagersTest;
-import org.infinispan.test.PerCacheExecutorThread;
-import org.infinispan.test.TestingUtil;
-import org.infinispan.util.concurrent.NotifyingNotifiableFuture;
-import org.infinispan.util.concurrent.locks.DeadlockDetectingLockManager;
-import org.infinispan.util.concurrent.locks.LockManager;
-import org.testng.annotations.AfterMethod;
-import org.testng.annotations.BeforeMethod;
-import org.testng.annotations.Test;
-
-import java.util.Collection;
-import java.util.List;
-import java.util.concurrent.CountDownLatch;
-
-/**
- * Functional test for deadlock detection.
- *
- * @author Mircea.Markus at jboss.com
- */
- at Test(testName = "tx.ReplDeadlockDetectionTest", groups = "functional")
-public class ReplDeadlockDetectionTest extends MultipleCacheManagersTest {
-
- protected ControlledRpcManager controlledRpcManager1;
- protected ControlledRpcManager controlledRpcManager2;
- protected CountDownLatch replicationLatch;
- protected PerCacheExecutorThread t1;
- protected PerCacheExecutorThread t2;
- protected DeadlockDetectingLockManager ddLm1;
- protected DeadlockDetectingLockManager ddLm2;
-
- protected Configuration.CacheMode cacheMode = Configuration.CacheMode.REPL_SYNC;
-
- protected void createCacheManagers() throws Throwable {
- Configuration config = getDefaultClusteredConfig(cacheMode, true);
- config.setEnableDeadlockDetection(true);
- config.setSyncCommitPhase(true);
- config.setSyncRollbackPhase(true);
- config.setUseLockStriping(false);
- assert config.isEnableDeadlockDetection();
- createClusteredCaches(2, "test", config);
- assert config.isEnableDeadlockDetection();
-
- assert cache(0, "test").getConfiguration().isEnableDeadlockDetection();
- assert cache(1, "test").getConfiguration().isEnableDeadlockDetection();
- assert !cache(0, "test").getConfiguration().isExposeJmxStatistics();
- assert !cache(1, "test").getConfiguration().isExposeJmxStatistics();
-
- ((DeadlockDetectingLockManager) TestingUtil.extractLockManager(cache(0, "test"))).setExposeJmxStats(true);
- ((DeadlockDetectingLockManager) TestingUtil.extractLockManager(cache(1, "test"))).setExposeJmxStats(true);
-
- RpcManager rpcManager1 = TestingUtil.extractComponent(cache(0, "test"), RpcManager.class);
- RpcManager rpcManager2 = TestingUtil.extractComponent(cache(1, "test"), RpcManager.class);
-
- controlledRpcManager1 = new ControlledRpcManager(rpcManager1);
- controlledRpcManager2 = new ControlledRpcManager(rpcManager2);
- TestingUtil.replaceComponent(cache(0, "test"), RpcManager.class, controlledRpcManager1, true);
- TestingUtil.replaceComponent(cache(1, "test"), RpcManager.class, controlledRpcManager2, true);
-
- assert TestingUtil.extractComponent(cache(0, "test"), RpcManager.class) instanceof ControlledRpcManager;
- assert TestingUtil.extractComponent(cache(1, "test"), RpcManager.class) instanceof ControlledRpcManager;
-
- ddLm1 = (DeadlockDetectingLockManager) TestingUtil.extractLockManager(cache(0, "test"));
- ddLm2 = (DeadlockDetectingLockManager) TestingUtil.extractLockManager(cache(1, "test"));
- }
-
-
- @BeforeMethod
- public void beforeMethod() {
- t1 = new PerCacheExecutorThread(cache(0, "test"), 1);
- t2 = new PerCacheExecutorThread(cache(1, "test"), 2);
- replicationLatch = new CountDownLatch(1);
- controlledRpcManager1.setReplicationLatch(replicationLatch);
- controlledRpcManager2.setReplicationLatch(replicationLatch);
- log.trace("_________________________ Here it begins");
- }
-
- @AfterMethod
- public void afterMethod() {
- t1.stopThread();
- t2.stopThread();
- ((DeadlockDetectingLockManager) TestingUtil.extractLockManager(cache(0, "test"))).resetStatistics();
- ((DeadlockDetectingLockManager) TestingUtil.extractLockManager(cache(1, "test"))).resetStatistics();
- }
-
- public void testExpectedInnerStructure() {
- LockManager lockManager = TestingUtil.extractComponent(cache(0, "test"), LockManager.class);
- assert lockManager instanceof DeadlockDetectingLockManager;
-
- InterceptorChain ic = TestingUtil.extractComponent(cache(0, "test"), InterceptorChain.class);
- assert ic.containsInterceptorType(DeadlockDetectingInterceptor.class);
- }
-
- public void testDeadlockDetectedTwoTransactions() throws Exception {
- t1.setKeyValue("key", "value1");
- t2.setKeyValue("key", "value2");
- assert PerCacheExecutorThread.OperationsResult.BEGGIN_TX_OK == t1.execute(PerCacheExecutorThread.Operations.BEGGIN_TX);
- assert PerCacheExecutorThread.OperationsResult.BEGGIN_TX_OK == t2.execute(PerCacheExecutorThread.Operations.BEGGIN_TX);
- System.out.println("After beggin");
-
- t1.execute(PerCacheExecutorThread.Operations.PUT_KEY_VALUE);
- t2.execute(PerCacheExecutorThread.Operations.PUT_KEY_VALUE);
- System.out.println("After put key value");
-
- t1.clearResponse();
- t2.clearResponse();
-
- t1.executeNoResponse(PerCacheExecutorThread.Operations.COMMIT_TX);
- t2.executeNoResponse(PerCacheExecutorThread.Operations.COMMIT_TX);
-
- System.out.println("Now replication is triggered");
- replicationLatch.countDown();
-
-
- Object t1Commit = t1.waitForResponse();
- Object t2Commit = t2.waitForResponse();
- System.out.println("After commit: " + t1Commit + ", " + t2Commit);
-
- assert xor(t1Commit instanceof Exception, t2Commit instanceof Exception) : "only one thread must be failing " + t1Commit + "," + t2Commit;
- System.out.println("t2Commit = " + t2Commit);
- System.out.println("t1Commit = " + t1Commit);
-
- if (t1Commit instanceof Exception) {
- System.out.println("t1 rolled back");
- Object o = cache(0, "test").get("key");
- assert o != null;
- assert o.equals("value2");
- } else {
- System.out.println("t2 rolled back");
- Object o = cache(0, "test").get("key");
- assert o != null;
- assert o.equals("value1");
- o = cache(1, "test").get("key");
- assert o != null;
- assert o.equals("value1");
- }
-
- assert ddLm1.getDetectedRemoteDeadlocks() + ddLm2.getDetectedRemoteDeadlocks() >= 1;
-
- LockManager lm1 = TestingUtil.extractComponent(cache(0, "test"), LockManager.class);
- assert !lm1.isLocked("key") : "It is locked by " + lm1.getOwner("key");
- LockManager lm2 = TestingUtil.extractComponent(cache(1, "test"), LockManager.class);
- assert !lm2.isLocked("key") : "It is locked by " + lm2.getOwner("key");
- LockAssert.assertNoLocks(cache(0, "test"));
- }
-
- public void testDeadlockDetectedOneTx() throws Exception {
- t1.setKeyValue("key", "value1");
-
- LockManager lm2 = TestingUtil.extractComponent(cache(1, "test"), LockManager.class);
- NonTxInvocationContext ctx = cache(1, "test").getAdvancedCache().getInvocationContextContainer().createNonTxInvocationContext();
- lm2.lockAndRecord("key", ctx);
- assert lm2.isLocked("key");
-
-
- assert PerCacheExecutorThread.OperationsResult.BEGGIN_TX_OK == t1.execute(PerCacheExecutorThread.Operations.BEGGIN_TX) : "but received " + t1.lastResponse();
- t1.execute(PerCacheExecutorThread.Operations.PUT_KEY_VALUE);
-
- t1.clearResponse();
- t1.executeNoResponse(PerCacheExecutorThread.Operations.COMMIT_TX);
-
- replicationLatch.countDown();
- System.out.println("Now replication is triggered");
-
- t1.waitForResponse();
-
-
- Object t1CommitRsp = t1.lastResponse();
-
- assert t1CommitRsp instanceof Exception : "expected exception, received " + t1.lastResponse();
-
- LockManager lm1 = TestingUtil.extractComponent(cache(0, "test"), LockManager.class);
- assert !lm1.isLocked("key") : "It is locked by " + lm1.getOwner("key");
-
- lm2.unlock("key");
- assert !lm2.isLocked("key");
- assert !lm1.isLocked("key");
- }
-
- public void testLockReleasedWhileTryingToAcquire() throws Exception {
- t1.setKeyValue("key", "value1");
-
- LockManager lm2 = TestingUtil.extractComponent(cache(1, "test"), LockManager.class);
- NonTxInvocationContext ctx = cache(1, "test").getAdvancedCache().getInvocationContextContainer().createNonTxInvocationContext();
- lm2.lockAndRecord("key", ctx);
- assert lm2.isLocked("key");
-
-
- assert PerCacheExecutorThread.OperationsResult.BEGGIN_TX_OK == t1.execute(PerCacheExecutorThread.Operations.BEGGIN_TX) : "but received " + t1.lastResponse();
- t1.execute(PerCacheExecutorThread.Operations.PUT_KEY_VALUE);
-
- t1.clearResponse();
- t1.executeNoResponse(PerCacheExecutorThread.Operations.COMMIT_TX);
-
- replicationLatch.countDown();
-
- Thread.sleep(3000); //just to make sure the remote tx thread managed to spin around for some times.
- lm2.unlock("key");
-
- t1.waitForResponse();
-
-
- Object t1CommitRsp = t1.lastResponse();
-
- assert t1CommitRsp == PerCacheExecutorThread.OperationsResult.COMMIT_TX_OK : "expected true, received " + t1.lastResponse();
-
- LockManager lm1 = TestingUtil.extractComponent(cache(0, "test"), LockManager.class);
- assert !lm1.isLocked("key") : "It is locked by " + lm1.getOwner("key");
-
- assert !lm2.isLocked("key");
- assert !lm1.isLocked("key");
- }
-
- public static final class ControlledRpcManager implements RpcManager {
-
- private volatile CountDownLatch replicationLatch;
-
- public ControlledRpcManager(RpcManager realOne) {
- this.realOne = realOne;
- }
-
- private RpcManager realOne;
-
- public void setReplicationLatch(CountDownLatch replicationLatch) {
- this.replicationLatch = replicationLatch;
- }
-
- public List<Response> invokeRemotely(Collection<Address> recipients, ReplicableCommand rpcCommand, ResponseMode mode, long timeout, boolean usePriorityQueue, ResponseFilter responseFilter) {
- return realOne.invokeRemotely(recipients, rpcCommand, mode, timeout, usePriorityQueue, responseFilter);
- }
-
- public List<Response> invokeRemotely(Collection<Address> recipients, ReplicableCommand rpcCommand, ResponseMode mode, long timeout, boolean usePriorityQueue) {
- return realOne.invokeRemotely(recipients, rpcCommand, mode, timeout, usePriorityQueue);
- }
-
- public List<Response> invokeRemotely(Collection<Address> recipients, ReplicableCommand rpcCommand, ResponseMode mode, long timeout) throws Exception {
- return realOne.invokeRemotely(recipients, rpcCommand, mode, timeout);
- }
-
- public void retrieveState(String cacheName, long timeout) throws StateTransferException {
- realOne.retrieveState(cacheName, timeout);
- }
-
- public void broadcastRpcCommand(ReplicableCommand rpc, boolean sync) throws ReplicationException {
- waitFirst();
- realOne.broadcastRpcCommand(rpc, sync);
- }
-
- public void broadcastRpcCommand(ReplicableCommand rpc, boolean sync, boolean usePriorityQueue) throws ReplicationException {
- waitFirst();
- realOne.broadcastRpcCommand(rpc, sync, usePriorityQueue);
- }
-
- private void waitFirst() {
- System.out.println(Thread.currentThread().getName() + " -- replication trigger called!");
- try {
- replicationLatch.await();
- } catch (Exception e) {
- throw new RuntimeException("Unexpected exception!", e);
- }
- }
-
- public void broadcastRpcCommandInFuture(ReplicableCommand rpc, NotifyingNotifiableFuture<Object> future) {
- realOne.broadcastRpcCommandInFuture(rpc, future);
- }
-
- public void broadcastRpcCommandInFuture(ReplicableCommand rpc, boolean usePriorityQueue, NotifyingNotifiableFuture<Object> future) {
- realOne.broadcastRpcCommandInFuture(rpc, usePriorityQueue, future);
- }
-
- public void invokeRemotely(Collection<Address> recipients, ReplicableCommand rpc, boolean sync) throws ReplicationException {
- realOne.invokeRemotely(recipients, rpc, sync);
- }
-
- public void invokeRemotely(Collection<Address> recipients, ReplicableCommand rpc, boolean sync, boolean usePriorityQueue) throws ReplicationException {
- realOne.invokeRemotely(recipients, rpc, sync, usePriorityQueue);
- }
-
- public void invokeRemotelyInFuture(Collection<Address> recipients, ReplicableCommand rpc, NotifyingNotifiableFuture<Object> future) {
- realOne.invokeRemotelyInFuture(recipients, rpc, future);
- }
-
- public void invokeRemotelyInFuture(Collection<Address> recipients, ReplicableCommand rpc, boolean usePriorityQueue, NotifyingNotifiableFuture<Object> future) {
- realOne.invokeRemotelyInFuture(recipients, rpc, usePriorityQueue, future);
- }
-
- public void invokeRemotelyInFuture(Collection<Address> recipients, ReplicableCommand rpc, boolean usePriorityQueue, NotifyingNotifiableFuture<Object> future, long timeout) {
- realOne.invokeRemotelyInFuture(recipients, rpc, usePriorityQueue, future, timeout);
- }
-
- public Transport getTransport() {
- return realOne.getTransport();
- }
-
- public Address getCurrentStateTransferSource() {
- return realOne.getCurrentStateTransferSource();
- }
-
- @Override
- public Address getAddress() {
- return null;
- }
- }
-}
Copied: trunk/core/src/test/java/org/infinispan/tx/dld (from rev 2385, branches/4.2.x/core/src/test/java/org/infinispan/tx/dld)
Deleted: trunk/core/src/test/java/org/infinispan/tx/dld/AsyncDeadlockDetectionTest.java
===================================================================
--- branches/4.2.x/core/src/test/java/org/infinispan/tx/dld/AsyncDeadlockDetectionTest.java 2010-09-15 16:19:59 UTC (rev 2385)
+++ trunk/core/src/test/java/org/infinispan/tx/dld/AsyncDeadlockDetectionTest.java 2010-09-15 19:09:38 UTC (rev 2386)
@@ -1,186 +0,0 @@
-package org.infinispan.tx.dld;
-
-import org.infinispan.Cache;
-import org.infinispan.commands.VisitableCommand;
-import org.infinispan.commands.write.PutKeyValueCommand;
-import org.infinispan.config.Configuration;
-import org.infinispan.context.InvocationContext;
-import org.infinispan.interceptors.base.CommandInterceptor;
-import org.infinispan.test.MultipleCacheManagersTest;
-import org.infinispan.test.PerCacheExecutorThread;
-import org.infinispan.test.TestingUtil;
-import org.infinispan.transaction.xa.TransactionTable;
-import org.infinispan.util.concurrent.locks.DeadlockDetectedException;
-import org.infinispan.util.concurrent.locks.DeadlockDetectingLockManager;
-import org.infinispan.util.concurrent.locks.LockManager;
-import static org.testng.Assert.assertEquals;
-import static org.testng.Assert.assertFalse;
-import org.testng.annotations.AfterMethod;
-import org.testng.annotations.BeforeMethod;
-import org.testng.annotations.Test;
-
-/**
- * Tests deadlock detection for async caches.
- *
- * @author Mircea.Markus at jboss.com
- */
- at Test(groups = "functional", testName = "tx.AsyncDeadlockDetectionTest")
-public class AsyncDeadlockDetectionTest extends MultipleCacheManagersTest {
- private PerCacheExecutorThread t0;
- private PerCacheExecutorThread t1;
- private RemoteReplicationInterceptor remoteReplicationInterceptor;
-
-
- protected void createCacheManagers() throws Throwable {
- Configuration config = getDefaultClusteredConfig(Configuration.CacheMode.REPL_ASYNC, true);
- config.setEnableDeadlockDetection(true);
- config.setSyncCommitPhase(true);
- config.setSyncRollbackPhase(true);
- config.setUseLockStriping(false);
- assert config.isEnableDeadlockDetection();
- createClusteredCaches(2, "test", config);
- assert config.isEnableDeadlockDetection();
-
-
- remoteReplicationInterceptor = new RemoteReplicationInterceptor();
- Cache cache0 = cache(0, "test");
- Cache cache1 = cache(1, "test");
- cache1.getAdvancedCache().addInterceptor(remoteReplicationInterceptor, 0);
- assert cache0.getConfiguration().isEnableDeadlockDetection();
- assert cache1.getConfiguration().isEnableDeadlockDetection();
- assert !cache0.getConfiguration().isExposeJmxStatistics();
- assert !cache1.getConfiguration().isExposeJmxStatistics();
-
- ((DeadlockDetectingLockManager) TestingUtil.extractLockManager(cache0)).setExposeJmxStats(true);
- ((DeadlockDetectingLockManager) TestingUtil.extractLockManager(cache1)).setExposeJmxStats(true);
- }
-
- @BeforeMethod
- public void beforeMethod() {
- Cache cache0 = cache(0, "test");
- Cache cache1 = cache(1, "test");
- t0 = new PerCacheExecutorThread(cache0, 0);
- t1 = new PerCacheExecutorThread(cache1, 1);
- }
-
- @AfterMethod
- public void afterMethod() {
- Cache cache0 = cache(0, "test");
- Cache cache1 = cache(1, "test");
- t0.stopThread();
- t1.stopThread();
- ((DeadlockDetectingLockManager) TestingUtil.extractLockManager(cache0)).resetStatistics();
- ((DeadlockDetectingLockManager) TestingUtil.extractLockManager(cache1)).resetStatistics();
- remoteReplicationInterceptor.executionResponse = null;
- remoteReplicationInterceptor = null;
- t0 = null;
- t1 = null;
- }
-
- public void testRemoteTxVsLocal() throws Exception {
- Cache cache0 = cache(0, "test");
- Cache cache1 = cache(1, "test");
- assertEquals(PerCacheExecutorThread.OperationsResult.BEGGIN_TX_OK, t0.execute(PerCacheExecutorThread.Operations.BEGGIN_TX));
- t0.setKeyValue("k1", "v1_t0");
- assertEquals(PerCacheExecutorThread.OperationsResult.PUT_KEY_VALUE_OK, t0.execute(PerCacheExecutorThread.Operations.PUT_KEY_VALUE));
- t0.setKeyValue("k2", "v2_t0");
- assertEquals(PerCacheExecutorThread.OperationsResult.PUT_KEY_VALUE_OK, t0.execute(PerCacheExecutorThread.Operations.PUT_KEY_VALUE));
-
- assertEquals(PerCacheExecutorThread.OperationsResult.BEGGIN_TX_OK, t1.execute(PerCacheExecutorThread.Operations.BEGGIN_TX));
- t1.setKeyValue("k2", "v2_t1");
- assertEquals(PerCacheExecutorThread.OperationsResult.PUT_KEY_VALUE_OK, t1.execute(PerCacheExecutorThread.Operations.PUT_KEY_VALUE));
-
- t0.execute(PerCacheExecutorThread.Operations.COMMIT_TX);
-
- final LockManager lm1 = TestingUtil.extractLockManager(cache1);
-
- eventually(new Condition() {
- public boolean isSatisfied() throws Exception {
- return lm1.isLocked("k1");
- }
- }); //now t0 replicated, acquired lock on k1 and it tries to acquire lock on k2
-
-
- t1.setKeyValue("k1", "v1_t1");
- t1.executeNoResponse(PerCacheExecutorThread.Operations.PUT_KEY_VALUE);
-
-
- Object t1Response = t1.waitForResponse();
- Object t0Response = remoteReplicationInterceptor.getResponse();
-
- log.trace("t0Response = " + t0Response);
- log.trace("t1Response = " + t1Response);
-
- assert xor(t1Response instanceof DeadlockDetectedException, t0Response instanceof DeadlockDetectedException);
- TransactionTable transactionTable1 = TestingUtil.extractComponent(cache1, TransactionTable.class);
-
-
- if (t0Response instanceof DeadlockDetectedException) {
- replListener(cache0).expectWithTx(PutKeyValueCommand.class, PutKeyValueCommand.class);
- assertEquals(t1.execute(PerCacheExecutorThread.Operations.COMMIT_TX), PerCacheExecutorThread.OperationsResult.COMMIT_TX_OK);
- replListener(cache0).waitForRpc();
- assertEquals(transactionTable1.getLocalTxCount(), 0);
- }
-
- DeadlockDetectingLockManager ddLm0 = (DeadlockDetectingLockManager) TestingUtil.extractLockManager(cache0);
- DeadlockDetectingLockManager ddLm1 = (DeadlockDetectingLockManager) TestingUtil.extractLockManager(cache1);
-
- assertFalse(ddLm0.isLocked("k1"));
- assertFalse(ddLm1.isLocked("k1"));
- assertFalse(ddLm0.isLocked("k2"));
- assertFalse(ddLm1.isLocked("k2"));
- TransactionTable transactionTable0 = TestingUtil.extractComponent(cache0, TransactionTable.class);
- assertEquals(transactionTable0.getLocalTxCount(), 0);
- for (int i = 0; i < 20; i++) {
- if (!(transactionTable0.getRemoteTxCount() == 0)) Thread.sleep(50);
- }
-
- assertEquals(transactionTable0.getRemoteTxCount(), 0);
-
- for (int i = 0; i < 20; i++) {
- if (!(transactionTable1.getRemoteTxCount() == 0)) Thread.sleep(50);
- }
- assertEquals(transactionTable1.getRemoteTxCount(), 0);
-
- if (t1Response instanceof DeadlockDetectedException) {
- assertEquals(cache0.get("k1"), "v1_t0");
- assertEquals(cache0.get("k2"), "v2_t0");
- assertEquals(cache1.get("k1"), "v1_t0");
- assertEquals(cache1.get("k2"), "v2_t0");
- } else {
- assertEquals(cache0.get("k1"), "v1_t1");
- assertEquals(cache0.get("k2"), "v2_t1");
- assertEquals(cache1.get("k1"), "v1_t1");
- assertEquals(cache1.get("k2"), "v2_t1");
- }
- }
-
-
- public static class RemoteReplicationInterceptor extends CommandInterceptor {
-
- public volatile Object executionResponse;
-
- @Override
- protected Object handleDefault(InvocationContext ctx, VisitableCommand command) throws Throwable {
- try {
- return invokeNextInterceptor(ctx, command);
- } catch (Throwable throwable) {
- if (!ctx.isOriginLocal()) {
- log.trace("Setting executionResponse to " + throwable);
- executionResponse = throwable;
- } else {
- log.trace("Ignoring throwable " + throwable);
- executionResponse = "NONE";
- }
- throw throwable;
- }
- }
-
- public Object getResponse() throws Exception {
- while (executionResponse == null) {
- Thread.sleep(50);
- }
- return executionResponse;
- }
- }
-}
Copied: trunk/core/src/test/java/org/infinispan/tx/dld/AsyncDeadlockDetectionTest.java (from rev 2385, branches/4.2.x/core/src/test/java/org/infinispan/tx/dld/AsyncDeadlockDetectionTest.java)
===================================================================
--- trunk/core/src/test/java/org/infinispan/tx/dld/AsyncDeadlockDetectionTest.java (rev 0)
+++ trunk/core/src/test/java/org/infinispan/tx/dld/AsyncDeadlockDetectionTest.java 2010-09-15 19:09:38 UTC (rev 2386)
@@ -0,0 +1,186 @@
+package org.infinispan.tx.dld;
+
+import org.infinispan.Cache;
+import org.infinispan.commands.VisitableCommand;
+import org.infinispan.commands.write.PutKeyValueCommand;
+import org.infinispan.config.Configuration;
+import org.infinispan.context.InvocationContext;
+import org.infinispan.interceptors.base.CommandInterceptor;
+import org.infinispan.test.MultipleCacheManagersTest;
+import org.infinispan.test.PerCacheExecutorThread;
+import org.infinispan.test.TestingUtil;
+import org.infinispan.transaction.xa.TransactionTable;
+import org.infinispan.util.concurrent.locks.DeadlockDetectedException;
+import org.infinispan.util.concurrent.locks.DeadlockDetectingLockManager;
+import org.infinispan.util.concurrent.locks.LockManager;
+import static org.testng.Assert.assertEquals;
+import static org.testng.Assert.assertFalse;
+import org.testng.annotations.AfterMethod;
+import org.testng.annotations.BeforeMethod;
+import org.testng.annotations.Test;
+
+/**
+ * Tests deadlock detection for async caches.
+ *
+ * @author Mircea.Markus at jboss.com
+ */
+ at Test(groups = "functional", testName = "tx.AsyncDeadlockDetectionTest")
+public class AsyncDeadlockDetectionTest extends MultipleCacheManagersTest {
+ private PerCacheExecutorThread t0;
+ private PerCacheExecutorThread t1;
+ private RemoteReplicationInterceptor remoteReplicationInterceptor;
+
+
+ protected void createCacheManagers() throws Throwable {
+ Configuration config = getDefaultClusteredConfig(Configuration.CacheMode.REPL_ASYNC, true);
+ config.setEnableDeadlockDetection(true);
+ config.setSyncCommitPhase(true);
+ config.setSyncRollbackPhase(true);
+ config.setUseLockStriping(false);
+ assert config.isEnableDeadlockDetection();
+ createClusteredCaches(2, "test", config);
+ assert config.isEnableDeadlockDetection();
+
+
+ remoteReplicationInterceptor = new RemoteReplicationInterceptor();
+ Cache cache0 = cache(0, "test");
+ Cache cache1 = cache(1, "test");
+ cache1.getAdvancedCache().addInterceptor(remoteReplicationInterceptor, 0);
+ assert cache0.getConfiguration().isEnableDeadlockDetection();
+ assert cache1.getConfiguration().isEnableDeadlockDetection();
+ assert !cache0.getConfiguration().isExposeJmxStatistics();
+ assert !cache1.getConfiguration().isExposeJmxStatistics();
+
+ ((DeadlockDetectingLockManager) TestingUtil.extractLockManager(cache0)).setExposeJmxStats(true);
+ ((DeadlockDetectingLockManager) TestingUtil.extractLockManager(cache1)).setExposeJmxStats(true);
+ }
+
+ @BeforeMethod
+ public void beforeMethod() {
+ Cache cache0 = cache(0, "test");
+ Cache cache1 = cache(1, "test");
+ t0 = new PerCacheExecutorThread(cache0, 0);
+ t1 = new PerCacheExecutorThread(cache1, 1);
+ }
+
+ @AfterMethod
+ public void afterMethod() {
+ Cache cache0 = cache(0, "test");
+ Cache cache1 = cache(1, "test");
+ t0.stopThread();
+ t1.stopThread();
+ ((DeadlockDetectingLockManager) TestingUtil.extractLockManager(cache0)).resetStatistics();
+ ((DeadlockDetectingLockManager) TestingUtil.extractLockManager(cache1)).resetStatistics();
+ remoteReplicationInterceptor.executionResponse = null;
+ remoteReplicationInterceptor = null;
+ t0 = null;
+ t1 = null;
+ }
+
+ public void testRemoteTxVsLocal() throws Exception {
+ Cache cache0 = cache(0, "test");
+ Cache cache1 = cache(1, "test");
+ assertEquals(PerCacheExecutorThread.OperationsResult.BEGGIN_TX_OK, t0.execute(PerCacheExecutorThread.Operations.BEGGIN_TX));
+ t0.setKeyValue("k1", "v1_t0");
+ assertEquals(PerCacheExecutorThread.OperationsResult.PUT_KEY_VALUE_OK, t0.execute(PerCacheExecutorThread.Operations.PUT_KEY_VALUE));
+ t0.setKeyValue("k2", "v2_t0");
+ assertEquals(PerCacheExecutorThread.OperationsResult.PUT_KEY_VALUE_OK, t0.execute(PerCacheExecutorThread.Operations.PUT_KEY_VALUE));
+
+ assertEquals(PerCacheExecutorThread.OperationsResult.BEGGIN_TX_OK, t1.execute(PerCacheExecutorThread.Operations.BEGGIN_TX));
+ t1.setKeyValue("k2", "v2_t1");
+ assertEquals(PerCacheExecutorThread.OperationsResult.PUT_KEY_VALUE_OK, t1.execute(PerCacheExecutorThread.Operations.PUT_KEY_VALUE));
+
+ t0.execute(PerCacheExecutorThread.Operations.COMMIT_TX);
+
+ final LockManager lm1 = TestingUtil.extractLockManager(cache1);
+
+ eventually(new Condition() {
+ public boolean isSatisfied() throws Exception {
+ return lm1.isLocked("k1");
+ }
+ }); //now t0 replicated, acquired lock on k1 and it tries to acquire lock on k2
+
+
+ t1.setKeyValue("k1", "v1_t1");
+ t1.executeNoResponse(PerCacheExecutorThread.Operations.PUT_KEY_VALUE);
+
+
+ Object t1Response = t1.waitForResponse();
+ Object t0Response = remoteReplicationInterceptor.getResponse();
+
+ log.trace("t0Response = " + t0Response);
+ log.trace("t1Response = " + t1Response);
+
+ assert xor(t1Response instanceof DeadlockDetectedException, t0Response instanceof DeadlockDetectedException);
+ TransactionTable transactionTable1 = TestingUtil.extractComponent(cache1, TransactionTable.class);
+
+
+ if (t0Response instanceof DeadlockDetectedException) {
+ replListener(cache0).expectWithTx(PutKeyValueCommand.class, PutKeyValueCommand.class);
+ assertEquals(t1.execute(PerCacheExecutorThread.Operations.COMMIT_TX), PerCacheExecutorThread.OperationsResult.COMMIT_TX_OK);
+ replListener(cache0).waitForRpc();
+ assertEquals(transactionTable1.getLocalTxCount(), 0);
+ }
+
+ DeadlockDetectingLockManager ddLm0 = (DeadlockDetectingLockManager) TestingUtil.extractLockManager(cache0);
+ DeadlockDetectingLockManager ddLm1 = (DeadlockDetectingLockManager) TestingUtil.extractLockManager(cache1);
+
+ assertFalse(ddLm0.isLocked("k1"));
+ assertFalse(ddLm1.isLocked("k1"));
+ assertFalse(ddLm0.isLocked("k2"));
+ assertFalse(ddLm1.isLocked("k2"));
+ TransactionTable transactionTable0 = TestingUtil.extractComponent(cache0, TransactionTable.class);
+ assertEquals(transactionTable0.getLocalTxCount(), 0);
+ for (int i = 0; i < 20; i++) {
+ if (!(transactionTable0.getRemoteTxCount() == 0)) Thread.sleep(50);
+ }
+
+ assertEquals(transactionTable0.getRemoteTxCount(), 0);
+
+ for (int i = 0; i < 20; i++) {
+ if (!(transactionTable1.getRemoteTxCount() == 0)) Thread.sleep(50);
+ }
+ assertEquals(transactionTable1.getRemoteTxCount(), 0);
+
+ if (t1Response instanceof DeadlockDetectedException) {
+ assertEquals(cache0.get("k1"), "v1_t0");
+ assertEquals(cache0.get("k2"), "v2_t0");
+ assertEquals(cache1.get("k1"), "v1_t0");
+ assertEquals(cache1.get("k2"), "v2_t0");
+ } else {
+ assertEquals(cache0.get("k1"), "v1_t1");
+ assertEquals(cache0.get("k2"), "v2_t1");
+ assertEquals(cache1.get("k1"), "v1_t1");
+ assertEquals(cache1.get("k2"), "v2_t1");
+ }
+ }
+
+
+ public static class RemoteReplicationInterceptor extends CommandInterceptor {
+
+ public volatile Object executionResponse;
+
+ @Override
+ protected Object handleDefault(InvocationContext ctx, VisitableCommand command) throws Throwable {
+ try {
+ return invokeNextInterceptor(ctx, command);
+ } catch (Throwable throwable) {
+ if (!ctx.isOriginLocal()) {
+ log.trace("Setting executionResponse to " + throwable);
+ executionResponse = throwable;
+ } else {
+ log.trace("Ignoring throwable " + throwable);
+ executionResponse = "NONE";
+ }
+ throw throwable;
+ }
+ }
+
+ public Object getResponse() throws Exception {
+ while (executionResponse == null) {
+ Thread.sleep(50);
+ }
+ return executionResponse;
+ }
+ }
+}
Deleted: trunk/core/src/test/java/org/infinispan/tx/dld/BaseDldEagerLockingTest.java
===================================================================
--- branches/4.2.x/core/src/test/java/org/infinispan/tx/dld/BaseDldEagerLockingTest.java 2010-09-15 16:19:59 UTC (rev 2385)
+++ trunk/core/src/test/java/org/infinispan/tx/dld/BaseDldEagerLockingTest.java 2010-09-15 19:09:38 UTC (rev 2386)
@@ -1,104 +0,0 @@
-package org.infinispan.tx.dld;
-
-import org.infinispan.test.PerCacheExecutorThread;
-import org.infinispan.test.TestingUtil;
-import org.infinispan.util.concurrent.locks.DeadlockDetectingLockManager;
-import org.testng.annotations.AfterMethod;
-import org.testng.annotations.BeforeMethod;
-
-import javax.transaction.RollbackException;
-import javax.transaction.Status;
-import javax.transaction.SystemException;
-
-import static org.testng.Assert.assertEquals;
-
-/**
- * // TODO: Document this
- *
- * @author Mircea.Markus at jboss.com
- * @since 4.2
- */
-public abstract class BaseDldEagerLockingTest extends BaseDldTest {
- protected PerCacheExecutorThread ex0;
- protected PerCacheExecutorThread ex1;
- protected DeadlockDetectingLockManager lm0;
- protected DeadlockDetectingLockManager lm1;
-
- @BeforeMethod
- public void beforeMethod() {
- ex0 = new PerCacheExecutorThread(cache(0), 0);
- ex1 = new PerCacheExecutorThread(cache(1), 1);
-
- lm0 = (DeadlockDetectingLockManager) TestingUtil.extractLockManager(cache(0));
- lm0.setExposeJmxStats(true);
- lm1 = (DeadlockDetectingLockManager) TestingUtil.extractLockManager(cache(1));
- lm1.setExposeJmxStats(true);
- }
-
- @AfterMethod
- public void afterMethod() {
- ex0.stopThread();
- ex1.stopThread();
- }
-
- protected void testSymmetricDld(Object k0, Object k1) throws SystemException {
-
- long start = System.currentTimeMillis();
-
- log.trace("Here is where the test starts");
-
- ex0.execute(PerCacheExecutorThread.Operations.BEGGIN_TX);
- ex1.execute(PerCacheExecutorThread.Operations.BEGGIN_TX);
-
-
- ex0.setKeyValue(k0, "v0_0");
- assertEquals(ex0.execute(PerCacheExecutorThread.Operations.PUT_KEY_VALUE), PerCacheExecutorThread.OperationsResult.PUT_KEY_VALUE_OK);
- ex1.setKeyValue(k1, "v1_1");
- assertEquals(ex1.execute(PerCacheExecutorThread.Operations.PUT_KEY_VALUE), PerCacheExecutorThread.OperationsResult.PUT_KEY_VALUE_OK);
-
- assert lm0.isLocked(k0);
-// assert lm0.isLocked(k1);
-// assert lm1.isLocked(k0);
- assert lm1.isLocked(k1);
-
- log.trace("After first set of puts");
-
- ex0.clearResponse();
- ex1.clearResponse();
-
- log.info("Here is where DLD happens");
-
- ex1.setKeyValue(k0, "v0_1");
- ex1.executeNoResponse(PerCacheExecutorThread.Operations.PUT_KEY_VALUE);
- ex0.setKeyValue(k1, "v1_0");
- ex0.executeNoResponse(PerCacheExecutorThread.Operations.PUT_KEY_VALUE);
- ex0.waitForResponse();
- ex1.waitForResponse();
-
- boolean b1 = ex0.lastResponse() instanceof Exception;
- boolean b2 = ex1.lastResponse() instanceof Exception;
- log.info("b1:", b1);
- log.info("b2:", b2);
- assert xor(b1, b2) : "Both are " + (b1 || b2);
-
- assert xor(ex0.getOngoingTransaction().getStatus() == Status.STATUS_MARKED_ROLLBACK,
- ex1.getOngoingTransaction().getStatus() == Status.STATUS_MARKED_ROLLBACK);
-
- Object txOutcome1 = ex0.execute(PerCacheExecutorThread.Operations.COMMIT_TX);
- Object txOutcome2 = ex1.execute(PerCacheExecutorThread.Operations.COMMIT_TX);
- assert xor(txOutcome1 == PerCacheExecutorThread.OperationsResult.COMMIT_TX_OK, txOutcome2 == PerCacheExecutorThread.OperationsResult.COMMIT_TX_OK);
- assert xor(txOutcome1 instanceof RollbackException, txOutcome2 instanceof RollbackException);
-
- assert cache(0).get(k0) != null;
- assert cache(0).get(k1) != null;
- assert cache(1).get(k0) != null;
- assert cache(1).get(k1) != null;
-
- long totalDeadlocks = lm0.getTotalNumberOfDetectedDeadlocks() + lm1.getTotalNumberOfDetectedDeadlocks();
- assert totalDeadlocks == 1 : "Expected 1 but received " + totalDeadlocks;
-
- System.out.println("Test took " + (System.currentTimeMillis() - start) + " millis.");
- }
-
-
-}
Copied: trunk/core/src/test/java/org/infinispan/tx/dld/BaseDldEagerLockingTest.java (from rev 2385, branches/4.2.x/core/src/test/java/org/infinispan/tx/dld/BaseDldEagerLockingTest.java)
===================================================================
--- trunk/core/src/test/java/org/infinispan/tx/dld/BaseDldEagerLockingTest.java (rev 0)
+++ trunk/core/src/test/java/org/infinispan/tx/dld/BaseDldEagerLockingTest.java 2010-09-15 19:09:38 UTC (rev 2386)
@@ -0,0 +1,104 @@
+package org.infinispan.tx.dld;
+
+import org.infinispan.test.PerCacheExecutorThread;
+import org.infinispan.test.TestingUtil;
+import org.infinispan.util.concurrent.locks.DeadlockDetectingLockManager;
+import org.testng.annotations.AfterMethod;
+import org.testng.annotations.BeforeMethod;
+
+import javax.transaction.RollbackException;
+import javax.transaction.Status;
+import javax.transaction.SystemException;
+
+import static org.testng.Assert.assertEquals;
+
+/**
+ * // TODO: Document this
+ *
+ * @author Mircea.Markus at jboss.com
+ * @since 4.2
+ */
+public abstract class BaseDldEagerLockingTest extends BaseDldTest {
+ protected PerCacheExecutorThread ex0;
+ protected PerCacheExecutorThread ex1;
+ protected DeadlockDetectingLockManager lm0;
+ protected DeadlockDetectingLockManager lm1;
+
+ @BeforeMethod
+ public void beforeMethod() {
+ ex0 = new PerCacheExecutorThread(cache(0), 0);
+ ex1 = new PerCacheExecutorThread(cache(1), 1);
+
+ lm0 = (DeadlockDetectingLockManager) TestingUtil.extractLockManager(cache(0));
+ lm0.setExposeJmxStats(true);
+ lm1 = (DeadlockDetectingLockManager) TestingUtil.extractLockManager(cache(1));
+ lm1.setExposeJmxStats(true);
+ }
+
+ @AfterMethod
+ public void afterMethod() {
+ ex0.stopThread();
+ ex1.stopThread();
+ }
+
+ protected void testSymmetricDld(Object k0, Object k1) throws SystemException {
+
+ long start = System.currentTimeMillis();
+
+ log.trace("Here is where the test starts");
+
+ ex0.execute(PerCacheExecutorThread.Operations.BEGGIN_TX);
+ ex1.execute(PerCacheExecutorThread.Operations.BEGGIN_TX);
+
+
+ ex0.setKeyValue(k0, "v0_0");
+ assertEquals(ex0.execute(PerCacheExecutorThread.Operations.PUT_KEY_VALUE), PerCacheExecutorThread.OperationsResult.PUT_KEY_VALUE_OK);
+ ex1.setKeyValue(k1, "v1_1");
+ assertEquals(ex1.execute(PerCacheExecutorThread.Operations.PUT_KEY_VALUE), PerCacheExecutorThread.OperationsResult.PUT_KEY_VALUE_OK);
+
+ assert lm0.isLocked(k0);
+// assert lm0.isLocked(k1);
+// assert lm1.isLocked(k0);
+ assert lm1.isLocked(k1);
+
+ log.trace("After first set of puts");
+
+ ex0.clearResponse();
+ ex1.clearResponse();
+
+ log.info("Here is where DLD happens");
+
+ ex1.setKeyValue(k0, "v0_1");
+ ex1.executeNoResponse(PerCacheExecutorThread.Operations.PUT_KEY_VALUE);
+ ex0.setKeyValue(k1, "v1_0");
+ ex0.executeNoResponse(PerCacheExecutorThread.Operations.PUT_KEY_VALUE);
+ ex0.waitForResponse();
+ ex1.waitForResponse();
+
+ boolean b1 = ex0.lastResponse() instanceof Exception;
+ boolean b2 = ex1.lastResponse() instanceof Exception;
+ log.info("b1:", b1);
+ log.info("b2:", b2);
+ assert xor(b1, b2) : "Both are " + (b1 || b2);
+
+ assert xor(ex0.getOngoingTransaction().getStatus() == Status.STATUS_MARKED_ROLLBACK,
+ ex1.getOngoingTransaction().getStatus() == Status.STATUS_MARKED_ROLLBACK);
+
+ Object txOutcome1 = ex0.execute(PerCacheExecutorThread.Operations.COMMIT_TX);
+ Object txOutcome2 = ex1.execute(PerCacheExecutorThread.Operations.COMMIT_TX);
+ assert xor(txOutcome1 == PerCacheExecutorThread.OperationsResult.COMMIT_TX_OK, txOutcome2 == PerCacheExecutorThread.OperationsResult.COMMIT_TX_OK);
+ assert xor(txOutcome1 instanceof RollbackException, txOutcome2 instanceof RollbackException);
+
+ assert cache(0).get(k0) != null;
+ assert cache(0).get(k1) != null;
+ assert cache(1).get(k0) != null;
+ assert cache(1).get(k1) != null;
+
+ long totalDeadlocks = lm0.getTotalNumberOfDetectedDeadlocks() + lm1.getTotalNumberOfDetectedDeadlocks();
+ assert totalDeadlocks == 1 : "Expected 1 but received " + totalDeadlocks;
+
+ System.out.println("Test took " + (System.currentTimeMillis() - start) + " millis.");
+ }
+
+
+}
Deleted: trunk/core/src/test/java/org/infinispan/tx/dld/BaseDldLazyLockingTest.java
===================================================================
--- branches/4.2.x/core/src/test/java/org/infinispan/tx/dld/BaseDldLazyLockingTest.java 2010-09-15 16:19:59 UTC (rev 2385)
+++ trunk/core/src/test/java/org/infinispan/tx/dld/BaseDldLazyLockingTest.java 2010-09-15 19:09:38 UTC (rev 2386)
@@ -1,125 +0,0 @@
-package org.infinispan.tx.dld;
-
-import org.infinispan.Cache;
-import org.infinispan.remoting.rpc.RpcManager;
-import org.infinispan.test.MultipleCacheManagersTest;
-import org.infinispan.test.PerCacheExecutorThread;
-import org.infinispan.test.TestingUtil;
-import org.infinispan.util.concurrent.locks.DeadlockDetectingLockManager;
-import org.infinispan.util.concurrent.locks.LockManager;
-
-import java.util.concurrent.CountDownLatch;
-
-import static org.testng.Assert.assertEquals;
-
-/**
- * // TODO: Document this
- *
- * @author Mircea.Markus at jboss.com
- * @since 4.2
- */
-public abstract class BaseDldLazyLockingTest extends BaseDldTest {
-
- protected void testSymmetricDeadlock(Object k0, Object k1) {
-
- CountDownLatch replLatch = new CountDownLatch(1);
- rpcManager0.setReplicationLatch(replLatch);
- rpcManager1.setReplicationLatch(replLatch);
-
- DeadlockDetectingLockManager ddLm0 = (DeadlockDetectingLockManager) TestingUtil.extractLockManager(cache(0));
- ddLm0.setExposeJmxStats(true);
- DeadlockDetectingLockManager ddLm1 = (DeadlockDetectingLockManager) TestingUtil.extractLockManager(cache(1));
- ddLm1.setExposeJmxStats(true);
-
-
- PerCacheExecutorThread t0 = new PerCacheExecutorThread(cache(0), 0);
- PerCacheExecutorThread t1 = new PerCacheExecutorThread(cache(1), 1);
-
- assert PerCacheExecutorThread.OperationsResult.BEGGIN_TX_OK == t0.execute(PerCacheExecutorThread.Operations.BEGGIN_TX);
- assert PerCacheExecutorThread.OperationsResult.BEGGIN_TX_OK == t1.execute(PerCacheExecutorThread.Operations.BEGGIN_TX);
-
- t0.setKeyValue(k0, "k0_0");
- t1.setKeyValue(k1, "k1_0");
-
- t0.execute(PerCacheExecutorThread.Operations.PUT_KEY_VALUE);
- t1.execute(PerCacheExecutorThread.Operations.PUT_KEY_VALUE);
-
- t0.setKeyValue(k1, "k1_0");
- t1.setKeyValue(k0, "k0_1");
-
- assertEquals(t0.execute(PerCacheExecutorThread.Operations.PUT_KEY_VALUE), PerCacheExecutorThread.OperationsResult.PUT_KEY_VALUE_OK);
- assertEquals(t1.execute(PerCacheExecutorThread.Operations.PUT_KEY_VALUE), PerCacheExecutorThread.OperationsResult.PUT_KEY_VALUE_OK);
-
- log.info("---Before commit");
- t0.executeNoResponse(PerCacheExecutorThread.Operations.COMMIT_TX);
- t1.executeNoResponse(PerCacheExecutorThread.Operations.COMMIT_TX);
-
- replLatch.countDown();
-
-
- Object t0Response = t0.waitForResponse();
- Object t1Response = t1.waitForResponse();
-
- assert xor(t0Response instanceof Exception, t1Response instanceof Exception);
-
- if (t0Response instanceof Exception) {
- Object o = cache(0).get(k0);
- assert o != null;
- assert o.equals("k0_1");
- } else {
- Object o = cache(1).get(k0);
- assert o != null;
- assert o.equals("k0_0");
- }
-
- assert ddLm0.getDetectedRemoteDeadlocks() + ddLm1.getDetectedRemoteDeadlocks() >= 1;
-
- LockManager lm0 = TestingUtil.extractComponent(cache(0), LockManager.class);
- assert !lm0.isLocked("key") : "It is locked by " + lm0.getOwner("key");
- LockManager lm1 = TestingUtil.extractComponent(cache(1), LockManager.class);
- assert !lm1.isLocked("key") : "It is locked by " + lm1.getOwner("key");
- }
-
- protected void testLocalVsRemoteDeadlock(Object k0, Object k1) {
-
- PerCacheExecutorThread t0 = new PerCacheExecutorThread(cache(0), 0);
- PerCacheExecutorThread t1 = new PerCacheExecutorThread(cache(1), 1);
-
- assert PerCacheExecutorThread.OperationsResult.BEGGIN_TX_OK == t0.execute(PerCacheExecutorThread.Operations.BEGGIN_TX);
- assert PerCacheExecutorThread.OperationsResult.BEGGIN_TX_OK == t1.execute(PerCacheExecutorThread.Operations.BEGGIN_TX);
-
- t0.setKeyValue(k0, "k0_0");
- t0.execute(PerCacheExecutorThread.Operations.PUT_KEY_VALUE);
-
- t1.setKeyValue(k1, "k1_0");
- assertEquals(t1.execute(PerCacheExecutorThread.Operations.PUT_KEY_VALUE), PerCacheExecutorThread.OperationsResult.PUT_KEY_VALUE_OK);
- t1.setKeyValue(k0, "k0_1");
- assertEquals(t1.execute(PerCacheExecutorThread.Operations.PUT_KEY_VALUE), PerCacheExecutorThread.OperationsResult.PUT_KEY_VALUE_OK);
- t1.executeNoResponse(PerCacheExecutorThread.Operations.COMMIT_TX);
-
- t0.setKeyValue(k1, "k1_0");
- t0.executeNoResponse(PerCacheExecutorThread.Operations.PUT_KEY_VALUE);
-
- Object t0Response = t0.waitForResponse();
- Object t1Response = t1.waitForResponse();
-
- boolean v0 = t0Response instanceof Exception;
- boolean v1 = t1Response instanceof Exception;
- assert xor(v0, v1) : "both exceptions? " + (v0 && v1);
-
- if (!v1) {
- System.out.println("V0" );
- assertEquals(cache(0).get(k0), "k0_1");
- assertEquals(cache(0).get(k1), "k1_1");
- assertEquals(cache(1).get(k0), "k0_1");
- assertEquals(cache(1).get(k1), "k1_1");
- } else {
- System.out.println("v1 = " + v1);
- assertEquals(t0.execute(PerCacheExecutorThread.Operations.COMMIT_TX), PerCacheExecutorThread.OperationsResult.COMMIT_TX_OK);
- assertEquals(cache(0).get(k0), "k0_0");
- assertEquals(cache(0).get(k1), "k1_0");
- assertEquals(cache(1).get(k0), "k0_0");
- assertEquals(cache(1).get(k1), "k1_0");
- }
- }
-}
Copied: trunk/core/src/test/java/org/infinispan/tx/dld/BaseDldLazyLockingTest.java (from rev 2385, branches/4.2.x/core/src/test/java/org/infinispan/tx/dld/BaseDldLazyLockingTest.java)
===================================================================
--- trunk/core/src/test/java/org/infinispan/tx/dld/BaseDldLazyLockingTest.java (rev 0)
+++ trunk/core/src/test/java/org/infinispan/tx/dld/BaseDldLazyLockingTest.java 2010-09-15 19:09:38 UTC (rev 2386)
@@ -0,0 +1,125 @@
+package org.infinispan.tx.dld;
+
+import org.infinispan.Cache;
+import org.infinispan.remoting.rpc.RpcManager;
+import org.infinispan.test.MultipleCacheManagersTest;
+import org.infinispan.test.PerCacheExecutorThread;
+import org.infinispan.test.TestingUtil;
+import org.infinispan.util.concurrent.locks.DeadlockDetectingLockManager;
+import org.infinispan.util.concurrent.locks.LockManager;
+
+import java.util.concurrent.CountDownLatch;
+
+import static org.testng.Assert.assertEquals;
+
+/**
+ * // TODO: Document this
+ *
+ * @author Mircea.Markus at jboss.com
+ * @since 4.2
+ */
+public abstract class BaseDldLazyLockingTest extends BaseDldTest {
+
+ protected void testSymmetricDeadlock(Object k0, Object k1) {
+
+ CountDownLatch replLatch = new CountDownLatch(1);
+ rpcManager0.setReplicationLatch(replLatch);
+ rpcManager1.setReplicationLatch(replLatch);
+
+ DeadlockDetectingLockManager ddLm0 = (DeadlockDetectingLockManager) TestingUtil.extractLockManager(cache(0));
+ ddLm0.setExposeJmxStats(true);
+ DeadlockDetectingLockManager ddLm1 = (DeadlockDetectingLockManager) TestingUtil.extractLockManager(cache(1));
+ ddLm1.setExposeJmxStats(true);
+
+
+ PerCacheExecutorThread t0 = new PerCacheExecutorThread(cache(0), 0);
+ PerCacheExecutorThread t1 = new PerCacheExecutorThread(cache(1), 1);
+
+ assert PerCacheExecutorThread.OperationsResult.BEGGIN_TX_OK == t0.execute(PerCacheExecutorThread.Operations.BEGGIN_TX);
+ assert PerCacheExecutorThread.OperationsResult.BEGGIN_TX_OK == t1.execute(PerCacheExecutorThread.Operations.BEGGIN_TX);
+
+ t0.setKeyValue(k0, "k0_0");
+ t1.setKeyValue(k1, "k1_0");
+
+ t0.execute(PerCacheExecutorThread.Operations.PUT_KEY_VALUE);
+ t1.execute(PerCacheExecutorThread.Operations.PUT_KEY_VALUE);
+
+ t0.setKeyValue(k1, "k1_0");
+ t1.setKeyValue(k0, "k0_1");
+
+ assertEquals(t0.execute(PerCacheExecutorThread.Operations.PUT_KEY_VALUE), PerCacheExecutorThread.OperationsResult.PUT_KEY_VALUE_OK);
+ assertEquals(t1.execute(PerCacheExecutorThread.Operations.PUT_KEY_VALUE), PerCacheExecutorThread.OperationsResult.PUT_KEY_VALUE_OK);
+
+ log.info("---Before commit");
+ t0.executeNoResponse(PerCacheExecutorThread.Operations.COMMIT_TX);
+ t1.executeNoResponse(PerCacheExecutorThread.Operations.COMMIT_TX);
+
+ replLatch.countDown();
+
+
+ Object t0Response = t0.waitForResponse();
+ Object t1Response = t1.waitForResponse();
+
+ assert xor(t0Response instanceof Exception, t1Response instanceof Exception);
+
+ if (t0Response instanceof Exception) {
+ Object o = cache(0).get(k0);
+ assert o != null;
+ assert o.equals("k0_1");
+ } else {
+ Object o = cache(1).get(k0);
+ assert o != null;
+ assert o.equals("k0_0");
+ }
+
+ assert ddLm0.getDetectedRemoteDeadlocks() + ddLm1.getDetectedRemoteDeadlocks() >= 1;
+
+ LockManager lm0 = TestingUtil.extractComponent(cache(0), LockManager.class);
+ assert !lm0.isLocked("key") : "It is locked by " + lm0.getOwner("key");
+ LockManager lm1 = TestingUtil.extractComponent(cache(1), LockManager.class);
+ assert !lm1.isLocked("key") : "It is locked by " + lm1.getOwner("key");
+ }
+
+ protected void testLocalVsRemoteDeadlock(Object k0, Object k1) {
+
+ PerCacheExecutorThread t0 = new PerCacheExecutorThread(cache(0), 0);
+ PerCacheExecutorThread t1 = new PerCacheExecutorThread(cache(1), 1);
+
+ assert PerCacheExecutorThread.OperationsResult.BEGGIN_TX_OK == t0.execute(PerCacheExecutorThread.Operations.BEGGIN_TX);
+ assert PerCacheExecutorThread.OperationsResult.BEGGIN_TX_OK == t1.execute(PerCacheExecutorThread.Operations.BEGGIN_TX);
+
+ t0.setKeyValue(k0, "k0_0");
+ t0.execute(PerCacheExecutorThread.Operations.PUT_KEY_VALUE);
+
+ t1.setKeyValue(k1, "k1_0");
+ assertEquals(t1.execute(PerCacheExecutorThread.Operations.PUT_KEY_VALUE), PerCacheExecutorThread.OperationsResult.PUT_KEY_VALUE_OK);
+ t1.setKeyValue(k0, "k0_1");
+ assertEquals(t1.execute(PerCacheExecutorThread.Operations.PUT_KEY_VALUE), PerCacheExecutorThread.OperationsResult.PUT_KEY_VALUE_OK);
+ t1.executeNoResponse(PerCacheExecutorThread.Operations.COMMIT_TX);
+
+ t0.setKeyValue(k1, "k1_0");
+ t0.executeNoResponse(PerCacheExecutorThread.Operations.PUT_KEY_VALUE);
+
+ Object t0Response = t0.waitForResponse();
+ Object t1Response = t1.waitForResponse();
+
+ boolean v0 = t0Response instanceof Exception;
+ boolean v1 = t1Response instanceof Exception;
+ assert xor(v0, v1) : "both exceptions? " + (v0 && v1);
+
+ if (!v1) {
+ System.out.println("V0" );
+ assertEquals(cache(0).get(k0), "k0_1");
+ assertEquals(cache(0).get(k1), "k1_1");
+ assertEquals(cache(1).get(k0), "k0_1");
+ assertEquals(cache(1).get(k1), "k1_1");
+ } else {
+ System.out.println("v1 = " + v1);
+ assertEquals(t0.execute(PerCacheExecutorThread.Operations.COMMIT_TX), PerCacheExecutorThread.OperationsResult.COMMIT_TX_OK);
+ assertEquals(cache(0).get(k0), "k0_0");
+ assertEquals(cache(0).get(k1), "k1_0");
+ assertEquals(cache(1).get(k0), "k0_0");
+ assertEquals(cache(1).get(k1), "k1_0");
+ }
+ }
+}
Deleted: trunk/core/src/test/java/org/infinispan/tx/dld/BaseDldTest.java
===================================================================
--- branches/4.2.x/core/src/test/java/org/infinispan/tx/dld/BaseDldTest.java 2010-09-15 16:19:59 UTC (rev 2385)
+++ trunk/core/src/test/java/org/infinispan/tx/dld/BaseDldTest.java 2010-09-15 19:09:38 UTC (rev 2386)
@@ -1,24 +0,0 @@
-package org.infinispan.tx.dld;
-
-import org.infinispan.Cache;
-import org.infinispan.remoting.rpc.RpcManager;
-import org.infinispan.test.MultipleCacheManagersTest;
-import org.infinispan.test.TestingUtil;
-
-/**
- * @author Mircea.Markus at jboss.com
- * @since 4.2
- */
-public abstract class BaseDldTest extends MultipleCacheManagersTest {
-
- protected ControlledRpcManager rpcManager0;
- protected ControlledRpcManager rpcManager1;
-
- public static ControlledRpcManager replaceRpcManager(Cache cache) {
- RpcManager rpcManager1 = TestingUtil.extractComponent(cache, RpcManager.class);
- ControlledRpcManager controlledRpcManager1 = new ControlledRpcManager(rpcManager1);
- TestingUtil.replaceComponent(cache, RpcManager.class, controlledRpcManager1, true);
- return controlledRpcManager1;
- }
-
-}
Copied: trunk/core/src/test/java/org/infinispan/tx/dld/BaseDldTest.java (from rev 2385, branches/4.2.x/core/src/test/java/org/infinispan/tx/dld/BaseDldTest.java)
===================================================================
--- trunk/core/src/test/java/org/infinispan/tx/dld/BaseDldTest.java (rev 0)
+++ trunk/core/src/test/java/org/infinispan/tx/dld/BaseDldTest.java 2010-09-15 19:09:38 UTC (rev 2386)
@@ -0,0 +1,24 @@
+package org.infinispan.tx.dld;
+
+import org.infinispan.Cache;
+import org.infinispan.remoting.rpc.RpcManager;
+import org.infinispan.test.MultipleCacheManagersTest;
+import org.infinispan.test.TestingUtil;
+
+/**
+ * @author Mircea.Markus at jboss.com
+ * @since 4.2
+ */
+public abstract class BaseDldTest extends MultipleCacheManagersTest {
+
+ protected ControlledRpcManager rpcManager0;
+ protected ControlledRpcManager rpcManager1;
+
+ public static ControlledRpcManager replaceRpcManager(Cache cache) {
+ RpcManager rpcManager1 = TestingUtil.extractComponent(cache, RpcManager.class);
+ ControlledRpcManager controlledRpcManager1 = new ControlledRpcManager(rpcManager1);
+ TestingUtil.replaceComponent(cache, RpcManager.class, controlledRpcManager1, true);
+ return controlledRpcManager1;
+ }
+
+}
Deleted: trunk/core/src/test/java/org/infinispan/tx/dld/ControlledRpcManager.java
===================================================================
--- branches/4.2.x/core/src/test/java/org/infinispan/tx/dld/ControlledRpcManager.java 2010-09-15 16:19:59 UTC (rev 2385)
+++ trunk/core/src/test/java/org/infinispan/tx/dld/ControlledRpcManager.java 2010-09-15 19:09:38 UTC (rev 2386)
@@ -1,146 +0,0 @@
-package org.infinispan.tx.dld;
-
-import org.infinispan.commands.ReplicableCommand;
-import org.infinispan.commands.control.LockControlCommand;
-import org.infinispan.commands.remote.ClusteredGetCommand;
-import org.infinispan.remoting.ReplicationException;
-import org.infinispan.remoting.responses.Response;
-import org.infinispan.remoting.rpc.ResponseFilter;
-import org.infinispan.remoting.rpc.ResponseMode;
-import org.infinispan.remoting.rpc.RpcManager;
-import org.infinispan.remoting.transport.Address;
-import org.infinispan.remoting.transport.Transport;
-import org.infinispan.statetransfer.StateTransferException;
-import org.infinispan.util.concurrent.NotifyingNotifiableFuture;
-
-import java.util.Collection;
-import java.util.List;
-import java.util.concurrent.CountDownLatch;
-
-/**
-* @author Mircea.Markus at jboss.com
-* @since 4.2
-*/
-public final class ControlledRpcManager implements RpcManager {
-
- private volatile CountDownLatch replicationLatch;
-
- private boolean fail;
-
- public ControlledRpcManager(RpcManager realOne) {
- this.realOne = realOne;
- }
-
- private RpcManager realOne;
-
- public boolean isFail() {
- return fail;
- }
-
- public void setFail(boolean fail) {
- this.fail = fail;
- }
-
- public void setReplicationLatch(CountDownLatch replicationLatch) {
- this.replicationLatch = replicationLatch;
- }
-
- public List<Response> invokeRemotely(Collection<Address> recipients, ReplicableCommand rpcCommand, ResponseMode mode, long timeout, boolean usePriorityQueue, ResponseFilter responseFilter) {
- failIfNeeded();
- waitFirst(rpcCommand);
- return realOne.invokeRemotely(recipients, rpcCommand, mode, timeout, usePriorityQueue, responseFilter);
- }
-
- public List<Response> invokeRemotely(Collection<Address> recipients, ReplicableCommand rpcCommand, ResponseMode mode, long timeout, boolean usePriorityQueue) {
- failIfNeeded();
- waitFirst(rpcCommand);
- return realOne.invokeRemotely(recipients, rpcCommand, mode, timeout, usePriorityQueue);
- }
-
- public List<Response> invokeRemotely(Collection<Address> recipients, ReplicableCommand rpcCommand, ResponseMode mode, long timeout) throws Exception {
- failIfNeeded();
- waitFirst(rpcCommand);
- return realOne.invokeRemotely(recipients, rpcCommand, mode, timeout);
- }
-
- public void retrieveState(String cacheName, long timeout) throws StateTransferException {
- failIfNeeded();
- realOne.retrieveState(cacheName, timeout);
- }
-
- public void broadcastRpcCommand(ReplicableCommand rpc, boolean sync) throws ReplicationException {
- failIfNeeded();
- waitFirst(rpc);
- realOne.broadcastRpcCommand(rpc, sync);
- }
-
- public void broadcastRpcCommand(ReplicableCommand rpc, boolean sync, boolean usePriorityQueue) throws ReplicationException {
- failIfNeeded();
- waitFirst(rpc);
- realOne.broadcastRpcCommand(rpc, sync, usePriorityQueue);
- }
-
- private void waitFirst(ReplicableCommand rpcCommand) {
- failIfNeeded();
- if (!(rpcCommand instanceof ClusteredGetCommand) && !(rpcCommand instanceof LockControlCommand)) {
- System.out.println(Thread.currentThread().getName() + " -- replication trigger called!");
- try {
- replicationLatch.await();
- } catch (Exception e) {
- throw new RuntimeException("Unexpected exception!", e);
- }
- }
-
- }
-
- public void broadcastRpcCommandInFuture(ReplicableCommand rpc, NotifyingNotifiableFuture<Object> future) {
- failIfNeeded();
- realOne.broadcastRpcCommandInFuture(rpc, future);
- }
-
- public void broadcastRpcCommandInFuture(ReplicableCommand rpc, boolean usePriorityQueue, NotifyingNotifiableFuture<Object> future) {
- failIfNeeded();
- realOne.broadcastRpcCommandInFuture(rpc, usePriorityQueue, future);
- }
-
- public void invokeRemotely(Collection<Address> recipients, ReplicableCommand rpc, boolean sync) throws ReplicationException {
- failIfNeeded();
- realOne.invokeRemotely(recipients, rpc, sync);
- }
-
- public void invokeRemotely(Collection<Address> recipients, ReplicableCommand rpc, boolean sync, boolean usePriorityQueue) throws ReplicationException {
- failIfNeeded();
- realOne.invokeRemotely(recipients, rpc, sync, usePriorityQueue);
- }
-
- public void invokeRemotelyInFuture(Collection<Address> recipients, ReplicableCommand rpc, NotifyingNotifiableFuture<Object> future) {
- failIfNeeded();
- realOne.invokeRemotelyInFuture(recipients, rpc, future);
- }
-
- public void invokeRemotelyInFuture(Collection<Address> recipients, ReplicableCommand rpc, boolean usePriorityQueue, NotifyingNotifiableFuture<Object> future) {
- failIfNeeded();
- realOne.invokeRemotelyInFuture(recipients, rpc, usePriorityQueue, future);
- }
-
- public void invokeRemotelyInFuture(Collection<Address> recipients, ReplicableCommand rpc, boolean usePriorityQueue, NotifyingNotifiableFuture<Object> future, long timeout) {
- failIfNeeded();
- realOne.invokeRemotelyInFuture(recipients, rpc, usePriorityQueue, future, timeout);
- }
-
- public Transport getTransport() {
- return realOne.getTransport();
- }
-
- public Address getCurrentStateTransferSource() {
- return realOne.getCurrentStateTransferSource();
- }
-
- public Address getAddress() {
- return realOne.getAddress();
- }
-
- public void failIfNeeded() {
- if (fail) throw new IllegalStateException("Induced failure!");
- }
-}
Copied: trunk/core/src/test/java/org/infinispan/tx/dld/ControlledRpcManager.java (from rev 2385, branches/4.2.x/core/src/test/java/org/infinispan/tx/dld/ControlledRpcManager.java)
===================================================================
--- trunk/core/src/test/java/org/infinispan/tx/dld/ControlledRpcManager.java (rev 0)
+++ trunk/core/src/test/java/org/infinispan/tx/dld/ControlledRpcManager.java 2010-09-15 19:09:38 UTC (rev 2386)
@@ -0,0 +1,146 @@
+package org.infinispan.tx.dld;
+
+import org.infinispan.commands.ReplicableCommand;
+import org.infinispan.commands.control.LockControlCommand;
+import org.infinispan.commands.remote.ClusteredGetCommand;
+import org.infinispan.remoting.ReplicationException;
+import org.infinispan.remoting.responses.Response;
+import org.infinispan.remoting.rpc.ResponseFilter;
+import org.infinispan.remoting.rpc.ResponseMode;
+import org.infinispan.remoting.rpc.RpcManager;
+import org.infinispan.remoting.transport.Address;
+import org.infinispan.remoting.transport.Transport;
+import org.infinispan.statetransfer.StateTransferException;
+import org.infinispan.util.concurrent.NotifyingNotifiableFuture;
+
+import java.util.Collection;
+import java.util.List;
+import java.util.concurrent.CountDownLatch;
+
+/**
+* @author Mircea.Markus at jboss.com
+* @since 4.2
+*/
+public final class ControlledRpcManager implements RpcManager {
+
+ private volatile CountDownLatch replicationLatch;
+
+ private boolean fail;
+
+ public ControlledRpcManager(RpcManager realOne) {
+ this.realOne = realOne;
+ }
+
+ private RpcManager realOne;
+
+ public boolean isFail() {
+ return fail;
+ }
+
+ public void setFail(boolean fail) {
+ this.fail = fail;
+ }
+
+ public void setReplicationLatch(CountDownLatch replicationLatch) {
+ this.replicationLatch = replicationLatch;
+ }
+
+ public List<Response> invokeRemotely(Collection<Address> recipients, ReplicableCommand rpcCommand, ResponseMode mode, long timeout, boolean usePriorityQueue, ResponseFilter responseFilter) {
+ failIfNeeded();
+ waitFirst(rpcCommand);
+ return realOne.invokeRemotely(recipients, rpcCommand, mode, timeout, usePriorityQueue, responseFilter);
+ }
+
+ public List<Response> invokeRemotely(Collection<Address> recipients, ReplicableCommand rpcCommand, ResponseMode mode, long timeout, boolean usePriorityQueue) {
+ failIfNeeded();
+ waitFirst(rpcCommand);
+ return realOne.invokeRemotely(recipients, rpcCommand, mode, timeout, usePriorityQueue);
+ }
+
+ public List<Response> invokeRemotely(Collection<Address> recipients, ReplicableCommand rpcCommand, ResponseMode mode, long timeout) throws Exception {
+ failIfNeeded();
+ waitFirst(rpcCommand);
+ return realOne.invokeRemotely(recipients, rpcCommand, mode, timeout);
+ }
+
+ public void retrieveState(String cacheName, long timeout) throws StateTransferException {
+ failIfNeeded();
+ realOne.retrieveState(cacheName, timeout);
+ }
+
+ public void broadcastRpcCommand(ReplicableCommand rpc, boolean sync) throws ReplicationException {
+ failIfNeeded();
+ waitFirst(rpc);
+ realOne.broadcastRpcCommand(rpc, sync);
+ }
+
+ public void broadcastRpcCommand(ReplicableCommand rpc, boolean sync, boolean usePriorityQueue) throws ReplicationException {
+ failIfNeeded();
+ waitFirst(rpc);
+ realOne.broadcastRpcCommand(rpc, sync, usePriorityQueue);
+ }
+
+ private void waitFirst(ReplicableCommand rpcCommand) {
+ failIfNeeded();
+ if (!(rpcCommand instanceof ClusteredGetCommand) && !(rpcCommand instanceof LockControlCommand)) {
+ System.out.println(Thread.currentThread().getName() + " -- replication trigger called!");
+ try {
+ replicationLatch.await();
+ } catch (Exception e) {
+ throw new RuntimeException("Unexpected exception!", e);
+ }
+ }
+
+ }
+
+ public void broadcastRpcCommandInFuture(ReplicableCommand rpc, NotifyingNotifiableFuture<Object> future) {
+ failIfNeeded();
+ realOne.broadcastRpcCommandInFuture(rpc, future);
+ }
+
+ public void broadcastRpcCommandInFuture(ReplicableCommand rpc, boolean usePriorityQueue, NotifyingNotifiableFuture<Object> future) {
+ failIfNeeded();
+ realOne.broadcastRpcCommandInFuture(rpc, usePriorityQueue, future);
+ }
+
+ public void invokeRemotely(Collection<Address> recipients, ReplicableCommand rpc, boolean sync) throws ReplicationException {
+ failIfNeeded();
+ realOne.invokeRemotely(recipients, rpc, sync);
+ }
+
+ public void invokeRemotely(Collection<Address> recipients, ReplicableCommand rpc, boolean sync, boolean usePriorityQueue) throws ReplicationException {
+ failIfNeeded();
+ realOne.invokeRemotely(recipients, rpc, sync, usePriorityQueue);
+ }
+
+ public void invokeRemotelyInFuture(Collection<Address> recipients, ReplicableCommand rpc, NotifyingNotifiableFuture<Object> future) {
+ failIfNeeded();
+ realOne.invokeRemotelyInFuture(recipients, rpc, future);
+ }
+
+ public void invokeRemotelyInFuture(Collection<Address> recipients, ReplicableCommand rpc, boolean usePriorityQueue, NotifyingNotifiableFuture<Object> future) {
+ failIfNeeded();
+ realOne.invokeRemotelyInFuture(recipients, rpc, usePriorityQueue, future);
+ }
+
+ public void invokeRemotelyInFuture(Collection<Address> recipients, ReplicableCommand rpc, boolean usePriorityQueue, NotifyingNotifiableFuture<Object> future, long timeout) {
+ failIfNeeded();
+ realOne.invokeRemotelyInFuture(recipients, rpc, usePriorityQueue, future, timeout);
+ }
+
+ public Transport getTransport() {
+ return realOne.getTransport();
+ }
+
+ public Address getCurrentStateTransferSource() {
+ return realOne.getCurrentStateTransferSource();
+ }
+
+ public Address getAddress() {
+ return realOne.getAddress();
+ }
+
+ public void failIfNeeded() {
+ if (fail) throw new IllegalStateException("Induced failure!");
+ }
+}
Deleted: trunk/core/src/test/java/org/infinispan/tx/dld/DldEagerLockingDistributedTest.java
===================================================================
--- branches/4.2.x/core/src/test/java/org/infinispan/tx/dld/DldEagerLockingDistributedTest.java 2010-09-15 16:19:59 UTC (rev 2385)
+++ trunk/core/src/test/java/org/infinispan/tx/dld/DldEagerLockingDistributedTest.java 2010-09-15 19:09:38 UTC (rev 2386)
@@ -1,56 +0,0 @@
-package org.infinispan.tx.dld;
-
-import org.infinispan.affinity.KeyAffinityService;
-import org.infinispan.affinity.KeyAffinityServiceFactory;
-import org.infinispan.affinity.RndKeyGenerator;
-import org.infinispan.config.Configuration;
-import org.infinispan.distribution.BaseDistFunctionalTest;
-import org.infinispan.manager.EmbeddedCacheManager;
-import org.infinispan.test.TestingUtil;
-import org.infinispan.test.fwk.TestCacheManagerFactory;
-import org.testng.annotations.AfterClass;
-import org.testng.annotations.Test;
-
-import javax.transaction.SystemException;
-import java.util.concurrent.Executor;
-
-/**
- * @author Mircea.Markus at jboss.com
- * @since 4.2
- */
- at Test (groups = "functional", testName = "tx.dld.DldEagerLockingDistributedTest")
-public class DldEagerLockingDistributedTest extends BaseDldEagerLockingTest {
-
- private KeyAffinityService cas;
- private Object k0;
- private Object k1;
-
- @Override
- protected void createCacheManagers() throws Throwable {
- Configuration config = getDefaultClusteredConfig(Configuration.CacheMode.DIST_SYNC);
- config.setUnsafeUnreliableReturnValues(true);
- config.setNumOwners(1);
- config.setEnableDeadlockDetection(true);
- config.setUseEagerLocking(true);
-
- EmbeddedCacheManager cm1 = TestCacheManagerFactory.createCacheManager(config, true);
- EmbeddedCacheManager cm2 = TestCacheManagerFactory.createCacheManager(config, true);
- registerCacheManager(cm1);
- registerCacheManager(cm2);
- TestingUtil.blockUntilViewsReceived(10000, cache(0), cache(1));
- BaseDistFunctionalTest.RehashWaiter.waitForInitRehashToComplete(cache(0), cache(1));
-
- cas = KeyAffinityServiceFactory.newKeyAffinityService(cache(0), new Executor() {
- public void execute(Runnable command) {
- new Thread(command).start();
- }
- }, new RndKeyGenerator(), 2, true);
- k0 = cas.getKeyForAddress(address(0));
- k1 = cas.getKeyForAddress(address(1));
- cas.stop();
- }
-
- public void testSymmetricDeadlock() throws SystemException {
- testSymmetricDld(k0, k1);
- }
-}
Copied: trunk/core/src/test/java/org/infinispan/tx/dld/DldEagerLockingDistributedTest.java (from rev 2385, branches/4.2.x/core/src/test/java/org/infinispan/tx/dld/DldEagerLockingDistributedTest.java)
===================================================================
--- trunk/core/src/test/java/org/infinispan/tx/dld/DldEagerLockingDistributedTest.java (rev 0)
+++ trunk/core/src/test/java/org/infinispan/tx/dld/DldEagerLockingDistributedTest.java 2010-09-15 19:09:38 UTC (rev 2386)
@@ -0,0 +1,56 @@
+package org.infinispan.tx.dld;
+
+import org.infinispan.affinity.KeyAffinityService;
+import org.infinispan.affinity.KeyAffinityServiceFactory;
+import org.infinispan.affinity.RndKeyGenerator;
+import org.infinispan.config.Configuration;
+import org.infinispan.distribution.BaseDistFunctionalTest;
+import org.infinispan.manager.EmbeddedCacheManager;
+import org.infinispan.test.TestingUtil;
+import org.infinispan.test.fwk.TestCacheManagerFactory;
+import org.testng.annotations.AfterClass;
+import org.testng.annotations.Test;
+
+import javax.transaction.SystemException;
+import java.util.concurrent.Executor;
+
+/**
+ * @author Mircea.Markus at jboss.com
+ * @since 4.2
+ */
+ at Test (groups = "functional", testName = "tx.dld.DldEagerLockingDistributedTest")
+public class DldEagerLockingDistributedTest extends BaseDldEagerLockingTest {
+
+ private KeyAffinityService cas;
+ private Object k0;
+ private Object k1;
+
+ @Override
+ protected void createCacheManagers() throws Throwable {
+ Configuration config = getDefaultClusteredConfig(Configuration.CacheMode.DIST_SYNC);
+ config.setUnsafeUnreliableReturnValues(true);
+ config.setNumOwners(1);
+ config.setEnableDeadlockDetection(true);
+ config.setUseEagerLocking(true);
+
+ EmbeddedCacheManager cm1 = TestCacheManagerFactory.createCacheManager(config, true);
+ EmbeddedCacheManager cm2 = TestCacheManagerFactory.createCacheManager(config, true);
+ registerCacheManager(cm1);
+ registerCacheManager(cm2);
+ TestingUtil.blockUntilViewsReceived(10000, cache(0), cache(1));
+ BaseDistFunctionalTest.RehashWaiter.waitForInitRehashToComplete(cache(0), cache(1));
+
+ cas = KeyAffinityServiceFactory.newKeyAffinityService(cache(0), new Executor() {
+ public void execute(Runnable command) {
+ new Thread(command).start();
+ }
+ }, new RndKeyGenerator(), 2, true);
+ k0 = cas.getKeyForAddress(address(0));
+ k1 = cas.getKeyForAddress(address(1));
+ cas.stop();
+ }
+
+ public void testSymmetricDeadlock() throws SystemException {
+ testSymmetricDld(k0, k1);
+ }
+}
Deleted: trunk/core/src/test/java/org/infinispan/tx/dld/DldEagerLockingReplicationTest.java
===================================================================
--- branches/4.2.x/core/src/test/java/org/infinispan/tx/dld/DldEagerLockingReplicationTest.java 2010-09-15 16:19:59 UTC (rev 2385)
+++ trunk/core/src/test/java/org/infinispan/tx/dld/DldEagerLockingReplicationTest.java 2010-09-15 19:09:38 UTC (rev 2386)
@@ -1,63 +0,0 @@
-package org.infinispan.tx.dld;
-
-import org.infinispan.config.Configuration;
-import org.infinispan.context.Flag;
-import org.infinispan.test.PerCacheExecutorThread;
-import org.infinispan.test.TestingUtil;
-import org.infinispan.util.concurrent.TimeoutException;
-import org.testng.annotations.Test;
-
-import javax.transaction.TransactionManager;
-
-/**
- * @author Mircea.Markus at jboss.com
- * @since 4.1
- */
- at Test(groups = "functional", testName = "tx.dld.DldEagerLockingReplicationTest")
-public class DldEagerLockingReplicationTest extends BaseDldEagerLockingTest {
-
- @Override
- protected void createCacheManagers() throws Throwable {
- Configuration configuration = getConfiguration();
- createClusteredCaches(2, configuration);
- TestingUtil.blockUntilViewsReceived(1000, cache(0), cache(1));
- }
-
- protected Configuration getConfiguration() throws Exception {
- Configuration configuration = getDefaultClusteredConfig(Configuration.CacheMode.REPL_SYNC, true);
- configuration.setUseEagerLocking(true);
- configuration.setEnableDeadlockDetection(true);
- configuration.setUseLockStriping(false);
- return configuration;
- }
-
- public void testDeadlock() throws Exception {
- testSymmetricDld("k1", "k2");
- }
-
- /**
- * On eager locking, remote locks are being acquired at first, and then local locks. This is for specifying the
- * behavior whe remote acquisition succeeds and local fails.
- */
- public void testDeadlockFailedToAcquireLocalLocks() throws Exception {
- //first acquire a local lock on k1
- TransactionManager tm = TestingUtil.getTransactionManager(cache(0));
- tm.begin();
- cache(0).getAdvancedCache().withFlags(Flag.CACHE_MODE_LOCAL).put("k1","v1");
- assert lm0.isLocked("k1");
- assert !lm1.isLocked("k1");
- try {
- ex0.execute(PerCacheExecutorThread.Operations.BEGGIN_TX);
- ex0.setKeyValue("k1", "v1_1");
- ex0.execute(PerCacheExecutorThread.Operations.PUT_KEY_VALUE);
- assert ex0.lastResponse() instanceof TimeoutException;
- eventually(new Condition() {
- public boolean isSatisfied() throws Exception {
- return !lm1.isLocked("k1");
- }
- });
- } finally {
- tm.rollback();
- }
- }
-}
Copied: trunk/core/src/test/java/org/infinispan/tx/dld/DldEagerLockingReplicationTest.java (from rev 2385, branches/4.2.x/core/src/test/java/org/infinispan/tx/dld/DldEagerLockingReplicationTest.java)
===================================================================
--- trunk/core/src/test/java/org/infinispan/tx/dld/DldEagerLockingReplicationTest.java (rev 0)
+++ trunk/core/src/test/java/org/infinispan/tx/dld/DldEagerLockingReplicationTest.java 2010-09-15 19:09:38 UTC (rev 2386)
@@ -0,0 +1,63 @@
+package org.infinispan.tx.dld;
+
+import org.infinispan.config.Configuration;
+import org.infinispan.context.Flag;
+import org.infinispan.test.PerCacheExecutorThread;
+import org.infinispan.test.TestingUtil;
+import org.infinispan.util.concurrent.TimeoutException;
+import org.testng.annotations.Test;
+
+import javax.transaction.TransactionManager;
+
+/**
+ * @author Mircea.Markus at jboss.com
+ * @since 4.1
+ */
+ at Test(groups = "functional", testName = "tx.dld.DldEagerLockingReplicationTest")
+public class DldEagerLockingReplicationTest extends BaseDldEagerLockingTest {
+
+ @Override
+ protected void createCacheManagers() throws Throwable {
+ Configuration configuration = getConfiguration();
+ createClusteredCaches(2, configuration);
+ TestingUtil.blockUntilViewsReceived(1000, cache(0), cache(1));
+ }
+
+ protected Configuration getConfiguration() throws Exception {
+ Configuration configuration = getDefaultClusteredConfig(Configuration.CacheMode.REPL_SYNC, true);
+ configuration.setUseEagerLocking(true);
+ configuration.setEnableDeadlockDetection(true);
+ configuration.setUseLockStriping(false);
+ return configuration;
+ }
+
+ public void testDeadlock() throws Exception {
+ testSymmetricDld("k1", "k2");
+ }
+
+ /**
+ * On eager locking, remote locks are being acquired at first, and then local locks. This is for specifying the
+ * behavior whe remote acquisition succeeds and local fails.
+ */
+ public void testDeadlockFailedToAcquireLocalLocks() throws Exception {
+ //first acquire a local lock on k1
+ TransactionManager tm = TestingUtil.getTransactionManager(cache(0));
+ tm.begin();
+ cache(0).getAdvancedCache().withFlags(Flag.CACHE_MODE_LOCAL).put("k1","v1");
+ assert lm0.isLocked("k1");
+ assert !lm1.isLocked("k1");
+ try {
+ ex0.execute(PerCacheExecutorThread.Operations.BEGGIN_TX);
+ ex0.setKeyValue("k1", "v1_1");
+ ex0.execute(PerCacheExecutorThread.Operations.PUT_KEY_VALUE);
+ assert ex0.lastResponse() instanceof TimeoutException;
+ eventually(new Condition() {
+ public boolean isSatisfied() throws Exception {
+ return !lm1.isLocked("k1");
+ }
+ });
+ } finally {
+ tm.rollback();
+ }
+ }
+}
Deleted: trunk/core/src/test/java/org/infinispan/tx/dld/DldLazyLockingDistributionTest.java
===================================================================
--- branches/4.2.x/core/src/test/java/org/infinispan/tx/dld/DldLazyLockingDistributionTest.java 2010-09-15 16:19:59 UTC (rev 2385)
+++ trunk/core/src/test/java/org/infinispan/tx/dld/DldLazyLockingDistributionTest.java 2010-09-15 19:09:38 UTC (rev 2386)
@@ -1,61 +0,0 @@
-package org.infinispan.tx.dld;
-
-import org.infinispan.affinity.KeyAffinityService;
-import org.infinispan.affinity.KeyAffinityServiceFactory;
-import org.infinispan.affinity.RndKeyGenerator;
-import org.infinispan.config.Configuration;
-import org.infinispan.distribution.BaseDistFunctionalTest;
-import org.infinispan.manager.EmbeddedCacheManager;
-import org.infinispan.test.TestingUtil;
-import org.infinispan.test.fwk.TestCacheManagerFactory;
-import org.testng.annotations.AfterClass;
-import org.testng.annotations.Test;
-
-import java.util.concurrent.Executor;
-
-/**
- * Tests deadlock detection when t1 acquire (k1, k2) and te acquires (k2, k1).
- *
- * @author Mircea.Markus at jboss.com
- * @since 4.2
- */
- at Test(groups = "functional", testName = "tx.dld.DldLazyLockingDistributionTest")
-public class DldLazyLockingDistributionTest extends BaseDldLazyLockingTest {
-
- private KeyAffinityService cas;
-
- @Override
- protected void createCacheManagers() throws Throwable {
- Configuration config = getDefaultClusteredConfig(Configuration.CacheMode.DIST_SYNC);
- config.setUnsafeUnreliableReturnValues(true);
- config.setNumOwners(1);
- config.setEnableDeadlockDetection(true);
- EmbeddedCacheManager cm1 = TestCacheManagerFactory.createCacheManager(config, true);
- EmbeddedCacheManager cm2 = TestCacheManagerFactory.createCacheManager(config, true);
- registerCacheManager(cm1);
- registerCacheManager(cm2);
- TestingUtil.blockUntilViewsReceived(10000, cache(0), cache(1));
- BaseDistFunctionalTest.RehashWaiter.waitForInitRehashToComplete(cache(0), cache(1));
-
- cas = KeyAffinityServiceFactory.newKeyAffinityService(cache(0), new Executor() {
- public void execute(Runnable command) {
- new Thread(command).start();
- }
- }, new RndKeyGenerator(), 2, true);
-
- rpcManager0 = DldLazyLockingReplicationTest.replaceRpcManager(cache(0));
- rpcManager1 = DldLazyLockingReplicationTest.replaceRpcManager(cache(1));
- }
-
- public void testSymmetricDeadlock() {
- Object k0 = cas.getKeyForAddress(address(0));
- Object k1 = cas.getKeyForAddress(address(1));
- testSymmetricDeadlock(k0, k1);
- }
-
- @AfterClass
- public void destroyKeyService() {
- cas.stop();
- }
-
-}
Copied: trunk/core/src/test/java/org/infinispan/tx/dld/DldLazyLockingDistributionTest.java (from rev 2385, branches/4.2.x/core/src/test/java/org/infinispan/tx/dld/DldLazyLockingDistributionTest.java)
===================================================================
--- trunk/core/src/test/java/org/infinispan/tx/dld/DldLazyLockingDistributionTest.java (rev 0)
+++ trunk/core/src/test/java/org/infinispan/tx/dld/DldLazyLockingDistributionTest.java 2010-09-15 19:09:38 UTC (rev 2386)
@@ -0,0 +1,61 @@
+package org.infinispan.tx.dld;
+
+import org.infinispan.affinity.KeyAffinityService;
+import org.infinispan.affinity.KeyAffinityServiceFactory;
+import org.infinispan.affinity.RndKeyGenerator;
+import org.infinispan.config.Configuration;
+import org.infinispan.distribution.BaseDistFunctionalTest;
+import org.infinispan.manager.EmbeddedCacheManager;
+import org.infinispan.test.TestingUtil;
+import org.infinispan.test.fwk.TestCacheManagerFactory;
+import org.testng.annotations.AfterClass;
+import org.testng.annotations.Test;
+
+import java.util.concurrent.Executor;
+
+/**
+ * Tests deadlock detection when t1 acquire (k1, k2) and te acquires (k2, k1).
+ *
+ * @author Mircea.Markus at jboss.com
+ * @since 4.2
+ */
+ at Test(groups = "functional", testName = "tx.dld.DldLazyLockingDistributionTest")
+public class DldLazyLockingDistributionTest extends BaseDldLazyLockingTest {
+
+ private KeyAffinityService cas;
+
+ @Override
+ protected void createCacheManagers() throws Throwable {
+ Configuration config = getDefaultClusteredConfig(Configuration.CacheMode.DIST_SYNC);
+ config.setUnsafeUnreliableReturnValues(true);
+ config.setNumOwners(1);
+ config.setEnableDeadlockDetection(true);
+ EmbeddedCacheManager cm1 = TestCacheManagerFactory.createCacheManager(config, true);
+ EmbeddedCacheManager cm2 = TestCacheManagerFactory.createCacheManager(config, true);
+ registerCacheManager(cm1);
+ registerCacheManager(cm2);
+ TestingUtil.blockUntilViewsReceived(10000, cache(0), cache(1));
+ BaseDistFunctionalTest.RehashWaiter.waitForInitRehashToComplete(cache(0), cache(1));
+
+ cas = KeyAffinityServiceFactory.newKeyAffinityService(cache(0), new Executor() {
+ public void execute(Runnable command) {
+ new Thread(command).start();
+ }
+ }, new RndKeyGenerator(), 2, true);
+
+ rpcManager0 = DldLazyLockingReplicationTest.replaceRpcManager(cache(0));
+ rpcManager1 = DldLazyLockingReplicationTest.replaceRpcManager(cache(1));
+ }
+
+ public void testSymmetricDeadlock() {
+ Object k0 = cas.getKeyForAddress(address(0));
+ Object k1 = cas.getKeyForAddress(address(1));
+ testSymmetricDeadlock(k0, k1);
+ }
+
+ @AfterClass
+ public void destroyKeyService() {
+ cas.stop();
+ }
+
+}
Deleted: trunk/core/src/test/java/org/infinispan/tx/dld/DldLazyLockingReplicationTest.java
===================================================================
--- branches/4.2.x/core/src/test/java/org/infinispan/tx/dld/DldLazyLockingReplicationTest.java 2010-09-15 16:19:59 UTC (rev 2385)
+++ trunk/core/src/test/java/org/infinispan/tx/dld/DldLazyLockingReplicationTest.java 2010-09-15 19:09:38 UTC (rev 2386)
@@ -1,217 +0,0 @@
-package org.infinispan.tx.dld;
-
-import org.infinispan.api.mvcc.LockAssert;
-import org.infinispan.config.Configuration;
-import org.infinispan.context.impl.NonTxInvocationContext;
-import org.infinispan.interceptors.DeadlockDetectingInterceptor;
-import org.infinispan.interceptors.InterceptorChain;
-import org.infinispan.remoting.rpc.RpcManager;
-import org.infinispan.test.PerCacheExecutorThread;
-import org.infinispan.test.TestingUtil;
-import org.infinispan.util.concurrent.locks.DeadlockDetectingLockManager;
-import org.infinispan.util.concurrent.locks.LockManager;
-import org.testng.annotations.AfterMethod;
-import org.testng.annotations.BeforeMethod;
-import org.testng.annotations.Test;
-
-import java.util.concurrent.CountDownLatch;
-
-/**
- * Functional test for deadlock detection.
- *
- * @author Mircea.Markus at jboss.com
- */
- at Test(testName = "tx.dld.DldLazyLockingReplicationTest", groups = "functional")
-public class DldLazyLockingReplicationTest extends BaseDldLazyLockingTest {
-
- protected CountDownLatch replicationLatch;
- protected PerCacheExecutorThread t1;
- protected PerCacheExecutorThread t2;
- protected DeadlockDetectingLockManager ddLm1;
- protected DeadlockDetectingLockManager ddLm2;
-
- protected void createCacheManagers() throws Throwable {
- Configuration config = getDefaultClusteredConfig(Configuration.CacheMode.REPL_SYNC, true);
- config.setEnableDeadlockDetection(true);
- config.setSyncCommitPhase(true);
- config.setSyncRollbackPhase(true);
- config.setUseLockStriping(false);
- assert config.isEnableDeadlockDetection();
- createClusteredCaches(2, config);
- assert config.isEnableDeadlockDetection();
-
- assert cache(0).getConfiguration().isEnableDeadlockDetection();
- assert cache(1).getConfiguration().isEnableDeadlockDetection();
- assert !cache(0).getConfiguration().isExposeJmxStatistics();
- assert !cache(1).getConfiguration().isExposeJmxStatistics();
-
- ((DeadlockDetectingLockManager) TestingUtil.extractLockManager(cache(0))).setExposeJmxStats(true);
- ((DeadlockDetectingLockManager) TestingUtil.extractLockManager(cache(1))).setExposeJmxStats(true);
-
- rpcManager0 = replaceRpcManager(cache(0));
- rpcManager1 = replaceRpcManager(cache(1));
-
- assert TestingUtil.extractComponent(cache(0), RpcManager.class) instanceof ControlledRpcManager;
- assert TestingUtil.extractComponent(cache(1), RpcManager.class) instanceof ControlledRpcManager;
-
- ddLm1 = (DeadlockDetectingLockManager) TestingUtil.extractLockManager(cache(0));
- ddLm2 = (DeadlockDetectingLockManager) TestingUtil.extractLockManager(cache(1));
- }
-
-
- @BeforeMethod
- public void beforeMethod() {
- t1 = new PerCacheExecutorThread(cache(0), 1);
- t2 = new PerCacheExecutorThread(cache(1), 2);
- replicationLatch = new CountDownLatch(1);
- rpcManager0.setReplicationLatch(replicationLatch);
- rpcManager1.setReplicationLatch(replicationLatch);
- log.trace("_________________________ Here it begins");
- }
-
- @AfterMethod
- public void afterMethod() {
- t1.stopThread();
- t2.stopThread();
- ((DeadlockDetectingLockManager) TestingUtil.extractLockManager(cache(0))).resetStatistics();
- ((DeadlockDetectingLockManager) TestingUtil.extractLockManager(cache(1))).resetStatistics();
- }
-
- public void testSymmetricDeadlock() {
- super.testSymmetricDeadlock("k0", "k1");
- }
-
- public void testLocalVsRemoteDeadlock() {
- replicationLatch.countDown();
- testLocalVsRemoteDeadlock("k0", "k1");
- }
-
- public void testExpectedInnerStructure() {
- LockManager lockManager = TestingUtil.extractComponent(cache(0), LockManager.class);
- assert lockManager instanceof DeadlockDetectingLockManager;
-
- InterceptorChain ic = TestingUtil.extractComponent(cache(0), InterceptorChain.class);
- assert ic.containsInterceptorType(DeadlockDetectingInterceptor.class);
- }
-
- public void testSameKeyDeadlock() throws Exception {
- t1.setKeyValue("key", "value1");
- t2.setKeyValue("key", "value2");
- assert PerCacheExecutorThread.OperationsResult.BEGGIN_TX_OK == t1.execute(PerCacheExecutorThread.Operations.BEGGIN_TX);
- assert PerCacheExecutorThread.OperationsResult.BEGGIN_TX_OK == t2.execute(PerCacheExecutorThread.Operations.BEGGIN_TX);
- System.out.println("After begin");
-
- t1.execute(PerCacheExecutorThread.Operations.PUT_KEY_VALUE);
- t2.execute(PerCacheExecutorThread.Operations.PUT_KEY_VALUE);
- System.out.println("After put key value");
-
- t1.clearResponse();
- t2.clearResponse();
-
- t1.executeNoResponse(PerCacheExecutorThread.Operations.COMMIT_TX);
- t2.executeNoResponse(PerCacheExecutorThread.Operations.COMMIT_TX);
-
- System.out.println("Now replication is triggered");
- replicationLatch.countDown();
-
-
- Object t1Commit = t1.waitForResponse();
- Object t2Commit = t2.waitForResponse();
- System.out.println("After commit: " + t1Commit + ", " + t2Commit);
-
- assert xor(t1Commit instanceof Exception, t2Commit instanceof Exception) : "only one thread must be failing " + t1Commit + "," + t2Commit;
- System.out.println("t2Commit = " + t2Commit);
- System.out.println("t1Commit = " + t1Commit);
-
- if (t1Commit instanceof Exception) {
- System.out.println("t1 rolled back");
- Object o = cache(0).get("key");
- assert o != null;
- assert o.equals("value2");
- } else {
- System.out.println("t2 rolled back");
- Object o = cache(0).get("key");
- assert o != null;
- assert o.equals("value1");
- o = cache(1).get("key");
- assert o != null;
- assert o.equals("value1");
- }
-
- assert ddLm1.getDetectedRemoteDeadlocks() + ddLm2.getDetectedRemoteDeadlocks() >= 1;
-
- LockManager lm1 = TestingUtil.extractComponent(cache(0), LockManager.class);
- assert !lm1.isLocked("key") : "It is locked by " + lm1.getOwner("key");
- LockManager lm2 = TestingUtil.extractComponent(cache(1), LockManager.class);
- assert !lm2.isLocked("key") : "It is locked by " + lm2.getOwner("key");
- LockAssert.assertNoLocks(cache(0));
- }
-
- public void testDeadlockDetectedOneTx() throws Exception {
- t1.setKeyValue("key", "value1");
-
- LockManager lm2 = TestingUtil.extractComponent(cache(1), LockManager.class);
- NonTxInvocationContext ctx = cache(1).getAdvancedCache().getInvocationContextContainer().createNonTxInvocationContext();
- lm2.lockAndRecord("key", ctx);
- assert lm2.isLocked("key");
-
-
- assert PerCacheExecutorThread.OperationsResult.BEGGIN_TX_OK == t1.execute(PerCacheExecutorThread.Operations.BEGGIN_TX) : "but received " + t1.lastResponse();
- t1.execute(PerCacheExecutorThread.Operations.PUT_KEY_VALUE);
-
- t1.clearResponse();
- t1.executeNoResponse(PerCacheExecutorThread.Operations.COMMIT_TX);
-
- replicationLatch.countDown();
- System.out.println("Now replication is triggered");
-
- t1.waitForResponse();
-
-
- Object t1CommitRsp = t1.lastResponse();
-
- assert t1CommitRsp instanceof Exception : "expected exception, received " + t1.lastResponse();
-
- LockManager lm1 = TestingUtil.extractComponent(cache(0), LockManager.class);
- assert !lm1.isLocked("key") : "It is locked by " + lm1.getOwner("key");
-
- lm2.unlock("key");
- assert !lm2.isLocked("key");
- assert !lm1.isLocked("key");
- }
-
- public void testLockReleasedWhileTryingToAcquire() throws Exception {
- t1.setKeyValue("key", "value1");
-
- LockManager lm2 = TestingUtil.extractComponent(cache(1), LockManager.class);
- NonTxInvocationContext ctx = cache(1).getAdvancedCache().getInvocationContextContainer().createNonTxInvocationContext();
- lm2.lockAndRecord("key", ctx);
- assert lm2.isLocked("key");
-
-
- assert PerCacheExecutorThread.OperationsResult.BEGGIN_TX_OK == t1.execute(PerCacheExecutorThread.Operations.BEGGIN_TX) : "but received " + t1.lastResponse();
- t1.execute(PerCacheExecutorThread.Operations.PUT_KEY_VALUE);
-
- t1.clearResponse();
- t1.executeNoResponse(PerCacheExecutorThread.Operations.COMMIT_TX);
-
- replicationLatch.countDown();
-
- Thread.sleep(3000); //just to make sure the remote tx thread managed to spin around for some times.
- lm2.unlock("key");
-
- t1.waitForResponse();
-
-
- Object t1CommitRsp = t1.lastResponse();
-
- assert t1CommitRsp == PerCacheExecutorThread.OperationsResult.COMMIT_TX_OK : "expected true, received " + t1.lastResponse();
-
- LockManager lm1 = TestingUtil.extractComponent(cache(0), LockManager.class);
- assert !lm1.isLocked("key") : "It is locked by " + lm1.getOwner("key");
-
- assert !lm2.isLocked("key");
- assert !lm1.isLocked("key");
- }
-
-}
Copied: trunk/core/src/test/java/org/infinispan/tx/dld/DldLazyLockingReplicationTest.java (from rev 2385, branches/4.2.x/core/src/test/java/org/infinispan/tx/dld/DldLazyLockingReplicationTest.java)
===================================================================
--- trunk/core/src/test/java/org/infinispan/tx/dld/DldLazyLockingReplicationTest.java (rev 0)
+++ trunk/core/src/test/java/org/infinispan/tx/dld/DldLazyLockingReplicationTest.java 2010-09-15 19:09:38 UTC (rev 2386)
@@ -0,0 +1,217 @@
+package org.infinispan.tx.dld;
+
+import org.infinispan.api.mvcc.LockAssert;
+import org.infinispan.config.Configuration;
+import org.infinispan.context.impl.NonTxInvocationContext;
+import org.infinispan.interceptors.DeadlockDetectingInterceptor;
+import org.infinispan.interceptors.InterceptorChain;
+import org.infinispan.remoting.rpc.RpcManager;
+import org.infinispan.test.PerCacheExecutorThread;
+import org.infinispan.test.TestingUtil;
+import org.infinispan.util.concurrent.locks.DeadlockDetectingLockManager;
+import org.infinispan.util.concurrent.locks.LockManager;
+import org.testng.annotations.AfterMethod;
+import org.testng.annotations.BeforeMethod;
+import org.testng.annotations.Test;
+
+import java.util.concurrent.CountDownLatch;
+
+/**
+ * Functional test for deadlock detection.
+ *
+ * @author Mircea.Markus at jboss.com
+ */
+ at Test(testName = "tx.dld.DldLazyLockingReplicationTest", groups = "functional")
+public class DldLazyLockingReplicationTest extends BaseDldLazyLockingTest {
+
+ protected CountDownLatch replicationLatch;
+ protected PerCacheExecutorThread t1;
+ protected PerCacheExecutorThread t2;
+ protected DeadlockDetectingLockManager ddLm1;
+ protected DeadlockDetectingLockManager ddLm2;
+
+ protected void createCacheManagers() throws Throwable {
+ Configuration config = getDefaultClusteredConfig(Configuration.CacheMode.REPL_SYNC, true);
+ config.setEnableDeadlockDetection(true);
+ config.setSyncCommitPhase(true);
+ config.setSyncRollbackPhase(true);
+ config.setUseLockStriping(false);
+ assert config.isEnableDeadlockDetection();
+ createClusteredCaches(2, config);
+ assert config.isEnableDeadlockDetection();
+
+ assert cache(0).getConfiguration().isEnableDeadlockDetection();
+ assert cache(1).getConfiguration().isEnableDeadlockDetection();
+ assert !cache(0).getConfiguration().isExposeJmxStatistics();
+ assert !cache(1).getConfiguration().isExposeJmxStatistics();
+
+ ((DeadlockDetectingLockManager) TestingUtil.extractLockManager(cache(0))).setExposeJmxStats(true);
+ ((DeadlockDetectingLockManager) TestingUtil.extractLockManager(cache(1))).setExposeJmxStats(true);
+
+ rpcManager0 = replaceRpcManager(cache(0));
+ rpcManager1 = replaceRpcManager(cache(1));
+
+ assert TestingUtil.extractComponent(cache(0), RpcManager.class) instanceof ControlledRpcManager;
+ assert TestingUtil.extractComponent(cache(1), RpcManager.class) instanceof ControlledRpcManager;
+
+ ddLm1 = (DeadlockDetectingLockManager) TestingUtil.extractLockManager(cache(0));
+ ddLm2 = (DeadlockDetectingLockManager) TestingUtil.extractLockManager(cache(1));
+ }
+
+
+ @BeforeMethod
+ public void beforeMethod() {
+ t1 = new PerCacheExecutorThread(cache(0), 1);
+ t2 = new PerCacheExecutorThread(cache(1), 2);
+ replicationLatch = new CountDownLatch(1);
+ rpcManager0.setReplicationLatch(replicationLatch);
+ rpcManager1.setReplicationLatch(replicationLatch);
+ log.trace("_________________________ Here it begins");
+ }
+
+ @AfterMethod
+ public void afterMethod() {
+ t1.stopThread();
+ t2.stopThread();
+ ((DeadlockDetectingLockManager) TestingUtil.extractLockManager(cache(0))).resetStatistics();
+ ((DeadlockDetectingLockManager) TestingUtil.extractLockManager(cache(1))).resetStatistics();
+ }
+
+ public void testSymmetricDeadlock() {
+ super.testSymmetricDeadlock("k0", "k1");
+ }
+
+ public void testLocalVsRemoteDeadlock() {
+ replicationLatch.countDown();
+ testLocalVsRemoteDeadlock("k0", "k1");
+ }
+
+ public void testExpectedInnerStructure() {
+ LockManager lockManager = TestingUtil.extractComponent(cache(0), LockManager.class);
+ assert lockManager instanceof DeadlockDetectingLockManager;
+
+ InterceptorChain ic = TestingUtil.extractComponent(cache(0), InterceptorChain.class);
+ assert ic.containsInterceptorType(DeadlockDetectingInterceptor.class);
+ }
+
+ public void testSameKeyDeadlock() throws Exception {
+ t1.setKeyValue("key", "value1");
+ t2.setKeyValue("key", "value2");
+ assert PerCacheExecutorThread.OperationsResult.BEGGIN_TX_OK == t1.execute(PerCacheExecutorThread.Operations.BEGGIN_TX);
+ assert PerCacheExecutorThread.OperationsResult.BEGGIN_TX_OK == t2.execute(PerCacheExecutorThread.Operations.BEGGIN_TX);
+ System.out.println("After begin");
+
+ t1.execute(PerCacheExecutorThread.Operations.PUT_KEY_VALUE);
+ t2.execute(PerCacheExecutorThread.Operations.PUT_KEY_VALUE);
+ System.out.println("After put key value");
+
+ t1.clearResponse();
+ t2.clearResponse();
+
+ t1.executeNoResponse(PerCacheExecutorThread.Operations.COMMIT_TX);
+ t2.executeNoResponse(PerCacheExecutorThread.Operations.COMMIT_TX);
+
+ System.out.println("Now replication is triggered");
+ replicationLatch.countDown();
+
+
+ Object t1Commit = t1.waitForResponse();
+ Object t2Commit = t2.waitForResponse();
+ System.out.println("After commit: " + t1Commit + ", " + t2Commit);
+
+ assert xor(t1Commit instanceof Exception, t2Commit instanceof Exception) : "only one thread must be failing " + t1Commit + "," + t2Commit;
+ System.out.println("t2Commit = " + t2Commit);
+ System.out.println("t1Commit = " + t1Commit);
+
+ if (t1Commit instanceof Exception) {
+ System.out.println("t1 rolled back");
+ Object o = cache(0).get("key");
+ assert o != null;
+ assert o.equals("value2");
+ } else {
+ System.out.println("t2 rolled back");
+ Object o = cache(0).get("key");
+ assert o != null;
+ assert o.equals("value1");
+ o = cache(1).get("key");
+ assert o != null;
+ assert o.equals("value1");
+ }
+
+ assert ddLm1.getDetectedRemoteDeadlocks() + ddLm2.getDetectedRemoteDeadlocks() >= 1;
+
+ LockManager lm1 = TestingUtil.extractComponent(cache(0), LockManager.class);
+ assert !lm1.isLocked("key") : "It is locked by " + lm1.getOwner("key");
+ LockManager lm2 = TestingUtil.extractComponent(cache(1), LockManager.class);
+ assert !lm2.isLocked("key") : "It is locked by " + lm2.getOwner("key");
+ LockAssert.assertNoLocks(cache(0));
+ }
+
+ public void testDeadlockDetectedOneTx() throws Exception {
+ t1.setKeyValue("key", "value1");
+
+ LockManager lm2 = TestingUtil.extractComponent(cache(1), LockManager.class);
+ NonTxInvocationContext ctx = cache(1).getAdvancedCache().getInvocationContextContainer().createNonTxInvocationContext();
+ lm2.lockAndRecord("key", ctx);
+ assert lm2.isLocked("key");
+
+
+ assert PerCacheExecutorThread.OperationsResult.BEGGIN_TX_OK == t1.execute(PerCacheExecutorThread.Operations.BEGGIN_TX) : "but received " + t1.lastResponse();
+ t1.execute(PerCacheExecutorThread.Operations.PUT_KEY_VALUE);
+
+ t1.clearResponse();
+ t1.executeNoResponse(PerCacheExecutorThread.Operations.COMMIT_TX);
+
+ replicationLatch.countDown();
+ System.out.println("Now replication is triggered");
+
+ t1.waitForResponse();
+
+
+ Object t1CommitRsp = t1.lastResponse();
+
+ assert t1CommitRsp instanceof Exception : "expected exception, received " + t1.lastResponse();
+
+ LockManager lm1 = TestingUtil.extractComponent(cache(0), LockManager.class);
+ assert !lm1.isLocked("key") : "It is locked by " + lm1.getOwner("key");
+
+ lm2.unlock("key");
+ assert !lm2.isLocked("key");
+ assert !lm1.isLocked("key");
+ }
+
+ public void testLockReleasedWhileTryingToAcquire() throws Exception {
+ t1.setKeyValue("key", "value1");
+
+ LockManager lm2 = TestingUtil.extractComponent(cache(1), LockManager.class);
+ NonTxInvocationContext ctx = cache(1).getAdvancedCache().getInvocationContextContainer().createNonTxInvocationContext();
+ lm2.lockAndRecord("key", ctx);
+ assert lm2.isLocked("key");
+
+
+ assert PerCacheExecutorThread.OperationsResult.BEGGIN_TX_OK == t1.execute(PerCacheExecutorThread.Operations.BEGGIN_TX) : "but received " + t1.lastResponse();
+ t1.execute(PerCacheExecutorThread.Operations.PUT_KEY_VALUE);
+
+ t1.clearResponse();
+ t1.executeNoResponse(PerCacheExecutorThread.Operations.COMMIT_TX);
+
+ replicationLatch.countDown();
+
+ Thread.sleep(3000); //just to make sure the remote tx thread managed to spin around for some times.
+ lm2.unlock("key");
+
+ t1.waitForResponse();
+
+
+ Object t1CommitRsp = t1.lastResponse();
+
+ assert t1CommitRsp == PerCacheExecutorThread.OperationsResult.COMMIT_TX_OK : "expected true, received " + t1.lastResponse();
+
+ LockManager lm1 = TestingUtil.extractComponent(cache(0), LockManager.class);
+ assert !lm1.isLocked("key") : "It is locked by " + lm1.getOwner("key");
+
+ assert !lm2.isLocked("key");
+ assert !lm1.isLocked("key");
+ }
+
+}
Deleted: trunk/core/src/test/java/org/infinispan/tx/dld/LocalDeadlockDetectionTest.java
===================================================================
--- branches/4.2.x/core/src/test/java/org/infinispan/tx/dld/LocalDeadlockDetectionTest.java 2010-09-15 16:19:59 UTC (rev 2385)
+++ trunk/core/src/test/java/org/infinispan/tx/dld/LocalDeadlockDetectionTest.java 2010-09-15 19:09:38 UTC (rev 2386)
@@ -1,190 +0,0 @@
-package org.infinispan.tx.dld;
-
-import org.infinispan.config.Configuration;
-import org.infinispan.manager.EmbeddedCacheManager;
-import org.infinispan.test.PerCacheExecutorThread;
-import org.infinispan.test.SingleCacheManagerTest;
-import org.infinispan.test.TestingUtil;
-import org.infinispan.test.fwk.TestCacheManagerFactory;
-import org.infinispan.util.concurrent.locks.DeadlockDetectedException;
-import org.infinispan.util.concurrent.locks.DeadlockDetectingLockManager;
-import static org.testng.Assert.assertEquals;
-
-import org.testng.annotations.AfterMethod;
-import org.testng.annotations.BeforeMethod;
-import org.testng.annotations.Test;
-
-import javax.transaction.RollbackException;
-
-/**
- * Tests deadlock detection functionality for local caches.
- *
- * @author Mircea.Markus at jboss.com
- */
- at Test(groups = "functional", testName = "tx.dld.LocalDeadlockDetectionTest")
-public class LocalDeadlockDetectionTest extends SingleCacheManagerTest {
-
- private PerCacheExecutorThread t1;
- private PerCacheExecutorThread t2;
- private DeadlockDetectingLockManager lockManager;
- private Object response1;
- private Object response2;
-
- protected EmbeddedCacheManager createCacheManager() throws Exception {
- cacheManager = TestCacheManagerFactory.createLocalCacheManager();
- Configuration configuration = getDefaultStandaloneConfig(true);
- configuration.setEnableDeadlockDetection(true);
- configuration.setUseLockStriping(false);
- configuration.setExposeJmxStatistics(true);
- cacheManager.defineConfiguration("test", configuration);
- cache = cacheManager.getCache("test");
- lockManager = (DeadlockDetectingLockManager) TestingUtil.extractLockManager(cache);
- return cacheManager;
- }
-
- @BeforeMethod
- public void startExecutors() {
- t1 = new PerCacheExecutorThread(cache, 0);
- t2 = new PerCacheExecutorThread(cache, 1);
- lockManager.resetStatistics();
- }
-
-
- @AfterMethod
- public void stopExecutors() {
- t1.stopThread();
- t2.stopThread();
- }
-
- public void testDldPutAndPut() {
- testLocalVsLocalTxDeadlock(PerCacheExecutorThread.Operations.PUT_KEY_VALUE,
- PerCacheExecutorThread.Operations.PUT_KEY_VALUE);
- if (response1 instanceof Exception) {
- assertEquals("value_1_t2", cache.get("k1"));
- assertEquals("value_2_t2", cache.get("k2"));
- } else {
- assertEquals("value_1_t1", cache.get("k1"));
- assertEquals("value_2_t1", cache.get("k2"));
- }
- }
-
- public void testDldPutAndRemove() {
- testLocalVsLocalTxDeadlock(PerCacheExecutorThread.Operations.PUT_KEY_VALUE,
- PerCacheExecutorThread.Operations.REMOVE_KEY);
- if (response1 instanceof Exception) {
- assertEquals(cache.get("k1"), null);
- assertEquals("value_2_t2", cache.get("k2"));
- } else {
- assertEquals("value_1_t1", cache.get("k1"));
- assertEquals(null, cache.get("k2"));
- }
- }
-
- public void testDldRemoveAndPut() {
- testLocalVsLocalTxDeadlock(PerCacheExecutorThread.Operations.REMOVE_KEY,
- PerCacheExecutorThread.Operations.PUT_KEY_VALUE);
- if (response1 instanceof Exception) {
- System.out.println("t1 failure");
- assertEquals(cache.get("k1"), "value_1_t2");
- assertEquals(cache.get("k2"), null);
- } else {
- System.out.println("t2 failure");
- assertEquals(cache.get("k1"), null);
- assertEquals(cache.get("k2"), "value_2_t1");
- }
- }
-
- public void testDldRemoveAndRemove() {
- testLocalVsLocalTxDeadlock(PerCacheExecutorThread.Operations.REMOVE_KEY,
- PerCacheExecutorThread.Operations.REMOVE_KEY);
- if (response1 instanceof Exception) {
- System.out.println("t1 failure");
- assertEquals(cache.get("k1"), null);
- assertEquals(cache.get("k2"), null);
- } else {
- System.out.println("t2 failure");
- assertEquals(cache.get("k1"), null);
- assertEquals(cache.get("k2"), null);
- }
- }
-
- public void testDldPutAndReplace() {
-
- cache.put("k1", "initial_1");
- cache.put("k2", "initial_2");
-
- testLocalVsLocalTxDeadlock(PerCacheExecutorThread.Operations.PUT_KEY_VALUE,
- PerCacheExecutorThread.Operations.REPLACE_KEY_VALUE);
- if (response1 instanceof Exception) {
- System.out.println("t1 failure");
- assertEquals(cache.get("k1"), "value_1_t2");
- assertEquals(cache.get("k2"), "value_2_t2");
- } else {
- System.out.println("t2 failure");
- assertEquals(cache.get("k1"), "value_1_t1");
- assertEquals(cache.get("k2"), "value_2_t1");
- }
- }
-
- public void testDldReplaceAndPut() {
-
- cache.put("k1", "initial_1");
- cache.put("k2", "initial_2");
-
- testLocalVsLocalTxDeadlock(PerCacheExecutorThread.Operations.REPLACE_KEY_VALUE,
- PerCacheExecutorThread.Operations.PUT_KEY_VALUE);
- if (response1 instanceof Exception) {
- System.out.println("t1 failure");
- assertEquals(cache.get("k1"), "value_1_t2");
- assertEquals(cache.get("k2"), "value_2_t2");
- } else {
- System.out.println("t2 failure");
- assertEquals(cache.get("k1"), "value_1_t1");
- assertEquals(cache.get("k2"), "value_2_t1");
- }
- }
-
-
- private void testLocalVsLocalTxDeadlock(PerCacheExecutorThread.Operations firstOperation, PerCacheExecutorThread.Operations secondOperation) {
-
- assert PerCacheExecutorThread.OperationsResult.BEGGIN_TX_OK == t1.execute(PerCacheExecutorThread.Operations.BEGGIN_TX);
- assert PerCacheExecutorThread.OperationsResult.BEGGIN_TX_OK == t2.execute(PerCacheExecutorThread.Operations.BEGGIN_TX);
- System.out.println("After begin");
-
- t1.setKeyValue("k1", "value_1_t1");
- t2.setKeyValue("k2", "value_2_t2");
-
- assertEquals(t1.execute(firstOperation), firstOperation.getCorrespondingOkResult());
- assertEquals(t2.execute(firstOperation), firstOperation.getCorrespondingOkResult());
-
- assert lockManager.isLocked("k1");
- assert lockManager.isLocked("k2");
-
-
- t1.setKeyValue("k2", "value_2_t1");
- t2.setKeyValue("k1", "value_1_t2");
- t1.executeNoResponse(secondOperation);
- t2.executeNoResponse(secondOperation);
-
- response1 = t1.waitForResponse();
- response2 = t2.waitForResponse();
-
- assert xor(response1 instanceof DeadlockDetectedException, response2 instanceof DeadlockDetectedException) : "expected one and only one exception: " + response1 + ", " + response2;
- assert xor(response1 == secondOperation.getCorrespondingOkResult(), response2 == secondOperation.getCorrespondingOkResult()) : "expected one and only one exception: " + response1 + ", " + response2;
-
- assert lockManager.isLocked("k1");
- assert lockManager.isLocked("k2");
- assert lockManager.getOwner("k1") == lockManager.getOwner("k2");
-
- if (response1 instanceof Exception) {
- assert PerCacheExecutorThread.OperationsResult.COMMIT_TX_OK == t2.execute(PerCacheExecutorThread.Operations.COMMIT_TX);
- assert t1.execute(PerCacheExecutorThread.Operations.COMMIT_TX) instanceof RollbackException;
- } else {
- assert PerCacheExecutorThread.OperationsResult.COMMIT_TX_OK == t1.execute(PerCacheExecutorThread.Operations.COMMIT_TX);
- assert t2.execute(PerCacheExecutorThread.Operations.COMMIT_TX) instanceof RollbackException;
- }
- assert lockManager.getNumberOfLocksHeld() == 0;
- assertEquals(lockManager.getDetectedLocalDeadlocks(), 1);
- }
-
-}
Copied: trunk/core/src/test/java/org/infinispan/tx/dld/LocalDeadlockDetectionTest.java (from rev 2385, branches/4.2.x/core/src/test/java/org/infinispan/tx/dld/LocalDeadlockDetectionTest.java)
===================================================================
--- trunk/core/src/test/java/org/infinispan/tx/dld/LocalDeadlockDetectionTest.java (rev 0)
+++ trunk/core/src/test/java/org/infinispan/tx/dld/LocalDeadlockDetectionTest.java 2010-09-15 19:09:38 UTC (rev 2386)
@@ -0,0 +1,190 @@
+package org.infinispan.tx.dld;
+
+import org.infinispan.config.Configuration;
+import org.infinispan.manager.EmbeddedCacheManager;
+import org.infinispan.test.PerCacheExecutorThread;
+import org.infinispan.test.SingleCacheManagerTest;
+import org.infinispan.test.TestingUtil;
+import org.infinispan.test.fwk.TestCacheManagerFactory;
+import org.infinispan.util.concurrent.locks.DeadlockDetectedException;
+import org.infinispan.util.concurrent.locks.DeadlockDetectingLockManager;
+import static org.testng.Assert.assertEquals;
+
+import org.testng.annotations.AfterMethod;
+import org.testng.annotations.BeforeMethod;
+import org.testng.annotations.Test;
+
+import javax.transaction.RollbackException;
+
+/**
+ * Tests deadlock detection functionality for local caches.
+ *
+ * @author Mircea.Markus at jboss.com
+ */
+ at Test(groups = "functional", testName = "tx.dld.LocalDeadlockDetectionTest")
+public class LocalDeadlockDetectionTest extends SingleCacheManagerTest {
+
+ private PerCacheExecutorThread t1;
+ private PerCacheExecutorThread t2;
+ private DeadlockDetectingLockManager lockManager;
+ private Object response1;
+ private Object response2;
+
+ protected EmbeddedCacheManager createCacheManager() throws Exception {
+ cacheManager = TestCacheManagerFactory.createLocalCacheManager();
+ Configuration configuration = getDefaultStandaloneConfig(true);
+ configuration.setEnableDeadlockDetection(true);
+ configuration.setUseLockStriping(false);
+ configuration.setExposeJmxStatistics(true);
+ cacheManager.defineConfiguration("test", configuration);
+ cache = cacheManager.getCache("test");
+ lockManager = (DeadlockDetectingLockManager) TestingUtil.extractLockManager(cache);
+ return cacheManager;
+ }
+
+ @BeforeMethod
+ public void startExecutors() {
+ t1 = new PerCacheExecutorThread(cache, 0);
+ t2 = new PerCacheExecutorThread(cache, 1);
+ lockManager.resetStatistics();
+ }
+
+
+ @AfterMethod
+ public void stopExecutors() {
+ t1.stopThread();
+ t2.stopThread();
+ }
+
+ public void testDldPutAndPut() {
+ testLocalVsLocalTxDeadlock(PerCacheExecutorThread.Operations.PUT_KEY_VALUE,
+ PerCacheExecutorThread.Operations.PUT_KEY_VALUE);
+ if (response1 instanceof Exception) {
+ assertEquals("value_1_t2", cache.get("k1"));
+ assertEquals("value_2_t2", cache.get("k2"));
+ } else {
+ assertEquals("value_1_t1", cache.get("k1"));
+ assertEquals("value_2_t1", cache.get("k2"));
+ }
+ }
+
+ public void testDldPutAndRemove() {
+ testLocalVsLocalTxDeadlock(PerCacheExecutorThread.Operations.PUT_KEY_VALUE,
+ PerCacheExecutorThread.Operations.REMOVE_KEY);
+ if (response1 instanceof Exception) {
+ assertEquals(cache.get("k1"), null);
+ assertEquals("value_2_t2", cache.get("k2"));
+ } else {
+ assertEquals("value_1_t1", cache.get("k1"));
+ assertEquals(null, cache.get("k2"));
+ }
+ }
+
+ public void testDldRemoveAndPut() {
+ testLocalVsLocalTxDeadlock(PerCacheExecutorThread.Operations.REMOVE_KEY,
+ PerCacheExecutorThread.Operations.PUT_KEY_VALUE);
+ if (response1 instanceof Exception) {
+ System.out.println("t1 failure");
+ assertEquals(cache.get("k1"), "value_1_t2");
+ assertEquals(cache.get("k2"), null);
+ } else {
+ System.out.println("t2 failure");
+ assertEquals(cache.get("k1"), null);
+ assertEquals(cache.get("k2"), "value_2_t1");
+ }
+ }
+
+ public void testDldRemoveAndRemove() {
+ testLocalVsLocalTxDeadlock(PerCacheExecutorThread.Operations.REMOVE_KEY,
+ PerCacheExecutorThread.Operations.REMOVE_KEY);
+ if (response1 instanceof Exception) {
+ System.out.println("t1 failure");
+ assertEquals(cache.get("k1"), null);
+ assertEquals(cache.get("k2"), null);
+ } else {
+ System.out.println("t2 failure");
+ assertEquals(cache.get("k1"), null);
+ assertEquals(cache.get("k2"), null);
+ }
+ }
+
+ public void testDldPutAndReplace() {
+
+ cache.put("k1", "initial_1");
+ cache.put("k2", "initial_2");
+
+ testLocalVsLocalTxDeadlock(PerCacheExecutorThread.Operations.PUT_KEY_VALUE,
+ PerCacheExecutorThread.Operations.REPLACE_KEY_VALUE);
+ if (response1 instanceof Exception) {
+ System.out.println("t1 failure");
+ assertEquals(cache.get("k1"), "value_1_t2");
+ assertEquals(cache.get("k2"), "value_2_t2");
+ } else {
+ System.out.println("t2 failure");
+ assertEquals(cache.get("k1"), "value_1_t1");
+ assertEquals(cache.get("k2"), "value_2_t1");
+ }
+ }
+
+ public void testDldReplaceAndPut() {
+
+ cache.put("k1", "initial_1");
+ cache.put("k2", "initial_2");
+
+ testLocalVsLocalTxDeadlock(PerCacheExecutorThread.Operations.REPLACE_KEY_VALUE,
+ PerCacheExecutorThread.Operations.PUT_KEY_VALUE);
+ if (response1 instanceof Exception) {
+ System.out.println("t1 failure");
+ assertEquals(cache.get("k1"), "value_1_t2");
+ assertEquals(cache.get("k2"), "value_2_t2");
+ } else {
+ System.out.println("t2 failure");
+ assertEquals(cache.get("k1"), "value_1_t1");
+ assertEquals(cache.get("k2"), "value_2_t1");
+ }
+ }
+
+
+ private void testLocalVsLocalTxDeadlock(PerCacheExecutorThread.Operations firstOperation, PerCacheExecutorThread.Operations secondOperation) {
+
+ assert PerCacheExecutorThread.OperationsResult.BEGGIN_TX_OK == t1.execute(PerCacheExecutorThread.Operations.BEGGIN_TX);
+ assert PerCacheExecutorThread.OperationsResult.BEGGIN_TX_OK == t2.execute(PerCacheExecutorThread.Operations.BEGGIN_TX);
+ System.out.println("After begin");
+
+ t1.setKeyValue("k1", "value_1_t1");
+ t2.setKeyValue("k2", "value_2_t2");
+
+ assertEquals(t1.execute(firstOperation), firstOperation.getCorrespondingOkResult());
+ assertEquals(t2.execute(firstOperation), firstOperation.getCorrespondingOkResult());
+
+ assert lockManager.isLocked("k1");
+ assert lockManager.isLocked("k2");
+
+
+ t1.setKeyValue("k2", "value_2_t1");
+ t2.setKeyValue("k1", "value_1_t2");
+ t1.executeNoResponse(secondOperation);
+ t2.executeNoResponse(secondOperation);
+
+ response1 = t1.waitForResponse();
+ response2 = t2.waitForResponse();
+
+ assert xor(response1 instanceof DeadlockDetectedException, response2 instanceof DeadlockDetectedException) : "expected one and only one exception: " + response1 + ", " + response2;
+ assert xor(response1 == secondOperation.getCorrespondingOkResult(), response2 == secondOperation.getCorrespondingOkResult()) : "expected one and only one exception: " + response1 + ", " + response2;
+
+ assert lockManager.isLocked("k1");
+ assert lockManager.isLocked("k2");
+ assert lockManager.getOwner("k1") == lockManager.getOwner("k2");
+
+ if (response1 instanceof Exception) {
+ assert PerCacheExecutorThread.OperationsResult.COMMIT_TX_OK == t2.execute(PerCacheExecutorThread.Operations.COMMIT_TX);
+ assert t1.execute(PerCacheExecutorThread.Operations.COMMIT_TX) instanceof RollbackException;
+ } else {
+ assert PerCacheExecutorThread.OperationsResult.COMMIT_TX_OK == t1.execute(PerCacheExecutorThread.Operations.COMMIT_TX);
+ assert t2.execute(PerCacheExecutorThread.Operations.COMMIT_TX) instanceof RollbackException;
+ }
+ assert lockManager.getNumberOfLocksHeld() == 0;
+ assertEquals(lockManager.getDetectedLocalDeadlocks(), 1);
+ }
+
+}
Copied: trunk/core/src/test/java/org/infinispan/tx/exception (from rev 2385, branches/4.2.x/core/src/test/java/org/infinispan/tx/exception)
Deleted: trunk/core/src/test/java/org/infinispan/tx/exception/CustomInterceptorException.java
===================================================================
--- branches/4.2.x/core/src/test/java/org/infinispan/tx/exception/CustomInterceptorException.java 2010-09-15 16:19:59 UTC (rev 2385)
+++ trunk/core/src/test/java/org/infinispan/tx/exception/CustomInterceptorException.java 2010-09-15 19:09:38 UTC (rev 2386)
@@ -1,45 +0,0 @@
-package org.infinispan.tx.exception;
-
-import org.infinispan.commands.write.PutKeyValueCommand;
-import org.infinispan.config.Configuration;
-import org.infinispan.config.CustomInterceptorConfigTest;
-import org.infinispan.context.InvocationContext;
-import org.infinispan.manager.EmbeddedCacheManager;
-import org.infinispan.test.SingleCacheManagerTest;
-import org.infinispan.test.fwk.TestCacheManagerFactory;
-import org.testng.annotations.Test;
-
-import javax.transaction.Status;
-import javax.transaction.TransactionManager;
-
-/**
- * @author Mircea.Markus at jboss.com
- * @since 4.2
- */
- at Test(groups = "functional", testName = "CustomInterceptorException")
-public class CustomInterceptorException extends SingleCacheManagerTest {
-
- @Override
- protected EmbeddedCacheManager createCacheManager() throws Exception {
- EmbeddedCacheManager eCm =
- TestCacheManagerFactory.createCacheManager(getDefaultClusteredConfig(Configuration.CacheMode.LOCAL), true);
- eCm.getCache().getAdvancedCache().addInterceptor(new CustomInterceptorConfigTest.DummyInterceptor() {
- @Override
- public Object visitPutKeyValueCommand(InvocationContext ctx, PutKeyValueCommand command) throws Throwable {
- throw new IllegalStateException("Induce failure!");
- }
- }, 1);
- return eCm;
- }
-
- public void testFailure() throws Exception {
- TransactionManager transactionManager = cache.getAdvancedCache().getTransactionManager();
- transactionManager.begin();
- try {
- cache.put("k", "v");
- assert false;
- } catch (Exception e) {
- assert transactionManager.getTransaction().getStatus() == Status.STATUS_MARKED_ROLLBACK;
- }
- }
-}
Copied: trunk/core/src/test/java/org/infinispan/tx/exception/CustomInterceptorException.java (from rev 2385, branches/4.2.x/core/src/test/java/org/infinispan/tx/exception/CustomInterceptorException.java)
===================================================================
--- trunk/core/src/test/java/org/infinispan/tx/exception/CustomInterceptorException.java (rev 0)
+++ trunk/core/src/test/java/org/infinispan/tx/exception/CustomInterceptorException.java 2010-09-15 19:09:38 UTC (rev 2386)
@@ -0,0 +1,45 @@
+package org.infinispan.tx.exception;
+
+import org.infinispan.commands.write.PutKeyValueCommand;
+import org.infinispan.config.Configuration;
+import org.infinispan.config.CustomInterceptorConfigTest;
+import org.infinispan.context.InvocationContext;
+import org.infinispan.manager.EmbeddedCacheManager;
+import org.infinispan.test.SingleCacheManagerTest;
+import org.infinispan.test.fwk.TestCacheManagerFactory;
+import org.testng.annotations.Test;
+
+import javax.transaction.Status;
+import javax.transaction.TransactionManager;
+
+/**
+ * @author Mircea.Markus at jboss.com
+ * @since 4.2
+ */
+ at Test(groups = "functional", testName = "CustomInterceptorException")
+public class CustomInterceptorException extends SingleCacheManagerTest {
+
+ @Override
+ protected EmbeddedCacheManager createCacheManager() throws Exception {
+ EmbeddedCacheManager eCm =
+ TestCacheManagerFactory.createCacheManager(getDefaultClusteredConfig(Configuration.CacheMode.LOCAL), true);
+ eCm.getCache().getAdvancedCache().addInterceptor(new CustomInterceptorConfigTest.DummyInterceptor() {
+ @Override
+ public Object visitPutKeyValueCommand(InvocationContext ctx, PutKeyValueCommand command) throws Throwable {
+ throw new IllegalStateException("Induce failure!");
+ }
+ }, 1);
+ return eCm;
+ }
+
+ public void testFailure() throws Exception {
+ TransactionManager transactionManager = cache.getAdvancedCache().getTransactionManager();
+ transactionManager.begin();
+ try {
+ cache.put("k", "v");
+ assert false;
+ } catch (Exception e) {
+ assert transactionManager.getTransaction().getStatus() == Status.STATUS_MARKED_ROLLBACK;
+ }
+ }
+}
Deleted: trunk/core/src/test/java/org/infinispan/tx/exception/ExplicitLockingAndTimeoutTest.java
===================================================================
--- branches/4.2.x/core/src/test/java/org/infinispan/tx/exception/ExplicitLockingAndTimeoutTest.java 2010-09-15 16:19:59 UTC (rev 2385)
+++ trunk/core/src/test/java/org/infinispan/tx/exception/ExplicitLockingAndTimeoutTest.java 2010-09-15 19:09:38 UTC (rev 2386)
@@ -1,139 +0,0 @@
-package org.infinispan.tx.exception;
-
-import org.infinispan.commands.VisitableCommand;
-import org.infinispan.commands.control.LockControlCommand;
-import org.infinispan.config.Configuration;
-import org.infinispan.context.InvocationContext;
-import org.infinispan.context.impl.TxInvocationContext;
-import org.infinispan.interceptors.base.CommandInterceptor;
-import org.infinispan.test.MultipleCacheManagersTest;
-import org.infinispan.test.TestingUtil;
-import org.infinispan.transaction.xa.TransactionTable;
-import org.infinispan.util.concurrent.TimeoutException;
-import org.infinispan.util.concurrent.locks.LockManager;
-import org.testng.annotations.Test;
-
-import javax.transaction.HeuristicMixedException;
-import javax.transaction.HeuristicRollbackException;
-import javax.transaction.InvalidTransactionException;
-import javax.transaction.NotSupportedException;
-import javax.transaction.RollbackException;
-import javax.transaction.Status;
-import javax.transaction.SystemException;
-import javax.transaction.Transaction;
-import javax.transaction.TransactionManager;
-
-import static org.testng.Assert.assertEquals;
-
-/**
- * @author Mircea.Markus at jboss.com
- * @since 4.2
- */
- at Test(groups = "functional", testName = "tx.timeout.EagerLockingAndTimeoutTest")
-public class ExplicitLockingAndTimeoutTest extends MultipleCacheManagersTest {
-
- private LockManager lm1;
- private LockManager lm0;
- private TransactionTable txTable0;
- private TransactionTable txTable1;
- private TransactionManager tm;
- private TxStatusInterceptor txStatus = new TxStatusInterceptor();
-
- @Override
- protected void createCacheManagers() throws Throwable {
- Configuration defaultConfig = getDefaultConfig();
- defaultConfig.setLockAcquisitionTimeout(500);
- defaultConfig.setUseLockStriping(false);
- addClusterEnabledCacheManager(defaultConfig);
- addClusterEnabledCacheManager(defaultConfig);
- lm0 = TestingUtil.extractLockManager(cache(0));
- lm1 = TestingUtil.extractLockManager(cache(1));
- txTable0 = TestingUtil.getTransactionTable(cache(0));
- txTable1 = TestingUtil.getTransactionTable(cache(1));
- tm = cache(0).getAdvancedCache().getTransactionManager();
- cache(1).getAdvancedCache().addInterceptor(txStatus, 0);
- TestingUtil.blockUntilViewReceived(cache(0), 2, 10000);
- }
-
- protected Configuration getDefaultConfig() {
- return getDefaultClusteredConfig(Configuration.CacheMode.REPL_SYNC, true);
- }
-
- public void testExplicitLockingRemoteTimeout() throws NotSupportedException, SystemException, HeuristicMixedException, HeuristicRollbackException, InvalidTransactionException, RollbackException {
- txStatus.reset();
- tm.begin();
- cache(1).put("k1", "v1");
- Transaction k1LockOwner = tm.suspend();
- assert lm1.isLocked("k1");
-
- assertEquals(1, txTable1.getLocalTxCount());
- tm.begin();
- cache(0).getAdvancedCache().lock("k2");
- assert lm0.isLocked("k2");
- assert lm1.isLocked("k2");
-
- try {
- cache(0).getAdvancedCache().lock("k1");
- assert false;
- } catch (TimeoutException e) {
- //expected
- }
-
- assert txStatus.teReceived;
- assert txStatus.isTxInTableAfterTeOnEagerLocking;
- //expect 1 as k1 is locked by the other tx
- assertEquals(lm1.isLocked("k2"), false, "Even though rollback was not received yet lock on k2, which was acquired, is no longer held");
- assert tm.getStatus() == Status.STATUS_MARKED_ROLLBACK;
-
- assertEquals(1, txTable0.getLocalTxCount());
- assertEquals(1, txTable1.getLocalTxCount());
- assertEquals(1, txTable1.getRemoteTxCount());
-
- tm.rollback();
- assertEquals(0, txTable0.getLocalTxCount());
- assertEquals(1, txTable1.getLocalTxCount());
- assertEquals(0, txTable1.getRemoteTxCount());
-
-
- tm.resume(k1LockOwner);
- tm.commit();
- assertEquals("v1", cache(0).get("k1"));
- assertEquals("v1", cache(1).get("k1"));
- assertEquals(0, txTable1.getLocalTxCount());
- assertEquals(0, txTable0.getLocalTxCount());
- assertEquals(0, lm0.getNumberOfLocksHeld());
- assertEquals(0, lm1.getNumberOfLocksHeld());
- }
-
- private class TxStatusInterceptor extends CommandInterceptor {
-
- private boolean teReceived;
-
- private boolean isTxInTableAfterTeOnEagerLocking;
-
- private int numLocksAfterTeOnEagerLocking;
-
- @Override
- public Object visitLockControlCommand(TxInvocationContext ctx, LockControlCommand command) throws Throwable {
- try {
- return invokeNextInterceptor(ctx, command);
- } catch (TimeoutException te) {
- teReceived = true;
- isTxInTableAfterTeOnEagerLocking = txTable1.containRemoteTx(ctx.getGlobalTransaction());
- numLocksAfterTeOnEagerLocking = lm1.getNumberOfLocksHeld();
- throw te;
- }
- }
-
- @Override
- protected Object handleDefault(InvocationContext ctx, VisitableCommand command) throws Throwable {
- return super.handleDefault(ctx, command);
- }
-
- public void reset() {
- this.teReceived = false;
- this.isTxInTableAfterTeOnEagerLocking = false;
- this.numLocksAfterTeOnEagerLocking = -1;
- }
- }
-}
\ No newline at end of file
Copied: trunk/core/src/test/java/org/infinispan/tx/exception/ExplicitLockingAndTimeoutTest.java (from rev 2385, branches/4.2.x/core/src/test/java/org/infinispan/tx/exception/ExplicitLockingAndTimeoutTest.java)
===================================================================
--- trunk/core/src/test/java/org/infinispan/tx/exception/ExplicitLockingAndTimeoutTest.java (rev 0)
+++ trunk/core/src/test/java/org/infinispan/tx/exception/ExplicitLockingAndTimeoutTest.java 2010-09-15 19:09:38 UTC (rev 2386)
@@ -0,0 +1,139 @@
+package org.infinispan.tx.exception;
+
+import org.infinispan.commands.VisitableCommand;
+import org.infinispan.commands.control.LockControlCommand;
+import org.infinispan.config.Configuration;
+import org.infinispan.context.InvocationContext;
+import org.infinispan.context.impl.TxInvocationContext;
+import org.infinispan.interceptors.base.CommandInterceptor;
+import org.infinispan.test.MultipleCacheManagersTest;
+import org.infinispan.test.TestingUtil;
+import org.infinispan.transaction.xa.TransactionTable;
+import org.infinispan.util.concurrent.TimeoutException;
+import org.infinispan.util.concurrent.locks.LockManager;
+import org.testng.annotations.Test;
+
+import javax.transaction.HeuristicMixedException;
+import javax.transaction.HeuristicRollbackException;
+import javax.transaction.InvalidTransactionException;
+import javax.transaction.NotSupportedException;
+import javax.transaction.RollbackException;
+import javax.transaction.Status;
+import javax.transaction.SystemException;
+import javax.transaction.Transaction;
+import javax.transaction.TransactionManager;
+
+import static org.testng.Assert.assertEquals;
+
+/**
+ * @author Mircea.Markus at jboss.com
+ * @since 4.2
+ */
+ at Test(groups = "functional", testName = "tx.timeout.EagerLockingAndTimeoutTest")
+public class ExplicitLockingAndTimeoutTest extends MultipleCacheManagersTest {
+
+ private LockManager lm1;
+ private LockManager lm0;
+ private TransactionTable txTable0;
+ private TransactionTable txTable1;
+ private TransactionManager tm;
+ private TxStatusInterceptor txStatus = new TxStatusInterceptor();
+
+ @Override
+ protected void createCacheManagers() throws Throwable {
+ Configuration defaultConfig = getDefaultConfig();
+ defaultConfig.setLockAcquisitionTimeout(500);
+ defaultConfig.setUseLockStriping(false);
+ addClusterEnabledCacheManager(defaultConfig);
+ addClusterEnabledCacheManager(defaultConfig);
+ lm0 = TestingUtil.extractLockManager(cache(0));
+ lm1 = TestingUtil.extractLockManager(cache(1));
+ txTable0 = TestingUtil.getTransactionTable(cache(0));
+ txTable1 = TestingUtil.getTransactionTable(cache(1));
+ tm = cache(0).getAdvancedCache().getTransactionManager();
+ cache(1).getAdvancedCache().addInterceptor(txStatus, 0);
+ TestingUtil.blockUntilViewReceived(cache(0), 2, 10000);
+ }
+
+ protected Configuration getDefaultConfig() {
+ return getDefaultClusteredConfig(Configuration.CacheMode.REPL_SYNC, true);
+ }
+
+ public void testExplicitLockingRemoteTimeout() throws NotSupportedException, SystemException, HeuristicMixedException, HeuristicRollbackException, InvalidTransactionException, RollbackException {
+ txStatus.reset();
+ tm.begin();
+ cache(1).put("k1", "v1");
+ Transaction k1LockOwner = tm.suspend();
+ assert lm1.isLocked("k1");
+
+ assertEquals(1, txTable1.getLocalTxCount());
+ tm.begin();
+ cache(0).getAdvancedCache().lock("k2");
+ assert lm0.isLocked("k2");
+ assert lm1.isLocked("k2");
+
+ try {
+ cache(0).getAdvancedCache().lock("k1");
+ assert false;
+ } catch (TimeoutException e) {
+ //expected
+ }
+
+ assert txStatus.teReceived;
+ assert txStatus.isTxInTableAfterTeOnEagerLocking;
+ //expect 1 as k1 is locked by the other tx
+ assertEquals(lm1.isLocked("k2"), false, "Even though rollback was not received yet lock on k2, which was acquired, is no longer held");
+ assert tm.getStatus() == Status.STATUS_MARKED_ROLLBACK;
+
+ assertEquals(1, txTable0.getLocalTxCount());
+ assertEquals(1, txTable1.getLocalTxCount());
+ assertEquals(1, txTable1.getRemoteTxCount());
+
+ tm.rollback();
+ assertEquals(0, txTable0.getLocalTxCount());
+ assertEquals(1, txTable1.getLocalTxCount());
+ assertEquals(0, txTable1.getRemoteTxCount());
+
+
+ tm.resume(k1LockOwner);
+ tm.commit();
+ assertEquals("v1", cache(0).get("k1"));
+ assertEquals("v1", cache(1).get("k1"));
+ assertEquals(0, txTable1.getLocalTxCount());
+ assertEquals(0, txTable0.getLocalTxCount());
+ assertEquals(0, lm0.getNumberOfLocksHeld());
+ assertEquals(0, lm1.getNumberOfLocksHeld());
+ }
+
+ private class TxStatusInterceptor extends CommandInterceptor {
+
+ private boolean teReceived;
+
+ private boolean isTxInTableAfterTeOnEagerLocking;
+
+ private int numLocksAfterTeOnEagerLocking;
+
+ @Override
+ public Object visitLockControlCommand(TxInvocationContext ctx, LockControlCommand command) throws Throwable {
+ try {
+ return invokeNextInterceptor(ctx, command);
+ } catch (TimeoutException te) {
+ teReceived = true;
+ isTxInTableAfterTeOnEagerLocking = txTable1.containRemoteTx(ctx.getGlobalTransaction());
+ numLocksAfterTeOnEagerLocking = lm1.getNumberOfLocksHeld();
+ throw te;
+ }
+ }
+
+ @Override
+ protected Object handleDefault(InvocationContext ctx, VisitableCommand command) throws Throwable {
+ return super.handleDefault(ctx, command);
+ }
+
+ public void reset() {
+ this.teReceived = false;
+ this.isTxInTableAfterTeOnEagerLocking = false;
+ this.numLocksAfterTeOnEagerLocking = -1;
+ }
+ }
+}
\ No newline at end of file
Deleted: trunk/core/src/test/java/org/infinispan/tx/exception/ReplicationExceptionTest.java
===================================================================
--- branches/4.2.x/core/src/test/java/org/infinispan/tx/exception/ReplicationExceptionTest.java 2010-09-15 16:19:59 UTC (rev 2385)
+++ trunk/core/src/test/java/org/infinispan/tx/exception/ReplicationExceptionTest.java 2010-09-15 19:09:38 UTC (rev 2386)
@@ -1,43 +0,0 @@
-package org.infinispan.tx.exception;
-
-import org.infinispan.config.Configuration;
-import org.infinispan.test.MultipleCacheManagersTest;
-import org.infinispan.test.TestingUtil;
-import org.infinispan.test.fwk.TestCacheManagerFactory;
-import org.infinispan.tx.dld.BaseDldTest;
-import org.infinispan.tx.dld.ControlledRpcManager;
-import org.testng.annotations.Test;
-
-import javax.transaction.RollbackException;
-import javax.transaction.TransactionManager;
-
-/**
- * @author Mircea.Markus at jboss.com
- * @since 4.2
- */
- at Test(testName = "tx.exception.ReplicationExceptionTest")
-public class ReplicationExceptionTest extends MultipleCacheManagersTest {
- private ControlledRpcManager crm0;
-
- @Override
- protected void createCacheManagers() throws Throwable {
- Configuration config = getDefaultClusteredConfig(Configuration.CacheMode.REPL_SYNC);
- registerCacheManager(TestCacheManagerFactory.createCacheManager(config, true));
- registerCacheManager(TestCacheManagerFactory.createCacheManager(config, true));
- TestingUtil.blockUntilViewsReceived(10000, cache(0), cache(1));
- crm0 = BaseDldTest.replaceRpcManager(cache(0));
- }
-
-
- public void testReplicationFailure() throws Exception {
- TransactionManager tm = cache(0).getAdvancedCache().getTransactionManager();
- tm.begin();
- cache(0).put("k0","v");
- try {
- tm.commit();
- assert false;
- } catch (RollbackException e) {
- //expected
- }
- }
-}
Copied: trunk/core/src/test/java/org/infinispan/tx/exception/ReplicationExceptionTest.java (from rev 2385, branches/4.2.x/core/src/test/java/org/infinispan/tx/exception/ReplicationExceptionTest.java)
===================================================================
--- trunk/core/src/test/java/org/infinispan/tx/exception/ReplicationExceptionTest.java (rev 0)
+++ trunk/core/src/test/java/org/infinispan/tx/exception/ReplicationExceptionTest.java 2010-09-15 19:09:38 UTC (rev 2386)
@@ -0,0 +1,43 @@
+package org.infinispan.tx.exception;
+
+import org.infinispan.config.Configuration;
+import org.infinispan.test.MultipleCacheManagersTest;
+import org.infinispan.test.TestingUtil;
+import org.infinispan.test.fwk.TestCacheManagerFactory;
+import org.infinispan.tx.dld.BaseDldTest;
+import org.infinispan.tx.dld.ControlledRpcManager;
+import org.testng.annotations.Test;
+
+import javax.transaction.RollbackException;
+import javax.transaction.TransactionManager;
+
+/**
+ * @author Mircea.Markus at jboss.com
+ * @since 4.2
+ */
+ at Test(testName = "tx.exception.ReplicationExceptionTest")
+public class ReplicationExceptionTest extends MultipleCacheManagersTest {
+ private ControlledRpcManager crm0;
+
+ @Override
+ protected void createCacheManagers() throws Throwable {
+ Configuration config = getDefaultClusteredConfig(Configuration.CacheMode.REPL_SYNC);
+ registerCacheManager(TestCacheManagerFactory.createCacheManager(config, true));
+ registerCacheManager(TestCacheManagerFactory.createCacheManager(config, true));
+ TestingUtil.blockUntilViewsReceived(10000, cache(0), cache(1));
+ crm0 = BaseDldTest.replaceRpcManager(cache(0));
+ }
+
+
+ public void testReplicationFailure() throws Exception {
+ TransactionManager tm = cache(0).getAdvancedCache().getTransactionManager();
+ tm.begin();
+ cache(0).put("k0","v");
+ try {
+ tm.commit();
+ assert false;
+ } catch (RollbackException e) {
+ //expected
+ }
+ }
+}
Deleted: trunk/core/src/test/java/org/infinispan/tx/exception/TxAndInvalidationTimeoutTest.java
===================================================================
--- branches/4.2.x/core/src/test/java/org/infinispan/tx/exception/TxAndInvalidationTimeoutTest.java 2010-09-15 16:19:59 UTC (rev 2385)
+++ trunk/core/src/test/java/org/infinispan/tx/exception/TxAndInvalidationTimeoutTest.java 2010-09-15 19:09:38 UTC (rev 2386)
@@ -1,174 +0,0 @@
-package org.infinispan.tx.exception;
-
-import org.infinispan.commands.VisitableCommand;
-import org.infinispan.commands.write.InvalidateCommand;
-import org.infinispan.config.Configuration;
-import org.infinispan.context.InvocationContext;
-import org.infinispan.interceptors.base.CommandInterceptor;
-import org.infinispan.test.MultipleCacheManagersTest;
-import org.infinispan.test.TestingUtil;
-import org.infinispan.transaction.xa.TransactionTable;
-import org.infinispan.util.concurrent.TimeoutException;
-import org.infinispan.util.concurrent.locks.LockManager;
-import org.infinispan.util.logging.Log;
-import org.infinispan.util.logging.LogFactory;
-import org.testng.annotations.Test;
-
-import javax.transaction.HeuristicMixedException;
-import javax.transaction.HeuristicRollbackException;
-import javax.transaction.InvalidTransactionException;
-import javax.transaction.NotSupportedException;
-import javax.transaction.RollbackException;
-import javax.transaction.SystemException;
-import javax.transaction.Transaction;
-import javax.transaction.TransactionManager;
-import java.util.HashMap;
-import java.util.Map;
-
-import static org.testng.Assert.assertEquals;
-
-/**
- *
- * @author Mircea.Markus at jboss.com
- * @since 4.2
- */
- at Test (testName = "tx.timeout.TxAndInvalidationTimeoutTest", groups = "functional")
-public class TxAndInvalidationTimeoutTest extends MultipleCacheManagersTest {
-
- private static Log log = LogFactory.getLog(TxAndInvalidationTimeoutTest.class);
-
- private LockManager lm1;
- private LockManager lm0;
- private TransactionTable txTable0;
- private TransactionTable txTable1;
- private TransactionManager tm;
- private TxStatusInterceptor txStatus = new TxStatusInterceptor();
-
- @Override
- protected void createCacheManagers() throws Throwable {
- Configuration defaultConfig = getDefaultConfig();
- defaultConfig.setLockAcquisitionTimeout(500);
- defaultConfig.setUseLockStriping(false);
- addClusterEnabledCacheManager(defaultConfig);
- addClusterEnabledCacheManager(defaultConfig);
- lm0 = TestingUtil.extractLockManager(cache(0));
- lm1 = TestingUtil.extractLockManager(cache(1));
- txTable0 = TestingUtil.getTransactionTable(cache(0));
- txTable1 = TestingUtil.getTransactionTable(cache(1));
- tm = cache(0).getAdvancedCache().getTransactionManager();
- cache(1).getAdvancedCache().addInterceptor(txStatus, 0);
- TestingUtil.blockUntilViewReceived(cache(0), 2, 10000);
- }
-
- protected Configuration getDefaultConfig() {
- return getDefaultClusteredConfig(Configuration.CacheMode.INVALIDATION_SYNC, true);
- }
-
- public void testPutTimeoutsInTx() throws Exception {
- runAssertion(new CacheOperation() {
- @Override
- public void execute() {
- cache(0).put("k1", "v2222");
- }
- });
- }
-
- public void testRemoveTimeoutsInTx() throws Exception {
- runAssertion(new CacheOperation() {
- @Override
- public void execute() {
- cache(0).remove("k1");
- }
- });
- }
-
- public void testPutAllTimeoutsInTx() throws Exception {
- runAssertion(new CacheOperation() {
- @Override
- public void execute() {
- Map toAdd = new HashMap();
- toAdd.put("k1", "v22222");
- cache(0).putAll(toAdd);
- }
- });
- }
-
-
- private void runAssertion(CacheOperation operation) throws NotSupportedException, SystemException, HeuristicMixedException, HeuristicRollbackException, InvalidTransactionException, RollbackException {
- txStatus.reset();
- tm.begin();
- cache(1).put("k1", "v1");
- Transaction k1LockOwner = tm.suspend();
- assert lm1.isLocked("k1");
-
- assertEquals(1, txTable1.getLocalTxCount());
- tm.begin();
- cache(0).put("k2", "v2");
- assert lm0.isLocked("k2");
- assert !lm1.isLocked("k2");
-
- operation.execute();
-
- assertEquals(1, txTable1.getLocalTxCount());
- assertEquals(1, txTable0.getLocalTxCount());
-
-
- log.trace("Before commit");
-
- try {
- tm.commit();
- assert false;
- } catch (RollbackException re) {
- //expected
- }
- assert txStatus.teReceived;
- //expect 1 as k1 is locked by the other tx
- assertEquals(txStatus.numLocksAfterTeOnInvalidate, 1, "This would make sure that locks are being released quickly, not waiting for a remote rollback to happen");
-
- assertEquals(0, txTable0.getLocalTxCount());
- assertEquals(1, txTable1.getLocalTxCount());
-
- log.trace("Right before second commit");
- tm.resume(k1LockOwner);
- tm.commit();
- assertEquals(null, cache(0).get("k1"));
- assertEquals("v1", cache(1).get("k1"));
- assertEquals(0, txTable1.getLocalTxCount());
- assertEquals(0, txTable1.getLocalTxCount());
- assertEquals(0, lm0.getNumberOfLocksHeld());
- assertEquals(0, lm1.getNumberOfLocksHeld());
- }
-
- private class TxStatusInterceptor extends CommandInterceptor {
-
- private boolean teReceived;
-
- private int numLocksAfterTeOnInvalidate;
-
- @Override
- public Object visitInvalidateCommand(InvocationContext ctx, InvalidateCommand invalidateCommand) throws Throwable {
- try {
- return invokeNextInterceptor(ctx, invalidateCommand);
- } catch (TimeoutException te) {
- numLocksAfterTeOnInvalidate = lm1.getNumberOfLocksHeld();
- teReceived = true;
- throw te;
- }
- }
-
- @Override
- protected Object handleDefault(InvocationContext ctx, VisitableCommand command) throws Throwable {
- return super.handleDefault(ctx, command);
- }
-
- public void reset() {
- this.teReceived = false;
- this.numLocksAfterTeOnInvalidate = -1;
- }
- }
-
- public interface CacheOperation {
-
- public abstract void execute();
- }
-}
Copied: trunk/core/src/test/java/org/infinispan/tx/exception/TxAndInvalidationTimeoutTest.java (from rev 2385, branches/4.2.x/core/src/test/java/org/infinispan/tx/exception/TxAndInvalidationTimeoutTest.java)
===================================================================
--- trunk/core/src/test/java/org/infinispan/tx/exception/TxAndInvalidationTimeoutTest.java (rev 0)
+++ trunk/core/src/test/java/org/infinispan/tx/exception/TxAndInvalidationTimeoutTest.java 2010-09-15 19:09:38 UTC (rev 2386)
@@ -0,0 +1,174 @@
+package org.infinispan.tx.exception;
+
+import org.infinispan.commands.VisitableCommand;
+import org.infinispan.commands.write.InvalidateCommand;
+import org.infinispan.config.Configuration;
+import org.infinispan.context.InvocationContext;
+import org.infinispan.interceptors.base.CommandInterceptor;
+import org.infinispan.test.MultipleCacheManagersTest;
+import org.infinispan.test.TestingUtil;
+import org.infinispan.transaction.xa.TransactionTable;
+import org.infinispan.util.concurrent.TimeoutException;
+import org.infinispan.util.concurrent.locks.LockManager;
+import org.infinispan.util.logging.Log;
+import org.infinispan.util.logging.LogFactory;
+import org.testng.annotations.Test;
+
+import javax.transaction.HeuristicMixedException;
+import javax.transaction.HeuristicRollbackException;
+import javax.transaction.InvalidTransactionException;
+import javax.transaction.NotSupportedException;
+import javax.transaction.RollbackException;
+import javax.transaction.SystemException;
+import javax.transaction.Transaction;
+import javax.transaction.TransactionManager;
+import java.util.HashMap;
+import java.util.Map;
+
+import static org.testng.Assert.assertEquals;
+
+/**
+ *
+ * @author Mircea.Markus at jboss.com
+ * @since 4.2
+ */
+ at Test (testName = "tx.timeout.TxAndInvalidationTimeoutTest", groups = "functional")
+public class TxAndInvalidationTimeoutTest extends MultipleCacheManagersTest {
+
+ private static Log log = LogFactory.getLog(TxAndInvalidationTimeoutTest.class);
+
+ private LockManager lm1;
+ private LockManager lm0;
+ private TransactionTable txTable0;
+ private TransactionTable txTable1;
+ private TransactionManager tm;
+ private TxStatusInterceptor txStatus = new TxStatusInterceptor();
+
+ @Override
+ protected void createCacheManagers() throws Throwable {
+ Configuration defaultConfig = getDefaultConfig();
+ defaultConfig.setLockAcquisitionTimeout(500);
+ defaultConfig.setUseLockStriping(false);
+ addClusterEnabledCacheManager(defaultConfig);
+ addClusterEnabledCacheManager(defaultConfig);
+ lm0 = TestingUtil.extractLockManager(cache(0));
+ lm1 = TestingUtil.extractLockManager(cache(1));
+ txTable0 = TestingUtil.getTransactionTable(cache(0));
+ txTable1 = TestingUtil.getTransactionTable(cache(1));
+ tm = cache(0).getAdvancedCache().getTransactionManager();
+ cache(1).getAdvancedCache().addInterceptor(txStatus, 0);
+ TestingUtil.blockUntilViewReceived(cache(0), 2, 10000);
+ }
+
+ protected Configuration getDefaultConfig() {
+ return getDefaultClusteredConfig(Configuration.CacheMode.INVALIDATION_SYNC, true);
+ }
+
+ public void testPutTimeoutsInTx() throws Exception {
+ runAssertion(new CacheOperation() {
+ @Override
+ public void execute() {
+ cache(0).put("k1", "v2222");
+ }
+ });
+ }
+
+ public void testRemoveTimeoutsInTx() throws Exception {
+ runAssertion(new CacheOperation() {
+ @Override
+ public void execute() {
+ cache(0).remove("k1");
+ }
+ });
+ }
+
+ public void testPutAllTimeoutsInTx() throws Exception {
+ runAssertion(new CacheOperation() {
+ @Override
+ public void execute() {
+ Map toAdd = new HashMap();
+ toAdd.put("k1", "v22222");
+ cache(0).putAll(toAdd);
+ }
+ });
+ }
+
+
+ private void runAssertion(CacheOperation operation) throws NotSupportedException, SystemException, HeuristicMixedException, HeuristicRollbackException, InvalidTransactionException, RollbackException {
+ txStatus.reset();
+ tm.begin();
+ cache(1).put("k1", "v1");
+ Transaction k1LockOwner = tm.suspend();
+ assert lm1.isLocked("k1");
+
+ assertEquals(1, txTable1.getLocalTxCount());
+ tm.begin();
+ cache(0).put("k2", "v2");
+ assert lm0.isLocked("k2");
+ assert !lm1.isLocked("k2");
+
+ operation.execute();
+
+ assertEquals(1, txTable1.getLocalTxCount());
+ assertEquals(1, txTable0.getLocalTxCount());
+
+
+ log.trace("Before commit");
+
+ try {
+ tm.commit();
+ assert false;
+ } catch (RollbackException re) {
+ //expected
+ }
+ assert txStatus.teReceived;
+ //expect 1 as k1 is locked by the other tx
+ assertEquals(txStatus.numLocksAfterTeOnInvalidate, 1, "This would make sure that locks are being released quickly, not waiting for a remote rollback to happen");
+
+ assertEquals(0, txTable0.getLocalTxCount());
+ assertEquals(1, txTable1.getLocalTxCount());
+
+ log.trace("Right before second commit");
+ tm.resume(k1LockOwner);
+ tm.commit();
+ assertEquals(null, cache(0).get("k1"));
+ assertEquals("v1", cache(1).get("k1"));
+ assertEquals(0, txTable1.getLocalTxCount());
+ assertEquals(0, txTable1.getLocalTxCount());
+ assertEquals(0, lm0.getNumberOfLocksHeld());
+ assertEquals(0, lm1.getNumberOfLocksHeld());
+ }
+
+ private class TxStatusInterceptor extends CommandInterceptor {
+
+ private boolean teReceived;
+
+ private int numLocksAfterTeOnInvalidate;
+
+ @Override
+ public Object visitInvalidateCommand(InvocationContext ctx, InvalidateCommand invalidateCommand) throws Throwable {
+ try {
+ return invokeNextInterceptor(ctx, invalidateCommand);
+ } catch (TimeoutException te) {
+ numLocksAfterTeOnInvalidate = lm1.getNumberOfLocksHeld();
+ teReceived = true;
+ throw te;
+ }
+ }
+
+ @Override
+ protected Object handleDefault(InvocationContext ctx, VisitableCommand command) throws Throwable {
+ return super.handleDefault(ctx, command);
+ }
+
+ public void reset() {
+ this.teReceived = false;
+ this.numLocksAfterTeOnInvalidate = -1;
+ }
+ }
+
+ public interface CacheOperation {
+
+ public abstract void execute();
+ }
+}
Deleted: trunk/core/src/test/java/org/infinispan/tx/exception/TxAndRemoteTimeoutExceptionTest.java
===================================================================
--- branches/4.2.x/core/src/test/java/org/infinispan/tx/exception/TxAndRemoteTimeoutExceptionTest.java 2010-09-15 16:19:59 UTC (rev 2385)
+++ trunk/core/src/test/java/org/infinispan/tx/exception/TxAndRemoteTimeoutExceptionTest.java 2010-09-15 19:09:38 UTC (rev 2386)
@@ -1,200 +0,0 @@
-package org.infinispan.tx.exception;
-
-import org.infinispan.commands.VisitableCommand;
-import org.infinispan.commands.tx.PrepareCommand;
-import org.infinispan.config.Configuration;
-import org.infinispan.context.InvocationContext;
-import org.infinispan.context.impl.TxInvocationContext;
-import org.infinispan.interceptors.base.CommandInterceptor;
-import org.infinispan.test.MultipleCacheManagersTest;
-import org.infinispan.test.TestingUtil;
-import org.infinispan.transaction.xa.TransactionTable;
-import org.infinispan.util.concurrent.TimeoutException;
-import org.infinispan.util.concurrent.locks.LockManager;
-import org.infinispan.util.logging.Log;
-import org.infinispan.util.logging.LogFactory;
-import org.testng.annotations.Test;
-
-import javax.transaction.HeuristicMixedException;
-import javax.transaction.HeuristicRollbackException;
-import javax.transaction.InvalidTransactionException;
-import javax.transaction.NotSupportedException;
-import javax.transaction.RollbackException;
-import javax.transaction.SystemException;
-import javax.transaction.Transaction;
-import javax.transaction.TransactionManager;
-
-import java.util.HashMap;
-import java.util.Map;
-
-import static org.testng.Assert.assertEquals;
-
-/**
- * Tester for https://jira.jboss.org/browse/ISPN-629.
- *
- * @author Mircea.Markus at jboss.com
- * @since 4.2
- */
- at Test(groups = "functional", testName = "tx.TestTxAndRemoteTimeoutException")
-public class TxAndRemoteTimeoutExceptionTest extends MultipleCacheManagersTest {
-
- private static Log log = LogFactory.getLog(TxAndRemoteTimeoutExceptionTest.class);
-
- private LockManager lm1;
- private LockManager lm0;
- private TransactionTable txTable0;
- private TransactionTable txTable1;
- private TransactionManager tm;
- private TxStatusInterceptor txStatus = new TxStatusInterceptor();
-
- @Override
- protected void createCacheManagers() throws Throwable {
- Configuration defaultConfig = getDefaultConfig();
- defaultConfig.setLockAcquisitionTimeout(500);
- defaultConfig.setUseLockStriping(false);
- addClusterEnabledCacheManager(defaultConfig);
- addClusterEnabledCacheManager(defaultConfig);
- lm0 = TestingUtil.extractLockManager(cache(0));
- lm1 = TestingUtil.extractLockManager(cache(1));
- txTable0 = TestingUtil.getTransactionTable(cache(0));
- txTable1 = TestingUtil.getTransactionTable(cache(1));
- tm = cache(0).getAdvancedCache().getTransactionManager();
- cache(1).getAdvancedCache().addInterceptor(txStatus, 0);
- TestingUtil.blockUntilViewReceived(cache(0), 2, 10000);
- }
-
- protected Configuration getDefaultConfig() {
- return getDefaultClusteredConfig(Configuration.CacheMode.REPL_SYNC, true);
- }
-
- public void testClearTimeoutsInTx() throws Exception {
- cache(0).put("k1", "value");
- runAssertion(new CacheOperation() {
- @Override
- public void execute() {
- cache(0).clear();
- }
- });
- }
-
- public void testPutTimeoutsInTx() throws Exception {
- runAssertion(new CacheOperation() {
- @Override
- public void execute() {
- cache(0).put("k1", "v2222");
- }
- });
- }
-
- public void testRemoveTimeoutsInTx() throws Exception {
- runAssertion(new CacheOperation() {
- @Override
- public void execute() {
- cache(0).remove("k1");
- }
- });
- }
-
- public void testReplaceTimeoutsInTx() throws Exception {
- cache(1).put("k1", "value");
- runAssertion(new CacheOperation() {
- @Override
- public void execute() {
- cache(0).replace("k1", "newValue");
- }
- });
- }
-
- public void testPutAllTimeoutsInTx() throws Exception {
- runAssertion(new CacheOperation() {
- @Override
- public void execute() {
- Map toAdd = new HashMap();
- toAdd.put("k1", "v22222");
- cache(0).putAll(toAdd);
- }
- });
- }
-
-
- private void runAssertion(CacheOperation operation) throws NotSupportedException, SystemException, HeuristicMixedException, HeuristicRollbackException, InvalidTransactionException, RollbackException {
- txStatus.reset();
- tm.begin();
- cache(1).put("k1", "v1");
- Transaction k1LockOwner = tm.suspend();
- assert lm1.isLocked("k1");
-
- assertEquals(1, txTable1.getLocalTxCount());
- tm.begin();
- cache(0).put("k2", "v2");
- assert lm0.isLocked("k2");
- assert !lm1.isLocked("k2");
-
- operation.execute();
-
- assertEquals(1, txTable1.getLocalTxCount());
- assertEquals(1, txTable0.getLocalTxCount());
-
-
- try {
- tm.commit();
- assert false;
- } catch (RollbackException re) {
- //expected
- }
- assert txStatus.teReceived;
- assert txStatus.isTxInTableAfterTeOnPrepare;
- //expect 1 as k1 is locked by the other tx
- assertEquals(txStatus.numLocksAfterTeOnPrepare, 1, "This would make sure that locks are being released quickly, not waiting for a remote rollback to happen");
-
- assertEquals(0, txTable0.getLocalTxCount());
- assertEquals(1, txTable1.getLocalTxCount());
-
- log.trace("Right before second commit");
- tm.resume(k1LockOwner);
- tm.commit();
- assertEquals("v1", cache(0).get("k1"));
- assertEquals("v1", cache(1).get("k1"));
- assertEquals(0, txTable1.getLocalTxCount());
- assertEquals(0, txTable1.getLocalTxCount());
- assertEquals(0, lm0.getNumberOfLocksHeld());
- assertEquals(0, lm1.getNumberOfLocksHeld());
- }
-
- private class TxStatusInterceptor extends CommandInterceptor {
-
- private boolean teReceived;
-
- private boolean isTxInTableAfterTeOnPrepare;
-
- private int numLocksAfterTeOnPrepare;
-
- @Override
- public Object visitPrepareCommand(TxInvocationContext ctx, PrepareCommand command) throws Throwable {
- try {
- return invokeNextInterceptor(ctx, command);
- } catch (TimeoutException te) {
- numLocksAfterTeOnPrepare = lm1.getNumberOfLocksHeld();
- isTxInTableAfterTeOnPrepare = txTable1.containRemoteTx(ctx.getGlobalTransaction());
- teReceived = true;
- throw te;
- }
- }
-
- @Override
- protected Object handleDefault(InvocationContext ctx, VisitableCommand command) throws Throwable {
- return super.handleDefault(ctx, command);
- }
-
- public void reset() {
- this.teReceived = false;
- this.isTxInTableAfterTeOnPrepare = false;
- this.numLocksAfterTeOnPrepare = -1;
- }
- }
-
- public interface CacheOperation {
-
- public abstract void execute();
- }
-}
Copied: trunk/core/src/test/java/org/infinispan/tx/exception/TxAndRemoteTimeoutExceptionTest.java (from rev 2385, branches/4.2.x/core/src/test/java/org/infinispan/tx/exception/TxAndRemoteTimeoutExceptionTest.java)
===================================================================
--- trunk/core/src/test/java/org/infinispan/tx/exception/TxAndRemoteTimeoutExceptionTest.java (rev 0)
+++ trunk/core/src/test/java/org/infinispan/tx/exception/TxAndRemoteTimeoutExceptionTest.java 2010-09-15 19:09:38 UTC (rev 2386)
@@ -0,0 +1,200 @@
+package org.infinispan.tx.exception;
+
+import org.infinispan.commands.VisitableCommand;
+import org.infinispan.commands.tx.PrepareCommand;
+import org.infinispan.config.Configuration;
+import org.infinispan.context.InvocationContext;
+import org.infinispan.context.impl.TxInvocationContext;
+import org.infinispan.interceptors.base.CommandInterceptor;
+import org.infinispan.test.MultipleCacheManagersTest;
+import org.infinispan.test.TestingUtil;
+import org.infinispan.transaction.xa.TransactionTable;
+import org.infinispan.util.concurrent.TimeoutException;
+import org.infinispan.util.concurrent.locks.LockManager;
+import org.infinispan.util.logging.Log;
+import org.infinispan.util.logging.LogFactory;
+import org.testng.annotations.Test;
+
+import javax.transaction.HeuristicMixedException;
+import javax.transaction.HeuristicRollbackException;
+import javax.transaction.InvalidTransactionException;
+import javax.transaction.NotSupportedException;
+import javax.transaction.RollbackException;
+import javax.transaction.SystemException;
+import javax.transaction.Transaction;
+import javax.transaction.TransactionManager;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import static org.testng.Assert.assertEquals;
+
+/**
+ * Tester for https://jira.jboss.org/browse/ISPN-629.
+ *
+ * @author Mircea.Markus at jboss.com
+ * @since 4.2
+ */
+ at Test(groups = "functional", testName = "tx.TestTxAndRemoteTimeoutException")
+public class TxAndRemoteTimeoutExceptionTest extends MultipleCacheManagersTest {
+
+ private static Log log = LogFactory.getLog(TxAndRemoteTimeoutExceptionTest.class);
+
+ private LockManager lm1;
+ private LockManager lm0;
+ private TransactionTable txTable0;
+ private TransactionTable txTable1;
+ private TransactionManager tm;
+ private TxStatusInterceptor txStatus = new TxStatusInterceptor();
+
+ @Override
+ protected void createCacheManagers() throws Throwable {
+ Configuration defaultConfig = getDefaultConfig();
+ defaultConfig.setLockAcquisitionTimeout(500);
+ defaultConfig.setUseLockStriping(false);
+ addClusterEnabledCacheManager(defaultConfig);
+ addClusterEnabledCacheManager(defaultConfig);
+ lm0 = TestingUtil.extractLockManager(cache(0));
+ lm1 = TestingUtil.extractLockManager(cache(1));
+ txTable0 = TestingUtil.getTransactionTable(cache(0));
+ txTable1 = TestingUtil.getTransactionTable(cache(1));
+ tm = cache(0).getAdvancedCache().getTransactionManager();
+ cache(1).getAdvancedCache().addInterceptor(txStatus, 0);
+ TestingUtil.blockUntilViewReceived(cache(0), 2, 10000);
+ }
+
+ protected Configuration getDefaultConfig() {
+ return getDefaultClusteredConfig(Configuration.CacheMode.REPL_SYNC, true);
+ }
+
+ public void testClearTimeoutsInTx() throws Exception {
+ cache(0).put("k1", "value");
+ runAssertion(new CacheOperation() {
+ @Override
+ public void execute() {
+ cache(0).clear();
+ }
+ });
+ }
+
+ public void testPutTimeoutsInTx() throws Exception {
+ runAssertion(new CacheOperation() {
+ @Override
+ public void execute() {
+ cache(0).put("k1", "v2222");
+ }
+ });
+ }
+
+ public void testRemoveTimeoutsInTx() throws Exception {
+ runAssertion(new CacheOperation() {
+ @Override
+ public void execute() {
+ cache(0).remove("k1");
+ }
+ });
+ }
+
+ public void testReplaceTimeoutsInTx() throws Exception {
+ cache(1).put("k1", "value");
+ runAssertion(new CacheOperation() {
+ @Override
+ public void execute() {
+ cache(0).replace("k1", "newValue");
+ }
+ });
+ }
+
+ public void testPutAllTimeoutsInTx() throws Exception {
+ runAssertion(new CacheOperation() {
+ @Override
+ public void execute() {
+ Map toAdd = new HashMap();
+ toAdd.put("k1", "v22222");
+ cache(0).putAll(toAdd);
+ }
+ });
+ }
+
+
+ private void runAssertion(CacheOperation operation) throws NotSupportedException, SystemException, HeuristicMixedException, HeuristicRollbackException, InvalidTransactionException, RollbackException {
+ txStatus.reset();
+ tm.begin();
+ cache(1).put("k1", "v1");
+ Transaction k1LockOwner = tm.suspend();
+ assert lm1.isLocked("k1");
+
+ assertEquals(1, txTable1.getLocalTxCount());
+ tm.begin();
+ cache(0).put("k2", "v2");
+ assert lm0.isLocked("k2");
+ assert !lm1.isLocked("k2");
+
+ operation.execute();
+
+ assertEquals(1, txTable1.getLocalTxCount());
+ assertEquals(1, txTable0.getLocalTxCount());
+
+
+ try {
+ tm.commit();
+ assert false;
+ } catch (RollbackException re) {
+ //expected
+ }
+ assert txStatus.teReceived;
+ assert txStatus.isTxInTableAfterTeOnPrepare;
+ //expect 1 as k1 is locked by the other tx
+ assertEquals(txStatus.numLocksAfterTeOnPrepare, 1, "This would make sure that locks are being released quickly, not waiting for a remote rollback to happen");
+
+ assertEquals(0, txTable0.getLocalTxCount());
+ assertEquals(1, txTable1.getLocalTxCount());
+
+ log.trace("Right before second commit");
+ tm.resume(k1LockOwner);
+ tm.commit();
+ assertEquals("v1", cache(0).get("k1"));
+ assertEquals("v1", cache(1).get("k1"));
+ assertEquals(0, txTable1.getLocalTxCount());
+ assertEquals(0, txTable1.getLocalTxCount());
+ assertEquals(0, lm0.getNumberOfLocksHeld());
+ assertEquals(0, lm1.getNumberOfLocksHeld());
+ }
+
+ private class TxStatusInterceptor extends CommandInterceptor {
+
+ private boolean teReceived;
+
+ private boolean isTxInTableAfterTeOnPrepare;
+
+ private int numLocksAfterTeOnPrepare;
+
+ @Override
+ public Object visitPrepareCommand(TxInvocationContext ctx, PrepareCommand command) throws Throwable {
+ try {
+ return invokeNextInterceptor(ctx, command);
+ } catch (TimeoutException te) {
+ numLocksAfterTeOnPrepare = lm1.getNumberOfLocksHeld();
+ isTxInTableAfterTeOnPrepare = txTable1.containRemoteTx(ctx.getGlobalTransaction());
+ teReceived = true;
+ throw te;
+ }
+ }
+
+ @Override
+ protected Object handleDefault(InvocationContext ctx, VisitableCommand command) throws Throwable {
+ return super.handleDefault(ctx, command);
+ }
+
+ public void reset() {
+ this.teReceived = false;
+ this.isTxInTableAfterTeOnPrepare = false;
+ this.numLocksAfterTeOnPrepare = -1;
+ }
+ }
+
+ public interface CacheOperation {
+
+ public abstract void execute();
+ }
+}
Deleted: trunk/core/src/test/java/org/infinispan/tx/exception/TxAndTimeoutExceptionTest.java
===================================================================
--- branches/4.2.x/core/src/test/java/org/infinispan/tx/exception/TxAndTimeoutExceptionTest.java 2010-09-15 16:19:59 UTC (rev 2385)
+++ trunk/core/src/test/java/org/infinispan/tx/exception/TxAndTimeoutExceptionTest.java 2010-09-15 19:09:38 UTC (rev 2386)
@@ -1,143 +0,0 @@
-package org.infinispan.tx.exception;
-
-import org.infinispan.config.Configuration;
-import org.infinispan.manager.EmbeddedCacheManager;
-import org.infinispan.test.SingleCacheManagerTest;
-import org.infinispan.test.TestingUtil;
-import org.infinispan.test.fwk.TestCacheManagerFactory;
-import org.infinispan.transaction.xa.TransactionTable;
-import org.infinispan.util.concurrent.TimeoutException;
-import org.infinispan.util.concurrent.locks.LockManager;
-import org.testng.annotations.Test;
-
-import javax.transaction.Status;
-import javax.transaction.Transaction;
-import javax.transaction.TransactionManager;
-import java.util.HashMap;
-import java.util.Map;
-
-import static org.testng.Assert.assertEquals;
-
-/**
- * Tester for https://jira.jboss.org/browse/ISPN-629.
- *
- * @author Mircea.Markus at jboss.com
- * @since 4.2
- */
- at Test(testName = "tx.TxAndTimeoutExceptionTest", groups = "functional")
-public class TxAndTimeoutExceptionTest extends SingleCacheManagerTest {
-
- @Override
- protected EmbeddedCacheManager createCacheManager() throws Exception {
- Configuration config = getDefaultStandaloneConfig(true);
- config.setUseLockStriping(false);
- config.setLockAcquisitionTimeout(1000);
- EmbeddedCacheManager cm = TestCacheManagerFactory.createCacheManager(config, true);
- cache = cm.getCache();
- return cm;
- }
-
-
- public void testPutTimeoutsInTx() throws Exception {
- assertExpectedBehavior(new CacheOperation() {
- @Override
- public void execute() {
- cache.put("k1", "v2222");
- }
- });
- }
-
- public void testRemoveTimeoutsInTx() throws Exception {
- assertExpectedBehavior(new CacheOperation() {
- @Override
- public void execute() {
- cache.remove("k1");
- }
- });
- }
-
- public void testClearTimeoutsInTx() throws Exception {
- cache.put("k1", "value");
- assertExpectedBehavior(new CacheOperation() {
- @Override
- public void execute() {
- cache.clear();
- }
- });
- }
-
- public void testReplaceTimeoutsInTx() throws Exception {
- assertExpectedBehavior(new CacheOperation() {
- @Override
- public void execute() {
- cache.replace("k1", "newValue");
- }
- });
- }
-
- public void testPutAllTimeoutsInTx() throws Exception {
- assertExpectedBehavior(new CacheOperation() {
- @Override
- public void execute() {
- Map toAdd = new HashMap();
- toAdd.put("k1", "v22222");
- cache.putAll(toAdd);
- }
- });
- }
-
- private void assertExpectedBehavior(CacheOperation op) throws Exception {
- LockManager lm = TestingUtil.extractLockManager(cache);
- TransactionTable txTable = TestingUtil.getTransactionTable(cache);
- TransactionManager tm = cache.getAdvancedCache().getTransactionManager();
- tm.begin();
- cache.put("k1", "v1");
- Transaction k1LockOwner = tm.suspend();
- assert lm.isLocked("k1");
-
- assertEquals(1, txTable.getLocalTxCount());
- tm.begin();
- cache.put("k2", "v2");
- assert lm.isLocked("k2");
- assertEquals(2, txTable.getLocalTxCount());
- try {
- op.execute();
- assert false : "Timeout exception expected";
- } catch (TimeoutException e) {
- //expected
- }
-
- //make sure that locks acquired by that tx were released even before the transaction is rolled back, the tx object
- //was marked for rollback
- Transaction transaction = tm.getTransaction();
- assert transaction != null;
- assert transaction.getStatus() == Status.STATUS_MARKED_ROLLBACK;
- assert !lm.isLocked("k2");
- assert lm.isLocked("k1");
- try {
- cache.put("k3", "v3");
- assert false;
- } catch (IllegalStateException e) {
- //expected
- }
- assertEquals(txTable.getLocalTxCount(), 2);
-
- //now the TM is expected to rollback the tx
- tm.rollback();
- assertEquals(txTable.getLocalTxCount(), 1);
-
- tm.resume(k1LockOwner);
- tm.commit();
-
- //now test that the other tx works as expected
- assertEquals(0, txTable.getLocalTxCount());
- assertEquals(cache.get("k1"), "v1");
- assert !lm.isLocked("k1");
- assertEquals(txTable.getLocalTxCount(), 0);
- }
-
- public interface CacheOperation {
-
- public abstract void execute();
- }
-}
Copied: trunk/core/src/test/java/org/infinispan/tx/exception/TxAndTimeoutExceptionTest.java (from rev 2385, branches/4.2.x/core/src/test/java/org/infinispan/tx/exception/TxAndTimeoutExceptionTest.java)
===================================================================
--- trunk/core/src/test/java/org/infinispan/tx/exception/TxAndTimeoutExceptionTest.java (rev 0)
+++ trunk/core/src/test/java/org/infinispan/tx/exception/TxAndTimeoutExceptionTest.java 2010-09-15 19:09:38 UTC (rev 2386)
@@ -0,0 +1,143 @@
+package org.infinispan.tx.exception;
+
+import org.infinispan.config.Configuration;
+import org.infinispan.manager.EmbeddedCacheManager;
+import org.infinispan.test.SingleCacheManagerTest;
+import org.infinispan.test.TestingUtil;
+import org.infinispan.test.fwk.TestCacheManagerFactory;
+import org.infinispan.transaction.xa.TransactionTable;
+import org.infinispan.util.concurrent.TimeoutException;
+import org.infinispan.util.concurrent.locks.LockManager;
+import org.testng.annotations.Test;
+
+import javax.transaction.Status;
+import javax.transaction.Transaction;
+import javax.transaction.TransactionManager;
+import java.util.HashMap;
+import java.util.Map;
+
+import static org.testng.Assert.assertEquals;
+
+/**
+ * Tester for https://jira.jboss.org/browse/ISPN-629.
+ *
+ * @author Mircea.Markus at jboss.com
+ * @since 4.2
+ */
+ at Test(testName = "tx.TxAndTimeoutExceptionTest", groups = "functional")
+public class TxAndTimeoutExceptionTest extends SingleCacheManagerTest {
+
+ @Override
+ protected EmbeddedCacheManager createCacheManager() throws Exception {
+ Configuration config = getDefaultStandaloneConfig(true);
+ config.setUseLockStriping(false);
+ config.setLockAcquisitionTimeout(1000);
+ EmbeddedCacheManager cm = TestCacheManagerFactory.createCacheManager(config, true);
+ cache = cm.getCache();
+ return cm;
+ }
+
+
+ public void testPutTimeoutsInTx() throws Exception {
+ assertExpectedBehavior(new CacheOperation() {
+ @Override
+ public void execute() {
+ cache.put("k1", "v2222");
+ }
+ });
+ }
+
+ public void testRemoveTimeoutsInTx() throws Exception {
+ assertExpectedBehavior(new CacheOperation() {
+ @Override
+ public void execute() {
+ cache.remove("k1");
+ }
+ });
+ }
+
+ public void testClearTimeoutsInTx() throws Exception {
+ cache.put("k1", "value");
+ assertExpectedBehavior(new CacheOperation() {
+ @Override
+ public void execute() {
+ cache.clear();
+ }
+ });
+ }
+
+ public void testReplaceTimeoutsInTx() throws Exception {
+ assertExpectedBehavior(new CacheOperation() {
+ @Override
+ public void execute() {
+ cache.replace("k1", "newValue");
+ }
+ });
+ }
+
+ public void testPutAllTimeoutsInTx() throws Exception {
+ assertExpectedBehavior(new CacheOperation() {
+ @Override
+ public void execute() {
+ Map toAdd = new HashMap();
+ toAdd.put("k1", "v22222");
+ cache.putAll(toAdd);
+ }
+ });
+ }
+
+ private void assertExpectedBehavior(CacheOperation op) throws Exception {
+ LockManager lm = TestingUtil.extractLockManager(cache);
+ TransactionTable txTable = TestingUtil.getTransactionTable(cache);
+ TransactionManager tm = cache.getAdvancedCache().getTransactionManager();
+ tm.begin();
+ cache.put("k1", "v1");
+ Transaction k1LockOwner = tm.suspend();
+ assert lm.isLocked("k1");
+
+ assertEquals(1, txTable.getLocalTxCount());
+ tm.begin();
+ cache.put("k2", "v2");
+ assert lm.isLocked("k2");
+ assertEquals(2, txTable.getLocalTxCount());
+ try {
+ op.execute();
+ assert false : "Timeout exception expected";
+ } catch (TimeoutException e) {
+ //expected
+ }
+
+ //make sure that locks acquired by that tx were released even before the transaction is rolled back, the tx object
+ //was marked for rollback
+ Transaction transaction = tm.getTransaction();
+ assert transaction != null;
+ assert transaction.getStatus() == Status.STATUS_MARKED_ROLLBACK;
+ assert !lm.isLocked("k2");
+ assert lm.isLocked("k1");
+ try {
+ cache.put("k3", "v3");
+ assert false;
+ } catch (IllegalStateException e) {
+ //expected
+ }
+ assertEquals(txTable.getLocalTxCount(), 2);
+
+ //now the TM is expected to rollback the tx
+ tm.rollback();
+ assertEquals(txTable.getLocalTxCount(), 1);
+
+ tm.resume(k1LockOwner);
+ tm.commit();
+
+ //now test that the other tx works as expected
+ assertEquals(0, txTable.getLocalTxCount());
+ assertEquals(cache.get("k1"), "v1");
+ assert !lm.isLocked("k1");
+ assertEquals(txTable.getLocalTxCount(), 0);
+ }
+
+ public interface CacheOperation {
+
+ public abstract void execute();
+ }
+}
Copied: trunk/core/src/test/java/org/infinispan/tx/timeout (from rev 2385, branches/4.2.x/core/src/test/java/org/infinispan/tx/timeout)
Modified: trunk/core/src/test/java/org/infinispan/util/DeadlockDetectingLockManagerTest.java
===================================================================
--- trunk/core/src/test/java/org/infinispan/util/DeadlockDetectingLockManagerTest.java 2010-09-15 16:19:59 UTC (rev 2385)
+++ trunk/core/src/test/java/org/infinispan/util/DeadlockDetectingLockManagerTest.java 2010-09-15 19:09:38 UTC (rev 2386)
@@ -5,14 +5,16 @@
import static org.easymock.EasyMock.expect;
import static org.easymock.classextension.EasyMock.replay;
import static org.easymock.classextension.EasyMock.verify;
+import static org.testng.Assert.assertEquals;
import org.infinispan.config.Configuration;
import org.infinispan.context.InvocationContext;
import org.infinispan.context.impl.NonTxInvocationContext;
import org.infinispan.context.impl.LocalTxInvocationContext;
import org.infinispan.test.AbstractInfinispanTest;
+import org.infinispan.transaction.xa.DldGlobalTransaction;
import org.infinispan.transaction.xa.GlobalTransactionFactory;
-import org.infinispan.transaction.xa.DeadlockDetectingGlobalTransaction;
+import org.infinispan.util.concurrent.locks.DeadlockDetectedException;
import org.infinispan.util.concurrent.locks.DeadlockDetectingLockManager;
import org.infinispan.util.concurrent.locks.containers.LockContainer;
import org.testng.annotations.BeforeMethod;
@@ -34,13 +36,13 @@
Configuration config = new Configuration();
private LockContainer lc;
private static final int SPIN_DURATION = 1000;
- private DeadlockDetectingGlobalTransaction lockOwner;
+ private DldGlobalTransaction lockOwner;
@BeforeMethod
public void setUp() {
lc = createMock(LockContainer.class);
lockManager = new DeadlockDetectingLockManagerMock(SPIN_DURATION, true, lc, config);
- lockOwner = (DeadlockDetectingGlobalTransaction) gtf.instantiateGlobalTransaction();
+ lockOwner = (DldGlobalTransaction) gtf.instantiateGlobalTransaction();
}
@@ -58,7 +60,7 @@
}
public void testLockHeldByThread() throws Exception {
- InvocationContext localTxContext = new LocalTxInvocationContext();
+ InvocationContext localTxContext = buildLocalTxIc(new DldGlobalTransaction());
//this makes sure that we cannot acquire lock from the first try
expect(lc.acquireLock("k", SPIN_DURATION, TimeUnit.MILLISECONDS)).andReturn(null);
@@ -73,31 +75,42 @@
}
public void testLocalDeadlock() throws Exception {
- final DeadlockDetectingGlobalTransaction ddgt = (DeadlockDetectingGlobalTransaction) gtf.instantiateGlobalTransaction();
+ final DldGlobalTransaction ddgt = (DldGlobalTransaction) gtf.instantiateGlobalTransaction();
- InvocationContext localTxContext = new LocalTxInvocationContext() {
- @Override
- public Object getLockOwner() {
- return ddgt;
- }
- };
+ InvocationContext localTxContext = buildLocalTxIc(ddgt);
ddgt.setCoinToss(0);
- lockOwner.setCoinToss(-1);
- assert ddgt.thisWillInterrupt(lockOwner);
+ lockOwner.setCoinToss(1);
+ assert ddgt.wouldLose(lockOwner);
//this makes sure that we cannot acquire lock from the first try
expect(lc.acquireLock("k", SPIN_DURATION, TimeUnit.MILLISECONDS)).andReturn(null);
Lock mockLock = createNiceMock(Lock.class);
expect(lc.acquireLock("k", SPIN_DURATION, TimeUnit.MILLISECONDS)).andReturn(mockLock);
lockOwner.setRemote(false);
+ lockOwner.setLockIntention("k");
lockManager.setOwner(lockOwner);
lockManager.setOwnsLock(true);
replay(lc);
- assert lockManager.lockAndRecord("k", localTxContext);
- assert lockManager.getDetectedLocalDeadlocks() == 1;
+ try {
+ lockManager.lockAndRecord("k", localTxContext);
+ assert false;
+ } catch (DeadlockDetectedException e) {
+ //expected
+ }
+ assertEquals(1l,lockManager.getDetectedLocalDeadlocks());
}
+ private InvocationContext buildLocalTxIc(final DldGlobalTransaction ddgt) {
+ InvocationContext localTxContext = new LocalTxInvocationContext() {
+ @Override
+ public Object getLockOwner() {
+ return ddgt;
+ }
+ };
+ return localTxContext;
+ }
+
public static class DeadlockDetectingLockManagerMock extends DeadlockDetectingLockManager {
private Object owner;
Modified: trunk/core/src/test/resources/configs/named-cache-test.xml
===================================================================
--- trunk/core/src/test/resources/configs/named-cache-test.xml 2010-09-15 16:19:59 UTC (rev 2385)
+++ trunk/core/src/test/resources/configs/named-cache-test.xml 2010-09-15 19:09:38 UTC (rev 2386)
@@ -54,7 +54,7 @@
</default>
<namedCache name="transactional">
- <transaction transactionManagerLookupClass="org.infinispan.transaction.lookup.GenericTransactionManagerLookup" useEagerLocking="true"/>
+ <transaction transactionManagerLookupClass="org.infinispan.transaction.lookup.GenericTransactionManagerLookup" useEagerLocking="true" eagerLockSingleNode="true"/>
</namedCache>
<namedCache name="syncRepl">
Modified: trunk/core/src/test/resources/log4j.xml
===================================================================
--- trunk/core/src/test/resources/log4j.xml 2010-09-15 16:19:59 UTC (rev 2385)
+++ trunk/core/src/test/resources/log4j.xml 2010-09-15 19:09:38 UTC (rev 2386)
@@ -45,7 +45,7 @@
<!-- ================ -->
<category name="org.infinispan">
- <priority value="INFO"/>
+ <priority value="TRACE"/>
</category>
<category name="org.infinispan.profiling">
@@ -65,7 +65,7 @@
<!-- ======================= -->
<root>
- <priority value="TRACE"/>
+ <priority value="INFO"/>
<!--<appender-ref ref="CONSOLE"/>-->
<appender-ref ref="FILE"/>
</root>
Modified: trunk/lucene-directory/src/main/java/org/infinispan/lucene/readlocks/DistributedSegmentReadLocker.java
===================================================================
--- trunk/lucene-directory/src/main/java/org/infinispan/lucene/readlocks/DistributedSegmentReadLocker.java 2010-09-15 16:19:59 UTC (rev 2385)
+++ trunk/lucene-directory/src/main/java/org/infinispan/lucene/readlocks/DistributedSegmentReadLocker.java 2010-09-15 19:09:38 UTC (rev 2386)
@@ -159,12 +159,15 @@
FileCacheKey key = new FileCacheKey(indexName, filename);
boolean batch = cache.startBatch();
FileMetadata file = (FileMetadata) cache.withFlags(Flag.SKIP_LOCKING).remove(key);
- for (int i = 0; i < file.getNumberOfChunks(); i++) {
- ChunkCacheKey chunkKey = new ChunkCacheKey(indexName, filename, i);
- cache.withFlags(Flag.SKIP_REMOTE_LOOKUP).removeAsync(chunkKey);
+ if (file != null) { //during optimization of index a same file could be deleted twice, so you could see a null here
+ for (int i = 0; i < file.getNumberOfChunks(); i++) {
+ ChunkCacheKey chunkKey = new ChunkCacheKey(indexName, filename, i);
+ cache.withFlags(Flag.SKIP_REMOTE_LOOKUP).removeAsync(chunkKey);
+ }
+ cache.withFlags(Flag.SKIP_REMOTE_LOOKUP).removeAsync(key);
}
- cache.withFlags(Flag.SKIP_REMOTE_LOOKUP).removeAsync(key);
- //last operation, as being set as value==0 it prevents others from using it during the deletion process:
+ // last operation, as being set as value==0 it prevents others from using it during the
+ // deletion process:
cache.withFlags(Flag.SKIP_REMOTE_LOOKUP).removeAsync(readLockKey);
if (batch) {
cache.endBatch(true);
Property changes on: trunk/tree
___________________________________________________________________
Name: svn:ignore
- target
.settings
eclipse-output
test-output
output
.classpath
.project
temp-testng-customsuite.xml
*.iml
*.log
+ target
.settings
eclipse-output
test-output
output
.classpath
.project
temp-testng-customsuite.xml
*.iml
*.log
PutObjectStoreDirHere
More information about the infinispan-commits
mailing list