db-derby-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From fuzzylo...@apache.org
Subject svn commit: r155990 [12/15] - in incubator/derby/code/trunk: ./ java/testing/ java/testing/org/apache/derbyTesting/functionTests/harness/ java/testing/org/apache/derbyTesting/functionTests/master/ java/testing/org/apache/derbyTesting/functionTests/suites/ java/testing/org/apache/derbyTesting/functionTests/tests/lang/ java/testing/org/apache/derbyTesting/functionTests/tests/store/ java/testing/org/apache/derbyTesting/functionTests/tests/unit/ java/testing/org/apache/derbyTesting/unitTests/ java/testing/org/apache/derbyTesting/unitTests/crypto/ java/testing/org/apache/derbyTesting/unitTests/harness/ java/testing/org/apache/derbyTesting/unitTests/lang/ java/testing/org/apache/derbyTesting/unitTests/services/ java/testing/org/apache/derbyTesting/unitTests/store/ java/testing/org/apache/derbyTesting/unitTests/util/
Date Thu, 03 Mar 2005 01:30:47 GMT
Propchange: incubator/derby/code/trunk/java/testing/org/apache/derbyTesting/unitTests/store/T_Recovery.java
------------------------------------------------------------------------------
    snv:eol-style = native

Added: incubator/derby/code/trunk/java/testing/org/apache/derbyTesting/unitTests/store/T_RowSource.java
URL: http://svn.apache.org/viewcvs/incubator/derby/code/trunk/java/testing/org/apache/derbyTesting/unitTests/store/T_RowSource.java?view=auto&rev=155990
==============================================================================
--- incubator/derby/code/trunk/java/testing/org/apache/derbyTesting/unitTests/store/T_RowSource.java (added)
+++ incubator/derby/code/trunk/java/testing/org/apache/derbyTesting/unitTests/store/T_RowSource.java Wed Mar  2 17:30:05 2005
@@ -0,0 +1,276 @@
+/*
+
+   Derby - Class org.apache.derbyTesting.unitTests.store.T_RowSource
+
+   Copyright 1999, 2005 The Apache Software Foundation or its licensors, as applicable.
+
+   Licensed under the Apache License, Version 2.0 (the "License");
+   you may not use this file except in compliance with the License.
+   You may obtain a copy of the License at
+
+      http://www.apache.org/licenses/LICENSE-2.0
+
+   Unless required by applicable law or agreed to in writing, software
+   distributed under the License is distributed on an "AS IS" BASIS,
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+   See the License for the specific language governing permissions and
+   limitations under the License.
+
+ */
+
+package org.apache.derbyTesting.unitTests.store;
+
+import org.apache.derby.iapi.store.access.*;
+
+import org.apache.derby.iapi.types.SQLInteger;
+
+import org.apache.derby.iapi.services.io.FormatableBitSet;
+
+import org.apache.derby.iapi.error.StandardException;
+
+import org.apache.derby.iapi.store.raw.Transaction;
+
+import org.apache.derby.iapi.types.DataValueDescriptor;
+
+import org.apache.derby.iapi.types.RowLocation;
+
+
+/**
+  A RowSource is the mechanism for iterating over a set of rows.  The RowSource
+  is the interface through which access recieved a set of rows from the client
+  for the purpose of inserting into a single container.
+
+  <p>
+  A RowSource can come from many sources - from rows that are from fast path
+  import, to rows coming out of a sort for index creation.
+
+  @see org.apache.derby.iapi.store.access.RowSource
+*/ 
+public class T_RowSource implements RowSource {
+
+	static public final int INTEGER_ROW_TYPE = 1;
+	static public final int STRING_ROW_TYPE = 2;
+
+	static protected final String REC_001 = "McLaren";
+	static protected final String REC_002 = "Ferrari";
+	static protected final String REC_003 = "Benetton";
+	static protected final String REC_004 = "Prost";
+	static protected final String REC_005 = "Tyrell";
+	static protected final String REC_006 = "012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789";
+	static protected final String REC_007 = "abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyz";
+	static protected final String REC_008 = "z";
+
+	static protected final int DEFAULT_ROW_COUNT = 500000;
+	static protected final int DEFAULT_COLUMN_COUNT = 13;
+	static protected final int DEFAULT_SEED = 53;	// some random number
+
+	private int rowCount;
+	private int columnCount;
+	private DataValueDescriptor row[];
+	private FormatableBitSet validColumns;
+	private boolean forceAbort;
+	private Transaction t;
+
+	/*
+	 *	constructor
+	 */
+	public T_RowSource() {
+
+		// default will create DEFAULT_ROW_COUNT rows,
+		// of DEFAULT_COLUMN_COUNT columns string type rows
+		// validColumns will be set to null.
+		this.rowCount = DEFAULT_ROW_COUNT;
+		this.columnCount = DEFAULT_COLUMN_COUNT;
+		this.row = new DataValueDescriptor[DEFAULT_COLUMN_COUNT];
+		row = setStringRow();
+	}
+
+	// if the caller does not pass in a validColumn, we will set it here
+	public T_RowSource(int count, int columnCount, int rowType, boolean forceAbort, Transaction t) {
+
+		this.rowCount = count;
+		this.columnCount = columnCount;
+		validColumns = new FormatableBitSet(columnCount);
+		for (int i = 0; i < columnCount; i++)
+			validColumns.set(i);
+
+		this.row = new DataValueDescriptor[columnCount];
+		if (rowType == INTEGER_ROW_TYPE)
+			setIntegerRow();
+		else
+			row = setStringRow();
+
+		this.forceAbort = forceAbort;
+		this.t = t;
+	}
+
+	// the caller has a chance to set the valisColumns to anything they want.
+	public T_RowSource(int count, int columnCount, int rowType, FormatableBitSet validColumns) {
+
+		this.rowCount = count;
+		this.columnCount = columnCount;
+		this.validColumns = validColumns;
+
+		this.row = new DataValueDescriptor[columnCount];
+		if (rowType == INTEGER_ROW_TYPE)
+			setIntegerRow();
+		else
+			row = setStringRow();
+	}
+
+	/*
+	 *	methods for RowSource
+	 */
+
+	/**
+	    @return true if more rows are coming, false if there is no more rows
+		in the RowSource
+	 * @exception StandardException		Thrown on error
+	 */
+	public boolean hasMoreRows() throws StandardException {
+		if (rowCount > 0)
+			return true;
+		else
+			return false;
+	}
+
+	/**
+		Get the next row as an array of column objects. The column objects can
+		be a JBMS Storable or any
+		Serializable/Externalizable/Formattable/Streaming type.  
+
+		@exception StandardException Derby Standard Error Policy
+	 */
+	public DataValueDescriptor[] getNextRowFromRowSource() 
+        throws StandardException {
+
+		if (this.rowCount <= 0)
+			return null;
+
+		// if we are testing error condition, force an abort now
+		if (forceAbort && (this.rowCount < 3))
+			t.abort();
+
+		this.rowCount--;
+		return row;
+	}
+
+	/**
+	  getValidColumns describes the DataValueDescriptor[] returned by all calls
+      to the getNextRowFromRowSource() call. 
+	*/
+	public FormatableBitSet getValidColumns() {
+		return validColumns;
+	} 
+
+	/**
+		closeRowSource tells the RowSource that it will no longer need to
+		return any rows and it can release any resource it may have.
+		Subsequent call to any method on the RowSource will result in undefined
+		behavior.  A closed rowSource can be closed again.
+	*/
+	public void closeRowSource() {
+
+		this.rowCount = 0;
+	}
+
+
+	/**
+		needsRowLocation returns true iff this the row source expects the
+		drainer of the row source to call rowLocation after getting a row from
+		getNextRowFromRowSource.
+
+		@return true iff this row source expects some row location to be
+		returned 
+		@see #rowLocation
+	 */
+	public boolean needsRowLocation() {
+		return false;
+	}
+
+	/**
+	 * @see RowSource#needsToClone
+	 */
+	public boolean needsToClone()
+	{
+		return true;
+	}
+
+	/**
+		rowLocation  is not implemented here
+	 */
+	public void rowLocation(RowLocation rl) {
+
+		rl = null;
+	}
+
+	/**
+		Get a copy of the template row.  Cast each column to
+		a CloneableObject and clone it.
+
+		@exception StandardException Derby Standard Error Policy
+	**/
+	public DataValueDescriptor[] getTemplate() throws StandardException {
+
+		return row;
+
+	}
+
+	// set all column of the row to integer object
+	private void setIntegerRow() {
+		for (int i = 0; i < columnCount; i++)
+			this.row[i] = new SQLInteger(i + DEFAULT_SEED);
+	}
+
+	private DataValueDescriptor[] setStringRow() {
+
+		T_RawStoreRow row = new T_RawStoreRow(columnCount);
+
+		for (int i = 0; i < columnCount; i++) {
+			switch (i % 13) {
+			case 0:
+				row.setColumn(i, (String) null);
+				break;
+			case 1:			
+				row.setColumn(i, REC_001);
+				break;
+			case 2:
+				row.setColumn(i, REC_002);
+				break;
+			case 3:
+				row.setColumn(i, REC_003);
+				break;
+			case 4:
+				row.setColumn(i, REC_004);
+				break;
+			case 5:
+				row.setColumn(i, REC_005);
+				break;
+			case 6:
+				row.setColumn(i, REC_006);
+				break;
+			case 7:
+				row.setColumn(i, REC_007);
+				break;
+			case 8:
+				row.setColumn(i, (String) null);
+				break;
+			case 9:
+				row.setColumn(i, REC_008);
+				break;
+			case 10:
+				row.setColumn(i, REC_007);
+				break;
+			case 11:
+				row.setColumn(i, (String) null);
+				break;
+			case 12:
+				row.setColumn(i, REC_006);
+				break;
+			default:
+				row.setColumn(i, REC_008);
+			}
+		}
+		return row.getRow();
+	}
+}

Propchange: incubator/derby/code/trunk/java/testing/org/apache/derbyTesting/unitTests/store/T_RowSource.java
------------------------------------------------------------------------------
    snv:eol-style = native

