[jboss-cvs] JBoss Messaging SVN: r1899 - in branches/Branch_Cleberts_Third_Failover: src/main/org/jboss/jms/client tests/src/org/jboss/test/messaging/jms
jboss-cvs-commits at lists.jboss.org
jboss-cvs-commits at lists.jboss.org
Fri Jan 5 15:50:39 EST 2007
Author: clebert.suconic at jboss.com
Date: 2007-01-05 15:50:36 -0500 (Fri, 05 Jan 2007)
New Revision: 1899
Added:
branches/Branch_Cleberts_Third_Failover/tests/src/org/jboss/test/messaging/jms/ValveTest.java
Modified:
branches/Branch_Cleberts_Third_Failover/src/main/org/jboss/jms/client/Valve.java
Log:
Adding sanity check and a testcase simulating a real life scenario. (the worse scenario identified)
Modified: branches/Branch_Cleberts_Third_Failover/src/main/org/jboss/jms/client/Valve.java
===================================================================
--- branches/Branch_Cleberts_Third_Failover/src/main/org/jboss/jms/client/Valve.java 2007-01-05 17:20:38 UTC (rev 1898)
+++ branches/Branch_Cleberts_Third_Failover/src/main/org/jboss/jms/client/Valve.java 2007-01-05 20:50:36 UTC (rev 1899)
@@ -45,6 +45,8 @@
// Information to avoid dead locks when multiple threads are closing the valve
ThreadLocal counterLocal = new ThreadLocal();
ReadWriteLock lock;
+ int activeLocks = 0;
+ int activeCloses = 0;
// Attributes used on debug operations only
@@ -73,11 +75,21 @@
}
}
+
+ public synchronized int getActiveLocks()
+ {
+ return activeLocks;
+ }
+
public void enter() throws InterruptedException
{
//log.info("Entering Valve on Thread " + Thread.currentThread().getName());
lock.readLock().acquire();
getCounter().counter++;
+ synchronized (this)
+ {
+ activeLocks++;
+ }
if (DEBUG_VALVE)
{
Exception ex = new Exception();
@@ -91,6 +103,14 @@
//log.info("Leaving Valve on Thread " + Thread.currentThread().getName());
lock.readLock().release();
getCounter().counter--;
+ synchronized (this)
+ {
+ activeLocks--;
+ if (activeLocks < 0)
+ {
+ throw new IllegalStateException("Valve::leave was called without a call to Valve::enter");
+ }
+ }
if (DEBUG_VALVE)
{
Exception ex = (Exception) getStackEnters().pop();
@@ -136,6 +156,18 @@
}
} while (!acquired);
+ activeCloses++;
+ activeLocks++;
+
+ // Sanity check only...
+ // This should never happen, unless something was changed breaking things
+ if (activeCloses > 1)
+ {
+ lock.writeLock().release();
+ throw new IllegalStateException("There is an internal BUG on Messaging, " +
+ "Valves are being closed twice which is not acceptable");
+ }
+
if (DEBUG_VALVE)
{
Exception ex = new Exception();
@@ -146,7 +178,14 @@
public void open() throws InterruptedException
{
+ if (activeCloses <= 0 || activeLocks <= 0)
+ {
+ throw new IllegalStateException("Valve wasn't closed");
+ }
//log.info("Opening Valve on Thread " + Thread.currentThread().getName());
+ activeCloses--;
+ activeLocks--;
+
lock.writeLock().release();
// re-apply the locks as we had before closing the valve
Added: branches/Branch_Cleberts_Third_Failover/tests/src/org/jboss/test/messaging/jms/ValveTest.java
===================================================================
--- branches/Branch_Cleberts_Third_Failover/tests/src/org/jboss/test/messaging/jms/ValveTest.java 2007-01-05 17:20:38 UTC (rev 1898)
+++ branches/Branch_Cleberts_Third_Failover/tests/src/org/jboss/test/messaging/jms/ValveTest.java 2007-01-05 20:50:36 UTC (rev 1899)
@@ -0,0 +1,174 @@
+/*
+ * JBoss, Home of Professional Open Source
+ * Copyright 2005, JBoss Inc., and individual contributors as indicated
+ * by the @authors tag. See the copyright.txt 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.jboss.test.messaging.jms;
+
+import junit.framework.TestCase;
+import org.jboss.jms.client.Valve;
+import org.jboss.logging.Logger;
+
+/**
+ * @author <a href="mailto:clebert.suconic at jboss.org">Clebert Suconic</a>
+ * @version <tt>$Revision:$</tt>
+ * <p/>
+ * $Id:$
+ */
+public class ValveTest extends TestCase
+{
+
+ // Constants
+ private static final Logger log = Logger.getLogger(ValveTest.class);
+
+ // Attributes
+
+ Object semaphore = new Object();
+ boolean running = false;
+
+ // Static
+
+ // Constructors
+
+ // Public
+
+
+ // You can have multiple threads trying to close the valve at the same time.
+
+ public void testMultipleThreadsClosingAValve() throws Exception
+ {
+ Valve valve = new Valve();
+
+ ValveThread threads[] = new ValveThread[50];
+
+ for (int i = 0; i < 50; i++)
+ {
+ threads[i] = new ValveThread(valve);
+ }
+
+ for (int i = 0; i < 50; i++)
+ {
+ threads[i].start();
+ }
+
+ // time to a line up
+ Thread.sleep(1000);
+
+ synchronized (semaphore)
+ {
+ running = true;
+ semaphore.notifyAll();
+ }
+
+ for (int i = 0; i < 50; i++)
+ {
+ threads[i].join();
+ if (threads[i].failed)
+ {
+ fail("One of threads had a failure, look at logs");
+ }
+ }
+
+ assertEquals (0, valve.getActiveLocks());
+ }
+
+ // Validate weird usages that are supposed to throw exceptions
+ public void testValidateExceptions() throws Exception
+ {
+ try
+ {
+ Valve valve = new Valve();
+ valve.open();
+ valve.close();
+ valve.close(); // closing without opening should throw an exception
+ fail("Valve.close didn't generate an exception on an extra close, Valve is not safe!");
+ }
+ catch (Throwable e)
+ {
+ //e.printStackTrace();
+ }
+
+ try
+ {
+ Valve valve = new Valve();
+ valve.enter();
+ valve.leave();
+ valve.leave(); // extra leave call, should throw an exception
+ fail("Valve.close didn't generate an exception, Valve is not safe!");
+ }
+ catch (Throwable e)
+ {
+ //e.printStackTrace();
+ }
+
+ }
+
+ // Package protected
+
+ // Protected
+
+ // Private
+
+ // Inner classes
+
+ class ValveThread extends Thread
+ {
+ Valve valve;
+
+ boolean failed;
+
+ public ValveThread(Valve valve)
+ {
+ this.valve = valve;
+ }
+
+ public void run()
+ {
+ try
+ {
+ synchronized (semaphore)
+ {
+ if (!running)
+ {
+ semaphore.wait();
+ }
+ }
+ for (int i = 0; i < 10; i++)
+ {
+ valve.enter();
+ }
+ log.info("There are " + valve.getActiveLocks() +
+ " active locks on the valve before we were trying to close it");
+ valve.close();
+ valve.open();
+ for (int i = 0; i < 10; i++)
+ {
+ valve.leave();
+ }
+ }
+ catch (Exception e)
+ {
+ e.printStackTrace();
+ failed = true;
+ }
+ }
+ }
+
+}
More information about the jboss-cvs-commits
mailing list