KickJava   Java API By Example, From Geeks To Geeks.

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


1 /*
2  
3  Derby - Class org.apache.derbyTesting.functionTests.tests.store.TestNoSyncs
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
24 import java.sql.Connection JavaDoc;
25 import java.sql.Statement JavaDoc;
26 import java.sql.PreparedStatement JavaDoc;
27 import java.sql.DriverManager JavaDoc;
28 import java.sql.SQLException JavaDoc;
29 import java.io.*;
30 import org.apache.derbyTesting.functionTests.util.TestUtil;
31 import java.util.Properties JavaDoc;
32
33 /**
34  * This program tests the system when the derby.system.durability property is
35  * set to 'test'.
36  * <BR>
37  * When the derby.system.durability is set to 'test', the system will not do
38  * any sync to the
39  * disk and the recovery system will not work property. It is provided for
40  * performance reasons and should ideally only be used when there is no
41  * requirement for the database to recover.
42  * <p>
43  * When set, the system will not do any syncs, the cases namely - no sync of the
44  * log file at each commit - no sync of the log file before data page is forced
45  * to disk - no sync of page allocation when file is grown - no sync of data
46  * writes during checkpoint
47  * <p>
48  * That means, when this property is set to 'test',
49  * - a commit no longer guarantees that the transaction's modification will
50  * survive a system crash or
51  * JVM termination
52  * - the database may not recover successfully upon restart
53  * - a near full disk at runtime may cause unexpected errors
54  * - database may be in an inconsistent state
55  *
56  * This program tests for
57  * 1. setting the derby.system.durability=test is actually not
58  * doing the syncs by timing inserts
59  * 2. check if a warning message exists in derby.log
60  * 3. read log.ctrl file and check if the flag is set or not
61  * 4. check if the log.ctrl file flag is not overwritten for the case when
62  * database booted with derby.system.durability=test set, then shutdown
63  * and database booted without derby.system.durability=test
64  *
65  * @author Sunitha Kambhampati
66  * @version 1.0
67  */

