1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21 package org.apache.log4j.helpers;
22
23 import org.apache.log4j.spi.LoggingEvent;
24
25 /***
26 <code>BoundedFIFO</code> serves as the bounded first-in-first-out
27 buffer heavily used by the {@link org.apache.log4j.AsyncAppender}.
28
29 @author Ceki Gülcü
30 @since version 0.9.1 */
31 public class BoundedFIFO {
32
33 LoggingEvent[] buf;
34 int numElements = 0;
35 int first = 0;
36 int next = 0;
37 int maxSize;
38
39 /***
40 Instantiate a new BoundedFIFO with a maximum size passed as argument.
41 */
42 public
43 BoundedFIFO(int maxSize) {
44 if(maxSize < 1) {
45 throw new IllegalArgumentException("The maxSize argument ("+maxSize+
46 ") is not a positive integer.");
47 }
48 this.maxSize = maxSize;
49 buf = new LoggingEvent[maxSize];
50 }
51
52 /***
53 Get the first element in the buffer. Returns <code>null</code> if
54 there are no elements in the buffer. */
55 public
56 LoggingEvent get() {
57 if(numElements == 0)
58 return null;
59
60 LoggingEvent r = buf[first];
61 buf[first] = null;
62
63 if(++first == maxSize) {
64 first = 0;
65 }
66 numElements--;
67 return r;
68 }
69
70 /***
71 Place a {@link LoggingEvent} in the buffer. If the buffer is full
72 then the event is <b>silently dropped</b>. It is the caller's
73 responsability to make sure that the buffer has free space. */
74 public
75 void put(LoggingEvent o) {
76 if(numElements != maxSize) {
77 buf[next] = o;
78 if(++next == maxSize) {
79 next = 0;
80 }
81 numElements++;
82 }
83 }
84
85 /***
86 Get the maximum size of the buffer.
87 */
88 public
89 int getMaxSize() {
90 return maxSize;
91 }
92
93 /***
94 Return <code>true</code> if the buffer is full, that is, whether
95 the number of elements in the buffer equals the buffer size. */
96 public
97 boolean isFull() {
98 return numElements == maxSize;
99 }
100
101 /***
102 Get the number of elements in the buffer. This number is
103 guaranteed to be in the range 0 to <code>maxSize</code>
104 (inclusive).
105 */
106 public
107 int length() {
108 return numElements;
109 }
110
111
112 int min(int a, int b) {
113 return a < b ? a : b;
114 }
115
116
117 /***
118 Resize the buffer to a new size. If the new size is smaller than
119 the old size events might be lost.
120
121 @since 1.1
122 */
123 synchronized
124 public
125 void resize(int newSize) {
126 if(newSize == maxSize)
127 return;
128
129
130 LoggingEvent[] tmp = new LoggingEvent[newSize];
131
132
133 int len1 = maxSize - first;
134
135
136 len1 = min(len1, newSize);
137
138
139
140 len1 = min(len1, numElements);
141
142
143 System.arraycopy(buf, first, tmp, 0, len1);
144
145
146 int len2 = 0;
147 if((len1 < numElements) && (len1 < newSize)) {
148 len2 = numElements - len1;
149 len2 = min(len2, newSize - len1);
150 System.arraycopy(buf, 0, tmp, len1, len2);
151 }
152
153 this.buf = tmp;
154 this.maxSize = newSize;
155 this.first=0;
156 this.numElements = len1+len2;
157 this.next = this.numElements;
158 if(this.next == this.maxSize)
159 this.next = 0;
160 }
161
162
163 /***
164 Returns <code>true</code> if there is just one element in the
165 buffer. In other words, if there were no elements before the last
166 {@link #put} operation completed. */
167 public
168 boolean wasEmpty() {
169 return numElements == 1;
170 }
171
172 /***
173 Returns <code>true</code> if the number of elements in the
174 buffer plus 1 equals the maximum buffer size, returns
175 <code>false</code> otherwise. */
176 public
177 boolean wasFull() {
178 return (numElements+1 == maxSize);
179 }
180
181 }