1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
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ülcü
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;
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 }