Adding JMCR-Stable version
[Benchmarks_CSolver.git] / JMCR-Stable / real-world application / MyDerby-10.3 / java / engine / org / apache / derby / impl / store / raw / xact / XactFactory.java
diff --git a/JMCR-Stable/real-world application/MyDerby-10.3/java/engine/org/apache/derby/impl/store/raw/xact/XactFactory.java b/JMCR-Stable/real-world application/MyDerby-10.3/java/engine/org/apache/derby/impl/store/raw/xact/XactFactory.java
new file mode 100644 (file)
index 0000000..8960094
--- /dev/null
@@ -0,0 +1,1160 @@
+/*\r
+\r
+   Derby - Class org.apache.derby.impl.store.raw.xact.XactFactory\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.raw.xact;\r
+\r
+import org.apache.derby.iapi.reference.Property;\r
+import org.apache.derby.iapi.reference.SQLState;\r
+\r
+import org.apache.derby.iapi.services.context.ContextService;\r
+import org.apache.derby.iapi.services.context.ContextManager;\r
+import org.apache.derby.iapi.services.daemon.DaemonService;\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.locks.LockFactory;\r
+import org.apache.derby.iapi.services.monitor.ModuleControl;\r
+import org.apache.derby.iapi.services.monitor.ModuleSupportable;\r
+import org.apache.derby.iapi.services.monitor.Monitor;\r
+import org.apache.derby.iapi.services.sanity.SanityManager;\r
+import org.apache.derby.iapi.services.io.Formatable;\r
+import org.apache.derby.iapi.services.io.FormatIdUtil;\r
+import org.apache.derby.iapi.services.uuid.UUIDFactory;\r
+import org.apache.derby.catalog.UUID;\r
+\r
+import org.apache.derby.iapi.store.access.AccessFactoryGlobals;\r
+import org.apache.derby.iapi.store.access.TransactionController;\r
+import org.apache.derby.iapi.store.access.TransactionInfo;\r
+\r
+import org.apache.derby.iapi.store.access.AccessFactory;\r
+\r
+import org.apache.derby.iapi.store.access.xa.XAResourceManager;\r
+\r
+import org.apache.derby.iapi.store.raw.LockingPolicy;\r
+import org.apache.derby.iapi.store.raw.GlobalTransactionId;\r
+import org.apache.derby.iapi.store.raw.RawStoreFactory;\r
+import org.apache.derby.iapi.store.raw.Transaction;\r
+\r
+import org.apache.derby.iapi.store.raw.data.DataFactory;\r
+\r
+import org.apache.derby.iapi.store.raw.log.LogFactory;\r
+import org.apache.derby.iapi.store.raw.log.LogInstant;\r
+\r
+import org.apache.derby.iapi.store.raw.xact.RawTransaction;\r
+import org.apache.derby.iapi.store.raw.xact.TransactionFactory;\r
+import org.apache.derby.iapi.store.raw.xact.TransactionId;\r
+import org.apache.derby.impl.store.raw.xact.XactXAResourceManager;\r
+\r
+import org.apache.derby.iapi.types.DataValueFactory;\r
+\r
+import org.apache.derby.iapi.error.StandardException;\r
+\r
+\r
+import java.util.Enumeration;\r
+import java.util.Properties;\r
+import java.util.Hashtable;\r
+\r
+public class XactFactory implements TransactionFactory, ModuleControl, ModuleSupportable\r
+{\r
+       protected static final String USER_CONTEXT_ID        = "UserTransaction";\r
+       protected static final String NESTED_READONLY_USER_CONTEXT_ID = \r
+        "NestedRawReadOnlyUserTransaction";\r
+       protected static final String NESTED_UPDATE_USER_CONTEXT_ID = \r
+        "NestedRawUpdateUserTransaction";\r
+       protected static final String INTERNAL_CONTEXT_ID    = "InternalTransaction";\r
+       protected static final String NTT_CONTEXT_ID         = "NestedTransaction";\r
+\r
+       /*\r
+       ** Fields\r
+       */\r
+\r
+       protected DaemonService rawStoreDaemon;\r
+\r
+       private   UUIDFactory           uuidFactory;\r
+       protected ContextService                contextFactory;\r
+       protected LockFactory           lockFactory;\r
+       protected LogFactory            logFactory;\r
+       protected DataFactory           dataFactory;\r
+       protected DataValueFactory      dataValueFactory;\r
+       protected RawStoreFactory       rawStoreFactory;\r
+\r
+       public TransactionTable ttab;\r
+       private long    tranId;\r
+       private LockingPolicy[][] lockingPolicies = new LockingPolicy[3][6];\r
+\r
+       private boolean inCreateNoLog = false;  // creating database, no logging\r
+\r
+       private   XAResourceManager xa_resource;\r
+\r
+       private Object   backupSemaphore = new Object();\r
+       private long     backupBlockingOperations = 0;\r
+       private boolean  inBackup = false;\r
+\r
+       /*\r
+       ** Constructor\r
+       */\r
+\r
+       public XactFactory() {\r
+               super();\r
+       }\r
+\r
+       /*\r
+       ** Methods of ModuleControl\r
+       */\r
+       public boolean canSupport(Properties startParams) {\r
+               return true;\r
+       }\r
+\r
+       public void     boot(boolean create, Properties properties)\r
+               throws StandardException\r
+       {\r
+\r
+               uuidFactory = Monitor.getMonitor().getUUIDFactory();\r
+\r
+        /*\r
+        dataValueFactory =  (DataValueFactory)\r
+            Monitor.findServiceModule(\r
+                this,\r
+                org.apache.derby.iapi.reference.ClassName.DataValueFactory);\r
+        */\r
+            // if datafactory has not been booted yet, try now.  This can\r
+            // happen in the unit tests.  Usually it is booted before store\r
+            // booting is called.\r
+            dataValueFactory = (DataValueFactory) \r
+                Monitor.bootServiceModule(\r
+                    create, \r
+                    this,\r
+                    org.apache.derby.iapi.reference.ClassName.DataValueFactory, \r
+                    properties);\r
+               \r
+\r
+               contextFactory = ContextService.getFactory();\r
+\r
+               lockFactory = \r
+            (LockFactory) Monitor.bootServiceModule(false, this,\r
+                               org.apache.derby.iapi.reference.Module.LockFactory, properties);\r
+\r
+               \r
+        // adding entries to locking policy table which means we support that\r
+        // level of concurrency.\r
+               lockingPolicies[LockingPolicy.MODE_NONE]\r
+                       [TransactionController.ISOLATION_NOLOCK] =\r
+                            new NoLocking();\r
+\r
+               lockingPolicies[LockingPolicy.MODE_RECORD]\r
+                       [TransactionController.ISOLATION_NOLOCK] =\r
+                            new NoLocking();\r
+               lockingPolicies[LockingPolicy.MODE_RECORD]\r
+                       [TransactionController.ISOLATION_READ_UNCOMMITTED] =\r
+                            new RowLocking1(lockFactory);\r
+           lockingPolicies[LockingPolicy.MODE_RECORD]\r
+                       [TransactionController.ISOLATION_READ_COMMITTED] =\r
+                            new RowLocking2(lockFactory);\r
+           lockingPolicies[LockingPolicy.MODE_RECORD]\r
+                       [TransactionController.ISOLATION_READ_COMMITTED_NOHOLDLOCK] =\r
+                            new RowLocking2nohold(lockFactory);\r
+           lockingPolicies[LockingPolicy.MODE_RECORD]\r
+                       [TransactionController.ISOLATION_REPEATABLE_READ] =\r
+                            new RowLockingRR(lockFactory);\r
+           lockingPolicies[LockingPolicy.MODE_RECORD]\r
+                       [TransactionController.ISOLATION_SERIALIZABLE] =\r
+                            new RowLocking3(lockFactory);\r
+\r
+               lockingPolicies[LockingPolicy.MODE_CONTAINER]\r
+                       [TransactionController.ISOLATION_NOLOCK] =\r
+                            new NoLocking();\r
+\r
+        // note that current implementation of read uncommitted still gets\r
+        // container and container intent locks to prevent concurrent ddl.  Thus\r
+        // the read uncommitted containerlocking implementation is the same as\r
+        // the read committed implementation.  Future customer requests may \r
+        // force us to change this - we will then have to figure out how to\r
+        // handle a table being dropped while a read uncommitted scanner is\r
+        // reading it - currently we just block that from happening.\r
+               lockingPolicies[LockingPolicy.MODE_CONTAINER]\r
+                       [TransactionController.ISOLATION_READ_UNCOMMITTED] =\r
+                            new ContainerLocking2(lockFactory);\r
+           lockingPolicies[LockingPolicy.MODE_CONTAINER]\r
+                       [TransactionController.ISOLATION_READ_COMMITTED] =\r
+                            new ContainerLocking2(lockFactory);\r
+           lockingPolicies[LockingPolicy.MODE_CONTAINER]\r
+                       [TransactionController.ISOLATION_READ_COMMITTED_NOHOLDLOCK] =\r
+                            new ContainerLocking2(lockFactory);\r
+           lockingPolicies[LockingPolicy.MODE_CONTAINER]\r
+                       [TransactionController.ISOLATION_REPEATABLE_READ] =\r
+                            new ContainerLocking3(lockFactory);\r
+           lockingPolicies[LockingPolicy.MODE_CONTAINER]\r
+                       [TransactionController.ISOLATION_SERIALIZABLE] =\r
+                            new ContainerLocking3(lockFactory);\r
+\r
+\r
+               if (create)\r
+               {\r
+                       ttab = new TransactionTable();\r
+\r
+                       String noLog =\r
+                               properties.getProperty(Property.CREATE_WITH_NO_LOG);\r
+\r
+                       inCreateNoLog = (noLog != null && Boolean.valueOf(noLog).booleanValue());\r
+\r
+               }\r
+       }\r
+\r
+       public void     stop() {\r
+\r
+               if (rawStoreDaemon != null)\r
+                       rawStoreDaemon.stop();\r
+\r
+       }\r
+\r
+       /*\r
+       ** Methods of TransactionFactory\r
+       */\r
+\r
+       /**\r
+               Get the LockFactory to use with this store.\r
+       */\r
+       public LockFactory getLockFactory() {\r
+               return lockFactory;\r
+       }\r
+\r
+\r
+       /**\r
+               Database creation finished\r
+               @exception StandardException standard Derby error policy\r
+       */\r
+       public void createFinished() throws StandardException\r
+       {\r
+               if (!inCreateNoLog) \r
+        {\r
+            throw StandardException.newException(SQLState.XACT_CREATE_NO_LOG);\r
+        }\r
+\r
+               // make sure there is no active update transaction\r
+               if (ttab.hasActiveUpdateTransaction())\r
+        {\r
+            throw StandardException.newException(SQLState.XACT_CREATE_NO_LOG);\r
+        }\r
+\r
+               inCreateNoLog = false;\r
+       }\r
+\r
+    /**\r
+     * Common work done to create local or global transactions.\r
+     *\r
+     * @param rsf    the raw store factory creating this xact.\r
+     * @param cm     the current context manager to associate the xact with.\r
+     * @param compatibilitySpace \r
+     *               if null, use the transaction being created, else if \r
+     *               non-null use this compatibilitySpace.\r
+     *\r
+        * @exception  StandardException  Standard exception policy.\r
+     **/\r
+       private RawTransaction startCommonTransaction(\r
+    RawStoreFactory rsf,\r
+    ContextManager  cm,\r
+    boolean         readOnly,\r
+    CompatibilitySpace compatibilitySpace,\r
+    String          xact_context_id,\r
+    String          transName,\r
+    boolean         excludeMe)\r
+        throws StandardException\r
+    {\r
+\r
+               if (SanityManager.DEBUG)\r
+               {\r
+                       if (rawStoreFactory != null)\r
+                               SanityManager.ASSERT(\r
+                    rawStoreFactory == rsf, "raw store factory different");\r
+\r
+                               SanityManager.ASSERT(\r
+                    cm == contextFactory.getCurrentContextManager());\r
+               }\r
+\r
+               Xact xact = \r
+            new Xact(\r
+                this, logFactory, dataFactory, dataValueFactory, \r
+                readOnly, compatibilitySpace);\r
+\r
+        xact.setTransName(transName);\r
+               pushTransactionContext(cm, xact_context_id, xact,\r
+                                                          false /* abortAll */,\r
+                                                          rsf,\r
+                                                          excludeMe /* excludeMe during quiesce state */);\r
+               return xact;\r
+       }\r
+\r
+       public RawTransaction startTransaction(\r
+    RawStoreFactory rsf,\r
+    ContextManager cm,\r
+    String transName)\r
+        throws StandardException\r
+    {\r
+        return(startCommonTransaction(\r
+                rsf, cm, false, null, USER_CONTEXT_ID, transName, true));\r
+       }\r
+\r
+       public RawTransaction startNestedReadOnlyUserTransaction(\r
+    RawStoreFactory rsf,\r
+    CompatibilitySpace compatibilitySpace,\r
+    ContextManager  cm,\r
+    String          transName)\r
+        throws StandardException\r
+    {\r
+        return(startCommonTransaction(\r
+            rsf, cm, true, compatibilitySpace, \r
+            NESTED_READONLY_USER_CONTEXT_ID, transName, false));\r
+       }\r
+\r
+       public RawTransaction startNestedUpdateUserTransaction(\r
+    RawStoreFactory rsf,\r
+    ContextManager  cm,\r
+    String          transName)\r
+        throws StandardException\r
+    {\r
+        return(startCommonTransaction(\r
+            rsf, cm, false, null, \r
+            NESTED_UPDATE_USER_CONTEXT_ID, transName, true));\r
+       }\r
+\r
+       public RawTransaction startGlobalTransaction(\r
+    RawStoreFactory rsf,\r
+    ContextManager  cm,\r
+    int             format_id,\r
+    byte[]          global_id,\r
+    byte[]          branch_id)\r
+        throws StandardException\r
+    {\r
+        GlobalXactId gid = new GlobalXactId(format_id, global_id, branch_id);\r
+\r
+        if (ttab.findTransactionContextByGlobalId(gid) != null)\r
+        {\r
+            throw StandardException.newException(SQLState.STORE_XA_XAER_DUPID);\r
+        }\r
+\r
+        RawTransaction xact = \r
+            startCommonTransaction(\r
+                rsf, cm, false, null, \r
+                USER_CONTEXT_ID, AccessFactoryGlobals.USER_TRANS_NAME, true);\r
+\r
+        xact.setTransactionId(gid, xact.getId());\r
+\r
+        return(xact);\r
+       }\r
+\r
+\r
+\r
+       public RawTransaction findUserTransaction(\r
+    RawStoreFactory rsf,\r
+    ContextManager  contextMgr,\r
+    String transName)\r
+                throws StandardException\r
+       {\r
+               if (SanityManager.DEBUG)\r
+               {\r
+                       SanityManager.ASSERT(\r
+                contextMgr == contextFactory.getCurrentContextManager(),\r
+                "passed in context mgr not the same as current context mgr");\r
+\r
+                       if (rawStoreFactory != null)\r
+                               SanityManager.ASSERT(\r
+                    rawStoreFactory == rsf, "raw store factory different");\r
+               }\r
+\r
+               XactContext xc = (XactContext)contextMgr.getContext(USER_CONTEXT_ID);\r
+               if (xc == null)\r
+                       return startTransaction(rsf, contextMgr, transName);\r
+               else\r
+                       return xc.getTransaction();\r
+       }\r
+\r
+\r
+       public RawTransaction startNestedTopTransaction(RawStoreFactory rsf, ContextManager cm)\r
+        throws StandardException\r
+    {\r
+\r
+               if (SanityManager.DEBUG)\r
+               {\r
+                       if (rawStoreFactory != null)\r
+                               SanityManager.ASSERT(\r
+                    rawStoreFactory == rsf, "raw store factory different");\r
+               }\r
+\r
+               Xact xact = \r
+            new Xact(\r
+                this, logFactory, dataFactory, dataValueFactory, false, null);\r
+\r
+               // hold latches etc. past commit in NTT\r
+               xact.setPostComplete();\r
+               pushTransactionContext(cm, NTT_CONTEXT_ID, xact, \r
+                                                          true /* abortAll */,\r
+                                                          rsf, \r
+                                                          true /* excludeMe during quiesce state*/);\r
+               return xact;\r
+       }\r
+\r
+       public RawTransaction startInternalTransaction(RawStoreFactory rsf, ContextManager cm) \r
+        throws StandardException \r
+    {\r
+               if (SanityManager.DEBUG)\r
+               {\r
+                       if (rawStoreFactory != null)\r
+                               SanityManager.ASSERT(\r
+                    rawStoreFactory == rsf, "raw store factory different");\r
+               }\r
+\r
+\r
+               Xact xact = \r
+            new InternalXact(this, logFactory, dataFactory, dataValueFactory);\r
+\r
+               pushTransactionContext(cm, INTERNAL_CONTEXT_ID, xact, \r
+                                                          true /* abortAll*/,\r
+                                                          rsf,\r
+                                                          true /* excludeMe during quiesce state */);\r
+               return xact;\r
+       }\r
+\r
+       /*\r
+        * the following TransactionFactory methods are to support recovery and\r
+        * should only be used by recovery!\r
+        */\r
+\r
+       /**\r
+               Find the TransactionTableEntry with the given ID and make the passed in\r
+               transaction assume the identity and properties of that\r
+               TransactionTableEntry.\r
+               Used in recovery only.\r
+       */\r
+       public boolean findTransaction(TransactionId id,  RawTransaction tran)\r
+       {\r
+               return ttab.findAndAssumeTransaction(id, tran);\r
+       }\r
+\r
+\r
+       /**\r
+               Rollback all active transactions that has updated the raw store.\r
+               Use the recovery Transaction that is passed in to do all the work.\r
+               Used in recovery only.\r
+\r
+               <P>\r
+               Transactions are rolled back in the following order:\r
+               <OL>\r
+               <LI>internal transactions in reversed beginXact chronological order,\r
+               <LI>all other transactions in reversed beginXact chronological order,\r
+               </NL>\r
+\r
+               @param recoveryTransaction use this transaction to do all the user \r
+                                   transaction work\r
+\r
+               @exception StandardException any exception thrown during rollback\r
+       */\r
+       public void rollbackAllTransactions(\r
+    RawTransaction  recoveryTransaction,\r
+    RawStoreFactory rsf) \r
+        throws StandardException\r
+       {\r
+               if (SanityManager.DEBUG)\r
+               {\r
+                       if (rawStoreFactory != null)\r
+                               SanityManager.ASSERT(\r
+                    rawStoreFactory == rsf, "raw store factory different");\r
+\r
+                       SanityManager.ASSERT(\r
+                recoveryTransaction != null, "recovery transaction null");\r
+               }\r
+\r
+               int irbcount = 0;\r
+\r
+               // First undo internal transactions if there is any\r
+               if (ttab.hasRollbackFirstTransaction())\r
+               {\r
+                       RawTransaction internalTransaction = startInternalTransaction(rsf,\r
+                               recoveryTransaction.getContextManager());\r
+\r
+                       // make this transaction be aware that it is being used by recovery\r
+                       internalTransaction.recoveryTransaction();\r
+\r
+                       if (SanityManager.DEBUG)\r
+                               SanityManager.ASSERT(\r
+                    internalTransaction.handlesPostTerminationWork() == false,\r
+                    "internal recovery xact handles post termination work");\r
+\r
+                       while(ttab.getMostRecentRollbackFirstTransaction(\r
+                                                internalTransaction))\r
+                       {\r
+                               irbcount++;\r
+                               internalTransaction.abort();\r
+                       }\r
+\r
+                       internalTransaction.close();\r
+               }\r
+\r
+               if (SanityManager.DEBUG)\r
+               {\r
+                       SanityManager.ASSERT(\r
+                ttab.hasRollbackFirstTransaction() == false,\r
+                "cant rollback user xacts with existing active internal xacts");\r
+               }\r
+\r
+               int rbcount = 0;\r
+\r
+               // recoveryTransacion assumes the identity of the most recent xact\r
+               while(ttab.getMostRecentTransactionForRollback(recoveryTransaction))\r
+               {\r
+                       if (SanityManager.DEBUG)\r
+            {\r
+                               SanityManager.ASSERT(\r
+                    recoveryTransaction.handlesPostTerminationWork() == false,\r
+                    "recovery transaction handles post termination work");\r
+            }\r
+\r
+                       rbcount++;\r
+                       recoveryTransaction.abort();\r
+               }\r
+\r
+               if (SanityManager.DEBUG)\r
+               {\r
+                       if (rbcount > 0 || irbcount > 0)\r
+                       {\r
+                               // RESOLVE: put this in the log trace\r
+                               //      System.out.println(\r
+                //         "Recovery rolled back " + irbcount + \r
+                //         " internal transactions,"\r
+                               //                      + rbcount + " user transactions");\r
+                       }\r
+               }\r
+\r
+       }\r
+\r
+\r
+       /**\r
+        Run through all prepared transactions known to this factory \r
+        and restore their state such that they remain after recovery, and\r
+        can be found and handled by a XA transaction manager.  This includes\r
+        creating a context manager for each, pushing a xact context, and\r
+        reclaiming update locks on all data changed by the transaction.\r
+\r
+        Expected to be called just after the redo and undo recovery loops, \r
+        where the transaction table should be empty except for prepared\r
+        xacts.\r
+\r
+               Used only in recovery.\r
+\r
+               @exception StandardException Derby Standard Error policy\r
+       */\r
+       public void handlePreparedXacts(\r
+    RawStoreFactory rsf)\r
+        throws StandardException\r
+       {\r
+               if (SanityManager.DEBUG)\r
+               {\r
+\r
+                       if (rawStoreFactory != null)\r
+                               SanityManager.ASSERT(\r
+                    rawStoreFactory == rsf, "raw store factory different");\r
+               }\r
+\r
+        int prepared_count = 0;\r
+\r
+               if (ttab.hasPreparedRecoveredXact())\r
+               {\r
+            // if there any prepared xacts \r
+\r
+            // At this point recovery has used one context and one transaction\r
+            // to deal with all transactions.  Prepared transactions are to\r
+            // be left in the transaction table, but the must have real and\r
+            // separate CM's and transactions associated with them.\r
+\r
+            // save old context.  Errors may go to funky contexts (the new\r
+            // context we created to bring the prepared transaction into the\r
+            // real world after recovery) after we switch contexts, but any \r
+            // error we get at this point is going to shut down the db.\r
+\r
+            while (true)\r
+            {\r
+                // allocate new context and associate new xact with it.\r
+                ContextManager cm      = contextFactory.newContextManager();\r
+                contextFactory.setCurrentContextManager(cm);\r
+\r
+                               try {\r
+                RawTransaction rawtran = \r
+                    startTransaction(\r
+                        rawStoreFactory, cm, \r
+                        AccessFactoryGlobals.USER_TRANS_NAME);\r
+\r
+                if (ttab.getMostRecentPreparedRecoveredXact(rawtran))\r
+                {\r
+                    // found a prepared xact.  The reprepare() call will \r
+                    // accumulate locks, and change the transaction table entry\r
+                    // to not be "in-recovery" so that it won't show up again.\r
+                    rawtran.reprepare();\r
+\r
+                    if (SanityManager.DEBUG)\r
+                        prepared_count++;\r
+                }\r
+                else\r
+                {\r
+                    // get rid of last transaction allocated.\r
+                    rawtran.destroy();\r
+                    break;\r
+                }\r
+                               }\r
+                               finally\r
+                               {\r
+                                        contextFactory.resetCurrentContextManager(cm);\r
+                               }\r
+            }\r
+\r
+               }\r
+\r
+               if (SanityManager.DEBUG)\r
+               {\r
+            // RESOLVE - need to only do this under a debug flag.\r
+            // SanityManager.DEBUG_PRINT("",\r
+            // "Recovery re-prepared " + prepared_count + " xa transactions.");\r
+               }\r
+       }\r
+\r
+\r
+       /**\r
+               Get the earliest log instant that is still active, ie, the first log\r
+               record logged by the earliest transaction that is still active.\r
+               <BR>\r
+               The logging system must guarentee that the transaction table is\r
+               populated in the order transactions are started.\r
+               Used in recovery only.\r
+       */\r
+\r
+       public LogInstant firstUpdateInstant()\r
+       {\r
+               return ttab.getFirstLogInstant();\r
+       }\r
+\r
+       /*\r
+       ** Methods of Corruptable\r
+       */\r
+\r
+       /**\r
+               Really this is just a convience routine for callers that might not\r
+               have access to a log factory.\r
+       */\r
+       public StandardException markCorrupt(StandardException originalError) {\r
+               logFactory.markCorrupt(originalError);\r
+               return originalError;\r
+       }\r
+\r
+       /*\r
+       **              Implementation specific methods.\r
+       */\r
+\r
+       public void setNewTransactionId(TransactionId oldxid, Xact t)\r
+       {\r
+               XactId xid;\r
+               boolean excludeMe = true; // by default\r
+\r
+               if (oldxid != null)\r
+                       excludeMe = remove(oldxid);\r
+\r
+               synchronized(this)\r
+               {\r
+                       xid = new XactId(tranId++);\r
+               }\r
+\r
+               t.setTransactionId(t.getGlobalId(), xid);\r
+\r
+               // RESOLVE: How does a real global xact id get set?\r
+\r
+               // If we got rid of the oldxid, that means this transaction object has\r
+               // merely committed and starting the next transaction with the same\r
+               // xact object.  In that case, the transaction context will remain the\r
+               // same and won't be pushed.  We need to add this transaction with the\r
+               // new id back into the transaction table.  If we did not get rid of\r
+               // the old oldxid, that means this is a brand new transaction being\r
+               // created.  The pushTransactionContext call will add it to the\r
+               // transaction table with the appropriate flags\r
+               if (oldxid != null)\r
+                       add(t, excludeMe);\r
+       }\r
+\r
+       /**\r
+       **      Set the shortTranId, this is called by the log factory after recovery\r
+       */\r
+       public void resetTranId()\r
+       {\r
+               XactId xid = (XactId)ttab.largestUpdateXactId();\r
+               if (xid != null)\r
+                       tranId = xid.getId() + 1;\r
+               else\r
+                       tranId = 1;\r
+       }\r
+\r
+\r
+       /**\r
+               Create a new RawTransaction, a context for it and push the context\r
+               onto the current context manager.  Then add the transacion to the\r
+               transaction table.\r
+\r
+               @param contextName the name of the transaction context\r
+               @param xact the Transaction object\r
+               @param abortAll if true, then any error will abort the whole\r
+               transaction.  Otherwise, let XactContext.cleanupOnError decide what to\r
+               do\r
+               @param rsf the raw store factory\r
+               @param excludeMe during systeme quiesce, i.e., this transaction should\r
+               not be allowed to be active during a quiesce state.\r
+\r
+\r
+               @exception StandardException Standard Derby error policy\r
+\r
+       */\r
+       protected void pushTransactionContext(ContextManager cm, String contextName, \r
+                                                                                 Xact xact,\r
+                                                                                 boolean abortAll, \r
+                                                                                 RawStoreFactory rsf,\r
+                                                                                 boolean excludeMe)\r
+                throws StandardException \r
+       {\r
+               if (cm.getContext(contextName) != null) \r
+        {\r
+            throw StandardException.newException(\r
+                    SQLState.XACT_TRANSACTION_ACTIVE);\r
+        }\r
+               \r
+               XactContext xc = new XactContext(cm, contextName, xact, abortAll, rsf);\r
+\r
+               // this transaction is now added to the transaction table.\r
+               // This will cause an idle transaction to take on an identity, which is\r
+               // unfortunate.  The reason why we have to add the transaction to the\r
+               // table right now is because the transaction table is used to bring\r
+               // system  to quisce state to  regulate who can go active during quiesce\r
+               // state, and if we add the transaction\r
+               // when it goes active, then there is a window where this transaction\r
+               // can sneak in.  The transaction table itself does not keep track of\r
+               // whether transactions can be started or not because quiesce related\r
+               // transactions can start after all other user\r
+               // transactions are excluded.  \r
+               // RESOLVE: need to put more thought on the overall requirement and\r
+               // design of the transaction table that satisfies the need of all the\r
+               // clients, namely: checkpoint, recovery, quiesce mode, transaction table.\r
+\r
+               add(xact, excludeMe);\r
+\r
+       }\r
+\r
+       /**\r
+               Add a transaction to the list of transactions that has updated\r
+               the raw store.  \r
+               <P>\r
+               This is called underneath the BeginXact log operation's doMe method.\r
+               The logging system must guarentee that transactions are added in the\r
+               true order they are started, as defined by the order of beginXact log\r
+               record in the log.\r
+       */\r
+       protected void addUpdateTransaction(\r
+    TransactionId   id, \r
+    RawTransaction  t, \r
+    int             transactionStatus)\r
+       {\r
+               if (SanityManager.DEBUG)\r
+                       SanityManager.ASSERT(\r
+                id != null, "addding update transaction with null id");\r
+\r
+               ttab.addUpdateTransaction(id, t, transactionStatus);\r
+       }\r
+\r
+       /**\r
+               Remove a transaction from the list of transactions that has updated the\r
+               raw store.\r
+       */\r
+       protected void removeUpdateTransaction(TransactionId id)\r
+       {\r
+               if (SanityManager.DEBUG)\r
+                       SanityManager.ASSERT(\r
+                id != null, "remove update transaction with null id");\r
+\r
+               ttab.removeUpdateTransaction(id);\r
+       } \r
+\r
+       /**\r
+        Change state of transaction to prepared.  Used by recovery to update\r
+        the transaction table entry to prepared state.\r
+       */\r
+       protected void prepareTransaction(TransactionId id)\r
+       {\r
+               if (SanityManager.DEBUG)\r
+                       SanityManager.ASSERT(\r
+                id != null, "prepare transaction with null id");\r
+\r
+               ttab.prepareTransaction(id);\r
+       } \r
+\r
+       /**\r
+               Submit this post commit work to the post commit daemon\r
+       */\r
+       public boolean submitPostCommitWork(Serviceable work)\r
+       {\r
+               if (rawStoreDaemon != null)\r
+                       return rawStoreDaemon.enqueue(work, work.serviceASAP());\r
+               return false;\r
+       }\r
+\r
+       public void setRawStoreFactory(RawStoreFactory rsf) throws StandardException \r
+       {\r
+               if (SanityManager.DEBUG)\r
+               {\r
+                       SanityManager.ASSERT(rsf != null, "rawStoreFactory == null");\r
+               }\r
+\r
+               rawStoreFactory = rsf;\r
+\r
+               // no need to remember raw store factory, \r
+               // just remember which daemon to use\r
+               rawStoreDaemon = rsf.getDaemon();\r
+\r
+               // now its ok to look for the log and data factory\r
+               // log factory is booted by the data factory\r
+               logFactory = (LogFactory) Monitor.findServiceModule(this, rsf.getLogFactoryModule());\r
+\r
+               // data factory is booted by the raw store implementation\r
+               dataFactory = (DataFactory) Monitor.findServiceModule(this, rsf.getDataFactoryModule());\r
+       }\r
+\r
+       /**\r
+               Returns true if there is no in flight updating tranasaction.\r
+               Caller must be aware that if there is no other mechanism to stop\r
+               transactions from starting and ending, then this information is\r
+               outdated as soon as it is reported.\r
+\r
+               Only call this function in special times - e.g, during recovery\r
+       */\r
+       public boolean noActiveUpdateTransaction()\r
+       {\r
+               return (ttab.hasActiveUpdateTransaction() == false);\r
+       }\r
+\r
+\r
+    /**\r
+     * Check if there are any prepared transanctions in the \r
+     * transaction table. \r
+     *\r
+     * Caller must be aware that if there is no other mechanism to stop\r
+     * transactions from starting and ending, then this information is\r
+     * outdated as soon as it is reported.\r
+     *\r
+     * @return     <tt>true</tt> if there are prepared \r
+     *              transactions in the transaction table,\r
+     *              <tt>false</tt> otherwise.\r
+     */\r
+       public boolean hasPreparedXact()\r
+       {\r
+               return (ttab.hasPreparedXact());\r
+       }\r
+\r
+\r
+\r
+       /**\r
+               remove the transaction Id an return false iff the transaction is found\r
+               in the table and it doesn't need exclusion from quiesce state\r
+        */\r
+       protected boolean remove(TransactionId xactId)\r
+       {\r
+               return ttab.remove(xactId);\r
+       }\r
+\r
+       protected void add(Xact xact, boolean excludeMe)\r
+       {\r
+               ttab.add(xact, excludeMe);\r
+       }\r
+\r
+\r
+       /**\r
+               Make a new UUID for whomever that wants it\r
+       */\r
+       public UUID makeNewUUID()\r
+       {\r
+               return uuidFactory.createUUID();\r
+       }\r
+\r
+       /**\r
+               Decide if a transaction of this contextId needs to flush the log when\r
+               it commits\r
+       */\r
+       public boolean flushLogOnCommit(String contextName)\r
+       {\r
+               //\r
+               // if this is a user transaction, flush the log\r
+               // if this is an internal or nested top transaction, do not\r
+               // flush, let it age out.\r
+               //\r
+               return (contextName == USER_CONTEXT_ID || \r
+                               contextName.equals(USER_CONTEXT_ID));\r
+       }\r
+\r
+\r
+       /**\r
+               Get a locking policy for a transaction.\r
+       */\r
+       final LockingPolicy getLockingPolicy(\r
+    int     mode, \r
+    int     isolation, \r
+    boolean stricterOk)\r
+    {\r
+\r
+               if (mode == LockingPolicy.MODE_NONE)\r
+                       isolation = TransactionController.ISOLATION_NOLOCK;\r
+\r
+               LockingPolicy policy = lockingPolicies[mode][isolation];\r
+\r
+               if ((policy != null) || (!stricterOk))\r
+                       return policy;\r
+\r
+               for (mode++; mode <= LockingPolicy.MODE_CONTAINER; mode++) \r
+        {\r
+                       for (int i = isolation; \r
+                 i <= TransactionController.ISOLATION_SERIALIZABLE; \r
+                 i++) \r
+            {\r
+                               policy = lockingPolicies[mode][i];\r
+                               if (policy != null)\r
+                                       return policy;\r
+                       }\r
+               }\r
+\r
+               return null;\r
+       }\r
+\r
+       /**\r
+               Return the transaction table to be logged with the checkpoint operation\r
+        */\r
+       public Formatable getTransactionTable()\r
+       {\r
+               return ttab;\r
+       }\r
+\r
+       /**\r
+               Use this transaction table, which is gotten from a checkpoint\r
+               operation.  Use ONLY during recovery.\r
+        */\r
+       public void useTransactionTable(Formatable transactionTable) \r
+                throws StandardException \r
+       {\r
+               if (ttab != null && transactionTable != null)\r
+        {\r
+            throw StandardException.newException(\r
+                    SQLState.XACT_TRANSACTION_TABLE_IN_USE);\r
+        }\r
+\r
+               if (ttab == null)\r
+               {\r
+                       if (transactionTable == null)\r
+                               ttab = new TransactionTable();\r
+                       else\r
+                       {\r
+                               if (SanityManager.DEBUG)\r
+                               {\r
+                                       if ((transactionTable instanceof TransactionTable) ==\r
+                                               false)\r
+                                       {\r
+                                               SanityManager.THROWASSERT(\r
+                                                       "using transaction table which is of class " + \r
+                                                       transactionTable.getClass().getName());\r
+                                       }\r
+                               }\r
+                               ttab = (TransactionTable)transactionTable;\r
+                       }\r
+               }\r
+               // else transactionTable must be null, if we already have a transaction\r
+               // table, no need to do anything\r
+       }\r
+\r
+       public TransactionInfo[] getTransactionInfo()\r
+       {\r
+               if (SanityManager.DEBUG)\r
+                       SanityManager.ASSERT(ttab != null, "transaction table is null");\r
+               return ttab.getTransactionInfo();\r
+       }\r
+\r
+\r
+       /**\r
+        * @return false, if the Database creation finished\r
+        */\r
+       public boolean inDatabaseCreation()\r
+       {\r
+               return inCreateNoLog;\r
+       }\r
+       \r
+       /**\r
+        * Return the module providing XAresource interface to the transaction \r
+     * table. \r
+     *\r
+        * @exception StandardException Standard Derby exception policy.\r
+        */\r
+       public /* XAResourceManager */ Object getXAResourceManager()\r
+        throws StandardException\r
+    {\r
+        if (xa_resource == null)\r
+            xa_resource = new XactXAResourceManager(rawStoreFactory, ttab);\r
+\r
+        return(xa_resource);\r
+    }\r
+\r
+\r
+    /**\r
+     * Block the online backup. Backup needs to be blocked while \r
+     * executing any unlogged operations or any opearation that \r
+     * prevents from  making a consistent backup.\r
+     * \r
+     * @param wait if <tt>true</tt>, waits until the backup \r
+     *             is blocked. \r
+     * @return     <tt>true</tt> if backup is blocked.\r
+     *                    <tt>false</tt> otherwise.\r
+     * @exception StandardException if interrupted while waiting for a \r
+     *           backup  to complete.\r
+     */\r
+       protected boolean blockBackup(boolean wait)\r
+        throws StandardException \r
+       {\r
+               synchronized(backupSemaphore) {\r
+            // do not allow backup blocking operations, if online backup is\r
+            // is in progress.\r
+                       if (inBackup) \r
+            {\r
+                if(wait) {\r
+                    while(inBackup) {\r
+                        try {\r
+                            backupSemaphore.wait();\r
+                        } catch (InterruptedException ie) {\r
+                            throw StandardException.interrupt(ie);\r
+                        }\r
+                    }\r
+                }else {\r
+                    return false;\r
+                }\r
+                       }\r
+\r
+            // not in online backup, allow backup blocking operations\r
+            backupBlockingOperations++;\r
+            return true;\r
+               }\r
+       }\r
+\r
+\r
+       /**\r
+     * Unblock the backup, a backup blocking operation finished. \r
+        */\r
+       protected void unblockBackup()\r
+       {\r
+               synchronized(backupSemaphore) {\r
+                       if (SanityManager.DEBUG)\r
+                               SanityManager.ASSERT(backupBlockingOperations > 0, \r
+                    "no backup blocking opeations in progress"); \r
+                       \r
+                       backupBlockingOperations--;\r
+\r
+                       if (inBackup) {\r
+                               // wake up the online backupthread\r
+                               backupSemaphore.notifyAll(); \r
+                       }\r
+               }\r
+       }\r
+\r
+       /**\r
+        * Checks if there are any backup blocking operations in progress and \r
+        * prevents new ones from starting until the backup is finished. \r
+        * If backup blocking operations are in progress and  <code> wait </code>\r
+        * parameter value is <tt>true</tt>, then it will wait for the current \r
+        * backup blocking operations to finish. \r
+        * \r
+        * A Consistent backup can not be made if there are any backup \r
+        * blocking operations (like unlogged operations) are in progress\r
+        *\r
+        * @param wait if <tt>true</tt>, waits for the current backup blocking \r
+        *             operation in progress to finish.\r
+        * @return     <tt>true</tt> if no backup blocking operations are in \r
+     *             progress\r
+        *             <tt>false</tt> otherwise.\r
+        * @exception StandardException if interrupted or a runtime exception occurs\r
+        */\r
+       public boolean blockBackupBlockingOperations(boolean wait) \r
+               throws StandardException \r
+       {\r
+               synchronized(backupSemaphore) {\r
+                       if (wait) {\r
+                               // set the inBackup state to true first to stop new backup\r
+                               // blocking operation from starting.\r
+                               inBackup= true;\r
+                               try     {\r
+                                       // wait for backup blocking operation in progress to finish\r
+                                       while(backupBlockingOperations > 0)\r
+                                       {\r
+                                               try     {\r
+                                                       backupSemaphore.wait();\r
+                                               }\r
+                                               catch (InterruptedException ie) {\r
+                                                       // make sure we are not stuck in the backup state \r
+                            // if we caught an interrupt exception and the \r
+                            // calling thread may not have a chance to clear \r
+                            // the in backup state.\r
+\r
+                                                       inBackup = false;\r
+                                                       backupSemaphore.notifyAll();\r
+                                                       throw StandardException.interrupt(ie);\r
+                                               }\r
+                                       }\r
+                               }\r
+                               catch (RuntimeException rte) {\r
+                                       // make sure we are not stuck in backup state if we\r
+                                       // caught a run time exception and the calling thread may \r
+                    // not have a chance to clear the in backup state.\r
+                                       inBackup= false;\r
+                                       backupSemaphore.notifyAll();\r
+                                       throw rte;              // rethrow run time exception\r
+                               }\r
+                       } else {\r
+                               // check if any backup blocking operations that are in  progress\r
+                               if (backupBlockingOperations == 0)\r
+                                       inBackup = true;\r
+                       }\r
+            \r
+               }\r
+\r
+        if (SanityManager.DEBUG) {\r
+            if (inBackup) {\r
+                SanityManager.ASSERT(backupBlockingOperations == 0 ,\r
+                                 "store is not in correct state for backup");\r
+            }\r
+        }\r
+\r
+               return inBackup;\r
+       }\r
+\r
+\r
+       /**\r
+        * Backup completed. Allow backup blocking operations. \r
+        */\r
+       public void unblockBackupBlockingOperations()\r
+       {\r
+               synchronized(backupSemaphore) {\r
+                       inBackup = false;\r
+                       backupSemaphore.notifyAll();\r
+               }\r
+       }\r
+       \r
+}\r