File: InterruptTest.java

package info (click to toggle)
libdb-je-java 3.3.98-3
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid, trixie
  • size: 13,052 kB
  • sloc: java: 153,077; xml: 2,034; makefile: 3
file content (190 lines) | stat: -rw-r--r-- 6,253 bytes parent folder | download | duplicates (3)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
/*-
 * See the file LICENSE for redistribution information.
 *
 * Copyright (c) 2002,2010 Oracle.  All rights reserved.
 *
 * $Id: InterruptTest.java,v 1.14.2.2 2010/01/04 15:30:42 cwl Exp $
 */

package com.sleepycat.je;

import java.io.File;
import java.io.IOException;

import junit.framework.TestCase;

import com.sleepycat.je.config.EnvironmentParams;
import com.sleepycat.je.util.TestUtils;

/**
 * @author Paul.Kendall@orionhealth.com
 *
 * This test throws thread interrupts while JE is doing I/O intensive
 * work. When an interrupt is received during various NIO activities, NIO
 * closes the underlying file descriptor. In this multi-threaded test, abruptly
 * closing the file descriptor causes exceptions such as
 * java.nio.ChannelClosedException, because the uninterrupted thread may be in
 * the middle of using that file.
 *
 * JE must convert all such exceptions to
 * com.sleepycat.je.RunRecoveryException.
 */
public class InterruptTest extends TestCase {

    private File envHome;
    private int NUM_OPS = 1000;
    private int NUM_ITERATIONS = 1;

    public InterruptTest() {
        envHome = new File(System.getProperty(TestUtils.DEST_DIR));
    }

    public void setUp()
        throws IOException {

        TestUtils.removeLogFiles("Setup", envHome, false);
    }

    public void testInterruptHandling()
    	throws Exception {

        for (int i = 0; i < NUM_ITERATIONS; i++) {
            interruptThreads(i);
        }
    }

    public void interruptThreads(int i)
    	throws Exception {

        // TestUtils.removeLogFiles("Loop", envHome, false);
        Environment env = null;
        Database db = null;

        try {
            EnvironmentConfig envConfig = TestUtils.initEnvConfig();
            envConfig.setTransactional(true);
            envConfig.setAllowCreate(true);
	    envConfig.setConfigParam
		(EnvironmentParams.ENV_CHECK_LEAKS.getName(), "false");
            env = new Environment(envHome, envConfig);

            DatabaseConfig dbConfig = new DatabaseConfig();
            dbConfig.setAllowCreate(true);
            dbConfig.setTransactional(true);
            db = env.openDatabase(null, "testDB" + i, dbConfig);

            ActionThread putter = new ActionThread(env, db, 1) {
                    protected void doStuff(Database db,
                                           Transaction txn,
                                           DatabaseEntry key,
                                           DatabaseEntry value)
                        throws DatabaseException {
                        db.put(txn, key, value);
                    }
                };

            ActionThread deleter = new ActionThread(env, db, 1) {
                    protected void doStuff(Database db,
                                           Transaction txn,
                                           DatabaseEntry key,
                                           DatabaseEntry value)
                        throws DatabaseException {
                        db.delete(txn, key);
                    }
                };

            putter.start();
            Thread.sleep(1000);

            deleter.start();
            Thread.sleep(2000);

            /*
             * Interrupting these threads will catch them in the middle of an
             * NIO operation, expect a RunRecovery exception.
             */
            putter.interrupt();
            deleter.interrupt();

            putter.join();
            deleter.join();
        } finally {
            try {
                if (db != null) {
                    db.close();
                }
            } catch (RunRecoveryException ok) {

                /*
		 * Expect a run recovery exception. Since it will be detected
                 * when we try to close the database, close the environment
                 * now so we can re-start in the same JVM.
                 */
            } catch (Throwable t) {
                t.printStackTrace();
                fail("Should not see any other kind of exception. Iteration=" +
		     i);
            } finally {
                if (env != null) {
                    try {
                        env.close();
                        env = null;
                    } catch (RunRecoveryException ignore) {
                        /* Sometimes the checkpointer can't close down. */
                    }
                }
            }
        }
    }

    abstract class ActionThread extends Thread {
    	private Environment env;
    	private Database db;
        private int threadNumber;
    	
    	public ActionThread(Environment env, Database db, int threadNumber) {
            this.env = env;
            this.db = db;
            this.threadNumber = threadNumber;
    	}
    	
    	public void run() {
            int i=0;
            Transaction txn = null;
            try {
                for ( ; i < NUM_OPS ; i++) {
                    txn = env.beginTransaction(null, null);
                    DatabaseEntry key = new DatabaseEntry();
                    key.setData(("" + threadNumber * 10000 + i).getBytes());
                    DatabaseEntry value = new DatabaseEntry();
                    value.setData(new byte[8192]);
                    doStuff(db, txn, key, value);
                    Thread.sleep(10);
                    txn.commit();
                    txn = null;
                }
            } catch (InterruptedException e) {
                /* possible outcome. */
            } catch (RunRecoveryException e) {
                /* possible outcome. */
            } catch (DatabaseException e) {
                /* possible outcome. */
                //System.out.println("Put to " + i);
                //e.printStackTrace();
            } finally {
                try {
                    if (txn != null) {
                        txn.abort();
                    }
                } catch (DatabaseException ignored) {
                }
            }
    	}

        abstract protected void doStuff(Database db,
                                        Transaction txn,
                                        DatabaseEntry key,
                                        DatabaseEntry value)
            throws DatabaseException;
    }
}