package org.radargun.stages.cache.listeners.cluster; import java.util.Collections; import java.util.List; import org.radargun.DistStageAck; import org.radargun.StageResult; import org.radargun.config.Property; import org.radargun.config.Stage; import org.radargun.reporting.Report; import org.radargun.stages.AbstractDistStage; import org.radargun.stages.cache.generators.TimestampKeyGenerator.TimestampKey; import org.radargun.state.SlaveState; import org.radargun.stats.BasicOperationStats; import org.radargun.stats.Statistics; import org.radargun.stats.SynchronizedStatistics; import org.radargun.traits.CacheListeners; import org.radargun.traits.InjectTrait; import org.radargun.utils.TimeConverter; import org.radargun.utils.TimeService; import org.radargun.utils.Utils; import static org.radargun.traits.CacheListeners.*; /** * Run this stage if you want to compare performance with enabled/disabled cluster listenersTrait * * @author vchepeli@redhat.com * @since 2.0 */ @Stage(doc = "Benchmark operations performance where cluster listenersTrait are enabled or disabled.") public class RegisterListenersStage extends AbstractDistStage { @Property(doc = "Use sleep time to simulate some work on listener. Default is -1(do not sleep) ms.", converter = TimeConverter.class) protected long sleepTime = -1; @Property(doc = "Before stress stage, cluster listeners would be enabled. This is flag to turn them on. Default is false.") protected boolean registerListeners = false; @Property(doc = "Before stress stage, cluster listeners would be disabled. This is flag to turn them off. Default is false.") protected boolean unregisterListeners = false; @Property(doc = "Name of the test as used for reporting. Default is 'Test'.") protected String testName = "Listeners"; @Property(doc = "Setup if cache listener is synchronous/asynchronous. Default is true") private boolean sync = true; @Property(doc = "Allows to reset statistics at the begining of the stage. Default is false.") private boolean resetStats = false; @InjectTrait // with infinispan70 plugin private CacheListeners listenersTrait; private SynchronizedStatistics statistics; @Override public DistStageAck executeOnSlave() { String statsKey = getClass().getName() + ".Stats"; statistics = (SynchronizedStatistics) slaveState.get(statsKey); if (statistics == null) { statistics = new SynchronizedStatistics(new BasicOperationStats()); slaveState.put(statsKey, statistics); } else if (resetStats) { statistics.reset(); } if (registerListeners) { initListenersOnSlave(slaveState); registerListeners(); } if (unregisterListeners) { unregisterListeners(); } return new ListenersAck(slaveState, statistics.snapshot(true)); } @Override public StageResult processAckOnMaster(List<DistStageAck> acks) { StageResult result = super.processAckOnMaster(acks); if (result.isError()) return result; Report.Test test = createTest(testName, null); if (test != null) { int testIteration = test.getIterations().size(); for (ListenersAck ack : instancesOf(acks, ListenersAck.class)) { if (ack.stats != null) test.addStatistics(testIteration, ack.getSlaveIndex(), Collections.singletonList(ack.stats)); } } return StageResult.SUCCESS; } protected Report.Test createTest(String testName, String iterationName) { if (testName == null || testName.isEmpty()) { log.warn("No test name - results are not recorded"); return null; } else { Report report = masterState.getReport(); return report.createTest(testName, iterationName, true); } } private void initListenersOnSlave(SlaveState slaveState) { CreatedListener createdListener = new CreatedListener() { @Override public void created(Object key, Object value) { if (sleepTime > 0) Utils.sleep(sleepTime); if (key instanceof TimestampKey) { statistics.message().times(((TimestampKey) key).getTimestamp(), TimeService.currentTimeMillis()).record(CREATED); } log.trace("Created " + key + " -> " + value); } }; slaveState.put(CREATED.name, createdListener); EvictedListener evictedListener = new EvictedListener() { @Override public void evicted(Object key, Object value) { if (sleepTime > 0) Utils.sleep(sleepTime); if (key instanceof TimestampKey) { statistics.message().times(((TimestampKey) key).getTimestamp(), TimeService.currentTimeMillis()).record(EVICTED); } log.trace("Evicted " + key + " -> " + value); } }; slaveState.put(EVICTED.name, evictedListener); RemovedListener removedListener = new RemovedListener() { @Override public void removed(Object key, Object value) { if (sleepTime > 0) Utils.sleep(sleepTime); if (key instanceof TimestampKey) { statistics.message().times(((TimestampKey) key).getTimestamp(), TimeService.currentTimeMillis()).record(REMOVED); } log.trace("Removed " + key + " -> " + value); } }; slaveState.put(REMOVED.name, removedListener); UpdatedListener updatedListener = new UpdatedListener() { @Override public void updated(Object key, Object value) { if (sleepTime > 0) Utils.sleep(sleepTime); if (key instanceof TimestampKey) { statistics.message().times(((TimestampKey) key).getTimestamp(), TimeService.currentTimeMillis()).record(UPDATED); } log.trace("Updated " + key + " -> " + value); } }; slaveState.put(UPDATED.name, updatedListener); ExpiredListener expiredListener = new ExpiredListener() { @Override public void expired(Object key, Object value) { if (sleepTime > 0) Utils.sleep(sleepTime); if (key instanceof TimestampKey) { statistics.message().times(((TimestampKey) key).getTimestamp(), TimeService.currentTimeMillis()).record(EXPIRED); } log.trace("Expired " + key + " -> " + value); } }; slaveState.put(EXPIRED.name, expiredListener); } public void registerListeners() { CreatedListener createdListener = (CreatedListener) slaveState.get(CREATED.name); if (createdListener != null && isSupported(Type.CREATED)) { listenersTrait.addCreatedListener(null, createdListener, sync); } EvictedListener evictedListener = (EvictedListener) slaveState.get(EVICTED.name); if (evictedListener != null && isSupported(Type.EVICTED)) { listenersTrait.addEvictedListener(null, evictedListener, sync); } RemovedListener removedListener = (RemovedListener) slaveState.get(REMOVED.name); if (removedListener != null && isSupported(Type.REMOVED)) { listenersTrait.addRemovedListener(null, removedListener, sync); } UpdatedListener updatedListener = (UpdatedListener) slaveState.get(UPDATED.name); if (updatedListener != null && isSupported(Type.UPDATED)) { listenersTrait.addUpdatedListener(null, updatedListener, sync); } ExpiredListener expiredListener = (ExpiredListener) slaveState.get(EXPIRED.name); if (expiredListener != null && isSupported(Type.EXPIRED)) { listenersTrait.addExpiredListener(null, expiredListener, sync); } } public void unregisterListeners() { CreatedListener createdListener = (CreatedListener) slaveState.get(CREATED.name); if (createdListener != null && isSupported(Type.CREATED)) { listenersTrait.removeCreatedListener(null, createdListener, sync); } slaveState.remove(CREATED.name); EvictedListener evictedListener = (EvictedListener) slaveState.get(EVICTED.name); if (evictedListener != null && isSupported(Type.EVICTED)) { listenersTrait.removeEvictedListener(null, evictedListener, sync); } slaveState.remove(EVICTED.name); RemovedListener removedListener = (RemovedListener) slaveState.get(REMOVED.name); if (removedListener != null && isSupported(Type.REMOVED)) { listenersTrait.removeRemovedListener(null, removedListener, sync); } slaveState.remove(REMOVED.name); UpdatedListener updatedListener = (UpdatedListener) slaveState.get(UPDATED.name); if (updatedListener != null && isSupported(Type.UPDATED)) { listenersTrait.removeUpdatedListener(null, updatedListener, sync); } slaveState.remove(UPDATED.name); ExpiredListener expiredListener = (ExpiredListener) slaveState.get(EXPIRED.name); if (expiredListener != null && isSupported(Type.EXPIRED)) { listenersTrait.removeExpiredListener(null, expiredListener, sync); } slaveState.remove(EXPIRED.name); } private boolean isSupported(Type type) { if (listenersTrait == null) { throw new IllegalArgumentException("Service does not support cache listeners"); } return listenersTrait.getSupportedListeners().contains(type); } private static class ListenersAck extends DistStageAck { public final Statistics stats; public ListenersAck(SlaveState slaveState, Statistics stats) { super(slaveState); this.stats = stats; } } }