StrictConnPool implements ManagedConnPool<T, C> { @Override public Future<PoolEntry<T, C>> lease( final T route, final Object state, final Timeout requestTimeout, final FutureCallback<PoolEntry<T, C>> callback) { Args.notNull(route, "Route"); Args.notNull(requestTimeout, "Request timeout"); Asserts.check(!this.isShutDown.get(), "Connection pool shut down"); final Deadline deadline = Deadline.calculate(requestTimeout); final BasicFuture<PoolEntry<T, C>> future = new BasicFuture<>(callback); final boolean acquiredLock; try { acquiredLock = this.lock.tryLock(requestTimeout.getDuration(), requestTimeout.getTimeUnit()); } catch (final InterruptedException interruptedException) { Thread.currentThread().interrupt(); future.cancel(); return future; } if (acquiredLock) { try { final LeaseRequest<T, C> request = new LeaseRequest<>(route, state, requestTimeout, future); final boolean completed = processPendingRequest(request); if (!request.isDone() && !completed) { this.leasingRequests.add(request); } if (request.isDone()) { this.completedRequests.add(request); } } finally { this.lock.unlock(); } fireCallbacks(); } else { future.failed(DeadlineTimeoutException.from(deadline)); } return future; } StrictConnPool(
            final int defaultMaxPerRoute,
            final int maxTotal,
            final TimeValue timeToLive,
            final PoolReusePolicy policy,
            final DisposalCallback<C> disposalCallback,
            final ConnPoolListener<T> connPoolListener);  StrictConnPool(
            final int defaultMaxPerRoute,
            final int maxTotal,
            final TimeValue timeToLive,
            final PoolReusePolicy policy,
            final ConnPoolListener<T> connPoolListener);  StrictConnPool(final int defaultMaxPerRoute, final int maxTotal); boolean isShutdown(); @Override void close(final CloseMode closeMode); @Override void close(); @Override Future<PoolEntry<T, C>> lease(
            final T route, final Object state,
            final Timeout requestTimeout,
            final FutureCallback<PoolEntry<T, C>> callback); Future<PoolEntry<T, C>> lease(final T route, final Object state); @Override void release(final PoolEntry<T, C> entry, final boolean reusable); void validatePendingRequests(); @Override void setMaxTotal(final int max); @Override int getMaxTotal(); @Override void setDefaultMaxPerRoute(final int max); @Override int getDefaultMaxPerRoute(); @Override void setMaxPerRoute(final T route, final int max); @Override int getMaxPerRoute(final T route); @Override PoolStats getTotalStats(); @Override PoolStats getStats(final T route); @Override Set<T> getRoutes(); void enumAvailable(final Callback<PoolEntry<T, C>> callback); void enumLeased(final Callback<PoolEntry<T, C>> callback); @Override void closeIdle(final TimeValue idleTime); @Override void closeExpired(); @Override String toString();  }
@Test public void testLeaseInvalid() throws Exception { final StrictConnPool<String, HttpConnection> pool = new StrictConnPool<>(2, 10); try { pool.lease(null, null, Timeout.ZERO_MILLISECONDS, null); Assert.fail("NullPointerException should have been thrown"); } catch (final NullPointerException expected) { } try { pool.lease("somehost", null, null, null); Assert.fail("IllegalArgumentException should have been thrown"); } catch (final NullPointerException expected) { } }
@Test public void testLeaseRequestLockTimeout() throws Exception { final StrictConnPool<String, HttpConnection> pool = new StrictConnPool<>(1, 1); final CountDownLatch lockHeld = new CountDownLatch(1); final Thread holdInternalLock = new HoldInternalLockThread(pool, lockHeld); holdInternalLock.start(); lockHeld.await(); final Future<PoolEntry<String, HttpConnection>> future2 = pool.lease("somehost", null, Timeout.ofMilliseconds(10), null); try { future2.get(); } catch (final ExecutionException executionException) { Assert.assertTrue(executionException.getCause() instanceof DeadlineTimeoutException); holdInternalLock.interrupt(); return; } Assert.fail("Expected deadline timeout."); }
@Test public void testLeaseRequestInterrupted() throws Exception { final StrictConnPool<String, HttpConnection> pool = new StrictConnPool<>(1, 1); final CountDownLatch lockHeld = new CountDownLatch(1); final Thread holdInternalLock = new HoldInternalLockThread(pool, lockHeld); holdInternalLock.start(); lockHeld.await(); Thread.currentThread().interrupt(); final Future<PoolEntry<String, HttpConnection>> future2 = pool.lease("somehost", null, Timeout.ofMilliseconds(10), null); Assert.assertTrue(Thread.interrupted()); try { future2.get(); } catch (final CancellationException cancellationException) { holdInternalLock.interrupt(); return; } Assert.fail("Expected interrupted exception."); }