package cz.cuni.mff.d3s.been.objectrepository; import com.hazelcast.core.ItemEvent; import com.hazelcast.core.ItemListener; /** * This listener counts the number of items in the queue to estimate whether the * current number of worker threads is capable of handling the amount of results * currently within the cluster. * * If the number of messages seems too high, this listener allocates new * threads. In case the queue was drained, the listener deallocates extra worker threads. * * @param <T> Type of objects listened to * * @author darklight * */ public class ItemCounterListener<T> implements ItemListener<T> { private static final long LOAD_BALANCE_INTERVAL_MILLIS = 10000; /** The pool of digester threads */ private final Digester<T> digester; /** Counter of available jobs (results to perform) */ private int jobCount = 0; /** State of the job counter from the last time a load balance was performed */ private int lastJobCount = 0; /** Time when the last load balance was performed */ private long lastLoadBalanceTimestamp = System.currentTimeMillis(); /** * Create an item-counting listener * * @param digester Digester to reinforce in case heuristics point to the need of more processing threads * @param <T> Type of digested items * * @return A new item-counting listener */ public static <T> ItemCounterListener<T> create(Digester<T> digester) { return new ItemCounterListener<T>(digester); } ItemCounterListener(Digester<T> digester) { this.digester = digester; } @Override public void itemAdded(ItemEvent<T> item) { ++jobCount; balanceLoad(); } @Override public void itemRemoved(ItemEvent<T> item) { --jobCount; } private void balanceLoad() { final long now = System.currentTimeMillis(); if (now > lastLoadBalanceTimestamp + LOAD_BALANCE_INTERVAL_MILLIS) { if (jobCount > lastJobCount) { digester.addNewWorkingThread(); } lastLoadBalanceTimestamp = now; lastJobCount = jobCount; } } }