# IGNITE-591 Don't use static ThreadLocal.
Project: http://git-wip-us.apache.org/repos/asf/incubator-ignite/repo Commit: http://git-wip-us.apache.org/repos/asf/incubator-ignite/commit/53143355 Tree: http://git-wip-us.apache.org/repos/asf/incubator-ignite/tree/53143355 Diff: http://git-wip-us.apache.org/repos/asf/incubator-ignite/diff/53143355 Branch: refs/heads/master Commit: 53143355dc713f2af3308f5ceef9fcc6e3d3d2a1 Parents: bac6f48 Author: sevdokimov <sevdoki...@gridgain.com> Authored: Thu Jul 2 16:38:10 2015 +0300 Committer: sevdokimov <sevdoki...@gridgain.com> Committed: Thu Jul 2 16:38:10 2015 +0300 ---------------------------------------------------------------------- .../processors/cache/jta/CacheJtaManager.java | 122 ++++++++++++------- 1 file changed, 77 insertions(+), 45 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/53143355/modules/jta/src/main/java/org/apache/ignite/internal/processors/cache/jta/CacheJtaManager.java ---------------------------------------------------------------------- diff --git a/modules/jta/src/main/java/org/apache/ignite/internal/processors/cache/jta/CacheJtaManager.java b/modules/jta/src/main/java/org/apache/ignite/internal/processors/cache/jta/CacheJtaManager.java index 2a078dc..c5a94bc 100644 --- a/modules/jta/src/main/java/org/apache/ignite/internal/processors/cache/jta/CacheJtaManager.java +++ b/modules/jta/src/main/java/org/apache/ignite/internal/processors/cache/jta/CacheJtaManager.java @@ -17,23 +17,34 @@ package org.apache.ignite.internal.processors.cache.jta; -import org.apache.ignite.*; -import org.apache.ignite.cache.jta.*; -import org.apache.ignite.configuration.*; -import org.apache.ignite.internal.processors.cache.transactions.*; -import org.jetbrains.annotations.*; - -import javax.transaction.*; +import org.apache.ignite.IgniteCheckedException; +import org.apache.ignite.cache.jta.CacheTmLookup; +import org.apache.ignite.configuration.CacheConfiguration; +import org.apache.ignite.configuration.TransactionConfiguration; +import org.apache.ignite.internal.processors.cache.transactions.IgniteInternalTx; +import org.jetbrains.annotations.Nullable; + +import javax.transaction.RollbackException; +import javax.transaction.SystemException; +import javax.transaction.Transaction; +import javax.transaction.TransactionManager; +import java.lang.ref.WeakReference; +import java.util.Map; +import java.util.WeakHashMap; /** * Implementation of {@link CacheJtaManagerAdapter}. */ public class CacheJtaManager extends CacheJtaManagerAdapter { /** */ - private final static ThreadLocal<GridCacheXAResource> xaRsrc = new ThreadLocal<>(); + private static final Map<TransactionManager, ThreadLocal<WeakReference<GridCacheXAResource>>> threadLocals = + new WeakHashMap<>(); + + /** */ + private volatile TransactionManager jtaTm; /** */ - private TransactionManager jtaTm; + private ThreadLocal<WeakReference<GridCacheXAResource>> xaRsrc; /** */ private CacheTmLookup tmLookup; @@ -54,55 +65,76 @@ public class CacheJtaManager extends CacheJtaManagerAdapter { /** {@inheritDoc} */ @Override public void checkJta() throws IgniteCheckedException { + TransactionManager jtaTm = this.jtaTm; + if (jtaTm == null) { try { jtaTm = tmLookup.getTm(); + + if (jtaTm == null) + return; + + synchronized (threadLocals) { + if (this.jtaTm != null) + jtaTm = this.jtaTm; + else { + xaRsrc = threadLocals.get(jtaTm); + + if (xaRsrc == null) { + xaRsrc = new ThreadLocal<>(); + + threadLocals.put(jtaTm, xaRsrc); + } + + this.jtaTm = jtaTm; + } + } } catch (Exception e) { throw new IgniteCheckedException("Failed to get transaction manager: " + e, e); } } - if (jtaTm != null) { - GridCacheXAResource rsrc = xaRsrc.get(); - - if (rsrc == null || rsrc.isFinished()) { - try { - Transaction jtaTx = jtaTm.getTransaction(); - - if (jtaTx != null) { - IgniteInternalTx tx = cctx.tm().userTx(); - - if (tx == null) { - TransactionConfiguration tCfg = cctx.kernalContext().config() - .getTransactionConfiguration(); - - tx = cctx.tm().newTx( - /*implicit*/false, - /*implicit single*/false, - null, - tCfg.getDefaultTxConcurrency(), - tCfg.getDefaultTxIsolation(), - tCfg.getDefaultTxTimeout(), - /*store enabled*/true, - /*tx size*/0 - ); - } - - rsrc = new GridCacheXAResource(tx, cctx.kernalContext()); + WeakReference<GridCacheXAResource> rsrcRef = xaRsrc.get(); - if (!jtaTx.enlistResource(rsrc)) - throw new IgniteCheckedException("Failed to enlist XA resource to JTA user transaction."); + GridCacheXAResource rsrc = rsrcRef == null ? null : rsrcRef.get(); - xaRsrc.set(rsrc); + if (rsrc == null || rsrc.isFinished()) { + try { + Transaction jtaTx = jtaTm.getTransaction(); + + if (jtaTx != null) { + IgniteInternalTx tx = cctx.tm().userTx(); + + if (tx == null) { + TransactionConfiguration tCfg = cctx.kernalContext().config() + .getTransactionConfiguration(); + + tx = cctx.tm().newTx( + /*implicit*/false, + /*implicit single*/false, + null, + tCfg.getDefaultTxConcurrency(), + tCfg.getDefaultTxIsolation(), + tCfg.getDefaultTxTimeout(), + /*store enabled*/true, + /*tx size*/0 + ); } + + rsrc = new GridCacheXAResource(tx, cctx.kernalContext()); + + if (!jtaTx.enlistResource(rsrc)) + throw new IgniteCheckedException("Failed to enlist XA resource to JTA user transaction."); + + xaRsrc.set(new WeakReference<>(rsrc)); } - catch (SystemException e) { - throw new IgniteCheckedException("Failed to obtain JTA transaction.", e); - } - catch (RollbackException e) { - throw new IgniteCheckedException("Failed to enlist XAResource to JTA transaction.", e); - } + } + catch (SystemException e) { + throw new IgniteCheckedException("Failed to obtain JTA transaction.", e); + } + catch (RollbackException e) { + throw new IgniteCheckedException("Failed to enlist XAResource to JTA transaction.", e); } } }