public BasicPool<T> build() { return new BasicPool<T>(this); } }
@Override public void close() throws IOException { synchronized (pool) { if (LOG.isDebugEnabled()) LOG.debug("{} closing, with {} resources ({})", new Object[] {this, pool.size(), getMetrics()}); closed.set(true); for (T resource : pool) { totalClosedCount.incrementAndGet(); closer.apply(resource); } pool.clear(); } }
@Override public <R> R exec(Function<? super T,R> receiver) { Lease<T> lease = leaseObject(); try { if (LOG.isTraceEnabled()) LOG.trace("{} executing {} with leasee {}", new Object[] {this, receiver, lease.leasedObject()}); return receiver.apply(lease.leasedObject()); } finally { Streams.closeQuietly(lease); } }
@Test public void testConcurrentCallsNeverHaveSameVal() throws Exception { final Pool<Integer> pool = BasicPool.<Integer>builder().supplier(supplier).build(); final Set<Lease<Integer>> leases = Collections.newSetFromMap(new ConcurrentHashMap<Lease<Integer>, Boolean>()); List<ListenableFuture<?>> futures = Lists.newArrayList(); for (int i = 0; i < 1000; i++) { futures.add(executor.submit(new Runnable() { @Override public void run() { leases.add(pool.leaseObject()); } })); } Futures.allAsList(futures).get(); Set<Integer> currentlyLeased = Sets.newLinkedHashSet(); for (Lease<Integer> lease : leases) { boolean val = currentlyLeased.add(lease.leasedObject()); if (!val) fail("duplicate="+lease.leasedObject()+"; vals="+leases); } } }
@Test public void testGeneratesNewValuesWhenRequired() throws Exception { Pool<Integer> pool = BasicPool.<Integer>builder().supplier(supplier).build(); Lease<Integer> lease1 = pool.leaseObject(); assertEquals(lease1.leasedObject(), (Integer)0); Lease<Integer> lease2 = pool.leaseObject(); assertEquals(lease2.leasedObject(), (Integer)1); }
@Test public void testClosesResourceReturnedAfterPoolIsClosed() throws Exception { Pool<Integer> pool = BasicPool.<Integer>builder().supplier(supplier).closer(closer).build(); Lease<Integer> lease1 = pool.leaseObject(); pool.close(); assertEquals(closedVals, ImmutableList.of()); lease1.close(); assertEquals(closedVals, ImmutableList.of(lease1.leasedObject())); }
private void returnLeasee(T val) { currentLeasedCount.decrementAndGet(); synchronized (pool) { if (closed.get()) { totalClosedCount.incrementAndGet(); if (LOG.isDebugEnabled()) LOG.debug("{} closing returned leasee {}, because pool closed ({})", new Object[] {this, val, getMetrics()}); closer.apply(val); } else { if (LOG.isTraceEnabled()) LOG.trace("{} adding {} back into pool ({})", new Object[] {this, val, getMetrics()}); pool.addLast(val); } } }
@Test public void testGeneratesNewIfOnlyUnviableValsInPool() throws Exception { Pool<Integer> pool = BasicPool.<Integer>builder().supplier(supplier).viabilityChecker(Predicates.alwaysFalse()).closer(closer).build(); Lease<Integer> lease1 = pool.leaseObject(); assertEquals(lease1.leasedObject(), (Integer)0); lease1.close(); Lease<Integer> lease2 = pool.leaseObject(); assertEquals(lease2.leasedObject(), (Integer)1); // Expect the "unviable" resource to have been closed assertEquals(closedVals, ImmutableList.of(0)); }
if (viabilityChecker.apply(existing)) { currentLeasedCount.incrementAndGet(); if (LOG.isTraceEnabled()) LOG.trace("{} reusing existing pool entry {} ({})", new Object[] {this, existing, getMetrics()}); return new BasicLease(existing); } else { totalCreatedCount.incrementAndGet(); currentLeasedCount.incrementAndGet(); if (LOG.isDebugEnabled()) LOG.debug("{} acquired and returning new entry {} ({})", new Object[] {this, result, getMetrics()}); return new BasicLease(result);
@Test public void testReusesReturnedVals() throws Exception { Pool<Integer> pool = BasicPool.<Integer>builder().supplier(supplier).build(); Lease<Integer> lease1 = pool.leaseObject(); assertEquals(lease1.leasedObject(), (Integer)0); lease1.close(); Lease<Integer> lease2 = pool.leaseObject(); assertEquals(lease2.leasedObject(), (Integer)0); }
@Test public void testClosesResourcesInPool() throws Exception { Pool<Integer> pool = BasicPool.<Integer>builder().supplier(supplier).closer(closer).build(); Lease<Integer> lease1 = pool.leaseObject(); Lease<Integer> lease2 = pool.leaseObject(); lease1.close(); lease2.close(); pool.close(); assertEquals(closedVals, ImmutableList.of(0, 1)); }
@Test public void testDoesNotReuseUnviableVals() throws Exception { Pool<Integer> pool = BasicPool.<Integer>builder().supplier(supplier).viabilityChecker(Predicates.alwaysFalse()).build(); Lease<Integer> lease1 = pool.leaseObject(); assertEquals(lease1.leasedObject(), (Integer)0); lease1.close(); Lease<Integer> lease2 = pool.leaseObject(); assertEquals(lease2.leasedObject(), (Integer)1); }
@Test public void testReusesOnlyViableVals() throws Exception { Pool<Integer> pool = BasicPool.<Integer>builder().supplier(supplier).viabilityChecker(Predicates.equalTo(1)).build(); Lease<Integer> lease1 = pool.leaseObject(); Lease<Integer> lease2 = pool.leaseObject(); Lease<Integer> lease3 = pool.leaseObject(); lease1.close(); lease2.close(); lease3.close(); Lease<Integer> lease4 = pool.leaseObject(); assertEquals(lease4.leasedObject(), (Integer)1); }
private BasicPool<SshTool> buildPool(final Map<String, ?> properties) { return BasicPool.<SshTool>builder() .name(getDisplayName()+"@"+address+":"+getPort()+ (config().getRaw(SSH_HOST).isPresent() ? "("+getConfig(SSH_HOST)+":"+getPort()+")" : "")+ ":hash"+System.identityHashCode(this)) .supplier(new Supplier<SshTool>() { @Override public SshTool get() { return connectSsh(properties); }}) .viabilityChecker(new Predicate<SshTool>() { @Override public boolean apply(SshTool input) { return input != null && input.isConnected(); }}) .closer(new Function<SshTool,Void>() { @Override public Void apply(SshTool input) { if (LOG.isDebugEnabled()) { LOG.debug("{} closing pool for {}", this, input); } try { input.disconnect(); } catch (Exception e) { if (logSsh.isDebugEnabled()) logSsh.debug("On machine "+SshMachineLocation.this+", ssh-disconnect failed", e); } return null; }}) .build(); }