Added: incubator/derby/code/trunk/java/testing/org/apache/derbyTesting/unitTests/store/T_SecondaryIndexRow.java
URL: http://svn.apache.org/viewcvs/incubator/derby/code/trunk/java/testing/org/apache/derbyTesting/unitTests/store/T_SecondaryIndexRow.java?view=auto&rev=155990
==============================================================================
--- incubator/derby/code/trunk/java/testing/org/apache/derbyTesting/unitTests/store/T_SecondaryIndexRow.java (added)
+++ incubator/derby/code/trunk/java/testing/org/apache/derbyTesting/unitTests/store/T_SecondaryIndexRow.java Wed Mar  2 17:30:05 2005
@@ -0,0 +1,167 @@
+/*
+
+   Derby - Class org.apache.derbyTesting.unitTests.store.T_SecondaryIndexRow
+
+   Copyright 1997, 2005 The Apache Software Foundation or its licensors, as applicable.
+
+   Licensed under the Apache License, Version 2.0 (the "License");
+   you may not use this file except in compliance with the License.
+   You may obtain a copy of the License at
+
+      http://www.apache.org/licenses/LICENSE-2.0
+
+   Unless required by applicable law or agreed to in writing, software
+   distributed under the License is distributed on an "AS IS" BASIS,
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+   See the License for the specific language governing permissions and
+   limitations under the License.
+
+ */
+
+package org.apache.derbyTesting.unitTests.store;
+
+import org.apache.derby.impl.store.access.conglomerate.*;
+
+import org.apache.derby.iapi.services.sanity.SanityManager;
+
+import org.apache.derby.iapi.services.io.Storable;
+
+import org.apache.derby.iapi.error.StandardException;
+
+import org.apache.derby.iapi.types.DataValueDescriptor;
+
+import org.apache.derby.iapi.types.RowLocation;
+
+
+/**
+This class implements a row which will be stored in a secondary index on 
+a heap table.  
+<p>
+This class creates a new DataValueDescriptor array which will be the row used 
+to insert into the secondary index.  The fields of this object array are made 
+up of references to DataValueDescriptors provided by the caller: the 
+DataValueDescriptors in the template and a RowLocation.
+The interface is designed to support the standard access method interface
+where callers provide a single template and then read rows into that template
+over and over.  This class keeps a reference to the objects in the template
+and the rowlocation, 
+so the state of this object changes whenever the caller changes the template.
+The caller provides a template which will contain a heap row,
+and a RowLocation which provides the location of the row within the heap table.
+<p>
+So for example to create an index from a base table by reading the base table
+and inserting each row one at a time into the secondary index you would 
+do something like:
+
+DataValueDescriptors[] template = get_template_for_base_table();
+RowLocation            rowloc   = ScanController_var.newRowLocationTemplate();
+T_SecondaryIndexRow    indrow   = new T_SecondaryIndexRow();
+
+indrow.init(template, rowloc, numcols_in_index);
+
+while (ScanController_variable.next())
+{ 
+    fetch(template)
+    fetchLocation(rowloc)
+
+    ConglomerateController_on_btree.insert(indrow.getRow());
+}
+
+**/
+
+public class T_SecondaryIndexRow
+{
+
+    DataValueDescriptor[]     row;
+    RowLocation  init_rowlocation = null;
+
+    /* Constructors for This class: */
+    public T_SecondaryIndexRow(){}
+
+    /* Private/Protected methods of This class: */
+    /* Public Methods of T_SecondaryIndexRow class: */
+
+    /**
+     * get the rows location field.
+     *
+	 * @return The base table row location field from the secondary index.
+     *
+	 * @exception  StandardException  Standard exception policy.
+     **/
+    /*
+    private RowLocation getRowLocationField()
+		throws StandardException
+    {
+        return(init_rowlocation);
+    }
+    */
+
+    /**
+     * Initialize the class.
+     * <p>
+     * Save away pointers to the base table template row, and the rowlocation
+     * class.  Build default map of base columns to key columns, this map
+     * can be changed with setMap().
+     * <p>
+     *
+     * @param template    The template for the base table row.
+     * @param rowlocation The template for the row location.
+     * @param numkeys     The total number of columns in the secondary index
+     *                    including the rowlocation column.
+     *
+	 * @exception  StandardException  Standard exception policy.
+     **/
+    public void init(
+    DataValueDescriptor[]   template,
+    RowLocation             rowlocation,
+    int                     numkeys)
+        throws StandardException
+    {
+        if (SanityManager.DEBUG)
+        {
+            if (numkeys != (template.length + 1))
+                SanityManager.THROWASSERT(
+                    "numkeys = " + numkeys + 
+                    " template.length = " + template.length);
+        }
+
+        init_rowlocation = rowlocation;
+
+        /* create new object array for the row, and copy all object references 
+         * from template row to new secondary index row.
+         */
+        row = new DataValueDescriptor[numkeys];
+
+        System.arraycopy(template, 0, row, 0, template.length);
+
+        /* add the reference to the row location column as the last column */
+        row[row.length - 1] = rowlocation;
+    }
+
+    /**
+     * Return the secondary index row.
+     * <p>
+     * Return the DataValueDescriptor array that represents the branch row, 
+     * for use in raw store calls to fetch, insert, and update.
+     * <p>
+     *
+	 * @return The branch row object array.
+     **/
+    public DataValueDescriptor[] getRow()
+    {
+        return(this.row);
+    }
+
+	public String toString()
+	{
+		String s = "{ ";
+		for (int colid = 0; colid < row.length; colid++)
+		{
+			s += row[colid];
+			if (colid < (row.length - 1))
+				s += ", ";
+		}
+		s += " }";
+		return s;
+	}
+}

Propchange: incubator/derby/code/trunk/java/testing/org/apache/derbyTesting/unitTests/store/T_SecondaryIndexRow.java
------------------------------------------------------------------------------
    snv:eol-style = native

