package org.infinispan.notifications.cachelistener.cluster; import static org.testng.Assert.assertEquals; import java.util.ArrayList; import java.util.Collections; import java.util.List; import org.infinispan.Cache; import org.infinispan.configuration.cache.CacheMode; import org.infinispan.configuration.cache.ConfigurationBuilder; import org.infinispan.context.Flag; import org.infinispan.notifications.Listener; import org.infinispan.notifications.cachelistener.annotation.CacheEntryCreated; import org.infinispan.notifications.cachelistener.annotation.CacheEntryModified; import org.infinispan.notifications.cachelistener.annotation.CacheEntryRemoved; import org.infinispan.notifications.cachelistener.event.CacheEntryEvent; import org.infinispan.test.MultipleCacheManagersTest; import org.infinispan.test.TestingUtil; import org.infinispan.util.ControlledConsistentHashFactory; import org.testng.annotations.BeforeMethod; import org.testng.annotations.Test; /** * Test to ensure when a rehash occurs that cluster listeners are not notified. * * @author wburns * @since 7.0 */ @Test(groups = "functional", testName = "org.infinispan.notifications.cachelistener.cluster.RehashClusterListenerTest") public class RehashClusterListenerTest extends MultipleCacheManagersTest { protected final static String CACHE_NAME = "cluster-listener"; protected final static String KEY = "key"; protected final static String VALUE = "value"; protected ConfigurationBuilder builderUsed; protected final ControlledConsistentHashFactory factory = new ControlledConsistentHashFactory(1, 2); @BeforeMethod protected void beforeMethod() { factory.setOwnerIndexes(1, 2); } @Override protected void createCacheManagers() throws Throwable { builderUsed = new ConfigurationBuilder(); builderUsed.clustering().cacheMode(CacheMode.DIST_SYNC).hash().consistentHashFactory(factory).numOwners(2).numSegments(1); createClusteredCaches(3, CACHE_NAME, builderUsed); } public void testClusterListenerNodeBecomingPrimaryFromNotAnOwner() throws Exception { final Cache<Object, String> cache0 = cache(0, CACHE_NAME); Cache<Object, String> cache1 = cache(1, CACHE_NAME); Cache<Object, String> cache2 = cache(2, CACHE_NAME); cache1.put(KEY, VALUE); ClusterListener listener = new ClusterListener(); cache0.addListener(listener); factory.setOwnerIndexes(0, 1); log.trace("Triggering rebalance to cause segment ownership to change"); factory.triggerRebalance(cache0); eventually(new Condition() { @Override public boolean isSatisfied() throws Exception { return cache0.getAdvancedCache().withFlags(Flag.CACHE_MODE_LOCAL).containsKey(KEY); } }); TestingUtil.waitForNoRebalance(cache0, cache1, cache2); assertEquals(listener.events.size(), 0); } public void testClusterListenerNodeBecomingBackupFromNotAnOwner() throws Exception { final Cache<Object, String> cache0 = cache(0, CACHE_NAME); Cache<Object, String> cache1 = cache(1, CACHE_NAME); Cache<Object, String> cache2 = cache(2, CACHE_NAME); cache1.put(KEY, VALUE); ClusterListener listener = new ClusterListener(); cache0.addListener(listener); factory.setOwnerIndexes(1, 0); log.trace("Triggering rebalance to cause segment ownership to change"); factory.triggerRebalance(cache0); eventually(new Condition() { @Override public boolean isSatisfied() throws Exception { return cache0.getAdvancedCache().withFlags(Flag.CACHE_MODE_LOCAL).containsKey(KEY); } }); TestingUtil.waitForNoRebalance(cache0, cache1, cache2); assertEquals(listener.events.size(), 0); } public void testOtherNodeBecomingBackupFromNotAnOwner() throws Exception { final Cache<Object, String> cache0 = cache(0, CACHE_NAME); Cache<Object, String> cache1 = cache(1, CACHE_NAME); Cache<Object, String> cache2 = cache(2, CACHE_NAME); cache1.put(KEY, VALUE); ClusterListener listener = new ClusterListener(); cache2.addListener(listener); factory.setOwnerIndexes(1, 0); log.trace("Triggering rebalance to cause segment ownership to change"); factory.triggerRebalance(cache0); eventually(new Condition() { @Override public boolean isSatisfied() throws Exception { return cache0.getAdvancedCache().withFlags(Flag.CACHE_MODE_LOCAL).containsKey(KEY); } }); TestingUtil.waitForNoRebalance(cache0, cache1, cache2); assertEquals(listener.events.size(), 0); } public void testOtherNodeBecomingPrimaryFromNotAnOwner() throws Exception { final Cache<Object, String> cache0 = cache(0, CACHE_NAME); Cache<Object, String> cache1 = cache(1, CACHE_NAME); Cache<Object, String> cache2 = cache(2, CACHE_NAME); cache1.put(KEY, VALUE); ClusterListener listener = new ClusterListener(); cache2.addListener(listener); factory.setOwnerIndexes(0, 1); log.trace("Triggering rebalance to cause segment ownership to change"); factory.triggerRebalance(cache0); eventually(new Condition() { @Override public boolean isSatisfied() throws Exception { return cache0.getAdvancedCache().withFlags(Flag.CACHE_MODE_LOCAL).containsKey(KEY); } }); TestingUtil.waitForNoRebalance(cache0, cache1, cache2); assertEquals(listener.events.size(), 0); } @Listener(clustered = true) protected class ClusterListener { List<CacheEntryEvent> events = Collections.synchronizedList(new ArrayList<CacheEntryEvent>()); @CacheEntryCreated @CacheEntryModified @CacheEntryRemoved public void onCacheEvent(CacheEntryEvent event) { log.debugf("Adding new cluster event %s", event); events.add(event); } } }