KickJava   Java API By Example, From Geeks To Geeks.

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


1 /*
2
3    Derby - Class org.apache.derbyTesting.unitTests.store.T_RawStoreFactory
4
5    Licensed to the Apache Software Foundation (ASF) under one or more
6    contributor license agreements. See the NOTICE file distributed with
7    this work for additional information regarding copyright ownership.
8    The ASF licenses this file to You under the Apache License, Version 2.0
9    (the "License"); you may not use this file except in compliance with
10    the License. You may obtain a copy of the License at
11
12       http://www.apache.org/licenses/LICENSE-2.0
13
14    Unless required by applicable law or agreed to in writing, software
15    distributed under the License is distributed on an "AS IS" BASIS,
16    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17    See the License for the specific language governing permissions and
18    limitations under the License.
19
20  */

21
22 package org.apache.derbyTesting.unitTests.store;
23
24 import org.apache.derby.iapi.store.raw.*;
25
26 // impl imports are the preferred way to create unit tests.
27
import org.apache.derbyTesting.unitTests.harness.T_MultiThreadedIterations;
28 import org.apache.derbyTesting.unitTests.harness.T_Fail;
29
30 import org.apache.derby.iapi.services.context.ContextService;
31 import org.apache.derby.iapi.services.context.ContextManager;
32 import org.apache.derby.iapi.services.locks.*;
33 import org.apache.derby.iapi.services.monitor.Monitor;
34 import org.apache.derby.iapi.services.sanity.SanityManager;
35 import org.apache.derby.iapi.services.uuid.UUIDFactory;
36 import org.apache.derby.catalog.UUID;
37 import org.apache.derby.iapi.services.property.PropertyUtil;
38 import org.apache.derby.iapi.error.ExceptionSeverity;
39 import org.apache.derby.iapi.error.StandardException;
40
41 import org.apache.derby.iapi.store.access.*;
42 import org.apache.derby.iapi.store.access.conglomerate.LogicalUndo;
43
44 import org.apache.derby.iapi.store.raw.xact.RawTransaction;
45 import org.apache.derby.iapi.store.raw.data.RawContainerHandle;
46 import org.apache.derby.iapi.store.raw.log.LogInstant;
47
48 import org.apache.derby.iapi.types.DataValueDescriptor;
49
50 // impl a logInstant implemented as log counter to test truncateLWMs
51
import org.apache.derby.impl.store.raw.log.LogCounter;
52
53 import org.apache.derby.iapi.types.SQLChar;
54
55 import org.apache.derby.iapi.reference.Property;
56
57 import org.apache.derby.iapi.services.io.FormatableBitSet;
58
59 import java.io.*;
60 import java.util.Properties JavaDoc;
61
62 /**
63     A protocol unit test for the RawStore interface.
64 */

