1 /*
2 * Licensed to the Apache Software Foundation (ASF) under one or more
3 * contributor license agreements. See the NOTICE file distributed with
4 * this work for additional information regarding copyright ownership.
5 * The ASF licenses this file to You under the Apache License, Version 2.0
6 * (the "License"); you may not use this file except in compliance with
7 * the License. You may obtain a copy of the License at
8 *
9 * http://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
16 */
17 package org.apache.tomcat.dbcp.pool2.impl;
18
19 import java.util.ArrayList;
20 import java.util.HashSet;
21 import java.util.Iterator;
22 import java.util.Map;
23 import java.util.NoSuchElementException;
24 import java.util.Set;
25 import java.util.concurrent.ConcurrentHashMap;
26 import java.util.concurrent.TimeUnit;
27 import java.util.concurrent.atomic.AtomicLong;
28
29 import org.apache.tomcat.dbcp.pool2.ObjectPool;
30 import org.apache.tomcat.dbcp.pool2.PoolUtils;
31 import org.apache.tomcat.dbcp.pool2.PooledObject;
32 import org.apache.tomcat.dbcp.pool2.PooledObjectFactory;
33 import org.apache.tomcat.dbcp.pool2.PooledObjectState;
34 import org.apache.tomcat.dbcp.pool2.UsageTracking;
35
36 /**
37 * A configurable {@link ObjectPool} implementation.
38 * <p>
39 * When coupled with the appropriate {@link PooledObjectFactory},
40 * <code>GenericObjectPool</code> provides robust pooling functionality for
41 * arbitrary objects.
42 * </p>
43 * <p>
44 * Optionally, one may configure the pool to examine and possibly evict objects
45 * as they sit idle in the pool and to ensure that a minimum number of idle
46 * objects are available. This is performed by an "idle object eviction" thread,
47 * which runs asynchronously. Caution should be used when configuring this
48 * optional feature. Eviction runs contend with client threads for access to
49 * objects in the pool, so if they run too frequently performance issues may
50 * result.
51 * </p>
52 * <p>
53 * The pool can also be configured to detect and remove "abandoned" objects,
54 * i.e. objects that have been checked out of the pool but neither used nor
55 * returned before the configured
56 * {@link AbandonedConfig#getRemoveAbandonedTimeout() removeAbandonedTimeout}.
57 * Abandoned object removal can be configured to happen when
58 * <code>borrowObject</code> is invoked and the pool is close to starvation, or
59 * it can be executed by the idle object evictor, or both. If pooled objects
60 * implement the {@link org.apache.tomcat.dbcp.pool2.TrackedUse} interface,
61 * their last use will be queried
62 * using the <code>getLastUsed</code> method on that interface; otherwise
63 * abandonment is determined by how long an object has been checked out from
64 * the pool.
65 * </p>
66 * <p>
67 * Implementation note: To prevent possible deadlocks, care has been taken to
68 * ensure that no call to a factory method will occur within a synchronization
69 * block. See POOL-125 and DBCP-44 for more information.
70 * </p>
71 * <p>
72 * This class is intended to be thread-safe.
73 * </p>
74 *
75 * @see GenericKeyedObjectPool
76 *
77 * @param <T> Type of element pooled in this pool.
78 *
79 * @since 2.0
80 */
81 public class GenericObjectPool<T> extends BaseGenericObjectPool<T>
82 implements ObjectPool<T>, GenericObjectPoolMXBean, UsageTracking<T> {
83
84 /**
85 * Creates a new <code>GenericObjectPool</code> using defaults from
86 * {@link GenericObjectPoolConfig}.
87 *
88 * @param factory The object factory to be used to create object instances
89 * used by this pool
90 */
91 public GenericObjectPool(final PooledObjectFactory<T> factory) {
92 this(factory, new GenericObjectPoolConfig<T>());
93 }
94
95 /**
96 * Creates a new <code>GenericObjectPool</code> using a specific
97 * configuration.
98 *
99 * @param factory The object factory to be used to create object instances
100 * used by this pool
101 * @param config The configuration to use for this pool instance. The
102 * configuration is used by value. Subsequent changes to
103 * the configuration object will not be reflected in the
104 * pool.
105 */
106 public GenericObjectPool(final PooledObjectFactory<T> factory,
107 final GenericObjectPoolConfig<T> config) {
108
109 super(config, ONAME_BASE, config.getJmxNamePrefix());
110
111 if (factory == null) {
112 jmxUnregister(); // tidy up
113 throw new IllegalArgumentException("factory may not be null");
114 }
115 this.factory = factory;
116
117 idleObjects = new LinkedBlockingDeque<>(config.getFairness());
118
119 setConfig(config);
120 }
121
122 /**
123 * Creates a new <code>GenericObjectPool</code> that tracks and destroys
124 * objects that are checked out, but never returned to the pool.
125 *
126 * @param factory The object factory to be used to create object instances
127 * used by this pool
128 * @param config The base pool configuration to use for this pool instance.
129 * The configuration is used by value. Subsequent changes to
130 * the configuration object will not be reflected in the
131 * pool.
132 * @param abandonedConfig Configuration for abandoned object identification
133 * and removal. The configuration is used by value.
134 */
135 public GenericObjectPool(final PooledObjectFactory<T> factory,
136 final GenericObjectPoolConfig<T> config, final AbandonedConfig abandonedConfig) {
137 this(factory, config);
138 setAbandonedConfig(abandonedConfig);
139 }
140
141 /**
142 * Returns the cap on the number of "idle" instances in the pool. If maxIdle
143 * is set too low on heavily loaded systems it is possible you will see
144 * objects being destroyed and almost immediately new objects being created.
145 * This is a result of the active threads momentarily returning objects
146 * faster than they are requesting them, causing the number of idle
147 * objects to rise above maxIdle. The best value for maxIdle for heavily
148 * loaded system will vary but the default is a good starting point.
149 *
150 * @return the maximum number of "idle" instances that can be held in the
151 * pool or a negative value if there is no limit
152 *
153 * @see #setMaxIdle
154 */
155 @Override
156 public int getMaxIdle() {
157 return maxIdle;
158 }
159
160 /**
161 * Returns the cap on the number of "idle" instances in the pool. If maxIdle
162 * is set too low on heavily loaded systems it is possible you will see
163 * objects being destroyed and almost immediately new objects being created.
164 * This is a result of the active threads momentarily returning objects
165 * faster than they are requesting them, causing the number of idle
166 * objects to rise above maxIdle. The best value for maxIdle for heavily
167 * loaded system will vary but the default is a good starting point.
168 *
169 * @param maxIdle
170 * The cap on the number of "idle" instances in the pool. Use a
171 * negative value to indicate an unlimited number of idle
172 * instances
173 *
174 * @see #getMaxIdle
175 */
176 public void setMaxIdle(final int maxIdle) {
177 this.maxIdle = maxIdle;
178 }
179
180 /**
181 * Sets the target for the minimum number of idle objects to maintain in
182 * the pool. This setting only has an effect if it is positive and
183 * {@link #getTimeBetweenEvictionRunsMillis()} is greater than zero. If this
184 * is the case, an attempt is made to ensure that the pool has the required
185 * minimum number of instances during idle object eviction runs.
186 * <p>
187 * If the configured value of minIdle is greater than the configured value
188 * for maxIdle then the value of maxIdle will be used instead.
189 * </p>
190 *
191 * @param minIdle
192 * The minimum number of objects.
193 *
194 * @see #getMinIdle()
195 * @see #getMaxIdle()
196 * @see #getTimeBetweenEvictionRunsMillis()
197 */
198 public void setMinIdle(final int minIdle) {
199 this.minIdle = minIdle;
200 }
201
202 /**
203 * Returns the target for the minimum number of idle objects to maintain in
204 * the pool. This setting only has an effect if it is positive and
205 * {@link #getTimeBetweenEvictionRunsMillis()} is greater than zero. If this
206 * is the case, an attempt is made to ensure that the pool has the required
207 * minimum number of instances during idle object eviction runs.
208 * <p>
209 * If the configured value of minIdle is greater than the configured value
210 * for maxIdle then the value of maxIdle will be used instead.
211 * </p>
212 *
213 * @return The minimum number of objects.
214 *
215 * @see #setMinIdle(int)
216 * @see #setMaxIdle(int)
217 * @see #setTimeBetweenEvictionRunsMillis(long)
218 */
219 @Override
220 public int getMinIdle() {
221 final int maxIdleSave = getMaxIdle();
222 if (this.minIdle > maxIdleSave) {
223 return maxIdleSave;
224 }
225 return minIdle;
226 }
227
228 /**
229 * Gets whether or not abandoned object removal is configured for this pool.
230 *
231 * @return true if this pool is configured to detect and remove
232 * abandoned objects
233 */
234 @Override
235 public boolean isAbandonedConfig() {
236 return abandonedConfig != null;
237 }
238
239 /**
240 * Gets whether this pool identifies and logs any abandoned objects.
241 *
242 * @return {@code true} if abandoned object removal is configured for this
243 * pool and removal events are to be logged otherwise {@code false}
244 *
245 * @see AbandonedConfig#getLogAbandoned()
246 */
247 @Override
248 public boolean getLogAbandoned() {
249 final AbandonedConfig ac = this.abandonedConfig;
250 return ac != null && ac.getLogAbandoned();
251 }
252
253 /**
254 * Gets whether a check is made for abandoned objects when an object is borrowed
255 * from this pool.
256 *
257 * @return {@code true} if abandoned object removal is configured to be
258 * activated by borrowObject otherwise {@code false}
259 *
260 * @see AbandonedConfig#getRemoveAbandonedOnBorrow()
261 */
262 @Override
263 public boolean getRemoveAbandonedOnBorrow() {
264 final AbandonedConfig ac = this.abandonedConfig;
265 return ac != null && ac.getRemoveAbandonedOnBorrow();
266 }
267
268 /**
269 * Gets whether a check is made for abandoned objects when the evictor runs.
270 *
271 * @return {@code true} if abandoned object removal is configured to be
272 * activated when the evictor runs otherwise {@code false}
273 *
274 * @see AbandonedConfig#getRemoveAbandonedOnMaintenance()
275 */
276 @Override
277 public boolean getRemoveAbandonedOnMaintenance() {
278 final AbandonedConfig ac = this.abandonedConfig;
279 return ac != null && ac.getRemoveAbandonedOnMaintenance();
280 }
281
282 /**
283 * Obtains the timeout before which an object will be considered to be
284 * abandoned by this pool.
285 *
286 * @return The abandoned object timeout in seconds if abandoned object
287 * removal is configured for this pool; Integer.MAX_VALUE otherwise.
288 *
289 * @see AbandonedConfig#getRemoveAbandonedTimeout()
290 */
291 @Override
292 public int getRemoveAbandonedTimeout() {
293 final AbandonedConfig ac = this.abandonedConfig;
294 return ac != null ? ac.getRemoveAbandonedTimeout() : Integer.MAX_VALUE;
295 }
296
297
298 /**
299 * Sets the base pool configuration.
300 *
301 * @param conf the new configuration to use. This is used by value.
302 *
303 * @see GenericObjectPoolConfig
304 */
305 public void setConfig(final GenericObjectPoolConfig<T> conf) {
306 super.setConfig(conf);
307 setMaxIdle(conf.getMaxIdle());
308 setMinIdle(conf.getMinIdle());
309 setMaxTotal(conf.getMaxTotal());
310 }
311
312 /**
313 * Sets the abandoned object removal configuration.
314 *
315 * @param abandonedConfig the new configuration to use. This is used by value.
316 *
317 * @see AbandonedConfig
318 */
319 public void setAbandonedConfig(final AbandonedConfig abandonedConfig) {
320 if (abandonedConfig == null) {
321 this.abandonedConfig = null;
322 } else {
323 this.abandonedConfig = new AbandonedConfig();
324 this.abandonedConfig.setLogAbandoned(abandonedConfig.getLogAbandoned());
325 this.abandonedConfig.setLogWriter(abandonedConfig.getLogWriter());
326 this.abandonedConfig.setRemoveAbandonedOnBorrow(abandonedConfig.getRemoveAbandonedOnBorrow());
327 this.abandonedConfig.setRemoveAbandonedOnMaintenance(abandonedConfig.getRemoveAbandonedOnMaintenance());
328 this.abandonedConfig.setRemoveAbandonedTimeout(abandonedConfig.getRemoveAbandonedTimeout());
329 this.abandonedConfig.setUseUsageTracking(abandonedConfig.getUseUsageTracking());
330 this.abandonedConfig.setRequireFullStackTrace(abandonedConfig.getRequireFullStackTrace());
331 }
332 }
333
334 /**
335 * Obtains a reference to the factory used to create, destroy and validate
336 * the objects used by this pool.
337 *
338 * @return the factory
339 */
340 public PooledObjectFactory<T> getFactory() {
341 return factory;
342 }
343
344 /**
345 * Equivalent to <code>{@link #borrowObject(long)
346 * borrowObject}({@link #getMaxWaitMillis()})</code>.
347 * <p>
348 * {@inheritDoc}
349 * </p>
350 */
351 @Override
352 public T borrowObject() throws Exception {
353 return borrowObject(getMaxWaitMillis());
354 }
355
356 /**
357 * Borrows an object from the pool using the specific waiting time which only
358 * applies if {@link #getBlockWhenExhausted()} is true.
359 * <p>
360 * If there is one or more idle instance available in the pool, then an
361 * idle instance will be selected based on the value of {@link #getLifo()},
362 * activated and returned. If activation fails, or {@link #getTestOnBorrow()
363 * testOnBorrow} is set to <code>true</code> and validation fails, the
364 * instance is destroyed and the next available instance is examined. This
365 * continues until either a valid instance is returned or there are no more
366 * idle instances available.
367 * </p>
368 * <p>
369 * If there are no idle instances available in the pool, behavior depends on
370 * the {@link #getMaxTotal() maxTotal}, (if applicable)
371 * {@link #getBlockWhenExhausted()} and the value passed in to the
372 * <code>borrowMaxWaitMillis</code> parameter. If the number of instances
373 * checked out from the pool is less than <code>maxTotal,</code> a new
374 * instance is created, activated and (if applicable) validated and returned
375 * to the caller. If validation fails, a <code>NoSuchElementException</code>
376 * is thrown.
377 * </p>
378 * <p>
379 * If the pool is exhausted (no available idle instances and no capacity to
380 * create new ones), this method will either block (if
381 * {@link #getBlockWhenExhausted()} is true) or throw a
382 * <code>NoSuchElementException</code> (if
383 * {@link #getBlockWhenExhausted()} is false). The length of time that this
384 * method will block when {@link #getBlockWhenExhausted()} is true is
385 * determined by the value passed in to the <code>borrowMaxWaitMillis</code>
386 * parameter.
387 * </p>
388 * <p>
389 * When the pool is exhausted, multiple calling threads may be
390 * simultaneously blocked waiting for instances to become available. A
391 * "fairness" algorithm has been implemented to ensure that threads receive
392 * available instances in request arrival order.
393 * </p>
394 *
395 * @param borrowMaxWaitMillis The time to wait in milliseconds for an object
396 * to become available
397 *
398 * @return object instance from the pool
399 *
400 * @throws NoSuchElementException if an instance cannot be returned
401 *
402 * @throws Exception if an object instance cannot be returned due to an
403 * error
404 */
405 public T borrowObject(final long borrowMaxWaitMillis) throws Exception {
406 assertOpen();
407
408 final AbandonedConfig ac = this.abandonedConfig;
409 if (ac != null && ac.getRemoveAbandonedOnBorrow() &&
410 (getNumIdle() < 2) &&
411 (getNumActive() > getMaxTotal() - 3) ) {
412 removeAbandoned(ac);
413 }
414
415 PooledObject<T> p = null;
416
417 // Get local copy of current config so it is consistent for entire
418 // method execution
419 final boolean blockWhenExhausted = getBlockWhenExhausted();
420
421 boolean create;
422 final long waitTime = System.currentTimeMillis();
423
424 while (p == null) {
425 create = false;
426 p = idleObjects.pollFirst();
427 if (p == null) {
428 p = create();
429 if (p != null) {
430 create = true;
431 }
432 }
433 if (blockWhenExhausted) {
434 if (p == null) {
435 if (borrowMaxWaitMillis < 0) {
436 p = idleObjects.takeFirst();
437 } else {
438 p = idleObjects.pollFirst(borrowMaxWaitMillis,
439 TimeUnit.MILLISECONDS);
440 }
441 }
442 if (p == null) {
443 throw new NoSuchElementException(
444 "Timeout waiting for idle object");
445 }
446 } else {
447 if (p == null) {
448 throw new NoSuchElementException("Pool exhausted");
449 }
450 }
451 if (!p.allocate()) {
452 p = null;
453 }
454
455 if (p != null) {
456 try {
457 factory.activateObject(p);
458 } catch (final Exception e) {
459 try {
460 destroy(p);
461 } catch (final Exception e1) {
462 // Ignore - activation failure is more important
463 }
464 p = null;
465 if (create) {
466 final NoSuchElementException nsee = new NoSuchElementException(
467 "Unable to activate object");
468 nsee.initCause(e);
469 throw nsee;
470 }
471 }
472 if (p != null && getTestOnBorrow()) {
473 boolean validate = false;
474 Throwable validationThrowable = null;
475 try {
476 validate = factory.validateObject(p);
477 } catch (final Throwable t) {
478 PoolUtils.checkRethrow(t);
479 validationThrowable = t;
480 }
481 if (!validate) {
482 try {
483 destroy(p);
484 destroyedByBorrowValidationCount.incrementAndGet();
485 } catch (final Exception e) {
486 // Ignore - validation failure is more important
487 }
488 p = null;
489 if (create) {
490 final NoSuchElementException nsee = new NoSuchElementException(
491 "Unable to validate object");
492 nsee.initCause(validationThrowable);
493 throw nsee;
494 }
495 }
496 }
497 }
498 }
499
500 updateStatsBorrow(p, System.currentTimeMillis() - waitTime);
501
502 return p.getObject();
503 }
504
505 /**
506 * {@inheritDoc}
507 * <p>
508 * If {@link #getMaxIdle() maxIdle} is set to a positive value and the
509 * number of idle instances has reached this value, the returning instance
510 * is destroyed.
511 * </p>
512 * <p>
513 * If {@link #getTestOnReturn() testOnReturn} == true, the returning
514 * instance is validated before being returned to the idle instance pool. In
515 * this case, if validation fails, the instance is destroyed.
516 * </p>
517 * <p>
518 * Exceptions encountered destroying objects for any reason are swallowed
519 * but notified via a
520 * {@link org.apache.tomcat.dbcp.pool2.SwallowedExceptionListener}.
521 * </p>
522 */
523 @Override
524 public void returnObject(final T obj) {
525 final PooledObject<T> p = allObjects.get(new IdentityWrapper<>(obj));
526
527 if (p == null) {
528 if (!isAbandonedConfig()) {
529 throw new IllegalStateException(
530 "Returned object not currently part of this pool");
531 }
532 return; // Object was abandoned and removed
533 }
534
535 markReturningState(p);
536
537 final long activeTime = p.getActiveTimeMillis();
538
539 if (getTestOnReturn() && !factory.validateObject(p)) {
540 try {
541 destroy(p);
542 } catch (final Exception e) {
543 swallowException(e);
544 }
545 try {
546 ensureIdle(1, false);
547 } catch (final Exception e) {
548 swallowException(e);
549 }
550 updateStatsReturn(activeTime);
551 return;
552 }
553
554 try {
555 factory.passivateObject(p);
556 } catch (final Exception e1) {
557 swallowException(e1);
558 try {
559 destroy(p);
560 } catch (final Exception e) {
561 swallowException(e);
562 }
563 try {
564 ensureIdle(1, false);
565 } catch (final Exception e) {
566 swallowException(e);
567 }
568 updateStatsReturn(activeTime);
569 return;
570 }
571
572 if (!p.deallocate()) {
573 throw new IllegalStateException(
574 "Object has already been returned to this pool or is invalid");
575 }
576
577 final int maxIdleSave = getMaxIdle();
578 if (isClosed() || maxIdleSave > -1 && maxIdleSave <= idleObjects.size()) {
579 try {
580 destroy(p);
581 } catch (final Exception e) {
582 swallowException(e);
583 }
584 try {
585 ensureIdle(1, false);
586 } catch (final Exception e) {
587 swallowException(e);
588 }
589 } else {
590 if (getLifo()) {
591 idleObjects.addFirst(p);
592 } else {
593 idleObjects.addLast(p);
594 }
595 if (isClosed()) {
596 // Pool closed while object was being added to idle objects.
597 // Make sure the returned object is destroyed rather than left
598 // in the idle object pool (which would effectively be a leak)
599 clear();
600 }
601 }
602 updateStatsReturn(activeTime);
603 }
604
605 /**
606 * {@inheritDoc}
607 * <p>
608 * Activation of this method decrements the active count and attempts to
609 * destroy the instance.
610 * </p>
611 *
612 * @throws Exception if an exception occurs destroying the
613 * object
614 * @throws IllegalStateException if obj does not belong to this pool
615 */
616 @Override
617 public void invalidateObject(final T obj) throws Exception {
618 final PooledObject<T> p = allObjects.get(new IdentityWrapper<>(obj));
619 if (p == null) {
620 if (isAbandonedConfig()) {
621 return;
622 }
623 throw new IllegalStateException(
624 "Invalidated object not currently part of this pool");
625 }
626 synchronized (p) {
627 if (p.getState() != PooledObjectState.INVALID) {
628 destroy(p);
629 }
630 }
631 ensureIdle(1, false);
632 }
633
634 /**
635 * Clears any objects sitting idle in the pool by removing them from the
636 * idle instance pool and then invoking the configured
637 * {@link PooledObjectFactory#destroyObject(PooledObject)} method on each
638 * idle instance.
639 * <p>
640 * Implementation notes:
641 * </p>
642 * <ul>
643 * <li>This method does not destroy or effect in any way instances that are
644 * checked out of the pool when it is invoked.</li>
645 * <li>Invoking this method does not prevent objects being returned to the
646 * idle instance pool, even during its execution. Additional instances may
647 * be returned while removed items are being destroyed.</li>
648 * <li>Exceptions encountered destroying idle instances are swallowed
649 * but notified via a
650 * {@link org.apache.tomcat.dbcp.pool2.SwallowedExceptionListener}.</li>
651 * </ul>
652 */
653 @Override
654 public void clear() {
655 PooledObject<T> p = idleObjects.poll();
656
657 while (p != null) {
658 try {
659 destroy(p);
660 } catch (final Exception e) {
661 swallowException(e);
662 }
663 p = idleObjects.poll();
664 }
665 }
666
667 @Override
668 public int getNumActive() {
669 return allObjects.size() - idleObjects.size();
670 }
671
672 @Override
673 public int getNumIdle() {
674 return idleObjects.size();
675 }
676
677 /**
678 * Closes the pool. Once the pool is closed, {@link #borrowObject()} will
679 * fail with IllegalStateException, but {@link #returnObject(Object)} and
680 * {@link #invalidateObject(Object)} will continue to work, with returned
681 * objects destroyed on return.
682 * <p>
683 * Destroys idle instances in the pool by invoking {@link #clear()}.
684 * </p>
685 */
686 @Override
687 public void close() {
688 if (isClosed()) {
689 return;
690 }
691
692 synchronized (closeLock) {
693 if (isClosed()) {
694 return;
695 }
696
697 // Stop the evictor before the pool is closed since evict() calls
698 // assertOpen()
699 stopEvictor();
700
701 closed = true;
702 // This clear removes any idle objects
703 clear();
704
705 jmxUnregister();
706
707 // Release any threads that were waiting for an object
708 idleObjects.interuptTakeWaiters();
709 }
710 }
711
712 /**
713 * {@inheritDoc}
714 * <p>
715 * Successive activations of this method examine objects in sequence,
716 * cycling through objects in oldest-to-youngest order.
717 * </p>
718 */
719 @Override
720 public void evict() throws Exception {
721 assertOpen();
722
723 if (idleObjects.size() > 0) {
724
725 PooledObject<T> underTest = null;
726 final EvictionPolicy<T> evictionPolicy = getEvictionPolicy();
727
728 synchronized (evictionLock) {
729 final EvictionConfig evictionConfig = new EvictionConfig(
730 getMinEvictableIdleTimeMillis(),
731 getSoftMinEvictableIdleTimeMillis(),
732 getMinIdle());
733
734 final boolean testWhileIdle = getTestWhileIdle();
735
736 for (int i = 0, m = getNumTests(); i < m; i++) {
737 if (evictionIterator == null || !evictionIterator.hasNext()) {
738 evictionIterator = new EvictionIterator(idleObjects);
739 }
740 if (!evictionIterator.hasNext()) {
741 // Pool exhausted, nothing to do here
742 return;
743 }
744
745 try {
746 underTest = evictionIterator.next();
747 } catch (final NoSuchElementException nsee) {
748 // Object was borrowed in another thread
749 // Don't count this as an eviction test so reduce i;
750 i--;
751 evictionIterator = null;
752 continue;
753 }
754
755 if (!underTest.startEvictionTest()) {
756 // Object was borrowed in another thread
757 // Don't count this as an eviction test so reduce i;
758 i--;
759 continue;
760 }
761
762 // User provided eviction policy could throw all sorts of
763 // crazy exceptions. Protect against such an exception
764 // killing the eviction thread.
765 boolean evict;
766 try {
767 evict = evictionPolicy.evict(evictionConfig, underTest,
768 idleObjects.size());
769 } catch (final Throwable t) {
770 // Slightly convoluted as SwallowedExceptionListener
771 // uses Exception rather than Throwable
772 PoolUtils.checkRethrow(t);
773 swallowException(new Exception(t));
774 // Don't evict on error conditions
775 evict = false;
776 }
777
778 if (evict) {
779 destroy(underTest);
780 destroyedByEvictorCount.incrementAndGet();
781 } else {
782 if (testWhileIdle) {
783 boolean active = false;
784 try {
785 factory.activateObject(underTest);
786 active = true;
787 } catch (final Exception e) {
788 destroy(underTest);
789 destroyedByEvictorCount.incrementAndGet();
790 }
791 if (active) {
792 if (!factory.validateObject(underTest)) {
793 destroy(underTest);
794 destroyedByEvictorCount.incrementAndGet();
795 } else {
796 try {
797 factory.passivateObject(underTest);
798 } catch (final Exception e) {
799 destroy(underTest);
800 destroyedByEvictorCount.incrementAndGet();
801 }
802 }
803 }
804 }
805 if (!underTest.endEvictionTest(idleObjects)) {
806 // TODO - May need to add code here once additional
807 // states are used
808 }
809 }
810 }
811 }
812 }
813 final AbandonedConfig ac = this.abandonedConfig;
814 if (ac != null && ac.getRemoveAbandonedOnMaintenance()) {
815 removeAbandoned(ac);
816 }
817 }
818
819 /**
820 * Tries to ensure that {@link #getMinIdle()} idle instances are available
821 * in the pool.
822 *
823 * @throws Exception If the associated factory throws an exception
824 * @since 2.4
825 */
826 public void preparePool() throws Exception {
827 if (getMinIdle() < 1) {
828 return;
829 }
830 ensureMinIdle();
831 }
832
833 /**
834 * Attempts to create a new wrapped pooled object.
835 * <p>
836 * If there are {@link #getMaxTotal()} objects already in circulation
837 * or in process of being created, this method returns null.
838 * </p>
839 *
840 * @return The new wrapped pooled object
841 *
842 * @throws Exception if the object factory's {@code makeObject} fails
843 */
844 private PooledObject<T> create() throws Exception {
845 int localMaxTotal = getMaxTotal();
846 // This simplifies the code later in this method
847 if (localMaxTotal < 0) {
848 localMaxTotal = Integer.MAX_VALUE;
849 }
850
851 final long localStartTimeMillis = System.currentTimeMillis();
852 final long localMaxWaitTimeMillis = Math.max(getMaxWaitMillis(), 0);
853
854 // Flag that indicates if create should:
855 // - TRUE: call the factory to create an object
856 // - FALSE: return null
857 // - null: loop and re-test the condition that determines whether to
858 // call the factory
859 Boolean create = null;
860 while (create == null) {
861 synchronized (makeObjectCountLock) {
862 final long newCreateCount = createCount.incrementAndGet();
863 if (newCreateCount > localMaxTotal) {
864 // The pool is currently at capacity or in the process of
865 // making enough new objects to take it to capacity.
866 createCount.decrementAndGet();
867 if (makeObjectCount == 0) {
868 // There are no makeObject() calls in progress so the
869 // pool is at capacity. Do not attempt to create a new
870 // object. Return and wait for an object to be returned
871 create = Boolean.FALSE;
872 } else {
873 // There are makeObject() calls in progress that might
874 // bring the pool to capacity. Those calls might also
875 // fail so wait until they complete and then re-test if
876 // the pool is at capacity or not.
877 makeObjectCountLock.wait(localMaxWaitTimeMillis);
878 }
879 } else {
880 // The pool is not at capacity. Create a new object.
881 makeObjectCount++;
882 create = Boolean.TRUE;
883 }
884 }
885
886 // Do not block more if maxWaitTimeMillis is set.
887 if (create == null &&
888 (localMaxWaitTimeMillis > 0 &&
889 System.currentTimeMillis() - localStartTimeMillis >= localMaxWaitTimeMillis)) {
890 create = Boolean.FALSE;
891 }
892 }
893
894 if (!create.booleanValue()) {
895 return null;
896 }
897
898 final PooledObject<T> p;
899 try {
900 p = factory.makeObject();
901 if (getTestOnCreate() && !factory.validateObject(p)) {
902 createCount.decrementAndGet();
903 return null;
904 }
905 } catch (final Throwable e) {
906 createCount.decrementAndGet();
907 throw e;
908 } finally {
909 synchronized (makeObjectCountLock) {
910 makeObjectCount--;
911 makeObjectCountLock.notifyAll();
912 }
913 }
914
915 final AbandonedConfig ac = this.abandonedConfig;
916 if (ac != null && ac.getLogAbandoned()) {
917 p.setLogAbandoned(true);
918 p.setRequireFullStackTrace(ac.getRequireFullStackTrace());
919 }
920
921 createdCount.incrementAndGet();
922 allObjects.put(new IdentityWrapper<>(p.getObject()), p);
923 return p;
924 }
925
926 /**
927 * Destroys a wrapped pooled object.
928 *
929 * @param toDestroy The wrapped pooled object to destroy
930 *
931 * @throws Exception If the factory fails to destroy the pooled object
932 * cleanly
933 */
934 private void destroy(final PooledObject<T> toDestroy) throws Exception {
935 toDestroy.invalidate();
936 idleObjects.remove(toDestroy);
937 allObjects.remove(new IdentityWrapper<>(toDestroy.getObject()));
938 try {
939 factory.destroyObject(toDestroy);
940 } finally {
941 destroyedCount.incrementAndGet();
942 createCount.decrementAndGet();
943 }
944 }
945
946 @Override
947 void ensureMinIdle() throws Exception {
948 ensureIdle(getMinIdle(), true);
949 }
950
951 /**
952 * Tries to ensure that {@code idleCount} idle instances exist in the pool.
953 * <p>
954 * Creates and adds idle instances until either {@link #getNumIdle()} reaches {@code idleCount}
955 * or the total number of objects (idle, checked out, or being created) reaches
956 * {@link #getMaxTotal()}. If {@code always} is false, no instances are created unless
957 * there are threads waiting to check out instances from the pool.
958 * </p>
959 *
960 * @param idleCount the number of idle instances desired
961 * @param always true means create instances even if the pool has no threads waiting
962 * @throws Exception if the factory's makeObject throws
963 */
964 private void ensureIdle(final int idleCount, final boolean always) throws Exception {
965 if (idleCount < 1 || isClosed() || (!always && !idleObjects.hasTakeWaiters())) {
966 return;
967 }
968
969 while (idleObjects.size() < idleCount) {
970 final PooledObject<T> p = create();
971 if (p == null) {
972 // Can't create objects, no reason to think another call to
973 // create will work. Give up.
974 break;
975 }
976 if (getLifo()) {
977 idleObjects.addFirst(p);
978 } else {
979 idleObjects.addLast(p);
980 }
981 }
982 if (isClosed()) {
983 // Pool closed while object was being added to idle objects.
984 // Make sure the returned object is destroyed rather than left
985 // in the idle object pool (which would effectively be a leak)
986 clear();
987 }
988 }
989
990 /**
991 * Creates an object, and place it into the pool. addObject() is useful for
992 * "pre-loading" a pool with idle objects.
993 * <p>
994 * If there is no capacity available to add to the pool, this is a no-op
995 * (no exception, no impact to the pool). </p>
996 */
997 @Override
998 public void addObject() throws Exception {
999 assertOpen();
1000 if (factory == null) {
1001 throw new IllegalStateException(
1002 "Cannot add objects without a factory.");
1003 }
1004 final PooledObject<T> p = create();
1005 addIdleObject(p);
1006 }
1007
1008 /**
1009 * Adds the provided wrapped pooled object to the set of idle objects for
1010 * this pool. The object must already be part of the pool. If {@code p}
1011 * is null, this is a no-op (no exception, but no impact on the pool).
1012 *
1013 * @param p The object to make idle
1014 *
1015 * @throws Exception If the factory fails to passivate the object
1016 */
1017 private void addIdleObject(final PooledObject<T> p) throws Exception {
1018 if (p != null) {
1019 factory.passivateObject(p);
1020 if (getLifo()) {
1021 idleObjects.addFirst(p);
1022 } else {
1023 idleObjects.addLast(p);
1024 }
1025 }
1026 }
1027
1028 /**
1029 * Calculates the number of objects to test in a run of the idle object
1030 * evictor.
1031 *
1032 * @return The number of objects to test for validity
1033 */
1034 private int getNumTests() {
1035 final int numTestsPerEvictionRun = getNumTestsPerEvictionRun();
1036 if (numTestsPerEvictionRun >= 0) {
1037 return Math.min(numTestsPerEvictionRun, idleObjects.size());
1038 }
1039 return (int) (Math.ceil(idleObjects.size() /
1040 Math.abs((double) numTestsPerEvictionRun)));
1041 }
1042
1043 /**
1044 * Recovers abandoned objects which have been checked out but
1045 * not used since longer than the removeAbandonedTimeout.
1046 *
1047 * @param ac The configuration to use to identify abandoned objects
1048 */
1049 private void removeAbandoned(final AbandonedConfig ac) {
1050 // Generate a list of abandoned objects to remove
1051 final long now = System.currentTimeMillis();
1052 final long timeout =
1053 now - (ac.getRemoveAbandonedTimeout() * 1000L);
1054 final ArrayList<PooledObject<T>> remove = new ArrayList<>();
1055 final Iterator<PooledObject<T>> it = allObjects.values().iterator();
1056 while (it.hasNext()) {
1057 final PooledObject<T> pooledObject = it.next();
1058 synchronized (pooledObject) {
1059 if (pooledObject.getState() == PooledObjectState.ALLOCATED &&
1060 pooledObject.getLastUsedTime() <= timeout) {
1061 pooledObject.markAbandoned();
1062 remove.add(pooledObject);
1063 }
1064 }
1065 }
1066
1067 // Now remove the abandoned objects
1068 final Iterator<PooledObject<T>> itr = remove.iterator();
1069 while (itr.hasNext()) {
1070 final PooledObject<T> pooledObject = itr.next();
1071 if (ac.getLogAbandoned()) {
1072 pooledObject.printStackTrace(ac.getLogWriter());
1073 }
1074 try {
1075 invalidateObject(pooledObject.getObject());
1076 } catch (final Exception e) {
1077 e.printStackTrace();
1078 }
1079 }
1080 }
1081
1082
1083 //--- Usage tracking support -----------------------------------------------
1084
1085 @Override
1086 public void use(final T pooledObject) {
1087 final AbandonedConfig ac = this.abandonedConfig;
1088 if (ac != null && ac.getUseUsageTracking()) {
1089 final PooledObject<T> wrapper = allObjects.get(new IdentityWrapper<>(pooledObject));
1090 wrapper.use();
1091 }
1092 }
1093
1094
1095 //--- JMX support ----------------------------------------------------------
1096
1097 private volatile String factoryType = null;
1098
1099 /**
1100 * Returns an estimate of the number of threads currently blocked waiting for
1101 * an object from the pool. This is intended for monitoring only, not for
1102 * synchronization control.
1103 *
1104 * @return The estimate of the number of threads currently blocked waiting
1105 * for an object from the pool
1106 */
1107 @Override
1108 public int getNumWaiters() {
1109 if (getBlockWhenExhausted()) {
1110 return idleObjects.getTakeQueueLength();
1111 }
1112 return 0;
1113 }
1114
1115 /**
1116 * Returns the type - including the specific type rather than the generic -
1117 * of the factory.
1118 *
1119 * @return A string representation of the factory type
1120 */
1121 @Override
1122 public String getFactoryType() {
1123 // Not thread safe. Accept that there may be multiple evaluations.
1124 if (factoryType == null) {
1125 final StringBuilder result = new StringBuilder();
1126 result.append(factory.getClass().getName());
1127 result.append('<');
1128 final Class<?> pooledObjectType =
1129 PoolImplUtils.getFactoryType(factory.getClass());
1130 result.append(pooledObjectType.getName());
1131 result.append('>');
1132 factoryType = result.toString();
1133 }
1134 return factoryType;
1135 }
1136
1137 /**
1138 * Provides information on all the objects in the pool, both idle (waiting
1139 * to be borrowed) and active (currently borrowed).
1140 * <p>
1141 * Note: This is named listAllObjects so it is presented as an operation via
1142 * JMX. That means it won't be invoked unless the explicitly requested
1143 * whereas all attributes will be automatically requested when viewing the
1144 * attributes for an object in a tool like JConsole.
1145 * </p>
1146 *
1147 * @return Information grouped on all the objects in the pool
1148 */
1149 @Override
1150 public Set<DefaultPooledObjectInfo> listAllObjects() {
1151 final Set<DefaultPooledObjectInfo> result =
1152 new HashSet<>(allObjects.size());
1153 for (final PooledObject<T> p : allObjects.values()) {
1154 result.add(new DefaultPooledObjectInfo(p));
1155 }
1156 return result;
1157 }
1158
1159 // --- configuration attributes --------------------------------------------
1160
1161 private volatile int maxIdle = GenericObjectPoolConfig.DEFAULT_MAX_IDLE;
1162 private volatile int minIdle = GenericObjectPoolConfig.DEFAULT_MIN_IDLE;
1163 private final PooledObjectFactory<T> factory;
1164
1165
1166 // --- internal attributes -------------------------------------------------
1167
1168 /*
1169 * All of the objects currently associated with this pool in any state. It
1170 * excludes objects that have been destroyed. The size of
1171 * {@link #allObjects} will always be less than or equal to {@link
1172 * #_maxActive}. Map keys are pooled objects, values are the PooledObject
1173 * wrappers used internally by the pool.
1174 */
1175 private final Map<IdentityWrapper<T>, PooledObject<T>> allObjects =
1176 new ConcurrentHashMap<>();
1177 /*
1178 * The combined count of the currently created objects and those in the
1179 * process of being created. Under load, it may exceed {@link #_maxActive}
1180 * if multiple threads try and create a new object at the same time but
1181 * {@link #create()} will ensure that there are never more than
1182 * {@link #_maxActive} objects created at any one time.
1183 */
1184 private final AtomicLong createCount = new AtomicLong(0);
1185 private long makeObjectCount = 0;
1186 private final Object makeObjectCountLock = new Object();
1187 private final LinkedBlockingDeque<PooledObject<T>> idleObjects;
1188
1189 // JMX specific attributes
1190 private static final String ONAME_BASE =
1191 "org.apache.tomcat.dbcp.pool2:type=GenericObjectPool,name=";
1192
1193 // Additional configuration properties for abandoned object tracking
1194 private volatile AbandonedConfig abandonedConfig = null;
1195
1196 @Override
1197 protected void toStringAppendFields(final StringBuilder builder) {
1198 super.toStringAppendFields(builder);
1199 builder.append(", factoryType=");
1200 builder.append(factoryType);
1201 builder.append(", maxIdle=");
1202 builder.append(maxIdle);
1203 builder.append(", minIdle=");
1204 builder.append(minIdle);
1205 builder.append(", factory=");
1206 builder.append(factory);
1207 builder.append(", allObjects=");
1208 builder.append(allObjects);
1209 builder.append(", createCount=");
1210 builder.append(createCount);
1211 builder.append(", idleObjects=");
1212 builder.append(idleObjects);
1213 builder.append(", abandonedConfig=");
1214 builder.append(abandonedConfig);
1215 }
1216
1217 }
1218