KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > apache > derbyTesting > unitTests > store > T_RecoverBadLog


1 /*
2
3    Derby - Class org.apache.derbyTesting.unitTests.store.T_RecoverBadLog
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.unitTests.store;
23
24 import org.apache.derbyTesting.unitTests.harness.T_Generic;
25 import org.apache.derbyTesting.unitTests.harness.T_Fail;
26 import org.apache.derbyTesting.unitTests.harness.UnitTest;
27
28 import org.apache.derby.impl.store.raw.log.*;
29
30 import org.apache.derby.iapi.services.context.ContextService;
31 import org.apache.derby.iapi.services.context.ContextManager;
32 import org.apache.derby.iapi.services.daemon.DaemonService;
33 import org.apache.derby.iapi.services.monitor.Monitor;
34 import org.apache.derby.iapi.services.locks.LockFactory;
35 import org.apache.derby.iapi.services.io.Storable;
36 import org.apache.derby.iapi.services.sanity.SanityManager;
37 import org.apache.derby.iapi.reference.Property;
38 import org.apache.derby.iapi.reference.EngineType;
39 import org.apache.derby.iapi.services.property.PropertyUtil;
40 import org.apache.derby.iapi.services.io.FormatableBitSet;
41 import org.apache.derby.io.StorageRandomAccessFile;
42
43 import org.apache.derby.iapi.error.StandardException;
44
45 import org.apache.derby.iapi.store.raw.*;
46
47 import org.apache.derby.iapi.store.access.conglomerate.LogicalUndo;
48
49 import org.apache.derby.iapi.store.access.Qualifier;
50
51 import java.io.IOException JavaDoc;
52 import java.io.RandomAccessFile JavaDoc;
53 import java.io.File JavaDoc;
54 import java.util.Properties JavaDoc;
55
56
57
58 /**
59     A implementation unit test for recovering log that has been damanged but salvagable.
60
61     To run, create a derby.properties file in a new directory with the
62     contents
63
64     derby.module.test.recoverBadLog=org.apache.derbyTesting.unitTests.store.T_RecoverBadLog
65
66     Execute in order
67
68     To Test Bad Log due to partial write that are identified by checking the
69     length in the beginning and end of the log record.
70
71     java -DTestBadLogSetup=true org.apache.derbyTesting.unitTests.harness.UnitTestMain
72     java -DTestBadLog1=true org.apache.derbyTesting.unitTests.harness.UnitTestMain
73     java -DTestBadLog2=true org.apache.derbyTesting.unitTests.harness.UnitTestMain
74     java -DTestBadLog3=true org.apache.derbyTesting.unitTests.harness.UnitTestMain
75     java -DTestBadLog4=true org.apache.derbyTesting.unitTests.harness.UnitTestMain
76     java -DTestBadLog5=true org.apache.derbyTesting.unitTests.harness.UnitTestMain
77     java -DTestBadLog6=true org.apache.derbyTesting.unitTests.harness.UnitTestMain
78     java -DTestBadLog7=true org.apache.derbyTesting.unitTests.harness.UnitTestMain
79     java -DTestBadLog1=true org.apache.derbyTesting.unitTests.harness.UnitTestMain
80
81     To Test Bad Log due to an incomplete out of order write that is identified
82     by the checksum logic (simulated by explicitly corrupting a middle of a
83     log record at the end of log file after it is written).
84     
85     java -DTestBadLogSetup=true -DTestBadChecksumLog=true org.apache.derbyTesting.unitTests.harness.UnitTestMain
86     java -DTestBadLog1=true -DTestBadChecksumLog=true org.apache.derbyTesting.unitTests.harness.UnitTestMain
87     java -DTestBadLog2=true -DTestBadChecksumLog=true org.apache.derbyTesting.unitTests.harness.UnitTestMain
88     java -DTestBadLog3=true -DTestBadChecksumLog=true org.apache.derbyTesting.unitTests.harness.UnitTestMain
89     java -DTestBadLog4=true -DTestBadChecksumLog=true org.apache.derbyTesting.unitTests.harness.UnitTestMain
90     java -DTestBadLog5=true -DTestBadChecksumLog=true org.apache.derbyTesting.unitTests.harness.UnitTestMain
91     java -DTestBadLog6=true -DTestBadChecksumLog=true org.apache.derbyTesting.unitTests.harness.UnitTestMain
92     java -DTestBadLog7=true -DTestBadChecksumLog=true org.apache.derbyTesting.unitTests.harness.UnitTestMain
93     java -DTestBadLog1=true -DTestBadChecksumLog=true org.apache.derbyTesting.unitTests.harness.UnitTestMain
94     
95     
96 */

