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 / RAMTransaction.java
diff --git a/JMCR-Stable/real-world application/derby-10.3.2.1/java/engine/org/apache/derby/impl/store/access/RAMTransaction.java b/JMCR-Stable/real-world application/derby-10.3.2.1/java/engine/org/apache/derby/impl/store/access/RAMTransaction.java
new file mode 100644 (file)
index 0000000..c059005
--- /dev/null
@@ -0,0 +1,2496 @@
+/*\r
+\r
+   Derby - Class org.apache.derby.impl.store.access.RAMTransaction\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;\r
+\r
+import java.util.ArrayList;\r
+import java.util.HashMap;\r
+import java.util.Iterator;\r
+import java.util.Properties;\r
+\r
+import org.apache.derby.iapi.reference.SQLState;\r
+import org.apache.derby.iapi.util.ReuseFactory;\r
+\r
+import org.apache.derby.iapi.services.context.ContextManager;\r
+\r
+import org.apache.derby.iapi.services.io.Storable;\r
+\r
+import org.apache.derby.iapi.services.daemon.Serviceable;\r
+import org.apache.derby.iapi.services.locks.CompatibilitySpace;\r
+import org.apache.derby.iapi.services.monitor.Monitor;\r
+import org.apache.derby.iapi.services.sanity.SanityManager;\r
+import org.apache.derby.iapi.error.StandardException;\r
+import org.apache.derby.iapi.store.access.conglomerate.Conglomerate;\r
+import org.apache.derby.iapi.store.access.conglomerate.ConglomerateFactory;\r
+import org.apache.derby.iapi.store.access.conglomerate.ScanManager;\r
+import org.apache.derby.iapi.store.access.conglomerate.MethodFactory;\r
+import org.apache.derby.iapi.store.access.conglomerate.ScanControllerRowSource;\r
+import org.apache.derby.iapi.store.access.conglomerate.Sort;\r
+import org.apache.derby.iapi.store.access.conglomerate.SortFactory;\r
+import org.apache.derby.iapi.store.access.conglomerate.TransactionManager;\r
+import org.apache.derby.iapi.store.access.AccessFactory;\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.FileResource;\r
+import org.apache.derby.iapi.store.access.GroupFetchScanController;\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.ScanController;\r
+import org.apache.derby.iapi.store.access.SortController;\r
+import org.apache.derby.iapi.store.access.SortCostController;\r
+import org.apache.derby.iapi.store.access.SortObserver;\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.access.XATransactionController;\r
+\r
+\r
+import org.apache.derby.iapi.store.raw.ContainerHandle;\r
+import org.apache.derby.iapi.store.raw.LockingPolicy;\r
+\r
+\r
+import org.apache.derby.iapi.store.raw.Loggable;\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.impl.store.access.conglomerate.ConglomerateUtil;\r
+\r
+import org.apache.derby.iapi.store.access.DatabaseInstant;\r
+\r
+import org.apache.derby.iapi.store.access.BackingStoreHashtable;\r
+import org.apache.derby.iapi.services.io.FormatableBitSet;\r
+\r
+import java.io.Serializable;\r
+\r
+// debugging\r
+import org.apache.derby.iapi.services.stream.HeaderPrintWriter;\r
+\r
+public class RAMTransaction \r
+    implements XATransactionController, TransactionManager\r
+{\r
+\r
+       /**\r
+       The corresponding raw store transaction.\r
+       **/\r
+       protected Transaction rawtran;\r
+\r
+       /**\r
+       The access manager this transaction is under.\r
+       **/\r
+       protected RAMAccessManager accessmanager;\r
+\r
+       /**\r
+       The context this transaction is being managed by.\r
+       **/\r
+       protected RAMTransactionContext context;\r
+\r
+       /**\r
+       The parent transaction if this is a nested user transaction.\r
+       **/\r
+       protected RAMTransaction        parent_tran;\r
+\r
+       // XXX (nat) management of the controllers is still embryonic.\r
+       // XXX (nat) would be nice if sort controllers were like conglom controllers\r
+       private ArrayList scanControllers;\r
+       private ArrayList conglomerateControllers;\r
+       private ArrayList sorts;\r
+       private ArrayList sortControllers;\r
+\r
+    /** List of sort identifiers (represented as <code>Integer</code> objects)\r
+     * which can be reused. Since sort identifiers are used as array indexes,\r
+     * we need to reuse them to avoid leaking memory (DERBY-912). */\r
+    private ArrayList freeSortIds;\r
+\r
+       /**\r
+       Where to look for temporary conglomerates.\r
+       **/\r
+       protected HashMap tempCongloms;\r
+\r
+       /**\r
+       Next id to use for a temporary conglomerate.\r
+       **/\r
+       private long nextTempConglomId = -1;\r
+\r
+    /**\r
+     * Set by alter table to indicate that the conglomerate cache needs to\r
+     * be invalidated if a transaction aborting error is encountered, cleared\r
+     * after cleanup.\r
+     */\r
+    private boolean alterTableCallMade = false;\r
+\r
+    /**\r
+     * The lock level of the transaction.\r
+     * <p>\r
+     * Cannot lock a level lower than the getSystemLockLevel().  So if \r
+     * getSystemLockLevel() is table level locking, setting the transaction\r
+     * locking level to record has no effect.\r
+     **/\r
+    private int transaction_lock_level;\r
+\r
+    /**************************************************************************\r
+     * Constructors for This class:\r
+     **************************************************************************\r
+     */\r
+\r
+    private final void init(\r
+    RAMAccessManager myaccessmanager, \r
+    Transaction      theRawTran,\r
+    RAMTransaction   parent_tran)\r
+       {\r
+               this.rawtran            = theRawTran;\r
+        this.parent_tran        = parent_tran;\r
+               accessmanager           = myaccessmanager;\r
+               scanControllers         = new ArrayList();\r
+               conglomerateControllers = new ArrayList();\r
+\r
+               sorts                   = null; // allocated on demand.\r
+               freeSortIds             = null; // allocated on demand.\r
+               sortControllers         = null; // allocated on demand\r
+\r
+        if (parent_tran != null)\r
+        {\r
+            // allow nested transactions to see temporary conglomerates which\r
+            // were created in the parent transaction.  This is necessary for\r
+            // language which compiling plans in nested transactions against \r
+            // user temporaries created in parent transactions.\r
+\r
+            tempCongloms        = parent_tran.tempCongloms;\r
+        }\r
+        else\r
+        {\r
+            tempCongloms        = null; // allocated on demand\r
+        }\r
+       }\r
+\r
+       protected RAMTransaction(\r
+    RAMAccessManager myaccessmanager, \r
+    Transaction      theRawTran,\r
+    RAMTransaction   parent_transaction)\r
+               throws StandardException\r
+       {\r
+        init(myaccessmanager, theRawTran, parent_transaction);\r
+       }\r
+\r
+       RAMTransaction(\r
+    RAMAccessManager myaccessmanager, \r
+    RAMTransaction   tc,\r
+    int              format_id,\r
+    byte[]           global_id,\r
+    byte[]           branch_id)\r
+               throws StandardException\r
+       {\r
+        init(myaccessmanager, tc.getRawStoreXact(), null);\r
+\r
+        if (SanityManager.DEBUG)\r
+            SanityManager.ASSERT(tc.getRawStoreXact().isIdle());\r
+\r
+        this.context = tc.context;\r
+\r
+        // switch the transaction pointer in the context to point to this xact\r
+        this.context.setTransaction(this);\r
+\r
+        this.rawtran.createXATransactionFromLocalTransaction(\r
+            format_id, global_id, branch_id);\r
+\r
+        // invalidate old tc, so caller does not use it.  Can't just call\r
+        // destroy as that screws up the contexts which we want to just leave\r
+        // alone.\r
+        tc.rawtran = null;\r
+       }\r
+\r
+\r
+       RAMTransaction()\r
+       {\r
+       }\r
+\r
+\r
+    /**************************************************************************\r
+     * Private/Protected methods of This class:\r
+     **************************************************************************\r
+     */\r
+\r
+\r
+       // XXX (nat) currently closes all controllers.\r
+       protected void closeControllers(boolean closeHeldControllers)\r
+        throws StandardException\r
+       {\r
+\r
+        if (!scanControllers.isEmpty())\r
+        {\r
+            // loop from end to beginning, removing scans which are not held.\r
+            for (int i = scanControllers.size() - 1; i >= 0; i--)\r
+            {\r
+                ScanManager sc = (ScanManager) scanControllers.get(i);\r
+\r
+                if (sc.closeForEndTransaction(closeHeldControllers))\r
+                {\r
+                    // TODO - now counting on scan's removing themselves by \r
+                    // calling the closeMe() method.\r
+                    /* scanControllers.removeElementAt(i); */\r
+                }\r
+            }\r
+\r
+            if (closeHeldControllers)\r
+            {\r
+                if (SanityManager.DEBUG)\r
+                {\r
+                    SanityManager.ASSERT(scanControllers.isEmpty());\r
+                }\r
+                // just to make sure everything has been closed and removed.\r
+                scanControllers.clear();\r
+            }\r
+        }\r
+\r
+        if (!conglomerateControllers.isEmpty())\r
+        {\r
+            // loop from end to beginning, removing scans which are not held.\r
+            for (int i = conglomerateControllers.size() - 1; i >= 0; i--)\r
+            {\r
+                ConglomerateController cc = \r
+                    (ConglomerateController) \r
+                        conglomerateControllers.get(i);\r
+\r
+                if (cc.closeForEndTransaction(closeHeldControllers))\r
+                {\r
+                    // TODO - now counting on cc's removing themselves by \r
+                    // calling the closeMe() method.\r
+                    /* conglomerateControllers.removeElementAt(i); */\r
+                }\r
+            }\r
+\r
+            if (closeHeldControllers)\r
+            {\r
+                if (SanityManager.DEBUG)\r
+                {\r
+                    SanityManager.ASSERT(scanControllers.isEmpty());\r
+                }\r
+                // just to make sure everything has been closed and removed.\r
+                conglomerateControllers.clear();\r
+            }\r
+        }\r
+\r
+        if ((sortControllers != null) && !sortControllers.isEmpty())\r
+        {\r
+            if (closeHeldControllers)\r
+            {\r
+                // Loop from the end since the call to close() will remove the\r
+                // element from the list.\r
+                for (int i = sortControllers.size() - 1; i >= 0; i--)\r
+                {\r
+                    SortController sc = (SortController) sortControllers.get(i);\r
+                    sc.completedInserts();\r
+                }\r
+                sortControllers.clear();\r
+            }\r
+        }\r
+\r
+               if ((sorts != null) && (!sorts.isEmpty()))\r
+               {\r
+            if (closeHeldControllers)\r
+            {\r
+                // Loop from the end since the call to drop() will remove the\r
+                // element from the list.\r
+                for (int i = sorts.size() - 1; i >= 0; i--)\r
+                {\r
+                    Sort sort = (Sort) sorts.get(i);\r
+                    if (sort != null)\r
+                        sort.drop(this);\r
+                }\r
+                sorts.clear();\r
+                freeSortIds.clear();\r
+            }\r
+               }\r
+       }\r
+\r
+\r
+    /**\r
+     * Determine correct locking policy for a conglomerate open.\r
+     * <p>\r
+     * Determine from the following table whether to table or record lock\r
+     * the conglomerate we are opening.\r
+     * <p>\r
+     *\r
+     *\r
+     *                                     System level override\r
+     *                                     -------------------------------\r
+     * user requests                       table locking    record locking\r
+     * -------------                       -------------    --------------\r
+     * TransactionController.MODE_TABLE     TABLE             TABLE\r
+     * TransactionController.MODE_RECORD    TABLE             RECORD\r
+     **/\r
+    private LockingPolicy determine_locking_policy(\r
+    int requested_lock_level,\r
+    int isolation_level)\r
+    {\r
+        LockingPolicy ret_locking_policy;\r
+\r
+        if ((accessmanager.getSystemLockLevel() == \r
+                TransactionController.MODE_TABLE) ||\r
+            (requested_lock_level == TransactionController.MODE_TABLE))\r
+        {\r
+            ret_locking_policy = \r
+                accessmanager.table_level_policy[isolation_level];\r
+        }\r
+        else \r
+        {\r
+            ret_locking_policy = \r
+                accessmanager.record_level_policy[isolation_level];\r
+            \r
+        }\r
+        return(ret_locking_policy);\r
+    }\r
+\r
+    private int determine_lock_level(\r
+    int requested_lock_level)\r
+    {\r
+        int ret_lock_level;\r
+\r
+        if ((accessmanager.getSystemLockLevel() == \r
+                TransactionController.MODE_TABLE) ||\r
+            (requested_lock_level == TransactionController.MODE_TABLE))\r
+        {\r
+            ret_lock_level = TransactionController.MODE_TABLE;\r
+        }\r
+        else \r
+        {\r
+            ret_lock_level = TransactionController.MODE_RECORD;\r
+            \r
+        }\r
+        return(ret_lock_level);\r
+    }\r
+\r
+       private Conglomerate findExistingConglomerate(long conglomId)\r
+               throws StandardException\r
+       {\r
+               Conglomerate conglom = null;\r
+\r
+               if (conglomId < 0)\r
+               {\r
+                       if (tempCongloms != null)\r
+                               conglom = (Conglomerate) tempCongloms.get(new Long(conglomId));\r
+               }\r
+        else\r
+        {\r
+            conglom = accessmanager.conglomCacheFind(this, conglomId);\r
+        }\r
+\r
+               if (conglom == null)\r
+        {\r
+                       throw StandardException.newException(\r
+                SQLState.STORE_CONGLOMERATE_DOES_NOT_EXIST, \r
+                new Long(conglomId));\r
+        }\r
+        else\r
+        {\r
+            return(conglom);\r
+        }\r
+       }\r
+\r
+       private Conglomerate findConglomerate(long conglomId)\r
+               throws StandardException\r
+       {\r
+               Conglomerate conglom = null;\r
+\r
+               if (conglomId >= 0)\r
+        {\r
+            conglom = accessmanager.conglomCacheFind(this, conglomId);\r
+        }\r
+        else\r
+               {\r
+                       if (tempCongloms != null)\r
+                               conglom = (Conglomerate) tempCongloms.get(new Long(conglomId));\r
+               }\r
+\r
+        return(conglom);\r
+       }\r
+\r
+       void setContext(RAMTransactionContext rtc)\r
+       {\r
+               context = rtc;\r
+       }\r
+\r
+       /**\r
+               Get cache statistics for the specified cache\r
+       */\r
+       public long[] getCacheStats(String cacheName) {\r
+               return getRawStoreXact().getCacheStats(cacheName);\r
+       }\r
+\r
+    private ConglomerateController openConglomerate(\r
+    Conglomerate                    conglom,\r
+    boolean                         hold,\r
+    int                             open_mode,\r
+    int                             lock_level,\r
+    int                             isolation_level,\r
+    StaticCompiledOpenConglomInfo   static_info,\r
+    DynamicCompiledOpenConglomInfo  dynamic_info)\r
+               throws StandardException\r
+       {\r
+        if (SanityManager.DEBUG)\r
+        {\r
+            if ((open_mode & \r
+                    ~(ContainerHandle.MODE_UNLOGGED                 |\r
+                      ContainerHandle.MODE_CREATE_UNLOGGED          |\r
+                      ContainerHandle.MODE_FORUPDATE                |\r
+                      ContainerHandle.MODE_READONLY                    |\r
+                      ContainerHandle.MODE_TRUNCATE_ON_COMMIT       |\r
+                      ContainerHandle.MODE_DROP_ON_COMMIT           |\r
+                      ContainerHandle.MODE_OPEN_FOR_LOCK_ONLY       |\r
+                      ContainerHandle.MODE_LOCK_NOWAIT              |\r
+                      ContainerHandle.MODE_TRUNCATE_ON_ROLLBACK     |\r
+                      ContainerHandle.MODE_FLUSH_ON_COMMIT          |\r
+                      ContainerHandle.MODE_NO_ACTIONS_ON_COMMIT     |\r
+                      ContainerHandle.MODE_TEMP_IS_KEPT                        |\r
+                      ContainerHandle.MODE_USE_UPDATE_LOCKS            |\r
+                      ContainerHandle.MODE_SECONDARY_LOCKED         |\r
+                      ContainerHandle.MODE_BASEROW_INSERT_LOCKED)) != 0)   \r
+            {\r
+                SanityManager.THROWASSERT(\r
+                    "Bad open mode to openConglomerate:" + \r
+                        Integer.toHexString(open_mode));\r
+            }\r
+\r
+            SanityManager.ASSERT(conglom != null);\r
+            \r
+            if (lock_level != MODE_RECORD && lock_level != MODE_TABLE)\r
+            {\r
+                SanityManager.THROWASSERT(\r
+                    "Bad lock level to openConglomerate:" + lock_level);\r
+            }\r
+        }\r
+\r
+               // Get a conglomerate controller.\r
+               ConglomerateController cc = \r
+            conglom.open(\r
+                this, rawtran, hold, open_mode, \r
+                determine_lock_level(lock_level), \r
+                determine_locking_policy(lock_level, isolation_level),\r
+                static_info,\r
+                dynamic_info);\r
+\r
+               // Keep track of it so we can release on close.\r
+               conglomerateControllers.add(cc);\r
+\r
+               return cc;\r
+    }\r
+\r
+       private ScanController openScan(\r
+    Conglomerate                    conglom,\r
+    boolean                         hold,\r
+    int                             open_mode,\r
+    int                             lock_level,\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
+        if (SanityManager.DEBUG)\r
+        {\r
+            if ((open_mode & \r
+                 ~(TransactionController.OPENMODE_FORUPDATE |\r
+                   TransactionController.OPENMODE_USE_UPDATE_LOCKS |\r
+                   TransactionController.OPENMODE_FOR_LOCK_ONLY |\r
+                   TransactionController.OPENMODE_LOCK_NOWAIT |\r
+                   TransactionController.OPENMODE_SECONDARY_LOCKED)) != 0)\r
+            {\r
+                SanityManager.THROWASSERT(\r
+                    "Bad open mode to openScan:" +\r
+                    Integer.toHexString(open_mode));\r
+            }\r
+\r
+            if (!((lock_level == MODE_RECORD | lock_level == MODE_TABLE)))\r
+            {\r
+                SanityManager.THROWASSERT(\r
+                    "Bad lock level to openScan:" + lock_level);\r
+            }\r
+        }\r
+\r
+               // Get a scan controller.\r
+               ScanManager sm =\r
+            conglom.openScan(\r
+                this, rawtran, hold, open_mode,\r
+                determine_lock_level(lock_level),\r
+                determine_locking_policy(lock_level, isolation_level),\r
+                isolation_level,\r
+                scanColumnList,\r
+                startKeyValue, startSearchOperator,\r
+                qualifier,\r
+                stopKeyValue, stopSearchOperator,\r
+                static_info,\r
+                dynamic_info);\r
+\r
+               // Keep track of it so we can release on close.\r
+               scanControllers.add(sm);\r
+\r
+               return(sm);\r
+       }\r
+\r
+\r
+\r
+       /**\r
+               Reset the cache statistics for the specified cache\r
+       */\r
+       public void resetCacheStats(String cacheName) {\r
+               getRawStoreXact().resetCacheStats(cacheName);\r
+       }\r
+\r
+    /**\r
+     * Invalidate the conglomerate cache, if necessary.  If an alter table\r
+     * call has been made then invalidate the cache.\r
+     *\r
+        * @exception  StandardException  Standard exception policy.\r
+     **/\r
+    protected void invalidateConglomerateCache()\r
+        throws StandardException\r
+    {\r
+        if (alterTableCallMade)\r
+        {\r
+            accessmanager.conglomCacheInvalidate();\r
+            alterTableCallMade = false;\r
+        }\r
+    }\r
+\r
+\r
+    /**************************************************************************\r
+     * Public Methods of TransactionController interface:\r
+     **************************************************************************\r
+     */\r
+\r
+    /**\r
+    Add a column to a conglomerate.  The conglomerate must not be open in\r
+       the current transaction.  This also means that there must not be any\r
+    active scans on it.\r
+\r
+    The column can only be added at the spot just after the current set of\r
+    columns.\r
+\r
+    The template_column must be nullable.\r
+\r
+    After this call has been made, all fetches of this column from rows that\r
+    existed in the table prior to this call will return "null".\r
+\r
+       @param conglomId        The identifier of the conglomerate to drop.\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 added column.\r
+\r
+       @exception StandardException Only some types of conglomerates can support\r
+        adding a column, for instance "heap" conglomerates support adding a\r
+        column while "btree" conglomerates do not.  If the column can not be\r
+        added an exception will be thrown.\r
+    **/\r
+    public void addColumnToConglomerate(\r
+    long        conglomId,\r
+    int         column_id,\r
+    Storable    template_column,\r
+    int         collation_id)\r
+               throws StandardException\r
+    {\r
+        boolean is_temporary = (conglomId < 0);\r
+\r
+               Conglomerate conglom = findConglomerate(conglomId);\r
+               if (conglom == null)\r
+        {\r
+                       throw StandardException.newException(\r
+                SQLState.AM_NO_SUCH_CONGLOMERATE_DROP, new Long(conglomId));\r
+        }\r
+\r
+        // Get exclusive lock on the table being altered.\r
+               ConglomerateController cc =\r
+            conglom.open(\r
+                this, rawtran, false, OPENMODE_FORUPDATE,\r
+                MODE_TABLE,\r
+                accessmanager.table_level_policy[\r
+                    TransactionController.ISOLATION_SERIALIZABLE],\r
+                (StaticCompiledOpenConglomInfo) null,\r
+                (DynamicCompiledOpenConglomInfo) null);\r
+\r
+               conglom.addColumn(this, column_id, template_column, collation_id);\r
+\r
+        // remove the old entry in the Conglomerate directory, and add the\r
+        // new one.\r
+               if (is_temporary)\r
+               {\r
+            // remove old entry in the Conglomerate directory, and add new one\r
+                       if (tempCongloms != null)\r
+                               tempCongloms.remove(new Long(conglomId));\r
+                       tempCongloms.put(new Long(conglomId), conglom);\r
+               }\r
+               else\r
+        {\r
+            alterTableCallMade = true;\r
+\r
+            // have access manager update the conglom to this new one.\r
+                       accessmanager.conglomCacheUpdateEntry(conglomId, conglom);\r
+        }\r
+\r
+        cc.close();\r
+\r
+        return;\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
+    long        conglomId)\r
+               throws StandardException\r
+    {\r
+        return(\r
+            findExistingConglomerate(\r
+                conglomId).getStaticCompiledConglomInfo(this, conglomId));\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(\r
+            findExistingConglomerate(\r
+                conglomId).getDynamicCompiledConglomInfo(conglomId));\r
+    }\r
+\r
+\r
+    private final int countCreatedSorts()\r
+    {\r
+        int ret_val = 0;\r
+        if (sorts != null)\r
+        {\r
+            for (int i = 0; i < sorts.size(); i++)\r
+            {\r
+                if (sorts.get(i) != null)\r
+                    ret_val++;\r
+            }\r
+        }\r
+\r
+        return(ret_val);\r
+    }\r
+\r
+    /**\r
+     * Report on the number of open conglomerates in the transaction.\r
+     * <p>\r
+     * There are 4 types of open "conglomerates" that can be tracked, those\r
+     * opened by each of the following: openConglomerate(), openScan(), \r
+     * openSort(), and openSortScan().  This routine can be used to either\r
+     * report on the number of all opens, or may be used to track one \r
+     * particular type of open.\r
+     *\r
+     * This routine is expected to be used for debugging only.  An \r
+     * implementation may only track this info under SanityManager.DEBUG mode.\r
+     * If the implementation does not track the info it will return -1 (so\r
+     * code using this call to verify that no congloms are open should check\r
+     * for return <= 0 rather than == 0).\r
+     *\r
+     * The return value depends on the "which_to_count" parameter as follows:\r
+     * OPEN_CONGLOMERATE  - return # of openConglomerate() calls not close()'d.\r
+     * OPEN_SCAN          - return # of openScan() calls not close()'d.\r
+     * OPEN_CREATED_SORTS - return # of sorts created (createSort()) in \r
+     *                      current xact.  There is currently no way to get\r
+     *                      rid of these sorts before end of transaction.\r
+     * OPEN_SORT          - return # of openSort() calls not close()'d.\r
+     * OPEN_TOTAL         - return total # of all above calls not close()'d.\r
+     *     - note an implementation may return -1 if it does not track the\r
+     *       above information.\r
+     *\r
+        * @return The nunber of open's of a type indicated by "which_to_count"\r
+     *         parameter.\r
+     *\r
+     * @param which_to_count Which kind of open to report on.\r
+     *\r
+        * @exception  StandardException  Standard exception policy.\r
+     **/\r
+    public int countOpens(int which_to_count)\r
+               throws StandardException\r
+       {\r
+        int         ret_val = -1;\r
+\r
+        switch (which_to_count)\r
+        {\r
+            case OPEN_CONGLOMERATE:\r
+                ret_val = conglomerateControllers.size();\r
+                break;\r
+            case OPEN_SCAN:\r
+                ret_val = scanControllers.size();\r
+                break;\r
+            case OPEN_CREATED_SORTS:\r
+                ret_val = countCreatedSorts();\r
+                break;\r
+            case OPEN_SORT:\r
+                ret_val = \r
+                    ((sortControllers != null) ? sortControllers.size() : 0);\r
+                break;\r
+            case OPEN_TOTAL:\r
+                ret_val = \r
+                    conglomerateControllers.size() + scanControllers.size() +\r
+                    ((sortControllers != null) ? sortControllers.size() : 0) +\r
+                    countCreatedSorts();\r
+                break;\r
+        }\r
+\r
+        return(ret_val);\r
+       }\r
+\r
+    /**\r
+     * Create a new conglomerate.\r
+     * <p>\r
+     * @see TransactionController#createConglomerate\r
+     *\r
+        * @exception  StandardException  Standard exception policy.\r
+     **/\r
+    public long createConglomerate(\r
+    String                  implementation,\r
+    DataValueDescriptor[]   template,\r
+    ColumnOrdering[]        columnOrder,\r
+    int[]                   collationIds,\r
+    Properties              properties,\r
+    int                     temporaryFlag)\r
+               throws StandardException\r
+       {\r
+               // Find the appropriate factory for the desired implementation.\r
+               MethodFactory mfactory;\r
+               mfactory = accessmanager.findMethodFactoryByImpl(implementation);\r
+               if (mfactory == null || !(mfactory instanceof ConglomerateFactory))\r
+        {\r
+                       throw StandardException.newException(\r
+                    SQLState.AM_NO_SUCH_CONGLOMERATE_TYPE, implementation);\r
+        }\r
+               ConglomerateFactory cfactory = (ConglomerateFactory) mfactory;\r
+\r
+               // Create the conglomerate\r
+        // RESOLVE (mikem) - eventually segmentid's will be passed into here\r
+        // in the properties.  For now just use 0.]\r
+               int     segment;\r
+        long    conglomid;\r
+               if ((temporaryFlag & TransactionController.IS_TEMPORARY)\r
+                               == TransactionController.IS_TEMPORARY)\r
+        {\r
+                       segment = ContainerHandle.TEMPORARY_SEGMENT;\r
+            conglomid = ContainerHandle.DEFAULT_ASSIGN_ID;\r
+        }\r
+               else\r
+        {\r
+                       segment = 0; // RESOLVE - only using segment 0\r
+            conglomid = \r
+                accessmanager.getNextConglomId(\r
+                    cfactory.getConglomerateFactoryId());\r
+        }\r
+\r
+        // call the factory to actually create the conglomerate.\r
+        Conglomerate conglom =\r
+            cfactory.createConglomerate(\r
+                this, segment, conglomid, template, \r
+                columnOrder, collationIds, properties, temporaryFlag);\r
+\r
+               long conglomId;\r
+               if ((temporaryFlag & TransactionController.IS_TEMPORARY)\r
+                               == TransactionController.IS_TEMPORARY)\r
+               {\r
+                       conglomId = nextTempConglomId--;\r
+                       if (tempCongloms == null)\r
+                               tempCongloms = new HashMap();\r
+                       tempCongloms.put(new Long(conglomId), conglom);\r
+               }\r
+               else\r
+               {\r
+                       conglomId = conglom.getContainerid();\r
+\r
+            accessmanager.conglomCacheAddEntry(conglomId, conglom);\r
+               }\r
+\r
+               return conglomId;\r
+       }\r
+\r
+       /**\r
+               Create a conglomerate and populate it with rows from rowSource.\r
+\r
+               @see TransactionController#createAndLoadConglomerate\r
+               @exception StandardException Standard Derby Error Policy\r
+       */\r
+    public long createAndLoadConglomerate(\r
+    String                  implementation,\r
+    DataValueDescriptor[]   template,\r
+       ColumnOrdering[]                columnOrder,\r
+    int[]                   collationIds,\r
+    Properties              properties,\r
+    int                     temporaryFlag,\r
+    RowLocationRetRowSource rowSource,\r
+       long[] rowCount)\r
+               throws StandardException\r
+       {\r
+        return(\r
+            recreateAndLoadConglomerate(\r
+                implementation,\r
+                true,\r
+                template,\r
+                               columnOrder,\r
+                collationIds,\r
+                properties,\r
+                temporaryFlag,\r
+                0 /* unused if recreate_ifempty is true */,\r
+                rowSource,\r
+                               rowCount));\r
+       }\r
+\r
+       /**\r
+               recreate a conglomerate and populate it with rows from rowSource.\r
+\r
+               @see TransactionController#createAndLoadConglomerate\r
+               @exception StandardException Standard Derby Error Policy\r
+       */\r
+    public long recreateAndLoadConglomerate(\r
+    String                  implementation,\r
+    boolean                 recreate_ifempty,\r
+    DataValueDescriptor[]   template,\r
+       ColumnOrdering[]                columnOrder,\r
+    int[]                   collationIds,\r
+    Properties              properties,\r
+    int                                    temporaryFlag,\r
+    long                    orig_conglomId,\r
+    RowLocationRetRowSource rowSource,\r
+       long[] rowCount)\r
+        throws StandardException\r
+\r
+       {\r
+               // RESOLVE: this create the conglom LOGGED, this is slower than\r
+               // necessary although still correct.\r
+               long conglomId = \r
+                       createConglomerate(\r
+                implementation, template, columnOrder, collationIds, \r
+                properties, temporaryFlag);\r
+\r
+        long rows_loaded = \r
+            loadConglomerate(\r
+                conglomId, \r
+                true, // conglom is being created\r
+                rowSource);\r
+\r
+               if (rowCount != null)\r
+                       rowCount[0] = rows_loaded;\r
+\r
+        if (!recreate_ifempty && (rows_loaded == 0))\r
+        {\r
+            dropConglomerate(conglomId);\r
+\r
+            conglomId = orig_conglomId;\r
+        }\r
+\r
+               return conglomId;\r
+       }\r
+\r
+    /**\r
+     * Return a string with debug information about opened congloms/scans/sorts.\r
+     * <p>\r
+     * Return a string with debugging information about current opened\r
+     * congloms/scans/sorts which have not been close()'d.\r
+     * Calls to this routine are only valid under code which is conditional\r
+     * on SanityManager.DEBUG.\r
+     * <p>\r
+     *\r
+        * @return String with debugging information.\r
+     *\r
+        * @exception  StandardException  Standard exception policy.\r
+     **/\r
+    public String debugOpened() throws StandardException\r
+    {\r
+        String str = null;\r
+\r
+        if (SanityManager.DEBUG)\r
+        {\r
+\r
+            str = new String();\r
+\r
+            for (Iterator it = scanControllers.iterator(); it.hasNext(); )\r
+            {\r
+                ScanController sc = (ScanController) it.next();\r
+                str += "open scan controller: " + sc + "\n";\r
+            }\r
+\r
+            for (Iterator it = conglomerateControllers.iterator();\r
+                 it.hasNext(); )\r
+            {\r
+                ConglomerateController cc = \r
+                    (ConglomerateController) it.next();\r
+                str += "open conglomerate controller: " + cc + "\n";\r
+            }\r
+\r
+            if (sortControllers != null)\r
+            {\r
+                for (Iterator it = sortControllers.iterator(); it.hasNext(); )\r
+                {\r
+                    SortController sc = (SortController) it.next();\r
+                    str += "open sort controller: " + sc + "\n";\r
+                }\r
+            }\r
+\r
+            if (sorts != null)\r
+            {\r
+                for (int i = 0; i < sorts.size(); i++)\r
+                {\r
+                    Sort sort = (Sort) sorts.get(i);\r
+\r
+                    if (sort != null)\r
+                    {\r
+                        str += \r
+                            "sorts created by createSort() in current xact:" + \r
+                            sort + "\n";\r
+                    }\r
+                }\r
+            }\r
+\r
+                       if (tempCongloms != null)\r
+                       {\r
+                for (Iterator it = tempCongloms.keySet().iterator();\r
+                     it.hasNext(); )\r
+                {\r
+                                       Long conglomId = (Long) it.next();\r
+                                       Conglomerate c = (Conglomerate) tempCongloms.get(conglomId);\r
+                                       str += "temp conglomerate id = " + conglomId + ": " + c;\r
+                               }\r
+                       }\r
+\r
+        }\r
+\r
+        return(str);\r
+    }\r
+\r
+    public boolean conglomerateExists(long conglomId)\r
+               throws StandardException\r
+       {\r
+               Conglomerate conglom = findConglomerate(conglomId);\r
+               if (conglom == null)\r
+                       return false;\r
+               return true;\r
+       }\r
+\r
+    public void dropConglomerate(long conglomId)\r
+               throws StandardException\r
+       {\r
+               Conglomerate conglom = findExistingConglomerate(conglomId);\r
+\r
+               conglom.drop(this);\r
+\r
+               if (conglomId < 0)\r
+               {\r
+                       if (tempCongloms != null)\r
+                               tempCongloms.remove(new Long(conglomId));\r
+               }\r
+               else\r
+        {\r
+                       accessmanager.conglomCacheRemoveEntry(conglomId);\r
+        }\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
+    long                    conglomId,\r
+    int                     open_mode,\r
+    int                     lock_level,\r
+    int                     isolation_level,\r
+    FormatableBitSet                 scanColumnList,\r
+    DataValueDescriptor[]   fetchRow)\r
+        throws StandardException\r
+    {\r
+               // Find the conglomerate.\r
+               Conglomerate conglom = findExistingConglomerate(conglomId);\r
+\r
+               // Get a scan controller.\r
+        return(\r
+            conglom.fetchMaxOnBTree(\r
+                this, \r
+                rawtran,\r
+                conglomId,\r
+                open_mode,\r
+                lock_level,\r
+                determine_locking_policy(lock_level, isolation_level),\r
+                isolation_level,\r
+                scanColumnList,\r
+                fetchRow));\r
+    }\r
+\r
+\r
+    /**\r
+     * A superset of properties that "users" can specify.\r
+     * <p>\r
+     * A superset of properties that "users" (ie. from sql) can specify.  Store\r
+     * may implement other properties which should not be specified by users.\r
+     * Layers above access may implement properties which are not known at\r
+     * all to Access.\r
+     * <p>\r
+     * This list is a superset, as some properties may not be implemented by\r
+     * certain types of conglomerates.  For instant an in-memory store may not\r
+     * implement a pageSize property.  Or some conglomerates may not support\r
+     * pre-allocation.\r
+     * <p>\r
+     * This interface is meant to be used by the SQL parser to do validation\r
+     * of properties passsed to the create table statement, and also by the\r
+     * various user interfaces which present table information back to the \r
+     * user.\r
+     * <p>\r
+     * Currently this routine returns the following list:\r
+     *      derby.storage.initialPages\r
+     *      derby.storage.minimumRecordSize\r
+     *      derby.storage.pageReservedSpace\r
+     *      derby.storage.pageSize\r
+     *\r
+        * @return The superset of properties that "users" can specify.\r
+     *\r
+     **/\r
+    public Properties getUserCreateConglomPropList()\r
+    {\r
+        Properties  ret_properties = \r
+            ConglomerateUtil.createUserRawStorePropertySet((Properties) null);\r
+\r
+        return(ret_properties);\r
+    }\r
+\r
+    /**\r
+     * Reveals whether the transaction has ever read or written data.\r
+     *\r
+        * @return true If the transaction has never read or written data.\r
+     *\r
+     **/\r
+       public boolean isIdle()\r
+    {\r
+               return rawtran.isIdle();\r
+    }\r
+\r
+    /**\r
+     * Reveals whether the transaction is a global or local transaction.\r
+     *\r
+        * @return true If the transaction was either started by \r
+     *         AccessFactory.startXATransaction() or was morphed to a global\r
+     *         transaction by calling \r
+     *         AccessFactory.createXATransactionFromLocalTransaction().\r
+     * \r
+     * @see AccessFactory#startXATransaction\r
+     * @see TransactionController#createXATransactionFromLocalTransaction\r
+     *\r
+     **/\r
+       public boolean isGlobal()\r
+    {\r
+        return(rawtran.getGlobalId() != null);\r
+    }\r
+\r
+    /**\r
+     * Reveals whether the transaction is currently pristine.\r
+     *\r
+        * @return true If the transaction is Pristine.\r
+     *\r
+        * @see TransactionController#isPristine\r
+     **/\r
+       public boolean isPristine()\r
+    {\r
+               return rawtran.isPristine();\r
+       }\r
+\r
+       /**\r
+     * Convert a local transaction to a global transaction.\r
+     * <p>\r
+        * Get a transaction controller with which to manipulate data within\r
+        * the access manager.  Tbis controller allows one to manipulate a \r
+     * global XA conforming transaction.\r
+     * <p>\r
+     * Must only be called a previous local transaction was created and exists\r
+     * in the context.  Can only be called if the current transaction is in\r
+     * the idle state.  Upon return from this call the old tc will be unusable,\r
+     * and all references to it should be dropped (it will have been implicitly\r
+     * destroy()'d by this call.\r
+     * <p>\r
+     * The (format_id, global_id, branch_id) triplet is meant to come exactly\r
+     * from a javax.transaction.xa.Xid.  We don't use Xid so that the system\r
+     * can be delivered on a non-1.2 vm system and not require the javax classes\r
+     * in the path.  \r
+     *\r
+     * @param format_id the format id part of the Xid - ie. Xid.getFormatId().\r
+     * @param global_id the global transaction identifier part of XID - ie.\r
+     *                  Xid.getGlobalTransactionId().\r
+     * @param branch_id The branch qualifier of the Xid - ie. \r
+     *                  Xid.getBranchQaulifier()\r
+     *         \r
+        * @exception StandardException Standard exception policy.\r
+        * @see TransactionController\r
+        **/\r
+       public /* XATransactionController */ Object \r
+    createXATransactionFromLocalTransaction(\r
+    int                     format_id,\r
+    byte[]                  global_id,\r
+    byte[]                  branch_id)\r
+               throws StandardException\r
+    {\r
+\r
+        getRawStoreXact().createXATransactionFromLocalTransaction(\r
+            format_id, global_id, branch_id);\r
+\r
+        return this;\r
+    }\r
+\r
+       /**\r
+               Bulk load into the conglomerate.  Rows being loaded into the\r
+               conglomerate are not logged.\r
+\r
+               @param conglomId The conglomerate Id.\r
+\r
+               @param createConglom If true, the conglomerate is being created in the\r
+               same operation as the loadConglomerate.  The enables further\r
+               optimization as recovery does not require page allocation to be\r
+               logged. \r
+\r
+               @param rowSource Where the rows come from.\r
+\r
+           @return true The number of rows loaded.\r
+\r
+               @exception StandardException Standard Derby Error Policy\r
+        */\r
+       public long loadConglomerate(\r
+    long                    conglomId,\r
+    boolean                 createConglom,\r
+    RowLocationRetRowSource rowSource)\r
+               throws StandardException\r
+       {\r
+               // Find the conglomerate.\r
+               Conglomerate conglom = findExistingConglomerate(conglomId);\r
+\r
+               // Load up the conglomerate with rows from the rowSource.\r
+               // Don't need to keep track of the conglomerate controller because load\r
+               // automatically closes it when it finished.\r
+               return(conglom.load(this, createConglom, rowSource));\r
+       }\r
+\r
+       /**\r
+               Use this for incremental load in the future.  \r
+\r
+               @param conglomId the conglomerate Id\r
+               @param rowSource where the rows to be loaded comes from \r
+\r
+               @exception StandardException Standard Derby Error Policy\r
+        */\r
+       public void loadConglomerate(\r
+    long                    conglomId,\r
+    RowLocationRetRowSource rowSource)\r
+               throws StandardException\r
+       {\r
+               loadConglomerate(\r
+                               conglomId, \r
+                               false, // conglomerate is not being created  \r
+                               rowSource);\r
+       }       \r
+\r
+    /**\r
+     * Log an operation and then action it in the context of this transaction.\r
+     * <p>\r
+     * This simply passes the operation to the RawStore which logs and does it.\r
+     * <p>\r
+     *\r
+     * @param operation the operation that is to be applied\r
+     *\r
+        * @exception  StandardException  Standard exception policy.\r
+     **/\r
+       public void logAndDo(Loggable operation)\r
+               throws StandardException\r
+       {\r
+               rawtran.logAndDo(operation);\r
+       }\r
+\r
+    public ConglomerateController openCompiledConglomerate(\r
+    boolean                         hold,\r
+    int                             open_mode,\r
+    int                             lock_level,\r
+    int                             isolation_level,\r
+    StaticCompiledOpenConglomInfo   static_info,\r
+    DynamicCompiledOpenConglomInfo  dynamic_info)\r
+               throws StandardException\r
+       {\r
+        if (SanityManager.DEBUG)\r
+        {\r
+            SanityManager.ASSERT(static_info != null);\r
+            SanityManager.ASSERT(dynamic_info != null);\r
+        }\r
+        \r
+        // in the current implementation, only Conglomerate's are passed around\r
+        // as StaticCompiledOpenConglomInfo.\r
+\r
+        return(\r
+            openConglomerate(\r
+                (Conglomerate) static_info.getConglom(),\r
+                hold, open_mode, lock_level, isolation_level, \r
+                static_info, dynamic_info));\r
+    }\r
+\r
+    public ConglomerateController openConglomerate(\r
+    long                            conglomId, \r
+    boolean                         hold,\r
+    int                             open_mode,\r
+    int                             lock_level,\r
+    int                             isolation_level)\r
+               throws StandardException\r
+       {\r
+        return(\r
+            openConglomerate(\r
+                findExistingConglomerate(conglomId),\r
+                hold, open_mode, lock_level, isolation_level, \r
+                (StaticCompiledOpenConglomInfo) null,\r
+                (DynamicCompiledOpenConglomInfo) null));\r
+       }\r
+\r
+    public long findConglomid(long container_id)\r
+        throws StandardException\r
+    {\r
+        return(container_id);\r
+    }\r
+\r
+    public long findContainerid(long conglom_id)\r
+        throws StandardException\r
+    {\r
+        return(conglom_id);\r
+    }\r
+\r
+    /**\r
+     * Create a BackingStoreHashtable which contains all rows that qualify for\r
+     * the described scan.\r
+     **/\r
+    public BackingStoreHashtable createBackingStoreHashtableFromScan(\r
+    long                    conglomId,\r
+    int                     open_mode,\r
+    int                     lock_level,\r
+    int                     isolation_level,\r
+    FormatableBitSet                 scanColumnList,\r
+    DataValueDescriptor[]   startKeyValue,\r
+    int                     startSearchOperator,\r
+    Qualifier               qualifier[][],\r
+    DataValueDescriptor[]   stopKeyValue,\r
+    int                     stopSearchOperator,\r
+    long                    max_rowcnt,\r
+    int[]                   key_column_numbers,\r
+    boolean                 remove_duplicates,\r
+    long                    estimated_rowcnt,\r
+    long                    max_inmemory_rowcnt,\r
+    int                     initialCapacity,\r
+    float                   loadFactor,\r
+    boolean                 collect_runtimestats,\r
+    boolean                        skipNullKeyColumns,\r
+    boolean                 keepAfterCommit)\r
+        throws StandardException\r
+    {\r
+        return (\r
+            new BackingStoreHashTableFromScan(\r
+                this,\r
+                conglomId,\r
+                open_mode,\r
+                lock_level,\r
+                isolation_level,\r
+                scanColumnList,\r
+                startKeyValue,\r
+                startSearchOperator,\r
+                qualifier,\r
+                stopKeyValue,\r
+                stopSearchOperator,\r
+                max_rowcnt,\r
+                key_column_numbers,\r
+                remove_duplicates,\r
+                estimated_rowcnt,\r
+                max_inmemory_rowcnt,\r
+                initialCapacity,\r
+                loadFactor,\r
+                collect_runtimestats,\r
+                               skipNullKeyColumns,\r
+                keepAfterCommit));\r
+    }\r
+\r
+\r
+       public GroupFetchScanController openGroupFetchScan(\r
+    long                            conglomId,\r
+    boolean                         hold,\r
+    int                             open_mode,\r
+    int                             lock_level,\r
+    int                             isolation_level,\r
+    FormatableBitSet                         scanColumnList,\r
+    DataValueDescriptor[]           startKeyValue,\r
+    int                             startSearchOperator,\r
+    Qualifier                       qualifier[][],\r
+    DataValueDescriptor[]           stopKeyValue,\r
+    int                             stopSearchOperator)\r
+        throws StandardException\r
+       {\r
+        if (SanityManager.DEBUG)\r
+        {\r
+                       if ((open_mode & \r
+                ~(TransactionController.OPENMODE_FORUPDATE | \r
+                  TransactionController.OPENMODE_FOR_LOCK_ONLY |\r
+                  TransactionController.OPENMODE_SECONDARY_LOCKED)) != 0)\r
+                               SanityManager.THROWASSERT(\r
+                                       "Bad open mode to openScan:" + \r
+                    Integer.toHexString(open_mode));\r
+\r
+                       if (!(lock_level == MODE_RECORD |\r
+                 lock_level == MODE_TABLE))\r
+                               SanityManager.THROWASSERT(\r
+                "Bad lock level to openScan:" + lock_level);\r
+        }\r
+\r
+               // Find the conglomerate.\r
+               Conglomerate conglom = findExistingConglomerate(conglomId);\r
+\r
+               // Get a scan controller.\r
+               ScanManager sm = \r
+            conglom.openScan(\r
+                this, rawtran, hold, open_mode, \r
+                determine_lock_level(lock_level),\r
+                determine_locking_policy(lock_level, isolation_level),\r
+                isolation_level,\r
+                scanColumnList,\r
+                startKeyValue, startSearchOperator,\r
+                qualifier,\r
+                stopKeyValue, stopSearchOperator,\r
+                (StaticCompiledOpenConglomInfo) null,\r
+                (DynamicCompiledOpenConglomInfo) null);\r
+\r
+               // Keep track of it so we can release on close.\r
+               scanControllers.add(sm);\r
+\r
+               return(sm);\r
+       }\r
+\r
+\r
+\r
+    /**\r
+     * Purge all committed deleted rows from the conglomerate.\r
+     * <p>\r
+     * This call will purge committed deleted rows from the conglomerate,\r
+     * that space will be available for future inserts into the conglomerate.\r
+     * <p>\r
+     *\r
+     * @param conglomId Id of the conglomerate to purge.\r
+     *\r
+        * @exception  StandardException  Standard exception policy.\r
+     **/\r
+    public void purgeConglomerate(\r
+    long    conglomId)\r
+        throws StandardException\r
+    {\r
+        findExistingConglomerate(conglomId).purgeConglomerate(\r
+            this, \r
+            rawtran);\r
+\r
+               return;\r
+    }\r
+\r
+    /**\r
+     * Return free space from the conglomerate back to the OS.\r
+     * <p>\r
+     * Returns free space from the conglomerate back to the OS.  Currently\r
+     * only the sequential free pages at the "end" of the conglomerate can\r
+     * be returned to the OS.\r
+     * <p>\r
+     *\r
+     * @param conglomId Id of the conglomerate to purge.\r
+     *\r
+        * @exception  StandardException  Standard exception policy.\r
+     **/\r
+    public void compressConglomerate(\r
+    long    conglomId)\r
+        throws StandardException\r
+    {\r
+        findExistingConglomerate(conglomId).compressConglomerate(\r
+            this, \r
+            rawtran); \r
+\r
+               return;\r
+    }\r
+\r
+    /**\r
+     * Compress table in place.\r
+     * <p>\r
+     * Returns a GroupFetchScanController which can be used to move rows\r
+     * around in a table, creating a block of free pages at the end of the\r
+     * table.  The process will move rows from the end of the table toward\r
+     * the beginning.  The GroupFetchScanController will return the \r
+     * old row location, the new row location, and the actual data of any\r
+     * row moved.  Note that this scan only returns moved rows, not an\r
+     * entire set of rows, the scan is designed specifically to be\r
+     * used by either explicit user call of the SYSCS_ONLINE_COMPRESS_TABLE()\r
+     * procedure, or internal background calls to compress the table.\r
+     *\r
+     * The old and new row locations are returned so that the caller can\r
+     * update any indexes necessary.\r
+     *\r
+     * This scan always returns all collumns of the row.\r
+     * \r
+     * All inputs work exactly as in openScan().  The return is \r
+     * a GroupFetchScanController, which only allows fetches of groups\r
+     * of rows from the conglomerate.\r
+     * <p>\r
+     *\r
+        * @return The GroupFetchScanController to be used to fetch the rows.\r
+     *\r
+        * @param conglomId             see openScan()\r
+     * @param hold                  see openScan()\r
+     * @param open_mode             see openScan()\r
+     * @param lock_level            see openScan()\r
+     * @param isolation_level       see openScan()\r
+     *\r
+        * @exception  StandardException  Standard exception policy.\r
+     *\r
+     * @see ScanController\r
+     * @see GroupFetchScanController\r
+     **/\r
+       public GroupFetchScanController defragmentConglomerate(\r
+    long                            conglomId,\r
+    boolean                         online,\r
+    boolean                         hold,\r
+    int                             open_mode,\r
+    int                             lock_level,\r
+    int                             isolation_level)\r
+        throws StandardException\r
+       {\r
+        if (SanityManager.DEBUG)\r
+        {\r
+                       if ((open_mode & \r
+                ~(TransactionController.OPENMODE_FORUPDATE | \r
+                  TransactionController.OPENMODE_FOR_LOCK_ONLY |\r
+                  TransactionController.OPENMODE_SECONDARY_LOCKED)) != 0)\r
+                               SanityManager.THROWASSERT(\r
+                                       "Bad open mode to openScan:" + \r
+                    Integer.toHexString(open_mode));\r
+\r
+                       if (!(lock_level == MODE_RECORD |\r
+                 lock_level == MODE_TABLE))\r
+                               SanityManager.THROWASSERT(\r
+                "Bad lock level to openScan:" + lock_level);\r
+        }\r
+\r
+               // Find the conglomerate.\r
+               Conglomerate conglom = findExistingConglomerate(conglomId);\r
+\r
+               // Get a scan controller.\r
+               ScanManager sm = \r
+            conglom.defragmentConglomerate(\r
+                this, \r
+                rawtran, \r
+                hold, \r
+                open_mode, \r
+                determine_lock_level(lock_level),\r
+                determine_locking_policy(lock_level, isolation_level),\r
+                isolation_level);\r
+\r
+               // Keep track of it so we can release on close.\r
+               scanControllers.add(sm);\r
+\r
+               return(sm);\r
+       }\r
+\r
+\r
+       public ScanController openScan(\r
+    long                            conglomId,\r
+    boolean                         hold,\r
+    int                             open_mode,\r
+    int                             lock_level,\r
+    int                             isolation_level,\r
+    FormatableBitSet                         scanColumnList,\r
+    DataValueDescriptor[]           startKeyValue,\r
+    int                             startSearchOperator,\r
+    Qualifier                       qualifier[][],\r
+    DataValueDescriptor[]           stopKeyValue,\r
+    int                             stopSearchOperator)\r
+        throws StandardException\r
+       {\r
+        return(\r
+            openScan(\r
+                findExistingConglomerate(conglomId),\r
+                hold,\r
+                open_mode,\r
+                lock_level,\r
+                isolation_level,\r
+                scanColumnList,\r
+                startKeyValue,\r
+                startSearchOperator,\r
+                qualifier,\r
+                stopKeyValue,\r
+                stopSearchOperator,\r
+                (StaticCompiledOpenConglomInfo) null,\r
+                (DynamicCompiledOpenConglomInfo) null));\r
+    }\r
+\r
+       public ScanController openCompiledScan(\r
+    boolean                         hold,\r
+    int                             open_mode,\r
+    int                             lock_level,\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
+        // in the current implementation, only Conglomerate's are passed around\r
+        // as StaticCompiledOpenConglomInfo.\r
+\r
+        if (SanityManager.DEBUG)\r
+        {\r
+            SanityManager.ASSERT(static_info != null);\r
+            SanityManager.ASSERT(dynamic_info != null);\r
+            SanityManager.ASSERT(\r
+                static_info instanceof StaticCompiledOpenConglomInfo);\r
+            SanityManager.ASSERT(\r
+                dynamic_info instanceof DynamicCompiledOpenConglomInfo);\r
+        }\r
+\r
+        return(\r
+            openScan(\r
+                ((Conglomerate) static_info.getConglom()),\r
+                hold,\r
+                open_mode,\r
+                lock_level,\r
+                isolation_level,\r
+                scanColumnList,\r
+                startKeyValue,\r
+                startSearchOperator,\r
+                qualifier,\r
+                stopKeyValue,\r
+                stopSearchOperator,\r
+                static_info,\r
+                dynamic_info));\r
+       }\r
+\r
+\r
+    /**\r
+     * Return an open StoreCostController for the given conglomid.\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
+     *\r
+        * @return The open StoreCostController.\r
+     *\r
+     * @param conglomId The identifier of the conglomerate to open.\r
+     *\r
+        * @exception  StandardException  Standard exception policy.\r
+     *\r
+     * @see StoreCostController\r
+     **/\r
+    public StoreCostController openStoreCost(\r
+    long        conglomId)\r
+               throws StandardException\r
+    {\r
+               // Find the conglomerate.\r
+               Conglomerate conglom = findExistingConglomerate(conglomId);\r
+\r
+               // Get a scan controller.\r
+               StoreCostController scc = conglom.openStoreCost(this, rawtran);\r
+\r
+               return(scc);\r
+    }\r
+\r
+       /**\r
+       @see TransactionController#createSort\r
+       @exception StandardException Standard error policy.\r
+       **/\r
+       public long createSort(\r
+    Properties              implParameters,\r
+    DataValueDescriptor[]   template,\r
+    ColumnOrdering          columnOrdering[],\r
+    SortObserver               sortObserver,\r
+    boolean                 alreadyInOrder,\r
+    long                    estimatedRows,\r
+    int                     estimatedRowSize)\r
+        throws StandardException\r
+       {\r
+               // Get the implementation type from the parameters.\r
+               // XXX (nat) need to figure out how to select sort implementation.\r
+               String implementation = null;\r
+               if (implParameters != null)\r
+                       implementation = \r
+                implParameters.getProperty(AccessFactoryGlobals.IMPL_TYPE);\r
+\r
+               if (implementation == null)\r
+                       implementation = AccessFactoryGlobals.SORT_EXTERNAL;\r
+\r
+               // Find the appropriate factory for the desired implementation.\r
+               MethodFactory mfactory;\r
+               mfactory = accessmanager.findMethodFactoryByImpl(implementation);\r
+               if (mfactory == null || !(mfactory instanceof SortFactory))\r
+        {\r
+                       throw(\r
+              StandardException.newException(\r
+                  SQLState.AM_NO_FACTORY_FOR_IMPLEMENTATION, implementation));\r
+        }\r
+               SortFactory sfactory = (SortFactory) mfactory;\r
+\r
+               // Decide what segment the sort should use.\r
+               int segment = 0; // XXX (nat) sorts always in segment 0\r
+\r
+               // Create the sort.\r
+               Sort sort = sfactory.createSort(this, segment,\r
+                                               implParameters, template, columnOrdering,\r
+                                               sortObserver, alreadyInOrder, estimatedRows, \r
+                        estimatedRowSize);\r
+\r
+               // Add the sort to the sorts vector\r
+               if (sorts == null) {\r
+                       sorts = new ArrayList();\r
+            freeSortIds = new ArrayList();\r
+        }\r
+\r
+        int sortid;\r
+        if (freeSortIds.isEmpty()) {\r
+            // no free identifiers, add sort at the end\r
+            sortid = sorts.size();\r
+            sorts.add(sort);\r
+        } else {\r
+            // reuse a sort identifier\r
+            sortid = ((Integer) freeSortIds.remove(freeSortIds.size() - 1))\r
+                .intValue();\r
+            sorts.set(sortid, sort);\r
+        }\r
+\r
+               return sortid;\r
+       }\r
+\r
+       /**\r
+       Drop a sort. \r
+    <p>\r
+    Drop a sort created by a call to createSort() within the current \r
+    transaction (sorts are automatically "dropped" at the end of a \r
+    transaction.  This call should only be made after all openSortScan()'s\r
+    and openSort()'s have been closed.\r
+    <p>\r
+\r
+    @param sortid The identifier of the sort to drop, as returned from \r
+                  createSort.\r
+       @exception StandardException From a lower-level exception.\r
+       **/\r
+    public void dropSort(long sortid) \r
+        throws StandardException\r
+    {\r
+        // should call close on the sort.\r
+        Sort sort = (Sort) sorts.get((int) sortid);\r
+\r
+        if (sort != null)\r
+        {\r
+            sort.drop(this);\r
+            sorts.set((int) sortid, null);\r
+            freeSortIds.add(ReuseFactory.getInteger((int) sortid));\r
+        }\r
+    }\r
+\r
+    /**\r
+       @see TransactionController#getProperty\r
+       @exception  StandardException  Standard exception policy.\r
+    **/\r
+    public Serializable getProperty(\r
+    String key) \r
+        throws StandardException\r
+       {\r
+               return \r
+            (accessmanager.getTransactionalProperties().getProperty(this, key));\r
+       }\r
+\r
+           /**\r
+       @see TransactionController#getPropertyDefault\r
+       @exception  StandardException  Standard exception policy.\r
+    **/\r
+    public Serializable getPropertyDefault(\r
+    String key) \r
+        throws StandardException\r
+       {\r
+               return \r
+            (accessmanager.getTransactionalProperties().getPropertyDefault(this, key));\r
+       }\r
+\r
+    /**\r
+       @see TransactionController#setProperty\r
+       @exception  StandardException  Standard exception policy.\r
+    **/\r
+    public void        setProperty(\r
+    String       key, \r
+    Serializable value,\r
+       boolean dbOnlyProperty) \r
+        throws StandardException\r
+       {\r
+               accessmanager.getTransactionalProperties().setProperty(\r
+            this, key, value, dbOnlyProperty);\r
+       }\r
+\r
+    /**\r
+       @see TransactionController#setProperty\r
+       @exception  StandardException  Standard exception policy.\r
+    **/\r
+    public void        setPropertyDefault(\r
+    String       key, \r
+    Serializable value) \r
+        throws StandardException\r
+       {\r
+               accessmanager.getTransactionalProperties().setPropertyDefault(\r
+            this, key, value);\r
+       }\r
+\r
+    /**\r
+       @see TransactionController#propertyDefaultIsVisible\r
+       @exception  StandardException  Standard exception policy.\r
+    **/\r
+    public boolean propertyDefaultIsVisible(String key) throws StandardException\r
+       {\r
+               return accessmanager.getTransactionalProperties().propertyDefaultIsVisible(this,key);\r
+       }\r
+\r
+    /**\r
+       @see TransactionController#getProperties\r
+       @exception  StandardException  Standard exception policy.\r
+    **/\r
+    public Properties  getProperties() \r
+        throws StandardException\r
+       {\r
+               return accessmanager.getTransactionalProperties().getProperties(this);\r
+       }\r
+\r
+       /**\r
+       @see TransactionController#openSort\r
+       @exception StandardException Standard error policy.\r
+       **/\r
+       public SortController openSort(long id)\r
+               throws StandardException\r
+       {\r
+               Sort sort;\r
+\r
+               // Find the sort in the sorts list, throw an error\r
+               // if it doesn't exist.\r
+               if (sorts == null || id >= sorts.size()\r
+                       || (sort = ((Sort) sorts.get((int) id))) == null)\r
+               {\r
+                       throw StandardException.newException(\r
+                    SQLState.AM_NO_SUCH_SORT, new Long(id));\r
+               }\r
+\r
+               // Open it.\r
+               SortController sc = sort.open(this);\r
+\r
+               // Keep track of it so we can release on close.\r
+               if (sortControllers == null)\r
+                       sortControllers = new ArrayList();\r
+               sortControllers.add(sc);\r
+\r
+               return sc;\r
+       }\r
+\r
+    /**\r
+     * Return an open SortCostController.\r
+     * <p>\r
+     * Return an open SortCostController which can be used to ask about \r
+     * the estimated costs of SortController() operations.\r
+     * <p>\r
+     *\r
+        * @return The open StoreCostController.\r
+     *\r
+        * @exception  StandardException  Standard exception policy.\r
+     *\r
+     * @see StoreCostController\r
+     **/\r
+    public SortCostController openSortCostController(\r
+    Properties      implParameters)\r
+               throws StandardException\r
+    {\r
+               // Get the implementation type from the parameters.\r
+               // RESOLVE (mikem) need to figure out how to select sort implementation.\r
+               String implementation = null;\r
+\r
+               if (implementation == null)\r
+                       implementation = AccessFactoryGlobals.SORT_EXTERNAL;\r
+\r
+               // Find the appropriate factory for the desired implementation.\r
+               MethodFactory mfactory;\r
+               mfactory = accessmanager.findMethodFactoryByImpl(implementation);\r
+               if (mfactory == null || !(mfactory instanceof SortFactory))\r
+        {\r
+                       throw(\r
+              StandardException.newException(\r
+                  SQLState.AM_NO_FACTORY_FOR_IMPLEMENTATION, implementation));\r
+        }\r
+               SortFactory sfactory = (SortFactory) mfactory;\r
+\r
+               // open sort cost controller\r
+        return(sfactory.openSortCostController());\r
+    }\r
+\r
+       /**\r
+       @see TransactionController#openSortScan\r
+       @exception StandardException Standard error policy.\r
+       **/\r
+       public ScanController openSortScan(\r
+    long    id,\r
+    boolean hold)\r
+               throws StandardException\r
+       {\r
+               Sort sort;\r
+\r
+               // Find the sort in the sorts list, throw an error\r
+               // if it doesn't exist.\r
+               if (sorts == null || id >= sorts.size()\r
+                       || (sort = ((Sort) sorts.get((int) id))) == null)\r
+               {\r
+                       throw StandardException.newException(\r
+                    SQLState.AM_NO_SUCH_SORT, new Long(id));\r
+               }\r
+\r
+               // Open a scan on it.\r
+               ScanController sc = sort.openSortScan(this, hold);\r
+\r
+               // Keep track of it so we can release on close.\r
+               scanControllers.add(sc);\r
+\r
+               return sc;\r
+       }\r
+\r
+       /**\r
+       @see TransactionController#openSortRowSource\r
+       @exception StandardException Standard error policy.\r
+       **/\r
+       public RowLocationRetRowSource openSortRowSource(long id) \r
+                throws StandardException\r
+       {\r
+               Sort sort;\r
+\r
+               // Find the sort in the sorts list, throw an error\r
+               // if it doesn't exist.\r
+               if (sorts == null || id >= sorts.size()\r
+                       || (sort = ((Sort) sorts.get((int) id))) == null)\r
+               {\r
+                       throw StandardException.newException(\r
+                    SQLState.AM_NO_SUCH_SORT, new Long(id));\r
+               }\r
+\r
+               // Open a scan row source on it.\r
+               ScanControllerRowSource sc = sort.openSortRowSource(this);\r
+\r
+               // Keep track of it so we can release on close.\r
+               scanControllers.add(sc);\r
+\r
+               return sc;\r
+       }\r
+\r
+\r
+       public void commit()\r
+               throws StandardException\r
+       {\r
+               this.closeControllers(false /* don't close held controllers */ );\r
+\r
+        rawtran.commit();\r
+\r
+        alterTableCallMade = false;\r
+\r
+        return;\r
+       }\r
+\r
+       public DatabaseInstant commitNoSync(int commitflag)\r
+               throws StandardException\r
+       {\r
+               this.closeControllers(false /* don't close held controllers */ );\r
+               return rawtran.commitNoSync(commitflag);\r
+       }\r
+\r
+       public void abort()\r
+               throws StandardException\r
+       {\r
+       \r
+        if (alterTableCallMade)\r
+        {\r
+            accessmanager.conglomCacheInvalidate();\r
+            alterTableCallMade = false;\r
+        }\r
+               this.closeControllers(true /* close all controllers */ );\r
+               rawtran.abort();\r
+\r
+        if (parent_tran != null)\r
+            parent_tran.abort();\r
+       }\r
+\r
+    /**\r
+     * Get the context manager that the transaction was created with.\r
+     * <p>\r
+     *\r
+        * @return The context manager that the transaction was created with.\r
+     *     **/\r
+    public ContextManager getContextManager()\r
+    {\r
+        return(context.getContextManager());\r
+    }\r
+\r
+       public int setSavePoint(String name, Object kindOfSavepoint)\r
+               throws StandardException\r
+       {\r
+               return rawtran.setSavePoint(name, kindOfSavepoint);\r
+       }\r
+\r
+       public int releaseSavePoint(String name, Object kindOfSavepoint)\r
+               throws StandardException\r
+       {\r
+               return rawtran.releaseSavePoint(name, kindOfSavepoint);\r
+       }\r
+\r
+       public int rollbackToSavePoint(String name, boolean close_controllers, Object kindOfSavepoint)\r
+               throws StandardException\r
+       {\r
+        if (close_controllers)\r
+            this.closeControllers(true /* close all controllers */ );\r
+               return rawtran.rollbackToSavePoint(name, kindOfSavepoint);\r
+       }\r
+\r
+       public void destroy()\r
+       {\r
+               try\r
+               {\r
+                       this.closeControllers(true /* close all controllers */);\r
+                       \r
+                       // If there's a transaction, abort it.\r
+                       if (rawtran != null) {\r
+                               rawtran.destroy();\r
+                               rawtran = null;\r
+                       }\r
+                       \r
+\r
+                       // If there's a context, pop it.\r
+                       if (context != null)\r
+                               context.popMe();\r
+                       context = null;\r
+\r
+                       accessmanager = null;\r
+                       tempCongloms = null;\r
+               }\r
+               catch (StandardException e)\r
+               {\r
+                       // XXX (nat) really need to figure out what to do\r
+                       // if there's an exception while aborting.\r
+                       rawtran = null;\r
+                       context = null;\r
+                       accessmanager = null;\r
+                       tempCongloms = null;\r
+               }\r
+       }\r
+\r
+       public boolean anyoneBlocked()\r
+       {\r
+               return rawtran.anyoneBlocked();\r
+       }\r
+\r
+    /**************************************************************************\r
+     * Public Methods implementing the XATransactionController interface.\r
+     **************************************************************************\r
+     */\r
+\r
+    /**\r
+     * This method is called to commit the current XA global transaction.\r
+     * <p>\r
+     * RESOLVE - how do we map to the "right" XAExceptions.\r
+     * <p>\r
+     *\r
+     * @param onePhase If true, the resource manager should use a one-phase\r
+     *                 commit protocol to commit the work done on behalf of \r
+     *                 current xid.\r
+     *\r
+        * @exception  StandardException  Standard exception policy.\r
+     **/\r
+    public void xa_commit(\r
+    boolean onePhase)\r
+               throws StandardException\r
+    {\r
+        rawtran.xa_commit(onePhase);\r
+    }\r
+\r
+    /**\r
+     * This method is called to ask the resource manager to prepare for\r
+     * a transaction commit of the transaction specified in xid.\r
+     * <p>\r
+     *\r
+     * @return         A value indicating the resource manager's vote on the\r
+     *                 the outcome of the transaction.  The possible values\r
+     *                 are:  XA_RDONLY or XA_OK.  If the resource manager wants\r
+     *                 to roll back the transaction, it should do so by \r
+     *                 throwing an appropriate XAException in the prepare\r
+     *                 method.\r
+     *\r
+        * @exception  StandardException  Standard exception policy.\r
+     **/\r
+    public int xa_prepare()\r
+               throws StandardException\r
+    {\r
+        return(rawtran.xa_prepare());\r
+    }\r
+\r
+    /**\r
+     * rollback the current global transaction.\r
+     * <p>\r
+     * The given transaction is roll'ed back and it's history is not\r
+     * maintained in the transaction table or long term log.\r
+     * <p>\r
+     *\r
+        * @exception  StandardException  Standard exception policy.\r
+     **/\r
+    public void xa_rollback()\r
+        throws StandardException\r
+    {\r
+        rawtran.xa_rollback();\r
+    }\r
+\r
+    /**************************************************************************\r
+     * Public Methods of TransactionManager interface:\r
+     **************************************************************************\r
+     */\r
+\r
+    /**\r
+     * Add to the list of post commit work.\r
+     * <p>\r
+     * Add to the list of post commit work that may be processed after this\r
+     * transaction commits.  If this transaction aborts, then the post commit\r
+     * work list will be thrown away.  No post commit work will be taken out\r
+     * on a rollback to save point.\r
+     * <p>\r
+     * This routine simply delegates the work to the Rawstore transaction.\r
+     *\r
+     * @param work  The post commit work to do.\r
+     *\r
+     **/\r
+       public void addPostCommitWork(Serviceable work)\r
+    {\r
+        rawtran.addPostCommitWork(work);\r
+\r
+        return;\r
+    }\r
+\r
+    /**\r
+     *  Check to see if a database has been upgraded to the required\r
+     *  level in order to use a store feature.\r
+     *\r
+     * @param requiredMajorVersion  required database Engine major version\r
+     * @param requiredMinorVersion  required database Engine minor version\r
+     * @param feature               Non-null to throw an exception, null to \r
+     *                              return the state of the version match.\r
+     *\r
+     * @return <code> true </code> if the database has been upgraded to \r
+     *         the required level, <code> false </code> otherwise.\r
+     *\r
+     * @exception  StandardException \r
+     *             if the database is not at the require version \r
+     *             when <code>feature</code> feature is \r
+     *             not <code> null </code>. \r
+     */\r
+       public boolean checkVersion(\r
+    int     requiredMajorVersion, \r
+    int     requiredMinorVersion, \r
+    String  feature) \r
+        throws StandardException\r
+    {\r
+        return(\r
+            accessmanager.getRawStore().checkVersion(\r
+                requiredMajorVersion, requiredMinorVersion, feature));\r
+    }\r
+\r
+    /**\r
+     * The ConglomerateController.close() method has been called on \r
+     * "conglom_control".\r
+     * <p>\r
+     * Take whatever cleanup action is appropriate to a closed \r
+     * conglomerateController.  It is likely this routine will remove\r
+     * references to the ConglomerateController object that it was maintaining\r
+     * for cleanup purposes.\r
+     *\r
+     **/\r
+    public void closeMe(ConglomerateController conglom_control)\r
+    {\r
+        conglomerateControllers.remove(conglom_control);\r
+    }\r
+\r
+    /**\r
+     * The SortController.close() method has been called on "sort_control".\r
+     * <p>\r
+     * Take whatever cleanup action is appropriate to a closed \r
+     * sortController.  It is likely this routine will remove\r
+     * references to the SortController object that it was maintaining\r
+     * for cleanup purposes.\r
+     **/\r
+    public void closeMe(SortController sort_control)\r
+    {\r
+        sortControllers.remove(sort_control);\r
+    }\r
+\r
+    /**\r
+     * The ScanManager.close() method has been called on "scan".\r
+     * <p>\r
+     * Take whatever cleanup action is appropriate to a closed scan.  It is\r
+     * likely this routine will remove references to the scan object that it\r
+     * was maintaining for cleanup purposes.\r
+     *\r
+     **/\r
+    public void closeMe(ScanManager scan)\r
+    {\r
+        scanControllers.remove(scan);\r
+    }\r
+\r
+    /**\r
+     * Get reference to access factory which started this transaction.\r
+     * <p>\r
+     *\r
+        * @return The AccessFactory which started this transaction.\r
+     *\r
+     **/\r
+    public AccessFactory getAccessManager()\r
+    {\r
+        return(accessmanager);\r
+    }\r
+\r
+    /**\r
+     * Get an Internal transaction.\r
+     * <p>\r
+     * Start an internal transaction.  An internal transaction is a completely\r
+     * separate transaction from the current user transaction.  All work done\r
+     * in the internal transaction must be physical (ie. it can be undone \r
+     * physically by the rawstore at the page level, rather than logically \r
+     * undone like btree insert/delete operations).  The rawstore guarantee's\r
+     * that in the case of a system failure all open Internal transactions are\r
+     * first undone in reverse order, and then other transactions are undone\r
+     * in reverse order.\r
+     * <p>\r
+     * Internal transactions are meant to implement operations which, if \r
+     * interupted before completion will cause logical operations like tree\r
+     * searches to fail.  This special undo order insures that the state of\r
+     * the tree is restored to a consistent state before any logical undo \r
+     * operation which may need to search the tree is performed.\r
+     * <p>\r
+     *\r
+        * @return The new internal transaction.\r
+     *\r
+        * @exception  StandardException  Standard exception policy.\r
+     **/\r
+    public TransactionManager getInternalTransaction()\r
+        throws StandardException\r
+    {\r
+        // Get the context manager.\r
+        ContextManager cm = getContextManager();\r
+\r
+        // Allocate a new transaction no matter what.\r
+        \r
+        // Create a transaction, make a context for it, and push the context.\r
+        // Note this puts the raw store transaction context\r
+        // above the access context, which is required for\r
+        // error handling assumptions to be correct.\r
+        \r
+        Transaction rawtran = \r
+            accessmanager.getRawStore().startInternalTransaction(cm);\r
+        RAMTransaction rt   = new RAMTransaction(accessmanager, rawtran, null);\r
+        RAMTransactionContext rtc   = \r
+                       new RAMTransactionContext(\r
+                cm, AccessFactoryGlobals.RAMXACT_INTERNAL_CONTEXT_ID, \r
+                rt, true /*abortAll */);\r
+\r
+        rawtran.setDefaultLockingPolicy(\r
+                accessmanager.getDefaultLockingPolicy());\r
+\r
+        return(rt);\r
+    }\r
+\r
+    /**\r
+     * Get an nested user transaction.\r
+     * <p>\r
+     * A nested user can be used exactly as any other TransactionController,\r
+     * except as follows.  For this discussion let the parent transaction \r
+     * be the transaction used to make the getNestedUserTransaction(), and\r
+     * let the child transaction be the transaction returned by the \r
+     * getNestedUserTransaction() call.\r
+     * <p>\r
+     * The nesting is limited to one level deep.  An exception will be thrown\r
+     * if a subsequent getNestedUserTransaction() is called on the child\r
+     * transaction.\r
+     * <p>\r
+     * The locks in the child transaction will be compatible with the locks\r
+     * of the parent transaction.\r
+     * <p>\r
+     * A commit in the child transaction will release locks associated with\r
+     * the child transaction only, work can continue in the parent transaction\r
+     * at this point.  \r
+     * <p>\r
+     * Any abort of the child transaction will result in an abort of both\r
+     * the child transaction and parent transaction.\r
+     * <p>\r
+     * A TransactionController.destroy() call should be made on the child\r
+     * transaction once all child work is done, and the caller wishes to \r
+     * continue work in the parent transaction.\r
+     * <p>\r
+     * Nested internal transactions are meant to be used to implement \r
+     * system work necessary to commit as part of implementing a user's\r
+     * request, but where holding the lock for the duration of the user\r
+     * transaction is not acceptable.  2 examples of this are system catalog\r
+     * read locks accumulated while compiling a plan, and auto-increment.\r
+     * <p>\r
+     *\r
+        * @return The new nested user transaction.\r
+     *\r
+        * @exception  StandardException  Standard exception policy.\r
+     **/\r
+    public TransactionController startNestedUserTransaction(boolean readOnly)\r
+        throws StandardException\r
+    {\r
+        // Get the context manager.\r
+        ContextManager cm = getContextManager();\r
+\r
+        // Allocate a new transaction no matter what.\r
+        \r
+        // Create a transaction, make a context for it, and push the context.\r
+        // Note this puts the raw store transaction context\r
+        // above the access context, which is required for\r
+        // error handling assumptions to be correct.\r
+        //\r
+        // Note that the nested transaction inherits the compatibility space\r
+        // from "this", thus the new transaction shares the compatibility space\r
+        // of the current transaction.\r
+        \r
+\r
+        Transaction child_rawtran = \r
+            ((readOnly) ?\r
+                accessmanager.getRawStore().startNestedReadOnlyUserTransaction(\r
+                    getLockSpace(), cm,\r
+                    AccessFactoryGlobals.NESTED_READONLY_USER_TRANS) :\r
+                accessmanager.getRawStore().startNestedUpdateUserTransaction(\r
+                    cm, AccessFactoryGlobals.NESTED_UPDATE_USER_TRANS));\r
+\r
+        RAMTransaction rt   = \r
+            new RAMTransaction(accessmanager, child_rawtran, this);\r
+\r
+        RAMTransactionContext rtc   = \r
+                       new RAMTransactionContext(\r
+                cm, \r
+                AccessFactoryGlobals.RAMXACT_CHILD_CONTEXT_ID,\r
+                rt, true /*abortAll */);\r
+\r
+        child_rawtran.setDefaultLockingPolicy(\r
+                accessmanager.getDefaultLockingPolicy());\r
+\r
+        /*\r
+        System.out.println("returning nested xact: " + rt + \r
+                "child_rawtran = " + child_rawtran); \r
+                */\r
+\r
+        return(rt);\r
+    }\r
+\r
+    /**\r
+     * Get the Transaction from the Transaction manager.\r
+     * <p>\r
+     * Access methods often need direct access to the "Transaction" - ie. the\r
+     * raw store transaction, so give access to it.\r
+     *\r
+        * @return The raw store transaction.\r
+     *\r
+     **/\r
+    public Transaction getRawStoreXact()\r
+       {\r
+        return(rawtran);\r
+    }\r
+\r
+\r
+    /**\r
+     * Do work necessary to maintain the current position in all the scans.\r
+     * <p>\r
+     * The latched page in the conglomerate "congomid" is changing, do\r
+     * whatever is necessary to maintain the current position of all the\r
+     * scans open in this transaction.\r
+     * <p>\r
+     * For some conglomerates this may be a no-op.\r
+     * <p>\r
+     *\r
+     * @param conglom   Conglomerate being changed.\r
+     * @param page      Page in the conglomerate being changed.\r
+     *\r
+        * @exception  StandardException  Standard exception policy.\r
+     **/\r
+    public void saveScanPositions(Conglomerate conglom, Page page)\r
+        throws StandardException\r
+    {\r
+        for (Iterator it = scanControllers.iterator(); it.hasNext(); )\r
+               {\r
+            Object o = it.next();\r
+\r
+            if (SanityManager.DEBUG)\r
+            {\r
+                // The following debugging code is here because the following \r
+                // (ScanManager) cast is occasionally causing a \r
+                // java.lang.ClassCastException.\r
+\r
+                if (!(o instanceof ScanManager))\r
+                {\r
+                    HeaderPrintWriter istream = Monitor.getStream();\r
+                    \r
+                    if (o == null)\r
+                        istream.println("next element was null\n");\r
+                    else\r
+                        istream.println("non ScanManager on list: " + o);\r
+\r
+                    istream.println(\r
+                        "Current list of open scans: " +  debugOpened());\r
+                }\r
+            }\r
+                       ScanManager sm = (ScanManager) o;\r
+            sm.savePosition(conglom, page);\r
+               }\r
+    }\r
+\r
+       public FileResource getFileHandler() {\r
+               return rawtran.getFileHandler();\r
+       }\r
+\r
+    /**\r
+     * Return an object that when used as the compatibility space,\r
+     * <strong>and</strong> the object returned when calling\r
+     * <code>getOwner()</code> on that object is used as group for a lock\r
+     * request, guarantees that the lock will be removed on a commit or an\r
+     * abort.\r
+     */\r
+    public CompatibilitySpace getLockSpace()\r
+    {\r
+               return rawtran.getCompatibilitySpace();\r
+       }\r
+\r
+    /**\r
+     * Get string id of the transaction.\r
+     * <p>\r
+     * This transaction "name" will be the same id which is returned in\r
+     * the TransactionInfo information, used by the lock and transaction\r
+     * vti's to identify transactions.\r
+     * <p>\r
+     * Although implementation specific, the transaction id is usually a number\r
+     * which is bumped every time a commit or abort is issued.\r
+     * <p>\r
+     * For now return the toString() method, which does what we want.  Later\r
+     * if that is not good enough we can add public raw tran interfaces to\r
+     * get exactly what we want.\r
+     *\r
+        * @return The a string which identifies the transaction.  \r
+     **/\r
+    public String getTransactionIdString()\r
+    {\r
+        return(rawtran.toString());\r
+    }\r
+\r
+\r
+    /**\r
+     * Get string id of the transaction that would be when the Transaction\r
+        * is IN active state.\r
+     **/\r
+    public String getActiveStateTxIdString()\r
+    {\r
+               return(rawtran.getActiveStateTxIdString());\r
+       }\r
+\r
+\r
+    public String toString()\r
+    {\r
+        String str = null;\r
+\r
+        if (SanityManager.DEBUG)\r
+        {\r
+            str = "rawtran = " + rawtran;\r
+        }\r
+        return(str);\r
+    }\r
+}\r