[logback-dev] svn commit: r1853 - logback/trunk/logback-core/src/main/java/ch/qos/logback/core

noreply.ceki at qos.ch noreply.ceki at qos.ch
Mon Oct 20 21:51:43 CEST 2008


Author: ceki
Date: Mon Oct 20 21:51:43 2008
New Revision: 1853

Added:
   logback/trunk/logback-core/src/main/java/ch/qos/logback/core/UnsynchronizedAppenderBase.java
Modified:
   logback/trunk/logback-core/src/main/java/ch/qos/logback/core/AppenderBase.java

Log:
LBCORE-58

UnsynchronizedAppenderBase is based on Ralph Goers contribution in LBCORE-58. 
Note that AppenderBase remains unchanged. Appenders which need to handle synchronization on their
own can do so by deriving from UnsynchronizedAppenderBase.

Modified: logback/trunk/logback-core/src/main/java/ch/qos/logback/core/AppenderBase.java
==============================================================================
--- logback/trunk/logback-core/src/main/java/ch/qos/logback/core/AppenderBase.java	(original)
+++ logback/trunk/logback-core/src/main/java/ch/qos/logback/core/AppenderBase.java	Mon Oct 20 21:51:43 2008
@@ -13,12 +13,13 @@
 import ch.qos.logback.core.spi.ContextAwareBase;
 import ch.qos.logback.core.spi.FilterAttachable;
 import ch.qos.logback.core.spi.FilterAttachableImpl;
-import ch.qos.logback.core.spi.FilterReply;
+import ch.qos.logback.core.spi.FilterReply; 
 import ch.qos.logback.core.status.WarnStatus;
 
 /**
- * This class is used to manage base functionnalities of all appenders.
+ * Sets a skeleton implementation for appenders.
  * 
+ * <p>
  * For more information about this appender, please refer to the online manual at
  * http://logback.qos.ch/manual/appenders.html#AppenderBase
  *

Added: logback/trunk/logback-core/src/main/java/ch/qos/logback/core/UnsynchronizedAppenderBase.java
==============================================================================
--- (empty file)
+++ logback/trunk/logback-core/src/main/java/ch/qos/logback/core/UnsynchronizedAppenderBase.java	Mon Oct 20 21:51:43 2008
@@ -0,0 +1,144 @@
+/**
+ * Logback: the generic, reliable, fast and flexible logging framework.
+ * 
+ * Copyright (C) 2000-2008, QOS.ch
+ * 
+ * This library is free software, you can redistribute it and/or modify it under
+ * the terms of the GNU Lesser General Public License as published by the Free
+ * Software Foundation.
+ */
+package ch.qos.logback.core;
+
+import ch.qos.logback.core.filter.Filter;
+import ch.qos.logback.core.spi.ContextAwareBase;
+import ch.qos.logback.core.spi.FilterAttachable;
+import ch.qos.logback.core.spi.FilterAttachableImpl;
+import ch.qos.logback.core.spi.FilterReply;
+import ch.qos.logback.core.status.WarnStatus;
+
+/**
+ * Similar to AppenderBase except that derived appenders need to handle 
+ * thread synchronization on their own.
+ * 
+ * @author Ceki G&uuml;lc&uuml;
+ * @author Ralph Goers
+ */
+abstract public class UnsynchronizedAppenderBase<E> extends ContextAwareBase implements
+    Appender<E>, FilterAttachable {
+
+  protected boolean started = false;
+
+  // using a ThreadLocal instead of a boolean add 75 nanoseconds per
+  // doAppend invocation. This is tolerable as doAppend takes at least a few microseconds
+  // on a real appender
+  /**
+   * The guard prevents an appender from repeatedly calling its own doAppend
+   * method.
+   */
+  private ThreadLocal<Boolean> guard = new ThreadLocal<Boolean>() {
+    protected Boolean initialValue() {
+      return false;
+    }
+  };
+
+  /**
+   * Appenders are named.
+   */
+  protected String name;
+
+  private FilterAttachableImpl fai = new FilterAttachableImpl();
+
+  public String getName() {
+    return name;
+  }
+
+  private int statusRepeatCount = 0;
+  private int exceptionCount = 0;
+
+  static final int ALLOWED_REPEATS = 5;
+
+  public synchronized void doAppend(E eventObject) {
+    // WARNING: The guard check MUST be the first statement in the
+    // doAppend() method.
+
+    // prevent re-entry.
+    if (guard.get()) {
+      return;
+    }
+
+    try {
+      guard.set(true);
+
+      if (!this.started) {
+        if (statusRepeatCount++ < ALLOWED_REPEATS) {
+          addStatus(new WarnStatus(
+              "Attempted to append to non started appender [" + name + "].",
+              this));
+        }
+        return;
+      }
+
+      if (getFilterChainDecision(eventObject) == FilterReply.DENY) {
+        return;
+      }
+
+      // ok, we now invoke derived class' implementation of append
+      this.append(eventObject);
+
+    } catch (Exception e) {
+      if (exceptionCount++ < ALLOWED_REPEATS) {
+        addError("Appender [" + name + "] failed to append.", e);
+      }
+    } finally {
+      guard.set(false);
+    }
+  }
+
+  abstract protected void append(E eventObject);
+
+  /**
+   * Set the name of this appender.
+   */
+  public void setName(String name) {
+    this.name = name;
+  }
+
+  public void start() {
+    started = true;
+  }
+
+  public void stop() {
+    started = false;
+  }
+
+  public boolean isStarted() {
+    return started;
+  }
+
+  public String toString() {
+    return this.getClass().getName() + "[" + name + "]";
+  }
+
+  public void addFilter(Filter newFilter) {
+    fai.addFilter(newFilter);
+  }
+
+  public Filter getFirstFilter() {
+    return fai.getFirstFilter();
+  }
+
+  public void clearAllFilters() {
+    fai.clearAllFilters();
+  }
+
+  public FilterReply getFilterChainDecision(Object event) {
+    return fai.getFilterChainDecision(event);
+  }
+
+  public Layout<E> getLayout() {
+    return null;
+  }
+
+  public void setLayout(Layout<E> layout) {
+  }
+}


More information about the logback-dev mailing list