package org.marketcetera.metrics; import org.marketcetera.util.misc.ClassVersion; import org.marketcetera.util.log.SLF4JLoggerProxy; import java.util.concurrent.Callable; import java.util.concurrent.atomic.AtomicLong; /* $License$ */ /** * A utility class for creating conditions that can be used with * {@link ThreadedMetric#end(java.util.concurrent.Callable, Object[])}. * * @author anshul@marketcetera.com * @version $Id: ConditionsFactory.java 16154 2012-07-14 16:34:05Z colin $ * @since 2.0.0 */ @ClassVersion("$Id: ConditionsFactory.java 16154 2012-07-14 16:34:05Z colin $") public final class ConditionsFactory { /** * Returns a condition that is true on every n<sup>th</sup> * (where n = <code>inDefaultInterval</code>) invocation for a * particular thread. * <p> * The returned condition maintains a separate counter for each thread. * * @param inDefaultInterval the default interval at which the condition * should be true. This value is used as interval value if no value * can be found for the condition's property name. The interval value * has to be greater than 0. * @param inName the condition's property name. This property name is * used to obtain the property value from the {@link Configurator} which, * if found, is used as the interval value. * * @return the condition. * * @see Configurator#getProperty(String, String) */ public static Callable<Boolean> createSamplingCondition( final int inDefaultInterval, final String inName) { if(inDefaultInterval <= 0) { throw new IllegalArgumentException(inDefaultInterval + " <= 0"); //$NON-NLS-1$ } int value = inDefaultInterval; String pValue = Configurator.getProperty(inName, String.valueOf(inDefaultInterval)); if(pValue != null) { try { value = Integer.parseInt(pValue); } catch (NumberFormatException e) { Messages.LOG_NON_NUMERIC_PROPERTY.warn(ConditionsFactory.class, e, inName, pValue, inDefaultInterval); } } SLF4JLoggerProxy.debug(ConditionsFactory.class, "Initializing sampling condition for interval {}", //$NON-NLS-1$ value); return new IntervalSampler(value); } /** * Utility class. No instances can be created. */ private ConditionsFactory() { } /** * A condition that is true on every n<sup>th</sup> check. Where 'n' is * the interval value supplied when instantiating this condition. */ private static final class IntervalSampler implements Callable<Boolean> { /** * Creates an instance. * * @param inInterval the interval value. */ public IntervalSampler(final int inInterval) { mInterval = inInterval; mCounter = new ThreadLocal<AtomicLong>() { @Override protected AtomicLong initialValue() { return new AtomicLong(); } }; } @Override public Boolean call() throws Exception { return mCounter.get().incrementAndGet() % mInterval == 0; } private final ThreadLocal<AtomicLong> mCounter; private final int mInterval; } }