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 / BTree.java
diff --git a/JMCR-Stable/real-world application/derby-10.3.2.1/java/engine/org/apache/derby/impl/store/access/btree/BTree.java b/JMCR-Stable/real-world application/derby-10.3.2.1/java/engine/org/apache/derby/impl/store/access/btree/BTree.java
new file mode 100644 (file)
index 0000000..9bfab58
--- /dev/null
@@ -0,0 +1,711 @@
+/*\r
+\r
+   Derby - Class org.apache.derby.impl.store.access.btree.BTree\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;\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
+\r
+import org.apache.derby.iapi.error.StandardException;\r
+import org.apache.derby.iapi.store.access.conglomerate.TransactionManager;\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.RowLocationRetRowSource;\r
+import org.apache.derby.iapi.store.access.StaticCompiledOpenConglomInfo;\r
+\r
+import org.apache.derby.iapi.store.raw.LockingPolicy;\r
+import org.apache.derby.iapi.store.raw.RawStoreFactory;\r
+import org.apache.derby.iapi.store.raw.ContainerHandle;\r
+import org.apache.derby.iapi.store.raw.Transaction;\r
+import org.apache.derby.iapi.store.raw.ContainerKey;\r
+\r
+import org.apache.derby.iapi.types.DataValueDescriptor;\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.OpenConglomerateScratchSpace;\r
+import org.apache.derby.impl.store.access.conglomerate.TemplateRow;\r
+\r
+import java.io.IOException;\r
+import java.io.ObjectOutput;\r
+import java.io.ObjectInput;\r
+\r
+import java.util.Properties;\r
+\r
+import org.apache.derby.iapi.services.io.ArrayUtil;\r
+\r
+/**\r
+\r
+  A b-tree object corresponds to an instance of a b-tree conglomerate.  It \r
+  contains the static information about a conglomerate which is built at \r
+  create conglomerate time.\r
+  <p>\r
+  This generic implementation is expected to be extended by the concreate\r
+  implementations.\r
+  <P>\r
+  The fields are set when the conglomerate is created and never changed \r
+  thereafter.  When alter table is supported then it will change under the\r
+  control of a table level lock.\r
+  <p>\r
+  They have package scope because they're read by the scans and controllers.\r
+  <p>\r
+  A table of all conglomerates in the system is maintained by the accessmanager.\r
+  A cache of conglomerates is maintained in the accessmanager, and references\r
+  to the read only objects are handed out.  A copy of the Conglomerate\r
+  object is kept in the control row of the root page, so that during logical\r
+  undo this information can be read without needing to access the possibly\r
+  corrupt table maintained by the access manager.\r
+**/\r
+\r
+public abstract class BTree extends GenericConglomerate\r
+{\r
+    /**************************************************************************\r
+     * Public Constants of BTree class:\r
+     **************************************************************************\r
+     */\r
+\r
+    /**\r
+     * The page number of the root page is always at the fixed page number:\r
+     * ROOTPAGEID.  This means that given an open container, during logical\r
+     * undo one can always find the root page and look up the conglomerate\r
+     * information.\r
+     **/\r
+    public static final long ROOTPAGEID = ContainerHandle.FIRST_PAGE_NUMBER;\r
+\r
+       /** \r
+    Property name for the maximum number of rows to place in a btree page (leaf\r
+    or branch).  Equal to 'derby.access.btreeMaxRowPerPage'.  Used by tests\r
+    and debugging to exactly control split points, and to make it easier to test\r
+    tall trees without needing lots of data.\r
+       */\r
+       public static final String PROPERTY_MAX_ROWS_PER_PAGE_PARAMETER = \r
+        (SanityManager.DEBUG ?  "derby.access.btreeMaxRowPerPage" : null);\r
+\r
+    /* properties of a btree see create(). */\r
+    public static final String PROPERTY_ALLOWDUPLICATES = "allowDuplicates";\r
+    public static final String PROPERTY_NKEYFIELDS      = "nKeyFields";\r
+    public static final String PROPERTY_NUNIQUECOLUMNS  = "nUniqueColumns";\r
+    public static final String PROPERTY_PARENTLINKS     = "maintainParentLinks";\r
+\r
+\r
+\r
+    /**************************************************************************\r
+     * Protected Fields of BTree class:\r
+     **************************************************************************\r
+     */\r
+\r
+       /**\r
+       The id of the container in which this b-tree is stored. \r
+       **/\r
+       protected ContainerKey id;\r
+\r
+       /**\r
+       The number of key fields.\r
+       **/\r
+       protected int nKeyFields;\r
+\r
+       /**\r
+       The number of uniqueness columns.  These are the columns that\r
+       are considered for the purpose of detecting duplicate keys and rows.\r
+       **/\r
+       int nUniqueColumns;\r
+\r
+       /**\r
+       Whether the index allows duplicates or not.\r
+       **/\r
+       boolean allowDuplicates;\r
+\r
+       /**\r
+       Whether the parent should maintain links from child pages to their parent.\r
+       These links are only used for consistency checking purposes.  They improve\r
+       consistency checking at the cost of run-time efficiency.\r
+       **/\r
+       boolean maintainParentLinks;\r
+\r
+    /**\r
+    Maximum rows per page to place on a btree leaf or nonleaf page.  Used\r
+    by testing to finely control split points.  Only changed for debugging\r
+    purposes.\r
+\r
+    RESOLVE (mikem) - this should not be static.  Need to design a way in\r
+    debugging mode to get btree created with a persistent "maxRowsPerPage".\r
+    This hack makes all btrees get created with the "last" maxRowsPerPage \r
+    value set.\r
+    **/\r
+    static int maxRowsPerPage = Integer.MAX_VALUE;\r
+\r
+       /**\r
+    Format id of the conglomerate.\r
+       **/\r
+       protected int conglom_format_id;\r
+\r
+    /**\r
+    The array of format id's, one for each column in the template.\r
+    **/\r
+    protected int[]    format_ids;\r
+\r
+\r
+       //columns sorting order information\r
+       // true - Ascending Order ; false -Descending Order\r
+       protected boolean[]     ascDescInfo;\r
+\r
+    /**\r
+    The array of collation id's for each column in the template.\r
+    **/\r
+    protected int[]   collation_ids;\r
+\r
+\r
+       /*\r
+       ** Private Methods of BTree.\r
+       */\r
+\r
+       /*\r
+       ** Public Methods of BTree.\r
+       */\r
+\r
+\r
+    /**************************************************************************\r
+     * Abstract Protected locking methods of BTree:\r
+     *     getBtreeLockingPolicy\r
+     *     lockScan\r
+     *     unlockScan\r
+     *     lockPreviousRow\r
+     *     lockRowOnPage\r
+     *     lockRow\r
+     *     lockTable\r
+     **************************************************************************\r
+     */\r
+\r
+    /**\r
+     * Create a new btree locking policy from scratch.\r
+     *\r
+        * @exception  StandardException  Standard exception policy.\r
+     **/\r
+    abstract 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
+    /**\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
+    abstract public ConglomerateController lockTable(\r
+    TransactionManager  xact_manager,\r
+    int                 open_mode,\r
+    int                 lock_level,\r
+    int                 isolation_level)\r
+               throws StandardException;\r
+\r
+\r
+    /**************************************************************************\r
+     * Private/Protected methods of BTree:\r
+     **************************************************************************\r
+     */\r
+\r
+\r
+    /**\r
+     * Create a branch row template for this conglomerate.\r
+     * <p>\r
+     * Reads the format id's of each of the columns and manufactures object of\r
+     * the given type for each.  It then uses these "empty" objects to create\r
+     * a template row.  The object passed in is then added to the last column\r
+     * of the row.\r
+     *\r
+        * @return The new template.\r
+     *\r
+        * @exception  StandardException  Standard exception policy.\r
+     **/\r
+    final DataValueDescriptor[] createBranchTemplate(\r
+    Transaction         rawtran,\r
+    DataValueDescriptor page_ptr)\r
+        throws StandardException\r
+    {\r
+        return(\r
+            TemplateRow.newBranchRow(\r
+                rawtran, format_ids, collation_ids, page_ptr));\r
+    }\r
+\r
+\r
+    /**************************************************************************\r
+     * Public methods of BTree:\r
+     **************************************************************************\r
+     */\r
+\r
+    /**\r
+     * Create a template for this conglomerate.\r
+     * <p>\r
+     * Reads the format id's of each of the columns and manufactures object of\r
+     * the given type for each.  It then uses these "empty" objects to create\r
+     * a template row.\r
+     * <p>\r
+     * This method is public so that B2IUndo() can call it.\r
+     *\r
+        * @return The new template.\r
+     *\r
+        * @exception  StandardException  Standard exception policy.\r
+     **/\r
+    final public DataValueDescriptor[] createTemplate(\r
+    Transaction rawtran)\r
+        throws StandardException\r
+    {\r
+        if (SanityManager.DEBUG)\r
+            SanityManager.ASSERT(format_ids != null);\r
+\r
+        return(TemplateRow.newRow(\r
+                    rawtran, \r
+                    (FormatableBitSet) null, format_ids, collation_ids));\r
+    }\r
+\r
+    /**\r
+     * Is this a "unique" index?\r
+     **/\r
+    final public boolean isUnique()\r
+    {\r
+        return(nKeyFields != nUniqueColumns);\r
+    }\r
+\r
+    /**************************************************************************\r
+     * Public Methods of Conglomerate Interface:\r
+     **************************************************************************\r
+     */\r
+\r
+    /**\r
+     * Add a column to the conglomerate.\r
+     * <p>\r
+     * Currently B2I does not support this operation.\r
+     * input template column.  \r
+     * \r
+     * @param xact_manager      Transaction to associate the lock with.\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
+     *\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
+        throw StandardException.newException(\r
+                SQLState.BTREE_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
+       /**\r
+       Do the generic part of creating a b-tree conglomerate.  This method \r
+    is called from the concrete subclass (which may also read some properties).\r
+    <p>\r
+    This method processes all properties which are generic to all BTree's.  It\r
+    creates the container for the btree.\r
+    <p>\r
+\r
+    The following properties are generic to a b-tree conglomerate.  :\r
+\r
+    <UL>\r
+    <LI>"allowDuplicates" (boolean).  If set to true the table will allow \r
+    rows which are duplicate in key column's 0 through (nUniqueColumns - 1).\r
+    Currently only supports "false".\r
+    This property is optional, defaults to false.\r
+    <LI>"nKeyFields"  (integer) Columns 0 through (nKeyFields - 1) will be \r
+    included in key of the conglomerate.\r
+    This implementation requires that "nKeyFields" must be the same as the\r
+    number of fields in the conglomerate, including the rowLocationColumn.\r
+    Other implementations may relax this restriction to allow non-key fields\r
+    in the index.\r
+    This property is required.\r
+    <LI>"nUniqueColumns" (integer) Columns 0 through "nUniqueColumns" will be \r
+    used to check for uniqueness.  So for a standard SQL non-unique index \r
+    implementation set "nUniqueColumns" to the same value as "nKeyFields"; and\r
+    for a unique index set "nUniqueColumns" to "nKeyFields" - 1 (ie. don't \r
+    include the rowLocationColumn in the uniqueness check).\r
+    This property is required.\r
+    <LI>"maintainParentLinks" (boolean)\r
+    Whether the b-tree pages maintain the page number of their parent.  Only\r
+    used for consistency checking.  It takes a certain amount more effort to\r
+    maintain these links, but they're really handy for ensuring that the index\r
+    is consistent.\r
+    This property is optional, defaults to true.\r
+    </UL>\r
+\r
+    @exception StandardException Thrown by underlying raw store, or thrown by\r
+    this routine on an invalid containerid.\r
+    \r
+       **/\r
+\r
+       public void create(\r
+    Transaction             rawtran,\r
+    int                     segmentId,\r
+    long                    input_containerid,\r
+    DataValueDescriptor[]   template,\r
+    Properties              properties,\r
+    int                     conglom_format_id,\r
+       int                     tmpFlag\r
+    )\r
+        throws StandardException\r
+       {\r
+        String result_string;\r
+\r
+        if (properties == null)\r
+        {\r
+            throw(\r
+                StandardException.newException(\r
+                    SQLState.BTREE_PROPERTY_NOT_FOUND, PROPERTY_NKEYFIELDS));\r
+        }\r
+\r
+        // Check input arguments\r
+        allowDuplicates = (Boolean.valueOf(\r
+            properties.getProperty(PROPERTY_ALLOWDUPLICATES, "false"))).booleanValue();\r
+\r
+        result_string = properties.getProperty(PROPERTY_NKEYFIELDS);\r
+        if (result_string == null)\r
+        {\r
+            throw(\r
+                StandardException.newException(\r
+                    SQLState.BTREE_PROPERTY_NOT_FOUND, PROPERTY_NKEYFIELDS));\r
+        }\r
+        else\r
+        {\r
+            nKeyFields = Integer.parseInt(result_string);\r
+        }\r
+\r
+        result_string = properties.getProperty(PROPERTY_NUNIQUECOLUMNS);\r
+        if (result_string == null)\r
+        {\r
+            throw(StandardException.newException(\r
+                SQLState.BTREE_PROPERTY_NOT_FOUND, PROPERTY_NUNIQUECOLUMNS));\r
+        }\r
+        else\r
+        {\r
+            nUniqueColumns = Integer.parseInt(result_string);\r
+        }\r
+\r
+\r
+        if (SanityManager.DEBUG)\r
+        {\r
+            result_string = \r
+                properties.getProperty(PROPERTY_MAX_ROWS_PER_PAGE_PARAMETER);\r
+\r
+            if (result_string != null)\r
+            {\r
+                maxRowsPerPage = Integer.parseInt(result_string);\r
+            }\r
+        }\r
+\r
+        maintainParentLinks = (Boolean.valueOf(\r
+            properties.getProperty(PROPERTY_PARENTLINKS, "true"))).booleanValue();\r
+\r
+        // RESOLVE (mikem) - true for now, if we want to support non-key \r
+        // fields eventually this assert may be wrong.\r
+        if (SanityManager.DEBUG)\r
+        {\r
+                       if (template.length != nKeyFields)\r
+                       {\r
+                               SanityManager.THROWASSERT(\r
+                                       "template.length (" + template.length +\r
+                                       ") expected to equal nKeyFields (" + \r
+                                       nKeyFields + ")");\r
+                       }\r
+            SanityManager.ASSERT((nUniqueColumns == nKeyFields) || \r
+                                 (nUniqueColumns == (nKeyFields - 1)));\r
+        }\r
+\r
+        // get format id's from each column in template and store it in the\r
+        // conglomerate state.\r
+        format_ids = ConglomerateUtil.createFormatIds(template);\r
+\r
+        // copy the format id of the conglomerate.\r
+        this.conglom_format_id = conglom_format_id;\r
+\r
+               // Create a container for the b-tree with default page size and \r
+        // fill up pages.\r
+               properties.put(RawStoreFactory.PAGE_RESERVED_SPACE_PARAMETER, "0");\r
+               properties.put(RawStoreFactory.MINIMUM_RECORD_SIZE_PARAMETER, "1");\r
+               properties.put(RawStoreFactory.PAGE_REUSABLE_RECORD_ID, "true");\r
+\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
+               // Open segment will get cleaned up when transaction is.\r
+               if (containerid <= 0)\r
+        {\r
+            throw(StandardException.newException(\r
+                    SQLState.BTREE_CANT_CREATE_CONTAINER)); \r
+        }\r
+\r
+        if (SanityManager.DEBUG)\r
+        {\r
+            if (input_containerid != ContainerHandle.DEFAULT_ASSIGN_ID)\r
+                SanityManager.ASSERT(containerid == input_containerid);\r
+        }\r
+\r
+               id = new ContainerKey(segmentId, containerid);\r
+       }\r
+\r
+       /**\r
+       Drop this btree.\r
+       This must be done by a concrete implementation.\r
+       @see org.apache.derby.iapi.store.access.conglomerate.Conglomerate#drop\r
+\r
+    @exception StandardException Standard exception policy.\r
+       **/\r
+       public abstract void drop(TransactionManager xact_manager)\r
+               throws StandardException;\r
+\r
+       /**\r
+       Load a b-tree.  This must be done by a concrete implementation.\r
+       @see org.apache.derby.iapi.store.access.conglomerate.Conglomerate#load\r
+\r
+    @exception StandardException Standard exception policy.\r
+       **/\r
+       public abstract long load(\r
+       TransactionManager      xact_manager,\r
+       boolean                 createConglom,\r
+       RowLocationRetRowSource rowSource)\r
+               throws StandardException;\r
+\r
+    public long getContainerid()\r
+    {\r
+        return(this.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
+    /**\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
+       Open a b-tree controller.\r
+       This must be done by a concrete implementation.\r
+       @see org.apache.derby.iapi.store.access.conglomerate.Conglomerate#open\r
+\r
+    @exception StandardException Standard exception policy.\r
+       **/\r
+       public abstract 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
+\r
+\r
+    /**************************************************************************\r
+     * Public Methods of Storable Interface (via Conglomerate):\r
+     *     This class is responsible for re/storing its own state.\r
+     **************************************************************************\r
+     */\r
+\r
+\r
+       /**\r
+       Return whether the value is null or not.\r
+       The containerid being zero is what determines nullness;  subclasses\r
+       are not expected to override this method.\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
+       The containerid being zero is what determines nullness;  subclasses\r
+       are not expected to override this method.\r
+\r
+       @see org.apache.derby.iapi.services.io.Storable#restoreToNull\r
+       **/\r
+       public void restoreToNull()\r
+       {\r
+               id = null;\r
+       }\r
+\r
+       /**\r
+       Restore the in-memory representation from the stream.\r
+\r
+       @exception ClassNotFoundException Thrown if the stored representation is\r
+       serialized and a class named in the stream could not be found.\r
+\r
+    @exception IOException thrown by readObject()\r
+\r
+       \r
+       @see java.io.Externalizable#readExternal\r
+       */\r
+       public void readExternal(ObjectInput in) \r
+        throws IOException, ClassNotFoundException\r
+       {\r
+        // read in the conglomerate format id.\r
+        conglom_format_id = FormatIdUtil.readFormatIdInteger(in);\r
+\r
+               // XXX (nat) need to improve error handling\r
+               long containerid         = in.readLong();\r
+               int segmentid                   = in.readInt();\r
+               nKeyFields          = in.readInt();\r
+               nUniqueColumns      = in.readInt();\r
+               allowDuplicates     = in.readBoolean();\r
+               maintainParentLinks = in.readBoolean();\r
+\r
+        // read in the array of format id's\r
+        format_ids = ConglomerateUtil.readFormatIdArray(this.nKeyFields, in);\r
+\r
+               id = new ContainerKey(segmentid, containerid);\r
+       }\r
+\r
+       public void readExternalFromArray(ArrayInputStream in) \r
+        throws IOException, ClassNotFoundException\r
+       {\r
+        // read in the conglomerate format id.\r
+        conglom_format_id = FormatIdUtil.readFormatIdInteger(in);\r
+\r
+               // XXX (nat) need to improve error handling\r
+               long containerid         = in.readLong();\r
+               int segmentid                   = in.readInt();\r
+               nKeyFields          = in.readInt();\r
+               nUniqueColumns      = in.readInt();\r
+               allowDuplicates     = in.readBoolean();\r
+               maintainParentLinks = in.readBoolean();\r
+\r
+        // read in the array of format id's\r
+        format_ids = ConglomerateUtil.readFormatIdArray(this.nKeyFields, in);\r
+\r
+               id = new ContainerKey(segmentid, containerid);\r
+       }\r
+\r
+       \r
+       /**\r
+       Store the stored representation of the column value in the stream.\r
+       It might be easier to simply store the properties - which would certainly\r
+       make upgrading easier.\r
+\r
+    @exception IOException thrown by writeObject()\r
+\r
+       */\r
+       public void writeExternal(ObjectOutput out) \r
+        throws IOException\r
+    {\r
+        FormatIdUtil.writeFormatIdInteger(out, conglom_format_id);\r
+\r
+               out.writeLong(id.getContainerId());\r
+               out.writeInt((int) id.getSegmentId());\r
+               out.writeInt((nKeyFields));\r
+               out.writeInt((nUniqueColumns));\r
+               out.writeBoolean((allowDuplicates));\r
+               out.writeBoolean((maintainParentLinks));\r
+\r
+        ConglomerateUtil.writeFormatIdArray(format_ids, out);\r
+       }\r
+\r
+    /**************************************************************************\r
+     * Public toString() Method:\r
+     **************************************************************************\r
+     */\r
+\r
+    public String toString()\r
+    {\r
+        if (SanityManager.DEBUG)\r
+        {\r
+            return  ("BTREE: containerid = " + \r
+                     (this.id == null ? "null" : this.id.toString()) +\r
+                     ";nKeyFields = " + nKeyFields +\r
+                     ";nUniqueColumns = " + nUniqueColumns +\r
+                     ";allowDuplicates = " + allowDuplicates);\r
+        }\r
+        else\r
+        {\r
+            return(super.toString());\r
+        }\r
+    }\r
+}\r