/*
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
* Common Development and Distribution License, Version 1.0 only
* (the "License"). You may not use this file except in compliance
* with the License.
*
* You can obtain a copy of the license at legal-notices/CDDLv1_0.txt
* See the License for the specific language governing permissions
* and limitations under the License.
*
* When distributing Covered Code, include this CDDL HEADER in each
* file and include the License file at legal-notices/CDDLv1_0.txt.
* If applicable, add the following below this CDDL HEADER, with the
* fields enclosed by brackets "[]" replaced with your own identifying
* information:
* Portions Copyright [yyyy] [name of copyright owner]
*
* CDDL HEADER END
*
*
* Copyright 2006-2010 Sun Microsystems, Inc.
* Portions Copyright 2013-2015 ForgeRock AS
*/
/**
* This class defines a generic thread that should be the superclass
* for all threads created by the Directory Server. That is, instead
* of having a class that "extends Thread", you should make it
* "extends DirectoryThread". This provides various value-added
* capabilities, including:
* <BR>
* <UL>
* <LI>It helps make sure that all threads have a human-readable
* name so they are easier to identify in stack traces.</LI>
* <LI>It can capture a stack trace from the time that this thread
* was created that could be useful for debugging purposes.</LI>
* <LI>It plays an important role in ensuring that log messages
* generated as part of the processing for Directory Server
* tasks are properly captured and made available as part of
* that task.</LI>
* </UL>
*/
mayInstantiate=true,
mayExtend=true,
mayInvoke=true)
{
/**
* Enumeration holding the "logical" (application) thread states, as opposed
* to the operating system-level java.lang.Thread.State.
*/
private static enum ThreadState
{
/** The current thread is currently not doing any useful work. */
IDLE(false),
/** The current thread is currently processing a task, doing useful work. */
PROCESSING(false),
/** The current thread is in the process of shutting down. */
SHUTTING_DOWN(true),
/**
* The current thread has stopped running. Equivalent to
* java.lang.Thread.State.TERMINATED.
*/
STOPPED(true);
/**
* Whether this state implies a shutdown has been initiated or completed.
*/
private final boolean shutdownInitiated;
/**
* Constructs an instance of this enum.
*
* @param shutdownInitiated
* whether this state implies a shutdown was initiated.
*/
{
this.shutdownInitiated = shutdownInitiated;
}
/**
* Returns whether the current thread started the shutdown process.
*
* @return true if the current thread started the shutdown process, false
* otherwise.
*/
public boolean isShutdownInitiated()
{
return shutdownInitiated;
}
}
/**
* A factory which can be used by thread pool based services such as
* {@code Executor}s to dynamically create new
* {@code DirectoryThread} instances.
*/
{
/** The name prefix used for all threads created using this factory. */
/** The ID to use for the next thread created using this factory. */
/**
* Creates a new directory thread factory using the provided
* thread name prefix.
*
* @param threadNamePrefix
* The name prefix used for all threads created using this factory.
*/
{
if (threadNamePrefix == null) {
throw new NullPointerException("Null thread name prefix");
}
this.threadNamePrefix = threadNamePrefix;
}
/** {@inheritDoc} */
{
+ nextID.getAndIncrement());
}
}
/**
* The directory thread group that all directory threads will be a
* member of.
*/
new DirectoryThreadGroup();
/** The stack trace taken at the time that this thread was created. */
/** The task with which this thread is associated, if any. */
/** A reference to the thread that was used to create this thread. */
/** The current logical thread's state. */
/**
* A thread group for all directory threads. This implements a
* custom unhandledException handler that logs the error.
*/
implements AlertGenerator
{
/** Private constructor for DirectoryThreadGroup. */
private DirectoryThreadGroup()
{
super("Directory Server Thread Group");
}
/** {@inheritDoc} */
}
/** {@inheritDoc} */
return DirectoryThread.class.getName();
}
/** {@inheritDoc} */
return alerts;
}
/**
* Provides a means of handling a case in which a thread is about
* to die because of an unhandled exception. This method does
* nothing to try to prevent the death of that thread, but will
* at least log it so that it can be available for debugging
* purposes.
*
* @param t The thread that threw the exception.
* @param e The exception that was thrown but not properly
* handled.
*/
{
if (e instanceof ThreadDeath)
{
// Ignore ThreadDeath errors that can happen when everything is being
// shutdown.
return;
}
logger.traceException(e);
LocalizableMessage message = ERR_UNCAUGHT_THREAD_EXCEPTION.get(t.getName(), stackTraceToSingleLineString(e));
}
}
/**
* Creates a new instance of this directory thread with the
* specified name and with the specified target as its run object.
*
* @param target The target runnable object.
* @param threadName The human-readable name to use for this
* thread for debugging purposes.
*/
{
init();
}
/**
* Creates a new instance of this directory thread with the
* specified name.
*
* @param threadName The human-readable name to use for this
* thread for debugging purposes.
*/
{
super(DIRECTORY_THREAD_GROUP, threadName);
init();
}
/**
* Private method used to factorize constructor initialization.
*/
private void init()
{
if (parentThread instanceof DirectoryThread)
{
}
else
{
}
{
setDaemon(true);
}
}
/**
* Retrieves the stack trace that was captured at the time that this
* thread was created.
*
* @return The stack trace that was captured at the time that this
* thread was created.
*/
{
return creationStackTrace;
}
/**
* Retrieves a reference to the parent thread that created this
* directory thread. That parent thread may or may not be a
* directory thread.
*
* @return A reference to the parent thread that created this
* directory thread.
*/
{
return parentThread;
}
/**
* Retrieves the task with which this thread is associated. This
* will only be available for threads that are used in the process
* of running a task.
*
* @return The task with which this thread is associated, or
* {@code null} if there is none.
*/
{
return task;
}
/**
* Sets the task with which this thread is associated. It may be
* {@code null} to indicate that it is not associated with any task.
*
* @param task The task with which this thread is associated.
*/
{
}
/**
* Retrieves any relevant debug information with which this tread is
* associated so they can be included in debug messages.
*
* @return debug information about this thread as a string.
*/
{
return properties;
}
/**
* Returns whether the shutdown process has been initiated on the current
* thread. It also returns true when the thread is actually terminated.
* <p>
* Waiting for the thread to terminate should be done by invoking one of the
* {@link Thread#join()} methods.
*
* @return true if the shutdown process has been initiated on the current
* thread, false otherwise.
*/
public boolean isShutdownInitiated()
{
}
/**
* Instructs the current thread to initiate the shutdown process. The actual
* shutdown of the thread is a best effort and is dependent on the
* implementation of the {@link Thread#run()} method.
*/
public void initiateShutdown()
{
}
/**
* Sets the current thread state to "processing" if the shutdown process was
* not initiated.
*/
public void startWork()
{
}
/**
* Sets the current thread state to "idle" if the shutdown process was not
* initiated.
*/
public void stopWork()
{
}
/**
* Sets this thread's current state to the passed in newState if the thread is
* not already in a shutting down state.
*
* @param newState
* the new state to set
*/
{
while (!currentState.isShutdownInitiated())
{
{
return;
}
}
}
/**
* Returns the current thread state, possibly returning
* {@link ThreadState#STOPPED} if the thread is not alive.
*
* @return an {@link AtomicReference} to a ThreadState. It can be passed down
* as a method call parameter.
*/
{
if (!isAlive())
{
}
return this.threadState;
}
}