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

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ülcü + * @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) { + } +}
participants (1)
-
noreply.ceki@qos.ch