1 25 26 package org.objectweb.easybeans.pool; 27 28 import java.util.ArrayList ; 29 import java.util.HashMap ; 30 import java.util.List ; 31 import java.util.Map ; 32 33 import org.objectweb.easybeans.api.pool.Pool; 34 import org.objectweb.easybeans.api.pool.PoolAttributes; 35 import org.objectweb.easybeans.api.pool.PoolException; 36 import org.objectweb.easybeans.log.JLog; 37 import org.objectweb.easybeans.log.JLogFactory; 38 39 40 49 public class JPool<InstanceType, Clue> implements Pool<InstanceType, Clue>, PoolAttributes { 50 51 54 private static final long DEFAULT_TIMEOUT = 10000; 55 56 59 private static final int DEFAULT_MAX_WAITERS = 1000; 60 61 64 private static final int NO_LIMIT = -1; 65 66 69 private JLog logger = JLogFactory.getLog(JPool.class); 70 71 74 private PoolFactory<InstanceType, Clue> poolFactory = null; 75 76 79 private List <InstanceType> availableList = null; 80 81 84 private List <InstanceType> busyList = null; 85 86 89 private Map <InstanceType, PoolEntryStatistics> infoMap = null; 90 91 94 private int minSize = 0; 95 96 99 private int maxSize = NO_LIMIT; 100 101 104 private int initSize = 0; 105 106 109 private boolean strict = true; 110 111 114 private int maxWaiters = DEFAULT_MAX_WAITERS; 115 116 119 private long waiterTimeout = DEFAULT_TIMEOUT; 120 121 124 private int currentWaiters = 0; 125 126 129 private int highMaxWaiters = 0; 130 131 134 private int totalWaiters = 0; 135 136 139 private long totalWaitingTime = 0; 140 141 144 private long highWaitingTime = 0; 145 146 149 private int servedInstance = 0; 150 151 154 private int rejectedTimeout = 0; 155 156 159 private int rejectedFull = 0; 160 161 165 private boolean allowSharedInstance = true; 166 167 171 public JPool(final PoolFactory<InstanceType, Clue> poolFactory) { 172 173 this.poolFactory = poolFactory; 175 176 this.availableList = new ArrayList <InstanceType>(); 178 179 this.busyList = new ArrayList <InstanceType>(); 181 182 infoMap = new HashMap <InstanceType, PoolEntryStatistics>(); 184 } 185 186 191 public InstanceType get() throws PoolException { 192 return this.get(null); 194 } 195 196 202 public synchronized InstanceType get(final Clue clue) throws PoolException { 203 InstanceType instance = null; 204 205 long timeToWait = waiterTimeout; 207 208 while (instance == null) { 211 212 if (!availableList.isEmpty()) { 214 logger.debug("Instances are available"); 215 216 int indexToExtract = -1; 217 218 if (clue == null) { 220 logger.debug("No clue, return the first available entry."); 221 indexToExtract = 0; 222 } else { 223 logger.debug("Clue is used, try to get a matching entry."); 224 for (int i = 0; i < availableList.size(); i++) { 228 InstanceType tmpInstance = availableList.get(i); 229 if (poolFactory.isMatching(tmpInstance, clue)) { 230 logger.debug("Found a matching instance, instance = {0}", tmpInstance); 231 indexToExtract = i; 232 break; 233 } 234 } 235 } 237 if (indexToExtract != -1) { 239 logger 240 .debug("Remove from available instance, item with index {0}", Integer 241 .valueOf(indexToExtract)); 242 instance = availableList.remove(indexToExtract); 243 busyList.add(instance); 244 } 245 } 246 247 254 if (instance == null) { 255 int curSize = availableList.size() + busyList.size(); 257 258 boolean sharedInstance = true; 259 if (!allowSharedInstance) { 260 for (int i = 0; i < busyList.size(); i++) { 262 InstanceType tmpInstance = busyList.get(i); 263 if (poolFactory.isMatching(tmpInstance, clue)) { 264 logger.debug("Found a matching instance, instance = {0}", tmpInstance); 265 sharedInstance = false; 266 break; 267 } 268 } 269 } 270 271 272 if (sharedInstance && (maxSize == NO_LIMIT || curSize < maxSize)) { 274 logger.debug("Maximum size not reached, can create a new entry with clue = {0}", clue); 275 instance = poolFactory.create(clue); 276 busyList.add(instance); 277 } else if (sharedInstance && availableList.size() > 0) { 278 logger.debug("limit reached but entries available in the pool. Replace one by a new one."); 280 281 InstanceType previousInstance = availableList.get(0); 283 284 poolFactory.remove(previousInstance); 287 288 availableList.remove(previousInstance); 290 infoMap.remove(previousInstance); 292 293 instance = poolFactory.create(clue); 296 busyList.add(instance); 298 } else { 299 logger.debug("limit reached and no available instances in the pool"); 300 boolean timeoutWokenUp = true; 301 long startSleeping = 0; 302 303 if (timeToWait > 0) { 305 if (currentWaiters < maxWaiters) { 306 currentWaiters++; 307 if (highMaxWaiters < currentWaiters) { 309 highMaxWaiters = currentWaiters; 310 } 311 if (startSleeping == 0) { 312 startSleeping = System.currentTimeMillis(); 313 logger.debug("Waiting an instance"); 314 } 315 try { 316 wait(timeToWait); 317 } catch (InterruptedException ie) { 318 logger.warn("Waiter has been interrupted", ie); 319 } finally { 320 currentWaiters--; 321 } 322 long sleepTime = System.currentTimeMillis() - startSleeping; 323 timeoutWokenUp = (waiterTimeout - sleepTime <= 0); 325 326 totalWaiters++; 328 totalWaitingTime += sleepTime; 329 if (highWaitingTime < sleepTime) { 330 highWaitingTime = sleepTime; 331 } 332 if (!timeoutWokenUp) { 334 continue; 335 } 336 } 337 } 338 339 if (timeoutWokenUp && availableList.isEmpty() && busyList.size() >= maxSize) { 341 if (startSleeping > 0) { 342 rejectedTimeout++; 343 logger.warn("Cannot create an instance due to a timeout"); 344 } else { 345 rejectedFull++; 346 logger.warn("Cannot create an instance"); 347 } 348 throw new PoolException("No more instances available"); 349 } 350 } 351 } 352 } 353 354 PoolEntryStatistics poolEntryStat = new PoolEntryStatistics(); 356 357 infoMap.put(instance, poolEntryStat); 358 359 361 363 servedInstance++; 364 return instance; 365 } 366 367 372 public synchronized void release(final InstanceType instance) throws PoolException { 373 374 if (!busyList.contains(instance)) { 375 logger.debug("Attempt to release inactive resource {0}. Probably discarded.", instance); 376 return; 377 } 378 busyList.remove(instance); 379 logger.debug("Put back into the pool the instance {0}", instance); 380 381 availableList.add(instance); 382 infoMap.remove(instance); 383 384 if (currentWaiters > 0) { 386 notify(); 387 } 388 } 389 390 395 public synchronized void discard(final InstanceType instance) throws PoolException { 396 if (!busyList.contains(instance)) { 397 throw new PoolException("Attempt to discard an inactive resource(" + instance + ")"); 398 } 399 400 poolFactory.remove(instance); 402 403 busyList.remove(instance); 405 infoMap.remove(instance); 406 407 408 if (currentWaiters > 0) { 410 notify(); 411 } 412 413 } 414 415 421 public void setAllowSharedInstance(final boolean allowSharedInstance) { 422 this.allowSharedInstance = allowSharedInstance; 423 } 424 425 429 public boolean isAllowSharedInstance() { 430 return allowSharedInstance; 431 } 432 433 434 439 public void start() throws PoolException { 440 441 } 442 443 447 public void stop() throws PoolException { 448 449 } 450 451 } 452 | Popular Tags |