0001: /*
0002:
0003: Derby - Class org.apache.derbyTesting.unitTests.store.T_Recovery
0004:
0005: Licensed to the Apache Software Foundation (ASF) under one or more
0006: contributor license agreements. See the NOTICE file distributed with
0007: this work for additional information regarding copyright ownership.
0008: The ASF licenses this file to You under the Apache License, Version 2.0
0009: (the "License"); you may not use this file except in compliance with
0010: the License. You may obtain a copy of the License at
0011:
0012: http://www.apache.org/licenses/LICENSE-2.0
0013:
0014: Unless required by applicable law or agreed to in writing, software
0015: distributed under the License is distributed on an "AS IS" BASIS,
0016: WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
0017: See the License for the specific language governing permissions and
0018: limitations under the License.
0019:
0020: */
0021:
0022: package org.apache.derbyTesting.unitTests.store;
0023:
0024: import org.apache.derbyTesting.unitTests.harness.T_Generic;
0025: import org.apache.derbyTesting.unitTests.harness.T_Fail;
0026:
0027: import org.apache.derby.iapi.store.raw.*;
0028:
0029: import org.apache.derby.iapi.reference.SQLState;
0030:
0031: import org.apache.derby.impl.store.raw.log.LogCounter;
0032:
0033: import org.apache.derby.iapi.services.context.ContextService;
0034: import org.apache.derby.iapi.services.context.ContextManager;
0035: import org.apache.derby.iapi.services.locks.*;
0036: import org.apache.derby.iapi.services.property.PropertyUtil;
0037: import org.apache.derby.iapi.services.monitor.Monitor;
0038: import org.apache.derby.iapi.services.sanity.SanityManager;
0039:
0040: import org.apache.derby.iapi.error.StandardException;
0041:
0042: import org.apache.derby.iapi.store.raw.xact.RawTransaction;
0043: import org.apache.derby.iapi.store.raw.data.RawContainerHandle;
0044: import org.apache.derby.iapi.store.raw.log.LogInstant;
0045:
0046: import org.apache.derby.iapi.store.access.conglomerate.LogicalUndo;
0047:
0048: import org.apache.derby.iapi.store.access.Qualifier;
0049:
0050: import org.apache.derby.iapi.types.SQLChar;
0051:
0052: import org.apache.derby.iapi.types.DataValueDescriptor;
0053:
0054: import org.apache.derby.iapi.services.uuid.UUIDFactory;
0055: import org.apache.derby.catalog.UUID;
0056: import org.apache.derby.iapi.reference.Property;
0057: import org.apache.derby.iapi.reference.Attribute;
0058: import org.apache.derby.iapi.services.io.FormatableBitSet;
0059:
0060: import java.io.*;
0061: import java.util.Properties;
0062:
0063: /**
0064: A protocol unit test for recovery.
0065:
0066: To run, create a derby.properties file in a new directory with the
0067: contents
0068:
0069: derby.module.test.recovery=org.apache.derbyTesting.unitTests.store.T_Recovery
0070:
0071: Execute
0072:
0073: java -DSetupRecovery=true org.apache.derbyTesting.unitTests.harness.UnitTestMain
0074: java -DTestRecovery=true org.apache.derbyTesting.unitTests.harness.UnitTestMain
0075: */
0076:
0077: public class T_Recovery extends T_Generic {
0078:
0079: private static final String testService = "RecoveryTest";
0080:
0081: static final String REC_001 = "McLaren";
0082: static final String REC_002 = "Ferrari";
0083: static final String REC_003 = "Benetton";
0084: static final String REC_004 = "Prost";
0085: static final String REC_005 = "Tyrell";
0086: static final String REC_006 = "Derby, Natscape, Goatscape, the popular names";
0087: static final String REC_UNDO = "Lotus";
0088: static final String REC_NULL = "NULL";
0089:
0090: static final String SP1 = "savepoint1";
0091: static final String SP2 = "savepoint2";
0092:
0093: static final FormatableBitSet BS_COL_0 = new FormatableBitSet(1);
0094:
0095: private RandomAccessFile filein = null;
0096: private RandomAccessFile fileout = null;
0097:
0098: private boolean setupRecovery;
0099: private boolean testRecovery;
0100: private static final String infoPath = "extinout/T_Recovery.info";
0101:
0102: private static final String SETUP_RECOVERY = "SetupRecovery";
0103: private static final String TEST_RECOVERY = "TestRecovery";
0104: private static final String RECOVERY_TESTPATH = "RecoveryTestPath";
0105:
0106: RawStoreFactory factory;
0107: LockFactory lf;
0108: ContextService contextService;
0109: UUIDFactory uuidfactory;
0110: T_Util t_util;
0111:
0112: public T_Recovery() {
0113: super ();
0114: BS_COL_0.set(0);
0115: }
0116:
0117: /*
0118: ** Methods required by T_Generic
0119: */
0120:
0121: public String getModuleToTestProtocolName() {
0122: return RawStoreFactory.MODULE;
0123: }
0124:
0125: /**
0126: */
0127: private void getConfig() {
0128:
0129: String param = PropertyUtil.getSystemProperty(SETUP_RECOVERY);
0130: setupRecovery = Boolean.valueOf(param).booleanValue();
0131:
0132: param = PropertyUtil.getSystemProperty(TEST_RECOVERY);
0133: testRecovery = Boolean.valueOf(param).booleanValue();
0134: }
0135:
0136: /**
0137: Tests in here come in pairs (Snnn Rnnn), one to set it up, one to test
0138: it after recovery. Information that needs to be passed from the setup
0139: to the recovery should, ideally, be written out to a database. For
0140: now, it is written out as a pair of <key,value> long in the file
0141: T_Recovery.info.
0142:
0143: To make sure you don't accidently tramples on someone else's key,
0144: encode your test number (nnn) by shifting over 32 bits and then add
0145: your key. Multiple invocations which needs paramaters saved should
0146: be encoded futher.
0147:
0148: 001 < nnn < 200 - no recovery undo
0149: 200 < nnn < 400 - recovery undo
0150:
0151: @exception T_Fail Unexpected behaviour from the API
0152: */
0153: public void runTests() throws T_Fail {
0154:
0155: getConfig();
0156:
0157: if (!(setupRecovery ^ testRecovery))
0158: throw T_Fail
0159: .testFailMsg("One & only one of the SetupRecovery and TestRecovery properties must be set");
0160:
0161: try {
0162:
0163: uuidfactory = Monitor.getMonitor().getUUIDFactory();
0164: if (uuidfactory == null) {
0165: throw T_Fail
0166: .testFailMsg("UUIDFactory.MODULE not found");
0167: }
0168:
0169: // see if we are testing encryption
0170: startParams = T_Util.setEncryptionParam(startParams);
0171:
0172: contextService = ContextService.getFactory();
0173:
0174: if (testRecovery) {
0175: if (!Monitor.startPersistentService(testService,
0176: startParams))
0177: throw T_Fail
0178: .testFailMsg("Monitor didn't know how to restart service: "
0179: + testService);
0180: factory = (RawStoreFactory) Monitor.findService(
0181: getModuleToTestProtocolName(), testService);
0182:
0183: } else // setup
0184: {
0185: // don't automatic boot this service if it gets left around
0186: if (startParams == null)
0187: startParams = new Properties();
0188:
0189: startParams.put(Property.NO_AUTO_BOOT, Boolean.TRUE
0190: .toString());
0191:
0192: // do not make T_Recovery test a source, or it won't run on a
0193: // syncless configuration
0194: //
0195: // remove the service directory to ensure a clean run
0196: startParams.put(Property.DELETE_ON_CREATE, Boolean.TRUE
0197: .toString());
0198:
0199: // keep all log files for diagnostics
0200: startParams.put(RawStoreFactory.KEEP_TRANSACTION_LOG,
0201: "true");
0202:
0203: factory = (RawStoreFactory) Monitor
0204: .createPersistentService(
0205: getModuleToTestProtocolName(),
0206: testService, startParams);
0207: }
0208:
0209: } catch (StandardException mse) {
0210: throw T_Fail.exceptionFail(mse);
0211: }
0212:
0213: if (factory == null) {
0214: throw T_Fail.testFailMsg(getModuleToTestProtocolName()
0215: + " service not started.");
0216: }
0217:
0218: lf = factory.getLockFactory();
0219:
0220: if (lf == null) {
0221: throw T_Fail.testFailMsg("LockFactory.MODULE not found");
0222: }
0223:
0224: // get a utility helper
0225: t_util = new T_Util(factory, lf, contextService);
0226:
0227: try {
0228:
0229: if (setupRecovery) {
0230: // dmls
0231: S001(); // insert 1 row
0232: S002(); // insert a bunch of rows
0233: S003(); // update row
0234: S004(); // update field
0235: S005(); // purge and delete
0236: S006(); // page allocation
0237: S007(); // page deallocation
0238: S008(); // rollback of page deallocation
0239: S009(); // deallocation and reuse of page
0240: S010(); // allocation/deallocation with overflow pages
0241: S011(); // allocate a lot of pages so that > 1
0242: // allocation pages are needed
0243: S012(); // test page estimation
0244:
0245: // ddls
0246: S020(); // create multiple containers
0247: S022();
0248:
0249: // committed transactions
0250: S100(); // multiple intervening transactions
0251: S101(); // transaction with rollback to savepoints
0252:
0253: // aborted transaction
0254: // - these transactions are rollback during runtime -
0255:
0256: // incomplete transaction
0257: // - these transactions are rollback during recovery -
0258:
0259: S200(); // 1 incomplete transaction
0260: S201(); // multiple intervening incomplete transaction
0261: S202(); // incomplete transaction with rollback to
0262: // savepoint
0263: S203(); // incomplete and committed and aborted
0264: // transaction with intervening rollback to savepoints
0265: S204(); // incomplete and committed and aborted
0266: // internal transactions
0267:
0268: // incomplete transaction with ddls
0269: S300(); // incomplete transactions with drop containers
0270: S301(); // incomplete transactions with create containers
0271: S302(); //purging rows with no data logged
0272: S303(); //purging long columns with no data logged
0273: S304(); //pruging long rows with no data logged.
0274: }
0275:
0276: if (testRecovery || setupRecovery) {
0277: // basic recovery
0278: R001();
0279: R002();
0280: R003();
0281: R004();
0282: R005();
0283: R006();
0284: R007();
0285: R008();
0286: R009();
0287: R010();
0288: R011();
0289: R012();
0290:
0291: R020();
0292: R022();
0293:
0294: R100();
0295: R101();
0296: R302();
0297:
0298: // the following tests depends on recovery to roll back the
0299: // changes. Only test them after recovery and not during setup
0300: if (testRecovery) {
0301:
0302: R200();
0303: R201();
0304: R202();
0305: R203();
0306: R204();
0307:
0308: R300();
0309: R301();
0310: R303();
0311: R304();
0312:
0313: R999();
0314: }
0315: }
0316:
0317: if (setupRecovery) {
0318: S999(); // always run this last, this leaves a 1/2
0319: // written log record at the end of the log
0320: // and it leaves a page latched
0321: }
0322:
0323: if (fileout != null) {
0324: fileout.close();
0325: fileout = null;
0326: }
0327:
0328: if (filein != null) {
0329: filein.close();
0330: filein = null;
0331: }
0332:
0333: } catch (Throwable t) {
0334:
0335: SanityManager.showTrace(t);
0336: System.out.println("caught exception t " + t);
0337:
0338: t.printStackTrace();
0339:
0340: // this test should exit the JVM as abruptly as possible.
0341: System.exit(0);
0342: }
0343: }
0344:
0345: private long find(long inkey) throws T_Fail {
0346: try {
0347: if (filein == null) {
0348: // make sure it does exist
0349: File infoFile = new File(infoPath);
0350: if (infoFile.exists()) {
0351: try {
0352: filein = new RandomAccessFile(infoFile, "r");
0353: } catch (IOException ioe) {
0354: System.out
0355: .println("Cannot write to temporary file "
0356: + infoPath
0357: + ". Please make sure it is correct, if not, please set the property "
0358: + "RecoveryTestPath=<where temp files should go>");
0359: throw T_Fail.exceptionFail(ioe);
0360: }
0361: } else
0362: return -1;
0363: }
0364:
0365: filein.seek(0);
0366:
0367: long key;
0368: while (true) {
0369: key = filein.readLong();
0370: if (key == inkey) {
0371: long value = filein.readLong();
0372: // System.out.println("found " + key + " " + value);
0373: return value;
0374: }
0375: filein.readLong();
0376: }
0377: } catch (IOException ioe) {
0378: // System.out.println("key not found " + inkey);
0379: return -1;
0380: }
0381:
0382: }
0383:
0384: private long key(int test, int param) {
0385: long i = test;
0386: return ((i << 32) + param);
0387: }
0388:
0389: private void register(long key, long value) throws T_Fail {
0390: // System.out.println("registering " + key + " " + value);
0391: try {
0392: if (fileout == null) {
0393: // make sure it does not exist
0394: File infofile = new File(infoPath);
0395: if (infofile.exists())
0396: infofile.delete();
0397:
0398: //if external input output files dir does not exist ,create one
0399: File ifdir = new File("extinout");
0400: if (!ifdir.exists())
0401: ifdir.mkdirs();
0402: fileout = new RandomAccessFile(infoPath, "rw");
0403: }
0404:
0405: fileout.writeLong(key);
0406: fileout.writeLong(value);
0407: } catch (IOException ioe) {
0408: T_Fail.exceptionFail(ioe);
0409: }
0410: }
0411:
0412: /*
0413: * test 1 - insert 1 row
0414: */
0415: protected void S001() throws T_Fail, StandardException {
0416: Transaction t = t_util.t_startTransaction();
0417:
0418: long cid = t_util.t_addContainer(t, 0);
0419:
0420: t_util.t_commit(t);
0421:
0422: ContainerHandle c = t_util.t_openContainer(t, 0, cid, true);
0423: Page page = t_util.t_getPage(c,
0424: ContainerHandle.FIRST_PAGE_NUMBER);
0425: try {
0426:
0427: T_RawStoreRow row1 = new T_RawStoreRow(REC_001);
0428:
0429: RecordHandle r1 = t_util.t_insertAtSlot(page, 0, row1);
0430:
0431: page.unlatch();
0432:
0433: c.close();
0434:
0435: register(key(1, 1), cid);
0436: } finally {
0437: t_util.t_commit(t);
0438: t.close();
0439: }
0440:
0441: REPORT("setup S001: " + cid);
0442: }
0443:
0444: /* recover test 1 */
0445: protected void R001() throws T_Fail, StandardException {
0446: long cid = find(key(1, 1));
0447: if (cid < 0) {
0448: REPORT("R001 not run");
0449: return;
0450: }
0451:
0452: Transaction t = t_util.t_startTransaction();
0453:
0454: try {
0455: ContainerHandle c = t_util
0456: .t_openContainer(t, 0, cid, false);
0457: Page page = t_util.t_getPage(c,
0458: ContainerHandle.FIRST_PAGE_NUMBER);
0459:
0460: t_util.t_checkRecordCount(page, 1, 1);
0461: t_util.t_checkFieldCount(page, 0, 1);
0462:
0463: t_util.t_checkFetchBySlot(page, 0, REC_001, false, false);
0464: page.unlatch();
0465:
0466: } finally {
0467: t_util.t_commit(t);
0468: t.close();
0469: }
0470:
0471: PASS("R001: containerId " + cid);
0472:
0473: }
0474:
0475: /*
0476: * test 2 - insert a bunch of rows into one container
0477: */
0478: protected void S002() throws T_Fail, StandardException {
0479: Transaction t = t_util.t_startTransaction();
0480:
0481: long cid = t_util.t_addContainer(t, 0);
0482:
0483: t_util.t_commit(t);
0484:
0485: try {
0486: ContainerHandle c = t_util.t_openContainer(t, 0, cid, true);
0487: Page page = t_util.t_getPage(c,
0488: ContainerHandle.FIRST_PAGE_NUMBER);
0489:
0490: T_RawStoreRow row1 = new T_RawStoreRow(REC_001);
0491: T_RawStoreRow row2 = new T_RawStoreRow(REC_002);
0492: T_RawStoreRow row3 = new T_RawStoreRow(REC_003);
0493: T_RawStoreRow row4 = new T_RawStoreRow(REC_004);
0494: T_RawStoreRow row5 = new T_RawStoreRow(REC_005);
0495:
0496: RecordHandle r1 = t_util.t_insertAtSlot(page, 0, row1);
0497:
0498: RecordHandle r2 = t_util.t_insertAtSlot(page, 1, row2);
0499:
0500: RecordHandle r3 = (r2 == null) ? r2 : t_util
0501: .t_insertAtSlot(page, 2, row3);
0502:
0503: RecordHandle r4 = (r3 == null) ? r3 : t_util
0504: .t_insertAtSlot(page, 3, row4);
0505:
0506: RecordHandle r5 = (r4 == null) ? r4 : t_util
0507: .t_insertAtSlot(page, 4, row5);
0508:
0509: REPORT("setup S002: containerId " + cid + " recordCount "
0510: + page.recordCount());
0511:
0512: register(key(2, 1), cid);
0513: register(key(2, 2), page.recordCount());
0514: page.unlatch();
0515: c.close();
0516: } finally {
0517: t_util.t_commit(t);
0518: t.close();
0519: }
0520: }
0521:
0522: /* recover test 2 */
0523: protected void R002() throws T_Fail, StandardException {
0524: long cid = find(key(2, 1));
0525: if (cid < 0) {
0526: REPORT("R002 not run");
0527: return;
0528: }
0529:
0530: int recordCount = (int) find(key(2, 2));
0531:
0532: Transaction t = t_util.t_startTransaction();
0533:
0534: try {
0535: ContainerHandle c = t_util
0536: .t_openContainer(t, 0, cid, false);
0537: Page page = t_util.t_getPage(c,
0538: ContainerHandle.FIRST_PAGE_NUMBER);
0539:
0540: t_util.t_checkRecordCount(page, recordCount, recordCount);
0541:
0542: switch (recordCount) {
0543: case 5:
0544: t_util.t_checkFetchBySlot(page, 4, REC_005, false,
0545: false);
0546: case 4:
0547: t_util.t_checkFetchBySlot(page, 3, REC_004, false,
0548: false);
0549: case 3:
0550: t_util.t_checkFetchBySlot(page, 2, REC_003, false,
0551: false);
0552: case 2:
0553: t_util.t_checkFetchBySlot(page, 1, REC_002, false,
0554: false);
0555: case 1:
0556: t_util.t_checkFetchBySlot(page, 0, REC_001, false,
0557: false);
0558: }
0559: page.unlatch();
0560: } finally {
0561: t_util.t_commit(t);
0562: t.close();
0563: }
0564:
0565: PASS("R002: containerId " + cid + " recordCount " + recordCount);
0566:
0567: }
0568:
0569: /*
0570: * test 3 - update row
0571: */
0572: protected void S003() throws T_Fail, StandardException {
0573: Transaction t = t_util.t_startTransaction();
0574:
0575: try {
0576: long cid = t_util.t_addContainer(t, 0);
0577: t_util.t_commit(t);
0578:
0579: ContainerHandle c = t_util.t_openContainer(t, 0, cid, true);
0580: Page page = t_util.t_getPage(c,
0581: ContainerHandle.FIRST_PAGE_NUMBER);
0582:
0583: T_RawStoreRow row1 = new T_RawStoreRow(REC_001);
0584:
0585: RecordHandle r1 = t_util.t_insertAtSlot(page, 0, row1);
0586:
0587: t_util.t_checkFetch(page, r1, row1);
0588:
0589: // REPORT("grows the #column in row");
0590: T_RawStoreRow upd1 = new T_RawStoreRow(3);
0591: upd1.setColumn(0, (String) null);
0592: upd1.setColumn(1, REC_003);
0593: upd1.setColumn(2, REC_004);
0594:
0595: r1 = page.updateAtSlot(0, upd1.getRow(),
0596: (FormatableBitSet) null);
0597:
0598: // REPORT("update that shrinks the #columns in row");
0599: T_RawStoreRow row2 = new T_RawStoreRow(3);
0600: row2.setColumn(0, REC_001);
0601: row2.setColumn(1, REC_002);
0602: row2.setColumn(2, REC_003);
0603:
0604: T_RawStoreRow upd2 = new T_RawStoreRow(REC_005);
0605:
0606: RecordHandle r2 = t_util.t_insertAtSlot(page, 1, row2);
0607: if (r2 != null) {
0608: r2 = page.updateAtSlot(1, upd2.getRow(),
0609: (FormatableBitSet) null);
0610: }
0611:
0612: t_util.t_checkFetch(page, r1, upd1);
0613: // first row should contain (null, REC_003, REC_004)
0614: DataValueDescriptor column = new SQLChar();
0615:
0616: // page, slot, field, column, forUpdate, data
0617: t_util.t_checkFetchColFromSlot(page, 0, 0, column, true,
0618: null);
0619: t_util.t_checkFetchColFromSlot(page, 0, 1, column, true,
0620: REC_003);
0621: t_util.t_checkFetchColFromSlot(page, 0, 2, column, true,
0622: REC_004);
0623:
0624: if (r2 != null) {
0625: t_util.t_checkFetch(page, r2, upd2);
0626: // second row should contain (REC_005)
0627: t_util.t_checkFetchColFromSlot(page, 1, 0, column,
0628: true, REC_005);
0629: }
0630:
0631: REPORT("setup S003: containerId " + cid + " recordCount "
0632: + page.recordCount());
0633: register(key(3, 1), cid);
0634: register(key(3, 2), page.recordCount());
0635:
0636: page.unlatch();
0637: } finally {
0638: t_util.t_commit(t);
0639: t.close();
0640: }
0641: }
0642:
0643: /*
0644: * recover test 3
0645: */
0646: protected void R003() throws T_Fail, StandardException {
0647: long cid = find(key(3, 1));
0648: if (cid < 0) {
0649: REPORT("R003 not run");
0650: return;
0651: }
0652:
0653: int recordCount = (int) find(key(3, 2));
0654:
0655: Transaction t = t_util.t_startTransaction();
0656: try {
0657:
0658: ContainerHandle c = t_util
0659: .t_openContainer(t, 0, cid, false);
0660: Page page = t_util.t_getPage(c,
0661: ContainerHandle.FIRST_PAGE_NUMBER);
0662:
0663: t_util.t_checkRecordCount(page, recordCount, recordCount);
0664:
0665: // first row should contain (null, REC_003, REC_004)
0666:
0667: t_util.t_checkFieldCount(page, 0, 3);
0668:
0669: DataValueDescriptor column = new SQLChar();
0670: t_util.t_checkFetchColFromSlot(page, 0, 0, column, false,
0671: null);
0672: t_util.t_checkFetchColFromSlot(page, 0, 1, column, false,
0673: REC_003);
0674: t_util.t_checkFetchColFromSlot(page, 0, 2, column, false,
0675: REC_004);
0676:
0677: if (recordCount == 2) {
0678: // second row should contain (REC_005)
0679: t_util.t_checkFieldCount(page, 1, 1);
0680: t_util.t_checkFetchColFromSlot(page, 1, 0, column,
0681: false, REC_005);
0682: }
0683:
0684: page.unlatch();
0685: } finally {
0686: t_util.t_commit(t);
0687: t.close();
0688: }
0689: PASS("R003: containerId " + cid + " recordCount " + recordCount);
0690: }
0691:
0692: /*
0693: * test 4 - update field
0694: */
0695: protected void S004() throws T_Fail, StandardException {
0696: Transaction t = t_util.t_startTransaction();
0697:
0698: try {
0699:
0700: long cid = t_util.t_addContainer(t, 0);
0701: t_util.t_commit(t);
0702:
0703: ContainerHandle c = t_util.t_openContainer(t, 0, cid, true);
0704: Page page = t_util.t_getPage(c,
0705: ContainerHandle.FIRST_PAGE_NUMBER);
0706:
0707: T_RawStoreRow row = new T_RawStoreRow(5);
0708: row.setColumn(0, (String) null);
0709: row.setColumn(1, REC_004);
0710: row.setColumn(2, (String) null);
0711: row.setColumn(3, REC_005);
0712: row.setColumn(4, REC_005);
0713:
0714: RecordHandle rh = t_util.t_insert(page, row);
0715:
0716: DataValueDescriptor col0 = new SQLChar(null);
0717: DataValueDescriptor col1 = new SQLChar(REC_001);
0718: DataValueDescriptor col2 = new SQLChar(REC_002);
0719: DataValueDescriptor col3 = new SQLChar(null);
0720:
0721: if (page.updateFieldAtSlot(page.FIRST_SLOT_NUMBER, 0, col0,
0722: null) == null
0723: || page.updateFieldAtSlot(page.FIRST_SLOT_NUMBER,
0724: 1, col1, null) == null
0725: || page.updateFieldAtSlot(page.FIRST_SLOT_NUMBER,
0726: 2, col2, null) == null
0727: || page.updateFieldAtSlot(page.FIRST_SLOT_NUMBER,
0728: 3, col3, null) == null) {
0729: throw T_Fail.testFailMsg("Failed to update field");
0730: }
0731:
0732: page.unlatch();
0733: REPORT("setup S004: containerId " + cid);
0734:
0735: register(key(4, 1), cid);
0736: } finally {
0737: t_util.t_commit(t);
0738: t.close();
0739: }
0740: }
0741:
0742: /* recover test 4 */
0743: protected void R004() throws T_Fail, StandardException {
0744: long cid = find(key(4, 1));
0745: if (cid < 0) {
0746: REPORT("R004 not run");
0747: return;
0748: }
0749:
0750: Transaction t = t_util.t_startTransaction();
0751:
0752: try {
0753: ContainerHandle c = t_util
0754: .t_openContainer(t, 0, cid, false);
0755: Page page = t_util.t_getPage(c,
0756: ContainerHandle.FIRST_PAGE_NUMBER);
0757:
0758: // first row should contain (null, REC_001, REC_002, null, REC_005)
0759: DataValueDescriptor column = new SQLChar();
0760: t_util.t_checkFetchColFromSlot(page, 0, 0, column, false,
0761: null);
0762: t_util.t_checkFetchColFromSlot(page, 0, 1, column, false,
0763: REC_001);
0764: t_util.t_checkFetchColFromSlot(page, 0, 2, column, false,
0765: REC_002);
0766: t_util.t_checkFetchColFromSlot(page, 0, 3, column, false,
0767: null);
0768: t_util.t_checkFetchColFromSlot(page, 0, 4, column, false,
0769: REC_005);
0770:
0771: page.unlatch();
0772: } finally {
0773: t_util.t_commit(t);
0774: t.close();
0775: }
0776:
0777: PASS("R004: containerId " + cid);
0778:
0779: }
0780:
0781: /*
0782: * test 5 - purge and delete
0783: */
0784: protected void S005() throws T_Fail, StandardException {
0785: Transaction t = t_util.t_startTransaction();
0786:
0787: try {
0788:
0789: long cid = t_util.t_addContainer(t, 0);
0790: t_util.t_commit(t);
0791:
0792: ContainerHandle c = t_util.t_openContainer(t, 0, cid, true);
0793: Page page = t_util.t_getPage(c,
0794: ContainerHandle.FIRST_PAGE_NUMBER);
0795:
0796: T_RawStoreRow row1 = new T_RawStoreRow(REC_001);
0797: T_RawStoreRow row2 = new T_RawStoreRow(REC_002);
0798: T_RawStoreRow row3 = new T_RawStoreRow(REC_003);
0799: T_RawStoreRow row4 = new T_RawStoreRow(REC_004);
0800: T_RawStoreRow row5 = new T_RawStoreRow(REC_005);
0801:
0802: long numPurged = 0;
0803:
0804: // row 0
0805: RecordHandle r1 = t_util.t_insertAtSlot(page, 0, row1);
0806:
0807: // purge slot 0
0808: page.purgeAtSlot(0, 1, true);
0809: numPurged++;
0810:
0811: // slot 0
0812: RecordHandle r2 = t_util.t_insertAtSlot(page, 0, row2);
0813: if (r2 != null) {
0814: page.delete(r2, (LogicalUndo) null);
0815: }
0816:
0817: // slot 1
0818: RecordHandle r3 = (r2 == null) ? r2 : t_util
0819: .t_insertAtSlot(page, 1, row3);
0820: if (r3 != null) {
0821:
0822: page.delete(r3, (LogicalUndo) null);
0823: }
0824:
0825: // slot 2
0826: RecordHandle r4 = (r3 == null) ? r3 : t_util
0827: .t_insertAtSlot(page, 2, row4);
0828:
0829: // slot 3
0830: RecordHandle r5 = (r4 == null) ? r4 : t_util
0831: .t_insertAtSlot(page, 3, row5);
0832: if (r5 != null) {
0833: // purge slot 1 and 2
0834: page.purgeAtSlot(1, 2, true);
0835: numPurged += 2;
0836: }
0837:
0838: REPORT("setup S005: containerId " + cid + " recordCount "
0839: + page.recordCount() + " numPurges " + numPurged);
0840:
0841: register(key(5, 1), cid);
0842: register(key(5, 2), page.recordCount());
0843: register(key(5, 3), numPurged);
0844:
0845: page.unlatch();
0846: } finally {
0847: t_util.t_commit(t);
0848: t.close();
0849: }
0850: }
0851:
0852: /* recover test 5 */
0853: protected void R005() throws T_Fail, StandardException {
0854: long cid = find(key(5, 1));
0855: if (cid < 0) {
0856: REPORT("R005 not run");
0857: return;
0858: }
0859: int recordCount = (int) find(key(5, 2));
0860: int numPurged = (int) find(key(5, 3));
0861:
0862: Transaction t = t_util.t_startTransaction();
0863: try {
0864: ContainerHandle c = t_util
0865: .t_openContainer(t, 0, cid, false);
0866: Page page = t_util.t_getPage(c,
0867: ContainerHandle.FIRST_PAGE_NUMBER);
0868:
0869: t_util.t_checkRecordCount(page, recordCount, 1);
0870:
0871: T_RawStoreRow row1 = new T_RawStoreRow(REC_001);
0872: T_RawStoreRow row2 = new T_RawStoreRow(REC_002);
0873: T_RawStoreRow row3 = new T_RawStoreRow(REC_003);
0874: T_RawStoreRow row4 = new T_RawStoreRow(REC_004);
0875: T_RawStoreRow row5 = new T_RawStoreRow(REC_005);
0876:
0877: if (numPurged == 1) {
0878: // REC_002 (deleted), REC_003 (deleted), REC_004
0879: switch (recordCount) {
0880: case 3:
0881: t_util.t_checkFetchBySlot(page, 2, REC_004, false,
0882: false);
0883:
0884: case 2:
0885: t_util.t_checkFetchBySlot(page, 1, REC_003, true,
0886: false);
0887:
0888: case 1:
0889: t_util.t_checkFetchBySlot(page, 0, REC_002, true,
0890: false);
0891: }
0892: } else {
0893: // REC_002 (deleted), REC_005
0894: switch (recordCount) {
0895: case 2:
0896: t_util.t_checkFetchBySlot(page, 1, REC_005, false,
0897: false);
0898:
0899: case 1:
0900: t_util.t_checkFetchBySlot(page, 0, REC_002, true,
0901: false);
0902: if (!page.isDeletedAtSlot(0))
0903: throw T_Fail
0904: .testFailMsg("record should be deleted");
0905: }
0906: }
0907:
0908: page.unlatch();
0909: } finally {
0910: t_util.t_commit(t);
0911: t.close();
0912: }
0913:
0914: PASS("R005: containerId " + cid + " recordCount " + recordCount
0915: + " numPurges " + numPurged);
0916: }
0917:
0918: /*
0919: * test 6 - page allocation
0920: */
0921: protected void S006() throws T_Fail, StandardException {
0922: Transaction t = t_util.t_startTransaction();
0923:
0924: try {
0925: long cid = t_util.t_addContainer(t, 0);
0926: t_util.t_commit(t);
0927:
0928: T_RawStoreRow row1 = new T_RawStoreRow(REC_001);
0929: T_RawStoreRow row2 = new T_RawStoreRow(REC_002);
0930: T_RawStoreRow row3 = new T_RawStoreRow(REC_003);
0931:
0932: ContainerHandle c = t_util.t_openContainer(t, 0, cid, true);
0933: Page page = t_util.t_getPage(c,
0934: ContainerHandle.FIRST_PAGE_NUMBER);
0935: t_util.t_insertAtSlot(page, 0, row1);
0936: long page1_Id = page.getPageNumber();
0937: page.unlatch();
0938:
0939: page = t_util.t_addPage(c);
0940: t_util.t_insertAtSlot(page, 0, row2);
0941: long page2_Id = page.getPageNumber();
0942: page.unlatch();
0943:
0944: page = t_util.t_addPage(c);
0945: t_util.t_insertAtSlot(page, 0, row3);
0946: long page3_Id = page.getPageNumber();
0947: page.unlatch();
0948:
0949: if (page1_Id == page2_Id || page1_Id == page3_Id
0950: || page2_Id == page3_Id)
0951: throw T_Fail.testFailMsg("not getting new pages");
0952:
0953: REPORT("setup S006: containerId " + cid);
0954:
0955: register(key(6, 1), cid);
0956: register(key(6, 2), page1_Id);
0957: register(key(6, 3), page2_Id);
0958: register(key(6, 4), page3_Id);
0959: } finally {
0960: t_util.t_commit(t);
0961: t.close();
0962: }
0963: }
0964:
0965: /* recover test 6 */
0966: protected void R006() throws T_Fail, StandardException {
0967: long cid = find(key(6, 1));
0968: if (cid < 0) {
0969: REPORT("R006 not run");
0970: return;
0971: }
0972:
0973: long page1_Id = find(key(6, 2));
0974: long page2_Id = find(key(6, 3));
0975: long page3_Id = find(key(6, 4));
0976:
0977: Transaction t = t_util.t_startTransaction();
0978: try {
0979:
0980: ContainerHandle c = t_util
0981: .t_openContainer(t, 0, cid, false);
0982: if (page1_Id != c.FIRST_PAGE_NUMBER)
0983: throw T_Fail
0984: .testFailMsg("first page != container first page");
0985:
0986: Page page = t_util.t_getPage(c, page1_Id);
0987: t_util.t_checkRecordCount(page, 1, 1);
0988: t_util.t_checkFetchBySlot(page, 0, REC_001, false, false);
0989: page.unlatch();
0990:
0991: page = t_util.t_getPage(c, page2_Id);
0992: t_util.t_checkRecordCount(page, 1, 1);
0993: t_util.t_checkFetchBySlot(page, 0, REC_002, false, false);
0994: page.unlatch();
0995:
0996: page = t_util.t_getPage(c, page3_Id);
0997: t_util.t_checkRecordCount(page, 1, 1);
0998: t_util.t_checkFetchBySlot(page, 0, REC_003, false, false);
0999: page.unlatch();
1000:
1001: page = t_util.t_getLastPage(c);
1002: t_util.t_checkPageNumber(page, page3_Id);
1003: page.unlatch();
1004:
1005: } finally {
1006: t_util.t_commit(t);
1007: t.close();
1008: }
1009:
1010: PASS("R006: containerId " + cid);
1011: }
1012:
1013: /*
1014: * test 7 - page deallocation
1015: */
1016: protected void S007() throws T_Fail, StandardException {
1017: Transaction t = t_util.t_startTransaction();
1018: try {
1019:
1020: long cid = t_util.t_addContainer(t, 0);
1021: t_util.t_commit(t);
1022:
1023: ContainerHandle c = t_util.t_openContainer(t, 0, cid, true);
1024:
1025: Page page1 = t_util.t_getPage(c,
1026: ContainerHandle.FIRST_PAGE_NUMBER);
1027: long p1 = page1.getPageNumber();
1028:
1029: Page page2 = t_util.t_addPage(c);
1030: long p2 = page2.getPageNumber();
1031:
1032: Page page3 = t_util.t_addPage(c);
1033: long p3 = page3.getPageNumber();
1034:
1035: t_util.t_removePage(c, page2);
1036: t_util.t_removePage(c, page3);
1037: t_util.t_removePage(c, page1);
1038:
1039: if (page1.isLatched())
1040: throw T_Fail
1041: .testFailMsg("page is still latched after remove");
1042:
1043: if (page2.isLatched())
1044: throw T_Fail
1045: .testFailMsg("page is still latched after remove");
1046:
1047: if (page3.isLatched())
1048: throw T_Fail
1049: .testFailMsg("page is still latched after remove");
1050:
1051: register(key(7, 0), cid);
1052: register(key(7, 1), p1);
1053: register(key(7, 2), p2);
1054: register(key(7, 3), p3);
1055:
1056: REPORT("setup S007: containerId " + cid);
1057: } finally {
1058: t_util.t_commit(t);
1059: t.close();
1060: }
1061: }
1062:
1063: /* recover test 7 */
1064: protected void R007() throws T_Fail, StandardException {
1065: long cid = find(key(7, 0));
1066: if (cid < 0) {
1067: REPORT("R007 not run");
1068: return;
1069: }
1070:
1071: long p1 = find(key(7, 1));
1072: long p2 = find(key(7, 2));
1073: long p3 = find(key(7, 3));
1074:
1075: Transaction t = t_util.t_startTransaction();
1076: try {
1077:
1078: ContainerHandle c = t_util
1079: .t_openContainer(t, 0, cid, false);
1080:
1081: Page p = c.getPage(p1);
1082: if (p != null)
1083: throw T_Fail.testFailMsg("got a deallcated page " + p1);
1084:
1085: p = c.getPage(p2);
1086: if (p != null)
1087: throw T_Fail.testFailMsg("got a deallcated page " + p2);
1088:
1089: p = c.getPage(p3);
1090: if (p != null)
1091: throw T_Fail.testFailMsg("got a deallcated page " + p3);
1092:
1093: p = c.getPage(p3 + 1);
1094: if (p != null)
1095: throw T_Fail.testFailMsg("got a non-existant page "
1096: + p3 + 100);
1097:
1098: p = c.getFirstPage();
1099: if (p != null)
1100: throw T_Fail
1101: .testFailMsg("got a non-existant first page ");
1102:
1103: p = t_util.t_getLastPage(c);
1104: if (p != null)
1105: throw T_Fail
1106: .testFailMsg("got a non-existant last page ");
1107:
1108: PASS("R007: containerId " + cid);
1109: } finally {
1110: t_util.t_commit(t);
1111: t.close();
1112: }
1113: }
1114:
1115: /*
1116: * test 8 - page deallocation with rollback
1117: */
1118: protected void S008() throws T_Fail, StandardException {
1119: Transaction t = t_util.t_startTransaction();
1120: try {
1121: long cid = t_util.t_addContainer(t, 0);
1122: t_util.t_commit(t);
1123:
1124: ContainerHandle c = t_util.t_openContainer(t, 0, cid, true);
1125:
1126: Page page1 = t_util.t_getPage(c,
1127: ContainerHandle.FIRST_PAGE_NUMBER);
1128: long p1 = page1.getPageNumber();
1129:
1130: Page page2 = t_util.t_addPage(c);
1131: long p2 = page2.getPageNumber();
1132:
1133: Page page3 = t_util.t_addPage(c);
1134: long p3 = page3.getPageNumber();
1135:
1136: Page page4 = t_util.t_addPage(c);
1137: long p4 = page4.getPageNumber();
1138:
1139: Page page5 = t_util.t_addPage(c);
1140: long p5 = page5.getPageNumber();
1141:
1142: t_util.t_removePage(c, page1);
1143: t_util.t_removePage(c, page3);
1144: t_util.t_removePage(c, page5);
1145: t_util.t_commit(t);
1146:
1147: c = t_util.t_openContainer(t, 0, cid, true);
1148: page3 = t_util.t_getPage(c, p2);
1149: page1 = t_util.t_getPage(c, p4);
1150:
1151: // page 2 and page 4 are not removed
1152: t_util.t_removePage(c, page2);
1153: t_util.t_removePage(c, page4);
1154:
1155: register(key(8, 0), cid);
1156: register(key(8, 1), p1);
1157: register(key(8, 2), p2);
1158: register(key(8, 3), p3);
1159: register(key(8, 4), p4);
1160: register(key(8, 5), p5);
1161:
1162: REPORT("setup S008: containerId " + cid);
1163: } finally {
1164: t_util.t_abort(t);
1165: t.close();
1166: }
1167:
1168: }
1169:
1170: /* recover test 8 */
1171: protected void R008() throws T_Fail, StandardException {
1172: long cid = find(key(8, 0));
1173: if (cid < 0) {
1174: REPORT("R008 not run");
1175: return;
1176: }
1177:
1178: long p1 = find(key(8, 1));
1179: long p2 = find(key(8, 2));
1180: long p3 = find(key(8, 3));
1181: long p4 = find(key(8, 4));
1182: long p5 = find(key(8, 5));
1183:
1184: Transaction t = t_util.t_startTransaction();
1185: try {
1186:
1187: ContainerHandle c = t_util
1188: .t_openContainer(t, 0, cid, false);
1189:
1190: /* page 1, 3, 5 has been removed, page 2, 4 has not */
1191:
1192: Page p = c.getPage(p1);
1193: if (p != null)
1194: throw T_Fail.testFailMsg("got a deallcated page " + p1);
1195:
1196: p = t_util.t_getPage(c, p2);
1197: p.unlatch();
1198:
1199: p = c.getPage(p3);
1200: if (p != null)
1201: throw T_Fail.testFailMsg("got a deallcated page " + p3);
1202:
1203: p = t_util.t_getPage(c, p4);
1204: p.unlatch();
1205:
1206: p = c.getPage(p5);
1207: if (p != null)
1208: throw T_Fail.testFailMsg("got a deallcated page " + p5);
1209:
1210: p = c.getPage(p5 + 1);
1211: if (p != null)
1212: throw T_Fail.testFailMsg("got a non-existant page "
1213: + p5 + 1);
1214:
1215: // make sure get first page skips over p1
1216: p = c.getFirstPage();
1217: if (p == null || p.getPageNumber() != p2)
1218: throw T_Fail.testFailMsg("get first page failed");
1219: p.unlatch();
1220:
1221: // make sure get next page skips over p3
1222: p = c.getNextPage(p2);
1223: if (p == null || p.getPageNumber() != p4)
1224: throw T_Fail.testFailMsg("get next page failed");
1225: p.unlatch();
1226:
1227: // make sure get next page skips over p5
1228: p = c.getNextPage(p4);
1229: if (p != null) {
1230: p.unlatch();
1231: throw T_Fail
1232: .testFailMsg("get next page failed to terminate");
1233: }
1234:
1235: p = t_util.t_getLastPage(c); // make sure it skips over p5
1236: if (p == null || p.getPageNumber() != p4)
1237: throw T_Fail.testFailMsg("getLastPage failed");
1238: p.unlatch();
1239:
1240: PASS("R008: containerId " + cid);
1241:
1242: } finally {
1243: t_util.t_commit(t);
1244: t.close();
1245: }
1246:
1247: }
1248:
1249: /*
1250: * test 9 - deallocation and reuse pag
1251: */
1252: protected void S009() throws T_Fail, StandardException {
1253: Transaction t = t_util.t_startTransaction();
1254: try {
1255: long cid = t_util.t_addContainer(t, 0);
1256: t_util.t_commit(t);
1257:
1258: ContainerHandle c = t_util.t_openContainer(t, 0, cid, true);
1259: int numpages = 10;
1260:
1261: Page[] origpage = new Page[numpages];
1262: int[] origrid = new int[numpages];
1263: long[] origpnum = new long[numpages];
1264: T_RawStoreRow row1 = new T_RawStoreRow(REC_001);
1265:
1266: for (int i = 0; i < numpages; i++) {
1267: if (i == 0)
1268: origpage[i] = t_util.t_getPage(c,
1269: ContainerHandle.FIRST_PAGE_NUMBER);
1270: else
1271: origpage[i] = t_util.t_addPage(c);
1272:
1273: origrid[i] = t_util.t_insert(origpage[i], row1).getId();
1274: origpnum[i] = origpage[i].getPageNumber();
1275:
1276: t_util.t_removePage(c, origpage[i]);
1277: }
1278: t_util.t_commit(t);
1279:
1280: // check that pages are not reused before transaction is committed
1281: for (int i = 0; i < numpages - 1; i++) {
1282: for (int j = i + 1; j < numpages; j++) {
1283: if (origpnum[i] == origpnum[j])
1284: throw T_Fail
1285: .testFailMsg("page reused before transaction is committed");
1286: }
1287: }
1288:
1289: register(key(9, 0), cid);
1290: register(key(9, 1), numpages);
1291:
1292: for (int i = 0; i < numpages; i++) {
1293: register(key(9, i + 10), origpnum[i]);
1294: register(key(9, i + numpages + 10), origrid[i]);
1295: }
1296:
1297: // now see if we can reuse them
1298: c = t_util.t_openContainer(t, 0, cid, true);
1299:
1300: Page[] newpage = new Page[numpages];
1301: int[] newrid = new int[numpages];
1302: long[] newpnum = new long[numpages];
1303: T_RawStoreRow row2 = new T_RawStoreRow(REC_002);
1304:
1305: for (int i = 0; i < numpages; i++) {
1306: newpage[i] = t_util.t_addPage(c);
1307: newpnum[i] = newpage[i].getPageNumber();
1308: newrid[i] = t_util.t_insert(newpage[i], row2).getId();
1309: }
1310:
1311: // if any page is reused, make sure the rid is not reused
1312: int reuse = 0;
1313: for (int i = 0; i < numpages; i++) {
1314: for (int j = 0; j < numpages; j++) {
1315: if (origpnum[i] == newpnum[j]) {
1316: reuse++;
1317: if (origrid[i] == newrid[j])
1318: throw T_Fail
1319: .testFailMsg("resued page rid is not preserved");
1320:
1321: break; // inner loop
1322: }
1323: }
1324: }
1325:
1326: for (int i = 0; i < numpages; i++) {
1327: register(key(9, i + 100), newpnum[i]);
1328: register(key(9, i + numpages + 100), newrid[i]);
1329: }
1330:
1331: REPORT("setup S009: containerId " + cid + " of " + numpages
1332: + " original pages," + reuse
1333: + " pages were reused.");
1334: } finally {
1335: t_util.t_commit(t);
1336: t.close();
1337: }
1338: }
1339:
1340: /* recover test 9 */
1341: protected void R009() throws T_Fail, StandardException {
1342: long cid = find(key(9, 0));
1343: if (cid < 0) {
1344: REPORT("R009 not run");
1345: return;
1346: }
1347: int numpages = (int) find(key(9, 1));
1348:
1349: int[] newrid = new int[numpages];
1350: long[] newpnum = new long[numpages];
1351: Page[] newpage = new Page[numpages];
1352:
1353: Transaction t = t_util.t_startTransaction();
1354: try {
1355:
1356: ContainerHandle c = t_util
1357: .t_openContainer(t, 0, cid, false);
1358:
1359: for (int i = 0; i < numpages; i++) {
1360: newrid[i] = (int) find(key(9, i + numpages + 100));
1361: newpnum[i] = find(key(9, i + 100));
1362:
1363: newpage[i] = t_util.t_getPage(c, newpnum[i]);
1364: t_util.t_checkRecordCount(newpage[i], 1, 1);
1365: RecordHandle rh = t_util.t_checkFetchFirst(newpage[i],
1366: REC_002);
1367: if (rh.getId() != newrid[i])
1368: throw T_Fail.testFailMsg("recordId not match");
1369: }
1370: REPORT("R009: containerId " + cid);
1371: } finally {
1372: t_util.t_commit(t);
1373: t.close();
1374: }
1375: }
1376:
1377: /*
1378: * test 10 - allocation/deallocation with overflow page
1379: */
1380: protected void S010() throws T_Fail, StandardException {
1381: // maufacture a container with the first and last page being overflow
1382: // pages
1383: Transaction t = t_util.t_startTransaction();
1384: try {
1385: long cid = t_util.t_addContainer(t, 0);
1386: t_util.t_commit(t);
1387:
1388: ContainerHandle c = t_util.t_openContainer(t, 0, cid, true);
1389: int numpages = 10;
1390: Page[] page = new Page[numpages];
1391: long[] pnum = new long[numpages];
1392: RecordHandle[] recordHandles = new RecordHandle[numpages];
1393:
1394: T_RawStoreRow row1 = new T_RawStoreRow(REC_001);
1395: for (int i = 0; i < numpages; i++) {
1396: if (i == 0)
1397: page[i] = t_util.t_getPage(c,
1398: ContainerHandle.FIRST_PAGE_NUMBER);
1399: else
1400: page[i] = t_util.t_addPage(c);
1401:
1402: pnum[i] = page[i].getPageNumber();
1403:
1404: // remove first two and last page as we go, pages are not reused
1405: // until after commit. These pages have no rows in them
1406: if (i < 2 || i == numpages - 1) {
1407: t_util.t_checkEmptyPage(page[i]);
1408: t_util.t_removePage(c, page[i]);
1409: } else
1410: recordHandles[i] = t_util.t_insert(page[i], row1);
1411:
1412: }
1413:
1414: t_util.t_commit(t);
1415: c = t_util.t_openContainer(t, 0, cid, true);
1416:
1417: Page p = c.getFirstPage();
1418: if (p.getPageNumber() != pnum[2])
1419: throw T_Fail
1420: .testFailMsg("first page expected to be page "
1421: + pnum[2] + ", got "
1422: + p.getPageNumber() + " instead");
1423: p.unlatch();
1424: p = t_util.t_getLastPage(c);
1425: if (p.getPageNumber() != pnum[numpages - 2])
1426: throw T_Fail
1427: .testFailMsg("last page expected to be page "
1428: + pnum[numpages - 2] + ", got "
1429: + p.getPageNumber() + " instead");
1430: p.unlatch();
1431:
1432: // now make rows on the rest of the page overflow
1433: RecordHandle rh;
1434: T_RawStoreRow big = new T_RawStoreRow(String
1435: .valueOf(new char[1500]));
1436: REPORT("start reusing pages hopefully");
1437: for (int i = 2; i < numpages - 1; i++) {
1438: T_RawStoreRow row2 = new T_RawStoreRow(REC_002);
1439:
1440: p = t_util.t_getPage(c, pnum[i]);
1441: while (p.spaceForInsert(row2.getRow(),
1442: (FormatableBitSet) null, 100))
1443: t_util.t_insert(p, row2);
1444:
1445: // now page is filled
1446: rh = p.fetchFromSlot((RecordHandle) null, 0, row2
1447: .getRow(), (FetchDescriptor) null, true);
1448: p.update(rh, big.getRow(), (FormatableBitSet) null);
1449: p.unlatch();
1450: }
1451:
1452: register(key(10, 1), cid);
1453: register(key(10, 2), numpages);
1454: for (int i = 0; i < numpages; i++)
1455: register(key(10, 10 + i), pnum[i]);
1456: REPORT("setup S010");
1457: } finally {
1458: t_util.t_commit(t);
1459: t.close();
1460: }
1461: }
1462:
1463: protected void R010() throws T_Fail, StandardException {
1464: long cid = find(key(10, 1));
1465: if (cid < 0) {
1466: REPORT("R010 not run");
1467: return;
1468: }
1469: int numpages = (int) find(key(10, 2));
1470: long[] pnum = new long[numpages];
1471: for (int i = 0; i < numpages; i++)
1472: pnum[i] = find(key(10, 10 + i));
1473:
1474: // now check the pages, 0, 1 and last page (...) are all overflowpages
1475: Transaction t = t_util.t_startTransaction();
1476: try {
1477: ContainerHandle c = t_util.t_openContainer(t, 0, cid, true);
1478: Page p;
1479:
1480: p = c.getPage(pnum[0]);
1481: if (p.recordCount() == 0) // it has no overflow rows in it
1482: {
1483: p.unlatch();
1484: throw T_Fail
1485: .testFailMsg("first page failed to get any overflow records");
1486: }
1487: p.unlatch();
1488: p = c.getPage(pnum[1]);
1489: if (p.recordCount() == 0) // it has no overflow rows in it
1490: {
1491: p.unlatch();
1492: throw T_Fail
1493: .testFailMsg("second page failed to get any overflow records");
1494: }
1495: p.unlatch();
1496: p = c.getPage(pnum[numpages - 1]);
1497: if (p.recordCount() == 0) // it has no overflow rows in it
1498: {
1499: p.unlatch();
1500: throw T_Fail
1501: .testFailMsg("last page failed to get any overflow records");
1502: }
1503: p.unlatch();
1504:
1505: // all other pages have one huge row at the beginning
1506: p = c.getFirstPage();
1507: if (p.getPageNumber() != pnum[2])
1508: throw T_Fail
1509: .testFailMsg("first page expected to be page "
1510: + pnum[2] + ", got "
1511: + p.getPageNumber() + " instead");
1512: long pageNum = p.getPageNumber();
1513: t_util.t_checkStringLengthFetch(p, 0, 1500);
1514:
1515: p.unlatch();
1516: int i = 3;
1517: while ((p = c.getNextPage(pageNum)) != null) {
1518: pageNum = p.getPageNumber();
1519: if (pageNum != pnum[i])
1520: throw T_Fail.testFailMsg("expect page " + pnum[i]
1521: + " get page " + pageNum);
1522: t_util.t_checkStringLengthFetch(p, 0, 1500);
1523: p.unlatch();
1524: i++;
1525: }
1526: if (i != numpages - 1)
1527: throw T_Fail.testFailMsg("expect last head page to be "
1528: + (numpages - 2) + " got " + i
1529: + " page instead");
1530: } finally {
1531: t_util.t_commit(t);
1532: t.close();
1533: }
1534:
1535: PASS("R010");
1536: }
1537:
1538: /*
1539: * test 11 - allocate a lot of pages so that we need > 1 allocation pages
1540: */
1541: protected void S011() throws T_Fail, StandardException {
1542: Transaction t = t_util.t_startTransaction();
1543: int iterations = 10000;
1544:
1545: try {
1546: long cid = t_util.t_addContainer(t, 0, 4096);
1547: t_util.t_commit(t);
1548:
1549: T_RawStoreRow row = new T_RawStoreRow(REC_001);
1550: ContainerHandle c = t_util.t_openContainer(t, 0, cid, true);
1551:
1552: // allocate iterations pages, this ought to bring the number of pages
1553: // over what 1 allocation page can handle
1554: Page p = t_util.t_getPage(c,
1555: ContainerHandle.FIRST_PAGE_NUMBER);
1556: t_util.t_insert(p, row);
1557: p.unlatch();
1558:
1559: long pnum = ContainerHandle.FIRST_PAGE_NUMBER;
1560: long lastPageNum = ContainerHandle.INVALID_PAGE_NUMBER;
1561: for (int i = 1; i <= iterations; i++) {
1562: p = t_util.t_addPage(c);
1563: if (p.getPageNumber() != pnum + 1)
1564: REPORT("S011: skipping " + (pnum + 1)
1565: + " going to " + p.getPageNumber());
1566: pnum = p.getPageNumber();
1567:
1568: t_util.t_insert(p, row);
1569:
1570: if (i == iterations) {
1571: lastPageNum = p.getPageNumber();
1572: REPORT("S011: Last page number is " + lastPageNum);
1573: }
1574:
1575: p.unlatch();
1576: }
1577: t_util.t_commit(t);
1578:
1579: // now scan the pages
1580: c = t_util.t_openContainer(t, 0, cid, true);
1581: p = c.getFirstPage();
1582: if (p == null
1583: || p.getPageNumber() != ContainerHandle.FIRST_PAGE_NUMBER)
1584: throw T_Fail
1585: .testFailMsg("first page not where it is expected");
1586: p.unlatch();
1587:
1588: p = t_util.t_getLastPage(c);
1589: if (p == null || p.getPageNumber() != lastPageNum)
1590: throw T_Fail
1591: .testFailMsg("last page not where it is expected");
1592: p.unlatch();
1593:
1594: register(key(11, 1), cid);
1595: register(key(11, 2), lastPageNum);
1596: register(key(11, 3), iterations);
1597:
1598: REPORT("setup S011, container id = " + cid);
1599: } finally {
1600: t_util.t_commit(t);
1601: t.close();
1602: }
1603: }
1604:
1605: protected void R011() throws T_Fail, StandardException {
1606: long cid = find(key(11, 1));
1607: if (cid < 0) {
1608: REPORT("R011 not run");
1609: return;
1610: } else
1611: REPORT("R011 container id = " + cid);
1612:
1613: long expectedLastPageNum = find(key(11, 2));
1614: int iterations = (int) find(key(11, 3));
1615:
1616: Transaction t = t_util.t_startTransaction();
1617: try {
1618: ContainerHandle c = t_util
1619: .t_openContainer(t, 0, cid, false);
1620: Page p = c.getFirstPage();
1621: if (p == null
1622: || p.getPageNumber() != ContainerHandle.FIRST_PAGE_NUMBER)
1623: throw T_Fail
1624: .testFailMsg("first page not where it is expected");
1625: p.unlatch();
1626:
1627: long pageNum = ContainerHandle.FIRST_PAGE_NUMBER;
1628: long pnum = pageNum;
1629: int pcount = 1;
1630: while ((p = c.getNextPage(pageNum)) != null) {
1631: t_util.t_checkFetchFirst(p, REC_001);
1632: pageNum = p.getPageNumber();
1633: if (pageNum != pnum + 1)
1634: REPORT("R011: skipping " + (pnum + 1)
1635: + " going to " + pageNum);
1636: pnum = pageNum;
1637:
1638: pcount++;
1639: p.unlatch();
1640: }
1641: if (pcount != (iterations + 1)) {
1642: throw T_Fail.testFailMsg("expect to see "
1643: + (iterations + 1) + " pages, got: " + pcount
1644: + " last page number is " + pageNum);
1645: }
1646:
1647: p = t_util.t_getLastPage(c);
1648: if (p.getPageNumber() != expectedLastPageNum) {
1649: throw T_Fail.testFailMsg("expect last page num to be "
1650: + expectedLastPageNum + " , instead got "
1651: + p.getPageNumber());
1652: }
1653:
1654: REPORT("Last page pagenumber is " + p.getPageNumber()
1655: + ", it is the last page of " + (iterations + 1)
1656: + " user pages");
1657: p.unlatch();
1658:
1659: PASS("R011");
1660: } finally {
1661: t_util.t_commit(t);
1662: t.close();
1663: }
1664:
1665: }
1666:
1667: /*
1668: * test 12 - test estimated page count
1669: */
1670: protected void S012() throws T_Fail, StandardException {
1671: Transaction t = t_util.t_startTransaction();
1672:
1673: long cid = t_util.t_addContainer(t, 0, 4096);
1674: t_util.t_commit(t);
1675:
1676: try {
1677: ContainerHandle c = t_util.t_openContainer(t, 0, cid, true);
1678:
1679: if (c.getEstimatedPageCount(0) != 1)
1680: throw T_Fail.testFailMsg("Expect 2 user page, got "
1681: + c.getEstimatedPageCount(0));
1682:
1683: // allocate 30 pages
1684: Page p = t_util.t_getPage(c,
1685: ContainerHandle.FIRST_PAGE_NUMBER);
1686: T_RawStoreRow row = new T_RawStoreRow(REC_001);
1687:
1688: t_util.t_insert(p, row);
1689: p.unlatch();
1690: for (int i = 2; i <= 30; i++) {
1691: p = t_util.t_addPage(c);
1692: t_util.t_insert(p, row);
1693: p.unlatch();
1694: }
1695:
1696: register(key(12, 1), cid);
1697: REPORT("Setup S012");
1698: } finally {
1699: t_util.t_commit(t);
1700: t.close();
1701: }
1702: }
1703:
1704: protected void R012() throws T_Fail, StandardException {
1705: long cid = find(key(12, 1));
1706: if (cid < 0) {
1707: REPORT("R012 not run");
1708: return;
1709: }
1710:
1711: Transaction t = t_util.t_startTransaction();
1712: try {
1713: ContainerHandle c = t_util
1714: .t_openContainer(t, 0, cid, false);
1715: if (c.getEstimatedPageCount(0) != 30)
1716: throw T_Fail.testFailMsg("expect 30 pages, got "
1717: + c.getEstimatedPageCount(0));
1718:
1719: PASS("R012");
1720: } finally {
1721: t_util.t_commit(t);
1722: t.close();
1723: }
1724:
1725: }
1726:
1727: /*
1728: * test 20 - create multiple containers
1729: */
1730: protected void S020() throws T_Fail, StandardException {
1731: Transaction t = t_util.t_startTransaction();
1732: T_RawStoreRow row1 = new T_RawStoreRow(REC_001);
1733: T_RawStoreRow row2 = new T_RawStoreRow(REC_002);
1734: T_RawStoreRow row3 = new T_RawStoreRow(REC_003);
1735:
1736: try {
1737:
1738: long cid1 = t_util.t_addContainer(t, 0);
1739: ContainerHandle c1 = t_util.t_openContainer(t, 0, cid1,
1740: true);
1741: Page page = t_util.t_getPage(c1,
1742: ContainerHandle.FIRST_PAGE_NUMBER);
1743: t_util.t_insertAtSlot(page, 0, row1);
1744: page.unlatch();
1745:
1746: long cid2 = t_util.t_addContainer(t, 0);
1747: ContainerHandle c2 = t_util.t_openContainer(t, 0, cid2,
1748: true);
1749:
1750: long cid3 = t_util.t_addContainer(t, 0);
1751: ContainerHandle c3 = t_util.t_openContainer(t, 0, cid3,
1752: true);
1753:
1754: page = t_util.t_getPage(c2,
1755: ContainerHandle.FIRST_PAGE_NUMBER);
1756: // blank first page
1757: page.unlatch();
1758:
1759: page = t_util.t_addPage(c2);
1760: t_util.t_insertAtSlot(page, 0, row2);
1761: long pageId = page.getPageNumber();
1762: page.unlatch();
1763:
1764: page = t_util.t_getPage(c3,
1765: ContainerHandle.FIRST_PAGE_NUMBER);
1766: t_util.t_insertAtSlot(page, 0, row3);
1767: page.unlatch();
1768:
1769: REPORT("setup S020: container1 " + cid1 + " container2 "
1770: + cid2 + " container3 " + cid3 + " page " + pageId);
1771:
1772: register(key(20, 1), cid1);
1773: register(key(20, 2), cid2);
1774: register(key(20, 3), cid3);
1775: register(key(20, 4), pageId);
1776: } finally {
1777: t_util.t_commit(t);
1778: t.close();
1779: }
1780: }
1781:
1782: /* recover test 20 */
1783: protected void R020() throws T_Fail, StandardException {
1784: long cid1 = find(key(20, 1));
1785: if (cid1 < 0) {
1786: REPORT("R020 not run");
1787: return;
1788: }
1789:
1790: long cid2 = find(key(20, 2));
1791: long cid3 = find(key(20, 3));
1792: long pageId = find(key(20, 4));
1793:
1794: Transaction t = t_util.t_startTransaction();
1795: try {
1796:
1797: ContainerHandle c = t_util.t_openContainer(t, 0, cid1,
1798: false);
1799: Page page = t_util.t_getPage(c, c.FIRST_PAGE_NUMBER);
1800: t_util.t_checkRecordCount(page, 1, 1);
1801: t_util.t_checkFetchBySlot(page, 0, REC_001, false, false);
1802: page.unlatch();
1803:
1804: c = t_util.t_openContainer(t, 0, cid2, false);
1805: page = t_util.t_getPage(c, c.FIRST_PAGE_NUMBER);
1806: t_util.t_checkEmptyPage(page);
1807: page.unlatch();
1808:
1809: page = t_util.t_getPage(c, pageId);
1810: t_util.t_checkRecordCount(page, 1, 1);
1811: t_util.t_checkFetchBySlot(page, 0, REC_002, false, false);
1812: page.unlatch();
1813:
1814: c = t_util.t_openContainer(t, 0, cid3, false);
1815: page = t_util.t_getPage(c, c.FIRST_PAGE_NUMBER);
1816: t_util.t_checkRecordCount(page, 1, 1);
1817: t_util.t_checkFetchBySlot(page, 0, REC_003, false, false);
1818: page.unlatch();
1819:
1820: } finally {
1821: t_util.t_commit(t);
1822: t.close();
1823: }
1824:
1825: PASS("R020 container1 " + cid1 + " container2 " + cid2
1826: + " container3 " + cid3 + " page " + pageId);
1827: }
1828:
1829: /*
1830: * test 022 - drop containers
1831: */
1832: protected void S022() throws T_Fail, StandardException {
1833: Transaction t = t_util.t_startTransaction();
1834: try {
1835:
1836: long cid = t_util.t_addContainer(t, 0);
1837: t_util.t_commit(t);
1838:
1839: t_util.t_openContainer(t, 0, cid, true);
1840: t_util.t_dropContainer(t, 0, cid);
1841:
1842: t_util.t_abort(t); // this should rollback the drop
1843: t_util.t_openContainer(t, 0, cid, true);
1844:
1845: REPORT("rollback of drop container tested");
1846:
1847: t.dropContainer(new ContainerKey(0, cid));
1848:
1849: t.commit();
1850:
1851: REPORT("setup S022: containerId " + cid);
1852:
1853: register(key(22, 1), cid);
1854:
1855: } finally {
1856: t_util.t_commit(t);
1857: t.close();
1858: }
1859: }
1860:
1861: /*
1862: * recover test 022 - drop container
1863: */
1864: protected void R022() throws T_Fail, StandardException {
1865: long cid = find(key(22, 1));
1866: if (cid < 0) {
1867: REPORT("R022 not run");
1868: return;
1869: }
1870:
1871: Transaction t = t_util.t_startTransaction();
1872: try {
1873: ContainerKey id = new ContainerKey(0, cid);
1874: ContainerHandle c1 = t.openContainer(id,
1875: ContainerHandle.MODE_READONLY); // this should fail
1876: if (c1 != null)
1877: throw T_Fail
1878: .testFailMsg("dropped container should fail to open");
1879: } finally {
1880: t_util.t_commit(t);
1881: t.close();
1882: }
1883: PASS("R022 : containerId " + cid);
1884: }
1885:
1886: /*
1887: * test 100 - multiple intervening committed transactions
1888: */
1889: protected void S100() throws T_Fail, StandardException {
1890: T_TWC t1 = t_util.t_startTransactionWithContext();
1891: T_TWC t2 = t_util.t_startTransactionWithContext();
1892: try {
1893:
1894: long cid10 = t_util.t_addContainer(t1, 0);
1895: long cid11 = t_util.t_addContainer(t1, 0);
1896: t_util.t_commit(t1);
1897:
1898: long cid20 = t_util.t_addContainer(t2, 0);
1899: long cid21 = t_util.t_addContainer(t2, 0);
1900: t_util.t_commit(t2);
1901:
1902: ContainerHandle c10 = t_util.t_openContainer(t1, 0, cid10,
1903: true);
1904: ContainerHandle c11 = t_util.t_openContainer(t1, 0, cid11,
1905: true);
1906: ContainerHandle c20 = t_util.t_openContainer(t2, 0, cid20,
1907: true);
1908: ContainerHandle c21 = t_util.t_openContainer(t2, 0, cid21,
1909: true);
1910:
1911: t1.switchTransactionContext();
1912: Page p10 = t_util.t_getPage(c10,
1913: ContainerHandle.FIRST_PAGE_NUMBER);
1914: Page p11 = t_util.t_getPage(c11,
1915: ContainerHandle.FIRST_PAGE_NUMBER);
1916: t1.resetContext();
1917:
1918: t2.switchTransactionContext();
1919: Page p20 = t_util.t_getPage(c20,
1920: ContainerHandle.FIRST_PAGE_NUMBER);
1921: Page p21 = t_util.t_getPage(c21,
1922: ContainerHandle.FIRST_PAGE_NUMBER);
1923:
1924: // for each page, insert, update, updatefield, (some) delete
1925:
1926: T_RawStoreRow row1 = new T_RawStoreRow(3);
1927: row1.setColumn(0, REC_001);
1928: row1.setColumn(1, REC_002);
1929: row1.setColumn(2, (String) null);
1930:
1931: T_RawStoreRow row2 = new T_RawStoreRow(2);
1932: row2.setColumn(0, REC_003);
1933: row2.setColumn(1, REC_004);
1934:
1935: T_RawStoreRow rowP = new T_RawStoreRow(1);
1936: rowP.setColumn(0, REC_005);
1937: t2.resetContext();
1938:
1939: t1.switchTransactionContext();
1940: RecordHandle r10 = t_util.t_insertAtSlot(p10, 0, row1);
1941: RecordHandle r11 = t_util.t_insertAtSlot(p11, 0, row1);
1942: t1.resetContext();
1943:
1944: t2.switchTransactionContext();
1945: RecordHandle r20 = t_util.t_insertAtSlot(p20, 0, row1);
1946: RecordHandle r21 = t_util.t_insertAtSlot(p21, 0, row1);
1947: t2.resetContext();
1948:
1949: t1.switchTransactionContext();
1950: p10.update(r10, row2.getRow(), (FormatableBitSet) null);
1951: p11.update(r11, row2.getRow(), (FormatableBitSet) null);
1952: t1.resetContext();
1953:
1954: t2.switchTransactionContext();
1955: p20.update(r20, row2.getRow(), (FormatableBitSet) null);
1956: p21.update(r21, row2.getRow(), (FormatableBitSet) null);
1957: t2.resetContext();
1958:
1959: t1.switchTransactionContext();
1960: p10.update(r10, rowP.getRow(), BS_COL_0);
1961: p11.update(r11, rowP.getRow(), BS_COL_0);
1962: p10.unlatch();
1963: p11.unlatch();
1964: t1.resetContext();
1965:
1966: t2.switchTransactionContext();
1967: p20.update(r20, rowP.getRow(), BS_COL_0);
1968: p21.update(r21, rowP.getRow(), BS_COL_0);
1969:
1970: p21.delete(r21, (LogicalUndo) null);
1971: p20.unlatch();
1972: p21.unlatch();
1973: t2.resetContext();
1974:
1975: REPORT("setup S100: container1 " + cid10 + " container2 "
1976: + cid11 + " container3 " + cid20 + " container4 "
1977: + cid21);
1978:
1979: register(key(100, 1), cid10);
1980: register(key(100, 2), cid11);
1981: register(key(100, 3), cid20);
1982: register(key(100, 4), cid21);
1983: } finally {
1984: t_util.t_commit(t1);
1985: t_util.t_close(t1);
1986:
1987: t_util.t_commit(t2);
1988: t_util.t_close(t2);
1989: }
1990: }
1991:
1992: /* recover S100 */
1993: protected void R100() throws T_Fail, StandardException {
1994: long[] cid = new long[4];
1995: cid[0] = find(key(100, 1));
1996: if (cid[0] < 0) {
1997: REPORT("R100 not run");
1998: return;
1999: }
2000:
2001: cid[1] = find(key(100, 2));
2002: cid[2] = find(key(100, 3));
2003: cid[3] = find(key(100, 4));
2004:
2005: Transaction t = t_util.t_startTransaction();
2006: try {
2007: ContainerHandle c;
2008: Page page;
2009:
2010: for (int i = 0; i < 4; i++) {
2011: c = t_util.t_openContainer(t, 0, cid[i], false);
2012: page = t_util.t_getPage(c,
2013: ContainerHandle.FIRST_PAGE_NUMBER);
2014: if (i == 3)
2015: t_util.t_checkRecordCount(page, 1, 0);
2016: else
2017: t_util.t_checkRecordCount(page, 1, 1);
2018:
2019: t_util.t_checkFieldCount(page, 0, 2);
2020:
2021: // each row has REC_005, REC_004
2022: DataValueDescriptor column = new SQLChar();
2023: t_util.t_checkFetchColFromSlot(page, 0, 0, column,
2024: false, REC_005);
2025: t_util.t_checkFetchColFromSlot(page, 0, 1, column,
2026: false, REC_004);
2027: page.unlatch();
2028: }
2029:
2030: PASS("R100 passed: container1 " + cid[0] + " container2 "
2031: + cid[1] + " container3 " + cid[2] + " container4 "
2032: + cid[3]);
2033: } finally {
2034: t_util.t_commit(t);
2035: t.close();
2036: }
2037: }
2038:
2039: /*
2040: * test 101 - transaction with rollback to savepoint
2041: */
2042: protected void S101() throws T_Fail, StandardException {
2043: Transaction t = t_util.t_startTransaction();
2044: try {
2045:
2046: long cid = t_util.t_addContainer(t, 0);
2047: t_util.t_commit(t);
2048:
2049: ContainerHandle c = t_util.t_openContainer(t, 0, cid, true);
2050: Page page = t_util.t_getPage(c,
2051: ContainerHandle.FIRST_PAGE_NUMBER);
2052:
2053: T_RawStoreRow row1 = new T_RawStoreRow(REC_001);
2054: T_RawStoreRow row2 = new T_RawStoreRow(REC_002);
2055: T_RawStoreRow row3 = new T_RawStoreRow(REC_003);
2056: T_RawStoreRow row4 = new T_RawStoreRow(REC_004);
2057: T_RawStoreRow row5 = new T_RawStoreRow(REC_005);
2058:
2059: RecordHandle r0 = t_util.t_insertAtSlot(page, 0, row1);
2060: if (t_util.t_insertAtSlot(page, 1, row2) == null)
2061: return; // test case not interesting
2062:
2063: t_util.t_checkRecordCount(page, 2, 2);
2064: t_util.t_checkFetchBySlot(page, 0, REC_001, false, false);
2065: t_util.t_checkFetchBySlot(page, 1, REC_002, false, false);
2066: /////////////////////////////////////////////////////
2067: // At SP1, has 2 records of REC_001 and REC_002 //
2068: /////////////////////////////////////////////////////
2069: t.setSavePoint(SP1, null);
2070:
2071: if (t_util.t_insertAtSlot(page, 2, row3) == null)
2072: return; // test case not interesting
2073:
2074: page.purgeAtSlot(1, 1, true);
2075:
2076: if (t_util.t_insertAtSlot(page, 1, row4) == null)
2077: return;
2078:
2079: t_util.t_checkRecordCount(page, 3, 3);
2080: t_util.t_checkFetchBySlot(page, 0, REC_001, false, false);
2081: t_util.t_checkFetchBySlot(page, 1, REC_004, false, false);
2082: t_util.t_checkFetchBySlot(page, 2, REC_003, false, false);
2083: ////////////////////////////////////////////////////////////////
2084: // At SP2, has 3 records of REC_001 and REC_004 and REC_003 //
2085: ////////////////////////////////////////////////////////////////
2086: t.setSavePoint(SP2, null);
2087:
2088: page.update(r0, row5.getRow(), (FormatableBitSet) null);
2089: page.deleteAtSlot(1, true, (LogicalUndo) null);
2090:
2091: t_util.t_checkRecordCount(page, 3, 2);
2092: t_util.t_checkFetchBySlot(page, 0, REC_005, false, false);
2093: t_util.t_checkFetchBySlot(page, 1, REC_004, true, false);
2094: t_util.t_checkFetchBySlot(page, 2, REC_003, false, false);
2095:
2096: page.unlatch();
2097: t.rollbackToSavePoint(SP2, null);
2098: page = t_util.t_getPage(c,
2099: ContainerHandle.FIRST_PAGE_NUMBER);
2100:
2101: t_util.t_checkRecordCount(page, 3, 3);
2102: t_util.t_checkFetchBySlot(page, 0, REC_001, false, false);
2103: t_util.t_checkFetchBySlot(page, 1, REC_004, false, false);
2104: t_util.t_checkFetchBySlot(page, 2, REC_003, false, false);
2105:
2106: // after a rollback to sp, do some more changes
2107:
2108: page.update(r0, row5.getRow(), (FormatableBitSet) null);
2109: page.deleteAtSlot(0, true, (LogicalUndo) null);
2110: page.deleteAtSlot(1, true, (LogicalUndo) null);
2111: page.deleteAtSlot(2, true, (LogicalUndo) null);
2112:
2113: t_util.t_checkRecordCount(page, 3, 0);
2114: t_util.t_checkFetchBySlot(page, 0, REC_005, true, false);
2115: t_util.t_checkFetchBySlot(page, 1, REC_004, true, false);
2116: t_util.t_checkFetchBySlot(page, 2, REC_003, true, false);
2117:
2118: page.unlatch();
2119: t.rollbackToSavePoint(SP1, null);
2120: page = t_util.t_getPage(c,
2121: ContainerHandle.FIRST_PAGE_NUMBER);
2122:
2123: // note that an insert, when rolled back, becomes a deleted row but
2124: // will not disappear. A purge row will come back at the same slot
2125: // and with the same record id.
2126: t_util.t_checkRecordCount(page, 4, 2);
2127:
2128: t_util.t_checkFetchBySlot(page, 0, REC_001, false, false);
2129: t_util.t_checkFetchBySlot(page, 1, REC_002, false, false);
2130: t_util.t_checkFetchBySlot(page, 2, REC_004, true, false);
2131: t_util.t_checkFetchBySlot(page, 3, REC_003, true, false);
2132:
2133: // add one more record to this
2134: if (page.spaceForInsert())
2135: t_util.t_insertAtSlot(page, 3, row5);
2136:
2137: REPORT("setup S101: containerId " + cid + " recordCount "
2138: + page.recordCount());
2139:
2140: register(key(101, 1), cid);
2141: register(key(101, 2), page.recordCount());
2142:
2143: page.unlatch();
2144: } finally {
2145: t_util.t_commit(t);
2146: t.close();
2147: }
2148: }
2149:
2150: /* recover test 101 */
2151: protected void R101() throws T_Fail, StandardException {
2152: long cid = find(key(101, 1));
2153: if (cid < 0) {
2154: REPORT("R101 not run");
2155: return;
2156: }
2157: int recordCount = (int) find(key(101, 2));
2158:
2159: Transaction t = t_util.t_startTransaction();
2160: try {
2161:
2162: ContainerHandle c = t_util
2163: .t_openContainer(t, 0, cid, false);
2164: Page page = t_util.t_getPage(c,
2165: ContainerHandle.FIRST_PAGE_NUMBER);
2166:
2167: t_util.t_checkRecordCount(page, recordCount,
2168: recordCount - 2);
2169: t_util.t_checkFetchBySlot(page, 0, REC_001, false, false);
2170: t_util.t_checkFetchBySlot(page, 1, REC_002, false, false);
2171: t_util.t_checkFetchBySlot(page, 2, REC_004, true, false);
2172: if (recordCount == 5) {
2173: t_util.t_checkFetchBySlot(page, 3, REC_005, false,
2174: false);
2175: t_util
2176: .t_checkFetchBySlot(page, 4, REC_003, true,
2177: false);
2178: } else
2179: t_util
2180: .t_checkFetchBySlot(page, 3, REC_003, true,
2181: false);
2182:
2183: page.unlatch();
2184: } finally {
2185: t_util.t_commit(t);
2186: t.close();
2187: }
2188:
2189: PASS("R101: containerId " + cid + " recordCount " + recordCount);
2190: }
2191:
2192: /*
2193: * the following tests has recovery undo work, cannot test Rnnn during
2194: * setup because it hasn't been rolled back during setup yet. Test the
2195: * state in Snnn.
2196: */
2197:
2198: /*
2199: * test 200 - incomplete transaction
2200: */
2201: protected void S200() throws T_Fail, StandardException {
2202: T_TWC ctx = t_util.t_startTransactionWithContext();
2203: Transaction t = ctx.tran;
2204: Page page = null;
2205:
2206: try {
2207: long cid = t_util.t_addContainer(t, 0);
2208:
2209: t_util.t_commit(t);
2210:
2211: ContainerHandle c = t_util.t_openContainer(t, 0, cid, true);
2212:
2213: ctx.switchTransactionContext();
2214:
2215: page = t_util.t_getPage(c,
2216: ContainerHandle.FIRST_PAGE_NUMBER);
2217:
2218: T_RawStoreRow row1 = new T_RawStoreRow(REC_001);
2219:
2220: int rowcount = 0;
2221: while (page.spaceForInsert()) {
2222: if (t_util.t_insertAtSlot(page, 0, row1) != null)
2223: rowcount++;
2224: }
2225:
2226: t_util.t_checkRecordCount(page, rowcount, rowcount);
2227: for (int i = 0; i < rowcount; i++)
2228: t_util.t_checkFetchBySlot(page, i, REC_001, false,
2229: false);
2230:
2231: REPORT("setup S200: containerId " + cid + " recordCount "
2232: + rowcount);
2233: register(key(200, 1), cid);
2234: register(key(200, 2), rowcount);
2235: } finally {
2236: if (page != null && page.isLatched())
2237: page.unlatch();
2238: ctx.resetContext();
2239: }
2240: // do not abort it at run time, abort it at recovery time
2241: // t_util.t_abort(t);
2242: // t.close();
2243: }
2244:
2245: /* recover test 200 */
2246: protected void R200() throws T_Fail, StandardException {
2247: long cid = find(key(200, 1));
2248: if (cid < 0) {
2249: REPORT("R200 not run");
2250: return;
2251: }
2252:
2253: int recordCount = (int) find(key(200, 2));
2254:
2255: Transaction t = t_util.t_startTransaction();
2256: try {
2257:
2258: ContainerHandle c = t_util
2259: .t_openContainer(t, 0, cid, false);
2260: Page page = t_util.t_getPage(c,
2261: ContainerHandle.FIRST_PAGE_NUMBER);
2262:
2263: // rollback of an insert is a deleted record
2264: t_util.t_checkRecordCount(page, recordCount, 0);
2265: for (int i = 0; i < recordCount; i++)
2266: t_util
2267: .t_checkFetchBySlot(page, i, REC_001, true,
2268: false);
2269: page.unlatch();
2270:
2271: PASS("R200: containerId " + cid + " recordCount "
2272: + recordCount);
2273:
2274: } finally {
2275: t_util.t_commit(t);
2276: t.close();
2277: }
2278: }
2279:
2280: /*
2281: * test 201 - multiple intervening incomplete transaction
2282: */
2283: protected void S201() throws T_Fail, StandardException {
2284: /* this is the same as S100 but left it at an incomplete state */
2285: T_TWC t1 = t_util.t_startTransactionWithContext();
2286: T_TWC t2 = t_util.t_startTransactionWithContext();
2287: Page p10, p11, p20, p21;
2288: p10 = p11 = p20 = p21 = null;
2289:
2290: try {
2291: long cid10 = t_util.t_addContainer(t1, 0);
2292: long cid11 = t_util.t_addContainer(t1, 0);
2293:
2294: long cid20 = t_util.t_addContainer(t2, 0);
2295: long cid21 = t_util.t_addContainer(t2, 0);
2296:
2297: t_util.t_commit(t1);
2298: t_util.t_commit(t2);
2299:
2300: ContainerHandle c10 = t_util.t_openContainer(t1, 0, cid10,
2301: true);
2302: ContainerHandle c11 = t_util.t_openContainer(t1, 0, cid11,
2303: true);
2304: ContainerHandle c20 = t_util.t_openContainer(t2, 0, cid20,
2305: true);
2306: ContainerHandle c21 = t_util.t_openContainer(t2, 0, cid21,
2307: true);
2308:
2309: t1.switchTransactionContext();
2310: p10 = t_util.t_getPage(c10,
2311: ContainerHandle.FIRST_PAGE_NUMBER);
2312: p11 = t_util.t_getPage(c11,
2313: ContainerHandle.FIRST_PAGE_NUMBER);
2314: t1.resetContext();
2315:
2316: t2.switchTransactionContext();
2317: p20 = t_util.t_getPage(c20,
2318: ContainerHandle.FIRST_PAGE_NUMBER);
2319: p21 = t_util.t_getPage(c21,
2320: ContainerHandle.FIRST_PAGE_NUMBER);
2321:
2322: // for each page, insert, update, updatefield, (some) delete
2323:
2324: T_RawStoreRow row1 = new T_RawStoreRow(3);
2325: row1.setColumn(0, REC_001);
2326: row1.setColumn(1, REC_002);
2327: row1.setColumn(2, (String) null);
2328:
2329: T_RawStoreRow row2 = new T_RawStoreRow(2);
2330: row2.setColumn(0, REC_003);
2331: row2.setColumn(1, REC_004);
2332:
2333: T_RawStoreRow rowP = new T_RawStoreRow(1);
2334: rowP.setColumn(0, REC_005);
2335: t2.resetContext();
2336:
2337: t1.switchTransactionContext();
2338: RecordHandle r10 = t_util.t_insertAtSlot(p10, 0, row1);
2339: RecordHandle r11 = t_util.t_insertAtSlot(p11, 0, row1);
2340: t1.resetContext();
2341:
2342: t2.switchTransactionContext();
2343: RecordHandle r20 = t_util.t_insertAtSlot(p20, 0, row1);
2344: RecordHandle r21 = t_util.t_insertAtSlot(p21, 0, row1);
2345: t2.resetContext();
2346:
2347: t1.switchTransactionContext();
2348: p10.update(r10, row2.getRow(), (FormatableBitSet) null);
2349: p11.update(r11, row2.getRow(), (FormatableBitSet) null);
2350: t1.resetContext();
2351:
2352: t2.switchTransactionContext();
2353: p20.update(r20, row2.getRow(), (FormatableBitSet) null);
2354: p21.update(r21, row2.getRow(), (FormatableBitSet) null);
2355: t2.resetContext();
2356:
2357: t1.switchTransactionContext();
2358: p10.update(r10, rowP.getRow(), BS_COL_0);
2359: p11.update(r11, rowP.getRow(), BS_COL_0);
2360: t1.resetContext();
2361:
2362: t2.switchTransactionContext();
2363: p20.update(r20, rowP.getRow(), BS_COL_0);
2364: p21.update(r21, rowP.getRow(), BS_COL_0);
2365:
2366: p21.delete(r21, (LogicalUndo) null);
2367: t2.resetContext();
2368:
2369: REPORT("setup S201: container1 " + cid10 + " container2 "
2370: + cid11 + " container3 " + cid20 + " container4 "
2371: + cid21);
2372:
2373: register(key(201, 1), cid10);
2374: register(key(201, 2), cid11);
2375: register(key(201, 3), cid20);
2376: register(key(201, 4), cid21);
2377: } finally {
2378: if (p10 != null && p10.isLatched())
2379: p10.unlatch();
2380:
2381: if (p11 != null && p11.isLatched())
2382: p11.unlatch();
2383:
2384: if (p20 != null && p20.isLatched())
2385: p20.unlatch();
2386:
2387: if (p21 != null && p21.isLatched())
2388: p21.unlatch();
2389: }
2390:
2391: // let recovery do the abort
2392: }
2393:
2394: /* recover test 201 */
2395: protected void R201() throws T_Fail, StandardException {
2396: long[] cid = new long[4];
2397: cid[0] = find(key(201, 1));
2398: if (cid[0] < 0) {
2399: REPORT("R201 not run");
2400: return;
2401: }
2402:
2403: cid[1] = find(key(201, 2));
2404: cid[2] = find(key(201, 3));
2405: cid[3] = find(key(201, 4));
2406:
2407: Transaction t = t_util.t_startTransaction();
2408: try {
2409:
2410: ContainerHandle c;
2411: Page page;
2412:
2413: for (int i = 0; i < 4; i++) {
2414: c = t_util.t_openContainer(t, 0, cid[i], false);
2415: page = t_util.t_getPage(c,
2416: ContainerHandle.FIRST_PAGE_NUMBER);
2417: t_util.t_checkRecordCount(page, 1, 0);
2418:
2419: // record has the following fields: REC_001, REC_002, null
2420: DataValueDescriptor column = new SQLChar();
2421: t_util.t_checkFetchColFromSlot(page, 0, 0, column,
2422: false, REC_001);
2423: t_util.t_checkFetchColFromSlot(page, 0, 1, column,
2424: false, REC_002);
2425: t_util.t_checkFetchColFromSlot(page, 0, 2, column,
2426: false, null);
2427: }
2428: } finally {
2429: t_util.t_commit(t);
2430: t.close();
2431: }
2432: PASS("R201 passed: container1 " + cid[0] + " container2 "
2433: + cid[1] + " container3 " + cid[2] + " container4 "
2434: + cid[3]);
2435: }
2436:
2437: /*
2438: * test 202 - incomplete transaction with rollback to savepoints
2439: */
2440: protected void S202() throws T_Fail, StandardException {
2441: /* this is S101 which is left in an incomplete state */
2442: T_TWC ctx = t_util.t_startTransactionWithContext();
2443: Transaction t = ctx.tran;
2444: Page page = null;
2445: ctx.switchTransactionContext();
2446:
2447: try {
2448: long cid = t_util.t_addContainer(t, 0);
2449: t_util.t_commit(t);
2450:
2451: ContainerHandle c = t_util.t_openContainer(t, 0, cid, true);
2452: page = t_util.t_getPage(c,
2453: ContainerHandle.FIRST_PAGE_NUMBER);
2454:
2455: T_RawStoreRow row1 = new T_RawStoreRow(REC_001);
2456: T_RawStoreRow row2 = new T_RawStoreRow(REC_002);
2457: T_RawStoreRow row3 = new T_RawStoreRow(REC_003);
2458: T_RawStoreRow row4 = new T_RawStoreRow(REC_004);
2459: T_RawStoreRow row5 = new T_RawStoreRow(REC_005);
2460:
2461: RecordHandle r0 = t_util.t_insertAtSlot(page, 0, row1);
2462: if (t_util.t_insertAtSlot(page, 1, row2) == null) {
2463: page.unlatch();
2464: t_util.t_abort(t);
2465: t.close();
2466: return; // test case not interesting
2467: }
2468:
2469: /////////////////////////////////////////////////////
2470: // At SP1, has 2 records of REC_001 and REC_002 //
2471: /////////////////////////////////////////////////////
2472: t.setSavePoint(SP1, null);
2473:
2474: page.update(r0, row5.getRow(), (FormatableBitSet) null);
2475: t_util.t_checkFetchBySlot(page, 0, REC_005, false, false);
2476: t_util.t_checkFetchBySlot(page, 1, REC_002, false, false);
2477:
2478: page.unlatch();
2479: t.rollbackToSavePoint(SP1, null);
2480: page = t_util.t_getPage(c,
2481: ContainerHandle.FIRST_PAGE_NUMBER);
2482:
2483: t_util.t_checkFetchBySlot(page, 0, REC_001, false, false);
2484: t_util.t_checkFetchBySlot(page, 1, REC_002, false, false);
2485:
2486: if (t_util.t_insertAtSlot(page, 2, row3) == null) {
2487: page.unlatch();
2488: t_util.t_abort(t);
2489: t.close();
2490: return; // test case not interesting
2491: }
2492:
2493: page.purgeAtSlot(1, 1, true);
2494:
2495: if (t_util.t_insertAtSlot(page, 1, row4) == null) {
2496: page.unlatch();
2497: t_util.t_abort(t);
2498: t.close();
2499: return; // test case not interesting
2500: }
2501:
2502: t_util.t_checkRecordCount(page, 3, 3);
2503: t_util.t_checkFetchBySlot(page, 0, REC_001, false, false);
2504: t_util.t_checkFetchBySlot(page, 1, REC_004, false, false);
2505: t_util.t_checkFetchBySlot(page, 2, REC_003, false, false);
2506: ////////////////////////////////////////////////////////////////
2507: // At SP2, has 3 records of REC_001 and REC_004 and REC_003 //
2508: ////////////////////////////////////////////////////////////////
2509: t.setSavePoint(SP2, null);
2510:
2511: page.update(r0, row5.getRow(), (FormatableBitSet) null);
2512: page.deleteAtSlot(1, true, (LogicalUndo) null);
2513:
2514: t_util.t_checkRecordCount(page, 3, 2);
2515: t_util.t_checkFetchBySlot(page, 0, REC_005, false, false);
2516: t_util.t_checkFetchBySlot(page, 1, REC_004, true, false);
2517: t_util.t_checkFetchBySlot(page, 2, REC_003, false, false);
2518:
2519: page.unlatch();
2520: t.rollbackToSavePoint(SP2, null);
2521: page = t_util.t_getPage(c,
2522: ContainerHandle.FIRST_PAGE_NUMBER);
2523:
2524: t_util.t_checkRecordCount(page, 3, 3);
2525: t_util.t_checkFetchBySlot(page, 0, REC_001, false, false);
2526: t_util.t_checkFetchBySlot(page, 1, REC_004, false, false);
2527: t_util.t_checkFetchBySlot(page, 2, REC_003, false, false);
2528:
2529: // after a rollback to sp, do some more changes
2530:
2531: page.update(r0, row5.getRow(), (FormatableBitSet) null);
2532: page.deleteAtSlot(0, true, (LogicalUndo) null);
2533: page.deleteAtSlot(1, true, (LogicalUndo) null);
2534: page.deleteAtSlot(2, true, (LogicalUndo) null);
2535:
2536: t_util.t_checkRecordCount(page, 3, 0);
2537: t_util.t_checkFetchBySlot(page, 0, REC_005, true, false);
2538: t_util.t_checkFetchBySlot(page, 1, REC_004, true, false);
2539: t_util.t_checkFetchBySlot(page, 2, REC_003, true, false);
2540:
2541: page.unlatch();
2542: t.rollbackToSavePoint(SP1, null);
2543: page = t_util.t_getPage(c,
2544: ContainerHandle.FIRST_PAGE_NUMBER);
2545:
2546: // note that an insert, when rolled back, becomes a deleted row but
2547: // will not disappear. A purge row will come back at the same slot
2548: // and with the same record id.
2549: t_util.t_checkRecordCount(page, 4, 2);
2550:
2551: t_util.t_checkFetchBySlot(page, 0, REC_001, false, false);
2552: t_util.t_checkFetchBySlot(page, 1, REC_002, false, false);
2553: t_util.t_checkFetchBySlot(page, 2, REC_004, true, false);
2554: t_util.t_checkFetchBySlot(page, 3, REC_003, true, false);
2555:
2556: // add one more record to this
2557: if (page.spaceForInsert())
2558: t_util.t_insertAtSlot(page, 3, row5);
2559:
2560: REPORT("setup S202: containerId " + cid + " recordCount "
2561: + page.recordCount());
2562:
2563: register(key(202, 1), cid);
2564: register(key(202, 2), page.recordCount());
2565:
2566: } finally {
2567: if (page != null && page.isLatched())
2568: page.unlatch();
2569: ctx.resetContext();
2570: }
2571:
2572: // let recovery undo rollback this transaction
2573:
2574: }
2575:
2576: /* recover test 202 */
2577: protected void R202() throws T_Fail, StandardException {
2578: long cid = find(key(202, 1));
2579: if (cid < 0) {
2580: REPORT("R202 not run");
2581: return;
2582: }
2583: int recordCount = (int) find(key(202, 2));
2584:
2585: Transaction t = t_util.t_startTransaction();
2586: Page page = null;
2587:
2588: try {
2589: ContainerHandle c = t_util.t_openContainer(t, 0, cid, true);
2590: page = t_util.t_getPage(c,
2591: ContainerHandle.FIRST_PAGE_NUMBER);
2592:
2593: // rollback will leave the page with only deleted rows
2594: t_util.t_checkRecordCount(page, recordCount, 0);
2595: t_util.t_checkFetchBySlot(page, 0, REC_001, true, true);
2596: t_util.t_checkFetchBySlot(page, 1, REC_002, true, true);
2597: t_util.t_checkFetchBySlot(page, 2, REC_004, true, true);
2598: if (recordCount == 5) {
2599: t_util.t_checkFetchBySlot(page, 3, REC_005, true, true);
2600: t_util.t_checkFetchBySlot(page, 4, REC_003, true, true);
2601: } else
2602: t_util.t_checkFetchBySlot(page, 3, REC_003, true, true);
2603:
2604: } finally {
2605: if (page != null && page.isLatched())
2606: page.unlatch();
2607:
2608: t_util.t_commit(t);
2609: t.close();
2610: }
2611: PASS("R202: containerId " + cid + " recordCount " + recordCount);
2612: }
2613:
2614: /*
2615: * test 203 - incomplete and committed and aborted
2616: * transaction with intervening rollback to savepoints
2617: */
2618: protected void S203() throws T_Fail, StandardException {
2619: int numtrans = 5;
2620: int numpages = 2;
2621: int i, j;
2622:
2623: T_TWC[] t = new T_TWC[numtrans];
2624: for (i = 0; i < numtrans; i++)
2625: t[i] = t_util.t_startTransactionWithContext();
2626:
2627: Page[][] page = null;
2628:
2629: try {
2630: long[] cid = new long[numtrans];
2631: ContainerHandle[] c = new ContainerHandle[numtrans];
2632:
2633: for (i = 0; i < numtrans; i++) {
2634: cid[i] = t_util.t_addContainer(t[i], 0);
2635: t_util.t_commit(t[i]);
2636: c[i] = t_util.t_openContainer(t[i], 0, cid[i], true);
2637: }
2638:
2639: page = new Page[numtrans][numpages];
2640: long pagenum[][] = new long[numtrans][numpages];
2641:
2642: for (i = 0; i < numtrans; i++) {
2643: for (j = 0; j < numpages; j++) {
2644: t[i].switchTransactionContext();
2645: page[i][j] = t_util.t_addPage(c[i]);
2646: pagenum[i][j] = page[i][j].getPageNumber();
2647: t[i].resetContext();
2648: }
2649: }
2650:
2651: // set up numtrans (at least 5) transactions, each with one
2652: // container and numpages pages. Do the following test:
2653: //
2654: // 1) insert 1 row onto each page
2655: // set savepoint SP1 on first transaction (t0)
2656: //
2657: // 2) update every rows
2658: // set savepoint SP1 on all other transactions
2659: //
2660: // 3) update every rows
2661: // set savepoint SP2 on all transactions
2662: //
2663: // 4) update every rows
2664: //
2665: // 5) rollback t0 to SP1
2666: //
2667: // check that only page[0][x] have been rolled back
2668: // past SP2
2669: //
2670: // 6) update every row
2671: // 7) rollback SP2 on all transaction except the first
2672: //
2673: // 8) update every rows
2674: // 9) rollback t0 to SP1
2675: //
2676: // 10) leave transactions in the following state
2677: // t0 - incomplete
2678: // t1 - abort
2679: // t2 - commit
2680: // t3 - incomplete
2681: // t4 - commit
2682: // any other transactions - incomplete
2683:
2684: //////////////////////// step 1 ////////////////////////
2685: RecordHandle[][] rh = new RecordHandle[numtrans][numpages];
2686: T_RawStoreRow row1 = new T_RawStoreRow(REC_001);
2687: for (i = 0; i < numtrans; i++)
2688: for (j = 0; j < numpages; j++) {
2689: t[i].switchTransactionContext();
2690: rh[i][j] = t_util.t_insert(page[i][j], row1);
2691: t[i].resetContext();
2692: }
2693:
2694: t[0].switchTransactionContext();
2695: t[0].setSavePoint(SP1, null); // sp1
2696: t[0].resetContext();
2697:
2698: //////////////////////// step 2 ////////////////////////
2699: T_RawStoreRow row2 = new T_RawStoreRow(REC_002);
2700: for (i = 0; i < numtrans; i++)
2701: for (j = 0; j < numpages; j++) {
2702: t[i].switchTransactionContext();
2703: page[i][j].update(rh[i][j], row2.getRow(),
2704: (FormatableBitSet) null);
2705: t[i].resetContext();
2706: }
2707:
2708: for (i = 1; i < numtrans; i++) // sp1
2709: {
2710: t[i].switchTransactionContext();
2711: t[i].setSavePoint(SP1, null);
2712: t[i].resetContext();
2713: }
2714:
2715: //////////////////////// step 3 ////////////////////////
2716: T_RawStoreRow row3 = new T_RawStoreRow(REC_003);
2717: for (i = 0; i < numtrans; i++)
2718: for (j = 0; j < numpages; j++)
2719: page[i][j].update(rh[i][j], row3.getRow(),
2720: (FormatableBitSet) null);
2721:
2722: for (i = 0; i < numtrans; i++)
2723: t[i].setSavePoint(SP2, null); // sp2
2724:
2725: //////////////////////// step 4 ////////////////////////
2726: T_RawStoreRow row4 = new T_RawStoreRow(REC_004);
2727: for (i = 0; i < numtrans; i++) {
2728: t[i].switchTransactionContext();
2729:
2730: for (j = 0; j < numpages; j++)
2731: page[i][j].update(rh[i][j], row4.getRow(),
2732: (FormatableBitSet) null);
2733: t[i].resetContext();
2734: }
2735:
2736: //////////////////////// step 5 ////////////////////////
2737: // unlatch relavante pages
2738: t[0].switchTransactionContext();
2739:
2740: for (j = 0; j < numpages; j++)
2741: page[0][j].unlatch();
2742:
2743: t[0].rollbackToSavePoint(SP1, null); // step 5
2744:
2745: // relatch relavante pages
2746: for (j = 0; j < numpages; j++)
2747: page[0][j] = t_util.t_getPage(c[0], pagenum[0][j]);
2748:
2749: t[0].resetContext();
2750:
2751: //////////////////////// check ////////////////////////
2752: for (i = 1; i < numtrans; i++) {
2753: t[i].switchTransactionContext();
2754: for (j = 0; j < numpages; j++)
2755: t_util.t_checkFetch(page[i][j], rh[i][j], REC_004);
2756: t[i].resetContext();
2757: }
2758:
2759: t[0].switchTransactionContext();
2760: for (j = 0; j < numpages; j++)
2761: t_util.t_checkFetch(page[0][j], rh[0][j], REC_001);
2762:
2763: t[0].resetContext();
2764: //////////////////////// step 6 ////////////////////////
2765: T_RawStoreRow row5 = new T_RawStoreRow(REC_005);
2766: for (i = 0; i < numtrans; i++) {
2767: t[i].switchTransactionContext();
2768: for (j = 0; j < numpages; j++)
2769: page[i][j].update(rh[i][j], row5.getRow(),
2770: (FormatableBitSet) null);
2771: t[i].resetContext();
2772: }
2773:
2774: //////////////////////// step 7 ////////////////////////
2775: for (i = 1; i < numtrans; i++) {
2776: t[i].switchTransactionContext();
2777:
2778: for (j = 0; j < numpages; j++)
2779: page[i][j].unlatch();
2780:
2781: t[i].rollbackToSavePoint(SP2, null);
2782:
2783: for (j = 0; j < numpages; j++)
2784: page[i][j] = t_util.t_getPage(c[i], pagenum[i][j]);
2785: t[i].resetContext();
2786: }
2787:
2788: //////////////////////// check ////////////////////////
2789: for (i = 1; i < numtrans; i++) {
2790: t[i].switchTransactionContext();
2791: for (j = 0; j < numpages; j++)
2792: t_util.t_checkFetch(page[i][j], rh[i][j], REC_003);
2793: t[i].resetContext();
2794: }
2795:
2796: t[0].switchTransactionContext();
2797: for (j = 0; j < numpages; j++)
2798: t_util.t_checkFetch(page[0][j], rh[0][j], REC_005);
2799: t[0].resetContext();
2800:
2801: //////////////////////// step 8 ////////////////////////
2802: T_RawStoreRow row6 = new T_RawStoreRow(REC_006);
2803: for (i = 0; i < numtrans; i++) {
2804: t[i].switchTransactionContext();
2805: for (j = 0; j < numpages; j++)
2806: page[i][j].update(rh[i][j], row6.getRow(),
2807: (FormatableBitSet) null); // step 8
2808: t[i].resetContext();
2809: }
2810:
2811: //////////////////////// step 9 ////////////////////////
2812: // unlatch relavante pages
2813: t[0].switchTransactionContext();
2814: for (j = 0; j < numpages; j++)
2815: page[0][j].unlatch();
2816:
2817: t[0].rollbackToSavePoint(SP1, null);
2818:
2819: // relatch relavante pages
2820: for (j = 0; j < numpages; j++)
2821: page[0][j] = t_util.t_getPage(c[0], pagenum[0][j]);
2822:
2823: t[0].resetContext();
2824: //////////////////////// check ////////////////////////
2825: for (i = 1; i < numtrans; i++) {
2826: t[i].switchTransactionContext();
2827:
2828: for (j = 0; j < numpages; j++) {
2829: t_util.t_checkFetch(page[i][j], rh[i][j], REC_006);
2830: t_util.t_checkRecordCount(page[i][j], 1, 1);
2831: }
2832: t[i].resetContext();
2833: }
2834:
2835: t[0].switchTransactionContext();
2836: for (j = 0; j < numpages; j++) {
2837: t_util.t_checkFetch(page[0][j], rh[0][j], REC_001);
2838: t_util.t_checkRecordCount(page[0][j], 1, 1);
2839: }
2840: t[0].resetContext();
2841:
2842: //////////////////////// step 10 ////////////////////////
2843: // unlatch all pages
2844: for (i = 0; i < numtrans; i++) {
2845: t[i].switchTransactionContext();
2846: for (j = 0; j < numpages; j++)
2847: page[i][j].unlatch();
2848: t[i].resetContext();
2849: }
2850:
2851: // t[0] incomplete
2852: t_util.t_abort(t[1]);
2853: t_util.t_commit(t[2]);
2854: // t[3] incomplete
2855: t_util.t_commit(t[4]);
2856:
2857: // reopen containers 1, 2, and 4, where were closed when the
2858: // transaction terminated.
2859: c[1] = t_util.t_openContainer(t[1], 0, cid[1], false);
2860: c[2] = t_util.t_openContainer(t[2], 0, cid[2], false);
2861: c[4] = t_util.t_openContainer(t[4], 0, cid[4], false);
2862:
2863: //////////////////////// check ////////////////////////
2864: for (j = 0; j < numpages; j++) {
2865: t[0].switchTransactionContext();
2866: t_util.t_checkFetch(c[0], rh[0][j], REC_001);
2867: t[0].resetContext();
2868:
2869: // t[1] has been aborted
2870: // rh[1][j] (REC_001) is deleted
2871: t[1].switchTransactionContext();
2872: page[1][j] = t_util.t_getPage(c[1], pagenum[1][j]);
2873: t_util.t_checkRecordCount(page[1][j], 1, 0);
2874: t_util.t_checkFetchBySlot(page[1][j],
2875: Page.FIRST_SLOT_NUMBER, REC_001, true, false);
2876: page[1][j].unlatch();
2877: t[1].resetContext();
2878:
2879: t[2].switchTransactionContext();
2880: t_util.t_checkFetch(c[2], rh[2][j], REC_006);
2881: t[2].resetContext();
2882:
2883: t[3].switchTransactionContext();
2884: t_util.t_checkFetch(c[3], rh[3][j], REC_006);
2885: t[3].resetContext();
2886:
2887: t[4].switchTransactionContext();
2888: t_util.t_checkFetch(c[4], rh[4][j], REC_006);
2889: t[4].resetContext();
2890: }
2891:
2892: REPORT("setup S203: numtrans " + numtrans + " numpages "
2893: + numpages);
2894:
2895: for (i = 0; i < numtrans; i++) {
2896: String str = "container " + i + ":" + cid[i]
2897: + " pages: ";
2898: register(key(203, i + 10), cid[i]);
2899:
2900: for (j = 0; j < numpages; j++) {
2901: str += pagenum[i][j] + " ";
2902: register(key(203, (i + 1) * 1000 + j),
2903: pagenum[i][j]);
2904: }
2905: REPORT("\t" + str);
2906: }
2907:
2908: register(key(203, 1), numtrans);
2909: register(key(203, 2), numpages);
2910:
2911: } finally {
2912: for (i = 0; i < numtrans; i++) {
2913: for (j = 0; j < numpages; j++) {
2914: if (page != null && page[i][j] != null
2915: && page[i][j].isLatched())
2916: page[i][j].unlatch();
2917: }
2918: }
2919: }
2920:
2921: // let recovery rollback incomplete transactions t0 and t3
2922:
2923: }
2924:
2925: /* recover test 203 */
2926: protected void R203() throws T_Fail, StandardException {
2927: int numtrans = (int) find(key(203, 1));
2928: int numpages = (int) find(key(203, 2));
2929: int i, j;
2930: if (numtrans < 5 || numpages < 1) {
2931: REPORT("R203 not run");
2932: return;
2933: } else {
2934: REPORT("R203 started, numtrans " + numtrans + " numpages "
2935: + numpages);
2936: }
2937:
2938: Transaction t = t_util.t_startTransaction();
2939:
2940: try {
2941:
2942: long[] cid = new long[numtrans];
2943: ContainerHandle[] c = new ContainerHandle[numtrans];
2944:
2945: long[][] pagenum = new long[numtrans][numpages];
2946: Page[][] page = new Page[numtrans][numpages];
2947:
2948: for (i = 0; i < numtrans; i++) {
2949:
2950: cid[i] = find(key(203, i + 10));
2951: c[i] = t_util.t_openContainer(t, 0, cid[i], true);
2952:
2953: for (j = 0; j < numpages; j++) {
2954: pagenum[i][j] = find(key(203, (i + 1) * 1000 + j));
2955:
2956: if (SanityManager.DEBUG) {
2957: if (i == 0 && j == (numpages - 1)) {
2958: SanityManager
2959: .DEBUG_SET("TEST_BAD_CHECKSUM");
2960: Page p = null;
2961: try {
2962: p = c[i].getPage(pagenum[i][j]);
2963: } catch (StandardException se) {
2964:
2965: if (se.getMessageId().equals(
2966: SQLState.FILE_IO_GARBLED))
2967: REPORT("bad checksum tested");
2968: else
2969: throw se; // not expected
2970: }
2971: SanityManager
2972: .DEBUG_CLEAR("TEST_BAD_CHECKSUM");
2973: if (p != null)
2974: throw T_Fail
2975: .testFailMsg("failed to generate expected error with bad checksum");
2976: }
2977: }
2978:
2979: page[i][j] = t_util.t_getPage(c[i], pagenum[i][j]);
2980: }
2981: }
2982:
2983: // transactions were left in the following state
2984: // t0 - incomplete (rolled back)
2985: // t1 - abort
2986: // t2 - commit
2987: // t3 - incomplete (rolled back)
2988: // t4 - commit
2989: // any other transactions - incomplete
2990: //
2991: // all the rolled back transaction should have a deleted REC_001
2992: // all the committed transactions should have a REC_006
2993: //
2994: for (j = 0; j < numpages; j++) {
2995: t_util.t_checkRecordCount(page[0][j], 1, 0);
2996: t_util.t_checkFetchBySlot(page[0][j],
2997: Page.FIRST_SLOT_NUMBER, REC_001, true, true);
2998:
2999: t_util.t_checkRecordCount(page[1][j], 1, 0);
3000: t_util.t_checkFetchBySlot(page[1][j],
3001: Page.FIRST_SLOT_NUMBER, REC_001, true, true);
3002:
3003: t_util.t_checkRecordCount(page[2][j], 1, 1);
3004: t_util.t_checkFetchBySlot(page[2][j],
3005: Page.FIRST_SLOT_NUMBER, REC_006, false, true);
3006:
3007: t_util.t_checkRecordCount(page[3][j], 1, 0);
3008: t_util.t_checkFetchBySlot(page[3][j],
3009: Page.FIRST_SLOT_NUMBER, REC_001, true, true);
3010:
3011: t_util.t_checkRecordCount(page[4][j], 1, 1);
3012: t_util.t_checkFetchBySlot(page[4][j],
3013: Page.FIRST_SLOT_NUMBER, REC_006, false, true);
3014: }
3015:
3016: for (i = 0; i < numtrans; i++) {
3017: String str = "container " + i + ":" + cid[i]
3018: + " pages: ";
3019: for (j = 0; j < numpages; j++)
3020: str += pagenum[i][j] + " ";
3021: REPORT("\t" + str);
3022: }
3023: } finally {
3024: t_util.t_commit(t);
3025: t.close();
3026: }
3027: PASS("R203: numtrans " + numtrans + " numpages " + numpages);
3028: }
3029:
3030: /*
3031: * test 204 - incomplete and committed and aborted internal transactions
3032: */
3033: protected void S204() throws T_Fail, StandardException {
3034: // start 2 user transaction, then 2 internal transaction, then
3035: // another user transaction.
3036: // do some work on all 5 transactions
3037: // roll back one of the internal transaction
3038: // commit the other one
3039: // do some more work on the 2 internal transactions and let
3040: // recovery roll them all back
3041: T_TWC ut1 = t_util.t_startTransactionWithContext();
3042: T_TWC ut2 = t_util.t_startTransactionWithContext();
3043: Page p10, p11, p20, p21, p30;
3044: p10 = p11 = p20 = p21 = p30 = null;
3045:
3046: try {
3047:
3048: long cid10 = t_util.t_addContainer(ut1, 0);
3049: long cid11 = t_util.t_addContainer(ut1, 0);
3050: t_util.t_commit(ut1);
3051:
3052: long cid20 = t_util.t_addContainer(ut2, 0);
3053: long cid21 = t_util.t_addContainer(ut2, 0);
3054: t_util.t_commit(ut2);
3055:
3056: T_RawStoreRow row = new T_RawStoreRow(REC_001);
3057:
3058: // all three user transactions have committed.
3059: //
3060: // container used by row row
3061: // cid10 ut1 r10
3062: // cid11 it1 r11 commit r12
3063: // cid20 ut2 r20
3064: // cid21 it2 r21 abort r22
3065: // cid30 ut3 r30
3066: // (ut3 is started after everything is done)
3067: // after recovery, r11 is the only record
3068:
3069: ut1.switchTransactionContext();
3070:
3071: ContainerHandle c10 = t_util.t_openContainer(ut1, 0, cid10,
3072: true);
3073: p10 = t_util.t_addPage(c10);
3074: RecordHandle r10 = t_util.t_insert(p10, row);
3075:
3076: Transaction it1 = t_util.t_startInternalTransaction();
3077: ContainerHandle c11 = t_util.t_openContainer(it1, 0, cid11,
3078: true);
3079: p11 = t_util.t_addPage(c11);
3080: RecordHandle r11 = t_util.t_insert(p11, row);
3081: ut1.resetContext();
3082:
3083: ut2.switchTransactionContext();
3084: ContainerHandle c20 = t_util.t_openContainer(ut2, 0, cid20,
3085: true);
3086: p20 = t_util.t_addPage(c20);
3087: RecordHandle r20 = t_util.t_insert(p20, row);
3088:
3089: Transaction it2 = t_util.t_startInternalTransaction();
3090: ContainerHandle c21 = t_util.t_openContainer(it2, 0, cid21,
3091: true);
3092: p21 = t_util.t_addPage(c21);
3093: RecordHandle r21 = t_util.t_insert(p21, row);
3094: ut2.resetContext();
3095:
3096: // r10, r1, r20, r21, r30 inserted by the corresponding transactions
3097:
3098: // commit it1 - it uses the same context manager as ut1
3099: ut1.switchTransactionContext();
3100: it1.commit();
3101:
3102: // container is left opened and page p11 is left latched
3103: t_util.t_checkFetch(p11, r11, REC_001);
3104:
3105: // use it1 to add another row
3106: T_RawStoreRow row2 = new T_RawStoreRow(REC_002);
3107: RecordHandle r12 = t_util.t_insert(p11, row2);
3108: t_util.t_checkFetch(p11, r12, REC_002);
3109: ut1.resetContext();
3110:
3111: // abort it2 - it uses the same context maanger as ut2
3112: ut2.switchTransactionContext();
3113: it2.abort();
3114:
3115: // need to reopen container
3116: c21 = t_util.t_openContainer(it2, 0, cid21, true);
3117: p21 = t_util.t_getLastPage(c21);
3118: RecordHandle r22 = t_util.t_insert(p21, row2);
3119: ut2.resetContext();
3120:
3121: // start ut3 at the end to test
3122: // internal transactions are rolled back first
3123:
3124: T_TWC ut3 = t_util.t_startTransactionWithContext();
3125: long cid30 = t_util.t_addContainer(ut3, 0);
3126: t_util.t_commit(ut3);
3127:
3128: ContainerHandle c30 = t_util.t_openContainer(ut3, 0, cid30,
3129: true);
3130:
3131: ut3.switchTransactionContext();
3132: p30 = t_util.t_addPage(c30);
3133: RecordHandle r30 = t_util.t_insert(p30, row);
3134: ut3.resetContext();
3135:
3136: register(key(204, 10), cid10);
3137: register(key(204, 11), cid11);
3138: register(key(204, 20), cid20);
3139: register(key(204, 21), cid21);
3140: register(key(204, 30), cid30);
3141:
3142: REPORT("setup S204: cid10 " + cid10 + ", cid11 " + cid11
3143: + ", cid20 " + cid20 + ", cid21 " + cid21
3144: + ", cid30 " + cid30);
3145:
3146: } finally {
3147: if (p10 != null && p10.isLatched())
3148: p10.unlatch();
3149:
3150: if (p11 != null && p11.isLatched())
3151: p11.unlatch();
3152:
3153: if (p20 != null && p20.isLatched())
3154: p20.unlatch();
3155:
3156: if (p21 != null && p21.isLatched())
3157: p21.unlatch();
3158:
3159: if (p30 != null && p30.isLatched())
3160: p30.unlatch();
3161: }
3162: // let recovery rollback incomplete transactions
3163:
3164: }
3165:
3166: /*
3167: * test recovery of 204
3168: */
3169: protected void R204() throws T_Fail, StandardException {
3170: long cid10 = find(key(204, 10));
3171: if (cid10 < 0) {
3172: REPORT("R204 not run");
3173: return;
3174: }
3175:
3176: long cid11 = find(key(204, 11));
3177: long cid20 = find(key(204, 20));
3178: long cid21 = find(key(204, 21));
3179: long cid30 = find(key(204, 30));
3180:
3181: Transaction t = t_util.t_startTransaction();
3182: try {
3183: ContainerHandle c;
3184: Page p;
3185:
3186: c = t_util.t_openContainer(t, 0, cid10, false);
3187: p = t_util.t_getLastPage(c);
3188: t_util.t_checkRecordCount(p, 1, 0);
3189: p.unlatch();
3190:
3191: c = t_util.t_openContainer(t, 0, cid11, false);
3192: p = t_util.t_getLastPage(c);
3193: t_util.t_checkRecordCount(p, 2, 1); // r11 is the only record that is not rolled back
3194: p.unlatch();
3195:
3196: c = t_util.t_openContainer(t, 0, cid20, false);
3197: p = t_util.t_getLastPage(c);
3198: t_util.t_checkRecordCount(p, 1, 0);
3199: p.unlatch();
3200:
3201: c = t_util.t_openContainer(t, 0, cid21, false);
3202: p = t_util.t_getLastPage(c);
3203: t_util.t_checkRecordCount(p, 2, 0);
3204: p.unlatch();
3205:
3206: c = t_util.t_openContainer(t, 0, cid30, false);
3207: p = t_util.t_getLastPage(c);
3208: t_util.t_checkRecordCount(p, 1, 0);
3209: p.unlatch();
3210: } finally {
3211: t_util.t_commit(t);
3212: t.close();
3213: }
3214:
3215: PASS("R204 passed: cid10 " + cid10 + ", cid11 " + cid11
3216: + ", cid20 " + cid20 + ", cid21 " + cid21 + ", cid30 "
3217: + cid30);
3218: }
3219:
3220: /*
3221: * test 300 - incomplete transaction with drop containers
3222: */
3223: protected void S300() throws T_Fail, StandardException {
3224: T_TWC ctx = t_util.t_startTransactionWithContext();
3225: Transaction t = ctx.tran;
3226:
3227: try {
3228: long cid = t_util.t_addContainer(t, 0);
3229: t_util.t_commit(t);
3230:
3231: t_util.t_openContainer(t, 0, cid, true);
3232: t_util.t_dropContainer(t, 0, cid);
3233:
3234: REPORT("setup S300: containerId " + cid);
3235:
3236: register(key(300, 1), cid);
3237: } catch (StandardException se) {
3238: t_util.t_abort(t);
3239: t.close();
3240: throw se;
3241: } catch (T_Fail tf) {
3242: t_util.t_abort(t);
3243: t.close();
3244: throw tf;
3245: }
3246:
3247: // let recovery rollback incomplete transaction
3248: }
3249:
3250: /*
3251: * test recovery of 300
3252: */
3253: protected void R300() throws T_Fail, StandardException {
3254: long cid = find(key(300, 1));
3255: if (cid < 0) {
3256: REPORT("R300 not run");
3257: return;
3258: }
3259:
3260: Transaction t = t_util.t_startTransaction();
3261: // recovery should have rolled back the dropped container
3262: t_util.t_openContainer(t, 0, cid, true);
3263:
3264: t_util.t_commit(t);
3265: t.close();
3266:
3267: PASS("R300 : containerId " + cid);
3268:
3269: }
3270:
3271: /*
3272: * incomplete transactions with create container
3273: */
3274: protected void S301() throws T_Fail, StandardException {
3275: T_TWC ctx = t_util.t_startTransactionWithContext();
3276: Transaction t = ctx.tran;
3277: Page page = null;
3278: ctx.switchTransactionContext();
3279:
3280: try {
3281:
3282: long cid1 = t_util.t_addContainer(t, 0);
3283: ContainerHandle c1 = t_util.t_openContainer(t, 0, cid1,
3284: true);
3285: page = t_util.t_addPage(c1);
3286: T_RawStoreRow row1 = new T_RawStoreRow(REC_001);
3287: RecordHandle r1 = t_util.t_insert(page, row1);
3288:
3289: t.abort();
3290:
3291: ContainerKey id1 = new ContainerKey(0, cid1);
3292: c1 = t.openContainer(id1, ContainerHandle.MODE_READONLY);
3293: if (c1 != null)
3294: throw T_Fail
3295: .testFailMsg("expect container to be dropped");
3296:
3297: LockingPolicy nolock = t.newLockingPolicy(
3298: LockingPolicy.MODE_NONE, 0, false);
3299:
3300: RawContainerHandle stub = ((RawTransaction) t)
3301: .openDroppedContainer(new ContainerKey(0, cid1),
3302: nolock);
3303:
3304: /*Not true always after fix for p4#25641(fix for bug:4580)
3305: Checkpoint calls cleans up the stubs that not necessary
3306: for recovery.
3307: if (stub == null)
3308: throw T_Fail.testFailMsg("drop container should still be there");
3309: */
3310: if (stub != null)
3311: if (stub.getContainerStatus() != RawContainerHandle.COMMITTED_DROP)
3312: throw T_Fail
3313: .testFailMsg("expect container to be committed dropped");
3314:
3315: long cid2 = t_util.t_addContainer(t, 0);
3316: ContainerHandle c2 = t_util.t_openContainer(t, 0, cid2,
3317: true);
3318: page = t_util.t_addPage(c2);
3319: T_RawStoreRow row2 = new T_RawStoreRow(REC_002);
3320: RecordHandle r2 = t_util.t_insert(page, row2);
3321:
3322: REPORT("setup S301: cid1 " + cid1 + " cid2 " + cid2);
3323: register(key(301, 1), cid1);
3324: register(key(301, 2), cid2);
3325:
3326: } finally {
3327: if (page != null && page.isLatched())
3328: page.unlatch();
3329: ctx.resetContext();
3330: }
3331: // let recovery rollback incomplete transaction
3332: }
3333:
3334: /*
3335: * test recovery of 301
3336: */
3337: protected void R301() throws T_Fail, StandardException {
3338: long cid1 = find(key(301, 1));
3339: if (cid1 < 0) {
3340: REPORT("R301 not run");
3341: return;
3342: }
3343:
3344: long cid2 = find(key(301, 2));
3345:
3346: Transaction t = t_util.t_startTransaction();
3347: try {
3348: LockingPolicy nolock = t.newLockingPolicy(
3349: LockingPolicy.MODE_NONE, 0, false);
3350:
3351: ContainerKey id1 = new ContainerKey(0, cid1);
3352: ContainerHandle c = t.openContainer(id1,
3353: ContainerHandle.MODE_READONLY);
3354: if (c != null)
3355: throw T_Fail
3356: .testFailMsg("expect container to be dropped");
3357:
3358: RawContainerHandle stub = ((RawTransaction) t)
3359: .openDroppedContainer(id1, nolock);
3360: /*Not true always after fix for p4#25641(fix for bug:4580)
3361: Checkpoint calls cleans up the stubs that not necessary
3362: for recovery.
3363: if (stub == null)
3364: throw T_Fail.testFailMsg("drop container should still be there");
3365: */
3366: if (stub != null)
3367: if (stub.getContainerStatus() != RawContainerHandle.COMMITTED_DROP)
3368: throw T_Fail
3369: .testFailMsg("expect container to be committed dropped");
3370:
3371: ContainerKey id2 = new ContainerKey(0, cid2);
3372: c = t.openContainer(id2, ContainerHandle.MODE_READONLY);
3373: if (c != null)
3374: throw T_Fail
3375: .testFailMsg("expect container to be dropped");
3376:
3377: stub = ((RawTransaction) t).openDroppedContainer(id2,
3378: nolock);
3379: /*Not true always after fix for p4#25641(fix for bug:4580)
3380: Checkpoint calls cleans up the stubs that not necessary
3381: for recovery.
3382: if (stub == null)
3383: throw T_Fail.testFailMsg("drop container should still be there");
3384: */
3385: if (stub != null)
3386: if (stub.getContainerStatus() != RawContainerHandle.COMMITTED_DROP)
3387: throw T_Fail
3388: .testFailMsg("expect container to be committed dropped");
3389:
3390: } finally {
3391: t_util.t_commit(t);
3392: t.close();
3393: }
3394:
3395: PASS("R301 : cid1 " + cid1 + " cid2 " + cid2);
3396:
3397: }
3398:
3399: /*
3400: * test 302 - purge and delete with no data logging for purges
3401: */
3402: protected void S302() throws T_Fail, StandardException {
3403: Transaction t = t_util.t_startTransaction();
3404:
3405: try {
3406:
3407: long cid = t_util.t_addContainer(t, 0);
3408: t_util.t_commit(t);
3409:
3410: ContainerHandle c = t_util.t_openContainer(t, 0, cid, true);
3411: Page page = t_util.t_getPage(c,
3412: ContainerHandle.FIRST_PAGE_NUMBER);
3413:
3414: T_RawStoreRow row1 = new T_RawStoreRow(REC_001);
3415: T_RawStoreRow row2 = new T_RawStoreRow(REC_002);
3416: T_RawStoreRow row3 = new T_RawStoreRow(REC_003);
3417: T_RawStoreRow row4 = new T_RawStoreRow(REC_004);
3418: T_RawStoreRow row5 = new T_RawStoreRow(REC_005);
3419:
3420: long numPurged = 0;
3421:
3422: // slot 0
3423: RecordHandle r1 = t_util.t_insertAtSlot(page, 0, row1);
3424: // slot 1
3425: RecordHandle r2 = t_util.t_insertAtSlot(page, 1, row2);
3426: // slot 2
3427: RecordHandle r3 = (r2 == null) ? r2 : t_util
3428: .t_insertAtSlot(page, 2, row3);
3429: // slot 3
3430: RecordHandle r4 = (r3 == null) ? r3 : t_util
3431: .t_insertAtSlot(page, 3, row4);
3432: // slot 4
3433: RecordHandle r5 = (r4 == null) ? r4 : t_util
3434: .t_insertAtSlot(page, 4, row5);
3435: if (r5 != null) {
3436: page.delete(r5, (LogicalUndo) null);
3437: }
3438:
3439: t_util.t_commit(t);
3440:
3441: c = t_util.t_openContainer(t, 0, cid, true);
3442: page = t_util.t_getPage(c,
3443: ContainerHandle.FIRST_PAGE_NUMBER);
3444: //do some purging now
3445: // purge slot 0
3446: page.purgeAtSlot(0, 1, false);
3447: // purge slot 1 and 2 3
3448: page.purgeAtSlot(0, 3, false);
3449: t_util.t_abort(t);
3450: c = t_util.t_openContainer(t, 0, cid, true);
3451: page = t_util.t_getPage(c,
3452: ContainerHandle.FIRST_PAGE_NUMBER);
3453: //repurge the rows that got rolled back.
3454: page.purgeAtSlot(0, 1, false);
3455: numPurged++;
3456: if (r5 != null) {
3457: // purge slot 1 and 2
3458: page.purgeAtSlot(0, 2, false);
3459: numPurged += 2;
3460: }
3461:
3462: REPORT("setup S302: containerId " + cid + " recordCount "
3463: + page.recordCount() + " numPurges " + numPurged);
3464:
3465: register(key(302, 1), cid);
3466: register(key(302, 2), page.recordCount());
3467: register(key(302, 3), numPurged);
3468:
3469: page.unlatch();
3470: } finally {
3471: t_util.t_commit(t);
3472: t.close();
3473: }
3474: }
3475:
3476: /* recover test 302 */
3477: protected void R302() throws T_Fail, StandardException {
3478: long cid = find(key(302, 1));
3479: if (cid < 0) {
3480: REPORT("R302 not run");
3481: return;
3482: }
3483: int recordCount = (int) find(key(302, 2));
3484: int numPurged = (int) find(key(302, 3));
3485:
3486: Transaction t = t_util.t_startTransaction();
3487: try {
3488: ContainerHandle c = t_util
3489: .t_openContainer(t, 0, cid, false);
3490: Page page = t_util.t_getPage(c,
3491: ContainerHandle.FIRST_PAGE_NUMBER);
3492:
3493: t_util.t_checkRecordCount(page, recordCount, 1);
3494:
3495: T_RawStoreRow row1 = new T_RawStoreRow(REC_001);
3496: T_RawStoreRow row2 = new T_RawStoreRow(REC_002);
3497: T_RawStoreRow row3 = new T_RawStoreRow(REC_003);
3498: T_RawStoreRow row4 = new T_RawStoreRow(REC_004);
3499: T_RawStoreRow row5 = new T_RawStoreRow(REC_005);
3500:
3501: t_util.t_checkFetchBySlot(page, 1, REC_005, true, false);
3502: if (!page.isDeletedAtSlot(1))
3503: throw T_Fail.testFailMsg("record should be deleted");
3504: //REC_004 should have become a null value because of rollback of purge
3505: t_util.t_checkFetchBySlot(page, 0, "NULL", false, false);
3506: page.unlatch();
3507: } finally {
3508: t_util.t_commit(t);
3509: t.close();
3510: }
3511:
3512: PASS("R302: containerId " + cid + " recordCount " + recordCount
3513: + " numPurges " + numPurged);
3514: }
3515:
3516: /**
3517: Test space reclaimation - purging of a row with serveral long columns
3518: rollback and repurge them again.
3519:
3520: @exception T_Fail Unexpected behaviour from the API
3521: @exception StandardException Unexpected exception from the implementation
3522: */
3523: protected void S303() throws StandardException, T_Fail {
3524: REPORT("START S303");
3525: long segment = 0;
3526: T_TWC ctx = t_util.t_startTransactionWithContext();
3527: Transaction t = ctx.tran;
3528: ctx.switchTransactionContext();
3529:
3530: long cid = t_util.t_addContainer(t, segment, 4096);
3531: ContainerHandle c = t_util.t_openContainer(t, segment, cid,
3532: true);
3533: Page page = t_util.t_getPage(c,
3534: ContainerHandle.FIRST_PAGE_NUMBER);
3535: try {
3536: t_util.t_checkEmptyPage(page);
3537:
3538: int insertFlag = Page.INSERT_INITIAL | Page.INSERT_OVERFLOW;
3539: T_RawStoreRow r1 = new T_RawStoreRow(1);
3540: // insert a long column
3541: r1.setColumn(0, 5000, REC_001);
3542: RecordHandle rh1 = t_util.t_insertAtSlot(page, 0, r1,
3543: (byte) insertFlag);
3544: t_util.t_checkFetch(page, rh1, r1);
3545:
3546: // insert a 6 column row, every other column is long
3547: T_RawStoreRow r2 = new T_RawStoreRow(6);
3548: r2.setColumn(0, 1600, REC_001); // this takes 3200 bytes
3549: r2.setColumn(1, 4000, REC_002); // this takes 8000 bytes
3550: r2.setColumn(2, 1600, REC_001);
3551: r2.setColumn(3, 4000, REC_002);
3552: r2.setColumn(4, 1600, REC_001);
3553: r2.setColumn(5, 4000, REC_002);
3554: RecordHandle rh2 = t_util.t_insertAtSlot(page, 0, r2,
3555: (byte) insertFlag);
3556:
3557: t_util.t_checkFetch(page, rh2, r2);
3558:
3559: // insert a long column - this should fail
3560: RecordHandle rh3 = t_util.t_insertAtSlot(page, 0, r1,
3561: (byte) insertFlag);
3562: if (rh3 != null) {
3563: throw T_Fail
3564: .testFailMsg("expect the 3rd row to not fit on page");
3565: }
3566: page.unlatch();
3567: page = null;
3568:
3569: Page nextPage = t_util.t_addPage(c);
3570: long nextPageNumber = nextPage.getPageNumber();
3571: // deallocate it
3572: t_util.t_removePage(c, nextPage);
3573:
3574: REPORT("S303 - Nextpage is " + nextPageNumber);
3575:
3576: t_util.t_commit(t);
3577:
3578: // now purge them
3579: c = t_util.t_openContainer(t, segment, cid, true);
3580: page = t_util.t_getPage(c,
3581: ContainerHandle.FIRST_PAGE_NUMBER);
3582:
3583: t_util.t_checkRecordCount(page, 2, 2);
3584: page.purgeAtSlot(0, 2, false);
3585: t_util.t_checkEmptyPage(page);
3586: page.unlatch();
3587: page = null;
3588:
3589: t_util.t_abort(t);
3590:
3591: // give some time for post commit to finish
3592: t_util.t_wait(10); // wait 10 milliseconds.
3593:
3594: // Purge them again and roll them back via recovery. These should not
3595: // be reclaimed.
3596: c = t_util.t_openContainer(t, segment, cid, true);
3597: page = t_util.t_getPage(c,
3598: ContainerHandle.FIRST_PAGE_NUMBER);
3599: t_util.t_checkRecordCount(page, 2, 2);
3600: int rh1slotnumber = page.getSlotNumber(rh1);
3601: int rh2slotnumber = page.getSlotNumber(rh2);
3602: page.purgeAtSlot(0, 2, false);
3603: t_util.t_checkEmptyPage(page);
3604:
3605: page.unlatch();
3606: page = null;
3607:
3608: REPORT("S303 - Purged Slots" + rh1slotnumber + ","
3609: + rh2slotnumber);
3610:
3611: register(key(303, 1), cid);
3612: register(key(303, 2), rh1slotnumber);
3613: register(key(303, 3), rh2slotnumber);
3614:
3615: // let recovery undo rollback this transaction
3616: } finally {
3617: if (page != null)
3618: page.unlatch();
3619: ctx.resetContext();
3620: }
3621:
3622: PASS("S303");
3623: }
3624:
3625: /* recover test 303:
3626: * repurge the same rows whose purging we rolled back in s303.
3627: */
3628: protected void R303() throws T_Fail, StandardException {
3629: long cid = find(key(303, 1));
3630: if (cid < 0) {
3631: REPORT("R303 not run");
3632: return;
3633: }
3634:
3635: Transaction t = t_util.t_startTransaction();
3636: try {
3637: ContainerHandle c = t_util.t_openContainer(t, 0, cid, true);
3638: Page page = t_util.t_getPage(c,
3639: ContainerHandle.FIRST_PAGE_NUMBER);
3640: t_util.t_checkRecordCount(page, 2, 2);
3641: int r1slot = (int) find(key(303, 2));
3642: int r2slot = (int) find(key(303, 3));
3643: T_RawStoreRow r1 = new T_RawStoreRow(1);
3644: // insert a long column
3645: r1.setColumn(0, 5000, REC_001);
3646: // During purges when data is not logged when slots are purged
3647: // they become null on rollback and some cases like long columns
3648: // we remove the wholepage on rollback we get the data back.
3649: T_RawStoreRow r2_wnl = new T_RawStoreRow(6);
3650: r2_wnl.setColumn(0, 4, REC_NULL);
3651: r2_wnl.setColumn(1, 4000, REC_002);
3652: r2_wnl.setColumn(2, 1600, REC_001);
3653: r2_wnl.setColumn(3, 4000, REC_002);
3654: r2_wnl.setColumn(4, 1600, REC_001);
3655: r2_wnl.setColumn(5, 4000, REC_002);
3656: RecordHandle rh1 = page.getRecordHandleAtSlot(r1slot);
3657:
3658: t_util.t_checkFetch(page, rh1, r1);
3659: RecordHandle rh2 = page.getRecordHandleAtSlot(r2slot);
3660: t_util.t_checkFetch(page, rh2, r2_wnl);
3661:
3662: //purge after the recovery.
3663: page.purgeAtSlot(0, 2, false);
3664:
3665: page.unlatch();
3666: page = null;
3667: } finally {
3668: t_util.t_commit(t);
3669: t.close();
3670: }
3671:
3672: PASS("R303");
3673: }
3674:
3675: /**
3676: Test space reclaimation - purging of a long rows with a rollback and
3677: purging again after recovery in R304
3678: @exception T_Fail Unexpected behaviour from the API
3679: @exception StandardException Unexpected exception from the implementation
3680: */
3681: protected void S304() throws StandardException, T_Fail {
3682: long segment = 0;
3683: T_TWC ctx = t_util.t_startTransactionWithContext();
3684: Transaction t = ctx.tran;
3685: ctx.switchTransactionContext();
3686:
3687: long cid = t_util.t_addContainer(t, segment, 4096);
3688: ContainerHandle c = t_util.t_openContainer(t, segment, cid,
3689: true);
3690: Page page = t_util.t_getPage(c,
3691: ContainerHandle.FIRST_PAGE_NUMBER);
3692: try {
3693: t_util.t_checkEmptyPage(page);
3694:
3695: int insertFlag = Page.INSERT_INITIAL | Page.INSERT_OVERFLOW;
3696:
3697: // insert a row with 100 columns from 200 to 400 bytes each and make it
3698: // sprawl across many pages.
3699: T_RawStoreRow r1 = new T_RawStoreRow(100);
3700: for (int i = 0; i < 100; i++)
3701: r1.setColumn(i, 100 + i, REC_001);
3702:
3703: RecordHandle rh1 = t_util.t_insertAtSlot(page, 0, r1,
3704: (byte) insertFlag);
3705: t_util.t_checkFetch(page, rh1, r1);
3706: page.unlatch();
3707: page = null;
3708: t_util.t_commit(t);
3709:
3710: c = t_util.t_openContainer(t, segment, cid, true);
3711: // Now purge that long row.
3712: page = t_util.t_getPage(c,
3713: ContainerHandle.FIRST_PAGE_NUMBER);
3714: t_util.t_checkRecordCount(page, 1, 1);
3715: page.purgeAtSlot(0, 1, false);
3716: t_util.t_checkEmptyPage(page);
3717: page.unlatch();
3718: page = null;
3719: // let recovery undo rollback this transaction
3720: register(key(304, 1), cid);
3721:
3722: } finally {
3723: if (page != null)
3724: page.unlatch();
3725: ctx.resetContext();
3726: }
3727:
3728: PASS("S304");
3729: }
3730:
3731: /* recover test 304:
3732: * repurge the same rows whose purging we rolled back in s304 at recovery.
3733: */
3734: protected void R304() throws T_Fail, StandardException {
3735: long cid = find(key(304, 1));
3736: if (cid < 0) {
3737: REPORT("R304 not run");
3738: return;
3739: }
3740:
3741: Transaction t = t_util.t_startTransaction();
3742: try {
3743: ContainerHandle c = t_util.t_openContainer(t, 0, cid, true);
3744: Page page = t_util.t_getPage(c,
3745: ContainerHandle.FIRST_PAGE_NUMBER);
3746: t_util.t_checkRecordCount(page, 1, 1);
3747:
3748: // During purges when data is not logged when slots are purged
3749: // they become null on rollback and some cases like long columns
3750: // we remove the wholepage on rollback we get the data back.
3751: T_RawStoreRow r1_wnl = new T_RawStoreRow(100);
3752: for (int i = 0; i < 18; i++)
3753: r1_wnl.setColumn(i, 4, REC_NULL);
3754: for (int i = 18; i < 100; i++)
3755: r1_wnl.setColumn(i, 100 + i, REC_001);
3756: RecordHandle rh1 = page.getRecordHandleAtSlot(0);
3757: t_util.t_checkFetch(page, rh1, r1_wnl);
3758:
3759: //purge after the recovery.
3760: page.purgeAtSlot(0, 1, false);
3761: page.unlatch();
3762: page = null;
3763: } finally {
3764: t_util.t_commit(t);
3765: t.close();
3766: }
3767:
3768: PASS("R304");
3769: }
3770:
3771: /*
3772: * S999 - last test of the recovery unit test, this leave the end of the
3773: * log in a fuzzy state, do NOT write any more log record after this or
3774: * you will corrupt the database
3775: *
3776: * DO NOT run this test if recovery test is ever run iteratively
3777: */
3778: protected void S999() throws T_Fail, StandardException {
3779: // only runnable in debug server since trace flags are set by SanityManager
3780: if (!SanityManager.DEBUG)
3781: return;
3782:
3783: T_TWC ctx = t_util.t_startTransactionWithContext();
3784: Transaction t = ctx.tran;
3785: ctx.switchTransactionContext();
3786:
3787: // LogToFile.TEST_LOG_SWITCH_LOG
3788: SanityManager.DEBUG_SET("TEST_LOG_SWITCH_LOG");
3789:
3790: // this will switch the log without writing out a checkpoint log record
3791: factory.checkpoint();
3792: Page page = null;
3793:
3794: try {
3795: long cid = t_util.t_addContainer(t, 0);
3796: ContainerHandle c = t_util.t_openContainer(t, 0, cid, true);
3797: page = t_util.t_getPage(c,
3798: ContainerHandle.FIRST_PAGE_NUMBER);
3799:
3800: T_RawStoreRow row1 = new T_RawStoreRow(REC_001);
3801: RecordHandle rh1 = t_util.t_insertAtSlot(page, 0, row1);
3802: t_util.t_commit(t);
3803:
3804: T_RawStoreRow row2 = new T_RawStoreRow(REC_002);
3805: c = t_util.t_openContainer(t, 0, cid, true);
3806: page = t_util.t_getPage(c,
3807: ContainerHandle.FIRST_PAGE_NUMBER);
3808:
3809: RecordHandle rh2 = t_util.t_insertAtSlot(page, 1, row2);
3810: if (rh2 == null) {
3811: REPORT("S999 not run, page cannot accomodate 2 rows");
3812: return;
3813: }
3814:
3815: t_util.t_checkRecordCount(page, 2, 2);
3816: t_util.t_checkFetch(page, rh1, REC_001);
3817: t_util.t_checkFetch(page, rh2, REC_002);
3818:
3819: T_RawStoreRow row3 = new T_RawStoreRow(REC_003);
3820:
3821: // LogToFile.TEST_LOG_INCOMPLETE_LOG_WRITE
3822: SanityManager.DEBUG_SET("TEST_LOG_INCOMPLETE_LOG_WRITE");
3823:
3824: // let's hope that this page is not written to disk... can't until
3825: // the page is unlatch, and we never unlatch it
3826: RecordHandle rh3 = t_util.t_insert(page, row3); // this is written out incompletely
3827: if (rh3 == null) {
3828: REPORT("S999 not run, page cannot accomodate 3 rows");
3829: return;
3830: }
3831:
3832: t_util.t_checkRecordCount(page, 3, 3);
3833: t_util.t_checkFetch(page, rh3, REC_003);
3834:
3835: REPORT("setup S999: cid1 " + cid + " page "
3836: + page.getPageNumber());
3837: register(key(999, 1), cid);
3838: register(key(999, 2), page.getPageNumber());
3839: } finally {
3840: SanityManager.DEBUG_CLEAR("TEST_LOG_SWITCH_LOG");
3841: SanityManager.DEBUG_CLEAR("TEST_LOG_INCOMPLETE_LOG_WRITE");
3842:
3843: ctx.resetContext();
3844: // let recovery roll it back
3845: }
3846: }
3847:
3848: protected void R999() throws StandardException, T_Fail {
3849: long cid = find(key(999, 1));
3850: if (cid < 0) {
3851: REPORT("R999 not run");
3852: return;
3853: }
3854:
3855: long pageid = find(key(999, 2));
3856: Transaction t = t_util.t_startTransaction();
3857: try {
3858: ContainerHandle c = t_util.t_openContainer(t, 0, cid, true);
3859: Page page = t_util.t_getPage(c, pageid);
3860:
3861: // there should be 2 rows on the page, 1 undelete and 1 deleted.
3862: // The third row is only partially written out the log and should
3863: // never appear
3864: t_util.t_checkRecordCount(page, 2, 1);
3865: t_util.t_checkFetchBySlot(page, 0, REC_001, false, false);
3866: t_util.t_checkFetchBySlot(page, 1, REC_002, true, false);
3867: } finally {
3868: t_util.t_commit(t);
3869: t.close();
3870: }
3871: PASS("R999: cid " + cid + " page " + pageid);
3872:
3873: }
3874:
3875: }
|