001    /*
002     * CDDL HEADER START
003     *
004     * The contents of this file are subject to the terms of the
005     * Common Development and Distribution License, Version 1.0 only
006     * (the "License").  You may not use this file except in compliance
007     * with the License.
008     *
009     * You can obtain a copy of the license at
010     * trunk/opends/resource/legal-notices/OpenDS.LICENSE
011     * or https://OpenDS.dev.java.net/OpenDS.LICENSE.
012     * See the License for the specific language governing permissions
013     * and limitations under the License.
014     *
015     * When distributing Covered Code, include this CDDL HEADER in each
016     * file and include the License file at
017     * trunk/opends/resource/legal-notices/OpenDS.LICENSE.  If applicable,
018     * add the following below this CDDL HEADER, with the fields enclosed
019     * by brackets "[]" replaced with your own identifying information:
020     *      Portions Copyright [yyyy] [name of copyright owner]
021     *
022     * CDDL HEADER END
023     *
024     *
025     *      Copyright 2006-2008 Sun Microsystems, Inc.
026     */
027    package org.opends.server.api;
028    
029    
030    
031    import java.util.Map;
032    import java.util.LinkedHashMap;
033    
034    import org.opends.server.backends.task.Task;
035    import org.opends.server.core.DirectoryServer;
036    
037    import static org.opends.server.util.ServerConstants.*;
038    import static org.opends.server.util.StaticUtils.*;
039    
040    
041    
042    /**
043     * This class defines a generic thread that should be the superclass
044     * for all threads created by the Directory Server.  That is, instead
045     * of having a class that "extends Thread", you should make it
046     * "extends DirectoryThread".  This provides various value-added
047     * capabilities, including:
048     * <BR>
049     * <UL>
050     *   <LI>It helps make sure that all threads have a human-readable
051     *       name so they are easier to identify in stack traces.</LI>
052     *   <LI>It can capture a stack trace from the time that this thread
053     *       was created that could be useful for debugging purposes.</LI>
054     *   <LI>It plays an important role in ensuring that log messages
055     *       generated as part of the processing for Directory Server
056     *       tasks are properly captured and made available as part of
057     *       that task.</LI>
058     * </UL>
059     */
060    @org.opends.server.types.PublicAPI(
061         stability=org.opends.server.types.StabilityLevel.VOLATILE,
062         mayInstantiate=true,
063         mayExtend=true,
064         mayInvoke=true)
065    public class DirectoryThread
066           extends Thread
067    {
068      // The stack trace taken at the time that this thread was created.
069      private StackTraceElement[] creationStackTrace;
070    
071      // The task with which this thread is associated, if any.
072      private Task task;
073    
074      // A reference to the thread that was used to create this thread.
075      private Thread parentThread;
076    
077    
078    
079      /**
080       * Creates a new instance of this directory thread with the
081       * specified name and with the specified target as its run object.
082       *
083       * @param  target      The target runnable object.
084       * @param  threadName  The human-readable name to use for this
085       *                     thread for debugging purposes.
086       */
087      public DirectoryThread(Runnable target, String threadName)
088      {
089        super (DirectoryServer.getDirectoryThreadGroup(), target,
090               threadName);
091    
092    
093        init();
094      }
095    
096      /**
097       * Creates a new instance of this directory thread with the
098       * specified name.
099       *
100       * @param  threadName  The human-readable name to use for this
101       *                     thread for debugging purposes.
102       */
103      protected DirectoryThread(String threadName)
104      {
105        super(DirectoryServer.getDirectoryThreadGroup(), threadName);
106    
107    
108        init();
109      }
110    
111    
112      /**
113       * Creates a new instance of this directory thread with the
114       * specified name as a part of the given thread group.
115       *
116       * @param  threadGroup  The thread group in which this thread is to
117       *                      be placed.
118       * @param  threadName   The human-readable name to use for this
119       *                      thread for debugging purposes.
120       */
121      protected DirectoryThread(ThreadGroup threadGroup,
122                                String threadName)
123      {
124        super(threadGroup, threadName);
125    
126    
127        init();
128      }
129    
130    
131    
132      /**
133       * private method used to factorize constructor initialization.
134       */
135      private void init()
136      {
137        parentThread       = currentThread();
138        creationStackTrace = parentThread.getStackTrace();
139    
140        if (parentThread instanceof DirectoryThread)
141        {
142          task = ((DirectoryThread) parentThread).task;
143        }
144        else
145        {
146          task = null;
147        }
148    
149        if (DirectoryServer.getEnvironmentConfig().forceDaemonThreads())
150        {
151          setDaemon(true);
152        }
153      }
154    
155    
156    
157      /**
158       * Retrieves the stack trace that was captured at the time that this
159       * thread was created.
160       *
161       * @return  The stack trace that was captured at the time that this
162       *          thread was created.
163       */
164      public StackTraceElement[] getCreationStackTrace()
165      {
166        return creationStackTrace;
167      }
168    
169    
170    
171      /**
172       * Retrieves a reference to the parent thread that created this
173       * directory thread.  That parent thread may or may not be a
174       * directory thread.
175       *
176       * @return  A reference to the parent thread that created this
177       *          directory thread.
178       */
179      public Thread getParentThread()
180      {
181        return parentThread;
182      }
183    
184    
185    
186      /**
187       * Retrieves the task with which this thread is associated.  This
188       * will only be available for threads that are used in the process
189       * of running a task.
190       *
191       * @return  The task with which this thread is associated, or
192       *          {@code null} if there is none.
193       */
194      public Task getAssociatedTask()
195      {
196        return task;
197      }
198    
199    
200    
201      /**
202       * Sets the task with which this thread is associated.  It may be
203       * {@code null} to indicate that it is not associated with any task.
204       *
205       * @param  task  The task with which this thread is associated.
206       */
207      public void setAssociatedTask(Task task)
208      {
209        this.task = task;
210      }
211    
212    
213      /**
214       * Retrieves any relevent debug information with which this tread is
215       * associated so they can be included in debug messages.
216       *
217       * @return debug information about this thread as a string.
218       */
219      public Map<String, String> getDebugProperties()
220      {
221        LinkedHashMap<String, String> properties =
222            new LinkedHashMap<String, String>();
223    
224        properties.put("parentThread", parentThread.getName() +
225            "(" + parentThread.getId() + ")");
226        properties.put("isDaemon", String.valueOf(this.isDaemon()));
227    
228        return properties;
229      }
230    }
231