View Javadoc

    1   /*
    2    * Licensed to the Apache Software Foundation (ASF) under one or more
    3    * contributor license agreements.  See the NOTICE file distributed with
    4    * this work for additional information regarding copyright ownership.
    5    * The ASF licenses this file to You under the Apache License, Version 2.0
    6    * (the "License"); you may not use this file except in compliance with
    7    * the License.  You may obtain a copy of the License at
    8    *
    9    *      http://www.apache.org/licenses/LICENSE-2.0
    10   *
    11   * Unless required by applicable law or agreed to in writing, software
    12   * distributed under the License is distributed on an "AS IS" BASIS,
    13   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    14   * See the License for the specific language governing permissions and
    15   * limitations under the License.
    16   */
    17
    18  package org.apache.log4j.helpers;
    19
    20  import org.apache.log4j.spi.LoggingEvent;
    21
    22  /***
    23
    24     CyclicBuffer is used by other appenders to hold {@link LoggingEvent
    25     LoggingEvents} for immediate or differed display.
    26
    27     <p>This buffer gives read access to any element in the buffer not
    28     just the first or last element.
    29
    30     @author Ceki G&uuml;lc&uuml;
    31     @since 0.9.0
    32
    33   */
    34  public class CyclicBuffer {
    35
    36    LoggingEvent[] ea;
    37    int first;
    38    int last;
    39    int numElems;
    40    int maxSize;
    41
    42    /***
    43       Instantiate a new CyclicBuffer of at most <code>maxSize</code> events.
    44
    45       The <code>maxSize</code> argument must a positive integer.
    46
    47       @param maxSize The maximum number of elements in the buffer.
    48    */
    49    public CyclicBuffer(int maxSize) throws IllegalArgumentException {
    50      if(maxSize < 1) {
    51        throw new IllegalArgumentException("The maxSize argument ("+maxSize+
    52  			    ") is not a positive integer.");
    53      }
    54      this.maxSize = maxSize;
    55      ea = new LoggingEvent[maxSize];
    56      first = 0;
    57      last = 0;
    58      numElems = 0;
    59    }
    60
    61    /***
    62       Add an <code>event</code> as the last event in the buffer.
    63
    64     */
    65    public
    66    void add(LoggingEvent event) {
    67      ea[last] = event;
    68      if(++last == maxSize)
    69        last = 0;
    70
    71      if(numElems < maxSize)
    72        numElems++;
    73      else if(++first == maxSize)
    74        first = 0;
    75    }
    76
    77
    78    /***
    79       Get the <i>i</i>th oldest event currently in the buffer. If
    80       <em>i</em> is outside the range 0 to the number of elements
    81       currently in the buffer, then <code>null</code> is returned.
    82
    83
    84    */
    85    public
    86    LoggingEvent get(int i) {
    87      if(i < 0 || i >= numElems)
    88        return null;
    89
    90      return ea[(first + i) % maxSize];
    91    }
    92
    93    public
    94    int getMaxSize() {
    95      return maxSize;
    96    }
    97
    98    /***
    99       Get the oldest (first) element in the buffer. The oldest element
    100      is removed from the buffer.
    101   */
    102   public
    103   LoggingEvent get() {
    104     LoggingEvent r = null;
    105     if(numElems > 0) {
    106       numElems--;
    107       r = ea[first];
    108       ea[first] = null;
    109       if(++first == maxSize)
    110 	first = 0;
    111     }
    112     return r;
    113   }
    114
    115   /***
    116      Get the number of elements in the buffer. This number is
    117      guaranteed to be in the range 0 to <code>maxSize</code>
    118      (inclusive).
    119   */
    120   public
    121   int length() {
    122     return numElems;
    123   }
    124
    125   /***
    126      Resize the cyclic buffer to <code>newSize</code>.
    127
    128      @throws IllegalArgumentException if <code>newSize</code> is negative.
    129    */
    130   public
    131   void resize(int newSize) {
    132     if(newSize < 0) {
    133       throw new IllegalArgumentException("Negative array size ["+newSize+
    134 					 "] not allowed.");
    135     }
    136     if(newSize == numElems)
    137       return; // nothing to do
    138
    139     LoggingEvent[] temp = new  LoggingEvent[newSize];
    140
    141     int loopLen = newSize < numElems ? newSize : numElems;
    142
    143     for(int i = 0; i < loopLen; i++) {
    144       temp[i] = ea[first];
    145       ea[first] = null;
    146       if(++first == numElems)
    147 	first = 0;
    148     }
    149     ea = temp;
    150     first = 0;
    151     numElems = loopLen;
    152     maxSize = newSize;
    153     if (loopLen == newSize) {
    154       last = 0;
    155     } else {
    156       last = loopLen;
    157     }
    158   }
    159 }