97
98 public class T_RecoverBadLog extends T_Generic {
99
100     private String JavaDoc testService = "BadLogTest";
101
102     static final String JavaDoc REC_001 = "McLaren";
103     static final String JavaDoc REC_002 = "Ferrari";
104     static final String JavaDoc REC_003 = "Benetton";
105     static final String JavaDoc REC_004 = "Prost";
106     static final String JavaDoc REC_005 = "Tyrell";
107     static final String JavaDoc REC_006 = "Derby, Natscape, Goatscape, the popular names";
108     static final String JavaDoc REC_UNDO = "Lotus";
109
110     static final String JavaDoc SP1 = "savepoint1";
111     static final String JavaDoc SP2 = "savepoint2";
112
113     private RandomAccessFile infofile = null;
114
115     private boolean setup;
116     private boolean test1;
117     private boolean test2;
118     private boolean test3;
119     private boolean test4;
120     private boolean test5;
121     private boolean test6;
122     private boolean test7;
123     private boolean checksumTest;
124     
125     private String JavaDoc infoPath = "extinout/T_RecoverBadLog.info";
126
127     private static final String JavaDoc TEST_BADLOG_SETUP = "TestBadLogSetup";
128     private static final String JavaDoc TEST_BADLOG1 = "TestBadLog1";
129     private static final String JavaDoc TEST_BADLOG2 = "TestBadLog2";
130     private static final String JavaDoc TEST_BADLOG3 = "TestBadLog3";
131     private static final String JavaDoc TEST_BADLOG4 = "TestBadLog4";
132     private static final String JavaDoc TEST_BADLOG5 = "TestBadLog5";
133     private static final String JavaDoc TEST_BADLOG6 = "TestBadLog6";
134     private static final String JavaDoc TEST_BADLOG7 = "TestBadLog7";
135
136     private static final String JavaDoc TEST_BAD_CHECKSUM_LOG = "TestBadChecksumLog";
137
138     private static final String JavaDoc TEST_BADLOG_INFO = "TestBadLogInfo";
139     private static final String JavaDoc TEST_BADCHECKSUMLOG_INFO = "TestBadChecksumLogInfo";
140
141     RawStoreFactory factory;
142     LockFactory lf;
143     LogToFile logFactory;
144     ContextService contextService;
145     T_Util t_util;
146
147     public T_RecoverBadLog() {
148         super();
149     }
150
151     /*
152     ** Methods required by T_Generic
153     */

154
155     public String JavaDoc getModuleToTestProtocolName() {
156         return RawStoreFactory.MODULE;
157     }
158
159     /**
160     */

161     private void getConfig()
162     {
163         String JavaDoc param;
164
165         param = PropertyUtil.getSystemProperty(TEST_BADLOG_SETUP);
166         setup = Boolean.valueOf(param).booleanValue();
167
168         param = PropertyUtil.getSystemProperty(TEST_BADLOG1);
169         test1 = Boolean.valueOf(param).booleanValue();
170
171         param = PropertyUtil.getSystemProperty(TEST_BADLOG2);
172         test2 = Boolean.valueOf(param).booleanValue();
173
174         param = PropertyUtil.getSystemProperty(TEST_BADLOG3);
175         test3 = Boolean.valueOf(param).booleanValue();
176         
177         
178         param = PropertyUtil.getSystemProperty(TEST_BADLOG4);
179         test4 = Boolean.valueOf(param).booleanValue();
180         
181         param = PropertyUtil.getSystemProperty(TEST_BADLOG5);
182         test5 = Boolean.valueOf(param).booleanValue();
183
184         param = PropertyUtil.getSystemProperty(TEST_BADLOG6);
185         test6 = Boolean.valueOf(param).booleanValue();
186
187         param = PropertyUtil.getSystemProperty(TEST_BADLOG7);
188         test7 = Boolean.valueOf(param).booleanValue();
189         
190         param = PropertyUtil.getSystemProperty(TEST_BAD_CHECKSUM_LOG);
191         checksumTest = Boolean.valueOf(param).booleanValue();
192         
193         if(checksumTest)
194         {
195             infoPath = "extinout/T_RecoverBadChecksumLog.info";
196             testService = "BadChecksumLogTest";
197         }
198     }
199
200
201     /**
202         See T_Recovery for the general testing frame work
203
204         @exception T_Fail Unexpected behaviour from the API
205      */

206     public void runTests() throws T_Fail {
207
208         getConfig();
209         int tests = 0;
210         if (setup) tests++;
211         if (test1) tests++;
212         if (test2) tests++;
213         if (test3) tests++;
214         if (test4) tests++;
215         if (test5) tests++;
216         if (test6) tests++;
217         if (test7) tests++;
218         
219         if (tests != 1)
220             throw T_Fail.testFailMsg("One & only one of the bad log recovery test should be run");
221
222         if (!SanityManager.DEBUG)
223         {
224             REPORT("recoverBadLog cannot be run on an insane server");
225             return;
226         }
227
228         try {
229             contextService = ContextService.getFactory();
230
231             File ifile = new File(infoPath);
232
233             //
234
// no checkpoint log record in any of the log files - unless this value
235
// is reset. LogToFile.TEST_LOG_SWITCH_LOG
236
// this will cause recovery to switch log without checkpointing
237
//
238
SanityManager.DEBUG_SET(LogToFile.TEST_LOG_SWITCH_LOG);
239
240             // don't want background checkpoint process to be running
241
SanityManager.DEBUG_SET(DaemonService.DaemonOff);
242
243             // see if we are testing encryption
244
startParams = T_Util.setEncryptionParam(startParams);
245
246             if (setup) // the first test cleans up and start from fresh
247
{
248                 // remove the service directory to ensure a clean run
249
REPORT("_______________________________________________________");
250                 REPORT("\n\t\tcleaning up database for recovering from bad logs");
251                 REPORT("_______________________________________________________");
252
253                 // don't automatic boot this service if it gets left around
254
if (startParams == null)
255                     startParams = new Properties JavaDoc();
256                 
257                 startParams.put(Property.NO_AUTO_BOOT, Boolean.TRUE.toString());
258                 // remove the service directory to ensure a clean run
259
startParams.put(Property.DELETE_ON_CREATE, Boolean.TRUE.toString());
260
261                 factory = (RawStoreFactory) Monitor.createPersistentService(getModuleToTestProtocolName(),
262                                                               testService,
263                                                               startParams);
264                 // create a database with nothing
265

266                 // delete the info file
267
if (ifile.exists())
268                     ifile.delete();
269
270                 return; // don't run anything now
271

272             }
273             else // not setup, recover it
274
{
275                 REPORT("_______________________________________________________");
276                 
277                 String JavaDoc message = "\n\t\tRunning bad log test ";
278                 if (checksumTest)
279                     message = "\n\t\tRunning bad checksum log test ";
280                 if (test1)
281                     REPORT(message + " 1");
282                 if (test2)
283                     REPORT(message + " 2");
284                 if (test3)
285                     REPORT(message + " 3");
286                 if (test4)
287                     REPORT(message + " 4");
288                 if (test5)
289                     REPORT(message + " 5");
290                 if (test6)
291                     REPORT(message + " 6");
292                 if (test7)
293                     REPORT(message + " 7");
294
295                 REPORT("_______________________________________________________");
296
297                 //if external input output files does not exist ,create one
298
File ifdir = new File("extinout");
299                 if(!ifdir.exists())
300                     ifdir.mkdirs();
301
302                 try
303                 {
304                     // make sure it does exist
305
infofile = new RandomAccessFile(ifile, "rw");
306                 }
307                 catch (IOException JavaDoc ioe)
308                 {
309                     System.out.println("Cannot write to temporary file " +
310                                        infoPath +
311                                        ". Please make sure it is correct, if not, please set the property " +
312                                        "TestBadLogInfo=<where temp files should go>");
313                     
314                     throw T_Fail.exceptionFail(ioe);
315                 }
316
317                 if (!Monitor.startPersistentService(testService, startParams))
318                     throw T_Fail.testFailMsg("Monitor didn't know how to restart service: " + testService);
319
320                 factory = (RawStoreFactory) Monitor.findService(getModuleToTestProtocolName(), testService);
321                 logFactory =(LogToFile) Monitor.findServiceModule(factory, factory.getLogFactoryModule());
322                 
323             }
324         } catch (StandardException mse) {
325             throw T_Fail.exceptionFail(mse);
326         }
327
328         if (factory == null) {
329             throw T_Fail.testFailMsg(getModuleToTestProtocolName() + " service not started.");
330         }
331             
332         lf = factory.getLockFactory();
333         if (lf == null) {
334             throw T_Fail.testFailMsg("LockFactory.MODULE not found");
335         }
336
337         // get a utility helper
338
t_util = new T_Util(factory, lf, contextService);
339
340         try {
341             
342
343             // these tests can be run in any order
344
RTest1();
345             RTest2();
346             RTest3();
347             RTest4();
348             RTest5();
349             RTest6();
350             RTest7();
351
352             if (test1)
353                 STest1();
354
355             if (test2)
356                 STest2();
357                 
358             if (test3)
359                 STest3();
360                         
361             if (test4)
362                 STest4();
363
364             if(test5)
365                 STest5();
366
367             if(test6)
368                 STest6();
369
370             if(test7)
371                 STest7();
372
373             if (infofile != null)
374                 infofile.close();
375
376         } catch (StandardException se) {
377
378             throw T_Fail.exceptionFail(se);
379         }
380         catch (IOException JavaDoc ioe)
381         {
382             throw T_Fail.exceptionFail(ioe);
383         }
384     }
385
386     private long find(long inkey)
387     {
388         if (infofile == null)
389             return -1;
390
391         try
392         {
393             infofile.seek(0);
394             long key;
395
396             while(true)
397             {
398                 key = infofile.readLong();
399                 if (key == inkey)
400                 {
401                     long value = infofile.readLong();
402                     // System.out.println("found " + key + " " + value);
403
return value;
404                 }
405                 infofile.readLong();
406             }
407         }
408         catch (IOException JavaDoc ioe)
409         {
410             // System.out.println("key not found " + inkey);
411
return -1;
412         }
413
414     }
415
416     private long key(int test, int param)
417     {
418         long i = test;
419         return ((i << 32) + param);
420     }
421
422     private void register(long key, long value)
423          throws T_Fail
424     {
425         // System.out.println("registering " + key + " " + value);
426
try
427         {
428             // go to the end
429
infofile.seek(infofile.length());
430             infofile.writeLong(key);
431             infofile.writeLong(value);
432         }
433         catch (IOException JavaDoc ioe)
434         {
435             T_Fail.exceptionFail(ioe);
436         }
437     }
438
439
440     /*
441      * test1 manufactures a log with the following recoverable 'defects':
442      * - a log file that only have a single large 1/2 written log record
443      */

444     protected void STest1() throws T_Fail, StandardException
445     {
446         Transaction t = t_util.t_startTransaction();
447
448         ///////////////////////////////////////////
449
//// log switch without checkpoint here ///
450
///////////////////////////////////////////
451
factory.checkpoint();
452
453         try
454         {
455             long cid = t_util.t_addContainer(t, 0);
456             ContainerHandle c = t_util.t_openContainer(t, 0, cid, true);
457
458             Page page = t_util.t_getPage(c, ContainerHandle.FIRST_PAGE_NUMBER);
459
460             // make a really big record - fill 80% of the page
461
int numcol = (int)((RawStoreFactory.PAGE_SIZE_MINIMUM*8)/(10*20));
462
463             T_RawStoreRow bigrow = new T_RawStoreRow(numcol);
464             String JavaDoc string1 = "01234567890123456789"; // 20 char string
465
for (int i = 0; i < numcol; i++)
466                 bigrow.setColumn(i, string1);
467
468             // if overhead is > 80%, then reduce the row size until it fits
469
RecordHandle rh = null;
470             while(numcol > 0)
471             {
472                 try {
473                     rh = t_util.t_insert(page, bigrow);
474                     break;
475                 } catch (StandardException se) {
476                     bigrow.setColumn(--numcol, (String JavaDoc) null);
477                 }
478             }
479             if (numcol == 0)
480                 throw T_Fail.testFailMsg("cannot fit any column into the page");
481
482             
483
484             t_util.t_commit(t);
485
486             // make a big log record - update row
487
String JavaDoc string2 = "abcdefghijklmnopqrst"; // 20 char string
488
for (int i = 0; i < numcol; i++)
489                 bigrow.setColumn(i, string2);
490
491             c = t_util.t_openContainer(t, 0, cid, true);
492             page = t_util.t_getPage(c, ContainerHandle.FIRST_PAGE_NUMBER);
493
494             Page p2 = t_util.t_addPage(c); // do something so we get the beginXact log
495
// record out of the way
496
t_util.t_insert(p2, new T_RawStoreRow(REC_001));
497
498
499             ///////////////////////////////////////////
500
//// log switch without checkpoint here ///
501
///////////////////////////////////////////
502
factory.checkpoint();
503
504             //////////////////////////////////////////////////////////
505
// writing approx 1/2 log record to the end of the log -
506
// NO MORE LOG RECORD SHOULD BE WRITTEN,
507
//////////////////////////////////////////////////////////
508
if(!checksumTest)
509             {
510                 SanityManager.DEBUG_SET(LogToFile.TEST_LOG_INCOMPLETE_LOG_WRITE);
511                 System.setProperty(LogToFile.TEST_LOG_PARTIAL_LOG_WRITE_NUM_BYTES, Integer.toString(numcol*20));
512             }
513             
514             logFactory.flushAll();
515
516             page.update(rh, bigrow.getRow(), (FormatableBitSet) null);
517
518             if(checksumTest)
519                 simulateLogFileCorruption();
520
521             ////////////////////////////////////////////////////////
522

523             REPORT("badlog test1: cid = " + cid + " numcol " + numcol);
524
525             register(key(1,1), cid);
526             register(key(1,2), numcol);
527         }
528         finally
529         {
530             SanityManager.DEBUG_CLEAR(LogToFile.TEST_LOG_INCOMPLETE_LOG_WRITE);
531         }
532     }
533
534     /*
535      * test recovery of test 1
536      */

537     void RTest1() throws T_Fail, StandardException
538     {
539         long cid = find(key(1, 1));
540         if (cid < 0)
541         {
542             REPORT("bad log test1 not run");
543             return;
544         }
545         int numcol = (int)find(key(1,2));
546
547         Transaction t = t_util.t_startTransaction();
548         try
549         {
550             ContainerHandle c = t_util.t_openContainer(t, 0, cid, true);
551             Page page = t_util.t_getPage(c, ContainerHandle.FIRST_PAGE_NUMBER);
552
553             int optimisticNumcol = (int)((RawStoreFactory.PAGE_SIZE_MINIMUM*8)/(10*20));
554             T_RawStoreRow bigrow = new T_RawStoreRow(optimisticNumcol);
555             for (int i = 0; i < optimisticNumcol; i++)
556                 bigrow.setColumn(i, (String JavaDoc) null);
557
558             page.fetchFromSlot(
559                 (RecordHandle) null, 0, bigrow.getRow(),
560                 (FetchDescriptor) null,
561                 false);
562
563             Storable column;
564             String JavaDoc string1 = "01234567890123456789"; // the original 20 char string
565

566             for (int i = 0; i < numcol; i++)
567             {
568                 column = bigrow.getStorableColumn(i);
569                 if (!(column.toString().equals(string1)))
570                     throw T_Fail.testFailMsg("Column " + i + " value incorrect, got :" + column.toString());
571             }
572             for (int i = numcol; i < optimisticNumcol; i++)
573             {
574                 column = bigrow.getStorableColumn(i);
575                 if (!column.isNull())
576                     throw T_Fail.testFailMsg("Column " + i +
577                                              " expect Null, got : " + column.toString());
578             }
579
580             REPORT("RTest1 passed");
581
582         }
583         finally
584         {
585             t_util.t_commit(t);
586             t.close();
587         }
588     }
589
590     /*
591      * test2 manufactures a log with the following recoverable 'defects':
592      * - a log file that ends with a large 1/2 written log record
593      */

594     protected void STest2() throws T_Fail, StandardException
595     {
596         Transaction t = t_util.t_startTransaction();
597
598         try
599         {
600             long cid = t_util.t_addContainer(t, 0);
601             ContainerHandle c = t_util.t_openContainer(t, 0, cid, true);
602
603             Page page = t_util.t_getPage(c, ContainerHandle.FIRST_PAGE_NUMBER);
604
605             // make a really big record - fill 80% of the page with 20 bytes row
606
int numcol = (int)((RawStoreFactory.PAGE_SIZE_MINIMUM*8)/(10*20));
607
608             T_RawStoreRow bigrow = new T_RawStoreRow(numcol);
609             String JavaDoc string1 = "01234567890123456789"; // 20 char string
610
for (int i = 0; i < numcol; i++)
611                 bigrow.setColumn(i, string1);
612
613             // if overhead is > 80%, then reduce the row size until it fits
614
RecordHandle rh = null;
615             while(numcol > 0)
616             {
617                 try {
618                     rh = t_util.t_insert(page, bigrow);
619                     break;
620                 } catch (StandardException se) {
621                     bigrow.setColumn(--numcol, (String JavaDoc) null);
622                 }
623             }
624             if (numcol == 0)
625                 throw T_Fail.testFailMsg("cannot fit any column into the page");
626
627             rh = t_util.t_insert(page, bigrow);
628
629             t_util.t_commit(t);
630
631             // make a big log record - update row
632
String JavaDoc string2 = "abcdefghijklmnopqrst"; // 20 char string
633
for (int i = 0; i < numcol; i++)
634                 bigrow.setColumn(i, string2);
635
636             c = t_util.t_openContainer(t, 0, cid, true);
637             page = t_util.t_getPage(c, ContainerHandle.FIRST_PAGE_NUMBER);
638
639             //////////////////////////////////////////////////////////
640
// writing approx 1/2 log record to the end of the log -
641
// NO MORE LOG RECORD SHOULD BE WRITTEN,
642
//////////////////////////////////////////////////////////
643
if(!checksumTest)
644             {
645                 SanityManager.DEBUG_SET(LogToFile.TEST_LOG_INCOMPLETE_LOG_WRITE);
646                 System.setProperty(LogToFile.TEST_LOG_PARTIAL_LOG_WRITE_NUM_BYTES,Integer.toString(numcol*20));
647             }
648
649             logFactory.flushAll();
650             page.update(rh, bigrow.getRow(), (FormatableBitSet) null);
651             
652             if(checksumTest)
653                 simulateLogFileCorruption();
654
655             ////////////////////////////////////////////////////////
656

657             REPORT("badlog test2: cid = " + cid + " numcol " + numcol);
658
659             register(key(2,1), cid);
660             register(key(2,2), numcol);
661         }
662         finally
663         {
664             SanityManager.DEBUG_CLEAR(LogToFile.TEST_LOG_INCOMPLETE_LOG_WRITE);
665         }
666     }
667
668     /*
669      * test recovery of test 2
670      */

671     void RTest2() throws T_Fail, StandardException
672     {
673         long cid = find(key(2, 1));
674         if (cid < 0)
675         {
676             REPORT("bad log test2 not run");
677             return;
678         }
679         int numcol = (int)find(key(2,2));
680
681         Transaction t = t_util.t_startTransaction();
682         try
683         {
684             ContainerHandle c = t_util.t_openContainer(t, 0, cid, true);
685             Page page = t_util.t_getPage(c, ContainerHandle.FIRST_PAGE_NUMBER);
686
687             int optimisticNumcol = (int)((RawStoreFactory.PAGE_SIZE_MINIMUM*8)/(10*20));
688             T_RawStoreRow bigrow = new T_RawStoreRow(optimisticNumcol);
689             for (int i = 0; i < optimisticNumcol; i++)
690                 bigrow.setColumn(i, (String JavaDoc) null);
691
692             page.fetchFromSlot(
693                 (RecordHandle) null, 0, bigrow.getRow(),
694                 (FetchDescriptor) null,
695                 false);
696             Storable column;
697             String JavaDoc string1 = "01234567890123456789"; // the original 20 char string
698

699             for (int i = 0; i < numcol; i++)
700             {
701                 column = bigrow.getStorableColumn(i);
702                 if (!(column.toString().equals(string1)))
703                     throw T_Fail.testFailMsg("Column " + i + " value incorrect, got :" + column.toString());
704             }
705             for (int i = numcol; i < optimisticNumcol; i++)
706             {
707                 column = bigrow.getStorableColumn(i);
708                 if (!column.isNull())
709                     throw T_Fail.testFailMsg("Column " + i +
710                                              " expect Null, got : " + column.toString());
711             }
712
713             REPORT("RTest2 passed");
714
715         }
716         finally
717         {
718             t_util.t_commit(t);
719             t.close();
720         }
721     }
722
723
724
725     /*
726      * test3 manufactures a log with the following recoverable 'defects':
727      * - a log with multiple files but no checkpoint log record
728      * - a last log file with a paritally written log record at the end
729      */

730     protected void STest3() throws T_Fail, StandardException
731     {
732         int numtrans = 7;
733         int numpages = 7;
734         int i,j;
735
736         // this is basically T_Recovery S203 with a couple of log switches
737
try
738         {
739             T_TWC[] t = new T_TWC[numtrans];
740             for (i = 0; i < numtrans; i++)
741                 t[i] = t_util.t_startTransactionWithContext();
742
743             long[] cid = new long[numtrans];
744             ContainerHandle[] c = new ContainerHandle[numtrans];
745
746             for (i = 0; i < numtrans; i++)
747             {
748                 cid[i] = t_util.t_addContainer(t[i], 0);
749                 t_util.t_commit(t[i]);
750                 c[i] = t_util.t_openContainer(t[i], 0, cid[i], true);
751             }
752
753             Page page[][] = new Page[numtrans][numpages];
754             long pagenum[][] = new long[numtrans][numpages];
755
756             for (i = 0; i < numtrans; i++)
757             {
758                 for (j = 0; j < numpages; j++)
759                 {
760                     t[i].switchTransactionContext();
761                     page[i][j] = t_util.t_addPage(c[i]);
762                     pagenum[i][j] = page[i][j].getPageNumber();
763                     t[i].resetContext();
764                 }
765             }
766
767             // set up numtrans (at least 5) transactions, each with one
768
// container and numpages pages. Do the following test:
769
//
770
// 1) insert 1 row onto each page
771
// set savepoint SP1 on first transaction (t0)
772
//
773
// 2) update every rows
774
// set savepoint SP1 on all other transactions
775
//
776
// 3) update every rows
777
// set savepoint SP2 on all transactions
778
//
779
// 4) update every rows
780
//
781
// 5) rollback t0 to SP1
782
//
783
// check that only page[0][x] have been rolled back
784
// past SP2
785
//
786
// 6) update every row
787
// 7) rollback SP2 on all transaction except the first
788
//
789
// 8) update every rows
790
// 9) rollback t0 to SP1
791
//
792
// 10) leave transactions in the following state
793
// t0 - incomplete
794
// t1 - abort
795
// t2 - commit
796
// t3 - incomplete
797
// t4 - commit
798
// any other transactions - incomplete
799

800
801             //////////////////////// step 1 ////////////////////////
802
RecordHandle[][] rh = new RecordHandle[numtrans][numpages];
803             T_RawStoreRow row1 = new T_RawStoreRow(REC_001);
804             for (i = 0; i < numtrans; i++)
805                 for (j = 0; j < numpages; j++)
806                 {
807                     t[i].switchTransactionContext();
808                     rh[i][j] = t_util.t_insert(page[i][j], row1);
809                     t[i].resetContext();
810                 }
811
812             t[0].setSavePoint(SP1, null); // sp1
813

814             //////////////////////// step 2 ////////////////////////
815
T_RawStoreRow row2 = new T_RawStoreRow(REC_002);
816             for (i = 0; i < numtrans; i++)
817                 for (j = 0; j < numpages; j++)
818                 {
819                     t[i].switchTransactionContext();
820                     page[i][j].update(rh[i][j], row2.getRow(), (FormatableBitSet) null);
821                     t[i].resetContext();
822                 }
823
824             for (i = 1; i < numtrans; i++) // sp1
825
{
826                 t[i].setSavePoint(SP1, null);
827             }
828
829             ///////////////////////////////////////////
830
//// log switch without checkpoint here ///
831
///////////////////////////////////////////
832
factory.checkpoint();
833
834
835             //////////////////////// step 3 ////////////////////////
836
T_RawStoreRow row3 = new T_RawStoreRow(REC_003);
837             for (i = 0; i < numtrans; i++)
838                 for (j = 0; j < numpages; j++)
839                     page[i][j].update(rh[i][j], row3.getRow(), (FormatableBitSet) null);
840
841             for (i = 0; i < numtrans; i++)
842                 t[i].setSavePoint(SP2, null); // sp2
843

844             //////////////////////// step 4 ////////////////////////
845
T_RawStoreRow row4 = new T_RawStoreRow(REC_004);
846             for (i = 0; i < numtrans; i++)
847             {
848                 t[i].switchTransactionContext();
849
850                 for (j = 0; j < numpages; j++)
851                     page[i][j].update(rh[i][j], row4.getRow(), (FormatableBitSet) null);
852                 t[i].resetContext();
853             }
854
855
856             //////////////////////// step 5 ////////////////////////
857
// unlatch relavante pages
858
t[0].switchTransactionContext();
859
860             for (j = 0; j < numpages; j++)
861                 page[0][j].unlatch();
862
863             t[0].rollbackToSavePoint(SP1, null); // step 5
864

865             // relatch relavante pages
866
for (j = 0; j < numpages; j++)
867                 page[0][j] = t_util.t_getPage(c[0], pagenum[0][j]);
868
869             t[0].resetContext();
870
871             ///////////////////////////////////////////
872
//// log switch without checkpoint here ///
873
///////////////////////////////////////////
874
factory.checkpoint();
875
876
877             //////////////////////// check ////////////////////////
878
for (i = 1; i < numtrans; i++)
879             {
880                 t[i].switchTransactionContext();
881                 for (j = 0; j < numpages; j++)
882                     t_util.t_checkFetch(page[i][j], rh[i][j], REC_004);
883                 t[i].resetContext();
884             }
885
886             t[0].switchTransactionContext();
887             for (j = 0; j < numpages; j++)
888                 t_util.t_checkFetch(page[0][j], rh[0][j], REC_001);
889             t[0].resetContext();
890
891             //////////////////////// step 6 ////////////////////////
892
T_RawStoreRow row5 = new T_RawStoreRow(REC_005);
893             for (i = 0; i < numtrans; i++)
894             {
895                 t[i].switchTransactionContext();
896                 for (j = 0; j < numpages; j++)
897                     page[i][j].update(rh[i][j], row5.getRow(), (FormatableBitSet) null);
898                 t[i].resetContext();
899             }
900
901             //////////////////////// step 7 ////////////////////////
902
for (i = 1; i < numtrans; i++)
903             {
904                 t[i].switchTransactionContext();
905
906                 for (j = 0; j < numpages; j++)
907                     page[i][j].unlatch();
908
909                 t[i].rollbackToSavePoint(SP2, null);
910
911                 for (j = 0; j < numpages; j++)
912                     page[i][j] = t_util.t_getPage(c[i],pagenum[i][j]);
913                 t[i].resetContext();
914             }
915
916             //////////////////////// check ////////////////////////
917
for (i = 1; i < numtrans; i++)
918             {
919                 t[i].switchTransactionContext();
920                 for (j = 0; j < numpages; j++)
921                     t_util.t_checkFetch(page[i][j], rh[i][j], REC_003);
922                 t[i].resetContext();
923             }
924
925             t[0].switchTransactionContext();
926             for (j = 0; j < numpages; j++)
927                 t_util.t_checkFetch(page[0][j], rh[0][j], REC_005);
928
929             t[0].resetContext();
930
931             ///////////////////////////////////////////
932
//// log switch without checkpoint here ///
933
///////////////////////////////////////////
934
factory.checkpoint();
935
936
937             //////////////////////// step 8 ////////////////////////
938
T_RawStoreRow row6 = new T_RawStoreRow(REC_006);
939             for (i = 0; i < numtrans; i++)
940             {
941                 t[i].switchTransactionContext();
942                 for (j = 0; j < numpages; j++)
943                     page[i][j].update(rh[i][j], row6.getRow(), (FormatableBitSet) null); // step 8
944
t[i].resetContext();
945             }
946
947             //////////////////////// step 9 ////////////////////////
948
// unlatch relavante pages
949
t[0].switchTransactionContext();
950             for (j = 0; j < numpages; j++)
951                 page[0][j].unlatch();
952
953             t[0].rollbackToSavePoint(SP1, null);
954
955             // relatch relevant pages
956
for (j = 0; j < numpages; j++)
957                 page[0][j] = t_util.t_getPage(c[0], pagenum[0][j]);
958
959             t[0].resetContext();
960             //////////////////////// check ////////////////////////
961
for (i = 1; i < numtrans; i++)
962             {
963                 t[i].switchTransactionContext();
964
965                 for (j = 0; j < numpages; j++)
966                 {
967                     t_util.t_checkFetch(page[i][j], rh[i][j], REC_006);
968                     t_util.t_checkRecordCount(page[i][j], 1, 1);
969                 }
970                 t[i].resetContext();
971             }
972
973             t[0].switchTransactionContext();
974             for (j = 0; j < numpages; j++)
975             {
976                 t_util.t_checkFetch(page[0][j], rh[0][j], REC_001);
977                 t_util.t_checkRecordCount(page[0][j], 1, 1);
978             }
979             t[0].resetContext();
980
981             //////////////////////// step 10 ////////////////////////
982
// unlatch all pages
983
for (i = 0; i < numtrans; i++)
984             {
985                 t[i].switchTransactionContext();
986                 for (j = 0; j < numpages; j++)
987                     page[i][j].unlatch();
988                 t[i].resetContext();
989             }
990
991             // t[0] incomplete
992
t_util.t_abort(t[1]);
993             t_util.t_commit(t[2]);
994             // t[3] incomplete
995
t_util.t_commit(t[4]);
996
997             // reopen containers 1, 2, and 4, where were closed when the
998
// transaction terminated.
999
c[1] = t_util.t_openContainer(t[1], 0, cid[1], false);
1000            c[2] = t_util.t_openContainer(t[2], 0, cid[2], false);
1001            c[4] = t_util.t_openContainer(t[4], 0, cid[4], false);
1002
1003            //////////////////////// check ////////////////////////
1004
for (j = 0; j < numpages; j++)
1005            {
1006                t[0].switchTransactionContext();
1007                t_util.t_checkFetch(c[0], rh[0][j], REC_001);
1008                t[0].resetContext();
1009
1010                // t[1] has been aborted
1011
// rh[1][j] (REC_001) is deleted
1012
t[1].switchTransactionContext();
1013                page[1][j] = t_util.t_getPage(c[1], pagenum[1][j]);
1014                t_util.t_checkRecordCount(page[1][j], 1, 0);
1015                t_util.t_checkFetchBySlot(page[1][j], Page.FIRST_SLOT_NUMBER,
1016                                   REC_001, true, false);
1017                page[1][j].unlatch();
1018                t[1].resetContext();
1019
1020                t[2].switchTransactionContext();
1021                t_util.t_checkFetch(c[2], rh[2][j], REC_006);
1022                t[2].resetContext();
1023
1024                t[3].switchTransactionContext();
1025                t_util.t_checkFetch(c[3], rh[3][j], REC_006);
1026                t[3].resetContext();
1027
1028                t[4].switchTransactionContext();
1029                t_util.t_checkFetch(c[4], rh[4][j], REC_006);
1030                t[4].resetContext();
1031            }
1032
1033
1034            ///////////////////////////////////////////////////////////
1035
//// now write a 1/2 log record to the end of the log
1036
//////////////////////////////////////////////////////////
1037
t[3].switchTransactionContext();// this is going to be an
1038
// incomplete transaction
1039

1040            // make a full page and then copy and purge it to another page
1041
Page badPage1 = t_util.t_addPage(c[3]);
1042            Page badPage2 = t_util.t_addPage(c[3]);
1043            T_RawStoreRow row;
1044            for (i = 0, row = new T_RawStoreRow("row at slot " + i);
1045                 badPage1.spaceForInsert();
1046                 i++, row = new T_RawStoreRow("row at slot " + i))
1047            {
1048                if (t_util.t_insertAtSlot(badPage1, i, row, Page.INSERT_UNDO_WITH_PURGE) == null)
1049                    break;
1050            }
1051
1052            //////////////////////////////////////////////////////////
1053
// writing 200 bytes of the log record to the end of the log -
1054
// NO MORE LOG RECORD SHOULD BE WRITTEN,
1055
//////////////////////////////////////////////////////////
1056
if(!checksumTest)
1057            {
1058                SanityManager.DEBUG_SET(LogToFile.TEST_LOG_INCOMPLETE_LOG_WRITE);
1059                System.setProperty(LogToFile.TEST_LOG_PARTIAL_LOG_WRITE_NUM_BYTES, "200");
1060            }
1061            logFactory.flushAll();
1062
1063
1064            // RESOLVE:
1065
// copy and purge actually generates 2 log records, this is
1066
// actually not a good operation to use for this test. Just make
1067
// sure the first log record is > 400 or else the log will be hosed
1068
//
1069
badPage1.copyAndPurge(badPage2, 0, i, 0);
1070
1071            t[3].resetContext();
1072
1073            if(checksumTest)
1074                simulateLogFileCorruption();
1075
1076            ////////////////////////////////////////////////////////
1077

1078            REPORT("badlog test3: numtrans " + numtrans + " numpages " + numpages);
1079
1080            for (i = 0; i < numtrans; i++)
1081            {
1082                register(key(3, i+10), cid[i]);
1083
1084                String JavaDoc str = "container " + i + ":" + find(key(3,i+10)) + " pages: ";
1085
1086                for (j = 0; j < numpages; j++)
1087                {
1088                    str += pagenum[i][j] + " ";
1089                    register(key(3, (i+1)*1000+j), pagenum[i][j]);
1090                }
1091                REPORT("\t" + str);
1092            }
1093
1094            register(key(3,1), numtrans);
1095            register(key(3,2), numpages);
1096            register(key(3,3), badPage1.getPageNumber());
1097            register(key(3,4), badPage2.getPageNumber());
1098
1099        }
1100        finally
1101        {
1102            SanityManager.DEBUG_CLEAR(LogToFile.TEST_LOG_INCOMPLETE_LOG_WRITE);
1103        }
1104    }
1105
1106    /*
1107     * test recovery of test3
1108     */

1109    void RTest3() throws T_Fail, StandardException
1110    {
1111        int numtrans = (int)find(key(3,1));
1112        if (numtrans < 0)
1113        {
1114            REPORT("bad log test3 not run");
1115            return;
1116        }
1117
1118        int numpages = (int)find(key(3,2));
1119        long badPagenum1 = find(key(3,3)); // these two pages are involved in
1120
// the 1/2 written log record, make
1121
// sure they are not corrupted
1122
long badPagenum2 = find(key(3,4));
1123
1124        Transaction t = t_util.t_startTransaction();
1125
1126        long[] cid = new long[numtrans];
1127        ContainerHandle[] c = new ContainerHandle[numtrans];
1128
1129        long[][] pagenum = new long[numtrans][numpages];
1130        Page[][] page = new Page[numtrans][numpages];
1131
1132        int i,j;
1133
1134        for (i = 0; i < numtrans; i++)
1135        {
1136            cid[i] = find(key(3, i+10));
1137
1138            c[i] = t_util.t_openContainer(t, 0, cid[i], true);
1139            
1140            for (j = 0; j < numpages; j++)
1141            {
1142                pagenum[i][j] = find(key(3, (i+1)*1000+j));
1143
1144                page[i][j] = t_util.t_getPage(c[i], pagenum[i][j]);
1145            }
1146        }
1147
1148        // transactions were left in the following state
1149
// t0 - incomplete (rolled back)
1150
// t1 - abort
1151
// t2 - commit
1152
// t3 - incomplete (rolled back)
1153
// t4 - commit
1154
// any other transactions - incomplete
1155
//
1156
// all the rolled back transaction should have a deleted REC_001
1157
// all the committed transactions should have a REC_006
1158
//
1159
try
1160        {
1161            for (j = 0; j < numpages; j++)
1162            {
1163                t_util.t_checkRecordCount(page[0][j], 1, 0);
1164                t_util.t_checkFetchBySlot(page[0][j], Page.FIRST_SLOT_NUMBER,
1165                                   REC_001, true, true);
1166
1167                t_util.t_checkRecordCount(page[1][j], 1, 0);
1168                t_util.t_checkFetchBySlot(page[1][j], Page.FIRST_SLOT_NUMBER,
1169                                   REC_001, true, true);
1170
1171                t_util.t_checkRecordCount(page[2][j], 1, 1);
1172                t_util.t_checkFetchBySlot(page[2][j], Page.FIRST_SLOT_NUMBER,
1173                                   REC_006, false, true);
1174
1175                t_util.t_checkRecordCount(page[3][j], 1, 0);
1176                t_util.t_checkFetchBySlot(page[3][j], Page.FIRST_SLOT_NUMBER,
1177                                   REC_001, true, true);
1178
1179                t_util.t_checkRecordCount(page[4][j], 1, 1);
1180                t_util.t_checkFetchBySlot(page[4][j], Page.FIRST_SLOT_NUMBER,
1181                                   REC_006, false, true);
1182            }
1183
1184            // now check the two bad pages - they are in c[3] and should be empty
1185
Page badPage1 = t_util.t_getPage(c[3], badPagenum1);
1186            Page badPage2 = t_util.t_getPage(c[3], badPagenum2);
1187            t_util.t_checkRecordCount(badPage1, 0, 0);
1188            t_util.t_checkRecordCount(badPage2, 0, 0);
1189
1190            REPORT("RTest3 passed: numtrans " + numtrans + " numpages " + numpages);
1191
1192            for (i = 0; i < numtrans; i++)
1193            {
1194                String JavaDoc str = "container " + i + ":" + cid[i] + " pages: ";
1195                for (j = 0; j < numpages; j++)
1196                    str += pagenum[i][j] + " ";
1197                REPORT("\t" + str);
1198            }
1199        }
1200        finally
1201        {
1202            t_util.t_commit(t);
1203            t.close();
1204        }
1205    }
1206
1207        
1208    /*
1209     * test4 manufactures a log with the following recoverable 'defects':
1210     * - a log file that only has the partial log instance(7 bytes instead of 8
1211     * bytes writtne) of a log record written
1212     */

1213    protected void STest4() throws T_Fail, StandardException
1214    {
1215        Transaction t = t_util.t_startTransaction();
1216
1217        try
1218        {
1219            long cid = t_util.t_addContainer(t, 0);
1220            ContainerHandle c = t_util.t_openContainer(t, 0, cid, true);
1221
1222            Page page = t_util.t_getPage(c, ContainerHandle.FIRST_PAGE_NUMBER);
1223
1224            // make a really big record - fill 80% of the page
1225
int numcol = (int)((RawStoreFactory.PAGE_SIZE_MINIMUM*8)/(10*20));
1226
1227            T_RawStoreRow bigrow = new T_RawStoreRow(numcol);
1228            String JavaDoc string1 = "01234567890123456789"; // 20 char string
1229
for (int i = 0; i < numcol; i++)
1230                bigrow.setColumn(i, string1);
1231
1232            // if overhead is > 80%, then reduce the row size until it fits
1233
RecordHandle rh = null;
1234            while(numcol > 0)
1235            {
1236                try {
1237                    rh = t_util.t_insert(page, bigrow);
1238                    break;
1239                } catch (StandardException se) {
1240                    bigrow.setColumn(--numcol, (String JavaDoc) null);
1241                }
1242            }
1243            if (numcol == 0)
1244                throw T_Fail.testFailMsg("cannot fit any column into the page");
1245
1246            
1247
1248            t_util.t_commit(t);
1249
1250            // make a big log record - update row
1251
String JavaDoc string2 = "abcdefghijklmnopqrst"; // 20 char string
1252
for (int i = 0; i < numcol; i++)
1253                bigrow.setColumn(i, string2);
1254
1255            c = t_util.t_openContainer(t, 0, cid, true);
1256            page = t_util.t_getPage(c, ContainerHandle.FIRST_PAGE_NUMBER);
1257
1258            Page p2 = t_util.t_addPage(c); // do something so we get the beginXact log
1259
// record out of the way
1260
t_util.t_insert(p2, new T_RawStoreRow(REC_001));
1261
1262
1263            //////////////////////////////////////////////////////////
1264
// writing approx 1/2 of log record instance to the end of the log -
1265
// NO MORE LOG RECORD SHOULD BE WRITTEN,
1266
// Length 4 bytes + 7(8) bytes of log record instance
1267
//////////////////////////////////////////////////////////
1268
if(!checksumTest)
1269            {
1270                SanityManager.DEBUG_SET(LogToFile.TEST_LOG_INCOMPLETE_LOG_WRITE);
1271                System.setProperty(LogToFile.TEST_LOG_PARTIAL_LOG_WRITE_NUM_BYTES, Integer.toString(11));
1272            }
1273
1274            logFactory.flushAll();
1275            page.update(rh, bigrow.getRow(), (FormatableBitSet) null);
1276
1277            if(checksumTest)
1278                simulateLogFileCorruption();
1279
1280            ////////////////////////////////////////////////////////
1281

1282            REPORT("badlog test4: cid = " + cid + " numcol " + numcol);
1283
1284            register(key(4,1), cid);
1285            register(key(4,2), numcol);
1286        }
1287        finally
1288        {
1289            SanityManager.DEBUG_CLEAR(LogToFile.TEST_LOG_INCOMPLETE_LOG_WRITE);
1290        }
1291    }
1292
1293    /*
1294     * test recovery of test 4
1295     */

1296    void RTest4() throws T_Fail, StandardException
1297    {
1298        long cid = find(key(4, 1));
1299        if (cid < 0)
1300        {
1301            REPORT("bad log test4 not run");
1302            return;
1303        }
1304        int numcol = (int)find(key(4,2));
1305
1306        Transaction t = t_util.t_startTransaction();
1307        try
1308        {
1309            ContainerHandle c = t_util.t_openContainer(t, 0, cid, true);
1310            Page page = t_util.t_getPage(c, ContainerHandle.FIRST_PAGE_NUMBER);
1311
1312            int optimisticNumcol = (int)((RawStoreFactory.PAGE_SIZE_MINIMUM*8)/(10*20));
1313            T_RawStoreRow bigrow = new T_RawStoreRow(optimisticNumcol);
1314            for (int i = 0; i < optimisticNumcol; i++)
1315                bigrow.setColumn(i, (String JavaDoc) null);
1316
1317            page.fetchFromSlot(
1318                (RecordHandle) null, 0, bigrow.getRow(),
1319                (FetchDescriptor) null,
1320                false);
1321
1322            Storable column;
1323            String JavaDoc string1 = "01234567890123456789"; // the original 20 char string
1324

1325            for (int i = 0; i < numcol; i++)
1326            {
1327                column = bigrow.getStorableColumn(i);
1328                if (!(column.toString().equals(string1)))
1329                    throw T_Fail.testFailMsg("Column " + i + " value incorrect, got :" + column.toString());
1330            }
1331            for (int i = numcol; i < optimisticNumcol; i++)
1332            {
1333                column = bigrow.getStorableColumn(i);
1334                if (!column.isNull())
1335                    throw T_Fail.testFailMsg("Column " + i +
1336                                             " expect Null, got : " + column.toString());
1337            }
1338
1339            REPORT("RTest4 passed");
1340
1341        }
1342        finally
1343        {
1344            t_util.t_commit(t);
1345            t.close();
1346        }
1347    }
1348    
1349    /*
1350     * test5 manufactures a log with the following recoverable 'defects':
1351     * - a log file that only has the partial log record length (3 bytes instead of 4
1352     * bytes writtne) of a log record written in the beginning
1353     */

1354    protected void STest5() throws T_Fail, StandardException
1355    {
1356        Transaction t = t_util.t_startTransaction();
1357
1358        try
1359        {
1360            long cid = t_util.t_addContainer(t, 0);
1361            ContainerHandle c = t_util.t_openContainer(t, 0, cid, true);
1362
1363            Page page = t_util.t_getPage(c, ContainerHandle.FIRST_PAGE_NUMBER);
1364
1365            // make a really big record - fill 80% of the page
1366
int numcol = (int)((RawStoreFactory.PAGE_SIZE_MINIMUM*8)/(10*20));
1367
1368            T_RawStoreRow bigrow = new T_RawStoreRow(numcol);
1369            String JavaDoc string1 = "01234567890123456789"; // 20 char string
1370
for (int i = 0; i < numcol; i++)
1371                bigrow.setColumn(i, string1);
1372
1373            // if overhead is > 80%, then reduce the row size until it fits
1374
RecordHandle rh = null;
1375            while(numcol > 0)
1376            {
1377                try {
1378                    rh = t_util.t_insert(page, bigrow);
1379                    break;
1380                } catch (StandardException se) {
1381                    bigrow.setColumn(--numcol, (String JavaDoc) null);
1382                }
1383            }
1384            if (numcol == 0)
1385                throw T_Fail.testFailMsg("cannot fit any column into the page");
1386
1387            
1388
1389            t_util.t_commit(t);
1390
1391            // make a big log record - update row
1392
String JavaDoc string2 = "abcdefghijklmnopqrst"; // 20 char string
1393
for (int i = 0; i < numcol; i++)
1394                bigrow.setColumn(i, string2);
1395
1396            c = t_util.t_openContainer(t, 0, cid, true);
1397            page = t_util.t_getPage(c, ContainerHandle.FIRST_PAGE_NUMBER);
1398
1399            Page p2 = t_util.t_addPage(c); // do something so we get the beginXact log
1400
// record out of the way
1401
t_util.t_insert(p2, new T_RawStoreRow(REC_001));
1402
1403
1404            //////////////////////////////////////////////////////////
1405
// writing approx 3 bytes of log record to the end of the log -
1406
// NO MORE LOG RECORD SHOULD BE WRITTEN,
1407
// Length 3 bytes (4) of log record length
1408
//////////////////////////////////////////////////////////
1409
if(!checksumTest)
1410            {
1411                SanityManager.DEBUG_SET(LogToFile.TEST_LOG_INCOMPLETE_LOG_WRITE);
1412                System.setProperty(LogToFile.TEST_LOG_PARTIAL_LOG_WRITE_NUM_BYTES, Integer.toString(3));
1413            }
1414            logFactory.flushAll();
1415
1416            page.update(rh, bigrow.getRow(), (FormatableBitSet) null);
1417
1418            if(checksumTest)
1419                simulateLogFileCorruption();
1420
1421            ////////////////////////////////////////////////////////
1422

1423            REPORT("badlog test5: cid = " + cid + " numcol " + numcol);
1424
1425            register(key(5,1), cid);
1426            register(key(5,2), numcol);
1427        }
1428        finally
1429        {
1430            SanityManager.DEBUG_CLEAR(LogToFile.TEST_LOG_INCOMPLETE_LOG_WRITE);
1431        }
1432    }
1433
1434    /*
1435     * test recovery of test 5
1436     */

1437    void RTest5() throws T_Fail, StandardException
1438    {
1439        long cid = find(key(5, 1));
1440        if (cid < 0)
1441        {
1442            REPORT("bad log test5 not run");
1443            return;
1444        }
1445        int numcol = (int)find(key(5,2));
1446
1447        Transaction t = t_util.t_startTransaction();
1448        try
1449        {
1450            ContainerHandle c = t_util.t_openContainer(t, 0, cid, true);
1451            Page page = t_util.t_getPage(c, ContainerHandle.FIRST_PAGE_NUMBER);
1452
1453            int optimisticNumcol = (int)((RawStoreFactory.PAGE_SIZE_MINIMUM*8)/(10*20));
1454            T_RawStoreRow bigrow = new T_RawStoreRow(optimisticNumcol);
1455            for (int i = 0; i < optimisticNumcol; i++)
1456                bigrow.setColumn(i, (String JavaDoc) null);
1457
1458            page.fetchFromSlot(
1459                (RecordHandle) null, 0, bigrow.getRow(),
1460                (FetchDescriptor) null,
1461                false);
1462
1463            Storable column;
1464            String JavaDoc string1 = "01234567890123456789"; // the original 20 char string
1465

1466            for (int i = 0; i < numcol; i++)
1467            {
1468                column = bigrow.getStorableColumn(i);
1469                if (!(column.toString().equals(string1)))
1470                    throw T_Fail.testFailMsg("Column " + i + " value incorrect, got :" + column.toString());
1471            }
1472            for (int i = numcol; i < optimisticNumcol; i++)
1473            {
1474                column = bigrow.getStorableColumn(i);
1475                if (!column.isNull())
1476                    throw T_Fail.testFailMsg("Column " + i +
1477                                             " expect Null, got : " + column.toString());
1478            }
1479
1480            REPORT("RTest5 passed");
1481
1482        }
1483        finally
1484        {
1485            t_util.t_commit(t);
1486            t.close();
1487        }
1488    }
1489        
1490    /*
1491     * test6 manufactures a log with the following recoverable 'defects':
1492     * - a log file that only has the log record with partial data portion
1493     * written (approximately (1997/2 (data)+ 16(log records ov))) */

1494    protected void STest6() throws T_Fail, StandardException
1495    {
1496        Transaction t = t_util.t_startTransaction();
1497
1498        try
1499        {
1500            long cid = t_util.t_addContainer(t, 0);
1501            ContainerHandle c = t_util.t_openContainer(t, 0, cid, true);
1502
1503            Page page = t_util.t_getPage(c, ContainerHandle.FIRST_PAGE_NUMBER);
1504
1505            // make a really big record - fill 80% of the page
1506
int numcol = (int)((RawStoreFactory.PAGE_SIZE_MINIMUM*8)/(10*20));
1507
1508            T_RawStoreRow bigrow = new T_RawStoreRow(numcol);
1509            String JavaDoc string1 = "01234567890123456789"; // 20 char string
1510
for (int i = 0; i < numcol; i++)
1511                bigrow.setColumn(i, string1);
1512
1513            // if overhead is > 80%, then reduce the row size until it fits
1514
RecordHandle rh = null;
1515            while(numcol > 0)
1516            {
1517                try {
1518                    rh = t_util.t_insert(page, bigrow);
1519                    break;
1520                } catch (StandardException se) {
1521                    bigrow.setColumn(--numcol, (String JavaDoc) null);
1522                }
1523            }
1524            if (numcol == 0)
1525                throw T_Fail.testFailMsg("cannot fit any column into the page");
1526
1527            
1528
1529            t_util.t_commit(t);
1530
1531            // make a big log record - update row
1532
String JavaDoc string2 = "abcdefghijklmnopqrst"; // 20 char string
1533
for (int i = 0; i < numcol; i++)
1534                bigrow.setColumn(i, string2);
1535
1536            c = t_util.t_openContainer(t, 0, cid, true);
1537            page = t_util.t_getPage(c, ContainerHandle.FIRST_PAGE_NUMBER);
1538
1539            Page p2 = t_util.t_addPage(c); // do something so we get the beginXact log
1540
// record out of the way
1541
t_util.t_insert(p2, new T_RawStoreRow(REC_001));
1542
1543
1544            //////////////////////////////////////////////////////////
1545
// writing (1997/2 (data)+ 16(log records ov)) bytes of log record to the end of the log -
1546
// NO MORE LOG RECORD SHOULD BE WRITTEN,
1547
//////////////////////////////////////////////////////////
1548
if(!checksumTest)
1549            {
1550                SanityManager.DEBUG_SET(LogToFile.TEST_LOG_INCOMPLETE_LOG_WRITE);
1551                System.setProperty(LogToFile.TEST_LOG_PARTIAL_LOG_WRITE_NUM_BYTES, Integer.toString((1997/2) + 16));
1552            }
1553            logFactory.flushAll();
1554            page.update(rh, bigrow.getRow(), (FormatableBitSet) null);
1555
1556            if(checksumTest)
1557                simulateLogFileCorruption();
1558
1559            ////////////////////////////////////////////////////////
1560

1561            REPORT("badlog test6: cid = " + cid + " numcol " + numcol);
1562
1563            register(key(6,1), cid);
1564            register(key(6,2), numcol);
1565        }
1566        finally
1567        {
1568            SanityManager.DEBUG_CLEAR(LogToFile.TEST_LOG_INCOMPLETE_LOG_WRITE);
1569        }
1570    }
1571
1572    /*
1573     * test recovery of test 6
1574     */

1575    void RTest6() throws T_Fail, StandardException
1576    {
1577        long cid = find(key(6, 1));
1578        if (cid < 0)
1579        {
1580            REPORT("bad log test6 not run");
1581            return;
1582        }
1583        int numcol = (int)find(key(6,2));
1584
1585        Transaction t = t_util.t_startTransaction();
1586        try
1587        {
1588            ContainerHandle c = t_util.t_openContainer(t, 0, cid, true);
1589            Page page = t_util.t_getPage(c, ContainerHandle.FIRST_PAGE_NUMBER);
1590
1591            int optimisticNumcol = (int)((RawStoreFactory.PAGE_SIZE_MINIMUM*8)/(10*20));
1592            T_RawStoreRow bigrow = new T_RawStoreRow(optimisticNumcol);
1593            for (int i = 0; i < optimisticNumcol; i++)
1594                bigrow.setColumn(i, (String JavaDoc) null);
1595
1596            page.fetchFromSlot(
1597                (RecordHandle) null, 0, bigrow.getRow(),
1598                (FetchDescriptor) null,
1599                false);
1600
1601            Storable column;
1602            String JavaDoc string1 = "01234567890123456789"; // the original 20 char string
1603

1604            for (int i = 0; i < numcol; i++)
1605            {
1606                column = bigrow.getStorableColumn(i);
1607                if (!(column.toString().equals(string1)))
1608                    throw T_Fail.testFailMsg("Column " + i + " value incorrect, got :" + column.toString());
1609            }
1610            for (int i = numcol; i < optimisticNumcol; i++)
1611            {
1612                column = bigrow.getStorableColumn(i);
1613                if (!column.isNull())
1614                    throw T_Fail.testFailMsg("Column " + i +
1615                                             " expect Null, got : " + column.toString());
1616            }
1617
1618            REPORT("RTest6 passed");
1619
1620        }
1621        finally
1622        {
1623            t_util.t_commit(t);
1624            t.close();
1625        }
1626    }
1627    /*
1628     * test7 manufactures a log with the following recoverable 'defects':
1629     * - a log file that has the last log record with partial end length
1630     * written( 3 of 4 bytes). instead of (1997(data) + 16 (log records overhead)) write (1997 + 15)
1631     */

1632    protected void STest7() throws T_Fail, StandardException
1633    {
1634        Transaction t = t_util.t_startTransaction();
1635
1636        try
1637        {
1638            long cid = t_util.t_addContainer(t, 0);
1639            ContainerHandle c = t_util.t_openContainer(t, 0, cid, true);
1640
1641            Page page = t_util.t_getPage(c, ContainerHandle.FIRST_PAGE_NUMBER);
1642
1643            // make a really big record - fill 80% of the page
1644
int numcol = (int)((RawStoreFactory.PAGE_SIZE_MINIMUM*8)/(10*20));
1645
1646            T_RawStoreRow bigrow = new T_RawStoreRow(numcol);
1647            String JavaDoc string1 = "01234567890123456789"; // 20 char string
1648
for (int i = 0; i < numcol; i++)
1649                bigrow.setColumn(i, string1);
1650
1651            // if overhead is > 80%, then reduce the row size until it fits
1652
RecordHandle rh = null;
1653            while(numcol > 0)
1654            {
1655                try {
1656                    rh = t_util.t_insert(page, bigrow);
1657                    break;
1658                } catch (StandardException se) {
1659                    bigrow.setColumn(--numcol, (String JavaDoc) null);
1660                }
1661            }
1662            if (numcol == 0)
1663                throw T_Fail.testFailMsg("cannot fit any column into the page");
1664
1665            
1666
1667            t_util.t_commit(t);
1668
1669            // make a big log record - update row
1670
String JavaDoc string2 = "abcdefghijklmnopqrst"; // 20 char string
1671
for (int i = 0; i < numcol; i++)
1672                bigrow.setColumn(i, string2);
1673
1674            c = t_util.t_openContainer(t, 0, cid, true);
1675            page = t_util.t_getPage(c, ContainerHandle.FIRST_PAGE_NUMBER);
1676
1677            Page p2 = t_util.t_addPage(c); // do something so we get the beginXact log
1678
// record out of the way
1679
t_util.t_insert(p2, new T_RawStoreRow(REC_001));
1680
1681
1682            //////////////////////////////////////////////////////////
1683
// writing only 3 bytes of end length of the log record to the end of the log -
1684
//i.e: instead of (1997(data) + 16 (log records overhead)) write (1997 + 15)
1685
// NO MORE LOG RECORD SHOULD BE WRITTEN,
1686
//////////////////////////////////////////////////////////
1687
if(!checksumTest)
1688            {
1689                SanityManager.DEBUG_SET(LogToFile.TEST_LOG_INCOMPLETE_LOG_WRITE);
1690                System.setProperty(LogToFile.TEST_LOG_PARTIAL_LOG_WRITE_NUM_BYTES, Integer.toString(1997+15));
1691            }
1692            logFactory.flushAll();
1693            page.update(rh, bigrow.getRow(), (FormatableBitSet) null);
1694
1695            if(checksumTest)
1696                simulateLogFileCorruption();
1697
1698
1699            ////////////////////////////////////////////////////////
1700

1701            REPORT("badlog test7: cid = " + cid + " numcol " + numcol);
1702
1703            register(key(7,1), cid);
1704            register(key(7,2), numcol);
1705        }
1706        finally
1707        {
1708            SanityManager.DEBUG_CLEAR(LogToFile.TEST_LOG_INCOMPLETE_LOG_WRITE);
1709        }
1710    }
1711
1712    /*
1713     * test recovery of test 7
1714     */

1715    void RTest7() throws T_Fail, StandardException
1716    {
1717        long cid = find(key(6, 1));
1718        if (cid < 0)
1719        {
1720            REPORT("bad log test7 not run");
1721            return;
1722        }
1723        int numcol = (int)find(key(6,2));
1724
1725        Transaction t = t_util.t_startTransaction();
1726        try
1727        {
1728            ContainerHandle c = t_util.t_openContainer(t, 0, cid, true);
1729            Page page = t_util.t_getPage(c, ContainerHandle.FIRST_PAGE_NUMBER);
1730
1731            int optimisticNumcol = (int)((RawStoreFactory.PAGE_SIZE_MINIMUM*8)/(10*20));
1732            T_RawStoreRow bigrow = new T_RawStoreRow(optimisticNumcol);
1733            for (int i = 0; i < optimisticNumcol; i++)
1734                bigrow.setColumn(i, (String JavaDoc) null);
1735
1736            page.fetchFromSlot(
1737                (RecordHandle) null, 0, bigrow.getRow(),
1738                (FetchDescriptor) null,
1739                false);
1740
1741            Storable column;
1742            String JavaDoc string1 = "01234567890123456789"; // the original 20 char string
1743

1744            for (int i = 0; i < numcol; i++)
1745            {
1746                column = bigrow.getStorableColumn(i);
1747                if (!(column.toString().equals(string1)))
1748                    throw T_Fail.testFailMsg("Column " + i + " value incorrect, got :" + column.toString());
1749            }
1750            for (int i = numcol; i < optimisticNumcol; i++)
1751            {
1752                column = bigrow.getStorableColumn(i);
1753                if (!column.isNull())
1754                    throw T_Fail.testFailMsg("Column " + i +
1755                                             " expect Null, got : " + column.toString());
1756            }
1757
1758            REPORT("RTest7 passed");
1759
1760        }
1761        finally
1762        {
1763            t_util.t_commit(t);
1764            t.close();
1765        }
1766    }
1767
1768
1769
1770    /*
1771     * simulate log corruption to test the checksuming of log records.
1772     */

1773    private void simulateLogFileCorruption() throws T_Fail, StandardException
1774    {
1775        long filenum;
1776        long filepos;
1777        long amountOfLogWritten;
1778        LogCounter logInstant = (LogCounter)logFactory.getFirstUnflushedInstant();
1779        filenum = logInstant.getLogFileNumber();
1780        filepos = logInstant.getLogFilePosition();
1781        logFactory.flushAll();
1782        logInstant = (LogCounter)logFactory.getFirstUnflushedInstant();
1783        filenum = logInstant.getLogFileNumber();
1784        amountOfLogWritten = logInstant.getLogFilePosition() - filepos;
1785
1786        // write some random garbage into the log file ,
1787
// purpose of doing this is to test that recovery works correctly when
1788
// log records in the end of a log file did not get wrtten completely
1789
// and in the correct order.
1790

1791        try{
1792            StorageRandomAccessFile log = logFactory.getLogFileToSimulateCorruption(filenum) ;
1793        
1794            int noWrites = (int) amountOfLogWritten / 512;
1795            //mess up few bytes in every block of a 512 bytes.
1796
filepos += 512;
1797            java.util.Random JavaDoc r = new java.util.Random JavaDoc();
1798            for(int i = 0 ; i < noWrites ; i++)
1799            {
1800                REPORT("corruptig log file : filenum " + filenum + " fileposition " + filepos);
1801                log.seek(filepos);
1802                log.writeInt(r.nextInt());
1803                filepos +=512;
1804
1805            }
1806            log.sync(false);
1807            log.close();
1808        }catch(IOException JavaDoc ie)
1809        {
1810            throw T_Fail.exceptionFail(ie);
1811        }
1812        
1813    }
1814
1815}
1816
1817
1818
1819
Popular Tags