PageRenderTime 51ms CodeModel.GetById 23ms RepoModel.GetById 0ms app.codeStats 0ms

/jboss-as-7.1.1.Final/ejb3/src/test/java/org/jboss/as/ejb3/concurrency/EJBReadWriteLockTest.java

#
Java | 228 lines | 88 code | 29 blank | 111 comment | 1 complexity | 1e73d391fdce7f867ef0a1aa696af7f4 MD5 | raw file
Possible License(s): LGPL-2.1, Apache-2.0
  1. /*
  2. * JBoss, Home of Professional Open Source
  3. * Copyright 2005, JBoss Inc., and individual contributors as indicated
  4. * by the @authors tag. See the copyright.txt in the distribution for a
  5. * full listing of individual contributors.
  6. *
  7. * This is free software; you can redistribute it and/or modify it
  8. * under the terms of the GNU Lesser General Public License as
  9. * published by the Free Software Foundation; either version 2.1 of
  10. * the License, or (at your option) any later version.
  11. *
  12. * This software is distributed in the hope that it will be useful,
  13. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  14. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  15. * Lesser General Public License for more details.
  16. *
  17. * You should have received a copy of the GNU Lesser General Public
  18. * License along with this software; if not, write to the Free
  19. * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
  20. * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
  21. */
  22. package org.jboss.as.ejb3.concurrency;
  23. import org.junit.After;
  24. import org.junit.Assert;
  25. import org.junit.Before;
  26. import org.junit.Test;
  27. import javax.ejb.ConcurrentAccessTimeoutException;
  28. import javax.ejb.IllegalLoopbackException;
  29. import java.util.concurrent.CountDownLatch;
  30. import java.util.concurrent.TimeUnit;
  31. import java.util.concurrent.locks.Lock;
  32. /**
  33. * Tests the {@link EJBReadWriteLock}
  34. *
  35. * @author Jaikiran Pai
  36. * @version $Revision: $
  37. */
  38. public class EJBReadWriteLockTest {
  39. /**
  40. * Used in tests
  41. */
  42. private EJBReadWriteLock ejbReadWriteLock;
  43. @Before
  44. public void beforeTest() {
  45. this.ejbReadWriteLock = new EJBReadWriteLock();
  46. }
  47. @After
  48. public void afterTest() {
  49. this.ejbReadWriteLock = null;
  50. }
  51. /**
  52. * Test that a {@link javax.ejb.IllegalLoopbackException} is thrown when the thread owning a read lock
  53. * tries to obtain a write lock
  54. *
  55. * @throws Exception
  56. */
  57. @Test
  58. public void testIllegalLoopBack() throws Exception {
  59. // get a read lock
  60. Lock readLock = this.ejbReadWriteLock.readLock();
  61. // lock it!
  62. readLock.lock();
  63. // now get a write lock and try to lock it (should fail with IllegalLoopBack)
  64. Lock writeLock = this.ejbReadWriteLock.writeLock();
  65. try {
  66. writeLock.lock();
  67. // unlock the (unexpected obtained lock) and then fail the testcase
  68. writeLock.unlock();
  69. Assert.fail("Unexpected acquired write lock");
  70. } catch (IllegalLoopbackException ilbe) {
  71. // expected
  72. } finally {
  73. // unlock the write lock
  74. readLock.unlock();
  75. }
  76. }
  77. /**
  78. * Test that when a thread tries to obtain a read lock when another thread holds a write lock,
  79. * fails to acquire the lock, if the write lock is not released within the timeout specified
  80. *
  81. * @throws Exception
  82. */
  83. @Test
  84. public void testTimeout() throws Exception {
  85. // we use a countdown latch for the 2 threads involved
  86. CountDownLatch latch = new CountDownLatch(2);
  87. // get a write lock
  88. Lock writeLock = this.ejbReadWriteLock.writeLock();
  89. // create a thread which will get hold of a write lock
  90. // and do some processing for 5 seconds
  91. Thread threadHoldingWriteLock = new Thread(new ThreadHoldingWriteLock(latch, writeLock, 5000));
  92. // get a read lock
  93. Lock readLock = this.ejbReadWriteLock.readLock();
  94. // start the write lock thread (which internally will obtain
  95. // a write lock and start a 5 second processing)
  96. threadHoldingWriteLock.start();
  97. // wait for few milli sec for the write lock thread to obtain a write lock
  98. Thread.sleep(500);
  99. // now try and get a read lock, *shouldn't* be able to obtain the lock
  100. // before the 2 second timeout
  101. try {
  102. // try a read lock with 2 second timeout
  103. boolean readLockAquired = readLock.tryLock(2, TimeUnit.SECONDS);
  104. Assert.assertFalse("Unexpected obtained a read lock", readLockAquired);
  105. } catch (ConcurrentAccessTimeoutException cate) {
  106. // expected
  107. } finally {
  108. // let the latch know that this thread is done with its part
  109. // of processing
  110. latch.countDown();
  111. // now let's wait for the other thread to complete processing
  112. // and bringing down the count on the latch
  113. latch.await();
  114. }
  115. }
  116. /**
  117. * Tests that a thread can first get a write lock and at a later point in time, get
  118. * a read lock
  119. *
  120. * @throws Exception
  121. */
  122. @Test
  123. public void testSameThreadCanGetWriteThenReadLock() throws Exception {
  124. Lock writeLock = this.ejbReadWriteLock.writeLock();
  125. // lock it!
  126. writeLock.lock();
  127. Lock readLock = this.ejbReadWriteLock.readLock();
  128. // lock it! (should work, because we are going from a write to read and *not*
  129. // the other way round)
  130. try {
  131. boolean readLockAquired = readLock.tryLock(2, TimeUnit.SECONDS);
  132. // unlock the read lock, because we don't need it anymore
  133. if (readLockAquired) {
  134. readLock.unlock();
  135. }
  136. Assert.assertTrue("Could not obtain read lock when write lock was held by the same thread!", readLockAquired);
  137. } finally {
  138. // unlock our write lock
  139. writeLock.unlock();
  140. }
  141. }
  142. /**
  143. * An implementation of {@link Runnable} which in its {@link #run()} method
  144. * will first obtain a lock and then will go to sleep for the specified amount
  145. * of time. After processing, it will unlock the {@link java.util.concurrent.locks.Lock}
  146. *
  147. * @author Jaikiran Pai
  148. * @version $Revision: $
  149. */
  150. private class ThreadHoldingWriteLock implements Runnable {
  151. /**
  152. * Lock
  153. */
  154. private Lock lock;
  155. /**
  156. * The amount of time, in milli seconds, this {@link ThreadHoldingWriteLock}
  157. * will sleep for in its {@link #run()} method
  158. */
  159. private long processingTime;
  160. /**
  161. * A latch for notifying any waiting threads
  162. */
  163. private CountDownLatch latch;
  164. /**
  165. * Creates a {@link ThreadHoldingWriteLock}
  166. *
  167. * @param latch A latch for notifying any waiting threads
  168. * @param lock A lock that will be used for obtaining a lock during processing
  169. * @param processingTime The amount of time in milli seconds, this thread will sleep (a.k.a process)
  170. * in its {@link #run()} method
  171. */
  172. public ThreadHoldingWriteLock(CountDownLatch latch, Lock lock, long processingTime) {
  173. this.lock = lock;
  174. this.processingTime = processingTime;
  175. this.latch = latch;
  176. }
  177. /**
  178. * Obtains a lock, sleeps for {@link #processingTime} milli seconds and then unlocks the lock
  179. *
  180. * @see Runnable#run()
  181. */
  182. @Override
  183. public void run() {
  184. // lock it!
  185. this.lock.lock();
  186. // process(sleep) for the specified time
  187. try {
  188. Thread.sleep(this.processingTime);
  189. } catch (InterruptedException e) {
  190. // ignore
  191. } finally {
  192. // unlock
  193. this.lock.unlock();
  194. // let any waiting threads know that we are done processing
  195. this.latch.countDown();
  196. }
  197. }
  198. }
  199. }