Added: incubator/derby/code/trunk/java/testing/org/apache/derbyTesting/unitTests/store/T_SortController.java
URL: http://svn.apache.org/viewcvs/incubator/derby/code/trunk/java/testing/org/apache/derbyTesting/unitTests/store/T_SortController.java?view=auto&rev=155990
==============================================================================
--- incubator/derby/code/trunk/java/testing/org/apache/derbyTesting/unitTests/store/T_SortController.java (added)
+++ incubator/derby/code/trunk/java/testing/org/apache/derbyTesting/unitTests/store/T_SortController.java Wed Mar  2 17:30:05 2005
@@ -0,0 +1,963 @@
+/*
+
+   Derby - Class org.apache.derbyTesting.unitTests.store.T_SortController
+
+   Copyright 1997, 2005 The Apache Software Foundation or its licensors, as applicable.
+
+   Licensed under the Apache License, Version 2.0 (the "License");
+   you may not use this file except in compliance with the License.
+   You may obtain a copy of the License at
+
+      http://www.apache.org/licenses/LICENSE-2.0
+
+   Unless required by applicable law or agreed to in writing, software
+   distributed under the License is distributed on an "AS IS" BASIS,
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+   See the License for the specific language governing permissions and
+   limitations under the License.
+
+ */
+
+package org.apache.derbyTesting.unitTests.store;
+
+// impl imports are the preferred way to create unit tests.
+import org.apache.derbyTesting.unitTests.harness.T_Generic;
+import org.apache.derbyTesting.unitTests.harness.T_Fail;
+
+import org.apache.derby.iapi.store.access.*;
+
+import org.apache.derby.iapi.services.context.ContextService;
+
+import org.apache.derby.iapi.services.monitor.Monitor;
+import org.apache.derby.iapi.services.io.Storable;
+
+import org.apache.derby.iapi.error.StandardException;
+
+import org.apache.derby.iapi.types.DataValueDescriptor;
+
+import org.apache.derby.iapi.reference.Property;
+
+import org.apache.derby.iapi.services.i18n.MessageService;
+
+import org.apache.derby.iapi.reference.SQLState;
+
+import org.apache.derby.iapi.types.SQLInteger;
+
+import java.util.Properties;
+import java.util.Vector;
+import java.util.StringTokenizer;
+import java.io.File;
+
+/**
+
+  Unit test for sorting.
+
+**/
+
+public class T_SortController extends T_Generic
+{
+	private static final String testService = "sortTest";
+
+	/** Set this to print out the rows that are inserted into
+	 ** and returned from each sort. **/
+	protected boolean verbose = false;
+
+	public String getModuleToTestProtocolName() {
+		return AccessFactory.MODULE;
+	}
+
+	private void setSortBufferSize(String buf_length) {
+		Properties p = System.getProperties();
+		p.put("derby.storage.sortBufferMax", buf_length);
+		System.setProperties(p);
+	}
+
+	/*
+	** Methods of T_SortController
+	*/
+
+	/**
+		@exception T_Fail test has failed
+	*/
+	protected void runTests() throws T_Fail
+	{
+		int failcount = 0;
+
+		// Get the AccessFactory to test.
+
+		// don't automatic boot this service if it gets left around
+		if (startParams == null) {
+			startParams = new Properties();
+		}
+		startParams.put(Property.NO_AUTO_BOOT, Boolean.TRUE.toString());
+		// remove the service directory to ensure a clean run
+		startParams.put(Property.DELETE_ON_CREATE, Boolean.TRUE.toString());
+
+		// see if we are testing encryption
+		startParams = T_Util.setEncryptionParam(startParams);
+
+		try {
+			REPORT("(unitTestMain) Testing " + "sortTest with default sort buffer size 1024");
+			AccessFactory store1024 = null;
+			failcount = runEachTest(store1024, "1024");
+
+			setSortBufferSize("4");
+			REPORT("(unitTestMain) Testing " + "sortTest with minimum sort buffer size 4");
+			AccessFactory store4 = null;
+			failcount += runEachTest(store4, "4");
+		}
+		catch (StandardException e)
+		{
+			String  msg = e.getMessage();
+			if (msg == null)
+				msg = e.getClass().getName();
+			REPORT("(unitTestMain) unexpected exception: " + msg);
+			throw T_Fail.exceptionFail(e);
+		}
+
+		if (failcount != 0)
+			throw T_Fail.testFailMsg("(unitTestMain)" + failcount + " cases failed.");
+
+		REPORT("(unitTestMain) succeeded");
+	}
+
+	protected int runEachTest(AccessFactory store, String tail) throws T_Fail, StandardException {
+
+		TransactionController tc = null;
+		int failcount = 0;
+
+		try {
+			store = (AccessFactory) Monitor.createPersistentService(getModuleToTestProtocolName(), 
+				testService + tail, startParams);
+		} catch (StandardException mse) {
+			throw T_Fail.exceptionFail(mse);
+		}
+		if (store == null) {
+			throw T_Fail.testFailMsg(getModuleToTestProtocolName() + " service not started.");
+		}
+
+		tc = store.getTransaction(
+                ContextService.getFactory().getCurrentContextManager());
+
+		if (!sortExample(tc))
+			failcount++;
+		if (!sortBufferCoverage(tc))
+			failcount++;
+		if (!sortBoundaries(tc))
+			failcount++;
+		if (!sortAllDuplicates(tc))
+			failcount++;
+		if (!sortDescending(tc))
+			failcount++;
+
+		tc.commit();
+		tc.destroy();
+
+		return failcount;
+	}
+
+	/**
+	This test is more of an example, with lots of comments to
+	explain what's going on.
+	**/
+	boolean sortExample(TransactionController tc)
+		throws StandardException
+	{
+		REPORT("(sortExample)");
+
+		// Create the rows to be sorted.
+		T_AccessRow row[] = new T_AccessRow[4];
+		row[0] = new T_AccessRow(18,  1,  2);
+		row[1] = new T_AccessRow( 6,  1, 18);
+		row[2] = new T_AccessRow(18,  1,  2);
+		row[3] = new T_AccessRow( 8, 14,  3);
+
+		// Decide on what kind of sort we want.  The properties
+		// can select different sorting techniques and options.
+		// But all sorts will result in the rows being in order.
+		// We don't care which sort technique is used, so set
+		// the properties to null.
+		Properties implParameters = null;
+
+		// Define the type of rows to be sorted by constructing
+		// a template.  Any row with the correct column types
+		// will do (the values in the template are never used,
+		// just the types).  The first row to be inserted will
+		// make a good template.
+		T_AccessRow template = row[0];
+
+		// Define the column ordering: sort on column 1
+		// (the second column) ascending, then column 2
+		// (the third column) ascending.
+		ColumnOrdering order[] = new ColumnOrdering[2];
+		order[0] = new T_ColumnOrderingImpl(1, true); // ascending
+		order[1] = new T_ColumnOrderingImpl(2, true); // ascending
+
+		// Tell the sort that the rows are not already in order.
+		boolean alreadyInOrder = false;
+
+		// Tell the sort that we're estimating that about 10
+		// rows will be inserted into the sort.  This is just
+		// a hint, the sort will still work if more rows or
+		// fewer rows are inserted.  But if the guess is close
+		// the sort will probably run faster.
+		long estimatedRows = 10;
+
+		// Tell the sort that we're estimating that the rows 
+        // are about 24 bytes long (3 int columns).
+		// This is just a hint, the sort will still work if rows of
+		// less or greater size are inserted.  But if the guess is close
+		// the sort will probably run faster.
+		int estimatedRowSize = 12;
+
+		// Create the sort.
+		long sortid = tc.createSort(implParameters, template.getRowArray(),
+			order, new T_DuplicateEliminator(template), alreadyInOrder, estimatedRows, 
+            estimatedRowSize);
+
+		// For the above sort, on the above input rows, we expect
+		// the output rows to look like this:
+		T_AccessRow expectedRow[] = new T_AccessRow[3];
+		expectedRow[0] = new T_AccessRow(18,  1,  2);
+		expectedRow[1] = new T_AccessRow( 6,  1, 18);
+		expectedRow[2] = new T_AccessRow( 8, 14,  3);
+
+		return testSort(tc, row, expectedRow, sortid);
+	}
+
+	/**
+	This test covers specific code paths in the external sort's
+	sort buffer.  It really should live closer to the sort buffer
+	since the effectiveness of this test is very very implementation
+	dependent.
+	**/
+	boolean sortBufferCoverage(TransactionController tc)
+		throws StandardException
+	{
+		REPORT("(sortBufferCoverage)");
+
+		// Create the rows to be sorted.  This sequence of values
+		// will provoke both single and double rotations on insert
+		// and both single and double rotations on removal.  Every
+		// row has a duplicate so that we can test duplicate handling
+		// in every tree position and through all manipulations.
+		T_AccessRow row[] = new T_AccessRow[16];
+		row[0] = new T_AccessRow(2, 0,  0); // first node
+		row[1] = new T_AccessRow(2, 0,  0);
+
+		row[2] = new T_AccessRow(4, 0,  0); // This makes the tree get higher [A7 case (i)]
+		row[3] = new T_AccessRow(4, 0,  0);
+
+		row[4] = new T_AccessRow(1, 0,  0); // This makes the tree more balanced [A7 case (ii)]
+		row[5] = new T_AccessRow(1, 0,  0);
+
+		row[6] = new T_AccessRow(7, 0,  0); // Tree getting higher again [A7 case (i)]
+		row[7] = new T_AccessRow(7, 0,  0);
+
+		row[8] = new T_AccessRow(8, 0,  0); // Tree getting out of balance [A7 case iii]
+									  // Single rotation will fix	[A8]
+		row[9] = new T_AccessRow(8, 0,  0);
+
+		row[10] = new T_AccessRow(3, 0,  0); // Tree getting out of balance [A7 case iii]
+									  // Double rotation will fix	[A9]
+		row[11] = new T_AccessRow(3, 0,  0);
+
+		row[12] = new T_AccessRow(5, 0,  0); // Tree more balanced [A7 case (ii)]
+		row[13] = new T_AccessRow(5, 0,  0);
+
+		row[14] = new T_AccessRow(6, 0,  0); // Tree getting higher again [A7 case (i)]
+		row[15] = new T_AccessRow(6, 0,  0);
+
+		// RESOLVE (nat) Should select the sort that being tested here.
+		Properties implParameters = null;
+
+		T_AccessRow template = row[0];
+
+		// Sort on column 0 (the first column) ascending
+		ColumnOrdering order[] = new ColumnOrdering[1];
+		order[0] = new T_ColumnOrderingImpl(0, true); // ascending
+
+		// The rows are not already in order.
+		boolean alreadyInOrder = false;
+
+		long estimatedRows = 20;
+		int estimatedRowSize = 12;
+
+		// Create the sort.
+		long sortid = tc.createSort(implParameters, template.getRowArray(),
+			order, new T_DummySortObserver(template), alreadyInOrder, estimatedRows,
+            estimatedRowSize);
+
+		// Rows should come out in order
+		T_AccessRow expectedRow[] = new T_AccessRow[16];
+		expectedRow[0] = new T_AccessRow(1, 0,  0);
+		expectedRow[1] = new T_AccessRow(1, 0,  0);
+		expectedRow[2] = new T_AccessRow(2, 0,  0);
+		expectedRow[3] = new T_AccessRow(2, 0,  0);
+		expectedRow[4] = new T_AccessRow(3, 0,  0);
+		expectedRow[5] = new T_AccessRow(3, 0,  0);
+		expectedRow[6] = new T_AccessRow(4, 0,  0);
+		expectedRow[7] = new T_AccessRow(4, 0,  0);
+		expectedRow[8] = new T_AccessRow(5, 0,  0);
+		expectedRow[9] = new T_AccessRow(5, 0,  0);
+		expectedRow[10] = new T_AccessRow(6, 0,  0);
+		expectedRow[11] = new T_AccessRow(6, 0,  0);
+		expectedRow[12] = new T_AccessRow(7, 0,  0);
+		expectedRow[13] = new T_AccessRow(7, 0,  0);
+		expectedRow[14] = new T_AccessRow(8, 0,  0);
+		expectedRow[15] = new T_AccessRow(8, 0,  0);
+
+		return testSort(tc, row, expectedRow, sortid);
+	}
+
+
+	/**
+	Test a sorts with one or zero rows.
+	**/
+	boolean sortBoundaries(TransactionController tc)
+		throws StandardException
+	{
+		int failcount = 0;
+		long sortid;
+		Properties implParameters;
+		T_AccessRow template;
+		ColumnOrdering order[];
+		boolean alreadyInOrder;
+		long estimatedRows;
+		int estimatedRowSize;
+		T_AccessRow input[];
+		T_AccessRow expected[];
+
+		/*
+		** The following sort parameters are the same for
+		** every sort tested in this method.
+		*/
+
+		implParameters = null;
+		template = new T_AccessRow(1, 1, 1);
+		order = new ColumnOrdering[1];
+		order[0] = new T_ColumnOrderingImpl(0, true); // ascending
+		estimatedRows = 10;
+		estimatedRowSize = 12;
+
+		/*
+		** A no-row sort.
+		*/
+
+		REPORT("(sortBoundaries) Sorting no rows");
+
+		input = new T_AccessRow[0];  // no rows in..
+		expected = new T_AccessRow[0];  // .. ==> no rows out!
+		alreadyInOrder = false;
+
+		sortid = tc.createSort(implParameters, template.getRowArray(),
+			order, new T_DummySortObserver(template), alreadyInOrder, estimatedRows, 
+            estimatedRowSize);
+
+		if (!testSort(tc, input, expected, sortid))
+			failcount++;
+
+		/*
+		** A no-row already in order sort.
+		*/
+
+		REPORT("(sortBoundaries) Sorting no rows - \"already in order\"");
+
+		input = new T_AccessRow[0];  // no rows in..
+		expected = new T_AccessRow[0];  // .. ==> no rows out!
+		alreadyInOrder = true;
+
+		sortid = tc.createSort(implParameters, template.getRowArray(),
+			order, new T_DummySortObserver(template), alreadyInOrder, estimatedRows, 
+            estimatedRowSize);
+
+		if (!testSort(tc, input, expected, sortid))
+			failcount++;
+
+		/*
+		** A single-row sort.
+		*/
+
+		REPORT("(sortBoundaries) Sorting a single row");
+
+		input = new T_AccessRow[1];
+		input[0] = new T_AccessRow(99, 88, 77);
+		expected = new T_AccessRow[1];
+		expected[0] = new T_AccessRow(99, 88, 77);
+		alreadyInOrder = false;
+
+		sortid = tc.createSort(implParameters, template.getRowArray(),
+			order, new T_DummySortObserver(template), alreadyInOrder, estimatedRows,
+            estimatedRowSize);
+
+		if (!testSort(tc, input, expected, sortid))
+			failcount++;
+
+		/*
+		** A single-row already-in-order sort.
+		*/
+
+		REPORT("(sortBoundaries) Sorting a single row - \"already in order\"");
+
+		input = new T_AccessRow[1];
+		input[0] = new T_AccessRow(99, 88, 77);
+		expected = new T_AccessRow[1];
+		expected[0] = new T_AccessRow(99, 88, 77);
+		alreadyInOrder = true;
+
+		sortid = tc.createSort(implParameters, template.getRowArray(),
+			order, new T_DummySortObserver(template), alreadyInOrder, estimatedRows, 
+            estimatedRowSize);
+
+		if (!testSort(tc, input, expected, sortid))
+			failcount++;
+
+		/*
+		** A single-row sort, eliminating duplicates
+		*/
+
+		REPORT("(sortBoundaries) Sorting a single row - \"eliminate duplicates\"");
+
+		input = new T_AccessRow[1];
+		input[0] = new T_AccessRow(99, 88, 77);
+		expected = new T_AccessRow[1];
+		expected[0] = new T_AccessRow(99, 88, 77);
+		alreadyInOrder = false;
+
+		sortid = tc.createSort(implParameters, template.getRowArray(),
+			order, new T_DuplicateEliminator(template), alreadyInOrder, estimatedRows, 
+            estimatedRowSize);
+
+		if (!testSort(tc, input, expected, sortid))
+			failcount++;
+
+		return failcount == 0;
+	}
+
+	/**
+	Test a sort where all the rows are duplicates
+	**/
+	boolean sortAllDuplicates(TransactionController tc)
+		throws StandardException
+	{
+		int failcount = 0;
+		long sortid;
+		Properties implParameters;
+		T_AccessRow template;
+		ColumnOrdering order[];
+		boolean alreadyInOrder;
+		long estimatedRows;
+		int estimatedRowSize;
+		T_AccessRow input[];
+		T_AccessRow expected[];
+
+		/*
+		** The following sort parameters will be used in every
+		** sort in this method.
+		*/
+		
+		implParameters = null;
+		template = new T_AccessRow(1, 1, 1);
+
+		// Ordering first two columns, ascending
+		order = new ColumnOrdering[2];
+		order[0] = new T_ColumnOrderingImpl(0, true); // ascending
+		order[1] = new T_ColumnOrderingImpl(1, true); // ascending
+
+		alreadyInOrder = false;
+		estimatedRows = 10;
+		estimatedRowSize = 12;
+
+		input = new T_AccessRow[5];
+		input[0] = new T_AccessRow(1, 1, 1);
+		input[1] = new T_AccessRow(1, 1, 1);
+		input[2] = new T_AccessRow(1, 1, 1);
+		input[3] = new T_AccessRow(1, 1, 1);
+		input[4] = new T_AccessRow(1, 1, 1);
+
+		/*
+		** When doing no aggregation, we expect every duplicate
+		** to come back out.
+		*/
+
+		REPORT("(sortAllDuplicates) no aggregation");
+
+		expected = new T_AccessRow[5];
+		expected[0] = new T_AccessRow(1, 1, 1);
+		expected[1] = new T_AccessRow(1, 1, 1);
+		expected[2] = new T_AccessRow(1, 1, 1);
+		expected[3] = new T_AccessRow(1, 1, 1);
+		expected[4] = new T_AccessRow(1, 1, 1);
+
+		sortid = tc.createSort(implParameters, template.getRowArray(),
+			order, new T_DummySortObserver(template), alreadyInOrder, estimatedRows, 
+            estimatedRowSize);
+
+		if (!testSort(tc, input, expected, sortid))
+			failcount++;
+
+		/*
+		** If we're doing duplicate elimination, we expect
+		** one row back (since they're all duplicates).
+		*/
+		
+		REPORT("(sortAllDuplicates) eliminate duplicates");
+
+		expected = new T_AccessRow[1];
+		expected[0] = new T_AccessRow(1, 1, 1);
+
+		sortid = tc.createSort(implParameters, template.getRowArray(),
+			order, new T_DuplicateEliminator(template), alreadyInOrder, estimatedRows, 
+            estimatedRowSize);
+
+		if (!testSort(tc, input, expected, sortid))
+			failcount++;
+
+		/*
+		** Another aggregation, this time summing up the 
+		** third column.
+		*/
+
+		REPORT("(sortAllDuplicates) sum aggregate");
+
+		expected = new T_AccessRow[1];
+		expected[0] = new T_AccessRow(1, 1, 5);
+
+		sortid = tc.createSort(implParameters, template.getRowArray(),
+			order, new T_SumForIntCol(2), alreadyInOrder, estimatedRows, 
+            estimatedRowSize);
+
+		if (!testSort(tc, input, expected, sortid))
+			failcount++;
+
+		return failcount == 0;
+	}
+
+	/**
+	Test a sort where we have some ascending and descending keys.
+	**/
+	boolean sortDescending(TransactionController tc)
+		throws StandardException
+	{
+		int failcount = 0;
+		long sortid;
+		Properties implParameters;
+		T_AccessRow template;
+		ColumnOrdering order[];
+		boolean alreadyInOrder;
+		long estimatedRows;
+		int estimatedRowSize;
+		T_AccessRow expected[];
+
+		/*
+		** The following sort parameters will be used in every
+		** sort in this method.
+		*/
+		
+		implParameters = null;
+		template = new T_AccessRow(1, 1, 1);
+
+		alreadyInOrder = false;
+		estimatedRows = 10;
+		estimatedRowSize = 12;
+
+		/*
+		** Straight descending sort.
+		*/
+
+		REPORT("(sortDescending) no aggregation");
+
+		order = new ColumnOrdering[2];
+		order[0] = new T_ColumnOrderingImpl(0, false); // descending
+		order[1] = new T_ColumnOrderingImpl(1, false); // descending
+
+		expected = new T_AccessRow[10];
+		expected[0] = new T_AccessRow(8, 1, 1);
+		expected[1] = new T_AccessRow(4, 8, 1);
+		expected[2] = new T_AccessRow(4, 2, 1);
+		expected[3] = new T_AccessRow(4, 1, 1);
+		expected[4] = new T_AccessRow(3, 8, 1);
+		expected[5] = new T_AccessRow(3, 5, 1);
+		expected[6] = new T_AccessRow(3, 3, 1);
+		expected[7] = new T_AccessRow(3, 3, 1);
+		expected[8] = new T_AccessRow(3, 3, 1);
+		expected[9] = new T_AccessRow(1, 1, 1);
+
+		sortid = tc.createSort(implParameters, template.getRowArray(),
+			order, new T_DummySortObserver(template), alreadyInOrder, estimatedRows,
+            estimatedRowSize);
+
+		if (!testSort(tc, getSortDescendingInput(), expected, sortid))
+			failcount++;
+
+		/*
+		** Descending sort eliminating duplicates
+		*/
+
+		REPORT("(sortDescending) eliminate duplicates");
+
+		order = new ColumnOrdering[2];
+		order[0] = new T_ColumnOrderingImpl(0, false); // descending
+		order[1] = new T_ColumnOrderingImpl(1, false); // descending
+
+		expected = new T_AccessRow[8];
+		expected[0] = new T_AccessRow(8, 1, 1);
+		expected[1] = new T_AccessRow(4, 8, 1);
+		expected[2] = new T_AccessRow(4, 2, 1);
+		expected[3] = new T_AccessRow(4, 1, 1);
+		expected[4] = new T_AccessRow(3, 8, 1);
+		expected[5] = new T_AccessRow(3, 5, 1);
+		expected[6] = new T_AccessRow(3, 3, 1);
+		expected[7] = new T_AccessRow(1, 1, 1);
+
+		sortid = tc.createSort(implParameters, template.getRowArray(),
+			order, new T_DuplicateEliminator(template), alreadyInOrder, estimatedRows,
+            estimatedRowSize);
+
+		if (!testSort(tc, getSortDescendingInput(), expected, sortid))
+			failcount++;
+
+		/*
+		** Eliminate duplicates, ascending on second column.
+		*/
+
+		REPORT("(sortDescending) descending/ascending - eliminate duplicates");
+
+		order = new ColumnOrdering[2];
+		order[0] = new T_ColumnOrderingImpl(0, false); // descending
+		order[1] = new T_ColumnOrderingImpl(1, true); // ascending
+
+		expected = new T_AccessRow[8];
+		expected[0] = new T_AccessRow(8, 1, 1);
+		expected[1] = new T_AccessRow(4, 1, 1);
+		expected[2] = new T_AccessRow(4, 2, 1);
+		expected[3] = new T_AccessRow(4, 8, 1);
+		expected[4] = new T_AccessRow(3, 3, 1);
+		expected[5] = new T_AccessRow(3, 5, 1);
+		expected[6] = new T_AccessRow(3, 8, 1);
+		expected[7] = new T_AccessRow(1, 1, 1);
+
+		sortid = tc.createSort(implParameters, template.getRowArray(),
+			order, new T_DuplicateEliminator(template), alreadyInOrder, estimatedRows,
+            estimatedRowSize);
+
+		if (!testSort(tc, getSortDescendingInput(), expected, sortid))
+			failcount++;
+
+
+		return failcount == 0;
+	}
+
+	private T_AccessRow[] getSortDescendingInput()
+	{
+		T_AccessRow[] input;
+
+		input = new T_AccessRow[10];
+		input[0] = new T_AccessRow(8, 1, 1);
+		input[1] = new T_AccessRow(1, 1, 1);
+		input[2] = new T_AccessRow(3, 5, 1);
+		input[3] = new T_AccessRow(4, 1, 1);
+		input[4] = new T_AccessRow(3, 3, 1);
+		input[5] = new T_AccessRow(3, 8, 1);
+		input[6] = new T_AccessRow(3, 3, 1);
+		input[7] = new T_AccessRow(3, 3, 1);
+		input[8] = new T_AccessRow(4, 2, 1);
+		input[9] = new T_AccessRow(4, 8, 1);
+
+		return input;
+	}
+
+
+	/**
+	Insert the given rows into the given sort, and check that the
+	rows retrieved from the sort match the output rows.
+	**/
+	boolean testSort(TransactionController tc, T_AccessRow in[], T_AccessRow outrow[], long sortid)
+		throws StandardException
+	{
+		// Open a sort controller for inserting the rows.
+		SortController sort = tc.openSort(sortid);
+
+		// Insert the rows to be sorted.
+		for (int i = 0; i < in.length; i++)
+		{
+			if (verbose)
+				REPORT("(testSort) in: " + in[i]);
+			sort.insert(in[i].getRowArray());
+		}
+
+		// Close the sort controller.  This makes the rows
+		// available to be retrieved.
+        // It also means we are getting final sort statistics.
+        sort.close();
+
+        // Test the SortInfo part of sort.
+        SortInfo   sort_info = sort.getSortInfo();
+        Properties sortprop      = sort_info.getAllSortInfo(null);
+
+        String sortType = sortprop.getProperty(
+				MessageService.getTextMessage(SQLState.STORE_RTS_SORT_TYPE));
+        int numRowsInput = Integer.parseInt(sortprop.getProperty(
+			MessageService.getTextMessage(SQLState.STORE_RTS_NUM_ROWS_INPUT)));
+        int numRowsOutput = Integer.parseInt(sortprop.getProperty(
+			MessageService.getTextMessage(SQLState.STORE_RTS_NUM_ROWS_OUTPUT)));
+
+		String external =
+			  MessageService.getTextMessage(SQLState.STORE_RTS_EXTERNAL);
+		String internal =
+			 MessageService.getTextMessage(SQLState.STORE_RTS_INTERNAL);
+        if (sortType.compareTo(internal) != 0 &&
+            sortType.compareTo(external) != 0)
+            FAIL("(testSort) unknown sortType.  Expected internal or external, got " + sortType);
+
+        if (numRowsInput != in.length)
+            FAIL("(testSort) SortInfo.numRowsInput (value: " + numRowsInput +
+                ") is not equal to in.length (value: " + in.length + ")");
+
+        if (numRowsOutput != outrow.length)
+            FAIL("(testSort) SortInfo.numRowsOutput (value: " +
+                numRowsOutput + ") is not equal to outrow.length (value: " + outrow.length + ")");
+
+		if (sortType.equals(external))
+        {
+            int numMergeRuns = Integer.parseInt(sortprop.getProperty(
+			 MessageService.getTextMessage(SQLState.STORE_RTS_NUM_MERGE_RUNS)));
+            Vector mergeRuns = new Vector();
+            StringTokenizer st = new StringTokenizer(sortprop.getProperty(
+			 MessageService.getTextMessage(SQLState.STORE_RTS_MERGE_RUNS_SIZE)),
+			 "[],",false);
+            while (st.hasMoreTokens())
+                mergeRuns.addElement(Integer.valueOf(st.nextToken().trim()));
+
+            if (mergeRuns.size() != numMergeRuns)
+                FAIL("(testSort) the number of elements in vector SortInfo.mergeRunsSize (value: " +
+                mergeRuns.size() + " ) is not equal to SortInfo.numMergeRuns (value: " +
+                numMergeRuns + " )");
+
+            int totRunSize = 0;
+            for (int i = 0; i < mergeRuns.size(); i++)
+                totRunSize += ((Integer) mergeRuns.elementAt(i)).intValue();
+            if (totRunSize != numRowsInput)
+               FAIL("(testSort) the sum of the elements of the vector SortInfo.mergeRunsSize (value: " +
+                totRunSize + " ) is not equal to SortInfo.numRowsInput (value: " +
+                numRowsInput + " )");
+        }
+
+		sort = null;
+
+		// Open a sort scan for reading the rows back.
+		ScanController scan = tc.openSortScan(sortid, false);
+
+		// Things that could go wrong.
+		boolean mismatch = false;
+		boolean toofew = false;
+		boolean toomany = false;
+
+		// Fetch the sorted rows and compare them to the rows
+		// in the outrow array.
+		T_AccessRow result = new T_AccessRow(3);
+		for (int i = 0; i < outrow.length; i++)
+		{
+			if (scan.next() == false)
+			{
+				// We were expecting the i'th row from outrow, but
+				// it didn't show up!
+				toofew = true;
+				FAIL("(testSort) Too few rows in sort output");
+				break;
+			}
+
+			scan.fetch(result.getRowArray());
+			if (verbose)
+				REPORT("(testSort) out: " + result);
+
+			if (!result.equals(outrow[i]))
+			{
+				// The i'th row from the sort didn't match the
+				// i'th row from out.
+				mismatch = true;
+				FAIL("(testSort) row " + result + " != " + outrow[i]);
+			}
+		}
+
+		// We should not see any more rows out of the sort,
+		// since we've exhausted the out array.
+		while (scan.next() == true)
+		{
+			scan.fetch(result.getRowArray());
+			if (verbose)
+				REPORT("(testSort) out: " + result);
+			toomany = true;
+			FAIL("(testSort) Extra row");
+		}
+
+        // Test the ScanInfo part of sort.
+        ScanInfo   scan_info = scan.getScanInfo();
+        Properties prop      = scan_info.getAllScanInfo(null);
+
+        if (prop.getProperty(
+				MessageService.getTextMessage(SQLState.STORE_RTS_SCAN_TYPE)
+							).compareTo(
+				MessageService.getTextMessage(SQLState.STORE_RTS_SORT)) != 0)
+        {
+            FAIL("(testSort) wrong scanType.  Expected sort, got " +
+                prop.getProperty(
+					MessageService.getTextMessage(
+												SQLState.STORE_RTS_SCAN_TYPE)));
+        }
+
+        if (tc.countOpens(TransactionController.OPEN_CREATED_SORTS) != 1)
+        {
+            FAIL("(testSort) sort count before close is wrong: " +
+                 tc.countOpens(TransactionController.OPEN_CREATED_SORTS));
+        }
+
+		// Close the scan controller (which implicitly destroys the sort).
+		scan.close();
+		scan = null;
+
+        if (tc.countOpens(TransactionController.OPEN_CREATED_SORTS) != 1)
+        {
+            FAIL("(testSort) sort count after close is wrong: " +
+                 tc.countOpens(TransactionController.OPEN_CREATED_SORTS));
+        }
+
+        tc.dropSort(sortid);
+
+        if (tc.countOpens(TransactionController.OPEN_CREATED_SORTS) > 0)
+        {
+            FAIL("(testSort) a sort is still open.");
+        }
+
+		return (!mismatch && !toofew && !toomany);
+	}
+}
+
+
+class T_DummySortObserver implements SortObserver
+{
+	T_AccessRow  template;
+	Vector vector;
+
+	T_DummySortObserver(T_AccessRow template)
+	{
+		this.template = template;
+		vector = new Vector();
+	}
+
+	/*
+	 * Methods of SortObserver
+	 */
+	public DataValueDescriptor[] insertNonDuplicateKey(
+    DataValueDescriptor[] insertRow)	
+	{
+		return insertRow;
+	}
+
+	public DataValueDescriptor[] insertDuplicateKey(
+    DataValueDescriptor[]   insertRow, 
+    DataValueDescriptor[]   existingRow)
+	{
+		return insertRow;
+	}
+
+	public void addToFreeList(
+    DataValueDescriptor[]   objectArray, 
+    int                     maxFreeListSize)
+	{
+		if (vector.size() < maxFreeListSize)
+		{
+			vector.addElement(objectArray);
+		}
+	}
+
+	public DataValueDescriptor[] getArrayClone()
+		throws StandardException
+	{
+		int lastElement = vector.size();
+
+		if (lastElement > 0)
+		{
+			DataValueDescriptor[] retval = 
+                (DataValueDescriptor[]) vector.elementAt(lastElement - 1);
+			vector.removeElementAt(lastElement - 1);
+			return retval;
+		}
+		return template.getRowArrayClone();
+	}
+}
+
+class T_DuplicateEliminator extends T_DummySortObserver
+{
+
+	T_DuplicateEliminator(T_AccessRow template)
+	{
+		super(template);
+	}
+	/*
+	 * Methods of SortObserver
+	 */
+	public DataValueDescriptor[] insertNonDuplicateKey(
+    DataValueDescriptor[] insertRow)	
+	{
+		return insertRow;
+	}
+
+	public DataValueDescriptor[] insertDuplicateKey(
+    DataValueDescriptor[] insertRow, 
+    DataValueDescriptor[] existingRow)
+	{
+		return null;
+	}
+}
+
+class T_SumForIntCol implements SortObserver
+{
+	private int columnId;
+	
+	T_SumForIntCol(int columnId)
+	{
+		this.columnId = columnId;
+	}
+
+	/*
+	 * Methods of SortObserver
+	 */
+
+	public DataValueDescriptor[] insertNonDuplicateKey(
+    DataValueDescriptor[] insertRow)	
+	{
+		return insertRow;
+	}
+
+	public DataValueDescriptor[] insertDuplicateKey(
+    DataValueDescriptor[] insertRow, 
+    DataValueDescriptor[] existingRow)
+		throws StandardException
+	{
+
+		// We know, because this is a test program and it's only
+		// used this way, that we can safely cast the arguments
+		// to SQLInteger.
+		SQLInteger increment = (SQLInteger) insertRow[columnId];
+		SQLInteger sum = (SQLInteger) existingRow[columnId];
+
+		// Perform the aggregation.
+		sum.plus(sum, increment, sum);
+
+		return null;
+	}
+
+	public void addToFreeList(
+    DataValueDescriptor[]   objectArray, 
+    int                     maxFreeListSize)
+	{
+	}
+
+	public DataValueDescriptor[] getArrayClone()
+		throws StandardException
+	{
+		return null;
+	}
+}
+

