[logback-dev] svn commit: r1931 - in logback/trunk/logback-classic/src: main/java/ch/qos/logback/classic main/java/ch/qos/logback/classic/spi test/java/ch/qos/logback/classic test/java/ch/qos/logback/classic/joran test/java/ch/qos/logback/classic/net/testObjectBuilders

noreply.ceki at qos.ch noreply.ceki at qos.ch
Sat Nov 1 18:17:37 CET 2008


Author: ceki
Date: Sat Nov  1 18:17:37 2008
New Revision: 1931

Added:
   logback/trunk/logback-classic/src/main/java/ch/qos/logback/classic/spi/TurboFilterList.java
      - copied, changed from r1899, /logback/trunk/logback-classic/src/main/java/ch/qos/logback/classic/spi/TurboFilterAttachableImpl.java
   logback/trunk/logback-classic/src/main/java/ch/qos/logback/classic/spi/XTurboFilterAttachable.java
      - copied, changed from r1899, /logback/trunk/logback-classic/src/main/java/ch/qos/logback/classic/spi/TurboFilterAttachable.java
Removed:
   logback/trunk/logback-classic/src/main/java/ch/qos/logback/classic/spi/TurboFilterAttachable.java
   logback/trunk/logback-classic/src/main/java/ch/qos/logback/classic/spi/TurboFilterAttachableImpl.java
Modified:
   logback/trunk/logback-classic/src/main/java/ch/qos/logback/classic/Logger.java
   logback/trunk/logback-classic/src/main/java/ch/qos/logback/classic/LoggerContext.java
   logback/trunk/logback-classic/src/test/java/ch/qos/logback/classic/LoggerPerfTest.java
   logback/trunk/logback-classic/src/test/java/ch/qos/logback/classic/TurboFilteringInLoggerTest.java
   logback/trunk/logback-classic/src/test/java/ch/qos/logback/classic/joran/JoranConfiguratorTest.java
   logback/trunk/logback-classic/src/test/java/ch/qos/logback/classic/net/testObjectBuilders/LoggingEventWithParametersBuilder.java

Log:
LBCLASSIC-54
 	 
- Heavy refactoring of TurboFilters 
  TurboFilters are now collected in a CopyOnWriteArrayList which is
  ensures safe access even if the turbo filter list is modified during
  the lifetime of the application
  
  Added test cases to ensure that performance does not degrade in an
  uncontrolled fashion
  
  More cleaning up to follow

Modified: logback/trunk/logback-classic/src/main/java/ch/qos/logback/classic/Logger.java
==============================================================================
--- logback/trunk/logback-classic/src/main/java/ch/qos/logback/classic/Logger.java	(original)
+++ logback/trunk/logback-classic/src/main/java/ch/qos/logback/classic/Logger.java	Sat Nov  1 18:17:37 2008
@@ -380,65 +380,18 @@
     return childLogger;
   }
 
-  public void trace(String msg) {
-    filterAndLog(FQCN, null, Level.TRACE, msg, null, null);
-  }
-
-  public final void trace(String format, Object arg) {
-    filterAndLog(FQCN, null, Level.TRACE, format, arg, null);
-  }
-
-  public void trace(String format, Object arg1, Object arg2) {
-    filterAndLog(FQCN, null, Level.TRACE, format, arg1, arg2, null);
-  }
-
-  public void trace(String format, Object[] argArray) {
-    filterAndLog(FQCN, null, Level.TRACE, format, argArray, null);
-  }
-
-  public void trace(String msg, Throwable t) {
-    filterAndLog(FQCN, null, Level.TRACE, msg, null, t);
-  }
-
-  public final void trace(Marker marker, String msg) {
-    filterAndLog(FQCN, marker, Level.TRACE, msg, null, null);
-  }
-
-  public void debug(String msg) {
-    filterAndLog(FQCN, null, Level.DEBUG, msg, null, null);
-  }
-
-  public final void debug(String format, Object arg) {
-    filterAndLog(FQCN, null, Level.DEBUG, format, arg, null);
-  }
-
-  public void debug(String format, Object arg1, Object arg2) {
-    filterAndLog(FQCN, null, Level.DEBUG, format, arg1, arg2, null);
-  }
-
-  public void debug(String format, Object[] argArray) {
-    filterAndLog(FQCN, null, Level.DEBUG, format, argArray, null);
-  }
-
-  public void debug(String msg, Throwable t) {
-    filterAndLog(FQCN, null, Level.DEBUG, msg, null, t);
-  }
-
-  public final void debug(Marker marker, String msg) {
-    filterAndLog(FQCN, marker, Level.DEBUG, msg, null, null);
-  }
-
   /**
    * The next methods are not merged into one because of the time we gain by not
    * creating a new Object[] with the params. This reduces the cost of not
-   * logging of about 20 nanos.
+   * logging by about 20 nanoseconds.
    */
 
