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