Adding JMCR-Stable version
[Benchmarks_CSolver.git] / JMCR-Stable / real-world application / MyDerby-10.3 / java / engine / org / apache / derby / iapi / services / context / ContextService.java
diff --git a/JMCR-Stable/real-world application/MyDerby-10.3/java/engine/org/apache/derby/iapi/services/context/ContextService.java b/JMCR-Stable/real-world application/MyDerby-10.3/java/engine/org/apache/derby/iapi/services/context/ContextService.java
new file mode 100644 (file)
index 0000000..fd2c005
--- /dev/null
@@ -0,0 +1,585 @@
+/*\r
+\r
+   Derby - Class org.apache.derby.iapi.services.context.ContextService\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.iapi.services.context;\r
+\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.stream.HeaderPrintWriter;\r
+\r
+import java.security.AccessController;\r
+import java.security.PrivilegedAction;\r
+import java.util.Hashtable;\r
+import java.util.Enumeration;\r
+\r
+import java.util.HashSet;\r
+import java.util.Iterator;\r
+\r
+/**\r
+       A set of static methods to supply easier access to contexts.\r
+*/\r
+public final class ContextService //OLD extends Hashtable\r
+{\r
+\r
+       private static ContextService factory;\r
+       private HeaderPrintWriter errorStream;\r
+\r
+       /**\r
+               Maintains a list of all the contexts that this thread has created\r
+               and/or used. The object stored in the thread local varys according\r
+               how this thread has been used and will be one of:\r
+\r
+               <UL>\r
+               <LI> null - the thread no affiliation with a context manager.\r
+\r
+               <LI> ContextManager - the current thread has used or is using\r
+            this context manager. If ContextManager.activeThread equals\r
+            the current thread then the thread is currently active with\r
+            the ContextManager. In this case ContextManager.activeCount\r
+            will be greater than zero and represent the level of nested\r
+            setCurrentContextmanager calls.\r
+            If ContextManager.activeThread is null then no other thread\r
+            is using the Contextmanager, if ContextManager.activeThread\r
+            is not-null and not equal to the current thread then some\r
+            other thread is using the context. It is assumed that\r
+            only a single thread can be using a ContextManager at any time\r
+            and this is enforced by synchronization outside the ContextManager.\r
+            E.g for JDBC connections, synchronization at the JDBC level.\r
+\r
+               <LI> java.util.Stack containing ContextManagers - the current\r
+        thread is actively using multiple different ContextManagers,\r
+        with nesting. All ContextManagers in the stack will have\r
+        activeThread set to the current thread, and their activeCount\r
+        set to -1. This is beacause nesting is soley represented by\r
+        the stack, with the current context manager on top of the stack.\r
+        This supports multiple levels of nesting across two stacks, e.g.\r
+        C1->C2->C2->C1->C2.\r
+               </UL>\r
+\r
+               This thread local is used to find the current context manager. Basically it provides\r
+               fast access to a list of candidate contexts. If one of the contexts has its activeThread\r
+               equal to the current thread then it is the current context manager.\r
+\r
+               If the thread has pushed multiple contexts (e.g. open a new non-nested Derby connection\r
+               from a server side method) then threadContextList will contain a Stack. The value for each cm\r
+               will be a push order, with higher numbers being more recently pushed.\r
+\r
+               To support the case where a single context manager is pushed twice (nested connection),\r
+               the context manager keeps track of the number of times it has been pushed (set). Note that\r
+               our synchronization requires that a single context can only be accessed by a single thread at a time.\r
+               In the JDBC layer this is enforced by the synchronization on the connection object.\r
+\r
+               <P>\r
+               There are two cases we are trying to optimise.\r
+               <UL>\r
+               <LI> Typical JDBC client program where there a Connection is always executed using a single thread.\r
+                       In this case this variable will contain the Connection's context manager \r
+               <LI> Typical application server pooled connection where a single thread may use a connection from a pool\r
+               for the lifetime of the request. In this case this variable will contain a  WeakReference.\r
+               </UL>\r
+        <BR>\r
+        Single thread for Connection exection.\r
+        <pre>\r
+        threadContextList.get() == cm\r
+        // while in JDBC engine code\r
+        cm.activeThread == Thread.currentThread();\r
+        cm.activeCount = 1;\r
+        </pre>\r
+        \r
+        <BR>\r
+        J2EE single thread for lifetime of execution.\r
+        <pre>\r
+        // thread executing request\r
+         threadContextList.get() == cm\r
+        // while in JDBC engine code\r
+        cm.activeThread == Thread.currentThread();\r
+        cm.activeCount = 1;\r
+        \r
+        // other threads that have recently executed\r
+        // the same connection can have\r
+        threadContextList.get() == cm\r
+        cm.activeThread != Thread.currentThread();\r
+       </pre>\r
+        \r
+        <BR>\r
+        Nested routine calls within single connection\r
+        <pre>\r
+        threadContextList.get() == cm\r
+        // Within server-side JDBC code in a\r
+        // function called from another function/procedure\r
+        // called from an applications's statement\r
+        // (three levels of nesting)\r
+        cm.activeThread == Thread.currentThread();\r
+        cm.activeCount = 3;         \r
+        </pre>\r
+        \r
+        <BR>\r
+        Nested routine calls with the inner routine\r
+        using a different connection to access a Derby database.\r
+        Note nesting of orignal Contextmanager cm is changed\r
+        from an activeCount of 2 to nesting within the stack\r
+        once multiple ContextManagers are involved.\r
+        <pre>\r
+        threadContextList.get() == stack {cm2,cm,cm}\r
+        cm.activeThread == Thread.currentThread();\r
+        cm.activeCount = -1; // nesting in stack\r
+        cm2.activeThread == Thread.currentThread();\r
+        cm2.activeCount = -1; // nesting in stack\r
+        </pre> \r
+        \r
+        <BR>\r
+        Nested multiple ContextManagers, the code supports\r
+        this, though it may not be possible currently\r
+        to have a stack like this from SQL/JDBC.\r
+        <pre>\r
+        threadContextList.get() == stack {cm3,cm2,cm,cm2,cm,cm}\r
+        cm.activeThread == Thread.currentThread();\r
+        cm.activeCount = -1; // nesting in stack\r
+        cm2.activeThread == Thread.currentThread();\r
+        cm2.activeCount = -1; // nesting in stack\r
+        cm3.activeThread == Thread.currentThread();\r
+        cm3.activeCount = -1; // nesting in stack\r
+        </pre>   \r
+       */\r
+       private ThreadLocal threadContextList = new ThreadLocal();\r
+\r
+    /**\r
+     * Collection of all ContextManagers that are open\r
+     * in the complete Derby system. A ContextManager is\r
+     * added when it is created with newContextManager and\r
+     * removed when the session is closed.\r
+     * \r
+     * @see #newContextManager()\r
+     * @see SystemContext#cleanupOnError(Throwable)\r
+     */\r
+       private HashSet allContexts;\r
+\r
+    /**\r
+     * Create a new ContextService for a Derby system.\r
+     * Only a single system is active at any time.\r
+     *\r
+     */\r
+       public ContextService() {\r
+\r
+               // find the error stream\r
+               errorStream = Monitor.getStream();              \r
+\r
+               ContextService.factory = this;\r
+\r
+               allContexts = new HashSet();\r
+\r
+       }\r
+\r
+       /**\r
+               So it can be given to us and taken away...\r
+        */\r
+       public static void stop() {\r
+               // For some unknown reason, the ContextManager and\r
+               // ContextService objects will not be garbage collected\r
+               // without the next two lines.\r
+        ContextService fact = ContextService.factory;\r
+        if (fact != null) {\r
+            synchronized (fact) {\r
+                fact.allContexts = null;\r
+                fact.threadContextList = null;\r
+                ContextService.factory = null;\r
+            }\r
+        }\r
+       }\r
+\r
+       public static ContextService getFactory() {\r
+               ContextService csf = factory;\r
+\r
+               if (csf == null)\r
+                       throw new ShutdownException();\r
+               return csf;\r
+       }\r
+       /**\r
+               Find the context with the given name in the context service factory\r
+               loaded for the system.\r
+\r
+               @return The requested context, null if it doesn't exist.\r
+       */\r
+       public static Context getContext(String contextId) {\r
+\r
+               ContextManager cm = getFactory().getCurrentContextManager();\r
+\r
+        if( cm == null)\r
+            return null;\r
+        \r
+               return cm.getContext(contextId);\r
+       }\r
+\r
+       /**\r
+               Find the context with the given name in the context service factory\r
+               loaded for the system.\r
+\r
+               This version will not do any debug checking, but return null\r
+               quietly if it runs into any problems.\r
+\r
+               @return The requested context, null if it doesn't exist.\r
+       */\r
+       public static Context getContextOrNull(String contextId) {\r
+               ContextService csf = factory;\r
+\r
+               if (csf == null)\r
+                       return null;\r
+               \r
+               ContextManager cm = csf.getCurrentContextManager();\r
+\r
+               if (cm == null)\r
+                       return null;\r
+\r
+               return cm.getContext(contextId);\r
+       }\r
+\r
+\r
+       /**\r
+        * Get current Context Manager linked to the current Thread.\r
+     * See setCurrentContextManager for details.\r
+     * Note that this call can be expensive and is only\r
+     * intended to be used in "stateless" situations.\r
+     * Ideally code has a reference to the correct\r
+     * ContextManager from another Object, such as a pushed Context.\r
+     * \r
+        * @return ContextManager current Context Manager\r
+        */\r
+       public ContextManager getCurrentContextManager() {\r
+\r
+               ThreadLocal tcl = threadContextList;\r
+               if (tcl == null) {\r
+                       // The context service is already stopped.\r
+                       return null;\r
+               }\r
+\r
+               Object list = tcl.get();\r
+\r
+               if (list instanceof ContextManager) {\r
+            \r
+            Thread me = Thread.currentThread();\r
+                       \r
+                       ContextManager cm = (ContextManager) list;\r
+                       if (cm.activeThread == me)\r
+                               return cm;\r
+                       return null;\r
+               }\r
+\r
+               if (list == null)\r
+                       return null;\r
+\r
+               java.util.Stack stack = (java.util.Stack) list;\r
+               return (ContextManager) (stack.peek());\r
+\r
+       }\r
+\r
+    /**\r
+     * Break the link between the current Thread and the passed\r
+     * in ContextManager. Called in a pair with setCurrentContextManager,\r
+     * see that method for details.\r
+     */\r
+       public void resetCurrentContextManager(ContextManager cm) {\r
+               ThreadLocal tcl = threadContextList;\r
+\r
+               if (tcl == null) {\r
+                       // The context service is already stopped.\r
+                       return;\r
+               }\r
+\r
+               if (SanityManager.DEBUG) {\r
+\r
+                       if (Thread.currentThread() != cm.activeThread) {\r
+                               SanityManager.THROWASSERT("resetCurrentContextManager - mismatch threads - current" + Thread.currentThread() + " - cm's " + cm.activeThread);\r
+                       }\r
+\r
+                       if (getCurrentContextManager() != cm) {\r
+                               SanityManager.THROWASSERT("resetCurrentContextManager - mismatch contexts - " + Thread.currentThread());\r
+                       }\r
+\r
+                       if (cm.activeCount < -1) {\r
+                               SanityManager.THROWASSERT("resetCurrentContextManager - invalid count - current" + Thread.currentThread() + " - count " + cm.activeCount);\r
+                       }\r
+\r
+                       if (cm.activeCount == 0) {\r
+                               SanityManager.THROWASSERT("resetCurrentContextManager - invalid count - current" + Thread.currentThread() + " - count " + cm.activeCount);\r
+                       }\r
+\r
+                       if (cm.activeCount > 0) {\r
+                               if (tcl.get() != cm)\r
+                                       SanityManager.THROWASSERT("resetCurrentContextManager - invalid thread local " + Thread.currentThread() + " - object " + tcl.get());\r
+\r
+                       }\r
+               }\r
+\r
+               if (cm.activeCount != -1) {\r
+                       if (--cm.activeCount == 0) {\r
+                               cm.activeThread = null;\r
+                \r
+                // If the ContextManager is empty\r
+                // then don't keep a reference to it\r
+                // when it is not in use. The ContextManager\r
+                // has been closed (most likely) and this\r
+                // is now unwanted. Keeping the reference\r
+                // would hold onto memory and increase the\r
+                // chance of holding onto a another reference\r
+                // will could cause issues for future operations.\r
+                if (cm.isEmpty())\r
+                    tcl.set(null);\r
+                    \r
+            }\r
+                       return;\r
+               }\r
+\r
+               java.util.Stack stack = (java.util.Stack) tcl.get();\r
+\r
+               Object oldCM = stack.pop();\r
+\r
+               ContextManager nextCM = (ContextManager) stack.peek();\r
+\r
+               boolean seenMultipleCM = false;\r
+               boolean seenCM = false;\r
+               for (int i = 0; i < stack.size(); i++) {\r
+\r
+                       Object stackCM = stack.elementAt(i);\r
+                       if (stackCM != nextCM)\r
+                               seenMultipleCM = true;\r
+\r
+                       if (stackCM == cm)\r
+                               seenCM = true;\r
+               }\r
+\r
+               if (!seenCM) {\r
+                       cm.activeThread = null;\r
+                       cm.activeCount = 0;\r
+               }\r
+\r
+               if (!seenMultipleCM)\r
+               {\r
+                       // all the context managers on the stack\r
+                       // are the same so reduce to a simple count.\r
+                       nextCM.activeCount = stack.size();\r
+                       tcl.set(nextCM);\r
+               }\r
+       }\r
+\r
+    /**\r
+     * The current thread (passed in a me) is setting associateCM\r
+     * to be its current context manager. Sets the thread local\r
+     * variable threadContextList to reflect associateCM being\r
+     * the current ContextManager.\r
+     * \r
+     * @return True if the nesting level is to be represented in\r
+     * the ContextManager.activeCount field. False if not.\r
+     * \r
+     * @see ContextManager#activeCount\r
+     * @see ContextManager#activeThread\r
+    */\r
+       private boolean addToThreadList(Thread me, ContextManager associateCM) {\r
+\r
+               ThreadLocal tcl = threadContextList;\r
+\r
+               if (tcl == null) {\r
+                       // The context service is already stopped.\r
+                       return false;\r
+               }\r
+\r
+               Object list = tcl.get();\r
+\r
+        // Already set up to reflect associateCM ContextManager\r
+               if (associateCM == list)\r
+                       return true;\r
+\r
+        // Not currently using any ContextManager\r
+               if (list == null)\r
+               {\r
+                       tcl.set(associateCM);\r
+                       return true;\r
+               }\r
+\r
+               java.util.Stack stack;\r
+               if (list instanceof ContextManager) {\r
+            \r
+            // Could be two situations:\r
+            // 1. Single ContextManager not in use by this thread\r
+            // 2. Single ContextManager in use by this thread (nested call)\r
+            \r
+                       ContextManager threadsCM = (ContextManager) list;\r
+                       if (me == null)\r
+                               me = Thread.currentThread();\r
+            \r
+                       if (threadsCM.activeThread != me) {\r
+                // Not nested, just a CM left over\r
+                // from a previous execution.\r
+                               tcl.set(associateCM);\r
+                               return true;\r
+                       }\r
+            \r
+            // Nested, need to create a Stack of ContextManagers,\r
+            // the top of the stack will be the active one.\r
+                       stack = new java.util.Stack();\r
+                       tcl.set(stack);\r
+            \r
+            // The stack represents the true nesting\r
+            // of ContextManagers, splitting out nesting\r
+            // of a single ContextManager into multiple\r
+            // entries in the stack.\r
+                       for (int i = 0; i < threadsCM.activeCount; i++)\r
+                       {\r
+                               stack.push(threadsCM);\r
+                       }\r
+                       threadsCM.activeCount = -1;\r
+               }\r
+               else\r
+               {\r
+            // existing stack, nesting represented\r
+            // by stack entries, not activeCount.\r
+                       stack = (java.util.Stack) list;\r
+               }\r
+\r
+               stack.push(associateCM);\r
+               associateCM.activeCount = -1;\r
+\r
+               if (SanityManager.DEBUG) {\r
+\r
+                       if (SanityManager.DEBUG_ON("memoryLeakTrace")) {\r
+\r
+                               if (stack.size() > 10)\r
+                                       System.out.println("memoryLeakTrace:ContextService:threadLocal " + stack.size());\r
+                       }\r
+               }\r
+\r
+               return false;\r
+       }\r
+\r
+       /**\r
+     * Link the current thread to the passed in Contextmanager\r
+     * so that a subsequent call to getCurrentContextManager by\r
+     * the current Thread will return cm.\r
+     * ContextManagers are tied to a Thread while the thread\r
+     * is executing Derby code. For example on most JDBC method\r
+     * calls the ContextManager backing the Connection object\r
+     * is tied to the current Thread at the start of the method\r
+     * and reset at the end of the method. Once the Thread\r
+     * has completed its Derby work the method resetCurrentContextManager\r
+     * must be called with the same ContextManager to break the link.\r
+     * Note that a subsquent use of the ContextManager may be on\r
+     * a separate Thread, the Thread is only linked to the ContextManager\r
+     * between the setCurrentContextManager and resetCurrentContextManager calls.\r
+     * <BR>\r
+     * ContextService supports nesting of calls by a single Thread, either\r
+     * with the same ContextManager or a different ContextManager.\r
+     * <UL>\r
+     * <LI>The same ContextManager would be pushed during a nested JDBC call in\r
+     * a procedure or function.\r
+     * <LI>A different ContextManager would be pushed during a call on\r
+     * a different embedded JDBC Connection in a procedure or function.\r
+     * </UL>\r
+        */\r
+       public void setCurrentContextManager(ContextManager cm) {\r
+\r
+\r
+               if (SanityManager.DEBUG) {\r
+                       Thread me = Thread.currentThread();\r
+\r
+                       if (cm.activeThread != null && me != cm.activeThread) {\r
+                               SanityManager.THROWASSERT("setCurrentContextManager - mismatch threads - current " + me + " - cm's " + cm.activeThread);\r
+                       }\r
+\r
+               }\r
+\r
+               Thread me = null;\r
+\r
+               if (cm.activeThread == null) {\r
+                       cm.activeThread = (me = Thread.currentThread());\r
+               }\r
+               if (addToThreadList(me, cm))\r
+                       cm.activeCount++;\r
+    }\r
+\r
+       /**\r
+        * It's up to the caller to track this context manager and set it\r
+        * in the context manager list using setCurrentContextManager.\r
+        * We don't keep track of it due to this call being made.\r
+        */\r
+       public ContextManager newContextManager()\r
+       {\r
+               ContextManager cm = new ContextManager(this, errorStream);\r
+\r
+               // push a context that will shut down the system on\r
+               // a severe error.\r
+               new SystemContext(cm);\r
+\r
+               synchronized (this) {\r
+                       allContexts.add(cm);\r
+            \r
+                       if (SanityManager.DEBUG) {\r
+\r
+                               if (SanityManager.DEBUG_ON("memoryLeakTrace")) {\r
+\r
+                                       if (allContexts.size() > 50)\r
+                                               System.out.println("memoryLeakTrace:ContextService:allContexts " + allContexts.size());\r
+                               }\r
+                       }\r
+               }\r
+\r
+               return cm;\r
+       }\r
+\r
+       public void notifyAllActiveThreads(Context c) {\r
+               Thread me = Thread.currentThread();\r
+\r
+               synchronized (this) {\r
+                       for (Iterator i = allContexts.iterator(); i.hasNext(); ) {\r
+\r
+                               ContextManager cm = (ContextManager) i.next();\r
+\r
+                               Thread active = cm.activeThread;\r
+\r
+                               if (active == me)\r
+                                       continue;\r
+\r
+                               if (active == null)\r
+                                       continue;\r
+\r
+                final Thread fActive = active;\r
+                               if (cm.setInterrupted(c))\r
+                {\r
+                    AccessController.doPrivileged(\r
+                            new PrivilegedAction() {\r
+                                public Object run()  {\r
+                                    fActive.interrupt();\r
+                                    return null;\r
+                                }\r
+                            });\r
+                }\r
+                       }\r
+               }\r
+       }\r
+\r
+    /**\r
+     * Remove a ContextManager from the list of all active\r
+     * contexts managers.\r
+     */\r
+    synchronized void removeContext(ContextManager cm)\r
+    {\r
+        if (allContexts != null)\r
+            allContexts.remove( cm);\r
+    }\r
+}\r