1 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 ; 39 import java.util.ArrayList ; 40 import java.util.logging.Level ; 41 import java.util.logging.Logger ; 42 43 46 public class AccessLogWriter extends AbstractRolloverLog implements Runnable 47 { 48 protected static final L10N L = new L10N(AccessLogWriter.class); 49 protected static final Logger 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 _bufferLock = new Object (); 61 private AccessLogBuffer _logBuffer; 62 private byte []_buffer; 63 private int _length; 64 65 private boolean _hasThread; 66 private boolean _isFlushing; 67 68 private int _maxQueueLength = 32; 70 private final ArrayList <AccessLogBuffer> _writeQueue 71 = new ArrayList <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 getBufferLock() 93 { 94 return _bufferLock; 95 } 96 97 101 byte []getBuffer(int requiredLength) 102 { 103 if (_buffer.length - _length < requiredLength || isRollover()) { 104 flush(); 105 } 106 107 return _buffer; 108 } 109 110 114 int getLength() 115 { 116 return _length; 117 } 118 119 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 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 log.fine("AccessLogWriter flushing log directly."); 174 175 run(); 176 } catch (Throwable 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 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 e) { 208 log.log(Level.WARNING, e.toString(), e); 209 } 210 } 211 212 215 private void writeBuffer(AccessLogBuffer buffer) 216 throws IOException 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 231 public void destroy() 232 throws IOException 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 e) { 257 log.log(Level.WARNING, e.toString(), e); 258 } 259 } 260 } 261 } 262 | Popular Tags |