001: /*
002:
003: Derby - Class org.apache.derbyTesting.unitTests.store.T_RecoverFullLog
004:
005: Licensed to the Apache Software Foundation (ASF) under one or more
006: contributor license agreements. See the NOTICE file distributed with
007: this work for additional information regarding copyright ownership.
008: The ASF licenses this file to You under the Apache License, Version 2.0
009: (the "License"); you may not use this file except in compliance with
010: the License. You may obtain a copy of the License at
011:
012: http://www.apache.org/licenses/LICENSE-2.0
013:
014: Unless required by applicable law or agreed to in writing, software
015: distributed under the License is distributed on an "AS IS" BASIS,
016: WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
017: See the License for the specific language governing permissions and
018: limitations under the License.
019:
020: */
021:
022: package org.apache.derbyTesting.unitTests.store;
023:
024: import org.apache.derbyTesting.unitTests.harness.T_Generic;
025: import org.apache.derbyTesting.unitTests.harness.T_Fail;
026:
027: import org.apache.derbyTesting.unitTests.harness.UnitTest;
028:
029: import org.apache.derby.impl.store.raw.log.*;
030:
031: import org.apache.derby.iapi.services.context.ContextService;
032: import org.apache.derby.iapi.services.context.ContextManager;
033: import org.apache.derby.iapi.services.daemon.DaemonService;
034: import org.apache.derby.iapi.services.property.PropertyUtil;
035: import org.apache.derby.iapi.services.monitor.Monitor;
036: import org.apache.derby.iapi.services.monitor.ModuleFactory;
037: import org.apache.derby.iapi.services.locks.LockFactory;
038: import org.apache.derby.iapi.services.io.Storable;
039: import org.apache.derby.iapi.services.sanity.SanityManager;
040: import org.apache.derby.iapi.reference.Property;
041: import org.apache.derby.iapi.reference.EngineType;
042: import org.apache.derby.iapi.services.property.PropertyUtil;
043: import org.apache.derby.iapi.services.io.FormatableBitSet;
044:
045: import org.apache.derby.iapi.error.StandardException;
046:
047: import org.apache.derby.iapi.store.raw.*;
048:
049: import org.apache.derby.iapi.store.access.conglomerate.LogicalUndo;
050:
051: import java.io.IOException;
052: import java.io.RandomAccessFile;
053: import java.io.File;
054: import java.util.Properties;
055:
056: /**
057: A implementation unit test for log full condition
058:
059: To run, create a derby.properties file in a new directory with the
060: contents
061:
062: derby.module.test.recoverFullLog=org.apache.derbyTesting.unitTests.store.T_RecoverFullLog
063:
064: Execute in order
065:
066: java -DTestFillLog=true org.apache.derbyTesting.unitTests.harness.UnitTestMain
067:
068: java -DTestLogSwitchFail=true org.apache.derbyTesting.unitTests.harness.UnitTestMain
069:
070: java -DTestFullRecoveryFail=true org.apache.derbyTesting.unitTests.harness.UnitTestMain
071: (run this serveral times, this simulate recovery running out of log)
072:
073: java -DTestFullRecover=true org.apache.derbyTesting.unitTests.harness.UnitTestMain
074:
075: */
076:
077: public class T_RecoverFullLog extends T_Generic {
078:
079: private static final String testService = "FullLogTest";
080:
081: static final String REC_001 = "McLaren";
082: static final String REC_002 = "Ferrari";
083: static final String REC_003 = "Benetton";
084: static final String REC_004 = "Prost";
085: static final String REC_005 = "Tyrell";
086: static final String REC_006 = "Derby, Natscape, Goatscape, the popular names";
087: static final String REC_UNDO = "Lotus";
088: static final String SP1 = "savepoint1";
089: static final String SP2 = "savepoint2";
090:
091: private RandomAccessFile infofile = null;
092: private static final String infoPath = "extinout/T_RecoverFullLog.info";
093:
094: private boolean fillLog; // test to full up the log
095: private boolean recoveryFail; // recovery fill up the log
096: private boolean logSwitchFail; // log filled up during log switch
097: private boolean recover; // successfully recover
098:
099: private String TEST_FILL_LOG = "TestFillLog"; // test to full up the log
100: private String TEST_FULL_RECOVER_FAIL = "TestFullRecoveryFail"; // recovery fill up the log
101: private String TEST_LOG_SWITCH_FAIL = "TestLogSwitchFail"; // log filled up during log switch
102: private String TEST_FULL_RECOVER = "TestFullRecover"; // successfully recover
103:
104: private static final String TEST_FULL_LOG_INFO = "TestFullLogInfo";
105:
106: RawStoreFactory factory;
107: LockFactory lf;
108: ContextService contextService;
109: T_Util t_util;
110:
111: public T_RecoverFullLog() {
112: super ();
113: }
114:
115: /*
116: ** Methods required by T_Generic
117: */
118:
119: public String getModuleToTestProtocolName() {
120: return RawStoreFactory.MODULE;
121: }
122:
123: /**
124: */
125: private void getConfig() {
126: String param;
127:
128: param = PropertyUtil.getSystemProperty(TEST_FILL_LOG);
129: fillLog = Boolean.valueOf(param).booleanValue();
130:
131: param = PropertyUtil.getSystemProperty(TEST_FULL_RECOVER_FAIL);
132: recoveryFail = Boolean.valueOf(param).booleanValue();
133:
134: param = PropertyUtil.getSystemProperty(TEST_FULL_RECOVER);
135: recover = Boolean.valueOf(param).booleanValue();
136:
137: param = PropertyUtil.getSystemProperty(TEST_LOG_SWITCH_FAIL);
138: logSwitchFail = Boolean.valueOf(param).booleanValue();
139: }
140:
141: /**
142: See T_Recovery for the general testing frame work
143:
144: @exception T_Fail Unexpected behaviour from the API
145: */
146: public void runTests() throws T_Fail {
147:
148: getConfig();
149: int tests = 0;
150: if (fillLog)
151: tests++;
152: if (recoveryFail)
153: tests++;
154: if (recover)
155: tests++;
156: if (logSwitchFail)
157: tests++;
158:
159: if (tests != 1)
160: throw T_Fail
161: .testFailMsg("One & only one of the full log recovery test should be run, now "
162: + tests + " set");
163:
164: if (!SanityManager.DEBUG) {
165: REPORT("recoverBadLog cannot be run on an insane server");
166: return;
167: }
168:
169: try {
170:
171: contextService = ContextService.getFactory();
172:
173: File ifile = new File(infoPath);
174:
175: //if external input output files dir does not exist ,create one
176: File ifdir = new File("extinout");
177: if (!ifdir.exists())
178: ifdir.mkdirs();
179: // see if we are testing encryption
180: startParams = T_Util.setEncryptionParam(startParams);
181:
182: if (fillLog) // the first test cleans up and start from fresh
183: {
184: // remove the service directory to ensure a clean run
185: REPORT("_______________________________________________________");
186: REPORT("\n\t\tcleaning up database for recovering from filled log");
187: REPORT("_______________________________________________________");
188:
189: // don't automatic boot this service if it gets left around
190: if (startParams == null)
191: startParams = new Properties();
192:
193: startParams.put(Property.NO_AUTO_BOOT, Boolean.TRUE
194: .toString());
195: // remove the service directory to ensure a clean run
196: startParams.put(Property.DELETE_ON_CREATE, Boolean.TRUE
197: .toString());
198:
199: factory = (RawStoreFactory) Monitor
200: .createPersistentService(
201: getModuleToTestProtocolName(),
202: testService, startParams);
203: // create a database with nothing
204:
205: // if exist, delete the info file
206: if (ifile.exists())
207: ifile.delete();
208:
209: // create a new info file
210: try {
211: infofile = new RandomAccessFile(ifile, "rw");
212: } catch (IOException ioe) {
213: System.out
214: .println("Cannot write to temporary file "
215: + infoPath
216: + ". Please make sure it is correct, if not, please set the property "
217: + "TestFullLogInfo=<where temp files should go>");
218:
219: throw T_Fail.exceptionFail(ioe);
220: }
221:
222: } else {
223: // see if we can recover the database
224: REPORT("_______________________________________________________");
225: if (recoveryFail)
226: REPORT("\n\t\trecovering database - recovery will fill up log");
227: else
228: REPORT("\n\t\trecovering database - recovery should succeed");
229: REPORT("_______________________________________________________");
230:
231: try {
232: // make sure it does exist
233: infofile = new RandomAccessFile(ifile, "rw");
234: } catch (IOException ioe) {
235: throw T_Fail.exceptionFail(ioe);
236: }
237:
238: // let recovery log 10 records then run out of space
239: if (recoveryFail) {
240: SanityManager.DEBUG_SET(LogToFile.TEST_LOG_FULL);
241: System.setProperty(
242: LogToFile.TEST_RECORD_TO_FILL_LOG, "10");
243: }
244:
245: if (!Monitor.startPersistentService(testService,
246: startParams))
247: throw T_Fail
248: .testFailMsg("Monitor didn't know how to restart service: "
249: + testService);
250: factory = (RawStoreFactory) Monitor.findService(
251: getModuleToTestProtocolName(), testService);
252:
253: if (recoveryFail) {
254: throw T_Fail
255: .testFailMsg("recovery should have failed but did not - did you run the test in order?");
256: }
257: }
258: } catch (StandardException mse) {
259:
260: if (recoveryFail) {
261: REPORT("_______________________________________________________");
262: REPORT("\n\tRecovery failed due to log full as requested ");
263: REPORT("\texception was " + mse.toString());
264: REPORT("_______________________________________________________");
265: return;
266:
267: }
268: throw T_Fail.exceptionFail(mse);
269: } catch (NullPointerException npe) {
270:
271: if (recoveryFail) {
272: REPORT("_______________________________________________________");
273: REPORT("\n\tRecovery failed due to log full as requested ");
274: REPORT("\texception was " + npe.toString());
275: REPORT("_______________________________________________________");
276: return;
277:
278: }
279: throw T_Fail.exceptionFail(npe);
280: }
281:
282: if (factory == null) {
283: throw T_Fail.testFailMsg(getModuleToTestProtocolName()
284: + " service not started.");
285: }
286:
287: lf = factory.getLockFactory();
288: if (lf == null) {
289: throw T_Fail.testFailMsg("LockFactory.MODULE not found");
290: }
291:
292: // get a utility helper
293: t_util = new T_Util(factory, lf, contextService);
294:
295: try {
296: if (fillLog) {
297: testBasic(1);
298: fillUpLog();
299: } else if (logSwitchFail) {
300: testBasic(2);
301: logSwitchFail1();
302: testBasic(3);
303: logSwitchFail2();
304: } else if (!recoveryFail) {
305: checkRecovery();
306: }
307: } catch (StandardException se) {
308:
309: throw T_Fail.exceptionFail(se);
310: }
311: }
312:
313: private long find(long inkey) {
314: if (infofile == null)
315: return -1;
316:
317: try {
318: infofile.seek(0);
319: long key;
320:
321: while (true) {
322: key = infofile.readLong();
323: if (key == inkey) {
324: long value = infofile.readLong();
325: // System.out.println("found " + key + " " + value);
326: return value;
327: }
328: infofile.readLong();
329: }
330: } catch (IOException ioe) {
331: // System.out.println("key not found " + inkey);
332: return -1;
333: }
334:
335: }
336:
337: private long key(int test, int param) {
338: long i = test;
339: return ((i << 32) + param);
340: }
341:
342: private void register(long key, long value) throws T_Fail {
343: // System.out.println("registering " + key + " " + value);
344: try {
345: // go to the end
346: infofile.seek(infofile.length());
347: infofile.writeLong(key);
348: infofile.writeLong(value);
349: } catch (IOException ioe) {
350: T_Fail.exceptionFail(ioe);
351: }
352: }
353:
354: /*
355: * A basic routine to write a bunch of stuff to the log
356: * There will be some committed transactions, some uncommitted transactions,
357: * serveral checkpoints.
358: */
359: protected void testBasic(int testNumber) throws T_Fail,
360: StandardException {
361: int numtrans = 7;
362: int numpages = 7;
363: int i, j;
364:
365: // this is basically T_Recovery S203
366: T_TWC[] t = new T_TWC[numtrans];
367: for (i = 0; i < numtrans; i++)
368: t[i] = t_util.t_startTransactionWithContext();
369:
370: long[] cid = new long[numtrans];
371: ContainerHandle[] c = new ContainerHandle[numtrans];
372:
373: for (i = 0; i < numtrans; i++) {
374: cid[i] = t_util.t_addContainer(t[i], 0);
375: t_util.t_commit(t[i]);
376: c[i] = t_util.t_openContainer(t[i], 0, cid[i], true);
377: }
378:
379: Page page[][] = new Page[numtrans][numpages];
380: long pagenum[][] = new long[numtrans][numpages];
381:
382: for (i = 0; i < numtrans; i++) {
383: for (j = 0; j < numpages; j++) {
384: t[i].switchTransactionContext();
385: page[i][j] = t_util.t_addPage(c[i]);
386: pagenum[i][j] = page[i][j].getPageNumber();
387: t[i].resetContext();
388: }
389: }
390:
391: // set up numtrans (at least 5) transactions, each with one
392: // container and numpages pages. Do the following test:
393: //
394: // 1) insert 1 row onto each page
395: // set savepoint SP1 on first transaction (t0)
396: //
397: // 2) update every rows
398: // set savepoint SP1 on all other transactions
399: //
400: // 3) update every rows
401: // set savepoint SP2 on all transactions
402: //
403: // 4) update every rows
404: //
405: // 5) rollback t0 to SP1
406: //
407: // check that only page[0][x] have been rolled back
408: // past SP2
409: //
410: // 6) update every row
411: // 7) rollback SP2 on all transaction except the first
412: //
413: // 8) update every rows
414: // 9) rollback t0 to SP1
415: //
416: // 10) leave transactions in the following state
417: // t0 - incomplete
418: // t1 - abort
419: // t2 - commit
420: // t3 - incomplete
421: // t4 - commit
422: // any other transactions - incomplete
423:
424: //////////////////////// step 1 ////////////////////////
425: RecordHandle[][] rh = new RecordHandle[numtrans][numpages];
426: T_RawStoreRow row1 = new T_RawStoreRow(REC_001);
427: for (i = 0; i < numtrans; i++)
428: for (j = 0; j < numpages; j++) {
429: t[i].switchTransactionContext();
430: rh[i][j] = t_util.t_insert(page[i][j], row1);
431: t[i].resetContext();
432: }
433:
434: t[0].setSavePoint(SP1, null); // sp1
435:
436: //////////////////////// step 2 ////////////////////////
437: T_RawStoreRow row2 = new T_RawStoreRow(REC_002);
438: for (i = 0; i < numtrans; i++)
439: for (j = 0; j < numpages; j++) {
440: t[i].switchTransactionContext();
441: page[i][j].update(rh[i][j], row2.getRow(),
442: (FormatableBitSet) null);
443: t[i].resetContext();
444: }
445:
446: for (i = 1; i < numtrans; i++) // sp1
447: {
448: t[i].setSavePoint(SP1, null);
449: }
450:
451: //////////////////////// step 3 ////////////////////////
452: T_RawStoreRow row3 = new T_RawStoreRow(REC_003);
453: for (i = 0; i < numtrans; i++)
454: for (j = 0; j < numpages; j++)
455: page[i][j].update(rh[i][j], row3.getRow(),
456: (FormatableBitSet) null);
457:
458: for (i = 0; i < numtrans; i++)
459: t[i].setSavePoint(SP2, null); // sp2
460:
461: //////////////////////// step 4 ////////////////////////
462: T_RawStoreRow row4 = new T_RawStoreRow(REC_004);
463: for (i = 0; i < numtrans; i++) {
464: t[i].switchTransactionContext();
465:
466: for (j = 0; j < numpages; j++)
467: page[i][j].update(rh[i][j], row4.getRow(),
468: (FormatableBitSet) null);
469: t[i].resetContext();
470: }
471:
472: //////////////////////// step 5 ////////////////////////
473: // unlatch relavante pages
474: t[0].switchTransactionContext();
475:
476: for (j = 0; j < numpages; j++)
477: page[0][j].unlatch();
478:
479: t[0].rollbackToSavePoint(SP1, null); // step 5
480:
481: // relatch relavante pages
482: for (j = 0; j < numpages; j++)
483: page[0][j] = t_util.t_getPage(c[0], pagenum[0][j]);
484:
485: t[0].resetContext();
486:
487: //////////////////////// check ////////////////////////
488: for (i = 1; i < numtrans; i++) {
489: t[i].switchTransactionContext();
490: for (j = 0; j < numpages; j++)
491: t_util.t_checkFetch(page[i][j], rh[i][j], REC_004);
492: t[i].resetContext();
493: }
494:
495: t[0].switchTransactionContext();
496: for (j = 0; j < numpages; j++)
497: t_util.t_checkFetch(page[0][j], rh[0][j], REC_001);
498:
499: t[0].resetContext();
500: //////////////////////// step 6 ////////////////////////
501: T_RawStoreRow row5 = new T_RawStoreRow(REC_005);
502: for (i = 0; i < numtrans; i++) {
503: t[i].switchTransactionContext();
504: for (j = 0; j < numpages; j++)
505: page[i][j].update(rh[i][j], row5.getRow(),
506: (FormatableBitSet) null);
507: t[i].resetContext();
508: }
509:
510: //////////////////////// step 7 ////////////////////////
511: for (i = 1; i < numtrans; i++) {
512: t[i].switchTransactionContext();
513:
514: for (j = 0; j < numpages; j++)
515: page[i][j].unlatch();
516:
517: t[i].rollbackToSavePoint(SP2, null);
518:
519: for (j = 0; j < numpages; j++)
520: page[i][j] = t_util.t_getPage(c[i], pagenum[i][j]);
521: t[i].resetContext();
522: }
523:
524: //////////////////////// check ////////////////////////
525: for (i = 1; i < numtrans; i++) {
526: t[i].switchTransactionContext();
527: for (j = 0; j < numpages; j++)
528: t_util.t_checkFetch(page[i][j], rh[i][j], REC_003);
529: t[i].resetContext();
530: }
531:
532: t[0].switchTransactionContext();
533: for (j = 0; j < numpages; j++)
534: t_util.t_checkFetch(page[0][j], rh[0][j], REC_005);
535:
536: t[0].resetContext();
537:
538: //////////////////////// step 8 ////////////////////////
539: T_RawStoreRow row6 = new T_RawStoreRow(REC_006);
540: for (i = 0; i < numtrans; i++) {
541: t[i].switchTransactionContext();
542: for (j = 0; j < numpages; j++)
543: page[i][j].update(rh[i][j], row6.getRow(),
544: (FormatableBitSet) null); // step 8
545: t[i].resetContext();
546: }
547:
548: //////////////////////// step 9 ////////////////////////
549: // unlatch relavante pages
550: t[0].switchTransactionContext();
551: for (j = 0; j < numpages; j++)
552: page[0][j].unlatch();
553:
554: t[0].rollbackToSavePoint(SP1, null);
555:
556: // relatch relevant pages
557: for (j = 0; j < numpages; j++)
558: page[0][j] = t_util.t_getPage(c[0], pagenum[0][j]);
559:
560: t[0].resetContext();
561: //////////////////////// check ////////////////////////
562: for (i = 1; i < numtrans; i++) {
563: t[i].switchTransactionContext();
564:
565: for (j = 0; j < numpages; j++) {
566: t_util.t_checkFetch(page[i][j], rh[i][j], REC_006);
567: t_util.t_checkRecordCount(page[i][j], 1, 1);
568: }
569: t[i].resetContext();
570: }
571:
572: t[0].switchTransactionContext();
573: for (j = 0; j < numpages; j++) {
574: t_util.t_checkFetch(page[0][j], rh[0][j], REC_001);
575: t_util.t_checkRecordCount(page[0][j], 1, 1);
576: }
577: t[0].resetContext();
578:
579: //////////////////////// step 10 ////////////////////////
580: // unlatch all pages
581: for (i = 0; i < numtrans; i++) {
582: t[i].switchTransactionContext();
583: for (j = 0; j < numpages; j++)
584: page[i][j].unlatch();
585: t[i].resetContext();
586: }
587:
588: // t[0] incomplete
589: t_util.t_abort(t[1]);
590: t_util.t_commit(t[2]);
591: // t[3] incomplete
592: t_util.t_commit(t[4]);
593:
594: // reopen containers 1, 2, and 4, where were closed when the
595: // transaction terminated.
596: c[1] = t_util.t_openContainer(t[1], 0, cid[1], false);
597: c[2] = t_util.t_openContainer(t[2], 0, cid[2], false);
598: c[4] = t_util.t_openContainer(t[4], 0, cid[4], false);
599:
600: //////////////////////// check ////////////////////////
601: for (j = 0; j < numpages; j++) {
602: t[0].switchTransactionContext();
603: t_util.t_checkFetch(c[0], rh[0][j], REC_001);
604: t[0].resetContext();
605:
606: // t[1] has been aborted
607: // rh[1][j] (REC_001) is deleted
608: t[1].switchTransactionContext();
609: page[1][j] = t_util.t_getPage(c[1], pagenum[1][j]);
610: t_util.t_checkRecordCount(page[1][j], 1, 0);
611: t_util.t_checkFetchBySlot(page[1][j],
612: Page.FIRST_SLOT_NUMBER, REC_001, true, false);
613: page[1][j].unlatch();
614: t[1].resetContext();
615:
616: t[2].switchTransactionContext();
617: t_util.t_checkFetch(c[2], rh[2][j], REC_006);
618: t[2].resetContext();
619:
620: t[3].switchTransactionContext();
621: t_util.t_checkFetch(c[3], rh[3][j], REC_006);
622: t[3].resetContext();
623:
624: t[4].switchTransactionContext();
625: t_util.t_checkFetch(c[4], rh[4][j], REC_006);
626: t[4].resetContext();
627: }
628:
629: for (i = 0; i < numtrans; i++) {
630: register(key(testNumber, i + 10), cid[i]);
631:
632: String str = "container " + i + ":"
633: + find(key(testNumber, i + 10)) + " pages: ";
634:
635: for (j = 0; j < numpages; j++) {
636: str += pagenum[i][j] + " ";
637: register(key(testNumber, (i + 1) * 1000 + j),
638: pagenum[i][j]);
639: }
640: REPORT("\t" + str);
641: }
642:
643: register(key(testNumber, 1), numtrans);
644: register(key(testNumber, 2), numpages);
645:
646: // let recovery try to roll back transactions t0, t3
647: }
648:
649: // fill up the log immediately
650: protected void fillUpLog() throws T_Fail, StandardException {
651: SanityManager.DEBUG_SET(LogToFile.TEST_LOG_FULL);
652: System.setProperty(LogToFile.TEST_RECORD_TO_FILL_LOG, "1");
653:
654: Transaction t = t_util.t_startTransaction();
655: try {
656: long cid = t_util.t_addContainer(t, 0);
657: } catch (StandardException se) {
658: REPORT("_______________________________________________________");
659: REPORT("\n\tlog filled up as requested");
660: REPORT("_______________________________________________________");
661: return;
662: } catch (NullPointerException npe) {
663: // likely to be a null pointer exception being thrown because the
664: // system is forcibly shutdown due to corruption
665: REPORT("_______________________________________________________");
666: REPORT("\n\tlog filled up as requested");
667: REPORT("_______________________________________________________");
668: return;
669: }
670:
671: throw T_Fail.testFailMsg("log should have filled but did not");
672: }
673:
674: protected void logSwitchFail1() throws T_Fail, StandardException {
675: SanityManager.DEBUG_SET(LogToFile.TEST_SWITCH_LOG_FAIL1);
676:
677: factory.checkpoint(); // this should succeed, switch log is
678: // optional before the end marker is written
679:
680: SanityManager.DEBUG_CLEAR(LogToFile.TEST_SWITCH_LOG_FAIL1);
681: }
682:
683: protected void logSwitchFail2() throws T_Fail, StandardException {
684: SanityManager.DEBUG_SET(LogToFile.TEST_SWITCH_LOG_FAIL2);
685:
686: int tries = 10;
687: try {
688: // checkpoint should fail if it is attempted, after end marker is
689: // written, any error is fatal. If another
690: // checkpoint is in progress, log some things and try again
691:
692: // if we are extremely unlucky, it is possible that we will fail
693: // even after 10 tries. It is better to keep trying than to
694: // disable the background checkpoint daemon because this is how the
695: // system actually runs in real life. Do not manufacture a
696: // non-existant condition just to make the test pass.
697:
698: for (int i = 10; i < 110 + tries; i++) {
699: factory.checkpoint();
700: testBasic(i);
701: }
702: } catch (StandardException se) {
703: REPORT("_______________________________________________________");
704: REPORT("\n\tlog switch failed as requested");
705: REPORT("_______________________________________________________");
706:
707: return;
708: } catch (NullPointerException npe) {
709: REPORT("_______________________________________________________");
710: REPORT("\n\tlog switch failed as requested");
711: REPORT("_______________________________________________________");
712:
713: return;
714: } finally {
715: SanityManager.DEBUG_CLEAR(LogToFile.TEST_SWITCH_LOG_FAIL2);
716: }
717:
718: throw T_Fail
719: .testFailMsg("log switch should have failed but did not even after "
720: + tries + " tries");
721: }
722:
723: protected void checkRecovery() throws T_Fail, StandardException {
724: // check for numTest=1, 2, 3
725:
726: for (int numTest = 1; numTest <= 3; numTest++) {
727: int numtrans = (int) find(key(numTest, 1));
728: int numpages = (int) find(key(numTest, 2));
729:
730: if (numtrans < 5 || numpages < 1) {
731: REPORT("full log test " + numTest + " not run");
732: continue;
733: } else {
734: REPORT("Test recovery of test " + numTest);
735: }
736:
737: Transaction t = t_util.t_startTransaction();
738:
739: long[] cid = new long[numtrans];
740: ContainerHandle[] c = new ContainerHandle[numtrans];
741:
742: long[][] pagenum = new long[numtrans][numpages];
743: Page[][] page = new Page[numtrans][numpages];
744:
745: int i, j;
746:
747: for (i = 0; i < numtrans; i++) {
748:
749: cid[i] = find(key(numTest, i + 10));
750: c[i] = t_util.t_openContainer(t, 0, cid[i], true);
751:
752: for (j = 0; j < numpages; j++) {
753: pagenum[i][j] = find(key(numTest, (i + 1) * 1000
754: + j));
755: page[i][j] = t_util.t_getPage(c[i], pagenum[i][j]);
756: }
757: }
758:
759: // transactions were left in the following state
760: // t0 - incomplete (rolled back)
761: // t1 - abort
762: // t2 - commit
763: // t3 - incomplete (rolled back)
764: // t4 - commit
765: // any other transactions - incomplete
766: //
767: // all the rolled back transaction should have a deleted REC_001
768: // all the committed transactions should have a REC_006
769: //
770: for (j = 0; j < numpages; j++) {
771: t_util.t_checkRecordCount(page[0][j], 1, 0);
772: t_util.t_checkFetchBySlot(page[0][j],
773: Page.FIRST_SLOT_NUMBER, REC_001, true, true);
774:
775: t_util.t_checkRecordCount(page[1][j], 1, 0);
776: t_util.t_checkFetchBySlot(page[1][j],
777: Page.FIRST_SLOT_NUMBER, REC_001, true, true);
778:
779: t_util.t_checkRecordCount(page[2][j], 1, 1);
780: t_util.t_checkFetchBySlot(page[2][j],
781: Page.FIRST_SLOT_NUMBER, REC_006, false, true);
782:
783: t_util.t_checkRecordCount(page[3][j], 1, 0);
784: t_util.t_checkFetchBySlot(page[3][j],
785: Page.FIRST_SLOT_NUMBER, REC_001, true, true);
786:
787: t_util.t_checkRecordCount(page[4][j], 1, 1);
788: t_util.t_checkFetchBySlot(page[4][j],
789: Page.FIRST_SLOT_NUMBER, REC_006, false, true);
790: }
791:
792: for (i = 0; i < numtrans; i++) {
793: String str = "container " + i + ":" + cid[i]
794: + " pages: ";
795: for (j = 0; j < numpages; j++)
796: str += pagenum[i][j] + " ";
797: REPORT("\t" + str);
798: }
799: t_util.t_commit(t);
800: t.close();
801:
802: }
803: }
804:
805: }
|