Propchange: incubator/derby/code/trunk/java/testing/org/apache/derbyTesting/unitTests/store/T_SortController.java
------------------------------------------------------------------------------
    snv:eol-style = native

Added: incubator/derby/code/trunk/java/testing/org/apache/derbyTesting/unitTests/store/T_StoreCostResult.java
URL: http://svn.apache.org/viewcvs/incubator/derby/code/trunk/java/testing/org/apache/derbyTesting/unitTests/store/T_StoreCostResult.java?view=auto&rev=155990
==============================================================================
--- incubator/derby/code/trunk/java/testing/org/apache/derbyTesting/unitTests/store/T_StoreCostResult.java (added)
+++ incubator/derby/code/trunk/java/testing/org/apache/derbyTesting/unitTests/store/T_StoreCostResult.java Wed Mar  2 17:30:05 2005
@@ -0,0 +1,77 @@
+/*
+
+   Derby - Class org.apache.derbyTesting.unitTests.store.T_StoreCostResult
+
+   Copyright 1998, 2005 The Apache Software Foundation or its licensors, as applicable.
+
+   Licensed under the Apache License, Version 2.0 (the "License");
+   you may not use this file except in compliance with the License.
+   You may obtain a copy of the License at
+
+      http://www.apache.org/licenses/LICENSE-2.0
+
+   Unless required by applicable law or agreed to in writing, software
+   distributed under the License is distributed on an "AS IS" BASIS,
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+   See the License for the specific language governing permissions and
+   limitations under the License.
+
+ */
+
+package org.apache.derbyTesting.unitTests.store;
+
+import org.apache.derby.iapi.store.access.*;
+
+/**
+
+Manage the result information from a single call to 
+StoreCostController.getScanCost().
+<p>
+@see StoreCostController
+
+**/
+
+public class T_StoreCostResult implements StoreCostResult
+{
+    long    row_count;
+    double  cost;
+
+    /**
+     * Get the estimated row count.
+     **/
+    public long getEstimatedRowCount()
+    {
+        return(row_count);
+    }
+
+    /**
+     * Set the estimated row count.
+     **/
+    public void setEstimatedRowCount(
+    long count)
+    {
+        row_count = count;
+    }
+
+    /**
+     * Get the estimated cost.
+     **/
+    public double getEstimatedCost()
+    {
+        return(cost);
+    }
+
+    /**
+     * Set the estimated cost.
+     **/
+    public void setEstimatedCost(
+    double input_cost)
+    {
+        this.cost = input_cost;
+    }
+
+    public String toString()
+    {
+        return("(row count = " + row_count + ", cost = " + cost + ")");
+    }
+}

