KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > apache > derbyTesting > functionTests > tests > store > LogChecksumSetup


1 /*
2
3    Derby - Class org.apache.derbyTesting.functionTests.store.LogChecksumSetup
4
5    Licensed to the Apache Software Foundation (ASF) under one or more
6    contributor license agreements. See the NOTICE file distributed with
7    this work for additional information regarding copyright ownership.
8    The ASF licenses this file to You under the Apache License, Version 2.0
9    (the "License"); you may not use this file except in compliance with
10    the License. You may obtain a copy of the License at
11
12       http://www.apache.org/licenses/LICENSE-2.0
13
14    Unless required by applicable law or agreed to in writing, software
15    distributed under the License is distributed on an "AS IS" BASIS,
16    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17    See the License for the specific language governing permissions and
18    limitations under the License.
19
20  */

21
22 package org.apache.derbyTesting.functionTests.tests.store;
23 import java.sql.*;
24 import java.io.ByteArrayOutputStream JavaDoc;
25 import java.io.DataOutputStream JavaDoc;
26 import java.io.IOException JavaDoc;
27 import java.util.zip.CRC32 JavaDoc;
28 import org.apache.derbyTesting.functionTests.util.corruptio.CorruptibleIo;
29 import org.apache.derby.tools.ij;
30
31 /*
32  * Purpose of this class is to simulate out of order incomplete
33  * log write corruption (see derby-96 for details) using the proxy storage
34  * factory (org.apache.derbyTesting.functionTests.util.corruptio.
35  * CorruptDiskStorageFactory) instead of the default storage factory.
36  * By defailt all io is delegated to the default database storage factory,
37  * except when corruption is enabled through CorruptibleIo class.
38  * Proxy storage factory is loaded using the following properties in
39  * the test properties file:
40  * derby.subSubProtocol.csf=org.apache.derbyTesting.functionTests.
41  * util.corruptio.CorruptDiskStorageFactory
42  * database=jdbc:derby:csf:wombat
43  *
44  * @author <a HREF="mailto:suresh.thalamati@gmail.com">Suresh Thalamati</a>
45  * @version 1.0
46  * @see CorruptibleIo
47  */

