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

Manik Surtani (JIRA) jira-events at jboss.com
Wed Jan 17 10:41:52 EST 2007


    [ http://jira.jboss.com/jira/browse/JBCACHE-740?page=comments#action_12351034 ] 
            
Manik Surtani commented on JBCACHE-740:
---------------------------------------

Is this specific to JOTM?  

Tried the attached test case (based on what you pasted in above, but uses DummyTransactionManager rather than JOTM) and it passes fine on 1.4.0.GA, 1.4.0.SP1 and 1.4.1.GA.




> 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.GA
>         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.BETA1
>
>         Attachments: MultithreadedTxTest.java
>
>
> 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