Propchange: incubator/derby/code/trunk/java/testing/org/apache/derbyTesting/unitTests/store/T_StoreCostResult.java
------------------------------------------------------------------------------
    snv:eol-style = native

Added: incubator/derby/code/trunk/java/testing/org/apache/derbyTesting/unitTests/store/T_StreamFile.java
URL: http://svn.apache.org/viewcvs/incubator/derby/code/trunk/java/testing/org/apache/derbyTesting/unitTests/store/T_StreamFile.java?view=auto&rev=155990
==============================================================================
--- incubator/derby/code/trunk/java/testing/org/apache/derbyTesting/unitTests/store/T_StreamFile.java (added)
+++ incubator/derby/code/trunk/java/testing/org/apache/derbyTesting/unitTests/store/T_StreamFile.java Wed Mar  2 17:30:05 2005
@@ -0,0 +1,389 @@
+/*
+
+   Derby - Class org.apache.derbyTesting.unitTests.store.T_StreamFile
+
+   Copyright 1997, 2005 The Apache Software Foundation or its licensors, as applicable.
+
+   Licensed under the Apache License, Version 2.0 (the "License");
+   you may not use this file except in compliance with the License.
+   You may obtain a copy of the License at
+
+      http://www.apache.org/licenses/LICENSE-2.0
+
+   Unless required by applicable law or agreed to in writing, software
+   distributed under the License is distributed on an "AS IS" BASIS,
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+   See the License for the specific language governing permissions and
+   limitations under the License.
+
+ */
+
+package org.apache.derbyTesting.unitTests.store;
+
+import org.apache.derbyTesting.unitTests.harness.T_MultiThreadedIterations;
+import org.apache.derbyTesting.unitTests.harness.T_Fail;
+
+import org.apache.derby.impl.store.raw.data.*;
+
+import org.apache.derby.iapi.services.context.ContextService;
+import org.apache.derby.iapi.services.context.ContextManager;
+import org.apache.derby.iapi.services.locks.*;
+import org.apache.derby.iapi.services.property.PropertyUtil;
+import org.apache.derby.iapi.services.monitor.Monitor;
+import org.apache.derby.iapi.services.sanity.SanityManager;
+import org.apache.derby.iapi.services.io.Storable;
+import org.apache.derby.iapi.services.io.FormatIdOutputStream;
+
+import org.apache.derby.iapi.error.StandardException;
+import org.apache.derby.iapi.store.raw.*;
+import org.apache.derby.iapi.store.raw.xact.RawTransaction;
+import org.apache.derby.iapi.store.raw.data.RawContainerHandle;
+
+import org.apache.derby.iapi.store.access.conglomerate.LogicalUndo;
+
+import org.apache.derby.iapi.types.DataValueDescriptor;
+
+import org.apache.derby.iapi.reference.Property;
+
+import org.apache.derby.iapi.services.io.FormatableBitSet;
+import org.apache.derby.iapi.services.io.DynamicByteArrayOutputStream;
+
+import java.io.*;
+import java.util.Properties;
+
+/**
+	An Impl unittest for rawstore data that is based on the stream file
+*/
+
+public class T_StreamFile extends T_MultiThreadedIterations {
+
+	private static final String testService = "streamFileTest";
+
+	static final String REC_001 = "McLaren";
+	static final String REC_002 = "Ferrari";
+	static final String REC_003 = "Benetton";
+	static final String REC_004 = "Prost";
+	static final String REC_005 = "Tyrell";
+	static final String REC_006 = "Derby, Natscape, Goatscape, the popular names";
+	static final String REC_007 = "abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyz";
+
+	static final String SP1 = "savepoint1";
+	static final String SP2 = "savepoint2";
+
+
+	static RawStoreFactory	factory;
+	static LockFactory lf;
+	static long commonContainer = -1;
+
+	static boolean testRollback; // initialize in start
+	static final String TEST_ROLLBACK_OFF = "derby.RawStore.RollbackTestOff";
+
+	private static ContextService contextService;
+	private T_Util t_util;
+
+	public T_StreamFile() {
+		super();
+	}
+
+	/**
+	  @exception StandardException cannot startup the context service
+	 */
+	public void boot(boolean create, Properties startParams)
+		 throws StandardException {
+		super.boot(create, startParams);
+		contextService = ContextService.getFactory();
+	}
+
+
+	/*
+	** Methods required by T_Generic
+	*/
+
+	protected String getModuleToTestProtocolName() {
+		return RawStoreFactory.MODULE;
+	}
+
+
+	/**
+		Run the tests
+
+		@exception T_Fail Unexpected behaviour from the API
+	 */
+	protected void setupTest() throws T_Fail {
+		String rollbackOff = PropertyUtil.getSystemProperty(TEST_ROLLBACK_OFF);
+		testRollback = !Boolean.valueOf(rollbackOff).booleanValue();
+
+		// don't automatic boot this service if it gets left around
+		if (startParams == null) {
+			startParams = new Properties();
+		}
+
+		startParams.put(Property.NO_AUTO_BOOT, Boolean.TRUE.toString());
+		// remove the service directory to ensure a clean run
+		startParams.put(Property.DELETE_ON_CREATE, Boolean.TRUE.toString());
+
+		// see if we are testing encryption
+		startParams = T_Util.setEncryptionParam(startParams);
+
+		try {
+			factory = (RawStoreFactory) Monitor.createPersistentService(getModuleToTestProtocolName(),
+								testService, startParams);
+			if (factory == null) {
+				throw T_Fail.testFailMsg(getModuleToTestProtocolName() + " service not started.");
+			}
+
+			lf = factory.getLockFactory();
+			if (lf == null) {
+				throw T_Fail.testFailMsg("LockFactory.MODULE not found");
+			}
+		} catch (StandardException mse) {
+			throw T_Fail.exceptionFail(mse);
+		}
+
+		t_util = new T_Util(factory, lf, contextService);
+		commonContainer = commonContainer();
+
+		return;
+	}
+
+
+	/**
+	 * T_MultiThreadedIteration method
+	 *
+	 * @exception T_Fail Unexpected behaviour from the API
+	 */
+	protected void joinSetupTest() throws T_Fail {
+
+		T_Fail.T_ASSERT(factory != null, "raw store factory not setup ");
+		T_Fail.T_ASSERT(contextService != null, "Context service not setup ");
+		T_Fail.T_ASSERT(commonContainer != -1, "common container not setup ");
+
+		t_util = new T_Util(factory, lf, contextService);
+
+	}
+
+	protected T_MultiThreadedIterations newTestObject() {
+		return new T_StreamFile();
+	}
+
+	/**
+	  run the test
+
+	  @exception T_Fail Unexpected behaviour from the API
+	*/
+	protected void runTestSet() throws T_Fail {
+
+		// get a utility helper
+
+		ContextManager cm1 = contextService.newContextManager();
+		contextService.setCurrentContextManager(cm1);
+
+		try {
+
+			// boundry case: 1 row, 13 columns, string types
+			SF001(1, 13, T_RowSource.STRING_ROW_TYPE, false);
+
+			// boundry case: 1 rows, 1 null column, string types
+			SF001(1, 1, T_RowSource.STRING_ROW_TYPE, false);
+
+			// boundry case: 1000 rows, 1 null column, string types
+			SF001(1000, 1, T_RowSource.STRING_ROW_TYPE, false);
+
+			// boundry case: 1000 rows, 2 column (first null, second not null), string types
+			SF001(1000, 2, T_RowSource.STRING_ROW_TYPE, false);
+
+			// boundry case: 500 rows, 9 columns (first & last column null), string types
+			SF001(500, 9, T_RowSource.STRING_ROW_TYPE, false);
+
+			// 500 rows, 13 column, string type
+			SF001(500, 13, T_RowSource.STRING_ROW_TYPE, false);
+
+			// test error condition
+			SF001(1000, 2, T_RowSource.STRING_ROW_TYPE, true);
+
+			// The following test tests externalizable types, but we currently don't support it.
+			// do, don't run the test yet.
+			// 100 rows, 5 column, Integer object type
+			//SF001(100, 5, T_RowSource.INTEGER_ROW_TYPE, false);
+			// 100 rows, 1 column, Integer object type
+			//SF001(100, 1, T_RowSource.INTEGER_ROW_TYPE, false);
+
+			// SF002() tests are used to check performance of the stream file.
+			// no need to run them regularly.
+			//SF002(0);
+			//SF002(1);
+
+		} catch (StandardException se) {
+
+			cm1.cleanupOnError(se);
+			throw T_Fail.exceptionFail(se);
+		}
+		finally {
+			contextService.resetCurrentContextManager(cm1);
+		}
+	}
+
+	/*
+	 * create a container that all threads can use
+	 */
+	private long commonContainer() throws T_Fail {
+
+		ContextManager cm1 = contextService.newContextManager();
+		contextService.setCurrentContextManager(cm1);
+		long cid;
+
+		try {
+			Transaction t = t_util.t_startTransaction();
+			cid = t_util.t_addContainer(t, 0);
+			t_util.t_commit(t);
+			t.close();
+		}
+		catch (StandardException se) {
+
+			cm1.cleanupOnError(se);
+			throw T_Fail.exceptionFail(se);
+		}
+		finally {
+			contextService.resetCurrentContextManager(cm1);
+		}
+		return cid;
+	}
+
+	/*
+	 * create a stream container load with rowCount number of rows.
+	 * fetch it all back, and check to make sure all rows are correct.
+	 */
+	protected void SF001(int rowCount, int columnCount, int columnType, boolean forceAbort)
+		throws StandardException, T_Fail {
+
+		Transaction t = t_util.t_startTransaction();
+
+		int segmentId = StreamContainerHandle.TEMPORARY_SEGMENT;
+		Properties properties = new Properties();
+		properties.put(RawStoreFactory.STREAM_FILE_BUFFER_SIZE_PARAMETER, "16384");
+ 
+		// create row source
+		T_RowSource testRowSource = null;
+		if (forceAbort)
+			testRowSource = new T_RowSource(rowCount, columnCount, columnType, forceAbort, t);
+		else
+			testRowSource = new T_RowSource(rowCount, columnCount, columnType, forceAbort, null);
+
+		long startms = System.currentTimeMillis();
+
+		long containerId = t.addAndLoadStreamContainer(segmentId, properties, testRowSource);
+
+		long endms = System.currentTimeMillis();
+		long time = endms - startms;
+		REPORT("SF001 - write: " + time + "ms");
+
+		// open the container, and start fetching...
+		StreamContainerHandle scHandle = 
+            t.openStreamContainer(segmentId, containerId, false);
+
+		// set up the template row
+		DataValueDescriptor template[] = null;
+		template = testRowSource.getTemplate();
+
+		DataValueDescriptor readRow[] = null;
+		readRow = testRowSource.getTemplate();
+		segmentId = StreamContainerHandle.TEMPORARY_SEGMENT;
+		int fetchCount = 0;
+		startms = System.currentTimeMillis();
+		while (scHandle.fetchNext(readRow)) {
+			fetchCount++;
+			// check to make sure the row is what we inserted.
+			// this depends on T_RowSource generate identical rows.
+			if (!readRow.toString().equals(template.toString()))
+				throw T_Fail.testFailMsg("Record's value incorrect, expected :"
+					+ template.toString() + ": - got :" + readRow.toString());
+		}
+		endms = System.currentTimeMillis();
+		time = endms - startms;
+		// check to make sure we got the right number of rows.
+		if (fetchCount != rowCount)
+			throw T_Fail.testFailMsg("incorrect number of row fetched.  Expecting " + rowCount
+				+ " rows, got " + fetchCount + ", rows instead.");
+		REPORT("SF001 - fetch: " + time + "ms");
+
+		scHandle.close();
+
+		t_util.t_commit(t);
+		t.close();
+
+		PASS("SF001, rowCount = " + rowCount + ", columnCount = " + columnCount + ", clumn type: " + columnType);
+	}
+
+	// this test test the rowSource over head.
+	// when param set to 1, also gets the overhead for writeExternal for Storables
+	protected void SF002(int param) throws StandardException, T_Fail {
+
+		T_RowSource rowSource = new T_RowSource(500000, 13, 2, false, null);
+
+		DynamicByteArrayOutputStream out = new DynamicByteArrayOutputStream(16384);
+		FormatIdOutputStream logicalDataOut = new FormatIdOutputStream(out);
+
+		long startms = System.currentTimeMillis();
+		System.out.println("starting rowSource test, time: " + startms);
+		try {
+
+			FormatableBitSet validColumns = rowSource.getValidColumns();
+
+			int numberFields = 0;
+			if (validColumns != null) {
+				for (int i = validColumns.size() - 1; i >= 0; i--) {
+					if (validColumns.get(i)) {
+						numberFields = i + 1;
+						break;
+					}
+				}
+			}
+
+			DataValueDescriptor[] row = rowSource.getNextRowFromRowSource();
+			while (row != null) {
+				if (SanityManager.DEBUG) {
+					SanityManager.ASSERT(row != null, 
+										 "RowSource returned null");
+				}
+
+				int arrayPosition = -1;
+				for (int i = 0; i < numberFields; i++) {
+					// write each column out
+					if (validColumns.get(i)) {
+						arrayPosition++;
+						DataValueDescriptor column = row[arrayPosition];
+
+						if (param == 1) {
+							try {
+								Storable sColumn = (Storable) column;
+								if (!sColumn.isNull()) {
+									sColumn.writeExternal(logicalDataOut);
+									out.reset();
+								}
+							} catch (IOException ioe) {
+								throw T_Fail.exceptionFail(ioe);
+							}
+						}
+
+					}
+				}
+
+				row = rowSource.getNextRowFromRowSource();
+			}
+
+		} finally {
+
+		}
+
+		long endms = System.currentTimeMillis();
+		long time2 = endms - startms;
+		if (param != 1)
+			System.out.println("ended rowSource test, time: " + endms
+				+ ", time spent = " + time2);
+		else
+			System.out.println("------ writeExternal called....\n ended rowSource test, time: " + endms
+				+ ", time spent = " + time2);
+		
+		PASS("SF002");
+	}
+}