-  public final void filterAndLog(final String localFQCN, final Marker marker,
-      final Level level, final String msg, final Object param, final Throwable t) {
+  private final void filterAndLog_0_Or3Plus(final String localFQCN,
+      final Marker marker, final Level level, final String msg,
+      final Object[] params, final Throwable t) {
 
-    final FilterReply decision = loggerContext.getTurboFilterChainDecision(
-        marker, this, level, msg, param, t);
+    final FilterReply decision = loggerContext.getTurboFilterChainDecision_0_3OrMore(
+        marker, this, level, msg, params, t);
 
     if (decision == FilterReply.NEUTRAL) {
       if (effectiveLevelInt > level.levelInt) {
@@ -448,16 +401,15 @@
       return;
     }
 
-    buildLoggingEventAndAppend(localFQCN, marker, level, msg,
-        new Object[] { param }, t);
+    buildLoggingEventAndAppend(localFQCN, marker, level, msg, params, t);
   }
+  
+  private final void filterAndLog_1(final String localFQCN,
+      final Marker marker, final Level level, final String msg,
+      final Object param, final Throwable t) {
 
-  public final void filterAndLog(final String localFQCN, final Marker marker,
-      final Level level, final String msg, final Object param1,
-      final Object param2, final Throwable t) {
-
-    final FilterReply decision = loggerContext.getTurboFilterChainDecision(
-        marker, this, level, msg, param1, param2, t);
+    final FilterReply decision = loggerContext.getTurboFilterChainDecision_1(
+        marker, this, level, msg, param, t);
 
     if (decision == FilterReply.NEUTRAL) {
       if (effectiveLevelInt > level.levelInt) {
@@ -467,16 +419,17 @@
       return;
     }
 
-    buildLoggingEventAndAppend(localFQCN, marker, level, msg, new Object[] {
-        param1, param2 }, t);
+    buildLoggingEventAndAppend(localFQCN, marker, level, msg,
+        new Object[] { param }, t);
   }
 
-  public final void filterAndLog(final String localFQCN, final Marker marker,
-      final Level level, final String msg, final Object[] params,
-      final Throwable t) {
 
-    final FilterReply decision = loggerContext.getTurboFilterChainDecision(
-        marker, this, level, msg, params, t);
+  private final void filterAndLog_2(final String localFQCN,
+      final Marker marker, final Level level, final String msg,
+      final Object param1, final Object param2, final Throwable t) {
+
+    final FilterReply decision = loggerContext.getTurboFilterChainDecision_2(
+        marker, this, level, msg, param1, param2, t);
 
     if (decision == FilterReply.NEUTRAL) {
       if (effectiveLevelInt > level.levelInt) {
@@ -486,9 +439,12 @@
       return;
     }
 
-    buildLoggingEventAndAppend(localFQCN, marker, level, msg, params, t);
+    buildLoggingEventAndAppend(localFQCN, marker, level, msg, new Object[] {
+        param1, param2 }, t);
   }
 
+
+
   private void buildLoggingEventAndAppend(final String localFQCN,
       final Marker marker, final Level level, final String msg,
       final Object[] params, final Throwable t) {
@@ -497,132 +453,204 @@
     callAppenders(le);
   }
 
-  final void filterAndLog(final Marker marker, final Level level,
-      final String msg, final Object param1, final Object param2,
-      final Throwable t) {
-    filterAndLog(FQCN, marker, level, msg, param1, param2, t);
+  public void trace(String msg) {
+    filterAndLog_0_Or3Plus(FQCN, null, Level.TRACE, msg, null, null);
+  }
+
+  public final void trace(String format, Object arg) {
+    filterAndLog_1(FQCN, null, Level.TRACE, format, arg, null);
+  }
+
+  public void trace(String format, Object arg1, Object arg2) {
+    filterAndLog_2(FQCN, null, Level.TRACE, format, arg1, arg2, null);
+  }
+
+  public void trace(String format, Object[] argArray) {
+    filterAndLog_0_Or3Plus(FQCN, null, Level.TRACE, format, argArray, null);
+  }
+
+  public void trace(String msg, Throwable t) {
+    filterAndLog_0_Or3Plus(FQCN, null, Level.TRACE, msg, null, t);
+  }
+
+  public final void trace(Marker marker, String msg) {
+    filterAndLog_0_Or3Plus(FQCN, marker, Level.TRACE, msg, null, null);
   }
 
   public void trace(Marker marker, String format, Object arg) {
-    filterAndLog(FQCN, marker, Level.TRACE, format, arg, null);
+    filterAndLog_1(FQCN, marker, Level.TRACE, format, arg, null);
   }
 
   public void trace(Marker marker, String format, Object arg1, Object arg2) {
-    filterAndLog(FQCN, marker, Level.TRACE, format, arg1, arg2, null);
+    filterAndLog_2(FQCN, marker, Level.TRACE, format, arg1, arg2, null);
   }
 
   public void trace(Marker marker, String format, Object[] argArray) {
-    filterAndLog(FQCN, marker, Level.TRACE, format, argArray, null);
+    filterAndLog_0_Or3Plus(FQCN, marker, Level.TRACE, format, argArray, null);
   }
 
   public void trace(Marker marker, String msg, Throwable t) {
-    filterAndLog(FQCN, marker, Level.TRACE, msg, null, t);
+    filterAndLog_0_Or3Plus(FQCN, marker, Level.TRACE, msg, null, t);
+  }
+
+  final public  boolean isDebugEnabled() {
+    return isDebugEnabled(null);
+  }
+
+  final public boolean isDebugEnabled(Marker marker) {
+    final FilterReply decision = callTurboFilters(marker, Level.DEBUG);
+    if (decision == FilterReply.NEUTRAL) {
+      return effectiveLevelInt <= Level.DEBUG_INT;
+    } else if (decision == FilterReply.DENY) {
+      return false;
+    } else if (decision == FilterReply.ACCEPT) {
+      return true;
+    } else {
+      throw new IllegalStateException("Unknown FilterReply value: " + decision);
+    }
+  }
+  
+  final public void debug(String msg) {
+    filterAndLog_0_Or3Plus(FQCN, null, Level.DEBUG, msg, null, null);
+  }
+
+  final public void debug(String format, Object arg) {
+    filterAndLog_1(FQCN, null, Level.DEBUG, format, arg, null);
+  }
+
+  final public void debug(String format, Object arg1, Object arg2) {
+    filterAndLog_2(FQCN, null, Level.DEBUG, format, arg1, arg2, null);
+  }
+
+  final public void debug(String format, Object[] argArray) {
+    filterAndLog_0_Or3Plus(FQCN, null, Level.DEBUG, format, argArray, null);
+  }
+
+  public void debug(String msg, Throwable t) {
+    filterAndLog_0_Or3Plus(FQCN, null, Level.DEBUG, msg, null, t);
+  }
+
+  public final void debug(Marker marker, String msg) {
+    filterAndLog_0_Or3Plus(FQCN, marker, Level.DEBUG, msg, null, null);
   }
 
   public void debug(Marker marker, String format, Object arg) {
-    filterAndLog(FQCN, marker, Level.DEBUG, format, arg, null);
+    filterAndLog_1(FQCN, marker, Level.DEBUG, format, arg, null);
   }
 
   public void debug(Marker marker, String format, Object arg1, Object arg2) {
-    filterAndLog(FQCN, marker, Level.DEBUG, format, arg1, arg2, null);
+    filterAndLog_2(FQCN, marker, Level.DEBUG, format, arg1, arg2, null);
   }
 
   public void debug(Marker marker, String format, Object[] argArray) {
-    filterAndLog(FQCN, marker, Level.DEBUG, format, argArray, null);
+    filterAndLog_0_Or3Plus(FQCN, marker, Level.DEBUG, format, argArray, null);
   }
 
   public void debug(Marker marker, String msg, Throwable t) {
-    filterAndLog(FQCN, marker, Level.DEBUG, msg, null, t);
+    filterAndLog_0_Or3Plus(FQCN, marker, Level.DEBUG, msg, null, t);
   }
 
   public void error(String msg) {
-    filterAndLog(FQCN, null, Level.ERROR, msg, null, null);
+    filterAndLog_0_Or3Plus(FQCN, null, Level.ERROR, msg, null, null);
   }
 
   public void error(String format, Object arg) {
-    filterAndLog(FQCN, null, Level.ERROR, format, arg, null);
+    filterAndLog_1(FQCN, null, Level.ERROR, format, arg, null);
   }
 
   public void error(String format, Object arg1, Object arg2) {
-    filterAndLog(FQCN, null, Level.ERROR, format, arg1, arg2, null);
+    filterAndLog_2(FQCN, null, Level.ERROR, format, arg1, arg2, null);
   }
 
   public void error(String format, Object[] argArray) {
-    filterAndLog(FQCN, null, Level.ERROR, format, argArray, null);
+    filterAndLog_0_Or3Plus(FQCN, null, Level.ERROR, format, argArray, null);
   }
 
   public void error(String msg, Throwable t) {
-    filterAndLog(FQCN, null, Level.ERROR, msg, null, t);
+    filterAndLog_0_Or3Plus(FQCN, null, Level.ERROR, msg, null, t);
   }
 
   public void error(Marker marker, String msg) {
-    filterAndLog(FQCN, marker, Level.ERROR, msg, null, null);
+    filterAndLog_0_Or3Plus(FQCN, marker, Level.ERROR, msg, null, null);
   }
 
   public void error(Marker marker, String format, Object arg) {
-    filterAndLog(FQCN, marker, Level.ERROR, format, arg, null);
+    filterAndLog_1(FQCN, marker, Level.ERROR, format, arg, null);
   }
 
   public void error(Marker marker, String format, Object arg1, Object arg2) {
-    filterAndLog(FQCN, marker, Level.ERROR, format, arg1, arg2, null);
+    filterAndLog_2(FQCN, marker, Level.ERROR, format, arg1, arg2, null);
   }
 
   public void error(Marker marker, String format, Object[] argArray) {
-    filterAndLog(FQCN, marker, Level.ERROR, format, argArray, null);
+    filterAndLog_0_Or3Plus(FQCN, marker, Level.ERROR, format, argArray, null);
   }
 
   public void error(Marker marker, String msg, Throwable t) {
-    filterAndLog(FQCN, marker, Level.ERROR, msg, null, t);
+    filterAndLog_0_Or3Plus(FQCN, marker, Level.ERROR, msg, null, t);
   }
 
+  public boolean isInfoEnabled() {
+    return isInfoEnabled(null);
+  }
+  
+  public boolean isInfoEnabled(Marker marker) {
+    FilterReply decision = callTurboFilters(marker, Level.INFO);
+    if (decision == FilterReply.NEUTRAL) {
+      return effectiveLevelInt <= Level.INFO_INT;
+    } else if (decision == FilterReply.DENY) {
+      return false;
+    } else if (decision == FilterReply.ACCEPT) {
+      return true;
+    } else {
+      throw new IllegalStateException("Unknown FilterReply value: " + decision);
+    }
+  }
+  
   public void info(String msg) {
-    filterAndLog(FQCN, null, Level.INFO, msg, null, null);
+    filterAndLog_0_Or3Plus(FQCN, null, Level.INFO, msg, null, null);
   }
 
   public void info(String format, Object arg) {
-    filterAndLog(FQCN, null, Level.INFO, format, arg, null);
+    filterAndLog_1(FQCN, null, Level.INFO, format, arg, null);
   }
 
   public void info(String format, Object arg1, Object arg2) {
-    filterAndLog(FQCN, null, Level.INFO, format, arg1, arg2, null);
+    filterAndLog_2(FQCN, null, Level.INFO, format, arg1, arg2, null);
   }
 
   public void info(String format, Object[] argArray) {
-    filterAndLog(FQCN, null, Level.INFO, format, argArray, null);
+    filterAndLog_0_Or3Plus(FQCN, null, Level.INFO, format, argArray, null);
   }
 
   public void info(String msg, Throwable t) {
-    filterAndLog(FQCN, null, Level.INFO, msg, null, t);
+    filterAndLog_0_Or3Plus(FQCN, null, Level.INFO, msg, null, t);
   }
 
   public void info(Marker marker, String msg) {
-    filterAndLog(FQCN, marker, Level.INFO, msg, null, null);
+    filterAndLog_0_Or3Plus(FQCN, marker, Level.INFO, msg, null, null);
   }
 
   public void info(Marker marker, String format, Object arg) {
-    filterAndLog(FQCN, marker, Level.INFO, format, arg, null);
+    filterAndLog_1(FQCN, marker, Level.INFO, format, arg, null);
   }
 
   public void info(Marker marker, String format, Object arg1, Object arg2) {
-    filterAndLog(FQCN, marker, Level.INFO, format, arg1, arg2, null);
+    filterAndLog_2(FQCN, marker, Level.INFO, format, arg1, arg2, null);
   }
 
   public void info(Marker marker, String format, Object[] argArray) {
-    filterAndLog(FQCN, marker, Level.INFO, format, argArray, null);
+    filterAndLog_0_Or3Plus(FQCN, marker, Level.INFO, format, argArray, null);
   }
 
   public void info(Marker marker, String msg, Throwable t) {
-    filterAndLog(FQCN, marker, Level.INFO, msg, null, t);
+    filterAndLog_0_Or3Plus(FQCN, marker, Level.INFO, msg, null, t);
   }
 
   public final boolean isTraceEnabled() {
     return isTraceEnabled(null);
   }
 
-  public final boolean isDebugEnabled() {
-    return isDebugEnabled(null);
-  }
-
   public boolean isTraceEnabled(Marker marker) {
     final FilterReply decision = callTurboFilters(marker, Level.TRACE);
     if (decision == FilterReply.NEUTRAL) {
@@ -636,18 +664,7 @@
     }
   }
 
-  public boolean isDebugEnabled(Marker marker) {
-    final FilterReply decision = callTurboFilters(marker, Level.DEBUG);
-    if (decision == FilterReply.NEUTRAL) {
-      return effectiveLevelInt <= Level.DEBUG_INT;
-    } else if (decision == FilterReply.DENY) {
-      return false;
-    } else if (decision == FilterReply.ACCEPT) {
-      return true;
-    } else {
-      throw new IllegalStateException("Unknown FilterReply value: " + decision);
-    }
-  }
+
 
   public final boolean isErrorEnabled() {
     return isErrorEnabled(null);
@@ -666,22 +683,6 @@
     }
   }
 
-  public boolean isInfoEnabled() {
-    return isInfoEnabled(null);
-  }
-
-  public boolean isInfoEnabled(Marker marker) {
-    FilterReply decision = callTurboFilters(marker, Level.INFO);
-    if (decision == FilterReply.NEUTRAL) {
-      return effectiveLevelInt <= Level.INFO_INT;
-    } else if (decision == FilterReply.DENY) {
-      return false;
-    } else if (decision == FilterReply.ACCEPT) {
-      return true;
-    } else {
-      throw new IllegalStateException("Unknown FilterReply value: " + decision);
-    }
-  }
 
   public boolean isWarnEnabled() {
     return isWarnEnabled(null);
@@ -719,43 +720,43 @@
   }
 
   public void warn(String msg) {
-    filterAndLog(FQCN, null, Level.WARN, msg, null, null);
+    filterAndLog_0_Or3Plus(FQCN, null, Level.WARN, msg, null, null);
   }
 
   public void warn(String msg, Throwable t) {
-    filterAndLog(FQCN, null, Level.WARN, msg, null, t);
+    filterAndLog_0_Or3Plus(FQCN, null, Level.WARN, msg, null, t);
   }
 
   public void warn(String format, Object arg) {
-    filterAndLog(FQCN, null, Level.WARN, format, arg, null);
+    filterAndLog_1(FQCN, null, Level.WARN, format, arg, null);
   }
 
   public void warn(String format, Object arg1, Object arg2) {
-    filterAndLog(FQCN, null, Level.WARN, format, arg1, arg2, null);
+    filterAndLog_2(FQCN, null, Level.WARN, format, arg1, arg2, null);
   }
 
   public void warn(String format, Object[] argArray) {
-    filterAndLog(FQCN, null, Level.WARN, format, argArray, null);
+    filterAndLog_0_Or3Plus(FQCN, null, Level.WARN, format, argArray, null);
   }
 
   public void warn(Marker marker, String msg) {
-    filterAndLog(FQCN, marker, Level.WARN, msg, null, null);
+    filterAndLog_0_Or3Plus(FQCN, marker, Level.WARN, msg, null, null);
   }
 
   public void warn(Marker marker, String format, Object arg) {
-    filterAndLog(FQCN, marker, Level.WARN, format, arg, null);
+    filterAndLog_1(FQCN, marker, Level.WARN, format, arg, null);
   }
 
   public void warn(Marker marker, String format, Object[] argArray) {
-    filterAndLog(FQCN, marker, Level.WARN, format, argArray, null);
+    filterAndLog_0_Or3Plus(FQCN, marker, Level.WARN, format, argArray, null);
   }
 
   public void warn(Marker marker, String format, Object arg1, Object arg2) {
-    filterAndLog(FQCN, marker, Level.WARN, format, arg1, arg2, null);
+    filterAndLog_2(FQCN, marker, Level.WARN, format, arg1, arg2, null);
   }
 
   public void warn(Marker marker, String msg, Throwable t) {
-    filterAndLog(FQCN, marker, Level.WARN, msg, null, t);
+    filterAndLog_0_Or3Plus(FQCN, marker, Level.WARN, msg, null, t);
   }
 
   public boolean isAdditive() {
@@ -782,7 +783,7 @@
    * @return the reply given by the TurboFilters
    */
   private FilterReply callTurboFilters(Marker marker, Level level) {
-    return loggerContext.getTurboFilterChainDecision(marker, this, level, null,
+    return loggerContext.getTurboFilterChainDecision_0_3OrMore(marker, this, level, null,
         null, null);
   }
 
@@ -825,7 +826,7 @@
     default:
       throw new IllegalArgumentException(levelInt + " not a valid level value");
     }
-    filterAndLog(fqcn, marker, level, message, null, t);
+    filterAndLog_0_Or3Plus(fqcn, marker, level, message, null, t);
   }
 
   /**

Modified: logback/trunk/logback-classic/src/main/java/ch/qos/logback/classic/LoggerContext.java
==============================================================================
--- logback/trunk/logback-classic/src/main/java/ch/qos/logback/classic/LoggerContext.java	(original)
+++ logback/trunk/logback-classic/src/main/java/ch/qos/logback/classic/LoggerContext.java	Sat Nov  1 18:17:37 2008
@@ -23,8 +23,7 @@
 import ch.qos.logback.classic.spi.ContextListener;
 import ch.qos.logback.classic.spi.LoggerComparator;
 import ch.qos.logback.classic.spi.LoggerContextRemoteView;
-import ch.qos.logback.classic.spi.TurboFilterAttachable;
-import ch.qos.logback.classic.spi.TurboFilterAttachableImpl;
+import ch.qos.logback.classic.spi.TurboFilterList;
 import ch.qos.logback.classic.turbo.TurboFilter;
 import ch.qos.logback.core.ContextBase;
 import ch.qos.logback.core.CoreConstants;
@@ -44,7 +43,7 @@
  * @author Ceki Gulcu
  */
 public class LoggerContext extends ContextBase implements ILoggerFactory,
-    TurboFilterAttachable, LifeCycle {
+    LifeCycle {
 
   public static final String ROOT_NAME = "root";
 
@@ -60,10 +59,14 @@
   private Hashtable<String, Logger> loggerCache;
 
   private LoggerContextRemoteView loggerContextRemoteView;
-  private TurboFilterAttachableImpl turboFilterAI = null;
+  private final TurboFilterList turboFilterAI = new TurboFilterList();
 
   boolean started = false;
 
+  public TurboFilterList getTurboFilterAI() {
+    return turboFilterAI;
+  }
+  
   public LoggerContext() {
     super();
     this.loggerCache = new Hashtable<String, Logger>();
@@ -104,10 +107,10 @@
 
   public final Logger getLogger(final String name) {
 
-    if(name == null) {
+    if (name == null) {
       throw new IllegalArgumentException("name argument cannot be null");
     }
-    
+
     // if we are asking for the root logger, then let us return it without
     // wasting time
     if (ROOT_NAME.equalsIgnoreCase(name)) {
@@ -206,55 +209,41 @@
   }
 
   public void addTurboFilter(TurboFilter newFilter) {
-    if (turboFilterAI == null) {
-      turboFilterAI = new TurboFilterAttachableImpl();
-    }
-    turboFilterAI.addTurboFilter(newFilter);
+    turboFilterAI.add(newFilter);
   }
 
   public void clearAllTurboFilters() {
-    if (turboFilterAI == null) {
-      return;
-    }
-    turboFilterAI.clearAllTurboFilters();
-    turboFilterAI = null;
+    turboFilterAI.clear();
   }
 
-  final public FilterReply getTurboFilterChainDecision(final Marker marker,
+  final public FilterReply getTurboFilterChainDecision_0_3OrMore(final Marker marker,
       final Logger logger, final Level level, final String format,
       final Object[] params, final Throwable t) {
-    if (turboFilterAI == null) {
+    if (turboFilterAI.size() == 0) {
       return FilterReply.NEUTRAL;
     }
-    return turboFilterAI.getTurboFilterChainDecision(marker, logger, level, format,
-        params, t);
+    return turboFilterAI.getTurboFilterChainDecision(marker, logger, level,
+        format, params, t);
   }
 
-  final public FilterReply getTurboFilterChainDecision(final Marker marker,
+  final public FilterReply getTurboFilterChainDecision_1(final Marker marker,
       final Logger logger, final Level level, final String format,
       final Object param, final Throwable t) {
-    if (turboFilterAI == null) {
+    if (turboFilterAI.size() == 0) {
       return FilterReply.NEUTRAL;
     }
-    return turboFilterAI.getTurboFilterChainDecision(marker, logger, level, format,
-        new Object[] { param }, t);
+    return turboFilterAI.getTurboFilterChainDecision(marker, logger, level,
+        format, new Object[] { param }, t);
   }
 
-  final public FilterReply getTurboFilterChainDecision(final Marker marker,
+  final public FilterReply getTurboFilterChainDecision_2(final Marker marker,
       final Logger logger, final Level level, final String format,
       final Object param1, final Object param2, final Throwable t) {
-    if (turboFilterAI == null) {
+    if (turboFilterAI.size() == 0) {
       return FilterReply.NEUTRAL;
     }
-    return turboFilterAI.getTurboFilterChainDecision(marker, logger, level, format,
-        new Object[] { param1, param2 }, t);
-  }
-
-  public TurboFilter getFirstTurboFilter() {
-    if (turboFilterAI == null) {
-      return null;
-    }
-    return turboFilterAI.getFirstTurboFilter();
+    return turboFilterAI.getTurboFilterChainDecision(marker, logger, level,
+        format, new Object[] { param1, param2 }, t);
   }
 
   public void addListener(ContextListener listener) {
@@ -289,9 +278,9 @@
   public void stop() {
     started = false;
   }
-  
+
   @Override
   public String toString() {
-    return this.getClass().getName()+"["+getName()+"]";
+    return this.getClass().getName() + "[" + getName() + "]";
   }
 }

Copied: logback/trunk/logback-classic/src/main/java/ch/qos/logback/classic/spi/TurboFilterList.java (from r1899, /logback/trunk/logback-classic/src/main/java/ch/qos/logback/classic/spi/TurboFilterAttachableImpl.java)
==============================================================================
--- /logback/trunk/logback-classic/src/main/java/ch/qos/logback/classic/spi/TurboFilterAttachableImpl.java	(original)
+++ logback/trunk/logback-classic/src/main/java/ch/qos/logback/classic/spi/TurboFilterList.java	Sat Nov  1 18:17:37 2008
@@ -9,6 +9,8 @@
  */
 package ch.qos.logback.classic.spi;
 
+import java.util.concurrent.CopyOnWriteArrayList;
+
 import org.slf4j.Marker;
 
 import ch.qos.logback.classic.Level;
@@ -17,72 +19,60 @@
 import ch.qos.logback.core.spi.FilterReply;
 
 /**
- * Implementation of ClassicFilterAttachable.
+ * Implementation of TurboFilterAttachable.
  * 
  * @author Ceki G&uuml;lc&uuml;
  */
-final public class TurboFilterAttachableImpl implements TurboFilterAttachable {
-
-  TurboFilter headFilter;
-  TurboFilter tailFilter;
-
-  /**
-   * Add a filter to end of the filter list.
-   */
-  public void addTurboFilter(TurboFilter newFilter) {
-    if (headFilter == null) {
-      headFilter = newFilter;
-      tailFilter = newFilter;
-    } else {
-      tailFilter.setNext(newFilter);
-      tailFilter = newFilter;
-    }
-  }
-
-  /**
-   * Get first filter in the chain.
-   */
-  public TurboFilter getFirstTurboFilter() {
-    return headFilter;
-  }
+final public class TurboFilterList extends CopyOnWriteArrayList<TurboFilter> {
 
-  /**
-   * Clear the filter chain
-   */
-  public void clearAllTurboFilters() {
-    TurboFilter f = headFilter;
-    while (f != null) {
-      final TurboFilter next = f.getNext();
-      f.setNext(null);
-      f = next;
-    }
-    f = null;
-    headFilter = null;
-    tailFilter = null;
-  }
+  private static final long serialVersionUID = 1L;
 
   /**
-   * Loop through the filters in the chain. As soon as a filter decides on 
+   * Loop through the filters in the chain. As soon as a filter decides on
    * ACCEPT or DENY, then that value is returned. If all of the filters return
-   * NEUTRAL, then  NEUTRAL is returned.
+   * NEUTRAL, then NEUTRAL is returned.
    */
-  public final FilterReply getTurboFilterChainDecision(final Marker marker, final Logger logger,
-      final Level level, final String format, final Object[] params, final Throwable t) {
-    TurboFilter f = headFilter;
-
+  public final FilterReply getTurboFilterChainDecision(final Marker marker,
+      final Logger logger, final Level level, final String format,
+      final Object[] params, final Throwable t) {
     
-    while (f != null) {
-      switch (f.decide(marker, logger,  level,  format, params,  t)) {
-      case DENY:
-        return FilterReply.DENY;
-
-      case ACCEPT:
-        return FilterReply.ACCEPT;
-
-      case NEUTRAL:
-        f = f.getNext();
+    
+    final int size = size();
+//    if (size == 0) {
+//      return FilterReply.NEUTRAL;
+//    }
+    if (size == 1) {
+      try {
+        TurboFilter tf = get(0);
+        return tf.decide(marker, logger, level, format, params, t);
+      } catch (IndexOutOfBoundsException iobe) {
+        return FilterReply.NEUTRAL;
+      }
+    }
+    
+    Object[] tfa = toArray();
+    final int len = tfa.length;
+    for (int i = 0; i < len; i++) {
+    //for (TurboFilter tf : this) {
+      final TurboFilter tf = (TurboFilter) tfa[i];
+      final FilterReply r = tf.decide(marker, logger, level, format, params, t);
+      if (r == FilterReply.DENY || r == FilterReply.ACCEPT) {
+        return r;
       }
     }
     return FilterReply.NEUTRAL;
   }
+
+  // public boolean remove(TurboFilter turboFilter) {
+  // return tfList.remove(turboFilter);
+  // }
+  //
+  // public TurboFilter remove(int index) {
+  // return tfList.remove(index);
+  // }
+  //
+  // final public int size() {
+  // return tfList.size();
+  // }
+
 }

Copied: logback/trunk/logback-classic/src/main/java/ch/qos/logback/classic/spi/XTurboFilterAttachable.java (from r1899, /logback/trunk/logback-classic/src/main/java/ch/qos/logback/classic/spi/TurboFilterAttachable.java)
==============================================================================
--- /logback/trunk/logback-classic/src/main/java/ch/qos/logback/classic/spi/TurboFilterAttachable.java	(original)
+++ logback/trunk/logback-classic/src/main/java/ch/qos/logback/classic/spi/XTurboFilterAttachable.java	Sat Nov  1 18:17:37 2008
@@ -8,23 +8,61 @@
 import ch.qos.logback.core.spi.FilterReply;
 
 /**
- * Interface for attaching {@link TurboFilter} instances to objects.
+ * Interface for attaching {@link TurboFilter} instances to container object.
+ * 
+ * <p>The container will implement this interface if it wishes that TurboFilter
+ * can be attached to it.
  * 
  * @author Ceki G&uuml;lc&uuml;
  */
-public interface TurboFilterAttachable {
+public interface XTurboFilterAttachable {
+
+  /**
+   * Add a filter at the end of .
+   * 
+   * @param newFilter
+   *                the filer to add
+   */
+  public boolean add(TurboFilter newFilter);
+
+  /**
+   * Add a filter at a specified position
+   * 
+   * @param index
+   *                the position at which to insert the new element
+   * @param newFilter
+   *                the filter to add
+   */
+  public void add(int index, TurboFilter newFilter);
+
+  /**
+   * Clear the chain.
+   */
+  public void clear();
 
   /**
-   * Add a filter.
+   * Remove the specified element from the filter chain.
+   * 
+   * @param turboFilter
+   * @return true if the chain contained the specified turbo filter
    */
-  public void addTurboFilter(TurboFilter newFilter);
+  public boolean remove(Object o);
 
   /**
-   * Get first filter in the chain.
+   * Remove a turbo filter at a specified position in this list.
+   * 
+   * @param index
+   *                of the filter to be removed
+   * @return the filter previously at the specified position
    */
-  public TurboFilter getFirstTurboFilter();
+  public TurboFilter remove(int index);
 
-  public void clearAllTurboFilters();
+  /**
+   * Returns the number of elements in this chain.
+   * 
+   * @return the number of filters in this chain.
+   */
+  public int size();
 
   /**
    * Loop through the filters in the chain. As soon as a filter decides on

Modified: logback/trunk/logback-classic/src/test/java/ch/qos/logback/classic/LoggerPerfTest.java
==============================================================================
--- logback/trunk/logback-classic/src/test/java/ch/qos/logback/classic/LoggerPerfTest.java	(original)
+++ logback/trunk/logback-classic/src/test/java/ch/qos/logback/classic/LoggerPerfTest.java	Sat Nov  1 18:17:37 2008
@@ -24,109 +24,135 @@
 
 public class LoggerPerfTest {
 
-  long NANOS_IN_ONE_SEC = 1000*1000*1000L;
-  static long NORMAL_RUN_LENGTH = 1000 * 1000;
+  static final long NANOS_IN_ONE_SEC = 1000 * 1000 * 1000L;
+  static long NORMAL_RUN_LENGTH = 1 * 1000 * 1000;
   static long SHORTENED_RUN_LENGTH = 500 * 1000;
-  
-  
+
+  LoggerContext lc = new LoggerContext();
+  Logger lbLogger = lc.getLogger(this.getClass());
+  org.slf4j.Logger logger = lbLogger;
+
   @Before
   public void setUp() throws Exception {
   }
 
+  // ===========================================================================
   @Test
-  public void testDurationOfDisabledLogWithStraightStringParameter() {
-    computeDurationOfDisabledLogWithStraightStringParameter(NORMAL_RUN_LENGTH);
-    double avg = computeDurationOfDisabledLogWithStraightStringParameter(NORMAL_RUN_LENGTH);
+  public void durationOfDisabledLogsWith_1_NOPFilter() {
+    double avg = computeDurationOfDisabledLogsWith_1_NOPFilter(1,
+        NORMAL_RUN_LENGTH);
+    System.out.println("durationOfDisabledLogsWith_1_NOPFilter=" + avg);
+    long referencePerf = 60;
 
-    long referencePerf = 17;
     BogoPerf.assertDuration(avg, referencePerf, CoreConstants.REFERENCE_BIPS);
   }
 
-  double computeDurationOfDisabledLogWithStraightStringParameter(long len) {
-    LoggerContext lc = new LoggerContext();
-    Logger logger = lc.getLogger(this.getClass());
-    logger.setLevel(Level.OFF);
-    for (long i = 0; i < len; i++) {
-      logger.debug("Toto");
+  double computeDurationOfDisabledLogsWith_1_NOPFilter(int numOfFilters,
+      long len) {
+    for (int i = 0; i < numOfFilters; i++) {
+      lc.addTurboFilter(new NOPTurboFilter());
     }
+    lbLogger.setLevel(Level.OFF);
+    for (long i = 0; i < len; i++)
+      logger.debug("Toto");
+
     long start = System.nanoTime();
-    for (long i = 0; i < len; i++) {
+    for (long i = 0; i < len; i++)
       logger.debug("Toto");
-    }
-    long end = System.nanoTime();
-    return (end - start) / len;
+
+    return (System.nanoTime() - start) / len;
   }
 
+  // ===========================================================================
   @Test
-  public void testDurationOfDisabledLogWithParameters() {
-    computeDurationOfDisabledLogWithParameters(NORMAL_RUN_LENGTH);
-    double avgDuration = computeDurationOfDisabledLogWithParameters(NORMAL_RUN_LENGTH);
-    long referencePerf = 36;
-    BogoPerf.assertDuration(avgDuration, referencePerf, CoreConstants.REFERENCE_BIPS);
-  }
-  
-  double computeDurationOfDisabledLogWithParameters(long len) {
-    LoggerContext lc = new LoggerContext();
-    Logger logger = lc.getLogger(this.getClass());
-    logger.setLevel(Level.OFF);
-    for (long i = 0; i < len; i++) {
-      logger.debug("Toto {}", i);
-    }
+  public void durationOfIsDebugEnabled() {
+    double avg = computedurationOfIsDebugEnabled(10 * NORMAL_RUN_LENGTH);
+    System.out.println("durationOfIsDebugEnabled=" + avg);
+
+    long referencePerf = 15;
+    BogoPerf.assertDuration(avg, referencePerf, CoreConstants.REFERENCE_BIPS);
+  }
+
+  double computedurationOfIsDebugEnabled(final long len) {
+    lbLogger.setLevel(Level.OFF);
+    for (long i = 0; i < len; i++)
+      logger.isDebugEnabled();
+
     long start = System.nanoTime();
-    for (long i = 0; i < len; i++) {
-      logger.debug("Toto {}", i);
-    }
-    long end = System.nanoTime();
-    return (end - start) / len;
+    for (long i = 0; i < len; i++)
+      logger.isDebugEnabled();
+    return (System.nanoTime() - start) / len;
   }
 
+  // ===========================================================================
   @Test
-  public void testDurationOfEnabledLog() {
-    if(Env.isLinux()) {
-      // the JIT on Linux behaves very differently
-      return;
-    }
-    computeDurationOfEnabledLog(SHORTENED_RUN_LENGTH);
-    double avgDuration = computeDurationOfEnabledLog(SHORTENED_RUN_LENGTH);
-    long referencePerf = 500;
-    BogoPerf.assertDuration(avgDuration, referencePerf, CoreConstants.REFERENCE_BIPS);
+  public void durationOfDisabledLog_NoParameters() {
+    double avg = computeDurationOfDisabledLog_NoParameters(10 * NORMAL_RUN_LENGTH);
+    System.out.println("durationOfDisabledLog_NoParameters=" + avg);
+
+    long referencePerf = 18;
+    BogoPerf.assertDuration(avg, referencePerf, CoreConstants.REFERENCE_BIPS);
   }
-  
-  double computeDurationOfEnabledLog(long len) {
-    LoggerContext lc = new LoggerContext();
-    Logger logger = lc.getLogger(this.getClass());
-    logger.setLevel(Level.ALL);
-    NOPAppender<LoggingEvent> nopAppender = new NOPAppender<LoggingEvent>();
-    nopAppender.start();
-    logger.addAppender(nopAppender);
-    for (long i = 0; i < len; i++) {
+
+  double computeDurationOfDisabledLog_NoParameters(final long len) {
+    lbLogger.setLevel(Level.OFF);
+    for (long i = 0; i < len; i++)
       logger.debug("Toto");
-    }
+
     long start = System.nanoTime();
-    for (long i = 0; i < len; i++) {
+    for (long i = 0; i < len; i++)
       logger.debug("Toto");
-    }
+    return (System.nanoTime() - start) / len;
+  }
+
+  // ===========================================================================
+
+  @Test
+  public void durationOfDisabledLog_1_Parameter() {
+    double avgDuration = computeDurationOfDisabledLog_1_Parameter(NORMAL_RUN_LENGTH);
+    System.out.println("durationOfDisabledLog_1_Parameter=" + avgDuration);
+
+    long referencePerf = 30;
+    BogoPerf.assertDuration(avgDuration, referencePerf,
+        CoreConstants.REFERENCE_BIPS);
+  }
+
+  double computeDurationOfDisabledLog_1_Parameter(long len) {
+    lbLogger.setLevel(Level.OFF);
+    final Object o = new Object();
+    for (long i = 0; i < len; i++)
+      logger.debug("Toto {}", o);
+
+    long start = System.nanoTime();
+    for (long i = 0; i < len; i++)
+      logger.debug("Toto {}", o);
+
     long end = System.nanoTime();
     return (end - start) / len;
   }
 
+  // ===========================================================================
+
   @Test
-  public void testComputeDurationOfDisabledLogsWithNOPFilter() {
-    computeDurationOfDisabledLogsWithNOPFilter(NORMAL_RUN_LENGTH);
-    double avg = computeDurationOfDisabledLogsWithNOPFilter(NORMAL_RUN_LENGTH);
-    long referencePerf = 48;
-    BogoPerf.assertDuration(avg, referencePerf, CoreConstants.REFERENCE_BIPS);
+  public void durationOfEnabledLog() {
+    if (Env.isLinux()) {
+      // the JIT on Linux behaves very differently
+      return;
+    }
+    double avgDuration = computeDurationOfEnabledLog(SHORTENED_RUN_LENGTH);
+    System.out.println("durationOfEnabledLog=" + avgDuration);
+
+    long referencePerf = 800;
+    BogoPerf.assertDuration(avgDuration, referencePerf,
+        CoreConstants.REFERENCE_BIPS);
   }
 
-  double computeDurationOfDisabledLogsWithNOPFilter(long len) {
-    LoggerContext lc = new LoggerContext();
-    NOPAppender<LoggingEvent> mopAppender = new NOPAppender<LoggingEvent>();
-    NOPTurboFilter nopFilter = new NOPTurboFilter();
-    nopFilter.setName("nop");
-    mopAppender.start();
-    lc.addTurboFilter(nopFilter);
-    Logger logger = lc.getLogger(this.getClass());
-    logger.setLevel(Level.OFF);
+  double computeDurationOfEnabledLog(long len) {
+    lbLogger.setLevel(Level.ALL);
+
+    NOPAppender<LoggingEvent> nopAppender = new NOPAppender<LoggingEvent>();
+    nopAppender.start();
+    ((ch.qos.logback.classic.Logger) logger).addAppender(nopAppender);
     for (long i = 0; i < len; i++) {
       logger.debug("Toto");
     }
@@ -138,18 +164,20 @@
     return (end - start) / len;
   }
 
+  // ===========================================================================
+
   @Test
   public void testThreadedLogging() throws InterruptedException {
-    LoggerContext lc = new LoggerContext();
     SleepAppender<LoggingEvent> appender = new SleepAppender<LoggingEvent>();
-    
+
     int MILLIS_PER_CALL = 250;
-    int NANOS_PER_CALL = 250*1000*1000;;
+    int NANOS_PER_CALL = 250 * 1000 * 1000;
+
     appender.setDuration(MILLIS_PER_CALL);
     appender.start();
-    Logger logger = lc.getLogger(this.getClass());
-    logger.addAppender(appender);
-    logger.setLevel(Level.DEBUG);
+
+    lbLogger.addAppender(appender);
+    lbLogger.setLevel(Level.DEBUG);
     long start;
     long end;
     int threadCount = 10;
@@ -168,9 +196,10 @@
     end = System.nanoTime();
     double tolerance = threadCount * .125; // Very little thread contention
     // should occur in this test.
-    double max = ((((double) NANOS_PER_CALL) / NANOS_IN_ONE_SEC) * iterCount) * tolerance;
-    double serialized = (((double) NANOS_PER_CALL) / NANOS_IN_ONE_SEC) * iterCount
-        * threadCount;
+    double max = ((((double) NANOS_PER_CALL) / NANOS_IN_ONE_SEC) * iterCount)
+        * tolerance;
+    double serialized = (((double) NANOS_PER_CALL) / NANOS_IN_ONE_SEC)
+        * iterCount * threadCount;
     double actual = ((double) (end - start)) / NANOS_IN_ONE_SEC;
     System.out
         .printf(
@@ -181,10 +210,10 @@
 
   // ============================================================
   private static class TestRunner extends Thread {
-    private Logger logger;
+    private org.slf4j.Logger logger;
     private long len;
 
-    public TestRunner(Logger logger, long len) {
+    public TestRunner(org.slf4j.Logger logger, long len) {
       this.logger = logger;
       this.len = len;
     }

Modified: logback/trunk/logback-classic/src/test/java/ch/qos/logback/classic/TurboFilteringInLoggerTest.java
==============================================================================
--- logback/trunk/logback-classic/src/test/java/ch/qos/logback/classic/TurboFilteringInLoggerTest.java	(original)
+++ logback/trunk/logback-classic/src/test/java/ch/qos/logback/classic/TurboFilteringInLoggerTest.java	Sat Nov  1 18:17:37 2008
@@ -133,9 +133,9 @@
 
   public void testLoggingContextShutdownAndReset() {
     addYesFilter();
-    assertNotNull(context.getFirstTurboFilter());
+    assertNotNull(context.getTurboFilterAI().get(0));
     context.shutdownAndReset();
-    assertNull(context.getFirstTurboFilter());
+    assertEquals(0, context.getTurboFilterAI().size());
   }
   
 }

Modified: logback/trunk/logback-classic/src/test/java/ch/qos/logback/classic/joran/JoranConfiguratorTest.java
==============================================================================
--- logback/trunk/logback-classic/src/test/java/ch/qos/logback/classic/joran/JoranConfiguratorTest.java	(original)
+++ logback/trunk/logback-classic/src/test/java/ch/qos/logback/classic/joran/JoranConfiguratorTest.java	Sat Nov  1 18:17:37 2008
@@ -99,7 +99,7 @@
     // and place the relevant object correctly.
     configure(TeztConstants.TEST_DIR_PREFIX + "input/joran/turbo.xml");
 
-    TurboFilter filter = loggerContext.getFirstTurboFilter();
+    TurboFilter filter = loggerContext.getTurboFilterAI().get(0);
     assertTrue(filter instanceof NOPTurboFilter);
   }
 
@@ -113,7 +113,7 @@
 
     // StatusPrinter.print(loggerContext.getStatusManager());
 
-    TurboFilter filter = loggerContext.getFirstTurboFilter();
+    TurboFilter filter = loggerContext.getTurboFilterAI().get(0);
     assertTrue(filter instanceof DebugUsersTurboFilter);
     DebugUsersTurboFilter dutf = (DebugUsersTurboFilter) filter;
     assertEquals(2, dutf.getUsers().size());

Modified: logback/trunk/logback-classic/src/test/java/ch/qos/logback/classic/net/testObjectBuilders/LoggingEventWithParametersBuilder.java
==============================================================================
--- logback/trunk/logback-classic/src/test/java/ch/qos/logback/classic/net/testObjectBuilders/LoggingEventWithParametersBuilder.java	(original)
+++ logback/trunk/logback-classic/src/test/java/ch/qos/logback/classic/net/testObjectBuilders/LoggingEventWithParametersBuilder.java	Sat Nov  1 18:17:37 2008
@@ -40,9 +40,6 @@
     le.setLoggerRemoteView(logger.getLoggerRemoteView());
     le.setThreadName("threadName");
 
-    if (i == 2) {
-      System.out.println(le.getFormattedMessage());
-    }
     return le;
   }
 }


More information about the logback-dev mailing list