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 / heap / Heap.java
diff --git a/JMCR-Stable/real-world application/derby-10.3.2.1/java/engine/org/apache/derby/impl/store/access/heap/Heap.java b/JMCR-Stable/real-world application/derby-10.3.2.1/java/engine/org/apache/derby/impl/store/access/heap/Heap.java
new file mode 100644 (file)
index 0000000..1044317
--- /dev/null
@@ -0,0 +1,1246 @@
+/*\r
+\r
+   Derby - Class org.apache.derby.impl.store.access.heap.Heap\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
+\r
+package org.apache.derby.impl.store.access.heap;\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
+\r
+import org.apache.derby.iapi.services.io.FormatIdUtil;\r
+import org.apache.derby.iapi.services.io.Storable;\r
+import org.apache.derby.iapi.services.io.StoredFormatIds;\r
+\r
+import org.apache.derby.iapi.error.StandardException;\r
+\r
+import org.apache.derby.iapi.store.access.conglomerate.Conglomerate;\r
+import org.apache.derby.iapi.store.access.conglomerate.LogicalUndo;\r
+import org.apache.derby.iapi.store.access.conglomerate.TransactionManager;\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.AccessFactoryGlobals;\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.RowUtil;\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
+import org.apache.derby.iapi.store.raw.ContainerKey;\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
+import org.apache.derby.iapi.store.raw.Page;\r
+import org.apache.derby.iapi.store.raw.RawStoreFactory;\r
+\r
+import org.apache.derby.iapi.types.DataValueDescriptor;\r
+import org.apache.derby.iapi.types.StringDataValue;\r
+\r
+import org.apache.derby.iapi.services.cache.ClassSize;\r
+\r
+import org.apache.derby.impl.store.access.conglomerate.ConglomerateUtil;\r
+import org.apache.derby.impl.store.access.conglomerate.GenericConglomerate;\r
+import org.apache.derby.impl.store.access.conglomerate.OpenConglomerate;\r
+import org.apache.derby.impl.store.access.conglomerate.OpenConglomerateScratchSpace;\r
+\r
+/**\r
+ * @format_id ACCESS_HEAP_V2_ID\r
+ *\r
+ * @purpose   The tag that describes the on disk representation of the Heap\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 HeapFactory which\r
+ *            must be able to read all heap format id's.  \r
+ *\r
+ *            This format was used for all Derby database Heap'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 heap \r
+ *            until we are in the "middle" of reading the Heap.  Thus the\r
+ *            base Heap 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_HEAP_V3_ID:\r
+ *                read:\r
+ *                    old format is readable by current Heap 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 Heap_v10_2 class to \r
+ *                    that will write out old format info.\r
+ *\r
+ *            hard upgrade to ACCESS_HEAP_V3_ID:\r
+ *                read:\r
+ *                    old format is readable by current Heap 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_columns(int)\r
+ *     array_of_format_ids(byte[][])\r
+ **/\r
+\r
+/**\r
+ * @format_id ACCESS_HEAP_V3_ID\r
+ *\r
+ * @purpose   The tag that describes the on disk representation of the Heap\r
+ *            conglomerate object.  The Heap conglomerate object is stored in\r
+ *            a field of a row in the Conglomerate directory.\r
+ *\r
+ * @purpose   The tag that describes the on disk representation of the Heap\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 HeapFactory which\r
+ *            must be able to read all heap format id's.  \r
+ *\r
+ *            This format is used for all Derby database Heap's in versions\r
+ *            subsequent to 10.2.  The format is contains first the \r
+ *            ACCESS_HEAP_V2_ID format, followed by a compressed representation\r
+ *            of the collation id's of each column in the heap.\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_columns(int)\r
+ *     array_of_format_ids(byte[][])\r
+ *     collation_ids(compressed array of ints)\r
+ **/\r
+\r
+/**\r
+\r
+  A heap object corresponds to an instance of a heap conglomerate.  It caches\r
+  information which makes it fast to open heap controllers from it.\r
+\r
+**/\r
+\r
+public class Heap \r
+    extends    GenericConglomerate\r
+    implements Conglomerate, StaticCompiledOpenConglomInfo\r
+{\r
+\r
+\r
+       /*\r
+       ** Fields of Heap.\r
+       */\r
+\r
+    /**\r
+     * Format id of the conglomerate.\r
+     **/\r
+       protected int conglom_format_id;\r
+\r
+       private ContainerKey id;\r
+\r
+    /**\r
+     * The format id's of each of the columns in the heap table.\r
+     **/\r
+    int[]    format_ids;\r
+\r
+    /**\r
+    The array of collation id's for each column in the template.\r
+    **/\r
+    protected int[]   collation_ids;\r
+\r
+    private static final int BASE_MEMORY_USAGE = ClassSize.estimateBaseFromCatalog( Heap.class);\r
+    private static final int CONTAINER_KEY_MEMORY_USAGE = ClassSize.estimateBaseFromCatalog( ContainerKey.class);\r
+\r
+    public int estimateMemoryUsage()\r
+    {\r
+        int sz = BASE_MEMORY_USAGE;\r
+\r
+        if( null != id)\r
+            sz += CONTAINER_KEY_MEMORY_USAGE;\r
+        if( null != format_ids)\r
+            sz += format_ids.length*ClassSize.getIntSize();\r
+        return sz;\r
+    } // end of estimateMemoryUsage\r
+\r
+       /*\r
+       ** Methods of Heap.\r
+       */\r
+\r
+    /* Constructors for This class: */\r
+\r
+    /**\r
+     * Zero arg constructor for Monitor to create empty object.\r
+     **/\r
+    public Heap()\r
+    {\r
+    }\r
+\r
+    /* Private/Protected methods of This class: */\r
+\r
+    /**\r
+     * Create a heap conglomerate.\r
+     * <p>\r
+     * Create a heap conglomerate.  This method is called from the heap factory\r
+     * to create a new instance of a heap.\r
+     * <p>\r
+     *\r
+        * @exception  StandardException  Standard exception policy.\r
+     **/\r
+       protected void create(\r
+    Transaction             rawtran,\r
+    int                     segmentId,\r
+    long                    input_containerid,\r
+    DataValueDescriptor[]   template,\r
+    ColumnOrdering[]        columnOrder,\r
+    int[]                   collationIds,\r
+    Properties              properties,\r
+    int                     conglom_format_id,\r
+       int                     tmpFlag)\r
+               throws StandardException\r
+       {\r
+               // Create a container for the heap table with\r
+               // default minimumRecordSize to be at least\r
+               // MINIMUM_RECORD_SIZE_DEFAULT (12),\r
+               // to guarantee there is enough room for updates\r
+               // of the row.\r
+               // Here we only take care of the case that\r
+               // that the properties are set with the create\r
+               // statement.  For the case when properties are\r
+               // not set with the create statement, it is taken\r
+               // care of in fileContainer.java: createInfoFromProp().\r
+               if (properties != null) \r
+        {\r
+                       String value = properties.getProperty(\r
+                               RawStoreFactory.MINIMUM_RECORD_SIZE_PARAMETER);\r
+\r
+                       int minimumRecordSize =\r
+                               (value == null) ? \r
+                    RawStoreFactory.MINIMUM_RECORD_SIZE_DEFAULT : \r
+                    Integer.parseInt(value);\r
+\r
+                       if (minimumRecordSize < RawStoreFactory.MINIMUM_RECORD_SIZE_DEFAULT)\r
+                       {\r
+                               properties.put(\r
+                    RawStoreFactory.MINIMUM_RECORD_SIZE_PARAMETER,\r
+                                       Integer.toString(\r
+                        RawStoreFactory.MINIMUM_RECORD_SIZE_DEFAULT));\r
+                       }\r
+               }\r
+\r
+               // Create a container for the heap with default page size.\r
+               long containerid = \r
+            rawtran.addContainer(\r
+                segmentId, input_containerid, \r
+                ContainerHandle.MODE_DEFAULT, properties, tmpFlag);\r
+\r
+               // Make sure the container was actually created.\r
+               if (containerid < 0)\r
+        {\r
+            throw StandardException.newException(\r
+                    SQLState.HEAP_CANT_CREATE_CONTAINER);\r
+        }\r
+\r
+               // Keep track of what segment the container's in.\r
+               id = new ContainerKey(segmentId, containerid);\r
+\r
+               // Heap requires a template representing every column in the table.\r
+        if ((template == null) || (template.length == 0))\r
+        {\r
+            throw StandardException.newException(\r
+                    SQLState.HEAP_COULD_NOT_CREATE_CONGLOMERATE);\r
+        }\r
+\r
+        // get format id's from each column in template and store it in the\r
+        // conglomerate state.\r
+        this.format_ids = ConglomerateUtil.createFormatIds(template);\r
+\r
+        // copy the format id of the conglomerate.\r
+        this.conglom_format_id = conglom_format_id;\r
+\r
+        // get collation ids from input collation ids, store it in the \r
+        // conglom state.\r
+        collation_ids = \r
+            ConglomerateUtil.createCollationIds(\r
+                format_ids.length, collationIds);\r
+\r
+        // need to open the container and insert the row.  Since we are\r
+        // creating it no need to bother with locking since no one can get\r
+        // to it until after we have created it and returned it's id.\r
+        ContainerHandle container = null;\r
+        Page            page      = null;\r
+\r
+        try\r
+        {\r
+            container = \r
+                rawtran.openContainer(\r
+                    id, (LockingPolicy) null, \r
+                    ContainerHandle.MODE_FORUPDATE | \r
+                        (isTemporary() ? ContainerHandle.MODE_TEMP_IS_KEPT : 0));\r
+\r
+            // row in slot 0 of heap page 1 which is just a single column with\r
+            // the heap entry.\r
+            DataValueDescriptor[] control_row = new DataValueDescriptor[1];\r
+            control_row[0] = this;\r
+\r
+            page =\r
+                container.getPage(ContainerHandle.FIRST_PAGE_NUMBER);\r
+\r
+            page.insertAtSlot(\r
+                Page.FIRST_SLOT_NUMBER,\r
+                control_row,\r
+                (FormatableBitSet) null,\r
+                (LogicalUndo) null, \r
+                Page.INSERT_OVERFLOW,\r
+                AccessFactoryGlobals.HEAP_OVERFLOW_THRESHOLD);\r
+            page.unlatch();\r
+            page = null;\r
+\r
+            // Don't include the control row in the estimated row count.\r
+            container.setEstimatedRowCount(0, /* unused flag */ 0);\r
+        }\r
+        finally\r
+        {\r
+            if (container != null)\r
+                container.close();\r
+            if (page !=null)\r
+                page.unlatch();\r
+        }\r
+       }\r
+\r
+    /**\r
+     * Create a heap conglomerate during the boot process.\r
+     * <p>\r
+     * Manufacture a Heap Conglomerate out of "thin" air, to boot strap\r
+     * the system.  Create an in-memory Heap Conglomerate with the input\r
+     * parameters, The caller will use this to open the conglomerate\r
+     * conglomerate and read the "real" values from disk.  Conglom-conglom\r
+     * is always on segment 0.\r
+     *\r
+     *\r
+     * @param containerid The container id of the conglomerate.\r
+     * @param template    Object array describing the columns of the heap.\r
+     **/\r
+    public void boot_create(\r
+    long                    containerid,\r
+    DataValueDescriptor[]   template)\r
+    {\r
+               id = new ContainerKey(0, containerid);\r
+        this.format_ids = ConglomerateUtil.createFormatIds(template);\r
+    }\r
+\r
+       /*\r
+       ** Methods of Conglomerate\r
+       */\r
+\r
+    /**\r
+     * Add a column to the heap conglomerate.\r
+     * <p>\r
+     * This routine update's the in-memory object version of the Heap\r
+     * Conglomerate to have one more column of the type described by the\r
+     * input template column.  \r
+     * \r
+     * @param column_id        The column number to add this column at.\r
+     * @param template_column  An instance of the column to be added to table.\r
+     * @param collation_id     Collation id of the column added.\r
+     *\r
+        * @exception  StandardException  Standard exception policy.\r
+     **/\r
+       public void addColumn(\r
+       TransactionManager  xact_manager,\r
+    int                 column_id,\r
+    Storable            template_column,\r
+    int                 collation_id)\r
+        throws StandardException\r
+    {\r
+        // need to open the container and update the row containing the \r
+        // serialized format of the heap.  \r
+        ContainerHandle container = null;\r
+        Page            page      = null;\r
+        Transaction     rawtran   = xact_manager.getRawStoreXact();\r
+\r
+        try\r
+        {\r
+            container = \r
+                rawtran.openContainer(\r
+                    id, \r
+                    rawtran.newLockingPolicy(\r
+                        LockingPolicy.MODE_CONTAINER,\r
+                        TransactionController.ISOLATION_SERIALIZABLE, true),\r
+                    ContainerHandle.MODE_FORUPDATE | \r
+                        (isTemporary() ? ContainerHandle.MODE_TEMP_IS_KEPT : 0));\r
+\r
+            if (column_id != format_ids.length)\r
+            {\r
+                if (SanityManager.DEBUG)\r
+                    SanityManager.THROWASSERT(\r
+                        "column_id = " + column_id +\r
+                        "format_ids.length = " + format_ids.length +\r
+                        "format_ids = " + format_ids);\r
+\r
+                throw(StandardException.newException(\r
+                        SQLState.HEAP_TEMPLATE_MISMATCH,\r
+                        new Long(column_id), \r
+                        new Long(this.format_ids.length)));\r
+            }\r
+\r
+            // create a new array, and copy old values to it.\r
+            int[] old_format_ids = format_ids;\r
+            format_ids              = new int[old_format_ids.length + 1];\r
+            System.arraycopy(\r
+                old_format_ids, 0, format_ids, 0, old_format_ids.length);\r
+\r
+            // add the new column\r
+            format_ids[old_format_ids.length] = \r
+                template_column.getTypeFormatId();\r
+\r
+            // create a new collation array, and copy old values to it.\r
+            int[] old_collation_ids = collation_ids;\r
+            collation_ids           = new int[old_collation_ids.length + 1];\r
+            System.arraycopy(\r
+                old_collation_ids, 0, collation_ids, 0, \r
+                old_collation_ids.length);\r
+\r
+            // add the new column's collation id.\r
+            collation_ids[old_collation_ids.length] =  collation_id;\r
+           \r
+            // row in slot 0 of heap page 1 which is just a single column with\r
+            // the heap entry.\r
+            DataValueDescriptor[] control_row = new DataValueDescriptor[1];\r
+            control_row[0] = this;\r
+\r
+            page =\r
+                container.getPage(ContainerHandle.FIRST_PAGE_NUMBER);\r
+\r
+            page.updateAtSlot(\r
+                Page.FIRST_SLOT_NUMBER,\r
+                control_row,\r
+                (FormatableBitSet) null);\r
+\r
+            page.unlatch();\r
+            page = null;\r
+        }\r
+        finally\r
+        {\r
+            if (container != null)\r
+                container.close();\r
+            if (page !=null)\r
+                page.unlatch();\r
+        }\r
+\r
+        return;\r
+    }\r
+\r
+\r
+       /**\r
+       Drop this heap.\r
+       @see Conglomerate#drop\r
+\r
+       @exception StandardException Standard exception policy.\r
+       **/\r
+       public void drop(TransactionManager xact_manager)\r
+               throws StandardException\r
+       {\r
+        xact_manager.getRawStoreXact().dropContainer(id);\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 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
+        // no support for max on a heap table.\r
+        throw(StandardException.newException(\r
+                SQLState.HEAP_UNIMPLEMENTED_FEATURE));\r
+    }\r
+\r
+    /**\r
+     * Get the id of the container of the conglomerate.\r
+     * <p>\r
+     * Will have to change when a conglomerate could have more than one \r
+     * container.  The ContainerKey is a combination of the container id\r
+     * and segment id.\r
+     *\r
+        * @return The ContainerKey.\r
+     **/\r
+    public final ContainerKey getId()\r
+    {\r
+        return(id);\r
+    }\r
+\r
+\r
+    public final long getContainerid()\r
+    {\r
+        return(id.getContainerId());\r
+    }\r
+\r
+    /**\r
+     * Return dynamic information about the conglomerate to be dynamically \r
+     * reused in repeated execution of a statement.\r
+     * <p>\r
+     * The dynamic info is a set of variables to be used in a given \r
+     * ScanController or ConglomerateController.  It can only be used in one \r
+     * controller at a time.  It is up to the caller to insure the correct \r
+     * thread access to this info.  The type of info in this is a scratch \r
+     * template for btree traversal, other scratch variables for qualifier \r
+     * evaluation, ...\r
+     * <p>\r
+     *\r
+        * @return The dynamic information.\r
+     *\r
+     * @param conglomId The identifier of the conglomerate to open.\r
+     *\r
+        * @exception  StandardException  Standard exception policy.\r
+     **/\r
+    public DynamicCompiledOpenConglomInfo getDynamicCompiledConglomInfo(\r
+    long        conglomId)\r
+               throws StandardException\r
+    {\r
+        return(new OpenConglomerateScratchSpace(format_ids, collation_ids));\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   tc,\r
+    long                    conglomId)\r
+               throws StandardException\r
+    {\r
+        return(this);\r
+    }\r
+\r
+\r
+    /**\r
+     * Is this conglomerate temporary?\r
+     * <p>\r
+     *\r
+        * @return whether conglomerate is temporary or not.\r
+     **/\r
+    public boolean isTemporary()\r
+    {\r
+        return(id.getSegmentId() == ContainerHandle.TEMPORARY_SEGMENT);\r
+    }\r
+\r
+\r
+    /**\r
+     * Bulk load into the conglomerate.\r
+     * <p>\r
+     *\r
+     * @see Conglomerate#load\r
+     *\r
+        * @exception  StandardException  Standard exception policy.\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
+\r
+               HeapController heapcontroller = new HeapController();\r
+\r
+               try\r
+               {\r
+                       num_rows_loaded = \r
+                heapcontroller.load(\r
+                    xact_manager,\r
+                    this, \r
+                    createConglom,\r
+                    rowSource);\r
+               }\r
+               finally\r
+               {\r
+                       // Done with this heap controller.\r
+                       heapcontroller.close();\r
+               }\r
+\r
+        return(num_rows_loaded);\r
+       }\r
+\r
+    /**\r
+     * Open a heap controller.\r
+     * <p>\r
+     *\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
+        OpenConglomerate open_conglom = new OpenHeap();\r
+\r
+        if (open_conglom.init(\r
+                (ContainerHandle) null,\r
+                this,\r
+                this.format_ids,\r
+                this.collation_ids,\r
+                xact_manager,\r
+                rawtran,\r
+                hold,\r
+                open_mode,\r
+                lock_level,\r
+                locking_policy,\r
+                dynamic_info) == null)\r
+        {\r
+            throw StandardException.newException(\r
+                    SQLState.HEAP_CONTAINER_NOT_FOUND, \r
+                    new Long(id.getContainerId()).toString());\r
+        }\r
+\r
+               HeapController heapcontroller = new HeapController();\r
+\r
+        heapcontroller.init(open_conglom);\r
+\r
+               return(heapcontroller);\r
+       }\r
+\r
+    /**\r
+     * Open a heap scan controller.\r
+     * <p>\r
+     *\r
+     * @see Conglomerate#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
+        // Heap scans do not suppport start and stop scan positions (these\r
+        // only make sense for ordered storage structures).\r
+               if (!RowUtil.isRowEmpty(startKeyValue)\r
+                       || !RowUtil.isRowEmpty(stopKeyValue))\r
+               {\r
+            throw StandardException.newException(\r
+                    SQLState.HEAP_UNIMPLEMENTED_FEATURE);\r
+               }\r
+\r
+        OpenConglomerate open_conglom = new OpenHeap();\r
+\r
+        if (open_conglom.init(\r
+                (ContainerHandle) null,\r
+                this,\r
+                this.format_ids,\r
+                this.collation_ids,\r
+                xact_manager,\r
+                rawtran,\r
+                hold,\r
+                open_mode,\r
+                lock_level,\r
+                locking_policy,\r
+                dynamic_info) == null)\r
+        {\r
+            throw StandardException.newException(\r
+                    SQLState.HEAP_CONTAINER_NOT_FOUND, \r
+                    new Long(id.getContainerId()));\r
+        }\r
+\r
+               HeapScan heapscan = new HeapScan();\r
+\r
+        heapscan.init(\r
+            open_conglom,\r
+            scanColumnList,\r
+            startKeyValue,\r
+            startSearchOperator,\r
+            qualifier,\r
+            stopKeyValue,\r
+            stopSearchOperator);\r
+\r
+               return(heapscan);\r
+       }\r
+\r
+       public void purgeConglomerate(\r
+    TransactionManager              xact_manager,\r
+    Transaction                     rawtran)\r
+        throws StandardException\r
+    {\r
+        OpenConglomerate        open_for_ddl_lock   = null;\r
+        HeapController          heapcontroller      = null;\r
+        TransactionManager      nested_xact         = null;\r
+\r
+        try\r
+        {\r
+            open_for_ddl_lock = new OpenHeap();\r
+\r
+            // Open table in intended exclusive mode in the top level \r
+            // transaction, this will stop any ddl from happening until \r
+            // purge of whole table is finished.\r
+\r
+            if (open_for_ddl_lock.init(\r
+                    (ContainerHandle) null,\r
+                    this,\r
+                    this.format_ids,\r
+                    this.collation_ids,\r
+                    xact_manager,\r
+                    rawtran,\r
+                    false,\r
+                    TransactionController.OPENMODE_FORUPDATE,\r
+                    TransactionController.MODE_RECORD,\r
+                    null,\r
+                    null) == null)\r
+            {\r
+                throw StandardException.newException(\r
+                        SQLState.HEAP_CONTAINER_NOT_FOUND, \r
+                        new Long(id.getContainerId()));\r
+            }\r
+\r
+            // perform all the "real" work in a non-readonly nested user \r
+            // transaction, so that as work is completed on each page resources\r
+            // can be released.  Must be careful as all locks obtained in nested\r
+            // transaction will conflict with parent transaction - so this call\r
+            // must be made only if parent transaction can have no conflicting\r
+            // locks on the table, otherwise the purge will fail with a self\r
+            // deadlock.\r
+            nested_xact = (TransactionManager) \r
+                xact_manager.startNestedUserTransaction(false);\r
+\r
+            // now open the table in a nested user transaction so that each\r
+            // page worth of work can be committed after it is done.\r
+\r
+            OpenConglomerate open_conglom = new OpenHeap();\r
+\r
+            if (open_conglom.init(\r
+                (ContainerHandle) null,\r
+                this,\r
+                this.format_ids,\r
+                this.collation_ids,\r
+                nested_xact,\r
+                nested_xact.getRawStoreXact(),\r
+                true,\r
+                TransactionController.OPENMODE_FORUPDATE,\r
+                TransactionController.MODE_RECORD,\r
+                nested_xact.getRawStoreXact().newLockingPolicy(\r
+                    LockingPolicy.MODE_RECORD,\r
+                        TransactionController.ISOLATION_REPEATABLE_READ, true),\r
+                null) == null)\r
+            {\r
+                throw StandardException.newException(\r
+                        SQLState.HEAP_CONTAINER_NOT_FOUND, \r
+                        new Long(id.getContainerId()).toString());\r
+            }\r
+\r
+            heapcontroller = new HeapController();\r
+\r
+            heapcontroller.init(open_conglom);\r
+\r
+            Page page   = open_conglom.getContainer().getFirstPage();\r
+\r
+            boolean purgingDone = false;\r
+\r
+            while (page != null)\r
+            {\r
+                long pageno = page.getPageNumber();\r
+                purgingDone = heapcontroller.purgeCommittedDeletes(page);\r
+\r
+                if (purgingDone)\r
+                {\r
+                    page = null;\r
+\r
+                    // commit xact to free resouurces ASAP, commit will\r
+                    // unlatch the page if it has not already been unlatched\r
+                    // by a remove.\r
+                    open_conglom.getXactMgr().commitNoSync(\r
+                                TransactionController.RELEASE_LOCKS);\r
+\r
+                    // the commit closes the underlying container, so let\r
+                    // the heapcontroller know this has happened.  Usually\r
+                    // the transaction takes care of this, but this controller\r
+                    // is internal, so the transaction does not know about it.\r
+                    heapcontroller.closeForEndTransaction(false);\r
+                    \r
+                    // the commit will close the underlying \r
+                    open_conglom.reopen();\r
+                }\r
+                else\r
+                {\r
+                    page.unlatch();\r
+                    page = null;\r
+                }\r
+\r
+                page = open_conglom.getContainer().getNextPage(pageno);\r
+            }\r
+        }\r
+        finally\r
+        {\r
+            if (open_for_ddl_lock != null)\r
+                open_for_ddl_lock.close();\r
+            if (heapcontroller != null)\r
+                heapcontroller.close();\r
+            if (nested_xact != null)\r
+            {\r
+                nested_xact.commitNoSync(TransactionController.RELEASE_LOCKS);\r
+                nested_xact.destroy();\r
+            }\r
+        }\r
+\r
+        return;\r
+    }\r
+\r
+       public void compressConglomerate(\r
+    TransactionManager              xact_manager,\r
+    Transaction                     rawtran)\r
+        throws StandardException\r
+    {\r
+        OpenConglomerate        open_conglom    = null;\r
+        HeapController          heapcontroller  = null;\r
+\r
+        try\r
+        {\r
+            open_conglom = new OpenHeap();\r
+\r
+            // Open table in intended exclusive mode in the top level \r
+            // transaction, this will stop any ddl from happening until \r
+            // purge of whole table is finished.\r
+\r
+            if (open_conglom.init(\r
+                    (ContainerHandle) null,\r
+                    this,\r
+                    this.format_ids,\r
+                    this.collation_ids,\r
+                    xact_manager,\r
+                    rawtran,\r
+                    false,\r
+                    TransactionController.OPENMODE_FORUPDATE,\r
+                    TransactionController.MODE_TABLE,\r
+                    rawtran.newLockingPolicy(\r
+                        LockingPolicy.MODE_CONTAINER,\r
+                        TransactionController.ISOLATION_REPEATABLE_READ, true),\r
+                    null) == null)\r
+            {\r
+                throw StandardException.newException(\r
+                        SQLState.HEAP_CONTAINER_NOT_FOUND, \r
+                        new Long(id.getContainerId()));\r
+            }\r
+\r
+            heapcontroller = new HeapController();\r
+\r
+            heapcontroller.init(open_conglom);\r
+\r
+            open_conglom.getContainer().compressContainer();\r
+        }\r
+        finally\r
+        {\r
+            if (open_conglom != null)\r
+                open_conglom.close();\r
+        }\r
+\r
+        return;\r
+    }\r
+\r
+    /**\r
+     * Open a heap compress scan.\r
+     * <p>\r
+     *\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
+        OpenConglomerate open_conglom = new OpenHeap();\r
+\r
+        if (open_conglom.init(\r
+                (ContainerHandle) null,\r
+                this,\r
+                this.format_ids,\r
+                this.collation_ids,\r
+                xact_manager,\r
+                rawtran,\r
+                hold,\r
+                open_mode,\r
+                lock_level,\r
+                rawtran.newLockingPolicy(\r
+                    LockingPolicy.MODE_RECORD,\r
+                    TransactionController.ISOLATION_REPEATABLE_READ, true),\r
+                null) == null)\r
+        {\r
+            throw StandardException.newException(\r
+                    SQLState.HEAP_CONTAINER_NOT_FOUND, \r
+                    new Long(id.getContainerId()));\r
+        }\r
+\r
+               HeapCompressScan heap_compress_scan = new HeapCompressScan();\r
+\r
+        heap_compress_scan.init(\r
+            open_conglom,\r
+            null,\r
+            null,\r
+            0,\r
+            null,\r
+            null,\r
+            0);\r
+\r
+               return(heap_compress_scan);\r
+       }\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
+        OpenHeap open_conglom = new OpenHeap();\r
+\r
+        if (open_conglom.init(\r
+                (ContainerHandle) null,\r
+                this,\r
+                this.format_ids,\r
+                this.collation_ids,\r
+                xact_manager,\r
+                rawtran,\r
+                false,\r
+                ContainerHandle.MODE_READONLY,\r
+                TransactionController.MODE_TABLE,\r
+                (LockingPolicy) null,\r
+                (DynamicCompiledOpenConglomInfo) null) == null)\r
+        {\r
+            throw StandardException.newException(\r
+                    SQLState.HEAP_CONTAINER_NOT_FOUND, \r
+                    new Long(id.getContainerId()));\r
+        }\r
+\r
+\r
+        HeapCostController heapcost = new HeapCostController();\r
+\r
+        heapcost.init(open_conglom);\r
+\r
+               return(heapcost);\r
+    }\r
+\r
+\r
+    /**\r
+     * Print this heap.\r
+     **/\r
+    public String toString()\r
+    {\r
+        return (id == null) ? "null" : id.toString();\r
+    }\r
+\r
+    /**************************************************************************\r
+     * Public Methods of StaticCompiledOpenConglomInfo Interface:\r
+     **************************************************************************\r
+     */\r
+\r
+    /**\r
+     * return the "Conglomerate".\r
+     * <p>\r
+     * For heap just return "this", which both implements Conglomerate and\r
+     * StaticCompiledOpenConglomInfo.\r
+     * <p>\r
+     *\r
+        * @return this\r
+     **/\r
+    public DataValueDescriptor getConglom()\r
+    {\r
+        return(this);\r
+    }\r
+\r
+\r
+    /**************************************************************************\r
+        * Methods of Storable (via Conglomerate)\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_HEAP_V3_ID;\r
+       }\r
+\r
+    /**\r
+     * Return whether the value is null or not.\r
+     *\r
+        * @see org.apache.derby.iapi.services.io.Storable#isNull\r
+     **/\r
+       public boolean isNull()\r
+       {\r
+               return id == null;\r
+       }\r
+\r
+    /**\r
+     * Restore the in-memory representation to the null value.\r
+     *\r
+     * @see org.apache.derby.iapi.services.io.Storable#restoreToNull\r
+     *\r
+     **/\r
+       public void restoreToNull()\r
+       {\r
+               id = null;\r
+       }\r
+\r
+    /**\r
+     * Store the stored representation of the column value in the stream.\r
+     *\r
+     **/\r
+\r
+    /**\r
+     * Store the 10.2 format stored representation of column value in stream.\r
+     * <p>\r
+     * This routine stores the 10.2 version the Heap, ie. the ACCESS_HEAP_V2_ID\r
+     * format.  It is used by any database which has been created in \r
+     * 10.2 or a previous release and has not been hard upgraded to a \r
+     * version subsequent to 10.2.\r
+     * <p>\r
+     **/\r
+       protected void writeExternal_v10_2(ObjectOutput out) throws IOException\r
+    {\r
+\r
+        // write the format id of this conglomerate\r
+        FormatIdUtil.writeFormatIdInteger(out, conglom_format_id);\r
+\r
+               out.writeInt((int) id.getSegmentId());\r
+        out.writeLong(id.getContainerId());\r
+\r
+        // write number of columns in heap.\r
+        out.writeInt(format_ids.length);\r
+\r
+        // write out array of format id's\r
+        ConglomerateUtil.writeFormatIdArray(format_ids, out);\r
+       }\r
+\r
+    /**\r
+     * Store the stored representation of column value in stream.\r
+     * <p>\r
+     * This routine uses the current database version to either store the\r
+     * the 10.2 format (ACCESS_HEAP_V2_ID) or the current format \r
+     * (ACCESS_HEAP_V3_ID).  \r
+     * <p>\r
+     **/\r
+       public void writeExternal(ObjectOutput out) throws IOException\r
+    {\r
+        writeExternal_v10_2(out);\r
+\r
+        if (conglom_format_id == StoredFormatIds.ACCESS_HEAP_V3_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
+\r
+        // read the format id of this conglomerate.\r
+        conglom_format_id = FormatIdUtil.readFormatIdInteger(in);\r
+\r
+               int segmentid = in.readInt();\r
+        long containerid = in.readLong();\r
+\r
+               id = new ContainerKey(segmentid, containerid);\r
+\r
+        // read the number of columns in the heap.\r
+        int num_columns = in.readInt();\r
+\r
+        // read the array of format ids.\r
+        format_ids = ConglomerateUtil.readFormatIdArray(num_columns, in);\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_HEAP_V2_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_HEAP_V3_ID)\r
+        {\r
+            // current format id, read collation info from disk\r
+\r
+            ConglomerateUtil.readCollationIdArray(collation_ids, in);\r
+        }\r
+        else if (conglom_format_id != StoredFormatIds.ACCESS_HEAP_V2_ID)\r
+        {\r
+            // Currently only V2 and V3 should be possible in a Derby DB.\r
+            // Actual work for V2 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
+\r
+       public void readExternalFromArray(ArrayInputStream in)\r
+               throws IOException, ClassNotFoundException\r
+       {\r
+        localReadExternal(in);\r
+    }\r
+}\r