Propchange: incubator/derby/code/trunk/java/testing/org/apache/derbyTesting/unitTests/store/T_StreamFile.java
------------------------------------------------------------------------------
    snv:eol-style = native

Added: incubator/derby/code/trunk/java/testing/org/apache/derbyTesting/unitTests/store/T_TWC.java
URL: http://svn.apache.org/viewcvs/incubator/derby/code/trunk/java/testing/org/apache/derbyTesting/unitTests/store/T_TWC.java?view=auto&rev=155990
==============================================================================
--- incubator/derby/code/trunk/java/testing/org/apache/derbyTesting/unitTests/store/T_TWC.java (added)
+++ incubator/derby/code/trunk/java/testing/org/apache/derbyTesting/unitTests/store/T_TWC.java Wed Mar  2 17:30:05 2005
@@ -0,0 +1,162 @@
+/*
+
+   Derby - Class org.apache.derbyTesting.unitTests.store.T_TWC
+
+   Copyright 1997, 2005 The Apache Software Foundation or its licensors, as applicable.
+
+   Licensed under the Apache License, Version 2.0 (the "License");
+   you may not use this file except in compliance with the License.
+   You may obtain a copy of the License at
+
+      http://www.apache.org/licenses/LICENSE-2.0
+
+   Unless required by applicable law or agreed to in writing, software
+   distributed under the License is distributed on an "AS IS" BASIS,
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+   See the License for the specific language governing permissions and
+   limitations under the License.
+
+ */
+
+package org.apache.derbyTesting.unitTests.store;
+
+import org.apache.derby.iapi.store.raw.*;
+
+import org.apache.derby.iapi.services.context.ContextManager;
+import org.apache.derby.iapi.services.sanity.SanityManager;
+import org.apache.derby.iapi.services.context.ContextService;
+import org.apache.derby.iapi.error.StandardException;
+import org.apache.derby.iapi.services.locks.LockFactory;
+import org.apache.derby.iapi.store.access.AccessFactoryGlobals;
+
+/**
+	Transaction with context, a utility class for tests to create
+	multiple interleaving transactions.
+*/
+public class T_TWC
+{
+	protected Transaction tran;
+	protected ContextManager cm;
+	protected ContextService contextService;
+	protected LockFactory lf;
+	protected RawStoreFactory rawStore;
+
+	public T_TWC(ContextService contextService,
+					LockFactory lockFactory,
+					RawStoreFactory rawStoreFactory)
+	{
+		this.contextService = contextService;
+		this.lf = lockFactory;
+		this.rawStore = rawStoreFactory;
+		tran = null;
+		cm = null;
+	}
+
+	public T_TWC startUserTransaction()
+		 throws StandardException
+	{
+		cm = contextService.newContextManager();
+		contextService.setCurrentContextManager(cm);
+		try {
+		tran = 
+            rawStore.startTransaction(cm, AccessFactoryGlobals.USER_TRANS_NAME);
+
+		if (SanityManager.DEBUG)
+			SanityManager.ASSERT(tran != null);
+		checkNullLockCount();
+		}
+		finally {
+			contextService.resetCurrentContextManager(cm);
+		}
+		return this;
+	}
+
+	public void checkNullLockCount()
+	{
+		switchTransactionContext();
+		try {
+		if (SanityManager.DEBUG)
+			SanityManager.ASSERT(!lf.areLocksHeld(tran));
+		} finally {
+			resetContext();
+		}
+	}
+
+	public void setSavePoint(String sp, Object kindOfSavepoint)
+		 throws StandardException
+	{
+		switchTransactionContext();
+		try {
+		tran.setSavePoint(sp, null);
+		} finally {
+			resetContext();
+		}
+	}
+
+	public void rollbackToSavePoint(String sp, Object kindOfSavepoint)
+		 throws StandardException
+	{
+		switchTransactionContext();
+		try {
+			tran.rollbackToSavePoint(sp, null);
+		} finally {
+			resetContext();
+		}
+	}
+
+	public void switchTransactionContext()
+	{
+		contextService.setCurrentContextManager(cm);
+	}
+	public void resetContext() {
+		contextService.resetCurrentContextManager(cm);
+	}
+
+	public void logAndDo(Loggable l)
+		 throws StandardException
+	{
+		switchTransactionContext();
+		try {
+			tran.logAndDo(l);
+		} finally {
+			resetContext();
+		}
+	}
+
+	public void commit()
+		 throws StandardException
+	{
+		switchTransactionContext();
+		try {
+		tran.commit();
+		} finally {
+			resetContext();
+		}
+		checkNullLockCount();		
+	}
+
+	public void abort()
+		 throws StandardException
+	{
+		switchTransactionContext();
+		try {
+		tran.abort();
+		} finally {
+			resetContext();
+		}
+		checkNullLockCount();		
+	}
+
+
+	public GlobalTransactionId getId()
+		 throws StandardException
+	{
+		switchTransactionContext();
+		try {
+			return tran.getGlobalId();
+		} finally {
+			resetContext();
+		}
+
+	}
+}

