/** * Recover abandoned objects which have been checked out but not used since longer than the * removeAbandonedTimeout. * * @param ac The configuration to use to identify abandoned objects */ private void removeAbandoned(AbandonedConfig ac) { // Generate a list of abandoned objects to remove final long now = System.currentTimeMillis(); final long timeout = now - (ac.getRemoveAbandonedTimeout() * 1000L); ArrayList<PooledObject<T>> remove = new ArrayList<>(); Iterator<PooledObject<T>> it = allObjects.values().iterator(); while (it.hasNext()) { PooledObject<T> pooledObject = it.next(); synchronized (pooledObject) { if (pooledObject.getState() == PooledObjectState.ALLOCATED && pooledObject.getLastUsedTime() <= timeout) { pooledObject.markAbandoned(); remove.add(pooledObject); } } } // Now remove the abandoned objects Iterator<PooledObject<T>> itr = remove.iterator(); while (itr.hasNext()) { PooledObject<T> pooledObject = itr.next(); if (ac.getLogAbandoned()) { pooledObject.printStackTrace(ac.getLogWriter()); } try { invalidateObject(pooledObject.getObject()); } catch (Exception e) { e.printStackTrace(); } } }
/** * Attempts to create a new wrapped pooled object. * * <p>If there are {@link #getMaxTotal()} objects already in circulation or in process of being * created, this method returns null. * * @return The new wrapped pooled object * @throws Exception if the object factory's {@code makeObject} fails */ private PooledObject<T> create() throws Exception { int localMaxTotal = getMaxTotal(); long newCreateCount = createCount.incrementAndGet(); if (localMaxTotal > -1 && newCreateCount > localMaxTotal || newCreateCount > Integer.MAX_VALUE) { createCount.decrementAndGet(); return null; } final PooledObject<T> p; try { p = factory.makeObject(); } catch (Exception e) { createCount.decrementAndGet(); throw e; } AbandonedConfig ac = this.abandonedConfig; if (ac != null && ac.getLogAbandoned()) { p.setLogAbandoned(true); } createdCount.incrementAndGet(); allObjects.put(new IdentityWrapper<>(p.getObject()), p); return p; }
/** * Sets the abandoned object removal configuration. * * @param abandonedConfig the new configuration to use. This is used by value. * @see AbandonedConfig */ public void setAbandonedConfig(AbandonedConfig abandonedConfig) { if (abandonedConfig == null) { this.abandonedConfig = null; } else { this.abandonedConfig = new AbandonedConfig(); this.abandonedConfig.setLogAbandoned(abandonedConfig.getLogAbandoned()); this.abandonedConfig.setLogWriter(abandonedConfig.getLogWriter()); this.abandonedConfig.setRemoveAbandonedOnBorrow(abandonedConfig.getRemoveAbandonedOnBorrow()); this.abandonedConfig.setRemoveAbandonedOnMaintenance( abandonedConfig.getRemoveAbandonedOnMaintenance()); this.abandonedConfig.setRemoveAbandonedTimeout(abandonedConfig.getRemoveAbandonedTimeout()); this.abandonedConfig.setUseUsageTracking(abandonedConfig.getUseUsageTracking()); } }
/** * Will this pool identify and log any abandoned objects? * * @return {@code true} if abandoned object removal is configured for this pool and removal events * are to be logged otherwise {@code false} * @see AbandonedConfig#getLogAbandoned() */ @Override public boolean getLogAbandoned() { AbandonedConfig ac = this.abandonedConfig; return ac != null && ac.getLogAbandoned(); }