1 48 49 50 package com.caucho.portal.generic; 51 52 import java.io.IOException ; 53 import java.io.OutputStream ; 54 import java.io.Writer ; 55 import java.util.ArrayList ; 56 import java.util.logging.Level ; 57 import java.util.logging.Logger ; 58 59 public class BufferFactoryImpl implements BufferFactory 60 { 61 static protected final Logger log = 62 Logger.getLogger(BufferFactoryImpl.class.getName()); 63 64 private static int _bufferCount = 10; 65 66 private int _bufferSize = 8192; 67 private int _poolSize = 32; 68 69 FreeList<CharBufferImpl> _charBufferFreeList 70 = new FreeList<CharBufferImpl>(_poolSize); 71 72 FreeList<ByteBufferImpl> _byteBufferFreeList 73 = new FreeList<ByteBufferImpl>(_poolSize); 74 75 76 public void setBufferSize(int bufferSize) 77 { 78 synchronized (_byteBufferFreeList) { 79 synchronized (_charBufferFreeList) { 80 _byteBufferFreeList.clear(); 81 _charBufferFreeList.clear(); 82 _bufferSize = bufferSize; 83 } 84 } 85 } 86 87 public void setPoolSize(int poolSize) 88 { 89 synchronized (_byteBufferFreeList) { 90 synchronized (_charBufferFreeList) { 91 _poolSize = poolSize; 92 _byteBufferFreeList.ensureCapacity(poolSize); 93 _charBufferFreeList.ensureCapacity(poolSize); 94 } 95 } 96 } 97 98 public int getDefaultBufferSize() 99 { 100 return _bufferSize; 101 } 102 103 public PortletCharBuffer allocateCharBuffer(int capacity) 104 { 105 CharBufferImpl b = null; 106 107 if (capacity == Integer.MAX_VALUE) 108 capacity = _bufferSize; 109 else if (capacity < _bufferSize) 110 capacity = _bufferSize; 111 112 if (capacity == _bufferSize) 113 b = _charBufferFreeList.allocate(); 114 115 if (b == null) { 116 b = new CharBufferImpl(capacity); 117 118 if (log.isLoggable(Level.FINEST)) 119 b.log("allocated new with capacity " + capacity); 120 } 121 else { 122 if (log.isLoggable(Level.FINEST)) 123 b.log("allocated reused with capacity " + b.getCapacity()); 124 } 125 126 return b; 127 } 128 129 public PortletByteBuffer allocateByteBuffer(int capacity) 130 { 131 ByteBufferImpl b = null; 132 133 if (capacity == Integer.MAX_VALUE) 134 capacity = _bufferSize; 135 else if (capacity <= _bufferSize) 136 capacity = _bufferSize; 137 138 b = _byteBufferFreeList.allocate(); 139 140 if (b == null) { 141 b = new ByteBufferImpl(capacity); 142 143 if (log.isLoggable(Level.FINEST)) 144 b.log("allocated new with capacity " + capacity); 145 } 146 else { 147 if (log.isLoggable(Level.FINEST)) 148 b.log("allocated reused with capacity " + b.getCapacity()); 149 } 150 151 return b; 152 } 153 154 private class CharBufferImpl implements PortletCharBuffer 155 { 156 private String _bufferId; 157 158 private int _bufferSize; 159 private char[] _buf; 160 private int _bufferPos = 0; 161 162 public CharBufferImpl(int size) 163 { 164 int id = _bufferCount++; 165 _bufferId = Integer.toString(id, Character.MAX_RADIX); 166 167 _bufferSize = size; 168 _buf = new char[size]; 169 } 170 171 void log(String message) 172 { 173 if (log.isLoggable(Level.FINEST)) { 174 message = new StringBuffer (256).append("char buffer ") 175 .append(_bufferId) 176 .append(' ') 177 .append(message) 178 .toString(); 179 180 log.log(Level.FINEST, message); 181 } 182 } 183 184 public boolean print(char buf[], int off, int len) 185 { 186 if (len > _bufferSize - _bufferPos) 187 return overrun(); 188 else { 189 System.arraycopy(buf, off, _buf, _bufferPos, len); 190 _bufferPos += len; 191 192 return true; 193 } 194 } 195 196 public boolean print(String str, int off, int len) 197 { 198 if (len > _bufferSize - _bufferPos) 199 return overrun(); 200 else { 201 str.getChars(off, off + len, _buf, _bufferPos); 202 _bufferPos += len; 203 204 return true; 205 } 206 } 207 208 public boolean print(int c) 209 { 210 if (_bufferPos == _bufferSize) 211 return overrun(); 212 else { 213 _buf[_bufferPos++] = (char) c; 214 215 return true; 216 } 217 } 218 219 private boolean overrun() 220 { 221 log("overrun"); 222 return false; 223 } 224 225 public void flush(Writer out) 226 throws IOException 227 { 228 if (_bufferPos != 0) { 229 log("flush"); 230 231 out.write(_buf, 0, _bufferPos); 232 _bufferPos = 0; 233 } 234 } 235 236 public int size() 237 { 238 return _bufferPos; 239 } 240 241 public int getCapacity() 242 { 243 return _bufferSize; 244 } 245 246 public void reset() 247 { 248 log("reset"); 249 250 _bufferPos = 0; 251 } 252 253 public void finish() 254 { 255 _bufferPos = 0; 256 257 log("finish"); 258 259 if (_bufferSize <= BufferFactoryImpl.this._bufferSize) { 260 if (!_charBufferFreeList.free(this)) 261 _buf = null; 262 } 263 else 264 _buf = null; 265 } 266 } 267 268 private class ByteBufferImpl implements PortletByteBuffer 269 { 270 private String _bufferId; 271 272 private int _bufferSize; 273 private byte[] _buf; 274 private int _bufferPos = 0; 275 276 public ByteBufferImpl(int size) 277 { 278 int id = _bufferCount++; 279 _bufferId = Integer.toString(id, Character.MAX_RADIX); 280 281 _bufferSize = size; 282 _buf = new byte[size]; 283 } 284 285 void log(String message) 286 { 287 if (log.isLoggable(Level.FINEST)) { 288 message = new StringBuffer (256).append("byte buffer ") 289 .append(_bufferId) 290 .append(' ') 291 .append(message) 292 .toString(); 293 294 log.log(Level.FINEST, message); 295 } 296 } 297 298 public boolean write(byte[] buf, int off, int len) 299 { 300 if (len > _bufferSize - _bufferPos) 301 return overrun(); 302 else { 303 System.arraycopy(buf, off, _buf, _bufferPos, len); 304 _bufferPos += len; 305 306 return true; 307 } 308 } 309 310 313 public boolean write(int b) 314 { 315 if (_bufferPos == _bufferSize) 316 return overrun(); 317 else { 318 _buf[_bufferPos++] = (byte) b; 319 320 return true; 321 } 322 } 323 324 public int size() 325 { 326 return _bufferPos; 327 } 328 329 public int getCapacity() 330 { 331 return _bufferSize; 332 } 333 334 private boolean overrun() 335 { 336 log("overrun"); 337 return false; 338 } 339 340 public void flush(OutputStream out) 341 throws IOException 342 { 343 if (_bufferPos != 0) { 344 log("flush"); 345 out.write(_buf, 0, _bufferPos); 346 _bufferPos = 0; 347 } 348 } 349 350 public void reset() 351 { 352 log("reset"); 353 _bufferPos = 0; 354 } 355 356 public void finish() 357 { 358 _bufferPos = 0; 359 log("finish"); 360 361 if (_bufferSize <= BufferFactoryImpl.this._bufferSize) { 362 if (!_byteBufferFreeList.free(this)) 363 _buf = null; 364 } 365 else 366 _buf = null; 367 } 368 } 369 370 private class FreeList<E> 371 { 372 private int _freeListSize; 373 private ArrayList <E> _freeList; 374 375 private long _lastAllocateFail; 376 377 public FreeList(int initialCapacity) 378 { 379 _freeListSize = initialCapacity; 380 _freeList = new ArrayList <E>(_freeListSize); 381 } 382 383 public E allocate() 384 { 385 synchronized (_freeList) { 386 int size = _freeList.size(); 387 388 if (size > 0) 389 return _freeList.remove(--size); 390 } 391 392 393 return null; 394 } 395 396 public boolean free(E obj) 397 { 398 synchronized (_freeList) { 399 int size = _freeList.size(); 400 401 if (size < _freeListSize) { 402 _freeList.add(obj); 403 return true; 404 } 405 else { 406 if (log.isLoggable(Level.CONFIG)) 407 log.config("buffer pool overrun, consider increasing buffer-factory pool-size"); 408 return false; 409 } 410 } 411 } 412 413 public void clear() 414 { 415 synchronized (_freeList) { 416 _freeList.clear(); 417 } 418 } 419 420 public void ensureCapacity(int capacity) 421 { 422 synchronized (_freeList) { 423 _freeList.ensureCapacity(capacity); 424 } 425 } 426 } 427 } 428 | Popular Tags |