001: /*-
002: * See the file LICENSE for redistribution information.
003: *
004: * Copyright (c) 2002,2008 Oracle. All rights reserved.
005: *
006: * $Id: TxnTimeoutTest.java,v 1.29.2.6 2008/02/21 08:09:03 chao Exp $
007: */
008:
009: package com.sleepycat.je.txn;
010:
011: import java.io.File;
012: import java.io.IOException;
013:
014: import junit.framework.TestCase;
015:
016: import com.sleepycat.je.Database;
017: import com.sleepycat.je.DatabaseConfig;
018: import com.sleepycat.je.DatabaseException;
019: import com.sleepycat.je.DbInternal;
020: import com.sleepycat.je.dbi.EnvironmentImpl;
021: import com.sleepycat.je.DeadlockException;
022: import com.sleepycat.je.Environment;
023: import com.sleepycat.je.EnvironmentConfig;
024: import com.sleepycat.je.LockStats;
025: import com.sleepycat.je.Transaction;
026: import com.sleepycat.je.txn.Locker;
027: import com.sleepycat.je.txn.BasicLocker;
028: import com.sleepycat.je.log.FileManager;
029: import com.sleepycat.je.util.TestUtils;
030:
031: /*
032: * Test transaction and lock timeouts.
033: */
034: public class TxnTimeoutTest extends TestCase {
035:
036: private Environment env;
037: private File envHome;
038:
039: public TxnTimeoutTest() throws DatabaseException {
040:
041: envHome = new File(System.getProperty(TestUtils.DEST_DIR));
042: }
043:
044: public void setUp() throws IOException, DatabaseException {
045: TestUtils.removeFiles("Setup", envHome, FileManager.JE_SUFFIX);
046: }
047:
048: public void tearDown() throws IOException, DatabaseException {
049:
050: if (env != null) {
051: env.close();
052: }
053: TestUtils.removeFiles("TearDown", envHome,
054: FileManager.JE_SUFFIX);
055: }
056:
057: private void createEnv(boolean setTimeout, long txnTimeoutVal,
058: long lockTimeoutVal) throws DatabaseException {
059: EnvironmentConfig envConfig = TestUtils.initEnvConfig();
060: envConfig.setTransactional(true);
061: envConfig.setAllowCreate(true);
062: if (setTimeout) {
063: envConfig.setTxnTimeout(txnTimeoutVal);
064: envConfig.setLockTimeout(lockTimeoutVal);
065: }
066:
067: env = new Environment(envHome, envConfig);
068: }
069:
070: /**
071: * Test timeout set at txn level.
072: */
073: public void testTxnTimeout() throws Throwable {
074:
075: try {
076: createEnv(false, 0, 0);
077:
078: Transaction txnA = env.beginTransaction(null, null);
079:
080: /* Grab a lock */
081: DatabaseConfig dbConfig = new DatabaseConfig();
082: dbConfig.setTransactional(true);
083: dbConfig.setAllowCreate(true);
084: env.openDatabase(txnA, "foo", dbConfig);
085:
086: /* Now make a second txn so we can induce some blocking. */
087: Transaction txnB = env.beginTransaction(null, null);
088: txnB.setTxnTimeout(300000); // microseconds
089: txnB.setLockTimeout(9000000);
090: Thread.sleep(400);
091:
092: try {
093: env.openDatabase(txnB, "foo", dbConfig);
094: fail("Should time out");
095: } catch (DeadlockException e) {
096: /* Skip the version string. */
097: assertTrue(TestUtils.skipVersion(e).startsWith(
098: "Transaction "));
099: /* Good, expect this exception */
100: txnB.abort();
101: } catch (Exception e) {
102: e.printStackTrace();
103: fail("Should not get another kind of exception");
104: }
105:
106: /* Now try a lock timeout. */
107: txnB = env.beginTransaction(null, null);
108: txnB.setLockTimeout(100000);
109:
110: try {
111: env.openDatabase(txnB, "foo", dbConfig);
112: fail("Should time out");
113: } catch (DeadlockException e) {
114: assertTrue(TestUtils.skipVersion(e).startsWith("Lock "));
115: /* Good, expect this exception */
116: txnB.abort();
117: } catch (Exception e) {
118: e.printStackTrace();
119: fail("Should not get another kind of exception");
120: }
121:
122: txnA.abort();
123: LockStats stats = env.getLockStats(TestUtils.FAST_STATS);
124: assertEquals(2, stats.getNWaits());
125:
126: } catch (Throwable t) {
127:
128: /*
129: * Print stack trace before trying to clean up JE files in
130: * teardown.
131: */
132: t.printStackTrace();
133: throw t;
134: }
135: }
136:
137: /**
138: * Use Txn.setTimeOut(), expect a txn timeout.
139: */
140: public void testPerTxnTimeout() throws Throwable {
141:
142: doEnvTimeout(false, true, true, 300000, 9000000, false);
143: }
144:
145: /**
146: * Use EnvironmentConfig.setTxnTimeOut(), expect a txn timeout.
147: */
148: public void testEnvTxnTimeout() throws Throwable {
149:
150: doEnvTimeout(true, true, true, 300000, 9000000, false);
151: }
152:
153: /**
154: * Use EnvironmentConfig.setTxnTimeOut(), use
155: * EnvironmentConfig.setLockTimeout(0), expect a txn timeout.
156: */
157: public void testEnvNoLockTimeout() throws Throwable {
158:
159: doEnvTimeout(true, true, true, 300000, 0, false);
160: }
161:
162: /**
163: * Use Txn.setLockTimeout(), expect a lock timeout.
164: */
165: public void testPerLockTimeout() throws Throwable {
166:
167: doEnvTimeout(false, false, true, 0, 100000, true);
168: }
169:
170: /**
171: * Use EnvironmentConfig.setTxnTimeOut(0), Use
172: * EnvironmentConfig.setLockTimeout(xxx), expect a lcok timeout.
173: */
174: public void testEnvLockTimeout() throws Throwable {
175:
176: doEnvTimeout(true, false, true, 0, 100000, true);
177: }
178:
179: /**
180: * @param setEnvConfigTimeout
181: * if true, use EnvironmentConfig.set{Lock,Txn}TimeOut
182: * @param setPerTxnTimeout if true, use Txn.setTxnTimeout()
183: * @param setPerLockTimeout if true, use Txn.setLockTimeout()
184: * @param long txnTimeout value for txn timeout
185: * @param long lockTimeout value for lock timeout
186: * @param expectLockException if true, expect a LockTimoutException, if
187: * false, expect a TxnTimeoutException
188: */
189: private void doEnvTimeout(boolean setEnvConfigTimeout,
190: boolean setPerTxnTimeout, boolean setPerLockTimeout,
191: long txnTimeout, long lockTimeout,
192: boolean expectLockException) throws Throwable {
193:
194: try {
195: createEnv(setEnvConfigTimeout, txnTimeout, lockTimeout);
196:
197: Transaction txnA = env.beginTransaction(null, null);
198: DatabaseConfig dbConfig = new DatabaseConfig();
199: dbConfig.setTransactional(true);
200: dbConfig.setAllowCreate(true);
201: Database dbA = env.openDatabase(txnA, "foo", dbConfig);
202:
203: /*
204: * Now make a second txn so we can induce some blocking. Make the
205: * txn timeout environment wide.
206: */
207: Transaction txnB = env.beginTransaction(null, null);
208: if (!setEnvConfigTimeout) {
209: if (setPerTxnTimeout) {
210: txnB.setTxnTimeout(300000);
211: }
212: if (setPerLockTimeout) {
213: txnB.setLockTimeout(9000000);
214: }
215: }
216:
217: Thread.sleep(400);
218:
219: try {
220: env.openDatabase(txnB, "foo", dbConfig);
221: fail("Should time out");
222: } catch (DeadlockException e) {
223: if (expectLockException) {
224: assertTrue(TestUtils.skipVersion(e).startsWith(
225: "Lock "));
226: } else {
227: assertTrue(TestUtils.skipVersion(e).startsWith(
228: "Transaction "));
229: }
230:
231: /* Good, expect this exception */
232: txnB.abort();
233: } catch (Exception e) {
234: e.printStackTrace();
235: fail("Should not get another kind of exception");
236: }
237:
238: dbA.close();
239: txnA.abort();
240: } catch (Throwable t) {
241:
242: /*
243: * Print stack trace before trying to clean up JE files in
244: * teardown.
245: */
246: t.printStackTrace();
247: throw t;
248: }
249: }
250:
251: /**
252: * Use Locker.setTxnTimeout(), expect a lock timeout.
253: */
254: public void testPerLockerTimeout() throws Throwable {
255:
256: try {
257: createEnv(true, 500000000, 0);
258:
259: EnvironmentImpl envImpl = DbInternal
260: .envGetEnvironmentImpl(env);
261:
262: /*
263: * Create our Locker object and set the transaction timeout to 0.
264: * 0 should mean no timeout per berkeley API docs).
265: */
266: Locker locker = new BasicLocker(envImpl);
267: locker.setTxnTimeout(0);
268: /* Wait for a short period. */
269: Thread.sleep(100);
270: /* Set the timeout to zero and should never be timed out. */
271: assertFalse(locker.isTimedOut());
272:
273: /* Set timeout to 10 milliseconds. */
274: locker.setTxnTimeout(10);
275: /* Wait for 100 milliseconds. */
276: Thread.sleep(100);
277: /* Should be timed out. */
278: assertTrue(locker.isTimedOut());
279:
280: try {
281:
282: /*
283: * Set timeout to a negative value, and expect a
284: * IllegalArgumentException.
285: */
286: locker.setTxnTimeout(-1000);
287:
288: /* Wait for 100 milliseconds. */
289: Thread.sleep(100);
290: /* Should not see me. */
291: assertTrue(locker.isTimedOut());
292: } catch (IllegalArgumentException ie) {
293: assertTrue(ie.getMessage().contains(
294: "the timeout value cannot be negative"));
295: } catch (Exception e) {
296: e.printStackTrace();
297: fail("Should not get another kind of exception");
298: }
299: } catch (Throwable t) {
300:
301: /*
302: * Print stack trace before trying to clean up je files in
303: * teardown.
304: */
305: t.printStackTrace();
306: throw t;
307: }
308:
309: }
310: }
|