[infinispan-commits] Infinispan SVN: r1799 - in trunk/core/src: main/java/org/infinispan/notifications and 2 other directories.
infinispan-commits at lists.jboss.org
infinispan-commits at lists.jboss.org
Mon May 17 13:36:16 EDT 2010
Author: manik.surtani at jboss.com
Date: 2010-05-17 13:36:15 -0400 (Mon, 17 May 2010)
New Revision: 1799
Added:
trunk/core/src/test/java/org/infinispan/context/InvocationContextTest.java
Removed:
trunk/core/src/test/java/org/infinispan/context/InvocationContextResumeTest.java
Modified:
trunk/core/src/main/java/org/infinispan/interceptors/InterceptorChain.java
trunk/core/src/main/java/org/infinispan/interceptors/InvocationContextInterceptor.java
trunk/core/src/main/java/org/infinispan/notifications/AbstractListenerImpl.java
trunk/core/src/main/java/org/infinispan/util/concurrent/locks/containers/AbstractPerEntryLockContainer.java
trunk/core/src/main/java/org/infinispan/util/concurrent/locks/containers/AbstractStripedLockContainer.java
Log:
[ISPN-444] (Release lock when thread is interrupted) Added tests
Modified: trunk/core/src/main/java/org/infinispan/interceptors/InterceptorChain.java
===================================================================
--- trunk/core/src/main/java/org/infinispan/interceptors/InterceptorChain.java 2010-05-17 16:51:57 UTC (rev 1798)
+++ trunk/core/src/main/java/org/infinispan/interceptors/InterceptorChain.java 2010-05-17 17:36:15 UTC (rev 1799)
@@ -69,12 +69,14 @@
/**
* Ensures that the interceptor of type passed in isn't already added
+ *
* @param clazz type of interceptor to check for
*/
private void assertNotAdded(Class<? extends CommandInterceptor> clazz) {
CommandInterceptor next = firstInChain;
while (next != null) {
- if (next.getClass().equals(clazz)) throw new ConfigurationException("Detected interceptor of type [" + clazz.getName() + "] being added to the interceptor chain more than once!");
+ if (next.getClass().equals(clazz))
+ throw new ConfigurationException("Detected interceptor of type [" + clazz.getName() + "] being added to the interceptor chain more than once!");
next = next.getNext();
}
}
@@ -221,11 +223,11 @@
}
return false;
}
-
+
/**
* Replaces an existing interceptor of the given type in the interceptor chain with a new interceptor instance passed as parameter.
- *
- * @param replacingInterceptor the interceptor to add to the interceptor chain
+ *
+ * @param replacingInterceptor the interceptor to add to the interceptor chain
* @param toBeReplacedInterceptorType the type of interceptor that should be swapped with the new one
* @return true if the interceptor was replaced
*/
@@ -267,14 +269,13 @@
public Object invoke(InvocationContext ctx, VisitableCommand command) {
try {
return command.acceptVisitor(ctx, firstInChain);
- }
- catch (CacheException e) {
+ } catch (CacheException e) {
+ if (e.getCause() instanceof InterruptedException)
+ Thread.currentThread().interrupt();
throw e;
- }
- catch (RuntimeException e) {
+ } catch (RuntimeException e) {
throw e;
- }
- catch (Throwable t) {
+ } catch (Throwable t) {
throw new CacheException(t);
}
}
@@ -282,6 +283,7 @@
/**
* @return the first interceptor in the chain.
*/
+
public CommandInterceptor getFirstInChain() {
return firstInChain;
}
Modified: trunk/core/src/main/java/org/infinispan/interceptors/InvocationContextInterceptor.java
===================================================================
--- trunk/core/src/main/java/org/infinispan/interceptors/InvocationContextInterceptor.java 2010-05-17 16:51:57 UTC (rev 1798)
+++ trunk/core/src/main/java/org/infinispan/interceptors/InvocationContextInterceptor.java 2010-05-17 17:36:15 UTC (rev 1799)
@@ -22,6 +22,7 @@
package org.infinispan.interceptors;
+import org.infinispan.CacheException;
import org.infinispan.commands.VisitableCommand;
import org.infinispan.context.Flag;
import org.infinispan.context.InvocationContext;
@@ -57,7 +58,6 @@
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)) {
@@ -77,6 +77,7 @@
return null;
} else {
log.error("Execution error: ", th);
+
throw th;
}
} finally {
Modified: trunk/core/src/main/java/org/infinispan/notifications/AbstractListenerImpl.java
===================================================================
--- trunk/core/src/main/java/org/infinispan/notifications/AbstractListenerImpl.java 2010-05-17 16:51:57 UTC (rev 1798)
+++ trunk/core/src/main/java/org/infinispan/notifications/AbstractListenerImpl.java 2010-05-17 17:36:15 UTC (rev 1799)
@@ -175,11 +175,8 @@
method.invoke(target, event);
}
catch (InvocationTargetException exception) {
- Throwable cause = exception.getCause();
- if (cause != null)
- throw new CacheException("Caught exception invoking method " + method + " on listener instance " + target, cause);
- else
- throw new CacheException("Caught exception invoking method " + method + " on listener instance " + target, exception);
+ Throwable cause = getRealException(exception);
+ throw new CacheException("Caught exception invoking method " + method + " on listener instance " + target, cause);
}
catch (IllegalAccessException exception) {
getLog().warn("Unable to invoke method " + method + " on Object instance " + target + " - removing this target object from list of listeners!", exception);
@@ -194,4 +191,14 @@
asyncProcessor.execute(r);
}
}
+
+ private Throwable getRealException(Throwable re) {
+ if (re.getCause() == null) return re;
+ Throwable cause = re.getCause();
+ if (cause instanceof CacheException || cause instanceof RuntimeException)
+ return getRealException(cause);
+ else
+ return re;
+ }
+
}
Modified: trunk/core/src/main/java/org/infinispan/util/concurrent/locks/containers/AbstractPerEntryLockContainer.java
===================================================================
--- trunk/core/src/main/java/org/infinispan/util/concurrent/locks/containers/AbstractPerEntryLockContainer.java 2010-05-17 16:51:57 UTC (rev 1798)
+++ trunk/core/src/main/java/org/infinispan/util/concurrent/locks/containers/AbstractPerEntryLockContainer.java 2010-05-17 17:36:15 UTC (rev 1799)
@@ -49,6 +49,9 @@
boolean locked = false;
try {
locked = lock.tryLock(timeout, unit);
+ } catch (InterruptedException ie) {
+ safeRelease(lock);
+ throw ie;
} catch (Throwable th) {
safeRelease(lock);
locked = false;
Modified: trunk/core/src/main/java/org/infinispan/util/concurrent/locks/containers/AbstractStripedLockContainer.java
===================================================================
--- trunk/core/src/main/java/org/infinispan/util/concurrent/locks/containers/AbstractStripedLockContainer.java 2010-05-17 16:51:57 UTC (rev 1798)
+++ trunk/core/src/main/java/org/infinispan/util/concurrent/locks/containers/AbstractStripedLockContainer.java 2010-05-17 17:36:15 UTC (rev 1799)
@@ -84,6 +84,9 @@
boolean locked = false;
try {
locked = lock.tryLock(timeout, unit);
+ } catch (InterruptedException ie) {
+ safeRelease(lock);
+ throw ie;
} catch (Throwable th) {
safeRelease(lock);
locked = false;
Deleted: trunk/core/src/test/java/org/infinispan/context/InvocationContextResumeTest.java
===================================================================
--- trunk/core/src/test/java/org/infinispan/context/InvocationContextResumeTest.java 2010-05-17 16:51:57 UTC (rev 1798)
+++ trunk/core/src/test/java/org/infinispan/context/InvocationContextResumeTest.java 2010-05-17 17:36:15 UTC (rev 1799)
@@ -1,70 +0,0 @@
-/*
- * JBoss, Home of Professional Open Source.
- * Copyright 2009, Red Hat, Inc. and/or its affiliates, and
- * individual contributors as indicated by the @author tags. See the
- * copyright.txt file in the distribution for a full listing of
- * individual contributors.
- *
- * This is free software; you can redistribute it and/or modify it
- * under the terms of the GNU Lesser General Public License as
- * published by the Free Software Foundation; either version 2.1 of
- * the License, or (at your option) any later version.
- *
- * This software is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this software; if not, write to the Free
- * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
- * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
- */
-package org.infinispan.context;
-
-import org.infinispan.Cache;
-import org.infinispan.CacheException;
-import org.infinispan.config.Configuration;
-import org.infinispan.context.Flag;
-import org.infinispan.notifications.Listener;
-import org.infinispan.notifications.cachelistener.annotation.CacheEntryModified;
-import org.infinispan.notifications.cachelistener.event.CacheEntryModifiedEvent;
-import org.infinispan.test.MultipleCacheManagersTest;
-import org.infinispan.test.fwk.TestCacheManagerFactory;
-import org.infinispan.util.logging.Log;
-import org.infinispan.util.logging.LogFactory;
-import org.testng.annotations.Test;
-
- at Test(groups = {"functional"}, testName = "context.InvocationContextResumeTest")
-public class InvocationContextResumeTest extends MultipleCacheManagersTest {
- private static final Log log = LogFactory.getLog(InvocationContextResumeTest.class);
-
- @Override
- protected void createCacheManagers() throws Throwable {
- Configuration cfg = TestCacheManagerFactory.getDefaultConfiguration(true);
- cfg.setSyncCommitPhase(true);
- cfg.setSyncRollbackPhase(true);
- createClusteredCaches(1, "timestamps", cfg);
- }
-
- public void testMishavingListenerResumesContext() {
- Cache cache = cache(0, "timestamps");
- cache.addListener(new CacheListener());
- try {
- cache.getAdvancedCache().withFlags(Flag.CACHE_MODE_LOCAL).put("k", "v");
- } catch (CacheException ce) {
- assert ce.getCause() instanceof NullPointerException;
- }
- }
-
- @Listener
- public static class CacheListener {
- @CacheEntryModified
- public void entryModified(CacheEntryModifiedEvent event) {
- if (!event.isPre()) {
- log.debug("Entry modified: {0}, let's throw an NPE!!", event);
- throw new NullPointerException();
- }
- }
- }
-}
Copied: trunk/core/src/test/java/org/infinispan/context/InvocationContextTest.java (from rev 1793, trunk/core/src/test/java/org/infinispan/context/InvocationContextResumeTest.java)
===================================================================
--- trunk/core/src/test/java/org/infinispan/context/InvocationContextTest.java (rev 0)
+++ trunk/core/src/test/java/org/infinispan/context/InvocationContextTest.java 2010-05-17 17:36:15 UTC (rev 1799)
@@ -0,0 +1,163 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2009, Red Hat, Inc. and/or its affiliates, and
+ * individual contributors as indicated by the @author tags. See the
+ * copyright.txt file in the distribution for a full listing of
+ * individual contributors.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.infinispan.context;
+
+import org.infinispan.Cache;
+import org.infinispan.CacheException;
+import org.infinispan.config.Configuration;
+import org.infinispan.notifications.Listener;
+import org.infinispan.notifications.cachelistener.annotation.CacheEntryModified;
+import org.infinispan.notifications.cachelistener.event.CacheEntryModifiedEvent;
+import org.infinispan.test.MultipleCacheManagersTest;
+import org.infinispan.test.fwk.TestCacheManagerFactory;
+import org.infinispan.util.logging.Log;
+import org.infinispan.util.logging.LogFactory;
+import org.testng.annotations.Test;
+
+import javax.transaction.Transaction;
+import javax.transaction.TransactionManager;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.concurrent.CountDownLatch;
+
+ at Test(groups = {"functional"}, testName = "context.InvocationContextTest")
+public class InvocationContextTest extends MultipleCacheManagersTest {
+ private static final Log log = LogFactory.getLog(InvocationContextTest.class);
+
+ @Override
+ protected void createCacheManagers() throws Throwable {
+ Configuration cfg = TestCacheManagerFactory.getDefaultConfiguration(true);
+ cfg.setSyncCommitPhase(true);
+ cfg.setSyncRollbackPhase(true);
+ createClusteredCaches(1, "timestamps", cfg);
+ }
+
+ public void testMishavingListenerResumesContext() {
+ Cache cache = cache(0, "timestamps");
+ cache.addListener(new CacheListener());
+ try {
+ cache.getAdvancedCache().withFlags(Flag.CACHE_MODE_LOCAL).put("k", "v");
+ } catch (CacheException ce) {
+ assert ce.getCause() instanceof NullPointerException;
+ }
+ }
+
+ public void testThreadInterruptedDuringLocking() throws Throwable {
+ final Cache cache = cache(0, "timestamps");
+ cache.put("k", "v");
+ // now acquire a lock on k so that subsequent threads will block
+ TransactionManager tm = cache.getAdvancedCache().getTransactionManager();
+ tm.begin();
+ cache.put("k", "v2");
+ Transaction tx = tm.suspend();
+ final List<Throwable> throwables = new LinkedList<Throwable>();
+
+ Thread th = new Thread() {
+ public void run() {
+ try {
+ cache.put("k", "v3");
+ } catch (Throwable th) {
+ throwables.add(th);
+ }
+ }
+ };
+
+ th.start();
+ // th will now block trying to acquire the lock.
+ th.interrupt();
+ th.join();
+ tm.resume(tx);
+ tm.rollback();
+ assert throwables.size() == 1;
+
+ for (Throwable thr : throwables) thr.printStackTrace();
+ assert throwables.get(0) instanceof CacheException;
+ assert ((CacheException) throwables.get(0)).getCause() instanceof InterruptedException;
+ }
+
+
+ public void testThreadInterruptedAfterLocking() throws Throwable {
+ final Cache cache = cache(0, "timestamps");
+ cache.put("k", "v");
+ CountDownLatch willTimeoutLatch = new CountDownLatch(1);
+ CountDownLatch lockAquiredSignal = new CountDownLatch(1);
+ DelayingListener dl = new DelayingListener(lockAquiredSignal, willTimeoutLatch);
+ cache.addListener(dl);
+ final List<Throwable> throwables = new LinkedList<Throwable>();
+
+ Thread th = new Thread() {
+ public void run() {
+ try {
+ cache.put("k", "v3");
+ } catch (Throwable th) {
+ throwables.add(th);
+ }
+ }
+ };
+
+ th.start();
+ // wait for th to acquire the lock
+ lockAquiredSignal.await();
+
+ // and now interrupt the thread.
+ th.interrupt();
+ th.join();
+ assert throwables.size() == 1;
+
+ for (Throwable thr : throwables) thr.printStackTrace();
+ assert throwables.get(0) instanceof CacheException;
+ }
+
+ @Listener
+ public static class DelayingListener {
+ CountDownLatch lockAcquiredLatch, waitLatch;
+
+ public DelayingListener(CountDownLatch lockAcquiredLatch, CountDownLatch waitLatch) {
+ this.lockAcquiredLatch = lockAcquiredLatch;
+ this.waitLatch = waitLatch;
+ }
+
+ @CacheEntryModified
+ public void entryModified(CacheEntryModifiedEvent event) {
+ if (!event.isPre()) {
+ lockAcquiredLatch.countDown();
+ try {
+ waitLatch.await();
+ } catch (InterruptedException e) {
+ throw new RuntimeException(e);
+ }
+ }
+ }
+ }
+
+ @Listener
+ public static class CacheListener {
+ @CacheEntryModified
+ public void entryModified(CacheEntryModifiedEvent event) {
+ if (!event.isPre()) {
+ log.debug("Entry modified: {0}, let's throw an NPE!!", event);
+ throw new NullPointerException();
+ }
+ }
+ }
+}
More information about the infinispan-commits
mailing list