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