package org.infinispan.counter; import static org.testng.AssertJUnit.assertFalse; import static org.testng.AssertJUnit.assertTrue; import java.io.File; import java.util.ArrayList; import java.util.Collection; import java.util.stream.Collectors; import org.infinispan.commons.util.Util; import org.infinispan.configuration.global.GlobalConfigurationBuilder; import org.infinispan.counter.api.CounterConfiguration; import org.infinispan.counter.api.CounterManager; import org.infinispan.counter.api.CounterType; import org.infinispan.counter.api.Storage; import org.infinispan.counter.configuration.CounterManagerConfigurationBuilder; import org.infinispan.counter.impl.BaseCounterTest; import org.infinispan.counter.impl.CounterModuleLifecycle; import org.infinispan.manager.EmbeddedCacheManager; import org.infinispan.test.TestingUtil; import org.infinispan.test.fwk.CleanupAfterMethod; import org.testng.annotations.AfterMethod; import org.testng.annotations.Test; /** * @author Pedro Ruivo * @since 9.0 */ @Test(groups = "functional", testName = "counter.RestartCounterTest") @CleanupAfterMethod public class RestartCounterTest extends BaseCounterTest { private static final String PERSISTENT_FOLDER = TestingUtil.tmpDirectory(RestartCounterTest.class.getSimpleName()); private static final String TEMP_PERSISTENT_FOLDER = PERSISTENT_FOLDER + File.separator + "temp"; private static final int CLUSTER_SIZE = 4; private final Collection<CounterDefinition> defaultCounters = new ArrayList<>(6); private final Collection<CounterDefinition> otherCounters = new ArrayList<>(6); public RestartCounterTest() { defaultCounters.add(new CounterDefinition("v-bounded", CounterType.BOUNDED_STRONG, Storage.VOLATILE)); defaultCounters.add(new CounterDefinition("p-bounded", CounterType.BOUNDED_STRONG, Storage.PERSISTENT)); defaultCounters.add(new CounterDefinition("v-unbounded", CounterType.UNBOUNDED_STRONG, Storage.VOLATILE)); defaultCounters.add(new CounterDefinition("p-unbounded", CounterType.UNBOUNDED_STRONG, Storage.PERSISTENT)); defaultCounters.add(new CounterDefinition("v-weak", CounterType.WEAK, Storage.VOLATILE)); defaultCounters.add(new CounterDefinition("p-weak", CounterType.WEAK, Storage.PERSISTENT)); otherCounters.add(new CounterDefinition("o-v-bounded", CounterType.BOUNDED_STRONG, Storage.VOLATILE)); otherCounters.add(new CounterDefinition("o-p-bounded", CounterType.BOUNDED_STRONG, Storage.PERSISTENT)); otherCounters.add(new CounterDefinition("o-v-unbounded", CounterType.UNBOUNDED_STRONG, Storage.VOLATILE)); otherCounters.add(new CounterDefinition("o-p-unbounded", CounterType.UNBOUNDED_STRONG, Storage.PERSISTENT)); otherCounters.add(new CounterDefinition("o-v-weak", CounterType.WEAK, Storage.VOLATILE)); otherCounters.add(new CounterDefinition("o-p-weak", CounterType.WEAK, Storage.PERSISTENT)); } private static void incrementAll(Collection<CounterDefinition> counters, CounterManager counterManager) { counters.forEach(counterDefinition -> counterDefinition.incrementCounter(counterManager)); } @AfterMethod(alwaysRun = true) public void removeFiles() { Util.recursiveFileRemove(PERSISTENT_FOLDER); Util.recursiveFileRemove(TEMP_PERSISTENT_FOLDER); } public void testCountersInConfiguration() throws Throwable { assertDefined(defaultCounters); incrementAll(defaultCounters, counterManager(0)); assertCounterValue(defaultCounters, counterManager(0), 1, 1); shutdownAndRestart(); assertDefined(defaultCounters); assertCounterValue(defaultCounters, counterManager(0), 0, 1); } public void testRuntimeCounters() throws Throwable { final CounterManager counterManager = counterManager(0); incrementAll(defaultCounters, counterManager); incrementAll(defaultCounters, counterManager); otherCounters.forEach(counterDefinition -> counterDefinition.define(counterManager)); incrementAll(otherCounters, counterManager); assertCounterValue(defaultCounters, counterManager, 2, 2); assertCounterValue(otherCounters, counterManager, 1, 1); shutdownAndRestart(); //recreate the counter manager. final CounterManager counterManager2 = counterManager(0); Collection<CounterDefinition> othersPersisted = otherCounters.stream() .filter(counterDefinition -> counterDefinition.storage == Storage.PERSISTENT).collect( Collectors.toList()); Collection<CounterDefinition> otherVolatile = otherCounters.stream() .filter(counterDefinition -> counterDefinition.storage == Storage.VOLATILE).collect( Collectors.toList()); assertDefined(defaultCounters); assertDefined(othersPersisted); assertNotDefined(otherVolatile); assertCounterValue(defaultCounters, counterManager2, 0, 2); assertCounterValue(othersPersisted, counterManager2, -1 /*doesn't mather*/, 1); } @Override protected int clusterSize() { return CLUSTER_SIZE; } @Override protected GlobalConfigurationBuilder configure(int nodeId) { GlobalConfigurationBuilder builder = GlobalConfigurationBuilder.defaultClusteredBuilder(); builder.globalState().enable().persistentLocation(PERSISTENT_FOLDER + File.separator + nodeId) .temporaryLocation(TEMP_PERSISTENT_FOLDER + File.separator + nodeId); CounterManagerConfigurationBuilder counterBuilder = builder.addModule(CounterManagerConfigurationBuilder.class); defaultCounters.forEach(counterDefinition -> counterDefinition.define(counterBuilder)); return builder; } private void shutdownAndRestart() throws Throwable { cache(0, CounterModuleLifecycle.COUNTER_CACHE_NAME).shutdown(); cache(0, CounterModuleLifecycle.COUNTER_CONFIGURATION_CACHE_NAME).shutdown(); log.debug("Shutdown caches"); for (EmbeddedCacheManager cacheManager : cacheManagers) { cacheManager.stop(); } cacheManagers.clear(); log.debug("Restart caches"); createCacheManagers(); } private void assertDefined(Collection<CounterDefinition> counters) { for (int i = 0; i < CLUSTER_SIZE; ++i) { CounterManager counterManager = counterManager(0); for (CounterDefinition definition : counters) { assertTrue("Configuration of " + definition.name + " is missing on manager " + i, counterManager.isDefined(definition.name)); } } } private void assertNotDefined(Collection<CounterDefinition> counters) { for (int i = 0; i < CLUSTER_SIZE; ++i) { CounterManager counterManager = counterManager(0); for (CounterDefinition definition : counters) { assertFalse("Configuration of " + definition.name + " is defined on manager " + i, counterManager.isDefined(definition.name)); } } } private void assertCounterValue(Collection<CounterDefinition> counters, CounterManager counterManager, long volatileValue, long persistentValue) { for (CounterDefinition definition : counters) { long expect = definition.storage == Storage.VOLATILE ? volatileValue : persistentValue; eventuallyEquals("Wrong value for counter " + definition.name, expect, () -> definition.getValue(counterManager)); } } private static class CounterDefinition { private final String name; private final CounterType type; private final Storage storage; private CounterDefinition(String name, CounterType type, Storage storage) { this.name = name; this.type = type; this.storage = storage; } private void define(CounterManagerConfigurationBuilder builder) { switch (type) { case UNBOUNDED_STRONG: builder.addStrongCounter().name(name).storage(storage); break; case BOUNDED_STRONG: builder.addStrongCounter().name(name).lowerBound(0).storage(storage); break; case WEAK: builder.addWeakCounter().name(name).storage(storage); } } private void define(CounterManager manager) { //lower bound is ignored if the type is not bounded. manager.defineCounter(name, CounterConfiguration.builder(type).lowerBound(0).storage(storage).build()); } private void incrementCounter(CounterManager counterManager) { switch (type) { case UNBOUNDED_STRONG: case BOUNDED_STRONG: counterManager.getStrongCounter(name).incrementAndGet(); break; case WEAK: counterManager.getWeakCounter(name).increment(); break; } } private long getValue(CounterManager counterManager) { switch (type) { case WEAK: return counterManager.getWeakCounter(name).getValue(); case BOUNDED_STRONG: case UNBOUNDED_STRONG: return new SyncStrongCounter(counterManager.getStrongCounter(name)).getValue(); } throw new IllegalStateException(); } } }