0001: /*
0002:
0003: Derby - Class org.apache.derbyTesting.unitTests.store.T_RawStoreFactory
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.derby.iapi.store.raw.*;
0025:
0026: // impl imports are the preferred way to create unit tests.
0027: import org.apache.derbyTesting.unitTests.harness.T_MultiThreadedIterations;
0028: import org.apache.derbyTesting.unitTests.harness.T_Fail;
0029:
0030: import org.apache.derby.iapi.services.context.ContextService;
0031: import org.apache.derby.iapi.services.context.ContextManager;
0032: import org.apache.derby.iapi.services.locks.*;
0033: import org.apache.derby.iapi.services.monitor.Monitor;
0034: import org.apache.derby.iapi.services.sanity.SanityManager;
0035: import org.apache.derby.iapi.services.uuid.UUIDFactory;
0036: import org.apache.derby.catalog.UUID;
0037: import org.apache.derby.iapi.services.property.PropertyUtil;
0038: import org.apache.derby.iapi.error.ExceptionSeverity;
0039: import org.apache.derby.iapi.error.StandardException;
0040:
0041: import org.apache.derby.iapi.store.access.*;
0042: import org.apache.derby.iapi.store.access.conglomerate.LogicalUndo;
0043:
0044: import org.apache.derby.iapi.store.raw.xact.RawTransaction;
0045: import org.apache.derby.iapi.store.raw.data.RawContainerHandle;
0046: import org.apache.derby.iapi.store.raw.log.LogInstant;
0047:
0048: import org.apache.derby.iapi.types.DataValueDescriptor;
0049:
0050: // impl a logInstant implemented as log counter to test truncateLWMs
0051: import org.apache.derby.impl.store.raw.log.LogCounter;
0052:
0053: import org.apache.derby.iapi.types.SQLChar;
0054:
0055: import org.apache.derby.iapi.reference.Property;
0056:
0057: import org.apache.derby.iapi.services.io.FormatableBitSet;
0058:
0059: import java.io.*;
0060: import java.util.Properties;
0061:
0062: /**
0063: A protocol unit test for the RawStore interface.
0064: */
0065:
0066: public class T_RawStoreFactory extends T_MultiThreadedIterations {
0067:
0068: static protected final String REC_001 = "McLaren";
0069: static protected final String REC_002 = "Ferrari";
0070: static protected final String REC_003 = "Benetton";
0071: static protected final String REC_004 = "Prost";
0072: static protected final String REC_005 = "Tyrell";
0073: static protected final String REC_006 = "012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789";
0074: static protected final String REC_007 = "abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyz";
0075: static protected final String REC_008 = "z";
0076: static protected final String REC_009 = "nanonano";
0077: static protected final String REC_010 = "fuzzbutt";
0078: static protected final String REC_011 = "mork";
0079: static protected final String REC_012 = "orson";
0080: static protected final String REC_013 = "mindy";
0081: static protected final String REC_014 = "thomas";
0082: static protected final String REC_015 = "henry";
0083: static protected final String REC_016 = "gordon";
0084: static protected final String REC_017 = "mavis";
0085: static protected final String REC_018 = "fatcontroller";
0086: static protected final String REC_UNDO = "Lotus";
0087: static protected final String REC_NULL = "NULL";
0088:
0089: static final FormatableBitSet BS_COL_0 = new FormatableBitSet(1);
0090:
0091: static protected final String SP1 = "savepoint1";
0092: static protected final String SP2 = "savepoint2";
0093:
0094: private static final String TEST_ROLLBACK_OFF = "derby.RawStore.RollbackTestOff";
0095:
0096: private static boolean testRollbackProperty;// initialize in start
0097: static protected boolean testRollback; // each thread has its own test rollback value
0098:
0099: static protected RawStoreFactory factory;
0100: static protected LockFactory lf;
0101: static protected ContextService contextService;
0102:
0103: static protected UUIDFactory uuidfactory;
0104: protected T_Util t_util;
0105: protected int openMode; // mode flags used in all open containers.
0106: protected boolean logDataForPurges = true; //used to test non-logged data purges
0107:
0108: public T_RawStoreFactory() {
0109: super ();
0110: BS_COL_0.set(0);
0111: }
0112:
0113: /**
0114: @exception StandardException cannot startup the context service
0115: */
0116: public void boot(boolean create, Properties startParams)
0117: throws StandardException {
0118: super .boot(create, startParams);
0119: contextService = ContextService.getFactory();
0120: }
0121:
0122: /*
0123: ** Methods required by T_Generic
0124: */
0125:
0126: protected String getModuleToTestProtocolName() {
0127: return RawStoreFactory.MODULE;
0128: }
0129:
0130: /**
0131: Set up test
0132:
0133: @exception T_Fail Unexpected behaviour from the API
0134: */
0135: protected void setupTest() throws T_Fail {
0136:
0137: String rollbackOff = PropertyUtil
0138: .getSystemProperty(TEST_ROLLBACK_OFF);
0139: testRollback = !Boolean.valueOf(rollbackOff).booleanValue();
0140:
0141: testRollbackProperty = testRollback; // testRollbackProperty never changes
0142:
0143: // don't automatic boot this service if it gets left around
0144: if (startParams == null) {
0145: startParams = new Properties();
0146: }
0147: startParams.put(Property.NO_AUTO_BOOT, Boolean.TRUE.toString());
0148: // remove the service directory to ensure a clean run
0149: startParams.put(Property.DELETE_ON_CREATE, Boolean.TRUE
0150: .toString());
0151:
0152: // see if we are testing encryption
0153: startParams = T_Util.setEncryptionParam(startParams);
0154:
0155: try {
0156:
0157: factory = (RawStoreFactory) Monitor
0158: .createPersistentService(
0159: getModuleToTestProtocolName(),
0160: getTestService(), startParams);
0161:
0162: if (factory == null) {
0163: throw T_Fail.testFailMsg(getModuleToTestProtocolName()
0164: + " service not started.");
0165: }
0166:
0167: lf = factory.getLockFactory();
0168: if (lf == null) {
0169: throw T_Fail
0170: .testFailMsg("LockFactory.MODULE not found");
0171: }
0172:
0173: uuidfactory = Monitor.getMonitor().getUUIDFactory();
0174:
0175: } catch (StandardException mse) {
0176: throw T_Fail.exceptionFail(mse);
0177: }
0178:
0179: REPORT("testRollback=" + testRollback);
0180:
0181: return;
0182: }
0183:
0184: protected String getTestService() {
0185: return "rawStoreTest";
0186: }
0187:
0188: /**
0189: * T_MultiThreadedIteration method
0190: *
0191: * @exception T_Fail Unexpected behaviour from the API
0192: */
0193: protected void joinSetupTest() throws T_Fail {
0194:
0195: T_Fail
0196: .T_ASSERT(factory != null,
0197: "raw store factory not setup ");
0198: T_Fail.T_ASSERT(lf != null, "Lock factory not setup ");
0199: T_Fail.T_ASSERT(contextService != null,
0200: "Context service not setup ");
0201:
0202: testRollback = testRollbackProperty;
0203:
0204: }
0205:
0206: protected T_MultiThreadedIterations newTestObject() {
0207: try {
0208: Class this Class = this .getClass();
0209: return (T_MultiThreadedIterations) (this Class.newInstance());
0210: } catch (InstantiationException ie) {
0211: return new T_RawStoreFactory();
0212: } catch (IllegalAccessException iae) {
0213: return new T_RawStoreFactory();
0214: }
0215: }
0216:
0217: /**
0218: run the test
0219:
0220: @exception T_Fail Unexpected behaviour from the API
0221: */
0222: protected void runTestSet() throws T_Fail {
0223:
0224: // get a utility helper
0225: t_util = new T_Util(factory, lf, contextService);
0226:
0227: ContextManager cm1 = contextService.newContextManager();
0228: contextService.setCurrentContextManager(cm1);
0229:
0230: try {
0231:
0232: // Run the tests with data not logged for purges.
0233: REPORT("Running tests with no data logged for purges");
0234: openMode = 0; // logged by default
0235: runPurgeWithNoDataLoggesTests();
0236:
0237: // Run the tests in normal logged mode
0238: REPORT("Running tests with logging requested");
0239: openMode = 0; // logged by default
0240: runEachTest();
0241:
0242: // run the tests on temp tables
0243: REPORT("Running tests for temp tables");
0244: testRollback = false; // obviously, we can't test rollback if we are not logging
0245: runTempTests();
0246:
0247: // Run the tests in unlogged mode
0248: REPORT("Running tests in unlogged mode");
0249: openMode = ContainerHandle.MODE_UNLOGGED
0250: | ContainerHandle.MODE_CREATE_UNLOGGED;
0251: testRollback = false; // obviously, we can't test rollback if we are not logging
0252: runEachTest();
0253:
0254: // if more runs are added here then you probably want to reset testRollback to
0255: // its initial value, or add the runs before the unlogged mode.
0256:
0257: } catch (StandardException se) {
0258:
0259: cm1.cleanupOnError(se);
0260: throw T_Fail.exceptionFail(se);
0261: } finally {
0262: contextService.resetCurrentContextManager(cm1);
0263: }
0264: }
0265:
0266: protected void runEachTest() throws T_Fail, StandardException {
0267:
0268: t_util.setOpenMode(openMode);
0269:
0270: // Transaction tests
0271: T000();
0272: T001();
0273: T002();
0274: T003();
0275: T004();
0276: T005();
0277: T006();
0278: T007();
0279: T008();
0280: T009();
0281: T010();
0282: T011();
0283: T012();
0284:
0285: // ContainerHandle tests
0286: C010(0);
0287: C011();
0288: C012(1);
0289: C014();
0290: C200();
0291: C201(0);
0292: C201(1);
0293:
0294: // Page tests
0295: P001(0);
0296: P002(0);
0297: P003(0);
0298: P004(0);
0299: P005(0);
0300: P006();
0301: P007(0);
0302: P008(0);
0303: P009(0);
0304: P011(0);
0305: P012(0);
0306: P013();
0307: P014();
0308: P015();
0309: P016();
0310: P017();
0311: P018();
0312: P019(); // test addPage with preallocation turned on
0313: P020(); // test createContainer with initialPage set to 10 pages
0314: P021(); // test preAllocate
0315: P022();
0316: P023(0); // overflowThreshold test
0317:
0318: // long row tests
0319: P030(0);
0320: P031(0);
0321: P032(0);
0322: P033(0);
0323: P034(0);
0324:
0325: P035(0); // long column test
0326:
0327: //run the following test because they do lot of checks
0328: //on rollbacking when contyainer is unlogged nothing is rolled back
0329: if ((openMode & ContainerHandle.MODE_UNLOGGED) == ContainerHandle.MODE_UNLOGGED) {
0330: openMode = 0; //run them as logged for time being
0331: t_util.setOpenMode(openMode);
0332: }
0333:
0334: // reclaiming space from long column and long rows - temp container
0335: // row space is not reclaimed.
0336: P036();
0337: P037();
0338: P038();
0339: P039();
0340: P040();
0341: P041();
0342: P042();
0343: P043();
0344:
0345: P050(); // rollback tests
0346: P051();
0347: P052();
0348: P053();
0349: P054();
0350: P055(0);
0351: P056(0);
0352:
0353: P061(); // sparse row test
0354:
0355: P071(); // serializable column test
0356:
0357: // update/update partial tests with long rows
0358: P701(0);
0359: P702(0);
0360: P703(0);
0361: P704(0);
0362: P705(0);
0363:
0364: P706(0, false);
0365: P706(0, true);
0366: P707(0);
0367: P708(0, false);
0368: P708(0, true);
0369:
0370: L001(); // large log record test
0371:
0372: // checkpoint test
0373: CP001();
0374: }
0375:
0376: protected void runTempTests() throws T_Fail, StandardException {
0377:
0378: REPORT("Thread " + threadNumber + " entering temp tests ");
0379:
0380: openMode = 0; // logged by default
0381: t_util.setOpenMode(openMode); // logged mode should be overriden for temp tables
0382:
0383: // now tests for temporary tables
0384:
0385: C010(ContainerHandle.TEMPORARY_SEGMENT);
0386: C012(ContainerHandle.TEMPORARY_SEGMENT);
0387: //P001(ContainerHandle.TEMPORARY_SEGMENT);
0388: //P002(ContainerHandle.TEMPORARY_SEGMENT);
0389: P003(ContainerHandle.TEMPORARY_SEGMENT);
0390: P004(ContainerHandle.TEMPORARY_SEGMENT);
0391: P005(ContainerHandle.TEMPORARY_SEGMENT);
0392: P011(ContainerHandle.TEMPORARY_SEGMENT);
0393: P012(ContainerHandle.TEMPORARY_SEGMENT);
0394: P030(ContainerHandle.TEMPORARY_SEGMENT);
0395:
0396: // update/update partial tests with long rows
0397: P055(ContainerHandle.TEMPORARY_SEGMENT);
0398: P056(ContainerHandle.TEMPORARY_SEGMENT);
0399:
0400: P701(ContainerHandle.TEMPORARY_SEGMENT);
0401: P702(ContainerHandle.TEMPORARY_SEGMENT);
0402: P703(ContainerHandle.TEMPORARY_SEGMENT);
0403: P704(ContainerHandle.TEMPORARY_SEGMENT);
0404: P705(ContainerHandle.TEMPORARY_SEGMENT);
0405: P706(ContainerHandle.TEMPORARY_SEGMENT, false);
0406: P706(ContainerHandle.TEMPORARY_SEGMENT, true);
0407: P707(ContainerHandle.TEMPORARY_SEGMENT);
0408:
0409: // tests specific to temp tables
0410:
0411: // checking truncate at commit/rollback works
0412: TC001();
0413: TC002(ContainerHandle.MODE_TRUNCATE_ON_COMMIT, true);
0414: TC002(ContainerHandle.MODE_TRUNCATE_ON_COMMIT, false);
0415: TC002(0, false);
0416:
0417: // checking an explict drop works ...
0418: TC003(ContainerHandle.MODE_TRUNCATE_ON_COMMIT, true);
0419: TC003(ContainerHandle.MODE_TRUNCATE_ON_COMMIT, false);
0420: TC003(0, false);
0421: TC003(0, true);
0422: TC003(ContainerHandle.MODE_DROP_ON_COMMIT, true);
0423: TC003(ContainerHandle.MODE_DROP_ON_COMMIT, false);
0424:
0425: // various combinations of opens ...
0426: TC004all();
0427:
0428: REPORT("Thread " + threadNumber + " exiting temp tests ");
0429: }
0430:
0431: protected void runPurgeWithNoDataLoggesTests() throws T_Fail,
0432: StandardException {
0433:
0434: REPORT("Thread " + threadNumber
0435: + " entering purges with no data logged tests ");
0436: logDataForPurges = false;
0437: P005(0);
0438: P006();
0439: P014();
0440: P036();
0441: P037();
0442: P709();
0443: P710();
0444: P711();
0445: REPORT("Thread " + threadNumber
0446: + " exiting purge with no data logged tests ");
0447: logDataForPurges = true;
0448: }
0449:
0450: /*
0451: ** The tests
0452: ** Tnnn indicates a test that is mainly testing the Transaction interface
0453: ** Cnnn indicates a test that is mainly testing the ContainerHandle interface
0454: ** Pnnn indicates a test that is mainly testing the Page interface
0455: **
0456: ** nnn < 200 tends to indicate purely API tests, ie checking methods
0457: ** are callable and return the right value. This includes negative tests.
0458: **
0459: ** nnn >= 200 tends to indicate more involved tests, ie ones that test the
0460: ** methods actually did something.
0461:
0462: */
0463:
0464: /**
0465: T000 - ensure a transaction starts out idle.
0466:
0467: @exception T_Fail Unexpected behaviour from the API
0468: @exception StandardException Unexpected exception from the implementation
0469: */
0470: protected void T000() throws T_Fail, StandardException {
0471:
0472: Transaction t1 = t_util.t_startTransaction();
0473:
0474: t1.close();
0475:
0476: t1 = t_util.t_startInternalTransaction();
0477:
0478: t1.close();
0479:
0480: t1 = t_util.t_startTransaction();
0481: Transaction ti = t_util.t_startInternalTransaction();
0482:
0483: ti.close();
0484:
0485: t1.close();
0486:
0487: PASS("T000");
0488: }
0489:
0490: /**
0491: T001 - start and commit an empty transaction.
0492:
0493: @exception T_Fail Unexpected behaviour from the API
0494: @exception StandardException Unexpected exception from the implementation
0495: */
0496: protected void T001() throws T_Fail, StandardException {
0497:
0498: Transaction t1 = t_util.t_startTransaction();
0499:
0500: t_util.t_commit(t1);
0501:
0502: t1.close();
0503:
0504: PASS("T001");
0505: }
0506:
0507: /**
0508: T002 - start and abort an empty transaction.
0509:
0510: @exception T_Fail Unexpected behaviour from the API
0511: @exception StandardException Unexpected exception from the implementation
0512: */
0513: protected void T002() throws T_Fail, StandardException {
0514:
0515: Transaction t1 = t_util.t_startTransaction();
0516:
0517: t_util.t_abort(t1);
0518:
0519: t1.close();
0520:
0521: PASS("T002");
0522: }
0523:
0524: /**
0525: T003 - start and commit an empty transaction and then ensure
0526: that the transaction remains open for another commit.
0527:
0528: @exception T_Fail Unexpected behaviour from the API
0529: @exception StandardException Unexpected exception from the implementation
0530: */
0531: protected void T003() throws T_Fail, StandardException {
0532:
0533: Transaction t1 = t_util.t_startTransaction();
0534:
0535: t_util.t_commit(t1);
0536:
0537: t_util.t_commit(t1);
0538: t_util.t_abort(t1);
0539:
0540: t1.close();
0541:
0542: PASS("T003");
0543: }
0544:
0545: /**
0546: T004 - start and abort an empty transaction and then ensure
0547: that the transaction remains open for a commit and another abort.
0548:
0549: @exception T_Fail Unexpected behaviour from the API
0550: @exception StandardException Unexpected exception from the implementation
0551: */
0552: protected void T004() throws T_Fail, StandardException {
0553:
0554: Transaction t1 = t_util.t_startTransaction();
0555:
0556: t_util.t_abort(t1);
0557:
0558: t_util.t_commit(t1);
0559:
0560: t_util.t_abort(t1);
0561:
0562: t1.close();
0563:
0564: PASS("T004");
0565: }
0566:
0567: /**
0568: T005 check transaction identifiers on idle transactions.
0569:
0570: @exception T_Fail Unexpected behaviour from the API
0571: @exception StandardException Unexpected exception from the implementation
0572:
0573: */
0574: protected void T005() throws T_Fail, StandardException {
0575:
0576: Transaction t1 = t_util.t_startTransaction();
0577:
0578: // local transactions do not have global id's
0579: GlobalTransactionId id1 = t1.getGlobalId();
0580: if (id1 != null)
0581: throw T_Fail
0582: .testFailMsg("null not returned from local Transaction.getId()");
0583: t1.close();
0584:
0585: byte[] global_id = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12,
0586: 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26,
0587: 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40,
0588: 41, 42, 44, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54,
0589: 55, 56, 57, 58, 59, 60, 61, 62, 63 };
0590: byte[] branch_id = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12,
0591: 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26,
0592: 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40,
0593: 41, 42, 44, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54,
0594: 55, 56, 57, 58, 59, 60, 61, 62, 63 };
0595:
0596: t1 = t_util.t_startGlobalTransaction(42, global_id, branch_id);
0597:
0598: id1 = t1.getGlobalId();
0599:
0600: if (!id1.equals(id1))
0601: throw T_Fail
0602: .testFailMsg("TransactionId does not compare equal to itself");
0603:
0604: if (!id1.equals(t1.getGlobalId()))
0605: throw T_Fail
0606: .testFailMsg("TransactionId has changed without any activity on Transaction");
0607:
0608: if (id1.equals(this ))
0609: throw T_Fail
0610: .testFailMsg("TransactionId compared equal to an non-transaction id object");
0611:
0612: t1.close();
0613: t1 = null;
0614:
0615: // change the branch_id for the second global xact.
0616: branch_id[63] = 82;
0617: Transaction t2 = t_util.t_startGlobalTransaction(42, global_id,
0618: branch_id);
0619:
0620: GlobalTransactionId id2 = t2.getGlobalId();
0621: if (id2 == null)
0622: throw T_Fail
0623: .testFailMsg("null returned from Transaction.getId()");
0624:
0625: if (id1.equals(id2))
0626: throw T_Fail
0627: .testFailMsg("TransactionId's returned equal from different transactions");
0628: if (id2.equals(id1))
0629: throw T_Fail
0630: .testFailMsg("TransactionId's returned equal from different transactions");
0631:
0632: t2.close();
0633:
0634: PASS("T005");
0635: }
0636:
0637: /**
0638: T006 - savepoint basic API testing
0639:
0640: @exception T_Fail Unexpected behaviour from the API
0641: @exception StandardException Unexpected exception from the implementation
0642: */
0643: protected void T006() throws T_Fail, StandardException {
0644:
0645: Transaction t1 = t_util.t_startTransaction();
0646:
0647: // check a random savepoint name is not accepted
0648: t_util.t_checkInvalidSavePoint(t1, "sdfjsdfg");
0649:
0650: t1.setSavePoint(SP1, null);
0651:
0652: t1.rollbackToSavePoint(SP1, null); // leaves savepoint around
0653: t1.rollbackToSavePoint(SP1, null); // therefore this should work
0654:
0655: t1.releaseSavePoint(SP1, null);
0656:
0657: // SP1 should no longer exist
0658: t_util.t_checkInvalidSavePoint(t1, SP1);
0659:
0660: // should be able to re-use it ...
0661: t1.setSavePoint(SP1, null);
0662: t1.rollbackToSavePoint(SP1, null); // leaves savepoint around
0663: t1.rollbackToSavePoint(SP1, null); // therefore this should work
0664:
0665: t1.releaseSavePoint(SP1, null);
0666: t_util.t_checkInvalidSavePoint(t1, SP1);
0667:
0668: t_util.t_commit(t1);
0669: t1.close();
0670:
0671: PASS("T006");
0672: }
0673:
0674: /**
0675: T007 - savepoint nesting testing
0676:
0677: @exception T_Fail Unexpected behaviour from the API
0678: @exception StandardException Unexpected exception from the implementation
0679: */
0680: protected void T007() throws T_Fail, StandardException {
0681:
0682: Transaction t1 = t_util.t_startTransaction();
0683: int position = 0;
0684:
0685: /*
0686: ** Push two save points and release the first, both should disappear
0687: */
0688: t1.setSavePoint(SP1, null);
0689: t1.setSavePoint(SP2, null);
0690:
0691: position = t1.releaseSavePoint(SP1, null);
0692: if (position != 0)
0693: throw T_Fail
0694: .testFailMsg("Save Point Position in the stack isincorrect:"
0695: + position);
0696:
0697: // SP1 and SP2 should no longer exist
0698: t_util.t_checkInvalidSavePoint(t1, SP1);
0699: t_util.t_checkInvalidSavePoint(t1, SP2);
0700:
0701: /*
0702: ** Push two save points and remove the second, first should remain
0703: */
0704: t1.setSavePoint(SP1, null);
0705: t1.setSavePoint(SP2, null);
0706:
0707: t1.rollbackToSavePoint(SP2, null); // leaves savepoint around
0708: position = t1.rollbackToSavePoint(SP2, null); // therefore this should work
0709:
0710: if (position != 2)
0711: throw T_Fail
0712: .testFailMsg("Save Point Position in the stack isincorrect:"
0713: + position);
0714:
0715: position = t1.releaseSavePoint(SP2, null);
0716: if (position != 1)
0717: throw T_Fail
0718: .testFailMsg("Save Point Position in the stack is incorrect:"
0719: + position);
0720:
0721: t_util.t_checkInvalidSavePoint(t1, SP2);
0722:
0723: t1.rollbackToSavePoint(SP1, null); // this is the main test
0724:
0725: t1.releaseSavePoint(SP1, null);
0726: t_util.t_checkInvalidSavePoint(t1, SP1);
0727:
0728: /*
0729: ** Push two save points and rollback to the first, the second should disappear
0730: */
0731: t1.setSavePoint(SP1, null);
0732: t1.setSavePoint(SP2, null);
0733:
0734: position = t1.rollbackToSavePoint(SP1, null); // leaves SP1, removes SP2
0735: if (position != 1)
0736: throw T_Fail
0737: .testFailMsg("Save Point Position in the stack is incorrect:"
0738: + position);
0739:
0740: t_util.t_checkInvalidSavePoint(t1, SP2);
0741: t1.rollbackToSavePoint(SP1, null);
0742:
0743: t1.releaseSavePoint(SP1, null);
0744:
0745: t_util.t_commit(t1);
0746: t1.close();
0747:
0748: PASS("T007");
0749: }
0750:
0751: /**
0752: T008 - savepoint testing, ensure save points disappear at commit or abort.
0753:
0754: @exception T_Fail Unexpected behaviour from the API
0755: @exception StandardException Unexpected exception from the implementation
0756: */
0757: protected void T008() throws T_Fail, StandardException {
0758:
0759: Transaction t1 = t_util.t_startTransaction();
0760: int position1 = 0;
0761: int position2 = 0;
0762:
0763: position1 = t1.setSavePoint(SP1, null);
0764: position2 = t1.setSavePoint(SP2, null);
0765:
0766: if (position1 != 1 && position2 != 2)
0767: throw T_Fail
0768: .testFailMsg("Save Point Position in the Stack seeme to wrong");
0769:
0770: t1.commit();
0771:
0772: t_util.t_checkInvalidSavePoint(t1, SP1);
0773: t_util.t_checkInvalidSavePoint(t1, SP2);
0774:
0775: position1 = t1.setSavePoint(SP1, null);
0776: position2 = t1.setSavePoint(SP2, null);
0777:
0778: if (position1 != 1 && position2 != 2)
0779: throw T_Fail
0780: .testFailMsg("Save Point Position in the Stack seeme to wrong");
0781:
0782: t1.abort();
0783: position1 = t1.setSavePoint(SP1, null);
0784: position2 = t1.setSavePoint(SP2, null);
0785: if (position1 != 1 && position2 != 2)
0786: throw T_Fail
0787: .testFailMsg("Save Point Position in the Stack seeme to wrong");
0788: t1.abort();
0789: t_util.t_checkInvalidSavePoint(t1, SP1);
0790: t_util.t_checkInvalidSavePoint(t1, SP2);
0791:
0792: t1.close();
0793:
0794: PASS("T008");
0795: }
0796:
0797: /**
0798: T009 - add a container and remove it within the same transaction.
0799: @exception T_Fail Unexpected behaviour from the API
0800: @exception StandardException Unexpected exception from the implementation
0801:
0802: */
0803:
0804: protected void T009() throws StandardException, T_Fail {
0805: Transaction t = t_util.t_startTransaction();
0806:
0807: long cid = t_util.t_addContainer(t, 0, 4096);
0808: t_util.t_dropContainer(t, 0, cid);
0809:
0810: ContainerKey id = new ContainerKey(0, cid);
0811: ContainerHandle ch = t.openContainer(id,
0812: ContainerHandle.MODE_READONLY);
0813: if (ch != null)
0814: throw T_Fail
0815: .testFailMsg("Dropped Container should not open");
0816:
0817: t_util.t_commit(t);
0818:
0819: t.close();
0820:
0821: PASS("T009");
0822: }
0823:
0824: /**
0825: T010 - add a container with a default size and remove it within the same transaction.
0826: @exception T_Fail Unexpected behaviour from the API
0827: @exception StandardException Unexpected exception from the implementation
0828:
0829: */
0830:
0831: protected void T010() throws StandardException, T_Fail {
0832: Transaction t1 = t_util.t_startTransaction();
0833:
0834: long cid = t_util.t_addContainer(t1, 0);
0835:
0836: t_util.t_dropContainer(t1, 0, cid);
0837:
0838: ContainerKey id = new ContainerKey(0, cid);
0839: ContainerHandle ch = t1.openContainer(id,
0840: ContainerHandle.MODE_READONLY);
0841: if (ch != null)
0842: throw T_Fail
0843: .testFailMsg("Dropped Container should not open");
0844:
0845: t_util.t_commit(t1);
0846:
0847: t1.close();
0848:
0849: PASS("T010");
0850: }
0851:
0852: /**
0853: T011 - see that a container remains open over the commit of an open transaction..
0854: @exception T_Fail Unexpected behaviour from the API
0855: @exception StandardException Unexpected exception from the implementation
0856:
0857: */
0858:
0859: protected void T011() throws StandardException, T_Fail {
0860:
0861: Transaction t = t_util.t_startInternalTransaction();
0862:
0863: long cid = t_util.t_addContainer(t, 0);
0864:
0865: ContainerHandle c;
0866:
0867: c = t_util.t_openContainer(t, 0, cid, true);
0868:
0869: t.commit();
0870:
0871: // container should still be open
0872: Page page = t_util.t_getPage(c,
0873: ContainerHandle.FIRST_PAGE_NUMBER);
0874:
0875: t.commit();
0876:
0877: // page should still be latched
0878: if (!page.isLatched())
0879: throw T_Fail
0880: .testFailMsg("page not latched after commit of internal transaction");
0881:
0882: page.unlatch();
0883: c.close();
0884:
0885: t.commit();
0886:
0887: c = t_util.t_openContainer(t, 0, cid, true);
0888: page = t_util.t_getPage(c, ContainerHandle.FIRST_PAGE_NUMBER);
0889:
0890: // container and page should be closed
0891: t.abort();
0892: if (page.isLatched())
0893: throw T_Fail
0894: .testFailMsg("page latched after abort of internal transaction");
0895:
0896: try {
0897: page = t_util.t_getLastPage(c);
0898: throw T_Fail
0899: .testFailMsg("container open after abort of internal transaction");
0900:
0901: } catch (StandardException te) {
0902: }
0903:
0904: t_util.t_dropContainer(t, 0, cid); // cleanup
0905:
0906: t_util.t_commit(t);
0907:
0908: t.close();
0909:
0910: PASS("T011");
0911: }
0912:
0913: /**
0914: Test Xact.makeRecordHandle()
0915:
0916: @exception T_Fail Unexpected behaviour from the API
0917: @exception StandardException Unexpected exception from the implementation
0918: */
0919: protected void T012() throws StandardException, T_Fail {
0920:
0921: Transaction t = t_util.t_startTransaction();
0922:
0923: long cid = t_util.t_addContainer(t, 0);
0924:
0925: ContainerHandle c = t_util.t_openContainer(t, 0, cid, true);
0926: Page page = t_util.t_getPage(c,
0927: ContainerHandle.FIRST_PAGE_NUMBER);
0928:
0929: RecordHandle r1, r2;
0930: RecordHandle new_r1, new_r2;
0931:
0932: T_RawStoreRow row1 = new T_RawStoreRow(REC_001);
0933: T_RawStoreRow row2 = new T_RawStoreRow(REC_002);
0934:
0935: r1 = t_util.t_insertAtSlot(page, 0, row1);
0936: new_r1 = c.makeRecordHandle(r1.getPageNumber(), r1.getId());
0937:
0938: t_util.t_checkFetch(page, new_r1, REC_001);
0939:
0940: r2 = t_util.t_insertAtSlot(page, 1, row2);
0941:
0942: if (r2 != null) {
0943: new_r2 = c.makeRecordHandle(r2.getPageNumber(), r2.getId());
0944: t_util.t_checkFetch(page, r2, REC_002);
0945: }
0946:
0947: t_util.t_commit(t);
0948: t.close();
0949:
0950: PASS("T012");
0951:
0952: }
0953:
0954: /**
0955: C010 - Create a container within a transaction, commit and the re-open
0956: the container twice.
0957:
0958: @exception T_Fail Unexpected behaviour from the API
0959: @exception StandardException Unexpected exception from the implementation
0960:
0961: */
0962: protected void C010(int segment) throws T_Fail, StandardException {
0963:
0964: Transaction t = t_util.t_startTransaction();
0965:
0966: long cid = t_util.t_addContainer(t, segment);
0967:
0968: t_util.t_commit(t);
0969:
0970: ContainerHandle c1, c2;
0971:
0972: c1 = t_util.t_openContainer(t, segment, cid, true);
0973: c1 = t_util.t_openContainer(t, segment, cid, true);
0974: t_util.t_dropContainer(t, segment, cid); // cleanup
0975:
0976: t_util.t_commit(t);
0977: t.close();
0978:
0979: PASS("C010");
0980:
0981: }
0982:
0983: /**
0984: C011 - Create a container withina transaction, commit and the re-open
0985: the container in update and non-update mode.
0986:
0987: @exception T_Fail Unexpected behaviour from the API
0988: @exception StandardException Unexpected exception from the implementation
0989:
0990: */
0991: protected void C011() throws T_Fail, StandardException {
0992:
0993: Transaction t = t_util.t_startTransaction();
0994:
0995: long cid = t_util.t_addContainer(t, 0);
0996:
0997: t_util.t_commit(t);
0998:
0999: ContainerHandle c1, c2;
1000:
1001: c1 = t_util.t_openContainer(t, 0, cid, false);
1002: c1 = t_util.t_openContainer(t, 0, cid, true);
1003:
1004: t_util.t_dropContainer(t, 0, cid); // cleanup
1005:
1006: t_util.t_commit(t);
1007: t.close();
1008: PASS("C011");
1009:
1010: }
1011:
1012: /**
1013: C012 - Drop a container within a transaction, commit, see that it is deleted.
1014: Drop a container within a transaction, rollback and re-open and see
1015: that it is not deleted.
1016:
1017: @exception T_Fail Unexpected behaviour from the API
1018: @exception StandardException Standard Derby error policy
1019: */
1020: protected void C012(long segment) throws T_Fail, StandardException {
1021:
1022: Transaction t = t_util.t_startTransaction();
1023:
1024: long cid = t_util.t_addContainer(t, segment);
1025: t_util.t_commit(t);
1026:
1027: ContainerHandle c1 = t_util.t_openContainer(t, segment, cid,
1028: true);
1029:
1030: t_util.t_dropContainer(t, segment, cid);
1031:
1032: if (testRollback) {
1033: t_util.t_abort(t); // this should rollback the drop
1034: c1 = t_util.t_openContainer(t, segment, cid, true);
1035:
1036: REPORT("rollback of drop container tested");
1037:
1038: t_util.t_dropContainer(t, segment, cid);
1039: }
1040:
1041: t_util.t_commit(t);
1042:
1043: ContainerKey id = new ContainerKey(segment, cid);
1044: c1 = t.openContainer(id,
1045: (ContainerHandle.MODE_FORUPDATE | openMode)); // this should fail
1046: if (c1 != null)
1047: throw T_Fail
1048: .testFailMsg("Deleted Container should fail to open");
1049:
1050: t_util.t_commit(t);
1051: t.close();
1052: PASS("C012");
1053: }
1054:
1055: /**
1056: C014 - Open a container for locking only.
1057: @exception T_Fail Unexpected behaviour from the API
1058: @exception StandardException Standard Derby error policy
1059: */
1060: protected void C014() throws T_Fail, StandardException {
1061:
1062: Transaction t = t_util.t_startTransaction();
1063:
1064: ContainerKey id = new ContainerKey(77, 45);
1065: ContainerHandle c = t.openContainer(id,
1066: ContainerHandle.MODE_OPEN_FOR_LOCK_ONLY);
1067:
1068: if (c == null)
1069: throw T_Fail
1070: .testFailMsg("open of a container for lock only failed.");
1071:
1072: RecordHandle rh1 = c.makeRecordHandle(23, 456);
1073: if (rh1 == null)
1074: throw T_Fail.testFailMsg("makeRecordHandle returned null");
1075: c.getLockingPolicy().lockRecordForRead(t, c, rh1, true, true);
1076:
1077: RecordHandle rh2 = c.makeRecordHandle(23, 7);
1078: if (rh2 == null)
1079: throw T_Fail.testFailMsg("makeRecordHandle returned null");
1080: c.getLockingPolicy().lockRecordForRead(t, c, rh2, true, false);
1081:
1082: RecordHandle rh3 = c.makeRecordHandle(23, 9);
1083: c.getLockingPolicy().lockRecordForWrite(t, rh3, false, true);
1084: if (rh3 == null)
1085: throw T_Fail.testFailMsg("makeRecordHandle returned null");
1086:
1087: c.getLockingPolicy().unlockRecordAfterRead(t, c, rh2, false,
1088: true);
1089:
1090: c.close();
1091:
1092: t.commit();
1093:
1094: t.close();
1095:
1096: PASS("C014");
1097: }
1098:
1099: /**
1100: @exception T_Fail Unexpected behaviour from the API
1101: @exception StandardException Unexpected exception from the implementation
1102: */
1103: protected void C200() throws T_Fail, StandardException {
1104:
1105: Transaction t1 = t_util.t_startTransaction();
1106:
1107: long cid = t_util.t_addContainer(t1, 0);
1108:
1109: t_util.t_commit(t1);
1110:
1111: ContainerHandle c1;
1112: Page lastPage;
1113: RecordHandle rh001, rh002, rh003;
1114: T_RawStoreRow row;
1115:
1116: REPORT("see if the container can be opened again");
1117: c1 = t_util.t_openContainer(t1, 0, cid, false);
1118:
1119: c1.close();
1120: t_util.t_commit(t1);
1121:
1122: REPORT("insert a record into the container.");
1123:
1124: c1 = t_util.t_openContainer(t1, 0, cid, true);
1125:
1126: lastPage = t_util.t_getLastPage(c1);
1127: if (lastPage == null)
1128: throw T_Fail.testFailMsg("Could get container's last page");
1129:
1130: if (lastPage.getPageNumber() != ContainerHandle.FIRST_PAGE_NUMBER)
1131: throw T_Fail.testFailMsg("Initial page must be "
1132: + ContainerHandle.FIRST_PAGE_NUMBER + ", is "
1133: + lastPage.getPageNumber());
1134:
1135: row = new T_RawStoreRow(REC_001);
1136: if (!lastPage.spaceForInsert())
1137: throw T_Fail.testFailMsg("No room for record on page");
1138:
1139: rh001 = t_util.t_insert(lastPage, row);
1140: if (rh001 == null)
1141: throw T_Fail.testFailMsg("Failed to insert record");
1142:
1143: // see if we can fetch that record
1144: t_util.t_checkFetch(lastPage, rh001, REC_001);
1145:
1146: lastPage.unlatch();
1147: lastPage = null;
1148:
1149: t_util.t_commit(t1);
1150: c1 = null;
1151:
1152: REPORT("read record just inserted.");
1153:
1154: c1 = t_util.t_openContainer(t1, 0, cid, false);
1155:
1156: lastPage = t_util.t_getLastPage(c1);
1157: if (lastPage == null)
1158: throw T_Fail.testFailMsg("Could get container's last page");
1159:
1160: t_util.t_checkFetch(lastPage, rh001, REC_001);
1161: t_util.t_checkFetchFirst(lastPage, REC_001);
1162: t_util.t_checkFetchLast(lastPage, REC_001);
1163:
1164: t_util.t_commit(t1);
1165: lastPage = null;
1166: c1 = null;
1167:
1168: REPORT("insert 2 more records.");
1169:
1170: c1 = t_util.t_openContainer(t1, 0, cid, true);
1171:
1172: lastPage = t_util.t_getLastPage(c1);
1173: if (lastPage == null)
1174: throw T_Fail.testFailMsg("Could get container's last page");
1175:
1176: if (lastPage.getPageNumber() != ContainerHandle.FIRST_PAGE_NUMBER)
1177: throw T_Fail.testFailMsg("Initial page must be "
1178: + ContainerHandle.FIRST_PAGE_NUMBER + ", is "
1179: + lastPage.getPageNumber());
1180:
1181: row = new T_RawStoreRow(REC_002);
1182: if (!lastPage.spaceForInsert())
1183: throw T_Fail.testFailMsg("No room for record on page");
1184:
1185: if (!lastPage.recordExists(rh001, false))
1186: throw T_Fail.testFailMsg("Record 001 has vanished");
1187:
1188: //
1189:
1190: // RESOLVE: just insert them for now, order is 002,001,003
1191: // 001 is already on the page
1192:
1193: rh002 = t_util.t_insertAtSlot(lastPage, 0, row);
1194: row = new T_RawStoreRow(REC_003);
1195: rh003 = t_util.t_insert(lastPage, row);
1196: // Order is 002, 001, 003
1197:
1198: lastPage.unlatch();
1199: lastPage = null;
1200:
1201: t_util.t_commit(t1);
1202: c1 = null;
1203:
1204: REPORT("checks on all 3 records.");
1205:
1206: c1 = t_util.t_openContainer(t1, 0, cid, false);
1207:
1208: lastPage = t_util.t_getLastPage(c1);
1209: if (lastPage == null)
1210: throw T_Fail.testFailMsg("Could get container's last page");
1211:
1212: // Order is 002, 001, 003
1213: t_util.t_checkFetch(lastPage, rh001, REC_001);
1214: t_util.t_checkFetch(lastPage, rh002, REC_002);
1215: t_util.t_checkFetch(lastPage, rh003, REC_003);
1216:
1217: t_util.t_checkFetch(lastPage, lastPage.getRecordHandle(rh001
1218: .getId()), REC_001);
1219: t_util.t_checkFetch(lastPage, lastPage.getRecordHandle(rh002
1220: .getId()), REC_002);
1221:
1222: lastPage.unlatch();
1223: lastPage = null;
1224:
1225: t_util.t_commit(t1);
1226:
1227: REPORT("start deleting.");
1228:
1229: c1 = t_util.t_openContainer(t1, 0, cid, true);
1230:
1231: lastPage = t_util.t_getLastPage(c1);
1232: if (lastPage == null)
1233: throw T_Fail.testFailMsg("Could get container's last page");
1234:
1235: // Order is 002, 001, 003
1236: t_util.t_checkFetch(lastPage, rh001, REC_001);
1237: t_util.t_checkFetch(lastPage, rh002, REC_002);
1238: t_util.t_checkFetch(lastPage, rh003, REC_003);
1239:
1240: lastPage.delete(rh001, (LogicalUndo) null);
1241: if (lastPage.fetch(rh001, new DataValueDescriptor[0],
1242: (FormatableBitSet) null, false) != null) {
1243: throw T_Fail.testFailMsg("deleted record is still present");
1244: }
1245: // Order is 002, 003
1246: t_util.t_checkFetch(lastPage, rh002, REC_002);
1247: t_util.t_checkFetch(lastPage, rh003, REC_003);
1248:
1249: t_util.t_checkFetchNext(lastPage, rh002, REC_003);
1250: t_util.t_checkFetchPrevious(lastPage, rh003, REC_002);
1251:
1252: lastPage.delete(rh002, (LogicalUndo) null);
1253: if (lastPage.fetch(rh002, new DataValueDescriptor[0],
1254: (FormatableBitSet) null, false) != null) {
1255: throw T_Fail.testFailMsg("deleted record is still present");
1256: }
1257:
1258: t_util.t_checkFetch(lastPage, rh003, REC_003);
1259: t_util.t_checkFetchFirst(lastPage, REC_003);
1260: t_util.t_checkFetchLast(lastPage, REC_003);
1261:
1262: lastPage.unlatch();
1263: lastPage = null;
1264:
1265: t_util.t_commit(t1);
1266:
1267: REPORT("update the remaining record.");
1268:
1269: c1 = t_util.t_openContainer(t1, 0, cid, true);
1270:
1271: lastPage = t_util.t_getLastPage(c1);
1272: if (lastPage == null)
1273: throw T_Fail.testFailMsg("Could get container's last page");
1274:
1275: // Order is 003
1276: t_util.t_checkFetch(lastPage, rh003, REC_003);
1277:
1278: T_RawStoreRow urow = new T_RawStoreRow(REC_004);
1279:
1280: if (lastPage.fetch(rh003, new DataValueDescriptor[0],
1281: (FormatableBitSet) null, true) == null) {
1282: throw T_Fail.testFailMsg("fetch for update returned false");
1283: }
1284:
1285: if (!lastPage.update(rh003, urow.getRow(),
1286: (FormatableBitSet) null))
1287: throw T_Fail.testFailMsg("update returned false");
1288:
1289: // Order is 003
1290: t_util.t_checkFetch(lastPage, rh003, REC_004);
1291:
1292: lastPage.unlatch();
1293: lastPage = null;
1294:
1295: t_util.t_commit(t1);
1296:
1297: t_util.t_dropContainer(t1, 0, cid); // cleanup
1298:
1299: t_util.t_commit(t1);
1300: t1.close();
1301:
1302: PASS("C200");
1303:
1304: }
1305:
1306: /**
1307: C201 - Create container with different page size, minimum record size,
1308: inserting into these containers to check if the variables are set correctly.
1309:
1310: @exception T_Fail Unexpected behaviour from the API
1311: @exception StandardException Unexpected exception from the implementation
1312: */
1313: protected void C201(int whatPage) throws T_Fail, StandardException {
1314:
1315: int pageSize = (whatPage == 0 ? 4096 : 32768);
1316:
1317: Transaction t1 = t_util.t_startTransaction();
1318:
1319: REPORT("create container with pageSize " + pageSize
1320: + ", spareSpace " + 0 + ", minimumRecordSize "
1321: + pageSize / 2);
1322: long cid = t_util.t_addContainer(t1, 0, pageSize, 0,
1323: pageSize / 2, false);
1324:
1325: t_util.t_commit(t1);
1326:
1327: ContainerHandle c1;
1328: Page lastPage;
1329: RecordHandle rh001, rh002, rh003;
1330: T_RawStoreRow row;
1331:
1332: REPORT("see if the container can be opened again");
1333: c1 = t_util.t_openContainer(t1, 0, cid, false);
1334:
1335: c1.close();
1336: t_util.t_commit(t1);
1337:
1338: REPORT("insert a record into the container.");
1339:
1340: c1 = t_util.t_openContainer(t1, 0, cid, true);
1341:
1342: lastPage = t_util.t_getLastPage(c1);
1343: if (lastPage == null)
1344: throw T_Fail
1345: .testFailMsg("Couldn't get container's last page");
1346:
1347: if (lastPage.getPageNumber() != ContainerHandle.FIRST_PAGE_NUMBER)
1348: throw T_Fail.testFailMsg("Initial page must be "
1349: + ContainerHandle.FIRST_PAGE_NUMBER + ", is "
1350: + lastPage.getPageNumber());
1351:
1352: row = new T_RawStoreRow(REC_001);
1353: if (!lastPage.spaceForInsert())
1354: throw T_Fail.testFailMsg("No room for record on page");
1355:
1356: rh001 = t_util.t_insert(lastPage, row);
1357: if (rh001 == null)
1358: throw T_Fail.testFailMsg("Failed to insert record");
1359:
1360: // see if we can fetch that record
1361: t_util.t_checkFetch(lastPage, rh001, REC_001);
1362:
1363: lastPage.unlatch();
1364: lastPage = null;
1365:
1366: t_util.t_commit(t1);
1367: c1 = null;
1368:
1369: REPORT("read record just inserted.");
1370:
1371: c1 = t_util.t_openContainer(t1, 0, cid, false);
1372:
1373: lastPage = t_util.t_getLastPage(c1);
1374: if (lastPage == null)
1375: throw T_Fail
1376: .testFailMsg("Couldn't get container's last page");
1377:
1378: t_util.t_checkFetch(lastPage, rh001, REC_001);
1379: t_util.t_checkFetchFirst(lastPage, REC_001);
1380: t_util.t_checkFetchLast(lastPage, REC_001);
1381:
1382: t_util.t_commit(t1);
1383: lastPage = null;
1384: c1 = null;
1385:
1386: // negative testing
1387: REPORT("try inserting 1 more record, but there should be no room on page for it.");
1388:
1389: c1 = t_util.t_openContainer(t1, 0, cid, true);
1390:
1391: lastPage = t_util.t_getLastPage(c1);
1392: if (lastPage == null)
1393: throw T_Fail
1394: .testFailMsg("Couldn't get container's last page");
1395:
1396: if (lastPage.getPageNumber() != ContainerHandle.FIRST_PAGE_NUMBER)
1397: throw T_Fail.testFailMsg("Initial page must be "
1398: + ContainerHandle.FIRST_PAGE_NUMBER + ", is "
1399: + lastPage.getPageNumber());
1400:
1401: row = new T_RawStoreRow(REC_002);
1402: if (lastPage.spaceForInsert()) {
1403: throw T_Fail
1404: .testFailMsg("Did not get no room for record on page error");
1405: }
1406:
1407: if (!lastPage.recordExists(rh001, false))
1408: throw T_Fail.testFailMsg("Record 001 has vanished");
1409:
1410: lastPage.unlatch();
1411: lastPage = null;
1412:
1413: t_util.t_commit(t1);
1414: c1 = null;
1415:
1416: t_util.t_dropContainer(t1, 0, cid); // cleanup
1417: t_util.t_commit(t1);
1418: //t1.close();
1419:
1420: //t1 = t_util.t_startTransaction();
1421:
1422: REPORT("create container with pageSize " + pageSize
1423: + ", spareSpace " + 0 + ", minimumRecordSize "
1424: + pageSize);
1425: REPORT("this should set minimumRecordSize to the default 100");
1426: cid = t_util
1427: .t_addContainer(t1, 0, pageSize, 0, pageSize, false);
1428:
1429: t_util.t_commit(t1);
1430:
1431: REPORT("see if the container can be opened again");
1432: c1 = t_util.t_openContainer(t1, 0, cid, false);
1433:
1434: c1.close();
1435: t_util.t_commit(t1);
1436:
1437: REPORT("insert a record into the container.");
1438:
1439: c1 = t_util.t_openContainer(t1, 0, cid, true);
1440:
1441: lastPage = t_util.t_getLastPage(c1);
1442: if (lastPage == null)
1443: throw T_Fail
1444: .testFailMsg("Couldn't get container's last page");
1445:
1446: if (lastPage.getPageNumber() != ContainerHandle.FIRST_PAGE_NUMBER)
1447: throw T_Fail.testFailMsg("Initial page must be "
1448: + ContainerHandle.FIRST_PAGE_NUMBER + ", is "
1449: + lastPage.getPageNumber());
1450:
1451: row = new T_RawStoreRow(REC_001);
1452: if (!lastPage.spaceForInsert())
1453: throw T_Fail.testFailMsg("No room for record on page");
1454:
1455: rh001 = t_util.t_insert(lastPage, row);
1456: if (rh001 == null)
1457: throw T_Fail.testFailMsg("Failed to insert record");
1458:
1459: // see if we can fetch that record
1460: t_util.t_checkFetch(lastPage, rh001, REC_001);
1461:
1462: lastPage.unlatch();
1463: lastPage = null;
1464:
1465: t_util.t_commit(t1);
1466: c1 = null;
1467:
1468: REPORT("read record just inserted.");
1469:
1470: c1 = t_util.t_openContainer(t1, 0, cid, false);
1471:
1472: lastPage = t_util.t_getLastPage(c1);
1473: if (lastPage == null)
1474: throw T_Fail
1475: .testFailMsg("Couldn't get container's last page");
1476:
1477: t_util.t_checkFetch(lastPage, rh001, REC_001);
1478: t_util.t_checkFetchFirst(lastPage, REC_001);
1479: t_util.t_checkFetchLast(lastPage, REC_001);
1480:
1481: t_util.t_commit(t1);
1482: lastPage = null;
1483: c1 = null;
1484:
1485: REPORT("insert 2 more records.");
1486:
1487: c1 = t_util.t_openContainer(t1, 0, cid, true);
1488:
1489: lastPage = t_util.t_getLastPage(c1);
1490: if (lastPage == null)
1491: throw T_Fail.testFailMsg("Could get container's last page");
1492:
1493: if (lastPage.getPageNumber() != ContainerHandle.FIRST_PAGE_NUMBER)
1494: throw T_Fail.testFailMsg("Initial page must be "
1495: + ContainerHandle.FIRST_PAGE_NUMBER + ", is "
1496: + lastPage.getPageNumber());
1497:
1498: row = new T_RawStoreRow(REC_002);
1499: if (!lastPage.spaceForInsert())
1500: throw T_Fail.testFailMsg("No room for record on page");
1501:
1502: if (!lastPage.recordExists(rh001, false))
1503: throw T_Fail.testFailMsg("Record 001 has vanished");
1504:
1505: rh002 = t_util.t_insertAtSlot(lastPage, 0, row);
1506: row = new T_RawStoreRow(REC_003);
1507: rh003 = t_util.t_insert(lastPage, row);
1508:
1509: lastPage.unlatch();
1510: lastPage = null;
1511:
1512: t_util.t_commit(t1);
1513: c1 = null;
1514:
1515: REPORT("checks on all 3 records.");
1516:
1517: c1 = t_util.t_openContainer(t1, 0, cid, false);
1518:
1519: lastPage = t_util.t_getLastPage(c1);
1520: if (lastPage == null)
1521: throw T_Fail.testFailMsg("Could get container's last page");
1522:
1523: // Order is 002, 001, 003
1524: t_util.t_checkFetch(lastPage, rh001, REC_001);
1525: t_util.t_checkFetch(lastPage, rh002, REC_002);
1526: t_util.t_checkFetch(lastPage, rh003, REC_003);
1527:
1528: t_util.t_checkFetch(lastPage, lastPage.getRecordHandle(rh001
1529: .getId()), REC_001);
1530: t_util.t_checkFetch(lastPage, lastPage.getRecordHandle(rh002
1531: .getId()), REC_002);
1532:
1533: lastPage.unlatch();
1534: lastPage = null;
1535:
1536: t_util.t_commit(t1);
1537:
1538: c1 = null;
1539:
1540: // clean ip
1541: t_util.t_dropContainer(t1, 0, cid);
1542: t_util.t_commit(t1);
1543: t1.close();
1544:
1545: PASS("C201 - " + whatPage);
1546:
1547: }
1548:
1549: /**
1550: Page tests
1551: */
1552: /**
1553: Create a container, ensure it has one page with no records. Then test
1554: all the things we can do with an empty page opened read-only in the container.
1555: Then add a new page, ensure it has the correct page number and is empty.
1556: @exception T_Fail Unexpected behaviour from the API
1557: @exception StandardException Unexpected exception from the implementation
1558: */
1559: protected void P001(long segment) throws T_Fail, StandardException {
1560:
1561: Transaction t = t_util.t_startTransaction();
1562:
1563: long cid = t_util.t_addContainer(t, segment);
1564:
1565: t_util.t_commit(t);
1566:
1567: // Get the first page & check the record counts are zero
1568: ContainerHandle c = t_util.t_openContainer(t, segment, cid,
1569: false);
1570: Page page = t_util.t_getPage(c,
1571: ContainerHandle.FIRST_PAGE_NUMBER);
1572:
1573: t_util.t_checkEmptyPage(page);
1574:
1575: if (Page.FIRST_SLOT_NUMBER != 0)
1576: throw T_Fail
1577: .testFailMsg("Page.FIRST_SLOT_NUMBER must be 0, is "
1578: + Page.FIRST_SLOT_NUMBER);
1579:
1580: page.unlatch();
1581: page = null;
1582:
1583: // get the last page and check it is the first page
1584: page = t_util.t_getLastPage(c);
1585:
1586: t_util.t_checkPageNumber(page,
1587: ContainerHandle.FIRST_PAGE_NUMBER);
1588:
1589: t_util.t_checkEmptyPage(page);
1590:
1591: t_util.t_commit(t);
1592:
1593: // t_util.t_addPage checks that the page is empty.
1594: c = t_util.t_openContainer(t, segment, cid, true);
1595: page = t_util.t_addPage(c);
1596:
1597: t_util.t_checkPageNumber(page,
1598: ContainerHandle.FIRST_PAGE_NUMBER + 1);
1599: page.unlatch();
1600:
1601: page = t_util.t_addPage(c);
1602: t_util.t_checkPageNumber(page,
1603: ContainerHandle.FIRST_PAGE_NUMBER + 2);
1604: page.unlatch();
1605:
1606: t_util.t_commit(t);
1607:
1608: c = t_util.t_openContainer(t, segment, cid, true);
1609: page = t_util.t_getPage(c, ContainerHandle.FIRST_PAGE_NUMBER);
1610: t_util.t_updateSlotOutOfRange(page, 0);
1611: t_util.t_updateSlotOutOfRange(page, -1);
1612: t_util.t_updateSlotOutOfRange(page, 1);
1613:
1614: t_util.t_dropContainer(t, segment, cid); // cleanup
1615: t_util.t_commit(t);
1616:
1617: // RESOLVE drop container
1618:
1619: t.close();
1620:
1621: PASS("P001");
1622: }
1623:
1624: /**
1625: Insert rows on the first page until the page is full, then add a page
1626: and repeat the test (for a total of three pages with full rows).
1627: Fetch the rows back by handle and slot methods.
1628:
1629: @exception T_Fail Unexpected behaviour from the API
1630: @exception StandardException Unexpected exception from the implementation
1631: */
1632: protected void P002(long segment) throws StandardException, T_Fail {
1633:
1634: Transaction t = t_util.t_startTransaction();
1635:
1636: long cid = t_util.t_addContainer(t, segment);
1637:
1638: ContainerHandle c = t_util.t_openContainer(t, segment, cid,
1639: true);
1640: Page page = t_util.t_getPage(c,
1641: ContainerHandle.FIRST_PAGE_NUMBER);
1642: t_util.t_checkEmptyPage(page);
1643:
1644: RecordHandle rh;
1645: T_RawStoreRow row;
1646: int recordCount[] = { 0, 0, 0 };
1647:
1648: for (int i = 0; i < 3;) {
1649: row = new T_RawStoreRow(REC_001 + i + "X" + recordCount[i]);
1650:
1651: boolean spaceThere = page.spaceForInsert();
1652:
1653: rh = t_util.t_insert(page, row);
1654:
1655: if (rh != null) {
1656: recordCount[i]++;
1657: if (!spaceThere)
1658: REPORT("record inserted after spaceForInsert() returned false, count is "
1659: + recordCount[i]);
1660: } else {
1661: if (spaceThere)
1662: REPORT("record insert failed after spaceForInsert() returned true, count is "
1663: + recordCount[i]);
1664: }
1665:
1666: t_util.t_checkRecordCount(page, recordCount[i],
1667: recordCount[i]);
1668:
1669: if (rh != null)
1670: continue;
1671:
1672: page.unlatch();
1673: page = null;
1674:
1675: if (++i < 3) {
1676: page = t_util.t_addPage(c);
1677: t_util.t_checkEmptyPage(page);
1678: }
1679: }
1680: t_util.t_commit(t);
1681:
1682: for (int i = 0; i < 3; i++) {
1683: REPORT("RecordCount on page " + i + "=" + recordCount[i]);
1684: }
1685:
1686: // now check that we read the same number of records back
1687: // using the handle interface
1688: c = t_util.t_openContainer(t, segment, cid, false);
1689:
1690: long pageNumber = ContainerHandle.FIRST_PAGE_NUMBER;
1691: for (int i = 0; i < 3; i++, pageNumber++) {
1692: page = t_util.t_getPage(c, pageNumber);
1693: t_util.t_checkRecordCount(page, recordCount[i],
1694: recordCount[i]);
1695: rh = t_util.t_checkFetchFirst(page, REC_001 + i + "X" + 0);
1696: for (int j = 1; j < recordCount[i]; j++)
1697: rh = t_util.t_checkFetchNext(page, rh, REC_001 + i
1698: + "X" + j);
1699:
1700: try {
1701: rh = page.fetchFromSlot(null,
1702: page.getSlotNumber(rh) + 1,
1703: new DataValueDescriptor[0],
1704: (FetchDescriptor) null, false);
1705:
1706: throw T_Fail
1707: .testFailMsg("reading more rows on page than were written");
1708: } catch (StandardException se) {
1709: // expected error.
1710: }
1711:
1712: rh = t_util.t_checkFetchLast(page, REC_001 + i + "X"
1713: + (recordCount[i] - 1));
1714: for (int j = recordCount[i] - 2; j >= 0; j--)
1715: rh = t_util.t_checkFetchPrevious(page, rh, REC_001 + i
1716: + "X" + j);
1717:
1718: page.unlatch();
1719: page = null;
1720: }
1721: t_util.t_commit(t);
1722:
1723: // now check that we read the same number of records back
1724: // using the slot interface
1725: c = t_util.t_openContainer(t, segment, cid, false);
1726:
1727: pageNumber = ContainerHandle.FIRST_PAGE_NUMBER;
1728: for (int i = 0; i < 3; i++, pageNumber++) {
1729: page = t_util.t_getPage(c, pageNumber);
1730:
1731: for (int j = 0; j < recordCount[i]; j++)
1732: t_util.t_checkFetchBySlot(page, j, REC_001 + i + "X"
1733: + j, false, false);
1734:
1735: t_util.t_readOnlySlotOutOfRange(page, recordCount[i]);
1736:
1737: page.unlatch();
1738: page = null;
1739: }
1740:
1741: t_util.t_dropContainer(t, segment, cid); // cleanup
1742:
1743: t_util.t_commit(t);
1744:
1745: t.close();
1746:
1747: PASS("P002");
1748: }
1749:
1750: /**
1751: Test Page.delete
1752:
1753: @exception T_Fail Unexpected behaviour from the API
1754: @exception StandardException Unexpected exception from the implementation
1755:
1756: @see Page#delete
1757: */
1758:
1759: protected void P003(long segment) throws StandardException, T_Fail {
1760:
1761: Transaction t = t_util.t_startTransaction();
1762:
1763: long cid = t_util.t_addContainer(t, segment);
1764:
1765: ContainerHandle c = t_util.t_openContainer(t, segment, cid,
1766: true);
1767: Page page = t_util.t_getPage(c,
1768: ContainerHandle.FIRST_PAGE_NUMBER);
1769:
1770: RecordHandle r1, r2;
1771:
1772: T_RawStoreRow row1 = new T_RawStoreRow(REC_001);
1773: T_RawStoreRow row2 = new T_RawStoreRow(REC_002);
1774:
1775: r1 = t_util.t_insertAtSlot(page, 0, row1);
1776: r2 = t_util.t_insertAtSlot(page, 1, row2);
1777:
1778: t_util.t_checkFetch(page, r1, REC_001);
1779: if (r2 != null)
1780: t_util.t_checkFetch(page, r2, REC_002);
1781:
1782: t_util.t_checkRecordCount(page, 2, r2 == null ? 1 : 2);
1783:
1784: // delete the first
1785: if (!page.delete(r1, (LogicalUndo) null))
1786: throw T_Fail.testFailMsg("delete() returned false");
1787:
1788: t_util.t_checkRecordCount(page, 2, r2 == null ? 0 : 1);
1789:
1790: if (page.delete(r1, (LogicalUndo) null))
1791: throw T_Fail
1792: .testFailMsg("delete() returned true on already deleted record");
1793:
1794: t_util.t_checkRecordCount(page, 2, r2 == null ? 0 : 1);
1795:
1796: if (page.recordExists(r1, false))
1797: throw T_Fail
1798: .testFailMsg("recordExists() returned true for deleted record");
1799:
1800: // check the other record is still there
1801: if (r2 != null)
1802: t_util.t_checkFetch(page, r2, REC_002);
1803:
1804: if (!page.isDeletedAtSlot(0))
1805: throw T_Fail
1806: .testFailMsg("isDeletedAtSlot() doesn't represent correct state");
1807:
1808: t_util.t_dropContainer(t, segment, cid); // cleanup
1809:
1810: t_util.t_commit(t);
1811: t.close();
1812:
1813: PASS("P003");
1814: }
1815:
1816: /**
1817: Test Page.update
1818:
1819: @exception T_Fail Unexpected behaviour from the API
1820: @exception StandardException Unexpected exception from the implementation
1821:
1822: @see Page#update
1823: */
1824: protected void P004(long segment) throws StandardException, T_Fail {
1825:
1826: Transaction t = t_util.t_startTransaction();
1827:
1828: long cid = t_util.t_addContainer(t, segment);
1829:
1830: ContainerHandle c = t_util.t_openContainer(t, segment, cid,
1831: true);
1832: Page page = t_util.t_getPage(c,
1833: ContainerHandle.FIRST_PAGE_NUMBER);
1834:
1835: RecordHandle r1, r2;
1836:
1837: T_RawStoreRow row1 = new T_RawStoreRow(REC_001);
1838: T_RawStoreRow row2 = new T_RawStoreRow(REC_002);
1839:
1840: r1 = t_util.t_insertAtSlot(page, 0, row1);
1841: r2 = t_util.t_insertAtSlot(page, 1, row2);
1842:
1843: t_util.t_checkFetch(page, r1, REC_001);
1844: if (r2 != null)
1845: t_util.t_checkFetch(page, r2, REC_002);
1846:
1847: row1 = new T_RawStoreRow((String) null);
1848: if (!page.update(r1, row1.getRow(), (FormatableBitSet) null))
1849: throw T_Fail.testFailMsg("update() returned false");
1850:
1851: t_util.t_checkFetch(page, r1, (String) null);
1852: if (r2 != null)
1853: t_util.t_checkFetch(page, r2, REC_002);
1854:
1855: t_util.t_checkFetch(page, r1, (String) null);
1856: if (r2 != null)
1857: t_util.t_checkFetch(page, r2, REC_002);
1858:
1859: row1 = new T_RawStoreRow(REC_003);
1860: if (!page.update(r1, row1.getRow(), (FormatableBitSet) null))
1861: throw T_Fail.testFailMsg("update() returned false");
1862:
1863: t_util.t_checkFetch(page, r1, REC_003);
1864: if (r2 != null)
1865: t_util.t_checkFetch(page, r2, REC_002);
1866:
1867: // now delete the record we have been updating
1868: if (!page.delete(r1, (LogicalUndo) null))
1869: throw T_Fail.testFailMsg("delete returned false");
1870:
1871: row1 = new T_RawStoreRow(REC_004);
1872: if (page.update(r1, row1.getRow(), (FormatableBitSet) null))
1873: throw T_Fail
1874: .testFailMsg("update returned true on deleted record");
1875:
1876: page.deleteAtSlot(0, false, (LogicalUndo) null);
1877:
1878: t_util.t_checkFetch(page, r1, REC_003);
1879:
1880: if (!page.update(r1, row1.getRow(), (FormatableBitSet) null))
1881: throw T_Fail.testFailMsg("update returned false");
1882:
1883: t_util.t_checkFetch(page, r1, REC_004);
1884:
1885: t_util.t_dropContainer(t, segment, cid); // cleanup
1886:
1887: t_util.t_commit(t);
1888: t.close();
1889:
1890: PASS("P004");
1891:
1892: }
1893:
1894: /* test repeated insert */
1895: protected void P005(long segment) throws StandardException, T_Fail {
1896: Transaction t = t_util.t_startTransaction();
1897:
1898: long cid = t_util.t_addContainer(t, segment);
1899:
1900: ContainerHandle c = t_util.t_openContainer(t, segment, cid,
1901: true);
1902: Page page1 = t_util.t_getLastPage(c);
1903:
1904: T_RawStoreRow row0 = new T_RawStoreRow(
1905: "long row xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx long row ");
1906: T_RawStoreRow row1 = new T_RawStoreRow(
1907: "medium row yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy medium row");
1908:
1909: t_util.t_insertAtSlot(page1, 0, row0);
1910:
1911: int i = 0;
1912: while (page1.spaceForInsert()) {
1913: if (t_util.t_insertAtSlot(page1, 1, row1) == null)
1914: break;
1915: i++;
1916: }
1917:
1918: int count1 = page1.recordCount();
1919:
1920: Page page2 = t_util.t_addPage(c);
1921: t_util.t_insertAtSlot(page2, 0, row0);
1922:
1923: i = 1;
1924: while (page2.spaceForInsert()) {
1925: if (t_util.t_insertAtSlot(page2, i++, row1) == null)
1926: break;
1927: }
1928:
1929: int count2 = page2.recordCount();
1930:
1931: // now purge them all and start over
1932: page1.purgeAtSlot(1, page1.recordCount() - 1, logDataForPurges);
1933: page2.purgeAtSlot(1, page2.recordCount() - 1, logDataForPurges);
1934: if (page1.recordCount() != 1)
1935: throw T_Fail.testFailMsg("purge did not clean up page");
1936:
1937: if (page2.recordCount() != 1)
1938: throw T_Fail.testFailMsg("purge did not clean up page");
1939:
1940: i = 0;
1941: while (page1.spaceForInsert()) {
1942: if (t_util.t_insertAtSlot(page1, 1, row1) == null)
1943: return;
1944: i++;
1945: }
1946:
1947: if (page1.recordCount() != count1)
1948: throw T_Fail
1949: .testFailMsg("cannot insert back same number of rows we purged");
1950:
1951: i = 1;
1952: while (page2.spaceForInsert()) {
1953: if (t_util.t_insertAtSlot(page2, i++, row1) == null)
1954: break;
1955: }
1956:
1957: if (page2.recordCount() != count2)
1958: throw T_Fail
1959: .testFailMsg("cannot insert back same number of rows we purged");
1960:
1961: page1.unlatch();
1962: page2.unlatch();
1963:
1964: t_util.t_dropContainer(t, segment, cid); // cleanup
1965:
1966: t_util.t_commit(t);
1967: t.close();
1968:
1969: PASS("P005");
1970: }
1971:
1972: /*
1973: P006
1974:
1975: test page time stamp - make sure all operation changes page time stamp
1976: */
1977: protected void P006() throws StandardException, T_Fail {
1978: Transaction t = t_util.t_startTransaction();
1979: PageTimeStamp ts;
1980:
1981: long cid = t_util.t_addContainer(t, 0);
1982: t_util.t_commit(t);
1983:
1984: ContainerHandle c = t_util.t_openContainer(t, 0, cid, true);
1985: Page page1 = t_util.t_getLastPage(c);
1986:
1987: ts = page1.currentTimeStamp();
1988: if (ts != null && !page1.equalTimeStamp(ts))
1989: throw T_Fail
1990: .testFailMsg("page returns non-null time stamp which is not equal to its current time stamp");
1991:
1992: T_RawStoreRow row = new T_RawStoreRow(REC_001);
1993: RecordHandle rh = t_util.t_insert(page1, row);
1994:
1995: if (page1.equalTimeStamp(ts))
1996: throw T_Fail
1997: .testFailMsg("timestamp on page not changed after insert operation");
1998: page1.setTimeStamp(ts);
1999: if (ts != null && !page1.equalTimeStamp(ts))
2000: throw T_Fail
2001: .testFailMsg("page returns non-null time stamp which is not equal to its current time stamp");
2002:
2003: // failed update should not change time stamp
2004: t_util.t_updateSlotOutOfRange(page1, 3);
2005: if (ts != null && !page1.equalTimeStamp(ts))
2006: throw T_Fail
2007: .testFailMsg("failed pdate should not change time stamp");
2008:
2009: T_RawStoreRow row2 = new T_RawStoreRow(REC_002);
2010: page1.update(rh, row2.getRow(), (FormatableBitSet) null);
2011: if (page1.equalTimeStamp(ts))
2012: throw T_Fail
2013: .testFailMsg("timestamp on page not changed after update operation");
2014:
2015: page1.setTimeStamp(ts);
2016:
2017: T_RawStoreRow upd1 = new T_RawStoreRow(REC_003);
2018: page1.update(rh, upd1.getRow(), BS_COL_0);
2019: if (page1.equalTimeStamp(ts))
2020: throw T_Fail
2021: .testFailMsg("timestamp on page not changed after update field operation");
2022:
2023: page1.setTimeStamp(ts);
2024:
2025: page1.delete(rh, (LogicalUndo) null);
2026: if (page1.equalTimeStamp(ts))
2027: throw T_Fail
2028: .testFailMsg("timestamp on page not changed after delete operation");
2029:
2030: page1.setTimeStamp(ts);
2031:
2032: page1.purgeAtSlot(0, 1, logDataForPurges);
2033: if (page1.equalTimeStamp(ts))
2034: throw T_Fail
2035: .testFailMsg("timestamp on page not changed after delete operation");
2036:
2037: page1.setTimeStamp(ts);
2038: page1.unlatch();
2039:
2040: if (testRollback) {
2041: t_util.t_abort(t);
2042: c = t_util.t_openContainer(t, 0, cid, true);
2043: page1 = t_util.t_getLastPage(c);
2044:
2045: if (page1.equalTimeStamp(ts))
2046: throw T_Fail
2047: .testFailMsg("timestamp on page not changed after rollback");
2048:
2049: page1.setTimeStamp(ts);
2050: }
2051:
2052: Page page2 = c.addPage();
2053: Page page3 = c.addPage();
2054:
2055: page2.setTimeStamp(ts);
2056:
2057: if (ts != null) {
2058: try {
2059: if (page3.equalTimeStamp(ts))
2060: throw T_Fail
2061: .testFailMsg("timestamp on 2 different pages should not equate");
2062: } catch (StandardException se) {
2063: // either throw an exception or return false is OK
2064: }
2065: }
2066:
2067: t_util.t_dropContainer(t, 0, cid); // cleanup
2068: t_util.t_commit(t);
2069: t.close();
2070:
2071: PASS("P006");
2072:
2073: }
2074:
2075: /**
2076: P007
2077:
2078: this test exercises repeated updates on a 1K page
2079:
2080: 2 rows (with 1 column) will be inserted into the page.
2081: We expand the row data in slot 0 by 1 byte until the page is completely full,
2082: and overflows the record to an overflow page.
2083:
2084: @exception T_Fail Unexpected behaviour from the API
2085: @exception StandardException Unexpected exception from the implementation
2086: */
2087:
2088: protected void P007(long segment) throws StandardException, T_Fail {
2089:
2090: Transaction t = t_util.t_startTransaction();
2091:
2092: // PART 1:
2093: // insert two 1-column rows into the page, expand the first row, until it overflows.
2094: long cid = t_util.t_addContainer(t, segment, 4096, 0, 1, false);
2095:
2096: ContainerHandle c = t_util.t_openContainer(t, segment, cid,
2097: true);
2098: Page page = t_util.t_getLastPage(c);
2099:
2100: T_RawStoreRow row = new T_RawStoreRow(REC_001); // McLaren
2101: T_RawStoreRow row2 = new T_RawStoreRow(
2102: new String(new char[300]));
2103:
2104: RecordHandle r1 = t_util.t_insertAtSlot(page, 0, row);
2105: RecordHandle r2 = t_util.t_insertAtSlot(page, 1, row2);
2106:
2107: // update the row size 1 byte larger, until the page is full
2108: String rowData = REC_001;
2109: // 900 is an estimated number, because for 1K page,
2110: // if you expand your row by 1 byte 900 times, the row will overflow for sure.
2111: for (int i = 0; i <= 900; i++) {
2112: t_util.t_checkFetch(page, r1, rowData);
2113:
2114: rowData = rowData + REC_008; // "z"
2115: row = new T_RawStoreRow(rowData);
2116: page.updateAtSlot(0, row.getRow(), (FormatableBitSet) null);
2117: }
2118:
2119: t_util.t_dropContainer(t, segment, cid); // cleanup
2120:
2121: // PART 2:
2122: // insert two 2-column rows into the page,
2123: // expand the first row by expanding the first column by 300 bytes,
2124: // and shrinking the second column by 300 bytes. Update should secceed.
2125: cid = t_util.t_addContainer(t, segment, 4096, 0, 1, false);
2126: c = t_util.t_openContainer(t, segment, cid, true);
2127: page = t_util.t_getLastPage(c);
2128: long pid = page.getPageNumber();
2129:
2130: row = new T_RawStoreRow(2);
2131: row.setColumn(0, REC_001); // small column
2132: row.setColumn(1, new String(new char[400])); // large column
2133:
2134: r1 = t_util.t_insertAtSlot(page, 0, row);
2135: r2 = t_util.t_insertAtSlot(page, 1, row2);
2136:
2137: row.setColumn(0, REC_001 + new String(new char[300]));
2138: row.setColumn(1, new String(new char[100]));
2139:
2140: page.updateAtSlot(0, row.getRow(), (FormatableBitSet) null);
2141:
2142: Page page2 = t_util.t_addPage(c);
2143: long pid2 = page2.getPageNumber();
2144: if (pid2 != (pid + 1))
2145: throw T_Fail
2146: .testFailMsg("The update should not have overflowed the record");
2147:
2148: // Now, shrink the first column by 300 bytes, and expand the second column by 300 bytes.
2149: // the update should also succeed.
2150: row.setColumn(0, REC_001);
2151: row.setColumn(1, new String(new char[400]));
2152:
2153: page.updateAtSlot(0, row.getRow(), (FormatableBitSet) null);
2154:
2155: Page page3 = t_util.t_addPage(c);
2156: long pid3 = page3.getPageNumber();
2157: if (pid3 != (pid2 + 1))
2158: throw T_Fail
2159: .testFailMsg("The update should not have overflowed the record");
2160:
2161: t_util.t_dropContainer(t, segment, cid); // cleanup
2162:
2163: t_util.t_commit(t);
2164: t.close();
2165:
2166: PASS("P007");
2167:
2168: }
2169:
2170: /**
2171: P008
2172:
2173: this test exercises repeated inserts with small rows on a 1K page
2174:
2175: we will insert as many rows as possible into the page. Then we reduce the row by 1 byte at a time,
2176: we will try to insert another smaller row.
2177: This test also tests spaceForInsert().
2178:
2179: @exception T_Fail Unexpected behaviour from the API
2180: @exception StandardException Unexpected exception from the implementation
2181: */
2182:
2183: protected void P008(long segment) throws StandardException, T_Fail {
2184: Transaction t = t_util.t_startTransaction();
2185:
2186: long cid = t_util.t_addContainer(t, segment, 4096, 0, 1, false);
2187:
2188: ContainerHandle c = t_util.t_openContainer(t, segment, cid,
2189: true);
2190: Page page1 = t_util.t_getLastPage(c);
2191:
2192: T_RawStoreRow row = new T_RawStoreRow(REC_001); // McLaren
2193:
2194: t_util.t_insertAtSlot(page1, 0, row);
2195:
2196: int i = 0;
2197: while (page1.spaceForInsert(row.getRow(),
2198: (FormatableBitSet) null, 100)) {
2199: // if it says there is enough room for this row, the insert should succeed.
2200: if (t_util.t_insertAtSlot(page1, 1, row) == null)
2201: throw T_Fail
2202: .testFailMsg("There is space for this insert. It shouldn't have failed. "
2203: + "record #" + i);
2204: i++;
2205: }
2206:
2207: REPORT(i + " rows inserted.");
2208:
2209: // We got out of the while loop because there is no room for the insert.
2210: // So, if the insert succeed, then we have a problem.
2211: if (t_util.t_insertAtSlot(page1, 1, row) != null)
2212: throw T_Fail
2213: .testFailMsg("There is no space for this insert. It should have failed.");
2214:
2215: // Now, we will try to fill the page with smaller rows.
2216: String[] s = new String[7];
2217: s[6] = "McLare";
2218: s[5] = "McLar";
2219: s[4] = "McLa";
2220: s[3] = "McL";
2221: s[2] = "Mc";
2222: s[1] = "M";
2223: s[0] = null;
2224: // reduce the row by 1 byte
2225: i = 6;
2226: boolean notDone = true;
2227: do {
2228: row = new T_RawStoreRow(s[i]);
2229: if (page1.spaceForInsert(row.getRow(),
2230: (FormatableBitSet) null, 100)) {
2231: // If it says there is enough room for the row, then the insert should succed.
2232: if (t_util.t_insertAtSlot(page1, 1, row) == null)
2233: throw T_Fail
2234: .testFailMsg("There should be space for this insert, row is "
2235: + s[i]);
2236: else
2237: notDone = false;
2238: } else
2239: i--;
2240: } while ((notDone) && (i >= 0));
2241:
2242: page1.unlatch();
2243:
2244: t_util.t_dropContainer(t, segment, cid); // cleanup
2245:
2246: t_util.t_commit(t);
2247: t.close();
2248:
2249: PASS("P008");
2250: }
2251:
2252: /**
2253: P009
2254:
2255: this test exercises repeated shrinking and expanding of fields using updateFieldBySlot
2256:
2257: we will insert as many rows as possible into the page. Then set some of the columns to null,
2258: That should not create more space on the page for inserts, because the extra space become
2259: reservedspace for the row. So, the next insert should fail.
2260:
2261: @exception T_Fail Unexpected behaviour from the API
2262: @exception StandardException Unexpected exception from the implementation
2263: */
2264:
2265: protected void P009(long segment) throws StandardException, T_Fail {
2266: int slot = 0;
2267: int i = 0;
2268: int j = 0;
2269: String field = REC_001;
2270:
2271: Transaction t = t_util.t_startTransaction();
2272:
2273: long cid = t_util.t_addContainer(t, segment);
2274:
2275: // Get the first page & check the record counts are zero
2276: ContainerHandle c = t_util.t_openContainer(t, segment, cid,
2277: true);
2278: Page page = t_util.t_getPage(c,
2279: ContainerHandle.FIRST_PAGE_NUMBER);
2280:
2281: t_util.t_checkEmptyPage(page);
2282:
2283: // Create a 13-column row
2284: T_RawStoreRow row = new T_RawStoreRow(13);
2285: row.setColumn(0, (String) null);
2286: row.setColumn(1, REC_001);
2287: row.setColumn(2, REC_002);
2288: row.setColumn(3, REC_003);
2289: row.setColumn(4, REC_004);
2290: row.setColumn(5, REC_005);
2291: row.setColumn(6, REC_006);
2292: row.setColumn(7, REC_007);
2293: row.setColumn(8, (String) null);
2294: row.setColumn(9, (String) null);
2295: row.setColumn(10, REC_007);
2296: row.setColumn(11, (String) null);
2297: row.setColumn(12, REC_006);
2298:
2299: // insert the row into the page until the page is full
2300: int numRows = 0;
2301: slot = page.FIRST_SLOT_NUMBER;
2302: while (page.spaceForInsert(row.getRow(),
2303: (FormatableBitSet) null, 100)) {
2304: t_util.t_insert(page, row);
2305: numRows++;
2306: }
2307: REPORT(numRows + " rows inserted ");
2308:
2309: // update all the fields in the even number rows to null
2310: // set all the fields in the odd number rows to REC_001
2311: DataValueDescriptor col = new SQLChar(); // null
2312: for (i = page.FIRST_SLOT_NUMBER; i < (page.FIRST_SLOT_NUMBER + 2); i++) {
2313:
2314: for (slot = i; slot <= (numRows - 1); slot += 2) {
2315:
2316: for (j = 0; j <= 12; j++) {
2317: if (page.updateFieldAtSlot(slot, j, col, null) == null) {
2318:
2319: throw T_Fail
2320: .testFailMsg("Failed to update field "
2321: + j + ", in row " + slot);
2322: }
2323: }
2324: }
2325:
2326: col = new SQLChar(REC_001);
2327: }
2328:
2329: // fetch all the fields, and see if they are correct
2330: DataValueDescriptor storedColumn = new SQLChar();
2331: field = null;
2332: for (i = page.FIRST_SLOT_NUMBER; i < (page.FIRST_SLOT_NUMBER + 2); i++) {
2333:
2334: for (slot = i; slot <= (numRows - 1); slot += 2) {
2335:
2336: for (j = 0; j <= 12; j++) {
2337:
2338: t_util.t_checkFetchColFromSlot(page, slot, j,
2339: storedColumn, false, field);
2340:
2341: }
2342: }
2343:
2344: field = REC_001;
2345: }
2346:
2347: // Now if we try to insert the old row again, there should still be no room
2348: if (page.spaceForInsert())
2349: throw T_Fail
2350: .testFailMsg("Did not get no room for record on page error");
2351:
2352: // update the first and last field of every row to REC_006
2353: col = new SQLChar(REC_006);
2354: for (slot = page.FIRST_SLOT_NUMBER; slot <= (numRows - 1); slot++) {
2355: if (page.updateFieldAtSlot(slot, 0, col, null) == null
2356: || page.updateFieldAtSlot(slot, 12, col, null) == null) {
2357:
2358: throw T_Fail
2359: .testFailMsg("Failed to update fields to REC_006 in row "
2360: + slot);
2361: }
2362: }
2363:
2364: // update field 5 and 6 of every row to REC_007
2365: col = new SQLChar(REC_007);
2366: for (slot = page.FIRST_SLOT_NUMBER; slot <= (numRows - 1); slot++) {
2367: if (page.updateFieldAtSlot(slot, 5, col, null) == null
2368: || page.updateFieldAtSlot(slot, 6, col, null) == null) {
2369:
2370: throw T_Fail
2371: .testFailMsg("Failed to update fields to REC_007 in row "
2372: + slot);
2373: }
2374: }
2375:
2376: // fetch all the fields again, and see if they are correct
2377: for (i = page.FIRST_SLOT_NUMBER; i < (page.FIRST_SLOT_NUMBER + 2); i++) {
2378:
2379: for (slot = i; slot <= (numRows - 1); slot += 2) {
2380:
2381: for (j = 0; j <= 12; j++) {
2382:
2383: switch (j) {
2384: case 0:
2385: case 12:
2386: field = REC_006;
2387: break;
2388: case 5:
2389: case 6:
2390: field = REC_007;
2391: break;
2392: default:
2393: if ((slot % 2) == 0)
2394: field = null;
2395: else
2396: field = REC_001;
2397: break;
2398: }
2399:
2400: t_util.t_checkFetchColFromSlot(page, slot, j,
2401: storedColumn, false, field);
2402:
2403: }
2404: }
2405: }
2406:
2407: // We now try to insert the old row one last time, there should still be no room
2408: if (page.spaceForInsert())
2409: throw T_Fail
2410: .testFailMsg("Did not get no room for record on page error");
2411:
2412: // now we want to increase row 0 and column 5 one byte at a time, until the page is full
2413: // but, every 5 increases we will reduce the field size by one byte
2414: field = REC_007;
2415: i = 0;
2416: String field_pre = null;
2417: while (true) {
2418: if ((i % 5) != 0) {
2419: field_pre = field;
2420: field += REC_008;
2421: } else {
2422: field = field_pre;
2423: }
2424:
2425: if (((i % 10) == 3) || ((i % 10) == 7)) {
2426: page.unlatch();
2427: page = null;
2428:
2429: factory.idle();
2430:
2431: page = t_util.t_getPage(c,
2432: ContainerHandle.FIRST_PAGE_NUMBER);
2433: }
2434:
2435: col = new SQLChar(field);
2436:
2437: try {
2438: page.updateFieldAtSlot(0, 5, col, null);
2439: } catch (StandardException se) {
2440: // now we have filled the page
2441: if (i < 809) {
2442: throw T_Fail
2443: .testFailMsg("should be able to update Row 0 Column 5 809 times"
2444: + ", but only updated "
2445: + i
2446: + " times. Note: you maybe getting this error if your page format has changed.");
2447: } else {
2448: REPORT("Row 0 Column 5 was updated " + i
2449: + " times.");
2450: }
2451: break;
2452: }
2453: i++;
2454: }
2455:
2456: // The page is completely full at this point.
2457: // update Row 1 Column 1 from REC_001 to REC_002. They are the same length
2458: page.unlatch();
2459: page = null;
2460: factory.idle();
2461: page = t_util.t_getPage(c, ContainerHandle.FIRST_PAGE_NUMBER);
2462: col = new SQLChar(REC_002);
2463: if (page.updateFieldAtSlot(1, 1, col, null) == null) {
2464: throw T_Fail
2465: .testFailMsg("update Row 1 and Column 1 to same length data failed.");
2466: }
2467:
2468: REPORT("updated col1 in row 1 to same length");
2469:
2470: // now expand update Row 1 Column 1 by one byte. This should fail.
2471: page.unlatch();
2472: page = null;
2473: factory.idle();
2474: page = t_util.t_getPage(c, ContainerHandle.FIRST_PAGE_NUMBER);
2475: field = REC_002 + REC_008;
2476: col = new SQLChar(field);
2477: try {
2478: page.updateFieldAtSlot(1, 1, col, null);
2479: throw T_Fail
2480: .testFailMsg("update Row 1 and Column 1 to longer length should have failed.");
2481: } catch (StandardException se) {
2482: ;
2483: }
2484:
2485: // clean up
2486: if (segment != ContainerHandle.TEMPORARY_SEGMENT) {
2487: t_util.t_dropContainer(t, segment, cid); // cleanup
2488: }
2489:
2490: t_util.t_commit(t);
2491: t.close();
2492:
2493: PASS("P009: segment " + segment);
2494:
2495: }
2496:
2497: /**
2498: P011
2499:
2500: this test exercises insertAtSlot, (LogicalUndo)null
2501:
2502: @exception T_Fail Unexpected behaviour from the API
2503: @exception StandardException Unexpected exception from the implementation
2504: */
2505: protected void P011(long segment) throws StandardException, T_Fail {
2506: Transaction t = t_util.t_startTransaction();
2507: long cid = t_util.t_addContainer(t, segment);
2508: t_util.t_commit(t);
2509:
2510: // Get the first page
2511: ContainerHandle c = t_util.t_openContainer(t, segment, cid,
2512: true);
2513: Page page = t_util.t_getPage(c,
2514: ContainerHandle.FIRST_PAGE_NUMBER);
2515:
2516: // REPORT("insert 2 records at FIRST_SLOT_NUMBER");
2517: T_RawStoreRow row1 = new T_RawStoreRow(REC_001);
2518: T_RawStoreRow row2 = new T_RawStoreRow(REC_002);
2519: T_RawStoreRow row3 = new T_RawStoreRow(REC_003);
2520: T_RawStoreRow row4 = new T_RawStoreRow(REC_004);
2521:
2522: // try inserting at slot -1 and slot 1
2523: try {
2524: RecordHandle r = t_util.t_insertAtSlot(page, -1, row1);
2525: throw T_Fail.testFailMsg("insert at slot -1 succeeded");
2526: } catch (StandardException se) {
2527: // throw if not a statement exception.
2528: if (se.getSeverity() > ExceptionSeverity.STATEMENT_SEVERITY)
2529: throw se;
2530: }
2531:
2532: try {
2533: RecordHandle r = t_util.t_insertAtSlot(page, 1, row1);
2534: throw T_Fail.testFailMsg("insert at slot 1 succeeded");
2535: } catch (StandardException se) {
2536: // throw if not a statement exception.
2537: if (se.getSeverity() > ExceptionSeverity.STATEMENT_SEVERITY)
2538: throw se;
2539: }
2540:
2541: RecordHandle r1, r2, r3, r4;
2542: // first insert to a page must suceed
2543: r3 = t_util.t_insertAtSlot(page, Page.FIRST_SLOT_NUMBER, row3);
2544: t_util.t_checkFetch(page, r3, REC_003);
2545: t_util.t_checkFetchBySlot(page, Page.FIRST_SLOT_NUMBER,
2546: REC_003, false, false);
2547:
2548: r1 = r2 = r4 = null;
2549: r1 = t_util.t_insertAtSlot(page, Page.FIRST_SLOT_NUMBER, row1);
2550:
2551: if (r1 != null) {
2552: t_util.t_checkFetch(page, r1, REC_001);
2553: t_util.t_checkFetchBySlot(page, Page.FIRST_SLOT_NUMBER,
2554: REC_001, false, false);
2555: } else {
2556: t_util.t_abort(t);
2557: t.close();
2558: REPORT("P011 not run - could not fit 4 rows on page");
2559: return;
2560: }
2561:
2562: // REPORT("insert a record at 2nd slot");
2563: r2 = t_util.t_insertAtSlot(page, Page.FIRST_SLOT_NUMBER + 1,
2564: row2);
2565:
2566: if (r2 != null) {
2567: t_util.t_checkFetch(page, r2, REC_002);
2568: t_util.t_checkFetchBySlot(page, Page.FIRST_SLOT_NUMBER + 1,
2569: REC_002, false, false);
2570: } else {
2571: t_util.t_abort(t);
2572: t.close();
2573: REPORT("P011 not completed - could not fit 4 rows on page");
2574: return;
2575: }
2576:
2577: // REPORT("insert a record at the end");
2578: r4 = t_util.t_insertAtSlot(page, 3, row4);
2579: if (r4 != null) {
2580: t_util.t_checkFetch(page, r4, REC_004);
2581: t_util.t_checkFetchBySlot(page, 3, REC_004, false, false);
2582: } else {
2583: t_util.t_abort(t);
2584: t.close();
2585: REPORT("P011 not completed - could not fit 4 rows on page");
2586: return;
2587: }
2588:
2589: // REPORT("make sure records are in the correct order");
2590: // order is REC_001 REC_002 REC_003 REC_004
2591:
2592: t_util.t_checkFetchFirst(page, REC_001);
2593: t_util.t_checkFetchNext(page, r1, REC_002);
2594: t_util.t_checkFetchNext(page, r2, REC_003);
2595: t_util.t_checkFetchNext(page, r3, REC_004);
2596: t_util.t_checkFetchLast(page, REC_004);
2597:
2598: // check the fetch by slot interface
2599: t_util.t_checkFetchBySlot(page, Page.FIRST_SLOT_NUMBER,
2600: REC_001, false, true);
2601: t_util.t_checkFetchBySlot(page, Page.FIRST_SLOT_NUMBER + 1,
2602: REC_002, false, false);
2603: t_util.t_checkFetchBySlot(page, Page.FIRST_SLOT_NUMBER + 2,
2604: REC_003, false, true);
2605: t_util.t_checkFetchBySlot(page, Page.FIRST_SLOT_NUMBER + 3,
2606: REC_004, false, false);
2607:
2608: // clean up
2609:
2610: t_util.t_dropContainer(t, segment, cid); // cleanup
2611:
2612: t_util.t_commit(t);
2613: t.close();
2614:
2615: PASS("P011");
2616:
2617: }
2618:
2619: /**
2620: P012
2621:
2622: this test exercises updateAtSlot
2623:
2624: @exception T_Fail Unexpected behaviour from the API
2625: @exception StandardException Unexpected exception from the implementation
2626: */
2627: protected void P012(long segment) throws StandardException, T_Fail {
2628: Transaction t = t_util.t_startTransaction();
2629: long cid = t_util.t_addContainer(t, segment);
2630:
2631: ContainerHandle c = t_util.t_openContainer(t, segment, cid,
2632: true);
2633: Page page = t_util.t_getPage(c,
2634: ContainerHandle.FIRST_PAGE_NUMBER);
2635:
2636: // REPORT("insert 3 records");
2637: T_RawStoreRow row1 = new T_RawStoreRow(REC_001);
2638:
2639: T_RawStoreRow row2 = new T_RawStoreRow(2);
2640: row2.setColumn(0, (String) null);
2641: row2.setColumn(1, REC_001);
2642:
2643: T_RawStoreRow row3 = new T_RawStoreRow(3);
2644: row3.setColumn(0, REC_001);
2645: row3.setColumn(1, REC_002);
2646: row3.setColumn(2, REC_003);
2647:
2648: RecordHandle r1, r2, r3;
2649: r1 = t_util.t_insertAtSlot(page, 0, row1);
2650:
2651: r2 = r3 = null;
2652: r2 = t_util.t_insertAtSlot(page, 1, row2);
2653:
2654: if (r2 == null) {
2655: REPORT("P012 not completed - cannot insert second row");
2656: return;
2657: }
2658:
2659: r3 = t_util.t_insertAtSlot(page, 2, row3);
2660: if (r3 == null) {
2661: REPORT("P012 not completed - cannot insert third row");
2662: return;
2663: }
2664:
2665: // check that they are inserted correctly
2666: t_util.t_checkFetch(page, r1, row1);
2667: t_util.t_checkFetch(page, r2, row2);
2668: t_util.t_checkFetch(page, r3, row3);
2669:
2670: // REPORT("update that grows the #columns in row");
2671: T_RawStoreRow upd1 = new T_RawStoreRow(2);
2672: upd1.setColumn(0, (String) null);
2673: upd1.setColumn(1, REC_001);
2674:
2675: r1 = page.updateAtSlot(0, upd1.getRow(),
2676: (FormatableBitSet) null);
2677: t_util.t_checkFetch(page, r1, upd1);
2678: t_util.t_checkFetch(page, r2, row2);
2679: t_util.t_checkFetch(page, r3, row3);
2680:
2681: // REPORT("update that shrinks the #columns in row");
2682: T_RawStoreRow upd2 = new T_RawStoreRow(REC_004);
2683:
2684: r2 = page.updateAtSlot(1, upd2.getRow(),
2685: (FormatableBitSet) null);
2686: t_util.t_checkFetch(page, r1, upd1);
2687: t_util.t_checkFetch(page, r2, upd2);
2688: t_util.t_checkFetch(page, r3, row3);
2689:
2690: // REPORT("update same #columns in row");
2691: T_RawStoreRow upd3 = new T_RawStoreRow(3);
2692: upd3.setColumn(0, REC_003);
2693: upd3.setColumn(1, REC_002);
2694: upd3.setColumn(2, REC_001);
2695:
2696: r3 = page.updateAtSlot(2, upd3.getRow(),
2697: (FormatableBitSet) null);
2698: t_util.t_checkFetch(page, r1, upd1);
2699: t_util.t_checkFetch(page, r2, upd2);
2700: t_util.t_checkFetch(page, r3, upd3);
2701:
2702: // clean up
2703:
2704: if (segment != ContainerHandle.TEMPORARY_SEGMENT) {
2705: t_util.t_dropContainer(t, segment, cid); // cleanup
2706: }
2707:
2708: t_util.t_commit(t);
2709: t.close();
2710:
2711: PASS("P012");
2712: }
2713:
2714: /**
2715: P013
2716:
2717: this test exercises deleteAtSlot and isDeletedAtSlot
2718: @exception T_Fail Unexpected behaviour from the API
2719: @exception StandardException Unexpected exception from the implementation
2720: */
2721: protected void P013() throws StandardException, T_Fail {
2722: Transaction t = t_util.t_startTransaction();
2723: long cid = t_util.t_addContainer(t, 0);
2724:
2725: t_util.t_commit(t);
2726:
2727: ContainerHandle c = t_util.t_openContainer(t, 0, cid, true);
2728: Page page = t_util.t_getPage(c,
2729: ContainerHandle.FIRST_PAGE_NUMBER);
2730:
2731: // REPORT("insert 2 records");
2732: T_RawStoreRow row1 = new T_RawStoreRow(REC_001);
2733: T_RawStoreRow row2 = new T_RawStoreRow(REC_002);
2734:
2735: RecordHandle r1 = t_util.t_insertAtSlot(page, 0, row1);
2736: RecordHandle r2;
2737: r2 = t_util.t_insertAtSlot(page, 1, row2);
2738: if (r2 == null) {
2739: REPORT("P013 not completed - could not fit two rows on a page");
2740: return;
2741: }
2742:
2743: t_util.t_checkRecordCount(page, 2, 2);
2744:
2745: // REPORT("delete them one by one");
2746: page.deleteAtSlot(0, true, (LogicalUndo) null);
2747:
2748: t_util.t_checkRecordCount(page, 2, 1);
2749:
2750: if (!page.isDeletedAtSlot(0))
2751: throw T_Fail.testFailMsg("Failed to delete record 0");
2752: if (page.isDeletedAtSlot(1))
2753: throw T_Fail.testFailMsg("Record mistakenly deleted");
2754:
2755: page.deleteAtSlot(1, true, (LogicalUndo) null);
2756: t_util.t_checkRecordCount(page, 2, 0);
2757: if (!page.isDeletedAtSlot(1))
2758: throw T_Fail.testFailMsg("Failed to delete record 1");
2759:
2760: page.deleteAtSlot(0, false, (LogicalUndo) null);
2761: t_util.t_checkRecordCount(page, 2, 1);
2762: if (page.isDeletedAtSlot(0))
2763: throw T_Fail.testFailMsg("Failed to undelete record 0");
2764: if (!page.isDeletedAtSlot(1))
2765: throw T_Fail.testFailMsg("Record mistakenly undeleted");
2766:
2767: page.deleteAtSlot(1, false, (LogicalUndo) null);
2768: t_util.t_checkRecordCount(page, 2, 2);
2769: if (page.isDeletedAtSlot(1))
2770: throw T_Fail.testFailMsg("Failed to undelete record 1");
2771:
2772: // try the negative tests
2773: try {
2774: page.deleteAtSlot(0, false, (LogicalUndo) null);
2775: throw T_Fail
2776: .testFailMsg("undeleted on undeleted record succeeded");
2777: } catch (StandardException se) {
2778: // throw if not a statement exception.
2779: if (se.getSeverity() > ExceptionSeverity.STATEMENT_SEVERITY)
2780: throw se;
2781: }
2782:
2783: page.deleteAtSlot(0, true, (LogicalUndo) null);
2784: try {
2785: page.deleteAtSlot(0, true, (LogicalUndo) null);
2786: throw T_Fail
2787: .testFailMsg("deleted on deleted record succeeded");
2788: } catch (StandardException se) {
2789: // throw if not a statement exception.
2790: if (se.getSeverity() > ExceptionSeverity.STATEMENT_SEVERITY)
2791: throw se;
2792: }
2793:
2794: t_util.t_checkRecordCount(page, 2, 1);
2795: // clean up
2796: PASS("P013");
2797:
2798: t_util.t_dropContainer(t, 0, cid); // cleanup
2799:
2800: t_util.t_commit(t);
2801: t.close();
2802:
2803: }
2804:
2805: /**
2806: P014
2807:
2808: this test exercises purgeAtSlot
2809: @exception T_Fail Unexpected behaviour from the API
2810: @exception StandardException Unexpected exception from the implementation
2811: */
2812: protected void P014() throws StandardException, T_Fail {
2813: Transaction t = t_util.t_startTransaction();
2814: long cid = t_util.t_addContainer(t, 0);
2815: t_util.t_commit(t);
2816:
2817: ContainerHandle c = t_util.t_openContainer(t, 0, cid, true);
2818: Page page = t_util.t_getPage(c,
2819: ContainerHandle.FIRST_PAGE_NUMBER);
2820:
2821: // REPORT("insert 5 records");
2822: T_RawStoreRow row0 = new T_RawStoreRow(REC_001);
2823: T_RawStoreRow row1 = new T_RawStoreRow(REC_001);
2824: T_RawStoreRow row2 = new T_RawStoreRow(REC_002);
2825: T_RawStoreRow row3 = new T_RawStoreRow(REC_003);
2826: T_RawStoreRow row4 = new T_RawStoreRow(REC_004);
2827:
2828: RecordHandle r0, r1, r2, r3, r4;
2829: r0 = t_util.t_insertAtSlot(page, 0, row0);
2830: r1 = t_util.t_insertAtSlot(page, 1, row1);
2831: r2 = t_util.t_insertAtSlot(page, 2, row2);
2832: r3 = t_util.t_insertAtSlot(page, 3, row3);
2833: r4 = t_util.t_insertAtSlot(page, 4, row4);
2834:
2835: if (r3 != null)
2836: page.deleteAtSlot(3, true, (LogicalUndo) null);
2837:
2838: // REPORT("commit it");
2839: t_util.t_commit(t);
2840:
2841: c = t_util.t_openContainer(t, 0, cid, true);
2842: page = t_util.t_getPage(c, ContainerHandle.FIRST_PAGE_NUMBER);
2843:
2844: try {
2845: page.purgeAtSlot(-1, 1, logDataForPurges);
2846: throw T_Fail
2847: .testFailMsg("negative slot number did not cause an exception");
2848: } catch (StandardException se) {
2849: } // expected
2850:
2851: try {
2852: page.purgeAtSlot(4, 4, logDataForPurges);
2853: throw T_Fail
2854: .testFailMsg("purging more rows than is on page did not cause an exception");
2855: } catch (StandardException se) {
2856: } // expected
2857:
2858: // if not all the rows are there, do minimal test
2859: if (r4 == null) {
2860: int rcount = page.recordCount();
2861: page.purgeAtSlot(0, 1, logDataForPurges);
2862: if (page.recordCount() != rcount - 1)
2863: T_Fail.testFailMsg("failed to purge a record, expect "
2864: + (rcount - 1) + " got " + page.recordCount());
2865:
2866: if (testRollback) {
2867: t_util.t_abort(t);
2868:
2869: c = t_util.t_openContainer(t, 0, cid, true);
2870: page = t_util.t_getPage(c,
2871: ContainerHandle.FIRST_PAGE_NUMBER);
2872: if (logDataForPurges)
2873: t_util.t_checkFetchBySlot(page, 0, REC_001, false,
2874: true);
2875: else
2876: t_util.t_checkFetchBySlot(page, 0, REC_NULL, false,
2877: true);
2878: if (page.recordCount() != rcount)
2879: T_Fail
2880: .testFailMsg("failed to rollback purge, expect "
2881: + rcount
2882: + " got "
2883: + page.recordCount());
2884: } else {
2885: t_util.t_commit(t);
2886: }
2887: PASS("minimal P014");
2888: return;
2889: }
2890:
2891: // REPORT("purge 2 records from middle");
2892: page.purgeAtSlot(1, 2, logDataForPurges);
2893: t_util.t_checkFetchBySlot(page, 0, REC_001, false, true);
2894: t_util.t_checkFetchBySlot(page, 1, REC_003, true, true);
2895: t_util.t_checkFetchBySlot(page, 2, REC_004, false, true);
2896:
2897: if (page.recordCount() != 3)
2898: T_Fail
2899: .testFailMsg("page expect to have 3 records, recordCount() = "
2900: + page.recordCount());
2901:
2902: // REPORT("purge all records from the page");
2903: page.purgeAtSlot(0, 3, logDataForPurges);
2904: if (page.recordCount() != 0)
2905: T_Fail
2906: .testFailMsg("page expect to have 0 records, recordCount() = "
2907: + page.recordCount());
2908:
2909: if (testRollback) {
2910:
2911: REPORT("testing rollback");
2912: t_util.t_abort(t);
2913:
2914: c = t_util.t_openContainer(t, 0, cid, true);
2915: page = t_util.t_getPage(c,
2916: ContainerHandle.FIRST_PAGE_NUMBER);
2917:
2918: if (logDataForPurges) {
2919: t_util
2920: .t_checkFetchBySlot(page, 0, REC_001, false,
2921: true);
2922: t_util
2923: .t_checkFetchBySlot(page, 1, REC_001, false,
2924: true);
2925: t_util
2926: .t_checkFetchBySlot(page, 2, REC_002, false,
2927: true);
2928: t_util.t_checkFetchBySlot(page, 3, REC_003, true, true);
2929: t_util
2930: .t_checkFetchBySlot(page, 4, REC_004, false,
2931: true);
2932: } else {
2933: t_util.t_checkFetchBySlot(page, 0, REC_NULL, false,
2934: true);
2935: t_util.t_checkFetchBySlot(page, 1, REC_NULL, false,
2936: true);
2937: t_util.t_checkFetchBySlot(page, 2, REC_NULL, false,
2938: true);
2939: t_util
2940: .t_checkFetchBySlot(page, 3, REC_NULL, true,
2941: true);
2942: t_util.t_checkFetchBySlot(page, 4, REC_NULL, false,
2943: true);
2944: }
2945:
2946: if (page.recordCount() != 5)
2947: T_Fail
2948: .testFailMsg("page expect to have 5 records, recordCount() = "
2949: + page.recordCount());
2950:
2951: // REPORT("purge 3 records from the end");
2952: page.purgeAtSlot(2, 3, logDataForPurges);
2953: if (logDataForPurges) {
2954: t_util
2955: .t_checkFetchBySlot(page, 0, REC_001, false,
2956: true);
2957: t_util
2958: .t_checkFetchBySlot(page, 1, REC_001, false,
2959: true);
2960: } else {
2961: t_util.t_checkFetchBySlot(page, 0, REC_NULL, false,
2962: true);
2963: t_util.t_checkFetchBySlot(page, 1, REC_NULL, false,
2964: true);
2965: }
2966: if (page.recordCount() != 2)
2967: T_Fail
2968: .testFailMsg("page expect to have 2 records, recordCount() = "
2969: + page.recordCount());
2970:
2971: // REPORT("rollback");
2972: t_util.t_abort(t);
2973:
2974: c = t_util.t_openContainer(t, 0, cid, true);
2975: page = t_util.t_getPage(c,
2976: ContainerHandle.FIRST_PAGE_NUMBER);
2977: if (logDataForPurges) {
2978: t_util
2979: .t_checkFetchBySlot(page, 0, REC_001, false,
2980: true);
2981: t_util
2982: .t_checkFetchBySlot(page, 1, REC_001, false,
2983: true);
2984: t_util
2985: .t_checkFetchBySlot(page, 2, REC_002, false,
2986: true);
2987: t_util.t_checkFetchBySlot(page, 3, REC_003, true, true);
2988: t_util
2989: .t_checkFetchBySlot(page, 4, REC_004, false,
2990: true);
2991: } else {
2992: t_util.t_checkFetchBySlot(page, 0, REC_NULL, false,
2993: true);
2994: t_util.t_checkFetchBySlot(page, 1, REC_NULL, false,
2995: true);
2996: t_util.t_checkFetchBySlot(page, 2, REC_NULL, false,
2997: true);
2998: t_util
2999: .t_checkFetchBySlot(page, 3, REC_NULL, true,
3000: true);
3001: t_util.t_checkFetchBySlot(page, 4, REC_NULL, false,
3002: true);
3003: }
3004:
3005: if (page.recordCount() != 5)
3006: T_Fail
3007: .testFailMsg("page expect to have 5 records, recordCount() = "
3008: + page.recordCount());
3009:
3010: // REPORT("make sure delete record is reconstituted as such");
3011: if (page.isDeletedAtSlot(1))
3012: T_Fail
3013: .testFailMsg("rolled back purged undeleted record cause record to be deleted");
3014: if (!page.isDeletedAtSlot(3))
3015: T_Fail
3016: .testFailMsg("rolled back purged deleted record cause record to be undeleted");
3017: }
3018: PASS("P014");
3019:
3020: t_util.t_dropContainer(t, 0, cid); // cleanup
3021: t_util.t_commit(t);
3022: t.close();
3023: }
3024:
3025: /**
3026: P015
3027:
3028: this test exercises updateAtSlot
3029:
3030: @exception T_Fail Unexpected behaviour from the API
3031: @exception StandardException Unexpected exception from the implementation
3032: */
3033: protected void P015() throws StandardException, T_Fail {
3034: Transaction t = t_util.t_startTransaction();
3035: long cid = t_util.t_addContainer(t, 0);
3036:
3037: t_util.t_commit(t);
3038:
3039: ContainerHandle c = t_util.t_openContainer(t, 0, cid, true);
3040: Page page = t_util.t_getPage(c,
3041: ContainerHandle.FIRST_PAGE_NUMBER);
3042:
3043: // REPORT("insert 3 records");
3044: T_RawStoreRow row1 = new T_RawStoreRow(REC_001);
3045:
3046: T_RawStoreRow row2 = new T_RawStoreRow(2);
3047: row2.setColumn(0, (String) null);
3048: row2.setColumn(1, REC_001);
3049:
3050: T_RawStoreRow row3 = new T_RawStoreRow(3);
3051: row3.setColumn(0, REC_001);
3052: row3.setColumn(1, REC_002);
3053: row3.setColumn(2, REC_003);
3054:
3055: RecordHandle r1, r2, r3;
3056: r1 = t_util.t_insertAtSlot(page, 0, row1);
3057:
3058: r2 = r3 = null;
3059: r2 = t_util.t_insertAtSlot(page, 1, row2);
3060:
3061: if (r2 == null) {
3062: REPORT("P015 not completed - cannot insert second row");
3063: return;
3064: }
3065:
3066: r3 = t_util.t_insertAtSlot(page, 2, row3);
3067:
3068: if (r3 == null) {
3069: REPORT("P015 not completed - cannot insert third row");
3070: return;
3071: }
3072:
3073: // check that they are inserted correctly
3074: t_util.t_checkFetch(page, r1, row1);
3075: t_util.t_checkFetch(page, r2, row2);
3076: t_util.t_checkFetch(page, r3, row3);
3077:
3078: // now update the middle row with a large value
3079: T_RawStoreRow row2u = new T_RawStoreRow(2);
3080: row2u
3081: .setColumn(
3082: 0,
3083: "012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789");
3084: row2u
3085: .setColumn(
3086: 1,
3087: "0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789");
3088:
3089: page.updateAtSlot(1, row2u.getRow(), (FormatableBitSet) null);
3090: t_util.t_checkFetch(page, r2, row2u);
3091:
3092: // now update the field of the first record with a large value
3093: ((T_RawStoreRow) row1)
3094: .setColumn(
3095: 0,
3096: "abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyz");
3097:
3098: FormatableBitSet validColumn = new FormatableBitSet(2);
3099:
3100: validColumn.clear();
3101: validColumn.set(0);
3102:
3103: page.updateAtSlot(0, row1.getRow(), validColumn);
3104:
3105: t_util.t_checkFetch(page, r1, row1);
3106:
3107: ((T_RawStoreRow) row3)
3108: .setColumn(
3109: 1,
3110: "XXabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyz");
3111:
3112: validColumn.clear();
3113: validColumn.set(1);
3114:
3115: page.updateAtSlot(2, row3.getRow(), validColumn);
3116: t_util.t_checkFetch(page, r3, row3);
3117:
3118: // clean up
3119: PASS("P015");
3120:
3121: t_util.t_dropContainer(t, 0, cid); // cleanup
3122:
3123: t_util.t_commit(t);
3124: t.close();
3125:
3126: }
3127:
3128: /*
3129: P016
3130:
3131: this test exercises copyAndPurge
3132: @exception T_Fail Unexpected behaviour from the API
3133: @exception StandardException Unexpected exception from the implementation
3134: */
3135: protected void P016() throws StandardException, T_Fail {
3136: Transaction t = t_util.t_startTransaction();
3137: long cid = t_util.t_addContainer(t, 0);
3138: long cid2 = t_util.t_addContainer(t, 0);
3139:
3140: t_util.t_commit(t);
3141:
3142: ContainerHandle c = t_util.t_openContainer(t, 0, cid, true);
3143:
3144: Page page1 = t_util.t_getPage(c,
3145: ContainerHandle.FIRST_PAGE_NUMBER);
3146: Page page2 = t_util.t_addPage(c);
3147: long pid1 = page1.getPageNumber();
3148: long pid2 = page2.getPageNumber();
3149:
3150: t_util.t_checkEmptyPage(page2);
3151:
3152: // first fill up page 1
3153:
3154: int i = 0;
3155: int deleted = 0;
3156: RecordHandle rh;
3157:
3158: T_RawStoreRow row;
3159:
3160: for (i = 0, row = new T_RawStoreRow("row at slot " + i); page1
3161: .spaceForInsert(); i++, row = new T_RawStoreRow(
3162: "row at slot " + i)) {
3163: rh = t_util.t_insertAtSlot(page1, i, row);
3164: if (rh == null)
3165: break;
3166:
3167: // delete every third row
3168: if ((i % 3) == 1) {
3169: deleted++;
3170: page1.delete(rh, (LogicalUndo) null);
3171: }
3172: }
3173:
3174: int recordCount = i;
3175:
3176: // negative testing
3177: // copy into page of different container
3178: ContainerHandle c2 = t_util.t_openContainer(t, 0, cid2, true);
3179: Page wrongPage = t_util.t_getPage(c2,
3180: ContainerHandle.FIRST_PAGE_NUMBER);
3181: try {
3182: page1.copyAndPurge(wrongPage, 0, recordCount, 0);
3183: throw T_Fail
3184: .testFailMsg("copying to page from a different contaier should cause and exception");
3185: } catch (StandardException se) {
3186: } // expected
3187:
3188: try {
3189: page1.copyAndPurge(page2, 1, 0, 0);
3190: throw T_Fail
3191: .testFailMsg("copying zero rows should cause an exception");
3192: } catch (StandardException se) {
3193: } // expected
3194:
3195: try {
3196: page1.copyAndPurge(page2, 1, recordCount, 0);
3197: throw T_Fail
3198: .testFailMsg("copying more rows than page contains should cause an exception");
3199: } catch (StandardException se) {
3200: } // expected
3201:
3202: try {
3203: page1.copyAndPurge(page2, 0, 1, 1);
3204: throw T_Fail
3205: .testFailMsg("copying rows to nonexistant slot should cause an exception");
3206: } catch (StandardException se) {
3207: } // expected
3208:
3209: // copy the whole page to page2
3210: page1.copyAndPurge(page2, 0, recordCount, 0);
3211:
3212: // check
3213: t_util.t_checkEmptyPage(page1);
3214:
3215: for (i = 0; i < recordCount; i++) {
3216: t_util.t_checkFetchBySlot(page2, i, "row at slot " + i,
3217: ((i % 3) == 1), true);
3218: }
3219: t_util.t_checkRecordCount(page2, recordCount, recordCount
3220: - deleted);
3221:
3222: t_util.t_commit(t);
3223:
3224: if (recordCount > 2) {
3225: // now copy and purge part of the page
3226: c = t_util.t_openContainer(t, 0, cid, true);
3227: page1 = t_util.t_getPage(c, pid1);
3228: page2 = t_util.t_getPage(c, pid2);
3229:
3230: // insert 2 rows into page1
3231: T_RawStoreRow row1 = new T_RawStoreRow(REC_001);
3232: T_RawStoreRow row2 = new T_RawStoreRow(REC_002);
3233: t_util.t_insertAtSlot(page1, 0, row1);
3234: t_util.t_insertAtSlot(page1, 1, row2);
3235:
3236: page2.copyAndPurge(page1, 1, recordCount - 2, 1);
3237:
3238: t_util.t_checkFetchBySlot(page2, 0, "row at slot " + 0,
3239: false, true);
3240:
3241: // need to figure out the delete status of the last row on page 2
3242: boolean tdeleted = ((recordCount - 1) % 3) == 1;
3243: t_util.t_checkFetchBySlot(page2, 1, "row at slot "
3244: + (recordCount - 1), tdeleted, true);
3245:
3246: if (((recordCount - 1) % 3) == 1)
3247: t_util.t_checkRecordCount(page2, 2, 1); // last record on page2 was deleted
3248: else
3249: t_util.t_checkRecordCount(page2, 2, 2); // last record on page2 was not deleted
3250:
3251: t_util.t_checkFetchBySlot(page1, 0, REC_001, false, false);
3252: for (i = 1; i < recordCount - 1; i++) {
3253: t_util.t_checkFetchBySlot(page1, i, "row at slot " + i,
3254: ((i % 3) == 1), false);
3255: }
3256: t_util.t_checkFetchBySlot(page1, recordCount - 1, REC_002,
3257: false, false);
3258: if (((recordCount - 1) % 3) == 1)
3259: // one (the last one) of the deleted rows did not get copied over
3260: t_util.t_checkRecordCount(page1, recordCount,
3261: recordCount - deleted + 1);
3262: else
3263: t_util.t_checkRecordCount(page1, recordCount,
3264: recordCount - deleted);
3265:
3266: if (testRollback) {
3267: t_util.t_abort(t);
3268:
3269: c = t_util.t_openContainer(t, 0, cid, true);
3270: page1 = t_util.t_getPage(c, pid1);
3271: page2 = t_util.t_getPage(c, pid2);
3272:
3273: // the two inserted rows is rolled back by deletion
3274: t_util.t_checkFetchBySlot(page1, 0, REC_001, true,
3275: false);
3276: t_util.t_checkFetchBySlot(page1, 1, REC_002, true,
3277: false);
3278: t_util.t_checkRecordCount(page1, 2, 0);
3279:
3280: for (i = 0; i < recordCount; i++) {
3281: t_util.t_checkFetchBySlot(page2, i, "row at slot "
3282: + i, ((i % 3) == 1), true);
3283: }
3284: t_util.t_checkRecordCount(page2, recordCount,
3285: recordCount - deleted);
3286:
3287: REPORT("tested roll back of copyAndPurge");
3288: }
3289:
3290: PASS("P016");
3291: }
3292:
3293: t_util.t_dropContainer(t, 0, cid); // cleanup
3294: t_util.t_dropContainer(t, 0, cid2); // cleanup
3295: t_util.t_commit(t);
3296: t.close();
3297: }
3298:
3299: /*
3300: P017
3301: this test getInvalidRecordHandle and makeRecordHandle
3302:
3303: @exception T_Fail Unexpected behaviour from the API
3304: @exception StandardException Unexpected exception from the implementation
3305: */
3306: protected void P017() throws StandardException, T_Fail {
3307: Transaction t = t_util.t_startTransaction();
3308:
3309: long cid = t_util.t_addContainer(t, 0);
3310: ContainerHandle c = t_util.t_openContainer(t, 0, cid, true);
3311:
3312: Page page1 = t_util.t_getPage(c,
3313: ContainerHandle.FIRST_PAGE_NUMBER);
3314: T_RawStoreRow row1 = new T_RawStoreRow(REC_001);
3315:
3316: RecordHandle valid = t_util.t_insert(page1, row1);
3317: RecordHandle special = page1
3318: .makeRecordHandle(RecordHandle.RECORD_ID_PROTECTION_HANDLE);
3319:
3320: RecordHandle[] rhs = new RecordHandle[RecordHandle.FIRST_RECORD_ID];
3321: rhs[0] = page1.getInvalidRecordHandle();
3322: rhs[1] = page1
3323: .makeRecordHandle(RecordHandle.RECORD_ID_PROTECTION_HANDLE);
3324: rhs[2] = page1
3325: .makeRecordHandle(RecordHandle.DEALLOCATE_PROTECTION_HANDLE);
3326: rhs[3] = page1
3327: .makeRecordHandle(RecordHandle.PREVIOUS_KEY_HANDLE);
3328: rhs[4] = page1
3329: .makeRecordHandle(RecordHandle.RESERVED4_RECORD_HANDLE);
3330: rhs[5] = page1
3331: .makeRecordHandle(RecordHandle.RESERVED5_RECORD_HANDLE);
3332:
3333: for (int i = 0; i < RecordHandle.FIRST_RECORD_ID; i++) {
3334: try {
3335: page1.recordExists(rhs[i], true);
3336: throw T_Fail
3337: .testFailMsg("record exists for invalid record "
3338: + rhs[i]);
3339: } catch (StandardException se) {
3340: /* expected */
3341: }
3342:
3343: try {
3344: page1.fetch(rhs[i], new DataValueDescriptor[0],
3345: (FormatableBitSet) null, true);
3346: throw T_Fail.testFailMsg("fetched an invalid record "
3347: + rhs[i]);
3348: } catch (StandardException se) {
3349: /* expected */
3350: }
3351:
3352: try {
3353: page1.update(rhs[i], row1.getRow(),
3354: (FormatableBitSet) null);
3355: throw T_Fail.testFailMsg("updated an invalid record "
3356: + rhs[i]);
3357: } catch (StandardException se) {
3358: /* expected */
3359: }
3360:
3361: try {
3362: page1.update(rhs[i], row1.getRow(), BS_COL_0);
3363: throw T_Fail
3364: .testFailMsg("updated an invalid record field");
3365: } catch (StandardException se) {
3366: /* expected */
3367: }
3368:
3369: try {
3370: page1.delete(rhs[i], null);
3371: throw T_Fail.testFailMsg("delete an invalid record "
3372: + rhs[i]);
3373: } catch (StandardException se) {
3374: /* expected */
3375: }
3376:
3377: try {
3378: page1.fetchNumFields(rhs[i]);
3379: throw T_Fail
3380: .testFailMsg("fetch num fields on invalid record "
3381: + rhs[i]);
3382: } catch (StandardException se) {
3383: /* expected */
3384: }
3385:
3386: try {
3387: page1.getSlotNumber(rhs[i]);
3388: throw T_Fail
3389: .testFailMsg("got slot number of invalid record "
3390: + rhs[i]);
3391: } catch (StandardException se) {
3392: /* expected */
3393: }
3394:
3395: }
3396: PASS("P017");
3397:
3398: t_util.t_dropContainer(t, 0, cid);
3399: t_util.t_commit(t);
3400: t.close();
3401: }
3402:
3403: /*
3404: P018
3405:
3406: this test exercises track # 590, test that copyRows successfully
3407: notices that a copy can't be done.
3408:
3409: @exception T_Fail Unexpected behaviour from the API
3410: @exception StandardException Unexpected exception from the implementation
3411: */
3412: protected void P018() throws StandardException, T_Fail {
3413: Transaction t = t_util.t_startTransaction();
3414:
3415: // create container with 0 spare space, 1 minimum record size to easily
3416: // force absolutely full page. Record id's are not reusable.
3417: long cid = t_util.t_addContainer(t, 0, 4096, 0, 1, false);
3418:
3419: t_util.t_commit(t);
3420:
3421: ContainerHandle c = t_util.t_openContainer(t, 0, cid, true);
3422:
3423: Page page1 = t_util.t_getPage(c,
3424: ContainerHandle.FIRST_PAGE_NUMBER);
3425: Page page2 = t_util.t_addPage(c);
3426: long pid1 = page1.getPageNumber();
3427: long pid2 = page2.getPageNumber();
3428:
3429: t_util.t_checkEmptyPage(page2);
3430:
3431: // first fill up page 1
3432:
3433: int i = 0;
3434: int deleted = 0;
3435: RecordHandle rh;
3436:
3437: T_RawStoreRow row;
3438:
3439: // first insert and purge 100 rows, setting the next recid to be
3440: // greater than 64. This will cause the next
3441: // recid to be allocated to be greater than 64, this means
3442: // that new recid's added to the page take 2 bytes rather than 1.
3443: for (i = 0; i < 100; i++) {
3444: row = new T_RawStoreRow("r" + i);
3445:
3446: rh = t_util.t_insertAtSlot(page1, 0, row);
3447:
3448: page1.purgeAtSlot(0, 1, logDataForPurges);
3449: }
3450:
3451: // fill up another page starting with "small" record id's.
3452: for (i = 0; true; i++) {
3453: row = new T_RawStoreRow("r" + i);
3454:
3455: rh = t_util.t_insertAtSlot(page2, i, row);
3456:
3457: if (rh == null)
3458: break;
3459: }
3460:
3461: // an attempt to copy all the rows should get an error, because the
3462: // recid's are bigger so all the records will not fit.
3463: try {
3464: page2.copyAndPurge(page1, 0, page2.recordCount(), 0);
3465:
3466: throw T_Fail
3467: .testFailMsg("copying rows with expanding recids should cause an exception");
3468: } catch (StandardException se) {
3469: // expect a out of space error.
3470:
3471: }
3472:
3473: // cleanup after first part of test.
3474: t_util.t_dropContainer(t, 0, cid);
3475: t_util.t_commit(t);
3476:
3477: // Now test that with the reusable record id's that the copy works.
3478:
3479: // create container with 0 spare space, 1 minimum record size to easily
3480: // force absolutely full page. This container will allow
3481: // reusable record id's which will mean the copy should succeed.
3482: cid = t_util.t_addContainer(t, 0, 4096, 0, 1, true);
3483:
3484: t_util.t_commit(t);
3485:
3486: c = t_util.t_openContainer(t, 0, cid, true);
3487:
3488: page1 = t_util.t_getPage(c, ContainerHandle.FIRST_PAGE_NUMBER);
3489: page2 = t_util.t_addPage(c);
3490: pid1 = page1.getPageNumber();
3491: pid2 = page2.getPageNumber();
3492:
3493: t_util.t_checkEmptyPage(page2);
3494:
3495: // first fill up page 1
3496:
3497: i = 0;
3498:
3499: // first insert and purge 100 rows, setting the next recid to be
3500: // greater than 64. This will cause the next
3501: // recid to be allocated to be greater than 64, this means
3502: // that new recid's added to the page take 2 bytes rather than 1.
3503: for (i = 0; i < 100; i++) {
3504: row = new T_RawStoreRow("r" + i);
3505:
3506: rh = t_util.t_insertAtSlot(page1, 0, row);
3507:
3508: page1.purgeAtSlot(0, 1, logDataForPurges);
3509: }
3510:
3511: // fill up another page starting with "small" record id's.
3512: for (i = 0; true; i++) {
3513: row = new T_RawStoreRow("r" + i);
3514:
3515: rh = t_util.t_insertAtSlot(page2, i, row);
3516:
3517: if (rh == null)
3518: break;
3519: }
3520: long pnum2 = page2.getPageNumber();
3521: int numrows = page2.recordCount();
3522:
3523: // an attempt to copy all the rows should get an error,
3524: try {
3525: // This copy should not succeed.
3526: page2.copyAndPurge(page1, 0, page2.recordCount(), 0);
3527:
3528: throw T_Fail
3529: .testFailMsg("copying rows with expanding recids should cause an exception");
3530: } catch (StandardException se) {
3531: // expect a out of space error.
3532: }
3533:
3534: // now deallocated this page and get it to go thru a reuse cycle
3535: t_util.t_removePage(c, page1);
3536: t_util.t_commit(t);
3537:
3538: c = t_util.t_openContainer(t, 0, cid, true);
3539: page1 = t_util.t_addPage(c);
3540: int tries = 0;
3541: while (page1.getPageNumber() != ContainerHandle.FIRST_PAGE_NUMBER) {
3542: REPORT("getting page " + page1.getPageNumber());
3543:
3544: t_util.t_commit(t);
3545:
3546: if (tries++ > 100)
3547: throw T_Fail
3548: .testFailMsg("failed to get back first page after "
3549: + tries + " tries");
3550: c = t_util.t_openContainer(t, 0, cid, true);
3551: page1 = t_util.t_addPage(c);
3552: }
3553: page2 = t_util.t_getPage(c, pnum2);
3554:
3555: t_util.t_checkRecordCount(page2, numrows, numrows);
3556: t_util.t_checkEmptyPage(page1);
3557:
3558: // now the attempt to copy all the rows should succeed
3559: try {
3560: page2.copyAndPurge(page1, 0, page2.recordCount(), 0);
3561: } catch (StandardException se) {
3562: throw T_Fail
3563: .testFailMsg("copying rows with non-expanding recids should not cause an exception");
3564: }
3565:
3566: PASS("P018");
3567:
3568: t_util.t_dropContainer(t, 0, cid); // cleanup
3569: t_util.t_commit(t);
3570: t.close();
3571: }
3572:
3573: /**
3574: Test bulk load and preallocation
3575: @exception T_Fail Unexpected behaviour from the API
3576: @exception StandardException Unexpected exception from the implementation
3577: */
3578: protected void P019() throws StandardException, T_Fail {
3579: Transaction t = t_util.t_startTransaction();
3580:
3581: long cid = t_util.t_addContainer(t, 0, 4096, 0, 1, false);
3582: t_util.t_commit(t);
3583:
3584: ContainerHandle c = t_util.t_openContainer(t, 0, cid, true);
3585:
3586: // add page for bulk load
3587: Page p1 = c.addPage(ContainerHandle.ADD_PAGE_BULK);
3588: long pnum1 = p1.getPageNumber();
3589: p1.unlatch();
3590:
3591: // since the interface does not guarentee that anything special will
3592: // actually happen, can't really test that. Just make sure that
3593: // everything else works
3594: Page p2 = c.addPage();
3595: long pnum2 = p2.getPageNumber();
3596: p2.unlatch();
3597:
3598: Page p3 = c.addPage(ContainerHandle.ADD_PAGE_BULK);
3599: long pnum3 = p3.getPageNumber();
3600: p3.unlatch();
3601:
3602: Page p = c.getFirstPage(); // this is the first page that came with the
3603: // container when it was created
3604:
3605: try {
3606: long pnum0 = p.getPageNumber();
3607: p.unlatch();
3608: p = c.getNextPage(pnum0);
3609: if (p.getPageNumber() != pnum1)
3610: throw T_Fail.testFailMsg("expected pagenum " + pnum1
3611: + " got " + p.getPageNumber());
3612: p.unlatch();
3613: p = null;
3614:
3615: p = c.getNextPage(pnum1);
3616: if (p.getPageNumber() != pnum2)
3617: throw T_Fail.testFailMsg("expected pagenum " + pnum2
3618: + " got " + p.getPageNumber());
3619: p.unlatch();
3620: p = null;
3621:
3622: p = c.getNextPage(pnum2);
3623: if (p.getPageNumber() != pnum3)
3624: throw T_Fail.testFailMsg("expected pagenum " + pnum3
3625: + " got " + p.getPageNumber());
3626: p.unlatch();
3627: p = null;
3628:
3629: p = c.getNextPage(pnum3);
3630: if (p != null)
3631: throw T_Fail.testFailMsg("expected null page after "
3632: + pnum3 + " got " + p.getPageNumber());
3633:
3634: // make sure rollback is unaffected
3635: if (testRollback) {
3636: t_util.t_abort(t);
3637: c = t_util.t_openContainer(t, 0, cid, true);
3638: p = t_util.t_getPage(c, pnum0);
3639: t_util.t_checkEmptyPage(p);
3640: p.unlatch();
3641: p = null;
3642:
3643: p = t_util.t_getPage(c, pnum1);
3644: t_util.t_checkEmptyPage(p);
3645: p.unlatch();
3646: p = null;
3647:
3648: p = t_util.t_getPage(c, pnum2);
3649: t_util.t_checkEmptyPage(p);
3650: p.unlatch();
3651: p = null;
3652:
3653: p = t_util.t_getPage(c, pnum3);
3654: t_util.t_checkEmptyPage(p);
3655: p.unlatch();
3656: p = null;
3657:
3658: p = t_util.t_getLastPage(c);
3659: if (p.getPageNumber() != pnum3)
3660: throw T_Fail.testFailMsg("expect last page to be "
3661: + pnum3 + " got " + p.getPageNumber());
3662: p.unlatch();
3663: p = null;
3664: }
3665:
3666: t_util.t_dropContainer(t, 0, cid); // cleanup
3667:
3668: } finally {
3669: if (p != null)
3670: p.unlatch();
3671: p = null;
3672: t_util.t_commit(t);
3673: t.close();
3674: }
3675: PASS("P019 - container " + cid);
3676:
3677: }
3678:
3679: /**
3680: Test create container with initial page set to 100 pages
3681: @exception T_Fail Unexpected behaviour from the API
3682: @exception StandardException Unexpected exception from the implementation
3683: */
3684: protected void P020() throws StandardException, T_Fail {
3685: Transaction t = t_util.t_startTransaction();
3686: Properties tableProperties = new Properties();
3687: tableProperties.put(Property.PAGE_SIZE_PARAMETER, Integer
3688: .toString(4096));
3689: tableProperties.put(RawStoreFactory.CONTAINER_INITIAL_PAGES,
3690: Integer.toString(100));
3691:
3692: long cid = t_util.t_addContainer(t, 0, tableProperties);
3693: if (cid < 0)
3694: throw T_Fail.testFailMsg("addContainer");
3695:
3696: ContainerHandle c = t_util.t_openContainer(t, 0, cid, true);
3697:
3698: Page p1 = c.getFirstPage();
3699: if (p1.getPageNumber() != ContainerHandle.FIRST_PAGE_NUMBER)
3700: throw T_Fail
3701: .testFailMsg("expect first page to have FIRST_PAGE_NUMBER");
3702: p1.unlatch();
3703:
3704: if (c.getNextPage(ContainerHandle.FIRST_PAGE_NUMBER) != null)
3705: throw T_Fail
3706: .testFailMsg("expect to have only 1 page allocated");
3707:
3708: t_util.t_dropContainer(t, 0, cid); // cleanup
3709: t_util.t_commit(t);
3710: t.close();
3711: PASS("P020 - container " + cid);
3712: }
3713:
3714: /**
3715: Test preAllocate
3716: @exception T_Fail Unexpected behaviour from the API
3717: @exception StandardException Unexpected exception from the implementation
3718: */
3719: protected void P021() throws StandardException, T_Fail {
3720: Transaction t = t_util.t_startTransaction();
3721: long cid = t_util.t_addContainer(t, 0, 4096);
3722: ContainerHandle c = t_util.t_openContainer(t, 0, cid, true);
3723:
3724: // now preallocate 10 pages
3725: c.preAllocate(10);
3726:
3727: Page p1 = c.getFirstPage();
3728: if (p1.getPageNumber() != ContainerHandle.FIRST_PAGE_NUMBER)
3729: throw T_Fail
3730: .testFailMsg("expect first page to have FIRST_PAGE_NUMBER");
3731: p1.unlatch();
3732:
3733: if (c.getNextPage(ContainerHandle.FIRST_PAGE_NUMBER) != null)
3734: throw T_Fail
3735: .testFailMsg("expect to have only 1 page allocated");
3736:
3737: t_util.t_dropContainer(t, 0, cid); // cleanup
3738: t_util.t_commit(t);
3739: t.close();
3740: PASS("P021 - container " + cid);
3741: }
3742:
3743: /**
3744: Test minimumRecordSize: this is to make sure that logRow and storeRecord
3745: are consistent with each other when it comes to reserve space.
3746:
3747: @exception T_Fail Unexpected behaviour from the API
3748: @exception StandardException Unexpected exception from the implementation
3749: */
3750: protected void P022() throws StandardException, T_Fail {
3751: Transaction t = t_util.t_startTransaction();
3752:
3753: // create container with 4096 page size, 0 spare space, 9 minimum record size
3754: long cid = t_util.t_addContainer(t, 0, 4096, 0, 9, false);
3755:
3756: t_util.t_commit(t);
3757:
3758: ContainerHandle c = t_util.t_openContainer(t, 0, cid, true);
3759:
3760: Page page1 = t_util.t_getPage(c,
3761: ContainerHandle.FIRST_PAGE_NUMBER);
3762:
3763: RecordHandle rh;
3764: T_RawStoreRow row;
3765:
3766: // insert records to fill the page.
3767: for (int i = 0; i < 60; i++) {
3768: row = new T_RawStoreRow("r" + i);
3769: rh = t_util.t_insertAtSlot(page1, 0, row);
3770: }
3771:
3772: // cleanup after first part of test.
3773: t_util.t_dropContainer(t, 0, cid); // cleanup
3774: t_util.t_commit(t);
3775: t.close();
3776: PASS("P022");
3777: }
3778:
3779: /**
3780: Test overflowThreshold: this is to make sure that logRow and storeRecord
3781: are consistent with each other when it comes to reserve space.
3782:
3783: @exception T_Fail Unexpected behaviour from the API
3784: @exception StandardException Unexpected exception from the implementation
3785: */
3786: protected void P023(int segment) throws StandardException, T_Fail {
3787:
3788: Transaction t = t_util.t_startTransaction();
3789: // create a container with 1K page, 0 spareSpace, and 0 minimumRecordSize
3790: long cid = t_util.t_addContainer(t, segment, 4096, 0, 0, false);
3791: t_util.t_commit(t);
3792:
3793: ContainerHandle c = t_util.t_openContainer(t, segment, cid,
3794: true);
3795: Page page = t_util.t_getPage(c,
3796: ContainerHandle.FIRST_PAGE_NUMBER);
3797: int overflowThreshold = 50;
3798:
3799: t_util.t_checkEmptyPage(page);
3800:
3801: // use default insert, not allowing overflow
3802: int insertFlag = Page.INSERT_INITIAL | Page.INSERT_DEFAULT;
3803:
3804: // test 1:
3805: // create a row that's under the threshold
3806: T_RawStoreRow r1 = new T_RawStoreRow(1);
3807: r1.setColumn(0, 200, REC_001);
3808: // insert the row twice, should fit on 1 page
3809: RecordHandle rh1 = t_util.t_insertAtSlot(page, 0, r1,
3810: (byte) insertFlag, overflowThreshold);
3811: if (rh1 == null)
3812: throw T_Fail
3813: .testFailMsg("insert of first long row failed.");
3814: RecordHandle rh2 = t_util.t_insertAtSlot(page, 1, r1,
3815: (byte) insertFlag, overflowThreshold);
3816: if (rh2 == null)
3817: throw T_Fail
3818: .testFailMsg("insert of second long row failed.");
3819: t_util.t_checkFetch(page, rh1, r1);
3820: t_util.t_checkFetch(page, rh2, r1);
3821: page.unlatch();
3822: page = null;
3823: REPORT("test 1: 2 rows under threshold inserted...");
3824:
3825: // test 2:
3826: // get a new page
3827: page = t_util.t_addPage(c);
3828: // create a row that's over the threshold
3829: T_RawStoreRow r2 = new T_RawStoreRow(1);
3830: r2.setColumn(0, 2000, REC_001);
3831: // insert the row twice, should fail both inserts
3832: rh1 = t_util.t_insertAtSlot(page, 0, r2, (byte) insertFlag,
3833: overflowThreshold);
3834: if (rh1 != null) {
3835: throw T_Fail
3836: .testFailMsg("insert of 1st over threshold row should failed.");
3837: }
3838: rh2 = t_util.t_insertAtSlot(page, 0, r2, (byte) insertFlag,
3839: overflowThreshold);
3840: if (rh2 != null)
3841: throw T_Fail
3842: .testFailMsg("insert of 2nd over threshold row should failed.");
3843: page.unlatch();
3844: page = null;
3845: REPORT("test 2: 2 rows over threshold not inserted...");
3846:
3847: // test 3:
3848: // get a new page
3849: page = t_util.t_addPage(c);
3850: // create a row with 2 columns, each column is under the threshold,
3851: // and the row is also under the threshold
3852: T_RawStoreRow r3 = new T_RawStoreRow(2);
3853: // create a row that's under the threshold
3854: r3.setColumn(0, 400, REC_001);
3855: r3.setColumn(1, 400, REC_001);
3856: // insert the row twice, should fit on 1 page
3857: rh1 = t_util.t_insertAtSlot(page, 0, r3, (byte) insertFlag,
3858: overflowThreshold);
3859: if (rh1 == null)
3860: throw T_Fail
3861: .testFailMsg("insert of 1st 2-column row failed.");
3862: rh2 = t_util.t_insertAtSlot(page, 1, r3, (byte) insertFlag,
3863: overflowThreshold);
3864: if (rh2 == null)
3865: throw T_Fail
3866: .testFailMsg("insert of 2nd 2-column row failed.");
3867: page.unlatch();
3868: page = null;
3869: REPORT("test 3: 2 rows with 2 columns under the threshold inserted...");
3870:
3871: // test 4:
3872: // get a new page
3873: page = t_util.t_addPage(c);
3874: // create a row with 2 columns, each column is under the threshold,
3875: // but the row is over the threshold
3876: T_RawStoreRow r4 = new T_RawStoreRow(2);
3877: // create a row that's under the threshold
3878: r4.setColumn(0, 800, REC_001);
3879: r4.setColumn(1, 800, REC_001);
3880: // insert the row twice, should fit on 1 page
3881: rh1 = t_util.t_insertAtSlot(page, 0, r4, (byte) insertFlag,
3882: overflowThreshold);
3883: if (rh1 != null) {
3884: SanityManager.DEBUG_PRINT("bug", "page = " + page);
3885: throw T_Fail
3886: .testFailMsg("insert of 1st 2-column row (OT) should failed.");
3887: }
3888: rh2 = t_util.t_insertAtSlot(page, 0, r4, (byte) insertFlag,
3889: overflowThreshold);
3890: if (rh2 != null)
3891: throw T_Fail
3892: .testFailMsg("insert of 2nd 2-column row (OT) should failed.");
3893: page.unlatch();
3894: page = null;
3895: REPORT("test 4: 2 rows with 2 columns over the threshold not inserted...");
3896:
3897: // cleanup after first part of test.
3898: t_util.t_dropContainer(t, segment, cid); // cleanup
3899: t_util.t_commit(t);
3900: t.close();
3901: PASS("P023");
3902: }
3903:
3904: /**
3905: Insert small rows and update them so that they overflow a page.
3906:
3907: @exception T_Fail Unexpected behaviour from the API
3908: @exception StandardException Unexpected exception from the implementation
3909: */
3910: protected void P030(long segment) throws StandardException, T_Fail {
3911:
3912: Transaction t = t_util.t_startTransaction();
3913:
3914: long cid = t_util.t_addContainer(t, segment, 4096);
3915:
3916: ContainerHandle c = t_util.t_openContainer(t, segment, cid,
3917: true);
3918: Page page = t_util.t_getPage(c,
3919: ContainerHandle.FIRST_PAGE_NUMBER);
3920: t_util.t_checkEmptyPage(page);
3921:
3922: T_RawStoreRow r0 = new T_RawStoreRow(0);
3923: T_RawStoreRow r1 = new T_RawStoreRow((String) null);
3924: T_RawStoreRow r2 = new T_RawStoreRow("0123456789");
3925:
3926: t_util.t_insertAtSlot(page, 0, r0);
3927: t_util.t_insertAtSlot(page, 1, r1);
3928: t_util.t_insertAtSlot(page, 2, r2);
3929:
3930: t_util.t_checkRecordCount(page, 3, 3);
3931: page.unlatch();
3932: page = null;
3933:
3934: // check there is only one page
3935: if (c.getNextPage(ContainerHandle.FIRST_PAGE_NUMBER) != null)
3936: throw T_Fail
3937: .testFailMsg("an extra page has appeared in the container");
3938: t_util.t_commit(t);
3939:
3940: //
3941: // Update the row at slot 1 so that it fills most of the page
3942: //
3943: c = t_util.t_openContainer(t, segment, cid, true);
3944: page = t_util.t_getPage(c, ContainerHandle.FIRST_PAGE_NUMBER);
3945:
3946: t_util.t_checkStringLengthFetch(page, 1, -1);
3947: t_util.t_checkStringLengthFetch(page, 2, 10);
3948:
3949: t_util.t_checkFieldCount(page, 0, 0);
3950: t_util.t_checkFieldCount(page, 1, 1);
3951: t_util.t_checkFieldCount(page, 2, 1);
3952:
3953: T_RawStoreRow r1u = new T_RawStoreRow(String
3954: .valueOf(new char[1937]));
3955: page.updateAtSlot(1, r1u.getRow(), (FormatableBitSet) null);
3956: t_util.t_checkStringLengthFetch(page, 1, 1937); // on page 1
3957: t_util.t_checkStringLengthFetch(page, 2, 10); // on page 1
3958: t_util.t_checkFieldCount(page, 0, 0);
3959: t_util.t_checkFieldCount(page, 1, 1);
3960: t_util.t_checkFieldCount(page, 2, 1);
3961: page.unlatch();
3962: // check there is only one page
3963: if (c.getNextPage(ContainerHandle.FIRST_PAGE_NUMBER) != null)
3964: throw T_Fail
3965: .testFailMsg("an extra page has appeared in the container");
3966: t_util.t_commit(t);
3967:
3968: //
3969: // Update the row at slot 2 so that it overflows
3970: //
3971: c = t_util.t_openContainer(t, segment, cid, true);
3972: T_RawStoreRow r2u = new T_RawStoreRow(String
3973: .valueOf(new char[1099])); // stored length is twice string lenght + 2
3974: page = t_util.t_getPage(c, ContainerHandle.FIRST_PAGE_NUMBER);
3975: page.updateAtSlot(2, r2u.getRow(), (FormatableBitSet) null);
3976: t_util.t_checkStringLengthFetch(page, 1, 1937); // on page 1
3977: t_util.t_checkStringLengthFetch(page, 2, 1099); // on first overflow page
3978: t_util.t_checkFieldCount(page, 0, 0);
3979: t_util.t_checkFieldCount(page, 1, 1);
3980: t_util.t_checkFieldCount(page, 2, 1);
3981: page.unlatch();
3982: // check there is only one page
3983: if (c.getNextPage(ContainerHandle.FIRST_PAGE_NUMBER) != null)
3984: throw T_Fail
3985: .testFailMsg("an extra page has appeared in the container");
3986: t_util.t_commit(t);
3987:
3988: c = t_util.t_openContainer(t, segment, cid, true);
3989: page = t_util.t_getPage(c, ContainerHandle.FIRST_PAGE_NUMBER);
3990: t_util.t_checkStringLengthFetch(page, 1, 1937); // on page 1
3991: t_util.t_checkStringLengthFetch(page, 2, 1099); // on first overflow page
3992: t_util.t_checkFieldCount(page, 0, 0);
3993: t_util.t_checkFieldCount(page, 1, 1);
3994: t_util.t_checkFieldCount(page, 2, 1);
3995: // check there is only one page
3996: if (c.getNextPage(ContainerHandle.FIRST_PAGE_NUMBER) != null)
3997: throw T_Fail
3998: .testFailMsg("an extra page has appeared in the container");
3999: t_util.t_commit(t);
4000:
4001: //
4002: // Update the row at slot 0 so that it overflows onto the same page as the first
4003: // overflow.
4004: //
4005: c = t_util.t_openContainer(t, segment, cid, true);
4006: page = t_util.t_getPage(c, ContainerHandle.FIRST_PAGE_NUMBER);
4007: T_RawStoreRow r0u = new T_RawStoreRow(String
4008: .valueOf(new char[423]));
4009: page.updateAtSlot(0, r0u.getRow(), (FormatableBitSet) null);
4010: t_util.t_checkStringLengthFetch(page, 0, 423); // on first overflow page
4011: t_util.t_checkStringLengthFetch(page, 1, 1937); // on page 1
4012: t_util.t_checkStringLengthFetch(page, 2, 1099); // on first overflow page
4013: t_util.t_checkFieldCount(page, 0, 1);
4014: t_util.t_checkFieldCount(page, 1, 1);
4015: t_util.t_checkFieldCount(page, 2, 1);
4016: page.unlatch();
4017: // check there is only one page
4018: if (c.getNextPage(ContainerHandle.FIRST_PAGE_NUMBER) != null)
4019: throw T_Fail
4020: .testFailMsg("an extra page has appeared in the container");
4021:
4022: t_util.t_commit(t);
4023:
4024: //
4025: // Update the row at slot 0 that has already been overflowed
4026: // but keeping it on the same page
4027: //
4028: c = t_util.t_openContainer(t, segment, cid, true);
4029: page = t_util.t_getPage(c, ContainerHandle.FIRST_PAGE_NUMBER);
4030: r0u = new T_RawStoreRow(String.valueOf(new char[399]));
4031: page.updateAtSlot(0, r0u.getRow(), (FormatableBitSet) null);
4032: t_util.t_checkStringLengthFetch(page, 0, 399); // on first overflow page
4033: t_util.t_checkStringLengthFetch(page, 1, 1937); // on page 1
4034: t_util.t_checkStringLengthFetch(page, 2, 1099); // on first overflow page
4035: t_util.t_checkFieldCount(page, 0, 1);
4036: t_util.t_checkFieldCount(page, 1, 1);
4037: t_util.t_checkFieldCount(page, 2, 1);
4038: page.unlatch();
4039: // check there is only one page
4040: if (c.getNextPage(ContainerHandle.FIRST_PAGE_NUMBER) != null)
4041: throw T_Fail
4042: .testFailMsg("an extra page has appeared in the container");
4043:
4044: //
4045: // Update the row at slot 0 that has already been overflowed
4046: // but moving it to a new page
4047: //
4048: c = t_util.t_openContainer(t, segment, cid, true);
4049: page = t_util.t_getPage(c, ContainerHandle.FIRST_PAGE_NUMBER);
4050: r0u = new T_RawStoreRow(String.valueOf(new char[1400]));
4051: page.updateAtSlot(0, r0u.getRow(), (FormatableBitSet) null);
4052: t_util.t_checkStringLengthFetch(page, 0, 1400); // on second overflow page
4053: t_util.t_checkStringLengthFetch(page, 1, 1937); // on page 1
4054: t_util.t_checkStringLengthFetch(page, 2, 1099); // on first overflow page
4055: t_util.t_checkFieldCount(page, 0, 1);
4056: t_util.t_checkFieldCount(page, 1, 1);
4057: t_util.t_checkFieldCount(page, 2, 1);
4058: page.unlatch();
4059: // check there is only one page
4060: if (c.getNextPage(ContainerHandle.FIRST_PAGE_NUMBER) != null)
4061: throw T_Fail
4062: .testFailMsg("an extra page has appeared in the container");
4063:
4064: if (segment != ContainerHandle.TEMPORARY_SEGMENT) {
4065: t_util.t_dropContainer(t, segment, cid); // cleanup
4066: }
4067:
4068: t_util.t_commit(t);
4069:
4070: t.close();
4071:
4072: PASS("P030: segment = " + segment);
4073: }
4074:
4075: /**
4076: Insert 4-column long rows into 1K pages, each column is less than a page.
4077:
4078: @exception T_Fail Unexpected behaviour from the API
4079: @exception StandardException Unexpected exception from the implementation
4080: */
4081: protected void P031(long segment) throws StandardException, T_Fail {
4082:
4083: Transaction t = t_util.t_startTransaction();
4084:
4085: long cid = t_util.t_addContainer(t, segment, 4096);
4086:
4087: ContainerHandle c = t_util.t_openContainer(t, segment, cid,
4088: true);
4089: Page page = t_util.t_getPage(c,
4090: ContainerHandle.FIRST_PAGE_NUMBER);
4091: t_util.t_checkEmptyPage(page);
4092:
4093: T_RawStoreRow r0 = new T_RawStoreRow(4);
4094: r0.setColumn(0, 256, REC_001);
4095: r0.setColumn(1, 256, REC_002);
4096: r0.setColumn(2, 256, REC_003);
4097: r0.setColumn(3, 256, REC_004);
4098:
4099: int insertFlag = Page.INSERT_INITIAL;
4100: insertFlag |= Page.INSERT_OVERFLOW;
4101:
4102: RecordHandle rh0 = null;
4103: try {
4104: rh0 = t_util.t_insertAtSlot(page, 0, r0, (byte) insertFlag);
4105: } catch (StandardException se) {
4106: throw T_Fail.testFailMsg("insert of long row failed.");
4107: }
4108:
4109: if (rh0 == null)
4110: throw T_Fail
4111: .testFailMsg("insert of first long row failed.");
4112: else {
4113: REPORT("about to check fetch...");
4114: DataValueDescriptor column = new SQLChar();
4115: t_util.t_checkFetchColFromSlot(page,
4116: page.FIRST_SLOT_NUMBER, 0, column, false, REC_001,
4117: 256);
4118: t_util.t_checkFetchColFromSlot(page,
4119: page.FIRST_SLOT_NUMBER, 1, column, false, REC_002,
4120: 256);
4121: t_util.t_checkFetchColFromSlot(page,
4122: page.FIRST_SLOT_NUMBER, 2, column, false, REC_003,
4123: 256);
4124: t_util.t_checkFetchColFromSlot(page,
4125: page.FIRST_SLOT_NUMBER, 3, column, false, REC_004,
4126: 256);
4127: }
4128:
4129: page.unlatch();
4130:
4131: if (segment != ContainerHandle.TEMPORARY_SEGMENT) {
4132: t_util.t_dropContainer(t, segment, cid); // cleanup
4133: }
4134:
4135: t_util.t_commit(t);
4136:
4137: t.close();
4138:
4139: PASS("P031: segment = " + segment);
4140: }
4141:
4142: /**
4143: Insert 60-column long rows into 1K pages, each column is less than a page.
4144:
4145: @exception T_Fail Unexpected behaviour from the API
4146: @exception StandardException Unexpected exception from the implementation
4147: */
4148: protected void P032(long segment) throws StandardException, T_Fail {
4149:
4150: Transaction t = t_util.t_startTransaction();
4151:
4152: long cid = t_util.t_addContainer(t, segment, 4096);
4153:
4154: ContainerHandle c = t_util.t_openContainer(t, segment, cid,
4155: true);
4156: Page page = t_util.t_getPage(c,
4157: ContainerHandle.FIRST_PAGE_NUMBER);
4158: t_util.t_checkEmptyPage(page);
4159:
4160: int insertFlag = Page.INSERT_INITIAL;
4161: insertFlag |= Page.INSERT_OVERFLOW;
4162:
4163: T_RawStoreRow r0 = new T_RawStoreRow(60);
4164: for (int i = 0; i < 60; i++) {
4165: r0.setColumn(i, 1200, REC_001);
4166: }
4167:
4168: RecordHandle rh0 = null;
4169: try {
4170: rh0 = t_util.t_insertAtSlot(page, 0, r0, (byte) insertFlag);
4171: } catch (StandardException se) {
4172: throw T_Fail
4173: .testFailMsg("insert of first long row failed.");
4174: }
4175:
4176: if (rh0 == null)
4177: throw T_Fail
4178: .testFailMsg("insert of a 60-column (300 bytes per column) row failed.");
4179: else {
4180: REPORT("about to check fetch the first long row inserted...");
4181: DataValueDescriptor column = new SQLChar();
4182: for (int i = 0; i < 60; i++) {
4183: t_util.t_checkFetchColFromSlot(page,
4184: page.FIRST_SLOT_NUMBER, i, column, false,
4185: REC_001, 1200);
4186: }
4187: }
4188:
4189: // create a new row with 60 columns, and each column has REC_001 = "McLaren"
4190: for (int i = 0; i < 60; i++) {
4191: r0.setColumn(i, REC_001);
4192: }
4193:
4194: RecordHandle rh1 = null;
4195: try {
4196: rh1 = t_util.t_insertAtSlot(page, 1, r0, (byte) insertFlag);
4197: } catch (StandardException se) {
4198: throw T_Fail
4199: .testFailMsg("insert of second long row failed.");
4200: }
4201:
4202: if (rh1 == null) {
4203: throw T_Fail
4204: .testFailMsg("insert of a 60-column (~10 bytes per column) row failed.");
4205: } else {
4206: REPORT("about to check fetch the second long row inserted ...");
4207: DataValueDescriptor column = new SQLChar();
4208: for (int i = 0; i < 60; i++) {
4209: t_util.t_checkFetchColFromSlot(page, 1, i, column,
4210: false, REC_001);
4211: }
4212: }
4213:
4214: page.unlatch();
4215:
4216: if (segment != ContainerHandle.TEMPORARY_SEGMENT) {
4217: t_util.t_dropContainer(t, segment, cid); // cleanup
4218: }
4219:
4220: t_util.t_commit(t);
4221:
4222: t.close();
4223:
4224: PASS("P032: segment = " + segment);
4225: }
4226:
4227: /**
4228: Insert 100-column long rows into 1K pages, each column is less than a page.
4229:
4230: @exception T_Fail Unexpected behaviour from the API
4231: @exception StandardException Unexpected exception from the implementation
4232: */
4233: protected void P033(long segment) throws StandardException, T_Fail {
4234:
4235: Transaction t = t_util.t_startTransaction();
4236:
4237: long cid = t_util.t_addContainer(t, segment, 4096);
4238:
4239: ContainerHandle c = t_util.t_openContainer(t, segment, cid,
4240: true);
4241: Page page = t_util.t_getPage(c,
4242: ContainerHandle.FIRST_PAGE_NUMBER);
4243: try {
4244: t_util.t_checkEmptyPage(page);
4245:
4246: T_RawStoreRow r0 = new T_RawStoreRow(100);
4247: for (int i = 0; i < 100; i++) {
4248: r0.setColumn(i, REC_007);
4249: }
4250:
4251: int insertFlag = Page.INSERT_INITIAL | Page.INSERT_OVERFLOW;
4252:
4253: RecordHandle rh0 = null;
4254: try {
4255: rh0 = t_util.t_insertAtSlot(page, 0, r0,
4256: (byte) insertFlag);
4257: } catch (StandardException se) {
4258: throw T_Fail.testFailMsg("insert of long row failed.");
4259: }
4260:
4261: if (rh0 == null)
4262: throw T_Fail
4263: .testFailMsg("insert of first long row failed.");
4264: else {
4265: REPORT("about to check fetch...");
4266: DataValueDescriptor column = new SQLChar();
4267: for (int i = 0; i < 100; i++) {
4268: t_util.t_checkFetchColFromSlot(page,
4269: page.FIRST_SLOT_NUMBER, i, column, false,
4270: REC_007);
4271: }
4272: }
4273:
4274: page.unlatch();
4275: page = null;
4276: if (segment != ContainerHandle.TEMPORARY_SEGMENT) {
4277: t_util.t_dropContainer(t, segment, cid); // cleanup
4278: }
4279:
4280: } finally {
4281: if (page != null)
4282: page.unlatch();
4283: t_util.t_commit(t);
4284: t.close();
4285: }
4286:
4287: PASS("P033: segment = " + segment);
4288: }
4289:
4290: /**
4291: Insert 401 column long row with many small columns in the beginning,
4292: and one large column at the end into 4K pages.
4293:
4294: @exception T_Fail Unexpected behaviour from the API
4295: @exception StandardException Unexpected exception from the implementation
4296: */
4297: protected void P034(long segment) throws StandardException, T_Fail {
4298:
4299: Transaction t = t_util.t_startTransaction();
4300:
4301: long cid = t_util.t_addContainer(t, segment, 4096);
4302:
4303: ContainerHandle c = t_util.t_openContainer(t, segment, cid,
4304: true);
4305: Page page = t_util.t_getPage(c,
4306: ContainerHandle.FIRST_PAGE_NUMBER);
4307: try {
4308: t_util.t_checkEmptyPage(page);
4309:
4310: int insertFlag = Page.INSERT_INITIAL | Page.INSERT_OVERFLOW;
4311:
4312: T_RawStoreRow r1 = new T_RawStoreRow(401);
4313: for (int i = 0; i < 400; i++)
4314: r1.setColumn(i, REC_001);
4315: r1.setColumn(400, 1500, REC_001);
4316: RecordHandle rh = t_util.t_insertAtSlot(page, 0, r1,
4317: (byte) insertFlag);
4318: t_util.t_checkFetch(page, rh, r1);
4319: page.unlatch();
4320: page = null;
4321: if (segment != ContainerHandle.TEMPORARY_SEGMENT) {
4322: t_util.t_dropContainer(t, segment, cid); // cleanup
4323: }
4324:
4325: } finally {
4326: if (page != null)
4327: page.unlatch();
4328:
4329: t_util.t_commit(t);
4330: t.close();
4331: }
4332:
4333: PASS("P034: segment = " + segment);
4334: }
4335:
4336: /**
4337: Insert a single long column long row into a 1K page.
4338:
4339: @exception T_Fail Unexpected behaviour from the API
4340: @exception StandardException Unexpected exception from the implementation
4341: */
4342: protected void P035(long segment) throws StandardException, T_Fail {
4343:
4344: Transaction t = t_util.t_startTransaction();
4345:
4346: long cid = t_util.t_addContainer(t, segment, 4096);
4347:
4348: ContainerHandle c = t_util.t_openContainer(t, segment, cid,
4349: true);
4350: Page page = t_util.t_getPage(c,
4351: ContainerHandle.FIRST_PAGE_NUMBER);
4352: try {
4353: t_util.t_checkEmptyPage(page);
4354:
4355: int insertFlag = Page.INSERT_INITIAL | Page.INSERT_OVERFLOW;
4356:
4357: T_RawStoreRow r1 = new T_RawStoreRow(1);
4358: // insert a long column
4359: r1.setColumn(0, 500, REC_001);
4360: RecordHandle rh1 = t_util.t_insertAtSlot(page, 0, r1,
4361: (byte) insertFlag);
4362: t_util.t_checkFetch(page, rh1, r1);
4363: REPORT("row 1 inserted...");
4364:
4365: // insert a 6 column row, every other column is long
4366: T_RawStoreRow r2 = new T_RawStoreRow(6);
4367: r2.setColumn(0, 400, REC_001); // this takes 800 bytes
4368: r2.setColumn(1, 500, REC_002); // this takes 1000 bytes
4369: r2.setColumn(2, 400, REC_001);
4370: r2.setColumn(3, 500, REC_002);
4371: r2.setColumn(4, 400, REC_001);
4372: r2.setColumn(5, 500, REC_002);
4373: RecordHandle rh2 = t_util.t_insertAtSlot(page, 0, r2,
4374: (byte) insertFlag);
4375: t_util.t_checkFetch(page, rh2, r2);
4376: REPORT("row 2 inserted...");
4377:
4378: // insert a long column
4379: r1.setColumn(0, 1500, REC_001);
4380: RecordHandle rh3 = t_util.t_insertAtSlot(page, 0, r1,
4381: (byte) insertFlag);
4382: if (rh3 != null)
4383: throw T_Fail
4384: .testFailMsg("expect the 3rd row to not fit on page");
4385:
4386: page.unlatch();
4387: page = null;
4388:
4389: if (segment != ContainerHandle.TEMPORARY_SEGMENT) {
4390: t_util.t_dropContainer(t, segment, cid); // cleanup
4391: }
4392:
4393: } finally {
4394: if (page != null)
4395: page.unlatch();
4396:
4397: t_util.t_commit(t);
4398: t.close();
4399: }
4400:
4401: PASS("P035: segment = " + segment);
4402: }
4403:
4404: /**
4405: Test space reclaimation - purging of a long row gets back all
4406: the row pieces.
4407:
4408: @exception T_Fail Unexpected behaviour from the API
4409: @exception StandardException Unexpected exception from the implementation
4410: */
4411: protected void P036() throws StandardException, T_Fail {
4412: long segment = 0;
4413: Transaction t = t_util.t_startTransaction();
4414: long cid = t_util.t_addContainer(t, segment, 4096);
4415:
4416: ContainerHandle c = t_util.t_openContainer(t, segment, cid,
4417: true);
4418: Page page = t_util.t_getPage(c,
4419: ContainerHandle.FIRST_PAGE_NUMBER);
4420: try {
4421: t_util.t_checkEmptyPage(page);
4422:
4423: int insertFlag = Page.INSERT_INITIAL | Page.INSERT_OVERFLOW;
4424:
4425: // insert a row with 400 columns from 200 to 400 bytes each and make it
4426: // sprawl across many pages.
4427: T_RawStoreRow r1 = new T_RawStoreRow(400);
4428: for (int i = 0; i < 400; i++)
4429: r1.setColumn(i, 100 + i, REC_001);
4430:
4431: RecordHandle rh1 = t_util.t_insertAtSlot(page, 0, r1,
4432: (byte) insertFlag);
4433: t_util.t_checkFetch(page, rh1, r1);
4434:
4435: Page nextPage = t_util.t_addPage(c);
4436: long nextPageNumber = nextPage.getPageNumber();
4437: // deallocate it
4438: t_util.t_removePage(c, nextPage);
4439:
4440: REPORT("P036 - Nextpage is " + nextPageNumber);
4441: page.unlatch();
4442: page = null;
4443: t_util.t_commit(t);
4444:
4445: // See what the next page is.
4446: c = t_util.t_openContainer(t, segment, cid, true);
4447:
4448: // Now purge that first row.
4449: page = t_util.t_getPage(c,
4450: ContainerHandle.FIRST_PAGE_NUMBER);
4451:
4452: t_util.t_checkRecordCount(page, 1, 1);
4453: page.purgeAtSlot(0, 1, logDataForPurges);
4454:
4455: t_util.t_checkEmptyPage(page);
4456: page.unlatch();
4457: page = null;
4458: t_util.t_commit(t);
4459:
4460: // give some time for post commit to finish
4461: t_util.t_wait(10); // wait 10 milliseconds.
4462:
4463: // reinsert r1, it should use no extra page than last time.
4464: c = t_util.t_openContainer(t, segment, cid, true);
4465: page = t_util.t_getPage(c,
4466: ContainerHandle.FIRST_PAGE_NUMBER);
4467:
4468: RecordHandle rh2 = t_util.t_insertAtSlot(page, 0, r1,
4469: (byte) insertFlag);
4470: t_util.t_checkFetch(page, rh2, r1);
4471: page.unlatch();
4472: page = null;
4473:
4474: // now verify that it used up no more page than last time
4475: nextPage = t_util.t_addPage(c);
4476: long checkNextPageNumber = nextPage.getPageNumber();
4477: nextPage.unlatch();
4478:
4479: if (nextPageNumber != checkNextPageNumber)
4480: throw T_Fail
4481: .testFailMsg("fail to reuse row pieces expect next page="
4482: + nextPageNumber
4483: + " but got "
4484: + checkNextPageNumber);
4485:
4486: t_util.t_commit(t);
4487:
4488: // Purge them and roll them back via savepoint. These should not
4489: // be reclaimed.
4490: c = t_util.t_openContainer(t, segment, cid, true);
4491: t.setSavePoint(SP1, null);
4492: page = t_util.t_getPage(c,
4493: ContainerHandle.FIRST_PAGE_NUMBER);
4494: t_util.t_checkRecordCount(page, 1, 1);
4495: page.purgeAtSlot(0, 1, logDataForPurges);
4496: page.unlatch();
4497: page = null;
4498:
4499: // make sure we cannot get our hands on a page that is freed up by
4500: // the purge
4501: Page testPage = t_util.t_addPage(c);
4502: T_RawStoreRow testRow = new T_RawStoreRow(REC_001);
4503: t_util.t_insert(testPage, testRow);
4504: testPage.unlatch();
4505:
4506: t.rollbackToSavePoint(SP1, null);
4507:
4508: testPage = t_util.t_addPage(c);
4509: t_util.t_insert(testPage, testRow);
4510: testPage.unlatch();
4511:
4512: t_util.t_commit(t);
4513: t_util.t_wait(10);
4514:
4515: c = t_util.t_openContainer(t, segment, cid, true);
4516:
4517: testPage = t_util.t_addPage(c);
4518: t_util.t_insert(testPage, testRow);
4519: testPage.unlatch();
4520:
4521: //when container is in unlogged mode, the check is untru,
4522: //because rollback to save point would have done nothing.
4523: //so purge was not rolled back. The row does not exist any more
4524: if ((openMode & ContainerHandle.MODE_UNLOGGED) == 0) {
4525: page = t_util.t_getPage(c,
4526: ContainerHandle.FIRST_PAGE_NUMBER);
4527: if (logDataForPurges) {
4528: t_util.t_checkFetch(page, rh2, r1);
4529: } else {
4530: //when data is not logged for purges ,
4531: //in this particular first four columns becomes null becuase
4532: //first 4 fileds data are on the 1st page and do not get
4533: //logged during pruge and
4534: //the rest of the columns gets the data back because they
4535: //are removed page by page.
4536: T_RawStoreRow r1_wnl = new T_RawStoreRow(400);
4537: for (int i = 0; i < 18; i++)
4538: r1_wnl.setColumn(i, 4, REC_NULL);
4539: for (int i = 18; i < 400; i++)
4540: r1_wnl.setColumn(i, 100 + i, REC_001);
4541: t_util.t_checkFetch(page, rh2, r1_wnl);
4542: }
4543: page.unlatch();
4544: page = null;
4545: }
4546:
4547: t_util.t_dropContainer(t, segment, cid); // cleanup
4548:
4549: } finally {
4550: if (page != null)
4551: page.unlatch();
4552: t_util.t_commit(t);
4553: t.close();
4554: }
4555:
4556: PASS("P036");
4557: }
4558:
4559: /**
4560: Test space reclaimation - purging of a row with serveral long columns
4561: get back all the column chains.
4562:
4563: @exception T_Fail Unexpected behaviour from the API
4564: @exception StandardException Unexpected exception from the implementation
4565: */
4566: protected void P037() throws StandardException, T_Fail {
4567: // Insert the 3 rows in P035, then purge them and reinsert them and
4568: // make sure it reuses all the pages from last time.
4569:
4570: long segment = 0;
4571: Transaction t = t_util.t_startTransaction();
4572: long cid = t_util.t_addContainer(t, segment, 4096);
4573:
4574: ContainerHandle c = t_util.t_openContainer(t, segment, cid,
4575: true);
4576: Page page = t_util.t_getPage(c,
4577: ContainerHandle.FIRST_PAGE_NUMBER);
4578: try {
4579: t_util.t_checkEmptyPage(page);
4580:
4581: int insertFlag = Page.INSERT_INITIAL | Page.INSERT_OVERFLOW;
4582: T_RawStoreRow r1 = new T_RawStoreRow(1);
4583: // insert a long column
4584: r1.setColumn(0, 5500, REC_001);
4585: RecordHandle rh1 = t_util.t_insertAtSlot(page, 0, r1,
4586: (byte) insertFlag);
4587: t_util.t_checkFetch(page, rh1, r1);
4588:
4589: // insert a 6 column row, every other column is long, sizes
4590: // picked so that 2 rows fit, but 3rd row won't fit even if whole
4591: // row is overflowed.
4592: T_RawStoreRow r2 = new T_RawStoreRow(6);
4593: r2.setColumn(0, 660, REC_001); // this takes ~1320 bytes
4594: r2.setColumn(1, 5000, REC_002); // this takes ~10000 bytes
4595: r2.setColumn(2, 660, REC_001);
4596: r2.setColumn(3, 5000, REC_002);
4597: r2.setColumn(4, 660, REC_001);
4598: r2.setColumn(5, 5000, REC_002);
4599: RecordHandle rh2 = t_util.t_insertAtSlot(page, 0, r2,
4600: (byte) insertFlag);
4601: t_util.t_checkFetch(page, rh2, r2);
4602:
4603: // insert a long column - this should fail
4604: RecordHandle rh3 = t_util.t_insertAtSlot(page, 0, r1,
4605: (byte) insertFlag);
4606: if (rh3 != null) {
4607: throw T_Fail
4608: .testFailMsg("expect the 3rd row to not fit on page");
4609: }
4610:
4611: page.unlatch();
4612: page = null;
4613:
4614: Page nextPage = t_util.t_addPage(c);
4615: long nextPageNumber = nextPage.getPageNumber();
4616: // deallocate it
4617: t_util.t_removePage(c, nextPage);
4618:
4619: REPORT("P037 - Nextpage is " + nextPageNumber);
4620:
4621: t_util.t_commit(t);
4622:
4623: // now purge them
4624: c = t_util.t_openContainer(t, segment, cid, true);
4625: page = t_util.t_getPage(c,
4626: ContainerHandle.FIRST_PAGE_NUMBER);
4627:
4628: t_util.t_checkRecordCount(page, 2, 2);
4629: page.purgeAtSlot(0, 2, logDataForPurges);
4630: t_util.t_checkEmptyPage(page);
4631: page.unlatch();
4632: page = null;
4633:
4634: t_util.t_commit(t);
4635:
4636: // give some time for post commit to finish
4637: t_util.t_wait(10); // wait 10 milliseconds.
4638:
4639: // reinsert all 3 of them again, exactly the same way.
4640: c = t_util.t_openContainer(t, segment, cid, true);
4641: page = t_util.t_getPage(c,
4642: ContainerHandle.FIRST_PAGE_NUMBER);
4643:
4644: rh1 = t_util.t_insertAtSlot(page, 0, r1, (byte) insertFlag);
4645: rh2 = t_util.t_insertAtSlot(page, 0, r2, (byte) insertFlag);
4646: rh3 = t_util.t_insertAtSlot(page, 0, r1, (byte) insertFlag);
4647: t_util.t_checkFetch(page, rh1, r1);
4648: t_util.t_checkFetch(page, rh2, r2);
4649: if (rh3 != null)
4650: throw T_Fail
4651: .testFailMsg("expect the 3rd row to not fit on page");
4652: page.unlatch();
4653: page = null;
4654:
4655: nextPage = t_util.t_addPage(c);
4656: long checkNextPageNumber = nextPage.getPageNumber();
4657: nextPage.unlatch();
4658:
4659: if (nextPageNumber != checkNextPageNumber)
4660: throw T_Fail
4661: .testFailMsg("fail to reuse row pieces expect next page="
4662: + nextPageNumber
4663: + " but got "
4664: + checkNextPageNumber);
4665:
4666: t_util.t_commit(t);
4667:
4668: // Purge them and roll them back via savepoint. These should not
4669: // be reclaimed.
4670: c = t_util.t_openContainer(t, segment, cid, true);
4671:
4672: t.setSavePoint(SP1, null);
4673: page = t_util.t_getPage(c,
4674: ContainerHandle.FIRST_PAGE_NUMBER);
4675:
4676: t_util.t_checkRecordCount(page, 2, 2);
4677: page.purgeAtSlot(0, 2, logDataForPurges);
4678: t_util.t_checkEmptyPage(page);
4679:
4680: page.unlatch();
4681: page = null;
4682:
4683: // make sure we cannot get our hands on a page that is freed up by
4684: // the purge
4685: Page testPage = t_util.t_addPage(c);
4686: T_RawStoreRow testRow = new T_RawStoreRow(REC_001);
4687: t_util.t_insert(testPage, testRow);
4688: testPage.unlatch();
4689:
4690: t.rollbackToSavePoint(SP1, null);
4691:
4692: testPage = t_util.t_addPage(c);
4693: t_util.t_insert(testPage, testRow);
4694: testPage.unlatch();
4695:
4696: t_util.t_commit(t);
4697:
4698: // give some time for post commit to finish
4699: t_util.t_wait(10);
4700:
4701: // check to make sure post commit did not reclaim those rows.
4702: c = t_util.t_openContainer(t, segment, cid, true);
4703:
4704: testPage = t_util.t_addPage(c);
4705: t_util.t_insert(testPage, testRow);
4706: testPage.unlatch();
4707:
4708: page = t_util.t_getPage(c,
4709: ContainerHandle.FIRST_PAGE_NUMBER);
4710:
4711: t_util.t_checkRecordCount(page, 2, 2);
4712: t_util.t_checkFetch(page, rh1, r1);
4713:
4714: if (logDataForPurges)
4715: t_util.t_checkFetch(page, rh2, r2);
4716: else {
4717:
4718: // During purges when data is not logged when slots are purged
4719: // they become null on rollback and some cases like long columns
4720: // we remove the wholepage on rollback we get the data back.
4721: T_RawStoreRow r2_wnl = new T_RawStoreRow(6);
4722: r2_wnl.setColumn(0, 4, REC_NULL);
4723: r2_wnl.setColumn(1, 5000, REC_002);
4724: r2_wnl.setColumn(2, 4, REC_NULL);
4725: r2_wnl.setColumn(3, 5000, REC_002);
4726: r2_wnl.setColumn(4, 4, REC_NULL);
4727: r2_wnl.setColumn(5, 5000, REC_002);
4728: t_util.t_checkFetch(page, rh2, r2_wnl);
4729: }
4730:
4731: page.unlatch();
4732: page = null;
4733:
4734: t_util.t_dropContainer(t, segment, cid); // cleanup
4735:
4736: } finally {
4737: if (page != null)
4738: page.unlatch();
4739: t_util.t_commit(t);
4740: t.close();
4741: }
4742:
4743: PASS("P037");
4744:
4745: }
4746:
4747: /**
4748: Test space reclaimation - rollback of an insert (with purge) of a row
4749: that overflows and with long column get back all the space in the row
4750: and column chain.
4751:
4752: @exception T_Fail Unexpected behaviour from the API
4753: @exception StandardException Unexpected exception from the implementation
4754: */
4755: protected void P038() throws StandardException, T_Fail {
4756: long segment = 0;
4757:
4758: // Insert the 3 rows in P035, then abort the insert.
4759: // Reinsert them and make sure it reuses all the pages from last time.
4760: Transaction t = t_util.t_startTransaction();
4761: long cid = t_util.t_addContainer(t, segment, 4096);
4762: t_util.t_commit(t);
4763:
4764: ContainerHandle c = t_util.t_openContainer(t, segment, cid,
4765: true);
4766: Page page = t_util.t_getPage(c,
4767: ContainerHandle.FIRST_PAGE_NUMBER);
4768: try {
4769: t_util.t_checkEmptyPage(page);
4770:
4771: int insertFlag = Page.INSERT_INITIAL | Page.INSERT_OVERFLOW
4772: | Page.INSERT_UNDO_WITH_PURGE;
4773:
4774: T_RawStoreRow r1 = new T_RawStoreRow(1);
4775: // insert a long column
4776: r1.setColumn(0, 1500, REC_001);
4777: RecordHandle rh1 = t_util.t_insertAtSlot(page, 0, r1,
4778: (byte) insertFlag);
4779:
4780: // insert a 6 column row, every other column is long
4781: T_RawStoreRow r2 = new T_RawStoreRow(6);
4782: r2.setColumn(0, 400, REC_001); // this takes ~800 bytes
4783: r2.setColumn(1, 500, REC_002); // this takes ~1000 bytes
4784: r2.setColumn(2, 400, REC_001);
4785: r2.setColumn(3, 500, REC_002);
4786: r2.setColumn(4, 400, REC_001);
4787: r2.setColumn(5, 500, REC_002);
4788: RecordHandle rh2 = t_util.t_insertAtSlot(page, 0, r2,
4789: (byte) insertFlag);
4790:
4791: // insert a long column
4792: RecordHandle rh3 = t_util.t_insertAtSlot(page, 0, r1,
4793: (byte) insertFlag);
4794: if (rh3 != null)
4795: throw T_Fail
4796: .testFailMsg("expect the 3rd row to not fit on page");
4797: page = null;
4798:
4799: Page nextPage = t_util.t_addPage(c);
4800: long nextPageNumber = nextPage.getPageNumber();
4801: // deallocate it
4802: t_util.t_removePage(c, nextPage);
4803:
4804: REPORT("P038 - Nextpage is " + nextPageNumber);
4805:
4806: t_util.t_abort(t);
4807:
4808: // the abort rolled back the removal of nextPage also, redo the removed
4809: c = t_util.t_openContainer(t, segment, cid, true);
4810: nextPage = t_util.t_getPage(c, nextPageNumber);
4811: t_util.t_removePage(c, nextPage);
4812: t_util.t_commit(t);
4813:
4814: // reinsert the 3 rows, they should not take up any more space than
4815: // last time.
4816: c = t_util.t_openContainer(t, segment, cid, true);
4817: page = t_util.t_getPage(c,
4818: ContainerHandle.FIRST_PAGE_NUMBER);
4819:
4820: t_util.t_checkEmptyPage(page);
4821:
4822: rh1 = t_util.t_insertAtSlot(page, 0, r1, (byte) insertFlag);
4823: rh2 = t_util.t_insertAtSlot(page, 0, r2, (byte) insertFlag);
4824: rh3 = t_util.t_insertAtSlot(page, 0, r1, (byte) insertFlag);
4825:
4826: t_util.t_checkFetch(page, rh1, r1);
4827: t_util.t_checkFetch(page, rh2, r2);
4828: if (rh3 != null)
4829: throw T_Fail
4830: .testFailMsg("expect the 3rd row to not fit on page");
4831:
4832: page.unlatch();
4833: page = null;
4834:
4835: nextPage = t_util.t_addPage(c);
4836: long checkNextPageNumber = nextPage.getPageNumber();
4837: nextPage.unlatch();
4838:
4839: if (nextPageNumber != checkNextPageNumber)
4840: throw T_Fail
4841: .testFailMsg("fail to reuse row pieces expect next page="
4842: + nextPageNumber
4843: + " but got "
4844: + checkNextPageNumber);
4845:
4846: t_util.t_dropContainer(t, segment, cid); // cleanup
4847:
4848: } finally {
4849: if (page != null)
4850: page.unlatch();
4851: t_util.t_commit(t);
4852: t.close();
4853: }
4854:
4855: PASS("P038");
4856: }
4857:
4858: /**
4859: Test space reclaimation - shrink a head row piece.
4860:
4861: @exception T_Fail Unexpected behaviour from the API
4862: @exception StandardException Unexpected exception from the implementation
4863: */
4864: protected void P039() throws StandardException, T_Fail {
4865: // insert 3 2K rows of 3 columns, size (100, 1500, 400), into an 8K
4866: // page, then fill up the page with 1K rows.
4867: //
4868: // 1. Update the first 2K row so that the 2nd and 3rd column gets moved
4869: // to another page. See that we can insert at least 1 more 1K row into
4870: // the page.
4871: //
4872: // 2. Update the second 2K row so that the 2nd column becomes a long
4873: // column. See that we can insert at least 1 more 1K row into the
4874: // page.
4875: //
4876: // 3. Update the third 2K row so that the column size shrinks to (200,
4877: // 200, 200). See that we can insert at least 1 more 1K row into the
4878: // page.
4879:
4880: long segment = 0;
4881: Transaction t = t_util.t_startTransaction();
4882: long cid = t_util.t_addContainer(t, segment, 8 * 1024);
4883:
4884: T_RawStoreRow bigRow = new T_RawStoreRow(3);
4885: bigRow.setColumn(0, 50, REC_001); // remember each char takes 2 bytes
4886: bigRow.setColumn(1, 750, REC_002);
4887: bigRow.setColumn(2, 200, REC_003);
4888:
4889: ContainerHandle c = t_util.t_openContainer(t, segment, cid,
4890: true);
4891: Page page = t_util.t_getPage(c,
4892: ContainerHandle.FIRST_PAGE_NUMBER);
4893: try {
4894: RecordHandle rh1 = t_util.t_insert(page, bigRow);
4895: RecordHandle rh2 = t_util.t_insert(page, bigRow);
4896: RecordHandle rh3 = t_util.t_insert(page, bigRow);
4897:
4898: t_util.t_checkFetch(page, rh1, bigRow);
4899: t_util.t_checkFetch(page, rh2, bigRow);
4900: t_util.t_checkFetch(page, rh3, bigRow);
4901:
4902: // now fill up the page with smaller rows
4903: T_RawStoreRow smallRow = new T_RawStoreRow(1);
4904: smallRow.setColumn(0, 500, REC_004);
4905:
4906: while (page.spaceForInsert()) {
4907: if (t_util.t_insert(page, smallRow) == null)
4908: break;
4909: }
4910: REPORT("P039: " + (page.recordCount() - 3)
4911: + " small rows have been inserted");
4912: page.unlatch();
4913: page = null;
4914:
4915: t_util.t_commit(t);
4916:
4917: // (1) update rh1 so that column 2 and 3 are moved off page
4918: bigRow.setColumn(1, 2000, REC_005);
4919: c = t_util.t_openContainer(t, segment, cid, true);
4920:
4921: page = t_util.t_getPage(c,
4922: ContainerHandle.FIRST_PAGE_NUMBER);
4923: page.update(rh1, bigRow.getRow(), (FormatableBitSet) null);
4924: t_util.t_checkFetch(page, rh1, bigRow);
4925: page.unlatch();
4926: page = null;
4927: t_util.t_commit(t);
4928:
4929: t_util.t_wait(10); // wait for post commit to get processed.
4930:
4931: c = t_util.t_openContainer(t, segment, cid, true);
4932: page = t_util.t_getPage(c,
4933: ContainerHandle.FIRST_PAGE_NUMBER);
4934:
4935: if (t_util.t_insert(page, smallRow) == null)
4936: throw T_Fail
4937: .testFailMsg("expect row to have shrunk (1)");
4938:
4939: // fill it up again
4940: while (page.spaceForInsert()) {
4941: if (t_util.t_insert(page, smallRow) == null)
4942: break;
4943: }
4944: REPORT("P039: " + (page.recordCount() - 3)
4945: + " small rows have been inserted");
4946:
4947: page.unlatch();
4948: page = null;
4949:
4950: t_util.t_commit(t);
4951:
4952: // (2) update rh2 so that column 2 becomes a long column
4953: FormatableBitSet colList = new FormatableBitSet(2);
4954: colList.set(1); // update column 1, the second column
4955: // use sparse rows
4956: T_RawStoreRow partialRow = new T_RawStoreRow(2);
4957: partialRow.setColumn(1, 8000, REC_006);
4958:
4959: c = t_util.t_openContainer(t, segment, cid, true);
4960:
4961: page = t_util.t_getPage(c,
4962: ContainerHandle.FIRST_PAGE_NUMBER);
4963:
4964: page.update(rh2, partialRow.getRow(), colList);
4965:
4966: bigRow.setColumn(1, 8000, REC_006);
4967: t_util.t_checkFetch(page, rh2, bigRow);
4968: page.unlatch();
4969: page = null;
4970: t_util.t_commit(t);
4971:
4972: t_util.t_wait(10); // wait for post commit to get processed.
4973:
4974: c = t_util.t_openContainer(t, segment, cid, true);
4975: page = t_util.t_getPage(c,
4976: ContainerHandle.FIRST_PAGE_NUMBER);
4977: if (t_util.t_insert(page, smallRow) == null)
4978: throw T_Fail
4979: .testFailMsg("expect row to have shrunk (2)");
4980:
4981: // fill it up again
4982: while (page.spaceForInsert()) {
4983: if (t_util.t_insert(page, smallRow) == null)
4984: break;
4985: }
4986: REPORT("P039: " + (page.recordCount() - 3)
4987: + " small rows have been inserted");
4988:
4989: page.unlatch();
4990: page = null;
4991:
4992: t_util.t_commit(t);
4993:
4994: // (3) - update rh3 to have (200, 400, 400) bytes columns
4995: bigRow.setColumn(0, 100, REC_001);
4996: bigRow.setColumn(1, 200, REC_002);
4997: bigRow.setColumn(2, 200, REC_003);
4998:
4999: c = t_util.t_openContainer(t, segment, cid, true);
5000: page = t_util.t_getPage(c,
5001: ContainerHandle.FIRST_PAGE_NUMBER);
5002: page.update(rh3, bigRow.getRow(), (FormatableBitSet) null);
5003: t_util.t_checkFetch(page, rh3, bigRow);
5004: page.unlatch();
5005: page = null;
5006: t_util.t_commit(t);
5007:
5008: t_util.t_wait(10); // wait for post commit to get processed.
5009:
5010: c = t_util.t_openContainer(t, segment, cid, true);
5011: page = t_util.t_getPage(c,
5012: ContainerHandle.FIRST_PAGE_NUMBER);
5013:
5014: if (t_util.t_insert(page, smallRow) == null)
5015: throw T_Fail
5016: .testFailMsg("expect row to have shrunk (3)");
5017: page.unlatch();
5018: page = null;
5019:
5020: t_util.t_dropContainer(t, segment, cid); // cleanup
5021: } finally {
5022: if (page != null)
5023: page.unlatch();
5024: t_util.t_commit(t);
5025: t.close();
5026: }
5027:
5028: PASS("P039");
5029: }
5030:
5031: /**
5032: Test space reclaimation - shrink a non head row piece.
5033:
5034: @exception T_Fail Unexpected behaviour from the API
5035: @exception StandardException Unexpected exception from the implementation
5036: */
5037: protected void P040() throws StandardException, T_Fail {
5038: // Manufacture a row that has a small head row piece, a large 2nd row
5039: // piece and a small third row piece.
5040: // Using the same head page, add a second row that has a small head row
5041: // piece and a medium sized 2nd row piece, a new overflow page should
5042: // be allocated.
5043: // Update the first row to now have a small 2nd row piece.
5044: // Using the same head page, add a third row that has a small head row
5045: // piece and a medium sized 2nd row piece, no new overflow page should
5046: // be allocated.
5047:
5048: long segment = 0;
5049: Transaction t = t_util.t_startTransaction();
5050: long cid = t_util.t_addContainer(t, 0, 4096);
5051: ContainerHandle c = t_util.t_openContainer(t, segment, cid,
5052: true);
5053:
5054: Page page = t_util.t_getPage(c,
5055: ContainerHandle.FIRST_PAGE_NUMBER);
5056: try {
5057: int insertFlag = Page.INSERT_INITIAL | Page.INSERT_OVERFLOW
5058: | Page.INSERT_UNDO_WITH_PURGE;
5059:
5060: T_RawStoreRow row1 = new T_RawStoreRow(3);
5061: row1.setColumn(0, 400, REC_001);
5062: row1.setColumn(1, 800, REC_002); // this takes ~1600 bytes
5063: row1.setColumn(2, 400, REC_003);
5064: RecordHandle rh1 = t_util.t_insertAtSlot(page, 0, row1,
5065: (byte) insertFlag);
5066:
5067: t_util.t_checkFetch(page, rh1, row1);
5068:
5069: page.unlatch();
5070: page = null;
5071: t_util.t_commit(t);
5072:
5073: c = t_util.t_openContainer(t, segment, cid, true);
5074: Page nextPage = t_util.t_addPage(c);
5075:
5076: // remember where next page is
5077: long nextPageNumber = nextPage.getPageNumber();
5078: t_util.t_removePage(c, nextPage);
5079: t_util.t_commit(t);
5080:
5081: T_RawStoreRow row2 = new T_RawStoreRow(3);
5082: row2.setColumn(0, 1200, REC_001);
5083: row2.setColumn(1, 1200, REC_002);
5084: row2.setColumn(2, 400, REC_003);
5085:
5086: c = t_util.t_openContainer(t, segment, cid, true);
5087: page = t_util.t_getPage(c,
5088: ContainerHandle.FIRST_PAGE_NUMBER);
5089: RecordHandle rh2 = t_util.t_insertAtSlot(page, 1, row2,
5090: (byte) insertFlag);
5091:
5092: t_util.t_checkFetch(page, rh2, row2);
5093: page.unlatch();
5094: page = null;
5095:
5096: // this should have allocated more overflow page
5097: nextPage = t_util.t_addPage(c);
5098: long checkNextPageNumber = nextPage.getPageNumber();
5099: if (checkNextPageNumber == nextPageNumber)
5100: throw T_Fail
5101: .testFailMsg("expected to allocate more pages");
5102: t_util.t_removePage(c, nextPage);
5103: t_util.t_commit(t);
5104:
5105: // now this is the next free page
5106: nextPageNumber = checkNextPageNumber;
5107:
5108: // shrink first row 2nd column, and second row 1st column so we
5109: // have space on both the first and the second page on the row
5110: // chain.
5111: // use sparse rows
5112: T_RawStoreRow partialRow = new T_RawStoreRow(2);
5113: partialRow.setColumn(1, 400, REC_004);
5114:
5115: T_RawStoreRow partialRow2 = new T_RawStoreRow(2);
5116: partialRow2.setColumn(0, 400, REC_004);
5117:
5118: c = t_util.t_openContainer(t, segment, cid, true);
5119: page = t_util.t_getPage(c,
5120: ContainerHandle.FIRST_PAGE_NUMBER);
5121:
5122: FormatableBitSet colList = new FormatableBitSet(2);
5123: colList.set(1); // update first row column 1, the second column
5124: page.update(rh1, partialRow.getRow(), colList);
5125:
5126: colList.clear(1);
5127: colList.set(0); // update second row column 0, the first column
5128: page.update(rh2, partialRow2.getRow(), colList);
5129:
5130: // verify the update worked.
5131: row1.setColumn(1, 400, REC_004);
5132: row2.setColumn(0, 400, REC_004);
5133: t_util.t_checkFetch(page, rh1, row1);
5134: t_util.t_checkFetch(page, rh2, row2);
5135:
5136: page.unlatch();
5137: page = null;
5138:
5139: t_util.t_commit(t);
5140: t_util.t_wait(10); // give post commit a chance to work
5141:
5142: // We think the head row should have 2 200 bytes row.
5143: // One of the overflow row piece chain has an overflow page with a
5144: // 200 bytes row followed by another overflow page with a 200 bytes
5145: // row.
5146: // The other overflow row piece should have 1 600 bytes row and no
5147: // other overflow page.
5148: T_RawStoreRow row3 = new T_RawStoreRow(2);
5149: row3.setColumn(0, 400, REC_001);
5150: row3.setColumn(1, 800, REC_002);
5151: // We think this should select the first overflow chain.
5152: c = t_util.t_openContainer(t, segment, cid, true);
5153: page = t_util.t_getPage(c,
5154: ContainerHandle.FIRST_PAGE_NUMBER);
5155:
5156: if (!page.spaceForInsert())
5157: throw T_Fail
5158: .testFailMsg("No space for insert after shrink row");
5159:
5160: RecordHandle rh3 = t_util.t_insertAtSlot(page, 1, row3,
5161: (byte) insertFlag);
5162: t_util.t_checkFetch(page, rh3, row3);
5163:
5164: page.unlatch();
5165: page = null;
5166:
5167: // this should not allocate more overflow pages
5168: nextPage = t_util.t_addPage(c);
5169: checkNextPageNumber = nextPage.getPageNumber();
5170: if (checkNextPageNumber != nextPageNumber)
5171: throw T_Fail
5172: .testFailMsg("not expected to allocate more pages "
5173: + nextPageNumber
5174: + ","
5175: + checkNextPageNumber);
5176:
5177: t_util.t_dropContainer(t, segment, cid); // cleanup
5178: } finally {
5179: if (page != null)
5180: page.unlatch();
5181:
5182: t_util.t_commit(t);
5183: t.close();
5184: }
5185: PASS("P040");
5186: }
5187:
5188: /**
5189: Test space reclaimation - update a long column to another long column.
5190:
5191: @exception T_Fail Unexpected behaviour from the API
5192: @exception StandardException Unexpected exception from the implementation
5193: */
5194: protected void P041() throws StandardException, T_Fail {
5195: // Make a row with several long columns, on different row pieces.
5196: // Update these long columns - to other long columns or to short
5197: // columns. Remember what the next page is.
5198: // Update these long columns to the original long column (in length),
5199: // we shouldn't be adding any more pages.
5200:
5201: long segment = 0;
5202: Transaction t = t_util.t_startTransaction();
5203: long cid = t_util.t_addContainer(t, segment, 4096);
5204:
5205: ContainerHandle c = t_util.t_openContainer(t, segment, cid,
5206: true);
5207: Page page = t_util.t_getPage(c,
5208: ContainerHandle.FIRST_PAGE_NUMBER);
5209: try {
5210: t_util.t_checkEmptyPage(page);
5211:
5212: int insertFlag = Page.INSERT_INITIAL | Page.INSERT_OVERFLOW;
5213:
5214: // insert a 6 column row, every other column is long
5215: T_RawStoreRow r1 = new T_RawStoreRow(6);
5216: r1.setColumn(0, 400, REC_001); // this takes ~800 bytes
5217: r1.setColumn(1, 500, REC_002); // this takes ~1000 bytes
5218: r1.setColumn(2, 400, REC_001);
5219: r1.setColumn(3, 500, REC_002);
5220: r1.setColumn(4, 400, REC_001);
5221: r1.setColumn(5, 500, REC_002);
5222: RecordHandle rh1 = t_util.t_insertAtSlot(page, 0, r1,
5223: (byte) insertFlag);
5224: t_util.t_checkFetch(page, rh1, r1);
5225:
5226: // update column 0,1,2 to short columns, columns 3, 4, 5 to other
5227: // long columns.
5228: T_RawStoreRow r2 = new T_RawStoreRow(6);
5229: r2.setColumn(0, 100, REC_003);
5230: r2.setColumn(1, 100, REC_004);
5231: r2.setColumn(2, 100, REC_003);
5232: r2.setColumn(3, 500, REC_005);
5233: r2.setColumn(4, 500, REC_006);
5234: r2.setColumn(5, 500, REC_005);
5235:
5236: page.update(rh1, r2.getRow(), (FormatableBitSet) null);
5237: t_util.t_checkFetch(page, rh1, r2);
5238:
5239: page.unlatch();
5240: page = null;
5241:
5242: Page nextpage = t_util.t_addPage(c);
5243: long nextPageNumber = nextpage.getPageNumber();
5244: t_util.t_removePage(c, nextpage);
5245:
5246: t_util.t_commit(t);
5247: t_util.t_wait(10); // let post commit work
5248:
5249: // now update to original long rows, should not take any more
5250: // space.
5251: c = t_util.t_openContainer(t, segment, cid, true);
5252: page = t_util.t_getPage(c,
5253: ContainerHandle.FIRST_PAGE_NUMBER);
5254: t_util.t_checkFetch(page, rh1, r2);
5255:
5256: t.setSavePoint(SP1, null);
5257:
5258: page.update(rh1, r1.getRow(), (FormatableBitSet) null);
5259: t_util.t_checkFetch(page, rh1, r1);
5260: page.unlatch();
5261: page = null;
5262:
5263: nextpage = t_util.t_addPage(c);
5264: long checkNextPageNumber = nextpage.getPageNumber();
5265: nextpage.unlatch();
5266: if (checkNextPageNumber != nextPageNumber)
5267: throw T_Fail
5268: .testFailMsg("expect next page to be unchanged");
5269:
5270: // now roll back the update via savepoint.
5271: t.rollbackToSavePoint(SP1, null);
5272:
5273: t_util.t_commit(t);
5274: t_util.t_wait(10); // make sure post commit don't
5275: // reclaim things that are not garbage.
5276:
5277: c = t_util.t_openContainer(t, segment, cid, true);
5278: page = t_util.t_getPage(c,
5279: ContainerHandle.FIRST_PAGE_NUMBER);
5280: t_util.t_checkFetch(page, rh1, r2);
5281: page.unlatch();
5282: page = null;
5283:
5284: t_util.t_dropContainer(t, segment, cid); // cleanup
5285: } finally {
5286: if (page != null)
5287: page.unlatch();
5288: t_util.t_commit(t);
5289: t.close();
5290: }
5291:
5292: PASS("P041");
5293:
5294: }
5295:
5296: /**
5297: Test space reclaimation - rollback of an update that create a long
5298: column.
5299:
5300: @exception T_Fail Unexpected behaviour from the API
5301: @exception StandardException Unexpected exception from the implementation
5302: */
5303: protected void P042() throws StandardException, T_Fail {
5304: // Make a row with a short column. Remember the next page.
5305: // Update it to a long column, roll back. See that the next page goes
5306: // back to before the update.
5307: //
5308: // Update the row so that it overflows to another page and have long
5309: // column there. Remember the next page. Update the long column to
5310: // another long column. Rollback the update. See that the next page
5311: // goes back to before the update.
5312: //
5313: long segment = 0;
5314: Transaction t = t_util.t_startTransaction();
5315: long cid = t_util.t_addContainer(t, segment, 4096);
5316:
5317: ContainerHandle c = t_util.t_openContainer(t, segment, cid,
5318: true);
5319: Page page = t_util.t_getPage(c,
5320: ContainerHandle.FIRST_PAGE_NUMBER);
5321: int insertFlag = Page.INSERT_INITIAL | Page.INSERT_OVERFLOW;
5322:
5323: try {
5324: T_RawStoreRow smallRow = new T_RawStoreRow(REC_001);
5325: RecordHandle rh1 = t_util.t_insert(page, smallRow);
5326: t_util.t_commit(t);
5327:
5328: c = t_util.t_openContainer(t, segment, cid, true);
5329: Page nextPage = t_util.t_addPage(c);
5330: long nextPageNumber = nextPage.getPageNumber();
5331: // deallocate it
5332: t_util.t_removePage(c, nextPage);
5333: t_util.t_commit(t);
5334:
5335: c = t_util.t_openContainer(t, segment, cid, true);
5336: page = t_util.t_getPage(c,
5337: ContainerHandle.FIRST_PAGE_NUMBER);
5338:
5339: T_RawStoreRow bigRow = new T_RawStoreRow(1);
5340: bigRow.setColumn(0, 6400, REC_001);
5341: page.update(rh1, bigRow.getRow(), (FormatableBitSet) null);
5342: t_util.t_checkFetch(page, rh1, bigRow);
5343: page.unlatch();
5344: page = null;
5345:
5346: Page checkGrow = t_util.t_addPage(c);
5347: long checkGrowPageNumber = checkGrow.getPageNumber();
5348: if (checkGrowPageNumber == nextPageNumber)
5349: throw T_Fail
5350: .testFailMsg("expect to have allocated more pages");
5351: t_util.t_removePage(c, checkGrow);
5352:
5353: t_util.t_abort(t);
5354:
5355: t_util.t_wait(10);
5356: c = t_util.t_openContainer(t, segment, cid, true);
5357:
5358: // the abort rolled back the removePage, remove it again.
5359: checkGrow = t_util.t_getPage(c, checkGrowPageNumber);
5360: t_util.t_removePage(c, checkGrow);
5361:
5362: nextPage = t_util.t_addPage(c);
5363: if (nextPage.getPageNumber() != nextPageNumber)
5364: throw T_Fail
5365: .testFailMsg("rollback of update to long column did not release the long column chain pages");
5366:
5367: t_util.t_removePage(c, nextPage);
5368: t_util.t_commit(t);
5369:
5370: T_RawStoreRow row2 = new T_RawStoreRow(6);
5371: row2.setColumn(0, 1600, REC_001); // this takes ~3200 bytes
5372: row2.setColumn(1, 2000, REC_002); // this takes ~4000 bytes
5373: row2.setColumn(2, 1600, REC_001);
5374: row2.setColumn(3, 2000, REC_002);
5375: row2.setColumn(4, 1600, REC_001);
5376: row2.setColumn(5, 2000, REC_002);
5377:
5378: c = t_util.t_openContainer(t, segment, cid, true);
5379: page = t_util.t_getPage(c,
5380: ContainerHandle.FIRST_PAGE_NUMBER);
5381:
5382: t.setSavePoint(SP1, null);
5383: page.update(rh1, row2.getRow(), (FormatableBitSet) null);
5384:
5385: nextPage = t_util.t_addPage(c);
5386: nextPageNumber = nextPage.getPageNumber();
5387: t_util.t_removePage(c, nextPage);
5388:
5389: t.rollbackToSavePoint(SP1, null); // this should free up some pages
5390:
5391: nextPage = t_util.t_getPage(c, nextPageNumber);
5392: t_util.t_removePage(c, nextPage);
5393:
5394: t_util.t_commit(t);
5395: t_util.t_wait(10);
5396:
5397: c = t_util.t_openContainer(t, segment, cid, true);
5398: Page checkNextPage = t_util.t_addPage(c);
5399: if (checkNextPage.getPageNumber() == nextPageNumber)
5400: throw T_Fail
5401: .testFailMsg("expect some pages to be freed by update rollback");
5402: t_util.t_removePage(c, checkNextPage);
5403: t_util.t_commit(t);
5404:
5405: c = t_util.t_openContainer(t, segment, cid, true);
5406: page = t_util.t_getPage(c,
5407: ContainerHandle.FIRST_PAGE_NUMBER);
5408: t_util.t_checkFetch(page, rh1, smallRow);
5409:
5410: // update row so that it has overflow rows and long columns
5411: page.update(rh1, row2.getRow(), (FormatableBitSet) null);
5412:
5413: // remember the next page
5414: nextPage = t_util.t_addPage(c);
5415: nextPageNumber = nextPage.getPageNumber();
5416: t_util.t_removePage(c, nextPage);
5417:
5418: t_util.t_commit(t);
5419:
5420: // now update columns 0, 1, 4 to long columns and roll it back.
5421: T_RawStoreRow row3 = new T_RawStoreRow(5);
5422: row3.setColumn(0, 4000, REC_003);
5423: row3.setColumn(1, 4000, REC_004);
5424: row3.setColumn(2, REC_001);
5425: row3.setColumn(3, REC_001);
5426: row3.setColumn(4, 4000, REC_003);
5427:
5428: c = t_util.t_openContainer(t, segment, cid, true);
5429: page = t_util.t_getPage(c,
5430: ContainerHandle.FIRST_PAGE_NUMBER);
5431: page.update(rh1, row3.getRow(), (FormatableBitSet) null);
5432: t_util.t_checkFetch(page, rh1, row3);
5433: page.unlatch();
5434: page = null;
5435:
5436: t_util.t_abort(t);
5437: t_util.t_wait(10);
5438:
5439: c = t_util.t_openContainer(t, segment, cid, true);
5440: nextPage = t_util.t_addPage(c);
5441: if (nextPage.getPageNumber() != nextPageNumber)
5442: throw T_Fail
5443: .testFailMsg("expect pages to be freed by update rollback");
5444: nextPage.unlatch();
5445:
5446: t_util.t_dropContainer(t, segment, cid);
5447: } finally {
5448: if (page != null)
5449: page.unlatch();
5450: t_util.t_commit(t);
5451: t.close();
5452: }
5453: PASS("P042");
5454:
5455: }
5456:
5457: /**
5458: Test space reclaimation - rollback of an update that create a new row
5459: piece.
5460: */
5461: protected void P043() {
5462: // this space cannot be reclaimed.
5463: }
5464:
5465: /**
5466: Test that post commit processor does not stubbify a drop table that is
5467: rolled back in a savepoint
5468: @exception T_Fail Unexpected behaviour from the API
5469: @exception StandardException Unexpected exception from the implementation
5470:
5471: */
5472: protected void P050() throws StandardException, T_Fail {
5473: if (!testRollback)
5474: return;
5475:
5476: Transaction t = t_util.t_startTransaction();
5477: long cid = t_util.t_addContainer(t, 0);
5478: t_util.t_commit(t);
5479:
5480: t.setSavePoint(SP1, null);
5481:
5482: t.dropContainer(new ContainerKey(0, cid));
5483: t.rollbackToSavePoint(SP1, null);
5484:
5485: ContainerHandle c = t_util.t_openContainer(t, 0, cid, true);
5486: t_util.t_addPage(c);
5487: t_util.t_commit(t);
5488:
5489: long cid2 = t_util.t_addContainer(t, 0);
5490: c = t_util.t_openContainer(t, 0, cid2, true);
5491: t_util.t_addPage(c);
5492: t_util.t_addPage(c);
5493: t_util.t_addPage(c);
5494: t_util.t_addPage(c);
5495: t_util.t_commit(t);
5496:
5497: c = t_util.t_openContainer(t, 0, cid, false); // it should not be stubbified...
5498:
5499: PASS("P050");
5500:
5501: t_util.t_dropContainer(t, 0, cid); // cleanup - commit it for real
5502: t_util.t_dropContainer(t, 0, cid2); // cleanup - commit it for real
5503:
5504: t_util.t_commit(t);
5505: t.close();
5506:
5507: }
5508:
5509: /**
5510: Test rollback of Page.insert
5511: @exception T_Fail Unexpected behaviour from the API
5512: @exception StandardException Unexpected exception from the implementation
5513:
5514: */
5515: protected void P051() throws StandardException, T_Fail {
5516: if (!testRollback)
5517: return;
5518:
5519: Transaction t = t_util.t_startTransaction();
5520: long cid = t_util.t_addContainer(t, 0);
5521: t_util.t_commit(t);
5522:
5523: T_RawStoreRow row = new T_RawStoreRow(REC_001);
5524: ContainerHandle c = t_util.t_openContainer(t, 0, cid, true);
5525: Page page = t_util.t_getPage(c,
5526: ContainerHandle.FIRST_PAGE_NUMBER);
5527:
5528: // first insert and check that an abort leaves the row there
5529: RecordHandle rh1 = t_util.t_insert(page, row);
5530:
5531: t_util.t_commit(t);
5532:
5533: c = t_util.t_openContainer(t, 0, cid, true);
5534:
5535: t_util.t_checkFetch(c, rh1, REC_001);
5536:
5537: row = new T_RawStoreRow(REC_002);
5538:
5539: RecordHandle rh2 = t_util.t_insert(c, row);
5540:
5541: t_util.t_checkFetch(c, rh1, REC_001);
5542: t_util.t_checkFetch(c, rh2, REC_002);
5543:
5544: t_util.t_abort(t);
5545:
5546: c = t_util.t_openContainer(t, 0, cid, true);
5547: t_util.t_checkFetch(c, rh1, REC_001);
5548:
5549: page = t_util.t_getPage(c, rh2.getPageNumber());
5550: if (page.recordExists(rh2, false)) {
5551: throw T_Fail.testFailMsg("record insert was not undone");
5552: }
5553: page.unlatch();
5554:
5555: PASS("P051");
5556:
5557: t_util.t_dropContainer(t, 0, cid); // cleanup
5558:
5559: t_util.t_commit(t);
5560: t.close();
5561: }
5562:
5563: /**
5564: Test rollback of Page.delete
5565: @exception T_Fail Unexpected behaviour from the API
5566: @exception StandardException Unexpected exception from the implementation
5567:
5568: @see Page#delete
5569:
5570: */
5571: protected void P052() throws StandardException, T_Fail {
5572: if (!testRollback)
5573: return;
5574:
5575: Transaction t = t_util.t_startTransaction();
5576:
5577: long cid = t_util.t_addContainer(t, 0);
5578: t_util.t_commit(t);
5579:
5580: ContainerHandle c = t_util.t_openContainer(t, 0, cid, true);
5581:
5582: // first insert two rows
5583: T_RawStoreRow row = new T_RawStoreRow(REC_001);
5584: RecordHandle rh1 = t_util.t_insert(c, row);
5585: row = new T_RawStoreRow(REC_002);
5586: RecordHandle rh2 = t_util.t_insert(c, row);
5587:
5588: t_util.t_commit(t);
5589:
5590: c = t_util.t_openContainer(t, 0, cid, true);
5591:
5592: t_util.t_checkFetch(c, rh1, REC_001);
5593: t_util.t_checkFetch(c, rh2, REC_002);
5594:
5595: t_util.t_delete(c, rh2);
5596:
5597: t_util.t_checkFetch(c, rh1, REC_001);
5598:
5599: t_util.t_abort(t);
5600:
5601: c = t_util.t_openContainer(t, 0, cid, true);
5602: t_util.t_checkFetch(c, rh1, REC_001);
5603: t_util.t_checkFetch(c, rh2, REC_002);
5604:
5605: PASS("P052");
5606:
5607: t_util.t_dropContainer(t, 0, cid); // cleanup
5608:
5609: t_util.t_commit(t);
5610: t.close();
5611: }
5612:
5613: /**
5614: Test insertAtSlot that rolls back with a purge
5615:
5616: @exception T_Fail Unexpected behaviour from the API
5617: @exception StandardException Unexpected exception from the implementation
5618:
5619: */
5620: protected void P053() throws StandardException, T_Fail {
5621: if (!testRollback)
5622: return;
5623: Transaction t = t_util.t_startTransaction();
5624:
5625: try {
5626: long cid = t_util.t_addContainer(t, 0);
5627: t_util.t_commit(t);
5628:
5629: ContainerHandle c = t_util.t_openContainer(t, 0, cid, true);
5630: Page page = t_util.t_addPage(c);
5631:
5632: T_RawStoreRow row0 = new T_RawStoreRow(REC_001);
5633: T_RawStoreRow row1 = new T_RawStoreRow(REC_001);
5634: T_RawStoreRow row2 = new T_RawStoreRow(REC_002);
5635: T_RawStoreRow row3 = new T_RawStoreRow(REC_003);
5636: T_RawStoreRow row4 = new T_RawStoreRow(REC_004);
5637:
5638: t_util.t_insertAtSlot(page, 0, row0,
5639: Page.INSERT_UNDO_WITH_PURGE);
5640:
5641: if (t_util.t_insertAtSlot(page, 1, row1) == null)
5642: return;
5643:
5644: if (t_util.t_insertAtSlot(page, 2, row2,
5645: Page.INSERT_UNDO_WITH_PURGE) == null)
5646: return;
5647:
5648: if (t_util.t_insertAtSlot(page, 3, row3) == null)
5649: return;
5650:
5651: if (t_util.t_insertAtSlot(page, 4, row4,
5652: Page.INSERT_UNDO_WITH_PURGE) == null)
5653: return;
5654:
5655: int fillerRows = 0;
5656: while (page.spaceForInsert()) {
5657: t_util.t_insertAtSlot(page, 4, row4);
5658: fillerRows++;
5659: }
5660:
5661: t_util.t_checkRecordCount(page, fillerRows + 5,
5662: fillerRows + 5);
5663: t_util.t_abort(t);
5664:
5665: c = t_util.t_openContainer(t, 0, cid, true);
5666: page = t_util.t_getLastPage(c);
5667:
5668: // 2 + fillerRows deleted, 3 purged, 0 nondeleted
5669: t_util.t_checkRecordCount(page, 2 + fillerRows, 0);
5670:
5671: // since I just purged them, there must be space for re-inserting them
5672: t_util.t_insert(page, row0);
5673: t_util.t_insert(page, row2);
5674: t_util.t_insert(page, row4);
5675:
5676: t_util.t_checkRecordCount(page, 5 + fillerRows, 3);
5677:
5678: page.unlatch();
5679: PASS("P053");
5680:
5681: t_util.t_dropContainer(t, 0, cid); // cleanup
5682: } finally {
5683: t_util.t_commit(t);
5684: t.close();
5685: }
5686: }
5687:
5688: /**
5689: Test internal transaction
5690:
5691: @exception T_Fail Unexpected behaviour from the API
5692: @exception StandardException Unexpected exception from the implementation
5693:
5694: */
5695: protected void P054() throws StandardException, T_Fail {
5696: if (!testRollback)
5697: return;
5698:
5699: ContextManager previousCM = contextService
5700: .getCurrentContextManager();
5701:
5702: ContextManager cm1 = contextService.newContextManager();
5703: contextService.setCurrentContextManager(cm1);
5704:
5705: Transaction tuser = t_util.t_startTransaction();
5706: Transaction tinternal = null;
5707:
5708: try {
5709:
5710: long cid1 = t_util.t_addContainer(tuser, 0);
5711: ContainerHandle c1 = t_util.t_openContainer(tuser, 0, cid1,
5712: true);
5713: Page p1 = t_util.t_addPage(c1);
5714: t_util.t_commit(tuser);
5715:
5716: // insert a row using user transaction
5717: T_RawStoreRow row = new T_RawStoreRow(REC_001);
5718:
5719: c1 = t_util.t_openContainer(tuser, 0, cid1, true);
5720: p1 = t_util.t_getLastPage(c1);
5721: RecordHandle r1 = t_util.t_insert(p1, row);
5722:
5723: REPORT("starting internal transaction");
5724:
5725: tinternal = t_util.t_startInternalTransaction();
5726: long cid2 = t_util.t_addContainer(tinternal, 0);
5727: ContainerHandle c2 = t_util.t_openContainer(tinternal, 0,
5728: cid2, true);
5729: Page p2 = t_util.t_addPage(c2);
5730: RecordHandle r2 = t_util.t_insert(p2, row);
5731:
5732: // commit internal transaction
5733: tinternal.commit();
5734: tinternal.abort(); // this will close the container and release
5735: // the page
5736: tinternal.close();
5737: tinternal = null;
5738:
5739: REPORT("commit internal transaction");
5740:
5741: // abort user transaction
5742: t_util.t_abort(tuser);
5743:
5744: REPORT("rollback user transaction");
5745:
5746: c1 = t_util.t_openContainer(tuser, 0, cid1, true);
5747:
5748: p1 = t_util.t_getPage(c1, r1.getPageNumber());
5749: if (p1.recordExists(r1, false))
5750: throw T_Fail
5751: .testFailMsg("user transaction failed to rollback");
5752:
5753: c2 = t_util.t_openContainer(tuser, 0, cid2, true);
5754: t_util.t_checkFetch(c2, r2, REC_001); // this should be unaffected by the
5755: // user transaction rollback
5756: p2 = t_util.t_getLastPage(c2);
5757:
5758: T_RawStoreRow row2 = new T_RawStoreRow(REC_002);
5759:
5760: if (!p2.spaceForInsert()) {
5761: REPORT("P054 not run, page cannot accomodate 2 rows");
5762: return;
5763: }
5764: RecordHandle r21 = t_util.t_insert(p2, row2);
5765:
5766: // throw an exception, make sure everything is aborted.
5767: tinternal = t_util.t_startInternalTransaction();
5768: long cid3 = t_util.t_addContainer(tinternal, 0);
5769: ContainerHandle c3 = t_util.t_openContainer(tinternal, 0,
5770: cid3, true);
5771: Page p3 = t_util.t_addPage(c3);
5772: RecordHandle r3 = t_util.t_insert(p3, row);
5773: try {
5774: // this will throw a data statement exception
5775: t_util.t_insertAtSlot(p3, 100, row);
5776: } catch (StandardException se) {
5777: REPORT("cleanup on error");
5778: cm1.cleanupOnError(se);
5779: REPORT("done cleanup on error");
5780: }
5781:
5782: tinternal = null;
5783: // tuser = t_util.t_startTransaction();
5784: c2 = t_util.t_openContainer(tuser, 0, cid2, true);
5785: t_util.t_checkFetch(c2, r2, REC_001);
5786:
5787: p2 = t_util.t_getPage(c2, r21.getPageNumber());
5788: if (p2.recordExists(r21, false))
5789: throw T_Fail
5790: .testFailMsg("expect user transaction to rollback");
5791:
5792: // this should fail
5793: ContainerKey id3 = new ContainerKey(0, cid3);
5794: c3 = tuser
5795: .openContainer(id3, ContainerHandle.MODE_READONLY);
5796: if (c3 != null)
5797: throw T_Fail
5798: .testFailMsg("expect internal transaction to rollback");
5799:
5800: LockingPolicy nolock = tuser.newLockingPolicy(
5801: LockingPolicy.MODE_NONE, 0, false);
5802:
5803: RawContainerHandle stub = ((RawTransaction) tuser)
5804: .openDroppedContainer(id3, nolock);
5805:
5806: if (stub == null)
5807: throw T_Fail
5808: .testFailMsg("expect container to be dropped");
5809:
5810: if (stub.getContainerStatus() != RawContainerHandle.COMMITTED_DROP)
5811: throw T_Fail
5812: .testFailMsg("expect container to be committed dropped");
5813:
5814: // this should fail
5815: p3 = stub.getPage(r3.getPageNumber());
5816:
5817: if (p3 != null)
5818: throw T_Fail
5819: .testFailMsg("should not getpage with committed dropped container");
5820:
5821: PASS("P054");
5822:
5823: t_util.t_dropContainer(tuser, 0, cid2); // cleanup
5824: t_util.t_dropContainer(tuser, 0, cid1); // cleanup
5825:
5826: if (tinternal != null) {
5827: t_util.t_abort(tinternal);
5828: tinternal.close();
5829: }
5830:
5831: if (tuser != null) {
5832: t_util.t_commit(tuser);
5833: tuser.close();
5834: }
5835: } finally {
5836:
5837: contextService.resetCurrentContextManager(cm1);
5838: }
5839:
5840: }
5841:
5842: /**
5843: Test rollback of partial row update.
5844: Create a long row with 10 columns on 2 pages (5 columns on each page).
5845: Update the 1st column on the 2nd page (the 6th column) which causes the
5846: last column (10th column) to move off the page. Then abort and make sure
5847: that all the original columns are there and correct.
5848:
5849: NOTE: stored length is twice string length + 2
5850:
5851: @exception T_Fail Unexpected behaviour from the API
5852: @exception StandardException Unexpected exception from the implementation
5853: */
5854: protected void P055(long segment) throws StandardException, T_Fail {
5855:
5856: if (!testRollback)
5857: return;
5858:
5859: Transaction t = t_util.t_startTransaction();
5860:
5861: long cid = t_util.t_addContainer(t, segment, 4096);
5862:
5863: ContainerHandle c = t_util.t_openContainer(t, segment, cid,
5864: true);
5865: Page page = t_util.t_getPage(c,
5866: ContainerHandle.FIRST_PAGE_NUMBER);
5867: t_util.t_checkEmptyPage(page);
5868:
5869: int colSize = 90;
5870: T_RawStoreRow r0 = new T_RawStoreRow(10);
5871: r0.setColumn(0, colSize, REC_001);
5872: r0.setColumn(1, colSize, REC_002);
5873: r0.setColumn(2, colSize, REC_003);
5874: r0.setColumn(3, colSize, REC_004);
5875: r0.setColumn(4, colSize, REC_005);
5876: r0.setColumn(5, colSize, REC_009);
5877: r0.setColumn(6, colSize, REC_010);
5878: r0.setColumn(7, colSize, REC_011);
5879: r0.setColumn(8, colSize, REC_012);
5880: r0.setColumn(9, colSize, REC_013);
5881:
5882: int insertFlag = Page.INSERT_INITIAL;
5883: insertFlag |= Page.INSERT_OVERFLOW;
5884:
5885: RecordHandle rh0 = null;
5886: try {
5887: rh0 = t_util.t_insertAtSlot(page, 0, r0, (byte) insertFlag);
5888: } catch (StandardException se) {
5889: throw T_Fail.testFailMsg("insert of long row failed.");
5890: }
5891:
5892: if (rh0 == null)
5893: throw T_Fail
5894: .testFailMsg("insert of first long row failed.");
5895: else {
5896: REPORT("about to check fetch...");
5897: DataValueDescriptor column = new SQLChar();
5898: t_util.t_checkFetchColFromSlot(page,
5899: page.FIRST_SLOT_NUMBER, 0, column, false, REC_001,
5900: colSize);
5901: t_util.t_checkFetchColFromSlot(page,
5902: page.FIRST_SLOT_NUMBER, 1, column, false, REC_002,
5903: colSize);
5904: t_util.t_checkFetchColFromSlot(page,
5905: page.FIRST_SLOT_NUMBER, 2, column, false, REC_003,
5906: colSize);
5907: t_util.t_checkFetchColFromSlot(page,
5908: page.FIRST_SLOT_NUMBER, 3, column, false, REC_004,
5909: colSize);
5910: t_util.t_checkFetchColFromSlot(page,
5911: page.FIRST_SLOT_NUMBER, 4, column, false, REC_005,
5912: colSize);
5913: t_util.t_checkFetchColFromSlot(page,
5914: page.FIRST_SLOT_NUMBER, 5, column, false, REC_009,
5915: colSize);
5916: t_util.t_checkFetchColFromSlot(page,
5917: page.FIRST_SLOT_NUMBER, 6, column, false, REC_010,
5918: colSize);
5919: t_util.t_checkFetchColFromSlot(page,
5920: page.FIRST_SLOT_NUMBER, 7, column, false, REC_011,
5921: colSize);
5922: t_util.t_checkFetchColFromSlot(page,
5923: page.FIRST_SLOT_NUMBER, 8, column, false, REC_012,
5924: colSize);
5925: t_util.t_checkFetchColFromSlot(page,
5926: page.FIRST_SLOT_NUMBER, 9, column, false, REC_013,
5927: colSize);
5928: }
5929:
5930: t_util.t_commit(t);
5931:
5932: // update col 5 (the 6th column, the first column on the 2nd overflow page), which causes
5933: // the last column (col 9, the 10th column) to move off the page.
5934:
5935: c = t_util.t_openContainer(t, segment, cid, true);
5936: page = t_util.t_getPage(c, ContainerHandle.FIRST_PAGE_NUMBER);
5937:
5938: T_RawStoreRow updateRow = new T_RawStoreRow(10);
5939: for (int i = 0; i < 10; i++)
5940: updateRow.setColumn(i, (String) null);
5941: updateRow.setColumn(5, colSize * 2, REC_009);
5942: FormatableBitSet colList = new FormatableBitSet(10);
5943: colList.set(5);
5944: page.updateAtSlot(0, updateRow.getRow(), colList);
5945:
5946: REPORT("about to check fetch after update ...");
5947: DataValueDescriptor column = new SQLChar();
5948: t_util.t_checkFetchColFromSlot(page, page.FIRST_SLOT_NUMBER, 0,
5949: column, false, REC_001, colSize);
5950: t_util.t_checkFetchColFromSlot(page, page.FIRST_SLOT_NUMBER, 1,
5951: column, false, REC_002, colSize);
5952: t_util.t_checkFetchColFromSlot(page, page.FIRST_SLOT_NUMBER, 2,
5953: column, false, REC_003, colSize);
5954: t_util.t_checkFetchColFromSlot(page, page.FIRST_SLOT_NUMBER, 3,
5955: column, false, REC_004, colSize);
5956: t_util.t_checkFetchColFromSlot(page, page.FIRST_SLOT_NUMBER, 4,
5957: column, false, REC_005, colSize);
5958: t_util.t_checkFetchColFromSlot(page, page.FIRST_SLOT_NUMBER, 5,
5959: column, false, REC_009, colSize * 2);
5960: t_util.t_checkFetchColFromSlot(page, page.FIRST_SLOT_NUMBER, 6,
5961: column, false, REC_010, colSize);
5962: t_util.t_checkFetchColFromSlot(page, page.FIRST_SLOT_NUMBER, 7,
5963: column, false, REC_011, colSize);
5964: t_util.t_checkFetchColFromSlot(page, page.FIRST_SLOT_NUMBER, 8,
5965: column, false, REC_012, colSize);
5966: t_util.t_checkFetchColFromSlot(page, page.FIRST_SLOT_NUMBER, 9,
5967: column, false, REC_013, colSize);
5968: page.unlatch();
5969:
5970: t_util.t_abort(t);
5971:
5972: REPORT("about to check fetch after abort ...");
5973: c = t_util.t_openContainer(t, segment, cid, false);
5974: page = t_util.t_getPage(c, ContainerHandle.FIRST_PAGE_NUMBER);
5975: t_util.t_checkFetchColFromSlot(page, page.FIRST_SLOT_NUMBER, 0,
5976: column, false, REC_001, colSize);
5977: t_util.t_checkFetchColFromSlot(page, page.FIRST_SLOT_NUMBER, 1,
5978: column, false, REC_002, colSize);
5979: t_util.t_checkFetchColFromSlot(page, page.FIRST_SLOT_NUMBER, 2,
5980: column, false, REC_003, colSize);
5981: t_util.t_checkFetchColFromSlot(page, page.FIRST_SLOT_NUMBER, 3,
5982: column, false, REC_004, colSize);
5983: t_util.t_checkFetchColFromSlot(page, page.FIRST_SLOT_NUMBER, 4,
5984: column, false, REC_005, colSize);
5985: t_util.t_checkFetchColFromSlot(page, page.FIRST_SLOT_NUMBER, 5,
5986: column, false, REC_009, colSize);
5987: t_util.t_checkFetchColFromSlot(page, page.FIRST_SLOT_NUMBER, 6,
5988: column, false, REC_010, colSize);
5989: t_util.t_checkFetchColFromSlot(page, page.FIRST_SLOT_NUMBER, 7,
5990: column, false, REC_011, colSize);
5991: t_util.t_checkFetchColFromSlot(page, page.FIRST_SLOT_NUMBER, 8,
5992: column, false, REC_012, colSize);
5993: t_util.t_checkFetchColFromSlot(page, page.FIRST_SLOT_NUMBER, 9,
5994: column, false, REC_013, colSize);
5995: page.unlatch();
5996:
5997: if (segment != ContainerHandle.TEMPORARY_SEGMENT) {
5998: t_util.t_dropContainer(t, segment, cid); // cleanup
5999: }
6000:
6001: t_util.t_commit(t);
6002: t.close();
6003:
6004: PASS("P055: segment = " + segment);
6005: }
6006:
6007: /**
6008: Test rollback of partial row update.
6009: Create a long row with 15 columns on 3 pages (5 columns on each page).
6010: Update the 1st column on the 2nd page (the 6th column) which causes the
6011: last column of that page (10th column) to move off the page. Then abort
6012: and make sure that all the original columns are there and correct.
6013:
6014: NOTE: stored length is twice string length + 2
6015:
6016: @exception T_Fail Unexpected behaviour from the API
6017: @exception StandardException Unexpected exception from the implementation
6018: */
6019: protected void P056(long segment) throws StandardException, T_Fail {
6020:
6021: if (!testRollback)
6022: return;
6023:
6024: Transaction t = t_util.t_startTransaction();
6025:
6026: long cid = t_util.t_addContainer(t, segment, 4096);
6027:
6028: ContainerHandle c = t_util.t_openContainer(t, segment, cid,
6029: true);
6030: Page page = t_util.t_getPage(c,
6031: ContainerHandle.FIRST_PAGE_NUMBER);
6032: t_util.t_checkEmptyPage(page);
6033:
6034: int colSize = 90;
6035: T_RawStoreRow r0 = new T_RawStoreRow(15);
6036: r0.setColumn(0, colSize, REC_001);
6037: r0.setColumn(1, colSize, REC_002);
6038: r0.setColumn(2, colSize, REC_003);
6039: r0.setColumn(3, colSize, REC_004);
6040: r0.setColumn(4, colSize, REC_005);
6041: r0.setColumn(5, colSize, REC_009);
6042: r0.setColumn(6, colSize, REC_010);
6043: r0.setColumn(7, colSize, REC_011);
6044: r0.setColumn(8, colSize, REC_012);
6045: r0.setColumn(9, colSize, REC_013);
6046: r0.setColumn(10, colSize, REC_014);
6047: r0.setColumn(11, colSize, REC_015);
6048: r0.setColumn(12, colSize, REC_016);
6049: r0.setColumn(13, colSize, REC_017);
6050: r0.setColumn(14, colSize, REC_018);
6051:
6052: int insertFlag = Page.INSERT_INITIAL;
6053: insertFlag |= Page.INSERT_OVERFLOW;
6054:
6055: RecordHandle rh0 = null;
6056: try {
6057: rh0 = t_util.t_insertAtSlot(page, 0, r0, (byte) insertFlag);
6058: } catch (StandardException se) {
6059: throw T_Fail.testFailMsg("insert of long row failed.");
6060: }
6061:
6062: if (rh0 == null)
6063: throw T_Fail
6064: .testFailMsg("insert of first long row failed.");
6065: else {
6066: REPORT("about to check fetch...");
6067: DataValueDescriptor column = new SQLChar();
6068: t_util.t_checkFetchColFromSlot(page,
6069: page.FIRST_SLOT_NUMBER, 0, column, false, REC_001,
6070: colSize);
6071: t_util.t_checkFetchColFromSlot(page,
6072: page.FIRST_SLOT_NUMBER, 1, column, false, REC_002,
6073: colSize);
6074: t_util.t_checkFetchColFromSlot(page,
6075: page.FIRST_SLOT_NUMBER, 2, column, false, REC_003,
6076: colSize);
6077: t_util.t_checkFetchColFromSlot(page,
6078: page.FIRST_SLOT_NUMBER, 3, column, false, REC_004,
6079: colSize);
6080: t_util.t_checkFetchColFromSlot(page,
6081: page.FIRST_SLOT_NUMBER, 4, column, false, REC_005,
6082: colSize);
6083: t_util.t_checkFetchColFromSlot(page,
6084: page.FIRST_SLOT_NUMBER, 5, column, false, REC_009,
6085: colSize);
6086: t_util.t_checkFetchColFromSlot(page,
6087: page.FIRST_SLOT_NUMBER, 6, column, false, REC_010,
6088: colSize);
6089: t_util.t_checkFetchColFromSlot(page,
6090: page.FIRST_SLOT_NUMBER, 7, column, false, REC_011,
6091: colSize);
6092: t_util.t_checkFetchColFromSlot(page,
6093: page.FIRST_SLOT_NUMBER, 8, column, false, REC_012,
6094: colSize);
6095: t_util.t_checkFetchColFromSlot(page,
6096: page.FIRST_SLOT_NUMBER, 9, column, false, REC_013,
6097: colSize);
6098: t_util.t_checkFetchColFromSlot(page,
6099: page.FIRST_SLOT_NUMBER, 10, column, false, REC_014,
6100: colSize);
6101: t_util.t_checkFetchColFromSlot(page,
6102: page.FIRST_SLOT_NUMBER, 11, column, false, REC_015,
6103: colSize);
6104: t_util.t_checkFetchColFromSlot(page,
6105: page.FIRST_SLOT_NUMBER, 12, column, false, REC_016,
6106: colSize);
6107: t_util.t_checkFetchColFromSlot(page,
6108: page.FIRST_SLOT_NUMBER, 13, column, false, REC_017,
6109: colSize);
6110: t_util.t_checkFetchColFromSlot(page,
6111: page.FIRST_SLOT_NUMBER, 14, column, false, REC_018,
6112: colSize);
6113: }
6114:
6115: t_util.t_commit(t);
6116:
6117: // update col 5 (the 6th column, the first column on the 2nd overflow page), which causes
6118: // the last column (col 9, the 10th column) to move off the page.
6119:
6120: c = t_util.t_openContainer(t, segment, cid, true);
6121: page = t_util.t_getPage(c, ContainerHandle.FIRST_PAGE_NUMBER);
6122:
6123: T_RawStoreRow updateRow = new T_RawStoreRow(15);
6124: for (int i = 0; i < 15; i++)
6125: updateRow.setColumn(i, (String) null);
6126: updateRow.setColumn(5, colSize * 2, REC_009);
6127: FormatableBitSet colList = new FormatableBitSet(15);
6128: colList.set(5);
6129: page.updateAtSlot(0, updateRow.getRow(), colList);
6130:
6131: REPORT("about to check fetch after update ...");
6132: DataValueDescriptor column = new SQLChar();
6133: t_util.t_checkFetchColFromSlot(page, page.FIRST_SLOT_NUMBER, 0,
6134: column, false, REC_001, colSize);
6135: t_util.t_checkFetchColFromSlot(page, page.FIRST_SLOT_NUMBER, 1,
6136: column, false, REC_002, colSize);
6137: t_util.t_checkFetchColFromSlot(page, page.FIRST_SLOT_NUMBER, 2,
6138: column, false, REC_003, colSize);
6139: t_util.t_checkFetchColFromSlot(page, page.FIRST_SLOT_NUMBER, 3,
6140: column, false, REC_004, colSize);
6141: t_util.t_checkFetchColFromSlot(page, page.FIRST_SLOT_NUMBER, 4,
6142: column, false, REC_005, colSize);
6143: t_util.t_checkFetchColFromSlot(page, page.FIRST_SLOT_NUMBER, 5,
6144: column, false, REC_009, colSize * 2);
6145: t_util.t_checkFetchColFromSlot(page, page.FIRST_SLOT_NUMBER, 6,
6146: column, false, REC_010, colSize);
6147: t_util.t_checkFetchColFromSlot(page, page.FIRST_SLOT_NUMBER, 7,
6148: column, false, REC_011, colSize);
6149: t_util.t_checkFetchColFromSlot(page, page.FIRST_SLOT_NUMBER, 8,
6150: column, false, REC_012, colSize);
6151: t_util.t_checkFetchColFromSlot(page, page.FIRST_SLOT_NUMBER, 9,
6152: column, false, REC_013, colSize);
6153: t_util.t_checkFetchColFromSlot(page, page.FIRST_SLOT_NUMBER,
6154: 10, column, false, REC_014, colSize);
6155: t_util.t_checkFetchColFromSlot(page, page.FIRST_SLOT_NUMBER,
6156: 11, column, false, REC_015, colSize);
6157: t_util.t_checkFetchColFromSlot(page, page.FIRST_SLOT_NUMBER,
6158: 12, column, false, REC_016, colSize);
6159: t_util.t_checkFetchColFromSlot(page, page.FIRST_SLOT_NUMBER,
6160: 13, column, false, REC_017, colSize);
6161: t_util.t_checkFetchColFromSlot(page, page.FIRST_SLOT_NUMBER,
6162: 14, column, false, REC_018, colSize);
6163: page.unlatch();
6164:
6165: t_util.t_abort(t);
6166:
6167: REPORT("about to check fetch after abort ...");
6168: c = t_util.t_openContainer(t, segment, cid, false);
6169: page = t_util.t_getPage(c, ContainerHandle.FIRST_PAGE_NUMBER);
6170: t_util.t_checkFetchColFromSlot(page, page.FIRST_SLOT_NUMBER, 0,
6171: column, false, REC_001, colSize);
6172: t_util.t_checkFetchColFromSlot(page, page.FIRST_SLOT_NUMBER, 1,
6173: column, false, REC_002, colSize);
6174: t_util.t_checkFetchColFromSlot(page, page.FIRST_SLOT_NUMBER, 2,
6175: column, false, REC_003, colSize);
6176: t_util.t_checkFetchColFromSlot(page, page.FIRST_SLOT_NUMBER, 3,
6177: column, false, REC_004, colSize);
6178: t_util.t_checkFetchColFromSlot(page, page.FIRST_SLOT_NUMBER, 4,
6179: column, false, REC_005, colSize);
6180: t_util.t_checkFetchColFromSlot(page, page.FIRST_SLOT_NUMBER, 5,
6181: column, false, REC_009, colSize);
6182: t_util.t_checkFetchColFromSlot(page, page.FIRST_SLOT_NUMBER, 6,
6183: column, false, REC_010, colSize);
6184: t_util.t_checkFetchColFromSlot(page, page.FIRST_SLOT_NUMBER, 7,
6185: column, false, REC_011, colSize);
6186: t_util.t_checkFetchColFromSlot(page, page.FIRST_SLOT_NUMBER, 8,
6187: column, false, REC_012, colSize);
6188: t_util.t_checkFetchColFromSlot(page, page.FIRST_SLOT_NUMBER, 9,
6189: column, false, REC_013, colSize);
6190: t_util.t_checkFetchColFromSlot(page, page.FIRST_SLOT_NUMBER,
6191: 10, column, false, REC_014, colSize);
6192: t_util.t_checkFetchColFromSlot(page, page.FIRST_SLOT_NUMBER,
6193: 11, column, false, REC_015, colSize);
6194: t_util.t_checkFetchColFromSlot(page, page.FIRST_SLOT_NUMBER,
6195: 12, column, false, REC_016, colSize);
6196: t_util.t_checkFetchColFromSlot(page, page.FIRST_SLOT_NUMBER,
6197: 13, column, false, REC_017, colSize);
6198: t_util.t_checkFetchColFromSlot(page, page.FIRST_SLOT_NUMBER,
6199: 14, column, false, REC_018, colSize);
6200: page.unlatch();
6201:
6202: if (segment != ContainerHandle.TEMPORARY_SEGMENT) {
6203: t_util.t_dropContainer(t, segment, cid); // cleanup
6204: }
6205: t_util.t_commit(t);
6206: t.close();
6207:
6208: PASS("P056: segment = " + segment);
6209: }
6210:
6211: /**
6212: Sparse row test.
6213: Test sparse representation of rows using the FormatableBitSet class.
6214: Insert, fetch and update a row having gaps.
6215:
6216: @exception T_Fail Unexpected behaviour from the API
6217: @exception StandardException Unexpected exception from the implementation
6218: */
6219: protected void P061() throws StandardException, T_Fail {
6220: long segment = 0;
6221: Transaction t = t_util.t_startTransaction();
6222: long cid = t_util.t_addContainer(t, segment);
6223:
6224: int numCols = 6;
6225: T_RawStoreRow row1 = new T_RawStoreRow(numCols);
6226: row1.setColumn(0, (String) null);
6227: row1.setColumn(1, REC_001);
6228: row1.setColumn(2, (String) null);
6229: row1.setColumn(3, REC_002);
6230: row1.setColumn(4, (String) null);
6231: row1.setColumn(5, REC_003);
6232:
6233: ContainerHandle c = t_util.t_openContainer(t, segment, cid,
6234: true);
6235: Page page = t_util.t_getPage(c,
6236: ContainerHandle.FIRST_PAGE_NUMBER);
6237: try {
6238: RecordHandle rh1 = t_util.t_insert(page, row1);
6239:
6240: t_util.t_checkFetchCol(page, rh1, 1, numCols, REC_001);
6241: t_util.t_checkFetchCol(page, rh1, 3, numCols, REC_002);
6242: t_util.t_checkFetchCol(page, rh1, 5, numCols, REC_003);
6243:
6244: t_util.t_checkUpdateCol(page, rh1, 1, numCols, "woody");
6245: t_util.t_checkUpdateCol(page, rh1, 3, numCols, "buzz");
6246: t_util.t_checkUpdateCol(page, rh1, 5, numCols, "andy");
6247:
6248: t_util.t_checkUpdateCol(page, rh1, 2, numCols, "dino");
6249:
6250: page.unlatch();
6251: page = null;
6252:
6253: t_util.t_commit(t);
6254: } finally {
6255: if (page != null)
6256: page.unlatch();
6257: t_util.t_commit(t);
6258: t.close();
6259: }
6260:
6261: PASS("P061");
6262: }
6263:
6264: /**
6265: Serializable column test.
6266: Want to make sure we hit some otherwise dead code in StoredPage, used
6267: for storing/reading Serializable/Externalizable data to/from a page.
6268:
6269: @exception T_Fail Unexpected behaviour from the API
6270: @exception StandardException Unexpected exception from the implementation
6271: */
6272: protected void P071() throws StandardException, T_Fail {
6273: /*
6274: long segment = 0;
6275: Transaction t = t_util.t_startTransaction();
6276: long cid = t_util.t_addContainer(t, segment);
6277:
6278: int numCols = 1;
6279: T_RawStoreRow row1 = new T_RawStoreRow(numCols);
6280: row1.setColumn(0, new T_Serializable(REC_001));
6281:
6282: ContainerHandle c = t_util.t_openContainer(t, segment, cid, true);
6283: Page page = t_util.t_getPage(c, ContainerHandle.FIRST_PAGE_NUMBER);
6284: try
6285: {
6286: RecordHandle rh1 = t_util.t_insert(page, row1);
6287:
6288: t_util.t_checkFetchSerCol(page, rh1, 0, numCols, new T_Serializable(REC_001));
6289:
6290: page.unlatch();
6291: page = null;
6292:
6293: t_util.t_commit(t);
6294: }
6295: finally
6296: {
6297: if (page != null)
6298: page.unlatch();
6299: t_util.t_commit(t);
6300: t.close();
6301: }
6302: */
6303:
6304: PASS("P071");
6305: }
6306:
6307: /*
6308: ** Update and update partial tests aimed at long rows
6309: */
6310:
6311: /**
6312: Insert a single row and keep updating it, adding columns
6313: not using partial rows.
6314:
6315: @exception T_Fail Unexpected behaviour from the API
6316: @exception StandardException Unexpected exception from the implementation
6317: */
6318: protected void P701(long segment) throws StandardException, T_Fail {
6319:
6320: Transaction t = t_util.t_startTransaction();
6321:
6322: long cid = t_util.t_addContainer(t, segment, 4096);
6323:
6324: ContainerHandle c = t_util.t_openContainer(t, segment, cid,
6325: true);
6326: Page page = t_util.t_getPage(c,
6327: ContainerHandle.FIRST_PAGE_NUMBER);
6328: t_util.t_checkEmptyPage(page);
6329:
6330: T_RawStoreRow row = new T_RawStoreRow(0);
6331: RecordHandle rh = t_util.t_insertAtSlot(page, 0, row,
6332: (byte) (Page.INSERT_INITIAL | Page.INSERT_OVERFLOW));
6333: t_util.t_checkFetch(page, rh, row);
6334:
6335: page.unlatch();
6336: page = t_util.t_getPage(c, ContainerHandle.FIRST_PAGE_NUMBER);
6337:
6338: for (int i = 0; i < 10; i++) {
6339:
6340: REPORT("P701 - iteration " + i);
6341:
6342: row = new T_RawStoreRow(i);
6343:
6344: for (int j = 0; j < i; j++) {
6345: row.setColumn(j, 256, "XX" + j + "YY");
6346: }
6347:
6348: page.update(rh, row.getRow(), (FormatableBitSet) null);
6349: page.unlatch();
6350: page = t_util.t_getPage(c,
6351: ContainerHandle.FIRST_PAGE_NUMBER);
6352:
6353: t_util.t_checkFetch(page, rh, row);
6354: }
6355:
6356: page.unlatch();
6357:
6358: if (segment != ContainerHandle.TEMPORARY_SEGMENT) {
6359: t_util.t_dropContainer(t, segment, cid); // cleanup
6360: }
6361:
6362: t_util.t_commit(t);
6363:
6364: t.close();
6365:
6366: PASS("P701: segment = " + segment);
6367: }
6368:
6369: /*
6370: ** Update and update partial tests aimed at long rows
6371: */
6372:
6373: /**
6374: Insert a single row and keep updating it, adding columns
6375: using partial rows.
6376:
6377: @exception T_Fail Unexpected behaviour from the API
6378: @exception StandardException Unexpected exception from the implementation
6379: */
6380: protected void P702(long segment) throws StandardException, T_Fail {
6381:
6382: Transaction t = t_util.t_startTransaction();
6383:
6384: long cid = t_util.t_addContainer(t, segment, 4096);
6385:
6386: ContainerHandle c = t_util.t_openContainer(t, segment, cid,
6387: true);
6388: Page page = t_util.t_getPage(c,
6389: ContainerHandle.FIRST_PAGE_NUMBER);
6390: t_util.t_checkEmptyPage(page);
6391:
6392: T_RawStoreRow row = new T_RawStoreRow(0);
6393: RecordHandle rh = t_util.t_insertAtSlot(page, 0, row,
6394: (byte) (Page.INSERT_INITIAL | Page.INSERT_OVERFLOW));
6395: t_util.t_checkFetch(page, rh, row);
6396:
6397: page.unlatch();
6398: page = t_util.t_getPage(c, ContainerHandle.FIRST_PAGE_NUMBER);
6399:
6400: for (int i = 0; i < 10; i++) {
6401:
6402: REPORT("P702 - iteration " + i);
6403:
6404: FormatableBitSet colList = new FormatableBitSet(i + 1);
6405: colList.set(i);
6406:
6407: T_RawStoreRow rowU = new T_RawStoreRow(i + 1);
6408: rowU.setColumn(i, 256, "XX" + i + "YY");
6409:
6410: page.update(rh, rowU.getRow(), colList);
6411: page.unlatch();
6412:
6413: T_RawStoreRow rowF = new T_RawStoreRow(i + 1);
6414:
6415: for (int j = 0; j <= i; j++) {
6416: rowF.setColumn(j, 256, "XX" + j + "YY");
6417: }
6418:
6419: page = t_util.t_getPage(c,
6420: ContainerHandle.FIRST_PAGE_NUMBER);
6421:
6422: t_util.t_checkFetch(page, rh, rowF);
6423: }
6424: page.unlatch();
6425:
6426: if (segment != ContainerHandle.TEMPORARY_SEGMENT) {
6427: t_util.t_dropContainer(t, segment, cid); // cleanup
6428: }
6429:
6430: t_util.t_commit(t);
6431:
6432: t.close();
6433:
6434: PASS("P702: segment = " + segment);
6435: }
6436:
6437: /**
6438: Simple set of partial row updates on a singel page with
6439: shrinking and expanding columns.
6440:
6441: @exception T_Fail Unexpected behaviour from the API
6442: @exception StandardException Unexpected exception from the implementation
6443: */
6444:
6445: protected void P703(long segment) throws StandardException, T_Fail {
6446: Transaction t = t_util.t_startTransaction();
6447:
6448: long cid = t_util.t_addContainer(t, segment, 4096);
6449:
6450: ContainerHandle c = t_util.t_openContainer(t, segment, cid,
6451: true);
6452: Page page = t_util.t_getPage(c,
6453: ContainerHandle.FIRST_PAGE_NUMBER);
6454: t_util.t_checkEmptyPage(page);
6455:
6456: REPORT("P703 - start ");
6457: T_RawStoreRow row = new T_RawStoreRow(2);
6458: row.setColumn(0, REC_001);
6459: row.setColumn(1, REC_002);
6460: RecordHandle rh = t_util.t_insertAtSlot(page, 0, row,
6461: (byte) (Page.INSERT_INITIAL | Page.INSERT_OVERFLOW));
6462: t_util.t_checkFetch(page, rh, row);
6463: REPORT("P703 - insert Ok ");
6464:
6465: page.unlatch();
6466: page = t_util.t_getPage(c, ContainerHandle.FIRST_PAGE_NUMBER);
6467:
6468: // Perform 10 tests
6469: // 1 update col0 to grow
6470: // 2 update col1 to grow
6471: // 3 update col0 to shrink
6472: // 4 update col1 to shrink
6473: // 5 update col0 to null
6474: // 6 update col1 to null
6475: // 7 update col0 to non-null
6476: // 8 update col1 to non-null
6477: // 9 update no columns
6478: // 10 update both cols
6479:
6480: P703Helper(page, rh, 0, REC_006, REC_002);
6481: REPORT("P703 - case 1 passed");
6482:
6483: P703Helper(page, rh, 1, REC_007, REC_006);
6484: REPORT("P703 - case 2 passed");
6485:
6486: P703Helper(page, rh, 0, REC_003, REC_007);
6487: REPORT("P703 - case 3 passed");
6488:
6489: P703Helper(page, rh, 1, REC_004, REC_003);
6490: REPORT("P703 - case 4 passed");
6491:
6492: P703Helper(page, rh, 0, null, REC_004);
6493: REPORT("P703 - case 5 passed");
6494:
6495: P703Helper(page, rh, 1, null, null);
6496: REPORT("P703 - case 6 passed");
6497:
6498: P703Helper(page, rh, 0, REC_002, null);
6499: REPORT("P703 - case 7 passed");
6500:
6501: P703Helper(page, rh, 1, REC_001, REC_002);
6502: REPORT("P703 - case 8 passed");
6503:
6504: P703Helper(page, rh, -1, REC_002, REC_001);
6505: REPORT("P703 - case 9 passed");
6506:
6507: FormatableBitSet colList = new FormatableBitSet(2);
6508: colList.set(0);
6509: colList.set(1);
6510: row.setColumn(0, REC_004);
6511: row.setColumn(1, REC_003);
6512: page.update(rh, row.getRow(), colList);
6513: t_util.t_checkFetch(page, rh, row);
6514:
6515: REPORT("P703 - case 10 passed");
6516:
6517: page.unlatch();
6518:
6519: if (segment != ContainerHandle.TEMPORARY_SEGMENT) {
6520: t_util.t_dropContainer(t, segment, cid); // cleanup
6521: }
6522:
6523: t.commit();
6524:
6525: t.close();
6526:
6527: PASS("P703: segment = " + segment);
6528: }
6529:
6530: private void P703Helper(Page page, RecordHandle rh, int colNum,
6531: String newVal, String unchangedCol)
6532: throws StandardException, T_Fail {
6533:
6534: FormatableBitSet colList = new FormatableBitSet(2);
6535: T_RawStoreRow rowU = new T_RawStoreRow(2);
6536:
6537: // -1 indicates no columns set in bit set
6538: if (colNum != -1) {
6539: colList.grow(colNum + 1);
6540: colList.set(colNum);
6541: rowU.setColumn(colNum, newVal);
6542: } else {
6543: colNum = 0; // only used for read from now on
6544: }
6545: page.update(rh, rowU.getRow(), colList);
6546:
6547: T_RawStoreRow row = new T_RawStoreRow(2);
6548: row.setColumn(colNum, newVal);
6549: row.setColumn(colNum == 0 ? 1 : 0, unchangedCol);
6550:
6551: t_util.t_checkFetch(page, rh, row);
6552: }
6553:
6554: /**
6555: Insert a single row with multiple portions.
6556: Update fields in the various portions that grow.
6557:
6558: @exception T_Fail Unexpected behaviour from the API
6559: @exception StandardException Unexpected exception from the implementation
6560: */
6561: protected void P704(long segment) throws StandardException, T_Fail {
6562:
6563: Transaction t = t_util.t_startTransaction();
6564:
6565: long cid = t_util.t_addContainer(t, segment, 4096);
6566:
6567: ContainerHandle c = t_util.t_openContainer(t, segment, cid,
6568: true);
6569: Page page = t_util.t_getPage(c,
6570: ContainerHandle.FIRST_PAGE_NUMBER);
6571: t_util.t_checkEmptyPage(page);
6572:
6573: // row has 15 cols, each with 200 (ish) bytes (100 null chars)
6574: // thus we would expect at least 3 pages
6575: T_RawStoreRow row = new T_RawStoreRow(15);
6576: for (int i = 0; i < 15; i++) {
6577: row.setColumn(i, 100, "XX" + i + "YY");
6578: }
6579:
6580: RecordHandle rh = t_util.t_insertAtSlot(page, 0, row,
6581: (byte) (Page.INSERT_INITIAL | Page.INSERT_OVERFLOW));
6582: t_util.t_checkFetch(page, rh, row);
6583:
6584: page.unlatch();
6585: page = t_util.t_getPage(c, ContainerHandle.FIRST_PAGE_NUMBER);
6586:
6587: // update the each column to grow to be a single page (800 bytes ish)
6588: for (int i = 0; i < 15; i++) {
6589:
6590: REPORT("P704 - col " + i);
6591:
6592: FormatableBitSet colList = new FormatableBitSet(i + 1);
6593: colList.set(i);
6594:
6595: T_RawStoreRow rowU = new T_RawStoreRow(i + 1);
6596: rowU.setColumn(i, 400, "WW" + i + "UU");
6597:
6598: page.update(rh, rowU.getRow(), colList);
6599: page.unlatch();
6600:
6601: row.setColumn(i, 400, "WW" + i + "UU");
6602:
6603: page = t_util.t_getPage(c,
6604: ContainerHandle.FIRST_PAGE_NUMBER);
6605:
6606: t_util.t_checkFetch(page, rh, row);
6607: }
6608: page.unlatch();
6609:
6610: if (segment != ContainerHandle.TEMPORARY_SEGMENT) {
6611: t_util.t_dropContainer(t, segment, cid); // cleanup
6612: }
6613:
6614: t_util.t_commit(t);
6615:
6616: t.close();
6617:
6618: PASS("P704: segment = " + segment);
6619: }
6620:
6621: /**
6622: Same as 704 but update fields in the reverse order.
6623:
6624: @exception T_Fail Unexpected behaviour from the API
6625: @exception StandardException Unexpected exception from the implementation
6626: */
6627: protected void P705(long segment) throws StandardException, T_Fail {
6628:
6629: Transaction t = t_util.t_startTransaction();
6630:
6631: long cid = t_util.t_addContainer(t, segment, 4096);
6632:
6633: ContainerHandle c = t_util.t_openContainer(t, segment, cid,
6634: true);
6635: Page page = t_util.t_getPage(c,
6636: ContainerHandle.FIRST_PAGE_NUMBER);
6637: t_util.t_checkEmptyPage(page);
6638:
6639: // row has 15 cols, each with 200 (ish) bytes (100 null chars)
6640: // thus we would expect at least 3 pages
6641: T_RawStoreRow row = new T_RawStoreRow(15);
6642: for (int i = 0; i < 15; i++) {
6643: row.setColumn(i, 100, "XX" + i + "YY");
6644: }
6645:
6646: RecordHandle rh = t_util.t_insertAtSlot(page, 0, row,
6647: (byte) (Page.INSERT_INITIAL | Page.INSERT_OVERFLOW));
6648: t_util.t_checkFetch(page, rh, row);
6649:
6650: page.unlatch();
6651: page = t_util.t_getPage(c, ContainerHandle.FIRST_PAGE_NUMBER);
6652:
6653: // update the each column to grow to be a single page (800 bytes ish)
6654: for (int i = 14; i >= 0; i--) {
6655:
6656: REPORT("P705 - col " + i);
6657:
6658: FormatableBitSet colList = new FormatableBitSet(i + 1);
6659: colList.set(i);
6660:
6661: T_RawStoreRow rowU = new T_RawStoreRow(i + 1);
6662: rowU.setColumn(i, 400, "WW" + i + "UU");
6663:
6664: page.update(rh, rowU.getRow(), colList);
6665: page.unlatch();
6666:
6667: row.setColumn(i, 400, "WW" + i + "UU");
6668:
6669: page = t_util.t_getPage(c,
6670: ContainerHandle.FIRST_PAGE_NUMBER);
6671:
6672: t_util.t_checkFetch(page, rh, row);
6673: }
6674: page.unlatch();
6675:
6676: if (segment != ContainerHandle.TEMPORARY_SEGMENT) {
6677: t_util.t_dropContainer(t, segment, cid); // cleanup
6678: }
6679:
6680: t_util.t_commit(t);
6681:
6682: t.close();
6683:
6684: PASS("P705: segment = " + segment);
6685: }
6686:
6687: /**
6688: Insert a single row with single or multiple portions.
6689: Update every other field with a long col
6690: The update each column back to a null
6691:
6692: @exception T_Fail Unexpected behaviour from the API
6693: @exception StandardException Unexpected exception from the implementation
6694: */
6695: protected void P706(long segment, boolean multiPortion)
6696: throws StandardException, T_Fail {
6697:
6698: Transaction t = t_util.t_startTransaction();
6699:
6700: long cid = t_util.t_addContainer(t, segment, 4096);
6701:
6702: ContainerHandle c = t_util.t_openContainer(t, segment, cid,
6703: true);
6704: Page page = t_util.t_getPage(c,
6705: ContainerHandle.FIRST_PAGE_NUMBER);
6706: t_util.t_checkEmptyPage(page);
6707:
6708: // row has 15 cols, each with 200 (ish) bytes (100 null chars)
6709: // thus we would expect at least 3 pages
6710: T_RawStoreRow row = new T_RawStoreRow(15);
6711: for (int i = 0; i < 15; i++) {
6712:
6713: row.setColumn(i, multiPortion ? 100 : 10, "XX" + i + "YY");
6714: }
6715:
6716: RecordHandle rh = t_util.t_insertAtSlot(page, 0, row,
6717: (byte) (Page.INSERT_INITIAL | Page.INSERT_OVERFLOW));
6718: t_util.t_checkFetch(page, rh, row);
6719:
6720: page.unlatch();
6721: page = t_util.t_getPage(c, ContainerHandle.FIRST_PAGE_NUMBER);
6722:
6723: // update every other column to be a long column
6724: for (int i = 0; i < 15; i++) {
6725:
6726: if ((i % 2) == 0) {
6727: continue;
6728: }
6729:
6730: REPORT("P706 : multiPortion " + multiPortion + " - col "
6731: + i);
6732:
6733: FormatableBitSet colList = new FormatableBitSet(i + 1);
6734: colList.set(i);
6735:
6736: T_RawStoreRow rowU = new T_RawStoreRow(i + 1);
6737: rowU.setColumn(i, 3000, "WW" + i + "UU"); // longer than 4096 page length
6738:
6739: page.update(rh, rowU.getRow(), colList);
6740: page.unlatch();
6741:
6742: row.setColumn(i, 3000, "WW" + i + "UU");
6743:
6744: page = t_util.t_getPage(c,
6745: ContainerHandle.FIRST_PAGE_NUMBER);
6746:
6747: t_util.t_checkFetch(page, rh, row);
6748: }
6749:
6750: t_util.t_commit(t);
6751:
6752: // update every column to a null
6753: c = t_util.t_openContainer(t, segment, cid, true);
6754: page = t_util.t_getPage(c, ContainerHandle.FIRST_PAGE_NUMBER);
6755: for (int i = 0; i < 15; i++) {
6756:
6757: REPORT("P706 : update to null " + multiPortion + " - col "
6758: + i);
6759:
6760: FormatableBitSet colList = new FormatableBitSet(i + 1);
6761: colList.set(i);
6762:
6763: T_RawStoreRow rowU = new T_RawStoreRow(i + 1);
6764: rowU.setColumn(i, (String) null);
6765:
6766: page.update(rh, rowU.getRow(), colList);
6767: page.unlatch();
6768:
6769: row.setColumn(i, (String) null);
6770:
6771: page = t_util.t_getPage(c,
6772: ContainerHandle.FIRST_PAGE_NUMBER);
6773:
6774: t_util.t_checkFetch(page, rh, row);
6775: }
6776: page.unlatch();
6777:
6778: if (segment != ContainerHandle.TEMPORARY_SEGMENT) {
6779: t_util.t_dropContainer(t, segment, cid); // cleanup
6780: }
6781:
6782: t_util.t_commit(t);
6783:
6784: t.close();
6785:
6786: PASS("P706: multiPortion " + multiPortion + " segment = "
6787: + segment);
6788: }
6789:
6790: /**
6791: Insert a single record that has several chunks
6792: and every other column is a long column
6793: @exception T_Fail Unexpected behaviour from the API
6794: @exception StandardException Unexpected exception from the implementation
6795: */
6796: protected void P707(long segment) throws StandardException, T_Fail {
6797:
6798: Transaction t = t_util.t_startTransaction();
6799:
6800: long cid = t_util.t_addContainer(t, segment, 4096);
6801:
6802: ContainerHandle c = t_util.t_openContainer(t, segment, cid,
6803: true);
6804: Page page = t_util.t_getPage(c,
6805: ContainerHandle.FIRST_PAGE_NUMBER);
6806: t_util.t_checkEmptyPage(page);
6807:
6808: T_RawStoreRow row = new T_RawStoreRow(20);
6809: for (int i = 0; i < 20; i++) {
6810: if ((i % 2) == 0)
6811: row.setColumn(i, 200, "XX" + i + "YY"); // big but first within a page
6812: else
6813: row.setColumn(i, 4000, "XX" + i + "YY"); // long column
6814: }
6815:
6816: RecordHandle rh = t_util.t_insertAtSlot(page, 0, row,
6817: (byte) (Page.INSERT_INITIAL | Page.INSERT_OVERFLOW));
6818: t_util.t_checkFetch(page, rh, row);
6819:
6820: page.unlatch();
6821:
6822: if (segment != ContainerHandle.TEMPORARY_SEGMENT) {
6823: t_util.t_dropContainer(t, segment, cid); // cleanup
6824: }
6825:
6826: t_util.t_commit(t);
6827:
6828: t.close();
6829:
6830: PASS("P707: segment = " + segment);
6831: }
6832:
6833: /**
6834: Insert a single row with single or multiple portions.
6835: Update every other field with a long col
6836: rollback.
6837: The update each column back to a null & rollback
6838:
6839: @exception T_Fail Unexpected behaviour from the API
6840: @exception StandardException Unexpected exception from the implementation
6841: */
6842: protected void P708(long segment, boolean multiPortion)
6843: throws StandardException, T_Fail {
6844:
6845: Transaction t = t_util.t_startTransaction();
6846:
6847: long cid = t_util.t_addContainer(t, segment, 4096);
6848:
6849: ContainerHandle c = t_util.t_openContainer(t, segment, cid,
6850: true);
6851: Page page = t_util.t_getPage(c,
6852: ContainerHandle.FIRST_PAGE_NUMBER);
6853: t_util.t_checkEmptyPage(page);
6854:
6855: // row has 15 cols, each with 200 (ish) bytes (100 null chars)
6856: // thus we would expect at least 3 pages
6857: T_RawStoreRow row = new T_RawStoreRow(15);
6858: for (int i = 0; i < 15; i++) {
6859:
6860: row.setColumn(i, multiPortion ? 100 : 10, "XX" + i + "YY");
6861: }
6862:
6863: RecordHandle rh = t_util.t_insertAtSlot(page, 0, row,
6864: (byte) (Page.INSERT_INITIAL | Page.INSERT_OVERFLOW));
6865: t_util.t_checkFetch(page, rh, row);
6866:
6867: page.unlatch();
6868: t_util.t_commit(t);
6869: c = t_util.t_openContainer(t, segment, cid, true);
6870:
6871: page = t_util.t_getPage(c, ContainerHandle.FIRST_PAGE_NUMBER);
6872:
6873: // update every other column to be a long column
6874: for (int i = 0; i < 15; i++) {
6875:
6876: if ((i % 2) == 0) {
6877: continue;
6878: }
6879:
6880: REPORT("P708 : multiPortion " + multiPortion + " - col "
6881: + i);
6882:
6883: FormatableBitSet colList = new FormatableBitSet(i + 1);
6884: colList.set(i);
6885:
6886: T_RawStoreRow rowU = new T_RawStoreRow(i + 1);
6887: rowU.setColumn(i, 3000, "WW" + i + "UU"); // longer than 4096 page length
6888:
6889: page.update(rh, rowU.getRow(), colList);
6890: }
6891:
6892: t_util.t_abort(t);
6893:
6894: c = t_util.t_openContainer(t, segment, cid, false);
6895: page = t_util.t_getPage(c, ContainerHandle.FIRST_PAGE_NUMBER);
6896: t_util.t_checkFetch(page, rh, row);
6897: page.unlatch();
6898:
6899: if (segment != ContainerHandle.TEMPORARY_SEGMENT) {
6900: t_util.t_dropContainer(t, segment, cid); // cleanup
6901: }
6902:
6903: t_util.t_commit(t);
6904:
6905: t.close();
6906:
6907: PASS("P708: multiPortion " + multiPortion + " segment = "
6908: + segment);
6909: }
6910:
6911: /**
6912: P709:
6913: this test exercises purgeAtSlot , rollsback and purges the slot again,
6914: to make sure not logging the data does not have any impact on repurging
6915: the rollbacked purges.
6916: @exception T_Fail Unexpected behaviour from the API
6917: @exception StandardException Unexpected exception from the implementation
6918: */
6919: protected void P709() throws StandardException, T_Fail {
6920: logDataForPurges = false;
6921: Transaction t = t_util.t_startTransaction();
6922: long cid = t_util.t_addContainer(t, 0);
6923: t_util.t_commit(t);
6924:
6925: ContainerHandle c = t_util.t_openContainer(t, 0, cid, true);
6926: Page page = t_util.t_getPage(c,
6927: ContainerHandle.FIRST_PAGE_NUMBER);
6928:
6929: // REPORT("insert 5 records");
6930: T_RawStoreRow row0 = new T_RawStoreRow(REC_001);
6931: T_RawStoreRow row1 = new T_RawStoreRow(REC_001);
6932: T_RawStoreRow row2 = new T_RawStoreRow(REC_002);
6933: T_RawStoreRow row3 = new T_RawStoreRow(REC_003);
6934: T_RawStoreRow row4 = new T_RawStoreRow(REC_004);
6935:
6936: RecordHandle r0, r1, r2, r3, r4;
6937: r0 = t_util.t_insertAtSlot(page, 0, row0);
6938: r1 = t_util.t_insertAtSlot(page, 1, row1);
6939: r2 = t_util.t_insertAtSlot(page, 2, row2);
6940: r3 = t_util.t_insertAtSlot(page, 3, row3);
6941: r4 = t_util.t_insertAtSlot(page, 4, row4);
6942:
6943: if (r3 != null)
6944: page.deleteAtSlot(3, true, (LogicalUndo) null);
6945:
6946: // REPORT("commit it");
6947: t_util.t_commit(t);
6948:
6949: c = t_util.t_openContainer(t, 0, cid, true);
6950: page = t_util.t_getPage(c, ContainerHandle.FIRST_PAGE_NUMBER);
6951:
6952: try {
6953: page.purgeAtSlot(-1, 1, logDataForPurges);
6954: throw T_Fail
6955: .testFailMsg("negative slot number did not cause an exception");
6956: } catch (StandardException se) {
6957: } // expected
6958:
6959: try {
6960: page.purgeAtSlot(4, 4, logDataForPurges);
6961: throw T_Fail
6962: .testFailMsg("purging more rows than is on page did not cause an exception");
6963: } catch (StandardException se) {
6964: } // expected
6965:
6966: // if not all the rows are there, do minimal test
6967: if (r4 == null) {
6968: int rcount = page.recordCount();
6969: page.purgeAtSlot(0, 1, logDataForPurges);
6970: if (page.recordCount() != rcount - 1)
6971: T_Fail.testFailMsg("failed to purge a record, expect "
6972: + (rcount - 1) + " got " + page.recordCount());
6973:
6974: if (testRollback) {
6975: t_util.t_abort(t);
6976:
6977: c = t_util.t_openContainer(t, 0, cid, true);
6978: page = t_util.t_getPage(c,
6979: ContainerHandle.FIRST_PAGE_NUMBER);
6980: if (logDataForPurges)
6981: t_util.t_checkFetchBySlot(page, 0, REC_001, false,
6982: true);
6983: else
6984: t_util.t_checkFetchBySlot(page, 0, REC_NULL, false,
6985: true);
6986: if (page.recordCount() != rcount)
6987: T_Fail
6988: .testFailMsg("failed to rollback purge, expect "
6989: + rcount
6990: + " got "
6991: + page.recordCount());
6992: } else {
6993: t_util.t_commit(t);
6994: }
6995: PASS("mimimal purging P709");
6996: return;
6997: }
6998:
6999: // REPORT("purge 2 records from middle");
7000: page.purgeAtSlot(1, 2, logDataForPurges);
7001: t_util.t_checkFetchBySlot(page, 0, REC_001, false, true);
7002: t_util.t_checkFetchBySlot(page, 1, REC_003, true, true);
7003: t_util.t_checkFetchBySlot(page, 2, REC_004, false, true);
7004:
7005: if (page.recordCount() != 3)
7006: T_Fail
7007: .testFailMsg("page expect to have 3 records, recordCount() = "
7008: + page.recordCount());
7009:
7010: // REPORT("purge all records from the page");
7011: page.purgeAtSlot(0, 3, logDataForPurges);
7012: if (page.recordCount() != 0)
7013: T_Fail
7014: .testFailMsg("page expect to have 0 records, recordCount() = "
7015: + page.recordCount());
7016:
7017: if (testRollback) {
7018:
7019: REPORT("testing rollback");
7020: t_util.t_abort(t);
7021:
7022: c = t_util.t_openContainer(t, 0, cid, true);
7023: page = t_util.t_getPage(c,
7024: ContainerHandle.FIRST_PAGE_NUMBER);
7025:
7026: if (logDataForPurges) {
7027: t_util
7028: .t_checkFetchBySlot(page, 0, REC_001, false,
7029: true);
7030: t_util
7031: .t_checkFetchBySlot(page, 1, REC_001, false,
7032: true);
7033: t_util
7034: .t_checkFetchBySlot(page, 2, REC_002, false,
7035: true);
7036: t_util.t_checkFetchBySlot(page, 3, REC_003, true, true);
7037: t_util
7038: .t_checkFetchBySlot(page, 4, REC_004, false,
7039: true);
7040: } else {
7041: t_util.t_checkFetchBySlot(page, 0, REC_NULL, false,
7042: true);
7043: t_util.t_checkFetchBySlot(page, 1, REC_NULL, false,
7044: true);
7045: t_util.t_checkFetchBySlot(page, 2, REC_NULL, false,
7046: true);
7047: t_util
7048: .t_checkFetchBySlot(page, 3, REC_NULL, true,
7049: true);
7050: t_util.t_checkFetchBySlot(page, 4, REC_NULL, false,
7051: true);
7052: }
7053:
7054: if (page.recordCount() != 5)
7055: T_Fail
7056: .testFailMsg("page expect to have 5 records, recordCount() = "
7057: + page.recordCount());
7058:
7059: // REPORT("purge 3 records from the end");
7060: page.purgeAtSlot(2, 3, logDataForPurges);
7061: if (logDataForPurges) {
7062: t_util
7063: .t_checkFetchBySlot(page, 0, REC_001, false,
7064: true);
7065: t_util
7066: .t_checkFetchBySlot(page, 1, REC_001, false,
7067: true);
7068: } else {
7069: t_util.t_checkFetchBySlot(page, 0, REC_NULL, false,
7070: true);
7071: t_util.t_checkFetchBySlot(page, 1, REC_NULL, false,
7072: true);
7073: }
7074: if (page.recordCount() != 2)
7075: T_Fail
7076: .testFailMsg("page expect to have 2 records, recordCount() = "
7077: + page.recordCount());
7078:
7079: // REPORT("rollback");
7080: t_util.t_abort(t);
7081:
7082: c = t_util.t_openContainer(t, 0, cid, true);
7083: page = t_util.t_getPage(c,
7084: ContainerHandle.FIRST_PAGE_NUMBER);
7085: if (logDataForPurges) {
7086: t_util
7087: .t_checkFetchBySlot(page, 0, REC_001, false,
7088: true);
7089: t_util
7090: .t_checkFetchBySlot(page, 1, REC_001, false,
7091: true);
7092: t_util
7093: .t_checkFetchBySlot(page, 2, REC_002, false,
7094: true);
7095: t_util.t_checkFetchBySlot(page, 3, REC_003, true, true);
7096: t_util
7097: .t_checkFetchBySlot(page, 4, REC_004, false,
7098: true);
7099: } else {
7100: t_util.t_checkFetchBySlot(page, 0, REC_NULL, false,
7101: true);
7102: t_util.t_checkFetchBySlot(page, 1, REC_NULL, false,
7103: true);
7104: t_util.t_checkFetchBySlot(page, 2, REC_NULL, false,
7105: true);
7106: t_util
7107: .t_checkFetchBySlot(page, 3, REC_NULL, true,
7108: true);
7109: t_util.t_checkFetchBySlot(page, 4, REC_NULL, false,
7110: true);
7111: }
7112:
7113: if (page.recordCount() != 5)
7114: T_Fail
7115: .testFailMsg("page expect to have 5 records, recordCount() = "
7116: + page.recordCount());
7117:
7118: // REPORT("make sure delete record is reconstituted as such");
7119: if (page.isDeletedAtSlot(1))
7120: T_Fail
7121: .testFailMsg("rolled back purged undeleted record cause record to be deleted");
7122: if (!page.isDeletedAtSlot(3))
7123: T_Fail
7124: .testFailMsg("rolled back purged deleted record cause record to be undeleted");
7125: }
7126:
7127: REPORT("purging again the purges rolled back earlier");
7128: //purge again and this time do commit , instead of rollback.
7129: // REPORT("purge 2 records from middle");
7130: page.purgeAtSlot(1, 2, logDataForPurges);
7131: t_util.t_checkFetchBySlot(page, 0, REC_NULL, false, true);
7132: t_util.t_checkFetchBySlot(page, 1, REC_NULL, true, true);
7133: t_util.t_checkFetchBySlot(page, 2, REC_NULL, false, true);
7134:
7135: if (page.recordCount() != 3)
7136: T_Fail
7137: .testFailMsg("page expect to have 3 records, recordCount() = "
7138: + page.recordCount());
7139:
7140: // REPORT("purge all records from the page");
7141: page.purgeAtSlot(0, 3, logDataForPurges);
7142: if (page.recordCount() != 0)
7143: T_Fail
7144: .testFailMsg("page expect to have 0 records, recordCount() = "
7145: + page.recordCount());
7146:
7147: t_util.t_abort(t);
7148:
7149: c = t_util.t_openContainer(t, 0, cid, true);
7150: page = t_util.t_getPage(c, ContainerHandle.FIRST_PAGE_NUMBER);
7151:
7152: if (page.recordCount() != 5)
7153: T_Fail
7154: .testFailMsg("page expect to have 5 records, recordCount() = "
7155: + page.recordCount());
7156:
7157: // REPORT("purge 3 records from the end");
7158: page.purgeAtSlot(2, 3, logDataForPurges);
7159: t_util.t_checkFetchBySlot(page, 0, REC_NULL, false, true);
7160: t_util.t_checkFetchBySlot(page, 1, REC_NULL, false, true);
7161: if (page.recordCount() != 2)
7162: T_Fail
7163: .testFailMsg("page expect to have 2 records, recordCount() = "
7164: + page.recordCount());
7165:
7166: // REPORT("commit");
7167: t_util.t_commit(t);
7168:
7169: c = t_util.t_openContainer(t, 0, cid, true);
7170: page = t_util.t_getPage(c, ContainerHandle.FIRST_PAGE_NUMBER);
7171: t_util.t_checkFetchBySlot(page, 0, REC_NULL, false, true);
7172: t_util.t_checkFetchBySlot(page, 1, REC_NULL, false, true);
7173:
7174: if (page.recordCount() != 2)
7175: T_Fail
7176: .testFailMsg("page expect to have 2 records, recordCount() = "
7177: + page.recordCount());
7178:
7179: PASS("P709");
7180:
7181: t_util.t_dropContainer(t, 0, cid); // cleanup
7182: t_util.t_commit(t);
7183: t.close();
7184: }
7185:
7186: /**
7187: Test space reclaimation - purging of a long rows with a rollback and
7188: purging againg with no data logging for purges
7189: @exception T_Fail Unexpected behaviour from the API
7190: @exception StandardException Unexpected exception from the implementation
7191: */
7192: protected void P710() throws StandardException, T_Fail {
7193: long segment = 0;
7194: Transaction t = t_util.t_startTransaction();
7195: long cid = t_util.t_addContainer(t, segment, 4096);
7196:
7197: ContainerHandle c = t_util.t_openContainer(t, segment, cid,
7198: true);
7199: Page page = t_util.t_getPage(c,
7200: ContainerHandle.FIRST_PAGE_NUMBER);
7201: try {
7202: t_util.t_checkEmptyPage(page);
7203:
7204: int insertFlag = Page.INSERT_INITIAL | Page.INSERT_OVERFLOW;
7205:
7206: // insert a row with 100 columns from 200 to 400 bytes each and make it
7207: // sprawl across many pages.
7208: T_RawStoreRow r1 = new T_RawStoreRow(100);
7209: for (int i = 0; i < 100; i++)
7210: r1.setColumn(i, 100 + i, REC_001);
7211:
7212: RecordHandle rh1 = t_util.t_insertAtSlot(page, 0, r1,
7213: (byte) insertFlag);
7214: t_util.t_checkFetch(page, rh1, r1);
7215:
7216: Page nextPage = t_util.t_addPage(c);
7217: long nextPageNumber = nextPage.getPageNumber();
7218: // deallocate it
7219: t_util.t_removePage(c, nextPage);
7220:
7221: REPORT("P710 - Nextpage is " + nextPageNumber);
7222: page.unlatch();
7223: page = null;
7224: t_util.t_commit(t);
7225:
7226: // See what the next page is.
7227: c = t_util.t_openContainer(t, segment, cid, true);
7228:
7229: // Now purge that first row.
7230: page = t_util.t_getPage(c,
7231: ContainerHandle.FIRST_PAGE_NUMBER);
7232:
7233: t_util.t_checkRecordCount(page, 1, 1);
7234: page.purgeAtSlot(0, 1, logDataForPurges);
7235:
7236: t_util.t_checkEmptyPage(page);
7237: page.unlatch();
7238: page = null;
7239: t_util.t_commit(t);
7240:
7241: // give some time for post commit to finish
7242: t_util.t_wait(10); // wait 10 milliseconds.
7243:
7244: // reinsert r1, it should use no extra page than last time.
7245: c = t_util.t_openContainer(t, segment, cid, true);
7246: page = t_util.t_getPage(c,
7247: ContainerHandle.FIRST_PAGE_NUMBER);
7248:
7249: RecordHandle rh2 = t_util.t_insertAtSlot(page, 0, r1,
7250: (byte) insertFlag);
7251: t_util.t_checkFetch(page, rh2, r1);
7252: page.unlatch();
7253: page = null;
7254:
7255: // now verify that it used up no more page than last time
7256: nextPage = t_util.t_addPage(c);
7257: long checkNextPageNumber = nextPage.getPageNumber();
7258: nextPage.unlatch();
7259:
7260: if (nextPageNumber != checkNextPageNumber)
7261: throw T_Fail
7262: .testFailMsg("fail to reuse row pieces expect next page="
7263: + nextPageNumber
7264: + " but got "
7265: + checkNextPageNumber);
7266:
7267: t_util.t_commit(t);
7268:
7269: // Purge them and roll them back via savepoint. These should not
7270: // be reclaimed.
7271: c = t_util.t_openContainer(t, segment, cid, true);
7272: t.setSavePoint(SP1, null);
7273: page = t_util.t_getPage(c,
7274: ContainerHandle.FIRST_PAGE_NUMBER);
7275: t_util.t_checkRecordCount(page, 1, 1);
7276: page.purgeAtSlot(0, 1, logDataForPurges);
7277: page.unlatch();
7278: page = null;
7279:
7280: // make sure we cannot get our hands on a page that is freed up by
7281: // the purge
7282: Page testPage = t_util.t_addPage(c);
7283: T_RawStoreRow testRow = new T_RawStoreRow(REC_001);
7284: t_util.t_insert(testPage, testRow);
7285: testPage.unlatch();
7286:
7287: t.rollbackToSavePoint(SP1, null);
7288:
7289: testPage = t_util.t_addPage(c);
7290: t_util.t_insert(testPage, testRow);
7291: testPage.unlatch();
7292:
7293: t_util.t_commit(t);
7294: t_util.t_wait(10);
7295:
7296: c = t_util.t_openContainer(t, segment, cid, true);
7297:
7298: testPage = t_util.t_addPage(c);
7299: t_util.t_insert(testPage, testRow);
7300: testPage.unlatch();
7301:
7302: page = t_util.t_getPage(c,
7303: ContainerHandle.FIRST_PAGE_NUMBER);
7304: t_util.t_checkRecordCount(page, 1, 1);
7305:
7306: //repurge again.
7307: page.purgeAtSlot(0, 1, logDataForPurges);
7308: t_util.t_abort(t);
7309: // t_util.t_checkFetch(page, rh2, r1);
7310: page = null;
7311: c = t_util.t_openContainer(t, segment, cid, true);
7312: page = t_util.t_getPage(c,
7313: ContainerHandle.FIRST_PAGE_NUMBER);
7314: t_util.t_checkRecordCount(page, 1, 1);
7315: //repurge again and do commit
7316: page.purgeAtSlot(0, 1, logDataForPurges);
7317: page.unlatch();
7318: page = null;
7319: t_util.t_commit(t);
7320: c = t_util.t_openContainer(t, segment, cid, true);
7321: page = t_util.t_getPage(c,
7322: ContainerHandle.FIRST_PAGE_NUMBER);
7323: t_util.t_checkRecordCount(page, 0, 0);
7324: page.unlatch();
7325: page = null;
7326: t_util.t_dropContainer(t, segment, cid); // cleanup
7327:
7328: } finally {
7329: if (page != null)
7330: page.unlatch();
7331: t_util.t_commit(t);
7332: t.close();
7333: }
7334:
7335: PASS("P710");
7336: }
7337:
7338: /**
7339: Test space reclaimation - purging of a row with serveral long columns
7340: rollback and repurge them again.
7341:
7342: @exception T_Fail Unexpected behaviour from the API
7343: @exception StandardException Unexpected exception from the implementation
7344: */
7345: protected void P711() throws StandardException, T_Fail {
7346:
7347: long segment = 0;
7348: Transaction t = t_util.t_startTransaction();
7349: long cid = t_util.t_addContainer(t, segment, 4096);
7350:
7351: ContainerHandle c = t_util.t_openContainer(t, segment, cid,
7352: true);
7353: Page page = t_util.t_getPage(c,
7354: ContainerHandle.FIRST_PAGE_NUMBER);
7355: try {
7356: t_util.t_checkEmptyPage(page);
7357:
7358: int insertFlag = Page.INSERT_INITIAL | Page.INSERT_OVERFLOW;
7359: T_RawStoreRow r1 = new T_RawStoreRow(1);
7360: // insert a long column
7361: r1.setColumn(0, 5000, REC_001);
7362: RecordHandle rh1 = t_util.t_insertAtSlot(page, 0, r1,
7363: (byte) insertFlag);
7364: t_util.t_checkFetch(page, rh1, r1);
7365:
7366: // insert a 6 column row, every other column is long
7367: T_RawStoreRow r2 = new T_RawStoreRow(6);
7368: r2.setColumn(0, 600, REC_001); // this takes ~1200 bytes
7369: r2.setColumn(1, 5000, REC_002); // this takes ~10000 bytes
7370: r2.setColumn(2, 600, REC_001);
7371: r2.setColumn(3, 5000, REC_002);
7372: r2.setColumn(4, 600, REC_001);
7373: r2.setColumn(5, 5000, REC_002);
7374: RecordHandle rh2 = t_util.t_insertAtSlot(page, 0, r2,
7375: (byte) insertFlag);
7376: t_util.t_checkFetch(page, rh2, r2);
7377:
7378: // insert a long column - this should fail
7379: RecordHandle rh3 = t_util.t_insertAtSlot(page, 0, r1,
7380: (byte) insertFlag);
7381: if (rh3 != null) {
7382: throw T_Fail
7383: .testFailMsg("expect the 3rd row to not fit on page");
7384: }
7385: page.unlatch();
7386: page = null;
7387:
7388: Page nextPage = t_util.t_addPage(c);
7389: long nextPageNumber = nextPage.getPageNumber();
7390: // deallocate it
7391: t_util.t_removePage(c, nextPage);
7392:
7393: REPORT("P711 - Nextpage is " + nextPageNumber);
7394:
7395: t_util.t_commit(t);
7396:
7397: // now purge them
7398: c = t_util.t_openContainer(t, segment, cid, true);
7399: page = t_util.t_getPage(c,
7400: ContainerHandle.FIRST_PAGE_NUMBER);
7401:
7402: t_util.t_checkRecordCount(page, 2, 2);
7403: page.purgeAtSlot(0, 2, logDataForPurges);
7404: t_util.t_checkEmptyPage(page);
7405: page.unlatch();
7406: page = null;
7407:
7408: t_util.t_abort(t);
7409:
7410: // give some time for post commit to finish
7411: t_util.t_wait(10); // wait 10 milliseconds.
7412:
7413: // Purge them again and roll them back via savepoint. These should not
7414: // be reclaimed.
7415: c = t_util.t_openContainer(t, segment, cid, true);
7416:
7417: t.setSavePoint(SP1, null);
7418: page = t_util.t_getPage(c,
7419: ContainerHandle.FIRST_PAGE_NUMBER);
7420:
7421: t_util.t_checkRecordCount(page, 2, 2);
7422: page.purgeAtSlot(0, 2, logDataForPurges);
7423: t_util.t_checkEmptyPage(page);
7424:
7425: page.unlatch();
7426: page = null;
7427:
7428: // make sure we cannot get our hands on a page that is freed up by
7429: // the purge
7430: Page testPage = t_util.t_addPage(c);
7431: T_RawStoreRow testRow = new T_RawStoreRow(REC_001);
7432: t_util.t_insert(testPage, testRow);
7433: testPage.unlatch();
7434:
7435: t.rollbackToSavePoint(SP1, null);
7436:
7437: testPage = t_util.t_addPage(c);
7438: t_util.t_insert(testPage, testRow);
7439: testPage.unlatch();
7440:
7441: t_util.t_commit(t);
7442:
7443: // give some time for post commit to finish
7444: t_util.t_wait(10);
7445:
7446: // check to make sure post commit did not reclaim those rows.
7447: c = t_util.t_openContainer(t, segment, cid, true);
7448:
7449: testPage = t_util.t_addPage(c);
7450: t_util.t_insert(testPage, testRow);
7451: testPage.unlatch();
7452:
7453: page = t_util.t_getPage(c,
7454: ContainerHandle.FIRST_PAGE_NUMBER);
7455:
7456: t_util.t_checkRecordCount(page, 2, 2);
7457: t_util.t_checkFetch(page, rh1, r1);
7458:
7459: // During purges when data is not logged when slots are purged
7460: // they become null on rollback and some cases like long columns
7461: // we remove the wholepage on rollback we get the data back.
7462: T_RawStoreRow r2_wnl = new T_RawStoreRow(6);
7463: r2_wnl.setColumn(0, 4, REC_NULL);
7464: r2_wnl.setColumn(1, 5000, REC_002);
7465: r2_wnl.setColumn(2, 4, REC_NULL);
7466: r2_wnl.setColumn(3, 5000, REC_002);
7467: r2_wnl.setColumn(4, 4, REC_NULL);
7468: r2_wnl.setColumn(5, 5000, REC_002);
7469: t_util.t_checkFetch(page, rh2, r2_wnl);
7470:
7471: page.unlatch();
7472: page = null;
7473:
7474: t_util.t_dropContainer(t, segment, cid); // cleanup
7475:
7476: } finally {
7477: if (page != null)
7478: page.unlatch();
7479: t_util.t_commit(t);
7480: t.close();
7481: }
7482:
7483: PASS("P711");
7484:
7485: }
7486:
7487: // test writing out large log records
7488: protected void L001() throws StandardException, T_Fail {
7489: Transaction t = t_util.t_startTransaction();
7490:
7491: // if runing multi threaded, only have 1 thread log these large record
7492: // or we may get out of memeory error
7493: int loop = 10;
7494: int logSize = (threadNumber == 0) ? 50000 : 50;
7495:
7496: try {
7497: for (int i = 0; i < loop; i++) {
7498: Loggable l = new T_Undoable(t.getGlobalId(), -1, -1,
7499: T_Undoable.REMOVE_NONE, 0, //LWM ignored
7500: true, 10, false, i * logSize, false);
7501: t.logAndDo(l);
7502: }
7503: t.commit();
7504: t.close();
7505: t = null;
7506:
7507: t = t_util.t_startTransaction();
7508: for (int i = 0; i < loop; i++) {
7509: Loggable l = new T_Undoable(t.getGlobalId(), -1, -1,
7510: T_Undoable.REMOVE_NONE, 0, //LWM ignored
7511: true, 10, false, i * logSize, false);
7512:
7513: t.logAndDo(l);
7514: }
7515:
7516: PASS("L001");
7517: } finally {
7518: t.commit();
7519: t.close();
7520: }
7521: }
7522:
7523: /**
7524: Test checkpoint
7525: @exception T_Fail Unexpected behaviour from the API
7526: @exception StandardException Unexpected exception from the implementation
7527: */
7528: protected void CP001() throws StandardException, T_Fail {
7529: if (!testRollback)
7530: return;
7531:
7532: ContextManager previousCM = contextService
7533: .getCurrentContextManager();
7534: Transaction longtran = null;
7535:
7536: ContextManager cm1 = null;
7537: Transaction t1 = null;
7538:
7539: ContextManager cm2 = null;
7540: Transaction t2 = null;
7541:
7542: // ContextManager cpm = null; // reserved for the checkpoint transaction
7543: try {
7544:
7545: T_RawStoreRow row1 = new T_RawStoreRow(REC_001);
7546: T_RawStoreRow row2 = new T_RawStoreRow(REC_002);
7547: T_RawStoreRow row3 = new T_RawStoreRow(REC_003);
7548: T_RawStoreRow row4 = new T_RawStoreRow(REC_004);
7549: T_RawStoreRow row5 = new T_RawStoreRow(REC_005);
7550:
7551: // start a long running transaction that spans multiple checkpoints
7552: // make sure it can be rolled back a the end
7553: longtran = t_util.t_startTransaction();
7554:
7555: long cid = t_util.t_addContainer(longtran, 0);
7556: ContainerHandle c = t_util.t_openContainer(longtran, 0,
7557: cid, true);
7558: RecordHandle r1 = t_util.t_insert(c, row1);
7559: RecordHandle r2 = t_util.t_insert(c, row2);
7560: t_util.t_commit(longtran);
7561:
7562: c = t_util.t_openContainer(longtran, 0, cid, true);
7563: Page p2 = t_util.t_getPage(c, r2.getPageNumber());
7564: p2.update(r2, row5.getRow(), (FormatableBitSet) null);
7565: p2.unlatch();
7566:
7567: // a bunch of short running transactions that criss cross the
7568: // checkpoints
7569:
7570: cm1 = contextService.newContextManager();
7571: contextService.setCurrentContextManager(cm1);
7572: t1 = t_util.t_startTransaction();
7573:
7574: long cid1 = t_util.t_addContainer(t1, 0);
7575: ContainerHandle c1 = t_util.t_openContainer(t1, 0, cid1,
7576: true);
7577: RecordHandle r3 = t_util.t_insert(c1, row3);
7578: RecordHandle r4 = t_util.t_insert(c1, row4);
7579: contextService.resetCurrentContextManager(cm1);
7580:
7581: cm2 = contextService.newContextManager();
7582: contextService.setCurrentContextManager(cm2);
7583: t2 = t_util.t_startTransaction();
7584:
7585: long cid2 = t_util.t_addContainer(t2, 0);
7586: ContainerHandle c2 = t_util.t_openContainer(t2, 0, cid2,
7587: true);
7588: RecordHandle r5 = t_util.t_insert(c2, row1);
7589: t_util.t_commit(t2);
7590: c2 = t_util.t_openContainer(t2, 0, cid2, true);
7591: Page p5 = t_util.t_getPage(c2, r5.getPageNumber());
7592: p5.update(r5, row5.getRow(), (FormatableBitSet) null);
7593: p5.unlatch();
7594:
7595: // cpm = contextService.newContextManager();
7596: // contextService.setCurrentContextManager(cpm);
7597: factory.checkpoint();
7598: contextService.resetCurrentContextManager(cm2);
7599:
7600: // make sure checkpoint did not destroy any data
7601: contextService.setCurrentContextManager(previousCM);
7602: t_util.t_checkFetch(c, r1, REC_001);
7603: t_util.t_checkFetch(c, r2, REC_005);
7604: contextService.resetCurrentContextManager(previousCM);
7605:
7606: contextService.setCurrentContextManager(cm1);
7607: t_util.t_checkFetch(c1, r3, REC_003);
7608: t_util.t_checkFetch(c1, r4, REC_004);
7609: contextService.resetCurrentContextManager(cm1);
7610:
7611: contextService.setCurrentContextManager(cm2);
7612: t_util.t_checkFetch(c2, r5, REC_005);
7613:
7614: // two consecutive checkpoints
7615: // contextService.setCurrentContextManager(cpm);
7616: factory.checkpoint();
7617: contextService.resetCurrentContextManager(cm2);
7618:
7619: // we can insert some more
7620: contextService.setCurrentContextManager(previousCM);
7621: Page page = t_util.t_addPage(c);
7622: RecordHandle r6 = t_util.t_insertAtSlot(page, 0, row1,
7623: Page.INSERT_UNDO_WITH_PURGE);
7624: page.unlatch();
7625: contextService.resetCurrentContextManager(previousCM);
7626:
7627: // commit/abort everything except the long running transaction
7628: contextService.setCurrentContextManager(cm1);
7629: t_util.t_commit(t1);
7630: contextService.resetCurrentContextManager(cm1);
7631:
7632: contextService.setCurrentContextManager(cm2);
7633: t_util.t_abort(t2);
7634: contextService.resetCurrentContextManager(cm2);
7635:
7636: contextService.setCurrentContextManager(previousCM);
7637: t_util.t_checkFetch(c, r1, REC_001);
7638: t_util.t_checkFetch(c, r2, REC_005);
7639: t_util.t_checkFetch(c, r6, REC_001);
7640: contextService.resetCurrentContextManager(previousCM);
7641:
7642: contextService.setCurrentContextManager(cm1);
7643: c1 = t_util.t_openContainer(t1, 0, cid1, true);
7644: t_util.t_checkFetch(c1, r3, REC_003);
7645: t_util.t_checkFetch(c1, r4, REC_004);
7646: contextService.resetCurrentContextManager(cm1);
7647:
7648: contextService.setCurrentContextManager(cm2);
7649: c2 = t_util.t_openContainer(t2, 0, cid2, true);
7650: t_util.t_checkFetch(c2, r5, REC_001);
7651:
7652: // checkpoint again
7653: // contextService.setCurrentContextManager(cpm);
7654: factory.checkpoint();
7655: contextService.resetCurrentContextManager(cm2);
7656:
7657: contextService.setCurrentContextManager(previousCM);
7658: t_util.t_abort(longtran);
7659: c = t_util.t_openContainer(longtran, 0, cid, true);
7660: t_util.t_checkFetch(c, r1, REC_001);
7661: t_util.t_checkFetch(c, r2, REC_002);
7662:
7663: Page p6 = t_util.t_getPage(c, r6.getPageNumber());
7664: t_util.t_checkEmptyPage(p6);
7665: p6.unlatch();
7666:
7667: t_util.t_dropContainer(longtran, 0, cid); // cleanup
7668: contextService.resetCurrentContextManager(previousCM);
7669:
7670: contextService.setCurrentContextManager(cm1);
7671: t_util.t_checkFetch(c1, r3, REC_003);
7672: t_util.t_checkFetch(c1, r4, REC_004);
7673: t_util.t_dropContainer(t1, 0, cid1);
7674: contextService.resetCurrentContextManager(cm1);
7675:
7676: contextService.setCurrentContextManager(cm2);
7677: t_util.t_checkFetch(c2, r5, REC_001);
7678: t_util.t_dropContainer(t2, 0, cid2);
7679:
7680: // checkpoint again
7681: // contextService.setCurrentContextManager(cpm);
7682: factory.checkpoint();
7683: contextService.resetCurrentContextManager(cm2);
7684:
7685: PASS("CP001");
7686:
7687: } catch (Throwable t) {
7688: t.printStackTrace(System.err);
7689:
7690: if (cm1 != null)
7691: cm1.cleanupOnError(t);
7692: if (cm2 != null)
7693: cm2.cleanupOnError(t);
7694: // if (cpm != null)
7695: // cpm.cleanupOnError(t);
7696:
7697: } finally {
7698:
7699: if (t2 != null) {
7700: contextService.setCurrentContextManager(cm2);
7701: t_util.t_commit(t2);
7702: t2.close();
7703: contextService.resetCurrentContextManager(cm2);
7704: }
7705:
7706: if (t1 != null) {
7707: contextService.setCurrentContextManager(cm1);
7708: t_util.t_commit(t1);
7709: t1.close();
7710: contextService.resetCurrentContextManager(cm1);
7711: }
7712:
7713: if (longtran != null) {
7714: contextService.setCurrentContextManager(previousCM);
7715: t_util.t_commit(longtran);
7716: longtran.close();
7717: contextService.resetCurrentContextManager(previousCM);
7718: }
7719:
7720: //DJD contextService.setCurrentContextManager(previousCM);
7721: }
7722: }
7723:
7724: /**
7725: TC001 - Test the drop on commit mode for temp containers.
7726:
7727: @exception T_Fail Unexpected behaviour from the API
7728: @exception StandardException Unexpected exception from the implementation
7729:
7730: */
7731: protected void TC001() throws T_Fail, StandardException {
7732:
7733: Transaction t = t_util.t_startTransaction();
7734:
7735: // open a container with drop on commit and see if it disappears
7736: long cid = t_util.t_addContainer(t,
7737: ContainerHandle.TEMPORARY_SEGMENT);
7738: t_util.setOpenMode(openMode
7739: | ContainerHandle.MODE_DROP_ON_COMMIT);
7740: ContainerHandle c = t_util.t_openContainer(t,
7741: ContainerHandle.TEMPORARY_SEGMENT, cid, true);
7742: t_util.t_commit(t);
7743:
7744: ContainerKey id = new ContainerKey(
7745: ContainerHandle.TEMPORARY_SEGMENT, cid);
7746: c = t.openContainer(id, ContainerHandle.MODE_READONLY);
7747: if (c != null)
7748: throw T_Fail.testFailMsg("Temp Container should not exist");
7749:
7750: // open a container with drop on commit, close it, check it is still there and see if it disappears on a commit
7751: cid = t_util.t_addContainer(t,
7752: ContainerHandle.TEMPORARY_SEGMENT);
7753: c = t_util.t_openContainer(t,
7754: ContainerHandle.TEMPORARY_SEGMENT, cid, true);
7755: c.close();
7756: c = t_util.t_openContainer(t,
7757: ContainerHandle.TEMPORARY_SEGMENT, cid, true);
7758: c.close();
7759: t_util.t_commit(t);
7760:
7761: id = new ContainerKey(ContainerHandle.TEMPORARY_SEGMENT, cid);
7762: c = t.openContainer(id, ContainerHandle.MODE_READONLY);
7763: if (c != null)
7764: throw T_Fail.testFailMsg("Temp Container should not exist");
7765:
7766: // open a container with drop on commit, abort the transaction, and see if it disappears
7767: cid = t_util.t_addContainer(t,
7768: ContainerHandle.TEMPORARY_SEGMENT);
7769: t_util.setOpenMode(openMode
7770: | ContainerHandle.MODE_DROP_ON_COMMIT);
7771: c = t_util.t_openContainer(t,
7772: ContainerHandle.TEMPORARY_SEGMENT, cid, true);
7773: t_util.t_abort(t);
7774:
7775: id = new ContainerKey(ContainerHandle.TEMPORARY_SEGMENT, cid);
7776: c = t.openContainer(id, ContainerHandle.MODE_READONLY);
7777: if (c != null)
7778: throw T_Fail.testFailMsg("Temp Container should not exist");
7779:
7780: t_util.t_commit(t);
7781: t.close();
7782: PASS("TC001");
7783:
7784: }
7785:
7786: // code to populate a temp table for some temp tests
7787: private int[] populateTempTable(ContainerHandle c)
7788: throws StandardException, T_Fail {
7789: Page page = t_util.t_getPage(c,
7790: ContainerHandle.FIRST_PAGE_NUMBER);
7791: t_util.t_checkEmptyPage(page);
7792:
7793: RecordHandle rh;
7794: T_RawStoreRow row;
7795: int[] recordCount = { 0, 0, 0 };
7796:
7797: for (int i = 0; i < 3;) {
7798:
7799: for (;;) {
7800:
7801: row = new T_RawStoreRow(REC_001 + i + "X"
7802: + recordCount[i]);
7803: rh = t_util.t_insert(page, row);
7804:
7805: if (rh == null)
7806: break;
7807:
7808: recordCount[i]++;
7809: t_util.t_checkRecordCount(page, recordCount[i],
7810: recordCount[i]);
7811: }
7812:
7813: page.unlatch();
7814: page = null;
7815:
7816: if (++i < 3) {
7817: page = t_util.t_addPage(c);
7818: t_util.t_checkEmptyPage(page);
7819: }
7820: }
7821:
7822: return recordCount;
7823: }
7824:
7825: /**
7826: A clone of P002 for temporary containers.
7827: Insert rows on the first page until the page is full, then add a page
7828: and repeat the test (for a total of three pages with full rows).
7829: Fetch the rows back by handle methods.
7830: Commit or abort the transaction, and see if table is empty.
7831: Can be used as follows:
7832:
7833: <PRE>
7834: mode doCommit
7835:
7836: TRUNCATE_ON_COMMIT true Ensure the table has only one empty page after commit
7837: TRUNCATE_ON_COMMIT false Ensure the table has only one empty page after abort
7838: 0 false Ensure the table has only one empty page after abort
7839:
7840: </PRE>
7841:
7842: @exception T_Fail Unexpected behaviour from the API
7843: @exception StandardException Unexpected exception from the implementation
7844: */
7845: protected void TC002(int mode, boolean doCommit)
7846: throws StandardException, T_Fail {
7847:
7848: Transaction t = t_util.t_startTransaction();
7849:
7850: long cid = t_util.t_addContainer(t,
7851: ContainerHandle.TEMPORARY_SEGMENT);
7852:
7853: REPORT("TC002 container id = " + cid);
7854:
7855: t_util.setOpenMode(openMode | mode);
7856:
7857: ContainerHandle c = t_util.t_openContainer(t,
7858: ContainerHandle.TEMPORARY_SEGMENT, cid, true);
7859:
7860: int[] recordCount = populateTempTable(c);
7861:
7862: for (int i = 0; i < recordCount.length; i++) {
7863: REPORT("RecordCount on page " + i + "=" + recordCount[i]);
7864: }
7865:
7866: // now check that we read the same number of records back
7867: // using the handle interface
7868:
7869: long pageNumber = ContainerHandle.FIRST_PAGE_NUMBER;
7870: for (int i = 0; i < recordCount.length; i++, pageNumber++) {
7871: Page page = t_util.t_getPage(c, pageNumber);
7872: t_util.t_checkRecordCount(page, recordCount[i],
7873: recordCount[i]);
7874: RecordHandle rh = t_util.t_checkFetchFirst(page, REC_001
7875: + i + "X" + 0);
7876: for (int j = 1; j < recordCount[i]; j++)
7877: rh = t_util.t_checkFetchNext(page, rh, REC_001 + i
7878: + "X" + j);
7879:
7880: try {
7881: rh = page.fetchFromSlot(null, recordCount[i],
7882: new DataValueDescriptor[0],
7883: (FetchDescriptor) null, false);
7884:
7885: throw T_Fail
7886: .testFailMsg("reading more rows on page than were written");
7887: } catch (StandardException se) {
7888: // expected exception.
7889: }
7890:
7891: rh = t_util.t_checkFetchLast(page, REC_001 + i + "X"
7892: + (recordCount[i] - 1));
7893: for (int j = recordCount[i] - 2; j >= 0; j--)
7894: rh = t_util.t_checkFetchPrevious(page, rh, REC_001 + i
7895: + "X" + j);
7896:
7897: page.unlatch();
7898: page = null;
7899: }
7900:
7901: c.close();
7902:
7903: // this commit or abort will truncate the table
7904: if (doCommit)
7905: t_util.t_commit(t);
7906: else
7907: t_util.t_abort(t);
7908:
7909: t_util.setOpenMode(openMode);
7910:
7911: c = t_util.t_openContainer(t,
7912: ContainerHandle.TEMPORARY_SEGMENT, cid, true);
7913:
7914: Page page = t_util.t_getPage(c,
7915: ContainerHandle.FIRST_PAGE_NUMBER);
7916:
7917: t_util.t_checkEmptyPage(page);
7918: page.unlatch();
7919: page = null;
7920:
7921: page = c.getPage(ContainerHandle.FIRST_PAGE_NUMBER + 1);
7922:
7923: if (page != null)
7924: throw T_Fail
7925: .testFailMsg("truncate of temp container did not succeed");
7926:
7927: t_util.t_commit(t);
7928:
7929: t.close();
7930:
7931: PASS("TC002 " + mode + " " + doCommit);
7932: }
7933:
7934: /**
7935:
7936: Add a number of rows to a temp table opened in various modes,
7937: and drop it before commit/abort.
7938:
7939: @exception T_Fail Unexpected behaviour from the API
7940: @exception StandardException Unexpected exception from the implementation
7941: */
7942: protected void TC003(int mode, boolean doCommit)
7943: throws StandardException, T_Fail {
7944:
7945: Transaction t = t_util.t_startTransaction();
7946:
7947: long cid = t_util.t_addContainer(t,
7948: ContainerHandle.TEMPORARY_SEGMENT);
7949:
7950: REPORT("TC003 container id = " + cid);
7951:
7952: t_util.setOpenMode(openMode | mode);
7953:
7954: ContainerHandle c = t_util.t_openContainer(t,
7955: ContainerHandle.TEMPORARY_SEGMENT, cid, true);
7956: populateTempTable(c);
7957:
7958: // table is populated, drop it ...
7959: t_util.t_dropContainer(t, ContainerHandle.TEMPORARY_SEGMENT,
7960: cid);
7961: // table should have disappeared ...
7962: ContainerKey id = new ContainerKey(
7963: ContainerHandle.TEMPORARY_SEGMENT, cid);
7964: ContainerHandle ce = t.openContainer(id,
7965: ContainerHandle.MODE_READONLY);
7966: if (ce != null)
7967: throw T_Fail
7968: .testFailMsg("Dropped Container should not open");
7969:
7970: if (doCommit)
7971: t_util.t_commit(t);
7972: else
7973: t_util.t_abort(t);
7974:
7975: // table should have disappeared ...
7976: ContainerHandle cd = t.openContainer(id,
7977: ContainerHandle.MODE_READONLY);
7978: if (cd != null)
7979: throw T_Fail
7980: .testFailMsg("Dropped Container should not open");
7981:
7982: t_util.t_commit(t);
7983:
7984: t.close();
7985:
7986: PASS("TC003 " + mode + " " + doCommit);
7987: }
7988:
7989: /**
7990: Open a temp table several times with different modes and ensure the
7991: correct behaviour (most severe open wins).
7992:
7993: @exception T_Fail Unexpected behaviour from the API
7994: @exception StandardException Unexpected exception from the implementation
7995: */
7996: protected void TC004all() throws StandardException, T_Fail {
7997: int[] modes = { 0, ContainerHandle.MODE_DROP_ON_COMMIT,
7998: ContainerHandle.MODE_TRUNCATE_ON_COMMIT };
7999:
8000: for (int m1 = 0; m1 < modes.length; m1++) {
8001: for (int m2 = 0; m2 < modes.length; m2++) {
8002: for (int m3 = 0; m3 < modes.length; m3++) {
8003:
8004: TC004(m1, m2, m3, false, false);
8005: TC004(m1, m2, m3, false, true);
8006: TC004(m1, m2, m3, true, false);
8007: TC004(m1, m2, m3, true, false);
8008: }
8009: }
8010:
8011: }
8012: }
8013:
8014: /**
8015: Open a temp table several time swith different modes and ensure the
8016: correct behaviour (most severe open wins).
8017:
8018: @exception T_Fail Unexpected behaviour from the API
8019: @exception StandardException Unexpected exception from the implementation
8020: */
8021: protected void TC004(int mode1, int mode2, int mode3,
8022: boolean doCommit, boolean closeThem)
8023: throws StandardException, T_Fail {
8024:
8025: String testInfo = "TC004 mode1 " + mode1 + " mode2 " + mode2
8026: + " mode3 " + mode3 + " doCommit " + doCommit
8027: + " closeThem " + closeThem;
8028: REPORT("start " + testInfo);
8029:
8030: Transaction t = t_util.t_startTransaction();
8031:
8032: long cid = t_util.t_addContainer(t,
8033: ContainerHandle.TEMPORARY_SEGMENT);
8034:
8035: REPORT("TC004 container id = " + cid);
8036:
8037: t_util.setOpenMode(openMode | mode1);
8038: ContainerHandle c1 = t_util.t_openContainer(t,
8039: ContainerHandle.TEMPORARY_SEGMENT, cid, true);
8040: populateTempTable(c1);
8041: if (closeThem)
8042: c1.close();
8043:
8044: t_util.setOpenMode(openMode | mode2);
8045: ContainerHandle c2 = t_util.t_openContainer(t,
8046: ContainerHandle.TEMPORARY_SEGMENT, cid, true);
8047: if (closeThem)
8048: c2.close();
8049:
8050: t_util.setOpenMode(openMode | mode3);
8051: ContainerHandle c3 = t_util.t_openContainer(t,
8052: ContainerHandle.TEMPORARY_SEGMENT, cid, true);
8053: if (closeThem)
8054: c2.close();
8055:
8056: if (doCommit)
8057: t_util.t_commit(t);
8058: else
8059: t_util.t_abort(t);
8060:
8061: int fullMode = mode1 | mode2 | mode3;
8062:
8063: if ((fullMode & ContainerHandle.MODE_DROP_ON_COMMIT) == ContainerHandle.MODE_DROP_ON_COMMIT) {
8064: // table should have disappeared ...
8065: ContainerKey id = new ContainerKey(
8066: ContainerHandle.TEMPORARY_SEGMENT, cid);
8067: ContainerHandle cd = t.openContainer(id,
8068: ContainerHandle.MODE_READONLY);
8069: if (cd != null)
8070: throw T_Fail
8071: .testFailMsg("Dropped Container should not open");
8072:
8073: } else if (!doCommit
8074: || ((fullMode & ContainerHandle.MODE_TRUNCATE_ON_COMMIT) == ContainerHandle.MODE_TRUNCATE_ON_COMMIT)) {
8075: // table should be empty
8076: ContainerHandle ce = t_util.t_openContainer(t,
8077: ContainerHandle.TEMPORARY_SEGMENT, cid, true);
8078:
8079: Page page = t_util.t_getPage(ce,
8080: ContainerHandle.FIRST_PAGE_NUMBER);
8081:
8082: t_util.t_checkEmptyPage(page);
8083: page.unlatch();
8084: page = null;
8085: }
8086:
8087: t_util.t_commit(t);
8088:
8089: t.close();
8090:
8091: PASS(testInfo);
8092: }
8093:
8094: }
|