68 public class TestDurabilityProperty {
69     public static void main(String JavaDoc[] args) {
70         try {
71             // Test 1: check if derby.system.durability=test
72
// mode is not doing syncs
73
testNoSyncs(args);
74             
75             String JavaDoc derbyHome = System.getProperty("derby.system.home");
76             // Test 2
77
// Check if derby.log has the warning message
78
report("Is warning message about derby.system.durability=test present in derby.log ="
79                     + isMessageInDerbyLog(derbyHome));
80             // Test 3
81
// Check if marker is correctly written out to database
82
markerInControlFile(derbyHome);
83             
84             // Test 4
85
// shutdown database and boot database afresh without
86
// derby.system.durability set to test. In this case the derby.log
87
// and the log control file should still have the marker that this
88
// mode was once used to boot database.
89
report(
90                 "2. shutdown database and reboot database without " +
91                 "derby.system.durability=test and test for marker in log.ctrl file");
92             markerNotOverwritten(derbyHome);
93
94         } catch (Throwable JavaDoc e) {
95             report("FAIL -- unexpected exception: " + e);
96             e.printStackTrace();
97         }
98
99     }
100
101     /**
102      * time inserts
103      *
104      * @param mode
105      * value for derby.system.durability property
106      * @param create
107      * should table be created or not
108      * @param autoCommit
109      * whether inserts should happen in autocommit mode or not
110      * @return time taken to do inserts
111      * @throws Exception
112      */

113     public static long timeTakenToInsert(String JavaDoc mode, boolean create,
114             boolean autoCommit) throws Exception JavaDoc {
115         System.setProperty("derby.system.durability", mode);
116         Connection JavaDoc conn = org.apache.derby.tools.ij.startJBMS();
117
118         if (create) {
119             Statement JavaDoc s = conn.createStatement();
120             s.execute("create table t1 (c1 int, c2 int)");
121             s.close();
122         }
123
124         long timeTaken = doInserts(conn, autoCommit);
125
126         try {
127             conn.close();
128             TestUtil.getConnection("","shutdown=true");
129         } catch (SQLException JavaDoc sqle) {
130             if ("XJ015".equals(sqle.getSQLState())) {
131             }// ok database shutdown
132
else {
133                 report(sqle.getSQLState());
134                 report("ERROR! during shutdown");
135                 sqle.printStackTrace();
136             }
137         }
138
139         return timeTaken;
140     }
141
142
143     /**
144      * Note doing inserts in autocommit mode is probably the worst case scenario
145      * in terms of performance as each commit will involve a flush/sync to disk
146      * but in case of the derby.system.durability=test mode, the syncs dont
147      * happen.
148      */

149     public static long doInserts(Connection JavaDoc conn,boolean autoCommit) throws Exception JavaDoc {
150         PreparedStatement JavaDoc ps = conn
151                 .prepareStatement("insert into t1 values(?,?)");
152         conn.setAutoCommit(autoCommit);
153         long count = 0;
154
155         long start = System.currentTimeMillis();
156
157         for (int i = 0; i < 500; i++) {
158             ps.setInt(1, i);
159             ps.setInt(2, i);
160             count += ps.executeUpdate();
161         }
162
163         if (!autoCommit)
164             conn.commit();
165         long end = System.currentTimeMillis();
166         if (count < 500)
167             report(" FAIL!! all rows didnt get inserted ?");
168         
169         return (end - start);
170     }
171
172     /**
173      * When derby.system.durability is set, a warning message is written out to
174      * derby.log indicating that the property is set and that it does not
175      * guarantee recoverability This test tests if a message is written out to
176      * derby.log or not
177      */

178     public static boolean isMessageInDerbyLog(String JavaDoc derbyHome) throws Exception JavaDoc {
179         BufferedReader reader = null;
180         File derbylog = null;
181         try {
182             derbylog = new File(derbyHome, "derby.log");
183             reader = new BufferedReader(new FileReader(derbylog));
184
185             String JavaDoc line = null;
186             while ((line = reader.readLine()) != null) {
187                 if (line.indexOf("derby.system.durability=test") != -1)
188                     return true;
189
190             }
191             return false;
192         } finally {
193             if (reader != null) {
194                 reader.close();
195             }
196             derbylog = null;
197         }
198     }
199
200     /**
201      * if database is booted with derby.system.durability=test,
202      * a marker is written out into log control
203      * file to recognize that the database was previously booted in this mode
204      * Test if the marker byte is set correctly or not. See comments in
205      * org.apache.derby.impl.store.log.LogToFile for IS_DURABILITY_TESTMODE_NO_SYNC_FLAG
206      */

207     public static void markerInControlFile(String JavaDoc derbyHome) throws Exception JavaDoc {
208         RandomAccessFile controlFile = null;
209         try {
210             int testModeNoSyncMarkerPosition = 28;
211             byte testModeNoSyncMarker = 0x2;
212             controlFile = new RandomAccessFile(derbyHome
213                     + "/wombat/log/log.ctrl", "r");
214             controlFile.seek(testModeNoSyncMarkerPosition);
215             report("log.ctrl file has durability testMode no sync marker value = "
216                     + ((controlFile.readByte() & testModeNoSyncMarker) != 0) );
217         } finally {
218             if (controlFile != null)
219                 controlFile.close();
220
221         }
222     }
223
224     /**
225      * Test for case when database is booted without derby.system.durability=test
226      * but previously has been booted with the derby.system.durability=test. In
227      * this scenario,the log control file should still have the marker to say
228      * that this mode was set previously, and derby.log must also have a warning
229      * message
230      * @param derbyHome value of derby.system.home where the database is
231      * @throws Exception
232      */

233     public static void markerNotOverwritten(String JavaDoc derbyHome) throws Exception JavaDoc
234     {
235         // shutdown database
236
Connection JavaDoc conn = null;
237         // unset property
238
System.setProperty("derby.system.durability","");
239         conn = org.apache.derby.tools.ij.startJBMS();
240         conn.close();
241         markerInControlFile(derbyHome);
242         report("Is warning message about derby.system.durability=test present in derby.log ="
243                 + isMessageInDerbyLog(derbyHome));
244     }
245     
246     /**
247      * print message
248      * @param msg to print out
249      */

250     public static void report(String JavaDoc msg) {
251         System.out.println(msg);
252     }
253
254     /**
255      * Test if derby.system.durability=test property is broken or not. We time
256      * inserts for 500 repeated inserts and make some approximate estimations on
257      * how fast it should be. Since it is a timing based test, there might be
258      * cases of a really really slow machine in some weird cases where this test
259      * may have diffs in this part of the test.
260      *
261      * So basically to determine if something is wrong, the following is done
262      * to try best to eliminate issues with slow machines
263      * 1)if inserts with autocommit on is fast enough (an estimated
264      * bound)
265      * 2)if not, then since no syncs happen , check if time taken to do
266      * inserts for autocommit on and off are in proximity range
267      * 3)if 1 and 2 is not satisfied, then check time taken without this mode set
268      * and with this mode set.
269      * If they are in proximity range something could be wrong. It
270      * might be good to check the machine configuration and environment when
271      * test was running <BR>
272      * Also note, although it would seem like a solution would be to bump the
273      * estimated bound to a high limit, this might not help since on a really
274      * good disk the inserts doing syncs might well be done within the bound and
275      * thus would not be possible to know if this mode was possibly broken.
276      *
277      */

278     public static void testNoSyncs(String JavaDoc[] args) throws Exception JavaDoc {
279         boolean debug = false; // if set, prints out useful info when debugging test
280

281         report("1. With derby.system.durability=test,"
282                 + "Test to see if syncs are not happening ");
283         // use the ij utility to read the property file and
284
// make the initial connection.
285
org.apache.derby.tools.ij.getPropertyArg(args);
286
287         boolean create = true;
288
289         // Note we time inserts in normal all syncs case first even
290
// though we may not require it if the inserts finish fast enough
291
// But timing them here because once database is booted with
292
// derby.system.durability=test there are no guarantees on consistency
293
// of database so dont want to mess up numbers for the all syncs case
294

295         // derby.system.durability is not test so it will default to
296
// normal mode and autocommit=true
297
long timeCommitOn = timeTakenToInsert("", create, true);
298         String JavaDoc derbyHome = System.getProperty("derby.system.home");
299         if (isMessageInDerbyLog(derbyHome))
300             report("ERROR! System should not have been booted with"
301                     + "derby.system.durability=test mode here");
302         create = false;
303         // derby.system.durability=test and autocommit=true
304
long timeWithTestModeCommitOn = timeTakenToInsert("test", create, true);
305         // derby.system.durability=test and autocommit=false
306
long timeWithTestModeCommitOff = timeTakenToInsert("test", create, false);
307       
308         if (debug) {
309             report("timeCommitOn = " + timeCommitOn);
310             report("timeWithTestModeCommitOn = " + timeWithTestModeCommitOn);
311             report("timeWithTestModeCommitOff = " + timeWithTestModeCommitOff);
312         }
313
314         // an approximation on the upper bound for time taken to do
315
// inserts in autocommit mode with derby.system.durability=test mode
316
long upperBound = 3000;
317
318         // if it takes a lot of time to do the inserts then do extra checks
319
// to determine if derby.system.durability=test mode is broken or not
320
// because we cant be sure if inserts just took a long time
321
// because of a really slow machine
322
if (timeWithTestModeCommitOn > upperBound) {
323
324             long proximityRange = 1000;
325
326             // in derby.system.durability=test autocommit on or off should
327
// be in same range since syncs are not happening
328
if (Math.abs(timeWithTestModeCommitOn - timeWithTestModeCommitOff) > proximityRange) {
329                 // another approximation here (1.5 times of with testmode set)
330
if (timeWithTestModeCommitOn > timeCommitOn
331                         || (timeCommitOn < (1.5 * timeWithTestModeCommitOn))) {
332                     report("FAIL -- derby.system.durability=test mode seems to be broken.");
333                     report("-- In this mode one would expect that inserts with autocommit off and on "
334                             + "would be in the same range as syncs are not happening but the difference "
335                             + "here seems to be more than the approximate estimated range.");
336                     report("-- Also comparing the time taken to do the inserts without this" +
337                             " property set seems to be in the same"
338                             + " range as with this property set.");
339                     report("-- Please note this test times inserts and approximate estimates were " +
340                             "considered to report this observation.");
341                 }
342             }
343         }
344
345     }
346 }
347
Popular Tags