Adding JMCR-Stable version
[Benchmarks_CSolver.git] / JMCR-Stable / real-world application / derby-10.3.2.1 / java / engine / org / apache / derby / impl / store / access / btree / index / B2I.java
diff --git a/JMCR-Stable/real-world application/derby-10.3.2.1/java/engine/org/apache/derby/impl/store/access/btree/index/B2I.java b/JMCR-Stable/real-world application/derby-10.3.2.1/java/engine/org/apache/derby/impl/store/access/btree/index/B2I.java
new file mode 100644 (file)
index 0000000..bdd417d
--- /dev/null
@@ -0,0 +1,1126 @@
+/*\r
+\r
+   Derby - Class org.apache.derby.impl.store.access.btree.index.B2I\r
+\r
+   Licensed to the Apache Software Foundation (ASF) under one or more\r
+   contributor license agreements.  See the NOTICE file distributed with\r
+   this work for additional information regarding copyright ownership.\r
+   The ASF licenses this file to you under the Apache License, Version 2.0\r
+   (the "License"); you may not use this file except in compliance with\r
+   the License.  You may obtain a copy of the License at\r
+\r
+      http://www.apache.org/licenses/LICENSE-2.0\r
+\r
+   Unless required by applicable law or agreed to in writing, software\r
+   distributed under the License is distributed on an "AS IS" BASIS,\r
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
+   See the License for the specific language governing permissions and\r
+   limitations under the License.\r
+\r
+ */\r
+\r
+package org.apache.derby.impl.store.access.btree.index;\r
+\r
+import java.io.ObjectOutput;\r
+import java.io.ObjectInput;\r
+import java.io.IOException;\r
+import java.util.Properties;\r
+\r
+import org.apache.derby.iapi.reference.SQLState;\r
+\r
+import org.apache.derby.iapi.services.io.ArrayInputStream;\r
+import org.apache.derby.iapi.services.io.FormatableBitSet;\r
+\r
+import org.apache.derby.iapi.services.sanity.SanityManager;\r
+import org.apache.derby.iapi.error.StandardException;\r
+\r
+import org.apache.derby.impl.store.access.conglomerate.ConglomerateUtil;\r
+import org.apache.derby.iapi.store.access.conglomerate.LogicalUndo;\r
+import org.apache.derby.iapi.store.access.conglomerate.ScanManager;\r
+import org.apache.derby.iapi.store.access.conglomerate.TransactionManager;\r
+\r
+import org.apache.derby.iapi.store.access.ColumnOrdering;\r
+import org.apache.derby.iapi.store.access.ConglomerateController;\r
+import org.apache.derby.iapi.store.access.DynamicCompiledOpenConglomInfo;\r
+import org.apache.derby.iapi.store.access.Qualifier;\r
+import org.apache.derby.iapi.store.access.RowLocationRetRowSource;\r
+import org.apache.derby.iapi.store.access.StaticCompiledOpenConglomInfo;\r
+import org.apache.derby.iapi.store.access.StoreCostController;\r
+import org.apache.derby.iapi.store.access.TransactionController;\r
+\r
+\r
+import org.apache.derby.iapi.store.raw.ContainerHandle;\r
+import org.apache.derby.iapi.store.raw.LockingPolicy;\r
+import org.apache.derby.iapi.store.raw.Transaction;\r
+\r
+import org.apache.derby.iapi.types.DataValueDescriptor;\r
+import org.apache.derby.iapi.types.RowLocation;\r
+import org.apache.derby.iapi.types.StringDataValue;\r
+\r
+import org.apache.derby.impl.store.access.btree.BTree;\r
+import org.apache.derby.impl.store.access.btree.BTreeLockingPolicy;\r
+import org.apache.derby.impl.store.access.btree.LeafControlRow;\r
+import org.apache.derby.impl.store.access.btree.OpenBTree;\r
+\r
+import org.apache.derby.iapi.services.cache.ClassSize;\r
+\r
+import org.apache.derby.iapi.services.io.CompressedNumber;\r
+import org.apache.derby.iapi.services.io.FormatableBitSet;\r
+import org.apache.derby.iapi.services.io.StoredFormatIds;\r
+\r
+\r
+// For JavaDoc references (i.e. @see)\r
+import org.apache.derby.iapi.store.access.conglomerate.Conglomerate;\r
+\r
+\r
+/*\r
+ * @format_id ACCESS_B2I_V3_ID\r
+ *\r
+ * @purpose   The tag that describes the on disk representation of the B2I\r
+ *            conglomerate object.  Access contains no "directory" of \r
+ *            conglomerate information.  In order to bootstrap opening a file\r
+ *            it encodes the factory that can open the conglomerate in the \r
+ *            conglomerate id itself.  There exists a single B2IFactory which\r
+ *            must be able to read all btree format id's.  \r
+ *\r
+ *            This format was used for all Derby database B2I's in version\r
+ *            10.2 and previous versions.\r
+ *\r
+ * @upgrade   The format id of this object is currently always read from disk\r
+ *            as the first field of the conglomerate itself.  A bootstrap\r
+ *            problem exists as we don't know the format id of the B2I \r
+ *            until we are in the "middle" of reading the B2I.  Thus the\r
+ *            base B2I implementation must be able to read and write \r
+ *            all formats based on the reading the \r
+ *            "format_of_this_conglomerate". \r
+ *\r
+ *            soft upgrade to ACCESS_B2I_V4_ID:\r
+ *                read:\r
+ *                    old format is readable by current B2I implementation,\r
+ *                    with automatic in memory creation of default collation\r
+ *                    id needed by new format.  No code other than\r
+ *                    readExternal and writeExternal need know about old format.\r
+ *                write:\r
+ *                    will never write out new format id in soft upgrade mode.\r
+ *                    Code in readExternal and writeExternal handles writing\r
+ *                    correct version.  Code in the factory handles making\r
+ *                    sure new conglomerates use the B2I_v10_2 class to \r
+ *                    that will write out old format info.\r
+ *\r
+ *            hard upgrade to ACCESS_B2I_V4_ID:\r
+ *                read:\r
+ *                    old format is readable by current B2I implementation,\r
+ *                    with automatic in memory creation of default collation\r
+ *                    id needed by new format.\r
+ *                write:\r
+ *                    Only "lazy" upgrade will happen.  New format will only\r
+ *                    get written for new conglomerate created after the \r
+ *                    upgrade.  Old conglomerates continue to be handled the\r
+ *                    same as soft upgrade.\r
+ *\r
+ * @disk_layout \r
+ *     format_of_this_conlgomerate(byte[])\r
+ *     containerid(long)\r
+ *     segmentid(int)\r
+ *     number_of_key_fields(int)\r
+ *     number_of_unique_columns(int)\r
+ *     allow_duplicates(boolean)\r
+ *     maintain_parent_links(boolean)\r
+ *     array_of_format_ids(byte[][])\r
+ *     baseConglomerateId(long)\r
+ *     rowLocationColumn(int)\r
+ *     ascend_column_info(FormatableBitSet)\r
+ *\r
+ */\r
+\r
+/*\r
+ * @format_id ACCESS_B2I_V4_ID\r
+ *\r
+ * @purpose   The tag that describes the on disk representation of the B2I\r
+ *            conglomerate object.  Access contains no "directory" of \r
+ *            conglomerate information.  In order to bootstrap opening a file\r
+ *            it encodes the factory that can open the conglomerate in the \r
+ *            conglomerate id itself.  There exists a single B2IFactory which\r
+ *            must be able to read all btree format id's.  \r
+ *\r
+ *            This format is the current version id of B2I and has been used \r
+ *            in versions of Derby after the 10.2 release.\r
+ *\r
+ * @upgrade   This is the current version, no upgrade necessary.\r
+ *\r
+ * @disk_layout \r
+ *     format_of_this_conlgomerate(byte[])\r
+ *     containerid(long)\r
+ *     segmentid(int)\r
+ *     number_of_key_fields(int)\r
+ *     number_of_unique_columns(int)\r
+ *     allow_duplicates(boolean)\r
+ *     maintain_parent_links(boolean)\r
+ *     array_of_format_ids(byte[][])\r
+ *     baseConglomerateId(long)\r
+ *     rowLocationColumn(int)\r
+ *     ascend_column_info(FormatableBitSet)\r
+ *     collation_ids(compressed array of ints)\r
+ *\r
+ */\r
+\r
+/**\r
+ * Implements an instance of a B-Tree secondary index conglomerate.\r
+ * A B2I object has two roles.\r
+ * <ol>\r
+ * <li>\r
+ * The B2I object is stored on disk, and holds the store specific\r
+ * information needed to access/describe the conglomerate. This\r
+ * includes information such as the format ids of the columns, \r
+ * the conglomerate id of the base table, the location of \r
+ * row location column.\r
+ * </li>\r
+ * <li>\r
+ * Access to all the interfaces start by making a call off the\r
+ * Conglomerate interface. So for instance to get a scan on the\r
+ * conglomerate method {@link #openScan openScan} should be called.\r
+ * </li>\r
+ * </ol>\r
+ */\r
+public class B2I extends BTree\r
+{\r
+    private static final String PROPERTY_BASECONGLOMID = "baseConglomerateId";\r
+    private static final String PROPERTY_ROWLOCCOLUMN  = "rowLocationColumn";\r
+\r
+    static final int FORMAT_NUMBER = StoredFormatIds.ACCESS_B2I_V4_ID;\r
+\r
+       /*\r
+       ** Fields of B2I.\r
+       */\r
+\r
+       /**\r
+       The id of the conglomerate which contains the base table.\r
+       Row locations inserted into this secondary index are assumed\r
+       to refer to that conglomerate.  Used to obtain table/row locks on the\r
+    base table rows which the index rows point at.\r
+       **/\r
+       long baseConglomerateId;\r
+\r
+       /**\r
+       The column id (zero-based integer index) of the column which holds the row \r
+    location to the base conglomerate.\r
+       The default value of RowLocationColumn is the last key column.\r
+    Used to obtain table/row locks on the base table rows with the index rows\r
+    point at.\r
+       Currently, RowLocationColumn must be the last key column.\r
+       **/\r
+       int rowLocationColumn;\r
+\r
+    private static final int BASE_MEMORY_USAGE = \r
+        ClassSize.estimateBaseFromCatalog( B2I.class);\r
+\r
+    public int estimateMemoryUsage()\r
+    {\r
+        return BASE_MEMORY_USAGE;\r
+    }\r
+\r
+    /**************************************************************************\r
+     * Constructors for This class:\r
+     **************************************************************************\r
+     */\r
+\r
+    /**************************************************************************\r
+     * Protected locking implmentations of abtract BTree routines:\r
+     *     getBtreeLockingPolicy\r
+     *     lockTable\r
+     **************************************************************************\r
+     */\r
+\r
+    /**\r
+     * Create a new btree locking policy from scratch.\r
+     *\r
+        * @exception  StandardException  Standard exception policy.\r
+     **/\r
+    protected BTreeLockingPolicy getBtreeLockingPolicy(\r
+    Transaction             rawtran,\r
+    int                     lock_level,\r
+    int                     mode,\r
+    int                     isolation_level,\r
+    ConglomerateController  base_cc,\r
+    OpenBTree               open_btree)\r
+               throws StandardException\r
+    {\r
+        BTreeLockingPolicy ret_locking_policy = null;\r
+\r
+        if (SanityManager.DEBUG)\r
+        {\r
+            SanityManager.ASSERT(\r
+                (isolation_level == \r
+                     TransactionController.ISOLATION_SERIALIZABLE)      ||\r
+                (isolation_level == \r
+                     TransactionController.ISOLATION_REPEATABLE_READ)   ||\r
+                (isolation_level == \r
+                     TransactionController.ISOLATION_READ_COMMITTED_NOHOLDLOCK) ||\r
+                (isolation_level == \r
+                     TransactionController.ISOLATION_READ_COMMITTED)    ||\r
+                (isolation_level == \r
+                     TransactionController.ISOLATION_READ_UNCOMMITTED),\r
+                "bad isolation_level = " + isolation_level);\r
+        }\r
+\r
+        if (lock_level == TransactionController.MODE_TABLE)\r
+        {\r
+            ret_locking_policy = \r
+                new B2ITableLocking3(\r
+                    rawtran,\r
+                    lock_level,\r
+                    rawtran.newLockingPolicy(\r
+                        LockingPolicy.MODE_CONTAINER, \r
+                        isolation_level,\r
+                        true), \r
+                    base_cc,\r
+                    open_btree);\r
+        }\r
+        else if (lock_level == TransactionController.MODE_RECORD)\r
+        {\r
+            if (isolation_level == TransactionController.ISOLATION_SERIALIZABLE)\r
+            {\r
+                ret_locking_policy = \r
+                    new B2IRowLocking3(\r
+                        rawtran,\r
+                        lock_level,\r
+                        rawtran.newLockingPolicy(\r
+                            LockingPolicy.MODE_RECORD, \r
+                            isolation_level,\r
+                            true), \r
+                        base_cc,\r
+                        open_btree);\r
+            }\r
+            else if ((isolation_level == \r
+                        TransactionController.ISOLATION_REPEATABLE_READ))\r
+            {\r
+                ret_locking_policy = \r
+                    new B2IRowLockingRR(\r
+                        rawtran,\r
+                        lock_level,\r
+                        rawtran.newLockingPolicy(\r
+                            LockingPolicy.MODE_RECORD, \r
+                            isolation_level,\r
+                            true), \r
+                        base_cc,\r
+                        open_btree);\r
+            }\r
+            else if ((isolation_level == \r
+                        TransactionController.ISOLATION_READ_COMMITTED) ||\r
+                     (isolation_level == \r
+                        TransactionController.ISOLATION_READ_COMMITTED_NOHOLDLOCK))\r
+            {\r
+                ret_locking_policy = \r
+                    new B2IRowLocking2(\r
+                        rawtran,\r
+                        lock_level,\r
+                        rawtran.newLockingPolicy(\r
+                            LockingPolicy.MODE_RECORD, \r
+                            isolation_level,\r
+                            true), \r
+                        base_cc,\r
+                        open_btree);\r
+            }\r
+            else if (isolation_level == \r
+                        TransactionController.ISOLATION_READ_UNCOMMITTED)\r
+            {\r
+                ret_locking_policy = \r
+                    new B2IRowLocking1(\r
+                        rawtran,\r
+                        lock_level,\r
+                        rawtran.newLockingPolicy(\r
+                            LockingPolicy.MODE_RECORD, \r
+                            isolation_level,\r
+                            true), \r
+                        base_cc,\r
+                        open_btree);\r
+            }\r
+        }\r
+\r
+\r
+        if (SanityManager.DEBUG)\r
+        {\r
+            SanityManager.ASSERT(\r
+                ret_locking_policy != null, "ret_locking_policy == null");\r
+        }\r
+\r
+        return(ret_locking_policy);\r
+    }\r
+\r
+    /**\r
+     * Lock the base table.\r
+     * <p>\r
+     * Assumes that segment of the base container is the same as the segment\r
+     * of the btree segment.\r
+     * <p>\r
+     * RESOLVE - we really want to get the lock without opening the container.\r
+     * raw store will be providing this.\r
+     *\r
+     * @param xact_manager Transaction to associate the lock with.\r
+     *\r
+        * @exception  StandardException  Standard exception policy.\r
+     **/\r
+    public final ConglomerateController lockTable(\r
+    TransactionManager  xact_manager,\r
+    int                 open_mode,\r
+    int                 lock_level,\r
+    int                 isolation_level)\r
+               throws StandardException\r
+    {\r
+        open_mode |= TransactionController.OPENMODE_FOR_LOCK_ONLY;\r
+\r
+        // open the base conglomerate - just to get the table lock.\r
+        ConglomerateController cc = \r
+            xact_manager.openConglomerate(\r
+                this.baseConglomerateId, false, open_mode, lock_level, \r
+                isolation_level);\r
+\r
+        return(cc);\r
+    }\r
+\r
+    /**************************************************************************\r
+        *  Private methods of B2I, arranged alphabetically.\r
+     **************************************************************************\r
+     */\r
+\r
+\r
+    private void traverseRight()\r
+    {\r
+        // RESOLVE - Do I have to do this???????????????\r
+\r
+               if (SanityManager.DEBUG)\r
+                       SanityManager.THROWASSERT("not implemented.");\r
+    }\r
+\r
+\r
+       /*\r
+       ** Methods of B2I.\r
+       */\r
+\r
+       /**\r
+       Create an empty secondary index b-tree, using the generic b-tree to do the\r
+    generic part of the creation process.\r
+\r
+    This routine opens the newly created container, adds a single page, and\r
+    makes this page the root by inserting a LeafControlRow onto this page\r
+    at slot 0 and marking in that control row that the page is a root page.\r
+\r
+    The following properties are specific to the b-tree secondary index:\r
+    <UL>\r
+    <LI> "baseConglomerateId" (integer).  The conglomerate id of the base\r
+    conglomerate is never actually accessed by the b-tree secondary\r
+    index implementation, it only serves as a namespace for row locks.\r
+    This property is required.\r
+    <LI> "rowLocationColumn" (integer).  The zero-based index into the row which\r
+    the b-tree secondary index will assume holds a @see RowLocation of\r
+    the base row in the base conglomerate.  This value will be used\r
+    for acquiring locks.  In this implementation RowLocationColumn must be \r
+    the last key column.\r
+    This property is required.\r
+    </UL>\r
+\r
+    A secondary index i (a, b) on table t (a, b, c) would have rows\r
+    which looked like (a, b, row_location).  baseConglomerateId is set to the\r
+    conglomerate id of t.  rowLocationColumns is set to 2.  allowsDuplicates\r
+    would be set to false, @see BTree#create.  To create a unique\r
+    secondary index set uniquenessColumns to 2, this means that the btree\r
+    code will compare the key values but not the row id when determing\r
+    uniqueness.  To create a nonunique secondary index set uniquenessColumns\r
+    to 3, this would mean that the uniqueness test would include the row\r
+    location and since all row locations will be unique  all rows inserted \r
+    into the index will be differentiated (at least) by row location.  \r
+\r
+       @see BTree#create\r
+\r
+       @exception StandardException Standard exception policy.\r
+       **/\r
+       public void create(\r
+    TransactionManager      xact_manager,\r
+    int                     segmentId, \r
+    long                    input_conglomid, \r
+    DataValueDescriptor[]      template, \r
+       ColumnOrdering[]            columnOrder,\r
+    int[]                   collationIds,\r
+    Properties              properties,\r
+       int                     temporaryFlag)\r
+               throws StandardException\r
+       {\r
+        String      property_value = null;\r
+        Transaction rawtran        = xact_manager.getRawStoreXact();\r
+\r
+        if (properties == null)\r
+        {\r
+            throw(StandardException.newException(\r
+                    SQLState.BTREE_PROPERTY_NOT_FOUND, PROPERTY_BASECONGLOMID));\r
+        }\r
+\r
+        // Get baseConglomerateId //\r
+        property_value = properties.getProperty(PROPERTY_BASECONGLOMID);\r
+        if (property_value == null)\r
+        {\r
+            throw(StandardException.newException(\r
+                    SQLState.BTREE_PROPERTY_NOT_FOUND, PROPERTY_BASECONGLOMID));\r
+        }\r
+\r
+        if (SanityManager.DEBUG)\r
+        {\r
+                       if (property_value == null)\r
+               SanityManager.THROWASSERT(\r
+                       PROPERTY_BASECONGLOMID +\r
+                                       "property not passed to B2I.create()");\r
+        }\r
+\r
+        baseConglomerateId = Long.parseLong(property_value);\r
+\r
+        // Get rowLocationColumn //\r
+        property_value = properties.getProperty(PROPERTY_ROWLOCCOLUMN);\r
+\r
+        if (SanityManager.DEBUG)\r
+        {\r
+                       if (property_value == null)\r
+               SanityManager.THROWASSERT(\r
+                       PROPERTY_ROWLOCCOLUMN +\r
+                                       "property not passed to B2I.create()");\r
+        }\r
+\r
+        if (property_value == null)\r
+        {\r
+            throw(StandardException.newException(\r
+                    SQLState.BTREE_PROPERTY_NOT_FOUND, PROPERTY_BASECONGLOMID));\r
+        }\r
+\r
+        rowLocationColumn = Integer.parseInt(property_value);\r
+\r
+        // Currently the row location column must be the last column (makes)\r
+        // comparing the columns in the index easier.\r
+        if (SanityManager.DEBUG)\r
+        {\r
+            SanityManager.ASSERT(rowLocationColumn == template.length - 1, \r
+                "rowLocationColumn is not the last column in the index");\r
+            SanityManager.ASSERT(\r
+                template[rowLocationColumn] instanceof \r
+                    RowLocation);\r
+\r
+            // There must be at least one key column\r
+                       if (rowLocationColumn < 1)\r
+               SanityManager.THROWASSERT(\r
+                                       "rowLocationColumn (" + rowLocationColumn +\r
+                                       ") expected to be >= 1");\r
+        }\r
+\r
+\r
+               /* convert the sorting order information into a boolean array map.\r
+                * If the sorting order for the columns is not provided, we\r
+                * assign the default as Ascending Order.\r
+                * array length is equal to template length, because column order\r
+                * length changes whether it is unique or is non unique. store assumes\r
+                * template length arrays. So, we make template length array and make\r
+                * the last column as ascending instead of having lot of execeptions \r
+         * code.\r
+                */\r
+               \r
+               ascDescInfo = new boolean[template.length];\r
+               for (int i=0 ; i < ascDescInfo.length; i++)\r
+               {\r
+                       if (columnOrder != null && i < columnOrder.length)\r
+                               ascDescInfo[i] = columnOrder[i].getIsAscending();\r
+                       else\r
+                               ascDescInfo[i] = true;  // default values - ascending order\r
+               }\r
+\r
+        // get collation ids from input collation ids, store it in the \r
+        // conglom state.\r
+        collation_ids = \r
+            ConglomerateUtil.createCollationIds(template.length, collationIds);\r
+\r
+               // Do the generic part of creating the b-tree.\r
+               super.create(\r
+            rawtran, segmentId, input_conglomid, template, \r
+            properties, getTypeFormatId(), temporaryFlag);\r
+\r
+        // open the base conglomerate - to get the lock\r
+        ConglomerateController base_cc = \r
+            xact_manager.openConglomerate(\r
+                baseConglomerateId,\r
+                false,\r
+                TransactionController.OPENMODE_FOR_LOCK_ONLY, \r
+                TransactionController.MODE_TABLE,\r
+                TransactionController.ISOLATION_SERIALIZABLE);\r
+        \r
+        OpenBTree open_btree = new OpenBTree();\r
+\r
+        BTreeLockingPolicy b2i_locking_policy = \r
+            new B2ITableLocking3(\r
+                rawtran,\r
+                TransactionController.MODE_TABLE,\r
+                rawtran.newLockingPolicy(\r
+                    LockingPolicy.MODE_CONTAINER,\r
+                    TransactionController.ISOLATION_SERIALIZABLE, true), \r
+                base_cc, open_btree);\r
+\r
+\r
+        // The following call will "open" the new btree.  Create is\r
+        // an interesting case.  What we really want is read only table lock\r
+        // on the base conglomerate and update locks on the index.  For now\r
+        // just get the update lock on the base table, this is done by the\r
+        // lockTable() call made by base class.\r
+\r
+        open_btree.init(\r
+            (TransactionManager) xact_manager,  // current user xact\r
+            (TransactionManager) xact_manager,  // current xact\r
+            (ContainerHandle) null,     // have init open the container.\r
+            rawtran, \r
+            false,\r
+            (ContainerHandle.MODE_FORUPDATE),\r
+            TransactionController.MODE_TABLE,\r
+            b2i_locking_policy,         // get table level lock.\r
+            this,                       \r
+            (LogicalUndo) null,         // no logical undo necessary, as \r
+                                        // initEmptyBtree()\r
+                                        // work will be done single user and\r
+                                        // rows will not move.\r
+            (DynamicCompiledOpenConglomInfo) null);\r
+                                        \r
+               // Open the newly created container, and insert the first control row.\r
+        LeafControlRow.initEmptyBtree(open_btree);\r
+\r
+        open_btree.close();\r
+\r
+        base_cc.close();\r
+       }\r
+\r
+\r
+\r
+       /*\r
+       ** Methods of Conglomerate\r
+       */\r
+\r
+    /**\r
+     * Retrieve the maximum value row in an ordered conglomerate.\r
+     * <p>\r
+     * Returns true and fetches the rightmost row of an ordered conglomerate \r
+     * into "fetchRow" if there is at least one row in the conglomerate.  If\r
+     * there are no rows in the conglomerate it returns false.\r
+     * <p>\r
+     * Non-ordered conglomerates will not implement this interface, calls\r
+     * will generate a StandardException.\r
+     * <p>\r
+     * RESOLVE - this interface is temporary, long term equivalent (and more) \r
+     * functionality will be provided by the openBackwardScan() interface.  \r
+     *\r
+        * @param xact_manager    The TransactionController under which this \r
+     *                        operation takes place.\r
+     *\r
+        * @param conglomId       The identifier of the conglomerate\r
+        *                        to open the scan for.\r
+     *\r
+        * @param open_mode       Specifiy flags to control opening of table.  \r
+     *                        OPENMODE_FORUPDATE - if set open the table for\r
+     *                        update otherwise open table shared.\r
+     * @param lock_level      One of (MODE_TABLE, MODE_RECORD, or MODE_NONE).\r
+     *\r
+     * @param isolation_level The isolation level to lock the conglomerate at.\r
+     *                        One of (ISOLATION_READ_COMMITTED or \r
+     *                        ISOLATION_SERIALIZABLE).\r
+     *\r
+        * @param scanColumnList  A description of which columns to return from \r
+     *                        every fetch in the scan.  template, \r
+     *                        and scanColumnList work together\r
+     *                        to describe the row to be returned by the scan - \r
+     *                        see RowUtil for description of how these three \r
+     *                        parameters work together to describe a "row".\r
+     *\r
+     * @param fetchRow        The row to retrieve the maximum value into.\r
+     *\r
+        * @return boolean indicating if a row was found and retrieved or not.\r
+     *\r
+        * @exception  StandardException  Standard exception policy.\r
+     **/\r
+       public boolean fetchMaxOnBTree(\r
+    TransactionManager      xact_manager,\r
+    Transaction             rawtran,\r
+    long                    conglomId,\r
+    int                     open_mode,\r
+    int                     lock_level,\r
+    LockingPolicy           locking_policy,\r
+    int                     isolation_level,\r
+    FormatableBitSet                 scanColumnList,\r
+    DataValueDescriptor[]   fetchRow)\r
+        throws StandardException\r
+    {\r
+        boolean row_exists;\r
+\r
+        // row level locking implementation.\r
+\r
+        // RESOLVE (revisit implementation after all the Xena rowlocking\r
+        // changes have been made).  Can probably come up with single\r
+        // path implementation.\r
+        \r
+        // Create a new b-tree secondary index scan.\r
+        B2IMaxScan b2is = new B2IMaxScan();\r
+\r
+        // Initialize it.\r
+        b2is.init(\r
+            xact_manager, \r
+            rawtran, \r
+            open_mode,\r
+            lock_level,\r
+            locking_policy,\r
+            isolation_level,\r
+            true /* get locks on base table as part of open */,\r
+            scanColumnList,\r
+            this, \r
+            new B2IUndo());\r
+\r
+        row_exists = b2is.fetchMax(fetchRow);\r
+\r
+        b2is.close();\r
+\r
+        return(row_exists);\r
+    }\r
+\r
+\r
+       /**\r
+       Bulk Load a B-tree secondary index.\r
+\r
+       @see Conglomerate#load\r
+       @exception StandardException Standard Derby Error policy.\r
+       raise SQLState.STORE_CONGLOMERATE_DUPLICATE_KEY_EXCEPTION if a duplicate \r
+    key is detected in the load.\r
+       **/\r
+\r
+       public long load(\r
+       TransactionManager      xact_manager,\r
+       boolean                 createConglom,\r
+       RowLocationRetRowSource rowSource)\r
+                throws StandardException\r
+       {\r
+        long num_rows_loaded = 0;\r
+               B2IController b2ic = new B2IController();\r
+\r
+               try\r
+               {\r
+            int open_mode = TransactionController.OPENMODE_FORUPDATE;\r
+\r
+            if (createConglom)\r
+            {\r
+                open_mode |=\r
+                    (ContainerHandle.MODE_UNLOGGED |\r
+                     ContainerHandle.MODE_CREATE_UNLOGGED);\r
+            }\r
+\r
+            // Do the actual open of the container in the super class.\r
+            b2ic.init(\r
+                xact_manager,                    // current transaction   \r
+                xact_manager.getRawStoreXact(),  // current raw store xact\r
+                false,                           // Not holdable\r
+                open_mode,\r
+                TransactionController.MODE_TABLE,\r
+                xact_manager.getRawStoreXact().newLockingPolicy(\r
+                    LockingPolicy.MODE_CONTAINER,\r
+                    TransactionController.ISOLATION_SERIALIZABLE, true),\r
+                true,\r
+                this, \r
+                new B2IUndo(),\r
+                (B2IStaticCompiledInfo) null,\r
+                (DynamicCompiledOpenConglomInfo) null);\r
+\r
+            num_rows_loaded = b2ic.load(xact_manager, createConglom, rowSource);\r
+\r
+               }\r
+               finally\r
+               {\r
+                       b2ic.close();\r
+               }\r
+\r
+        return(num_rows_loaded);\r
+       }\r
+\r
+       /**\r
+       Open a b-tree controller.\r
+       @see Conglomerate#open\r
+\r
+       @exception StandardException Standard exception policy.\r
+       **/\r
+       public ConglomerateController open(\r
+    TransactionManager              xact_manager,\r
+    Transaction                     rawtran, \r
+    boolean                         hold,\r
+    int                             open_mode,\r
+    int                             lock_level,\r
+    LockingPolicy                   locking_policy,\r
+    StaticCompiledOpenConglomInfo   static_info,\r
+    DynamicCompiledOpenConglomInfo  dynamic_info)\r
+               throws StandardException\r
+       {\r
+               // Create a new b-tree secondary index controller.\r
+               B2IController b2ic = new B2IController();\r
+\r
+               // Do the actual open of the container in the super class.\r
+               b2ic.init(\r
+            xact_manager,               // current transaction   \r
+            rawtran,                    // current raw store transaction\r
+            hold,                       // holdability\r
+            open_mode,\r
+            lock_level,\r
+            locking_policy,\r
+            true,\r
+            this, \r
+            new B2IUndo(),\r
+            (B2IStaticCompiledInfo) static_info,\r
+            dynamic_info);\r
+\r
+               // Return it to the caller.\r
+               return b2ic;\r
+       }\r
+\r
+       /**\r
+       Open a b-tree secondary index scan controller.\r
+       @see Conglomerate#openScan\r
+       @see BTree#openScan\r
+\r
+       @exception StandardException Standard exception policy.\r
+       **/\r
+       public ScanManager openScan(\r
+    TransactionManager              xact_manager,\r
+    Transaction                     rawtran,\r
+    boolean                         hold,\r
+    int                             open_mode,\r
+    int                             lock_level,\r
+    LockingPolicy                   locking_policy,\r
+    int                             isolation_level,\r
+       FormatableBitSet                         scanColumnList,\r
+    DataValueDescriptor[]                      startKeyValue,\r
+    int                             startSearchOperator,\r
+    Qualifier                       qualifier[][],\r
+    DataValueDescriptor[]                      stopKeyValue,\r
+    int                             stopSearchOperator,\r
+    StaticCompiledOpenConglomInfo   static_info,\r
+    DynamicCompiledOpenConglomInfo  dynamic_info)\r
+                       throws StandardException\r
+       {\r
+               // Create a new b-tree secondary index scan.\r
+               B2IForwardScan b2is = new B2IForwardScan();\r
+\r
+               // Initialize it.\r
+               b2is.init(xact_manager, rawtran, \r
+                  hold,\r
+                  open_mode,\r
+                  lock_level,\r
+                  locking_policy,\r
+                  isolation_level,\r
+                  true /* get locks on base table as part of open */,\r
+                  scanColumnList,\r
+                  startKeyValue, startSearchOperator,\r
+                  qualifier,\r
+                  stopKeyValue, stopSearchOperator, this, new B2IUndo(),\r
+                  (B2IStaticCompiledInfo) static_info,\r
+                  dynamic_info);\r
+\r
+               // Return it to the caller.\r
+               return b2is;\r
+       }\r
+\r
+    /**\r
+     * Open a b-tree compress scan.\r
+     * <p>\r
+     * B2I does not support a compress scan.\r
+     * <p>\r
+        * @see Conglomerate#defragmentConglomerate\r
+     *\r
+        * @exception  StandardException  Standard exception policy.\r
+     **/\r
+       public ScanManager defragmentConglomerate(\r
+    TransactionManager              xact_manager,\r
+    Transaction                     rawtran,\r
+    boolean                         hold,\r
+    int                             open_mode,\r
+    int                             lock_level,\r
+    LockingPolicy                   locking_policy,\r
+    int                             isolation_level)\r
+                       throws StandardException\r
+       {\r
+        throw StandardException.newException(\r
+            SQLState.BTREE_UNIMPLEMENTED_FEATURE);\r
+       }\r
+\r
+       public void purgeConglomerate(\r
+    TransactionManager              xact_manager,\r
+    Transaction                     rawtran)\r
+        throws StandardException\r
+    {\r
+        // currently on work to do in btree's for purge rows, purging\r
+        // happens best when split is about to happen.\r
+        return;\r
+    }\r
+\r
+       public void compressConglomerate(\r
+    TransactionManager              xact_manager,\r
+    Transaction                     rawtran)\r
+        throws StandardException\r
+    {\r
+               B2IController b2ic = new B2IController();\r
+\r
+               try\r
+               {\r
+            int open_mode = TransactionController.OPENMODE_FORUPDATE;\r
+\r
+            // Do the actual open of the container in the super class.\r
+            b2ic.init(\r
+                xact_manager,                    // current transaction   \r
+                xact_manager.getRawStoreXact(),  // current raw store xact\r
+                false,                           // Not holdable\r
+                open_mode,\r
+                TransactionController.MODE_TABLE,\r
+                xact_manager.getRawStoreXact().newLockingPolicy(\r
+                    LockingPolicy.MODE_CONTAINER,\r
+                    TransactionController.ISOLATION_SERIALIZABLE, true),\r
+                true,\r
+                this, \r
+                new B2IUndo(),\r
+                (B2IStaticCompiledInfo) null,\r
+                (DynamicCompiledOpenConglomInfo) null);\r
+\r
+            b2ic.getContainer().compressContainer();\r
+\r
+               }\r
+               finally\r
+               {\r
+                       b2ic.close();\r
+               }\r
+\r
+        return;\r
+    }\r
+\r
+    /**\r
+     * Return an open StoreCostController for the conglomerate.\r
+     * <p>\r
+     * Return an open StoreCostController which can be used to ask about \r
+     * the estimated row counts and costs of ScanController and \r
+     * ConglomerateController operations, on the given conglomerate.\r
+     * <p>\r
+        * @param xact_manager The TransactionController under which this \r
+     *                     operation takes place.\r
+        * @param rawtran  raw transaction context in which scan is managed.\r
+     *\r
+        * @return The open StoreCostController.\r
+     *\r
+        * @exception  StandardException  Standard exception policy.\r
+     *\r
+     * @see StoreCostController\r
+     **/\r
+    public StoreCostController openStoreCost(\r
+    TransactionManager  xact_manager,\r
+    Transaction         rawtran)\r
+               throws StandardException\r
+    {\r
+        B2ICostController b2icost = new B2ICostController();\r
+\r
+        b2icost.init(xact_manager, this, rawtran);\r
+\r
+        return(b2icost);\r
+    }\r
+\r
+       /**\r
+       Drop this b-tree secondary index.\r
+       @see Conglomerate#drop\r
+       @see BTree#drop\r
+\r
+       @exception StandardException Standard exception policy.\r
+       **/\r
+       public void drop(TransactionManager xact_manager)\r
+               throws StandardException\r
+       {\r
+        // HACK to get around problem where index is dropped after the base\r
+        // table.\r
+        ConglomerateController base_cc = null;\r
+\r
+\r
+        /* Get X table lock to make sure no thread is accessing index */\r
+        base_cc = \r
+            lockTable(\r
+                xact_manager, \r
+                TransactionController.OPENMODE_FORUPDATE, \r
+                TransactionController.MODE_TABLE,\r
+                TransactionController.ISOLATION_REPEATABLE_READ);\r
+\r
+        xact_manager.getRawStoreXact().dropContainer(id);\r
+\r
+        if (base_cc != null)\r
+            base_cc.close();\r
+       }\r
+\r
+    /**\r
+     * Return static information about the conglomerate to be included in a\r
+     * a compiled plan.\r
+     * <p>\r
+     * The static info would be valid until any ddl was executed on the \r
+     * conglomid, and would be up to the caller to throw away when that \r
+     * happened.  This ties in with what language already does for other \r
+     * invalidation of static info.  The type of info in this would be \r
+     * containerid and array of format id's from which templates can be created.\r
+     * The info in this object is read only and can be shared among as many \r
+     * threads as necessary.\r
+     * <p>\r
+     *\r
+        * @return The static compiled information.\r
+     *\r
+     * @param conglomId The identifier of the conglomerate to open.\r
+     *\r
+        * @exception  StandardException  Standard exception policy.\r
+     **/\r
+    public StaticCompiledOpenConglomInfo getStaticCompiledConglomInfo(\r
+    TransactionController   xact_manager,\r
+    long                    conglomId)\r
+               throws StandardException\r
+    {\r
+        return(new B2IStaticCompiledInfo(xact_manager, this));\r
+    }\r
+\r
+       /*\r
+       ** Methods of Storable (via Conglomerate via BTree).\r
+       ** This class is responsible for re/storing its\r
+       ** own state and calling its superclass to store its'.\r
+       */\r
+\r
+\r
+       /*\r
+        * Storable interface, implies Externalizable, TypedFormat\r
+        */\r
+\r
+\r
+       /**\r
+               Return my format identifier.\r
+\r
+               @see org.apache.derby.iapi.services.io.TypedFormat#getTypeFormatId\r
+       */\r
+       public int getTypeFormatId() \r
+    {\r
+               return StoredFormatIds.ACCESS_B2I_V4_ID;\r
+       }\r
+\r
+\r
+    /**\r
+     * Store the stored representation of the column value in the\r
+     * stream.\r
+     * <p>\r
+     * For more detailed description of the ACCESS_B2I_V3_ID format see \r
+     * documentation at top of file.\r
+     *\r
+     * @see java.io.Externalizable#writeExternal\r
+     **/\r
+       public void writeExternal_v10_2(ObjectOutput out) \r
+        throws IOException \r
+    {\r
+               super.writeExternal(out);\r
+               out.writeLong(baseConglomerateId);\r
+               out.writeInt(rowLocationColumn);\r
+\r
+        //write the columns ascend/descend information as bits\r
+        FormatableBitSet ascDescBits = \r
+            new FormatableBitSet(ascDescInfo.length);\r
+\r
+        for (int i = 0; i < ascDescInfo.length; i++)\r
+        {      \r
+            if (ascDescInfo[i])\r
+                ascDescBits.set(i);\r
+        }\r
+        ascDescBits.writeExternal(out);\r
+       }\r
+\r
+    /**\r
+     * Store the stored representation of the column value in the\r
+     * stream.\r
+     * <p>\r
+     * For more detailed description of the ACCESS_B2I_V3_ID and \r
+     * ACCESS_B2I_V4_ID formats see documentation at top of file.\r
+     *\r
+     * @see java.io.Externalizable#writeExternal\r
+     **/\r
+       public void writeExternal(ObjectOutput out) \r
+        throws IOException \r
+    {\r
+        // First part of ACCESS_B2I_V4_ID format is the ACCESS_B2I_V3_ID format.\r
+        writeExternal_v10_2(out);\r
+\r
+               if (conglom_format_id == StoredFormatIds.ACCESS_B2I_V4_ID)\r
+        {\r
+            // Now append sparse array of collation ids\r
+            ConglomerateUtil.writeCollationIdArray(collation_ids, out);\r
+        }\r
+       }\r
+\r
+    /**\r
+     * Restore the in-memory representation from the stream.\r
+     * <p>\r
+     *\r
+     * @exception ClassNotFoundException Thrown if the stored representation \r
+     *                                   is serialized and a class named in \r
+     *                                   the stream could not be found.\r
+     *\r
+     * @see java.io.Externalizable#readExternal\r
+     **/\r
+       private final void localReadExternal(ObjectInput in)\r
+               throws IOException, ClassNotFoundException\r
+       {\r
+               super.readExternal(in);\r
+               \r
+               baseConglomerateId = in.readLong();\r
+               rowLocationColumn  = in.readInt();\r
+\r
+        // read the column sort order info\r
+        FormatableBitSet ascDescBits = new FormatableBitSet();\r
+        ascDescBits.readExternal(in);\r
+        ascDescInfo = new boolean[ascDescBits.getLength()];\r
+        for(int i =0 ; i < ascDescBits.getLength(); i++)\r
+            ascDescInfo[i] = ascDescBits.isSet(i);\r
+\r
+        // In memory maintain a collation id per column in the template.\r
+        collation_ids = new int[format_ids.length];\r
+\r
+        // initialize all the entries to COLLATION_TYPE_UCS_BASIC, \r
+        // and then reset as necessary.  For version ACCESS_B2I_V3_ID,\r
+        // this is the default and no resetting is necessary.\r
+        for (int i = 0; i < format_ids.length; i++)\r
+            collation_ids[i] = StringDataValue.COLLATION_TYPE_UCS_BASIC;\r
+\r
+               if (conglom_format_id == StoredFormatIds.ACCESS_B2I_V4_ID)\r
+        {\r
+            // current format id, read collation info from disk\r
+\r
+            if (SanityManager.DEBUG)\r
+            {\r
+                // length must include row location column and at least\r
+                // one other field.\r
+                SanityManager.ASSERT(\r
+                    collation_ids.length >= 2, \r
+                    "length = " + collation_ids.length);\r
+            }\r
+\r
+            ConglomerateUtil.readCollationIdArray(collation_ids, in);\r
+        }\r
+        else if (conglom_format_id != StoredFormatIds.ACCESS_B2I_V3_ID)\r
+        {\r
+            // Currently only V3 and V4 should be possible in a Derby DB.\r
+            // Actual work for V3 is handled by default code above, so no\r
+            // special work is necessary.\r
+\r
+            if (SanityManager.DEBUG)\r
+            {\r
+                SanityManager.THROWASSERT(\r
+                    "Unexpected format id: " + conglom_format_id);\r
+            }\r
+        }\r
+       }\r
+\r
+       public void readExternal(ObjectInput in)\r
+               throws IOException, ClassNotFoundException\r
+       {\r
+        localReadExternal(in);\r
+    }\r
+       public void readExternalFromArray(ArrayInputStream in)\r
+               throws IOException, ClassNotFoundException\r
+       {\r
+        localReadExternal(in);\r
+    }\r
+}\r