in src/main/java/org/apache/commons/pool3/impl/GenericKeyedObjectPool.java [421:520]
public T borrowObject(final K key, final long borrowMaxWaitMillis) throws E {
assertOpen();
final AbandonedConfig ac = this.abandonedConfig;
if (ac != null && ac.getRemoveAbandonedOnBorrow() && getNumIdle() < 2 &&
getNumActive() > getMaxTotal() - 3) {
removeAbandoned(ac);
}
PooledObject<T> p = null;
// Get local copy of current config so it is consistent for entire
// method execution
final boolean blockWhenExhausted = getBlockWhenExhausted();
boolean create;
final Instant waitTime = Instant.now();
final ObjectDeque<T> objectDeque = register(key);
try {
while (p == null) {
create = false;
p = objectDeque.getIdleObjects().pollFirst();
if (p == null) {
p = create(key);
if (!PooledObject.isNull(p)) {
create = true;
}
}
if (blockWhenExhausted) {
if (PooledObject.isNull(p)) {
try {
p = borrowMaxWaitMillis < 0 ? objectDeque.getIdleObjects().takeFirst() :
objectDeque.getIdleObjects().pollFirst(borrowMaxWaitMillis, TimeUnit.MILLISECONDS);
} catch (final InterruptedException e) {
throw cast(e);
}
}
if (PooledObject.isNull(p)) {
throw new NoSuchElementException(appendStats(
"Timeout waiting for idle object, borrowMaxWaitMillis=" + borrowMaxWaitMillis));
}
} else if (PooledObject.isNull(p)) {
throw new NoSuchElementException(appendStats("Pool exhausted"));
}
if (!p.allocate()) {
p = null;
}
if (!PooledObject.isNull(p)) {
try {
factory.activateObject(key, p);
} catch (final Exception e) {
try {
destroy(key, p, true, DestroyMode.NORMAL);
} catch (final Exception ignored) {
// ignored - activation failure is more important
}
p = null;
if (create) {
final NoSuchElementException nsee = new NoSuchElementException(appendStats("Unable to activate object"));
nsee.initCause(e);
throw nsee;
}
}
if (!PooledObject.isNull(p) && getTestOnBorrow()) {
boolean validate = false;
Throwable validationThrowable = null;
try {
validate = factory.validateObject(key, p);
} catch (final Throwable t) {
PoolUtils.checkRethrow(t);
validationThrowable = t;
}
if (!validate) {
try {
destroy(key, p, true, DestroyMode.NORMAL);
destroyedByBorrowValidationCount.incrementAndGet();
} catch (final Exception ignored) {
// ignored - validation failure is more important
}
p = null;
if (create) {
final NoSuchElementException nsee = new NoSuchElementException(
appendStats("Unable to validate object"));
nsee.initCause(validationThrowable);
throw nsee;
}
}
}
}
}
} finally {
deregister(key);
}
updateStatsBorrow(p, Duration.between(waitTime, Instant.now()));
return p.getObject();
}