KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > jboss > cache > transaction > IsolationLevelReadCommittedTest


1 package org.jboss.cache.transaction;
2
3
4 import EDU.oswego.cs.dl.util.concurrent.Latch;
5 import junit.framework.AssertionFailedError;
6 import junit.framework.Test;
7 import junit.framework.TestCase;
8 import junit.framework.TestSuite;
9 import org.jboss.cache.Cache;
10 import org.jboss.cache.CacheImpl;
11 import org.jboss.cache.DummyTransactionManagerLookup;
12 import org.jboss.cache.Fqn;
13 import org.jboss.cache.config.Configuration;
14 import org.jboss.cache.config.Configuration.CacheMode;
15 import org.jboss.cache.factories.DefaultCacheFactory;
16 import org.jboss.cache.lock.IsolationLevel;
17 import org.jboss.cache.lock.TimeoutException;
18
19 import javax.transaction.NotSupportedException JavaDoc;
20 import javax.transaction.SystemException JavaDoc;
21 import javax.transaction.Transaction JavaDoc;
22
23
24 /**
25  * Tests READ_COMMITED isolation level.
26  *
27  * @author <a HREF="mailto:ovidiu@jboss.org">Ovidiu Feodorov</a>
28  * @version $Id: IsolationLevelReadCommittedTest.java,v 1.13 2007/01/02 18:26:05 msurtani Exp $
29  */

