From 73990e3fb7efd701b9a6d06b7929c4d557002fd7 Mon Sep 17 00:00:00 2001 From: rob bygrave Date: Thu, 16 May 2019 22:26:11 +1200 Subject: [PATCH] #1701 (v2) - Replace TransactionMap with HashMap in DefaultTransactionThreadLocal --- .../DefaultTransactionThreadLocal.java | 106 +++++++++++------ .../server/transaction/TransactionMap.java | 112 ------------------ 2 files changed, 71 insertions(+), 147 deletions(-) delete mode 100644 src/main/java/io/ebeaninternal/server/transaction/TransactionMap.java diff --git a/src/main/java/io/ebeaninternal/server/transaction/DefaultTransactionThreadLocal.java b/src/main/java/io/ebeaninternal/server/transaction/DefaultTransactionThreadLocal.java index 3502f0bc4..5c497514f 100644 --- a/src/main/java/io/ebeaninternal/server/transaction/DefaultTransactionThreadLocal.java +++ b/src/main/java/io/ebeaninternal/server/transaction/DefaultTransactionThreadLocal.java @@ -1,19 +1,17 @@ package io.ebeaninternal.server.transaction; import io.ebeaninternal.api.SpiTransaction; -import io.ebeaninternal.server.transaction.TransactionMap.State; + +import javax.persistence.PersistenceException; +import java.util.HashMap; +import java.util.Map; /** * Used to store Transactions in a ThreadLocal. */ public final class DefaultTransactionThreadLocal { - private static final ThreadLocal local = new ThreadLocal() { - @Override - protected synchronized TransactionMap initialValue() { - return new TransactionMap(); - } - }; + private static final ThreadLocal> local = new ThreadLocal<>(); /** * Not allowed. @@ -21,19 +19,46 @@ public final class DefaultTransactionThreadLocal { private DefaultTransactionThreadLocal() { } + private static Map createMap() { + Map map = new HashMap<>(); + local.set(map); + return map; + } + /** - * Return the current TransactionState for a given serverName. This is for the - * local thread of course. + * Obtain the map creating if needed. */ - private static TransactionMap.State getState(String serverName) { - return local.get().getStateWithCreate(serverName); + private static Map obtainMap() { + final Map map = local.get(); + if (map == null) { + return createMap(); + } + return map; + } + + /** + * Remove the transaction entry for the given serverName. + */ + private static void remove(String serverName) { + Map map = local.get(); + if (map != null) { + map.remove(serverName); + } } /** * Set a new Transaction for this serverName and Thread. */ public static void set(String serverName, SpiTransaction trans) { - getState(serverName).set(trans); + if (trans == null) { + remove(serverName); + } else { + Map map = obtainMap(); + SpiTransaction existingTransaction = map.put(serverName, trans); + if (existingTransaction != null && existingTransaction.isActive()) { + throw new PersistenceException("The existing transaction is still active?"); + } + } } /** @@ -46,32 +71,43 @@ public final class DefaultTransactionThreadLocal { *

*/ public static void replace(String serverName, SpiTransaction trans) { - getState(serverName).replace(trans); + if (trans == null) { + remove(serverName); + } else { + Map map = obtainMap(); + map.put(serverName, trans); + } } /** * Return the current Transaction for this serverName and Thread. */ public static SpiTransaction get(String serverName) { - TransactionMap map = local.get(); - State state = map.getState(serverName); - SpiTransaction t = (state == null) ? null : state.transaction; - if (map.isEmpty()) { - local.remove(); + Map map = local.get(); + if (map == null) { + return null; } - return t; + return map.get(serverName); + } + + private static SpiTransaction obtain(String serverName, Map map) { + if (map == null) { + throw new IllegalStateException("No current transaction for [" + serverName + "]"); + } + SpiTransaction transaction = map.remove(serverName); + if (transaction == null) { + throw new IllegalStateException("No current transaction for [" + serverName + "]"); + } + return transaction; } /** * Commit the current transaction. */ public static void commit(String serverName) { - TransactionMap map = local.get(); - State state = map.removeState(serverName); - if (state == null) { - throw new IllegalStateException("No current transaction for [" + serverName + "]"); - } - state.commit(); + Map map = local.get(); + SpiTransaction transaction = obtain(serverName, map); + transaction.commit(); if (map.isEmpty()) { local.remove(); } @@ -81,12 +117,9 @@ public final class DefaultTransactionThreadLocal { * Rollback the current transaction. */ public static void rollback(String serverName) { - TransactionMap map = local.get(); - State state = map.removeState(serverName); - if (state == null) { - throw new IllegalStateException("No current transaction for [" + serverName + "]"); - } - state.rollback(); + Map map = local.get(); + SpiTransaction transaction = obtain(serverName, map); + transaction.rollback(); if (map.isEmpty()) { local.remove(); } @@ -113,10 +146,13 @@ public final class DefaultTransactionThreadLocal { */ public static void end(String serverName) { - TransactionMap map = local.get(); - State state = map.removeState(serverName); - if (state != null) { - state.end(); + Map map = local.get(); + if (map == null) { + return; + } + SpiTransaction transaction = map.remove(serverName); + if (transaction != null) { + transaction.end(); } if (map.isEmpty()) { local.remove(); diff --git a/src/main/java/io/ebeaninternal/server/transaction/TransactionMap.java b/src/main/java/io/ebeaninternal/server/transaction/TransactionMap.java deleted file mode 100644 index 033e6c74a..000000000 --- a/src/main/java/io/ebeaninternal/server/transaction/TransactionMap.java +++ /dev/null @@ -1,112 +0,0 @@ -package io.ebeaninternal.server.transaction; - -import io.ebeaninternal.api.SpiTransaction; - -import javax.persistence.PersistenceException; -import java.util.HashMap; -import java.util.Map; - - -/** - * Current transactions mapped by server name. - */ -public class TransactionMap { - - /** - * Map of State by serverName. - */ - private final Map map = new HashMap<>(); - - @Override - public String toString() { - return map.toString(); - } - - public boolean isEmpty() { - return map.isEmpty(); - } - - /** - * Return the State for a given serverName. - */ - public State getState(String serverName) { - - return map.get(serverName); - } - - /** - * Return the State for a given serverName. - */ - public State getStateWithCreate(String serverName) { - - return map.computeIfAbsent(serverName, k -> new State()); - } - - /** - * Remove and return the State for a given serverName. - */ - public State removeState(String serverName) { - return map.remove(serverName); - } - - /** - * The transaction and whether it is active. - */ - public static class State { - - SpiTransaction transaction; - - @Override - public String toString() { - return "txn[" + transaction + "]"; - } - - public SpiTransaction get() { - return transaction; - } - - /** - * Set the transaction. This will now be the current transaction. - */ - public void set(SpiTransaction trans) { - if (transaction != null && transaction.isActive()) { - throw new PersistenceException("The existing transaction is still active?"); - } - transaction = trans; - } - - /** - * Commit the transaction. - */ - public void commit() { - transaction.commit(); - transaction = null; - } - - /** - * Rollback the transaction. - */ - public void rollback() { - transaction.rollback(); - transaction = null; - } - - /** - * End the transaction. - */ - public void end() { - if (transaction != null) { - transaction.end(); - transaction = null; - } - } - - /** - * Used to replace transaction with a proxy. - */ - public void replace(SpiTransaction trans) { - transaction = trans; - } - - } -}