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 }