JAL-3048 test updated for AlignExportSettings changes
[jalview.git] / srcjar2 / org / apache / log4j / NDC.java
1 /*
2  * Licensed to the Apache Software Foundation (ASF) under one or more
3  * contributor license agreements.  See the NOTICE file distributed with
4  * this work for additional information regarding copyright ownership.
5  * The ASF licenses this file to You under the Apache License, Version 2.0
6  * (the "License"); you may not use this file except in compliance with
7  * the License.  You may obtain a copy of the License at
8  * 
9  *      http://www.apache.org/licenses/LICENSE-2.0
10  * 
11  * Unless required by applicable law or agreed to in writing, software
12  * distributed under the License is distributed on an "AS IS" BASIS,
13  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  * See the License for the specific language governing permissions and
15  * limitations under the License.
16  */
17
18 //      Contributors:      Dan Milstein 
19 //                         Ray Millard
20
21 package org.apache.log4j;
22
23 import java.util.Hashtable;
24 import java.util.Stack;
25 import java.util.Enumeration;
26 import java.util.Vector;
27
28 import org.apache.log4j.helpers.LogLog;
29
30 /**
31    The NDC class implements <i>nested diagnostic contexts</i> as
32    defined by Neil Harrison in the article "Patterns for Logging
33    Diagnostic Messages" part of the book "<i>Pattern Languages of
34    Program Design 3</i>" edited by Martin et al.
35
36    <p>A Nested Diagnostic Context, or NDC in short, is an instrument
37    to distinguish interleaved log output from different sources. Log
38    output is typically interleaved when a server handles multiple
39    clients near-simultaneously.
40
41    <p>Interleaved log output can still be meaningful if each log entry
42    from different contexts had a distinctive stamp. This is where NDCs
43    come into play.
44
45    <p><em><b>Note that NDCs are managed on a per thread
46    basis</b></em>. NDC operations such as {@link #push push}, {@link
47    #pop}, {@link #clear}, {@link #getDepth} and {@link #setMaxDepth}
48    affect the NDC of the <em>current</em> thread only. NDCs of other
49    threads remain unaffected.
50
51    <p>For example, a servlet can build a per client request NDC
52    consisting the clients host name and other information contained in
53    the the request. <em>Cookies</em> are another source of distinctive
54    information. To build an NDC one uses the {@link #push push}
55    operation. Simply put,
56
57    <p><ul>
58      <li>Contexts can be nested.
59
60      <p><li>When entering a context, call <code>NDC.push</code>. As a
61      side effect, if there is no nested diagnostic context for the
62      current thread, this method will create it.
63
64      <p><li>When leaving a context, call <code>NDC.pop</code>.
65
66      <p><li><b>When exiting a thread make sure to call {@link #remove
67      NDC.remove()}</b>.  
68    </ul>
69    
70    <p>There is no penalty for forgetting to match each
71    <code>push</code> operation with a corresponding <code>pop</code>,
72    except the obvious mismatch between the real application context
73    and the context set in the NDC.
74
75    <p>If configured to do so, {@link PatternLayout} and {@link
76    TTCCLayout} instances automatically retrieve the nested diagnostic
77    context for the current thread without any user intervention.
78    Hence, even if a servlet is serving multiple clients
79    simultaneously, the logs emanating from the same code (belonging to
80    the same category) can still be distinguished because each client
81    request will have a different NDC tag.
82
83    <p>Heavy duty systems should call the {@link #remove} method when
84    leaving the run method of a thread. This ensures that the memory
85    used by the thread can be freed by the Java garbage
86    collector. There is a mechanism to lazily remove references to dead
87    threads. In practice, this means that you can be a little sloppy
88    and sometimes forget to call {@link #remove} before exiting a
89    thread.
90    
91    <p>A thread may inherit the nested diagnostic context of another
92    (possibly parent) thread using the {@link #inherit inherit}
93    method. A thread may obtain a copy of its NDC with the {@link
94    #cloneStack cloneStack} method and pass the reference to any other
95    thread, in particular to a child.
96    
97    @author Ceki G&uuml;lc&uuml;
98    @since 0.7.0
99   
100 */
101  
102 public class NDC {
103
104   // The synchronized keyword is not used in this class. This may seem
105   // dangerous, especially since the class will be used by
106   // multiple-threads. In particular, all threads share the same
107   // hashtable (the "ht" variable). This is OK since java hashtables
108   // are thread safe. Same goes for Stacks.
109
110   // More importantly, when inheriting diagnostic contexts the child
111   // thread is handed a clone of the parent's NDC.  It follows that
112   // each thread has its own NDC (i.e. stack).
113
114   static Hashtable ht = new Hashtable();
115
116   static int pushCounter = 0; // the number of times push has been called
117                               // after the latest call to lazyRemove
118
119   // The number of times we allow push to be called before we call lazyRemove
120   // 5 is a relatively small number. As such, lazyRemove is not called too
121   // frequently. We thus avoid the cost of creating an Enumeration too often.
122   // The higher this number, the longer is the avarage period for which all
123   // logging calls in all threads are blocked.
124   static final int REAP_THRESHOLD = 5;
125   
126   // No instances allowed.
127   private NDC() {}
128   
129   /**
130    *   Get NDC stack for current thread.
131    *   @return NDC stack for current thread.
132    */
133   private static Stack getCurrentStack() {
134       if (ht != null) {
135           return (Stack) ht.get(Thread.currentThread());
136       }
137       return null;
138   }
139
140
141   /**
142      Clear any nested diagnostic information if any. This method is
143      useful in cases where the same thread can be potentially used
144      over and over in different unrelated contexts.
145
146      <p>This method is equivalent to calling the {@link #setMaxDepth}
147      method with a zero <code>maxDepth</code> argument.
148      
149      @since 0.8.4c */
150   public
151   static
152   void clear() {
153     Stack stack = getCurrentStack();    
154     if(stack != null) {
155         stack.setSize(0);
156     }    
157   }
158
159   
160   /**
161      Clone the diagnostic context for the current thread.
162
163      <p>Internally a diagnostic context is represented as a stack.  A
164      given thread can supply the stack (i.e. diagnostic context) to a
165      child thread so that the child can inherit the parent thread's
166      diagnostic context.
167
168      <p>The child thread uses the {@link #inherit inherit} method to
169      inherit the parent's diagnostic context.
170      
171      @return Stack A clone of the current thread's  diagnostic context.
172
173   */
174   public
175   static
176   Stack cloneStack() {
177     Stack stack = getCurrentStack();
178     if(stack == null) {
179         return null;
180     } else {
181       return (Stack) stack.clone();
182     }
183   }
184
185   
186   /**
187      Inherit the diagnostic context of another thread.
188
189      <p>The parent thread can obtain a reference to its diagnostic
190      context using the {@link #cloneStack} method.  It should
191      communicate this information to its child so that it may inherit
192      the parent's diagnostic context.
193
194      <p>The parent's diagnostic context is cloned before being
195      inherited. In other words, once inherited, the two diagnostic
196      contexts can be managed independently.
197      
198      <p>In java, a child thread cannot obtain a reference to its
199      parent, unless it is directly handed the reference. Consequently,
200      there is no client-transparent way of inheriting diagnostic
201      contexts. Do you know any solution to this problem?
202
203      @param stack The diagnostic context of the parent thread.
204
205   */
206   public
207   static
208   void inherit(Stack stack) {
209     if(stack != null) {
210         ht.put(Thread.currentThread(), stack);
211     }
212   }
213
214
215   /**
216      <font color="#FF4040"><b>Never use this method directly, use the {@link
217      org.apache.log4j.spi.LoggingEvent#getNDC} method instead</b></font>.
218   */
219   static
220   public
221   String get() {
222     Stack s = getCurrentStack();
223     if(s != null && !s.isEmpty()) {
224         return ((DiagnosticContext) s.peek()).fullMessage;
225     } else {
226         return null;
227     }
228   }
229   
230   /**
231    * Get the current nesting depth of this diagnostic context.
232    *
233    * @see #setMaxDepth
234    * @since 0.7.5
235    */
236   public
237   static
238   int getDepth() {
239     Stack stack = getCurrentStack();          
240     if(stack == null) {
241         return 0;
242     } else {
243         return stack.size();
244     }      
245   }
246
247   private
248   static
249   void lazyRemove() {
250     if (ht == null) {
251         return;
252     }
253      
254     // The synchronization on ht is necessary to prevent JDK 1.2.x from
255     // throwing ConcurrentModificationExceptions at us. This sucks BIG-TIME.
256     // One solution is to write our own hashtable implementation.
257     Vector v;
258     
259     synchronized(ht) {
260       // Avoid calling clean-up too often.
261       if(++pushCounter <= REAP_THRESHOLD) {
262         return; // We release the lock ASAP.
263       } else {
264         pushCounter = 0; // OK let's do some work.
265       }
266
267       int misses = 0;
268       v = new Vector(); 
269       Enumeration enumeration = ht.keys();
270       // We give up after 4 straigt missses. That is 4 consecutive
271       // inspected threads in 'ht' that turn out to be alive.
272       // The higher the proportion on dead threads in ht, the higher the
273       // chances of removal.
274       while(enumeration.hasMoreElements() && (misses <= 4)) {
275         Thread t = (Thread) enumeration.nextElement();
276         if(t.isAlive()) {
277           misses++;
278         } else {
279           misses = 0;
280           v.addElement(t);
281         }
282       }
283     } // synchronized
284
285     int size = v.size();
286     for(int i = 0; i < size; i++) {
287       Thread t = (Thread) v.elementAt(i);
288       LogLog.debug("Lazy NDC removal for thread [" + t.getName() + "] ("+ 
289                    ht.size() + ").");
290       ht.remove(t);
291     }
292   }
293
294   /**
295      Clients should call this method before leaving a diagnostic
296      context.
297
298      <p>The returned value is the value that was pushed last. If no
299      context is available, then the empty string "" is returned.
300      
301      @return String The innermost diagnostic context.
302      
303      */
304   public
305   static
306   String pop() {
307     Stack stack = getCurrentStack();
308     if(stack != null && !stack.isEmpty()) {
309         return ((DiagnosticContext) stack.pop()).message;
310     } else {
311         return "";
312     }
313   }
314
315   /**
316      Looks at the last diagnostic context at the top of this NDC
317      without removing it.
318
319      <p>The returned value is the value that was pushed last. If no
320      context is available, then the empty string "" is returned.
321      
322      @return String The innermost diagnostic context.
323      
324      */
325   public
326   static
327   String peek() {
328     Stack stack = getCurrentStack();
329     if(stack != null && !stack.isEmpty()) {
330         return ((DiagnosticContext) stack.peek()).message;
331     } else {
332         return "";
333     }
334   }
335   
336   /**
337      Push new diagnostic context information for the current thread.
338
339      <p>The contents of the <code>message</code> parameter is
340      determined solely by the client.  
341      
342      @param message The new diagnostic context information.  */
343   public
344   static
345   void push(String message) {
346     Stack stack = getCurrentStack();
347       
348     if(stack == null) {
349       DiagnosticContext dc = new DiagnosticContext(message, null);      
350       stack = new Stack();
351       Thread key = Thread.currentThread();
352       ht.put(key, stack);
353       stack.push(dc);
354     } else if (stack.isEmpty()) {
355       DiagnosticContext dc = new DiagnosticContext(message, null);            
356       stack.push(dc);
357     } else {
358       DiagnosticContext parent = (DiagnosticContext) stack.peek();
359       stack.push(new DiagnosticContext(message, parent));
360     }    
361   }
362
363   /**
364      Remove the diagnostic context for this thread.
365
366      <p>Each thread that created a diagnostic context by calling
367      {@link #push} should call this method before exiting. Otherwise,
368      the memory used by the <b>thread</b> cannot be reclaimed by the
369      VM.
370
371      <p>As this is such an important problem in heavy duty systems and
372      because it is difficult to always guarantee that the remove
373      method is called before exiting a thread, this method has been
374      augmented to lazily remove references to dead threads. In
375      practice, this means that you can be a little sloppy and
376      occasionally forget to call {@link #remove} before exiting a
377      thread. However, you must call <code>remove</code> sometime. If
378      you never call it, then your application is sure to run out of
379      memory.
380      
381   */
382   static
383   public
384   void remove() {
385     if (ht != null) {
386         ht.remove(Thread.currentThread());
387     
388         // Lazily remove dead-thread references in ht.
389         lazyRemove();
390     }
391   }
392
393   /**
394      Set maximum depth of this diagnostic context. If the current
395      depth is smaller or equal to <code>maxDepth</code>, then no
396      action is taken.
397
398      <p>This method is a convenient alternative to multiple {@link
399      #pop} calls. Moreover, it is often the case that at the end of
400      complex call sequences, the depth of the NDC is
401      unpredictable. The <code>setMaxDepth</code> method circumvents
402      this problem.
403
404      <p>For example, the combination
405      <pre>
406        void foo() {
407        &nbsp;  int depth = NDC.getDepth();
408
409        &nbsp;  ... complex sequence of calls
410
411        &nbsp;  NDC.setMaxDepth(depth);
412        }
413      </pre>
414
415      ensures that between the entry and exit of foo the depth of the
416      diagnostic stack is conserved.
417      
418      @see #getDepth
419      @since 0.7.5 */
420   static
421   public
422   void setMaxDepth(int maxDepth) {
423     Stack stack = getCurrentStack();    
424     if(stack != null && maxDepth < stack.size()) {
425         stack.setSize(maxDepth);
426     }
427   }
428   
429   // =====================================================================
430    private static class DiagnosticContext {
431
432     String fullMessage;
433     String message;
434     
435     DiagnosticContext(String message, DiagnosticContext parent) {
436       this.message = message;
437       if(parent != null) {
438         fullMessage = parent.fullMessage + ' ' + message;
439       } else {
440         fullMessage = message;
441       }
442     }
443   }
444 }
445