Class ContextService
- java.lang.Object
-
- org.apache.derby.iapi.services.context.ContextService
-
public final class ContextService extends java.lang.Object
A set of static methods to supply easier access to contexts.
-
-
Nested Class Summary
Nested Classes Modifier and Type Class Description private static class
ContextService.ContextManagerStack
Specialized stack class that contains context managers.
-
Field Summary
Fields Modifier and Type Field Description private java.util.HashSet<ContextManager>
allContexts
Collection of all ContextManagers that are open in the complete Derby system.private HeaderPrintWriter
errorStream
private static ContextService
factory
private java.lang.ThreadLocal<java.lang.Object>
threadContextList
Maintains a list of all the contexts that this thread has created and/or used.
-
Constructor Summary
Constructors Constructor Description ContextService()
Create a new ContextService for a Derby system.
-
Method Summary
All Methods Static Methods Instance Methods Concrete Methods Modifier and Type Method Description private boolean
addToThreadList(java.lang.Thread me, ContextManager associateCM)
The current thread (passed in a me) is setting associateCM to be its current context manager.static Context
getContext(java.lang.String contextId)
Find the context with the given name in the context service factory loaded for the system.static Context
getContextOrNull(java.lang.String contextId)
Find the context with the given name in the context service factory loaded for the system.ContextManager
getCurrentContextManager()
Get current Context Manager linked to the current Thread.static ContextService
getFactory()
ContextManager
newContextManager()
It's up to the caller to track this context manager and set it in the context manager list using setCurrentContextManager.void
notifyAllActiveThreads(Context c)
(package private) void
removeContext(ContextManager cm)
Remove a ContextManager from the list of all active contexts managers.void
resetCurrentContextManager(ContextManager cm)
Break the link between the current Thread and the passed in ContextManager.void
setCurrentContextManager(ContextManager cm)
Link the current thread to the passed in Contextmanager so that a subsequent call to getCurrentContextManager by the current Thread will return cm.static void
stop()
So it can be given to us and taken away...
-
-
-
Field Detail
-
factory
private static ContextService factory
-
errorStream
private HeaderPrintWriter errorStream
-
threadContextList
private java.lang.ThreadLocal<java.lang.Object> threadContextList
Maintains a list of all the contexts that this thread has created and/or used. The object stored in the thread local varys according how this thread has been used and will be one of:- null - the thread no affiliation with a context manager.
- ContextManager - the current thread has used or is using this context manager. If ContextManager.activeThread equals the current thread then the thread is currently active with the ContextManager. In this case ContextManager.activeCount will be greater than zero and represent the level of nested setCurrentContextmanager calls. If ContextManager.activeThread is null then no other thread is using the Contextmanager, if ContextManager.activeThread is not-null and not equal to the current thread then some other thread is using the context. It is assumed that only a single thread can be using a ContextManager at any time and this is enforced by synchronization outside the ContextManager. E.g for JDBC connections, synchronization at the JDBC level.
- ContextManagerStack containing ContextManagers - the current thread is actively using multiple different ContextManagers, with nesting. All ContextManagers in the stack will have activeThread set to the current thread, and their activeCount set to -1. This is because nesting is solely represented by the stack, with the current context manager on top of the stack. This supports multiple levels of nesting across two stacks, e.g. C1->C2->C2->C1->C2.
There are two cases we are trying to optimise.
- Typical JDBC client program where there a Connection is always executed using a single thread. In this case this variable will contain the Connection's context manager
- Typical application server pooled connection where a single thread may use a connection from a pool for the lifetime of the request. In this case this variable will contain a WeakReference.
Single thread for Connection execution.threadContextList.get() == cm // while in JDBC engine code cm.activeThread == Thread.currentThread(); cm.activeCount = 1;
J2EE single thread for lifetime of execution.// thread executing request threadContextList.get() == cm // while in JDBC engine code cm.activeThread == Thread.currentThread(); cm.activeCount = 1; // other threads that have recently executed // the same connection can have threadContextList.get() == cm cm.activeThread != Thread.currentThread();
Nested routine calls within single connectionthreadContextList.get() == cm // Within server-side JDBC code in a // function called from another function/procedure // called from an applications's statement // (three levels of nesting) cm.activeThread == Thread.currentThread(); cm.activeCount = 3;
Nested routine calls with the inner routine using a different connection to access a Derby database. Note nesting of orignal Contextmanager cm is changed from an activeCount of 2 to nesting within the stack once multiple ContextManagers are involved.threadContextList.get() == stack {cm2,cm,cm} cm.activeThread == Thread.currentThread(); cm.activeCount = -1; // nesting in stack cm2.activeThread == Thread.currentThread(); cm2.activeCount = -1; // nesting in stack
Nested multiple ContextManagers, the code supports this, though it may not be possible currently to have a stack like this from SQL/JDBC.threadContextList.get() == stack {cm3,cm2,cm,cm2,cm,cm} cm.activeThread == Thread.currentThread(); cm.activeCount = -1; // nesting in stack cm2.activeThread == Thread.currentThread(); cm2.activeCount = -1; // nesting in stack cm3.activeThread == Thread.currentThread(); cm3.activeCount = -1; // nesting in stack
-
allContexts
private java.util.HashSet<ContextManager> allContexts
Collection of all ContextManagers that are open in the complete Derby system. A ContextManager is added when it is created with newContextManager and removed when the session is closed.
-
-
Method Detail
-
stop
public static void stop()
So it can be given to us and taken away...
-
getFactory
public static ContextService getFactory()
-
getContext
public static Context getContext(java.lang.String contextId)
Find the context with the given name in the context service factory loaded for the system.- Returns:
- The requested context, null if it doesn't exist.
-
getContextOrNull
public static Context getContextOrNull(java.lang.String contextId)
Find the context with the given name in the context service factory loaded for the system. This version will not do any debug checking, but return null quietly if it runs into any problems.- Returns:
- The requested context, null if it doesn't exist.
-
getCurrentContextManager
public ContextManager getCurrentContextManager()
Get current Context Manager linked to the current Thread. See setCurrentContextManager for details. Note that this call can be expensive and is only intended to be used in "stateless" situations. Ideally code has a reference to the correct ContextManager from another Object, such as a pushed Context.- Returns:
- ContextManager current Context Manager
-
resetCurrentContextManager
public void resetCurrentContextManager(ContextManager cm)
Break the link between the current Thread and the passed in ContextManager. Called in a pair with setCurrentContextManager, see that method for details.
-
addToThreadList
private boolean addToThreadList(java.lang.Thread me, ContextManager associateCM)
The current thread (passed in a me) is setting associateCM to be its current context manager. Sets the thread local variable threadContextList to reflect associateCM being the current ContextManager.- Returns:
- True if the nesting level is to be represented in the ContextManager.activeCount field. False if not.
- See Also:
ContextManager.activeCount
,ContextManager.activeThread
-
setCurrentContextManager
public void setCurrentContextManager(ContextManager cm)
Link the current thread to the passed in Contextmanager so that a subsequent call to getCurrentContextManager by the current Thread will return cm. ContextManagers are tied to a Thread while the thread is executing Derby code. For example on most JDBC method calls the ContextManager backing the Connection object is tied to the current Thread at the start of the method and reset at the end of the method. Once the Thread has completed its Derby work the method resetCurrentContextManager must be called with the same ContextManager to break the link. Note that a subsquent use of the ContextManager may be on a separate Thread, the Thread is only linked to the ContextManager between the setCurrentContextManager and resetCurrentContextManager calls.
ContextService supports nesting of calls by a single Thread, either with the same ContextManager or a different ContextManager.- The same ContextManager would be pushed during a nested JDBC call in a procedure or function.
- A different ContextManager would be pushed during a call on a different embedded JDBC Connection in a procedure or function.
-
newContextManager
public ContextManager newContextManager()
It's up to the caller to track this context manager and set it in the context manager list using setCurrentContextManager. We don't keep track of it due to this call being made.
-
notifyAllActiveThreads
public void notifyAllActiveThreads(Context c)
-
removeContext
void removeContext(ContextManager cm)
Remove a ContextManager from the list of all active contexts managers.
-
-