KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > h2 > test > db > TestPowerOff


1 /*
2  * Copyright 2004-2006 H2 Group. Licensed under the H2 License, Version 1.0 (http://h2database.com/html/license.html).
3  * Initial Developer: H2 Group
4  */

5 package org.h2.test.db;
6
7 import java.sql.Connection JavaDoc;
8 import java.sql.DatabaseMetaData JavaDoc;
9 import java.sql.ResultSet JavaDoc;
10 import java.sql.SQLException JavaDoc;
11 import java.sql.Statement JavaDoc;
12 import java.util.ArrayList JavaDoc;
13 import java.util.Random JavaDoc;
14
15 import org.h2.engine.Constants;
16 import org.h2.engine.Database;
17 import org.h2.jdbc.JdbcConnection;
18 import org.h2.test.TestBase;
19 import org.h2.tools.FileBase;
20 import org.h2.util.FileUtils;
21 import org.h2.util.JdbcUtils;
22
23 public class TestPowerOff extends TestBase {
24     
25     private String JavaDoc dbName = "powerOff";
26     private String JavaDoc dir, url;
27
28     private int maxPowerOffCount;
29
30     public void test() throws Exception JavaDoc {
31         if(config.memory || config.logMode==0) {
32             return;
33         }
34         if(config.big) {
35             dir = BASE_DIR;
36         } else {
37             dir = "inmemory:";
38         }
39         url = dir + "/" + dbName + ";file_lock=no";
40         testSummaryCrash();
41         testCrash();
42         testShutdown();
43         testNoIndexFile();
44         testMemoryTables();
45         testPersistentTables();
46     }
47     
48     private void testSummaryCrash() throws Exception JavaDoc {
49         if(config.networked) {
50             return;
51         }
52         deleteDb(dir, dbName);
53         Connection JavaDoc conn = getConnection(url);
54         Statement JavaDoc stat = conn.createStatement();
55         for(int i=0; i<10; i++) {
56             stat.execute("CREATE TABLE TEST" + i + "(ID INT PRIMARY KEY, NAME VARCHAR)");
57             for(int j=0; j<10; j++) {
58                 stat.execute("INSERT INTO TEST" + i + " VALUES("+j+", 'Hello')");
59             }
60         }
61         for(int i=0; i<10; i+=2) {
62             stat.execute("DROP TABLE TEST" + i);
63         }
64         stat.execute("SET WRITE_DELAY 0");
65         stat.execute("CHECKPOINT");
66         for(int j=0; j<10; j++) {
67             stat.execute("INSERT INTO TEST1 VALUES("+(10+j)+", 'World')");
68         }
69         stat.execute("SHUTDOWN IMMEDIATELY");
70         JdbcUtils.closeSilently(conn);
71         conn = getConnection(url);
72         stat = conn.createStatement();
73         for(int i=1; i<10; i+=2) {
74             ResultSet JavaDoc rs = stat.executeQuery("SELECT * FROM TEST" + i + " ORDER BY ID");
75             for(int j=0; j<10; j++) {
76                 rs.next();
77                 check(rs.getInt(1), j);
78                 check(rs.getString(2), "Hello");
79             }
80             if(i == 1) {
81                 for(int j=0; j<10; j++) {
82                     rs.next();
83                     check(rs.getInt(1), j + 10);
84                     check(rs.getString(2), "World");
85                 }
86             }
87             checkFalse(rs.next());
88         }
89         conn.close();
90     }
91     
92     private void testCrash() throws Exception JavaDoc {
93         if(config.networked) {
94             return;
95         }
96         deleteDb(dir, dbName);
97         Random JavaDoc random = new Random JavaDoc(1);
98         Constants.RUN_FINALIZERS = false;
99         int repeat = getSize(1, 20);
100         for(int i=0; i<repeat; i++) {
101             Connection JavaDoc conn = getConnection(url);
102             conn.close();
103             conn = getConnection(url);
104             Statement JavaDoc stat = conn.createStatement();
105             stat.execute("SET WRITE_DELAY 0");
106             ((JdbcConnection)conn).setPowerOffCount(random.nextInt(100));
107             try {
108                 stat.execute("DROP TABLE IF EXISTS TEST");
109                 stat.execute("CREATE TABLE TEST(ID INT PRIMARY KEY, NAME VARCHAR(255))");
110                 conn.setAutoCommit(false);
111                 int len = getSize(3, 100);
112                 for (int j=0; j<len; j++) {
113                     stat.execute("INSERT INTO TEST VALUES("+j+", 'Hello')");
114                     if(random.nextInt(5) == 0) {
115                         conn.commit();
116                     }
117                     if(random.nextInt(10) == 0) {
118                         stat.execute("DROP TABLE IF EXISTS TEST");
119                         stat.execute("CREATE TABLE TEST(ID INT PRIMARY KEY, NAME VARCHAR(255))");
120                     }
121                 }
122                 stat.execute("DROP TABLE IF EXISTS TEST");
123                 conn.close();
124             } catch(SQLException JavaDoc e) {
125                 if(!e.getSQLState().equals("90098")) {
126                     TestBase.logError("power", e);
127                 }
128             }
129         }
130     }
131     
132     private void testShutdown() throws Exception JavaDoc {
133         deleteDb(dir, dbName);
134         Connection JavaDoc conn = getConnection(url);
135         Statement JavaDoc stat = conn.createStatement();
136         stat.execute("CREATE TABLE TEST(ID INT PRIMARY KEY, NAME VARCHAR(255))");
137         stat.execute("INSERT INTO TEST VALUES(1, 'Hello')");
138         stat.execute("SHUTDOWN");
139         conn.close();
140         
141         conn = getConnection(url);
142         stat = conn.createStatement();
143         ResultSet JavaDoc rs = stat.executeQuery("SELECT * FROM TEST");
144         check(rs.next());
145         checkFalse(rs.next());
146         conn.close();
147     }
148     
149     private void testNoIndexFile() throws Exception JavaDoc {
150         if(config.networked) {
151             return;
152         }
153         deleteDb(dir, dbName);
154         Connection JavaDoc conn = getConnection(url);
155         Statement JavaDoc stat = conn.createStatement();
156         stat.execute("CREATE MEMORY TABLE TEST(ID INT PRIMARY KEY, NAME VARCHAR(255))");
157         stat.execute("INSERT INTO TEST VALUES(1, 'Hello')");
158         ((JdbcConnection)conn).setPowerOffCount(1);
159          try {
160              stat.execute("INSERT INTO TEST VALUES(2, 'Hello')");
161              stat.execute("CHECKPOINT");
162              error("should not work!");
163          } catch(SQLException JavaDoc e) {
164              // expected
165
}
166          boolean deleted = false;
167          ArrayList JavaDoc files = FileBase.getDatabaseFiles(dir, dbName, false);
168          for(int i=0; i<files.size(); i++) {
169              String JavaDoc fileName = (String JavaDoc) files.get(i);
170              if(fileName.endsWith(Constants.SUFFIX_INDEX_FILE)) {
171                  FileUtils.delete(fileName);
172                  deleted = true;
173              }
174          }
175          check(deleted);
176          conn = getConnection(url);
177          conn.close();
178     }
179     
180     private void testMemoryTables() throws Exception JavaDoc {
181         if(config.networked) {
182             return;
183         }
184         deleteDb(dir, dbName);
185         
186         Connection JavaDoc conn = getConnection(url);
187         Statement JavaDoc stat = conn.createStatement();
188         stat.execute("CREATE MEMORY TABLE TEST(ID INT PRIMARY KEY, NAME VARCHAR(255))");
189         stat.execute("INSERT INTO TEST VALUES(1, 'Hello')");
190         stat.execute("CHECKPOINT");
191         ((JdbcConnection)conn).setPowerOffCount(1);
192         try {
193             stat.execute("INSERT INTO TEST VALUES(2, 'Hello')");
194             stat.execute("INSERT INTO TEST VALUES(3, 'Hello')");
195             stat.execute("CHECKPOINT");
196             error("should have failed!");
197         } catch(Exception JavaDoc e) {
198             // ok
199
}
200
201         ((JdbcConnection)conn).setPowerOffCount(0);
202         conn = getConnection(url);
203         stat = conn.createStatement();
204         ResultSet JavaDoc rs = stat.executeQuery("SELECT COUNT(*) FROM TEST");
205         rs.next();
206         check(rs.getInt(1), 1);
207         conn.close();
208     }
209     
210     private void testPersistentTables() throws Exception JavaDoc {
211         if(config.networked) {
212             return;
213         }
214         deleteDb(dir, dbName);
215
216         // ((JdbcConnection)conn).setPowerOffCount(Integer.MAX_VALUE);
217
testRun(true);
218         int max = maxPowerOffCount;
219         trace("max="+max);
220         runTest(0, max, true);
221         recoverAndCheckConsistency();
222         runTest(0, max, false);
223         recoverAndCheckConsistency();
224     }
225     
226     void runTest(int min, int max, boolean withConsistencyCheck) throws Exception JavaDoc {
227         for(int i=min; i<max; i++) {
228             deleteDb(dir, dbName);
229             Database.setInitialPowerOffCount(i);
230             int expect = testRun(false);
231             if(withConsistencyCheck) {
232                 int got = recoverAndCheckConsistency();
233                 trace("test "+i+" of "+max+" expect="+expect+" got="+got);
234             } else {
235                 trace("test "+i+" of "+max+" expect="+expect);
236             }
237         }
238         Database.setInitialPowerOffCount(0);
239     }
240     
241     int testRun(boolean init) throws Exception JavaDoc {
242         if(init) {
243             Database.setInitialPowerOffCount(Integer.MAX_VALUE);
244         }
245         int state = 0;
246         try {
247             Connection JavaDoc conn = getConnection(url);
248             Statement JavaDoc stat = conn.createStatement();
249             stat.execute("SET WRITE_DELAY 0");
250             stat.execute("CREATE TABLE IF NOT EXISTS TEST(ID INT PRIMARY KEY, NAME VARCHAR(255))");
251             state = 1;
252             conn.setAutoCommit(false);
253             stat.execute("INSERT INTO TEST VALUES(1, 'Hello')");
254             stat.execute("INSERT INTO TEST VALUES(2, 'World')");
255             conn.commit();
256             state = 2;
257             stat.execute("UPDATE TEST SET NAME='Hallo' WHERE ID=1");
258             stat.execute("UPDATE TEST SET NAME='Welt' WHERE ID=2");
259             conn.commit();
260             state = 3;
261             stat.execute("DELETE FROM TEST WHERE ID=1");
262             stat.execute("DELETE FROM TEST WHERE ID=2");
263             conn.commit();
264             state = 1;
265             stat.execute("DROP TABLE TEST");
266             state = 0;
267             if(init) {
268                 maxPowerOffCount = Integer.MAX_VALUE - ((JdbcConnection)conn).getPowerOffCount();
269             }
270             conn.close();
271         } catch(SQLException JavaDoc e) {
272             if(e.getSQLState().equals("90098")) {
273                 // this is ok
274
} else {
275                 throw e;
276             }
277         }
278         return state;
279     }
280     
281     int recoverAndCheckConsistency() throws Exception JavaDoc {
282         int state;
283         Database.setInitialPowerOffCount(0);
284         Connection JavaDoc conn = getConnection(url);
285         if(((JdbcConnection)conn).getPowerOffCount() != 0) {
286             error("power off count is not 0");
287         }
288         Statement JavaDoc stat = conn.createStatement();
289         DatabaseMetaData JavaDoc meta = conn.getMetaData();
290         ResultSet JavaDoc rs = meta.getTables(null, null, "TEST", null);
291         if(!rs.next()) {
292             state = 0;
293         } else {
294             // table does not exist
295
rs = stat.executeQuery("SELECT * FROM TEST ORDER BY ID");
296             if(!rs.next()) {
297                 state = 1;
298             } else {
299                 check(rs.getInt(1), 1);
300                 String JavaDoc name1 = rs.getString(2);
301                 check(rs.next());
302                 check(rs.getInt(1), 2);
303                 String JavaDoc name2 = rs.getString(2);
304                 checkFalse(rs.next());
305                 if("Hello".equals(name1)) {
306                     check(name2, "World");
307                     state = 2;
308                 } else {
309                     check(name1, "Hallo");
310                     check(name2, "Welt");
311                     state = 3;
312                 }
313             }
314         }
315         conn.close();
316         return state;
317     }
318
319 }
320
Popular Tags