1 package org.jacorb.notification.util; 2 3 23 24 import java.util.ArrayList ; 25 import java.util.Collection ; 26 import java.util.Collections ; 27 import java.util.Iterator ; 28 import java.util.LinkedList ; 29 import java.util.List ; 30 import java.util.Set ; 31 32 import org.apache.avalon.framework.configuration.Configurable; 33 import org.apache.avalon.framework.configuration.Configuration; 34 import org.apache.avalon.framework.configuration.ConfigurationException; 35 import org.apache.avalon.framework.logger.Logger; 36 import org.jacorb.notification.interfaces.Disposable; 37 38 import EDU.oswego.cs.dl.util.concurrent.SynchronizedBoolean; 39 40 50 51 public abstract class AbstractObjectPool implements Runnable , Configurable 52 { 53 public static final boolean DEBUG = false; 54 55 58 public static final long SLEEP = 5000L; 59 60 public static final int LOWER_WATERMARK_DEFAULT = 5; 61 62 public static final int SIZE_INCREASE_DEFAULT = 3; 63 64 public static final int INITIAL_SIZE_DEFAULT = 10; 65 66 public static final int MAXIMUM_WATERMARK_DEFAULT = 20; 67 68 public static final int MAXIMUM_SIZE_DEFAULT = 0; 69 70 73 private static final List sPoolsToLookAfter = new ArrayList (); 74 75 private static AbstractObjectPool[] asArray; 76 77 private static boolean modified = true; 78 79 private final static AbstractObjectPool[] ARRAY_TEMPLATE = new AbstractObjectPool[0]; 80 81 static Thread sCleanerThread; 82 83 static final Logger sLogger_ = LogUtil.getLogger(AbstractObjectPool.class.getName()); 84 85 private static ListCleaner sListCleaner; 86 87 private static boolean sUseListCleaner = true; 88 89 static AbstractObjectPool[] getAllPools() 90 { 91 synchronized (sPoolsToLookAfter) 92 { 93 if (modified) 94 { 95 asArray = (AbstractObjectPool[]) sPoolsToLookAfter.toArray(ARRAY_TEMPLATE); 96 modified = false; 97 } 98 } 99 return asArray; 100 } 101 102 private static void registerPool(AbstractObjectPool pool) 103 { 104 synchronized (sPoolsToLookAfter) 105 { 106 sPoolsToLookAfter.add(pool); 107 modified = true; 108 startListCleaner(); 109 } 110 } 111 112 private static void deregisterPool(AbstractObjectPool pool) 113 { 114 synchronized (sPoolsToLookAfter) 115 { 116 sPoolsToLookAfter.remove(pool); 117 modified = true; 118 if (sPoolsToLookAfter.isEmpty()) 119 { 120 getAllPools(); 122 123 stopListCleaner(); 124 } 125 } 126 } 127 128 private static class ListCleaner extends Thread 129 { 130 private SynchronizedBoolean active_ = new SynchronizedBoolean(true); 131 132 public void setInactive() 133 { 134 active_.set(false); 135 136 interrupt(); 137 } 138 139 private void ensureIsActive() throws InterruptedException 140 { 141 if (!active_.get()) 142 { 143 throw new InterruptedException (); 144 } 145 } 146 147 public void run() 148 { 149 try 150 { 151 while (active_.get()) 152 { 153 try 154 { 155 runLoop(); 156 } catch (InterruptedException e) 157 { 158 sLogger_.info("PoolCleaner was interrupted"); 159 } catch (Exception e) 160 { 161 sLogger_.error("Error cleaning Pool", e); 162 } 163 } 164 } finally 165 { 166 synchronized (AbstractObjectPool.class) 167 { 168 sCleanerThread = null; 169 } 170 } 171 } 172 173 private void runLoop() throws InterruptedException 174 { 175 while (true) 176 { 177 try 178 { 179 sleep(SLEEP); 180 } catch (InterruptedException ie) 181 { 182 } 186 187 ensureIsActive(); 188 189 Runnable [] poolsToCheck = getAllPools(); 190 191 for (int x = 0; x < poolsToCheck.length; ++x) 192 { 193 try 194 { 195 poolsToCheck[x].run(); 196 } catch (Throwable t) 197 { 198 sLogger_.error("Error cleaning up Pool", t); 200 } 201 } 202 } 203 } 204 } 205 206 private static ListCleaner getListCleaner() 207 { 208 synchronized (AbstractObjectPool.class) 209 { 210 if (sListCleaner == null) 211 { 212 sListCleaner = new ListCleaner(); 213 } 214 return sListCleaner; 215 } 216 } 217 218 private static void stopListCleaner() 219 { 220 synchronized (AbstractObjectPool.class) 221 { 222 if (sCleanerThread != null) 223 { 224 sListCleaner.setInactive(); 225 } 226 } 227 } 228 229 private static void startListCleaner() 230 { 231 synchronized (AbstractObjectPool.class) 232 { 233 if (sCleanerThread == null && sUseListCleaner ) 234 { 235 sCleanerThread = new Thread (getListCleaner()); 236 237 sCleanerThread.setName("ObjectPoolCleaner"); 238 sCleanerThread.setPriority(Thread.MIN_PRIORITY + 1); 239 sCleanerThread.setDaemon(true); 240 sCleanerThread.start(); 241 } 242 } 243 } 244 245 private final String name_; 246 247 private final DisposableManager disposeHooks_ = new DisposableManager(); 248 249 private final LinkedList pool_; 250 251 private boolean isInitialized_; 252 253 258 private final Set active_ = Collections.synchronizedSet(new WeakHashSet()); 259 260 263 private int lowerWatermark_; 264 265 269 private int maxWatermark_; 270 271 274 private int sizeIncrease_; 275 276 279 private int initialSize_; 280 281 private int maximumSize_; 282 283 protected final Logger logger_ = LogUtil.getLogger(getClass().getName()); 284 285 protected Configuration config_; 286 287 public void configure(Configuration conf) 288 { 289 config_ = conf; 290 291 init(); 292 } 293 294 protected AbstractObjectPool(String name) 295 { 296 this(name, LOWER_WATERMARK_DEFAULT, SIZE_INCREASE_DEFAULT, INITIAL_SIZE_DEFAULT, 297 MAXIMUM_WATERMARK_DEFAULT, MAXIMUM_SIZE_DEFAULT); 298 } 299 300 protected AbstractObjectPool(String name, int lowerWatermark, int sizeincrease, 301 int initialsize, int maxWatermark, int maximumSize) 302 { 303 if (maximumSize > 0 && initialsize > maximumSize) 304 { 305 throw new IllegalArgumentException ("InitialSize: " + initialsize 306 + " may not be larger than MaximumSize: " + maximumSize); 307 } 308 309 name_ = name; 310 pool_ = new LinkedList (); 311 lowerWatermark_ = lowerWatermark; 312 sizeIncrease_ = sizeincrease; 313 initialSize_ = initialsize; 314 maxWatermark_ = maxWatermark; 315 maximumSize_ = maximumSize; 316 } 317 318 public void addDisposeHook(Disposable d) 319 { 320 disposeHooks_.addDisposable(d); 321 } 322 323 public void run() 324 { 325 final int maxToBeCreated; 326 327 synchronized (pool_) 328 { 329 if (pool_.size() > lowerWatermark_) 330 { 331 return; 332 } 333 334 maxToBeCreated = getNumberOfCreationsAllowed(); 335 } 336 337 final int sizeIncrease = Math.min(sizeIncrease_, maxToBeCreated); 338 339 if (sizeIncrease > 0) 340 { 341 List os = new ArrayList (sizeIncrease); 342 343 for (int x = 0; x < sizeIncrease; ++x) 344 { 345 Object _i = createInstance(); 346 347 os.add(_i); 348 } 349 350 synchronized (pool_) 351 { 352 pool_.addAll(os); 353 } 354 } 355 } 356 357 362 private int getNumberOfCreationsAllowed() 363 { 364 final int maxToBeCreated; 365 366 if (maximumSize_ > 0) 367 { 368 maxToBeCreated = maximumSize_ - active_.size() - pool_.size(); 369 } 370 else 371 { 372 maxToBeCreated = Integer.MAX_VALUE; 373 } 374 375 return maxToBeCreated; 376 } 377 378 private Object createInstance() 379 { 380 Object _i = newInstance(); 381 382 return _i; 383 } 384 385 388 private void init() 389 { 390 registerPool(this); 391 392 synchronized (pool_) 393 { 394 if (isInitialized_) 395 { 396 throw new IllegalStateException ("Already Initialized"); 397 } 398 399 for (int x = 0; x < initialSize_; ++x) 400 { 401 Object _i = createInstance(); 402 403 pool_.add(_i); 404 } 405 406 isInitialized_ = true; 407 } 408 } 409 410 413 public void dispose() 414 { 415 deregisterPool(this); 416 disposeCollection(pool_); 417 pool_.clear(); 418 disposeCollection(active_); 419 active_.clear(); 420 421 disposeHooks_.dispose(); 422 } 423 424 private void disposeCollection(Collection c) 425 { 426 Iterator i = c.iterator(); 427 428 while (i.hasNext()) 429 { 430 Object o = i.next(); 431 432 try 433 { 434 Disposable disposable = (Disposable) o; 435 436 try 437 { 438 ((AbstractPoolable) o).setObjectPool(null); 439 } catch (ClassCastException e) 440 { 441 } 443 444 disposable.dispose(); 445 } catch (ClassCastException e) 446 { 447 } 449 } 450 } 451 452 455 public Object lendObject() 456 { 457 checkIsInitialized(); 458 459 Object _ret = null; 460 461 synchronized (pool_) 462 { 463 if (!pool_.isEmpty()) 464 { 465 _ret = pool_.removeFirst(); 466 } 467 468 if (_ret == null) 469 { 470 while (!isCreationAllowed()) 471 { 472 poolIsEmpty(); 473 } 474 } 475 } 476 477 if (_ret == null) 478 { 479 _ret = createInstance(); 480 } 481 482 try 483 { 484 ((Configurable) _ret).configure(this.config_); 485 } catch (ClassCastException cce) 486 { 487 } catch (ConfigurationException ce) 489 { 490 throw new RuntimeException ("Could not configure instance"); 491 } 492 493 activateObject(_ret); 494 active_.add(_ret); 495 496 return _ret; 497 } 498 499 502 private void checkIsInitialized() 503 { 504 synchronized (pool_) 505 { 506 if (!isInitialized_) 507 { 508 throw new IllegalStateException ("Not initialized"); 509 } 510 } 511 } 512 513 518 private boolean isCreationAllowed() 519 { 520 return getNumberOfCreationsAllowed() > 0; 521 } 522 523 526 private void poolIsEmpty() 527 { 528 throw new RuntimeException (name_ + ": No more Elements allowed. " + getInfo()); 529 } 530 531 534 public void returnObject(Object o) 535 { 536 checkIsInitialized(); 537 538 if (active_.remove(o)) 539 { 540 passivateObject(o); 541 542 if (pool_.size() < maxWatermark_) 543 { 544 synchronized (pool_) 545 { 546 pool_.add(o); 547 pool_.notifyAll(); 548 } 549 } 550 else 551 { 552 destroyObject(o); 553 } 554 } 555 else 556 { 557 throw new RuntimeException ("Object " + o + " was not created here"); 558 } 559 } 560 561 public String toString() 562 { 563 return name_ + " " + getInfo(); 564 } 565 566 private String getInfo() 567 { 568 return "Active=" + active_.size() + " Pooled=" + pool_.size() + " MaximumSize=" 569 + ((maximumSize_ > 0) ? Integer.toString(maximumSize_) : "unlimited"); 570 } 571 572 576 public abstract Object newInstance(); 577 578 581 public void passivateObject(Object o) 582 { 583 } 585 586 589 public void activateObject(Object o) 590 { 591 } 593 594 597 public void destroyObject(Object o) 598 { 599 } 601 } | Popular Tags |