blob: 2fa4409be7c120e40944a1a4d7655c89972ff62d [file] [log] [blame]
/*=============================================================================#
# Copyright (c) 2009, 2020 Stephan Wahlbrink and others.
#
# This program and the accompanying materials are made available under the
# terms of the Eclipse Public License 2.0 which is available at
# https://www.eclipse.org/legal/epl-2.0, or the Apache License, Version 2.0
# which is available at https://www.apache.org/licenses/LICENSE-2.0.
#
# SPDX-License-Identifier: EPL-2.0 OR Apache-2.0
#
# Contributors:
# Stephan Wahlbrink <sw@wahlbrink.eu> - initial API and implementation
#=============================================================================*/
package org.eclipse.statet.internal.rj.servi;
import org.apache.commons.pool2.PooledObject;
import org.apache.commons.pool2.impl.DefaultEvictionPolicy;
import org.apache.commons.pool2.impl.EvictionConfig;
import org.apache.commons.pool2.impl.EvictionPolicy;
import org.apache.commons.pool2.impl.GenericObjectPool;
import org.apache.commons.pool2.impl.GenericObjectPoolConfig;
import org.eclipse.statet.jcommons.collections.ImList;
import org.eclipse.statet.jcommons.lang.NonNullByDefault;
import org.eclipse.statet.rj.servi.pool.PoolConfig;
@NonNullByDefault
public class APool2 extends GenericObjectPool<APool2NodeHandler> {
private static final byte CLOSING= 2;
private static final byte CLOSING_FINALLY= 3;
private static final byte CLOSED= 4;
private static final EvictionPolicy<APool2NodeHandler> EVICTION_POLICY= new DefaultEvictionPolicy<APool2NodeHandler>() {
@Override
public boolean evict(final EvictionConfig config,
final PooledObject<APool2NodeHandler> underTest, final int idleCount) {
return (super.evict(config, underTest, idleCount)
|| underTest.getObject().isEvictRequested(0) );
}
};
private static GenericObjectPoolConfig<APool2NodeHandler> createAConfig(final PoolConfig config) {
final GenericObjectPoolConfig<APool2NodeHandler> aConfig= new GenericObjectPoolConfig<>();
aConfig.setLifo(true);
aConfig.setTestOnReturn(true);
aConfig.setTestWhileIdle(false);
aConfig.setTestOnBorrow(false);
aConfig.setBlockWhenExhausted(true);
aConfig.setMaxTotal(config.getMaxTotalCount());
aConfig.setMaxWaitMillis(config.getMaxWaitTime());
aConfig.setMinIdle(config.getMinIdleCount());
aConfig.setMaxIdle(config.getMaxIdleCount());
aConfig.setMinEvictableIdleTimeMillis(0);
aConfig.setSoftMinEvictableIdleTimeMillis(config.getMinIdleTime());
aConfig.setTimeBetweenEvictionRunsMillis(5000);
aConfig.setNumTestsPerEvictionRun(-4);
aConfig.setEvictorShutdownTimeoutMillis(0);
return aConfig;
}
private final APool2NodeFactory factory;
private volatile byte state;
private boolean evicting;
private final Object stateLock= new Object();
public APool2(final APool2NodeFactory factory, final PoolConfig config) {
super(factory, createAConfig(config));
factory.setPool(this);
this.factory= factory;
}
public void setConfig(final PoolConfig config) {
setConfig(createAConfig(config));
}
public APool2NodeHandler borrowObject(final String client) throws Exception {
if (this.state != 0) {
throw new IllegalStateException("Pool not open");
}
this.factory.registerArgs(client);
try {
return super.borrowObject();
}
finally {
this.factory.clearArgs();
}
}
@Override
public int getMinIdle() {
if (this.state != 0) {
return 0;
}
return super.getMinIdle();
}
@Override
public void close() {
throw new UnsupportedOperationException();
}
public void close(final long evictionTimeout) {
synchronized (this.stateLock) {
if (this.state > CLOSING) {
return;
}
this.state= CLOSING;
}
clear();
final long evictNanos= APool2NodeHandler.evictNanos(evictionTimeout);
final boolean evictDirect= (evictionTimeout == 0);
final ImList<APool2NodeHandler> objects= this.factory.getAllObjects();
for (final APool2NodeHandler poolObj : objects) {
poolObj.doEvict(evictNanos, evictDirect);
}
if (this.state > CLOSING) {
return;
}
setTimeBetweenEvictionRunsMillis(500);
}
protected void closeFinally() {
super.close();
synchronized (this.stateLock) {
this.state= CLOSED;
}
}
@Override
public void evict() throws Exception {
synchronized (this.stateLock) {
if (this.state > CLOSING || this.evicting) {
return;
}
this.evicting= true;
}
try {
int evicted;
do {
evicted= 0;
final long nanos= APool2NodeHandler.safeNanos(System.nanoTime());
final ImList<APool2NodeHandler> objects= this.factory.getAllObjects();
for (final APool2NodeHandler poolObj : objects) {
if (poolObj.isEvictRequested(nanos)) {
try {
evicted++;
invalidateObject(poolObj);
}
catch (final Exception e) {}
}
}
}
while (evicted > 0);
super.evict();
synchronized (this.stateLock) {
if (this.state != CLOSING || this.factory.getNumAll() > 0) {
return;
}
this.state= CLOSING_FINALLY;
}
closeFinally();
}
finally {
this.evicting= false;
}
}
@Override
public EvictionPolicy<APool2NodeHandler> getEvictionPolicy() {
return EVICTION_POLICY;
}
}