/* * Hibernate OGM, Domain model persistence for NoSQL datastores * * License: GNU Lesser General Public License (LGPL), version 2.1 or later * See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>. */ package org.hibernate.ogm.datastore.infinispan.utils; import java.io.InputStream; import org.hibernate.AssertionFailure; import org.infinispan.Cache; import org.infinispan.commons.util.FileLookupFactory; import org.infinispan.configuration.cache.Configuration; import org.infinispan.configuration.global.GlobalConfiguration; import org.infinispan.configuration.parsing.ConfigurationBuilderHolder; import org.infinispan.configuration.parsing.ParserRegistry; import org.infinispan.manager.DefaultCacheManager; import org.infinispan.manager.EmbeddedCacheManager; import org.infinispan.test.TestingUtil; import org.junit.Assert; import org.junit.rules.ExternalResource; /** * Helper to manage a clustered Infinispan CacheManager: * designed to be rather defensive and avoid some common pitfalls. * <p> * Example: * <p> * <pre> * {@code * @Rule * public final InfinispanNode nodeA = new InfinispanNode( "nodeA", "infinispan-dist.xml" ); * @Rule * public final InfinispanNode nodeB = new InfinispanNode( "nodeB", "infinispan-dist.xml" ); * * @Test * public void testExample() throws Exception { * EmbeddedCacheManager manager = nodeA.getCacheManager( 2 ); // Number of nodes this cluster should have * ... * } * } * </pre> * * @author Sanne Grinovero <sanne@hibernate.org> (C) 2014 Red Hat Inc. */ public class InfinispanNode extends ExternalResource { private static final long DEFAULT_JOIN_TIMEOUT_MS = 15000; private static final String JGROUPS_HOSTNAME = System.getProperty( "jgroups.bind_addr" ); private static final Boolean IPV4_STACK = Boolean.getBoolean( "java.net.preferIPv4Stack" ); private final String configurationFile; private final long joinTimeoutMilliseconds; private final String cacheManagerName; private EmbeddedCacheManager manager; private volatile boolean started = false; private volatile boolean groupFormed = false; public InfinispanNode(final String cacheManagerName, final String configurationFile) { this( cacheManagerName, configurationFile, DEFAULT_JOIN_TIMEOUT_MS ); } public InfinispanNode(final String cacheManagerName, final String configurationFile, final long joinTimeoutMilliseconds) { this.cacheManagerName = cacheManagerName; this.configurationFile = configurationFile; this.joinTimeoutMilliseconds = joinTimeoutMilliseconds; } public EmbeddedCacheManager getCacheManager(final int expectedGroupSize) { if ( ! started ) { throw new IllegalStateException( "The before() method of this Rule was not triggered (or did not complete succesfully)" ); } if ( manager == null ) { throw new AssertionFailure( "Unexpected state: the CacheManager not created?" ); } if ( ! groupFormed && expectedGroupSize != 1 ) { verifyNetworkStackEnabled(); verifyConfiguredAsClustered( manager ); TestingUtil.blockUntilViewReceived( manager.getCache(), expectedGroupSize, joinTimeoutMilliseconds, true ); } return manager; } public static void verifyNetworkStackEnabled() { Assert.assertEquals( "Environment property '-Djgroups.bind_addr=127.0.0.1' was not detected", "127.0.0.1", JGROUPS_HOSTNAME ); Assert.assertTrue( "Environment property '-Djava.net.preferIPv4Stack=true' was not detected", IPV4_STACK.booleanValue() ); } @Override public void before() throws Throwable { InputStream inputStream = FileLookupFactory.newInstance().lookupFileStrict( configurationFile, InfinispanNode.class.getClassLoader() ); ConfigurationBuilderHolder cfgBuilder = new ParserRegistry().parse( inputStream ); cfgBuilder.getGlobalConfigurationBuilder().globalJmxStatistics().cacheManagerName( cacheManagerName ); manager = new DefaultCacheManager( cfgBuilder, true ); System.out.println( "Started CacheManager" ); //Now *Actually* start it: manager.getCache(); started = true; } @Override public void after() { TestingUtil.killCacheManagers( manager ); } public static void verifyConfiguredAsClustered(final EmbeddedCacheManager cacheManager) { final GlobalConfiguration globalConfiguration = cacheManager.getCacheManagerConfiguration(); Assert.assertTrue( "This CacheManager is not configured for clustering", globalConfiguration.isClustered() ); Assert.assertNotNull( "This CacheManager is configured for clustering but the Transport was not found", cacheManager.getTransport() ); } public static void verifyConfiguredAsClustered(final Cache<?, ?> cache) { verifyConfiguredAsClustered( cache.getCacheManager() ); final Configuration cacheConfiguration = cache.getCacheConfiguration(); Assert.assertTrue( "This Cache is managed by a clustered CacheManager, but the Cache is having clustering disabled!", cacheConfiguration.clustering().cacheMode().isClustered() ); } /** * For manual tests and debugging */ public static void main(String[] args) throws Throwable { final InfinispanNode nodeA = new InfinispanNode( "nodeA", "infinispan-dist.xml" ); nodeA.before(); try { final InfinispanNode nodeB = new InfinispanNode( "nodeB", "infinispan-dist.xml" ); nodeB.before(); try { nodeA.getCacheManager( 2 ); nodeB.getCacheManager( 2 ); } finally { nodeB.after(); } } finally { nodeA.after(); } } }