65
66 public class T_RawStoreFactory extends T_MultiThreadedIterations {
67
68
69     static protected final String JavaDoc REC_001 = "McLaren";
70     static protected final String JavaDoc REC_002 = "Ferrari";
71     static protected final String JavaDoc REC_003 = "Benetton";
72     static protected final String JavaDoc REC_004 = "Prost";
73     static protected final String JavaDoc REC_005 = "Tyrell";
74     static protected final String JavaDoc REC_006 = "012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789";
75     static protected final String JavaDoc REC_007 = "abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyz";
76     static protected final String JavaDoc REC_008 = "z";
77     static protected final String JavaDoc REC_009 = "nanonano";
78     static protected final String JavaDoc REC_010 = "fuzzbutt";
79     static protected final String JavaDoc REC_011 = "mork";
80     static protected final String JavaDoc REC_012 = "orson";
81     static protected final String JavaDoc REC_013 = "mindy";
82     static protected final String JavaDoc REC_014 = "thomas";
83     static protected final String JavaDoc REC_015 = "henry";
84     static protected final String JavaDoc REC_016 = "gordon";
85     static protected final String JavaDoc REC_017 = "mavis";
86     static protected final String JavaDoc REC_018 = "fatcontroller";
87     static protected final String JavaDoc REC_UNDO = "Lotus";
88     static protected final String JavaDoc REC_NULL = "NULL";
89
90     static final FormatableBitSet BS_COL_0 = new FormatableBitSet(1);
91
92     static protected final String JavaDoc SP1 = "savepoint1";
93     static protected final String JavaDoc SP2 = "savepoint2";
94
95     private static final String JavaDoc TEST_ROLLBACK_OFF = "derby.RawStore.RollbackTestOff";
96
97     private static boolean testRollbackProperty;// initialize in start
98
static protected boolean testRollback; // each thread has its own test rollback value
99

100     static protected RawStoreFactory factory;
101     static protected LockFactory lf;
102     static protected ContextService contextService;
103
104     static protected UUIDFactory uuidfactory;
105     protected T_Util t_util;
106     protected int openMode; // mode flags used in all open containers.
107
protected boolean logDataForPurges = true; //used to test non-logged data purges
108

109     public T_RawStoreFactory() {
110         super();
111         BS_COL_0.set(0);
112     }
113
114     /**
115       @exception StandardException cannot startup the context service
116     */

117     public void boot(boolean create, Properties JavaDoc startParams)
118          throws StandardException
119     {
120         super.boot(create, startParams);
121         contextService = ContextService.getFactory();
122     }
123
124     /*
125     ** Methods required by T_Generic
126     */

127
128     protected String JavaDoc getModuleToTestProtocolName() {
129         return RawStoreFactory.MODULE;
130     }
131
132     /**
133         Set up test
134
135         @exception T_Fail Unexpected behaviour from the API
136      */

137     protected void setupTest() throws T_Fail {
138         
139         String JavaDoc rollbackOff = PropertyUtil.getSystemProperty(TEST_ROLLBACK_OFF);
140         testRollback = !Boolean.valueOf(rollbackOff).booleanValue();
141
142         testRollbackProperty = testRollback; // testRollbackProperty never changes
143

144         // don't automatic boot this service if it gets left around
145
if (startParams == null) {
146             startParams = new Properties JavaDoc();
147         }
148         startParams.put(Property.NO_AUTO_BOOT, Boolean.TRUE.toString());
149         // remove the service directory to ensure a clean run
150
startParams.put(Property.DELETE_ON_CREATE, Boolean.TRUE.toString());
151
152         // see if we are testing encryption
153
startParams = T_Util.setEncryptionParam(startParams);
154
155         try {
156
157             factory = (RawStoreFactory) Monitor.createPersistentService(getModuleToTestProtocolName(),
158                                 getTestService(), startParams);
159
160             if (factory == null) {
161                 throw T_Fail.testFailMsg(getModuleToTestProtocolName() + " service not started.");
162             }
163
164             lf = factory.getLockFactory();
165             if (lf == null) {
166                 throw T_Fail.testFailMsg("LockFactory.MODULE not found");
167             }
168
169             uuidfactory = Monitor.getMonitor().getUUIDFactory();
170
171         } catch (StandardException mse) {
172             throw T_Fail.exceptionFail(mse);
173         }
174
175         REPORT("testRollback=" + testRollback);
176
177         return;
178     }
179
180     protected String JavaDoc getTestService()
181     {
182         return "rawStoreTest";
183     }
184
185
186     /**
187      * T_MultiThreadedIteration method
188      *
189      * @exception T_Fail Unexpected behaviour from the API
190      */

191     protected void joinSetupTest() throws T_Fail {
192
193         T_Fail.T_ASSERT(factory != null, "raw store factory not setup ");
194         T_Fail.T_ASSERT(lf != null, "Lock factory not setup ");
195         T_Fail.T_ASSERT(contextService != null, "Context service not setup ");
196
197         testRollback = testRollbackProperty;
198
199     }
200
201     protected T_MultiThreadedIterations newTestObject() {
202         try
203         {
204             Class JavaDoc thisClass = this.getClass();
205             return (T_MultiThreadedIterations)(thisClass.newInstance());
206         }
207         catch (InstantiationException JavaDoc ie)
208         {
209             return new T_RawStoreFactory();
210         }
211         catch (IllegalAccessException JavaDoc iae)
212         {
213             return new T_RawStoreFactory();
214         }
215     }
216
217
218     /**
219       run the test
220
221       @exception T_Fail Unexpected behaviour from the API
222     */

223     protected void runTestSet() throws T_Fail {
224
225         // get a utility helper
226
t_util = new T_Util(factory, lf, contextService);
227
228         ContextManager cm1 = contextService.newContextManager();
229         contextService.setCurrentContextManager(cm1);
230
231         try {
232
233
234             // Run the tests with data not logged for purges.
235
REPORT("Running tests with no data logged for purges");
236             openMode = 0; // logged by default
237
runPurgeWithNoDataLoggesTests();
238
239             // Run the tests in normal logged mode
240
REPORT("Running tests with logging requested");
241             openMode = 0; // logged by default
242
runEachTest();
243
244             
245             // run the tests on temp tables
246
REPORT("Running tests for temp tables");
247             testRollback = false; // obviously, we can't test rollback if we are not logging
248
runTempTests();
249
250             // Run the tests in unlogged mode
251
REPORT("Running tests in unlogged mode");
252             openMode = ContainerHandle.MODE_UNLOGGED | ContainerHandle.MODE_CREATE_UNLOGGED;
253             testRollback = false; // obviously, we can't test rollback if we are not logging
254
runEachTest();
255
256             // if more runs are added here then you probably want to reset testRollback to
257
// its initial value, or add the runs before the unlogged mode.
258

259         } catch (StandardException se) {
260
261             cm1.cleanupOnError(se);
262             throw T_Fail.exceptionFail(se);
263         }
264         finally {
265             contextService.resetCurrentContextManager(cm1);
266         }
267     }
268
269     protected void runEachTest() throws T_Fail, StandardException {
270
271         t_util.setOpenMode(openMode);
272
273         // Transaction tests
274
T000();
275         T001();
276         T002();
277         T003();
278         T004();
279         T005();
280         T006();
281         T007();
282         T008();
283         T009();
284         T010();
285         T011();
286         T012();
287
288         // ContainerHandle tests
289
C010(0);
290         C011();
291         C012(1);
292         C014();
293         C200();
294         C201(0);
295         C201(1);
296
297         // Page tests
298
P001(0);
299         P002(0);
300         P003(0);
301         P004(0);
302         P005(0);
303         P006();
304         P007(0);
305         P008(0);
306         P009(0);
307         P011(0);
308         P012(0);
309         P013();
310         P014();
311         P015();
312         P016();
313         P017();
314         P018();
315         P019(); // test addPage with preallocation turned on
316
P020(); // test createContainer with initialPage set to 10 pages
317
P021(); // test preAllocate
318
P022();
319         P023(0); // overflowThreshold test
320

321         // long row tests
322
P030(0);
323         P031(0);
324         P032(0);
325         P033(0);
326         P034(0);
327
328         P035(0); // long column test
329

330
331
332         //run the following test because they do lot of checks
333
//on rollbacking when contyainer is unlogged nothing is rolled back
334
if((openMode & ContainerHandle.MODE_UNLOGGED) == ContainerHandle.MODE_UNLOGGED)
335         {
336             openMode = 0; //run them as logged for time being
337
t_util.setOpenMode(openMode);
338         }
339
340         // reclaiming space from long column and long rows - temp container
341
// row space is not reclaimed.
342
P036();
343         P037();
344         P038();
345         P039();
346         P040();
347         P041();
348         P042();
349         P043();
350
351
352         P050(); // rollback tests
353
P051();
354         P052();
355         P053();
356         P054();
357         P055(0);
358         P056(0);
359
360
361         P061(); // sparse row test
362

363         P071(); // serializable column test
364

365         // update/update partial tests with long rows
366
P701(0);
367         P702(0);
368         P703(0);
369         P704(0);
370         P705(0);
371
372         P706(0, false);
373         P706(0, true);
374         P707(0);
375         P708(0, false);
376         P708(0, true);
377
378
379         L001(); // large log record test
380

381         // checkpoint test
382
CP001();
383     }
384
385     protected void runTempTests() throws T_Fail, StandardException {
386
387         REPORT("Thread " + threadNumber + " entering temp tests ");
388
389         openMode = 0; // logged by default
390
t_util.setOpenMode(openMode); // logged mode should be overriden for temp tables
391

392         // now tests for temporary tables
393

394         C010(ContainerHandle.TEMPORARY_SEGMENT);
395         C012(ContainerHandle.TEMPORARY_SEGMENT);
396         //P001(ContainerHandle.TEMPORARY_SEGMENT);
397
//P002(ContainerHandle.TEMPORARY_SEGMENT);
398
P003(ContainerHandle.TEMPORARY_SEGMENT);
399         P004(ContainerHandle.TEMPORARY_SEGMENT);
400         P005(ContainerHandle.TEMPORARY_SEGMENT);
401         P011(ContainerHandle.TEMPORARY_SEGMENT);
402         P012(ContainerHandle.TEMPORARY_SEGMENT);
403         P030(ContainerHandle.TEMPORARY_SEGMENT);
404
405         // update/update partial tests with long rows
406
P055(ContainerHandle.TEMPORARY_SEGMENT);
407         P056(ContainerHandle.TEMPORARY_SEGMENT);
408
409         P701(ContainerHandle.TEMPORARY_SEGMENT);
410         P702(ContainerHandle.TEMPORARY_SEGMENT);
411         P703(ContainerHandle.TEMPORARY_SEGMENT);
412         P704(ContainerHandle.TEMPORARY_SEGMENT);
413         P705(ContainerHandle.TEMPORARY_SEGMENT);
414         P706(ContainerHandle.TEMPORARY_SEGMENT, false);
415         P706(ContainerHandle.TEMPORARY_SEGMENT, true);
416         P707(ContainerHandle.TEMPORARY_SEGMENT);
417
418         // tests specific to temp tables
419

420         // checking truncate at commit/rollback works
421
TC001();
422         TC002(ContainerHandle.MODE_TRUNCATE_ON_COMMIT, true);
423         TC002(ContainerHandle.MODE_TRUNCATE_ON_COMMIT, false);
424         TC002(0, false);
425
426         // checking an explict drop works ...
427
TC003(ContainerHandle.MODE_TRUNCATE_ON_COMMIT, true);
428         TC003(ContainerHandle.MODE_TRUNCATE_ON_COMMIT, false);
429         TC003(0, false);
430         TC003(0, true);
431         TC003(ContainerHandle.MODE_DROP_ON_COMMIT, true);
432         TC003(ContainerHandle.MODE_DROP_ON_COMMIT, false);
433
434         // various combinations of opens ...
435
TC004all();
436
437         REPORT("Thread " + threadNumber + " exiting temp tests ");
438     }
439
440
441     protected void runPurgeWithNoDataLoggesTests() throws T_Fail, StandardException {
442
443         REPORT("Thread " + threadNumber + " entering purges with no data logged tests ");
444         logDataForPurges = false;
445         P005(0);
446         P006();
447         P014();
448         P036();
449         P037();
450         P709();
451         P710();
452         P711();
453         REPORT("Thread " + threadNumber + " exiting purge with no data logged tests ");
454         logDataForPurges = true;
455     }
456     /*
457     ** The tests
458     ** Tnnn indicates a test that is mainly testing the Transaction interface
459     ** Cnnn indicates a test that is mainly testing the ContainerHandle interface
460     ** Pnnn indicates a test that is mainly testing the Page interface
461     **
462     ** nnn < 200 tends to indicate purely API tests, ie checking methods
463     ** are callable and return the right value. This includes negative tests.
464     **
465     ** nnn >= 200 tends to indicate more involved tests, ie ones that test the
466     ** methods actually did something.
467
468     */

469
470     /**
471         T000 - ensure a transaction starts out idle.
472
473         @exception T_Fail Unexpected behaviour from the API
474         @exception StandardException Unexpected exception from the implementation
475     */

476     protected void T000() throws T_Fail, StandardException {
477
478         Transaction t1 = t_util.t_startTransaction();
479
480         t1.close();
481
482
483         t1 = t_util.t_startInternalTransaction();
484
485         t1.close();
486
487         t1 = t_util.t_startTransaction();
488         Transaction ti = t_util.t_startInternalTransaction();
489
490         ti.close();
491
492         t1.close();
493
494         PASS("T000");
495     }
496
497     /**
498         T001 - start and commit an empty transaction.
499
500         @exception T_Fail Unexpected behaviour from the API
501         @exception StandardException Unexpected exception from the implementation
502     */

503     protected void T001() throws T_Fail, StandardException {
504
505         Transaction t1 = t_util.t_startTransaction();
506
507         t_util.t_commit(t1);
508
509         t1.close();
510
511         PASS("T001");
512     }
513
514     /**
515         T002 - start and abort an empty transaction.
516
517         @exception T_Fail Unexpected behaviour from the API
518         @exception StandardException Unexpected exception from the implementation
519     */

520     protected void T002() throws T_Fail, StandardException {
521
522         Transaction t1 = t_util.t_startTransaction();
523
524         t_util.t_abort(t1);
525
526         t1.close();
527
528         PASS("T002");
529     }
530
531     /**
532         T003 - start and commit an empty transaction and then ensure
533         that the transaction remains open for another commit.
534
535         @exception T_Fail Unexpected behaviour from the API
536         @exception StandardException Unexpected exception from the implementation
537     */

538     protected void T003() throws T_Fail, StandardException {
539
540         Transaction t1 = t_util.t_startTransaction();
541
542         t_util.t_commit(t1);
543
544         t_util.t_commit(t1);
545         t_util.t_abort(t1);
546
547         t1.close();
548
549         PASS("T003");
550     }
551
552     /**
553         T004 - start and abort an empty transaction and then ensure
554         that the transaction remains open for a commit and another abort.
555
556         @exception T_Fail Unexpected behaviour from the API
557         @exception StandardException Unexpected exception from the implementation
558     */

559     protected void T004() throws T_Fail, StandardException {
560
561         Transaction t1 = t_util.t_startTransaction();
562
563         t_util.t_abort(t1);
564
565         t_util.t_commit(t1);
566
567         t_util.t_abort(t1);
568
569         t1.close();
570
571         PASS("T004");
572     }
573
574
575     /**
576         T005 check transaction identifiers on idle transactions.
577
578         @exception T_Fail Unexpected behaviour from the API
579         @exception StandardException Unexpected exception from the implementation
580
581     */

582     protected void T005() throws T_Fail, StandardException {
583
584         Transaction t1 = t_util.t_startTransaction();
585
586         // local transactions do not have global id's
587
GlobalTransactionId id1 = t1.getGlobalId();
588         if (id1 != null)
589             throw T_Fail.testFailMsg("null not returned from local Transaction.getId()");
590         t1.close();
591
592         byte[] global_id =
593             { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,
594              10, 11, 12, 13, 14, 15, 16, 17, 18, 19,
595              20, 21, 22, 23, 24, 25, 26, 27, 28, 29,
596              30, 31, 32, 33, 34, 35, 36, 37, 38, 39,
597              40, 41, 42, 44, 44, 45, 46, 47, 48, 49,
598              50, 51, 52, 53, 54, 55, 56, 57, 58, 59,
599              60, 61, 62, 63};
600         byte[] branch_id =
601             { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,
602              10, 11, 12, 13, 14, 15, 16, 17, 18, 19,
603              20, 21, 22, 23, 24, 25, 26, 27, 28, 29,
604              30, 31, 32, 33, 34, 35, 36, 37, 38, 39,
605              40, 41, 42, 44, 44, 45, 46, 47, 48, 49,
606              50, 51, 52, 53, 54, 55, 56, 57, 58, 59,
607              60, 61, 62, 63};
608
609         t1 = t_util.t_startGlobalTransaction(42, global_id, branch_id);
610
611         id1 = t1.getGlobalId();
612
613         if (!id1.equals(id1))
614             throw T_Fail.testFailMsg("TransactionId does not compare equal to itself");
615
616         if (!id1.equals(t1.getGlobalId()))
617             throw T_Fail.testFailMsg("TransactionId has changed without any activity on Transaction");
618
619         if (id1.equals(this))
620             throw T_Fail.testFailMsg("TransactionId compared equal to an non-transaction id object");
621
622         t1.close();
623         t1 = null;
624
625         // change the branch_id for the second global xact.
626
branch_id[63] = 82;
627         Transaction t2 =
628             t_util.t_startGlobalTransaction(42, global_id, branch_id);
629
630         GlobalTransactionId id2 = t2.getGlobalId();
631         if (id2 == null)
632             throw T_Fail.testFailMsg("null returned from Transaction.getId()");
633
634         if (id1.equals(id2))
635             throw T_Fail.testFailMsg("TransactionId's returned equal from different transactions");
636         if (id2.equals(id1))
637             throw T_Fail.testFailMsg("TransactionId's returned equal from different transactions");
638
639         t2.close();
640
641         PASS("T005");
642     }
643
644     /**
645         T006 - savepoint basic API testing
646
647         @exception T_Fail Unexpected behaviour from the API
648         @exception StandardException Unexpected exception from the implementation
649     */

650     protected void T006() throws T_Fail, StandardException {
651
652         Transaction t1 = t_util.t_startTransaction();
653
654         // check a random savepoint name is not accepted
655
t_util.t_checkInvalidSavePoint(t1, "sdfjsdfg");
656
657
658         t1.setSavePoint(SP1, null);
659
660         t1.rollbackToSavePoint(SP1, null); // leaves savepoint around
661
t1.rollbackToSavePoint(SP1, null); // therefore this should work
662

663         t1.releaseSavePoint(SP1, null);
664
665         // SP1 should no longer exist
666
t_util.t_checkInvalidSavePoint(t1, SP1);
667
668         // should be able to re-use it ...
669
t1.setSavePoint(SP1, null);
670         t1.rollbackToSavePoint(SP1, null); // leaves savepoint around
671
t1.rollbackToSavePoint(SP1, null); // therefore this should work
672

673         t1.releaseSavePoint(SP1, null);
674         t_util.t_checkInvalidSavePoint(t1, SP1);
675
676         t_util.t_commit(t1);
677         t1.close();
678
679         PASS("T006");
680     }
681
682
683     /**
684         T007 - savepoint nesting testing
685
686         @exception T_Fail Unexpected behaviour from the API
687         @exception StandardException Unexpected exception from the implementation
688     */

689     protected void T007() throws T_Fail, StandardException {
690
691         Transaction t1 = t_util.t_startTransaction();
692         int position = 0;
693
694         /*
695         ** Push two save points and release the first, both should disappear
696         */

697         t1.setSavePoint(SP1, null);
698         t1.setSavePoint(SP2, null);
699
700         position = t1.releaseSavePoint(SP1, null);
701         if (position != 0)
702             throw T_Fail.testFailMsg("Save Point Position in the stack isincorrect:"+
703                                      position);
704
705
706         // SP1 and SP2 should no longer exist
707
t_util.t_checkInvalidSavePoint(t1, SP1);
708         t_util.t_checkInvalidSavePoint(t1, SP2);
709
710         /*
711         ** Push two save points and remove the second, first should remain
712         */

713         t1.setSavePoint(SP1, null);
714         t1.setSavePoint(SP2, null);
715
716         t1.rollbackToSavePoint(SP2, null); // leaves savepoint around
717
position = t1.rollbackToSavePoint(SP2, null); // therefore this should work
718

719         if (position != 2)
720             throw T_Fail.testFailMsg("Save Point Position in the stack isincorrect:"+
721                                      position);
722
723
724
725         position = t1.releaseSavePoint(SP2, null);
726         if (position != 1)
727             throw T_Fail.testFailMsg("Save Point Position in the stack is incorrect:"+
728                                      position);
729
730
731         t_util.t_checkInvalidSavePoint(t1, SP2);
732
733         t1.rollbackToSavePoint(SP1, null); // this is the main test
734

735         t1.releaseSavePoint(SP1, null);
736         t_util.t_checkInvalidSavePoint(t1, SP1);
737
738         /*
739         ** Push two save points and rollback to the first, the second should disappear
740         */

741         t1.setSavePoint(SP1, null);
742         t1.setSavePoint(SP2, null);
743
744         position = t1.rollbackToSavePoint(SP1, null); // leaves SP1, removes SP2
745
if (position != 1)
746             throw T_Fail.testFailMsg("Save Point Position in the stack is incorrect:"+
747                                                  position);
748
749         
750         t_util.t_checkInvalidSavePoint(t1, SP2);
751         t1.rollbackToSavePoint(SP1, null);
752
753         t1.releaseSavePoint(SP1, null);
754
755         t_util.t_commit(t1);
756         t1.close();
757
758         PASS("T007");
759     }
760
761     /**
762         T008 - savepoint testing, ensure save points disappear at commit or abort.
763
764         @exception T_Fail Unexpected behaviour from the API
765         @exception StandardException Unexpected exception from the implementation
766     */

767     protected void T008() throws T_Fail, StandardException {
768
769         Transaction t1 = t_util.t_startTransaction();
770         int position1 = 0;
771         int position2 = 0;
772
773         position1 = t1.setSavePoint(SP1, null);
774         position2 = t1.setSavePoint(SP2, null);
775
776         if (position1 != 1 && position2 != 2)
777             throw T_Fail.testFailMsg("Save Point Position in the Stack seeme to wrong");
778
779         t1.commit();
780
781         t_util.t_checkInvalidSavePoint(t1, SP1);
782         t_util.t_checkInvalidSavePoint(t1, SP2);
783
784         position1 = t1.setSavePoint(SP1, null);
785         position2 = t1.setSavePoint(SP2, null);
786         
787         if (position1 != 1 && position2 != 2)
788             throw T_Fail.testFailMsg("Save Point Position in the Stack seeme to wrong");
789
790         t1.abort();
791         position1 = t1.setSavePoint(SP1, null);
792         position2 = t1.setSavePoint(SP2, null);
793         if (position1 != 1 && position2 != 2)
794             throw T_Fail.testFailMsg("Save Point Position in the Stack seeme to wrong");
795         t1.abort();
796         t_util.t_checkInvalidSavePoint(t1, SP1);
797         t_util.t_checkInvalidSavePoint(t1, SP2);
798
799         t1.close();
800
801         PASS("T008");
802     }
803
804
805     /**
806         T009 - add a container and remove it within the same transaction.
807         @exception T_Fail Unexpected behaviour from the API
808         @exception StandardException Unexpected exception from the implementation
809
810     */

811
812     protected void T009() throws StandardException, T_Fail {
813         Transaction t = t_util.t_startTransaction();
814
815         long cid = t_util.t_addContainer(t, 0, 4096);
816         t_util.t_dropContainer(t, 0, cid);
817
818         ContainerKey id = new ContainerKey(0, cid);
819         ContainerHandle ch = t.openContainer(id, ContainerHandle.MODE_READONLY);
820         if (ch != null)
821             throw T_Fail.testFailMsg("Dropped Container should not open");
822
823         t_util.t_commit(t);
824
825         t.close();
826
827         PASS("T009");
828     }
829
830     /**
831         T010 - add a container with a default size and remove it within the same transaction.
832         @exception T_Fail Unexpected behaviour from the API
833         @exception StandardException Unexpected exception from the implementation
834
835     */

836
837     protected void T010() throws StandardException, T_Fail {
838         Transaction t1 = t_util.t_startTransaction();
839
840         long cid = t_util.t_addContainer(t1, 0);
841
842         t_util.t_dropContainer(t1, 0, cid);
843
844         ContainerKey id = new ContainerKey(0, cid);
845         ContainerHandle ch = t1.openContainer(id, ContainerHandle.MODE_READONLY);
846         if (ch != null)
847             throw T_Fail.testFailMsg("Dropped Container should not open");
848
849         t_util.t_commit(t1);
850
851         t1.close();
852
853         PASS("T010");
854     }
855
856     /**
857         T011 - see that a container remains open over the commit of an open transaction..
858         @exception T_Fail Unexpected behaviour from the API
859         @exception StandardException Unexpected exception from the implementation
860
861     */

862
863     protected void T011() throws StandardException, T_Fail {
864
865         Transaction t = t_util.t_startInternalTransaction();
866
867
868         long cid = t_util.t_addContainer(t, 0);
869
870         ContainerHandle c;
871
872         c = t_util.t_openContainer(t, 0, cid, true);
873
874         t.commit();
875
876         // container should still be open
877
Page page = t_util.t_getPage(c, ContainerHandle.FIRST_PAGE_NUMBER);
878
879         t.commit();
880
881         // page should still be latched
882
if (!page.isLatched())
883             throw T_Fail.testFailMsg("page not latched after commit of internal transaction");
884
885         page.unlatch();
886         c.close();
887
888         t.commit();
889
890         c = t_util.t_openContainer(t, 0, cid, true);
891         page = t_util.t_getPage(c, ContainerHandle.FIRST_PAGE_NUMBER);
892
893         // container and page should be closed
894
t.abort();
895         if (page.isLatched())
896             throw T_Fail.testFailMsg("page latched after abort of internal transaction");
897
898         try {
899             page = t_util.t_getLastPage(c);
900             throw T_Fail.testFailMsg("container open after abort of internal transaction");
901
902         } catch (StandardException te) {
903         }
904
905         t_util.t_dropContainer(t, 0, cid); // cleanup
906

907         t_util.t_commit(t);
908
909         t.close();
910
911         PASS("T011");
912     }
913
914     /**
915         Test Xact.makeRecordHandle()
916
917         @exception T_Fail Unexpected behaviour from the API
918         @exception StandardException Unexpected exception from the implementation
919     */

920     protected void T012() throws StandardException, T_Fail {
921
922         Transaction t = t_util.t_startTransaction();
923
924         long cid = t_util.t_addContainer(t, 0);
925
926         ContainerHandle c = t_util.t_openContainer(t, 0, cid, true);
927         Page page = t_util.t_getPage(c, ContainerHandle.FIRST_PAGE_NUMBER);
928
929         RecordHandle r1, r2;
930         RecordHandle new_r1, new_r2;
931
932         T_RawStoreRow row1 = new T_RawStoreRow(REC_001);
933         T_RawStoreRow row2 = new T_RawStoreRow(REC_002);
934
935         r1 = t_util.t_insertAtSlot(page, 0, row1);
936         new_r1 = c.makeRecordHandle(r1.getPageNumber(), r1.getId());
937
938         t_util.t_checkFetch(page, new_r1, REC_001);
939
940         r2 = t_util.t_insertAtSlot(page, 1, row2);
941
942         if (r2 != null)
943         {
944             new_r2 =
945                 c.makeRecordHandle(r2.getPageNumber(), r2.getId());
946             t_util.t_checkFetch(page, r2, REC_002);
947         }
948
949         t_util.t_commit(t);
950         t.close();
951
952         PASS("T012");
953
954     }
955
956     /**
957         C010 - Create a container within a transaction, commit and the re-open
958         the container twice.
959
960         @exception T_Fail Unexpected behaviour from the API
961         @exception StandardException Unexpected exception from the implementation
962
963     */

964     protected void C010(int segment) throws T_Fail, StandardException {
965
966         Transaction t = t_util.t_startTransaction();
967
968         long cid = t_util.t_addContainer(t, segment);
969
970         t_util.t_commit(t);
971     
972         ContainerHandle c1, c2;
973
974         c1 = t_util.t_openContainer(t, segment, cid, true);
975         c1 = t_util.t_openContainer(t, segment, cid, true);
976         t_util.t_dropContainer(t, segment, cid); // cleanup
977

978
979         t_util.t_commit(t);
980         t.close();
981
982         PASS("C010");
983
984     }
985
986     /**
987         C011 - Create a container withina transaction, commit and the re-open
988         the container in update and non-update mode.
989         
990         @exception T_Fail Unexpected behaviour from the API
991         @exception StandardException Unexpected exception from the implementation
992
993     */

994     protected void C011() throws T_Fail, StandardException {
995
996         Transaction t = t_util.t_startTransaction();
997
998         long cid = t_util.t_addContainer(t, 0);
999
1000        t_util.t_commit(t);
1001    
1002        ContainerHandle c1, c2;
1003
1004        c1 = t_util.t_openContainer(t, 0, cid, false);
1005        c1 = t_util.t_openContainer(t, 0, cid, true);
1006
1007        t_util.t_dropContainer(t, 0, cid); // cleanup
1008

1009        t_util.t_commit(t);
1010        t.close();
1011        PASS("C011");
1012
1013    }
1014
1015    /**
1016        C012 - Drop a container within a transaction, commit, see that it is deleted.
1017        Drop a container within a transaction, rollback and re-open and see
1018        that it is not deleted.
1019
1020        @exception T_Fail Unexpected behaviour from the API
1021        @exception StandardException Standard Derby error policy
1022    */

1023    protected void C012(long segment) throws T_Fail, StandardException {
1024
1025        Transaction t = t_util.t_startTransaction();
1026
1027        long cid = t_util.t_addContainer(t, segment);
1028        t_util.t_commit(t);
1029
1030        ContainerHandle c1 = t_util.t_openContainer(t, segment, cid, true);
1031
1032        t_util.t_dropContainer(t, segment, cid);
1033
1034        if (testRollback)
1035        {
1036            t_util.t_abort(t); // this should rollback the drop
1037
c1 = t_util.t_openContainer(t, segment, cid, true);
1038
1039            REPORT("rollback of drop container tested");
1040
1041            t_util.t_dropContainer(t, segment, cid);
1042        }
1043
1044        t_util.t_commit(t);
1045
1046        ContainerKey id = new ContainerKey(segment, cid);
1047        c1 = t.openContainer(id, (ContainerHandle.MODE_FORUPDATE | openMode)); // this should fail
1048
if (c1 != null)
1049            throw T_Fail.testFailMsg("Deleted Container should fail to open");
1050
1051        t_util.t_commit(t);
1052        t.close();
1053        PASS("C012");
1054    }
1055
1056    /**
1057        C014 - Open a container for locking only.
1058        @exception T_Fail Unexpected behaviour from the API
1059        @exception StandardException Standard Derby error policy
1060    */

1061    protected void C014() throws T_Fail, StandardException {
1062
1063        Transaction t = t_util.t_startTransaction();
1064
1065        ContainerKey id = new ContainerKey(77, 45);
1066        ContainerHandle c = t.openContainer(id,
1067            ContainerHandle.MODE_OPEN_FOR_LOCK_ONLY);
1068
1069        if (c == null)
1070            throw T_Fail.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
1078        RecordHandle rh2 = c.makeRecordHandle(23, 7);
1079        if (rh2 == null)
1080            throw T_Fail.testFailMsg("makeRecordHandle returned null");
1081        c.getLockingPolicy().lockRecordForRead(t, c, rh2, true, false);
1082
1083        RecordHandle rh3 = c.makeRecordHandle(23, 9);
1084        c.getLockingPolicy().lockRecordForWrite(t, rh3, false, true);
1085        if (rh3 == null)
1086            throw T_Fail.testFailMsg("makeRecordHandle returned null");
1087
1088        c.getLockingPolicy().unlockRecordAfterRead(t, c, rh2, false, 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 " + ContainerHandle.FIRST_PAGE_NUMBER + ", is " + lastPage.getPageNumber());
1132
1133        row = new T_RawStoreRow(REC_001);
1134        if (!lastPage.spaceForInsert())
1135            throw T_Fail.testFailMsg("No room for record on page");
1136
1137        rh001 = t_util.t_insert(lastPage, row);
1138        if (rh001 == null)
1139            throw T_Fail.testFailMsg("Failed to insert record");
1140
1141        // see if we can fetch that record
1142
t_util.t_checkFetch(lastPage, rh001, REC_001);
1143
1144        lastPage.unlatch();
1145        lastPage = null;
1146
1147        t_util.t_commit(t1);
1148        c1 = null;
1149
1150
1151        REPORT("read record just inserted.");
1152
1153        c1 = t_util.t_openContainer(t1, 0, cid, false);
1154
1155        lastPage = t_util.t_getLastPage(c1);
1156        if (lastPage == null)
1157            throw T_Fail.testFailMsg("Could get container's last page");
1158
1159        t_util.t_checkFetch(lastPage, rh001, REC_001);
1160        t_util.t_checkFetchFirst(lastPage, REC_001);
1161        t_util.t_checkFetchLast(lastPage, REC_001);
1162
1163        t_util.t_commit(t1);
1164        lastPage = null;
1165        c1 = null;
1166
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 " + ContainerHandle.FIRST_PAGE_NUMBER + ", is " + lastPage.getPageNumber());
1178
1179        row = new T_RawStoreRow(REC_002);
1180        if (!lastPage.spaceForInsert())
1181            throw T_Fail.testFailMsg("No room for record on page");
1182
1183        if (!lastPage.recordExists(rh001, false))
1184            throw T_Fail.testFailMsg("Record 001 has vanished");
1185
1186        //
1187

1188        // RESOLVE: just insert them for now, order is 002,001,003
1189
// 001 is already on the page
1190

1191        rh002 = t_util.t_insertAtSlot(lastPage, 0, row);
1192        row = new T_RawStoreRow(REC_003);
1193        rh003 = t_util.t_insert(lastPage, row);
1194        // Order is 002, 001, 003
1195

1196
1197        lastPage.unlatch();
1198        lastPage = null;
1199
1200        t_util.t_commit(t1);
1201        c1 = null;
1202    
1203        REPORT("checks on all 3 records.");
1204
1205        c1 = t_util.t_openContainer(t1, 0, cid, false);
1206
1207        lastPage = t_util.t_getLastPage(c1);
1208        if (lastPage == null)
1209            throw T_Fail.testFailMsg("Could get container's last page");
1210
1211        // Order is 002, 001, 003
1212
t_util.t_checkFetch(lastPage, rh001, REC_001);
1213        t_util.t_checkFetch(lastPage, rh002, REC_002);
1214        t_util.t_checkFetch(lastPage, rh003, REC_003);
1215
1216
1217        t_util.t_checkFetch(lastPage, lastPage.getRecordHandle(rh001.getId()), REC_001);
1218        t_util.t_checkFetch(lastPage, lastPage.getRecordHandle(rh002.getId()), REC_002);
1219
1220        lastPage.unlatch();
1221        lastPage = null;
1222
1223        t_util.t_commit(t1);
1224
1225        REPORT("start deleting.");
1226
1227        c1 = t_util.t_openContainer(t1, 0, cid, true);
1228
1229        lastPage = t_util.t_getLastPage(c1);
1230        if (lastPage == null)
1231            throw T_Fail.testFailMsg("Could get container's last page");
1232
1233        // Order is 002, 001, 003
1234
t_util.t_checkFetch(lastPage, rh001, REC_001);
1235        t_util.t_checkFetch(lastPage, rh002, REC_002);
1236        t_util.t_checkFetch(lastPage, rh003, REC_003);
1237
1238        lastPage.delete(rh001, (LogicalUndo)null);
1239        if (lastPage.fetch(
1240              rh001, new DataValueDescriptor[0], (FormatableBitSet) null, false) != null)
1241        {
1242            throw T_Fail.testFailMsg("deleted record is still present");
1243        }
1244        // Order is 002, 003
1245
t_util.t_checkFetch(lastPage, rh002, REC_002);
1246        t_util.t_checkFetch(lastPage, rh003, REC_003);
1247
1248        t_util.t_checkFetchNext(lastPage, rh002, REC_003);
1249        t_util.t_checkFetchPrevious(lastPage, rh003, REC_002);
1250
1251        lastPage.delete(rh002, (LogicalUndo)null);
1252        if (lastPage.fetch(
1253              rh002, new DataValueDescriptor[0], (FormatableBitSet) null, false) != null)
1254        {
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(
1281              rh003, new DataValueDescriptor[0], (FormatableBitSet) null, true) == null)
1282        {
1283            throw T_Fail.testFailMsg("fetch for update returned false");
1284        }
1285    
1286        if (!lastPage.update(rh003, urow.getRow(), (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 + ", spareSpace " + 0 + ", minimumRecordSize " + pageSize/2);
1320        long cid = t_util.t_addContainer(t1, 0, pageSize, 0, pageSize/2, false);
1321        
1322        t_util.t_commit(t1);
1323
1324        ContainerHandle c1;
1325        Page lastPage;
1326        RecordHandle rh001, rh002, rh003;
1327        T_RawStoreRow row;
1328    
1329        REPORT("see if the container can be opened again");
1330        c1 = t_util.t_openContainer(t1, 0, cid, false);
1331
1332        c1.close();
1333        t_util.t_commit(t1);
1334
1335        REPORT("insert a record into the container.");
1336
1337        c1 = t_util.t_openContainer(t1, 0, cid, true);
1338
1339        lastPage = t_util.t_getLastPage(c1);
1340        if (lastPage == null)
1341            throw T_Fail.testFailMsg("Couldn't get container's last page");
1342
1343        if (lastPage.getPageNumber() != ContainerHandle.FIRST_PAGE_NUMBER)
1344            throw T_Fail.testFailMsg("Initial page must be " + ContainerHandle.FIRST_PAGE_NUMBER + ", is " + lastPage.getPageNumber());
1345
1346        row = new T_RawStoreRow(REC_001);
1347        if (!lastPage.spaceForInsert())
1348            throw T_Fail.testFailMsg("No room for record on page");
1349
1350        rh001 = t_util.t_insert(lastPage, row);
1351        if (rh001 == null)
1352            throw T_Fail.testFailMsg("Failed to insert record");
1353
1354        // see if we can fetch that record
1355
t_util.t_checkFetch(lastPage, rh001, REC_001);
1356
1357        lastPage.unlatch();
1358        lastPage = null;
1359
1360        t_util.t_commit(t1);
1361        c1 = null;
1362
1363        REPORT("read record just inserted.");
1364
1365        c1 = t_util.t_openContainer(t1, 0, cid, false);
1366
1367        lastPage = t_util.t_getLastPage(c1);
1368        if (lastPage == null)
1369            throw T_Fail.testFailMsg("Couldn't get container's last page");
1370
1371        t_util.t_checkFetch(lastPage, rh001, REC_001);
1372        t_util.t_checkFetchFirst(lastPage, REC_001);
1373        t_util.t_checkFetchLast(lastPage, REC_001);
1374
1375        t_util.t_commit(t1);
1376        lastPage = null;
1377        c1 = null;
1378
1379        // negative testing
1380
REPORT("try inserting 1 more record, but there should be no room on page for it.");
1381
1382        c1 = t_util.t_openContainer(t1, 0, cid, true);
1383
1384        lastPage = t_util.t_getLastPage(c1);
1385        if (lastPage == null)
1386            throw T_Fail.testFailMsg("Couldn't get container's last page");
1387
1388        if (lastPage.getPageNumber() != ContainerHandle.FIRST_PAGE_NUMBER)
1389            throw T_Fail.testFailMsg("Initial page must be " + ContainerHandle.FIRST_PAGE_NUMBER + ", is " + lastPage.getPageNumber());
1390
1391        row = new T_RawStoreRow(REC_002);
1392        if (lastPage.spaceForInsert())
1393        {
1394            throw T_Fail.testFailMsg("Did not get no room for record on page error");
1395        }
1396
1397        if (!lastPage.recordExists(rh001, false))
1398            throw T_Fail.testFailMsg("Record 001 has vanished");
1399
1400        lastPage.unlatch();
1401        lastPage = null;
1402
1403        t_util.t_commit(t1);
1404        c1 = null;
1405
1406        t_util.t_dropContainer(t1, 0, cid); // cleanup
1407
t_util.t_commit(t1);
1408        //t1.close();
1409

1410
1411        //t1 = t_util.t_startTransaction();
1412

1413        REPORT("create container with pageSize " + pageSize + ", spareSpace " + 0 + ", minimumRecordSize " + pageSize);
1414        REPORT("this should set minimumRecordSize to the default 100");
1415        cid = t_util.t_addContainer(t1, 0, pageSize, 0, pageSize, false);
1416        
1417        t_util.t_commit(t1);
1418
1419        REPORT("see if the container can be opened again");
1420        c1 = t_util.t_openContainer(t1, 0, cid, false);
1421
1422        c1.close();
1423        t_util.t_commit(t1);
1424
1425        REPORT("insert a record into the container.");
1426
1427        c1 = t_util.t_openContainer(t1, 0, cid, true);
1428
1429        lastPage = t_util.t_getLastPage(c1);
1430        if (lastPage == null)
1431            throw T_Fail.testFailMsg("Couldn't get container's last page");
1432
1433        if (lastPage.getPageNumber() != ContainerHandle.FIRST_PAGE_NUMBER)
1434            throw T_Fail.testFailMsg("Initial page must be " + ContainerHandle.FIRST_PAGE_NUMBER + ", is " + lastPage.getPageNumber());
1435
1436        row = new T_RawStoreRow(REC_001);
1437        if (!lastPage.spaceForInsert())
1438            throw T_Fail.testFailMsg("No room for record on page");
1439
1440        rh001 = t_util.t_insert(lastPage, row);
1441        if (rh001 == null)
1442            throw T_Fail.testFailMsg("Failed to insert record");
1443
1444        // see if we can fetch that record
1445
t_util.t_checkFetch(lastPage, rh001, REC_001);
1446
1447        lastPage.unlatch();
1448        lastPage = null;
1449
1450        t_util.t_commit(t1);
1451        c1 = null;
1452
1453        REPORT("read record just inserted.");
1454
1455        c1 = t_util.t_openContainer(t1, 0, cid, false);
1456
1457        lastPage = t_util.t_getLastPage(c1);
1458        if (lastPage == null)
1459            throw T_Fail.testFailMsg("Couldn't get container's last page");
1460
1461        t_util.t_checkFetch(lastPage, rh001, REC_001);
1462        t_util.t_checkFetchFirst(lastPage, REC_001);
1463        t_util.t_checkFetchLast(lastPage, REC_001);
1464
1465        t_util.t_commit(t1);
1466        lastPage = null;
1467        c1 = null;
1468
1469        REPORT("insert 2 more records.");
1470
1471        c1 = t_util.t_openContainer(t1, 0, cid, true);
1472
1473        lastPage = t_util.t_getLastPage(c1);
1474        if (lastPage == null)
1475            throw T_Fail.testFailMsg("Could get container's last page");
1476
1477        if (lastPage.getPageNumber() != ContainerHandle.FIRST_PAGE_NUMBER)
1478            throw T_Fail.testFailMsg("Initial page must be " + ContainerHandle.FIRST_PAGE_NUMBER + ", is " + lastPage.getPageNumber());
1479
1480        row = new T_RawStoreRow(REC_002);
1481        if (!lastPage.spaceForInsert())
1482            throw T_Fail.testFailMsg("No room for record on page");
1483
1484        if (!lastPage.recordExists(rh001, false))
1485            throw T_Fail.testFailMsg("Record 001 has vanished");
1486
1487        rh002 = t_util.t_insertAtSlot(lastPage, 0, row);
1488        row = new T_RawStoreRow(REC_003);
1489        rh003 = t_util.t_insert(lastPage, row);
1490
1491        lastPage.unlatch();
1492        lastPage = null;
1493
1494        t_util.t_commit(t1);
1495        c1 = null;
1496    
1497        REPORT("checks on all 3 records.");
1498
1499        c1 = t_util.t_openContainer(t1, 0, cid, false);
1500
1501        lastPage = t_util.t_getLastPage(c1);
1502        if (lastPage == null)
1503            throw T_Fail.testFailMsg("Could get container's last page");
1504
1505        // Order is 002, 001, 003
1506
t_util.t_checkFetch(lastPage, rh001, REC_001);
1507        t_util.t_checkFetch(lastPage, rh002, REC_002);
1508        t_util.t_checkFetch(lastPage, rh003, REC_003);
1509
1510
1511        t_util.t_checkFetch(lastPage, lastPage.getRecordHandle(rh001.getId()), REC_001);
1512        t_util.t_checkFetch(lastPage, lastPage.getRecordHandle(rh002.getId()), REC_002);
1513
1514        lastPage.unlatch();
1515        lastPage = null;
1516
1517        t_util.t_commit(t1);
1518
1519        c1 = null;
1520
1521        // clean ip
1522
t_util.t_dropContainer(t1, 0, cid);
1523        t_util.t_commit(t1);
1524        t1.close();
1525
1526        PASS("C201 - " + whatPage);
1527
1528    }
1529
1530    /**
1531        Page tests
1532     */

1533     /**
1534        Create a container, ensure it has one page with no records. Then test
1535        all the things we can do with an empty page opened read-only in the container.
1536        Then add a new page, ensure it has the correct page number and is empty.
1537        @exception T_Fail Unexpected behaviour from the API
1538        @exception StandardException Unexpected exception from the implementation
1539    */

1540    protected void P001(long segment) throws T_Fail, StandardException {
1541
1542        Transaction t = t_util.t_startTransaction();
1543
1544        long cid = t_util.t_addContainer(t, segment);
1545
1546        t_util.t_commit(t);
1547
1548        // Get the first page & check the record counts are zero
1549
ContainerHandle c = t_util.t_openContainer(t, segment, cid, false);
1550        Page page = t_util.t_getPage(c, ContainerHandle.FIRST_PAGE_NUMBER);
1551
1552        t_util.t_checkEmptyPage(page);
1553
1554        if (Page.FIRST_SLOT_NUMBER != 0)
1555            throw T_Fail.testFailMsg("Page.FIRST_SLOT_NUMBER must be 0, is " + Page.FIRST_SLOT_NUMBER);
1556
1557        page.unlatch();
1558        page = null;
1559
1560        // get the last page and check it is the first page
1561
page = t_util.t_getLastPage(c);
1562
1563        t_util.t_checkPageNumber(page, ContainerHandle.FIRST_PAGE_NUMBER);
1564    
1565        t_util.t_checkEmptyPage(page);
1566
1567        t_util.t_commit(t);
1568
1569        // t_util.t_addPage checks that the page is empty.
1570
c = t_util.t_openContainer(t, segment, cid, true);
1571        page = t_util.t_addPage(c);
1572
1573        t_util.t_checkPageNumber(page, ContainerHandle.FIRST_PAGE_NUMBER + 1);
1574        page.unlatch();
1575
1576        page = t_util.t_addPage(c);
1577        t_util.t_checkPageNumber(page, ContainerHandle.FIRST_PAGE_NUMBER + 2);
1578        page.unlatch();
1579
1580        t_util.t_commit(t);
1581
1582        c = t_util.t_openContainer(t, segment, cid, true);
1583        page = t_util.t_getPage(c, ContainerHandle.FIRST_PAGE_NUMBER);
1584        t_util.t_updateSlotOutOfRange(page, 0);
1585        t_util.t_updateSlotOutOfRange(page, -1);
1586        t_util.t_updateSlotOutOfRange(page, 1);
1587
1588
1589        t_util.t_dropContainer(t, segment, cid); // cleanup
1590
t_util.t_commit(t);
1591
1592        // RESOLVE drop container
1593

1594        t.close();
1595
1596        PASS("P001");
1597    }
1598
1599    /**
1600        Insert rows on the first page until the page is full, then add a page
1601        and repeat the test (for a total of three pages with full rows).
1602        Fetch the rows back by handle and slot methods.
1603
1604        @exception T_Fail Unexpected behaviour from the API
1605        @exception StandardException Unexpected exception from the implementation
1606    */

1607    protected void P002(long segment) throws StandardException, T_Fail {
1608
1609        Transaction t = t_util.t_startTransaction();
1610
1611        long cid = t_util.t_addContainer(t, segment);
1612
1613        ContainerHandle c = t_util.t_openContainer(t, segment, cid, true);
1614        Page page = t_util.t_getPage(c, ContainerHandle.FIRST_PAGE_NUMBER);
1615        t_util.t_checkEmptyPage(page);
1616
1617        RecordHandle rh;
1618        T_RawStoreRow row;
1619        int recordCount[] = {0,0,0};
1620
1621        for (int i = 0; i < 3;) {
1622            row = new T_RawStoreRow(REC_001 + i + "X" + recordCount[i]);
1623
1624            boolean spaceThere = page.spaceForInsert();
1625
1626            rh = t_util.t_insert(page, row);
1627
1628            if (rh != null) {
1629                recordCount[i]++;
1630                if (!spaceThere)
1631                    REPORT("record inserted after spaceForInsert() returned false, count is " + recordCount[i]);
1632            } else {
1633                if (spaceThere)
1634                    REPORT("record insert failed after spaceForInsert() returned true, count is " + recordCount[i]);
1635            }
1636
1637            t_util.t_checkRecordCount(page, recordCount[i], recordCount[i]);
1638
1639            if (rh != null)
1640                continue;
1641
1642            page.unlatch();
1643            page = null;
1644
1645            if (++i < 3) {
1646                page = t_util.t_addPage(c);
1647                t_util.t_checkEmptyPage(page);
1648            }
1649        }
1650        t_util.t_commit(t);
1651
1652        for (int i = 0; i < 3; i++) {
1653            REPORT("RecordCount on page " + i + "=" + recordCount[i]);
1654        }
1655
1656        // now check that we read the same number of records back
1657
// using the handle interface
1658
c = t_util.t_openContainer(t, segment, cid, false);
1659
1660        long pageNumber = ContainerHandle.FIRST_PAGE_NUMBER;
1661        for (int i = 0; i < 3; i++, pageNumber++) {
1662            page = t_util.t_getPage(c, pageNumber);
1663            t_util.t_checkRecordCount(page, recordCount[i], recordCount[i]);
1664            rh = t_util.t_checkFetchFirst(page, REC_001 + i + "X" + 0);
1665            for (int j = 1; j < recordCount[i]; j++)
1666                rh = t_util.t_checkFetchNext(page, rh, REC_001 + i + "X" + j);
1667
1668            try
1669            {
1670                rh = page.fetchFromSlot(
1671                        null,
1672                        page.getSlotNumber(rh) + 1,
1673                        new DataValueDescriptor[0],
1674                        (FetchDescriptor) null,
1675                        false);
1676
1677                throw T_Fail.testFailMsg(
1678                        "reading more rows on page than were written");
1679            }
1680            catch (StandardException se)
1681            {
1682                // expected error.
1683
}
1684
1685            rh = t_util.t_checkFetchLast(page, REC_001 + i + "X" + (recordCount[i] - 1));
1686            for (int j = recordCount[i] - 2; j >= 0; j--)
1687                rh = t_util.t_checkFetchPrevious(page, rh, REC_001 + i + "X" + j);
1688
1689            page.unlatch();
1690            page = null;
1691        }
1692        t_util.t_commit(t);
1693
1694        // now check that we read the same number of records back
1695
// using the slot interface
1696
c = t_util.t_openContainer(t, segment, cid, false);
1697
1698        pageNumber = ContainerHandle.FIRST_PAGE_NUMBER;
1699        for (int i = 0; i < 3; i++, pageNumber++) {
1700            page = t_util.t_getPage(c, pageNumber);
1701        
1702            for (int j = 0; j < recordCount[i]; j++)
1703                t_util.t_checkFetchBySlot(page, j, REC_001 + i + "X" + j,
1704                                        false, false);
1705
1706            t_util.t_readOnlySlotOutOfRange(page, recordCount[i]);
1707
1708            page.unlatch();
1709            page = null;
1710        }
1711
1712        t_util.t_dropContainer(t, segment, cid); // cleanup
1713

1714        t_util.t_commit(t);
1715
1716        t.close();
1717
1718        PASS("P002");
1719    }
1720
1721    /**
1722        Test Page.delete
1723
1724        @exception T_Fail Unexpected behaviour from the API
1725        @exception StandardException Unexpected exception from the implementation
1726
1727        @see Page#delete
1728    */

1729
1730    protected void P003(long segment) throws StandardException, T_Fail {
1731
1732        Transaction t = t_util.t_startTransaction();
1733
1734        long cid = t_util.t_addContainer(t, segment);
1735
1736        ContainerHandle c = t_util.t_openContainer(t, segment, cid, true);
1737        Page page = t_util.t_getPage(c, ContainerHandle.FIRST_PAGE_NUMBER);
1738
1739        RecordHandle r1, r2;
1740
1741        T_RawStoreRow row1 = new T_RawStoreRow(REC_001);
1742        T_RawStoreRow row2 = new T_RawStoreRow(REC_002);
1743
1744        r1 = t_util.t_insertAtSlot(page, 0, row1);
1745        r2 = t_util.t_insertAtSlot(page, 1, row2);
1746
1747        t_util.t_checkFetch(page, r1, REC_001);
1748        if (r2 != null)
1749            t_util.t_checkFetch(page, r2, REC_002);
1750
1751        t_util.t_checkRecordCount(page, 2, r2 == null ? 1 : 2);
1752
1753        // delete the first
1754
if (!page.delete(r1, (LogicalUndo)null))
1755            throw T_Fail.testFailMsg("delete() returned false");
1756
1757        t_util.t_checkRecordCount(page, 2, r2 == null ? 0 : 1);
1758
1759        if (page.delete(r1, (LogicalUndo)null))
1760            throw T_Fail.testFailMsg("delete() returned true on already deleted record");
1761
1762        t_util.t_checkRecordCount(page, 2, r2 == null ? 0 : 1);
1763
1764        if (page.recordExists(r1, false))
1765            throw T_Fail.testFailMsg("recordExists() returned true for deleted record");
1766
1767        // check the other record is still there
1768
if (r2 != null)
1769            t_util.t_checkFetch(page, r2, REC_002);
1770
1771
1772        if (!page.isDeletedAtSlot(0))
1773            throw T_Fail.testFailMsg("isDeletedAtSlot() doesn't represent correct state");
1774
1775        t_util.t_dropContainer(t, segment, cid); // cleanup
1776

1777        t_util.t_commit(t);
1778        t.close();
1779
1780        PASS("P003");
1781    }
1782
1783    /**
1784        Test Page.update
1785
1786        @exception T_Fail Unexpected behaviour from the API
1787        @exception StandardException Unexpected exception from the implementation
1788
1789        @see Page#update
1790    */

1791    protected void P004(long segment) throws StandardException, T_Fail {
1792
1793        Transaction t = t_util.t_startTransaction();
1794
1795        long cid = t_util.t_addContainer(t, segment);
1796
1797        ContainerHandle c = t_util.t_openContainer(t, segment, cid, true);
1798        Page page = t_util.t_getPage(c, ContainerHandle.FIRST_PAGE_NUMBER);
1799
1800        RecordHandle r1, r2;
1801
1802        T_RawStoreRow row1 = new T_RawStoreRow(REC_001);
1803        T_RawStoreRow row2 = new T_RawStoreRow(REC_002);
1804
1805        r1 = t_util.t_insertAtSlot(page, 0, row1);
1806        r2 = t_util.t_insertAtSlot(page, 1, row2);
1807
1808        t_util.t_checkFetch(page, r1, REC_001);
1809        if (r2 != null)
1810            t_util.t_checkFetch(page, r2, REC_002);
1811
1812        row1 = new T_RawStoreRow((String JavaDoc) null);
1813        if (!page.update(r1, row1.getRow(), (FormatableBitSet) null))
1814            throw T_Fail.testFailMsg("update() returned false");
1815
1816        t_util.t_checkFetch(page, r1, (String JavaDoc) null);
1817        if (r2 != null)
1818            t_util.t_checkFetch(page, r2, REC_002);
1819
1820        t_util.t_checkFetch(page, r1, (String JavaDoc) null);
1821        if (r2 != null)
1822            t_util.t_checkFetch(page, r2, REC_002);
1823
1824        row1 = new T_RawStoreRow(REC_003);
1825        if (!page.update(r1, row1.getRow(), (FormatableBitSet) null))
1826            throw T_Fail.testFailMsg("update() returned false");
1827
1828        t_util.t_checkFetch(page, r1, REC_003);
1829        if (r2 != null)
1830            t_util.t_checkFetch(page, r2, REC_002);
1831
1832        // now delete the record we have been updating
1833
if (!page.delete(r1, (LogicalUndo)null))
1834            throw T_Fail.testFailMsg("delete returned false");
1835
1836        row1 = new T_RawStoreRow(REC_004);
1837        if (page.update(r1, row1.getRow(), (FormatableBitSet) null))
1838            throw T_Fail.testFailMsg("update returned true on deleted record");
1839
1840        page.deleteAtSlot(0, false, (LogicalUndo)null);
1841
1842        t_util.t_checkFetch(page, r1, REC_003);
1843
1844        if (!page.update(r1, row1.getRow(), (FormatableBitSet) null))
1845            throw T_Fail.testFailMsg("update returned false");
1846
1847        t_util.t_checkFetch(page, r1, REC_004);
1848
1849
1850        t_util.t_dropContainer(t, segment, cid); // cleanup
1851

1852        t_util.t_commit(t);
1853        t.close();
1854
1855        PASS("P004");
1856
1857    }
1858
1859    /* test repeated insert */
1860    protected void P005(long segment) throws StandardException, T_Fail
1861    {
1862        Transaction t = t_util.t_startTransaction();
1863
1864        long cid = t_util.t_addContainer(t, segment);
1865
1866        ContainerHandle c = t_util.t_openContainer(t, segment, cid, true);
1867        Page page1 = t_util.t_getLastPage(c);
1868    
1869        T_RawStoreRow row0 = new T_RawStoreRow
1870            ("long row xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx long row ");
1871        T_RawStoreRow row1 = new T_RawStoreRow
1872            ("medium row yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy medium row");
1873
1874        t_util.t_insertAtSlot(page1, 0, row0);
1875
1876        int i = 0;
1877        while (page1.spaceForInsert())
1878        {
1879            if (t_util.t_insertAtSlot(page1, 1, row1) == null)
1880                break;
1881            i++;
1882        }
1883
1884        int count1 = page1.recordCount();
1885
1886        Page page2 = t_util.t_addPage(c);
1887        t_util.t_insertAtSlot(page2, 0, row0);
1888
1889        i = 1;
1890        while (page2.spaceForInsert())
1891        {
1892            if (t_util.t_insertAtSlot(page2, i++, row1) == null)
1893                break;
1894        }
1895
1896        int count2 = page2.recordCount();
1897
1898        // now purge them all and start over
1899
page1.purgeAtSlot(1, page1.recordCount()-1, logDataForPurges);
1900        page2.purgeAtSlot(1, page2.recordCount()-1, logDataForPurges);
1901        if (page1.recordCount() != 1)
1902            throw T_Fail.testFailMsg("purge did not clean up page");
1903
1904        if (page2.recordCount() != 1)
1905            throw T_Fail.testFailMsg("purge did not clean up page");
1906
1907        i = 0;
1908        while(page1.spaceForInsert())
1909        {
1910            if (t_util.t_insertAtSlot(page1, 1, row1) == null)
1911                return;
1912            i++;
1913        }
1914
1915        if (page1.recordCount() != count1)
1916            throw T_Fail.testFailMsg("cannot insert back same number of rows we purged");
1917
1918
1919        i = 1;
1920        while(page2.spaceForInsert())
1921        {
1922            if (t_util.t_insertAtSlot(page2, i++, row1) == null)
1923                break;
1924        }
1925
1926        if (page2.recordCount() != count2)
1927            throw T_Fail.testFailMsg("cannot insert back same number of rows we purged");
1928
1929        page1.unlatch();
1930        page2.unlatch();
1931
1932        t_util.t_dropContainer(t, segment, cid); // cleanup
1933

1934        t_util.t_commit(t);
1935        t.close();
1936
1937        PASS("P005");
1938    }
1939
1940    /*
1941        P006
1942
1943        test page time stamp - make sure all operation changes page time stamp
1944    */

1945    protected void P006() throws StandardException, T_Fail
1946    {
1947        Transaction t = t_util.t_startTransaction();
1948        PageTimeStamp ts;
1949
1950        long cid = t_util.t_addContainer(t, 0);
1951        t_util.t_commit(t);
1952
1953        ContainerHandle c = t_util.t_openContainer(t, 0, cid, true);
1954        Page page1 = t_util.t_getLastPage(c);
1955        
1956        ts = page1.currentTimeStamp();
1957        if (ts != null && !page1.equalTimeStamp(ts))
1958            throw T_Fail.testFailMsg("page returns non-null time stamp which is not equal to its current time stamp");
1959
1960        T_RawStoreRow row = new T_RawStoreRow(REC_001);
1961        RecordHandle rh = t_util.t_insert(page1, row);
1962
1963        if (page1.equalTimeStamp(ts))
1964            throw T_Fail.testFailMsg("timestamp on page not changed after insert operation");
1965        page1.setTimeStamp(ts);
1966        if (ts != null && !page1.equalTimeStamp(ts))
1967            throw T_Fail.testFailMsg("page returns non-null time stamp which is not equal to its current time stamp");
1968
1969        // failed update should not change time stamp
1970
t_util.t_updateSlotOutOfRange(page1, 3);
1971        if (ts != null && !page1.equalTimeStamp(ts))
1972            throw T_Fail.testFailMsg("failed pdate should not change time stamp");
1973
1974        T_RawStoreRow row2 = new T_RawStoreRow(REC_002);
1975        page1.update(rh, row2.getRow(), (FormatableBitSet) null);
1976        if (page1.equalTimeStamp(ts))
1977            throw T_Fail.testFailMsg("timestamp on page not changed after update operation");
1978
1979        page1.setTimeStamp(ts);
1980
1981        T_RawStoreRow upd1 = new T_RawStoreRow(REC_003);
1982        page1.update(rh, upd1.getRow(), BS_COL_0);
1983        if (page1.equalTimeStamp(ts))
1984            throw T_Fail.testFailMsg("timestamp on page not changed after update field operation");
1985
1986        page1.setTimeStamp(ts);
1987
1988        page1.delete(rh, (LogicalUndo)null);
1989        if (page1.equalTimeStamp(ts))
1990            throw T_Fail.testFailMsg("timestamp on page not changed after delete operation");
1991
1992        page1.setTimeStamp(ts);
1993        
1994        page1.purgeAtSlot(0, 1, logDataForPurges);
1995        if (page1.equalTimeStamp(ts))
1996            throw T_Fail.testFailMsg("timestamp on page not changed after delete operation");
1997
1998        page1.setTimeStamp(ts);
1999        page1.unlatch();
2000
2001        if (testRollback)
2002        {
2003            t_util.t_abort(t);
2004            c = t_util.t_openContainer(t, 0, cid, true);
2005            page1 = t_util.t_getLastPage(c);
2006
2007            if (page1.equalTimeStamp(ts))
2008                throw T_Fail.testFailMsg("timestamp on page not changed after rollback");
2009
2010            page1.setTimeStamp(ts);
2011        }
2012        
2013        Page page2 = c.addPage();
2014        Page page3 = c.addPage();
2015
2016        page2.setTimeStamp(ts);
2017
2018        if (ts != null)
2019        {
2020            try
2021            {
2022                if (page3.equalTimeStamp(ts))
2023                    throw T_Fail.testFailMsg("timestamp on 2 different pages should not equate");
2024            }
2025            catch (StandardException se)
2026            {
2027                // either throw an exception or return false is OK
2028
}
2029        }
2030
2031
2032        t_util.t_dropContainer(t, 0, cid); // cleanup
2033
t_util.t_commit(t);
2034        t.close();
2035
2036        PASS("P006");
2037
2038    }
2039
2040    /**
2041        P007
2042
2043        this test exercises repeated updates on a 1K page
2044
2045        2 rows (with 1 column) will be inserted into the page.
2046        We expand the row data in slot 0 by 1 byte until the page is completely full,
2047        and overflows the record to an overflow page.
2048
2049        @exception T_Fail Unexpected behaviour from the API
2050        @exception StandardException Unexpected exception from the implementation
2051      */

2052
2053      protected void P007(long segment) throws StandardException, T_Fail {
2054
2055        Transaction t = t_util.t_startTransaction();
2056
2057        // PART 1:
2058
// insert two 1-column rows into the page, expand the first row, until it overflows.
2059
long cid = t_util.t_addContainer(t, segment, 4096, 0, 1, false);
2060
2061        ContainerHandle c = t_util.t_openContainer(t, segment, cid, true);
2062        Page page = t_util.t_getLastPage(c);
2063    
2064        T_RawStoreRow row = new T_RawStoreRow(REC_001); // McLaren
2065
T_RawStoreRow row2 = new T_RawStoreRow(new String JavaDoc(new char[300]));
2066
2067        RecordHandle r1 = t_util.t_insertAtSlot(page, 0, row);
2068        RecordHandle r2 = t_util.t_insertAtSlot(page, 1, row2);
2069
2070        // update the row size 1 byte larger, until the page is full
2071
String JavaDoc rowData = REC_001;
2072        // 900 is an estimated number, because for 1K page,
2073
// if you expand your row by 1 byte 900 times, the row will overflow for sure.
2074
for (int i = 0; i <= 900; i++) {
2075            t_util.t_checkFetch(page, r1, rowData);
2076
2077            rowData = rowData + REC_008; // "z"
2078
row = new T_RawStoreRow(rowData);
2079            page.updateAtSlot(0, row.getRow(), (FormatableBitSet) null);
2080        }
2081
2082        t_util.t_dropContainer(t, segment, cid); // cleanup
2083

2084        // PART 2:
2085
// insert two 2-column rows into the page,
2086
// expand the first row by expanding the first column by 300 bytes,
2087
// and shrinking the second column by 300 bytes. Update should secceed.
2088
cid = t_util.t_addContainer(t, segment, 4096, 0, 1, false);
2089        c = t_util.t_openContainer(t, segment, cid, true);
2090        page = t_util.t_getLastPage(c);
2091        long pid = page.getPageNumber();
2092
2093        row = new T_RawStoreRow(2);
2094        row.setColumn(0, REC_001); // small column
2095
row.setColumn(1, new String JavaDoc (new char[400])); // large column
2096

2097        r1 = t_util.t_insertAtSlot(page, 0, row);
2098        r2 = t_util.t_insertAtSlot(page, 1, row2);
2099
2100        row.setColumn(0, REC_001 + new String JavaDoc (new char[300]));
2101        row.setColumn(1, new String JavaDoc (new char[100]));
2102
2103        page.updateAtSlot(0, row.getRow(), (FormatableBitSet) null);
2104
2105        Page page2 = t_util.t_addPage(c);
2106        long pid2 = page2.getPageNumber();
2107        if (pid2 != (pid + 1))
2108            throw T_Fail.testFailMsg("The update should not have overflowed the record");
2109
2110        // Now, shrink the first column by 300 bytes, and expand the second column by 300 bytes.
2111
// the update should also succeed.
2112
row.setColumn(0, REC_001);
2113        row.setColumn(1, new String JavaDoc (new char[400]));
2114
2115        page.updateAtSlot(0, row.getRow(), (FormatableBitSet) null);
2116
2117        Page page3 = t_util.t_addPage(c);
2118        long pid3 = page3.getPageNumber();
2119        if (pid3 != (pid2 + 1))
2120            throw T_Fail.testFailMsg("The update should not have overflowed the record");
2121
2122        t_util.t_dropContainer(t, segment, cid); // cleanup
2123

2124        t_util.t_commit(t);
2125        t.close();
2126
2127        PASS("P007");
2128
2129    }
2130
2131    /**
2132        P008
2133
2134        this test exercises repeated inserts with small rows on a 1K page
2135
2136        we will insert as many rows as possible into the page. Then we reduce the row by 1 byte at a time,
2137        we will try to insert another smaller row.
2138        This test also tests spaceForInsert().
2139
2140        @exception T_Fail Unexpected behaviour from the API
2141        @exception StandardException Unexpected exception from the implementation
2142      */

2143
2144    protected void P008(long segment) throws StandardException, T_Fail
2145    {
2146        Transaction t = t_util.t_startTransaction();
2147
2148        long cid = t_util.t_addContainer(t, segment, 4096, 0, 1, false);
2149
2150        ContainerHandle c = t_util.t_openContainer(t, segment, cid, true);
2151        Page page1 = t_util.t_getLastPage(c);
2152    
2153        T_RawStoreRow row = new T_RawStoreRow(REC_001); // McLaren
2154

2155        t_util.t_insertAtSlot(page1, 0, row);
2156
2157        int i = 0;
2158        while (page1.spaceForInsert(row.getRow(), (FormatableBitSet) null, 100))
2159        {
2160            // if it says there is enough room for this row, the insert should succeed.
2161
if (t_util.t_insertAtSlot(page1, 1, row) == null)
2162                throw T_Fail.testFailMsg("There is space for this insert. It shouldn't have failed. "
2163                    + "record #" + i);
2164            i++;
2165        }
2166
2167        REPORT(i + " rows inserted.");
2168
2169        // We got out of the while loop because there is no room for the insert.
2170
// So, if the insert succeed, then we have a problem.
2171
if (t_util.t_insertAtSlot(page1, 1, row) != null)
2172            throw T_Fail.testFailMsg("There is no space for this insert. It should have failed.");
2173
2174        // Now, we will try to fill the page with smaller rows.
2175
String JavaDoc[] s = new String JavaDoc[7];
2176        s[6] = "McLare";
2177        s[5] = "McLar";
2178        s[4] = "McLa";
2179        s[3] = "McL";
2180        s[2] = "Mc";
2181        s[1] = "M";
2182        s[0] = null;
2183        // reduce the row by 1 byte
2184
i = 6;
2185        boolean notDone = true;
2186        do
2187        {
2188            row = new T_RawStoreRow(s[i]);
2189            if (page1.spaceForInsert(row.getRow(), (FormatableBitSet) null, 100))
2190            {
2191                // If it says there is enough room for the row, then the insert should succed.
2192
if (t_util.t_insertAtSlot(page1, 1, row) == null)
2193                    throw T_Fail.testFailMsg("There should be space for this insert, row is " + s[i]);
2194                else
2195                    notDone = false;
2196            }
2197            else
2198                i--;
2199        } while ((notDone) && (i >= 0));
2200
2201
2202        page1.unlatch();
2203
2204        t_util.t_dropContainer(t, segment, cid); // cleanup
2205

2206        t_util.t_commit(t);
2207        t.close();
2208
2209        PASS("P008");
2210    }
2211
2212    /**
2213        P009
2214
2215        this test exercises repeated shrinking and expanding of fields using updateFieldBySlot
2216
2217        we will insert as many rows as possible into the page. Then set some of the columns to null,
2218        That should not create more space on the page for inserts, because the extra space become
2219        reservedspace for the row. So, the next insert should fail.
2220
2221        @exception T_Fail Unexpected behaviour from the API
2222        @exception StandardException Unexpected exception from the implementation
2223      */

2224
2225    protected void P009(long segment)
2226         throws StandardException, T_Fail
2227    {
2228        int slot = 0;
2229        int i = 0;
2230        int j = 0;
2231        String JavaDoc field = REC_001;
2232
2233        Transaction t = t_util.t_startTransaction();
2234
2235        long cid = t_util.t_addContainer(t, segment);
2236
2237        // Get the first page & check the record counts are zero
2238
ContainerHandle c = t_util.t_openContainer(t, segment, cid, true);
2239        Page page = t_util.t_getPage(c, ContainerHandle.FIRST_PAGE_NUMBER);
2240
2241        t_util.t_checkEmptyPage(page);
2242
2243        // Create a 13-column row
2244
T_RawStoreRow row = new T_RawStoreRow(13);
2245        row.setColumn(0, (String JavaDoc) null);
2246        row.setColumn(1, REC_001);
2247        row.setColumn(2, REC_002);
2248        row.setColumn(3, REC_003);
2249        row.setColumn(4, REC_004);
2250        row.setColumn(5, REC_005);
2251        row.setColumn(6, REC_006);
2252        row.setColumn(7, REC_007);
2253        row.setColumn(8, (String JavaDoc) null);
2254        row.setColumn(9, (String JavaDoc) null);
2255        row.setColumn(10, REC_007);
2256        row.setColumn(11, (String JavaDoc) null);
2257        row.setColumn(12, REC_006);
2258
2259        // insert the row into the page until the page is full
2260
int numRows = 0;
2261        slot = page.FIRST_SLOT_NUMBER;
2262        while (page.spaceForInsert(row.getRow(), (FormatableBitSet) null, 100)) {
2263            t_util.t_insert(page, row);
2264            numRows++;
2265        }
2266        REPORT(numRows + " rows inserted ");
2267
2268        // update all the fields in the even number rows to null
2269
// set all the fields in the odd number rows to REC_001
2270
DataValueDescriptor col = new SQLChar(); // null
2271
for (i = page.FIRST_SLOT_NUMBER; i < (page.FIRST_SLOT_NUMBER + 2); i++) {
2272
2273            for (slot = i; slot <= (numRows - 1); slot += 2) {
2274
2275                for (j = 0; j <= 12; j++) {
2276                    if (page.updateFieldAtSlot(slot, j, col, null) == null) {
2277
2278                        throw T_Fail.testFailMsg("Failed to update field " + j+ ", in row " + slot);
2279                    }
2280                }
2281            }
2282
2283            col = new SQLChar(REC_001);
2284        }
2285
2286        // fetch all the fields, and see if they are correct
2287
DataValueDescriptor storedColumn = new SQLChar();
2288        field = null;
2289        for (i = page.FIRST_SLOT_NUMBER; i < (page.FIRST_SLOT_NUMBER + 2); i++) {
2290
2291            for (slot = i; slot <= (numRows - 1); slot += 2) {
2292
2293                for (j = 0; j <= 12; j++) {
2294
2295                    t_util.t_checkFetchColFromSlot(page, slot, j, storedColumn, false, field);
2296
2297                }
2298            }
2299
2300            field = REC_001;
2301        }
2302
2303        // Now if we try to insert the old row again, there should still be no room
2304
if (page.spaceForInsert())
2305            throw T_Fail.testFailMsg("Did not get no room for record on page error");
2306
2307        // update the first and last field of every row to REC_006
2308
col = new SQLChar(REC_006);
2309        for (slot = page.FIRST_SLOT_NUMBER; slot <= (numRows - 1); slot++) {
2310            if (page.updateFieldAtSlot(slot, 0, col, null) == null ||
2311                    page.updateFieldAtSlot(slot, 12, col, null) == null) {
2312
2313                throw T_Fail.testFailMsg("Failed to update fields to REC_006 in row " + slot);
2314            }
2315        }
2316        
2317        // update field 5 and 6 of every row to REC_007
2318
col = new SQLChar(REC_007);
2319        for (slot = page.FIRST_SLOT_NUMBER; slot <= (numRows - 1); slot++) {
2320            if (page.updateFieldAtSlot(slot, 5, col, null) == null ||
2321                    page.updateFieldAtSlot(slot, 6, col, null) == null) {
2322
2323                throw T_Fail.testFailMsg("Failed to update fields to REC_007 in row " + slot);
2324            }
2325        }
2326
2327        // fetch all the fields again, and see if they are correct
2328
for (i = page.FIRST_SLOT_NUMBER; i < (page.FIRST_SLOT_NUMBER + 2); i++) {
2329
2330            for (slot = i; slot <= (numRows - 1); slot += 2) {
2331
2332                for (j = 0; j <= 12; j++) {
2333
2334                    switch (j) {
2335                    case 0:
2336                    case 12:
2337                        field = REC_006;
2338                        break;
2339                    case 5:
2340                    case 6:
2341                        field = REC_007;
2342                        break;
2343                    default:
2344                        if ((slot % 2) == 0)
2345                            field = null;
2346                        else
2347                            field = REC_001;
2348                        break;
2349                    }
2350
2351                    t_util.t_checkFetchColFromSlot(page, slot, j, storedColumn, false, field);
2352
2353                }
2354            }
2355        }
2356
2357        // We now try to insert the old row one last time, there should still be no room
2358
if (page.spaceForInsert())
2359            throw T_Fail.testFailMsg("Did not get no room for record on page error");
2360
2361        // now we want to increase row 0 and column 5 one byte at a time, until the page is full
2362
// but, every 5 increases we will reduce the field size by one byte
2363
field = REC_007;
2364        i = 0;
2365        String JavaDoc field_pre = null;
2366        while (true) {
2367            if ((i % 5) != 0) {
2368                field_pre = field;
2369                field += REC_008;
2370            } else {
2371                field = field_pre;
2372            }
2373
2374            if (((i % 10) == 3) || ((i % 10) == 7)) {
2375                page.unlatch();
2376                page = null;
2377
2378                factory.idle();
2379
2380                page = t_util.t_getPage(c, ContainerHandle.FIRST_PAGE_NUMBER);
2381            }
2382
2383            col = new SQLChar(field);
2384
2385            try {
2386                page.updateFieldAtSlot(0, 5, col, null);
2387            } catch (StandardException se) {
2388                // now we have filled the page
2389
if (i < 809) {
2390                    throw T_Fail.testFailMsg("should be able to update Row 0 Column 5 809 times"
2391                        + ", but only updated " + i
2392                        + " times. Note: you maybe getting this error if your page format has changed.");
2393                } else {
2394                    REPORT("Row 0 Column 5 was updated " + i + " times.");
2395                }
2396                break;
2397            }
2398            i++;
2399        }
2400        
2401        // The page is completely full at this point.
2402
// update Row 1 Column 1 from REC_001 to REC_002. They are the same length
2403
page.unlatch();
2404        page = null;
2405        factory.idle();
2406        page = t_util.t_getPage(c, ContainerHandle.FIRST_PAGE_NUMBER);
2407        col = new SQLChar(REC_002);
2408        if (page.updateFieldAtSlot(1, 1, col, null) == null) {
2409            throw T_Fail.testFailMsg("update Row 1 and Column 1 to same length data failed.");
2410        }
2411
2412        REPORT("updated col1 in row 1 to same length");
2413
2414        // now expand update Row 1 Column 1 by one byte. This should fail.
2415
page.unlatch();
2416        page = null;
2417        factory.idle();
2418        page = t_util.t_getPage(c, ContainerHandle.FIRST_PAGE_NUMBER);
2419        field = REC_002 + REC_008;
2420        col = new SQLChar(field);
2421        try {
2422            page.updateFieldAtSlot(1, 1, col, null);
2423            throw T_Fail.testFailMsg("update Row 1 and Column 1 to longer length should have failed.");
2424        } catch (StandardException se) {
2425            ;
2426        }
2427
2428
2429        // clean up
2430
if (segment != ContainerHandle.TEMPORARY_SEGMENT) {
2431            t_util.t_dropContainer(t, segment, cid); // cleanup
2432
}
2433
2434        t_util.t_commit(t);
2435        t.close();
2436
2437        PASS("P009: segment " + segment);
2438        
2439    }
2440
2441
2442
2443    /**
2444        P011
2445
2446        this test exercises insertAtSlot, (LogicalUndo)null
2447
2448        @exception T_Fail Unexpected behaviour from the API
2449        @exception StandardException Unexpected exception from the implementation
2450      */

2451    protected void P011(long segment)
2452         throws StandardException, T_Fail
2453    {
2454        Transaction t = t_util.t_startTransaction();
2455        long cid = t_util.t_addContainer(t, segment);
2456        t_util.t_commit(t);
2457
2458    
2459        // Get the first page
2460
ContainerHandle c = t_util.t_openContainer(t, segment, cid, true);
2461        Page page = t_util.t_getPage(c, ContainerHandle.FIRST_PAGE_NUMBER);
2462
2463        // REPORT("insert 2 records at FIRST_SLOT_NUMBER");
2464
T_RawStoreRow row1 = new T_RawStoreRow(REC_001);
2465        T_RawStoreRow row2 = new T_RawStoreRow(REC_002);
2466        T_RawStoreRow row3 = new T_RawStoreRow(REC_003);
2467        T_RawStoreRow row4 = new T_RawStoreRow(REC_004);
2468
2469        // try inserting at slot -1 and slot 1
2470
try {
2471            RecordHandle r = t_util.t_insertAtSlot(page, -1, row1);
2472            throw T_Fail.testFailMsg("insert at slot -1 succeeded");
2473        } catch (StandardException se) {
2474            // throw if not a statement exception.
2475
if (se.getSeverity() > ExceptionSeverity.STATEMENT_SEVERITY)
2476                throw se;
2477        }
2478
2479        try {
2480            RecordHandle r = t_util.t_insertAtSlot(page, 1, row1);
2481            throw T_Fail.testFailMsg("insert at slot 1 succeeded");
2482        } catch (StandardException se) {
2483            // throw if not a statement exception.
2484
if (se.getSeverity() > ExceptionSeverity.STATEMENT_SEVERITY)
2485                throw se;
2486        }
2487        
2488        RecordHandle r1, r2, r3, r4;
2489        // first insert to a page must suceed
2490
r3 = t_util.t_insertAtSlot(page, Page.FIRST_SLOT_NUMBER, row3);
2491        t_util.t_checkFetch(page, r3, REC_003);
2492        t_util.t_checkFetchBySlot(page, Page.FIRST_SLOT_NUMBER, REC_003,false, false);
2493
2494        r1 = r2 = r4 = null;
2495        r1 = t_util.t_insertAtSlot(page, Page.FIRST_SLOT_NUMBER, row1);
2496
2497        if (r1 != null) {
2498            t_util.t_checkFetch(page, r1, REC_001);
2499            t_util.t_checkFetchBySlot(page, Page.FIRST_SLOT_NUMBER, REC_001,false, false);
2500        } else {
2501            t_util.t_abort(t);
2502            t.close();
2503            REPORT("P011 not run - could not fit 4 rows on page");
2504            return;
2505        }
2506
2507        // REPORT("insert a record at 2nd slot");
2508
r2 = t_util.t_insertAtSlot(page, Page.FIRST_SLOT_NUMBER+1, row2);
2509
2510        if (r2 != null) {
2511            t_util.t_checkFetch(page, r2, REC_002);
2512            t_util.t_checkFetchBySlot(page, Page.FIRST_SLOT_NUMBER+1, REC_002,false, false);
2513        } else {
2514            t_util.t_abort(t);
2515            t.close();
2516            REPORT("P011 not completed - could not fit 4 rows on page");
2517            return;
2518        }
2519
2520        // REPORT("insert a record at the end");
2521
r4 = t_util.t_insertAtSlot(page, 3, row4);
2522        if (r4 != null) {
2523            t_util.t_checkFetch(page, r4, REC_004);
2524            t_util.t_checkFetchBySlot(page, 3, REC_004,false, false);
2525        } else {
2526            t_util.t_abort(t);
2527            t.close();
2528            REPORT("P011 not completed - could not fit 4 rows on page");
2529            return;
2530        }
2531
2532        // REPORT("make sure records are in the correct order");
2533
// order is REC_001 REC_002 REC_003 REC_004
2534

2535
2536        t_util.t_checkFetchFirst(page, REC_001);
2537        t_util.t_checkFetchNext(page, r1, REC_002);
2538        t_util.t_checkFetchNext(page, r2, REC_003);
2539        t_util.t_checkFetchNext(page, r3, REC_004);
2540        t_util.t_checkFetchLast(page, REC_004);
2541
2542        // check the fetch by slot interface
2543
t_util.t_checkFetchBySlot(page, Page.FIRST_SLOT_NUMBER, REC_001,false, true);
2544        t_util.t_checkFetchBySlot(page, Page.FIRST_SLOT_NUMBER+1, REC_002,false, false);
2545        t_util.t_checkFetchBySlot(page, Page.FIRST_SLOT_NUMBER+2, REC_003,false, true);
2546        t_util.t_checkFetchBySlot(page, Page.FIRST_SLOT_NUMBER+3, REC_004,false, false);
2547
2548        // clean up
2549

2550        t_util.t_dropContainer(t, segment, cid); // cleanup
2551

2552        t_util.t_commit(t);
2553        t.close();
2554
2555        PASS("P011");
2556
2557    }
2558
2559    /**
2560      P012
2561
2562      this test exercises updateAtSlot
2563
2564        @exception T_Fail Unexpected behaviour from the API
2565        @exception StandardException Unexpected exception from the implementation
2566    */

2567    protected void P012(long segment)
2568         throws StandardException, T_Fail
2569    {
2570        Transaction t = t_util.t_startTransaction();
2571        long cid = t_util.t_addContainer(t, segment);
2572
2573        ContainerHandle c = t_util.t_openContainer(t, segment, cid, true);
2574        Page page = t_util.t_getPage(c, ContainerHandle.FIRST_PAGE_NUMBER);
2575
2576        // REPORT("insert 3 records");
2577
T_RawStoreRow row1 = new T_RawStoreRow(REC_001);
2578
2579        T_RawStoreRow row2 = new T_RawStoreRow(2);
2580        row2.setColumn(0, (String JavaDoc) null);
2581        row2.setColumn(1, REC_001);
2582
2583        T_RawStoreRow row3 = new T_RawStoreRow(3);
2584        row3.setColumn(0, REC_001);
2585        row3.setColumn(1, REC_002);
2586        row3.setColumn(2, REC_003);
2587
2588        RecordHandle r1, r2, r3;
2589        r1 = t_util.t_insertAtSlot(page, 0, row1);
2590
2591        r2 = r3 = null;
2592        r2 = t_util.t_insertAtSlot(page, 1, row2);
2593    
2594        if (r2 == null) {
2595            REPORT("P012 not completed - cannot insert second row");
2596            return;
2597        }
2598
2599        r3 = t_util.t_insertAtSlot(page, 2, row3);
2600        if (r3 == null) {
2601            REPORT("P012 not completed - cannot insert third row");
2602            return;
2603        }
2604
2605        // check that they are inserted correctly
2606
t_util.t_checkFetch(page, r1, row1);
2607        t_util.t_checkFetch(page, r2, row2);
2608        t_util.t_checkFetch(page, r3, row3);
2609
2610        // REPORT("update that grows the #columns in row");
2611
T_RawStoreRow upd1 = new T_RawStoreRow(2);
2612        upd1.setColumn(0, (String JavaDoc) null);
2613        upd1.setColumn(1, REC_001);
2614
2615        r1 = page.updateAtSlot(0, upd1.getRow(), (FormatableBitSet) null);
2616        t_util.t_checkFetch(page, r1, upd1);
2617        t_util.t_checkFetch(page, r2, row2);
2618        t_util.t_checkFetch(page, r3, row3);
2619
2620        // REPORT("update that shrinks the #columns in row");
2621
T_RawStoreRow upd2 = new T_RawStoreRow(REC_004);
2622
2623        r2 = page.updateAtSlot(1, upd2.getRow(), (FormatableBitSet) null);
2624        t_util.t_checkFetch(page, r1, upd1);
2625        t_util.t_checkFetch(page, r2, upd2);
2626        t_util.t_checkFetch(page, r3, row3);
2627
2628        // REPORT("update same #columns in row");
2629
T_RawStoreRow upd3 = new T_RawStoreRow(3);
2630        upd3.setColumn(0, REC_003);
2631        upd3.setColumn(1, REC_002);
2632        upd3.setColumn(2, REC_001);
2633
2634        r3 = page.updateAtSlot(2, upd3.getRow(), (FormatableBitSet) null);
2635        t_util.t_checkFetch(page, r1, upd1);
2636        t_util.t_checkFetch(page, r2, upd2);
2637        t_util.t_checkFetch(page, r3, upd3);
2638
2639        // clean up
2640

2641        if (segment != ContainerHandle.TEMPORARY_SEGMENT) {
2642            t_util.t_dropContainer(t, segment, cid); // cleanup
2643
}
2644
2645        t_util.t_commit(t);
2646        t.close();
2647
2648        PASS("P012");
2649    }
2650
2651    /**
2652      P013
2653
2654      this test exercises deleteAtSlot and isDeletedAtSlot
2655        @exception T_Fail Unexpected behaviour from the API
2656        @exception StandardException Unexpected exception from the implementation
2657    */

2658    protected void P013()
2659         throws StandardException, T_Fail
2660    {
2661        Transaction t = t_util.t_startTransaction();
2662        long cid = t_util.t_addContainer(t, 0);
2663
2664        t_util.t_commit(t);
2665
2666        ContainerHandle c = t_util.t_openContainer(t, 0, cid, true);
2667        Page page = t_util.t_getPage(c, ContainerHandle.FIRST_PAGE_NUMBER);
2668
2669        // REPORT("insert 2 records");
2670
T_RawStoreRow row1 = new T_RawStoreRow(REC_001);
2671        T_RawStoreRow row2 = new T_RawStoreRow(REC_002);
2672
2673        RecordHandle r1 = t_util.t_insertAtSlot(page, 0, row1);
2674        RecordHandle r2;
2675        r2 = t_util.t_insertAtSlot(page, 1, row2);
2676        if (r2 == null) {
2677            REPORT("P013 not completed - could not fit two rows on a page");
2678            return;
2679        }
2680
2681        t_util.t_checkRecordCount(page, 2, 2);
2682
2683        // REPORT("delete them one by one");
2684
page.deleteAtSlot(0, true, (LogicalUndo)null);
2685
2686        t_util.t_checkRecordCount(page, 2, 1);
2687
2688        if (!page.isDeletedAtSlot(0))
2689            throw T_Fail.testFailMsg("Failed to delete record 0");
2690        if (page.isDeletedAtSlot(1))
2691            throw T_Fail.testFailMsg("Record mistakenly deleted");
2692
2693        page.deleteAtSlot(1, true, (LogicalUndo)null);
2694        t_util.t_checkRecordCount(page, 2, 0);
2695        if (!page.isDeletedAtSlot(1))
2696            throw T_Fail.testFailMsg("Failed to delete record 1");
2697
2698        page.deleteAtSlot(0, false, (LogicalUndo)null);
2699        t_util.t_checkRecordCount(page, 2, 1);
2700        if (page.isDeletedAtSlot(0))
2701            throw T_Fail.testFailMsg("Failed to undelete record 0");
2702        if (!page.isDeletedAtSlot(1))
2703            throw T_Fail.testFailMsg("Record mistakenly undeleted");
2704
2705        page.deleteAtSlot(1, false, (LogicalUndo)null);
2706        t_util.t_checkRecordCount(page, 2, 2);
2707        if (page.isDeletedAtSlot(1))
2708            throw T_Fail.testFailMsg("Failed to undelete record 1");
2709
2710        // try the negative tests
2711
try {
2712            page.deleteAtSlot(0, false, (LogicalUndo)null);
2713            throw T_Fail.testFailMsg("undeleted on undeleted record succeeded");
2714        } catch (StandardException se) {
2715            // throw if not a statement exception.
2716
if (se.getSeverity() > ExceptionSeverity.STATEMENT_SEVERITY)
2717                throw se;
2718        }
2719
2720        page.deleteAtSlot(0, true, (LogicalUndo)null);
2721        try {
2722            page.deleteAtSlot(0, true, (LogicalUndo)null);
2723            throw T_Fail.testFailMsg("deleted on deleted record succeeded");
2724        } catch (StandardException se) {
2725            // throw if not a statement exception.
2726
if (se.getSeverity() > ExceptionSeverity.STATEMENT_SEVERITY)
2727                throw se;
2728        }
2729
2730        t_util.t_checkRecordCount(page, 2, 1);
2731        // clean up
2732
PASS("P013");
2733
2734        t_util.t_dropContainer(t, 0, cid); // cleanup
2735

2736
2737
2738        t_util.t_commit(t);
2739        t.close();
2740
2741        
2742    }
2743
2744    /**
2745      P014
2746
2747      this test exercises purgeAtSlot
2748        @exception T_Fail Unexpected behaviour from the API
2749        @exception StandardException Unexpected exception from the implementation
2750    */

2751    protected void P014()
2752         throws StandardException, T_Fail
2753    {
2754        Transaction t = t_util.t_startTransaction();
2755        long cid = t_util.t_addContainer(t,0);
2756        t_util.t_commit(t);
2757
2758    
2759        ContainerHandle c = t_util.t_openContainer(t, 0, cid, true);
2760        Page page = t_util.t_getPage(c, ContainerHandle.FIRST_PAGE_NUMBER);
2761
2762        // REPORT("insert 5 records");
2763
T_RawStoreRow row0 = new T_RawStoreRow(REC_001);
2764        T_RawStoreRow row1 = new T_RawStoreRow(REC_001);
2765        T_RawStoreRow row2 = new T_RawStoreRow(REC_002);
2766        T_RawStoreRow row3 = new T_RawStoreRow(REC_003);
2767        T_RawStoreRow row4 = new T_RawStoreRow(REC_004);
2768        
2769        RecordHandle r0, r1, r2, r3, r4;
2770        r0 = t_util.t_insertAtSlot(page, 0, row0);
2771        r1 = t_util.t_insertAtSlot(page, 1, row1);
2772        r2 = t_util.t_insertAtSlot(page, 2, row2);
2773        r3 = t_util.t_insertAtSlot(page, 3, row3);
2774        r4 = t_util.t_insertAtSlot(page, 4, row4);
2775
2776        if (r3 != null) page.deleteAtSlot(3, true, (LogicalUndo)null);
2777
2778        // REPORT("commit it");
2779
t_util.t_commit(t);
2780
2781        c = t_util.t_openContainer(t, 0, cid, true);
2782        page = t_util.t_getPage(c, ContainerHandle.FIRST_PAGE_NUMBER);
2783
2784        try
2785        {
2786            page.purgeAtSlot(-1, 1, logDataForPurges);
2787            throw T_Fail.testFailMsg("negative slot number did not cause an exception");
2788        }
2789        catch (StandardException se) {} // expected
2790

2791        try
2792        {
2793            page.purgeAtSlot(4, 4, logDataForPurges);
2794            throw T_Fail.testFailMsg("purging more rows than is on page did not cause an exception");
2795        }
2796        catch (StandardException se) {} // expected
2797

2798        // if not all the rows are there, do minimal test
2799
if (r4 == null)
2800        {
2801            int rcount = page.recordCount();
2802            page.purgeAtSlot(0, 1, logDataForPurges);
2803            if (page.recordCount() != rcount-1)
2804                T_Fail.testFailMsg("failed to purge a record, expect " +
2805                                   (rcount-1) + " got " + page.recordCount());
2806
2807            if (testRollback)
2808            {
2809                t_util.t_abort(t);
2810
2811                c = t_util.t_openContainer(t, 0, cid, true);
2812                page = t_util.t_getPage(c, ContainerHandle.FIRST_PAGE_NUMBER);
2813                if(logDataForPurges)
2814                    t_util.t_checkFetchBySlot(page, 0, REC_001,false, true);
2815                else
2816                    t_util.t_checkFetchBySlot(page, 0, REC_NULL,false, true);
2817                if (page.recordCount() != rcount)
2818                    T_Fail.testFailMsg("failed to rollback purge, expect " +
2819                                   rcount + " got " + page.recordCount());
2820            }
2821            else
2822            {
2823                t_util.t_commit(t);
2824            }
2825            PASS("minimal P014");
2826            return;
2827        }
2828
2829        // REPORT("purge 2 records from middle");
2830
page.purgeAtSlot(1, 2, logDataForPurges);
2831        t_util.t_checkFetchBySlot(page, 0, REC_001,false, true);
2832        t_util.t_checkFetchBySlot(page, 1, REC_003,true, true);
2833        t_util.t_checkFetchBySlot(page, 2, REC_004,false, true);
2834
2835        if (page.recordCount() != 3)
2836            T_Fail.testFailMsg("page expect to have 3 records, recordCount() = " +
2837                               page.recordCount());
2838
2839        // REPORT("purge all records from the page");
2840
page.purgeAtSlot(0, 3, logDataForPurges);
2841        if (page.recordCount() != 0)
2842            T_Fail.testFailMsg("page expect to have 0 records, recordCount() = " +
2843                               page.recordCount());
2844
2845        if (testRollback)
2846        {
2847
2848            REPORT("testing rollback");
2849            t_util.t_abort(t);
2850
2851            c = t_util.t_openContainer(t, 0, cid, true);
2852            page = t_util.t_getPage(c, ContainerHandle.FIRST_PAGE_NUMBER);
2853
2854            if(logDataForPurges){
2855                t_util.t_checkFetchBySlot(page, 0, REC_001,false, true);
2856                t_util.t_checkFetchBySlot(page, 1, REC_001,false, true);
2857                t_util.t_checkFetchBySlot(page, 2, REC_002,false, true);
2858                t_util.t_checkFetchBySlot(page, 3, REC_003,true, true);
2859                t_util.t_checkFetchBySlot(page, 4, REC_004,false, true);
2860            }else
2861            {
2862                t_util.t_checkFetchBySlot(page, 0, REC_NULL,false, true);
2863                t_util.t_checkFetchBySlot(page, 1, REC_NULL,false, true);
2864                t_util.t_checkFetchBySlot(page, 2, REC_NULL,false, true);
2865                t_util.t_checkFetchBySlot(page, 3, REC_NULL,true, true);
2866                t_util.t_checkFetchBySlot(page, 4, REC_NULL,false, true);
2867            }
2868
2869            if (page.recordCount() != 5)
2870                T_Fail.testFailMsg("page expect to have 5 records, recordCount() = " +
2871                                   page.recordCount());
2872
2873            // REPORT("purge 3 records from the end");
2874
page.purgeAtSlot(2, 3, logDataForPurges);
2875            if(logDataForPurges)
2876            {
2877                t_util.t_checkFetchBySlot(page, 0, REC_001,false, true);
2878                t_util.t_checkFetchBySlot(page, 1, REC_001,false, true);
2879            }else
2880            {
2881                t_util.t_checkFetchBySlot(page, 0, REC_NULL,false, true);
2882                t_util.t_checkFetchBySlot(page, 1, REC_NULL,false, true);
2883            }
2884            if (page.recordCount() != 2)
2885                T_Fail.testFailMsg("page expect to have 2 records, recordCount() = " +
2886                                   page.recordCount());
2887
2888            // REPORT("rollback");
2889
t_util.t_abort(t);
2890
2891            c = t_util.t_openContainer(t, 0, cid, true);
2892            page = t_util.t_getPage(c, ContainerHandle.FIRST_PAGE_NUMBER);
2893            if(logDataForPurges){
2894                t_util.t_checkFetchBySlot(page, 0, REC_001,false, true);
2895                t_util.t_checkFetchBySlot(page, 1, REC_001,false, true);
2896                t_util.t_checkFetchBySlot(page, 2, REC_002,false, true);
2897                t_util.t_checkFetchBySlot(page, 3, REC_003,true, true);
2898                t_util.t_checkFetchBySlot(page, 4, REC_004,false, true);
2899            }else
2900            {
2901                t_util.t_checkFetchBySlot(page, 0, REC_NULL,false, true);
2902                t_util.t_checkFetchBySlot(page, 1, REC_NULL,false, true);
2903                t_util.t_checkFetchBySlot(page, 2, REC_NULL,false, true);
2904                t_util.t_checkFetchBySlot(page, 3, REC_NULL,true, true);
2905                t_util.t_checkFetchBySlot(page, 4, REC_NULL,false, true);
2906            }
2907
2908            if (page.recordCount() != 5)
2909                T_Fail.testFailMsg("page expect to have 5 records, recordCount() = " +
2910                                   page.recordCount());
2911
2912            // REPORT("make sure delete record is reconstituted as such");
2913
if (page.isDeletedAtSlot(1))
2914                T_Fail.testFailMsg("rolled back purged undeleted record cause record to be deleted");
2915            if (!page.isDeletedAtSlot(3))
2916                T_Fail.testFailMsg("rolled back purged deleted record cause record to be undeleted");
2917        }
2918        PASS("P014");
2919
2920        t_util.t_dropContainer(t, 0, cid); // cleanup
2921
t_util.t_commit(t);
2922        t.close();
2923    }
2924
2925
2926    /**
2927      P015
2928
2929      this test exercises updateAtSlot
2930
2931        @exception T_Fail Unexpected behaviour from the API
2932        @exception StandardException Unexpected exception from the implementation
2933    */

2934    protected void P015()
2935         throws StandardException, T_Fail
2936    {
2937        Transaction t = t_util.t_startTransaction();
2938        long cid = t_util.t_addContainer(t, 0);
2939
2940        t_util.t_commit(t);
2941
2942
2943        ContainerHandle c = t_util.t_openContainer(t, 0, cid, true);
2944        Page page = t_util.t_getPage(c, ContainerHandle.FIRST_PAGE_NUMBER);
2945
2946        // REPORT("insert 3 records");
2947
T_RawStoreRow row1 = new T_RawStoreRow(REC_001);
2948
2949        T_RawStoreRow row2 = new T_RawStoreRow(2);
2950        row2.setColumn(0, (String JavaDoc) null);
2951        row2.setColumn(1, REC_001);
2952
2953        T_RawStoreRow row3 = new T_RawStoreRow(3);
2954        row3.setColumn(0, REC_001);
2955        row3.setColumn(1, REC_002);
2956        row3.setColumn(2, REC_003);
2957
2958        RecordHandle r1, r2, r3;
2959        r1 = t_util.t_insertAtSlot(page, 0, row1);
2960
2961        r2 = r3 = null;
2962        r2 = t_util.t_insertAtSlot(page, 1, row2);
2963
2964        if (r2 == null) {
2965            REPORT("P015 not completed - cannot insert second row");
2966            return;
2967        }
2968
2969        r3 = t_util.t_insertAtSlot(page, 2, row3);
2970
2971        if (r3 == null) {
2972            REPORT("P015 not completed - cannot insert third row");
2973            return;
2974        }
2975
2976        // check that they are inserted correctly
2977
t_util.t_checkFetch(page, r1, row1);
2978        t_util.t_checkFetch(page, r2, row2);
2979        t_util.t_checkFetch(page, r3, row3);
2980
2981        // now update the middle row with a large value
2982
T_RawStoreRow row2u = new T_RawStoreRow(2);
2983        row2u.setColumn(0, "012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789");
2984        row2u.setColumn(1, "0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789");
2985
2986        page.updateAtSlot(1, row2u.getRow(), (FormatableBitSet) null);
2987        t_util.t_checkFetch(page, r2, row2u);
2988
2989
2990        // now update the field of the first record with a large value
2991
((T_RawStoreRow) row1).setColumn(0, "abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyz");
2992
2993        FormatableBitSet validColumn = new FormatableBitSet(2);
2994
2995        validColumn.clear();
2996        validColumn.set(0);
2997
2998        page.updateAtSlot(0, row1.getRow(), validColumn);
2999
3000        t_util.t_checkFetch(page, r1, row1);
3001
3002        ((T_RawStoreRow) row3).setColumn(1, "XXabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyz");
3003
3004        validColumn.clear();
3005        validColumn.set(1);
3006
3007        page.updateAtSlot(2, row3.getRow(), validColumn);
3008        t_util.t_checkFetch(page, r3, row3);
3009
3010        // clean up
3011
PASS("P015");
3012
3013        t_util.t_dropContainer(t, 0, cid); // cleanup
3014

3015
3016        t_util.t_commit(t);
3017        t.close();
3018
3019    }
3020
3021    /*
3022        P016
3023
3024        this test exercises copyAndPurge
3025        @exception T_Fail Unexpected behaviour from the API
3026        @exception StandardException Unexpected exception from the implementation
3027    */

3028    protected void P016()
3029         throws StandardException, T_Fail
3030    {
3031        Transaction t = t_util.t_startTransaction();
3032        long cid = t_util.t_addContainer(t, 0);
3033        long cid2 = t_util.t_addContainer(t, 0);
3034
3035        t_util.t_commit(t);
3036
3037
3038        ContainerHandle c = t_util.t_openContainer(t, 0, cid, true);
3039
3040        Page page1 = t_util.t_getPage(c, ContainerHandle.FIRST_PAGE_NUMBER);
3041        Page page2 = t_util.t_addPage(c);
3042        long pid1 = page1.getPageNumber();
3043        long pid2 = page2.getPageNumber();
3044
3045        t_util.t_checkEmptyPage(page2);
3046
3047        // first fill up page 1
3048

3049        int i = 0;
3050        int deleted = 0;
3051        RecordHandle rh;
3052
3053        T_RawStoreRow row;
3054
3055        for (i = 0, row = new T_RawStoreRow("row at slot " + i);
3056             page1.spaceForInsert();
3057             i++, row = new T_RawStoreRow("row at slot " + i))
3058        {
3059            rh = t_util.t_insertAtSlot(page1, i, row );
3060            if (rh == null)
3061                break;
3062            
3063            // delete every third row
3064
if ((i % 3) == 1)
3065            {
3066                deleted++;
3067                page1.delete(rh, (LogicalUndo)null);
3068            }
3069        }
3070
3071        int recordCount = i;
3072
3073        // negative testing
3074
// copy into page of different container
3075
ContainerHandle c2 = t_util.t_openContainer(t, 0, cid2, true);
3076        Page wrongPage = t_util.t_getPage(c2, ContainerHandle.FIRST_PAGE_NUMBER);
3077        try
3078        {
3079            page1.copyAndPurge(wrongPage, 0, recordCount, 0);
3080            throw T_Fail.testFailMsg("copying to page from a different contaier should cause and exception");
3081        }
3082        catch (StandardException se) {} // expected
3083

3084        try
3085        {
3086            page1.copyAndPurge(page2, 1, 0, 0);
3087            throw T_Fail.testFailMsg("copying zero rows should cause an exception");
3088        }
3089        catch (StandardException se) {} // expected
3090

3091        try
3092        {
3093            page1.copyAndPurge(page2, 1, recordCount, 0);
3094            throw T_Fail.testFailMsg("copying more rows than page contains should cause an exception");
3095        }
3096        catch (StandardException se) {} // expected
3097

3098        try
3099        {
3100            page1.copyAndPurge(page2, 0, 1, 1);
3101            throw T_Fail.testFailMsg("copying rows to nonexistant slot should cause an exception");
3102        }
3103        catch (StandardException se) {} // expected
3104

3105
3106        // copy the whole page to page2
3107
page1.copyAndPurge(page2, 0, recordCount, 0);
3108
3109        // check
3110
t_util.t_checkEmptyPage(page1);
3111
3112        for (i = 0; i < recordCount; i++)
3113        {
3114            t_util.t_checkFetchBySlot(page2, i, "row at slot " + i,
3115                                    ((i%3) == 1), true);
3116        }
3117        t_util.t_checkRecordCount(page2, recordCount, recordCount-deleted);
3118
3119
3120        t_util.t_commit(t);
3121
3122        if (recordCount > 2)
3123        {
3124            // now copy and purge part of the page
3125
c = t_util.t_openContainer(t, 0, cid, true);
3126            page1 = t_util.t_getPage(c, pid1);
3127            page2 = t_util.t_getPage(c, pid2);
3128
3129
3130            // insert 2 rows into page1
3131
T_RawStoreRow row1 = new T_RawStoreRow(REC_001);
3132            T_RawStoreRow row2 = new T_RawStoreRow(REC_002);
3133            t_util.t_insertAtSlot(page1, 0, row1);
3134            t_util.t_insertAtSlot(page1, 1, row2);
3135
3136            page2.copyAndPurge(page1, 1, recordCount-2, 1);
3137
3138            t_util.t_checkFetchBySlot(page2, 0, "row at slot " + 0,false, true);
3139            
3140            // need to figure out the delete status of the last row on page 2
3141
boolean tdeleted = ((recordCount-1)%3) == 1;
3142            t_util.t_checkFetchBySlot(page2, 1, "row at slot " + (recordCount-1),tdeleted, true);
3143            
3144            if (((recordCount-1) % 3) == 1)
3145                t_util.t_checkRecordCount(page2, 2, 1); // last record on page2 was deleted
3146
else
3147                t_util.t_checkRecordCount(page2, 2, 2); // last record on page2 was not deleted
3148

3149            t_util.t_checkFetchBySlot(page1, 0, REC_001,false, false);
3150            for (i = 1; i < recordCount-1; i++)
3151            {
3152                t_util.t_checkFetchBySlot(page1, i, "row at slot " + i,
3153                                        ((i%3)==1), false);
3154            }
3155            t_util.t_checkFetchBySlot(page1, recordCount-1, REC_002,false, false);
3156            if (((recordCount-1) % 3) == 1)
3157                // one (the last one) of the deleted rows did not get copied over
3158
t_util.t_checkRecordCount(page1, recordCount, recordCount-deleted+1);
3159            else
3160                t_util.t_checkRecordCount(page1, recordCount, recordCount-deleted);
3161
3162            if (testRollback)
3163            {
3164                t_util.t_abort(t);
3165
3166                c = t_util.t_openContainer(t, 0, cid, true);
3167                page1 = t_util.t_getPage(c, pid1);
3168                page2 = t_util.t_getPage(c, pid2);
3169
3170                // the two inserted rows is rolled back by deletion
3171
t_util.t_checkFetchBySlot(page1, 0, REC_001,true, false);
3172                t_util.t_checkFetchBySlot(page1, 1, REC_002,true, false);
3173                t_util.t_checkRecordCount(page1, 2, 0);
3174
3175                for (i = 0; i < recordCount; i++)
3176                {
3177                    t_util.t_checkFetchBySlot(page2, i, "row at slot " + i,
3178                                            ((i%3)==1), true);
3179                }
3180                t_util.t_checkRecordCount(page2, recordCount, recordCount-deleted);
3181
3182                REPORT("tested roll back of copyAndPurge");
3183            }
3184
3185
3186            PASS("P016");
3187        }
3188
3189        t_util.t_dropContainer(t, 0, cid); // cleanup
3190
t_util.t_dropContainer(t, 0, cid2); // cleanup
3191
t_util.t_commit(t);
3192        t.close();
3193    }
3194
3195
3196    /*
3197        P017
3198        this test getInvalidRecordHandle and makeRecordHandle
3199
3200        @exception T_Fail Unexpected behaviour from the API
3201        @exception StandardException Unexpected exception from the implementation
3202    */

3203    protected void P017() throws StandardException, T_Fail
3204    {
3205        Transaction t = t_util.t_startTransaction();
3206        
3207
3208        long cid = t_util.t_addContainer(t, 0);
3209        ContainerHandle c = t_util.t_openContainer(t, 0, cid, true);
3210
3211        Page page1 = t_util.t_getPage(c, ContainerHandle.FIRST_PAGE_NUMBER);
3212        T_RawStoreRow row1 = new T_RawStoreRow(REC_001);
3213
3214        RecordHandle valid = t_util.t_insert(page1, row1);
3215        RecordHandle special = page1.makeRecordHandle(RecordHandle.RECORD_ID_PROTECTION_HANDLE);
3216
3217        RecordHandle[] rhs = new RecordHandle[RecordHandle.FIRST_RECORD_ID];
3218        rhs[0] = page1.getInvalidRecordHandle();
3219        rhs[1] = page1.makeRecordHandle(RecordHandle.RECORD_ID_PROTECTION_HANDLE);
3220        rhs[2] = page1.makeRecordHandle(RecordHandle.DEALLOCATE_PROTECTION_HANDLE);
3221        rhs[3] = page1.makeRecordHandle(RecordHandle.PREVIOUS_KEY_HANDLE);
3222        rhs[4] = page1.makeRecordHandle(RecordHandle.RESERVED4_RECORD_HANDLE);
3223        rhs[5] = page1.makeRecordHandle(RecordHandle.RESERVED5_RECORD_HANDLE);
3224
3225        for (int i = 0; i < RecordHandle.FIRST_RECORD_ID; i++)
3226        {
3227            try
3228            {
3229                page1.recordExists(rhs[i], true);
3230                throw T_Fail.testFailMsg("record exists for invalid record " + rhs[i]);
3231            }
3232            catch (StandardException se)
3233            {
3234                /* expected */
3235            }
3236
3237
3238            try
3239            {
3240                page1.fetch(
3241                    rhs[i], new DataValueDescriptor[0], (FormatableBitSet) null, true);
3242                throw T_Fail.testFailMsg("fetched an invalid record " + rhs[i]);
3243            }
3244            catch (StandardException se)
3245            {
3246                /* expected */
3247            }
3248
3249            try
3250            {
3251                page1.update(rhs[i], row1.getRow(), (FormatableBitSet) null);
3252                throw T_Fail.testFailMsg("updated an invalid record " + rhs[i]);
3253            }
3254            catch (StandardException se)
3255            {
3256                /* expected */
3257            }
3258
3259            try
3260            {
3261                page1.update(rhs[i], row1.getRow(), BS_COL_0);
3262                throw T_Fail.testFailMsg("updated an invalid record field");
3263            }
3264            catch (StandardException se)
3265            {
3266                /* expected */
3267            }
3268
3269            try
3270            {
3271                page1.delete(rhs[i], null);
3272                throw T_Fail.testFailMsg("delete an invalid record " + rhs[i]);
3273            }
3274            catch (StandardException se)
3275            {
3276                /* expected */
3277            }
3278
3279
3280            try
3281            {
3282                page1.fetchNumFields(rhs[i]);
3283                throw T_Fail.testFailMsg("fetch num fields on invalid record " + rhs[i]);
3284            }
3285            catch (StandardException se)
3286            {
3287                /* expected */
3288            }
3289
3290            try
3291            {
3292                page1.getSlotNumber(rhs[i]);
3293                throw T_Fail.testFailMsg("got slot number of invalid record " + rhs[i]);
3294            }
3295            catch (StandardException se)
3296            {
3297                /* expected */
3298            }
3299
3300        }
3301        PASS("P017");
3302
3303        t_util.t_dropContainer(t, 0, cid);
3304        t_util.t_commit(t);
3305        t.close();
3306    }
3307
3308    /*
3309        P018
3310
3311        this test exercises track # 590, test that copyRows successfully
3312        notices that a copy can't be done.
3313
3314        @exception T_Fail Unexpected behaviour from the API
3315        @exception StandardException Unexpected exception from the implementation
3316    */

3317    protected void P018()
3318         throws StandardException, T_Fail
3319    {
3320        Transaction t = t_util.t_startTransaction();
3321
3322        // create container with 0 spare space, 1 minimum record size to easily
3323
// force absolutely full page. Record id's are not reusable.
3324
long cid = t_util.t_addContainer(t, 0, 4096, 0, 1, false);
3325
3326        t_util.t_commit(t);
3327
3328        ContainerHandle c = t_util.t_openContainer(t, 0, cid, true);
3329
3330        Page page1 = t_util.t_getPage(c, ContainerHandle.FIRST_PAGE_NUMBER);
3331        Page page2 = t_util.t_addPage(c);
3332        long pid1 = page1.getPageNumber();
3333        long pid2 = page2.getPageNumber();
3334
3335        t_util.t_checkEmptyPage(page2);
3336
3337        // first fill up page 1
3338

3339        int i = 0;
3340        int deleted = 0;
3341        RecordHandle rh;
3342
3343        T_RawStoreRow row;
3344
3345        // first insert and purge 100 rows, setting the next recid to be
3346
// greater than 64. This will cause the next
3347
// recid to be allocated to be greater than 64, this means
3348
// that new recid's added to the page take 2 bytes rather than 1.
3349
for (i = 0; i < 100; i++)
3350        {
3351            row = new T_RawStoreRow("r" + i);
3352
3353            rh = t_util.t_insertAtSlot(page1, 0, row);
3354
3355            page1.purgeAtSlot(0, 1, logDataForPurges);
3356        }
3357
3358        // fill up another page starting with "small" record id's.
3359
for (i = 0; true; i++)
3360        {
3361            row = new T_RawStoreRow("r" + i);
3362
3363            rh = t_util.t_insertAtSlot(page2, i, row);
3364
3365            if (rh == null)
3366                break;
3367        }
3368
3369        // an attempt to copy all the rows should get an error, because the
3370
// recid's are bigger so all the records will not fit.
3371
try
3372        {
3373            page2.copyAndPurge(page1, 0, page2.recordCount(), 0);
3374
3375            throw T_Fail.testFailMsg(
3376                "copying rows with expanding recids should cause an exception");
3377        }
3378        catch (StandardException se)
3379        {
3380            // expect a out of space error.
3381

3382        }
3383
3384        // cleanup after first part of test.
3385
t_util.t_dropContainer(t, 0, cid);
3386        t_util.t_commit(t);
3387
3388        // Now test that with the reusable record id's that the copy works.
3389

3390        // create container with 0 spare space, 1 minimum record size to easily
3391
// force absolutely full page. This container will allow
3392
// reusable record id's which will mean the copy should succeed.
3393
cid = t_util.t_addContainer(t, 0, 4096, 0, 1, true);
3394
3395        t_util.t_commit(t);
3396
3397        c = t_util.t_openContainer(t, 0, cid, true);
3398
3399        page1 = t_util.t_getPage(c, ContainerHandle.FIRST_PAGE_NUMBER);
3400        page2 = t_util.t_addPage(c);
3401        pid1 = page1.getPageNumber();
3402        pid2 = page2.getPageNumber();
3403
3404        t_util.t_checkEmptyPage(page2);
3405
3406        // first fill up page 1
3407

3408        i = 0;
3409
3410        // first insert and purge 100 rows, setting the next recid to be
3411
// greater than 64. This will cause the next
3412
// recid to be allocated to be greater than 64, this means
3413
// that new recid's added to the page take 2 bytes rather than 1.
3414
for (i = 0; i < 100; i++)
3415        {
3416            row = new T_RawStoreRow("r" + i);
3417
3418            rh = t_util.t_insertAtSlot(page1, 0, row);
3419
3420            page1.purgeAtSlot(0, 1, logDataForPurges);
3421        }
3422
3423        // fill up another page starting with "small" record id's.
3424
for (i = 0; true; i++)
3425        {
3426            row = new T_RawStoreRow("r" + i);
3427
3428            rh = t_util.t_insertAtSlot(page2, i, row);
3429
3430            if (rh == null)
3431                break;
3432        }
3433        long pnum2 = page2.getPageNumber();
3434        int numrows = page2.recordCount();
3435
3436        // an attempt to copy all the rows should get an error,
3437
try
3438        {
3439            // This copy should not succeed.
3440
page2.copyAndPurge(page1, 0, page2.recordCount(), 0);
3441
3442            throw T_Fail.testFailMsg(
3443                "copying rows with expanding recids should cause an exception");
3444        }
3445        catch (StandardException se)
3446        {
3447            // expect a out of space error.
3448
}
3449
3450        // now deallocated this page and get it to go thru a reuse cycle
3451
t_util.t_removePage(c, page1);
3452        t_util.t_commit(t);
3453        
3454        c = t_util.t_openContainer(t, 0, cid, true);
3455        page1 = t_util.t_addPage(c);
3456        int tries = 0;
3457        while(page1.getPageNumber() != ContainerHandle.FIRST_PAGE_NUMBER)
3458        {
3459            REPORT("getting page " + page1.getPageNumber());
3460
3461            t_util.t_commit(t);
3462
3463            if (tries++ > 100)
3464                throw T_Fail.testFailMsg("failed to get back first page after "
3465                                         + tries + " tries");
3466            c = t_util.t_openContainer(t, 0, cid, true);
3467            page1 = t_util.t_addPage(c);
3468        }
3469        page2 = t_util.t_getPage(c, pnum2);
3470
3471
3472        t_util.t_checkRecordCount(page2, numrows, numrows);
3473        t_util.t_checkEmptyPage(page1);
3474
3475        // now the attempt to copy all the rows should succeed
3476
try
3477        {
3478            page2.copyAndPurge(page1, 0, page2.recordCount(), 0);
3479        }
3480        catch (StandardException se)
3481        {
3482            throw T_Fail.testFailMsg(
3483                "copying rows with non-expanding recids should not cause an exception");
3484        }
3485
3486        PASS("P018");
3487
3488        t_util.t_dropContainer(t, 0, cid); // cleanup
3489
t_util.t_commit(t);
3490        t.close();
3491    }
3492
3493    /**
3494        Test bulk load and preallocation
3495        @exception T_Fail Unexpected behaviour from the API
3496        @exception StandardException Unexpected exception from the implementation
3497    */

3498    protected void P019() throws StandardException, T_Fail
3499    {
3500        Transaction t = t_util.t_startTransaction();
3501
3502        long cid = t_util.t_addContainer(t, 0, 4096, 0, 1, false);
3503        t_util.t_commit(t);
3504
3505        ContainerHandle c = t_util.t_openContainer(t, 0, cid, true);
3506
3507        // add page for bulk load
3508
Page p1 = c.addPage(ContainerHandle.ADD_PAGE_BULK);
3509        long pnum1 = p1.getPageNumber();
3510        p1.unlatch();
3511
3512        // since the interface does not guarentee that anything special will
3513
// actually happen, can't really test that. Just make sure that
3514
// everything else works
3515
Page p2 = c.addPage();
3516        long pnum2 = p2.getPageNumber();
3517        p2.unlatch();
3518
3519        Page p3 = c.addPage(ContainerHandle.ADD_PAGE_BULK);
3520        long pnum3 = p3.getPageNumber();
3521        p3.unlatch();
3522
3523        Page p = c.getFirstPage(); // this is the first page that came with the
3524
// container when it was created
3525

3526        try
3527        {
3528            long pnum0 = p.getPageNumber();
3529            p.unlatch();
3530            p = c.getNextPage(pnum0);
3531            if (p.getPageNumber() != pnum1)
3532                throw T_Fail.testFailMsg("expected pagenum " + pnum1 + " got " + p.getPageNumber());
3533            p.unlatch();
3534            p = null;
3535
3536            p = c.getNextPage(pnum1);
3537            if (p.getPageNumber() != pnum2)
3538                throw T_Fail.testFailMsg("expected pagenum " + pnum2 + " got " + p.getPageNumber());
3539            p.unlatch();
3540            p = null;
3541
3542            p = c.getNextPage(pnum2);
3543            if (p.getPageNumber() != pnum3)
3544                throw T_Fail.testFailMsg("expected pagenum " + pnum3 + " got " + p.getPageNumber());
3545            p.unlatch();
3546            p = null;
3547
3548            p = c.getNextPage(pnum3);
3549            if (p != null)
3550                throw T_Fail.testFailMsg("expected null page after " + pnum3 +
3551                                         " got " + p.getPageNumber());
3552
3553            // make sure rollback is unaffected
3554
if (testRollback)
3555            {
3556                t_util.t_abort(t);
3557                c = t_util.t_openContainer(t, 0, cid, true);
3558                p = t_util.t_getPage(c, pnum0);
3559                t_util.t_checkEmptyPage(p);
3560                p.unlatch();
3561                p = null;
3562            
3563                p = t_util.t_getPage(c, pnum1);
3564                t_util.t_checkEmptyPage(p);
3565                p.unlatch();
3566                p = null;
3567
3568                p = t_util.t_getPage(c, pnum2);
3569                t_util.t_checkEmptyPage(p);
3570                p.unlatch();
3571                p = null;
3572
3573                p = t_util.t_getPage(c, pnum3);
3574                t_util.t_checkEmptyPage(p);
3575                p.unlatch();
3576                p = null;
3577
3578                p = t_util.t_getLastPage(c);
3579                if (p.getPageNumber() != pnum3)
3580                    throw T_Fail.testFailMsg("expect last page to be " + pnum3
3581                                             + " got " + p.getPageNumber());
3582                p.unlatch();
3583                p = null;
3584            }
3585
3586            t_util.t_dropContainer(t, 0, cid); // cleanup
3587

3588        }
3589        finally
3590        {
3591            if (p != null)
3592                p.unlatch();
3593            p = null;
3594            t_util.t_commit(t);
3595            t.close();
3596        }
3597        PASS("P019 - container " + cid);
3598
3599    }
3600
3601    /**
3602        Test create container with initial page set to 100 pages
3603        @exception T_Fail Unexpected behaviour from the API
3604        @exception StandardException Unexpected exception from the implementation
3605    */

3606    protected void P020() throws StandardException, T_Fail
3607    {
3608        Transaction t = t_util.t_startTransaction();
3609        Properties JavaDoc tableProperties = new Properties JavaDoc();
3610        tableProperties.put(Property.PAGE_SIZE_PARAMETER, Integer.toString(4096));
3611        tableProperties.put(RawStoreFactory.CONTAINER_INITIAL_PAGES, Integer.toString(100));
3612
3613        long cid = t_util.t_addContainer(t, 0, tableProperties);
3614        if (cid < 0)
3615            throw T_Fail.testFailMsg("addContainer");
3616
3617        ContainerHandle c = t_util.t_openContainer(t, 0, cid, true);
3618
3619        Page p1 = c.getFirstPage();
3620        if (p1.getPageNumber() != ContainerHandle.FIRST_PAGE_NUMBER)
3621            throw T_Fail.testFailMsg("expect first page to have FIRST_PAGE_NUMBER");
3622        p1.unlatch();
3623
3624        if (c.getNextPage(ContainerHandle.FIRST_PAGE_NUMBER) != null)
3625            throw T_Fail.testFailMsg("expect to have only 1 page allocated");
3626
3627        t_util.t_dropContainer(t, 0, cid); // cleanup
3628
t_util.t_commit(t);
3629        t.close();
3630        PASS("P020 - container " + cid);
3631    }
3632
3633    /**
3634        Test preAllocate
3635        @exception T_Fail Unexpected behaviour from the API
3636        @exception StandardException Unexpected exception from the implementation
3637    */

3638    protected void P021() throws StandardException, T_Fail
3639    {
3640        Transaction t = t_util.t_startTransaction();
3641        long cid = t_util.t_addContainer(t, 0, 4096);
3642        ContainerHandle c = t_util.t_openContainer(t, 0, cid, true);
3643
3644        // now preallocate 10 pages
3645
c.preAllocate(10);
3646
3647        Page p1 = c.getFirstPage();
3648        if (p1.getPageNumber() != ContainerHandle.FIRST_PAGE_NUMBER)
3649            throw T_Fail.testFailMsg("expect first page to have FIRST_PAGE_NUMBER");
3650        p1.unlatch();
3651
3652        if (c.getNextPage(ContainerHandle.FIRST_PAGE_NUMBER) != null)
3653            throw T_Fail.testFailMsg("expect to have only 1 page allocated");
3654
3655        t_util.t_dropContainer(t, 0, cid); // cleanup
3656
t_util.t_commit(t);
3657        t.close();
3658        PASS("P021 - container " + cid);
3659    }
3660
3661    /**
3662        Test minimumRecordSize: this is to make sure that logRow and storeRecord
3663        are consistent with each other when it comes to reserve space.
3664
3665        @exception T_Fail Unexpected behaviour from the API
3666        @exception StandardException Unexpected exception from the implementation
3667    */

3668    protected void P022()
3669         throws StandardException, T_Fail
3670    {
3671        Transaction t = t_util.t_startTransaction();
3672
3673        // create container with 4096 page size, 0 spare space, 9 minimum record size
3674
long cid = t_util.t_addContainer(t, 0, 4096, 0, 9, false);
3675
3676        t_util.t_commit(t);
3677
3678        ContainerHandle c = t_util.t_openContainer(t, 0, cid, true);
3679
3680        Page page1 = t_util.t_getPage(c, ContainerHandle.FIRST_PAGE_NUMBER);
3681
3682        RecordHandle rh;
3683        T_RawStoreRow row;
3684
3685        // insert records to fill the page.
3686
for (int i = 0; i < 60; i++) {
3687            row = new T_RawStoreRow("r" + i);
3688            rh = t_util.t_insertAtSlot(page1, 0, row);
3689        }
3690
3691        // cleanup after first part of test.
3692
t_util.t_dropContainer(t, 0, cid); // cleanup
3693
t_util.t_commit(t);
3694        t.close();
3695        PASS("P022");
3696    }
3697        
3698    /**
3699        Test overflowThreshold: this is to make sure that logRow and storeRecord
3700        are consistent with each other when it comes to reserve space.
3701
3702        @exception T_Fail Unexpected behaviour from the API
3703        @exception StandardException Unexpected exception from the implementation
3704    */

3705    protected void P023(int segment) throws StandardException, T_Fail {
3706
3707        Transaction t = t_util.t_startTransaction();
3708        // create a container with 1K page, 0 spareSpace, and 0 minimumRecordSize
3709
long cid = t_util.t_addContainer(t, segment, 4096, 0, 0, false);
3710        t_util.t_commit(t);
3711
3712        ContainerHandle c = t_util.t_openContainer(t, segment, cid, true);
3713        Page page = t_util.t_getPage(c, ContainerHandle.FIRST_PAGE_NUMBER);
3714        int overflowThreshold = 50;
3715
3716        t_util.t_checkEmptyPage(page);
3717
3718        // use default insert, not allowing overflow
3719
int insertFlag = Page.INSERT_INITIAL | Page.INSERT_DEFAULT;
3720
3721        // test 1:
3722
// create a row that's under the threshold
3723
T_RawStoreRow r1 = new T_RawStoreRow(1);
3724        r1.setColumn(0, 200, REC_001);
3725        // insert the row twice, should fit on 1 page
3726
RecordHandle rh1 = t_util.t_insertAtSlot(page, 0, r1, (byte) insertFlag, overflowThreshold);
3727        if (rh1 == null)
3728            throw T_Fail.testFailMsg("insert of first long row failed.");
3729        RecordHandle rh2 = t_util.t_insertAtSlot(page, 1, r1, (byte) insertFlag, overflowThreshold);
3730        if (rh2 == null)
3731            throw T_Fail.testFailMsg("insert of second long row failed.");
3732        t_util.t_checkFetch(page, rh1, r1);
3733        t_util.t_checkFetch(page, rh2, r1);
3734        page.unlatch();
3735        page = null;
3736        REPORT("test 1: 2 rows under threshold inserted...");
3737
3738        // test 2:
3739
// get a new page
3740
page = t_util.t_addPage(c);
3741        // create a row that's over the threshold
3742
T_RawStoreRow r2 = new T_RawStoreRow(1);
3743        r2.setColumn(0, 2000, REC_001);
3744        // insert the row twice, should fail both inserts
3745
rh1 = t_util.t_insertAtSlot(page, 0, r2, (byte) insertFlag, overflowThreshold);
3746        if (rh1 != null)
3747        {
3748            throw T_Fail.testFailMsg("insert of 1st over threshold row should failed.");
3749        }
3750        rh2 = t_util.t_insertAtSlot(page, 0, r2, (byte) insertFlag, overflowThreshold);
3751        if (rh2 != null)
3752            throw T_Fail.testFailMsg("insert of 2nd over threshold row should failed.");
3753        page.unlatch();
3754        page = null;
3755        REPORT("test 2: 2 rows over threshold not inserted...");
3756
3757        // test 3:
3758
// get a new page
3759
page = t_util.t_addPage(c);
3760        // create a row with 2 columns, each column is under the threshold,
3761
// and the row is also under the threshold
3762
T_RawStoreRow r3 = new T_RawStoreRow(2);
3763        // create a row that's under the threshold
3764
r3.setColumn(0, 400, REC_001);
3765        r3.setColumn(1, 400, REC_001);
3766        // insert the row twice, should fit on 1 page
3767
rh1 = t_util.t_insertAtSlot(page, 0, r3, (byte) insertFlag, overflowThreshold);
3768        if (rh1 == null)
3769            throw T_Fail.testFailMsg("insert of 1st 2-column row failed.");
3770        rh2 = t_util.t_insertAtSlot(page, 1, r3, (byte) insertFlag, overflowThreshold);
3771        if (rh2 == null)
3772            throw T_Fail.testFailMsg("insert of 2nd 2-column row failed.");
3773        page.unlatch();
3774        page = null;
3775        REPORT("test 3: 2 rows with 2 columns under the threshold inserted...");
3776
3777        // test 4:
3778
// get a new page
3779
page = t_util.t_addPage(c);
3780        // create a row with 2 columns, each column is under the threshold,
3781
// but the row is over the threshold
3782
T_RawStoreRow r4 = new T_RawStoreRow(2);
3783        // create a row that's under the threshold
3784
r4.setColumn(0, 800, REC_001);
3785        r4.setColumn(1, 800, REC_001);
3786        // insert the row twice, should fit on 1 page
3787
rh1 = t_util.t_insertAtSlot(page, 0, r4, (byte) insertFlag, overflowThreshold);
3788        if (rh1 != null)
3789        {
3790            SanityManager.DEBUG_PRINT("bug", "page = " + page);
3791            throw T_Fail.testFailMsg("insert of 1st 2-column row (OT) should failed.");
3792        }
3793        rh2 = t_util.t_insertAtSlot(page, 0, r4, (byte) insertFlag, overflowThreshold);
3794        if (rh2 != null)
3795            throw T_Fail.testFailMsg("insert of 2nd 2-column row (OT) should failed.");
3796        page.unlatch();
3797        page = null;
3798        REPORT("test 4: 2 rows with 2 columns over the threshold not inserted...");
3799
3800        // cleanup after first part of test.
3801
t_util.t_dropContainer(t, segment, cid); // cleanup
3802
t_util.t_commit(t);
3803        t.close();
3804        PASS("P023");
3805    }
3806        
3807    /**
3808        Insert small rows and update them so that they overflow a page.
3809
3810        @exception T_Fail Unexpected behaviour from the API
3811        @exception StandardException Unexpected exception from the implementation
3812    */

3813    protected void P030(long segment) throws StandardException, T_Fail {
3814
3815        Transaction t = t_util.t_startTransaction();
3816
3817        long cid = t_util.t_addContainer(t, segment, 4096);
3818
3819        ContainerHandle c = t_util.t_openContainer(t, segment, cid, true);
3820        Page page = t_util.t_getPage(c, ContainerHandle.FIRST_PAGE_NUMBER);
3821        t_util.t_checkEmptyPage(page);
3822
3823        T_RawStoreRow r0 = new T_RawStoreRow(0);
3824        T_RawStoreRow r1 = new T_RawStoreRow((String JavaDoc) null);
3825        T_RawStoreRow r2 = new T_RawStoreRow("0123456789");
3826
3827        t_util.t_insertAtSlot(page, 0, r0);
3828        t_util.t_insertAtSlot(page, 1, r1);
3829        t_util.t_insertAtSlot(page, 2, r2);
3830
3831        t_util.t_checkRecordCount(page, 3, 3);
3832        page.unlatch();
3833        page = null;
3834
3835        // check there is only one page
3836
if (c.getNextPage(ContainerHandle.FIRST_PAGE_NUMBER) != null)
3837            throw T_Fail.testFailMsg("an extra page has appeared in the container");
3838        t_util.t_commit(t);
3839
3840        //
3841
// Update the row at slot 1 so that it fills most of the page
3842
//
3843
c = t_util.t_openContainer(t, segment, cid, true);
3844        page = t_util.t_getPage(c, ContainerHandle.FIRST_PAGE_NUMBER);
3845
3846        t_util.t_checkStringLengthFetch(page, 1, -1);
3847        t_util.t_checkStringLengthFetch(page, 2, 10);
3848
3849        t_util.t_checkFieldCount(page, 0, 0);
3850        t_util.t_checkFieldCount(page, 1, 1);
3851        t_util.t_checkFieldCount(page, 2, 1);
3852
3853        T_RawStoreRow r1u = new T_RawStoreRow(String.valueOf(new char[1937]));
3854        page.updateAtSlot(1, r1u.getRow(), (FormatableBitSet) null);
3855        t_util.t_checkStringLengthFetch(page, 1, 1937); // on page 1
3856
t_util.t_checkStringLengthFetch(page, 2, 10); // on page 1
3857
t_util.t_checkFieldCount(page, 0, 0);
3858        t_util.t_checkFieldCount(page, 1, 1);
3859        t_util.t_checkFieldCount(page, 2, 1);
3860        page.unlatch();
3861        // check there is only one page
3862
if (c.getNextPage(ContainerHandle.FIRST_PAGE_NUMBER) != null)
3863            throw T_Fail.testFailMsg("an extra page has appeared in the container");
3864        t_util.t_commit(t);
3865
3866        //
3867
// Update the row at slot 2 so that it overflows
3868
//
3869
c = t_util.t_openContainer(t, segment, cid, true);
3870        T_RawStoreRow r2u = new T_RawStoreRow(String.valueOf(new char[1099])); // stored length is twice string lenght + 2
3871
page = t_util.t_getPage(c, ContainerHandle.FIRST_PAGE_NUMBER);
3872        page.updateAtSlot(2, r2u.getRow(), (FormatableBitSet) null);
3873        t_util.t_checkStringLengthFetch(page, 1, 1937); // on page 1
3874
t_util.t_checkStringLengthFetch(page, 2, 1099); // on first overflow page
3875
t_util.t_checkFieldCount(page, 0, 0);
3876        t_util.t_checkFieldCount(page, 1, 1);
3877        t_util.t_checkFieldCount(page, 2, 1);
3878        page.unlatch();
3879        // check there is only one page
3880
if (c.getNextPage(ContainerHandle.FIRST_PAGE_NUMBER) != null)
3881            throw T_Fail.testFailMsg("an extra page has appeared in the container");
3882        t_util.t_commit(t);
3883
3884        c = t_util.t_openContainer(t, segment, cid, true);
3885        page = t_util.t_getPage(c, ContainerHandle.FIRST_PAGE_NUMBER);
3886        t_util.t_checkStringLengthFetch(page, 1, 1937); // on page 1
3887
t_util.t_checkStringLengthFetch(page, 2, 1099); // on first overflow page
3888
t_util.t_checkFieldCount(page, 0, 0);
3889        t_util.t_checkFieldCount(page, 1, 1);
3890        t_util.t_checkFieldCount(page, 2, 1);
3891        // check there is only one page
3892
if (c.getNextPage(ContainerHandle.FIRST_PAGE_NUMBER) != null)
3893            throw T_Fail.testFailMsg("an extra page has appeared in the container");
3894        t_util.t_commit(t);
3895
3896        //
3897
// Update the row at slot 0 so that it overflows onto the same page as the first
3898
// overflow.
3899
//
3900
c = t_util.t_openContainer(t, segment, cid, true);
3901        page = t_util.t_getPage(c, ContainerHandle.FIRST_PAGE_NUMBER);
3902        T_RawStoreRow r0u = new T_RawStoreRow(String.valueOf(new char[423]));
3903        page.updateAtSlot(0, r0u.getRow(), (FormatableBitSet) null);
3904        t_util.t_checkStringLengthFetch(page, 0, 423); // on first overflow page
3905
t_util.t_checkStringLengthFetch(page, 1, 1937); // on page 1
3906
t_util.t_checkStringLengthFetch(page, 2, 1099); // on first overflow page
3907
t_util.t_checkFieldCount(page, 0, 1);
3908        t_util.t_checkFieldCount(page, 1, 1);
3909        t_util.t_checkFieldCount(page, 2, 1);
3910        page.unlatch();
3911        // check there is only one page
3912
if (c.getNextPage(ContainerHandle.FIRST_PAGE_NUMBER) != null)
3913            throw T_Fail.testFailMsg("an extra page has appeared in the container");
3914
3915        t_util.t_commit(t);
3916
3917        //
3918
// Update the row at slot 0 that has already been overflowed
3919
// but keeping it on the same page
3920
//
3921
c = t_util.t_openContainer(t, segment, cid, true);
3922        page = t_util.t_getPage(c, ContainerHandle.FIRST_PAGE_NUMBER);
3923        r0u = new T_RawStoreRow(String.valueOf(new char[399]));
3924        page.updateAtSlot(0, r0u.getRow(), (FormatableBitSet) null);
3925        t_util.t_checkStringLengthFetch(page, 0, 399); // on first overflow page
3926
t_util.t_checkStringLengthFetch(page, 1, 1937); // on page 1
3927
t_util.t_checkStringLengthFetch(page, 2, 1099); // on first overflow page
3928
t_util.t_checkFieldCount(page, 0, 1);
3929        t_util.t_checkFieldCount(page, 1, 1);
3930        t_util.t_checkFieldCount(page, 2, 1);
3931        page.unlatch();
3932        // check there is only one page
3933
if (c.getNextPage(ContainerHandle.FIRST_PAGE_NUMBER) != null)
3934            throw T_Fail.testFailMsg("an extra page has appeared in the container");
3935
3936        //
3937
// Update the row at slot 0 that has already been overflowed
3938
// but moving it to a new page
3939
//
3940
c = t_util.t_openContainer(t, segment, cid, true);
3941        page = t_util.t_getPage(c, ContainerHandle.FIRST_PAGE_NUMBER);
3942        r0u = new T_RawStoreRow(String.valueOf(new char[1400]));
3943        page.updateAtSlot(0, r0u.getRow(), (FormatableBitSet) null);
3944        t_util.t_checkStringLengthFetch(page, 0, 1400); // on second overflow page
3945
t_util.t_checkStringLengthFetch(page, 1, 1937); // on page 1
3946
t_util.t_checkStringLengthFetch(page, 2, 1099); // on first overflow page
3947
t_util.t_checkFieldCount(page, 0, 1);
3948        t_util.t_checkFieldCount(page, 1, 1);
3949        t_util.t_checkFieldCount(page, 2, 1);
3950        page.unlatch();
3951        // check there is only one page
3952
if (c.getNextPage(ContainerHandle.FIRST_PAGE_NUMBER) != null)
3953            throw T_Fail.testFailMsg("an extra page has appeared in the container");
3954
3955        if (segment != ContainerHandle.TEMPORARY_SEGMENT) {
3956            t_util.t_dropContainer(t, segment, cid); // cleanup
3957
}
3958
3959        t_util.t_commit(t);
3960
3961        t.close();
3962
3963        PASS("P030: segment = " + segment);
3964    }
3965
3966    /**
3967        Insert 4-column long rows into 1K pages, each column is less than a page.
3968
3969        @exception T_Fail Unexpected behaviour from the API
3970        @exception StandardException Unexpected exception from the implementation
3971    */

3972    protected void P031(long segment) throws StandardException, T_Fail {
3973
3974        Transaction t = t_util.t_startTransaction();
3975
3976        long cid = t_util.t_addContainer(t, segment, 4096);
3977
3978        ContainerHandle c = t_util.t_openContainer(t, segment, cid, true);
3979        Page page = t_util.t_getPage(c, ContainerHandle.FIRST_PAGE_NUMBER);
3980        t_util.t_checkEmptyPage(page);
3981
3982        T_RawStoreRow r0 = new T_RawStoreRow(4);
3983        r0.setColumn(0, 256, REC_001);
3984        r0.setColumn(1, 256, REC_002);
3985        r0.setColumn(2, 256, REC_003);
3986        r0.setColumn(3, 256, REC_004);
3987
3988        int insertFlag = Page.INSERT_INITIAL;
3989        insertFlag |= Page.INSERT_OVERFLOW;
3990
3991        RecordHandle rh0 = null;
3992        try {
3993            rh0 = t_util.t_insertAtSlot(page, 0, r0, (byte) insertFlag);
3994        } catch (StandardException se) {
3995            throw T_Fail.testFailMsg("insert of long row failed.");
3996        }
3997
3998        if (rh0 == null)
3999            throw T_Fail.testFailMsg("insert of first long row failed.");
4000        else {
4001            REPORT("about to check fetch...");
4002            DataValueDescriptor column = new SQLChar();
4003            t_util.t_checkFetchColFromSlot(page, page.FIRST_SLOT_NUMBER, 0, column, false, REC_001, 256);
4004            t_util.t_checkFetchColFromSlot(page, page.FIRST_SLOT_NUMBER, 1, column, false, REC_002, 256);
4005            t_util.t_checkFetchColFromSlot(page, page.FIRST_SLOT_NUMBER, 2, column, false, REC_003, 256);
4006            t_util.t_checkFetchColFromSlot(page, page.FIRST_SLOT_NUMBER, 3, column, false, REC_004, 256);
4007        }
4008
4009        page.unlatch();
4010
4011        if (segment != ContainerHandle.TEMPORARY_SEGMENT) {
4012            t_util.t_dropContainer(t, segment, cid); // cleanup
4013
}
4014
4015        t_util.t_commit(t);
4016
4017        t.close();
4018
4019        PASS("P031: segment = " + segment);
4020    }
4021
4022    /**
4023        Insert 60-column long rows into 1K pages, each column is less than a page.
4024
4025        @exception T_Fail Unexpected behaviour from the API
4026        @exception StandardException Unexpected exception from the implementation
4027    */

4028    protected void P032(long segment) throws StandardException, T_Fail {
4029
4030        Transaction t = t_util.t_startTransaction();
4031
4032        long cid = t_util.t_addContainer(t, segment, 4096);
4033
4034        ContainerHandle c = t_util.t_openContainer(t, segment, cid, true);
4035        Page page = t_util.t_getPage(c, ContainerHandle.FIRST_PAGE_NUMBER);
4036        t_util.t_checkEmptyPage(page);
4037
4038        int insertFlag = Page.INSERT_INITIAL;
4039        insertFlag |= Page.INSERT_OVERFLOW;
4040
4041        T_RawStoreRow r0 = new T_RawStoreRow(60);
4042        for (int i = 0; i < 60; i++) {
4043            r0.setColumn(i, 1200, REC_001);
4044        }
4045
4046        RecordHandle rh0 = null;
4047        try {
4048            rh0 = t_util.t_insertAtSlot(page, 0, r0, (byte) insertFlag);
4049        } catch (StandardException se) {
4050            throw T_Fail.testFailMsg("insert of first long row failed.");
4051        }
4052
4053        if (rh0 == null)
4054            throw T_Fail.testFailMsg("insert of a 60-column (300 bytes per column) row failed.");
4055        else {
4056            REPORT("about to check fetch the first long row inserted...");
4057            DataValueDescriptor column = new SQLChar();
4058            for (int i = 0; i < 60; i++) {
4059                t_util.t_checkFetchColFromSlot(page, page.FIRST_SLOT_NUMBER, i, column, false, REC_001, 1200);
4060            }
4061        }
4062
4063        // create a new row with 60 columns, and each column has REC_001 = "McLaren"
4064
for (int i = 0; i < 60; i++) {
4065            r0.setColumn(i, REC_001);
4066        }
4067
4068        RecordHandle rh1 = null;
4069        try {
4070            rh1 = t_util.t_insertAtSlot(page, 1, r0, (byte) insertFlag);
4071        } catch (StandardException se) {
4072            throw T_Fail.testFailMsg("insert of second long row failed.");
4073        }
4074
4075        if (rh1 == null) {
4076            throw T_Fail.testFailMsg("insert of a 60-column (~10 bytes per column) row failed.");
4077        } else {
4078            REPORT("about to check fetch the second long row inserted ...");
4079            DataValueDescriptor column = new SQLChar();
4080            for (int i = 0; i < 60; i++) {
4081                t_util.t_checkFetchColFromSlot(page, 1, i, column, false, REC_001);
4082            }
4083        }
4084
4085        page.unlatch();
4086
4087        if (segment != ContainerHandle.TEMPORARY_SEGMENT) {
4088            t_util.t_dropContainer(t, segment, cid); // cleanup
4089
}
4090
4091        t_util.t_commit(t);
4092
4093        t.close();
4094
4095        PASS("P032: segment = " + segment);
4096    }
4097
4098    /**
4099        Insert 100-column long rows into 1K pages, each column is less than a page.
4100
4101        @exception T_Fail Unexpected behaviour from the API
4102        @exception StandardException Unexpected exception from the implementation
4103    */

4104    protected void P033(long segment) throws StandardException, T_Fail {
4105
4106        Transaction t = t_util.t_startTransaction();
4107
4108        long cid = t_util.t_addContainer(t, segment, 4096);
4109
4110        ContainerHandle c = t_util.t_openContainer(t, segment, cid, true);
4111        Page page = t_util.t_getPage(c, ContainerHandle.FIRST_PAGE_NUMBER);
4112        try
4113        {
4114            t_util.t_checkEmptyPage(page);
4115
4116            T_RawStoreRow r0 = new T_RawStoreRow(100);
4117            for (int i = 0; i < 100; i++) {
4118                r0.setColumn(i, REC_007);
4119            }
4120
4121            int insertFlag = Page.INSERT_INITIAL | Page.INSERT_OVERFLOW;
4122
4123            RecordHandle rh0 = null;
4124            try {
4125                rh0 = t_util.t_insertAtSlot(page, 0, r0, (byte) insertFlag);
4126            } catch (StandardException se) {
4127                throw T_Fail.testFailMsg("insert of long row failed.");
4128            }
4129
4130            if (rh0 == null)
4131                throw T_Fail.testFailMsg("insert of first long row failed.");
4132            else {
4133                REPORT("about to check fetch...");
4134                DataValueDescriptor column = new SQLChar();
4135                for (int i = 0; i < 100; i++) {
4136                    t_util.t_checkFetchColFromSlot(page, page.FIRST_SLOT_NUMBER, i, column, false, REC_007);
4137                }
4138            }
4139
4140            page.unlatch();
4141            page = null;
4142            if (segment != ContainerHandle.TEMPORARY_SEGMENT) {
4143                t_util.t_dropContainer(t, segment, cid); // cleanup
4144
}
4145
4146        }
4147        finally
4148        {
4149            if (page != null)
4150                page.unlatch();
4151            t_util.t_commit(t);
4152            t.close();
4153        }
4154
4155        PASS("P033: segment = " + segment);
4156    }
4157
4158    /**
4159        Insert 401 column long row with many small columns in the beginning,
4160        and one large column at the end into 4K pages.
4161
4162        @exception T_Fail Unexpected behaviour from the API
4163        @exception StandardException Unexpected exception from the implementation
4164    */

4165    protected void P034(long segment) throws StandardException, T_Fail {
4166
4167        Transaction t = t_util.t_startTransaction();
4168
4169        long cid = t_util.t_addContainer(t, segment, 4096);
4170
4171        ContainerHandle c = t_util.t_openContainer(t, segment, cid, true);
4172        Page page = t_util.t_getPage(c, ContainerHandle.FIRST_PAGE_NUMBER);
4173        try
4174        {
4175            t_util.t_checkEmptyPage(page);
4176
4177            int insertFlag = Page.INSERT_INITIAL | Page.INSERT_OVERFLOW;
4178
4179            T_RawStoreRow r1 = new T_RawStoreRow(401);
4180            for (int i = 0; i < 400; i++)
4181                r1.setColumn(i, REC_001);
4182            r1.setColumn(400, 1500, REC_001);
4183            RecordHandle rh = t_util.t_insertAtSlot(page, 0, r1, (byte) insertFlag);
4184            t_util.t_checkFetch(page, rh, r1);
4185            page.unlatch();
4186            page = null;
4187            if (segment != ContainerHandle.TEMPORARY_SEGMENT) {
4188                t_util.t_dropContainer(t, segment, cid); // cleanup
4189
}
4190
4191        }
4192        finally
4193        {
4194            if (page != null)
4195                page.unlatch();
4196
4197            t_util.t_commit(t);
4198            t.close();
4199        }
4200
4201        PASS("P034: segment = " + segment);
4202    }
4203
4204    /**
4205        Insert a single long column long row into a 1K page.
4206
4207        @exception T_Fail Unexpected behaviour from the API
4208        @exception StandardException Unexpected exception from the implementation
4209    */

4210    protected void P035(long segment) throws StandardException, T_Fail {
4211
4212        Transaction t = t_util.t_startTransaction();
4213
4214        long cid = t_util.t_addContainer(t, segment, 4096);
4215
4216        ContainerHandle c = t_util.t_openContainer(t, segment, cid, true);
4217        Page page = t_util.t_getPage(c, ContainerHandle.FIRST_PAGE_NUMBER);
4218        try
4219        {
4220            t_util.t_checkEmptyPage(page);
4221
4222            int insertFlag = Page.INSERT_INITIAL | Page.INSERT_OVERFLOW;
4223
4224            T_RawStoreRow r1 = new T_RawStoreRow(1);
4225            // insert a long column
4226
r1.setColumn(0, 500, REC_001);
4227            RecordHandle rh1 = t_util.t_insertAtSlot(page, 0, r1, (byte) insertFlag);
4228            t_util.t_checkFetch(page, rh1, r1);
4229            REPORT("row 1 inserted...");
4230
4231            // insert a 6 column row, every other column is long
4232
T_RawStoreRow r2 = new T_RawStoreRow(6);
4233            r2.setColumn(0, 400, REC_001); // this takes 800 bytes
4234
r2.setColumn(1, 500, REC_002); // this takes 1000 bytes
4235
r2.setColumn(2, 400, REC_001);
4236            r2.setColumn(3, 500, REC_002);
4237            r2.setColumn(4, 400, REC_001);
4238            r2.setColumn(5, 500, REC_002);
4239            RecordHandle rh2 = t_util.t_insertAtSlot(page, 0, r2, (byte) insertFlag);
4240            t_util.t_checkFetch(page, rh2, r2);
4241            REPORT("row 2 inserted...");
4242
4243            // insert a long column
4244
r1.setColumn(0, 1500, REC_001);
4245            RecordHandle rh3 = t_util.t_insertAtSlot(page, 0, r1, (byte) insertFlag);
4246            if (rh3 != null)
4247                throw T_Fail.testFailMsg("expect the 3rd row to not fit on page");
4248
4249            page.unlatch();
4250            page = null;
4251
4252            if (segment != ContainerHandle.TEMPORARY_SEGMENT) {
4253                t_util.t_dropContainer(t, segment, cid); // cleanup
4254
}
4255
4256        }
4257        finally
4258        {
4259            if (page != null)
4260                page.unlatch();
4261
4262            t_util.t_commit(t);
4263            t.close();
4264        }
4265
4266
4267        PASS("P035: segment = " + segment);
4268    }
4269
4270    /**
4271        Test space reclaimation - purging of a long row gets back all
4272        the row pieces.
4273
4274        @exception T_Fail Unexpected behaviour from the API
4275        @exception StandardException Unexpected exception from the implementation
4276     */

4277    protected void P036() throws StandardException, T_Fail
4278    {
4279        long segment = 0;
4280        Transaction t = t_util.t_startTransaction();
4281        long cid = t_util.t_addContainer(t, segment, 4096);
4282
4283        ContainerHandle c = t_util.t_openContainer(t, segment, cid, true);
4284        Page page = t_util.t_getPage(c, ContainerHandle.FIRST_PAGE_NUMBER);
4285        try
4286        {
4287            t_util.t_checkEmptyPage(page);
4288
4289            int insertFlag = Page.INSERT_INITIAL | Page.INSERT_OVERFLOW;
4290
4291            // insert a row with 400 columns from 200 to 400 bytes each and make it
4292
// sprawl across many pages.
4293
T_RawStoreRow r1 = new T_RawStoreRow(400);
4294            for (int i = 0; i < 400; i++)
4295                r1.setColumn(i, 100+i, REC_001);
4296
4297            RecordHandle rh1 = t_util.t_insertAtSlot(page, 0, r1, (byte)insertFlag);
4298            t_util.t_checkFetch(page, rh1, r1);
4299
4300            Page nextPage = t_util.t_addPage(c);
4301            long nextPageNumber = nextPage.getPageNumber();
4302            // deallocate it
4303
t_util.t_removePage(c, nextPage);
4304
4305            REPORT("P036 - Nextpage is " + nextPageNumber);
4306            page.unlatch();
4307            page = null;
4308            t_util.t_commit(t);
4309
4310            // See what the next page is.
4311
c = t_util.t_openContainer(t, segment, cid, true);
4312
4313            // Now purge that first row.
4314
page = t_util.t_getPage(c, ContainerHandle.FIRST_PAGE_NUMBER);
4315
4316            t_util.t_checkRecordCount(page, 1, 1);
4317            page.purgeAtSlot(0, 1, logDataForPurges);
4318
4319            t_util.t_checkEmptyPage(page);
4320            page.unlatch();
4321            page = null;
4322            t_util.t_commit(t);
4323
4324            // give some time for post commit to finish
4325
t_util.t_wait(10); // wait 10 milliseconds.
4326

4327            // reinsert r1, it should use no extra page than last time.
4328
c = t_util.t_openContainer(t, segment, cid, true);
4329            page = t_util.t_getPage(c, ContainerHandle.FIRST_PAGE_NUMBER);
4330
4331            RecordHandle rh2 = t_util.t_insertAtSlot(page, 0, r1, (byte)insertFlag);
4332            t_util.t_checkFetch(page, rh2, r1);
4333            page.unlatch();
4334            page = null;
4335
4336            // now verify that it used up no more page than last time
4337
nextPage = t_util.t_addPage(c);
4338            long checkNextPageNumber = nextPage.getPageNumber();
4339            nextPage.unlatch();
4340
4341            if (nextPageNumber != checkNextPageNumber)
4342                throw T_Fail.testFailMsg("fail to reuse row pieces expect next page=" +
4343                    nextPageNumber + " but got " + checkNextPageNumber );
4344
4345
4346            t_util.t_commit(t);
4347
4348            // Purge them and roll them back via savepoint. These should not
4349
// be reclaimed.
4350
c = t_util.t_openContainer(t, segment, cid, true);
4351            t.setSavePoint(SP1, null);
4352            page = t_util.t_getPage(c, ContainerHandle.FIRST_PAGE_NUMBER);
4353            t_util.t_checkRecordCount(page, 1, 1);
4354            page.purgeAtSlot(0, 1, logDataForPurges);
4355            page.unlatch();
4356            page = null;
4357
4358            // make sure we cannot get our hands on a page that is freed up by
4359
// the purge
4360
Page testPage = t_util.t_addPage(c);
4361            T_RawStoreRow testRow = new T_RawStoreRow(REC_001);
4362            t_util.t_insert(testPage, testRow);
4363            testPage.unlatch();
4364
4365            t.rollbackToSavePoint(SP1, null);
4366
4367            testPage = t_util.t_addPage(c);
4368            t_util.t_insert(testPage, testRow);
4369            testPage.unlatch();
4370
4371            t_util.t_commit(t);
4372            t_util.t_wait(10);
4373            
4374            c = t_util.t_openContainer(t, segment, cid, true);
4375
4376            testPage = t_util.t_addPage(c);
4377            t_util.t_insert(testPage, testRow);
4378            testPage.unlatch();
4379
4380            //when container is in unlogged mode, the check is untru,
4381
//because rollback to save point would have done nothing.
4382
//so purge was not rolled back. The row does not exist any more
4383
if((openMode & ContainerHandle.MODE_UNLOGGED) == 0)
4384            {
4385                page = t_util.t_getPage(c, ContainerHandle.FIRST_PAGE_NUMBER);
4386                if(logDataForPurges)
4387                {
4388                    t_util.t_checkFetch(page, rh2, r1);
4389                }else
4390                {
4391                    //when data is not logged for purges ,
4392
//in this particular first four columns becomes null becuase
4393
//first 4 fileds data are on the 1st page and do not get
4394
//logged during pruge and
4395
//the rest of the columns gets the data back because they
4396
//are removed page by page.
4397
T_RawStoreRow r1_wnl = new T_RawStoreRow(400);
4398                    for (int i = 0; i < 18; i++)
4399                        r1_wnl.setColumn(i, 4, REC_NULL);
4400                    for (int i = 18; i < 400; i++)
4401                        r1_wnl.setColumn(i, 100+i, REC_001);
4402                    t_util.t_checkFetch(page, rh2, r1_wnl);
4403                }
4404                page.unlatch();
4405                page = null;
4406            }
4407
4408
4409            t_util.t_dropContainer(t, segment, cid); // cleanup
4410

4411        }
4412        finally
4413        {
4414            if (page != null)
4415                page.unlatch();
4416            t_util.t_commit(t);
4417            t.close();
4418        }
4419
4420        PASS("P036");
4421    }
4422
4423
4424    /**
4425        Test space reclaimation - purging of a row with serveral long columns
4426        get back all the column chains.
4427
4428        @exception T_Fail Unexpected behaviour from the API
4429        @exception StandardException Unexpected exception from the implementation
4430     */

4431    protected void P037() throws StandardException, T_Fail
4432    {
4433        // Insert the 3 rows in P035, then purge them and reinsert them and
4434
// make sure it reuses all the pages from last time.
4435

4436        long segment = 0;
4437        Transaction t = t_util.t_startTransaction();
4438        long cid = t_util.t_addContainer(t, segment, 4096);
4439
4440        ContainerHandle c = t_util.t_openContainer(t, segment, cid, true);
4441        Page page = t_util.t_getPage(c, ContainerHandle.FIRST_PAGE_NUMBER);
4442        try
4443        {
4444            t_util.t_checkEmptyPage(page);
4445
4446            int insertFlag = Page.INSERT_INITIAL | Page.INSERT_OVERFLOW;
4447            T_RawStoreRow r1 = new T_RawStoreRow(1);
4448            // insert a long column
4449
r1.setColumn(0, 5500, REC_001);
4450            RecordHandle rh1 = t_util.t_insertAtSlot(page, 0, r1, (byte) insertFlag);
4451            t_util.t_checkFetch(page, rh1, r1);
4452
4453            // insert a 6 column row, every other column is long, sizes
4454
// picked so that 2 rows fit, but 3rd row won't fit even if whole
4455
// row is overflowed.
4456
T_RawStoreRow r2 = new T_RawStoreRow(6);
4457            r2.setColumn(0, 660, REC_001); // this takes ~1320 bytes
4458
r2.setColumn(1, 5000, REC_002); // this takes ~10000 bytes
4459
r2.setColumn(2, 660, REC_001);
4460            r2.setColumn(3, 5000, REC_002);
4461            r2.setColumn(4, 660, REC_001);
4462            r2.setColumn(5, 5000, REC_002);
4463            RecordHandle rh2 = t_util.t_insertAtSlot(page, 0, r2, (byte) insertFlag);
4464            t_util.t_checkFetch(page, rh2, r2);
4465
4466
4467            // insert a long column - this should fail
4468
RecordHandle rh3 = t_util.t_insertAtSlot(page, 0, r1, (byte) insertFlag);
4469            if (rh3 != null)
4470            {
4471                throw T_Fail.testFailMsg("expect the 3rd row to not fit on page");
4472            }
4473
4474            page.unlatch();
4475            page = null;
4476
4477            Page nextPage = t_util.t_addPage(c);
4478            long nextPageNumber = nextPage.getPageNumber();
4479            // deallocate it
4480
t_util.t_removePage(c, nextPage);
4481
4482            REPORT("P037 - Nextpage is " + nextPageNumber);
4483
4484            t_util.t_commit(t);
4485
4486            // now purge them
4487
c = t_util.t_openContainer(t, segment, cid, true);
4488            page = t_util.t_getPage(c, ContainerHandle.FIRST_PAGE_NUMBER);
4489
4490            t_util.t_checkRecordCount(page, 2, 2);
4491            page.purgeAtSlot(0, 2, logDataForPurges);
4492            t_util.t_checkEmptyPage(page);
4493            page.unlatch();
4494            page = null;
4495
4496            t_util.t_commit(t);
4497
4498            // give some time for post commit to finish
4499
t_util.t_wait(10); // wait 10 milliseconds.
4500

4501            // reinsert all 3 of them again, exactly the same way.
4502
c = t_util.t_openContainer(t, segment, cid, true);
4503            page = t_util.t_getPage(c, ContainerHandle.FIRST_PAGE_NUMBER);
4504
4505            rh1 = t_util.t_insertAtSlot(page, 0, r1, (byte) insertFlag);
4506            rh2 = t_util.t_insertAtSlot(page, 0, r2, (byte) insertFlag);
4507            rh3 = t_util.t_insertAtSlot(page, 0, r1, (byte) insertFlag);
4508            t_util.t_checkFetch(page, rh1, r1);
4509            t_util.t_checkFetch(page, rh2, r2);
4510            if (rh3 != null)
4511                throw T_Fail.testFailMsg("expect the 3rd row to not fit on page");
4512            page.unlatch();
4513            page = null;
4514
4515            nextPage = t_util.t_addPage(c);
4516            long checkNextPageNumber = nextPage.getPageNumber();
4517            nextPage.unlatch();
4518
4519            if (nextPageNumber != checkNextPageNumber)
4520                throw T_Fail.testFailMsg("fail to reuse row pieces expect next page=" +
4521                     nextPageNumber + " but got " + checkNextPageNumber );
4522
4523            t_util.t_commit(t);
4524
4525            // Purge them and roll them back via savepoint. These should not
4526
// be reclaimed.
4527
c = t_util.t_openContainer(t, segment, cid, true);
4528
4529            t.setSavePoint(SP1, null);
4530            page = t_util.t_getPage(c, ContainerHandle.FIRST_PAGE_NUMBER);
4531            
4532            t_util.t_checkRecordCount(page, 2, 2);
4533            page.purgeAtSlot(0, 2, logDataForPurges);
4534            t_util.t_checkEmptyPage(page);
4535
4536            page.unlatch();
4537            page = null;
4538
4539            // make sure we cannot get our hands on a page that is freed up by
4540
// the purge
4541
Page testPage = t_util.t_addPage(c);
4542            T_RawStoreRow testRow = new T_RawStoreRow(REC_001);
4543            t_util.t_insert(testPage, testRow);
4544            testPage.unlatch();
4545
4546            t.rollbackToSavePoint(SP1, null);
4547
4548            testPage = t_util.t_addPage(c);
4549            t_util.t_insert(testPage, testRow);
4550            testPage.unlatch();
4551
4552            t_util.t_commit(t);
4553
4554            // give some time for post commit to finish
4555
t_util.t_wait(10);
4556
4557            // check to make sure post commit did not reclaim those rows.
4558
c = t_util.t_openContainer(t, segment, cid, true);
4559
4560            testPage = t_util.t_addPage(c);
4561            t_util.t_insert(testPage, testRow);
4562            testPage.unlatch();
4563
4564            page = t_util.t_getPage(c, ContainerHandle.FIRST_PAGE_NUMBER);
4565            
4566            t_util.t_checkRecordCount(page, 2, 2);
4567            t_util.t_checkFetch(page, rh1, r1);
4568        
4569            if(logDataForPurges)
4570                t_util.t_checkFetch(page, rh2, r2);
4571            else{
4572                
4573                // During purges when data is not logged when slots are purged
4574
// they become null on rollback and some cases like long columns
4575
// we remove the wholepage on rollback we get the data back.
4576
T_RawStoreRow r2_wnl = new T_RawStoreRow(6);
4577                r2_wnl.setColumn(0, 4, REC_NULL);
4578                r2_wnl.setColumn(1, 5000, REC_002);
4579                r2_wnl.setColumn(2, 4, REC_NULL);
4580                r2_wnl.setColumn(3, 5000, REC_002);
4581                r2_wnl.setColumn(4, 4, REC_NULL);
4582                r2_wnl.setColumn(5, 5000, REC_002);
4583                t_util.t_checkFetch(page, rh2, r2_wnl);
4584            }
4585                
4586            page.unlatch();
4587            page = null;
4588
4589            t_util.t_dropContainer(t, segment, cid); // cleanup
4590

4591        }
4592        finally
4593        {
4594            if (page != null)
4595                page.unlatch();
4596            t_util.t_commit(t);
4597            t.close();
4598        }
4599
4600        PASS("P037");
4601
4602    }
4603
4604    /**
4605        Test space reclaimation - rollback of an insert (with purge) of a row
4606        that overflows and with long column get back all the space in the row
4607        and column chain.
4608
4609        @exception T_Fail Unexpected behaviour from the API
4610        @exception StandardException Unexpected exception from the implementation
4611     */

4612    protected void P038() throws StandardException, T_Fail
4613    {
4614        long segment = 0;
4615
4616        // Insert the 3 rows in P035, then abort the insert.
4617
// Reinsert them and make sure it reuses all the pages from last time.
4618
Transaction t = t_util.t_startTransaction();
4619        long cid = t_util.t_addContainer(t, segment, 4096);
4620        t_util.t_commit(t);
4621
4622        ContainerHandle c = t_util.t_openContainer(t, segment, cid, true);
4623        Page page = t_util.t_getPage(c, ContainerHandle.FIRST_PAGE_NUMBER);
4624        try
4625        {
4626            t_util.t_checkEmptyPage(page);
4627
4628            int insertFlag = Page.INSERT_INITIAL | Page.INSERT_OVERFLOW |
4629                Page.INSERT_UNDO_WITH_PURGE;
4630
4631            T_RawStoreRow r1 = new T_RawStoreRow(1);
4632            // insert a long column
4633
r1.setColumn(0, 1500, REC_001);
4634            RecordHandle rh1 = t_util.t_insertAtSlot(page, 0, r1, (byte) insertFlag);
4635
4636            // insert a 6 column row, every other column is long
4637
T_RawStoreRow r2 = new T_RawStoreRow(6);
4638            r2.setColumn(0, 400, REC_001); // this takes ~800 bytes
4639
r2.setColumn(1, 500, REC_002); // this takes ~1000 bytes
4640
r2.setColumn(2, 400, REC_001);
4641            r2.setColumn(3, 500, REC_002);
4642            r2.setColumn(4, 400, REC_001);
4643            r2.setColumn(5, 500, REC_002);
4644            RecordHandle rh2 = t_util.t_insertAtSlot(page, 0, r2, (byte) insertFlag);
4645
4646            // insert a long column
4647
RecordHandle rh3 = t_util.t_insertAtSlot(page, 0, r1, (byte) insertFlag);
4648            if (rh3 != null)
4649                throw T_Fail.testFailMsg("expect the 3rd row to not fit on page");
4650            page = null;
4651
4652            Page nextPage = t_util.t_addPage(c);
4653            long nextPageNumber = nextPage.getPageNumber();
4654            // deallocate it
4655
t_util.t_removePage(c, nextPage);
4656
4657            REPORT("P038 - Nextpage is " + nextPageNumber);
4658
4659            t_util.t_abort(t);
4660
4661            // the abort rolled back the removal of nextPage also, redo the removed
4662
c = t_util.t_openContainer(t, segment, cid, true);
4663            nextPage = t_util.t_getPage(c, nextPageNumber);
4664            t_util.t_removePage(c, nextPage);
4665            t_util.t_commit(t);
4666
4667            // reinsert the 3 rows, they should not take up any more space than
4668
// last time.
4669
c = t_util.t_openContainer(t, segment, cid, true);
4670            page = t_util.t_getPage(c, ContainerHandle.FIRST_PAGE_NUMBER);
4671
4672            t_util.t_checkEmptyPage(page);
4673
4674            rh1 = t_util.t_insertAtSlot(page, 0, r1, (byte) insertFlag);
4675            rh2 = t_util.t_insertAtSlot(page, 0, r2, (byte) insertFlag);
4676            rh3 = t_util.t_insertAtSlot(page, 0, r1, (byte) insertFlag);
4677        
4678            t_util.t_checkFetch(page, rh1, r1);
4679            t_util.t_checkFetch(page, rh2, r2);
4680            if (rh3 != null)
4681                throw T_Fail.testFailMsg("expect the 3rd row to not fit on page");
4682
4683            page.unlatch();
4684            page = null;
4685
4686            nextPage = t_util.t_addPage(c);
4687            long checkNextPageNumber = nextPage.getPageNumber();
4688            nextPage.unlatch();
4689
4690
4691            if (nextPageNumber != checkNextPageNumber)
4692                throw T_Fail.testFailMsg("fail to reuse row pieces expect next page=" +
4693                    nextPageNumber + " but got " + checkNextPageNumber );
4694
4695            t_util.t_dropContainer(t, segment, cid); // cleanup
4696

4697        }
4698        finally
4699        {
4700            if (page != null)
4701                page.unlatch();
4702            t_util.t_commit(t);
4703            t.close();
4704        }
4705
4706        PASS("P038");
4707    }
4708
4709    /**
4710        Test space reclaimation - shrink a head row piece.
4711
4712        @exception T_Fail Unexpected behaviour from the API
4713        @exception StandardException Unexpected exception from the implementation
4714     */

4715    protected void P039() throws StandardException, T_Fail
4716    {
4717        // insert 3 2K rows of 3 columns, size (100, 1500, 400), into an 8K
4718
// page, then fill up the page with 1K rows.
4719
//
4720
// 1. Update the first 2K row so that the 2nd and 3rd column gets moved
4721
// to another page. See that we can insert at least 1 more 1K row into
4722
// the page.
4723
//
4724
// 2. Update the second 2K row so that the 2nd column becomes a long
4725
// column. See that we can insert at least 1 more 1K row into the
4726
// page.
4727
//
4728
// 3. Update the third 2K row so that the column size shrinks to (200,
4729
// 200, 200). See that we can insert at least 1 more 1K row into the
4730
// page.
4731

4732        long segment = 0;
4733        Transaction t = t_util.t_startTransaction();
4734        long cid = t_util.t_addContainer(t, segment, 8*1024);
4735
4736        T_RawStoreRow bigRow = new T_RawStoreRow(3);
4737        bigRow.setColumn(0, 50, REC_001); // remember each char takes 2 bytes
4738
bigRow.setColumn(1, 750, REC_002);
4739        bigRow.setColumn(2, 200, REC_003);
4740
4741        ContainerHandle c = t_util.t_openContainer(t, segment, cid, true);
4742        Page page = t_util.t_getPage(c, ContainerHandle.FIRST_PAGE_NUMBER);
4743        try
4744        {
4745            RecordHandle rh1 = t_util.t_insert(page, bigRow);
4746            RecordHandle rh2 = t_util.t_insert(page, bigRow);
4747            RecordHandle rh3 = t_util.t_insert(page, bigRow);
4748
4749            t_util.t_checkFetch(page, rh1, bigRow);
4750            t_util.t_checkFetch(page, rh2, bigRow);
4751            t_util.t_checkFetch(page, rh3, bigRow);
4752
4753            // now fill up the page with smaller rows
4754
T_RawStoreRow smallRow = new T_RawStoreRow(1);
4755            smallRow.setColumn(0, 500, REC_004);
4756
4757            while(page.spaceForInsert())
4758            {
4759                if (t_util.t_insert(page, smallRow) == null)
4760                    break;
4761            }
4762            REPORT("P039: " + (page.recordCount()-3) + " small rows have been inserted");
4763            page.unlatch();
4764            page = null;
4765
4766            t_util.t_commit(t);
4767        
4768            // (1) update rh1 so that column 2 and 3 are moved off page
4769
bigRow.setColumn(1, 2000, REC_005);
4770            c = t_util.t_openContainer(t, segment, cid, true);
4771
4772            page = t_util.t_getPage(c, ContainerHandle.FIRST_PAGE_NUMBER);
4773            page.update(rh1, bigRow.getRow(), (FormatableBitSet)null);
4774            t_util.t_checkFetch(page, rh1, bigRow);
4775            page.unlatch();
4776            page = null;
4777            t_util.t_commit(t);
4778
4779            t_util.t_wait(10); // wait for post commit to get processed.
4780

4781            c = t_util.t_openContainer(t, segment, cid, true);
4782            page = t_util.t_getPage(c, ContainerHandle.FIRST_PAGE_NUMBER);
4783
4784            if (t_util.t_insert(page, smallRow) == null)
4785                throw T_Fail.testFailMsg("expect row to have shrunk (1)");
4786
4787            // fill it up again
4788
while(page.spaceForInsert())
4789            {
4790                if (t_util.t_insert(page, smallRow) == null)
4791                    break;
4792            }
4793            REPORT("P039: " + (page.recordCount()-3) + " small rows have been inserted");
4794            
4795            page.unlatch();
4796            page = null;
4797
4798            t_util.t_commit(t);
4799
4800            // (2) update rh2 so that column 2 becomes a long column
4801
FormatableBitSet colList = new FormatableBitSet(2);
4802            colList.set(1); // update column 1, the second column
4803
// use sparse rows
4804
T_RawStoreRow partialRow = new T_RawStoreRow(2);
4805            partialRow.setColumn(1, 8000, REC_006);
4806
4807            c = t_util.t_openContainer(t, segment, cid, true);
4808
4809            page = t_util.t_getPage(c, ContainerHandle.FIRST_PAGE_NUMBER);
4810
4811            page.update(rh2, partialRow.getRow(), colList);
4812
4813            bigRow.setColumn(1, 8000, REC_006);
4814            t_util.t_checkFetch(page, rh2, bigRow);
4815            page.unlatch();
4816            page = null;
4817            t_util.t_commit(t);
4818
4819            t_util.t_wait(10); // wait for post commit to get processed.
4820

4821            c = t_util.t_openContainer(t, segment, cid, true);
4822            page = t_util.t_getPage(c, ContainerHandle.FIRST_PAGE_NUMBER);
4823            if (t_util.t_insert(page,smallRow) == null)
4824                throw T_Fail.testFailMsg("expect row to have shrunk (2)");
4825
4826            // fill it up again
4827
while(page.spaceForInsert())
4828            {
4829                if (t_util.t_insert(page, smallRow) == null)
4830                    break;
4831            }
4832            REPORT("P039: " + (page.recordCount()-3) + " small rows have been inserted");
4833
4834            page.unlatch();
4835            page = null;
4836
4837            t_util.t_commit(t);
4838
4839            // (3) - update rh3 to have (200, 400, 400) bytes columns
4840
bigRow.setColumn(0, 100, REC_001);
4841            bigRow.setColumn(1, 200, REC_002);
4842            bigRow.setColumn(2, 200, REC_003);
4843
4844            c = t_util.t_openContainer(t, segment, cid, true);
4845            page = t_util.t_getPage(c, ContainerHandle.FIRST_PAGE_NUMBER);
4846            page.update(rh3, bigRow.getRow(), (FormatableBitSet)null);
4847            t_util.t_checkFetch(page, rh3, bigRow);
4848            page.unlatch();
4849            page = null;
4850            t_util.t_commit(t);
4851
4852            t_util.t_wait(10); // wait for post commit to get processed.
4853

4854            c = t_util.t_openContainer(t, segment, cid, true);
4855            page = t_util.t_getPage(c, ContainerHandle.FIRST_PAGE_NUMBER);
4856
4857            if (t_util.t_insert(page,smallRow) == null)
4858                throw T_Fail.testFailMsg("expect row to have shrunk (3)");
4859            page.unlatch();
4860            page = null;
4861
4862            t_util.t_dropContainer(t, segment, cid); // cleanup
4863
}
4864        finally
4865        {
4866            if (page != null)
4867                page.unlatch();
4868            t_util.t_commit(t);
4869            t.close();
4870        }
4871
4872        PASS("P039");
4873    }
4874
4875    /**
4876        Test space reclaimation - shrink a non head row piece.
4877
4878        @exception T_Fail Unexpected behaviour from the API
4879        @exception StandardException Unexpected exception from the implementation
4880     */

4881    protected void P040() throws StandardException, T_Fail
4882    {
4883        // Manufacture a row that has a small head row piece, a large 2nd row
4884
// piece and a small third row piece.
4885
// Using the same head page, add a second row that has a small head row
4886
// piece and a medium sized 2nd row piece, a new overflow page should
4887
// be allocated.
4888
// Update the first row to now have a small 2nd row piece.
4889
// Using the same head page, add a third row that has a small head row
4890
// piece and a medium sized 2nd row piece, no new overflow page should
4891
// be allocated.
4892

4893        long segment = 0;
4894        Transaction t = t_util.t_startTransaction();
4895        long cid = t_util.t_addContainer(t, 0, 4096);
4896        ContainerHandle c = t_util.t_openContainer(t, segment, cid, true);
4897
4898        Page page = t_util.t_getPage(c, ContainerHandle.FIRST_PAGE_NUMBER);
4899        try
4900        {
4901            int insertFlag = Page.INSERT_INITIAL | Page.INSERT_OVERFLOW |
4902                Page.INSERT_UNDO_WITH_PURGE;
4903
4904            T_RawStoreRow row1 = new T_RawStoreRow(3);
4905            row1.setColumn(0, 400, REC_001);
4906            row1.setColumn(1, 800, REC_002); // this takes ~1600 bytes
4907
row1.setColumn(2, 400, REC_003);
4908            RecordHandle rh1 = t_util.t_insertAtSlot(page, 0, row1, (byte)insertFlag);
4909
4910            t_util.t_checkFetch(page, rh1, row1);
4911
4912            page.unlatch();
4913            page = null;
4914            t_util.t_commit(t);
4915
4916            c = t_util.t_openContainer(t, segment, cid, true);
4917            Page nextPage = t_util.t_addPage(c);
4918
4919            // remember where next page is
4920
long nextPageNumber = nextPage.getPageNumber();
4921            t_util.t_removePage(c, nextPage);
4922            t_util.t_commit(t);
4923
4924            T_RawStoreRow row2 = new T_RawStoreRow(3);
4925            row2.setColumn(0, 1200, REC_001);
4926            row2.setColumn(1, 1200, REC_002);
4927            row2.setColumn(2, 400, REC_003);
4928
4929            c = t_util.t_openContainer(t, segment, cid, true);
4930            page = t_util.t_getPage(c, ContainerHandle.FIRST_PAGE_NUMBER);
4931            RecordHandle rh2 = t_util.t_insertAtSlot(page, 1, row2, (byte)insertFlag);
4932
4933            t_util.t_checkFetch(page, rh2, row2);
4934            page.unlatch();
4935            page = null;
4936
4937            // this should have allocated more overflow page
4938
nextPage = t_util.t_addPage(c);
4939            long checkNextPageNumber = nextPage.getPageNumber();
4940            if (checkNextPageNumber == nextPageNumber)
4941                throw T_Fail.testFailMsg("expected to allocate more pages");
4942            t_util.t_removePage(c, nextPage);
4943            t_util.t_commit(t);
4944
4945            // now this is the next free page
4946
nextPageNumber = checkNextPageNumber;
4947
4948            // shrink first row 2nd column, and second row 1st column so we
4949
// have space on both the first and the second page on the row
4950
// chain.
4951
// use sparse rows
4952
T_RawStoreRow partialRow = new T_RawStoreRow(2);
4953            partialRow.setColumn(1, 400, REC_004);
4954
4955            T_RawStoreRow partialRow2 = new T_RawStoreRow(2);
4956            partialRow2.setColumn(0, 400, REC_004);
4957
4958            c = t_util.t_openContainer(t, segment, cid, true);
4959            page = t_util.t_getPage(c, ContainerHandle.FIRST_PAGE_NUMBER);
4960
4961            FormatableBitSet colList = new FormatableBitSet(2);
4962            colList.set(1); // update first row column 1, the second column
4963
page.update(rh1, partialRow.getRow(), colList);
4964
4965            colList.clear(1);
4966            colList.set(0); // update second row column 0, the first column
4967
page.update(rh2, partialRow2.getRow(), colList);
4968
4969            // verify the update worked.
4970
row1.setColumn(1, 400, REC_004);
4971            row2.setColumn(0, 400, REC_004);
4972            t_util.t_checkFetch(page, rh1, row1);
4973            t_util.t_checkFetch(page, rh2, row2);
4974
4975            page.unlatch();
4976            page = null;
4977
4978            t_util.t_commit(t);
4979            t_util.t_wait(10); // give post commit a chance to work
4980

4981            // We think the head row should have 2 200 bytes row.
4982
// One of the overflow row piece chain has an overflow page with a
4983
// 200 bytes row followed by another overflow page with a 200 bytes
4984
// row.
4985
// The other overflow row piece should have 1 600 bytes row and no
4986
// other overflow page.
4987
T_RawStoreRow row3 = new T_RawStoreRow(2);
4988            row3.setColumn(0, 400, REC_001);
4989            row3.setColumn(1, 800, REC_002);
4990            // We think this should select the first overflow chain.
4991
c = t_util.t_openContainer(t, segment, cid, true);
4992            page = t_util.t_getPage(c, ContainerHandle.FIRST_PAGE_NUMBER);
4993
4994            if (!page.spaceForInsert())
4995                throw T_Fail.testFailMsg("No space for insert after shrink row");
4996
4997            RecordHandle rh3 = t_util.t_insertAtSlot(page, 1, row3, (byte)insertFlag);
4998            t_util.t_checkFetch(page, rh3, row3);
4999
5000            page.unlatch();
5001            page = null;
5002
5003            // this should not allocate more overflow pages
5004
nextPage = t_util.t_addPage(c);
5005            checkNextPageNumber = nextPage.getPageNumber();
5006            if (checkNextPageNumber != nextPageNumber)
5007                throw T_Fail.testFailMsg("not expected to allocate more pages "
5008                                         + nextPageNumber + "," + checkNextPageNumber);
5009
5010            t_util.t_dropContainer(t, segment, cid); // cleanup
5011
}
5012        finally
5013        {
5014            if (page != null)
5015                page.unlatch();
5016
5017            t_util.t_commit(t);
5018            t.close();
5019        }
5020        PASS("P040");
5021    }
5022
5023    /**
5024        Test space reclaimation - update a long column to another long column.
5025
5026        @exception T_Fail Unexpected behaviour from the API
5027        @exception StandardException Unexpected exception from the implementation
5028     */

5029    protected void P041() throws StandardException, T_Fail
5030    {
5031        // Make a row with several long columns, on different row pieces.
5032
// Update these long columns - to other long columns or to short
5033
// columns. Remember what the next page is.
5034
// Update these long columns to the original long column (in length),
5035
// we shouldn't be adding any more pages.
5036

5037        long segment = 0;
5038        Transaction t = t_util.t_startTransaction();
5039        long cid = t_util.t_addContainer(t, segment, 4096);
5040
5041        ContainerHandle c = t_util.t_openContainer(t, segment, cid, true);
5042        Page page = t_util.t_getPage(c, ContainerHandle.FIRST_PAGE_NUMBER);
5043        try
5044        {
5045            t_util.t_checkEmptyPage(page);
5046
5047            int insertFlag = Page.INSERT_INITIAL | Page.INSERT_OVERFLOW;
5048
5049            // insert a 6 column row, every other column is long
5050
T_RawStoreRow r1 = new T_RawStoreRow(6);
5051            r1.setColumn(0, 400, REC_001); // this takes ~800 bytes
5052
r1.setColumn(1, 500, REC_002); // this takes ~1000 bytes
5053
r1.setColumn(2, 400, REC_001);
5054            r1.setColumn(3, 500, REC_002);
5055            r1.setColumn(4, 400, REC_001);
5056            r1.setColumn(5, 500, REC_002);
5057            RecordHandle rh1 = t_util.t_insertAtSlot(page, 0, r1, (byte) insertFlag);
5058            t_util.t_checkFetch(page, rh1, r1);
5059
5060            // update column 0,1,2 to short columns, columns 3, 4, 5 to other
5061
// long columns.
5062
T_RawStoreRow r2 = new T_RawStoreRow(6);
5063            r2.setColumn(0, 100, REC_003);
5064            r2.setColumn(1, 100, REC_004);
5065            r2.setColumn(2, 100, REC_003);
5066            r2.setColumn(3, 500, REC_005);
5067            r2.setColumn(4, 500, REC_006);
5068            r2.setColumn(5, 500, REC_005);
5069
5070            page.update(rh1, r2.getRow(), (FormatableBitSet)null);
5071            t_util.t_checkFetch(page, rh1, r2);
5072
5073            page.unlatch();
5074            page = null;
5075
5076            Page nextpage = t_util.t_addPage(c);
5077            long nextPageNumber = nextpage.getPageNumber();
5078            t_util.t_removePage(c, nextpage);
5079
5080            t_util.t_commit(t);
5081            t_util.t_wait(10); // let post commit work
5082

5083            // now update to original long rows, should not take any more
5084
// space.
5085
c = t_util.t_openContainer(t, segment, cid, true);
5086            page = t_util.t_getPage(c, ContainerHandle.FIRST_PAGE_NUMBER);
5087            t_util.t_checkFetch(page, rh1, r2);
5088            
5089            t.setSavePoint(SP1, null);
5090
5091            page.update(rh1, r1.getRow(), (FormatableBitSet)null);
5092            t_util.t_checkFetch(page, rh1, r1);
5093            page.unlatch();
5094            page = null;
5095
5096            nextpage = t_util.t_addPage(c);
5097            long checkNextPageNumber = nextpage.getPageNumber();
5098            nextpage.unlatch();
5099            if (checkNextPageNumber != nextPageNumber)
5100                throw T_Fail.testFailMsg("expect next page to be unchanged");
5101
5102            // now roll back the update via savepoint.
5103
t.rollbackToSavePoint(SP1, null);
5104
5105            t_util.t_commit(t);
5106            t_util.t_wait(10); // make sure post commit don't
5107
// reclaim things that are not garbage.
5108

5109            c = t_util.t_openContainer(t, segment, cid, true);
5110            page = t_util.t_getPage(c, ContainerHandle.FIRST_PAGE_NUMBER);
5111            t_util.t_checkFetch(page, rh1, r2);
5112            page.unlatch();
5113            page = null;
5114
5115            t_util.t_dropContainer(t, segment, cid); // cleanup
5116
}
5117        finally
5118        {
5119            if (page != null)
5120                page.unlatch();
5121            t_util.t_commit(t);
5122            t.close();
5123        }
5124
5125        PASS("P041");
5126
5127    }
5128
5129    /**
5130        Test space reclaimation - rollback of an update that create a long
5131        column.
5132
5133        @exception T_Fail Unexpected behaviour from the API
5134        @exception StandardException Unexpected exception from the implementation
5135     */

5136    protected void P042() throws StandardException, T_Fail
5137    {
5138        // Make a row with a short column. Remember the next page.
5139
// Update it to a long column, roll back. See that the next page goes
5140
// back to before the update.
5141
//
5142
// Update the row so that it overflows to another page and have long
5143
// column there. Remember the next page. Update the long column to
5144
// another long column. Rollback the update. See that the next page
5145
// goes back to before the update.
5146
//
5147
long segment = 0;
5148        Transaction t = t_util.t_startTransaction();
5149        long cid = t_util.t_addContainer(t, segment, 4096);
5150
5151        ContainerHandle c = t_util.t_openContainer(t, segment, cid, true);
5152        Page page = t_util.t_getPage(c, ContainerHandle.FIRST_PAGE_NUMBER);
5153        int insertFlag = Page.INSERT_INITIAL | Page.INSERT_OVERFLOW;
5154
5155        try
5156        {
5157            T_RawStoreRow smallRow = new T_RawStoreRow(REC_001);
5158            RecordHandle rh1 = t_util.t_insert(page, smallRow);
5159            t_util.t_commit(t);
5160
5161            c = t_util.t_openContainer(t, segment, cid, true);
5162            Page nextPage = t_util.t_addPage(c);
5163            long nextPageNumber = nextPage.getPageNumber();
5164            // deallocate it
5165
t_util.t_removePage(c, nextPage);
5166            t_util.t_commit(t);
5167
5168            c = t_util.t_openContainer(t, segment, cid, true);
5169            page = t_util.t_getPage(c, ContainerHandle.FIRST_PAGE_NUMBER);
5170
5171            T_RawStoreRow bigRow = new T_RawStoreRow(1);
5172            bigRow.setColumn(0, 6400, REC_001);
5173            page.update(rh1, bigRow.getRow(), (FormatableBitSet)null);
5174            t_util.t_checkFetch(page,rh1, bigRow);
5175            page.unlatch();
5176            page = null;
5177
5178            Page checkGrow = t_util.t_addPage(c);
5179            long checkGrowPageNumber = checkGrow.getPageNumber();
5180            if (checkGrowPageNumber == nextPageNumber)
5181                throw T_Fail.testFailMsg("expect to have allocated more pages");
5182            t_util.t_removePage(c, checkGrow);
5183
5184            t_util.t_abort(t);
5185
5186            t_util.t_wait(10);
5187            c = t_util.t_openContainer(t, segment, cid, true);
5188
5189            // the abort rolled back the removePage, remove it again.
5190
checkGrow = t_util.t_getPage(c, checkGrowPageNumber);
5191            t_util.t_removePage(c, checkGrow);
5192
5193            nextPage = t_util.t_addPage(c);
5194            if (nextPage.getPageNumber() != nextPageNumber)
5195                throw T_Fail.testFailMsg(
5196                "rollback of update to long column did not release the long column chain pages");
5197
5198            t_util.t_removePage(c, nextPage);
5199            t_util.t_commit(t);
5200
5201            T_RawStoreRow row2 = new T_RawStoreRow(6);
5202            row2.setColumn(0, 1600, REC_001); // this takes ~3200 bytes
5203
row2.setColumn(1, 2000, REC_002); // this takes ~4000 bytes
5204
row2.setColumn(2, 1600, REC_001);
5205            row2.setColumn(3, 2000, REC_002);
5206            row2.setColumn(4, 1600, REC_001);
5207            row2.setColumn(5, 2000, REC_002);
5208
5209            c = t_util.t_openContainer(t, segment, cid, true);
5210            page = t_util.t_getPage(c, ContainerHandle.FIRST_PAGE_NUMBER);
5211
5212            t.setSavePoint(SP1, null);
5213            page.update(rh1, row2.getRow(), (FormatableBitSet)null);
5214
5215            nextPage = t_util.t_addPage(c);
5216            nextPageNumber = nextPage.getPageNumber();
5217            t_util.t_removePage(c, nextPage);
5218
5219            t.rollbackToSavePoint(SP1, null); // this should free up some pages
5220

5221            nextPage = t_util.t_getPage(c, nextPageNumber);
5222            t_util.t_removePage(c, nextPage);
5223
5224            t_util.t_commit(t);
5225            t_util.t_wait(10);
5226
5227            c = t_util.t_openContainer(t, segment, cid, true);
5228            Page checkNextPage = t_util.t_addPage(c);
5229            if (checkNextPage.getPageNumber() == nextPageNumber)
5230                throw T_Fail.testFailMsg(
5231                    "expect some pages to be freed by update rollback");
5232            t_util.t_removePage(c, checkNextPage);
5233            t_util.t_commit(t);
5234
5235            c = t_util.t_openContainer(t, segment, cid, true);
5236            page = t_util.t_getPage(c, ContainerHandle.FIRST_PAGE_NUMBER);
5237            t_util.t_checkFetch(page, rh1, smallRow);
5238
5239            // update row so that it has overflow rows and long columns
5240
page.update(rh1, row2.getRow(), (FormatableBitSet)null);
5241
5242            // remember the next page
5243
nextPage = t_util.t_addPage(c);
5244            nextPageNumber = nextPage.getPageNumber();
5245            t_util.t_removePage(c, nextPage);
5246
5247            t_util.t_commit(t);
5248
5249            // now update columns 0, 1, 4 to long columns and roll it back.
5250
T_RawStoreRow row3 = new T_RawStoreRow(5);
5251            row3.setColumn(0, 4000, REC_003);
5252            row3.setColumn(1, 4000, REC_004);
5253            row3.setColumn(2, REC_001);
5254            row3.setColumn(3, REC_001);
5255            row3.setColumn(4, 4000, REC_003);
5256            
5257            c = t_util.t_openContainer(t, segment, cid, true);
5258            page = t_util.t_getPage(c, ContainerHandle.FIRST_PAGE_NUMBER);
5259            page.update(rh1, row3.getRow(), (FormatableBitSet)null);
5260            t_util.t_checkFetch(page, rh1, row3);
5261            page.unlatch();
5262            page = null;
5263
5264            t_util.t_abort(t);
5265            t_util.t_wait(10);
5266
5267            c = t_util.t_openContainer(t, segment, cid, true);
5268            nextPage = t_util.t_addPage(c);
5269            if (nextPage.getPageNumber() != nextPageNumber)
5270                throw T_Fail.testFailMsg("expect pages to be freed by update rollback");
5271            nextPage.unlatch();
5272
5273            t_util.t_dropContainer(t, segment, cid);
5274        }
5275        finally
5276        {
5277            if (page != null)
5278                page.unlatch();
5279            t_util.t_commit(t);
5280            t.close();
5281        }
5282        PASS("P042");
5283
5284    }
5285
5286    /**
5287        Test space reclaimation - rollback of an update that create a new row
5288        piece.
5289     */

5290    protected void P043()
5291    {
5292        // this space cannot be reclaimed.
5293
}
5294
5295
5296    /**
5297        Test that post commit processor does not stubbify a drop table that is
5298        rolled back in a savepoint
5299        @exception T_Fail Unexpected behaviour from the API
5300        @exception StandardException Unexpected exception from the implementation
5301
5302    */

5303    protected void P050()
5304         throws StandardException, T_Fail
5305    {
5306        if (!testRollback)
5307            return;
5308
5309        Transaction t = t_util.t_startTransaction();
5310        long cid = t_util.t_addContainer(t,0);
5311        t_util.t_commit(t);
5312
5313        t.setSavePoint(SP1, null);
5314
5315        t.dropContainer(new ContainerKey(0, cid));
5316        t.rollbackToSavePoint(SP1, null);
5317
5318        ContainerHandle c = t_util.t_openContainer(t, 0, cid, true);
5319        t_util.t_addPage(c);
5320        t_util.t_commit(t);
5321
5322        long cid2 = t_util.t_addContainer(t, 0);
5323        c = t_util.t_openContainer(t, 0, cid2, true);
5324        t_util.t_addPage(c);
5325        t_util.t_addPage(c);
5326        t_util.t_addPage(c);
5327        t_util.t_addPage(c);
5328        t_util.t_commit(t);
5329
5330        c = t_util.t_openContainer(t, 0, cid, false); // it should not be stubbified...
5331

5332        PASS("P050");
5333
5334        t_util.t_dropContainer(t, 0, cid); // cleanup - commit it for real
5335
t_util.t_dropContainer(t, 0, cid2); // cleanup - commit it for real
5336

5337        t_util.t_commit(t);
5338        t.close();
5339
5340    }
5341
5342    /**
5343        Test rollback of Page.insert
5344        @exception T_Fail Unexpected behaviour from the API
5345        @exception StandardException Unexpected exception from the implementation
5346
5347    */

5348    protected void P051()
5349         throws StandardException, T_Fail
5350    {
5351        if (!testRollback)
5352            return;
5353
5354        Transaction t = t_util.t_startTransaction();
5355        long cid = t_util.t_addContainer(t,0);
5356        t_util.t_commit(t);
5357
5358
5359        T_RawStoreRow row = new T_RawStoreRow(REC_001);
5360        ContainerHandle c = t_util.t_openContainer(t, 0, cid, true);
5361        Page page = t_util.t_getPage(c, ContainerHandle.FIRST_PAGE_NUMBER);
5362
5363        // first insert and check that an abort leaves the row there
5364
RecordHandle rh1 = t_util.t_insert(page, row);
5365
5366        t_util.t_commit(t);
5367
5368        c = t_util.t_openContainer(t, 0, cid, true);
5369
5370        t_util.t_checkFetch(c, rh1, REC_001);
5371
5372        row = new T_RawStoreRow(REC_002);
5373
5374        RecordHandle rh2 = t_util.t_insert(c, row);
5375
5376        t_util.t_checkFetch(c, rh1, REC_001);
5377        t_util.t_checkFetch(c, rh2, REC_002);
5378
5379        t_util.t_abort(t);
5380
5381        c = t_util.t_openContainer(t, 0, cid, true);
5382        t_util.t_checkFetch(c, rh1, REC_001);
5383
5384        page = t_util.t_getPage(c, rh2.getPageNumber());
5385        if (page.recordExists(rh2, false)) {
5386            throw T_Fail.testFailMsg("record insert was not undone");
5387        }
5388        page.unlatch();
5389
5390        PASS("P051");
5391
5392        t_util.t_dropContainer(t, 0, cid); // cleanup
5393

5394        t_util.t_commit(t);
5395        t.close();
5396    }
5397    /**
5398        Test rollback of Page.delete
5399        @exception T_Fail Unexpected behaviour from the API
5400        @exception StandardException Unexpected exception from the implementation
5401
5402        @see Page#delete
5403
5404    */

5405    protected void P052()
5406         throws StandardException, T_Fail
5407    {
5408        if (!testRollback)
5409            return;
5410
5411        Transaction t = t_util.t_startTransaction();
5412
5413        long cid = t_util.t_addContainer(t,0);
5414        t_util.t_commit(t);
5415
5416        ContainerHandle c = t_util.t_openContainer(t, 0, cid, true);
5417
5418        // first insert two rows
5419
T_RawStoreRow row = new T_RawStoreRow(REC_001);
5420        RecordHandle rh1 = t_util.t_insert(c, row);
5421        row = new T_RawStoreRow(REC_002);
5422        RecordHandle rh2 = t_util.t_insert(c, row);
5423
5424        t_util.t_commit(t);
5425
5426        c = t_util.t_openContainer(t, 0, cid, true);
5427
5428        t_util.t_checkFetch(c, rh1, REC_001);
5429        t_util.t_checkFetch(c, rh2, REC_002);
5430
5431        t_util.t_delete(c, rh2);
5432
5433        t_util.t_checkFetch(c, rh1, REC_001);
5434
5435        t_util.t_abort(t);
5436
5437        c = t_util.t_openContainer(t, 0, cid, true);
5438        t_util.t_checkFetch(c, rh1, REC_001);
5439        t_util.t_checkFetch(c, rh2, REC_002);
5440
5441        PASS("P052");
5442
5443        t_util.t_dropContainer(t, 0, cid); // cleanup
5444

5445        t_util.t_commit(t);
5446        t.close();
5447    }
5448
5449    /**
5450        Test insertAtSlot that rolls back with a purge
5451
5452        @exception T_Fail Unexpected behaviour from the API
5453        @exception StandardException Unexpected exception from the implementation
5454
5455    */

5456    protected void P053()
5457         throws StandardException, T_Fail
5458    {
5459        if (!testRollback)
5460            return;
5461        Transaction t = t_util.t_startTransaction();
5462
5463        try
5464        {
5465            long cid = t_util.t_addContainer(t,0);
5466            t_util.t_commit(t);
5467
5468            
5469            ContainerHandle c = t_util.t_openContainer(t, 0, cid, true);
5470            Page page = t_util.t_addPage(c);
5471
5472            T_RawStoreRow row0 = new T_RawStoreRow(REC_001);
5473            T_RawStoreRow row1 = new T_RawStoreRow(REC_001);
5474            T_RawStoreRow row2 = new T_RawStoreRow(REC_002);
5475            T_RawStoreRow row3 = new T_RawStoreRow(REC_003);
5476            T_RawStoreRow row4 = new T_RawStoreRow(REC_004);
5477            
5478            t_util.t_insertAtSlot(page, 0, row0, Page.INSERT_UNDO_WITH_PURGE);
5479
5480            if (t_util.t_insertAtSlot(page, 1, row1) == null)
5481                return;
5482
5483            if (t_util.t_insertAtSlot(page, 2, row2, Page.INSERT_UNDO_WITH_PURGE) == null)
5484                return;
5485
5486            if (t_util.t_insertAtSlot(page, 3, row3) == null)
5487                return;
5488    
5489            if (t_util.t_insertAtSlot(page, 4, row4, Page.INSERT_UNDO_WITH_PURGE) == null)
5490                return;
5491    
5492            int fillerRows = 0;
5493            while (page.spaceForInsert())
5494            {
5495                t_util.t_insertAtSlot(page, 4, row4);
5496                fillerRows++;
5497            }
5498
5499            t_util.t_checkRecordCount(page, fillerRows + 5, fillerRows + 5);
5500            t_util.t_abort(t);
5501
5502            c = t_util.t_openContainer(t, 0, cid, true);
5503            page = t_util.t_getLastPage(c);
5504
5505            // 2 + fillerRows deleted, 3 purged, 0 nondeleted
5506
t_util.t_checkRecordCount(page, 2 + fillerRows, 0);
5507
5508            // since I just purged them, there must be space for re-inserting them
5509
t_util.t_insert(page, row0);
5510            t_util.t_insert(page, row2);
5511            t_util.t_insert(page, row4);
5512
5513            t_util.t_checkRecordCount(page, 5 + fillerRows, 3);
5514
5515            page.unlatch();
5516            PASS("P053");
5517
5518            t_util.t_dropContainer(t, 0, cid); // cleanup
5519
}
5520        finally
5521        {
5522            t_util.t_commit(t);
5523            t.close();
5524        }
5525    }
5526
5527    /**
5528        Test internal transaction
5529
5530        @exception T_Fail Unexpected behaviour from the API
5531        @exception StandardException Unexpected exception from the implementation
5532
5533    */

5534    protected void P054()
5535         throws StandardException, T_Fail
5536    {
5537        if (!testRollback)
5538            return;
5539
5540        ContextManager previousCM = contextService.getCurrentContextManager();
5541
5542        ContextManager cm1 = contextService.newContextManager();
5543        contextService.setCurrentContextManager(cm1);
5544
5545        Transaction tuser = t_util.t_startTransaction();
5546        Transaction tinternal = null;
5547
5548        try
5549        {
5550
5551            long cid1 = t_util.t_addContainer(tuser, 0);
5552            ContainerHandle c1 = t_util.t_openContainer(tuser, 0, cid1, true);
5553            Page p1 = t_util.t_addPage(c1);
5554            t_util.t_commit(tuser);
5555
5556            // insert a row using user transaction
5557
T_RawStoreRow row = new T_RawStoreRow(REC_001);
5558
5559            c1 = t_util.t_openContainer(tuser, 0, cid1, true);
5560            p1 = t_util.t_getLastPage(c1);
5561            RecordHandle r1 = t_util.t_insert(p1, row);
5562
5563            REPORT("starting internal transaction");
5564
5565            tinternal = t_util.t_startInternalTransaction();
5566            long cid2 = t_util.t_addContainer(tinternal, 0);
5567            ContainerHandle c2 = t_util.t_openContainer(tinternal, 0, cid2, true);
5568            Page p2 = t_util.t_addPage(c2);
5569            RecordHandle r2 = t_util.t_insert(p2, row);
5570
5571            // commit internal transaction
5572
tinternal.commit();
5573            tinternal.abort(); // this will close the container and release
5574
// the page
5575
tinternal.close();
5576            tinternal = null;
5577
5578            REPORT("commit internal transaction");
5579
5580            // abort user transaction
5581
t_util.t_abort(tuser);
5582
5583            REPORT("rollback user transaction");
5584
5585            c1 = t_util.t_openContainer(tuser, 0, cid1, true);
5586
5587            p1 = t_util.t_getPage(c1, r1.getPageNumber());
5588            if (p1.recordExists(r1, false))
5589                throw T_Fail.testFailMsg("user transaction failed to rollback");
5590
5591
5592            c2 = t_util.t_openContainer(tuser, 0, cid2, true);
5593            t_util.t_checkFetch(c2, r2, REC_001); // this should be unaffected by the
5594
// user transaction rollback
5595
p2 = t_util.t_getLastPage(c2);
5596
5597            T_RawStoreRow row2 = new T_RawStoreRow(REC_002);
5598
5599            if (!p2.spaceForInsert())
5600            {
5601                REPORT("P054 not run, page cannot accomodate 2 rows");
5602                return;
5603            }
5604            RecordHandle r21 = t_util.t_insert(p2, row2);
5605
5606            // throw an exception, make sure everything is aborted.
5607
tinternal = t_util.t_startInternalTransaction();
5608            long cid3 = t_util.t_addContainer(tinternal, 0);
5609            ContainerHandle c3 = t_util.t_openContainer(tinternal, 0, cid3, true);
5610            Page p3 = t_util.t_addPage(c3);
5611            RecordHandle r3 = t_util.t_insert(p3, row);
5612            try
5613            {
5614                // this will throw a data statement exception
5615
t_util.t_insertAtSlot(p3, 100, row);
5616            }
5617            catch (StandardException se)
5618            {
5619                REPORT("cleanup on error");
5620                cm1.cleanupOnError(se);
5621                REPORT("done cleanup on error");
5622            }
5623
5624            tinternal = null;
5625            // tuser = t_util.t_startTransaction();
5626
c2 = t_util.t_openContainer(tuser, 0, cid2, true);
5627            t_util.t_checkFetch(c2, r2, REC_001);
5628
5629            p2 = t_util.t_getPage(c2, r21.getPageNumber());
5630            if (p2.recordExists(r21, false))
5631                throw T_Fail.testFailMsg("expect user transaction to rollback");
5632
5633            // this should fail
5634
ContainerKey id3 = new ContainerKey(0, cid3);
5635            c3 = tuser.openContainer(id3, ContainerHandle.MODE_READONLY);
5636            if (c3 != null)
5637                throw T_Fail.testFailMsg("expect internal transaction to rollback");
5638
5639            LockingPolicy nolock =
5640                tuser.newLockingPolicy(LockingPolicy.MODE_NONE, 0, false);
5641
5642            RawContainerHandle stub =
5643                ((RawTransaction)tuser).openDroppedContainer(
5644                    id3, nolock);
5645
5646            if (stub == null)
5647                throw T_Fail.testFailMsg("expect container to be dropped");
5648
5649            if (stub.getContainerStatus() != RawContainerHandle.COMMITTED_DROP)
5650                throw T_Fail.testFailMsg("expect container to be committed dropped");
5651
5652            // this should fail
5653
p3 = stub.getPage(r3.getPageNumber());
5654
5655            if (p3 != null)
5656                throw T_Fail.testFailMsg("should not getpage with committed dropped container");
5657
5658            PASS("P054");
5659
5660
5661            t_util.t_dropContainer(tuser, 0, cid2); // cleanup
5662
t_util.t_dropContainer(tuser, 0, cid1); // cleanup
5663

5664            if (tinternal != null)
5665            {
5666                t_util.t_abort(tinternal);
5667                tinternal.close();
5668            }
5669
5670            if (tuser != null)
5671            {
5672                t_util.t_commit(tuser);
5673                tuser.close();
5674            }
5675        }
5676        finally
5677        {
5678
5679            contextService.resetCurrentContextManager(cm1);
5680        }
5681
5682    }
5683
5684
5685    /**
5686        Test rollback of partial row update.
5687        Create a long row with 10 columns on 2 pages (5 columns on each page).
5688        Update the 1st column on the 2nd page (the 6th column) which causes the
5689        last column (10th column) to move off the page. Then abort and make sure
5690        that all the original columns are there and correct.
5691
5692        NOTE: stored length is twice string length + 2
5693
5694        @exception T_Fail Unexpected behaviour from the API
5695        @exception StandardException Unexpected exception from the implementation
5696    */

5697    protected void P055(long segment) throws StandardException, T_Fail {
5698
5699        if (!testRollback)
5700            return;
5701
5702        Transaction t = t_util.t_startTransaction();
5703
5704        long cid = t_util.t_addContainer(t, segment, 4096);
5705
5706        ContainerHandle c = t_util.t_openContainer(t, segment, cid, true);
5707        Page page = t_util.t_getPage(c, ContainerHandle.FIRST_PAGE_NUMBER);
5708        t_util.t_checkEmptyPage(page);
5709
5710        int colSize = 90;
5711        T_RawStoreRow r0 = new T_RawStoreRow(10);
5712        r0.setColumn(0, colSize, REC_001);
5713        r0.setColumn(1, colSize, REC_002);
5714        r0.setColumn(2, colSize, REC_003);
5715        r0.setColumn(3, colSize, REC_004);
5716        r0.setColumn(4, colSize, REC_005);
5717        r0.setColumn(5, colSize, REC_009);
5718        r0.setColumn(6, colSize, REC_010);
5719        r0.setColumn(7, colSize, REC_011);
5720        r0.setColumn(8, colSize, REC_012);
5721        r0.setColumn(9, colSize, REC_013);
5722
5723        int insertFlag = Page.INSERT_INITIAL;
5724        insertFlag |= Page.INSERT_OVERFLOW;
5725
5726        RecordHandle rh0 = null;
5727        try {
5728            rh0 = t_util.t_insertAtSlot(page, 0, r0, (byte) insertFlag);
5729        } catch (StandardException se) {
5730            throw T_Fail.testFailMsg("insert of long row failed.");
5731        }
5732
5733        if (rh0 == null)
5734            throw T_Fail.testFailMsg("insert of first long row failed.");
5735        else {
5736            REPORT("about to check fetch...");
5737            DataValueDescriptor column = new SQLChar();
5738            t_util.t_checkFetchColFromSlot(page, page.FIRST_SLOT_NUMBER, 0, column, false, REC_001, colSize);
5739            t_util.t_checkFetchColFromSlot(page, page.FIRST_SLOT_NUMBER, 1, column, false, REC_002, colSize);
5740            t_util.t_checkFetchColFromSlot(page, page.FIRST_SLOT_NUMBER, 2, column, false, REC_003, colSize);
5741            t_util.t_checkFetchColFromSlot(page, page.FIRST_SLOT_NUMBER, 3, column, false, REC_004, colSize);
5742            t_util.t_checkFetchColFromSlot(page, page.FIRST_SLOT_NUMBER, 4, column, false, REC_005, colSize);
5743            t_util.t_checkFetchColFromSlot(page, page.FIRST_SLOT_NUMBER, 5, column, false, REC_009, colSize);
5744            t_util.t_checkFetchColFromSlot(page, page.FIRST_SLOT_NUMBER, 6, column, false, REC_010, colSize);
5745            t_util.t_checkFetchColFromSlot(page, page.FIRST_SLOT_NUMBER, 7, column, false, REC_011, colSize);
5746            t_util.t_checkFetchColFromSlot(page, page.FIRST_SLOT_NUMBER, 8, column, false, REC_012, colSize);
5747            t_util.t_checkFetchColFromSlot(page, page.FIRST_SLOT_NUMBER, 9, column, false, REC_013, colSize);
5748        }
5749
5750        t_util.t_commit(t);
5751
5752
5753        // update col 5 (the 6th column, the first column on the 2nd overflow page), which causes
5754
// the last column (col 9, the 10th column) to move off the page.
5755

5756        c = t_util.t_openContainer(t, segment, cid, true);
5757        page = t_util.t_getPage(c, ContainerHandle.FIRST_PAGE_NUMBER);
5758
5759        T_RawStoreRow updateRow = new T_RawStoreRow(10);
5760        for (int i = 0; i < 10; i++)
5761            updateRow.setColumn(i, (String JavaDoc) null);
5762        updateRow.setColumn(5, colSize*2, REC_009);
5763        FormatableBitSet colList = new FormatableBitSet(10);
5764        colList.set(5);
5765        page.updateAtSlot(0, updateRow.getRow(), colList);
5766
5767        REPORT("about to check fetch after update ...");
5768        DataValueDescriptor column = new SQLChar();
5769        t_util.t_checkFetchColFromSlot(page, page.FIRST_SLOT_NUMBER, 0, column, false, REC_001, colSize);
5770        t_util.t_checkFetchColFromSlot(page, page.FIRST_SLOT_NUMBER, 1, column, false, REC_002, colSize);
5771        t_util.t_checkFetchColFromSlot(page, page.FIRST_SLOT_NUMBER, 2, column, false, REC_003, colSize);
5772        t_util.t_checkFetchColFromSlot(page, page.FIRST_SLOT_NUMBER, 3, column, false, REC_004, colSize);
5773        t_util.t_checkFetchColFromSlot(page, page.FIRST_SLOT_NUMBER, 4, column, false, REC_005, colSize);
5774        t_util.t_checkFetchColFromSlot(page, page.FIRST_SLOT_NUMBER, 5, column, false, REC_009, colSize*2);
5775        t_util.t_checkFetchColFromSlot(page, page.FIRST_SLOT_NUMBER, 6, column, false, REC_010, colSize);
5776        t_util.t_checkFetchColFromSlot(page, page.FIRST_SLOT_NUMBER, 7, column, false, REC_011, colSize);
5777        t_util.t_checkFetchColFromSlot(page, page.FIRST_SLOT_NUMBER, 8, column, false, REC_012, colSize);
5778        t_util.t_checkFetchColFromSlot(page, page.FIRST_SLOT_NUMBER, 9, column, false, REC_013, colSize);
5779        page.unlatch();
5780
5781        t_util.t_abort(t);
5782
5783        REPORT("about to check fetch after abort ...");
5784        c = t_util.t_openContainer(t, segment, cid, false);
5785        page = t_util.t_getPage(c, ContainerHandle.FIRST_PAGE_NUMBER);
5786        t_util.t_checkFetchColFromSlot(page, page.FIRST_SLOT_NUMBER, 0, column, false, REC_001, colSize);
5787        t_util.t_checkFetchColFromSlot(page, page.FIRST_SLOT_NUMBER, 1, column, false, REC_002, colSize);
5788        t_util.t_checkFetchColFromSlot(page, page.FIRST_SLOT_NUMBER, 2, column, false, REC_003, colSize);
5789        t_util.t_checkFetchColFromSlot(page, page.FIRST_SLOT_NUMBER, 3, column, false, REC_004, colSize);
5790        t_util.t_checkFetchColFromSlot(page, page.FIRST_SLOT_NUMBER, 4, column, false, REC_005, colSize);
5791        t_util.t_checkFetchColFromSlot(page, page.FIRST_SLOT_NUMBER, 5, column, false, REC_009, colSize);
5792        t_util.t_checkFetchColFromSlot(page, page.FIRST_SLOT_NUMBER, 6, column, false, REC_010, colSize);
5793        t_util.t_checkFetchColFromSlot(page, page.FIRST_SLOT_NUMBER, 7, column, false, REC_011, colSize);
5794        t_util.t_checkFetchColFromSlot(page, page.FIRST_SLOT_NUMBER, 8, column, false, REC_012, colSize);
5795        t_util.t_checkFetchColFromSlot(page, page.FIRST_SLOT_NUMBER, 9, column, false, REC_013, colSize);
5796        page.unlatch();
5797
5798
5799        if (segment != ContainerHandle.TEMPORARY_SEGMENT) {
5800            t_util.t_dropContainer(t, segment, cid); // cleanup
5801
}
5802
5803        t_util.t_commit(t);
5804        t.close();
5805
5806        PASS("P055: segment = " + segment);
5807    }
5808
5809
5810    /**
5811        Test rollback of partial row update.
5812        Create a long row with 15 columns on 3 pages (5 columns on each page).
5813        Update the 1st column on the 2nd page (the 6th column) which causes the
5814        last column of that page (10th column) to move off the page. Then abort
5815        and make sure that all the original columns are there and correct.
5816
5817        NOTE: stored length is twice string length + 2
5818
5819        @exception T_Fail Unexpected behaviour from the API
5820        @exception StandardException Unexpected exception from the implementation
5821    */

5822    protected void P056(long segment) throws StandardException, T_Fail {
5823
5824        if (!testRollback)
5825            return;
5826
5827        Transaction t = t_util.t_startTransaction();
5828
5829        long cid = t_util.t_addContainer(t, segment, 4096);
5830
5831        ContainerHandle c = t_util.t_openContainer(t, segment, cid, true);
5832        Page page = t_util.t_getPage(c, ContainerHandle.FIRST_PAGE_NUMBER);
5833        t_util.t_checkEmptyPage(page);
5834
5835        int colSize = 90;
5836        T_RawStoreRow r0 = new T_RawStoreRow(15);
5837        r0.setColumn(0, colSize, REC_001);
5838        r0.setColumn(1, colSize, REC_002);
5839        r0.setColumn(2, colSize, REC_003);
5840        r0.setColumn(3, colSize, REC_004);
5841        r0.setColumn(4, colSize, REC_005);
5842        r0.setColumn(5, colSize, REC_009);
5843        r0.setColumn(6, colSize, REC_010);
5844        r0.setColumn(7, colSize, REC_011);
5845        r0.setColumn(8, colSize, REC_012);
5846        r0.setColumn(9, colSize, REC_013);
5847        r0.setColumn(10, colSize, REC_014);
5848        r0.setColumn(11, colSize, REC_015);
5849        r0.setColumn(12, colSize, REC_016);
5850        r0.setColumn(13, colSize, REC_017);
5851        r0.setColumn(14, colSize, REC_018);
5852
5853
5854        int insertFlag = Page.INSERT_INITIAL;
5855        insertFlag |= Page.INSERT_OVERFLOW;
5856
5857        RecordHandle rh0 = null;
5858        try {
5859            rh0 = t_util.t_insertAtSlot(page, 0, r0, (byte) insertFlag);
5860        } catch (StandardException se) {
5861            throw T_Fail.testFailMsg("insert of long row failed.");
5862        }
5863
5864        if (rh0 == null)
5865            throw T_Fail.testFailMsg("insert of first long row failed.");
5866        else {
5867            REPORT("about to check fetch...");
5868            DataValueDescriptor column = new SQLChar();
5869            t_util.t_checkFetchColFromSlot(page, page.FIRST_SLOT_NUMBER, 0, column, false, REC_001, colSize);
5870            t_util.t_checkFetchColFromSlot(page, page.FIRST_SLOT_NUMBER, 1, column, false, REC_002, colSize);
5871            t_util.t_checkFetchColFromSlot(page, page.FIRST_SLOT_NUMBER, 2, column, false, REC_003, colSize);
5872            t_util.t_checkFetchColFromSlot(page, page.FIRST_SLOT_NUMBER, 3, column, false, REC_004, colSize);
5873            t_util.t_checkFetchColFromSlot(page, page.FIRST_SLOT_NUMBER, 4, column, false, REC_005, colSize);
5874            t_util.t_checkFetchColFromSlot(page, page.FIRST_SLOT_NUMBER, 5, column, false, REC_009, colSize);
5875            t_util.t_checkFetchColFromSlot(page, page.FIRST_SLOT_NUMBER, 6, column, false, REC_010, colSize);
5876            t_util.t_checkFetchColFromSlot(page, page.FIRST_SLOT_NUMBER, 7, column, false, REC_011, colSize);
5877            t_util.t_checkFetchColFromSlot(page, page.FIRST_SLOT_NUMBER, 8, column, false, REC_012, colSize);
5878            t_util.t_checkFetchColFromSlot(page, page.FIRST_SLOT_NUMBER, 9, column, false, REC_013, colSize);
5879            t_util.t_checkFetchColFromSlot(page, page.FIRST_SLOT_NUMBER, 10, column, false, REC_014, colSize);
5880            t_util.t_checkFetchColFromSlot(page, page.FIRST_SLOT_NUMBER, 11, column, false, REC_015, colSize);
5881            t_util.t_checkFetchColFromSlot(page, page.FIRST_SLOT_NUMBER, 12, column, false, REC_016, colSize);
5882            t_util.t_checkFetchColFromSlot(page, page.FIRST_SLOT_NUMBER, 13, column, false, REC_017, colSize);
5883            t_util.t_checkFetchColFromSlot(page, page.FIRST_SLOT_NUMBER, 14, column, false, REC_018, colSize);
5884        }
5885
5886        t_util.t_commit(t);
5887
5888
5889        // update col 5 (the 6th column, the first column on the 2nd overflow page), which causes
5890
// the last column (col 9, the 10th column) to move off the page.
5891

5892        c = t_util.t_openContainer(t, segment, cid, true);
5893        page = t_util.t_getPage(c, ContainerHandle.FIRST_PAGE_NUMBER);
5894
5895        T_RawStoreRow updateRow = new T_RawStoreRow(15);
5896        for (int i = 0; i < 15; i++)
5897            updateRow.setColumn(i, (String JavaDoc) null);
5898        updateRow.setColumn(5, colSize*2, REC_009);
5899        FormatableBitSet colList = new FormatableBitSet(15);
5900        colList.set(5);
5901        page.updateAtSlot(0, updateRow.getRow(), colList);
5902
5903        REPORT("about to check fetch after update ...");
5904        DataValueDescriptor column = new SQLChar();
5905        t_util.t_checkFetchColFromSlot(page, page.FIRST_SLOT_NUMBER, 0, column, false, REC_001, colSize);
5906        t_util.t_checkFetchColFromSlot(page, page.FIRST_SLOT_NUMBER, 1, column, false, REC_002, colSize);
5907        t_util.t_checkFetchColFromSlot(page, page.FIRST_SLOT_NUMBER, 2, column, false, REC_003, colSize);
5908        t_util.t_checkFetchColFromSlot(page, page.FIRST_SLOT_NUMBER, 3, column, false, REC_004, colSize);
5909        t_util.t_checkFetchColFromSlot(page, page.FIRST_SLOT_NUMBER, 4, column, false, REC_005, colSize);
5910        t_util.t_checkFetchColFromSlot(page, page.FIRST_SLOT_NUMBER, 5, column, false, REC_009, colSize*2);
5911        t_util.t_checkFetchColFromSlot(page, page.FIRST_SLOT_NUMBER, 6, column, false, REC_010, colSize);
5912        t_util.t_checkFetchColFromSlot(page, page.FIRST_SLOT_NUMBER, 7, column, false, REC_011, colSize);
5913        t_util.t_checkFetchColFromSlot(page, page.FIRST_SLOT_NUMBER, 8, column, false, REC_012, colSize);
5914        t_util.t_checkFetchColFromSlot(page, page.FIRST_SLOT_NUMBER, 9, column, false, REC_013, colSize);
5915        t_util.t_checkFetchColFromSlot(page, page.FIRST_SLOT_NUMBER, 10, column, false, REC_014, colSize);
5916        t_util.t_checkFetchColFromSlot(page, page.FIRST_SLOT_NUMBER, 11, column, false, REC_015, colSize);
5917        t_util.t_checkFetchColFromSlot(page, page.FIRST_SLOT_NUMBER, 12, column, false, REC_016, colSize);
5918        t_util.t_checkFetchColFromSlot(page, page.FIRST_SLOT_NUMBER, 13, column, false, REC_017, colSize);
5919        t_util.t_checkFetchColFromSlot(page, page.FIRST_SLOT_NUMBER, 14, column, false, REC_018, colSize);
5920        page.unlatch();
5921
5922        t_util.t_abort(t);
5923
5924
5925        REPORT("about to check fetch after abort ...");
5926        c = t_util.t_openContainer(t, segment, cid, false);
5927        page = t_util.t_getPage(c, ContainerHandle.FIRST_PAGE_NUMBER);
5928        t_util.t_checkFetchColFromSlot(page, page.FIRST_SLOT_NUMBER, 0, column, false, REC_001, colSize);
5929        t_util.t_checkFetchColFromSlot(page, page.FIRST_SLOT_NUMBER, 1, column, false, REC_002, colSize);
5930        t_util.t_checkFetchColFromSlot(page, page.FIRST_SLOT_NUMBER, 2, column, false, REC_003, colSize);
5931        t_util.t_checkFetchColFromSlot(page, page.FIRST_SLOT_NUMBER, 3, column, false, REC_004, colSize);
5932        t_util.t_checkFetchColFromSlot(page, page.FIRST_SLOT_NUMBER, 4, column, false, REC_005, colSize);
5933        t_util.t_checkFetchColFromSlot(page, page.FIRST_SLOT_NUMBER, 5, column, false, REC_009, colSize);
5934        t_util.t_checkFetchColFromSlot(page, page.FIRST_SLOT_NUMBER, 6, column, false, REC_010, colSize);
5935        t_util.t_checkFetchColFromSlot(page, page.FIRST_SLOT_NUMBER, 7, column, false, REC_011, colSize);
5936        t_util.t_checkFetchColFromSlot(page, page.FIRST_SLOT_NUMBER, 8, column, false, REC_012, colSize);
5937        t_util.t_checkFetchColFromSlot(page, page.FIRST_SLOT_NUMBER, 9, column, false, REC_013, colSize);
5938        t_util.t_checkFetchColFromSlot(page, page.FIRST_SLOT_NUMBER, 10, column, false, REC_014, colSize);
5939        t_util.t_checkFetchColFromSlot(page, page.FIRST_SLOT_NUMBER, 11, column, false, REC_015, colSize);
5940        t_util.t_checkFetchColFromSlot(page, page.FIRST_SLOT_NUMBER, 12, column, false, REC_016, colSize);
5941        t_util.t_checkFetchColFromSlot(page, page.FIRST_SLOT_NUMBER, 13, column, false, REC_017, colSize);
5942        t_util.t_checkFetchColFromSlot(page, page.FIRST_SLOT_NUMBER, 14, column, false, REC_018, colSize);
5943        page.unlatch();
5944
5945
5946        if (segment != ContainerHandle.TEMPORARY_SEGMENT) {
5947            t_util.t_dropContainer(t, segment, cid); // cleanup
5948
}
5949        t_util.t_commit(t);
5950        t.close();
5951
5952        PASS("P056: segment = " + segment);
5953    }
5954
5955
5956
5957
5958    /**
5959       Sparse row test.
5960       Test sparse representation of rows using the FormatableBitSet class.
5961       Insert, fetch and update a row having gaps.
5962
5963        @exception T_Fail Unexpected behaviour from the API
5964        @exception StandardException Unexpected exception from the implementation
5965     */

5966    protected void P061() throws StandardException, T_Fail
5967    {
5968        long segment = 0;
5969        Transaction t = t_util.t_startTransaction();
5970        long cid = t_util.t_addContainer(t, segment);
5971
5972        int numCols = 6;
5973        T_RawStoreRow row1 = new T_RawStoreRow(numCols);
5974        row1.setColumn(0, (String JavaDoc) null);
5975        row1.setColumn(1, REC_001);
5976        row1.setColumn(2, (String JavaDoc) null);
5977        row1.setColumn(3, REC_002);
5978        row1.setColumn(4, (String JavaDoc) null);
5979        row1.setColumn(5, REC_003);
5980
5981        ContainerHandle c = t_util.t_openContainer(t, segment, cid, true);
5982        Page page = t_util.t_getPage(c, ContainerHandle.FIRST_PAGE_NUMBER);
5983        try
5984        {
5985            RecordHandle rh1 = t_util.t_insert(page, row1);
5986
5987            t_util.t_checkFetchCol(page, rh1, 1, numCols, REC_001);
5988            t_util.t_checkFetchCol(page, rh1, 3, numCols, REC_002);
5989            t_util.t_checkFetchCol(page, rh1, 5, numCols, REC_003);
5990
5991            t_util.t_checkUpdateCol(page, rh1, 1, numCols, "woody");
5992            t_util.t_checkUpdateCol(page, rh1, 3, numCols, "buzz");
5993            t_util.t_checkUpdateCol(page, rh1, 5, numCols, "andy");
5994
5995            t_util.t_checkUpdateCol(page, rh1, 2, numCols, "dino");
5996
5997            page.unlatch();
5998            page = null;
5999
6000            t_util.t_commit(t);
6001        }
6002        finally
6003        {
6004            if (page != null)
6005                page.unlatch();
6006            t_util.t_commit(t);
6007            t.close();
6008        }
6009
6010        PASS("P061");
6011    }
6012
6013
6014    /**
6015       Serializable column test.
6016       Want to make sure we hit some otherwise dead code in StoredPage, used
6017       for storing/reading Serializable/Externalizable data to/from a page.
6018
6019        @exception T_Fail Unexpected behaviour from the API
6020        @exception StandardException Unexpected exception from the implementation
6021     */

6022    protected void P071() throws StandardException, T_Fail
6023    {
6024        /*
6025        long segment = 0;
6026        Transaction t = t_util.t_startTransaction();
6027        long cid = t_util.t_addContainer(t, segment);
6028
6029        int numCols = 1;
6030        T_RawStoreRow row1 = new T_RawStoreRow(numCols);
6031        row1.setColumn(0, new T_Serializable(REC_001));
6032
6033        ContainerHandle c = t_util.t_openContainer(t, segment, cid, true);
6034        Page page = t_util.t_getPage(c, ContainerHandle.FIRST_PAGE_NUMBER);
6035        try
6036        {
6037            RecordHandle rh1 = t_util.t_insert(page, row1);
6038
6039            t_util.t_checkFetchSerCol(page, rh1, 0, numCols, new T_Serializable(REC_001));
6040
6041            page.unlatch();
6042            page = null;
6043
6044            t_util.t_commit(t);
6045        }
6046        finally
6047        {
6048            if (page != null)
6049                page.unlatch();
6050            t_util.t_commit(t);
6051            t.close();
6052        }
6053        */

6054
6055        PASS("P071");
6056    }
6057
6058
6059
6060    /*
6061    ** Update and update partial tests aimed at long rows
6062    */

6063
6064    /**
6065        Insert a single row and keep updating it, adding columns
6066        not using partial rows.
6067
6068        @exception T_Fail Unexpected behaviour from the API
6069        @exception StandardException Unexpected exception from the implementation
6070    */

6071    protected void P701(long segment) throws StandardException, T_Fail {
6072
6073        Transaction t = t_util.t_startTransaction();
6074
6075        long cid = t_util.t_addContainer(t, segment, 4096);
6076
6077        ContainerHandle c = t_util.t_openContainer(t, segment, cid, true);
6078        Page page = t_util.t_getPage(c, ContainerHandle.FIRST_PAGE_NUMBER);
6079        t_util.t_checkEmptyPage(page);
6080
6081        T_RawStoreRow row = new T_RawStoreRow(0);
6082        RecordHandle rh = t_util.t_insertAtSlot(page, 0, row, (byte) (Page.INSERT_INITIAL | Page.INSERT_OVERFLOW));
6083        t_util.t_checkFetch(page, rh, row);
6084
6085        page.unlatch();
6086        page = t_util.t_getPage(c, ContainerHandle.FIRST_PAGE_NUMBER);
6087
6088
6089        for (int i = 0; i < 10;i++) {
6090
6091            REPORT("P701 - iteration " + i);
6092            
6093            row = new T_RawStoreRow(i);
6094
6095            for (int j = 0; j < i; j++) {
6096                row.setColumn(j, 256, "XX" + j + "YY");
6097            }
6098
6099            page.update(rh, row.getRow(), (FormatableBitSet) null);
6100            page.unlatch();
6101            page = t_util.t_getPage(c, ContainerHandle.FIRST_PAGE_NUMBER);
6102
6103            t_util.t_checkFetch(page, rh, row);
6104        }
6105
6106        page.unlatch();
6107
6108        if (segment != ContainerHandle.TEMPORARY_SEGMENT) {
6109            t_util.t_dropContainer(t, segment, cid); // cleanup
6110
}
6111
6112
6113        t_util.t_commit(t);
6114
6115        t.close();
6116
6117        PASS("P701: segment = " + segment);
6118    }
6119    /*
6120    ** Update and update partial tests aimed at long rows
6121    */

6122
6123    /**
6124        Insert a single row and keep updating it, adding columns
6125        using partial rows.
6126
6127        @exception T_Fail Unexpected behaviour from the API
6128        @exception StandardException Unexpected exception from the implementation
6129    */

6130    protected void P702(long segment) throws StandardException, T_Fail {
6131
6132        Transaction t = t_util.t_startTransaction();
6133
6134        long cid = t_util.t_addContainer(t, segment, 4096);
6135
6136        ContainerHandle c = t_util.t_openContainer(t, segment, cid, true);
6137        Page page = t_util.t_getPage(c, ContainerHandle.FIRST_PAGE_NUMBER);
6138        t_util.t_checkEmptyPage(page);
6139
6140        T_RawStoreRow row = new T_RawStoreRow(0);
6141        RecordHandle rh = t_util.t_insertAtSlot(page, 0, row, (byte) (Page.INSERT_INITIAL | Page.INSERT_OVERFLOW));
6142        t_util.t_checkFetch(page, rh, row);
6143
6144        page.unlatch();
6145        page = t_util.t_getPage(c, ContainerHandle.FIRST_PAGE_NUMBER);
6146
6147
6148        for (int i = 0; i < 10;i++) {
6149
6150            REPORT("P702 - iteration " + i);
6151
6152            FormatableBitSet colList = new FormatableBitSet(i+1);
6153            colList.set(i);
6154
6155            T_RawStoreRow rowU = new T_RawStoreRow(i+1);
6156            rowU.setColumn(i, 256, "XX" + i + "YY");
6157
6158            page.update(rh, rowU.getRow(), colList);
6159            page.unlatch();
6160
6161            T_RawStoreRow rowF = new T_RawStoreRow(i+1);
6162
6163            for (int j = 0; j <= i; j++) {
6164                rowF.setColumn(j, 256, "XX" + j + "YY");
6165            }
6166
6167            page = t_util.t_getPage(c, ContainerHandle.FIRST_PAGE_NUMBER);
6168
6169            t_util.t_checkFetch(page, rh, rowF);
6170        }
6171        page.unlatch();
6172
6173        if (segment != ContainerHandle.TEMPORARY_SEGMENT) {
6174            t_util.t_dropContainer(t, segment, cid); // cleanup
6175
}
6176
6177        t_util.t_commit(t);
6178
6179        t.close();
6180
6181        PASS("P702: segment = " + segment);
6182    }
6183
6184    /**
6185        Simple set of partial row updates on a singel page with
6186        shrinking and expanding columns.
6187
6188        @exception T_Fail Unexpected behaviour from the API
6189        @exception StandardException Unexpected exception from the implementation
6190    */

6191
6192    protected void P703(long segment)
6193         throws StandardException, T_Fail
6194    {
6195        Transaction t = t_util.t_startTransaction();
6196
6197        long cid = t_util.t_addContainer(t, segment, 4096);
6198
6199        ContainerHandle c = t_util.t_openContainer(t, segment, cid, true);
6200        Page page = t_util.t_getPage(c, ContainerHandle.FIRST_PAGE_NUMBER);
6201        t_util.t_checkEmptyPage(page);
6202
6203        REPORT("P703 - start ");
6204        T_RawStoreRow row = new T_RawStoreRow(2);
6205        row.setColumn(0, REC_001);
6206        row.setColumn(1, REC_002);
6207        RecordHandle rh = t_util.t_insertAtSlot(page, 0, row, (byte) (Page.INSERT_INITIAL | Page.INSERT_OVERFLOW));
6208        t_util.t_checkFetch(page, rh, row);
6209        REPORT("P703 - insert Ok ");
6210
6211        page.unlatch();
6212        page = t_util.t_getPage(c, ContainerHandle.FIRST_PAGE_NUMBER);
6213
6214        // Perform 10 tests
6215
// 1 update col0 to grow
6216
// 2 update col1 to grow
6217
// 3 update col0 to shrink
6218
// 4 update col1 to shrink
6219
// 5 update col0 to null
6220
// 6 update col1 to null
6221
// 7 update col0 to non-null
6222
// 8 update col1 to non-null
6223
// 9 update no columns
6224
// 10 update both cols
6225

6226        P703Helper(page, rh, 0, REC_006, REC_002);
6227        REPORT("P703 - case 1 passed");
6228
6229        P703Helper(page, rh, 1, REC_007, REC_006);
6230        REPORT("P703 - case 2 passed");
6231
6232        P703Helper(page, rh, 0, REC_003, REC_007);
6233        REPORT("P703 - case 3 passed");
6234
6235        P703Helper(page, rh, 1, REC_004, REC_003);
6236        REPORT("P703 - case 4 passed");
6237
6238        P703Helper(page, rh, 0, null, REC_004);
6239        REPORT("P703 - case 5 passed");
6240
6241        P703Helper(page, rh, 1, null, null);
6242        REPORT("P703 - case 6 passed");
6243
6244        P703Helper(page, rh, 0, REC_002, null);
6245        REPORT("P703 - case 7 passed");
6246
6247        P703Helper(page, rh, 1, REC_001, REC_002);
6248        REPORT("P703 - case 8 passed");
6249
6250
6251
6252        P703Helper(page, rh, -1, REC_002, REC_001);
6253        REPORT("P703 - case 9 passed");
6254
6255        FormatableBitSet colList = new FormatableBitSet(2);
6256        colList.set(0);
6257        colList.set(1);
6258        row.setColumn(0, REC_004);
6259        row.setColumn(1, REC_003);
6260        page.update(rh, row.getRow(), colList);
6261        t_util.t_checkFetch(page, rh, row);
6262
6263
6264        REPORT("P703 - case 10 passed");
6265
6266
6267        page.unlatch();
6268
6269        if (segment != ContainerHandle.TEMPORARY_SEGMENT) {
6270            t_util.t_dropContainer(t, segment, cid); // cleanup
6271
}
6272
6273        t.commit();
6274
6275        t.close();
6276
6277        PASS("P703: segment = " + segment);
6278    }
6279
6280    private void P703Helper(Page page, RecordHandle rh, int colNum, String JavaDoc newVal, String JavaDoc unchangedCol)
6281        throws StandardException, T_Fail {
6282
6283        FormatableBitSet colList = new FormatableBitSet(2);
6284        T_RawStoreRow rowU = new T_RawStoreRow(2);
6285
6286        // -1 indicates no columns set in bit set
6287
if (colNum != -1) {
6288            colList.grow(colNum+1);
6289            colList.set(colNum);
6290            rowU.setColumn(colNum, newVal);
6291        } else {
6292            colNum = 0; // only used for read from now on
6293
}
6294        page.update(rh, rowU.getRow(), colList);
6295
6296        T_RawStoreRow row = new T_RawStoreRow(2);
6297        row.setColumn(colNum, newVal);
6298        row.setColumn(colNum == 0 ? 1 : 0, unchangedCol);
6299
6300        t_util.t_checkFetch(page, rh, row);
6301    }
6302
6303
6304    /**
6305        Insert a single row with multiple portions.
6306        Update fields in the various portions that grow.
6307
6308        @exception T_Fail Unexpected behaviour from the API
6309        @exception StandardException Unexpected exception from the implementation
6310    */

6311    protected void P704(long segment) throws StandardException, T_Fail {
6312
6313        Transaction t = t_util.t_startTransaction();
6314
6315        long cid = t_util.t_addContainer(t, segment, 4096);
6316
6317        ContainerHandle c = t_util.t_openContainer(t, segment, cid, true);
6318        Page page = t_util.t_getPage(c, ContainerHandle.FIRST_PAGE_NUMBER);
6319        t_util.t_checkEmptyPage(page);
6320
6321        // row has 15 cols, each with 200 (ish) bytes (100 null chars)
6322
// thus we would expect at least 3 pages
6323
T_RawStoreRow row = new T_RawStoreRow(15);
6324        for (int i = 0; i < 15; i++) {
6325            row.setColumn(i, 100, "XX" + i + "YY");
6326        }
6327
6328        RecordHandle rh = t_util.t_insertAtSlot(page, 0, row, (byte) (Page.INSERT_INITIAL | Page.INSERT_OVERFLOW));
6329        t_util.t_checkFetch(page, rh, row);
6330
6331        page.unlatch();
6332        page = t_util.t_getPage(c, ContainerHandle.FIRST_PAGE_NUMBER);
6333
6334
6335        // update the each column to grow to be a single page (800 bytes ish)
6336
for (int i = 0; i < 15;i++) {
6337
6338            REPORT("P704 - col " + i);
6339
6340            FormatableBitSet colList = new FormatableBitSet(i+1);
6341            colList.set(i);
6342
6343            T_RawStoreRow rowU = new T_RawStoreRow(i+1);
6344            rowU.setColumn(i, 400, "WW" + i + "UU");
6345
6346            page.update(rh, rowU.getRow(), colList);
6347            page.unlatch();
6348
6349            row.setColumn(i, 400, "WW" + i + "UU");
6350
6351            page = t_util.t_getPage(c, ContainerHandle.FIRST_PAGE_NUMBER);
6352
6353            t_util.t_checkFetch(page, rh, row);
6354        }
6355        page.unlatch();
6356
6357        if (segment != ContainerHandle.TEMPORARY_SEGMENT) {
6358            t_util.t_dropContainer(t, segment, cid); // cleanup
6359
}
6360
6361        t_util.t_commit(t);
6362
6363        t.close();
6364
6365        PASS("P704: segment = " + segment);
6366    }
6367
6368    /**
6369        Same as 704 but update fields in the reverse order.
6370
6371        @exception T_Fail Unexpected behaviour from the API
6372        @exception StandardException Unexpected exception from the implementation
6373    */

6374    protected void P705(long segment) throws StandardException, T_Fail {
6375
6376        Transaction t = t_util.t_startTransaction();
6377
6378        long cid = t_util.t_addContainer(t, segment, 4096);
6379
6380        ContainerHandle c = t_util.t_openContainer(t, segment, cid, true);
6381        Page page = t_util.t_getPage(c, ContainerHandle.FIRST_PAGE_NUMBER);
6382        t_util.t_checkEmptyPage(page);
6383
6384        // row has 15 cols, each with 200 (ish) bytes (100 null chars)
6385
// thus we would expect at least 3 pages
6386
T_RawStoreRow row = new T_RawStoreRow(15);
6387        for (int i = 0; i < 15; i++) {
6388            row.setColumn(i, 100, "XX" + i + "YY");
6389        }
6390
6391        RecordHandle rh = t_util.t_insertAtSlot(page, 0, row, (byte) (Page.INSERT_INITIAL | Page.INSERT_OVERFLOW));
6392        t_util.t_checkFetch(page, rh, row);
6393
6394        page.unlatch();
6395        page = t_util.t_getPage(c, ContainerHandle.FIRST_PAGE_NUMBER);
6396
6397
6398        // update the each column to grow to be a single page (800 bytes ish)
6399
for (int i = 14; i >=0; i--) {
6400
6401            REPORT("P705 - col " + i);
6402
6403            FormatableBitSet colList = new FormatableBitSet(i+1);
6404            colList.set(i);
6405
6406            T_RawStoreRow rowU = new T_RawStoreRow(i+1);
6407            rowU.setColumn(i, 400, "WW" + i + "UU");
6408
6409            page.update(rh, rowU.getRow(), colList);
6410            page.unlatch();
6411
6412            row.setColumn(i, 400, "WW" + i + "UU");
6413
6414            page = t_util.t_getPage(c, ContainerHandle.FIRST_PAGE_NUMBER);
6415
6416            t_util.t_checkFetch(page, rh, row);
6417        }
6418        page.unlatch();
6419
6420        if (segment != ContainerHandle.TEMPORARY_SEGMENT) {
6421            t_util.t_dropContainer(t, segment, cid); // cleanup
6422
}
6423
6424        t_util.t_commit(t);
6425
6426        t.close();
6427
6428        PASS("P705: segment = " + segment);
6429    }
6430
6431    /**
6432        Insert a single row with single or multiple portions.
6433        Update every other field with a long col
6434        The update each column back to a null
6435
6436        @exception T_Fail Unexpected behaviour from the API
6437        @exception StandardException Unexpected exception from the implementation
6438    */

6439    protected void P706(long segment, boolean multiPortion) throws StandardException, T_Fail {
6440
6441        Transaction t = t_util.t_startTransaction();
6442
6443        long cid = t_util.t_addContainer(t, segment, 4096);
6444
6445        ContainerHandle c = t_util.t_openContainer(t, segment, cid, true);
6446        Page page = t_util.t_getPage(c, ContainerHandle.FIRST_PAGE_NUMBER);
6447        t_util.t_checkEmptyPage(page);
6448
6449        // row has 15 cols, each with 200 (ish) bytes (100 null chars)
6450
// thus we would expect at least 3 pages
6451
T_RawStoreRow row = new T_RawStoreRow(15);
6452        for (int i = 0; i < 15; i++) {
6453    
6454            row.setColumn(i, multiPortion ? 100 : 10, "XX" + i + "YY");
6455        }
6456
6457        RecordHandle rh = t_util.t_insertAtSlot(page, 0, row, (byte) (Page.INSERT_INITIAL | Page.INSERT_OVERFLOW));
6458        t_util.t_checkFetch(page, rh, row);
6459
6460        page.unlatch();
6461        page = t_util.t_getPage(c, ContainerHandle.FIRST_PAGE_NUMBER);
6462
6463        // update every other column to be a long column
6464
for (int i = 0; i < 15;i++) {
6465
6466            if ((i % 2) == 0) {
6467                continue;
6468            }
6469
6470            REPORT("P706 : multiPortion " + multiPortion + " - col " + i);
6471
6472            FormatableBitSet colList = new FormatableBitSet(i+1);
6473            colList.set(i);
6474
6475            T_RawStoreRow rowU = new T_RawStoreRow(i+1);
6476            rowU.setColumn(i, 3000, "WW" + i + "UU"); // longer than 4096 page length
6477

6478            page.update(rh, rowU.getRow(), colList);
6479            page.unlatch();
6480
6481            row.setColumn(i, 3000, "WW" + i + "UU");
6482
6483            page = t_util.t_getPage(c, ContainerHandle.FIRST_PAGE_NUMBER);
6484
6485            t_util.t_checkFetch(page, rh, row);
6486        }
6487
6488        t_util.t_commit(t);
6489
6490        // update every column to a null
6491
c = t_util.t_openContainer(t, segment, cid, true);
6492        page = t_util.t_getPage(c, ContainerHandle.FIRST_PAGE_NUMBER);
6493        for (int i = 0; i < 15;i++) {
6494
6495            REPORT("P706 : update to null " + multiPortion + " - col " + i);
6496
6497            FormatableBitSet colList = new FormatableBitSet(i+1);
6498            colList.set(i);
6499
6500            T_RawStoreRow rowU = new T_RawStoreRow(i+1);
6501            rowU.setColumn(i, (String JavaDoc) null);
6502
6503            page.update(rh, rowU.getRow(), colList);
6504            page.unlatch();
6505
6506            row.setColumn(i, (String JavaDoc) null);
6507
6508            page = t_util.t_getPage(c, ContainerHandle.FIRST_PAGE_NUMBER);
6509
6510            t_util.t_checkFetch(page, rh, row);
6511        }
6512        page.unlatch();
6513
6514        if (segment != ContainerHandle.TEMPORARY_SEGMENT) {
6515            t_util.t_dropContainer(t, segment, cid); // cleanup
6516
}
6517
6518        t_util.t_commit(t);
6519
6520        t.close();
6521
6522        PASS("P706: multiPortion " + multiPortion + " segment = " + segment);
6523    }
6524
6525    /**
6526        Insert a single record that has several chunks
6527        and every other column is a long column
6528        @exception T_Fail Unexpected behaviour from the API
6529        @exception StandardException Unexpected exception from the implementation
6530    */

6531    protected void P707(long segment) throws StandardException, T_Fail {
6532
6533        Transaction t = t_util.t_startTransaction();
6534
6535        long cid = t_util.t_addContainer(t, segment, 4096);
6536
6537        ContainerHandle c = t_util.t_openContainer(t, segment, cid, true);
6538        Page page = t_util.t_getPage(c, ContainerHandle.FIRST_PAGE_NUMBER);
6539        t_util.t_checkEmptyPage(page);
6540
6541        T_RawStoreRow row = new T_RawStoreRow(20);
6542        for (int i = 0; i < 20; i++) {
6543            if ((i % 2) ==0)
6544                row.setColumn(i, 200, "XX" + i + "YY"); // big but first within a page
6545
else
6546                row.setColumn(i, 4000, "XX" + i + "YY"); // long column
6547
}
6548
6549        RecordHandle rh = t_util.t_insertAtSlot(page, 0, row, (byte) (Page.INSERT_INITIAL | Page.INSERT_OVERFLOW));
6550        t_util.t_checkFetch(page, rh, row);
6551
6552        page.unlatch();
6553
6554        if (segment != ContainerHandle.TEMPORARY_SEGMENT) {
6555            t_util.t_dropContainer(t, segment, cid); // cleanup
6556
}
6557
6558
6559        t_util.t_commit(t);
6560
6561        t.close();
6562
6563        PASS("P707: segment = " + segment);
6564    }
6565
6566    /**
6567        Insert a single row with single or multiple portions.
6568        Update every other field with a long col
6569        rollback.
6570        The update each column back to a null & rollback
6571
6572        @exception T_Fail Unexpected behaviour from the API
6573        @exception StandardException Unexpected exception from the implementation
6574    */

6575    protected void P708(long segment, boolean multiPortion) throws StandardException, T_Fail {
6576
6577        Transaction t = t_util.t_startTransaction();
6578
6579        long cid = t_util.t_addContainer(t, segment, 4096);
6580
6581        ContainerHandle c = t_util.t_openContainer(t, segment, cid, true);
6582        Page page = t_util.t_getPage(c, ContainerHandle.FIRST_PAGE_NUMBER);
6583        t_util.t_checkEmptyPage(page);
6584
6585        // row has 15 cols, each with 200 (ish) bytes (100 null chars)
6586
// thus we would expect at least 3 pages
6587
T_RawStoreRow row = new T_RawStoreRow(15);
6588        for (int i = 0; i < 15; i++) {
6589
6590            row.setColumn(i, multiPortion ? 100 : 10, "XX" + i + "YY");
6591        }
6592
6593        RecordHandle rh = t_util.t_insertAtSlot(page, 0, row, (byte) (Page.INSERT_INITIAL | Page.INSERT_OVERFLOW));
6594        t_util.t_checkFetch(page, rh, row);
6595
6596        page.unlatch();
6597        t_util.t_commit(t);
6598        c = t_util.t_openContainer(t, segment, cid, true);
6599
6600        page = t_util.t_getPage(c, ContainerHandle.FIRST_PAGE_NUMBER);
6601
6602        // update every other column to be a long column
6603
for (int i = 0; i < 15;i++) {
6604
6605            if ((i % 2) == 0) {
6606                continue;
6607            }
6608
6609            REPORT("P708 : multiPortion " + multiPortion + " - col " + i);
6610
6611            FormatableBitSet colList = new FormatableBitSet(i+1);
6612            colList.set(i);
6613
6614            T_RawStoreRow rowU = new T_RawStoreRow(i+1);
6615            rowU.setColumn(i, 3000, "WW" + i + "UU"); // longer than 4096 page length
6616

6617            page.update(rh, rowU.getRow(), colList);
6618        }
6619
6620        t_util.t_abort(t);
6621
6622        c = t_util.t_openContainer(t, segment, cid, false);
6623        page = t_util.t_getPage(c, ContainerHandle.FIRST_PAGE_NUMBER);
6624        t_util.t_checkFetch(page, rh, row);
6625        page.unlatch();
6626
6627        if (segment != ContainerHandle.TEMPORARY_SEGMENT) {
6628            t_util.t_dropContainer(t, segment, cid); // cleanup
6629
}
6630
6631        t_util.t_commit(t);
6632
6633        t.close();
6634
6635        PASS("P708: multiPortion " + multiPortion + " segment = " + segment);
6636    }
6637
6638
6639    /**
6640      P709:
6641      this test exercises purgeAtSlot , rollsback and purges the slot again,
6642      to make sure not logging the data does not have any impact on repurging
6643      the rollbacked purges.
6644      @exception T_Fail Unexpected behaviour from the API
6645      @exception StandardException Unexpected exception from the implementation
6646    */

6647    protected void P709()
6648         throws StandardException, T_Fail
6649    {
6650        logDataForPurges = false;
6651        Transaction t = t_util.t_startTransaction();
6652        long cid = t_util.t_addContainer(t,0);
6653        t_util.t_commit(t);
6654
6655    
6656        ContainerHandle c = t_util.t_openContainer(t, 0, cid, true);
6657        Page page = t_util.t_getPage(c, ContainerHandle.FIRST_PAGE_NUMBER);
6658
6659        // REPORT("insert 5 records");
6660
T_RawStoreRow row0 = new T_RawStoreRow(REC_001);
6661        T_RawStoreRow row1 = new T_RawStoreRow(REC_001);
6662        T_RawStoreRow row2 = new T_RawStoreRow(REC_002);
6663        T_RawStoreRow row3 = new T_RawStoreRow(REC_003);
6664        T_RawStoreRow row4 = new T_RawStoreRow(REC_004);
6665        
6666        RecordHandle r0, r1, r2, r3, r4;
6667        r0 = t_util.t_insertAtSlot(page, 0, row0);
6668        r1 = t_util.t_insertAtSlot(page, 1, row1);
6669        r2 = t_util.t_insertAtSlot(page, 2, row2);
6670        r3 = t_util.t_insertAtSlot(page, 3, row3);
6671        r4 = t_util.t_insertAtSlot(page, 4, row4);
6672
6673        if (r3 != null) page.deleteAtSlot(3, true, (LogicalUndo)null);
6674
6675        // REPORT("commit it");
6676
t_util.t_commit(t);
6677
6678        c = t_util.t_openContainer(t, 0, cid, true);
6679        page = t_util.t_getPage(c, ContainerHandle.FIRST_PAGE_NUMBER);
6680
6681        try
6682        {
6683            page.purgeAtSlot(-1, 1, logDataForPurges);
6684            throw T_Fail.testFailMsg("negative slot number did not cause an exception");
6685        }
6686        catch (StandardException se) {} // expected
6687

6688        try
6689        {
6690            page.purgeAtSlot(4, 4, logDataForPurges);
6691            throw T_Fail.testFailMsg("purging more rows than is on page did not cause an exception");
6692        }
6693        catch (StandardException se) {} // expected
6694

6695        // if not all the rows are there, do minimal test
6696
if (r4 == null)
6697        {
6698            int rcount = page.recordCount();
6699            page.purgeAtSlot(0, 1, logDataForPurges);
6700            if (page.recordCount() != rcount-1)
6701                T_Fail.testFailMsg("failed to purge a record, expect " +
6702                                   (rcount-1) + " got " + page.recordCount());
6703
6704            if (testRollback)
6705            {
6706                t_util.t_abort(t);
6707
6708                c = t_util.t_openContainer(t, 0, cid, true);
6709                page = t_util.t_getPage(c, ContainerHandle.FIRST_PAGE_NUMBER);
6710                if(logDataForPurges)
6711                    t_util.t_checkFetchBySlot(page, 0, REC_001,false, true);
6712                else
6713                    t_util.t_checkFetchBySlot(page, 0, REC_NULL,false, true);
6714                if (page.recordCount() != rcount)
6715                    T_Fail.testFailMsg("failed to rollback purge, expect " +
6716                                   rcount + " got " + page.recordCount());
6717            }
6718            else
6719            {
6720                t_util.t_commit(t);
6721            }
6722            PASS("mimimal purging P709");
6723            return;
6724        }
6725
6726        // REPORT("purge 2 records from middle");
6727
page.purgeAtSlot(1, 2, logDataForPurges);
6728        t_util.t_checkFetchBySlot(page, 0, REC_001,false, true);
6729        t_util.t_checkFetchBySlot(page, 1, REC_003,true, true);
6730        t_util.t_checkFetchBySlot(page, 2, REC_004,false, true);
6731
6732        if (page.recordCount() != 3)
6733            T_Fail.testFailMsg("page expect to have 3 records, recordCount() = " +
6734                               page.recordCount());
6735
6736        // REPORT("purge all records from the page");
6737
page.purgeAtSlot(0, 3, logDataForPurges);
6738        if (page.recordCount() != 0)
6739            T_Fail.testFailMsg("page expect to have 0 records, recordCount() = " +
6740                               page.recordCount());
6741
6742        if (testRollback)
6743        {
6744
6745            REPORT("testing rollback");
6746            t_util.t_abort(t);
6747
6748            c = t_util.t_openContainer(t, 0, cid, true);
6749            page = t_util.t_getPage(c, ContainerHandle.FIRST_PAGE_NUMBER);
6750
6751            if(logDataForPurges){
6752                t_util.t_checkFetchBySlot(page, 0, REC_001,false, true);
6753                t_util.t_checkFetchBySlot(page, 1, REC_001,false, true);
6754                t_util.t_checkFetchBySlot(page, 2, REC_002,false, true);
6755                t_util.t_checkFetchBySlot(page, 3, REC_003,true, true);
6756                t_util.t_checkFetchBySlot(page, 4, REC_004,false, true);
6757            }else
6758            {
6759                t_util.t_checkFetchBySlot(page, 0, REC_NULL,false, true);
6760                t_util.t_checkFetchBySlot(page, 1, REC_NULL,false, true);
6761                t_util.t_checkFetchBySlot(page, 2, REC_NULL,false, true);
6762                t_util.t_checkFetchBySlot(page, 3, REC_NULL,true, true);
6763                t_util.t_checkFetchBySlot(page, 4, REC_NULL,false, true);
6764            }
6765
6766            if (page.recordCount() != 5)
6767                T_Fail.testFailMsg("page expect to have 5 records, recordCount() = " +
6768                                   page.recordCount());
6769
6770            // REPORT("purge 3 records from the end");
6771
page.purgeAtSlot(2, 3, logDataForPurges);
6772            if(logDataForPurges)
6773            {
6774                t_util.t_checkFetchBySlot(page, 0, REC_001,false, true);
6775                t_util.t_checkFetchBySlot(page, 1, REC_001,false, true);
6776            }else
6777            {
6778                t_util.t_checkFetchBySlot(page, 0, REC_NULL,false, true);
6779                t_util.t_checkFetchBySlot(page, 1, REC_NULL,false, true);
6780            }
6781            if (page.recordCount() != 2)
6782                T_Fail.testFailMsg("page expect to have 2 records, recordCount() = " +
6783                                   page.recordCount());
6784
6785            // REPORT("rollback");
6786
t_util.t_abort(t);
6787
6788            c = t_util.t_openContainer(t, 0, cid, true);
6789            page = t_util.t_getPage(c, ContainerHandle.FIRST_PAGE_NUMBER);
6790            if(logDataForPurges){
6791                t_util.t_checkFetchBySlot(page, 0, REC_001,false, true);
6792                t_util.t_checkFetchBySlot(page, 1, REC_001,false, true);
6793                t_util.t_checkFetchBySlot(page, 2, REC_002,false, true);
6794                t_util.t_checkFetchBySlot(page, 3, REC_003,true, true);
6795                t_util.t_checkFetchBySlot(page, 4, REC_004,false, true);
6796            }else
6797            {
6798                t_util.t_checkFetchBySlot(page, 0, REC_NULL,false, true);
6799                t_util.t_checkFetchBySlot(page, 1, REC_NULL,false, true);
6800                t_util.t_checkFetchBySlot(page, 2, REC_NULL,false, true);
6801                t_util.t_checkFetchBySlot(page, 3, REC_NULL,true, true);
6802                t_util.t_checkFetchBySlot(page, 4, REC_NULL,false, true);
6803            }
6804
6805            if (page.recordCount() != 5)
6806                T_Fail.testFailMsg("page expect to have 5 records, recordCount() = " +
6807                                   page.recordCount());
6808
6809            // REPORT("make sure delete record is reconstituted as such");
6810
if (page.isDeletedAtSlot(1))
6811                T_Fail.testFailMsg("rolled back purged undeleted record cause record to be deleted");
6812            if (!page.isDeletedAtSlot(3))
6813                T_Fail.testFailMsg("rolled back purged deleted record cause record to be undeleted");
6814        }
6815
6816        REPORT("purging again the purges rolled back earlier");
6817        //purge again and this time do commit , instead of rollback.
6818
// REPORT("purge 2 records from middle");
6819
page.purgeAtSlot(1, 2, logDataForPurges);
6820        t_util.t_checkFetchBySlot(page, 0, REC_NULL,false, true);
6821        t_util.t_checkFetchBySlot(page, 1, REC_NULL,true, true);
6822        t_util.t_checkFetchBySlot(page, 2, REC_NULL,false, true);
6823
6824        if (page.recordCount() != 3)
6825            T_Fail.testFailMsg("page expect to have 3 records, recordCount() = " +
6826                               page.recordCount());
6827
6828        // REPORT("purge all records from the page");
6829
page.purgeAtSlot(0, 3, logDataForPurges);
6830        if (page.recordCount() != 0)
6831            T_Fail.testFailMsg("page expect to have 0 records, recordCount() = " +
6832                               page.recordCount());
6833        
6834        
6835        t_util.t_abort(t);
6836
6837        c = t_util.t_openContainer(t, 0, cid, true);
6838        page = t_util.t_getPage(c, ContainerHandle.FIRST_PAGE_NUMBER);
6839
6840        if (page.recordCount() != 5)
6841            T_Fail.testFailMsg("page expect to have 5 records, recordCount() = " +
6842                               page.recordCount());
6843
6844        // REPORT("purge 3 records from the end");
6845
page.purgeAtSlot(2, 3, logDataForPurges);
6846        t_util.t_checkFetchBySlot(page, 0, REC_NULL,false, true);
6847        t_util.t_checkFetchBySlot(page, 1, REC_NULL,false, true);
6848        if (page.recordCount() != 2)
6849            T_Fail.testFailMsg("page expect to have 2 records, recordCount() = " +
6850                               page.recordCount());
6851
6852        // REPORT("commit");
6853
t_util.t_commit(t);
6854
6855        c = t_util.t_openContainer(t, 0, cid, true);
6856        page = t_util.t_getPage(c, ContainerHandle.FIRST_PAGE_NUMBER);
6857        t_util.t_checkFetchBySlot(page, 0, REC_NULL,false, true);
6858        t_util.t_checkFetchBySlot(page, 1, REC_NULL,false, true);
6859
6860        if (page.recordCount() != 2)
6861                T_Fail.testFailMsg("page expect to have 2 records, recordCount() = " +
6862                                   page.recordCount());
6863
6864        
6865        PASS("P709");
6866
6867        t_util.t_dropContainer(t, 0, cid); // cleanup
6868
t_util.t_commit(t);
6869        t.close();
6870    }
6871
6872    
6873    /**
6874        Test space reclaimation - purging of a long rows with a rollback and
6875        purging againg with no data logging for purges
6876        @exception T_Fail Unexpected behaviour from the API
6877        @exception StandardException Unexpected exception from the implementation
6878     */

6879    protected void P710() throws StandardException, T_Fail
6880    {
6881        long segment = 0;
6882        Transaction t = t_util.t_startTransaction();
6883        long cid = t_util.t_addContainer(t, segment, 4096);
6884
6885        ContainerHandle c = t_util.t_openContainer(t, segment, cid, true);
6886        Page page = t_util.t_getPage(c, ContainerHandle.FIRST_PAGE_NUMBER);
6887        try
6888        {
6889            t_util.t_checkEmptyPage(page);
6890
6891            int insertFlag = Page.INSERT_INITIAL | Page.INSERT_OVERFLOW;
6892
6893            // insert a row with 100 columns from 200 to 400 bytes each and make it
6894
// sprawl across many pages.
6895
T_RawStoreRow r1 = new T_RawStoreRow(100);
6896            for (int i = 0; i < 100; i++)
6897                r1.setColumn(i, 100+i, REC_001);
6898
6899            RecordHandle rh1 = t_util.t_insertAtSlot(page, 0, r1, (byte)insertFlag);
6900            t_util.t_checkFetch(page, rh1, r1);
6901
6902            Page nextPage = t_util.t_addPage(c);
6903            long nextPageNumber = nextPage.getPageNumber();
6904            // deallocate it
6905
t_util.t_removePage(c, nextPage);
6906
6907            REPORT("P710 - Nextpage is " + nextPageNumber);
6908            page.unlatch();
6909            page = null;
6910            t_util.t_commit(t);
6911
6912            // See what the next page is.
6913
c = t_util.t_openContainer(t, segment, cid, true);
6914
6915            // Now purge that first row.
6916
page = t_util.t_getPage(c, ContainerHandle.FIRST_PAGE_NUMBER);
6917
6918            t_util.t_checkRecordCount(page, 1, 1);
6919            page.purgeAtSlot(0, 1, logDataForPurges);
6920
6921            t_util.t_checkEmptyPage(page);
6922            page.unlatch();
6923            page = null;
6924            t_util.t_commit(t);
6925
6926            // give some time for post commit to finish
6927
t_util.t_wait(10); // wait 10 milliseconds.
6928

6929            // reinsert r1, it should use no extra page than last time.
6930
c = t_util.t_openContainer(t, segment, cid, true);
6931            page = t_util.t_getPage(c, ContainerHandle.FIRST_PAGE_NUMBER);
6932
6933            RecordHandle rh2 = t_util.t_insertAtSlot(page, 0, r1, (byte)insertFlag);
6934            t_util.t_checkFetch(page, rh2, r1);
6935            page.unlatch();
6936            page = null;
6937
6938            // now verify that it used up no more page than last time
6939
nextPage = t_util.t_addPage(c);
6940            long checkNextPageNumber = nextPage.getPageNumber();
6941            nextPage.unlatch();
6942
6943            if (nextPageNumber != checkNextPageNumber)
6944                throw T_Fail.testFailMsg("fail to reuse row pieces expect next page=" +
6945                    nextPageNumber + " but got " + checkNextPageNumber );
6946
6947
6948            t_util.t_commit(t);
6949
6950            // Purge them and roll them back via savepoint. These should not
6951
// be reclaimed.
6952
c = t_util.t_openContainer(t, segment, cid, true);
6953            t.setSavePoint(SP1, null);
6954            page = t_util.t_getPage(c, ContainerHandle.FIRST_PAGE_NUMBER);
6955            t_util.t_checkRecordCount(page, 1, 1);
6956            page.purgeAtSlot(0, 1, logDataForPurges);
6957            page.unlatch();
6958            page = null;
6959
6960            // make sure we cannot get our hands on a page that is freed up by
6961
// the purge
6962
Page testPage = t_util.t_addPage(c);
6963            T_RawStoreRow testRow = new T_RawStoreRow(REC_001);
6964            t_util.t_insert(testPage, testRow);
6965            testPage.unlatch();
6966
6967            t.rollbackToSavePoint(SP1, null);
6968
6969            testPage = t_util.t_addPage(c);
6970            t_util.t_insert(testPage, testRow);
6971            testPage.unlatch();
6972
6973            t_util.t_commit(t);
6974            t_util.t_wait(10);
6975            
6976            c = t_util.t_openContainer(t, segment, cid, true);
6977
6978            testPage = t_util.t_addPage(c);
6979            t_util.t_insert(testPage, testRow);
6980            testPage.unlatch();
6981
6982            page = t_util.t_getPage(c, ContainerHandle.FIRST_PAGE_NUMBER);
6983            t_util.t_checkRecordCount(page, 1, 1);
6984
6985            //repurge again.
6986
page.purgeAtSlot(0, 1, logDataForPurges);
6987            t_util.t_abort(t);
6988            // t_util.t_checkFetch(page, rh2, r1);
6989
page = null;
6990            c = t_util.t_openContainer(t, segment, cid, true);
6991            page = t_util.t_getPage(c, ContainerHandle.FIRST_PAGE_NUMBER);
6992            t_util.t_checkRecordCount(page, 1, 1);
6993            //repurge again and do commit
6994
page.purgeAtSlot(0, 1, logDataForPurges);
6995            page.unlatch();
6996            page = null;
6997            t_util.t_commit(t);
6998            c = t_util.t_openContainer(t, segment, cid, true);
6999            page = t_util.t_getPage(c, ContainerHandle.FIRST_PAGE_NUMBER);
7000            t_util.t_checkRecordCount(page, 0, 0);
7001            page.unlatch();
7002            page = null;
7003            t_util.t_dropContainer(t, segment, cid); // cleanup
7004

7005        }
7006        finally
7007        {
7008            if (page != null)
7009                page.unlatch();
7010            t_util.t_commit(t);
7011            t.close();
7012        }
7013
7014        PASS("P710");
7015    }
7016
7017    
7018    /**
7019        Test space reclaimation - purging of a row with serveral long columns
7020        rollback and repurge them again.
7021
7022        @exception T_Fail Unexpected behaviour from the API
7023        @exception StandardException Unexpected exception from the implementation
7024     */

7025    protected void P711() throws StandardException, T_Fail
7026    {
7027
7028        long segment = 0;
7029        Transaction t = t_util.t_startTransaction();
7030        long cid = t_util.t_addContainer(t, segment, 4096);
7031
7032        ContainerHandle c = t_util.t_openContainer(t, segment, cid, true);
7033        Page page = t_util.t_getPage(c, ContainerHandle.FIRST_PAGE_NUMBER);
7034        try
7035        {
7036            t_util.t_checkEmptyPage(page);
7037
7038            int insertFlag = Page.INSERT_INITIAL | Page.INSERT_OVERFLOW;
7039            T_RawStoreRow r1 = new T_RawStoreRow(1);
7040            // insert a long column
7041
r1.setColumn(0, 5000, REC_001);
7042            RecordHandle rh1 = t_util.t_insertAtSlot(page, 0, r1, (byte) insertFlag);
7043            t_util.t_checkFetch(page, rh1, r1);
7044
7045            // insert a 6 column row, every other column is long
7046
T_RawStoreRow r2 = new T_RawStoreRow(6);
7047            r2.setColumn(0, 600, REC_001); // this takes ~1200 bytes
7048
r2.setColumn(1, 5000, REC_002); // this takes ~10000 bytes
7049
r2.setColumn(2, 600, REC_001);
7050            r2.setColumn(3, 5000, REC_002);
7051            r2.setColumn(4, 600, REC_001);
7052            r2.setColumn(5, 5000, REC_002);
7053            RecordHandle rh2 = t_util.t_insertAtSlot(page, 0, r2, (byte) insertFlag);
7054            t_util.t_checkFetch(page, rh2, r2);
7055
7056            // insert a long column - this should fail
7057
RecordHandle rh3 = t_util.t_insertAtSlot(page, 0, r1, (