00001
00002
00003
00004
00005
00006
00007
00008
00009
00010 package com.sleepycat.collections.test;
00011
00012 import com.sleepycat.compat.DbCompat;
00013 import com.sleepycat.db.Database;
00014 import com.sleepycat.db.DatabaseConfig;
00015 import com.sleepycat.db.DeadlockException;
00016 import com.sleepycat.db.Environment;
00017 import com.sleepycat.bind.ByteArrayBinding;
00018 import com.sleepycat.collections.CurrentTransaction;
00019 import com.sleepycat.collections.TransactionRunner;
00020 import com.sleepycat.collections.TransactionWorker;
00021 import com.sleepycat.collections.StoredIterator;
00022 import com.sleepycat.collections.StoredSortedMap;
00023 import java.util.Iterator;
00024 import java.util.ListIterator;
00025 import junit.framework.Test;
00026 import junit.framework.TestCase;
00027 import junit.framework.TestSuite;
00028
00036 public class IterDeadlockTest extends TestCase {
00037
00038 private static final byte[] ONE = { 1 };
00039
00040 public static void main(String[] args)
00041 throws Exception {
00042
00043 junit.framework.TestResult tr =
00044 junit.textui.TestRunner.run(suite());
00045 if (tr.errorCount() > 0 ||
00046 tr.failureCount() > 0) {
00047 System.exit(1);
00048 } else {
00049 System.exit(0);
00050 }
00051 }
00052
00053 public static Test suite()
00054 throws Exception {
00055
00056 TestSuite suite = new TestSuite(IterDeadlockTest.class);
00057 return suite;
00058 }
00059
00060 private Environment env;
00061 private CurrentTransaction currentTxn;
00062 private Database store1;
00063 private Database store2;
00064 private StoredSortedMap map1;
00065 private StoredSortedMap map2;
00066 private ByteArrayBinding binding = new ByteArrayBinding();
00067
00068 public IterDeadlockTest(String name) {
00069
00070 super(name);
00071 }
00072
00073 public void setUp()
00074 throws Exception {
00075
00076 env = TestEnv.TXN.open("IterDeadlockTest");
00077 currentTxn = CurrentTransaction.getInstance(env);
00078 store1 = openDb("store1.db");
00079 store2 = openDb("store2.db");
00080 map1 = new StoredSortedMap(store1, binding, binding, true);
00081 map2 = new StoredSortedMap(store2, binding, binding, true);
00082 }
00083
00084 public void tearDown() {
00085
00086 if (store1 != null) {
00087 try {
00088 store1.close();
00089 } catch (Exception e) {
00090 System.out.println("Ignored exception during tearDown: " + e);
00091 }
00092 }
00093 if (store2 != null) {
00094 try {
00095 store2.close();
00096 } catch (Exception e) {
00097 System.out.println("Ignored exception during tearDown: " + e);
00098 }
00099 }
00100 if (env != null) {
00101 try {
00102 env.close();
00103 } catch (Exception e) {
00104 System.out.println("Ignored exception during tearDown: " + e);
00105 }
00106 }
00107
00108 env = null;
00109 currentTxn = null;
00110 store1 = null;
00111 store2 = null;
00112 map1 = null;
00113 map2 = null;
00114 }
00115
00116 private Database openDb(String file)
00117 throws Exception {
00118
00119 DatabaseConfig config = new DatabaseConfig();
00120 DbCompat.setTypeBtree(config);
00121 config.setTransactional(true);
00122 config.setAllowCreate(true);
00123
00124 return DbCompat.openDatabase(env, null, file, null, config);
00125 }
00126
00127 public void testIterDeadlock()
00128 throws Exception {
00129
00130 final Object parent = new Object();
00131 final Object child1 = new Object();
00132 final Object child2 = new Object();
00133 final TransactionRunner runner = new TransactionRunner(env);
00134 runner.setMaxRetries(0);
00135
00136
00137 runner.run(new TransactionWorker() {
00138 public void doWork() throws Exception {
00139 assertNull(map1.put(ONE, ONE));
00140 assertNull(map2.put(ONE, ONE));
00141 }
00142 });
00143
00144
00145
00146
00147
00148 final Thread thread1 = new Thread(new Runnable() {
00149 public void run() {
00150 try {
00151 runner.run(new TransactionWorker() {
00152 public void doWork() throws Exception {
00153 synchronized (child1) {
00154 ListIterator i1 =
00155 (ListIterator) map1.values().iterator();
00156 i1.next();
00157 i1.set(ONE);
00158 StoredIterator.close(i1);
00159 synchronized (parent) { parent.notify(); }
00160 child1.wait();
00161 Iterator i2 = map2.values().iterator();
00162 assertTrue(i2.hasNext());
00163 StoredIterator.close(i2);
00164 }
00165 }
00166 });
00167 } catch (DeadlockException expected) {
00168 } catch (Exception e) {
00169 e.printStackTrace();
00170 fail(e.toString());
00171 }
00172 }
00173 });
00174
00175
00176
00177
00178
00179 final Thread thread2 = new Thread(new Runnable() {
00180 public void run() {
00181 try {
00182 runner.run(new TransactionWorker() {
00183 public void doWork() throws Exception {
00184 synchronized (child2) {
00185 ListIterator i2 =
00186 (ListIterator) map2.values().iterator();
00187 i2.next();
00188 i2.set(ONE);
00189 StoredIterator.close(i2);
00190 synchronized (parent) { parent.notify(); }
00191 child2.wait();
00192 Iterator i1 = map1.values().iterator();
00193 assertTrue(i1.hasNext());
00194 StoredIterator.close(i1);
00195 }
00196 }
00197 });
00198 } catch (DeadlockException expected) {
00199 } catch (Exception e) {
00200 e.printStackTrace();
00201 fail(e.toString());
00202 }
00203 }
00204 });
00205
00206
00207
00208
00209
00210 synchronized (parent) {
00211 thread1.start();
00212 parent.wait();
00213 thread2.start();
00214 parent.wait();
00215 synchronized (child1) { child1.notify(); }
00216 synchronized (child2) { child2.notify(); }
00217 thread1.join();
00218 thread2.join();
00219 }
00220
00221
00222
00223
00224
00225 store1.close();
00226 store1 = null;
00227 store2.close();
00228 store2 = null;
00229 env.close();
00230 env = null;
00231 }
00232 }