48
49 public class LogChecksumSetup{
50
51     private CorruptibleIo cbio;
52
53     LogChecksumSetup()
54     {
55         cbio = CorruptibleIo.getInstance();
56     }
57     
58     /**
59      * Insert some rows into the table and corrupt the log for the last row,
60      * so when we recover , there should be one row less even though we committed.
61      */

62     void insertAndCorrupt(Connection conn, int rowCount) throws SQLException {
63
64         PreparedStatement ps = conn.prepareStatement("INSERT INTO " +
65                                                      "T1" +
66                                                      " VALUES(?,?,?)");
67
68         java.util.Random JavaDoc r = new java.util.Random JavaDoc();
69         CRC32 JavaDoc checksum = new CRC32 JavaDoc(); // holder for the checksum
70
boolean corrupt = false;
71         for (int i = 0; i < rowCount; i++) {
72             
73             //setup last row for log corruption
74
if (i == (rowCount -1 ))
75             {
76                 // Note: offset/len for corruption here refers to
77
// the actual log write request
78
// that is being done for this insert.
79
setupLogCorruption(50, 10);
80                 corrupt = true;
81             }
82             ps.setInt(1, i); // ID
83
byte[] dataBytes = generateBinaryData(r, 90000 , 1000 * i);
84             ps.setBytes(2, dataBytes);
85             //calculate checksum for blob data
86
checksum.update(dataBytes, 0, dataBytes.length);
87             checksum.reset();
88             checksum.update(dataBytes, 0, dataBytes.length);
89             ps.setLong(3, checksum.getValue());
90             ps.executeUpdate();
91             conn.commit();
92         }
93     }
94
95         
96     /**
97      * update some rows in the table and corrupt the log for the last row,
98      * so when we recover , All checsum should be correct because corrupted
99      * log transaction should been rolled back.
100      */

101
102     void updateAndCorrupt(Connection conn, int rowCount) throws SQLException{
103
104         PreparedStatement ps = conn.prepareStatement("update " + "T1" +
105                                                      " SET " +
106                                                      "DATA=?, DATACHECKSUM=? where ID=?");
107         
108         java.util.Random JavaDoc r = new java.util.Random JavaDoc();
109         CRC32 JavaDoc checksum = new CRC32 JavaDoc(); // holder for the checksum
110
int updateCount = 0;
111         boolean corrupt = false;
112         for (int i = 0; i < rowCount; i++) {
113             
114             //setup last row for log corruption
115
if (i == (rowCount -1 ))
116             {
117                 // Note: offset/len for corruption here refers to
118
// the actual log write request
119
// that is being done for this insert.
120
setupLogCorruption(50, 10);
121                 corrupt = true;
122             }
123             byte[] dataBytes = generateBinaryData(r, 1234 , 5000 * i);
124             ps.setBytes(1, dataBytes);
125
126             // calculate checksum for blob data
127
checksum.update(dataBytes, 0, dataBytes.length);
128             checksum.reset();
129             checksum.update(dataBytes, 0, dataBytes.length);
130
131             ps.setLong(2, checksum.getValue());
132             ps.setInt(3, i); // ID
133
updateCount += ps.executeUpdate();
134             conn.commit();
135         }
136     }
137
138
139     /*
140      * read the data from the table and verify the blob data using the
141      * checksum and make sure that expected number rows exist in the table.
142      *
143      */

144     void verifyData(Connection conn, int expectedRowCount) throws SQLException {
145         
146         Statement s = conn.createStatement();
147         CRC32 JavaDoc checksum = new CRC32 JavaDoc(); // holder for the checksum
148

149         ResultSet rs = s.executeQuery("SELECT DATA , DATACHECKSUM, ID FROM "
150                                       + "T1" );
151         int count = 0;
152         while(rs.next())
153         {
154             byte[] dataBytes = rs.getBytes(1);
155             long ckmRead = rs.getLong(2);
156             int id = rs.getInt(3);
157
158             checksum.reset();
159             checksum.update(dataBytes, 0, dataBytes.length);
160
161             if(checksum.getValue() != ckmRead )
162             {
163                 logMessage("CHECKSUMs ARE NOT MATCHING");
164                 logMessage("ID=" + id + " Checksum From DB:" + ckmRead);
165                 logMessage("Recalcaulted sum :" + checksum.getValue());
166                 logMessage("Length of Data:" + dataBytes.length);
167             }
168             
169             count++;
170         }
171         conn.commit();
172
173         if(count != expectedRowCount)
174         {
175             logMessage("Expected Number Of Rows (" +
176                        expectedRowCount + ")" + "!=" +
177                        "No Of rows in the Table(" +
178                        count + ")");
179         }
180     }
181
182     /*
183      * create the tables that are used by this test.
184      */

185     private void createTable(Connection conn) throws SQLException {
186
187         Statement s = conn.createStatement();
188         s.executeUpdate("CREATE TABLE " + "T1" + "(ID INT," +
189                         "DATA BLOB(300000),"+
190                         "DATACHECKSUM BIGINT)");
191         conn.commit();
192         s.close();
193     }
194
195     /*
196      * Log is corrupted using the corrupt storage factory.
197      * setup offset/length where we want the transaction
198      * log to be corrupted. Transaction tat the corruption
199      * is simulated on should be rolled back because the log check
200      * should identify that the writes were incomplete.
201      */

202     private void setupLogCorruption(int off , int len)
203     {
204         cbio.setLogCorruption(true);
205         cbio.setOffset(off);
206         cbio.setLength(len);
207     }
208
209
210     /*
211      * utility routine to generate random byte array of data.
212      */

213     private byte[] generateBinaryData(java.util.Random JavaDoc r,
214                                              int factor,
215                                              int size) {
216         
217         ByteArrayOutputStream JavaDoc baos = new ByteArrayOutputStream JavaDoc(64);
218         try{
219             DataOutputStream JavaDoc daos = new DataOutputStream JavaDoc(baos);
220             for(int i = 0 ; i < size ; i++)
221             {
222                 int p = r.nextInt() % factor;
223                 if (p < 0)
224                     p = p * -1;
225                 daos.writeInt(p);
226             }
227             
228         }catch(IOException JavaDoc ie)
229         {
230             logMessage(ie.getMessage()) ;
231         }
232         return baos.toByteArray();
233     }
234
235
236     private void runTest(Connection conn) throws SQLException
237     {
238         logMessage("Begin LogCheckum Setup Test");
239         createTable(conn);
240         insertAndCorrupt(conn, 11);
241         logMessage("End LogChecksum Setup Test");
242     }
243     
244     void logMessage(String JavaDoc str)
245     {
246         System.out.println(str);
247     }
248
249     public static void main(String JavaDoc[] argv) throws Throwable JavaDoc {
250         LogChecksumSetup lctest = new LogChecksumSetup();
251         ij.getPropertyArg(argv);
252         Connection conn = ij.startJBMS();
253         conn.setAutoCommit(false);
254
255         try {
256             lctest.runTest(conn);
257         }
258         catch (SQLException sqle) {
259             org.apache.derby.tools.JDBCDisplayUtil.ShowSQLException(
260                 System.out, sqle);
261             sqle.printStackTrace(System.out);
262         }
263     }
264 }
265
Popular Tags