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

TransactionTest.java

00001 /*-
00002  * See the file LICENSE for redistribution information.
00003  *
00004  * Copyright (c) 2002-2005
00005  *      Sleepycat Software.  All rights reserved.
00006  *
00007  * $Id: TransactionTest.java,v 12.3 2005/02/11 23:17:00 mark Exp $
00008  */
00009 
00010 package com.sleepycat.collections.test;
00011 
00012 import java.util.Iterator;
00013 import java.util.List;
00014 import java.util.SortedSet;
00015 
00016 import junit.framework.Test;
00017 import junit.framework.TestCase;
00018 import junit.framework.TestSuite;
00019 
00020 import com.sleepycat.collections.CurrentTransaction;
00021 import com.sleepycat.collections.StoredCollections;
00022 import com.sleepycat.collections.StoredContainer;
00023 import com.sleepycat.collections.StoredIterator;
00024 import com.sleepycat.collections.StoredList;
00025 import com.sleepycat.collections.StoredSortedMap;
00026 import com.sleepycat.collections.TransactionRunner;
00027 import com.sleepycat.collections.TransactionWorker;
00028 import com.sleepycat.compat.DbCompat;
00029 import com.sleepycat.db.CursorConfig;
00030 import com.sleepycat.db.Database;
00031 import com.sleepycat.db.DatabaseConfig;
00032 import com.sleepycat.db.DatabaseEntry;
00033 import com.sleepycat.db.Environment;
00034 import com.sleepycat.db.Transaction;
00035 import com.sleepycat.db.TransactionConfig;
00036 import com.sleepycat.util.RuntimeExceptionWrapper;
00037 
00041 public class TransactionTest extends TestCase {
00042 
00043     private static final Long ONE = new Long(1);
00044     private static final Long TWO = new Long(2);
00045     private static final Long THREE = new Long(3);
00046 
00051     public static void main(String[] args)
00052         throws Exception {
00053 
00054         if (args.length == 1 &&
00055             (args[0].equals("-h") || args[0].equals("-help"))) {
00056             usage();
00057         } else {
00058             junit.framework.TestResult tr =
00059                 junit.textui.TestRunner.run(suite());
00060             if (tr.errorCount() > 0 ||
00061                 tr.failureCount() > 0) {
00062                 System.exit(1);
00063             } else {
00064                 System.exit(0);
00065             }
00066         }
00067     }
00068 
00069     private static void usage() {
00070 
00071         System.out.println(
00072               "Usage: java com.sleepycat.collections.test.TransactionTest"
00073             + " [-h | -help]\n");
00074         System.exit(2);
00075     }
00076 
00077     public static Test suite()
00078         throws Exception {
00079 
00080         TestSuite suite = new TestSuite(TransactionTest.class);
00081         return suite;
00082     }
00083 
00084     private Environment env;
00085     private CurrentTransaction currentTxn;
00086     private Database store;
00087     private StoredSortedMap map;
00088     private TestStore testStore = TestStore.BTREE_UNIQ;
00089 
00090     public TransactionTest(String name) {
00091 
00092         super(name);
00093     }
00094 
00095     public void setUp()
00096         throws Exception {
00097 
00098         DbTestUtil.printTestName(DbTestUtil.qualifiedTestName(this));
00099         env = TestEnv.TXN.open("TransactionTests");
00100         currentTxn = CurrentTransaction.getInstance(env);
00101         store = testStore.open(env, dbName(0));
00102         map = new StoredSortedMap(store, testStore.getKeyBinding(),
00103                                   testStore.getValueBinding(), true);
00104     }
00105 
00106     public void tearDown() {
00107 
00108         try {
00109             if (store != null) {
00110                 store.close();
00111             }
00112             if (env != null) {
00113                 env.close();
00114             }
00115         } catch (Exception e) {
00116             System.out.println("Ignored exception during tearDown: " + e);
00117         } finally {
00118             /* Ensure that GC can cleanup. */
00119             store = null;
00120             env = null;
00121             currentTxn = null;
00122             map = null;
00123             testStore = null;
00124         }
00125     }
00126 
00127     private String dbName(int i) {
00128 
00129         return "txn-test-" + getName() + '-' + i;
00130     }
00131 
00132     public void testGetters()
00133         throws Exception {
00134 
00135         assertNotNull(env);
00136         assertNotNull(currentTxn);
00137         assertNull(currentTxn.getTransaction());
00138 
00139         currentTxn.beginTransaction(null);
00140         assertNotNull(currentTxn.getTransaction());
00141         currentTxn.commitTransaction();
00142         assertNull(currentTxn.getTransaction());
00143 
00144         currentTxn.beginTransaction(null);
00145         assertNotNull(currentTxn.getTransaction());
00146         currentTxn.abortTransaction();
00147         assertNull(currentTxn.getTransaction());
00148 
00149         // read-uncommitted property should be inherited
00150 
00151         assertTrue(!isReadUncommitted(map));
00152         assertTrue(!isReadUncommitted(map.values()));
00153         assertTrue(!isReadUncommitted(map.keySet()));
00154         assertTrue(!isReadUncommitted(map.entrySet()));
00155 
00156         StoredSortedMap other = (StoredSortedMap)
00157             StoredCollections.configuredMap
00158                 (map, CursorConfig.READ_UNCOMMITTED);
00159         assertTrue(isReadUncommitted(other));
00160         assertTrue(isReadUncommitted(other.values()));
00161         assertTrue(isReadUncommitted(other.keySet()));
00162         assertTrue(isReadUncommitted(other.entrySet()));
00163         assertTrue(!isReadUncommitted(map));
00164         assertTrue(!isReadUncommitted(map.values()));
00165         assertTrue(!isReadUncommitted(map.keySet()));
00166         assertTrue(!isReadUncommitted(map.entrySet()));
00167 
00168         // read-committed property should be inherited
00169 
00170         assertTrue(!isReadCommitted(map));
00171         assertTrue(!isReadCommitted(map.values()));
00172         assertTrue(!isReadCommitted(map.keySet()));
00173         assertTrue(!isReadCommitted(map.entrySet()));
00174 
00175         other = (StoredSortedMap)
00176             StoredCollections.configuredMap
00177                 (map, CursorConfig.READ_COMMITTED);
00178         assertTrue(isReadCommitted(other));
00179         assertTrue(isReadCommitted(other.values()));
00180         assertTrue(isReadCommitted(other.keySet()));
00181         assertTrue(isReadCommitted(other.entrySet()));
00182         assertTrue(!isReadCommitted(map));
00183         assertTrue(!isReadCommitted(map.values()));
00184         assertTrue(!isReadCommitted(map.keySet()));
00185         assertTrue(!isReadCommitted(map.entrySet()));
00186     }
00187 
00188     public void testTransactional()
00189         throws Exception {
00190 
00191         // is transactional because DB_AUTO_COMMIT was passed to
00192         // Database.open()
00193         //
00194         assertTrue(map.isTransactional());
00195         store.close();
00196         store = null;
00197 
00198         // is not transactional
00199         //
00200         DatabaseConfig dbConfig = new DatabaseConfig();
00201         DbCompat.setTypeBtree(dbConfig);
00202         dbConfig.setAllowCreate(true);
00203         Database db = DbCompat.openDatabase(env, null, 
00204                                             dbName(1), null,
00205                                             dbConfig);
00206         map = new StoredSortedMap(db, testStore.getKeyBinding(),
00207                                       testStore.getValueBinding(), true);
00208         assertTrue(!map.isTransactional());
00209         map.put(ONE, ONE);
00210         readCheck(map, ONE, ONE);
00211         db.close();
00212 
00213         // is transactional
00214         //
00215         dbConfig.setTransactional(true);
00216         currentTxn.beginTransaction(null);
00217         db = DbCompat.openDatabase(env, currentTxn.getTransaction(), 
00218                                    dbName(2), null, dbConfig);
00219         currentTxn.commitTransaction();
00220         map = new StoredSortedMap(db, testStore.getKeyBinding(),
00221                                       testStore.getValueBinding(), true);
00222         assertTrue(map.isTransactional());
00223         currentTxn.beginTransaction(null);
00224         map.put(ONE, ONE);
00225         readCheck(map, ONE, ONE);
00226         currentTxn.commitTransaction();
00227         db.close();
00228     }
00229 
00230     public void testExceptions()
00231         throws Exception {
00232 
00233         try {
00234             currentTxn.commitTransaction();
00235             fail();
00236         } catch (IllegalStateException expected) {}
00237 
00238         try {
00239             currentTxn.abortTransaction();
00240             fail();
00241         } catch (IllegalStateException expected) {}
00242     }
00243 
00244     public void testNested()
00245         throws Exception {
00246 
00247         if (!DbCompat.NESTED_TRANSACTIONS) {
00248             return;
00249         }
00250         assertNull(currentTxn.getTransaction());
00251 
00252         Transaction txn1 = currentTxn.beginTransaction(null);
00253         assertNotNull(txn1);
00254         assertTrue(txn1 == currentTxn.getTransaction());
00255 
00256         assertNull(map.get(ONE));
00257         assertNull(map.put(ONE, ONE));
00258         assertEquals(ONE, map.get(ONE));
00259 
00260         Transaction txn2 = currentTxn.beginTransaction(null);
00261         assertNotNull(txn2);
00262         assertTrue(txn2 == currentTxn.getTransaction());
00263         assertTrue(txn1 != txn2);
00264 
00265         assertNull(map.put(TWO, TWO));
00266         assertEquals(TWO, map.get(TWO));
00267 
00268         Transaction txn3 = currentTxn.beginTransaction(null);
00269         assertNotNull(txn3);
00270         assertTrue(txn3 == currentTxn.getTransaction());
00271         assertTrue(txn1 != txn2);
00272         assertTrue(txn1 != txn3);
00273         assertTrue(txn2 != txn3);
00274 
00275         assertNull(map.put(THREE, THREE));
00276         assertEquals(THREE, map.get(THREE));
00277 
00278         Transaction txn = currentTxn.abortTransaction();
00279         assertTrue(txn == txn2);
00280         assertTrue(txn == currentTxn.getTransaction());
00281         assertNull(map.get(THREE));
00282         assertEquals(TWO, map.get(TWO));
00283 
00284         txn3 = currentTxn.beginTransaction(null);
00285         assertNotNull(txn3);
00286         assertTrue(txn3 == currentTxn.getTransaction());
00287         assertTrue(txn1 != txn2);
00288         assertTrue(txn1 != txn3);
00289         assertTrue(txn2 != txn3);
00290 
00291         assertNull(map.put(THREE, THREE));
00292         assertEquals(THREE, map.get(THREE));
00293 
00294         txn = currentTxn.commitTransaction();
00295         assertTrue(txn == txn2);
00296         assertTrue(txn == currentTxn.getTransaction());
00297         assertEquals(THREE, map.get(THREE));
00298         assertEquals(TWO, map.get(TWO));
00299 
00300         txn = currentTxn.commitTransaction();
00301         assertTrue(txn == txn1);
00302         assertTrue(txn == currentTxn.getTransaction());
00303         assertEquals(THREE, map.get(THREE));
00304         assertEquals(TWO, map.get(TWO));
00305         assertEquals(ONE, map.get(ONE));
00306 
00307         txn = currentTxn.commitTransaction();
00308         assertNull(txn);
00309         assertNull(currentTxn.getTransaction());
00310         assertEquals(THREE, map.get(THREE));
00311         assertEquals(TWO, map.get(TWO));
00312         assertEquals(ONE, map.get(ONE));
00313     }
00314 
00315     public void testRunnerCommit()
00316         throws Exception {
00317 
00318         commitTest(false);
00319     }
00320 
00321     public void testExplicitCommit()
00322         throws Exception {
00323 
00324         commitTest(true);
00325     }
00326 
00327     private void commitTest(final boolean explicit)
00328         throws Exception {
00329 
00330         final TransactionRunner runner = new TransactionRunner(env);
00331         runner.setAllowNestedTransactions(DbCompat.NESTED_TRANSACTIONS);
00332 
00333         assertNull(currentTxn.getTransaction());
00334 
00335         runner.run(new TransactionWorker() {
00336             public void doWork() throws Exception {
00337                 final Transaction txn1 = currentTxn.getTransaction();
00338                 assertNotNull(txn1);
00339                 assertNull(map.put(ONE, ONE));
00340                 assertEquals(ONE, map.get(ONE));
00341 
00342                 runner.run(new TransactionWorker() {
00343                     public void doWork() throws Exception {
00344                         final Transaction txn2 = currentTxn.getTransaction();
00345                         assertNotNull(txn2);
00346                         if (DbCompat.NESTED_TRANSACTIONS) {
00347                             assertTrue(txn1 != txn2);
00348                         } else {
00349                             assertTrue(txn1 == txn2);
00350                         }
00351                         assertNull(map.put(TWO, TWO));
00352                         assertEquals(TWO, map.get(TWO));
00353                         assertEquals(ONE, map.get(ONE));
00354                         if (DbCompat.NESTED_TRANSACTIONS && explicit) {
00355                             currentTxn.commitTransaction();
00356                         }
00357                     }
00358                 });
00359 
00360                 Transaction txn3 = currentTxn.getTransaction();
00361                 assertSame(txn1, txn3);
00362 
00363                 assertEquals(TWO, map.get(TWO));
00364                 assertEquals(ONE, map.get(ONE));
00365             }
00366         });
00367 
00368         assertNull(currentTxn.getTransaction());
00369     }
00370 
00371     public void testRunnerAbort()
00372         throws Exception {
00373 
00374         abortTest(false);
00375     }
00376 
00377     public void testExplicitAbort()
00378         throws Exception {
00379 
00380         abortTest(true);
00381     }
00382 
00383     private void abortTest(final boolean explicit)
00384         throws Exception {
00385 
00386         final TransactionRunner runner = new TransactionRunner(env);
00387         runner.setAllowNestedTransactions(DbCompat.NESTED_TRANSACTIONS);
00388 
00389         assertNull(currentTxn.getTransaction());
00390 
00391         runner.run(new TransactionWorker() {
00392             public void doWork() throws Exception {
00393                 final Transaction txn1 = currentTxn.getTransaction();
00394                 assertNotNull(txn1);
00395                 assertNull(map.put(ONE, ONE));
00396                 assertEquals(ONE, map.get(ONE));
00397 
00398                 if (DbCompat.NESTED_TRANSACTIONS) {
00399                     try {
00400                         runner.run(new TransactionWorker() {
00401                             public void doWork() throws Exception {
00402                                 final Transaction txn2 =
00403                                         currentTxn.getTransaction();
00404                                 assertNotNull(txn2);
00405                                 assertTrue(txn1 != txn2);
00406                                 assertNull(map.put(TWO, TWO));
00407                                 assertEquals(TWO, map.get(TWO));
00408                                 if (explicit) {
00409                                     currentTxn.abortTransaction();
00410                                 } else {
00411                                     throw new IllegalArgumentException(
00412                                                                 "test-abort");
00413                                 }
00414                             }
00415                         });
00416                         assertTrue(explicit);
00417                     } catch (IllegalArgumentException e) {
00418                         assertTrue(!explicit);
00419                         assertEquals("test-abort", e.getMessage());
00420                     }
00421                 }
00422 
00423                 Transaction txn3 = currentTxn.getTransaction();
00424                 assertSame(txn1, txn3);
00425 
00426                 assertEquals(ONE, map.get(ONE));
00427                 assertNull(map.get(TWO));
00428             }
00429         });
00430 
00431         assertNull(currentTxn.getTransaction());
00432     }
00433 
00434     public void testReadCommittedCollection()
00435         throws Exception {
00436 
00437         StoredSortedMap degree2Map = (StoredSortedMap)
00438             StoredCollections.configuredSortedMap
00439                 (map, CursorConfig.READ_COMMITTED);
00440 
00441         // original map is not read-committed
00442         assertTrue(!isReadCommitted(map));
00443 
00444         // all read-committed containers are read-uncommitted
00445         assertTrue(isReadCommitted(degree2Map));
00446         assertTrue(isReadCommitted
00447             (StoredCollections.configuredMap
00448                 (map, CursorConfig.READ_COMMITTED)));
00449         assertTrue(isReadCommitted
00450             (StoredCollections.configuredCollection
00451                 (map.values(), CursorConfig.READ_COMMITTED)));
00452         assertTrue(isReadCommitted
00453             (StoredCollections.configuredSet
00454                 (map.keySet(), CursorConfig.READ_COMMITTED)));
00455         assertTrue(isReadCommitted
00456             (StoredCollections.configuredSortedSet
00457                 ((SortedSet) map.keySet(),
00458                  CursorConfig.READ_COMMITTED)));
00459 
00460         if (DbCompat.RECNO_METHOD) {
00461             // create a list just so we can call configuredList()
00462             Database listStore = TestStore.RECNO_RENUM.open(env, null);
00463             List list = new StoredList(listStore, TestStore.VALUE_BINDING,
00464                                        true);
00465             assertTrue(isReadCommitted
00466                 (StoredCollections.configuredList
00467                     (list, CursorConfig.READ_COMMITTED)));
00468             listStore.close();
00469         }
00470 
00471         map.put(ONE, ONE);
00472         doReadCommitted(degree2Map, null);
00473     }
00474 
00475     private static boolean isReadCommitted(Object container) {
00476         StoredContainer storedContainer = (StoredContainer) container;
00477         /* We can't use getReadCommitted until is is added to DB core. */
00478         return storedContainer.getCursorConfig() != null &&
00479                storedContainer.getCursorConfig().getReadCommitted();
00480     }
00481 
00482     public void testReadCommittedTransaction()
00483         throws Exception {
00484 
00485         TransactionConfig config = new TransactionConfig();
00486         config.setReadCommitted(true);
00487         doReadCommitted(map, config);
00488     }
00489 
00490     private void doReadCommitted(final StoredSortedMap degree2Map,
00491                                  TransactionConfig txnConfig)
00492         throws Exception {
00493 
00494         map.put(ONE, ONE);
00495         TransactionRunner runner = new TransactionRunner(env);
00496         runner.setTransactionConfig(txnConfig);
00497         assertNull(currentTxn.getTransaction());
00498         runner.run(new TransactionWorker() {
00499             public void doWork() throws Exception {
00500                 assertNotNull(currentTxn.getTransaction());
00501 
00502                 /* Do a read-committed get(), the lock is not retained. */
00503                 assertEquals(ONE, degree2Map.get(ONE));
00504 
00505                 /*
00506                  * If we were not using read-committed, the following write of
00507                  * key ONE with an auto-commit transaction would self-deadlock
00508                  * since two transactions in the same thread would be
00509                  * attempting to lock the same key, one for write and one for
00510                  * read.  This test passes if we do not deadlock.
00511                  */
00512                 DatabaseEntry key = new DatabaseEntry();
00513                 DatabaseEntry value = new DatabaseEntry();
00514                 testStore.getKeyBinding().objectToEntry(ONE, key);
00515                 testStore.getValueBinding().objectToEntry(TWO, value);
00516                 store.put(null, key, value);
00517             }
00518         });
00519         assertNull(currentTxn.getTransaction());
00520     }
00521 
00522     public void testReadUncommittedCollection()
00523         throws Exception {
00524 
00525         StoredSortedMap dirtyMap = (StoredSortedMap)
00526             StoredCollections.configuredSortedMap
00527                 (map, CursorConfig.READ_UNCOMMITTED);
00528 
00529         // original map is not read-uncommitted
00530         assertTrue(!isReadUncommitted(map));
00531 
00532         // all read-uncommitted containers are read-uncommitted
00533         assertTrue(isReadUncommitted(dirtyMap));
00534         assertTrue(isReadUncommitted
00535             (StoredCollections.configuredMap
00536                 (map, CursorConfig.READ_UNCOMMITTED)));
00537         assertTrue(isReadUncommitted
00538             (StoredCollections.configuredCollection
00539                 (map.values(), CursorConfig.READ_UNCOMMITTED)));
00540         assertTrue(isReadUncommitted
00541             (StoredCollections.configuredSet
00542                 (map.keySet(), CursorConfig.READ_UNCOMMITTED)));
00543         assertTrue(isReadUncommitted
00544             (StoredCollections.configuredSortedSet
00545                 ((SortedSet) map.keySet(), CursorConfig.READ_UNCOMMITTED)));
00546 
00547         if (DbCompat.RECNO_METHOD) {
00548             // create a list just so we can call configuredList()
00549             Database listStore = TestStore.RECNO_RENUM.open(env, null);
00550             List list = new StoredList(listStore, TestStore.VALUE_BINDING,
00551                                        true);
00552             assertTrue(isReadUncommitted
00553                 (StoredCollections.configuredList
00554                     (list, CursorConfig.READ_UNCOMMITTED)));
00555             listStore.close();
00556         }
00557 
00558         doReadUncommitted(dirtyMap);
00559     }
00560 
00561     private static boolean isReadUncommitted(Object container) {
00562         StoredContainer storedContainer = (StoredContainer) container;
00563         return storedContainer.getCursorConfig() != null &&
00564                storedContainer.getCursorConfig().getReadUncommitted();
00565     }
00566 
00567     public void testReadUncommittedTransaction()
00568         throws Exception {
00569 
00570         TransactionRunner runner = new TransactionRunner(env);
00571         TransactionConfig config = new TransactionConfig();
00572         config.setReadUncommitted(true);
00573         runner.setTransactionConfig(config);
00574         assertNull(currentTxn.getTransaction());
00575         runner.run(new TransactionWorker() {
00576             public void doWork() throws Exception {
00577                 assertNotNull(currentTxn.getTransaction());
00578                 doReadUncommitted(map);
00579             }
00580         });
00581         assertNull(currentTxn.getTransaction());
00582     }
00583 
00584     private synchronized void doReadUncommitted(StoredSortedMap dirtyMap)
00585         throws Exception {
00586 
00587         // start thread one
00588         ReadUncommittedThreadOne t1 = new ReadUncommittedThreadOne(env, this);
00589         t1.start();
00590         wait();
00591 
00592         // put ONE
00593         synchronized (t1) { t1.notify(); }
00594         wait();
00595         readCheck(dirtyMap, ONE, ONE);
00596         assertTrue(!dirtyMap.isEmpty());
00597 
00598         // abort ONE
00599         synchronized (t1) { t1.notify(); }
00600         t1.join();
00601         readCheck(dirtyMap, ONE, null);
00602         assertTrue(dirtyMap.isEmpty());
00603 
00604         // start thread two
00605         ReadUncommittedThreadTwo t2 = new ReadUncommittedThreadTwo(env, this);
00606         t2.start();
00607         wait();
00608 
00609         // put TWO
00610         synchronized (t2) { t2.notify(); }
00611         wait();
00612         readCheck(dirtyMap, TWO, TWO);
00613         assertTrue(!dirtyMap.isEmpty());
00614 
00615         // commit TWO
00616         synchronized (t2) { t2.notify(); }
00617         t2.join();
00618         readCheck(dirtyMap, TWO, TWO);
00619         assertTrue(!dirtyMap.isEmpty());
00620     }
00621 
00622     private static class ReadUncommittedThreadOne extends Thread {
00623 
00624         private Environment env;
00625         private CurrentTransaction currentTxn;
00626         private TransactionTest parent;
00627         private StoredSortedMap map;
00628 
00629         private ReadUncommittedThreadOne(Environment env,
00630                                          TransactionTest parent) {
00631 
00632             this.env = env;
00633             this.currentTxn = CurrentTransaction.getInstance(env);
00634             this.parent = parent;
00635             this.map = parent.map;
00636         }
00637 
00638         public synchronized void run() {
00639 
00640             try {
00641                 assertNull(currentTxn.getTransaction());
00642                 assertNotNull(currentTxn.beginTransaction(null));
00643                 assertNotNull(currentTxn.getTransaction());
00644                 readCheck(map, ONE, null);
00645                 synchronized (parent) { parent.notify(); }
00646                 wait();
00647 
00648                 // put ONE
00649                 assertNull(map.put(ONE, ONE));
00650                 readCheck(map, ONE, ONE);
00651                 synchronized (parent) { parent.notify(); }
00652                 wait();
00653 
00654                 // abort ONE
00655                 assertNull(currentTxn.abortTransaction());
00656                 assertNull(currentTxn.getTransaction());
00657             } catch (Exception e) {
00658                 throw new RuntimeExceptionWrapper(e);
00659             }
00660         }
00661     }
00662 
00663     private static class ReadUncommittedThreadTwo extends Thread {
00664 
00665         private Environment env;
00666         private CurrentTransaction currentTxn;
00667         private TransactionTest parent;
00668         private StoredSortedMap map;
00669 
00670         private ReadUncommittedThreadTwo(Environment env,
00671                                          TransactionTest parent) {
00672 
00673             this.env = env;
00674             this.currentTxn = CurrentTransaction.getInstance(env);
00675             this.parent = parent;
00676             this.map = parent.map;
00677         }
00678 
00679         public synchronized void run() {
00680 
00681             try {
00682                 final TransactionRunner runner = new TransactionRunner(env);
00683                 final Object thread = this;
00684                 assertNull(currentTxn.getTransaction());
00685 
00686                 runner.run(new TransactionWorker() {
00687                     public void doWork() throws Exception {
00688                         assertNotNull(currentTxn.getTransaction());
00689                         readCheck(map, TWO, null);
00690                         synchronized (parent) { parent.notify(); }
00691                         thread.wait();
00692 
00693                         // put TWO
00694                         assertNull(map.put(TWO, TWO));
00695                         readCheck(map, TWO, TWO);
00696                         synchronized (parent) { parent.notify(); }
00697                         thread.wait();
00698 
00699                         // commit TWO
00700                     }
00701                 });
00702                 assertNull(currentTxn.getTransaction());
00703             } catch (Exception e) {
00704                 throw new RuntimeExceptionWrapper(e);
00705             }
00706         }
00707     }
00708 
00709     private static void readCheck(StoredSortedMap checkMap, Object key,
00710                                   Object expect) {
00711         if (expect == null) {
00712             assertNull(checkMap.get(key));
00713             assertTrue(checkMap.tailMap(key).isEmpty());
00714             assertTrue(!checkMap.tailMap(key).containsKey(key));
00715             assertTrue(!checkMap.keySet().contains(key));
00716             assertTrue(checkMap.duplicates(key).isEmpty());
00717             Iterator i = checkMap.keySet().iterator();
00718             try {
00719                 while (i.hasNext()) {
00720                     assertTrue(!key.equals(i.next()));
00721                 }
00722             } finally { StoredIterator.close(i); }
00723         } else {
00724             assertEquals(expect, checkMap.get(key));
00725             assertEquals(expect, checkMap.tailMap(key).get(key));
00726             assertTrue(!checkMap.tailMap(key).isEmpty());
00727             assertTrue(checkMap.tailMap(key).containsKey(key));
00728             assertTrue(checkMap.keySet().contains(key));
00729             assertTrue(checkMap.values().contains(expect));
00730             assertTrue(!checkMap.duplicates(key).isEmpty());
00731             assertTrue(checkMap.duplicates(key).contains(expect));
00732             Iterator i = checkMap.keySet().iterator();
00733             try {
00734                 boolean found = false;
00735                 while (i.hasNext()) {
00736                     if (expect.equals(i.next())) {
00737                         found = true;
00738                     }
00739                 }
00740                 assertTrue(found);
00741             }
00742             finally { StoredIterator.close(i); }
00743         }
00744     }
00745 }

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