PageRenderTime 49ms CodeModel.GetById 36ms app.highlight 10ms 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*/
 22package org.jboss.as.ejb3.concurrency;
 23
 24import org.junit.After;
 25import org.junit.Assert;
 26import org.junit.Before;
 27import org.junit.Test;
 28
 29import javax.ejb.ConcurrentAccessTimeoutException;
 30import javax.ejb.IllegalLoopbackException;
 31import java.util.concurrent.CountDownLatch;
 32import java.util.concurrent.TimeUnit;
 33import java.util.concurrent.locks.Lock;
 34
 35/**
 36 * Tests the {@link EJBReadWriteLock}
 37 *
 38 * @author Jaikiran Pai
 39 * @version $Revision: $
 40 */
 41public class EJBReadWriteLockTest {
 42
 43    /**
 44     * Used in tests
 45     */
 46    private EJBReadWriteLock ejbReadWriteLock;
 47
 48    @Before
 49    public void beforeTest() {
 50        this.ejbReadWriteLock = new EJBReadWriteLock();
 51
 52    }
 53
 54    @After
 55    public void afterTest() {
 56        this.ejbReadWriteLock = null;
 57    }
 58
 59    /**
 60     * Test that a {@link javax.ejb.IllegalLoopbackException} is thrown when the thread owning a read lock
 61     * tries to obtain a write lock
 62     *
 63     * @throws Exception
 64     */
 65    @Test
 66    public void testIllegalLoopBack() throws Exception {
 67        // get a read lock
 68        Lock readLock = this.ejbReadWriteLock.readLock();
 69
 70        // lock it!
 71        readLock.lock();
 72
 73        // now get a write lock and try to lock it (should fail with IllegalLoopBack)
 74        Lock writeLock = this.ejbReadWriteLock.writeLock();
 75        try {
 76            writeLock.lock();
 77            // unlock the (unexpected obtained lock) and then fail the testcase
 78            writeLock.unlock();
 79
 80            Assert.fail("Unexpected acquired write lock");
 81
 82        } catch (IllegalLoopbackException ilbe) {
 83            // expected
 84        } finally {
 85            // unlock the write lock
 86            readLock.unlock();
 87        }
 88
 89    }
 90
 91    /**
 92     * Test that when a thread tries to obtain a read lock when another thread holds a write lock,
 93     * fails to acquire the lock, if the write lock is not released within the timeout specified
 94     *
 95     * @throws Exception
 96     */
 97    @Test
 98    public void testTimeout() throws Exception {
 99        // we use a countdown latch for the 2 threads involved
100        CountDownLatch latch = new CountDownLatch(2);
101        // get a write lock
102        Lock writeLock = this.ejbReadWriteLock.writeLock();
103        // create a thread which will get hold of a write lock
104        // and do some processing for 5 seconds
105        Thread threadHoldingWriteLock = new Thread(new ThreadHoldingWriteLock(latch, writeLock, 5000));
106
107        // get a read lock
108        Lock readLock = this.ejbReadWriteLock.readLock();
109
110        // start the write lock thread (which internally will obtain
111        // a write lock and start a 5 second processing)
112        threadHoldingWriteLock.start();
113        // wait for few milli sec for the write lock thread to obtain a write lock
114        Thread.sleep(500);
115        // now try and get a read lock, *shouldn't* be able to obtain the lock
116        // before the 2 second timeout
117        try {
118            // try a read lock with 2 second timeout
119            boolean readLockAquired = readLock.tryLock(2, TimeUnit.SECONDS);
120            Assert.assertFalse("Unexpected obtained a read lock", readLockAquired);
121        } catch (ConcurrentAccessTimeoutException cate) {
122            // expected
123        } finally {
124            // let the latch know that this thread is done with its part
125            // of processing
126            latch.countDown();
127
128            // now let's wait for the other thread to complete processing
129            // and bringing down the count on the latch
130            latch.await();
131        }
132
133
134    }
135
136    /**
137     * Tests that a thread can first get a write lock and at a later point in time, get
138     * a read lock
139     *
140     * @throws Exception
141     */
142    @Test
143    public void testSameThreadCanGetWriteThenReadLock() throws Exception {
144        Lock writeLock = this.ejbReadWriteLock.writeLock();
145        // lock it!
146        writeLock.lock();
147
148        Lock readLock = this.ejbReadWriteLock.readLock();
149        // lock it! (should work, because we are going from a write to read and *not*
150        // the other way round)
151        try {
152            boolean readLockAquired = readLock.tryLock(2, TimeUnit.SECONDS);
153            // unlock the read lock, because we don't need it anymore
154            if (readLockAquired) {
155                readLock.unlock();
156            }
157            Assert.assertTrue("Could not obtain read lock when write lock was held by the same thread!", readLockAquired);
158        } finally {
159            // unlock our write lock
160            writeLock.unlock();
161        }
162
163    }
164
165    /**
166     * An implementation of {@link Runnable} which in its {@link #run()} method
167     * will first obtain a lock and then will go to sleep for the specified amount
168     * of time. After processing, it will unlock the {@link java.util.concurrent.locks.Lock}
169     *
170     * @author Jaikiran Pai
171     * @version $Revision: $
172     */
173    private class ThreadHoldingWriteLock implements Runnable {
174        /**
175         * Lock
176         */
177        private Lock lock;
178
179        /**
180         * The amount of time, in milli seconds, this {@link ThreadHoldingWriteLock}
181         * will sleep for in its {@link #run()} method
182         */
183        private long processingTime;
184
185        /**
186         * A latch for notifying any waiting threads
187         */
188        private CountDownLatch latch;
189
190        /**
191         * Creates a {@link ThreadHoldingWriteLock}
192         *
193         * @param latch          A latch for notifying any waiting threads
194         * @param lock           A lock that will be used for obtaining a lock during processing
195         * @param processingTime The amount of time in milli seconds, this thread will sleep (a.k.a process)
196         *                       in its {@link #run()} method
197         */
198        public ThreadHoldingWriteLock(CountDownLatch latch, Lock lock, long processingTime) {
199            this.lock = lock;
200            this.processingTime = processingTime;
201            this.latch = latch;
202        }
203
204        /**
205         * Obtains a lock, sleeps for {@link #processingTime} milli seconds and then unlocks the lock
206         *
207         * @see Runnable#run()
208         */
209        @Override
210        public void run() {
211            // lock it!
212            this.lock.lock();
213            // process(sleep) for the specified time
214            try {
215                Thread.sleep(this.processingTime);
216            } catch (InterruptedException e) {
217                // ignore
218            } finally {
219                // unlock
220                this.lock.unlock();
221                // let any waiting threads know that we are done processing
222                this.latch.countDown();
223            }
224        }
225    }
226
227
228}