KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > com > caucho > server > log > AccessLogWriter


1 /*
2  * Copyright (c) 1998-2006 Caucho Technology -- all rights reserved
3  *
4  * This file is part of Resin(R) Open Source
5  *
6  * Each copy or derived work must preserve the copyright notice and this
7  * notice unmodified.
8  *
9  * Resin Open Source is free software; you can redistribute it and/or modify
10  * it under the terms of the GNU General Public License as published by
11  * the Free Software Foundation; either version 2 of the License, or
12  * (at your option) any later version.
13  *
14  * Resin Open Source is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, or any warranty
17  * of NON-INFRINGEMENT. See the GNU General Public License for more
18  * details.
19  *
20  * You should have received a copy of the GNU General Public License
21  * along with Resin Open Source; if not, write to the
22  *
23  * Free Software Foundation, Inc.
24  * 59 Temple Place, Suite 330
25  * Boston, MA 02111-1307 USA
26  *
27  * @author Scott Ferguson
28  */

29
30 package com.caucho.server.log;
31
32 import com.caucho.log.AbstractRolloverLog;
33 import com.caucho.util.Alarm;
34 import com.caucho.util.FreeList;
35 import com.caucho.util.L10N;
36 import com.caucho.util.ThreadPool;
37
38 import java.io.IOException JavaDoc;
39 import java.util.ArrayList JavaDoc;
40 import java.util.logging.Level JavaDoc;
41 import java.util.logging.Logger JavaDoc;
42
43 /**
44  * Represents an log of every top-level request to the server.
45  */

46 public class AccessLogWriter extends AbstractRolloverLog implements Runnable JavaDoc
47 {
48   protected static final L10N L = new L10N(AccessLogWriter.class);
49   protected static final Logger JavaDoc log
50     = Logger.getLogger(AccessLogWriter.class.getName());
51
52   private static final int BUFFER_SIZE = 65536;
53   private static final int BUFFER_GAP = 8 * 1024;
54
55   private static final FreeList<AccessLogBuffer> _freeBuffers
56     = new FreeList<AccessLogBuffer>(4);
57
58   private final AccessLog _log;
59
60   private final Object JavaDoc _bufferLock = new Object JavaDoc();
61   private AccessLogBuffer _logBuffer;
62   private byte []_buffer;
63   private int _length;
64
65   private boolean _hasThread;
66   private boolean _isFlushing;
67  
68   // the write queue
69
private int _maxQueueLength = 32;
70   private final ArrayList JavaDoc<AccessLogBuffer> _writeQueue
71     = new ArrayList JavaDoc<AccessLogBuffer>();
72   
73   AccessLogWriter(AccessLog log)
74   {
75     _log = log;
76
77     _logBuffer = getLogBuffer();
78     _buffer = _logBuffer.getBuffer();
79     _length = 0;
80   }
81   
82   private AccessLogBuffer getLogBuffer()
83   {
84     AccessLogBuffer buffer = _freeBuffers.allocate();
85
86     if (buffer == null)
87       buffer = new AccessLogBuffer();
88
89     return buffer;
90   }
91
92   Object JavaDoc getBufferLock()
93   {
94     return _bufferLock;
95   }
96
97   /**
98    * Returns the current buffer for shared-buffer. _bufferLock
99    * must be synchronized.
100    */

101   byte []getBuffer(int requiredLength)
102   {
103     if (_buffer.length - _length < requiredLength || isRollover()) {
104       flush();
105     }
106
107     return _buffer;
108   }
109
110   /**
111    * Returns the current buffer length for shared-buffer. _bufferLock
112    * must be synchronized.
113    */

114   int getLength()
115   {
116     return _length;
117   }
118
119   /**
120    * Returns the current buffer length for shared-buffer. _bufferLock
121    * must be synchronized.
122    */

123   void setLength(int length)
124   {
125     _length = length;
126   }
127
128   void writeBuffer(byte []buffer, int offset, int length)
129   {
130     synchronized (_bufferLock) {
131       if (_buffer.length - _length < length || isRollover()) {
132     flush();
133       }
134
135       if (_buffer.length < length)
136     length = _buffer.length;
137
138       System.arraycopy(buffer, offset, _buffer, _length, length);
139       _length += length;
140     }
141   }
142
143   void writeThrough(byte []buffer, int offset, int length)
144   {
145     try {
146       write(buffer, offset, length);
147       flush();
148     } catch (IOException JavaDoc e) {
149       log.log(Level.WARNING, e.toString(), e);
150     }
151   }
152
153   private AccessLogBuffer write(AccessLogBuffer logBuffer)
154   {
155     while (true) {
156       synchronized (_writeQueue) {
157     if (_writeQueue.size() < _maxQueueLength) {
158       _writeQueue.add(logBuffer);
159
160       if (! _hasThread) {
161         _hasThread = true;
162         ThreadPool.getThreadPool().start(this);
163       }
164
165       break;
166     }
167     else if (! _isFlushing) {
168       try {
169         _isFlushing = true;
170         // If the queue is full, call the flush code directly
171
// since the thread pool may be out of threads for
172
// a schedule
173
log.fine("AccessLogWriter flushing log directly.");
174           
175         run();
176       } catch (Throwable JavaDoc e) {
177         log.log(Level.WARNING, e.toString(), e);
178       } finally {
179         _isFlushing = false;
180       }
181     }
182       }
183     }
184     
185     AccessLogBuffer buffer = _freeBuffers.allocate();
186
187     if (buffer == null)
188       buffer = new AccessLogBuffer();
189
190     return buffer;
191   }
192
193   // must be synchronized by _bufferLock.
194
protected void flush()
195   {
196     synchronized (_bufferLock) {
197       if (_length > 0) {
198     _logBuffer.setLength(_length);
199     _logBuffer = write(_logBuffer);
200     _buffer = _logBuffer.getBuffer();
201     _length = 0;
202       }
203     }
204
205     try {
206       super.flush();
207     } catch (IOException JavaDoc e) {
208       log.log(Level.WARNING, e.toString(), e);
209     }
210   }
211
212   /**
213    * Writes the buffer data to the output stream.
214    */

215   private void writeBuffer(AccessLogBuffer buffer)
216     throws IOException JavaDoc
217   {
218     long now = Alarm.getCurrentTime();
219
220     write(buffer.getBuffer(), 0, buffer.getLength());
221     super.flush();
222     
223     _freeBuffers.free(buffer);
224     
225     rolloverLog(now);
226   }
227
228   /**
229    * Closes the log, flushing the results.
230    */

231   public void destroy()
232     throws IOException JavaDoc
233   {
234   }
235
236   public void run()
237   {
238     while (true) {
239       try {
240     AccessLogBuffer buffer = null;
241     
242     synchronized (_writeQueue) {
243       if (_writeQueue.size() > 0) {
244         buffer = _writeQueue.remove(0);
245         _writeQueue.notifyAll();
246       }
247       else {
248         _hasThread = false;
249         return;
250       }
251     }
252
253     if (buffer != null) {
254       writeBuffer(buffer);
255     }
256       } catch (Throwable JavaDoc e) {
257     log.log(Level.WARNING, e.toString(), e);
258       }
259     }
260   }
261 }
262
Popular Tags