package org.apereo.cas.monitor;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Future;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;
/**
* Describes a monitor that observes a pool of resources.
*
* @author Marvin S. Addison
* @since 3.5.0
*/
public abstract class AbstractPoolMonitor extends AbstractNamedMonitor<PoolStatus> {
/** Maximum amount of time in ms to wait while validating pool resources. */
private final int maxWait;
/** Executor that performs pool resource validation. */
private final ExecutorService executor;
/**
* Creates a new instance.
*
* @param name monitor name
* @param executorService executor service responsible for pool resource validation.
* @param maxWait Set the maximum amount of time wait while validating pool resources.
* If the pool defines a maximum time to wait for a resource, this property
* should be set less than that value.
*/
public AbstractPoolMonitor(final String name, final ExecutorService executorService, final int maxWait) {
super(name);
this.executor = executorService;
this.maxWait = maxWait;
}
@Override
public PoolStatus observe() {
final Future<StatusCode> result = this.executor.submit(new Validator(this));
StatusCode code;
String description = null;
try {
code = result.get(this.maxWait, TimeUnit.MILLISECONDS);
} catch (final InterruptedException e) {
code = StatusCode.UNKNOWN;
description = "Validator thread interrupted during pool validation.";
} catch (final TimeoutException e) {
code = StatusCode.WARN;
description = String.format("Pool validation timed out. Max wait is %s ms.", this.maxWait);
} catch (final Exception e) {
code = StatusCode.ERROR;
description = e.getMessage();
}
return new PoolStatus(code, description, getActiveCount(), getIdleCount());
}
/**
* Performs a health check on a the pool. The recommended implementation is to
* obtain a pool resource, validate it, and return it to the pool.
*
* @return Status code describing pool health.
*
* @throws Exception Thrown to indicate a serious problem with pool validation.
*/
protected abstract StatusCode checkPool() throws Exception;
/**
* Gets the number of pool resources idle at present.
*
* @return Number of idle pool resources.
*/
protected abstract int getIdleCount();
/**
* Gets the number of pool resources active at present.
*
* @return Number of active pool resources.
*/
protected abstract int getActiveCount();
private static class Validator implements Callable<StatusCode> {
private final AbstractPoolMonitor monitor;
/**
* Instantiates a new Validator.
*
* @param monitor the monitor
*/
Validator(final AbstractPoolMonitor monitor) {
this.monitor = monitor;
}
@Override
public StatusCode call() throws Exception {
return this.monitor.checkPool();
}
}
}