KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > com > sleepycat > collections > test > SecondaryDeadlockTest


1 /*-
2  * See the file LICENSE for redistribution information.
3  *
4  * Copyright (c) 2002,2006 Oracle. All rights reserved.
5  *
6  * $Id: SecondaryDeadlockTest.java,v 1.10 2006/10/30 21:14:39 bostic Exp $
7  */

8
9 package com.sleepycat.collections.test;
10
11 import com.sleepycat.je.Database;
12 import com.sleepycat.je.DeadlockException;
13 import com.sleepycat.je.Environment;
14 import com.sleepycat.je.TransactionConfig;
15 import com.sleepycat.collections.StoredSortedMap;
16 import com.sleepycat.collections.TransactionRunner;
17 import com.sleepycat.collections.TransactionWorker;
18 import com.sleepycat.util.ExceptionUnwrapper;
19 import junit.framework.Test;
20 import junit.framework.TestCase;
21 import junit.framework.TestSuite;
22
23 /**
24  * Tests whether secondary access can cause a self-deadlock when reading via a
25  * secondary because the collections API secondary implementation in DB 4.2
26  * opens two cursors. Part of the problem in [#10516] was because the
27  * secondary get() was not done in a txn. This problem should not occur in DB
28  * 4.3 and JE -- an ordinary deadlock occurs instead and is detected.
29  *
30  * @author Mark Hayes
31  */

32 public class SecondaryDeadlockTest extends TestCase {
33
34     private static final Long JavaDoc N_ONE = new Long JavaDoc(1);
35     private static final Long JavaDoc N_101 = new Long JavaDoc(101);
36     private static final int N_ITERS = 20;
37     private static final int MAX_RETRIES = 1000;
38
39     public static void main(String JavaDoc[] args)
40         throws Exception JavaDoc {
41
42         junit.framework.TestResult tr =
43             junit.textui.TestRunner.run(suite());
44         if (tr.errorCount() > 0 ||
45             tr.failureCount() > 0) {
46             System.exit(1);
47         } else {
48             System.exit(0);
49         }
50     }
51
52     public static Test suite()
53         throws Exception JavaDoc {
54
55         TestSuite suite = new TestSuite(SecondaryDeadlockTest.class);
56         return suite;
57     }
58
59     private Environment env;
60     private Database store;
61     private Database index;
62     private StoredSortedMap storeMap;
63     private StoredSortedMap indexMap;
64     private Exception JavaDoc exception;
65
66     public SecondaryDeadlockTest(String JavaDoc name) {
67
68         super(name);
69     }
70
71     public void setUp()
72         throws Exception JavaDoc {
73
74         env = TestEnv.TXN.open("SecondaryDeadlockTest");
75         store = TestStore.BTREE_UNIQ.open(env, "store.db");
76         index = TestStore.BTREE_UNIQ.openIndex(store, "index.db");
77         storeMap = new StoredSortedMap(store,
78                                        TestStore.BTREE_UNIQ.getKeyBinding(),
79                                        TestStore.BTREE_UNIQ.getValueBinding(),
80                                        true);
81         indexMap = new StoredSortedMap(index,
82                                        TestStore.BTREE_UNIQ.getKeyBinding(),
83                                        TestStore.BTREE_UNIQ.getValueBinding(),
84                                        true);
85     }
86
87     public void tearDown() {
88
89         if (index != null) {
90             try {
91                 index.close();
92             } catch (Exception JavaDoc e) {
93                 System.out.println("Ignored exception during tearDown: " + e);
94             }
95         }
96         if (store != null) {
97             try {
98                 store.close();
99             } catch (Exception JavaDoc e) {
100                 System.out.println("Ignored exception during tearDown: " + e);
101             }
102         }
103         if (env != null) {
104             try {
105                 env.close();
106             } catch (Exception JavaDoc e) {
107                 System.out.println("Ignored exception during tearDown: " + e);
108             }
109         }
110         /* Allow GC of DB objects in the test case. */
111         env = null;
112         store = null;
113         index = null;
114         storeMap = null;
115         indexMap = null;
116     }
117
118     public void testSecondaryDeadlock()
119         throws Exception JavaDoc {
120
121         final TransactionRunner runner = new TransactionRunner(env);
122         runner.setMaxRetries(MAX_RETRIES);
123
124         /*
125          * This test deadlocks a lot at degree 3 serialization. In debugging
126          * this I discovered it was not due to phantom prevention per se but
127          * just to a change in timing.
128          */

129         TransactionConfig txnConfig = new TransactionConfig();
130         runner.setTransactionConfig(txnConfig);
131
132         /*
133          * A thread to do put() and delete() via the primary, which will lock
134          * the primary first then the secondary. Uses transactions.
135          */

136         final Thread JavaDoc thread1 = new Thread JavaDoc(new Runnable JavaDoc() {
137             public void run() {
138                 try {
139                     /* The TransactionRunner performs retries. */
140                     for (int i = 0; i < N_ITERS; i +=1 ) {
141                         runner.run(new TransactionWorker() {
142                             public void doWork() throws Exception JavaDoc {
143                                 assertEquals(null, storeMap.put(N_ONE, N_101));
144                             }
145                         });
146                         runner.run(new TransactionWorker() {
147                             public void doWork() throws Exception JavaDoc {
148                                 assertEquals(N_101, storeMap.remove(N_ONE));
149                             }
150                         });
151                     }
152                 } catch (Exception JavaDoc e) {
153                     e.printStackTrace();
154                     exception = e;
155                 }
156             }
157         }, "ThreadOne");
158
159         /*
160          * A thread to get() via the secondary, which will lock the secondary
161          * first then the primary. Does not use a transaction.
162          */

163         final Thread JavaDoc thread2 = new Thread JavaDoc(new Runnable JavaDoc() {
164             public void run() {
165                 try {
166                     for (int i = 0; i < N_ITERS; i +=1 ) {
167                         for (int j = 0; j < MAX_RETRIES; j += 1) {
168                             try {
169                                 Object JavaDoc value = indexMap.get(N_ONE);
170                                 assertTrue(value == null ||
171                                            N_101.equals(value));
172                                 break;
173                             } catch (Exception JavaDoc e) {
174                                 e = ExceptionUnwrapper.unwrap(e);
175                                 if (e instanceof DeadlockException) {
176                                     continue; /* Retry on deadlock. */
177                                 } else {
178                                     throw e;
179                                 }
180                             }
181                         }
182                     }
183                 } catch (Exception JavaDoc e) {
184                     e.printStackTrace();
185                     exception = e;
186                 }
187             }
188         }, "ThreadTwo");
189
190         thread1.start();
191         thread2.start();
192         thread1.join();
193         thread2.join();
194
195         index.close();
196         index = null;
197         store.close();
198         store = null;
199         env.close();
200         env = null;
201
202         if (exception != null) {
203             fail(exception.toString());
204         }
205     }
206 }
207
Popular Tags