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

SecondaryDeadlockTest.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: SecondaryDeadlockTest.java,v 12.3 2005/08/01 20:25:30 mark Exp $
00008  */
00009 
00010 package com.sleepycat.collections.test;
00011 
00012 import com.sleepycat.db.Database;
00013 import com.sleepycat.db.DeadlockException;
00014 import com.sleepycat.db.Environment;
00015 import com.sleepycat.db.TransactionConfig;
00016 import com.sleepycat.collections.StoredSortedMap;
00017 import com.sleepycat.collections.TransactionRunner;
00018 import com.sleepycat.collections.TransactionWorker;
00019 import com.sleepycat.util.ExceptionUnwrapper;
00020 import junit.framework.Test;
00021 import junit.framework.TestCase;
00022 import junit.framework.TestSuite;
00023 
00033 public class SecondaryDeadlockTest extends TestCase {
00034 
00035     private static final Long N_ONE = new Long(1);
00036     private static final Long N_101 = new Long(101);
00037     private static final int N_ITERS = 20;
00038     private static final int MAX_RETRIES = 1000;
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(SecondaryDeadlockTest.class);
00057         return suite;
00058     }
00059 
00060     private Environment env;
00061     private Database store;
00062     private Database index;
00063     private StoredSortedMap storeMap;
00064     private StoredSortedMap indexMap;
00065     private Exception exception;
00066 
00067     public SecondaryDeadlockTest(String name) {
00068 
00069         super(name);
00070     }
00071 
00072     public void setUp()
00073         throws Exception {
00074 
00075         env = TestEnv.TXN.open("SecondaryDeadlockTest");
00076         store = TestStore.BTREE_UNIQ.open(env, "store.db");
00077         index = TestStore.BTREE_UNIQ.openIndex(store, "index.db");
00078         storeMap = new StoredSortedMap(store,
00079                                        TestStore.BTREE_UNIQ.getKeyBinding(),
00080                                        TestStore.BTREE_UNIQ.getValueBinding(),
00081                                        true);
00082         indexMap = new StoredSortedMap(index,
00083                                        TestStore.BTREE_UNIQ.getKeyBinding(),
00084                                        TestStore.BTREE_UNIQ.getValueBinding(),
00085                                        true);
00086     }
00087 
00088     public void tearDown() {
00089 
00090         if (index != null) {
00091             try {
00092                 index.close();
00093             } catch (Exception e) {
00094                 System.out.println("Ignored exception during tearDown: " + e);
00095             }
00096         }
00097         if (store != null) {
00098             try {
00099                 store.close();
00100             } catch (Exception e) {
00101                 System.out.println("Ignored exception during tearDown: " + e);
00102             }
00103         }
00104         if (env != null) {
00105             try {
00106                 env.close();
00107             } catch (Exception e) {
00108                 System.out.println("Ignored exception during tearDown: " + e);
00109             }
00110         }
00111         /* Allow GC of DB objects in the test case. */
00112         env = null;
00113         store = null;
00114         index = null;
00115         storeMap = null;
00116         indexMap = null;
00117     }
00118 
00119     public void testSecondaryDeadlock()
00120         throws Exception {
00121 
00122         final TransactionRunner runner = new TransactionRunner(env);
00123         runner.setMaxRetries(MAX_RETRIES);
00124 
00125         /*
00126          * This test deadlocks a lot at degree 3 serialization.  In debugging
00127          * this I discovered it was not due to phantom prevention per se but
00128          * just to a change in timing.
00129          */
00130         TransactionConfig txnConfig = new TransactionConfig();
00131         runner.setTransactionConfig(txnConfig);
00132 
00133         /*
00134          * A thread to do put() and delete() via the primary, which will lock
00135          * the primary first then the secondary.  Uses transactions.
00136          */
00137         final Thread thread1 = new Thread(new Runnable() {
00138             public void run() {
00139                 try {
00140                     /* The TransactionRunner performs retries. */
00141                     for (int i = 0; i < N_ITERS; i +=1 ) {
00142                         runner.run(new TransactionWorker() {
00143                             public void doWork() throws Exception {
00144                                 assertEquals(null, storeMap.put(N_ONE, N_101));
00145                             }
00146                         });
00147                         runner.run(new TransactionWorker() {
00148                             public void doWork() throws Exception {
00149                                 assertEquals(N_101, storeMap.remove(N_ONE));
00150                             }
00151                         });
00152                     }
00153                 } catch (Exception e) {
00154                     e.printStackTrace();
00155                     exception = e;
00156                 }
00157             }
00158         }, "ThreadOne");
00159 
00160         /*
00161          * A thread to get() via the secondary, which will lock the secondary
00162          * first then the primary.  Does not use a transaction.
00163          */
00164         final Thread thread2 = new Thread(new Runnable() {
00165             public void run() {
00166                 try {
00167                     for (int i = 0; i < N_ITERS; i +=1 ) {
00168                         for (int j = 0; j < MAX_RETRIES; j += 1) {
00169                             try {
00170                                 Object value = indexMap.get(N_ONE);
00171                                 assertTrue(value == null ||
00172                                            N_101.equals(value));
00173                                 break;
00174                             } catch (Exception e) {
00175                                 e = ExceptionUnwrapper.unwrap(e);
00176                                 if (e instanceof DeadlockException) {
00177                                     continue; /* Retry on deadlock. */
00178                                 } else {
00179                                     throw e;
00180                                 }
00181                             }
00182                         }
00183                     }
00184                 } catch (Exception e) {
00185                     e.printStackTrace();
00186                     exception = e;
00187                 }
00188             }
00189         }, "ThreadTwo");
00190 
00191         thread1.start();
00192         thread2.start();
00193         thread1.join();
00194         thread2.join();
00195 
00196         index.close();
00197         index = null;
00198         store.close();
00199         store = null;
00200         env.close();
00201         env = null;
00202 
00203         if (exception != null) {
00204             fail(exception.toString());
00205         }
00206     }
00207 }

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