[jboss-jira] [JBoss JIRA] Created: (JBCACHE-740) Optimistic Locking Scheme: Occasional IllegalStateExceptions on commit

Carsten Krebs (JIRA) jira-events at jboss.com
Fri Aug 18 15:58:41 EDT 2006


Optimistic Locking Scheme: Occasional IllegalStateExceptions on commit
----------------------------------------------------------------------

                 Key: JBCACHE-740
                 URL: http://jira.jboss.com/jira/browse/JBCACHE-740
             Project: JBoss Cache
          Issue Type: Bug
      Security Level: Public (Everyone can see)
    Affects Versions: 1.4.0
         Environment: Linux 2.6.15-26-686 #1 SMP PREEMPT Thu Aug 3 03:13:28 UTC 2006 i686 GNU/Linux

java version "1.5.0_06"
Java(TM) 2 Runtime Environment, Standard Edition (build 1.5.0_06-b05)
Java HotSpot(TM) Client VM (build 1.5.0_06-b05, mixed mode, sharing)

JOTM 2.0.10
JUnit 3.8.1


            Reporter: Carsten Krebs
         Assigned To: Manik Surtani
             Fix For: 2.0.0


The unit test below reproduces "occasional" IllegalStateExceptions (s.b.) on commiting a transaction.  This test tries to modify the same node at the same time by different threads in different transactions using the optimistic locking scheme.

java.lang.IllegalStateException: there is already a writer holding the lock: GlobalTransaction:<null>:43
	at org.jboss.cache.lock.LockMap.setWriterIfNotNull(LockMap.java:96)
	at org.jboss.cache.lock.IdentityLock.acquireWriteLock(IdentityLock.java:204)
	at org.jboss.cache.Node.acquireWriteLock(Node.java:431)
	at org.jboss.cache.Node.acquire(Node.java:386)
	at org.jboss.cache.interceptors.OptimisticLockingInterceptor.lockNodes(OptimisticLockingInterceptor.java:149)
	at org.jboss.cache.interceptors.OptimisticLockingInterceptor.invoke(OptimisticLockingInterceptor.java:76)
	at org.jboss.cache.interceptors.Interceptor.invoke(Interceptor.java:68)
	at org.jboss.cache.interceptors.TxInterceptor.runPreparePhase(TxInterceptor.java:804)
	at org.jboss.cache.interceptors.TxInterceptor$LocalSynchronizationHandler.beforeCompletion(TxInterceptor.java:1069)
	at org.jboss.cache.interceptors.OrderedSynchronizationHandler.beforeCompletion(OrderedSynchronizationHandler.java:75)
	at org.objectweb.jotm.SubCoordinator.doBeforeCompletion(SubCoordinator.java:1487)
	at org.objectweb.jotm.SubCoordinator.commit_one_phase(SubCoordinator.java:416)
	at org.objectweb.jotm.TransactionImpl.commit(TransactionImpl.java:239)
	at OptimisticLockingTest$Worker.run(OptimisticLockingTest.java:135)


The Cache Config:
-------------------------
<?xml version="1.0" encoding="UTF-8"?>
<server>
    <mbean code="org.jboss.cache.TreeCache" name="jboss.cache:service=TreeCache">
		<attribute name="NodeLockingScheme">OPTIMISTIC</attribute>	
        <attribute name="CacheMode">LOCAL</attribute>
    </mbean>
</server>   


The Unit Test:
-------------------
import javax.transaction.Transaction;
import javax.transaction.TransactionManager;

import junit.framework.TestCase;

import org.jboss.cache.CacheException;
import org.jboss.cache.PropertyConfigurator;
import org.jboss.cache.TransactionManagerLookup;
import org.jboss.cache.TreeCache;
import org.objectweb.jotm.Current;

import EDU.oswego.cs.dl.util.concurrent.CyclicBarrier;

/**
 * OptimisticLockingTest
 */
public class OptimisticLockingTest extends TestCase {

	private static final String NODE_PATH = "/path/node";
	private static final String KEY = "key";

	private static final Current jotm = new Current();

	private TreeCache cache;

	protected void setUp() throws Exception {
		super.setUp();

		cache = new TreeCache();
		final PropertyConfigurator config = new PropertyConfigurator();
		cache.setTransactionManagerLookup(new TransactionManagerLookup() {

			public TransactionManager getTransactionManager() throws Exception {
				return Current.getTransactionManager();
			}
		});
		config.configure(cache, this.getClass().getResourceAsStream(
				"/cache-config.xml"));
		cache.startService();
	}

	public void testSimultanWrite() throws Exception {
		for (int i = 2; i < 20; i++) {
			System.out.println(">> testing simultaneous writes with " + i
					+ " threads...");
			testSimultanWrite(i);
		}
	}

	public void testSimultanWrite(final int _numThreads) throws Exception {
		final CyclicBarrier barrier = new CyclicBarrier(_numThreads);

		Worker[] workers = new Worker[_numThreads];
		for (int i = 0; i < workers.length; i++) {
			workers[i] = new Worker();
			workers[i].barrier = barrier;
			workers[i].value = "worker" + i;
			if (i == 0) {
				workers[i].isMaster = true;
			}
			workers[i].start();
		}

		for (int i = 0; i < workers.length; i++) {
			workers[i].join();
		}

		assertNull(workers[0].exception);

		for (int i = 0; i < workers.length; i++) {
			assertNull("rollback failed", workers[i].rollbackException);
		}

		for (int i = 1; i < workers.length; i++) {
			assertNotNull("missing exception", workers[i].exception);
			assertTrue("exception is not of type CacheException",
					workers[i].exception.getCause() instanceof CacheException);
		}
		assertEquals("worker0", cache.get(NODE_PATH, KEY));

		cache.getTransactionManager().begin();
		cache.remove(NODE_PATH);
		cache.getTransactionManager().commit();
	}

	private class Worker extends Thread {

		private CyclicBarrier barrier;
		private Exception exception;
		private Exception rollbackException;
		private String value;
		private boolean isMaster;

		/**
		 * @see java.lang.Thread#run()
		 */
		public void run() {

			final TransactionManager txManager = cache.getTransactionManager();

			Transaction tx = null;
			try {
				// wait for all threads started
				barrier.barrier();

				if (isMaster) {
					txManager.begin();
					cache.put(NODE_PATH, KEY, value);

					// lets the other threads start writing
					barrier.barrier();

					// wait for other threads to their modification
					barrier.barrier();

					// commit first
					tx = txManager.getTransaction();
					tx.commit();

					// lets the other threads commit
					barrier.barrier();
				} else {
					// wait for master to start transaction
					barrier.barrier();

					txManager.begin();
					cache.put(NODE_PATH, KEY, value);

					// signal modification
					barrier.barrier();

					// wait for master to commit transaction
					barrier.barrier();
					tx = txManager.getTransaction();
					tx.commit();
				}
			} catch (Exception e) {
				exception = e;
				try {
					tx.rollback();
				} catch (Exception e1) {
					rollbackException = e1;
				}
			}
		}
	}
}

-- 
This message is automatically generated by JIRA.
-
If you think it was sent incorrectly contact one of the administrators: http://jira.jboss.com/jira/secure/Administrators.jspa
-
For more information on JIRA, see: http://www.atlassian.com/software/jira

        



More information about the jboss-jira mailing list