/* * Hibernate, Relational Persistence for Idiomatic Java * * Copyright (c) 2007, Red Hat, Inc. and/or it's affiliates or third-party contributors as * indicated by the @author tags or express copyright attribution * statements applied by the authors.  All third-party contributions are * distributed under license by Red Hat, Inc. and/or it's affiliates. * * This copyrighted material is made available to anyone wishing to use, modify, * copy, or redistribute it subject to the terms and conditions of the GNU * Lesser General Public License, as published by the Free Software Foundation. * * This program 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 distribution; if not, write to: * Free Software Foundation, Inc. * 51 Franklin Street, Fifth Floor * Boston, MA 02110-1301 USA */ package org.hibernate.test.cache.infinispan.functional.cluster; import java.util.Hashtable; import javax.transaction.HeuristicMixedException; import javax.transaction.HeuristicRollbackException; import javax.transaction.InvalidTransactionException; import javax.transaction.NotSupportedException; import javax.transaction.RollbackException; import javax.transaction.Status; import javax.transaction.SystemException; import javax.transaction.Transaction; import javax.transaction.TransactionManager; import org.infinispan.util.logging.Log; import org.infinispan.util.logging.LogFactory; /** * Variant of SimpleJtaTransactionManagerImpl that doesn't use a VM-singleton, but rather a set of * impls keyed by a node id. * * TODO: Merge with single node transaction manager as much as possible * * @author Brian Stansberry */ public class DualNodeJtaTransactionManagerImpl implements TransactionManager { private static final Log log = LogFactory.getLog(DualNodeJtaTransactionManagerImpl.class); private static final Hashtable INSTANCES = new Hashtable(); private ThreadLocal currentTransaction = new ThreadLocal(); private String nodeId; public synchronized static DualNodeJtaTransactionManagerImpl getInstance(String nodeId) { DualNodeJtaTransactionManagerImpl tm = (DualNodeJtaTransactionManagerImpl) INSTANCES .get(nodeId); if (tm == null) { tm = new DualNodeJtaTransactionManagerImpl(nodeId); INSTANCES.put(nodeId, tm); } return tm; } public synchronized static void cleanupTransactions() { for (java.util.Iterator it = INSTANCES.values().iterator(); it.hasNext();) { TransactionManager tm = (TransactionManager) it.next(); try { tm.suspend(); } catch (Exception e) { log.error("Exception cleaning up TransactionManager " + tm); } } } public synchronized static void cleanupTransactionManagers() { INSTANCES.clear(); } private DualNodeJtaTransactionManagerImpl(String nodeId) { this.nodeId = nodeId; } public int getStatus() throws SystemException { Transaction tx = getCurrentTransaction(); return tx == null ? Status.STATUS_NO_TRANSACTION : tx.getStatus(); } public Transaction getTransaction() throws SystemException { return (Transaction) currentTransaction.get(); } public DualNodeJtaTransactionImpl getCurrentTransaction() { return (DualNodeJtaTransactionImpl) currentTransaction.get(); } public void begin() throws NotSupportedException, SystemException { currentTransaction.set(new DualNodeJtaTransactionImpl(this)); } public Transaction suspend() throws SystemException { DualNodeJtaTransactionImpl suspended = getCurrentTransaction(); log.trace(nodeId + ": Suspending " + suspended + " for thread " + Thread.currentThread().getName()); currentTransaction.set(null); return suspended; } public void resume(Transaction transaction) throws InvalidTransactionException, IllegalStateException, SystemException { currentTransaction.set(transaction); log.trace(nodeId + ": Resumed " + transaction + " for thread " + Thread.currentThread().getName()); } public void commit() throws RollbackException, HeuristicMixedException, HeuristicRollbackException, SecurityException, IllegalStateException, SystemException { Transaction tx = getCurrentTransaction(); if (tx == null) { throw new IllegalStateException("no current transaction to commit"); } tx.commit(); } public void rollback() throws IllegalStateException, SecurityException, SystemException { Transaction tx = getCurrentTransaction(); if (tx == null) { throw new IllegalStateException("no current transaction"); } tx.rollback(); } public void setRollbackOnly() throws IllegalStateException, SystemException { Transaction tx = getCurrentTransaction(); if (tx == null) { throw new IllegalStateException("no current transaction"); } tx.setRollbackOnly(); } public void setTransactionTimeout(int i) throws SystemException { } void endCurrent(DualNodeJtaTransactionImpl transaction) { if (transaction == currentTransaction.get()) { currentTransaction.set(null); } } @Override public String toString() { StringBuffer sb = new StringBuffer(getClass().getName()); sb.append("[nodeId="); sb.append(nodeId); sb.append("]"); return sb.toString(); } }