You are viewing a plain text version of this content. The canonical link for it is here.
Posted to log4j-dev@logging.apache.org by sd...@apache.org on 2004/03/27 07:46:27 UTC

cvs commit: logging-log4j/tests/input NDC1.properties

sdeboy      2004/03/26 22:46:27

  Modified:    src/java/org/apache/log4j NDC.java
               tests    build.xml
  Added:       tests/witness NDC.1
               tests/input NDC1.properties
  Log:
  Applying NDC patch provided by Ray DeCampo - see http://nagoya.apache.org/bugzilla/show_bug.cgi?id=25890
  
  Revision  Changes    Path
  1.18      +19 -98    logging-log4j/src/java/org/apache/log4j/NDC.java
  
  Index: NDC.java
  ===================================================================
  RCS file: /home/cvs/logging-log4j/src/java/org/apache/log4j/NDC.java,v
  retrieving revision 1.17
  retrieving revision 1.18
  diff -u -r1.17 -r1.18
  --- NDC.java	27 Feb 2004 16:47:28 -0000	1.17
  +++ NDC.java	27 Mar 2004 06:46:27 -0000	1.18
  @@ -17,14 +17,10 @@
   
   //      Contributors:      Dan Milstein 
   //                         Ray Millard
  +//                         Ray DeCampo
   package org.apache.log4j;
   
  -import org.apache.log4j.helpers.LogLog;
  -
  -import java.util.Enumeration;
  -import java.util.Hashtable;
   import java.util.Stack;
  -import java.util.Vector;
   
   
   /**
  @@ -63,8 +59,8 @@
   
        <p><li>When leaving a context, call <code>NDC.pop</code>.
   
  -     <p><li><b>When exiting a thread make sure to call {@link #remove
  -     NDC.remove()}</b>.
  +     <p><li>As of log4j 1.3, it is no longer necessary to call {@link #remove
  +     NDC.remove()} when exiting a thread.</b>.
      </ul>
   
      <p>There is no penalty for forgetting to match each
  @@ -80,14 +76,6 @@
      the same category) can still be distinguished because each client
      request will have a different NDC tag.
   
  -   <p>Heavy duty systems should call the {@link #remove} method when
  -   leaving the run method of a thread. This ensures that the memory
  -   used by the thread can be freed by the Java garbage
  -   collector. There is a mechanism to lazily remove references to dead
  -   threads. In practice, this means that you can be a little sloppy
  -   and sometimes forget to call {@link #remove} before exiting a
  -   thread.
  -
      <p>A thread may inherit the nested diagnostic context of another
      (possibly parent) thread using the {@link #inherit inherit}
      method. A thread may obtain a copy of its NDC with the {@link
  @@ -101,13 +89,12 @@
   public class NDC {
     // The synchronized keyword is not used in this class. This may seem
     // dangerous, especially since the class will be used by
  -  // multiple-threads. In particular, all threads share the same
  -  // hashtable (the "ht" variable). This is OK since java hashtables
  -  // are thread safe. Same goes for Stacks.
  +  // multiple-threads.
  +  // This is OK since java Stacks are thread safe.
     // More importantly, when inheriting diagnostic contexts the child
     // thread is handed a clone of the parent's NDC.  It follows that
     // each thread has its own NDC (i.e. stack).
  -  static Hashtable ht = new Hashtable();
  +  private static final ThreadLocal tl = new ThreadLocal();
     static int pushCounter = 0; // the number of times push has been called
                                 // after the latest call to lazyRemove
     static final int REAP_THRESHOLD = 5;
  @@ -126,7 +113,7 @@
   
        @since 0.8.4c */
     public static void clear() {
  -    Stack stack = (Stack) ht.get(Thread.currentThread());
  +    Stack stack = (Stack) tl.get();
   
       if (stack != null) {
         stack.setSize(0);
  @@ -148,7 +135,7 @@
   
     */
     public static Stack cloneStack() {
  -    Object o = ht.get(Thread.currentThread());
  +    Object o = tl.get();
   
       if (o == null) {
         return null;
  @@ -181,7 +168,7 @@
     */
     public static void inherit(Stack stack) {
       if (stack != null) {
  -      ht.put(Thread.currentThread(), stack);
  +      tl.set(stack);
       }
     }
   
  @@ -190,7 +177,7 @@
        org.apache.log4j.spi.LoggingEvent#getNDC} method instead</b></font>.
     */
     public static String get() {
  -    Stack s = (Stack) ht.get(Thread.currentThread());
  +    Stack s = (Stack) tl.get();
   
       if ((s != null) && !s.isEmpty()) {
         return ((DiagnosticContext) s.peek()).fullMessage;
  @@ -206,7 +193,7 @@
        @since 0.7.5
      */
     public static int getDepth() {
  -    Stack stack = (Stack) ht.get(Thread.currentThread());
  +    Stack stack = (Stack) tl.get();
   
       if (stack == null) {
         return 0;
  @@ -215,53 +202,6 @@
       }
     }
   
  -  private static void lazyRemove() {
  -    // The synchronization on ht is necessary to prevent JDK 1.2.x from
  -    // throwing ConcurrentModificationExceptions at us. This sucks BIG-TIME.
  -    // One solution is to write our own hashtable implementation.
  -    Vector v;
  -
  -    synchronized (ht) {
  -      // Avoid calling clean-up too often.
  -      if (++pushCounter <= REAP_THRESHOLD) {
  -        return; // We release the lock ASAP.
  -      } else {
  -        pushCounter = 0; // OK let's do some work.
  -      }
  -
  -      int misses = 0;
  -      v = new Vector();
  -
  -      Enumeration enum = ht.keys();
  -
  -      // We give up after 4 straigt missses. That is 4 consecutive
  -      // inspected threads in 'ht' that turn out to be alive.
  -      // The higher the proportion on dead threads in ht, the higher the
  -      // chances of removal.
  -      while (enum.hasMoreElements() && (misses <= 4)) {
  -        Thread t = (Thread) enum.nextElement();
  -
  -        if (t.isAlive()) {
  -          misses++;
  -        } else {
  -          misses = 0;
  -          v.addElement(t);
  -        }
  -      }
  -    }
  -     // synchronized
  -
  -    int size = v.size();
  -
  -    for (int i = 0; i < size; i++) {
  -      Thread t = (Thread) v.elementAt(i);
  -      LogLog.debug(
  -        "Lazy NDC removal for thread [" + t.getName() + "] (" + ht.size()
  -        + ").");
  -      ht.remove(t);
  -    }
  -  }
  -
     /**
        Clients should call this method before leaving a diagnostic
        context.
  @@ -273,8 +213,7 @@
   
        */
     public static String pop() {
  -    Thread key = Thread.currentThread();
  -    Stack stack = (Stack) ht.get(key);
  +    Stack stack = (Stack) tl.get();
   
       if ((stack != null) && !stack.isEmpty()) {
         return ((DiagnosticContext) stack.pop()).message;
  @@ -294,8 +233,7 @@
   
        */
     public static String peek() {
  -    Thread key = Thread.currentThread();
  -    Stack stack = (Stack) ht.get(key);
  +    Stack stack = (Stack) tl.get();
   
       if ((stack != null) && !stack.isEmpty()) {
         return ((DiagnosticContext) stack.peek()).message;
  @@ -312,13 +250,12 @@
   
        @param message The new diagnostic context information.  */
     public static void push(String message) {
  -    Thread key = Thread.currentThread();
  -    Stack stack = (Stack) ht.get(key);
  +    Stack stack = (Stack) tl.get();
   
       if (stack == null) {
         DiagnosticContext dc = new DiagnosticContext(message, null);
         stack = new Stack();
  -      ht.put(key, stack);
  +      tl.set(stack);
         stack.push(dc);
       } else if (stack.isEmpty()) {
         DiagnosticContext dc = new DiagnosticContext(message, null);
  @@ -332,27 +269,11 @@
     /**
        Remove the diagnostic context for this thread.
   
  -     <p>Each thread that created a diagnostic context by calling
  -     {@link #push} should call this method before exiting. Otherwise,
  -     the memory used by the <b>thread</b> cannot be reclaimed by the
  -     VM.
  -
  -     <p>As this is such an important problem in heavy duty systems and
  -     because it is difficult to always guarantee that the remove
  -     method is called before exiting a thread, this method has been
  -     augmented to lazily remove references to dead threads. In
  -     practice, this means that you can be a little sloppy and
  -     occasionally forget to call {@link #remove} before exiting a
  -     thread. However, you must call <code>remove</code> sometime. If
  -     you never call it, then your application is sure to run out of
  -     memory.
  -
  +     <p>As of log4j 1.3, the <code>NDC</code> class uses {@link ThreadLocal}
  +     technology to store the context.  It is no longer necessary to call this
  +     method.  It remains for backwards compatibility.
     */
     public static void remove() {
  -    ht.remove(Thread.currentThread());
  -
  -    // Lazily remove dead-thread references in ht.
  -    lazyRemove();
     }
   
     /**
  @@ -383,7 +304,7 @@
        @see #getDepth
        @since 0.7.5 */
     public static void setMaxDepth(int maxDepth) {
  -    Stack stack = (Stack) ht.get(Thread.currentThread());
  +    Stack stack = (Stack) tl.get();
   
       if ((stack != null) && (maxDepth < stack.size())) {
         stack.setSize(maxDepth);
  
  
  
  1.1                  logging-log4j/tests/witness/NDC.1
  
  Index: NDC.1
  ===================================================================
  DEBUG null - m1
  INFO  null - m2
  WARN  null - m3
  ERROR null - m4
  FATAL null - m5
  DEBUG n1 - m1
  INFO  n1 - m2
  WARN  n1 - m3
  ERROR n1 - m4
  FATAL n1 - m5
  DEBUG n1 n2 n3 - m1
  INFO  n1 n2 n3 - m2
  WARN  n1 n2 n3 - m3
  ERROR n1 n2 n3 - m4
  FATAL n1 n2 n3 - m5
  DEBUG n1 n2 - m1
  INFO  n1 n2 - m2
  WARN  n1 n2 - m3
  ERROR n1 n2 - m4
  FATAL n1 n2 - m5
  DEBUG null - m1
  INFO  null - m2
  WARN  null - m3
  ERROR null - m4
  FATAL null - m5
  
  
  
  1.47      +9 -0      logging-log4j/tests/build.xml
  
  Index: build.xml
  ===================================================================
  RCS file: /home/cvs/logging-log4j/tests/build.xml,v
  retrieving revision 1.46
  retrieving revision 1.47
  diff -u -r1.46 -r1.47
  --- build.xml	10 Mar 2004 16:23:19 -0000	1.46
  +++ build.xml	27 Mar 2004 06:46:27 -0000	1.47
  @@ -122,6 +122,7 @@
                                        LevelMatchFilter, DRFA, 
                                        SizeBasedRolling, Compress, 
                                        TimeBasedRolling, ReaderWriterLock,
  +                                     NDC,
                                        Plugins"/>
   
     <!-- ================================================================= -->
  @@ -177,6 +178,14 @@
         <classpath refid="tests.classpath"/>
         <formatter type="plain" usefile="false"/>
         <test name="org.apache.log4j.xml.DOMTestCase" />
  +    </junit>
  +  </target>
  +
  +  <target name="NDC" depends="build, cleanOutputDir">
  +    <junit printsummary="yes" fork="yes" haltonfailure="yes">
  +      <classpath refid="tests.classpath"/>
  +      <formatter type="plain" usefile="false"/>
  +      <test name="org.apache.log4j.NDCTestCase" />
       </junit>
     </target>
   
  
  
  
  1.1                  logging-log4j/tests/input/NDC1.properties
  
  Index: NDC1.properties
  ===================================================================
  log4j.rootCategory=DEBUG, testAppender
  log4j.appender.testAppender=org.apache.log4j.FileAppender
  log4j.appender.testAppender.file=output/temp
  log4j.appender.testAppender.Append=false
  log4j.appender.testAppender.layout=org.apache.log4j.PatternLayout
  log4j.appender.testAppender.layout.ConversionPattern=%-5p %x - %m%n
  
  

---------------------------------------------------------------------
To unsubscribe, e-mail: log4j-dev-unsubscribe@logging.apache.org
For additional commands, e-mail: log4j-dev-help@logging.apache.org