package org.infinispan.jmx; import static org.testng.Assert.assertEquals; import static org.testng.AssertJUnit.assertNull; import static org.testng.AssertJUnit.assertTrue; import java.util.Arrays; import javax.management.Attribute; import javax.management.MBeanServer; import javax.management.ObjectName; import org.infinispan.configuration.cache.CacheMode; import org.infinispan.configuration.cache.ConfigurationBuilder; import org.infinispan.configuration.global.GlobalConfigurationBuilder; import org.infinispan.manager.CacheContainer; import org.infinispan.statetransfer.StateTransferManager; import org.infinispan.test.MultipleCacheManagersTest; import org.infinispan.test.TestingUtil; import org.testng.annotations.Test; /** * @author Dan Berindei */ @Test(groups = "functional", testName = "jmx.CacheAvailabilityJmxTest") public class CacheAvailabilityJmxTest extends MultipleCacheManagersTest { @Override protected void createCacheManagers() throws Throwable { addClusterEnabledCacheManager(getGlobalConfigurationBuilder("r1"), getConfigurationBuilder()); addClusterEnabledCacheManager(getGlobalConfigurationBuilder("r1"), getConfigurationBuilder()); waitForClusterToForm(); } private ConfigurationBuilder getConfigurationBuilder() { ConfigurationBuilder cb = new ConfigurationBuilder(); cb.clustering().cacheMode(CacheMode.DIST_SYNC) .stateTransfer().awaitInitialTransfer(false) .partitionHandling().enabled(true); return cb; } private GlobalConfigurationBuilder getGlobalConfigurationBuilder(String rackId) { GlobalConfigurationBuilder gcb = GlobalConfigurationBuilder.defaultClusteredBuilder(); gcb.globalJmxStatistics() .enable() .mBeanServerLookup(new PerThreadMBeanServerLookup()) .transport().rackId(rackId); return gcb; } public void testAvailabilityChange() throws Exception { final MBeanServer mBeanServer = PerThreadMBeanServerLookup.getThreadMBeanServer(); String domain0 = manager(1).getCacheManagerConfiguration().globalJmxStatistics().domain(); final ObjectName cacheName0 = TestingUtil.getCacheObjectName(domain0, CacheContainer.DEFAULT_CACHE_NAME + "(dist_sync)"); String domain1 = manager(1).getCacheManagerConfiguration().globalJmxStatistics().domain(); final ObjectName cacheName1 = TestingUtil.getCacheObjectName(domain1, CacheContainer.DEFAULT_CACHE_NAME + "(dist_sync)"); // Check initial state StateTransferManager stm0 = TestingUtil.extractComponent(cache(0), StateTransferManager.class); assertEquals(Arrays.asList(address(0), address(1)), stm0.getCacheTopology().getCurrentCH().getMembers()); assertNull(stm0.getCacheTopology().getPendingCH()); assertTrue(mBeanServer.isRegistered(cacheName0)); assertEquals("AVAILABLE", mBeanServer.getAttribute(cacheName0, "CacheAvailability")); assertEquals("AVAILABLE", mBeanServer.getAttribute(cacheName1, "CacheAvailability")); // Enter degraded mode log.debugf("Entering degraded mode"); mBeanServer.setAttribute(cacheName0, new Attribute("CacheAvailability", "DEGRADED_MODE")); eventually(new Condition() { @Override public boolean isSatisfied() throws Exception { Object availability0 = mBeanServer.getAttribute(cacheName0, "CacheAvailability"); Object availability1 = mBeanServer.getAttribute(cacheName1, "CacheAvailability"); return "DEGRADED_MODE".equals(availability0) && "DEGRADED_MODE".equals(availability1); } }); // Add 2 nodes log.debugf("Starting 2 new nodes"); addClusterEnabledCacheManager(getGlobalConfigurationBuilder("r2"), getConfigurationBuilder()); addClusterEnabledCacheManager(getGlobalConfigurationBuilder("r2"), getConfigurationBuilder()); cache(2); cache(3); // Check that no rebalance happened after 1 second Thread.sleep(1000); assertEquals(Arrays.asList(address(0), address(1)), stm0.getCacheTopology().getCurrentCH().getMembers()); assertNull(stm0.getCacheTopology().getPendingCH()); assertEquals("DEGRADED_MODE", mBeanServer.getAttribute(cacheName0, "CacheAvailability")); assertEquals("DEGRADED_MODE", mBeanServer.getAttribute(cacheName1, "CacheAvailability")); // Enter available mode log.debugf("Back to available mode"); mBeanServer.setAttribute(cacheName0, new Attribute("CacheAvailability", "AVAILABLE")); eventually(new Condition() { @Override public boolean isSatisfied() throws Exception { Object availability0 = mBeanServer.getAttribute(cacheName0, "CacheAvailability"); Object availability1 = mBeanServer.getAttribute(cacheName1, "CacheAvailability"); return "AVAILABLE".equals(availability0) && "AVAILABLE".equals(availability1); } }); // Check that the cache now has 4 nodes, and the CH is balanced TestingUtil.waitForNoRebalance(cache(0), cache(1), cache(2), cache(3)); } }