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(); } } }