30
31 public class IsolationLevelReadCommittedTest extends TestCase
32 {
33
34    private Cache cache = null;
35    private final Fqn FQN = Fqn.fromString("/a/b/c");
36    private final Fqn PARENT_FQN = FQN.getParent();
37    private final String JavaDoc KEY = "key";
38    private final String JavaDoc VALUE = "value";
39
40    private volatile boolean writerFailed;
41    private volatile boolean readerFailed;
42    private volatile AssertionFailedError writerError;
43    private volatile AssertionFailedError readerError;
44
45    protected void setUp() throws Exception JavaDoc
46    {
47       super.setUp();
48
49       writerFailed = false;
50       readerFailed = false;
51
52       writerError = null;
53       readerError = null;
54
55       Configuration config = new Configuration();
56       config.setCacheMode(CacheMode.LOCAL);
57       config.setIsolationLevel(IsolationLevel.READ_COMMITTED);
58       config.setLockAcquisitionTimeout(1000);
59       config.setTransactionManagerLookupClass(DummyTransactionManagerLookup.class.getName());
60       cache = DefaultCacheFactory.getInstance().createCache(config);
61    }
62
63
64    protected void tearDown() throws Exception JavaDoc
65    {
66       super.tearDown();
67
68       cache.stop();
69       cache.destroy();
70       cache = null;
71    }
72
73
74    /**
75     * The test starts a reader and writer thread and coordinates access to the cache so the reader
76     * reads after the writer changes a node in a transaction, but before roll back. The reader
77     * should never read anything else than the original value (uncommitted values should be
78     * isolated)
79     */

80    public void testReadCommitted() throws Exception JavaDoc
81    {
82       final Latch readerCanRead = new Latch();
83       final Latch readerDone = new Latch();
84       final Latch writerCanWrite = new Latch();
85       final Latch writerCanRollback = new Latch();
86       final Latch writerDone = new Latch();
87
88       cache.put(FQN, KEY, VALUE);
89       assertEquals(VALUE, cache.get(FQN, KEY));
90
91       // start a reader thread; need a transaction so its initial
92
// read lock is maintained while the writer does its work
93

94       Thread JavaDoc readerThread = new Thread JavaDoc(new Runnable JavaDoc()
95       {
96          public void run()
97          {
98             Transaction JavaDoc tx = null;
99             try
100             {
101                tx = startTransaction();
102
103                // Read the value, thus acquiring a read lock on FQN
104
assertEquals("Could not read node with expected value!", VALUE, cache.get(FQN, KEY));
105
106                writerCanWrite.release();
107
108                // wait until the writer thread changes the value in a transaction, but it did not
109
// yet commit or roll back.
110
readerCanRead.acquire();
111
112                try
113                {
114                   // I shouldn't be able to see the "dirty" value
115
assertEquals("thread w/ read lock can see subsequent uncommitted changes!!", VALUE, cache.get(FQN, KEY));
116                }
117                catch (TimeoutException good)
118                {
119                   // this is what should happen due to writer's WL
120
}
121
122                // let the writer know it can rollback
123
writerCanRollback.release();
124
125                // I should still be able to see the "clean" value
126
assertEquals("Could not read node with expected value!", VALUE, cache.get(FQN, KEY));
127             }
128             catch (AssertionFailedError e)
129             {
130                readerError = e;
131             }
132             catch (Throwable JavaDoc t)
133             {
134                t.printStackTrace();
135                readerFailed = true;
136             }
137             finally
138             {
139                System.out.println("reader thread exits");
140                if (tx != null)
141                {
142                   try { tx.commit(); } catch (Exception JavaDoc e) {}
143                }
144                writerCanWrite.release();
145                writerCanRollback.release();
146                readerDone.release();
147             }
148          }
149       }, "READER");
150       readerThread.start();
151
152       // start a writer thread and a transaction
153

154       Thread JavaDoc writerThread = new Thread JavaDoc(new Runnable JavaDoc()
155       {
156          public void run()
157          {
158             try
159             {
160                // wait until the reader thread reads and allows me to start
161
writerCanWrite.attempt(3000);
162
163                Transaction JavaDoc tx2 = startTransaction();
164
165                // change VALUE in a transaction
166
cache.put(FQN, KEY, "this-shouldnt-be-visible");
167
168                // notify the reading thread
169
readerCanRead.release();
170
171                // wait until the reader thread reads and allows me to rollback or until I timeout
172
writerCanRollback.attempt(3000);
173
174                System.out.println("rolling back");
175
176                tx2.rollback();
177             }
178             catch (AssertionFailedError e)
179             {
180                writerError = e;
181             }
182             catch (Throwable JavaDoc t)
183             {
184                t.printStackTrace();
185                writerFailed = true;
186             }
187             finally
188             {
189                System.out.println("writer thread exits");
190                readerCanRead.release();
191                writerDone.release();
192             }
193          }
194       }, "WRITER");
195       writerThread.start();
196
197       // wait for both threads to finish
198
readerDone.acquire();
199       writerDone.acquire();
200
201       // If any assertion failed, throw on the AssertionFailedError
202
if (readerError != null)
203       {
204          throw readerError;
205       }
206
207       if (writerError != null)
208       {
209          throw writerError;
210       }
211
212       if (readerFailed)
213       {
214          fail("The reader thread exited incorrectly. Watch the log for previous stack traces");
215       }
216
217       if (writerFailed)
218       {
219          fail("The writer thread exited incorrectly. Watch the log for previous stack traces");
220       }
221    }
222
223    /**
224     * Test creates a cache node then starts a separate thread that removes
225     * the node inside a tx. Test confirms that the removal cannot be seen
226     * before the test commits.
227     *
228     * @throws Exception
229     */

230    public void testNodeRemoved() throws Exception JavaDoc
231    {
232       final Latch readerCanRead = new Latch();
233       final Latch readerDone = new Latch();
234       final Latch writerDone = new Latch();
235
236       cache.put(FQN, KEY, VALUE);
237       assertEquals(VALUE, cache.get(FQN, KEY));
238
239       // start a writer thread and a transaction
240

241       Thread JavaDoc writerThread = new Thread JavaDoc(new Runnable JavaDoc()
242       {
243          public void run()
244          {
245             try
246             {
247                Transaction JavaDoc tx = startTransaction();
248
249                // change VALUE in a transaction
250
cache.removeNode(PARENT_FQN);
251
252                // notify the reading thread
253
readerCanRead.release();
254
255                readerDone.acquire();
256
257                tx.commit();
258             }
259             catch (AssertionFailedError e)
260             {
261                writerError = e;
262             }
263             catch (Throwable JavaDoc t)
264             {
265                t.printStackTrace();
266                writerFailed = true;
267             }
268             finally
269             {
270                System.out.println("writer thread exits");
271                readerCanRead.release();
272                writerDone.release();
273             }
274          }
275       }, "WRITER");
276       writerThread.start();
277
278       try
279       {
280          // wait until the writer thread changes the value in a transaction,
281
// but it did not yet commit or roll back.
282
readerCanRead.acquire();
283
284          // I shouldn't be able to see the "dirty" value
285
assertEquals("2nd thread cannot see uncommitted changes",
286                  VALUE, cache.get(FQN, KEY));
287       }
288       catch (TimeoutException t)
289       {
290          // ignore, this is good
291
}
292       finally
293       {
294          System.out.println("reader thread exits");
295          readerDone.release();
296       }
297
298       // wait for the writer to finish
299
writerDone.acquire();
300
301       assertNull("Node was removed", ((CacheImpl) cache).get(FQN));
302
303       // If any assertion failed, throw on the AssertionFailedError
304

305       if (writerError != null)
306       {
307          throw writerError;
308       }
309
310       if (writerFailed)
311       {
312          fail("The writer thread exited incorrectly. Watch the log for previous stack traces");
313       }
314
315    }
316
317    private Transaction JavaDoc startTransaction() throws SystemException JavaDoc, NotSupportedException JavaDoc
318    {
319       DummyTransactionManager mgr = DummyTransactionManager.getInstance();
320       mgr.begin();
321       return mgr.getTransaction();
322    }
323
324
325    public static Test suite()
326    {
327
328       return new TestSuite(IsolationLevelReadCommittedTest.class);
329
330    }
331
332 }
333
334
Popular Tags