/* * JBoss, Home of Professional Open Source * Copyright 2012 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.tx; import org.infinispan.commands.tx.CommitCommand; import org.infinispan.commands.tx.PrepareCommand; import org.infinispan.commands.tx.RollbackCommand; import org.infinispan.config.Configuration; import org.infinispan.configuration.cache.CacheMode; import org.infinispan.configuration.cache.ConfigurationBuilder; import org.infinispan.context.impl.TxInvocationContext; import org.infinispan.interceptors.base.CommandInterceptor; import org.infinispan.test.MultipleCacheManagersTest; import org.infinispan.test.TestingUtil; import org.infinispan.transaction.lookup.DummyTransactionManagerLookup; import org.infinispan.transaction.tm.DummyTransactionManager; import org.infinispan.util.concurrent.TimeoutException; import org.testng.annotations.Test; import javax.transaction.Transaction; import java.util.concurrent.CountDownLatch; import static org.testng.Assert.assertEquals; /** * // TODO: Document this * * @author Mircea Markus (C) 2011 Red Hat Inc. * @since 5.2 */ @Test(testName = "tx.RollbackNotSentBeforePrepareTest", groups = "functional") public class RollbackNotSentBeforePrepareTest extends MultipleCacheManagersTest { public static final long REPL_TIMEOUT = 1000; public static final long LOCK_TIMEOUT = 500; @Override protected void createCacheManagers() throws Throwable { ConfigurationBuilder config = getDefaultClusteredCacheConfig(CacheMode.REPL_SYNC, true); config .locking().lockAcquisitionTimeout(LOCK_TIMEOUT) .clustering().sync().replTimeout(REPL_TIMEOUT) .transaction().transactionManagerLookup(new DummyTransactionManagerLookup()); createCluster(config, 3); waitForClusterToForm(); advancedCache(1).addInterceptor(new CheckInterceptor(), 1); advancedCache(2).addInterceptor(new FailPrepareInterceptor(), 1); } public void testCommitNotSentBeforeAllPrepareAreAck() throws Exception { tm(0).begin(); cache(0).put("k", "v"); try { ((DummyTransactionManager)tm(0)).getTransaction().runPrepare(); } catch (Exception e) { ((DummyTransactionManager)tm(0)).getTransaction().runRollback(); } Thread.sleep(REPL_TIMEOUT * 2); assertEquals(1, TestingUtil.getTransactionTable(cache(1)).getRemoteTransactions()); } public static class CheckInterceptor extends CommandInterceptor { private volatile boolean receivedCommit; @Override public Object visitPrepareCommand(TxInvocationContext ctx, PrepareCommand command) throws Throwable { Thread.sleep(REPL_TIMEOUT * 2); try { return super.visitPrepareCommand(ctx, command); } finally { System.out.println("RollbackNotSentBeforePrepareTest$CheckInterceptor.visitPrepareCommand"); } } @Override public Object visitRollbackCommand(TxInvocationContext ctx, RollbackCommand command) throws Throwable { try { return super.visitRollbackCommand(ctx, command); } finally { System.out.println("RollbackNotSentBeforePrepareTest$CheckInterceptor.visitRollbackCommand"); } } @Override public Object visitCommitCommand(TxInvocationContext ctx, CommitCommand command) throws Throwable { try { return super.visitCommitCommand(ctx, command); } finally { System.out.println("RollbackNotSentBeforePrepareTest$CheckInterceptor.visitCommitCommand"); } } } public static class FailPrepareInterceptor extends CommandInterceptor { private volatile boolean receivedCommit; @Override public Object visitPrepareCommand(TxInvocationContext ctx, PrepareCommand command) throws Throwable { throw new TimeoutException("Induced!"); } } }