[Home] DMelt member access. Java source code: org.apache.derby.iapi.services.context.ContextService
/*
Derby - Class org.apache.derby.iapi.services.context.ContextService
Licensed to the Apache Software Foundation (ASF) under one or more
contributor license agreements. See the NOTICE file distributed with
this work for additional information regarding copyright ownership.
The ASF licenses this file to you under the Apache License, Version 2.0
(the "License"); you may not use this file except in compliance with
the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package org.apache.derby.iapi.services.context;
import java.security.AccessController;
import java.security.PrivilegedAction;
import java.util.HashSet;
import java.util.Stack;
import org.apache.derby.iapi.error.ShutdownException;
import org.apache.derby.iapi.services.monitor.Monitor;
import org.apache.derby.shared.common.sanity.SanityManager;
import org.apache.derby.iapi.services.stream.HeaderPrintWriter;
/**
A set of static methods to supply easier access to contexts.
*/
public final class ContextService //OLD extends Hashtable
{
private static ContextService factory;
private HeaderPrintWriter errorStream;
/**
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.
This thread local is used to find the current context manager. Basically it provides
fast access to a list of candidate contexts. If one of the contexts has its activeThread
equal to the current thread then it is the current context manager.
If the thread has pushed multiple contexts (e.g. open a new non-nested Derby connection
from a server side method) then threadContextList will contain a Stack. The value for each cm
will be a push order, with higher numbers being more recently pushed.
To support the case where a single context manager is pushed twice (nested connection),
the context manager keeps track of the number of times it has been pushed (set). Note that
our synchronization requires that a single context can only be accessed by a single thread at a time.
In the JDBC layer this is enforced by the synchronization on the connection object.
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 connection
threadContextList.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.