/* * JBoss, Home of Professional Open Source * Copyright 2010 Red Hat Inc. and/or its affiliates and other * contributors as indicated by the @author tags. All rights reserved. * See the copyright.txt in the distribution for a full listing of * individual contributors. * * This is free software; you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License as * published by the Free Software Foundation; either version 2.1 of * the License, or (at your option) any later version. * * This software is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this software; if not, write to the Free * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA * 02110-1301 USA, or see the FSF site: http://www.fsf.org. */ package org.infinispan.distribution; import org.infinispan.Cache; import org.infinispan.config.Configuration; import org.infinispan.config.GlobalConfiguration; import org.infinispan.manager.CacheContainer; import org.infinispan.manager.EmbeddedCacheManager; import org.infinispan.test.AbstractInfinispanTest; import org.infinispan.test.MultipleCacheManagersTest; import org.infinispan.test.TestingUtil; import org.infinispan.test.fwk.TestCacheManagerFactory; import org.infinispan.test.fwk.UnitTestTestNGListener; import org.infinispan.util.concurrent.AbstractInProcessFuture; import org.testng.annotations.BeforeTest; import org.testng.annotations.Test; import java.util.concurrent.Callable; import java.util.concurrent.ExecutionException; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.Future; /** * Tests concurrent startup of replicated and distributed caches * * @author Mircea.Markus@jboss.com * @since 4.1 */ @Test(testName = "distribution.ConcurrentStartWithReplTest", groups = "functional") public class ConcurrentStartWithReplTest extends AbstractInfinispanTest { Configuration replCfg, distCfg; @BeforeTest public void setUp() { replCfg = MultipleCacheManagersTest.getDefaultClusteredConfig(Configuration.CacheMode.REPL_SYNC); replCfg.setFetchInMemoryState(true); distCfg = MultipleCacheManagersTest.getDefaultClusteredConfig(Configuration.CacheMode.DIST_SYNC); distCfg.setRehashEnabled(true); } @Test(timeOut = 60000) public void testSequence1() throws ExecutionException, InterruptedException { TestCacheManagerFactory.backgroundTestStarted(this); /* Sequence 1: C1 (repl) (becomes coord) C2 (dist) C1 (repl) C2 (dist) in the same thread. */ doTest(true, false); } // ****** This will probably always be an unsupported sequence of startup, in a single thread // public void testSequence2() throws ExecutionException, InterruptedException { /* Sequence 2: C1 (repl) (becomes coord) C2 (repl) C2 (dist) C1 (dist) in the same thread. */ // doTest(false, false); // } @Test(timeOut = 60000) public void testSequence3() throws ExecutionException, InterruptedException { TestCacheManagerFactory.backgroundTestStarted(this); /* Sequence 3: C1 (repl) (becomes coord) C2 (repl) C1 (dist) (async thread) C2 (dist) (async thread) in the same thread, except the last two which are in separate threads */ doTest(true, true); } @Test(timeOut = 60000) public void testSequence4() throws ExecutionException, InterruptedException { TestCacheManagerFactory.backgroundTestStarted(this); /* Sequence 4: C1 (repl) (becomes coord) C2 (repl) C2 (dist) (async thread) C1 (dist) (async thread) in the same thread, except the last two which are in separate threads */ doTest(false, true); } private void doTest(boolean inOrder, boolean nonBlockingStartupForDist) throws ExecutionException, InterruptedException { EmbeddedCacheManager cm1 = TestCacheManagerFactory.createCacheManager(GlobalConfiguration.getClusteredDefault()); EmbeddedCacheManager cm2 = TestCacheManagerFactory.createCacheManager(GlobalConfiguration.getClusteredDefault()); try { cm1.defineConfiguration("r", replCfg); cm1.defineConfiguration("d", distCfg); cm2.defineConfiguration("r", replCfg); cm2.defineConfiguration("d", distCfg); // first start the repl caches Cache<String, String> c1r = startCache(cm1, "r", false).get(); c1r.put("key", "value"); Cache<String, String> c2r = startCache(cm2, "r", false).get(); TestingUtil.blockUntilViewsReceived(10000, c1r, c2r); TestingUtil.waitForRehashToComplete(c1r, c2r); assert "value".equals(c2r.get("key")); // now the dist ones Future<Cache<String, String>> c1df = startCache(inOrder ? cm1 : cm2, "d", nonBlockingStartupForDist); Future<Cache<String, String>> c2df = startCache(inOrder ? cm2 : cm1, "d", nonBlockingStartupForDist); Cache<String, String> c1d = c1df.get(); Cache<String, String> c2d = c2df.get(); c1d.put("key", "value"); assert "value".equals(c2d.get("key")); } finally { TestingUtil.killCacheManagers(cm1, cm2); } } private Future<Cache<String, String>> startCache(final CacheContainer cm, final String cacheName, boolean nonBlockingStartup) { final Callable<Cache<String, String>> cacheCreator = new Callable<Cache<String, String>>() { @Override public Cache<String, String> call() throws Exception { Cache<String, String> c = cm.getCache(cacheName); return c; } }; if (nonBlockingStartup) { final ExecutorService e = Executors.newFixedThreadPool(1); Future<Cache<String, String>> future = e.submit(cacheCreator); e.shutdown(); return future; } else { return new AbstractInProcessFuture<Cache<String, String>>() { @Override public Cache<String, String> get() throws InterruptedException, ExecutionException { try { return cacheCreator.call(); } catch (Exception e) { throw new ExecutionException(e); } } }; } } }