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 / conglomerate / OpenConglomerate.java
diff --git a/JMCR-Stable/real-world application/derby-10.3.2.1/java/engine/org/apache/derby/impl/store/access/conglomerate/OpenConglomerate.java b/JMCR-Stable/real-world application/derby-10.3.2.1/java/engine/org/apache/derby/impl/store/access/conglomerate/OpenConglomerate.java
new file mode 100644 (file)
index 0000000..f357123
--- /dev/null
@@ -0,0 +1,921 @@
+/*\r
+\r
+   Derby - Class org.apache.derby.impl.store.access.conglomerate.OpenConglomerate\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.conglomerate;\r
+\r
+import org.apache.derby.iapi.reference.SQLState;\r
+\r
+import org.apache.derby.iapi.services.sanity.SanityManager;\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.TransactionManager;\r
+\r
+import org.apache.derby.iapi.store.access.DynamicCompiledOpenConglomInfo;\r
+import org.apache.derby.iapi.store.access.RowUtil;\r
+import org.apache.derby.iapi.store.access.SpaceInfo;\r
+import org.apache.derby.iapi.store.access.TransactionController;\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.Page;\r
+import org.apache.derby.iapi.store.raw.Transaction;\r
+\r
+import org.apache.derby.iapi.types.DataValueDescriptor;\r
+\r
+import org.apache.derby.iapi.types.RowLocation;\r
+\r
+import java.util.Properties; \r
+\r
+\r
+/**\r
+\r
+A Generic class which implements the basic functionality needed to operate\r
+on an "open" conglomerate.  This class assumes the following general things\r
+about the access method.\r
+<p>\r
+The access method is page based and contained in a single container maintained\r
+by raw store.  \r
+\r
+**/\r
+\r
+public abstract class OpenConglomerate\r
+{\r
+    /**************************************************************************\r
+     * Fields of the class\r
+     **************************************************************************\r
+     */\r
+\r
+    /**\r
+     * The following group of fields are all basic input parameters which are\r
+     * provided by the calling code when doing any sort of operation requiring\r
+     * an open conglomerate (openScan(), open(), openCostController(), ...).\r
+     * These are just saved values from what was initially input.\r
+     **/\r
+    private Conglomerate                    init_conglomerate;\r
+    private TransactionManager              init_xact_manager;\r
+    private Transaction                     init_rawtran;\r
+    private int                             init_openmode;\r
+    private int                             init_lock_level;\r
+    private DynamicCompiledOpenConglomInfo  init_dynamic_info;\r
+    private boolean                         init_hold;\r
+    private LockingPolicy                   init_locking_policy;\r
+\r
+\r
+    /**\r
+     * convenience boolean's for various mode's\r
+     **/\r
+    private boolean useUpdateLocks;\r
+    private boolean forUpdate;\r
+    private boolean getBaseTableLocks;\r
+\r
+    /**\r
+     * scratch space used for stuff like templates, export rows, ...\r
+     **/\r
+    private OpenConglomerateScratchSpace  runtime_mem;\r
+\r
+\r
+    /*\r
+     * The open raw store container associated with this open conglomerate\r
+     **/\r
+    private ContainerHandle container;\r
+\r
+    /**************************************************************************\r
+     * Constructors for This class:\r
+     **************************************************************************\r
+     */\r
+\r
+    /**************************************************************************\r
+     * Private methods for This class:\r
+     **************************************************************************\r
+     */\r
+\r
+    /**************************************************************************\r
+     * abstract methods of This class:\r
+     **************************************************************************\r
+     */\r
+\r
+    /**\r
+     * Return an "empty" row location object of the correct type.\r
+     * <p>\r
+     *\r
+        * @return The empty Rowlocation.\r
+     *\r
+        * @exception  StandardException  Standard exception policy.\r
+     **/\r
+       protected abstract RowLocation newRowLocationTemplate()\r
+               throws StandardException;\r
+\r
+    abstract public int[] getFormatIds();\r
+\r
+\r
+    /**************************************************************************\r
+     * Public Methods implementing standard store row locking interfaces:\r
+     *     latchPage(RowPosition)\r
+     *     latchPageAndRepositionScan(RowPosition)\r
+     *     lockPositionForRead(RowPosition, aux_pos, moveForwardIfRowDisappears)\r
+     *     lockPositionForWrite(RowPosition, forInsert, wait)\r
+     *     unlockPositionAfterRead(RowPosition)\r
+     **************************************************************************\r
+     */\r
+    /**\r
+     * Latch the page containing the current RowPosition, and reposition scan.\r
+     * <p>\r
+     * Upon return the scan will hold a latch on the page to continue the\r
+     * scan on.  The scan will positioned on the record, just before the\r
+     * next record to return.\r
+     *\r
+     * Note that for both hold cursor and read uncommitted support this routine\r
+     * handles all cases of either the current position "dissappearing" (either\r
+     * the row and/or page).  The row and/or page can disappear by deleted \r
+     * space being reclaimed post commit of that delete, and for some reason \r
+     * the code requesting the reposition does not have locks which prevented\r
+     * the space reclamation.  Both hold cursor and read uncommitted scans are \r
+     * examples of ways the caller will not prevent space reclamation from \r
+     * claiming the position.\r
+     *\r
+     * This implementation also automatically updates the RowPosition to\r
+     * point at the slot containing the current RowPosition.  This slot \r
+     * value is only valid while the latch is held.\r
+     *\r
+        * @return true if scan had to reposition because a row disappeared.\r
+     *\r
+        * @exception  StandardException  Standard exception policy.\r
+     **/\r
+    public boolean latchPageAndRepositionScan(RowPosition pos)\r
+               throws StandardException\r
+    {\r
+        boolean scan_repositioned = false;\r
+\r
+        // Get the page the record handle refers to.\r
+        pos.current_page = null;\r
+\r
+        try\r
+        {\r
+            if (pos.current_rh != null)\r
+            {\r
+                pos.current_page = \r
+                    container.getPage(pos.current_rh.getPageNumber());\r
+            }\r
+\r
+        }\r
+        catch (Throwable t)\r
+        {\r
+            // Assume all errors are caused by the page "disappearing", will\r
+            // handle this by positioning on next page in code below.\r
+            // Note that in most cases if the page does not exist, getPage()\r
+            // will return null rather than throw an exception, so this path\r
+            // is hard to reach.\r
+\r
+            // just continue on first record of the next page.\r
+            // This should only happen if the page on which the scan was\r
+            // positioned had all of it's row deleted and the page was\r
+            // purged.\r
+\r
+            // This can happen in a cursor held across a commit, where the\r
+            // scan needs to be repositioned after the first "next()" in the\r
+            // subsequent reopen() of the held cursor.\r
+        }\r
+\r
+        if (pos.current_page != null)\r
+        {\r
+            try\r
+            {\r
+                // reposition scan at the old position, now that latch is held.\r
+                pos.current_slot = \r
+                    pos.current_page.getSlotNumber(pos.current_rh);\r
+            }\r
+            catch (StandardException se)\r
+            {\r
+                scan_repositioned = true;\r
+\r
+                // The record that the scan was positioned on, no longer exists.\r
+                // The normal way this happens is if we were positioned on\r
+                // a deleted row, without holding a lock on it, and while\r
+                // the scan did not hold the latch on the page a post commit\r
+                // job purged the row as part of space reclamation.   This can\r
+                // happen in all ISOLATION level scans below serializable.\r
+                pos.current_slot = \r
+                    pos.current_page.getNextSlotNumber(pos.current_rh);\r
+\r
+                if (pos.current_slot == -1)\r
+                {\r
+                    // in this case we there are no more rows on this page\r
+                    // to visit, so position on the next page.  In this case\r
+                    // the row that the scan was positioned on was purged,\r
+                    // and there exists no rows now which are greater than this\r
+                    // record id.\r
+\r
+                    pos.current_page.unlatch();\r
+                    pos.current_page = null;\r
+                }\r
+                else\r
+                {\r
+                    // The way scans work, need to position on the row just\r
+                    // before the one to return "next".  The first thing the\r
+                    // next loop will do is move the scan forward one row.\r
+                    pos.current_slot--;\r
+                }\r
+            }\r
+        }\r
+\r
+        if (pos.current_page == null)\r
+        {\r
+            // position on the next page.\r
+            long current_pageno;\r
+\r
+            if (pos.current_rh != null)\r
+            {\r
+                current_pageno = pos.current_rh.getPageNumber();\r
+            }\r
+            else if (pos.current_pageno != ContainerHandle.INVALID_PAGE_NUMBER)\r
+            {\r
+                current_pageno = pos.current_pageno;\r
+            }\r
+            else\r
+            {\r
+                // no valid position, return a null page\r
+                return(false);\r
+            }\r
+\r
+            pos.current_page = container.getNextPage(current_pageno);\r
+\r
+            pos.current_slot   = Page.FIRST_SLOT_NUMBER - 1;\r
+\r
+            // now position is tracked by active page\r
+            pos.current_pageno = ContainerHandle.INVALID_PAGE_NUMBER;\r
+\r
+            scan_repositioned = true;\r
+        }\r
+\r
+        if (scan_repositioned)\r
+        {\r
+            pos.current_rh = null;\r
+        }\r
+\r
+        return(scan_repositioned);\r
+    }\r
+\r
+    /**\r
+     * Latch the page containing the current RowPosition.\r
+     * <p>\r
+     * This implementation also automatically updates the RowPosition to\r
+     * point at the slot containing the current RowPosition.  This slot \r
+     * value is only valid while the latch is held.\r
+     *\r
+        * @exception  StandardException  Standard exception policy.\r
+     **/\r
+    public boolean latchPage(RowPosition pos)\r
+               throws StandardException\r
+    {\r
+        pos.current_page = null; \r
+\r
+        try\r
+        {\r
+            pos.current_page = \r
+                container.getPage(pos.current_rh.getPageNumber());\r
+\r
+        }\r
+        catch (Throwable t)\r
+        {\r
+            // Assume all errors are caused by the page "disappearing", will\r
+            // handle this by returning false indicating that row can't be \r
+            // found.  This can easily happen when using read uncommitted \r
+            // isolation level.\r
+        }\r
+\r
+        if (pos.current_page != null)\r
+        {\r
+            try\r
+            {\r
+                pos.current_slot = \r
+                    pos.current_page.getSlotNumber(pos.current_rh);\r
+                \r
+                return(true);\r
+            }\r
+            catch (Throwable t)\r
+            {\r
+                // Assume all errors are caused by the row "disappearing",\r
+                // will handle this by returning false indicating that row\r
+                // can't be found.  This can easily happen when using read\r
+                // uncommitted isolation level.\r
+\r
+                pos.current_page.unlatch();\r
+                pos.current_page = null;\r
+            }\r
+        }\r
+\r
+        return(false);\r
+    }\r
+\r
+\r
+    /**\r
+     * Lock row at given row position for read.\r
+     * <p>\r
+     * This routine requests a row lock NOWAIT on the row located at the given\r
+     * RowPosition.  If the lock is granted NOWAIT the \r
+     * routine will return true.  If the lock cannot be granted NOWAIT, then \r
+     * the routine will release the latch on "page" and then it will request \r
+     * a WAIT lock on the row.  \r
+     * <p>\r
+     * This implementation:\r
+     * Assumes latch held on current_page.\r
+     * If the current_rh field of RowPosition is non-null it is assumed that\r
+     * we want to lock that record handle and that we don't have a slot number.\r
+     * If the current_rh field of RowPosition is null, it is assumed the we\r
+     * want to lock the indicated current_slot.  Upon return current_rh will\r
+     * point to the record handle associated with current_slot.\r
+     * <p>\r
+     * After waiting and getting the lock on the row, this routine will fix up\r
+     * RowPosition to point at the row locked.  This means it will get the\r
+     * page latch again, and it will fix the current_slot to point at the \r
+     * waited for record handle - it may have moved while waiting on the lock.\r
+     *\r
+     * @param pos       Position to lock.\r
+     * @param aux_pos   If you have to give up latch to get lock, then also \r
+     *                  unlock this position if it is non-null.\r
+     * @param moveForwardIfRowDisappears\r
+     *                  If true, then this routine must handle the case where\r
+     *                  the row id we are waiting on disappears when the latch\r
+     *                  is released.  If false an exception will be thrown if\r
+     *                  the row disappears.\r
+     * @param waitForLock\r
+     *                  if true wait for lock, if lock can't be granted NOWAIT,\r
+     *                  else if false, throw a lock timeout exception if the\r
+     *                  lock can't be granted without waiting.\r
+     *\r
+        * @return true if lock granted without releasing the latch, else return\r
+     *              false.\r
+     *\r
+        * @exception  StandardException  Standard exception policy.\r
+     **/\r
+    public boolean lockPositionForRead(\r
+    RowPosition pos,\r
+    RowPosition aux_pos,\r
+    boolean     moveForwardIfRowDisappears,\r
+    boolean     waitForLock)\r
+        throws StandardException\r
+    {\r
+        if (pos.current_rh == null)\r
+        {\r
+            if (SanityManager.DEBUG)\r
+            {\r
+                SanityManager.ASSERT(\r
+                    pos.current_page != null &&\r
+                    pos.current_slot != Page.INVALID_SLOT_NUMBER);\r
+\r
+            }\r
+\r
+            // work around for lockmanager problem with lock/latch releasing.\r
+            // Get RecordHandle to lock.\r
+            pos.current_rh = \r
+                pos.current_page.getRecordHandleAtSlot(pos.current_slot);\r
+\r
+            if (SanityManager.DEBUG)\r
+            {\r
+                // make sure current_rh and current_slot are in sync\r
+                if (pos.current_slot !=\r
+                        pos.current_page.getSlotNumber(pos.current_rh))\r
+                {\r
+                    SanityManager.THROWASSERT(\r
+                        "current_slot = " + pos.current_slot +\r
+                        "current_rh = " + pos.current_rh +\r
+                        "current_rh.slot = " + \r
+                        pos.current_page.getSlotNumber(pos.current_rh));\r
+                }\r
+            }\r
+        }\r
+\r
+        if (SanityManager.DEBUG)\r
+            SanityManager.ASSERT(pos.current_rh != null);\r
+\r
+        boolean lock_granted_with_latch_held =\r
+            this.container.getLockingPolicy().lockRecordForRead(\r
+                init_rawtran, container, pos.current_rh, \r
+                false /* NOWAIT */, forUpdate);\r
+\r
+        if (!lock_granted_with_latch_held)\r
+        {\r
+\r
+            // Could not get the lock NOWAIT, release latch and wait for lock.\r
+            pos.current_page.unlatch();\r
+            pos.current_page = null;\r
+\r
+\r
+            if (aux_pos != null)\r
+            {\r
+                aux_pos.current_page.unlatch();\r
+                aux_pos.current_page = null;\r
+            }\r
+\r
+            if (!waitForLock)\r
+            {\r
+                // throw lock timeout error.\r
+                throw StandardException.newException(SQLState.LOCK_TIMEOUT);\r
+            }\r
+\r
+            this.container.getLockingPolicy().lockRecordForRead(\r
+                init_rawtran, container, pos.current_rh, \r
+                true /* WAIT */, forUpdate);\r
+\r
+            if (moveForwardIfRowDisappears)\r
+            {\r
+\r
+                if (latchPageAndRepositionScan(pos))\r
+                {\r
+                    if (pos.current_slot != -1)\r
+                    {\r
+                        // If scan was repositioned to just before a valid row\r
+                        // on the current page, then move forward and lock and\r
+                        // return that row (slot != -1).  \r
+                        // \r
+                        // Let the caller handle the "-1" \r
+                        // case, which may be one of 3 cases - need to go to \r
+                        // slot 1 on current page, need to go to next page, \r
+                        // need to end scan as there is no "next" page.  All\r
+                        // 3 cases are handled by the generic scan loop in \r
+                        // GenericScanController.fetchRows().\r
+\r
+                        pos.positionAtNextSlot();\r
+                        lockPositionForRead(pos, aux_pos, true, true);\r
+\r
+                    }\r
+                }\r
+            }\r
+            else\r
+            {\r
+                latchPage(pos);\r
+            }\r
+        }\r
+\r
+        return(lock_granted_with_latch_held);\r
+    }\r
+\r
+    public boolean lockPositionForWrite(\r
+    RowPosition pos,\r
+    boolean     forInsert,\r
+    boolean     waitForLock)\r
+        throws StandardException\r
+    {\r
+        if (pos.current_rh == null)\r
+        {\r
+            if (SanityManager.DEBUG)\r
+            {\r
+                SanityManager.ASSERT(pos.current_page != null);\r
+                SanityManager.ASSERT(\r
+                    pos.current_slot != Page.INVALID_SLOT_NUMBER);\r
+\r
+            }\r
+\r
+            // work around for lockmanager problem with lock/latch releasing.\r
+            // Get RecordHandle to lock.\r
+            pos.current_rh = \r
+                pos.current_page.fetchFromSlot(\r
+                    null, \r
+                    pos.current_slot, \r
+                    RowUtil.EMPTY_ROW, \r
+                    RowUtil.EMPTY_ROW_FETCH_DESCRIPTOR, \r
+                    true);\r
+\r
+            if (SanityManager.DEBUG)\r
+            {\r
+                // make sure current_rh and current_slot are in sync\r
+                if (pos.current_slot !=\r
+                        pos.current_page.getSlotNumber(pos.current_rh))\r
+                {\r
+                    SanityManager.THROWASSERT(\r
+                        "current_slot = " + pos.current_slot +\r
+                        "current_rh = " + pos.current_rh +\r
+                        "current_rh.slot = " + \r
+                        pos.current_page.getSlotNumber(pos.current_rh));\r
+                }\r
+            }\r
+        }\r
+\r
+        if (SanityManager.DEBUG)\r
+            SanityManager.ASSERT(pos.current_rh != null);\r
+\r
+        boolean lock_granted_with_latch_held =\r
+            this.container.getLockingPolicy().\r
+                lockRecordForWrite(\r
+                    init_rawtran, pos.current_rh, \r
+                    forInsert, false /* NOWAIT */);\r
+\r
+        if (!lock_granted_with_latch_held)\r
+        {\r
+            if (!waitForLock)\r
+            {\r
+                // throw lock timeout error.\r
+                throw StandardException.newException(SQLState.LOCK_TIMEOUT);\r
+            }\r
+\r
+            // Could not get the lock NOWAIT, release latch and wait for lock.\r
+            pos.current_page.unlatch();\r
+            pos.current_page = null;\r
+\r
+            if (!waitForLock)\r
+            {\r
+                // throw lock timeout error.\r
+                throw StandardException.newException(SQLState.LOCK_TIMEOUT);\r
+            }\r
+\r
+            this.container.getLockingPolicy().\r
+                lockRecordForWrite(\r
+                    init_rawtran, pos.current_rh, forInsert, true /* WAIT */);\r
+\r
+            latchPage(pos);\r
+        }\r
+\r
+        return(lock_granted_with_latch_held);\r
+    }\r
+\r
+\r
+    /**\r
+     * Unlock the record after a previous request to lock it.\r
+     * <p>\r
+     * Unlock the record after a previous call to lockRecordForRead().  It is\r
+     * expected that RowPosition contains information used to lock the record,\r
+     * Thus it is important if using a single RowPosition to track a scan to\r
+     * call unlock before you move the position forward to the next record.\r
+     * <p>\r
+     * Note that this routine assumes that the row was locked forUpdate if\r
+     * the OpenConglomerate is forUpdate, else it assumes the record was\r
+     * locked for read.\r
+     *\r
+        * @exception  StandardException  Standard exception policy.\r
+     **/\r
+    public void unlockPositionAfterRead(\r
+    RowPosition pos) \r
+        throws StandardException\r
+    {\r
+        if (!isClosed())\r
+            container.getLockingPolicy().\r
+                unlockRecordAfterRead(\r
+                    init_rawtran, container, pos.current_rh, forUpdate, \r
+                    pos.current_rh_qualified);\r
+    }\r
+\r
+\r
+    /**************************************************************************\r
+     * Public Methods implementing ConglomPropertyQueryable Interface: \r
+     **************************************************************************\r
+     */\r
+\r
+    /**\r
+     * Request set of properties associated with a table. \r
+     * <p>\r
+     * Returns a property object containing all properties that the store\r
+     * knows about, which are stored persistently by the store.  This set\r
+     * of properties may vary from implementation to implementation of the\r
+     * store.\r
+     * <p>\r
+     * This call is meant to be used only for internal query of the properties\r
+     * by jbms, for instance by language during bulk insert so that it can\r
+     * create a new conglomerate which exactly matches the properties that\r
+     * the original container was created with.  This call should not be used\r
+     * by the user interface to present properties to users as it may contain\r
+     * properties that are meant to be internal to jbms.  Some properties are \r
+     * meant only to be specified by jbms code and not by users on the command\r
+     * line.\r
+     * <p>\r
+     * Note that not all properties passed into createConglomerate() are stored\r
+     * persistently, and that set may vary by store implementation.\r
+     *\r
+     * @param prop   Property list to add properties to.  If null, routine will\r
+     *               create a new Properties object, fill it in and return it.\r
+     *\r
+        * @exception  StandardException  Standard exception policy.\r
+     **/\r
+    public Properties getInternalTablePropertySet(Properties prop)\r
+               throws StandardException\r
+    {\r
+        Properties  ret_properties = \r
+            ConglomerateUtil.createRawStorePropertySet(prop);\r
+\r
+        getTableProperties(ret_properties);\r
+\r
+        return(ret_properties);\r
+    }\r
+\r
+    /**\r
+     * Request the system properties associated with a table. \r
+     * <p>\r
+     * Request the value of properties that are associated with a table.  The\r
+     * following properties can be requested:\r
+     *     derby.storage.pageSize \r
+     *     derby.storage.pageReservedSpace\r
+     *     derby.storage.minimumRecordSize\r
+     *     derby.storage.initialPages\r
+     * <p>\r
+     * To get the value of a particular property add it to the property list,\r
+     * and on return the value of the property will be set to it's current \r
+     * value.  For example:\r
+     *\r
+     * get_prop(ConglomerateController cc)\r
+     * {\r
+     *     Properties prop = new Properties();\r
+     *     prop.put("derby.storage.pageSize", "");\r
+     *     cc.getTableProperties(prop);\r
+     *\r
+     *     System.out.println(\r
+     *         "table's page size = " + \r
+     *         prop.getProperty("derby.storage.pageSize");\r
+     * }\r
+     *\r
+     * @param prop   Property list to fill in.\r
+     *\r
+        * @exception  StandardException  Standard exception policy.\r
+     **/\r
+    public void getTableProperties(Properties prop)\r
+               throws StandardException\r
+    {\r
+        container.getContainerProperties(prop);\r
+\r
+        return;\r
+    }\r
+\r
+    /**************************************************************************\r
+     * Public Accessors of This class:\r
+     **************************************************************************\r
+     */\r
+    public final TransactionManager getXactMgr()\r
+    {\r
+        return(init_xact_manager);\r
+    }\r
+\r
+    public final Transaction getRawTran()\r
+    {\r
+        return(init_rawtran);\r
+    }\r
+\r
+    public final ContainerHandle getContainer()\r
+    {\r
+        return(container);\r
+    }\r
+\r
+    public final int getOpenMode()\r
+    {\r
+        return(init_openmode);\r
+    }\r
+    \r
+    public final Conglomerate getConglomerate()\r
+    {\r
+        return(init_conglomerate);\r
+    }\r
+\r
+    public final boolean getHold()\r
+    {\r
+        return(init_hold);\r
+    }\r
+\r
+\r
+    public final boolean isForUpdate()\r
+    {\r
+        return(forUpdate);\r
+    }\r
+\r
+    public final boolean isClosed()\r
+    {\r
+        return(container == null);\r
+    }\r
+\r
+    public final boolean isUseUpdateLocks()\r
+    {\r
+        return(useUpdateLocks);\r
+    }\r
+\r
+    public final OpenConglomerateScratchSpace getRuntimeMem()\r
+    {\r
+        return(runtime_mem);\r
+    }\r
+\r
+    /**************************************************************************\r
+     * Public Methods implementing some ConglomerateController Interfaces: \r
+     **************************************************************************\r
+     */\r
+\r
+\r
+    /**\r
+     * Check consistency of a conglomerate.\r
+     * <p>\r
+     * Checks the consistency of the data within a given conglomerate, does not\r
+     * check consistency external to the conglomerate (ie. does not check that \r
+     * base table row pointed at by a secondary index actually exists).\r
+     * <p>\r
+     * There is no checking in the default implementation, you must override\r
+     * to get conglomerate specific consistency checking.\r
+     *\r
+        * @exception  StandardException  Standard exception policy.\r
+     **/\r
+    public void checkConsistency()\r
+               throws StandardException\r
+    {\r
+        return;\r
+    }\r
+\r
+\r
+\r
+    public void debugConglomerate()\r
+               throws StandardException\r
+    {\r
+        if (SanityManager.DEBUG)\r
+        {\r
+            SanityManager.DEBUG_PRINT(\r
+                "p_heap", "\nHEAP DUMP:containerId " + container.getId());\r
+\r
+            // get a template.\r
+\r
+            DataValueDescriptor[] row = \r
+                runtime_mem.get_row_for_export(getRawTran());\r
+\r
+            // Print pages of the heap.\r
+            Page page = container.getFirstPage();\r
+\r
+            while (page != null)\r
+            {\r
+                SanityManager.DEBUG_PRINT(\r
+                    "p_heap", ConglomerateUtil.debugPage(page, 0, false, row));\r
+\r
+                long pageid = page.getPageNumber();\r
+                page.unlatch();\r
+                page = container.getNextPage(pageid);\r
+            }\r
+        }\r
+\r
+        return;\r
+    }\r
+\r
+\r
+    /**\r
+    Get information about space used by the conglomerate.\r
+    **/\r
+    public SpaceInfo getSpaceInfo()\r
+        throws StandardException\r
+    {\r
+        return container.getSpaceInfo();\r
+    }\r
+\r
+       protected boolean isKeyed()\r
+       {\r
+               return false;\r
+       }\r
+\r
+    /**\r
+     * is the open btree table locked?\r
+     **/\r
+    protected boolean isTableLocked()\r
+    {\r
+        return(init_lock_level == TransactionController.MODE_TABLE);\r
+    }\r
+\r
+    /**************************************************************************\r
+     * Public Methods of this class:\r
+     **************************************************************************\r
+     */\r
+\r
+    /**\r
+     * Open the container.\r
+     * <p>\r
+     * Open the container, obtaining necessary locks.  Most work is actually\r
+     * done by RawStore.openContainer().  \r
+     *\r
+        * @exception  StandardException  Standard exception policy.\r
+     **/\r
+    public ContainerHandle init(\r
+    ContainerHandle                 open_container,\r
+    Conglomerate                    conglomerate,\r
+    int[]                           format_ids,\r
+    int[]                           collation_ids,\r
+    TransactionManager              xact_manager,\r
+    Transaction                     rawtran,\r
+    boolean                         hold,\r
+    int                             openmode,\r
+    int                             lock_level,\r
+    LockingPolicy                   locking_policy,\r
+    DynamicCompiledOpenConglomInfo  dynamic_info)\r
+        throws StandardException\r
+    {\r
+        // save state of all inputs.\r
+        init_conglomerate       = conglomerate;\r
+        init_xact_manager       = xact_manager;\r
+        init_rawtran            = rawtran;\r
+        init_openmode           = openmode;\r
+        init_lock_level         = lock_level;\r
+        init_dynamic_info       = dynamic_info;\r
+        init_hold               = hold;\r
+        init_locking_policy     = locking_policy;\r
+\r
+\r
+        // either use passed in "compiled" runtime scratch space, or create\r
+        // new space.\r
+        this.runtime_mem    = \r
+            (dynamic_info != null ? \r
+             ((OpenConglomerateScratchSpace) dynamic_info) : \r
+             new OpenConglomerateScratchSpace(format_ids, collation_ids));\r
+\r
+        // Is this an open for update or read?  This will\r
+               // be passed down to the raw store fetch methods, which allows\r
+               // it to do the appropriate locking.\r
+               this.forUpdate = \r
+            ((openmode & ContainerHandle.MODE_FORUPDATE) != 0); \r
+\r
+        // keep track of whether this open conglomerate should use update locks.\r
+               this.useUpdateLocks = \r
+            ((openmode & ContainerHandle.MODE_USE_UPDATE_LOCKS) != 0);\r
+\r
+        // If this flag is set, then the client has already locked the row\r
+        // by accessing it through the secondary index and has already locked\r
+        // the row, so the base conglomerate need not re-lock the row.\r
+        this.getBaseTableLocks =\r
+            ((openmode & ContainerHandle.MODE_SECONDARY_LOCKED) == 0);\r
+\r
+               // if the conglomerate is temporary, open with IS_KEPT set.\r
+               // RESOLVE(mikem): track 1825\r
+               // don't want to open temp cantainer with IS_KEPT always.\r
+        if (conglomerate.isTemporary())\r
+        {\r
+                       init_openmode |= ContainerHandle.MODE_TEMP_IS_KEPT;\r
+        }\r
+\r
+        if (!getBaseTableLocks)\r
+            init_locking_policy = null;\r
+\r
+               // Open the container. \r
+        this.container = \r
+            (open_container != null ?  \r
+                 open_container : \r
+                 rawtran.openContainer(\r
+                    conglomerate.getId(), init_locking_policy, init_openmode));\r
+\r
+        return(this.container);\r
+    }\r
+\r
+    /**\r
+     * Open the container.\r
+     * <p>\r
+     * Open the container, obtaining necessary locks.  Most work is actually\r
+     * done by RawStore.openContainer().  Will only reopen() if the container\r
+     * is not already open.\r
+     *\r
+        * @exception  StandardException  Standard exception policy.\r
+     **/\r
+    public ContainerHandle reopen()\r
+        throws StandardException\r
+    {\r
+        // reget transaction from context manager, in the case of XA\r
+        // transaction this may have changed.\r
+        //\r
+        /* TODO - XA transactions my change the current transaction on the \r
+         * context stack.  Will want to something like:\r
+         *\r
+         * init_rawtran = context_manager.getcurrenttransaction()\r
+         */\r
+     \r
+        if (this.container == null)\r
+        {\r
+            this.container = \r
+                 init_rawtran.openContainer(\r
+                    init_conglomerate.getId(), \r
+                    init_locking_policy, \r
+                    init_openmode);\r
+        }\r
+\r
+        return(this.container);\r
+    }\r
+\r
+    /**\r
+     * Close the container.\r
+     * <p>\r
+     * Handles being closed more than once.\r
+     *\r
+        * @exception  StandardException  Standard exception policy.\r
+     **/\r
+    public void close()\r
+        throws StandardException\r
+       {\r
+               if (container != null)\r
+        {\r
+                       container.close();\r
+            container = null;\r
+        }\r
+       }\r
+}\r