001: /* ====================================================================
002: * The Apache Software License, Version 1.1
003: *
004: * Copyright (c) 1997-2003 The Apache Software Foundation. All rights
005: * reserved.
006: *
007: * Redistribution and use in source and binary forms, with or without
008: * modification, are permitted provided that the following conditions
009: * are met:
010: *
011: * 1. Redistributions of source code must retain the above copyright
012: * notice, this list of conditions and the following disclaimer.
013: *
014: * 2. Redistributions in binary form must reproduce the above copyright
015: * notice, this list of conditions and the following disclaimer in
016: * the documentation and/or other materials provided with the
017: * distribution.
018: *
019: * 3. The end-user documentation included with the redistribution,
020: * if any, must include the following acknowledgment:
021: * "This product includes software developed by the
022: * Apache Software Foundation (http://www.apache.org/)."
023: * Alternately, this acknowledgment may appear in the software
024: * itself, if and wherever such third-party acknowledgments
025: * normally appear.
026: *
027: * 4. The names "Jakarta", "Avalon", and "Apache Software Foundation"
028: * must not be used to endorse or promote products derived from this
029: * software without prior written permission. For written
030: * permission, please contact apache@apache.org.
031: *
032: * 5. Products derived from this software may not be called "Apache",
033: * nor may "Apache" appear in their name, without prior written
034: * permission of the Apache Software Foundation.
035: *
036: * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
037: * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
038: * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
039: * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
040: * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
041: * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
042: * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
043: * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
044: * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
045: * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
046: * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
047: * SUCH DAMAGE.
048: * ====================================================================
049: *
050: * This software consists of voluntary contributions made by many
051: * individuals on behalf of the Apache Software Foundation. For more
052: * information on the Apache Software Foundation, please see
053: * <http://www.apache.org/>.
054: */
055: package org.apache.log.output;
056:
057: import org.apache.log.LogEvent;
058: import org.apache.log.LogTarget;
059: import org.apache.log.Priority;
060:
061: /**
062: * Output LogEvents into an buffer in memory.
063: * At a later stage these LogEvents can be forwarded or
064: * pushed to another target. This pushing is triggered
065: * when buffer is full, the priority of a LogEvent reaches a threshold
066: * or when another class calls the push method.
067: *
068: * This is based on specification of MemoryHandler in Logging JSR47.
069: *
070: * @author <a href="mailto:dev@avalon.apache.org">Avalon Development Team</a>
071: * @author <a href="mailto:peter@apache.org">Peter Donald</a>
072: */
073: public class MemoryTarget extends AbstractTarget {
074: ///Buffer for all the LogEvents
075: private final LogEvent[] m_buffer;
076:
077: ///Priority at which to push LogEvents to next LogTarget
078: private Priority m_threshold;
079:
080: ///Target to push LogEvents to
081: private LogTarget m_target;
082:
083: ///Count of used events
084: private int m_used;
085:
086: ///Position of last element inserted
087: private int m_index;
088:
089: ///Flag indicating whether it is possible to overite elements in array
090: private boolean m_overwrite;
091:
092: /**
093: * Creation of a new instance of the memory target.
094: * @param target the target to push LogEvents to
095: * @param size the event buffer size
096: * @param threshold the priority at which to push LogEvents to next LogTarget
097: */
098: public MemoryTarget(final LogTarget target, final int size,
099: final Priority threshold) {
100: m_target = target;
101: m_buffer = new LogEvent[size];
102: m_threshold = threshold;
103: open();
104: }
105:
106: /**
107: * Set flag indicating whether it is valid to overwrite memory buffer.
108: *
109: * @param overwrite true if buffer should overwrite logevents in buffer, false otherwise
110: */
111: protected synchronized void setOverwrite(final boolean overwrite) {
112: m_overwrite = overwrite;
113: }
114:
115: /**
116: * Process a log event, via formatting and outputting it.
117: *
118: * @param event the log event
119: */
120: protected synchronized void doProcessEvent(final LogEvent event) {
121: //Check if it is full
122: if (isFull()) {
123: if (m_overwrite) {
124: m_used--;
125: } else {
126: getErrorHandler().error("Memory buffer is full", null,
127: event);
128: return;
129: }
130: }
131:
132: if (0 == m_used) {
133: m_index = 0;
134: } else {
135: m_index = (m_index + 1) % m_buffer.length;
136: }
137: m_buffer[m_index] = event;
138: m_used++;
139:
140: if (shouldPush(event)) {
141: push();
142: }
143: }
144:
145: /**
146: * Check if memory buffer is full.
147: *
148: * @return true if buffer is full, false otherwise
149: */
150: public final synchronized boolean isFull() {
151: return m_buffer.length == m_used;
152: }
153:
154: /**
155: * Determine if LogEvent should initiate a push to target.
156: * Subclasses can overide this method to change the conditions
157: * under which a push occurs.
158: *
159: * @param event the incoming LogEvent
160: * @return true if should push, false otherwise
161: */
162: protected synchronized boolean shouldPush(final LogEvent event) {
163: return (m_threshold.isLowerOrEqual(event.getPriority()) || isFull());
164: }
165:
166: /**
167: * Push log events to target.
168: */
169: public synchronized void push() {
170: if (null == m_target) {
171: getErrorHandler().error(
172: "Can not push events to a null target", null, null);
173: return;
174: }
175:
176: try {
177: final int size = m_used;
178: int base = m_index - m_used + 1;
179: if (base < 0) {
180: base += m_buffer.length;
181: }
182:
183: for (int i = 0; i < size; i++) {
184: final int index = (base + i) % m_buffer.length;
185:
186: //process event in buffer
187: m_target.processEvent(m_buffer[index]);
188:
189: //help GC
190: m_buffer[index] = null;
191: m_used--;
192: }
193: } catch (final Throwable throwable) {
194: getErrorHandler().error("Unknown error pushing events.",
195: throwable, null);
196: }
197: }
198: }
|