From derby-commits-return-376-apmail-db-derby-commits-archive=db.apache.org@db.apache.org Thu Mar 03 01:57:32 2005 Return-Path: Delivered-To: apmail-db-derby-commits-archive@www.apache.org Received: (qmail 29492 invoked from network); 3 Mar 2005 01:57:32 -0000 Received: from hermes.apache.org (HELO mail.apache.org) (209.237.227.199) by minotaur-2.apache.org with SMTP; 3 Mar 2005 01:57:31 -0000 Received: (qmail 99044 invoked by uid 500); 3 Mar 2005 01:57:31 -0000 Delivered-To: apmail-db-derby-commits-archive@db.apache.org Received: (qmail 99016 invoked by uid 500); 3 Mar 2005 01:57:31 -0000 Mailing-List: contact derby-commits-help@db.apache.org; run by ezmlm Precedence: bulk list-help: list-unsubscribe: List-Post: Reply-To: "Derby Development" Delivered-To: mailing list derby-commits@db.apache.org Received: (qmail 98998 invoked by uid 500); 3 Mar 2005 01:57:30 -0000 Delivered-To: apmail-incubator-derby-cvs@incubator.apache.org Received: (qmail 98982 invoked by uid 99); 3 Mar 2005 01:57:30 -0000 X-ASF-Spam-Status: No, hits=-9.8 required=10.0 tests=ALL_TRUSTED,NO_REAL_NAME X-Spam-Check-By: apache.org Received: from minotaur.apache.org (HELO minotaur.apache.org) (209.237.227.194) by apache.org (qpsmtpd/0.28) with SMTP; Wed, 02 Mar 2005 17:57:27 -0800 Received: (qmail 20457 invoked by uid 65534); 3 Mar 2005 01:30:46 -0000 Message-ID: <20050303013046.20455.qmail@minotaur.apache.org> Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-Mailer: svnmailer-1.0.0-dev Date: Thu, 03 Mar 2005 01:30:46 -0000 Subject: svn commit: r155990 [9/15] - in incubator/derby/code/trunk: ./ java/testing/ java/testing/org/apache/derbyTesting/functionTests/harness/ java/testing/org/apache/derbyTesting/functionTests/master/ java/testing/org/apache/derbyTesting/functionTests/suites/ java/testing/org/apache/derbyTesting/functionTests/tests/lang/ java/testing/org/apache/derbyTesting/functionTests/tests/store/ java/testing/org/apache/derbyTesting/functionTests/tests/unit/ java/testing/org/apache/derbyTesting/unitTests/ java/testing/org/apache/derbyTesting/unitTests/crypto/ java/testing/org/apache/derbyTesting/unitTests/harness/ java/testing/org/apache/derbyTesting/unitTests/lang/ java/testing/org/apache/derbyTesting/unitTests/services/ java/testing/org/apache/derbyTesting/unitTests/store/ java/testing/org/apache/derbyTesting/unitTests/util/ To: derby-cvs@incubator.apache.org From: fuzzylogic@apache.org X-Virus-Checked: Checked X-Spam-Rating: minotaur-2.apache.org 1.6.2 0/1000/N Added: incubator/derby/code/trunk/java/testing/org/apache/derbyTesting/unit= Tests/store/T_RawStoreFactory.java URL: http://svn.apache.org/viewcvs/incubator/derby/code/trunk/java/testing/= org/apache/derbyTesting/unitTests/store/T_RawStoreFactory.java?view=3Dauto&= rev=3D155990 =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D --- incubator/derby/code/trunk/java/testing/org/apache/derbyTesting/unitTes= ts/store/T_RawStoreFactory.java (added) +++ incubator/derby/code/trunk/java/testing/org/apache/derbyTesting/unitTes= ts/store/T_RawStoreFactory.java Wed Mar 2 17:30:05 2005 @@ -0,0 +1,7757 @@ +/* + + Derby - Class org.apache.derbyTesting.unitTests.store.T_RawStoreFactory + + Copyright 1997, 2005 The Apache Software Foundation or its licensors, a= s applicable. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + + */ + +package org.apache.derbyTesting.unitTests.store; + +import org.apache.derby.iapi.store.raw.*; + +// impl imports are the preferred way to create unit tests. +import org.apache.derbyTesting.unitTests.harness.T_MultiThreadedIterations; +import org.apache.derbyTesting.unitTests.harness.T_Fail; + +import org.apache.derby.iapi.services.context.ContextService; +import org.apache.derby.iapi.services.context.ContextManager; +import org.apache.derby.iapi.services.locks.*; +import org.apache.derby.iapi.services.monitor.Monitor; +import org.apache.derby.iapi.services.sanity.SanityManager; +import org.apache.derby.iapi.services.uuid.UUIDFactory; +import org.apache.derby.catalog.UUID; +import org.apache.derby.iapi.services.property.PropertyUtil; +import org.apache.derby.iapi.error.ExceptionSeverity; +import org.apache.derby.iapi.error.StandardException; + +import org.apache.derby.iapi.store.access.*; +import org.apache.derby.iapi.store.access.conglomerate.LogicalUndo; + +import org.apache.derby.iapi.store.raw.xact.RawTransaction; +import org.apache.derby.iapi.store.raw.data.RawContainerHandle; +import org.apache.derby.iapi.store.raw.log.LogInstant; + +import org.apache.derby.iapi.types.DataValueDescriptor; + +// impl a logInstant implemented as log counter to test truncateLWMs +import org.apache.derby.impl.store.raw.log.LogCounter; + +import org.apache.derby.iapi.types.SQLChar; + +import org.apache.derby.iapi.reference.Property; + +import org.apache.derby.iapi.services.io.FormatableBitSet; + +import java.io.*; +import java.util.Properties; + +/** + A protocol unit test for the RawStore interface. +*/ + +public class T_RawStoreFactory extends T_MultiThreadedIterations { + + + static protected final String REC_001 =3D "McLaren"; + static protected final String REC_002 =3D "Ferrari"; + static protected final String REC_003 =3D "Benetton"; + static protected final String REC_004 =3D "Prost"; + static protected final String REC_005 =3D "Tyrell"; + static protected final String REC_006 =3D "012345678901234567890123456789= 012345678901234567890123456789012345678901234567890123456789012345678901234= 567890123456789"; + static protected final String REC_007 =3D "abcdefghijklmnopqrstuvwxyzabcd= efghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyza= bcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwx= yzabcdefghijklmnopqrstuvwxyz"; + static protected final String REC_008 =3D "z"; + static protected final String REC_009 =3D "nanonano"; + static protected final String REC_010 =3D "fuzzbutt"; + static protected final String REC_011 =3D "mork"; + static protected final String REC_012 =3D "orson"; + static protected final String REC_013 =3D "mindy"; + static protected final String REC_014 =3D "thomas"; + static protected final String REC_015 =3D "henry"; + static protected final String REC_016 =3D "gordon"; + static protected final String REC_017 =3D "mavis"; + static protected final String REC_018 =3D "fatcontroller"; + static protected final String REC_UNDO =3D "Lotus"; + static protected final String REC_NULL =3D "NULL"; + + static final FormatableBitSet BS_COL_0 =3D new FormatableBitSet(1); + + static protected final String SP1 =3D "savepoint1"; + static protected final String SP2 =3D "savepoint2"; + + private static final String TEST_ROLLBACK_OFF =3D "derby.RawStore.Rollbac= kTestOff"; + + private static boolean testRollbackProperty;// initialize in start + static protected boolean testRollback; // each thread has its own test ro= llback value + + static protected RawStoreFactory factory; + static protected LockFactory lf; + static protected ContextService contextService; + + static protected UUIDFactory uuidfactory; + protected T_Util t_util; + protected int openMode; // mode flags used in all open containers. + protected boolean logDataForPurges =3D true; //used to test non-logged da= ta purges + + public T_RawStoreFactory() { + super(); + BS_COL_0.set(0); + } + + /** + @exception StandardException cannot startup the context service + */ + public void boot(boolean create, Properties startParams) + throws StandardException + { + super.boot(create, startParams); + contextService =3D ContextService.getFactory(); + } + + /* + ** Methods required by T_Generic + */ + + protected String getModuleToTestProtocolName() { + return RawStoreFactory.MODULE; + } + + /** + Set up test + + @exception T_Fail Unexpected behaviour from the API + */ + protected void setupTest() throws T_Fail { + =09 + String rollbackOff =3D PropertyUtil.getSystemProperty(TEST_ROLLBACK_OFF); + testRollback =3D !Boolean.valueOf(rollbackOff).booleanValue(); + + testRollbackProperty =3D testRollback; // testRollbackProperty never cha= nges + + // don't automatic boot this service if it gets left around + if (startParams =3D=3D null) { + startParams =3D new Properties(); + } + startParams.put(Property.NO_AUTO_BOOT, Boolean.TRUE.toString()); + // remove the service directory to ensure a clean run + startParams.put(Property.DELETE_ON_CREATE, Boolean.TRUE.toString()); + + // see if we are testing encryption + startParams =3D T_Util.setEncryptionParam(startParams); + + try { + + factory =3D (RawStoreFactory) Monitor.createPersistentService(getModule= ToTestProtocolName(), + getTestService(), startParams); + + if (factory =3D=3D null) { + throw T_Fail.testFailMsg(getModuleToTestProtocolName() + " service not= started."); + } + + lf =3D factory.getLockFactory(); + if (lf =3D=3D null) { + throw T_Fail.testFailMsg("LockFactory.MODULE not found"); + } + + uuidfactory =3D Monitor.getMonitor().getUUIDFactory(); + + } catch (StandardException mse) { + throw T_Fail.exceptionFail(mse); + } + + REPORT("testRollback=3D" + testRollback); + + return; + } + + protected String getTestService() + { + return "rawStoreTest"; + } + + + /** + * T_MultiThreadedIteration method + * + * @exception T_Fail Unexpected behaviour from the API + */ + protected void joinSetupTest() throws T_Fail { + + T_Fail.T_ASSERT(factory !=3D null, "raw store factory not setup "); + T_Fail.T_ASSERT(lf !=3D null, "Lock factory not setup "); + T_Fail.T_ASSERT(contextService !=3D null, "Context service not setup "); + + testRollback =3D testRollbackProperty; + + } + + protected T_MultiThreadedIterations newTestObject() { + try + { + Class thisClass =3D this.getClass(); + return (T_MultiThreadedIterations)(thisClass.newInstance()); + } + catch (InstantiationException ie) + { + return new T_RawStoreFactory(); + }=09 + catch (IllegalAccessException iae) + { + return new T_RawStoreFactory(); + } + }=09 + + + /** + run the test + + @exception T_Fail Unexpected behaviour from the API + */ + protected void runTestSet() throws T_Fail { + + // get a utility helper + t_util =3D new T_Util(factory, lf, contextService); + + ContextManager cm1 =3D contextService.newContextManager(); + contextService.setCurrentContextManager(cm1); + + try { + + + // Run the tests with data not logged for purges. + REPORT("Running tests with no data logged for purges"); + openMode =3D 0; // logged by default + runPurgeWithNoDataLoggesTests(); + + // Run the tests in normal logged mode + REPORT("Running tests with logging requested"); + openMode =3D 0; // logged by default + runEachTest(); + + =09 + // run the tests on temp tables + REPORT("Running tests for temp tables"); + testRollback =3D false; // obviously, we can't test rollback if we are = not logging + runTempTests(); + + // Run the tests in unlogged mode + REPORT("Running tests in unlogged mode"); + openMode =3D ContainerHandle.MODE_UNLOGGED | ContainerHandle.MODE_CREAT= E_UNLOGGED; + testRollback =3D false; // obviously, we can't test rollback if we are = not logging + runEachTest(); + + // if more runs are added here then you probably want to reset testRoll= back to + // its initial value, or add the runs before the unlogged mode. + + } catch (StandardException se) { + + cm1.cleanupOnError(se); + throw T_Fail.exceptionFail(se); + } + finally { + contextService.resetCurrentContextManager(cm1); + } + } + + protected void runEachTest() throws T_Fail, StandardException { + + t_util.setOpenMode(openMode); + + // Transaction tests + T000(); + T001(); + T002(); + T003(); + T004(); + T005(); + T006(); + T007(); + T008(); + T009(); + T010(); + T011(); + T012(); + + // ContainerHandle tests + C010(0); + C011(); + C012(1); + C014(); + C200(); + C201(0); + C201(1); + + // Page tests + P001(0); + P002(0); + P003(0); + P004(0); + P005(0); + P006(); + P007(0); + P008(0); + P009(0); + P011(0); + P012(0); + P013(); + P014(); + P015(); + P016(); + P017(); + P018(); + P019(); // test addPage with preallocation turned on + P020(); // test createContainer with initialPage set to 10 pages + P021(); // test preAllocate + P022(); + P023(0); // overflowThreshold test + + // long row tests + P030(0); + P031(0); + P032(0); + P033(0); + P034(0); + + P035(0); // long column test + + + + //run the following test because they do lot of checks=20 + //on rollbacking when contyainer is unlogged nothing is rolled back + if((openMode & ContainerHandle.MODE_UNLOGGED) =3D=3D ContainerHandle.MO= DE_UNLOGGED) + { + openMode =3D 0; //run them as logged for time being + t_util.setOpenMode(openMode); + } + + // reclaiming space from long column and long rows - temp container + // row space is not reclaimed. + P036(); + P037(); + P038(); + P039(); + P040(); + P041(); + P042(); + P043(); + + + P050(); // rollback tests + P051(); + P052(); + P053(); + P054(); + P055(0); + P056(0); + + + P061(); // sparse row test + + P071(); // serializable column test + + // update/update partial tests with long rows + P701(0); + P702(0); + P703(0); + P704(0); + P705(0); + + P706(0, false); + P706(0, true); + P707(0); + P708(0, false); + P708(0, true); + + + L001(); // large log record test + + // checkpoint test + CP001(); + } + + protected void runTempTests() throws T_Fail, StandardException { + + REPORT("Thread " + threadNumber + " entering temp tests "); + + openMode =3D 0; // logged by default + t_util.setOpenMode(openMode); // logged mode should be overriden for tem= p tables + + // now tests for temporary tables + + C010(ContainerHandle.TEMPORARY_SEGMENT); + C012(ContainerHandle.TEMPORARY_SEGMENT); + //P001(ContainerHandle.TEMPORARY_SEGMENT); + //P002(ContainerHandle.TEMPORARY_SEGMENT); + P003(ContainerHandle.TEMPORARY_SEGMENT); + P004(ContainerHandle.TEMPORARY_SEGMENT); + P005(ContainerHandle.TEMPORARY_SEGMENT); + P011(ContainerHandle.TEMPORARY_SEGMENT); + P012(ContainerHandle.TEMPORARY_SEGMENT); + P030(ContainerHandle.TEMPORARY_SEGMENT); + + // update/update partial tests with long rows + P055(ContainerHandle.TEMPORARY_SEGMENT); + P056(ContainerHandle.TEMPORARY_SEGMENT); + + P701(ContainerHandle.TEMPORARY_SEGMENT); + P702(ContainerHandle.TEMPORARY_SEGMENT); + P703(ContainerHandle.TEMPORARY_SEGMENT); + P704(ContainerHandle.TEMPORARY_SEGMENT); + P705(ContainerHandle.TEMPORARY_SEGMENT); + P706(ContainerHandle.TEMPORARY_SEGMENT, false); + P706(ContainerHandle.TEMPORARY_SEGMENT, true); + P707(ContainerHandle.TEMPORARY_SEGMENT); + + // tests specific to temp tables + + // checking truncate at commit/rollback works + TC001(); + TC002(ContainerHandle.MODE_TRUNCATE_ON_COMMIT, true); + TC002(ContainerHandle.MODE_TRUNCATE_ON_COMMIT, false); + TC002(0, false); + + // checking an explict drop works ... + TC003(ContainerHandle.MODE_TRUNCATE_ON_COMMIT, true); + TC003(ContainerHandle.MODE_TRUNCATE_ON_COMMIT, false); + TC003(0, false); + TC003(0, true); + TC003(ContainerHandle.MODE_DROP_ON_COMMIT, true); + TC003(ContainerHandle.MODE_DROP_ON_COMMIT, false); + + // various combinations of opens ... + TC004all(); + + REPORT("Thread " + threadNumber + " exiting temp tests "); + } + + + protected void runPurgeWithNoDataLoggesTests() throws T_Fail, StandardExc= eption { + + REPORT("Thread " + threadNumber + " entering purges with no data logged = tests "); + logDataForPurges =3D false; + P005(0); + P006(); + P014(); + P036(); + P037(); + P709(); + P710(); + P711(); + REPORT("Thread " + threadNumber + " exiting purge with no data logged te= sts "); + logDataForPurges =3D true; + } + /* + ** The tests + ** Tnnn indicates a test that is mainly testing the Transaction interface + ** Cnnn indicates a test that is mainly testing the ContainerHandle inte= rface + ** Pnnn indicates a test that is mainly testing the Page interface + ** + ** nnn < 200 tends to indicate purely API tests, ie checking methods + ** are callable and return the right value. This includes negative tests. + ** + ** nnn >=3D 200 tends to indicate more involved tests, ie ones that test= the + ** methods actually did something. + + */ + + /** + T000 - ensure a transaction starts out idle. + + @exception T_Fail Unexpected behaviour from the API + @exception StandardException Unexpected exception from the implementation + */ + protected void T000() throws T_Fail, StandardException { + + Transaction t1 =3D t_util.t_startTransaction(); + + t1.close(); + + + t1 =3D t_util.t_startInternalTransaction(); + + t1.close(); + + t1 =3D t_util.t_startTransaction(); + Transaction ti =3D t_util.t_startInternalTransaction(); + + ti.close(); + + t1.close(); + + PASS("T000"); + } + + /** + T001 - start and commit an empty transaction. + + @exception T_Fail Unexpected behaviour from the API + @exception StandardException Unexpected exception from the implementation + */ + protected void T001() throws T_Fail, StandardException { + + Transaction t1 =3D t_util.t_startTransaction(); + + t_util.t_commit(t1); + + t1.close(); + + PASS("T001"); + } + + /** + T002 - start and abort an empty transaction. + + @exception T_Fail Unexpected behaviour from the API + @exception StandardException Unexpected exception from the implementation + */ + protected void T002() throws T_Fail, StandardException { + + Transaction t1 =3D t_util.t_startTransaction(); + + t_util.t_abort(t1); + + t1.close(); + + PASS("T002"); + } + + /** + T003 - start and commit an empty transaction and then ensure + that the transaction remains open for another commit. + + @exception T_Fail Unexpected behaviour from the API + @exception StandardException Unexpected exception from the implementation + */ + protected void T003() throws T_Fail, StandardException { + + Transaction t1 =3D t_util.t_startTransaction(); + + t_util.t_commit(t1); + + t_util.t_commit(t1); + t_util.t_abort(t1); + + t1.close(); + + PASS("T003"); + } + + /** + T004 - start and abort an empty transaction and then ensure + that the transaction remains open for a commit and another abort. + + @exception T_Fail Unexpected behaviour from the API + @exception StandardException Unexpected exception from the implementation + */ + protected void T004() throws T_Fail, StandardException { + + Transaction t1 =3D t_util.t_startTransaction(); + + t_util.t_abort(t1); + + t_util.t_commit(t1); + + t_util.t_abort(t1); + + t1.close(); + + PASS("T004"); + } + + + /** + T005 check transaction identifiers on idle transactions. + + @exception T_Fail Unexpected behaviour from the API + @exception StandardException Unexpected exception from the implementation + + */ + protected void T005() throws T_Fail, StandardException { + + Transaction t1 =3D t_util.t_startTransaction(); + + // local transactions do not have global id's + GlobalTransactionId id1 =3D t1.getGlobalId(); + if (id1 !=3D null) + throw T_Fail.testFailMsg("null not returned from local Transaction.getI= d()"); + t1.close(); + + byte[] global_id =3D=20 + { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, + 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, + 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, + 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, + 40, 41, 42, 44, 44, 45, 46, 47, 48, 49, + 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, + 60, 61, 62, 63}; + byte[] branch_id =3D=20 + { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, + 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, + 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, + 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, + 40, 41, 42, 44, 44, 45, 46, 47, 48, 49, + 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, + 60, 61, 62, 63}; + + t1 =3D t_util.t_startGlobalTransaction(42, global_id, branch_id); + + id1 =3D t1.getGlobalId(); + + if (!id1.equals(id1)) + throw T_Fail.testFailMsg("TransactionId does not compare equal to itsel= f"); + + if (!id1.equals(t1.getGlobalId())) + throw T_Fail.testFailMsg("TransactionId has changed without any activit= y on Transaction"); + + if (id1.equals(this)) + throw T_Fail.testFailMsg("TransactionId compared equal to an non-transa= ction id object"); + + t1.close(); + t1 =3D null; + + // change the branch_id for the second global xact. + branch_id[63] =3D 82; + Transaction t2 =3D=20 + t_util.t_startGlobalTransaction(42, global_id, branch_id); + + GlobalTransactionId id2 =3D t2.getGlobalId(); + if (id2 =3D=3D null) + throw T_Fail.testFailMsg("null returned from Transaction.getId()"); + + if (id1.equals(id2)) + throw T_Fail.testFailMsg("TransactionId's returned equal from different= transactions"); + if (id2.equals(id1)) + throw T_Fail.testFailMsg("TransactionId's returned equal from different= transactions"); + + t2.close(); + + PASS("T005"); + } + + /** + T006 - savepoint basic API testing + + @exception T_Fail Unexpected behaviour from the API + @exception StandardException Unexpected exception from the implementation + */ + protected void T006() throws T_Fail, StandardException {=09 + + Transaction t1 =3D t_util.t_startTransaction(); + + // check a random savepoint name is not accepted + t_util.t_checkInvalidSavePoint(t1, "sdfjsdfg"); + + + t1.setSavePoint(SP1, null); + + t1.rollbackToSavePoint(SP1, null); // leaves savepoint around + t1.rollbackToSavePoint(SP1, null); // therefore this should work + + t1.releaseSavePoint(SP1, null); + + // SP1 should no longer exist + t_util.t_checkInvalidSavePoint(t1, SP1); + + // should be able to re-use it ... + t1.setSavePoint(SP1, null); + t1.rollbackToSavePoint(SP1, null); // leaves savepoint around + t1.rollbackToSavePoint(SP1, null); // therefore this should work + + t1.releaseSavePoint(SP1, null); + t_util.t_checkInvalidSavePoint(t1, SP1); + + t_util.t_commit(t1); + t1.close(); + + PASS("T006"); + } + + + /** + T007 - savepoint nesting testing + + @exception T_Fail Unexpected behaviour from the API + @exception StandardException Unexpected exception from the implementation + */ + protected void T007() throws T_Fail, StandardException {=09 + + Transaction t1 =3D t_util.t_startTransaction(); + int position =3D 0; + + /* + ** Push two save points and release the first, both should disappear + */ + t1.setSavePoint(SP1, null); + t1.setSavePoint(SP2, null); + + position =3D t1.releaseSavePoint(SP1, null); + if (position !=3D 0) + throw T_Fail.testFailMsg("Save Point Position in the stack isincorrect:= "+ + position); + + + // SP1 and SP2 should no longer exist + t_util.t_checkInvalidSavePoint(t1, SP1); + t_util.t_checkInvalidSavePoint(t1, SP2); + + /* + ** Push two save points and remove the second, first should remain + */ + t1.setSavePoint(SP1, null); + t1.setSavePoint(SP2, null); + + t1.rollbackToSavePoint(SP2, null); // leaves savepoint around + position =3D t1.rollbackToSavePoint(SP2, null); // therefore this should= work + =09 + if (position !=3D 2) + throw T_Fail.testFailMsg("Save Point Position in the stack isincorrect:= "+ + position); + + + + position =3D t1.releaseSavePoint(SP2, null); + if (position !=3D 1) + throw T_Fail.testFailMsg("Save Point Position in the stack is incorrect= :"+ + position); + + + t_util.t_checkInvalidSavePoint(t1, SP2); + + t1.rollbackToSavePoint(SP1, null); // this is the main test + + t1.releaseSavePoint(SP1, null); + t_util.t_checkInvalidSavePoint(t1, SP1); + + /* + ** Push two save points and rollback to the first, the second should dis= appear + */ + t1.setSavePoint(SP1, null); + t1.setSavePoint(SP2, null); + + position =3D t1.rollbackToSavePoint(SP1, null); // leaves SP1, removes S= P2 + if (position !=3D 1) + throw T_Fail.testFailMsg("Save Point Position in the stack is incorrect= :"+ + position); + + =09 + t_util.t_checkInvalidSavePoint(t1, SP2); + t1.rollbackToSavePoint(SP1, null); + + t1.releaseSavePoint(SP1, null); + + t_util.t_commit(t1); + t1.close(); + + PASS("T007"); + } + + /** + T008 - savepoint testing, ensure save points disappear at commit or abo= rt. + + @exception T_Fail Unexpected behaviour from the API + @exception StandardException Unexpected exception from the implementation + */ + protected void T008() throws T_Fail, StandardException {=09 + + Transaction t1 =3D t_util.t_startTransaction(); + int position1 =3D 0; + int position2 =3D 0; + + position1 =3D t1.setSavePoint(SP1, null); + position2 =3D t1.setSavePoint(SP2, null); + + if (position1 !=3D 1 && position2 !=3D 2) + throw T_Fail.testFailMsg("Save Point Position in the Stack seeme to wro= ng"); + + t1.commit(); + + t_util.t_checkInvalidSavePoint(t1, SP1); + t_util.t_checkInvalidSavePoint(t1, SP2); + + position1 =3D t1.setSavePoint(SP1, null); + position2 =3D t1.setSavePoint(SP2, null); + =09 + if (position1 !=3D 1 && position2 !=3D 2) + throw T_Fail.testFailMsg("Save Point Position in the Stack seeme to wro= ng"); + + t1.abort(); + position1 =3D t1.setSavePoint(SP1, null); + position2 =3D t1.setSavePoint(SP2, null); + if (position1 !=3D 1 && position2 !=3D 2) + throw T_Fail.testFailMsg("Save Point Position in the Stack seeme to wro= ng"); + t1.abort(); + t_util.t_checkInvalidSavePoint(t1, SP1); + t_util.t_checkInvalidSavePoint(t1, SP2); + + t1.close(); + + PASS("T008"); + } + + + /** + T009 - add a container and remove it within the same transaction. + @exception T_Fail Unexpected behaviour from the API + @exception StandardException Unexpected exception from the implementation + + */ + + protected void T009() throws StandardException, T_Fail { + Transaction t =3D t_util.t_startTransaction(); + + long cid =3D t_util.t_addContainer(t, 0, 4096); + t_util.t_dropContainer(t, 0, cid); + + ContainerKey id =3D new ContainerKey(0, cid); + ContainerHandle ch =3D t.openContainer(id, ContainerHandle.MODE_READONLY= ); + if (ch !=3D null) + throw T_Fail.testFailMsg("Dropped Container should not open"); + + t_util.t_commit(t); + + t.close(); + + PASS("T009"); + } + + /** + T010 - add a container with a default size and remove it within the same= transaction. + @exception T_Fail Unexpected behaviour from the API + @exception StandardException Unexpected exception from the implementation + + */ + + protected void T010() throws StandardException, T_Fail { + Transaction t1 =3D t_util.t_startTransaction(); + + long cid =3D t_util.t_addContainer(t1, 0); + + t_util.t_dropContainer(t1, 0, cid); + + ContainerKey id =3D new ContainerKey(0, cid); + ContainerHandle ch =3D t1.openContainer(id, ContainerHandle.MODE_READONL= Y); + if (ch !=3D null) + throw T_Fail.testFailMsg("Dropped Container should not open"); + + t_util.t_commit(t1); + + t1.close(); + + PASS("T010"); + } + + /** + T011 - see that a container remains open over the commit of an open tran= saction.. + @exception T_Fail Unexpected behaviour from the API + @exception StandardException Unexpected exception from the implementation + + */ + + protected void T011() throws StandardException, T_Fail { + + Transaction t =3D t_util.t_startInternalTransaction(); + + + long cid =3D t_util.t_addContainer(t, 0); + + ContainerHandle c; + + c =3D t_util.t_openContainer(t, 0, cid, true); + + t.commit(); + + // container should still be open + Page page =3D t_util.t_getPage(c, ContainerHandle.FIRST_PAGE_NUMBER); + + t.commit(); + + // page should still be latched + if (!page.isLatched()) + throw T_Fail.testFailMsg("page not latched after commit of internal tra= nsaction"); + + page.unlatch(); + c.close(); + + t.commit(); + + c =3D t_util.t_openContainer(t, 0, cid, true); + page =3D t_util.t_getPage(c, ContainerHandle.FIRST_PAGE_NUMBER); + + // container and page should be closed + t.abort(); + if (page.isLatched()) + throw T_Fail.testFailMsg("page latched after abort of internal transact= ion"); + + try { + page =3D t_util.t_getLastPage(c); + throw T_Fail.testFailMsg("container open after abort of internal transa= ction"); + + } catch (StandardException te) { + } + + t_util.t_dropContainer(t, 0, cid); // cleanup + + t_util.t_commit(t); + + t.close(); + + PASS("T011");=09 + } + + /** + Test Xact.makeRecordHandle() + + @exception T_Fail Unexpected behaviour from the API + @exception StandardException Unexpected exception from the implementation + */ + protected void T012() throws StandardException, T_Fail { + + Transaction t =3D t_util.t_startTransaction(); =09 + + long cid =3D t_util.t_addContainer(t, 0); + + ContainerHandle c =3D t_util.t_openContainer(t, 0, cid, true); + Page page =3D t_util.t_getPage(c, ContainerHandle.FIRST_PAGE_NUMBER); + + RecordHandle r1, r2; + RecordHandle new_r1, new_r2; + + T_RawStoreRow row1 =3D new T_RawStoreRow(REC_001); + T_RawStoreRow row2 =3D new T_RawStoreRow(REC_002); + + r1 =3D t_util.t_insertAtSlot(page, 0, row1); + new_r1 =3D c.makeRecordHandle(r1.getPageNumber(), r1.getId()); + + t_util.t_checkFetch(page, new_r1, REC_001); + + r2 =3D t_util.t_insertAtSlot(page, 1, row2); + + if (r2 !=3D null) + { + new_r2 =3D=20 + c.makeRecordHandle(r2.getPageNumber(), r2.getId()); + t_util.t_checkFetch(page, r2, REC_002); + } + + t_util.t_commit(t); + t.close(); + + PASS("T012"); + + } + + /** + C010 - Create a container within a transaction, commit and the re-open + the container twice. + + @exception T_Fail Unexpected behaviour from the API + @exception StandardException Unexpected exception from the implementation + + */ + protected void C010(int segment) throws T_Fail, StandardException { + + Transaction t =3D t_util.t_startTransaction(); + + long cid =3D t_util.t_addContainer(t, segment); + + t_util.t_commit(t); +=09 + ContainerHandle c1, c2; + + c1 =3D t_util.t_openContainer(t, segment, cid, true); + c1 =3D t_util.t_openContainer(t, segment, cid, true); + t_util.t_dropContainer(t, segment, cid); // cleanup + + + t_util.t_commit(t); + t.close(); + + PASS("C010"); + + } + + /** + C011 - Create a container withina transaction, commit and the re-open + the container in update and non-update mode. + =09 + @exception T_Fail Unexpected behaviour from the API + @exception StandardException Unexpected exception from the implementation + + */ + protected void C011() throws T_Fail, StandardException { + + Transaction t =3D t_util.t_startTransaction(); + + long cid =3D t_util.t_addContainer(t, 0); + + t_util.t_commit(t); +=09 + ContainerHandle c1, c2; + + c1 =3D t_util.t_openContainer(t, 0, cid, false); + c1 =3D t_util.t_openContainer(t, 0, cid, true); + + t_util.t_dropContainer(t, 0, cid); // cleanup + + t_util.t_commit(t); + t.close(); + PASS("C011"); + + } + + /** + C012 - Drop a container within a transaction, commit, see that it is del= eted. + Drop a container within a transaction, rollback and re-open and see + that it is not deleted.=20 + + @exception T_Fail Unexpected behaviour from the API + @exception StandardException Standard Derby error policy + */ + protected void C012(long segment) throws T_Fail, StandardException { + + Transaction t =3D t_util.t_startTransaction(); + + long cid =3D t_util.t_addContainer(t, segment); + t_util.t_commit(t); + + ContainerHandle c1 =3D t_util.t_openContainer(t, segment, cid, true); + + t_util.t_dropContainer(t, segment, cid); + + if (testRollback) + { + t_util.t_abort(t); // this should rollback the drop + c1 =3D t_util.t_openContainer(t, segment, cid, true); + + REPORT("rollback of drop container tested"); + + t_util.t_dropContainer(t, segment, cid); + } + + t_util.t_commit(t); + + ContainerKey id =3D new ContainerKey(segment, cid); + c1 =3D t.openContainer(id, (ContainerHandle.MODE_FORUPDATE | openMode));= // this should fail + if (c1 !=3D null) + throw T_Fail.testFailMsg("Deleted Container should fail to open"); + + t_util.t_commit(t); + t.close(); + PASS("C012"); + } + + /** + C014 - Open a container for locking only. + @exception T_Fail Unexpected behaviour from the API + @exception StandardException Standard Derby error policy + */ + protected void C014() throws T_Fail, StandardException { + + Transaction t =3D t_util.t_startTransaction(); + + ContainerKey id =3D new ContainerKey(77, 45); + ContainerHandle c =3D t.openContainer(id, + ContainerHandle.MODE_OPEN_FOR_LOCK_ONLY); + + if (c =3D=3D null) + throw T_Fail.testFailMsg("open of a container for lock only failed."); + + RecordHandle rh1 =3D c.makeRecordHandle(23, 456); + if (rh1 =3D=3D null) + throw T_Fail.testFailMsg("makeRecordHandle returned null"); + c.getLockingPolicy().lockRecordForRead(t, c, rh1, true, true); + + + RecordHandle rh2 =3D c.makeRecordHandle(23, 7); + if (rh2 =3D=3D null) + throw T_Fail.testFailMsg("makeRecordHandle returned null"); + c.getLockingPolicy().lockRecordForRead(t, c, rh2, true, false); + + RecordHandle rh3 =3D c.makeRecordHandle(23, 9); + c.getLockingPolicy().lockRecordForWrite(t, rh3, false, true); + if (rh3 =3D=3D null) + throw T_Fail.testFailMsg("makeRecordHandle returned null"); + + c.getLockingPolicy().unlockRecordAfterRead(t, c, rh2, false, true); + + c.close(); + + t.commit(); + + t.close(); + + PASS("C014"); + } + + /** + @exception T_Fail Unexpected behaviour from the API + @exception StandardException Unexpected exception from the implementation + */ + protected void C200() throws T_Fail, StandardException { + + Transaction t1 =3D t_util.t_startTransaction(); + + long cid =3D t_util.t_addContainer(t1, 0); + + t_util.t_commit(t1); + + ContainerHandle c1; + Page lastPage; + RecordHandle rh001, rh002, rh003; + T_RawStoreRow row; +=09 + REPORT("see if the container can be opened again"); + c1 =3D t_util.t_openContainer(t1, 0, cid, false); + + c1.close(); + t_util.t_commit(t1); + + REPORT("insert a record into the container."); + + c1 =3D t_util.t_openContainer(t1, 0, cid, true); + + lastPage =3D t_util.t_getLastPage(c1); + if (lastPage =3D=3D null) + throw T_Fail.testFailMsg("Could get container's last page"); + + if (lastPage.getPageNumber() !=3D ContainerHandle.FIRST_PAGE_NUMBER) + throw T_Fail.testFailMsg("Initial page must be " + ContainerHandle.FIRS= T_PAGE_NUMBER + ", is " + lastPage.getPageNumber()); + + row =3D new T_RawStoreRow(REC_001); + if (!lastPage.spaceForInsert()) + throw T_Fail.testFailMsg("No room for record on page"); + + rh001 =3D t_util.t_insert(lastPage, row); + if (rh001 =3D=3D null) + throw T_Fail.testFailMsg("Failed to insert record"); + + // see if we can fetch that record + t_util.t_checkFetch(lastPage, rh001, REC_001); + + lastPage.unlatch(); + lastPage =3D null; + + t_util.t_commit(t1); + c1 =3D null; + + + REPORT("read record just inserted."); + + c1 =3D t_util.t_openContainer(t1, 0, cid, false); + + lastPage =3D t_util.t_getLastPage(c1); + if (lastPage =3D=3D null) + throw T_Fail.testFailMsg("Could get container's last page"); + + t_util.t_checkFetch(lastPage, rh001, REC_001); + t_util.t_checkFetchFirst(lastPage, REC_001); + t_util.t_checkFetchLast(lastPage, REC_001); + + t_util.t_commit(t1); + lastPage =3D null; + c1 =3D null; + + + REPORT("insert 2 more records."); + + c1 =3D t_util.t_openContainer(t1, 0, cid, true); + + lastPage =3D t_util.t_getLastPage(c1); + if (lastPage =3D=3D null) + throw T_Fail.testFailMsg("Could get container's last page"); + + if (lastPage.getPageNumber() !=3D ContainerHandle.FIRST_PAGE_NUMBER) + throw T_Fail.testFailMsg("Initial page must be " + ContainerHandle.FIRS= T_PAGE_NUMBER + ", is " + lastPage.getPageNumber()); + + row =3D new T_RawStoreRow(REC_002); + if (!lastPage.spaceForInsert()) + throw T_Fail.testFailMsg("No room for record on page"); + + if (!lastPage.recordExists(rh001, false)) + throw T_Fail.testFailMsg("Record 001 has vanished"); + + // + + // RESOLVE: just insert them for now, order is 002,001,003 + // 001 is already on the page + + rh002 =3D t_util.t_insertAtSlot(lastPage, 0, row); + row =3D new T_RawStoreRow(REC_003); + rh003 =3D t_util.t_insert(lastPage, row); + // Order is 002, 001, 003 +=09 + + lastPage.unlatch(); + lastPage =3D null; + + t_util.t_commit(t1); + c1 =3D null; +=09 + REPORT("checks on all 3 records."); + + c1 =3D t_util.t_openContainer(t1, 0, cid, false); + + lastPage =3D t_util.t_getLastPage(c1); + if (lastPage =3D=3D null) + throw T_Fail.testFailMsg("Could get container's last page"); + + // Order is 002, 001, 003 + t_util.t_checkFetch(lastPage, rh001, REC_001); + t_util.t_checkFetch(lastPage, rh002, REC_002); + t_util.t_checkFetch(lastPage, rh003, REC_003); + + + t_util.t_checkFetch(lastPage, lastPage.getRecordHandle(rh001.getId()), R= EC_001); + t_util.t_checkFetch(lastPage, lastPage.getRecordHandle(rh002.getId()), R= EC_002); + + lastPage.unlatch(); + lastPage =3D null; + + t_util.t_commit(t1); + + REPORT("start deleting."); + + c1 =3D t_util.t_openContainer(t1, 0, cid, true); + + lastPage =3D t_util.t_getLastPage(c1); + if (lastPage =3D=3D null) + throw T_Fail.testFailMsg("Could get container's last page"); + + // Order is 002, 001, 003 + t_util.t_checkFetch(lastPage, rh001, REC_001); + t_util.t_checkFetch(lastPage, rh002, REC_002); + t_util.t_checkFetch(lastPage, rh003, REC_003); + + lastPage.delete(rh001, (LogicalUndo)null); + if (lastPage.fetch( + rh001, new DataValueDescriptor[0], (FormatableBitSet) null, = false) !=3D null) + { + throw T_Fail.testFailMsg("deleted record is still present"); + } + // Order is 002, 003 + t_util.t_checkFetch(lastPage, rh002, REC_002); + t_util.t_checkFetch(lastPage, rh003, REC_003); + + t_util.t_checkFetchNext(lastPage, rh002, REC_003); + t_util.t_checkFetchPrevious(lastPage, rh003, REC_002); + + lastPage.delete(rh002, (LogicalUndo)null); + if (lastPage.fetch( + rh002, new DataValueDescriptor[0], (FormatableBitSet) null, = false) !=3D null) + { + throw T_Fail.testFailMsg("deleted record is still present"); + } + + t_util.t_checkFetch(lastPage, rh003, REC_003); + t_util.t_checkFetchFirst(lastPage, REC_003); + t_util.t_checkFetchLast(lastPage, REC_003); + + lastPage.unlatch(); + lastPage =3D null; + + t_util.t_commit(t1); + + REPORT("update the remaining record."); + + c1 =3D t_util.t_openContainer(t1, 0, cid, true); + + lastPage =3D t_util.t_getLastPage(c1); + if (lastPage =3D=3D null) + throw T_Fail.testFailMsg("Could get container's last page"); + + // Order is 003 + t_util.t_checkFetch(lastPage, rh003, REC_003); + + T_RawStoreRow urow =3D new T_RawStoreRow(REC_004); + + if (lastPage.fetch( + rh003, new DataValueDescriptor[0], (FormatableBitSet) null, = true) =3D=3D null) + { + throw T_Fail.testFailMsg("fetch for update returned false"); + } +=09 + if (!lastPage.update(rh003, urow.getRow(), (FormatableBitSet) null)) + throw T_Fail.testFailMsg("update returned false"); + + // Order is 003 + t_util.t_checkFetch(lastPage, rh003, REC_004); + + lastPage.unlatch(); + lastPage =3D null; + + t_util.t_commit(t1); + + t_util.t_dropContainer(t1, 0, cid); // cleanup + + t_util.t_commit(t1); + t1.close(); + =20 + PASS("C200"); + + } + + /** + C201 - Create container with different page size, minimum record size, + inserting into these containers to check if the variables are set correc= tly. + + @exception T_Fail Unexpected behaviour from the API + @exception StandardException Unexpected exception from the implementation + */ + protected void C201(int whatPage) throws T_Fail, StandardException { + + int pageSize =3D (whatPage =3D=3D 0 ? 4096 : 32768); + + Transaction t1 =3D t_util.t_startTransaction(); + + REPORT("create container with pageSize " + pageSize + ", spareSpace " + = 0 + ", minimumRecordSize " + pageSize/2); + long cid =3D t_util.t_addContainer(t1, 0, pageSize, 0, pageSize/2, false= ); + =09 + t_util.t_commit(t1); + + ContainerHandle c1; + Page lastPage; + RecordHandle rh001, rh002, rh003; + T_RawStoreRow row; +=09 + REPORT("see if the container can be opened again"); + c1 =3D t_util.t_openContainer(t1, 0, cid, false); + + c1.close(); + t_util.t_commit(t1); + + REPORT("insert a record into the container."); + + c1 =3D t_util.t_openContainer(t1, 0, cid, true); + + lastPage =3D t_util.t_getLastPage(c1); + if (lastPage =3D=3D null) + throw T_Fail.testFailMsg("Couldn't get container's last page"); + + if (lastPage.getPageNumber() !=3D ContainerHandle.FIRST_PAGE_NUMBER) + throw T_Fail.testFailMsg("Initial page must be " + ContainerHandle.FIRS= T_PAGE_NUMBER + ", is " + lastPage.getPageNumber()); + + row =3D new T_RawStoreRow(REC_001); + if (!lastPage.spaceForInsert()) + throw T_Fail.testFailMsg("No room for record on page"); + + rh001 =3D t_util.t_insert(lastPage, row); + if (rh001 =3D=3D null) + throw T_Fail.testFailMsg("Failed to insert record"); + + // see if we can fetch that record + t_util.t_checkFetch(lastPage, rh001, REC_001); + + lastPage.unlatch(); + lastPage =3D null; + + t_util.t_commit(t1); + c1 =3D null; + + REPORT("read record just inserted."); + + c1 =3D t_util.t_openContainer(t1, 0, cid, false); + + lastPage =3D t_util.t_getLastPage(c1); + if (lastPage =3D=3D null) + throw T_Fail.testFailMsg("Couldn't get container's last page"); + + t_util.t_checkFetch(lastPage, rh001, REC_001); + t_util.t_checkFetchFirst(lastPage, REC_001); + t_util.t_checkFetchLast(lastPage, REC_001); + + t_util.t_commit(t1); + lastPage =3D null; + c1 =3D null; + + // negative testing + REPORT("try inserting 1 more record, but there should be no room on page= for it."); + + c1 =3D t_util.t_openContainer(t1, 0, cid, true); + + lastPage =3D t_util.t_getLastPage(c1); + if (lastPage =3D=3D null) + throw T_Fail.testFailMsg("Couldn't get container's last page"); + + if (lastPage.getPageNumber() !=3D ContainerHandle.FIRST_PAGE_NUMBER) + throw T_Fail.testFailMsg("Initial page must be " + ContainerHandle.FIRS= T_PAGE_NUMBER + ", is " + lastPage.getPageNumber()); + + row =3D new T_RawStoreRow(REC_002); + if (lastPage.spaceForInsert()) + { + throw T_Fail.testFailMsg("Did not get no room for record on page error"= ); + } + + if (!lastPage.recordExists(rh001, false)) + throw T_Fail.testFailMsg("Record 001 has vanished"); + + lastPage.unlatch(); + lastPage =3D null; + + t_util.t_commit(t1); + c1 =3D null; + + t_util.t_dropContainer(t1, 0, cid); // cleanup + t_util.t_commit(t1); + //t1.close(); + + + //t1 =3D t_util.t_startTransaction(); + + REPORT("create container with pageSize " + pageSize + ", spareSpace " + = 0 + ", minimumRecordSize " + pageSize); + REPORT("this should set minimumRecordSize to the default 100"); + cid =3D t_util.t_addContainer(t1, 0, pageSize, 0, pageSize, false); + =09 + t_util.t_commit(t1); + + REPORT("see if the container can be opened again"); + c1 =3D t_util.t_openContainer(t1, 0, cid, false); + + c1.close(); + t_util.t_commit(t1); + + REPORT("insert a record into the container."); + + c1 =3D t_util.t_openContainer(t1, 0, cid, true); + + lastPage =3D t_util.t_getLastPage(c1); + if (lastPage =3D=3D null) + throw T_Fail.testFailMsg("Couldn't get container's last page"); + + if (lastPage.getPageNumber() !=3D ContainerHandle.FIRST_PAGE_NUMBER) + throw T_Fail.testFailMsg("Initial page must be " + ContainerHandle.FIRS= T_PAGE_NUMBER + ", is " + lastPage.getPageNumber()); + + row =3D new T_RawStoreRow(REC_001); + if (!lastPage.spaceForInsert()) + throw T_Fail.testFailMsg("No room for record on page"); + + rh001 =3D t_util.t_insert(lastPage, row); + if (rh001 =3D=3D null) + throw T_Fail.testFailMsg("Failed to insert record"); + + // see if we can fetch that record + t_util.t_checkFetch(lastPage, rh001, REC_001); + + lastPage.unlatch(); + lastPage =3D null; + + t_util.t_commit(t1); + c1 =3D null; + + REPORT("read record just inserted."); + + c1 =3D t_util.t_openContainer(t1, 0, cid, false); + + lastPage =3D t_util.t_getLastPage(c1); + if (lastPage =3D=3D null) + throw T_Fail.testFailMsg("Couldn't get container's last page"); + + t_util.t_checkFetch(lastPage, rh001, REC_001); + t_util.t_checkFetchFirst(lastPage, REC_001); + t_util.t_checkFetchLast(lastPage, REC_001); + + t_util.t_commit(t1); + lastPage =3D null; + c1 =3D null; + + REPORT("insert 2 more records."); + + c1 =3D t_util.t_openContainer(t1, 0, cid, true); + + lastPage =3D t_util.t_getLastPage(c1); + if (lastPage =3D=3D null) + throw T_Fail.testFailMsg("Could get container's last page"); + + if (lastPage.getPageNumber() !=3D ContainerHandle.FIRST_PAGE_NUMBER) + throw T_Fail.testFailMsg("Initial page must be " + ContainerHandle.FIRS= T_PAGE_NUMBER + ", is " + lastPage.getPageNumber()); + + row =3D new T_RawStoreRow(REC_002); + if (!lastPage.spaceForInsert()) + throw T_Fail.testFailMsg("No room for record on page"); + + if (!lastPage.recordExists(rh001, false)) + throw T_Fail.testFailMsg("Record 001 has vanished"); + + rh002 =3D t_util.t_insertAtSlot(lastPage, 0, row); + row =3D new T_RawStoreRow(REC_003); + rh003 =3D t_util.t_insert(lastPage, row); + + lastPage.unlatch(); + lastPage =3D null; + + t_util.t_commit(t1); + c1 =3D null; +=09 + REPORT("checks on all 3 records."); + + c1 =3D t_util.t_openContainer(t1, 0, cid, false); + + lastPage =3D t_util.t_getLastPage(c1); + if (lastPage =3D=3D null) + throw T_Fail.testFailMsg("Could get container's last page"); + + // Order is 002, 001, 003 + t_util.t_checkFetch(lastPage, rh001, REC_001); + t_util.t_checkFetch(lastPage, rh002, REC_002); + t_util.t_checkFetch(lastPage, rh003, REC_003); + + + t_util.t_checkFetch(lastPage, lastPage.getRecordHandle(rh001.getId()), R= EC_001); + t_util.t_checkFetch(lastPage, lastPage.getRecordHandle(rh002.getId()), R= EC_002); + + lastPage.unlatch(); + lastPage =3D null; + + t_util.t_commit(t1); + + c1 =3D null; + + // clean ip + t_util.t_dropContainer(t1, 0, cid); + t_util.t_commit(t1); + t1.close(); + + PASS("C201 - " + whatPage); + + } + + /** + Page tests + */ + /** + Create a container, ensure it has one page with no records. Then test + all the things we can do with an empty page opened read-only in the cont= ainer. + Then add a new page, ensure it has the correct page number and is empty. + @exception T_Fail Unexpected behaviour from the API + @exception StandardException Unexpected exception from the implementation + */ + protected void P001(long segment) throws T_Fail, StandardException { + + Transaction t =3D t_util.t_startTransaction(); + + long cid =3D t_util.t_addContainer(t, segment); + + t_util.t_commit(t); + + // Get the first page & check the record counts are zero + ContainerHandle c =3D t_util.t_openContainer(t, segment, cid, false); + Page page =3D t_util.t_getPage(c, ContainerHandle.FIRST_PAGE_NUMBER); + + t_util.t_checkEmptyPage(page); + + if (Page.FIRST_SLOT_NUMBER !=3D 0) + throw T_Fail.testFailMsg("Page.FIRST_SLOT_NUMBER must be 0, is " + Page= .FIRST_SLOT_NUMBER); + + page.unlatch(); + page =3D null; + + // get the last page and check it is the first page + page =3D t_util.t_getLastPage(c); + + t_util.t_checkPageNumber(page, ContainerHandle.FIRST_PAGE_NUMBER); +=09 + t_util.t_checkEmptyPage(page); + + t_util.t_commit(t); + + // t_util.t_addPage checks that the page is empty. + c =3D t_util.t_openContainer(t, segment, cid, true); + page =3D t_util.t_addPage(c); + + t_util.t_checkPageNumber(page, ContainerHandle.FIRST_PAGE_NUMBER + 1); + page.unlatch(); + + page =3D t_util.t_addPage(c); + t_util.t_checkPageNumber(page, ContainerHandle.FIRST_PAGE_NUMBER + 2); + page.unlatch(); + + t_util.t_commit(t); + + c =3D t_util.t_openContainer(t, segment, cid, true); + page =3D t_util.t_getPage(c, ContainerHandle.FIRST_PAGE_NUMBER); + t_util.t_updateSlotOutOfRange(page, 0); + t_util.t_updateSlotOutOfRange(page, -1); + t_util.t_updateSlotOutOfRange(page, 1); + + + t_util.t_dropContainer(t, segment, cid); // cleanup + t_util.t_commit(t); + + // RESOLVE drop container + + t.close(); + + PASS("P001"); + } + + /** + Insert rows on the first page until the page is full, then add a page + and repeat the test (for a total of three pages with full rows). + Fetch the rows back by handle and slot methods. + + @exception T_Fail Unexpected behaviour from the API + @exception StandardException Unexpected exception from the implementation + */ + protected void P002(long segment) throws StandardException, T_Fail { + + Transaction t =3D t_util.t_startTransaction(); =09 + + long cid =3D t_util.t_addContainer(t, segment); + + ContainerHandle c =3D t_util.t_openContainer(t, segment, cid, true); + Page page =3D t_util.t_getPage(c, ContainerHandle.FIRST_PAGE_NUMBER); + t_util.t_checkEmptyPage(page); + + RecordHandle rh; + T_RawStoreRow row; + int recordCount[] =3D {0,0,0}; + + for (int i =3D 0; i < 3;) { + row =3D new T_RawStoreRow(REC_001 + i + "X" + recordCount[i]); + + boolean spaceThere =3D page.spaceForInsert(); + + rh =3D t_util.t_insert(page, row); + + if (rh !=3D null) { + recordCount[i]++; + if (!spaceThere) + REPORT("record inserted after spaceForInsert() returned false, count = is " + recordCount[i]); + } else { + if (spaceThere) + REPORT("record insert failed after spaceForInsert() returned true, co= unt is " + recordCount[i]); + } + + t_util.t_checkRecordCount(page, recordCount[i], recordCount[i]); + + if (rh !=3D null) + continue; + + page.unlatch(); + page =3D null; + + if (++i < 3) { + page =3D t_util.t_addPage(c); + t_util.t_checkEmptyPage(page); + } + } + t_util.t_commit(t); + + for (int i =3D 0; i < 3; i++) { + REPORT("RecordCount on page " + i + "=3D" + recordCount[i]); + } + + // now check that we read the same number of records back + // using the handle interface + c =3D t_util.t_openContainer(t, segment, cid, false); + + long pageNumber =3D ContainerHandle.FIRST_PAGE_NUMBER; + for (int i =3D 0; i < 3; i++, pageNumber++) { + page =3D t_util.t_getPage(c, pageNumber); + t_util.t_checkRecordCount(page, recordCount[i], recordCount[i]); + rh =3D t_util.t_checkFetchFirst(page, REC_001 + i + "X" + 0); + for (int j =3D 1; j < recordCount[i]; j++) + rh =3D t_util.t_checkFetchNext(page, rh, REC_001 + i + "X" + j); + + try + { + rh =3D page.fetchFromSlot( + null,=20 + page.getSlotNumber(rh) + 1,=20 + new DataValueDescriptor[0],=20 + (FetchDescriptor) null,=20 + false); + + throw T_Fail.testFailMsg( + "reading more rows on page than were written"); + } + catch (StandardException se) + { + // expected error. + } + + rh =3D t_util.t_checkFetchLast(page, REC_001 + i + "X" + (recordCount[i= ] - 1)); + for (int j =3D recordCount[i] - 2; j >=3D 0; j--) + rh =3D t_util.t_checkFetchPrevious(page, rh, REC_001 + i + "X" + j); + + page.unlatch(); + page =3D null; + } + t_util.t_commit(t); + + // now check that we read the same number of records back + // using the slot interface + c =3D t_util.t_openContainer(t, segment, cid, false); + + pageNumber =3D ContainerHandle.FIRST_PAGE_NUMBER; + for (int i =3D 0; i < 3; i++, pageNumber++) { + page =3D t_util.t_getPage(c, pageNumber); + =09 + for (int j =3D 0; j < recordCount[i]; j++) + t_util.t_checkFetchBySlot(page, j, REC_001 + i + "X" + j, + false, false); + + t_util.t_readOnlySlotOutOfRange(page, recordCount[i]); + + page.unlatch(); + page =3D null; + } + + t_util.t_dropContainer(t, segment, cid); // cleanup + + t_util.t_commit(t); + + t.close(); + + PASS("P002"); + } + + /** + Test Page.delete + + @exception T_Fail Unexpected behaviour from the API + @exception StandardException Unexpected exception from the implementation + + @see Page#delete + */ + + protected void P003(long segment) throws StandardException, T_Fail { + + Transaction t =3D t_util.t_startTransaction(); =09 + + long cid =3D t_util.t_addContainer(t, segment); + + ContainerHandle c =3D t_util.t_openContainer(t, segment, cid, true); + Page page =3D t_util.t_getPage(c, ContainerHandle.FIRST_PAGE_NUMBER); + + RecordHandle r1, r2; + + T_RawStoreRow row1 =3D new T_RawStoreRow(REC_001); + T_RawStoreRow row2 =3D new T_RawStoreRow(REC_002); + + r1 =3D t_util.t_insertAtSlot(page, 0, row1); + r2 =3D t_util.t_insertAtSlot(page, 1, row2); + + t_util.t_checkFetch(page, r1, REC_001); + if (r2 !=3D null) + t_util.t_checkFetch(page, r2, REC_002); + + t_util.t_checkRecordCount(page, 2, r2 =3D=3D null ? 1 : 2); + + // delete the first + if (!page.delete(r1, (LogicalUndo)null)) + throw T_Fail.testFailMsg("delete() returned false"); + + t_util.t_checkRecordCount(page, 2, r2 =3D=3D null ? 0 : 1); + + if (page.delete(r1, (LogicalUndo)null)) + throw T_Fail.testFailMsg("delete() returned true on already deleted rec= ord"); + + t_util.t_checkRecordCount(page, 2, r2 =3D=3D null ? 0 : 1); + + if (page.recordExists(r1, false)) + throw T_Fail.testFailMsg("recordExists() returned true for deleted reco= rd"); + + // check the other record is still there + if (r2 !=3D null) + t_util.t_checkFetch(page, r2, REC_002); + + + if (!page.isDeletedAtSlot(0)) + throw T_Fail.testFailMsg("isDeletedAtSlot() doesn't represent correct s= tate"); + + t_util.t_dropContainer(t, segment, cid); // cleanup + + t_util.t_commit(t); + t.close(); + + PASS("P003"); + } + + /** + Test Page.update + + @exception T_Fail Unexpected behaviour from the API + @exception StandardException Unexpected exception from the implementation + + @see Page#update + */ + protected void P004(long segment) throws StandardException, T_Fail { + + Transaction t =3D t_util.t_startTransaction(); =09 + + long cid =3D t_util.t_addContainer(t, segment); + + ContainerHandle c =3D t_util.t_openContainer(t, segment, cid, true); + Page page =3D t_util.t_getPage(c, ContainerHandle.FIRST_PAGE_NUMBER); + + RecordHandle r1, r2; + + T_RawStoreRow row1 =3D new T_RawStoreRow(REC_001); + T_RawStoreRow row2 =3D new T_RawStoreRow(REC_002); + + r1 =3D t_util.t_insertAtSlot(page, 0, row1); + r2 =3D t_util.t_insertAtSlot(page, 1, row2); + + t_util.t_checkFetch(page, r1, REC_001); + if (r2 !=3D null) + t_util.t_checkFetch(page, r2, REC_002); + + row1 =3D new T_RawStoreRow((String) null); + if (!page.update(r1, row1.getRow(), (FormatableBitSet) null)) + throw T_Fail.testFailMsg("update() returned false"); + + t_util.t_checkFetch(page, r1, (String) null); + if (r2 !=3D null) + t_util.t_checkFetch(page, r2, REC_002); + + t_util.t_checkFetch(page, r1, (String) null); + if (r2 !=3D null) + t_util.t_checkFetch(page, r2, REC_002); + + row1 =3D new T_RawStoreRow(REC_003); + if (!page.update(r1, row1.getRow(), (FormatableBitSet) null)) + throw T_Fail.testFailMsg("update() returned false"); + + t_util.t_checkFetch(page, r1, REC_003); + if (r2 !=3D null) + t_util.t_checkFetch(page, r2, REC_002); + + // now delete the record we have been updating + if (!page.delete(r1, (LogicalUndo)null)) + throw T_Fail.testFailMsg("delete returned false"); + + row1 =3D new T_RawStoreRow(REC_004); + if (page.update(r1, row1.getRow(), (FormatableBitSet) null)) + throw T_Fail.testFailMsg("update returned true on deleted record"); + + page.deleteAtSlot(0, false, (LogicalUndo)null); + + t_util.t_checkFetch(page, r1, REC_003); + + if (!page.update(r1, row1.getRow(), (FormatableBitSet) null)) + throw T_Fail.testFailMsg("update returned false"); + + t_util.t_checkFetch(page, r1, REC_004); + + + t_util.t_dropContainer(t, segment, cid); // cleanup + + t_util.t_commit(t); + t.close(); + + PASS("P004"); + + } + + /* test repeated insert */ + protected void P005(long segment) throws StandardException, T_Fail=20 + { + Transaction t =3D t_util.t_startTransaction(); =09 + + long cid =3D t_util.t_addContainer(t, segment); + + ContainerHandle c =3D t_util.t_openContainer(t, segment, cid, true); + Page page1 =3D t_util.t_getLastPage(c); +=09 + T_RawStoreRow row0 =3D new T_RawStoreRow + ("long row xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx= xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx long row "); + T_RawStoreRow row1 =3D new T_RawStoreRow + ("medium row yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy= yy medium row"); + + t_util.t_insertAtSlot(page1, 0, row0); + + int i =3D 0; + while (page1.spaceForInsert()) + { + if (t_util.t_insertAtSlot(page1, 1, row1) =3D=3D null) + break; + i++; + } + + int count1 =3D page1.recordCount(); + + Page page2 =3D t_util.t_addPage(c); + t_util.t_insertAtSlot(page2, 0, row0); + + i =3D 1; + while (page2.spaceForInsert()) + { + if (t_util.t_insertAtSlot(page2, i++, row1) =3D=3D null) + break; + } + + int count2 =3D page2.recordCount(); + + // now purge them all and start over + page1.purgeAtSlot(1, page1.recordCount()-1, logDataForPurges); + page2.purgeAtSlot(1, page2.recordCount()-1, logDataForPurges); + if (page1.recordCount() !=3D 1) + throw T_Fail.testFailMsg("purge did not clean up page"); + + if (page2.recordCount() !=3D 1) + throw T_Fail.testFailMsg("purge did not clean up page"); + + i =3D 0; + while(page1.spaceForInsert()) + { + if (t_util.t_insertAtSlot(page1, 1, row1) =3D=3D null) + return; + i++; + } + + if (page1.recordCount() !=3D count1) + throw T_Fail.testFailMsg("cannot insert back same number of rows we pur= ged"); + + + i =3D 1; + while(page2.spaceForInsert()) + { + if (t_util.t_insertAtSlot(page2, i++, row1) =3D=3D null) + break; + } + + if (page2.recordCount() !=3D count2) + throw T_Fail.testFailMsg("cannot insert back same number of rows we pur= ged"); + + page1.unlatch(); + page2.unlatch();=09 + + t_util.t_dropContainer(t, segment, cid); // cleanup + + t_util.t_commit(t); + t.close(); + + PASS("P005"); + } + + /* + P006 + + test page time stamp - make sure all operation changes page time stamp + */ + protected void P006() throws StandardException, T_Fail + { + Transaction t =3D t_util.t_startTransaction(); + PageTimeStamp ts; + + long cid =3D t_util.t_addContainer(t, 0); + t_util.t_commit(t); + + ContainerHandle c =3D t_util.t_openContainer(t, 0, cid, true); + Page page1 =3D t_util.t_getLastPage(c); + =09 + ts =3D page1.currentTimeStamp(); + if (ts !=3D null && !page1.equalTimeStamp(ts)) + throw T_Fail.testFailMsg("page returns non-null time stamp which is not= equal to its current time stamp"); + + T_RawStoreRow row =3D new T_RawStoreRow(REC_001); + RecordHandle rh =3D t_util.t_insert(page1, row); + + if (page1.equalTimeStamp(ts)) + throw T_Fail.testFailMsg("timestamp on page not changed after insert op= eration"); + page1.setTimeStamp(ts); + if (ts !=3D null && !page1.equalTimeStamp(ts)) + throw T_Fail.testFailMsg("page returns non-null time stamp which is not= equal to its current time stamp"); + + // failed update should not change time stamp + t_util.t_updateSlotOutOfRange(page1, 3); + if (ts !=3D null && !page1.equalTimeStamp(ts)) + throw T_Fail.testFailMsg("failed pdate should not change time stamp"); + + T_RawStoreRow row2 =3D new T_RawStoreRow(REC_002); + page1.update(rh, row2.getRow(), (FormatableBitSet) null); + if (page1.equalTimeStamp(ts)) + throw T_Fail.testFailMsg("timestamp on page not changed after update op= eration"); + + page1.setTimeStamp(ts); + + T_RawStoreRow upd1 =3D new T_RawStoreRow(REC_003); + page1.update(rh, upd1.getRow(), BS_COL_0); + if (page1.equalTimeStamp(ts)) + throw T_Fail.testFailMsg("timestamp on page not changed after update fi= eld operation"); + + page1.setTimeStamp(ts); + + page1.delete(rh, (LogicalUndo)null); + if (page1.equalTimeStamp(ts)) + throw T_Fail.testFailMsg("timestamp on page not changed after delete op= eration"); + + page1.setTimeStamp(ts); + =09 + page1.purgeAtSlot(0, 1, logDataForPurges); + if (page1.equalTimeStamp(ts)) + throw T_Fail.testFailMsg("timestamp on page not changed after delete op= eration"); + + page1.setTimeStamp(ts); + page1.unlatch(); + + if (testRollback) + { + t_util.t_abort(t); + c =3D t_util.t_openContainer(t, 0, cid, true); + page1 =3D t_util.t_getLastPage(c); + + if (page1.equalTimeStamp(ts)) + throw T_Fail.testFailMsg("timestamp on page not changed after rollback= "); + + page1.setTimeStamp(ts); + } + =09 + Page page2 =3D c.addPage(); + Page page3 =3D c.addPage(); + + page2.setTimeStamp(ts); + + if (ts !=3D null) + { + try=20 + { + if (page3.equalTimeStamp(ts)) + throw T_Fail.testFailMsg("timestamp on 2 different pages should not e= quate"); + } + catch (StandardException se) + { + // either throw an exception or return false is OK + } + } + + + t_util.t_dropContainer(t, 0, cid); // cleanup + t_util.t_commit(t); + t.close(); + + PASS("P006"); + + } + + /** + P007 + + this test exercises repeated updates on a 1K page + + 2 rows (with 1 column) will be inserted into the page. + We expand the row data in slot 0 by 1 byte until the page is completely = full, + and overflows the record to an overflow page. + + @exception T_Fail Unexpected behaviour from the API + @exception StandardException Unexpected exception from the implementation + */ + + protected void P007(long segment) throws StandardException, T_Fail { + + Transaction t =3D t_util.t_startTransaction(); =09 + + // PART 1: + // insert two 1-column rows into the page, expand the first row, until i= t overflows. + long cid =3D t_util.t_addContainer(t, segment, 4096, 0, 1, false); + + ContainerHandle c =3D t_util.t_openContainer(t, segment, cid, true); + Page page =3D t_util.t_getLastPage(c); +=09 + T_RawStoreRow row =3D new T_RawStoreRow(REC_001); // McLaren + T_RawStoreRow row2 =3D new T_RawStoreRow(new String(new char[300]));=20 + + RecordHandle r1 =3D t_util.t_insertAtSlot(page, 0, row); + RecordHandle r2 =3D t_util.t_insertAtSlot(page, 1, row2); + + // update the row size 1 byte larger, until the page is full + String rowData =3D REC_001; + // 900 is an estimated number, because for 1K page, + // if you expand your row by 1 byte 900 times, the row will overflow for= sure. + for (int i =3D 0; i <=3D 900; i++) { + t_util.t_checkFetch(page, r1, rowData); + + rowData =3D rowData + REC_008; // "z" + row =3D new T_RawStoreRow(rowData); + page.updateAtSlot(0, row.getRow(), (FormatableBitSet) null); + } + + t_util.t_dropContainer(t, segment, cid); // cleanup + + // PART 2: + // insert two 2-column rows into the page, + // expand the first row by expanding the first column by 300 bytes, + // and shrinking the second column by 300 bytes. Update should secceed. + cid =3D t_util.t_addContainer(t, segment, 4096, 0, 1, false); + c =3D t_util.t_openContainer(t, segment, cid, true); + page =3D t_util.t_getLastPage(c); + long pid =3D page.getPageNumber(); + + row =3D new T_RawStoreRow(2); + row.setColumn(0, REC_001); // small column + row.setColumn(1, new String (new char[400])); // large column + + r1 =3D t_util.t_insertAtSlot(page, 0, row); + r2 =3D t_util.t_insertAtSlot(page, 1, row2); + + row.setColumn(0, REC_001 + new String (new char[300])); + row.setColumn(1, new String (new char[100])); + + page.updateAtSlot(0, row.getRow(), (FormatableBitSet) null); + + Page page2 =3D t_util.t_addPage(c); + long pid2 =3D page2.getPageNumber(); + if (pid2 !=3D (pid + 1)) + throw T_Fail.testFailMsg("The update should not have overflowed the rec= ord"); + + // Now, shrink the first column by 300 bytes, and expand the second colu= mn by 300 bytes. + // the update should also succeed. + row.setColumn(0, REC_001); + row.setColumn(1, new String (new char[400])); + + page.updateAtSlot(0, row.getRow(), (FormatableBitSet) null); + + Page page3 =3D t_util.t_addPage(c); + long pid3 =3D page3.getPageNumber(); + if (pid3 !=3D (pid2 + 1)) + throw T_Fail.testFailMsg("The update should not have overflowed the rec= ord"); + + t_util.t_dropContainer(t, segment, cid); // cleanup + + t_util.t_commit(t); + t.close(); + + PASS("P007"); + + } + + /** + P008 + + this test exercises repeated inserts with small rows on a 1K page + + we will insert as many rows as possible into the page. Then we reduce t= he row by 1 byte at a time, + we will try to insert another smaller row. + This test also tests spaceForInsert(). + + @exception T_Fail Unexpected behaviour from the API + @exception StandardException Unexpected exception from the implementation + */ + + protected void P008(long segment) throws StandardException, T_Fail=20 + { + Transaction t =3D t_util.t_startTransaction(); =09 + + long cid =3D t_util.t_addContainer(t, segment, 4096, 0, 1, false); + + ContainerHandle c =3D t_util.t_openContainer(t, segment, cid, true); + Page page1 =3D t_util.t_getLastPage(c); +=09 + T_RawStoreRow row =3D new T_RawStoreRow(REC_001); // McLaren + + t_util.t_insertAtSlot(page1, 0, row); + + int i =3D 0; + while (page1.spaceForInsert(row.getRow(), (FormatableBitSet) null, 100)) + { + // if it says there is enough room for this row, the insert should succ= eed. + if (t_util.t_insertAtSlot(page1, 1, row) =3D=3D null) + throw T_Fail.testFailMsg("There is space for this insert. It shouldn'= t have failed. " + + "record #" + i); + i++; + } + + REPORT(i + " rows inserted."); + + // We got out of the while loop because there is no room for the insert. + // So, if the insert succeed, then we have a problem. + if (t_util.t_insertAtSlot(page1, 1, row) !=3D null) + throw T_Fail.testFailMsg("There is no space for this insert. It should= have failed."); + + // Now, we will try to fill the page with smaller rows. + String[] s =3D new String[7]; + s[6] =3D "McLare"; + s[5] =3D "McLar"; + s[4] =3D "McLa"; + s[3] =3D "McL"; + s[2] =3D "Mc"; + s[1] =3D "M"; + s[0] =3D null; + // reduce the row by 1 byte + i =3D 6; + boolean notDone =3D true; + do + { + row =3D new T_RawStoreRow(s[i]); + if (page1.spaceForInsert(row.getRow(), (FormatableBitSet) null, 100)) + { + // If it says there is enough room for the row, then the insert should= succed. + if (t_util.t_insertAtSlot(page1, 1, row) =3D=3D null) + throw T_Fail.testFailMsg("There should be space for this insert, row = is " + s[i]); + else + notDone =3D false; + } + else + i--; + } while ((notDone) && (i >=3D 0)); + + + page1.unlatch(); + + t_util.t_dropContainer(t, segment, cid); // cleanup + + t_util.t_commit(t); + t.close(); + + PASS("P008"); + } + + /** + P009 + + this test exercises repeated shrinking and expanding of fields using upd= ateFieldBySlot + + we will insert as many rows as possible into the page. Then set some of = the columns to null, + That should not create more space on the page for inserts, because the e= xtra space become + reservedspace for the row. So, the next insert should fail. + + @exception T_Fail Unexpected behaviour from the API + @exception StandardException Unexpected exception from the implementation + */ + + protected void P009(long segment)=20 + throws StandardException, T_Fail=20 + { + int slot =3D 0; + int i =3D 0; + int j =3D 0; + String field =3D REC_001; + + Transaction t =3D t_util.t_startTransaction(); + + long cid =3D t_util.t_addContainer(t, segment); + + // Get the first page & check the record counts are zero + ContainerHandle c =3D t_util.t_openContainer(t, segment, cid, true); + Page page =3D t_util.t_getPage(c, ContainerHandle.FIRST_PAGE_NUMBER); + + t_util.t_checkEmptyPage(page); + + // Create a 13-column row + T_RawStoreRow row =3D new T_RawStoreRow(13); + row.setColumn(0, (String) null); + row.setColumn(1, REC_001); + row.setColumn(2, REC_002); + row.setColumn(3, REC_003); + row.setColumn(4, REC_004); + row.setColumn(5, REC_005); + row.setColumn(6, REC_006); + row.setColumn(7, REC_007); + row.setColumn(8, (String) null); + row.setColumn(9, (String) null); + row.setColumn(10, REC_007); + row.setColumn(11, (String) null); + row.setColumn(12, REC_006); + + // insert the row into the page until the page is full + int numRows =3D 0; + slot =3D page.FIRST_SLOT_NUMBER; + while (page.spaceForInsert(row.getRow(), (FormatableBitSet) null, 100)) { + t_util.t_insert(page, row); + numRows++; + } + REPORT(numRows + " rows inserted "); + + // update all the fields in the even number rows to null + // set all the fields in the odd number rows to REC_001 + DataValueDescriptor col =3D new SQLChar(); // null + for (i =3D page.FIRST_SLOT_NUMBER; i < (page.FIRST_SLOT_NUMBER + 2); i++= ) { + + for (slot =3D i; slot <=3D (numRows - 1); slot +=3D 2) { + + for (j =3D 0; j <=3D 12; j++) { + if (page.updateFieldAtSlot(slot, j, col, null) =3D=3D null) { + + throw T_Fail.testFailMsg("Failed to update field " + j+ ", in row " = + slot); + } + } + } + + col =3D new SQLChar(REC_001); + } + + // fetch all the fields, and see if they are correct + DataValueDescriptor storedColumn =3D new SQLChar(); + field =3D null; + for (i =3D page.FIRST_SLOT_NUMBER; i < (page.FIRST_SLOT_NUMBER + 2); i++= ) { + + for (slot =3D i; slot <=3D (numRows - 1); slot +=3D 2) { + + for (j =3D 0; j <=3D 12; j++) { + + t_util.t_checkFetchColFromSlot(page, slot, j, storedColumn, false, fi= eld); + + } + } + + field =3D REC_001; + } + + // Now if we try to insert the old row again, there should still be no r= oom + if (page.spaceForInsert()) + throw T_Fail.testFailMsg("Did not get no room for record on page error"= ); + + // update the first and last field of every row to REC_006 + col =3D new SQLChar(REC_006); + for (slot =3D page.FIRST_SLOT_NUMBER; slot <=3D (numRows - 1); slot++) { + if (page.updateFieldAtSlot(slot, 0, col, null) =3D=3D null || + page.updateFieldAtSlot(slot, 12, col, null) =3D=3D null) { + + throw T_Fail.testFailMsg("Failed to update fields to REC_006 in row " = + slot); + } + } + =09 + // update field 5 and 6 of every row to REC_007 + col =3D new SQLChar(REC_007); + for (slot =3D page.FIRST_SLOT_NUMBER; slot <=3D (numRows - 1); slot++) { + if (page.updateFieldAtSlot(slot, 5, col, null) =3D=3D null || + page.updateFieldAtSlot(slot, 6, col, null) =3D=3D null) { + + throw T_Fail.testFailMsg("Failed to update fields to REC_007 in row " = + slot); + } + } + + // fetch all the fields again, and see if they are correct + for (i =3D page.FIRST_SLOT_NUMBER; i < (page.FIRST_SLOT_NUMBER + 2); i++= ) { + + for (slot =3D i; slot <=3D (numRows - 1); slot +=3D 2) { + + for (j =3D 0; j <=3D 12; j++) { + + switch (j) { + case 0: + case 12: + field =3D REC_006; + break; + case 5: + case 6: + field =3D REC_007; + break; + default: + if ((slot % 2) =3D=3D 0) + field =3D null; + else + field =3D REC_001; + break; + } + + t_util.t_checkFetchColFromSlot(page, slot, j, storedColumn, false, fi= eld); + + } + } + } + + // We now try to insert the old row one last time, there should still be= no room + if (page.spaceForInsert()) + throw T_Fail.testFailMsg("Did not get no room for record on page error"= ); + + // now we want to increase row 0 and column 5 one byte at a time, until = the page is full + // but, every 5 increases we will reduce the field size by one byte + field =3D REC_007; + i =3D 0; + String field_pre =3D null; + while (true) { + if ((i % 5) !=3D 0) { + field_pre =3D field; + field +=3D REC_008; + } else { + field =3D field_pre; + } + + if (((i % 10) =3D=3D 3) || ((i % 10) =3D=3D 7)) { + page.unlatch(); + page =3D null; + + factory.idle(); + + page =3D t_util.t_getPage(c, ContainerHandle.FIRST_PAGE_NUMBER); + } + + col =3D new SQLChar(field); + + try { + page.updateFieldAtSlot(0, 5, col, null); + } catch (StandardException se) { + // now we have filled the page + if (i < 809) { + throw T_Fail.testFailMsg("should be able to update Row 0 Column 5 809= times" + + ", but only updated " + i + + " times. Note: you maybe getting this error if your page format h= as changed."); + } else { + REPORT("Row 0 Column 5 was updated " + i + " times."); + } + break; + } + i++; + } + =09 + // The page is completely full at this point. + // update Row 1 Column 1 from REC_001 to REC_002. They are the same len= gth + page.unlatch(); + page =3D null; + factory.idle(); + page =3D t_util.t_getPage(c, ContainerHandle.FIRST_PAGE_NUMBER); + col =3D new SQLChar(REC_002); + if (page.updateFieldAtSlot(1, 1, col, null) =3D=3D null) { + throw T_Fail.testFailMsg("update Row 1 and Column 1 to same length data= failed."); + } + + REPORT("updated col1 in row 1 to same length"); + + // now expand update Row 1 Column 1 by one byte. This should fail. + page.unlatch(); + page =3D null; + factory.idle(); + page =3D t_util.t_getPage(c, ContainerHandle.FIRST_PAGE_NUMBER); + field =3D REC_002 + REC_008; + col =3D new SQLChar(field); + try { + page.updateFieldAtSlot(1, 1, col, null); + throw T_Fail.testFailMsg("update Row 1 and Column 1 to longer length sh= ould have failed."); + } catch (StandardException se) { + ; + } + + + // clean up + if (segment !=3D ContainerHandle.TEMPORARY_SEGMENT) { + t_util.t_dropContainer(t, segment, cid); // cleanup + } + + t_util.t_commit(t); + t.close(); + + PASS("P009: segment " + segment); + =09 + } + + + + /** + P011 + + this test exercises insertAtSlot, (LogicalUndo)null + + @exception T_Fail Unexpected behaviour from the API + @exception StandardException Unexpected exception from the implementation + */ + protected void P011(long segment) + throws StandardException, T_Fail + { + Transaction t =3D t_util.t_startTransaction(); + long cid =3D t_util.t_addContainer(t, segment); + t_util.t_commit(t); + +=09 + // Get the first page + ContainerHandle c =3D t_util.t_openContainer(t, segment, cid, true); + Page page =3D t_util.t_getPage(c, ContainerHandle.FIRST_PAGE_NUMBER); + + // REPORT("insert 2 records at FIRST_SLOT_NUMBER"); + T_RawStoreRow row1 =3D new T_RawStoreRow(REC_001); + T_RawStoreRow row2 =3D new T_RawStoreRow(REC_002); + T_RawStoreRow row3 =3D new T_RawStoreRow(REC_003); + T_RawStoreRow row4 =3D new T_RawStoreRow(REC_004); + + // try inserting at slot -1 and slot 1 + try { + RecordHandle r =3D t_util.t_insertAtSlot(page, -1, row1); + throw T_Fail.testFailMsg("insert at slot -1 succeeded"); + } catch (StandardException se) { + // throw if not a statement exception. + if (se.getSeverity() > ExceptionSeverity.STATEMENT_SEVERITY) + throw se; + } + + try { + RecordHandle r =3D t_util.t_insertAtSlot(page, 1, row1); + throw T_Fail.testFailMsg("insert at slot 1 succeeded"); + } catch (StandardException se) { + // throw if not a statement exception. + if (se.getSeverity() > ExceptionSeverity.STATEMENT_SEVERITY) + throw se; + } + =09 + RecordHandle r1, r2, r3, r4; + // first insert to a page must suceed + r3 =3D t_util.t_insertAtSlot(page, Page.FIRST_SLOT_NUMBER, row3); + t_util.t_checkFetch(page, r3, REC_003); + t_util.t_checkFetchBySlot(page, Page.FIRST_SLOT_NUMBER, REC_003,false, f= alse); =09 + + r1 =3D r2 =3D r4 =3D null; + r1 =3D t_util.t_insertAtSlot(page, Page.FIRST_SLOT_NUMBER, row1); + + if (r1 !=3D null) { + t_util.t_checkFetch(page, r1, REC_001); + t_util.t_checkFetchBySlot(page, Page.FIRST_SLOT_NUMBER, REC_001,false, = false); + } else { + t_util.t_abort(t); + t.close(); + REPORT("P011 not run - could not fit 4 rows on page"); + return; + } + + // REPORT("insert a record at 2nd slot"); + r2 =3D t_util.t_insertAtSlot(page, Page.FIRST_SLOT_NUMBER+1, row2); + + if (r2 !=3D null) { + t_util.t_checkFetch(page, r2, REC_002); + t_util.t_checkFetchBySlot(page, Page.FIRST_SLOT_NUMBER+1, REC_002,false= , false); + } else { + t_util.t_abort(t); + t.close(); + REPORT("P011 not completed - could not fit 4 rows on page"); + return; + } + + // REPORT("insert a record at the end"); + r4 =3D t_util.t_insertAtSlot(page, 3, row4); + if (r4 !=3D null) { + t_util.t_checkFetch(page, r4, REC_004); + t_util.t_checkFetchBySlot(page, 3, REC_004,false, false); + } else { + t_util.t_abort(t); + t.close(); + REPORT("P011 not completed - could not fit 4 rows on page"); + return; + } + + // REPORT("make sure records are in the correct order"); + // order is REC_001 REC_002 REC_003 REC_004=20 + + + t_util.t_checkFetchFirst(page, REC_001); + t_util.t_checkFetchNext(page, r1, REC_002); + t_util.t_checkFetchNext(page, r2, REC_003); + t_util.t_checkFetchNext(page, r3, REC_004); + t_util.t_checkFetchLast(page, REC_004); + + // check the fetch by slot interface + t_util.t_checkFetchBySlot(page, Page.FIRST_SLOT_NUMBER, REC_001,false, t= rue); + t_util.t_checkFetchBySlot(page, Page.FIRST_SLOT_NUMBER+1, REC_002,false,= false); + t_util.t_checkFetchBySlot(page, Page.FIRST_SLOT_NUMBER+2, REC_003,false,= true); + t_util.t_checkFetchBySlot(page, Page.FIRST_SLOT_NUMBER+3, REC_004,false,= false); + + // clean up + + t_util.t_dropContainer(t, segment, cid); // cleanup + + t_util.t_commit(t); + t.close(); + + PASS("P011"); + + } + + /** + P012 + + this test exercises updateAtSlot + + @exception T_Fail Unexpected behaviour from the API + @exception StandardException Unexpected exception from the implementation + */ + protected void P012(long segment) + throws StandardException, T_Fail + { + Transaction t =3D t_util.t_startTransaction(); + long cid =3D t_util.t_addContainer(t, segment); + + ContainerHandle c =3D t_util.t_openContainer(t, segment, cid, true); + Page page =3D t_util.t_getPage(c, ContainerHandle.FIRST_PAGE_NUMBER); + + // REPORT("insert 3 records"); + T_RawStoreRow row1 =3D new T_RawStoreRow(REC_001); + + T_RawStoreRow row2 =3D new T_RawStoreRow(2); + row2.setColumn(0, (String) null); + row2.setColumn(1, REC_001); + + T_RawStoreRow row3 =3D new T_RawStoreRow(3); + row3.setColumn(0, REC_001); + row3.setColumn(1, REC_002); + row3.setColumn(2, REC_003); + + RecordHandle r1, r2, r3; + r1 =3D t_util.t_insertAtSlot(page, 0, row1); + + r2 =3D r3 =3D null; + r2 =3D t_util.t_insertAtSlot(page, 1, row2); +=09 + if (r2 =3D=3D null) { + REPORT("P012 not completed - cannot insert second row"); + return; + } + + r3 =3D t_util.t_insertAtSlot(page, 2, row3); + if (r3 =3D=3D null) { + REPORT("P012 not completed - cannot insert third row"); + return; + } + + // check that they are inserted correctly + t_util.t_checkFetch(page, r1, row1); + t_util.t_checkFetch(page, r2, row2); + t_util.t_checkFetch(page, r3, row3); + + // REPORT("update that grows the #columns in row"); + T_RawStoreRow upd1 =3D new T_RawStoreRow(2); + upd1.setColumn(0, (String) null); + upd1.setColumn(1, REC_001); + + r1 =3D page.updateAtSlot(0, upd1.getRow(), (FormatableBitSet) null); + t_util.t_checkFetch(page, r1, upd1); + t_util.t_checkFetch(page, r2, row2); + t_util.t_checkFetch(page, r3, row3); + + // REPORT("update that shrinks the #columns in row"); + T_RawStoreRow upd2 =3D new T_RawStoreRow(REC_004); + + r2 =3D page.updateAtSlot(1, upd2.getRow(), (FormatableBitSet) null); + t_util.t_checkFetch(page, r1, upd1); + t_util.t_checkFetch(page, r2, upd2); + t_util.t_checkFetch(page, r3, row3); + + // REPORT("update same #columns in row"); + T_RawStoreRow upd3 =3D new T_RawStoreRow(3); + upd3.setColumn(0, REC_003); + upd3.setColumn(1, REC_002); + upd3.setColumn(2, REC_001); + + r3 =3D page.updateAtSlot(2, upd3.getRow(), (FormatableBitSet) null); + t_util.t_checkFetch(page, r1, upd1); + t_util.t_checkFetch(page, r2, upd2); + t_util.t_checkFetch(page, r3, upd3); + + // clean up + + if (segment !=3D ContainerHandle.TEMPORARY_SEGMENT) { + t_util.t_dropContainer(t, segment, cid); // cleanup + } + + t_util.t_commit(t); + t.close(); + + PASS("P012"); + } + + /** + P013 + + this test exercises deleteAtSlot and isDeletedAtSlot + @exception T_Fail Unexpected behaviour from the API + @exception StandardException Unexpected exception from the implementation + */ + protected void P013() + throws StandardException, T_Fail + { + Transaction t =3D t_util.t_startTransaction(); + long cid =3D t_util.t_addContainer(t, 0); + + t_util.t_commit(t); + + ContainerHandle c =3D t_util.t_openContainer(t, 0, cid, true); + Page page =3D t_util.t_getPage(c, ContainerHandle.FIRST_PAGE_NUMBER); + + // REPORT("insert 2 records"); + T_RawStoreRow row1 =3D new T_RawStoreRow(REC_001); + T_RawStoreRow row2 =3D new T_RawStoreRow(REC_002); + + RecordHandle r1 =3D t_util.t_insertAtSlot(page, 0, row1); + RecordHandle r2; + r2 =3D t_util.t_insertAtSlot(page, 1, row2); + if (r2 =3D=3D null) { + REPORT("P013 not completed - could not fit two rows on a page"); + return; + } + + t_util.t_checkRecordCount(page, 2, 2); + + // REPORT("delete them one by one"); + page.deleteAtSlot(0, true, (LogicalUndo)null); + + t_util.t_checkRecordCount(page, 2, 1); + + if (!page.isDeletedAtSlot(0)) + throw T_Fail.testFailMsg("Failed to delete record 0"); + if (page.isDeletedAtSlot(1)) + throw T_Fail.testFailMsg("Record mistakenly deleted"); + + page.deleteAtSlot(1, true, (LogicalUndo)null); + t_util.t_checkRecordCount(page, 2, 0); + if (!page.isDeletedAtSlot(1)) + throw T_Fail.testFailMsg("Failed to delete record 1"); + + page.deleteAtSlot(0, false, (LogicalUndo)null); + t_util.t_checkRecordCount(page, 2, 1); + if (page.isDeletedAtSlot(0)) + throw T_Fail.testFailMsg("Failed to undelete record 0"); + if (!page.isDeletedAtSlot(1)) + throw T_Fail.testFailMsg("Record mistakenly undeleted"); + + page.deleteAtSlot(1, false, (LogicalUndo)null); + t_util.t_checkRecordCount(page, 2, 2); + if (page.isDeletedAtSlot(1)) + throw T_Fail.testFailMsg("Failed to undelete record 1"); + + // try the negative tests + try { + page.deleteAtSlot(0, false, (LogicalUndo)null); + throw T_Fail.testFailMsg("undeleted on undeleted record succeeded"); + } catch (StandardException se) { + // throw if not a statement exception. + if (se.getSeverity() > ExceptionSeverity.STATEMENT_SEVERITY) + throw se; + } + + page.deleteAtSlot(0, true, (LogicalUndo)null); + try { + page.deleteAtSlot(0, true, (LogicalUndo)null); + throw T_Fail.testFailMsg("deleted on deleted record succeeded"); + } catch (StandardException se) { + // throw if not a statement exception. + if (se.getSeverity() > ExceptionSeverity.STATEMENT_SEVERITY) + throw se; + } + + t_util.t_checkRecordCount(page, 2, 1); + // clean up + PASS("P013"); + + t_util.t_dropContainer(t, 0, cid); // cleanup + + + + t_util.t_commit(t); + t.close(); + + =09 + } + + /** + P014 + + this test exercises purgeAtSlot + @exception T_Fail Unexpected behaviour from the API + @exception StandardException Unexpected exception from the implementation + */ + protected void P014() + throws StandardException, T_Fail + { + Transaction t =3D t_util.t_startTransaction(); + long cid =3D t_util.t_addContainer(t,0); + t_util.t_commit(t); + +=09 + ContainerHandle c =3D t_util.t_openContainer(t, 0, cid, true); + Page page =3D t_util.t_getPage(c, ContainerHandle.FIRST_PAGE_NUMBER); + + // REPORT("insert 5 records"); + T_RawStoreRow row0 =3D new T_RawStoreRow(REC_001); + T_RawStoreRow row1 =3D new T_RawStoreRow(REC_001); + T_RawStoreRow row2 =3D new T_RawStoreRow(REC_002); + T_RawStoreRow row3 =3D new T_RawStoreRow(REC_003); + T_RawStoreRow row4 =3D new T_RawStoreRow(REC_004); + =09 + RecordHandle r0, r1, r2, r3, r4; + r0 =3D t_util.t_insertAtSlot(page, 0, row0); + r1 =3D t_util.t_insertAtSlot(page, 1, row1); + r2 =3D t_util.t_insertAtSlot(page, 2, row2); + r3 =3D t_util.t_insertAtSlot(page, 3, row3); + r4 =3D t_util.t_insertAtSlot(page, 4, row4); + + if (r3 !=3D null) page.deleteAtSlot(3, true, (LogicalUndo)null); + + // REPORT("commit it"); + t_util.t_commit(t); + + c =3D t_util.t_openContainer(t, 0, cid, true); + page =3D t_util.t_getPage(c, ContainerHandle.FIRST_PAGE_NUMBER); + + try=20 + { + page.purgeAtSlot(-1, 1, logDataForPurges); + throw T_Fail.testFailMsg("negative slot number did not cause an excepti= on"); + } + catch (StandardException se) {} // expected + + try + { + page.purgeAtSlot(4, 4, logDataForPurges); + throw T_Fail.testFailMsg("purging more rows than is on page did not cau= se an exception"); + } + catch (StandardException se) {} // expected + + // if not all the rows are there, do minimal test + if (r4 =3D=3D null) + { + int rcount =3D page.recordCount(); + page.purgeAtSlot(0, 1, logDataForPurges); + if (page.recordCount() !=3D rcount-1) + T_Fail.testFailMsg("failed to purge a record, expect " +=20 + (rcount-1) + " got " + page.recordCount()); + + if (testRollback) + { + t_util.t_abort(t); + + c =3D t_util.t_openContainer(t, 0, cid, true); + page =3D t_util.t_getPage(c, ContainerHandle.FIRST_PAGE_NUMBER); + if(logDataForPurges) + t_util.t_checkFetchBySlot(page, 0, REC_001,false, true); + else + t_util.t_checkFetchBySlot(page, 0, REC_NULL,false, true); + if (page.recordCount() !=3D rcount) + T_Fail.testFailMsg("failed to rollback purge, expect " +=20 + rcount + " got " + page.recordCount()); + } + else + { + t_util.t_commit(t); + } + PASS("minimal P014"); + return; + } + + // REPORT("purge 2 records from middle"); + page.purgeAtSlot(1, 2, logDataForPurges); + t_util.t_checkFetchBySlot(page, 0, REC_001,false, true); + t_util.t_checkFetchBySlot(page, 1, REC_003,true, true); + t_util.t_checkFetchBySlot(page, 2, REC_004,false, true); + + if (page.recordCount() !=3D 3) + T_Fail.testFailMsg("page expect to have 3 records, recordCount() =3D " + + page.recordCount()); + + // REPORT("purge all records from the page"); + page.purgeAtSlot(0, 3, logDataForPurges); + if (page.recordCount() !=3D 0) + T_Fail.testFailMsg("page expect to have 0 records, recordCount() =3D " + + page.recordCount()); + + if (testRollback) + { + + REPORT("testing rollback"); + t_util.t_abort(t); + + c =3D t_util.t_openContainer(t, 0, cid, true); + page =3D t_util.t_getPage(c, ContainerHandle.FIRST_PAGE_NUMBER); + + if(logDataForPurges){ + t_util.t_checkFetchBySlot(page, 0, REC_001,false, true); + t_util.t_checkFetchBySlot(page, 1, REC_001,false, true); + t_util.t_checkFetchBySlot(page, 2, REC_002,false, true); + t_util.t_checkFetchBySlot(page, 3, REC_003,true, true); + t_util.t_checkFetchBySlot(page, 4, REC_004,false, true); + }else + { + t_util.t_checkFetchBySlot(page, 0, REC_NULL,false, true); + t_util.t_checkFetchBySlot(page, 1, REC_NULL,false, true); + t_util.t_checkFetchBySlot(page, 2, REC_NULL,false, true); + t_util.t_checkFetchBySlot(page, 3, REC_NULL,true, true); + t_util.t_checkFetchBySlot(page, 4, REC_NULL,false, true); + } + + if (page.recordCount() !=3D 5) + T_Fail.testFailMsg("page expect to have 5 records, recordCount() =3D "= + + page.recordCount()); + + // REPORT("purge 3 records from the end"); + page.purgeAtSlot(2, 3, logDataForPurges); + if(logDataForPurges) + { + t_util.t_checkFetchBySlot(page, 0, REC_001,false, true); + t_util.t_checkFetchBySlot(page, 1, REC_001,false, true); + }else + { + t_util.t_checkFetchBySlot(page, 0, REC_NULL,false, true); + t_util.t_checkFetchBySlot(page, 1, REC_NULL,false, true); + } + if (page.recordCount() !=3D 2) + T_Fail.testFailMsg("page expect to have 2 records, recordCount() =3D "= + + page.recordCount()); + + // REPORT("rollback"); + t_util.t_abort(t); + + c =3D t_util.t_openContainer(t, 0, cid, true); + page =3D t_util.t_getPage(c, ContainerHandle.FIRST_PAGE_NUMBER); + if(logDataForPurges){ + t_util.t_checkFetchBySlot(page, 0, REC_001,false, true); + t_util.t_checkFetchBySlot(page, 1, REC_001,false, true); + t_util.t_checkFetchBySlot(page, 2, REC_002,false, true); + t_util.t_checkFetchBySlot(page, 3, REC_003,true, true); + t_util.t_checkFetchBySlot(page, 4, REC_004,false, true); + }else + { + t_util.t_checkFetchBySlot(page, 0, REC_NULL,false, true); + t_util.t_checkFetchBySlot(page, 1, REC_NULL,false, true); + t_util.t_checkFetchBySlot(page, 2, REC_NULL,false, true); + t_util.t_checkFetchBySlot(page, 3, REC_NULL,true, true); + t_util.t_checkFetchBySlot(page, 4, REC_NULL,false, true);=09 + } + + if (page.recordCount() !=3D 5) + T_Fail.testFailMsg("page expect to have 5 records, recordCount() =3D "= + + page.recordCount()); + + // REPORT("make sure delete record is reconstituted as such"); + if (page.isDeletedAtSlot(1)) + T_Fail.testFailMsg("rolled back purged undeleted record cause record t= o be deleted"); + if (!page.isDeletedAtSlot(3)) + T_Fail.testFailMsg("rolled back purged deleted record cause record to = be undeleted"); + } + PASS("P014"); + + t_util.t_dropContainer(t, 0, cid); // cleanup + t_util.t_commit(t); + t.close(); + } + + + /** + P015 + + this test exercises updateAtSlot + + @exception T_Fail Unexpected behaviour from the API + @exception StandardException Unexpected exception from the implementation + */ + protected void P015() + throws StandardException, T_Fail + { + Transaction t =3D t_util.t_startTransaction(); + long cid =3D t_util.t_addContainer(t, 0); + + t_util.t_commit(t); + + + ContainerHandle c =3D t_util.t_openContainer(t, 0, cid, true); + Page page =3D t_util.t_getPage(c, ContainerHandle.FIRST_PAGE_NUMBER); + + // REPORT("insert 3 records"); + T_RawStoreRow row1 =3D new T_RawStoreRow(REC_001); + + T_RawStoreRow row2 =3D new T_RawStoreRow(2); + row2.setColumn(0, (String) null); + row2.setColumn(1, REC_001); + + T_RawStoreRow row3 =3D new T_RawStoreRow(3); + row3.setColumn(0, REC_001); + row3.setColumn(1, REC_002); + row3.setColumn(2, REC_003); + + RecordHandle r1, r2, r3; + r1 =3D t_util.t_insertAtSlot(page, 0, row1); + + r2 =3D r3 =3D null; + r2 =3D t_util.t_insertAtSlot(page, 1, row2); + + if (r2 =3D=3D null) { + REPORT("P015 not completed - cannot insert second row"); + return; + } + + r3 =3D t_util.t_insertAtSlot(page, 2, row3); + + if (r3 =3D=3D null) { + REPORT("P015 not completed - cannot insert third row"); + return; + } + + // check that they are inserted correctly + t_util.t_checkFetch(page, r1, row1); + t_util.t_checkFetch(page, r2, row2); + t_util.t_checkFetch(page, r3, row3); + + // now update the middle row with a large value + T_RawStoreRow row2u =3D new T_RawStoreRow(2); + row2u.setColumn(0, "0123456789012345678901234567890123456789012345678901= 23456789012345678901234567890123456789012345678901234567890123456789"); + row2u.setColumn(1, "0123456789012345678901234567890123456789012345678901= 234567890123456789012345678901234567890123456789012345678901234567890123456= 789"); + + page.updateAtSlot(1, row2u.getRow(), (FormatableBitSet) null); + t_util.t_checkFetch(page, r2, row2u); + + + // now update the field of the first record with a large value + ((T_RawStoreRow) row1).setColumn(0, "abcdefghijklmnopqrstuvwxyzabcdefghi= jklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdef= ghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabc= defghijklmnopqrstuvwxyz"); + + FormatableBitSet validColumn =3D new FormatableBitSet(2); + + validColumn.clear(); + validColumn.set(0); + + page.updateAtSlot(0, row1.getRow(), validColumn); + + t_util.t_checkFetch(page, r1, row1); + + ((T_RawStoreRow) row3).setColumn(1, "XXabcdefghijklmnopqrstuvwxyzabcdefg= hijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcd= efghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyza= bcdefghijklmnopqrstuvwxyz"); + + validColumn.clear(); + validColumn.set(1); + + page.updateAtSlot(2, row3.getRow(), validColumn); + t_util.t_checkFetch(page, r3, row3); + + // clean up + PASS("P015"); + + t_util.t_dropContainer(t, 0, cid); // cleanup + + + t_util.t_commit(t); + t.close(); + + } + + /* + P016 + + this test exercises copyAndPurge + @exception T_Fail Unexpected behaviour from the API + @exception StandardException Unexpected exception from the implementation + */ + protected void P016() + throws StandardException, T_Fail + { + Transaction t =3D t_util.t_startTransaction(); + long cid =3D t_util.t_addContainer(t, 0); + long cid2 =3D t_util.t_addContainer(t, 0); + + t_util.t_commit(t); + + + ContainerHandle c =3D t_util.t_openContainer(t, 0, cid, true); + + Page page1 =3D t_util.t_getPage(c, ContainerHandle.FIRST_PAGE_NUMBER); + Page page2 =3D t_util.t_addPage(c); + long pid1 =3D page1.getPageNumber(); + long pid2 =3D page2.getPageNumber(); + + t_util.t_checkEmptyPage(page2); + + // first fill up page 1 + + int i =3D 0; + int deleted =3D 0; + RecordHandle rh; + + T_RawStoreRow row; + + for (i =3D 0, row =3D new T_RawStoreRow("row at slot " + i); + page1.spaceForInsert(); [=2E.. 4703 lines stripped ...]