Propchange: incubator/derby/code/trunk/java/testing/org/apache/derbyTesting/unitTests/store/T_TWC.java
------------------------------------------------------------------------------
    snv:eol-style = native

Added: incubator/derby/code/trunk/java/testing/org/apache/derbyTesting/unitTests/store/T_Undoable.java
URL: http://svn.apache.org/viewcvs/incubator/derby/code/trunk/java/testing/org/apache/derbyTesting/unitTests/store/T_Undoable.java?view=auto&rev=155990
==============================================================================
--- incubator/derby/code/trunk/java/testing/org/apache/derbyTesting/unitTests/store/T_Undoable.java (added)
+++ incubator/derby/code/trunk/java/testing/org/apache/derbyTesting/unitTests/store/T_Undoable.java Wed Mar  2 17:30:05 2005
@@ -0,0 +1,284 @@
+/*
+
+   Derby - Class org.apache.derbyTesting.unitTests.store.T_DaemonService
+
+   Copyright 1997, 2005 The Apache Software Foundation or its licensors, as applicable.
+
+   Licensed under the Apache License, Version 2.0 (the "License");
+   you may not use this file except in compliance with the License.
+   You may obtain a copy of the License at
+
+      http://www.apache.org/licenses/LICENSE-2.0
+
+   Unless required by applicable law or agreed to in writing, software
+   distributed under the License is distributed on an "AS IS" BASIS,
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+   See the License for the specific language governing permissions and
+   limitations under the License.
+
+ */
+
+package org.apache.derbyTesting.unitTests.store;
+
+import org.apache.derbyTesting.unitTests.harness.T_Fail;
+
+import org.apache.derby.iapi.store.raw.*;
+
+import org.apache.derby.iapi.services.sanity.SanityManager;
+import org.apache.derby.iapi.services.io.FormatIdUtil;
+import org.apache.derby.iapi.services.io.Formatable;
+import org.apache.derby.iapi.services.io.StoredFormatIds;
+import org.apache.derby.iapi.error.StandardException;
+import org.apache.derby.iapi.store.raw.log.LogInstant;
+import org.apache.derby.iapi.util.ByteArray;
+import org.apache.derby.iapi.services.io.DynamicByteArrayOutputStream;
+import java.io.IOException;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.ObjectInput;
+import java.io.ObjectOutput;
+import java.io.StreamCorruptedException;
+import java.util.Vector;
+import java.io.OutputStream;
+import java.io.InputStream;
+import org.apache.derby.iapi.services.io.LimitObjectInput;
+
+//
+// Tracing can be done like so (commented out)
+//import org.apache.derbyTesting.unitTests.util.MsgTrace;
+
+public class T_Undoable
+implements Undoable
+{
+	static final int REMOVE_NONE  = 0;
+	static final int REMOVE_ME    = 1;
+	static final int REMOVE_TO_ME = 2;
+
+	protected ByteArray preparedLog;
+	protected DynamicByteArrayOutputStream logBuffer;
+
+	GlobalTransactionId tid = null;
+	int tranSeq = -1;
+	int recordSeq = -1;
+	int removeWhat = REMOVE_NONE;
+	int LWMTranSeq = 0;
+	boolean rollBack = true;
+	int lastRecord = -1;
+	boolean lastTransaction = false;
+	int optionalDataLen;
+	boolean verbose;
+
+	// no-arg constructor, required by Formatable 
+	public T_Undoable() { super(); }
+
+
+	T_Undoable(GlobalTransactionId tid, int tranSeq, int recordSeq,
+			   int removeWhat, int LWMTranSeq,
+			   boolean rollBack, int lastRecord, boolean lastTransaction,
+			   int optionalDataLen,boolean verbose)
+		 throws T_Fail
+	{
+//MsgTrace.traceString("{{{tu.new");
+		T_Fail.T_ASSERT((removeWhat >= REMOVE_NONE) &&
+							 (removeWhat <= REMOVE_TO_ME));
+		T_Fail.T_ASSERT(rollBack == (recordSeq < 0));
+		T_Fail.T_ASSERT(rollBack == (tranSeq < 0));
+		this.tid = tid;
+		this.tranSeq = tranSeq;
+		this.recordSeq = recordSeq;
+		this.removeWhat = removeWhat;
+		this.LWMTranSeq = LWMTranSeq;
+		this.rollBack = rollBack;
+		this.lastRecord = lastRecord;
+		this.lastTransaction = lastTransaction;
+		this.optionalDataLen = optionalDataLen;
+		this.verbose = verbose;
+		
+		try {
+			writeOptionalDataToBuffer();
+		} catch (IOException ioe) {
+			throw T_Fail.exceptionFail(ioe);
+		} catch (StandardException se) {
+			throw T_Fail.exceptionFail(se);
+		}
+
+//MsgTrace.traceString("}}}tu.new");
+
+	}
+	
+	private void writeOptionalDataToBuffer()
+		throws StandardException, IOException
+	{
+
+		if (logBuffer == null) {
+			// YYZ: need to revisit this.  Do we really want to allocate this much for a buffer every time?
+			logBuffer = new DynamicByteArrayOutputStream(1024); // init size 1K
+		} else {
+			logBuffer.reset();
+		}
+
+		int optionalDataStart = logBuffer.getPosition();
+
+		if (SanityManager.DEBUG) {
+			SanityManager.ASSERT(optionalDataStart == 0,
+				"Buffer for writing the optional data should start at position 0");
+		}
+
+//MsgTrace.traceString("{{{tu.writeOpetionalData");
+		if (optionalDataLen > 0)
+		{
+			byte[] buf = new byte[optionalDataLen];
+			for (int ix=0;ix <optionalDataLen;ix++)
+				buf[ix] = (byte)ix;
+			logBuffer.write(buf);
+		}
+//MsgTrace.traceString("}}}tu.writeOpetionalData");
+
+		int optionalDataLength = logBuffer.getPosition() - optionalDataStart;
+		
+		if (SanityManager.DEBUG) {
+			if (optionalDataLength != logBuffer.getUsed())
+				SanityManager.THROWASSERT("wrong optional data length, optionalDataLength = "
+					+ optionalDataLength + ", logBuffer.getUsed() = " + logBuffer.getUsed());
+		}
+
+		// set the position to the beginning of the buffer
+		logBuffer.setPosition(optionalDataStart);
+
+		this.preparedLog = new ByteArray (logBuffer.getByteArray(), optionalDataStart,
+			optionalDataLength);
+	}
+	
+	/*
+	  Loggable methods
+	  */
+	public void doMe(Transaction xact, LogInstant instant,
+					 LimitObjectInput in)
+	{
+		if (verbose)
+			System.out.println("Loggable.doMe("+toString()+")");
+		return;
+	}
+
+	/*
+		methods to support prepared log
+		the following two methods should not be called during recover
+	*/
+
+	public ByteArray getPreparedLog()
+	{
+		return this.preparedLog;
+	}
+
+	public boolean needsRedo(Transaction xact) {return false;}
+	public void releaseResource(Transaction xact) {return;}
+	public int group () { return Loggable.RAWSTORE ; };
+
+	/*
+	  Undoable methods.
+	 */
+	public Compensation generateUndo(Transaction xact, LimitObjectInput in)
+		 throws StandardException, IOException
+	{
+//MsgTrace.traceString("+++tu.generateUndo");
+		return new T_Compensation();
+	}
+
+	/*
+	  Formatable methods
+	  */
+
+	/**
+	 @exception IOException	thrown on error
+	 */
+	public void writeExternal(ObjectOutput out)
+	throws IOException
+	{
+//MsgTrace.traceString("{{{tu.writeExternal");
+		if (SanityManager.DEBUG)
+		{
+			SanityManager.ASSERT((removeWhat >= REMOVE_NONE) &&
+								 (removeWhat <= REMOVE_TO_ME));
+			SanityManager.ASSERT(rollBack == (recordSeq < 0));
+			SanityManager.ASSERT(rollBack == (tranSeq < 0));
+		}
+		out.writeObject(tid);
+		out.writeInt(tranSeq);
+		out.writeInt(recordSeq);
+		out.writeInt(removeWhat);
+		out.writeInt(LWMTranSeq);
+		out.writeBoolean(rollBack);
+		out.writeInt(lastRecord);
+		out.writeBoolean(lastTransaction);
+		out.writeInt(optionalDataLen);
+//MsgTrace.traceString("}}}tu.writeExternal");
+	}
+
+	public void readExternal(ObjectInput in) 
+	throws IOException,ClassNotFoundException
+	{
+//MsgTrace.traceString("{{{tu.readExternal");
+		try
+		{
+			tid = (GlobalTransactionId)in.readObject();
+			tranSeq = in.readInt();
+			recordSeq = in.readInt();
+			removeWhat = in.readInt();
+			LWMTranSeq = in.readInt();
+			rollBack = in.readBoolean();
+			lastRecord = in.readInt();
+			lastTransaction = in.readBoolean();
+			optionalDataLen = in.readInt();
+		}
+
+		catch ( ClassCastException exception ) {
+//MsgTrace.traceString("{{{tu.readExternal---exception");
+			throw new StreamCorruptedException();
+		}
+//MsgTrace.traceString("}}}tu.readExternal");
+	}
+
+	public int getTypeFormatId()
+	{
+		return StoredFormatIds.SERIALIZABLE_FORMAT_ID;
+	}
+
+	/*
+	  Object methods.
+	  */
+	public String toString()
+	{
+	    String traceTid = "tid: null";
+
+		if (tid !=null) traceTid = "tid: "+tid;
+
+		String traceRemoveWhat;
+		switch (removeWhat)
+		{
+		case  REMOVE_NONE:
+			traceRemoveWhat = "REMOVE_NONE";
+			break;
+		case  REMOVE_ME:
+			traceRemoveWhat = "REMOVE_ME";
+			break;
+		case  REMOVE_TO_ME:
+			traceRemoveWhat = "REMOVE_TO_ME";
+			break;
+		default:
+			traceRemoveWhat = "removeWhat: invalidValue";
+			break;
+		}
+
+		return
+			traceTid+" "+
+			"tranSeq: "+tranSeq+" "+
+			"recordSeq: "+recordSeq+" "+
+			traceRemoveWhat+" "+
+			"LWMTranSeq: "+LWMTranSeq+" "+
+			"rollback: "+rollBack+" "+
+			"lastRecord: "+lastRecord+" "+
+			"optionalDataLen: "+optionalDataLen+" "+
+			"lastTransaction: "+lastTransaction;
+	}
+
+}

Propchange: incubator/derby/code/trunk/java/testing/org/apache/derbyTesting/unitTests/store/T_Undoable.java
------------------------------------------------------------------------------
    snv:eol-style = native



Mime
View raw message