Main Page | Class Hierarchy | Data Structures | Directories | File List | Data Fields | Related Pages

IterDeadlockTest.java

00001 /*-
00002  * See the file LICENSE for redistribution information.
00003  *
00004  * Copyright (c) 2002-2003
00005  *      Sleepycat Software.  All rights reserved.
00006  *
00007  * $Id: IterDeadlockTest.java,v 12.2 2005/08/01 20:25:29 mark Exp $
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         /* Allow GC of DB objects in the test case. */
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         /* Write a record in each db. */
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          * A thread to open iterator 1, then wait to be notified, then open
00146          * iterator 2.
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); /* Write lock. */
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          * A thread to open iterator 2, then wait to be notified, then open
00177          * iterator 1.
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); /* Write lock. */
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          * Open iterator 1 in thread 1, then iterator 2 in thread 2, then let
00208          * the threads run to open the other iterators and cause a deadlock.
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          * Before the fix for [#10516] we would get an exception indicating
00223          * that cursors were not closed, when closing the stores below.
00224          */
00225         store1.close();
00226         store1 = null;
00227         store2.close();
00228         store2 = null;
00229         env.close();
00230         env = null;
00231     }
00232 }

Generated on Sun Dec 25 12:14:55 2005 for Berkeley DB 4.4.16 by  doxygen 1.4.2