[jboss-cvs] JBossAS SVN: r81075 - in branches/JBPAPP_4_2_0_GA_CP/cluster/src/main/org/jboss: invocation/unified/interfaces and 1 other directories.
jboss-cvs-commits at lists.jboss.org
jboss-cvs-commits at lists.jboss.org
Fri Nov 14 11:56:32 EST 2008
Author: galder.zamarreno at jboss.com
Date: 2008-11-14 11:56:32 -0500 (Fri, 14 Nov 2008)
New Revision: 81075
Added:
branches/JBPAPP_4_2_0_GA_CP/cluster/src/main/org/jboss/proxy/AbstractTransactionStickyInterceptor.java
branches/JBPAPP_4_2_0_GA_CP/cluster/src/main/org/jboss/proxy/ClientUserTransactionStickyInterceptor.java
branches/JBPAPP_4_2_0_GA_CP/cluster/src/main/org/jboss/proxy/TransactionStickyInterceptor.java
Modified:
branches/JBPAPP_4_2_0_GA_CP/cluster/src/main/org/jboss/invocation/jrmp/interfaces/JRMPInvokerProxyHA.java
branches/JBPAPP_4_2_0_GA_CP/cluster/src/main/org/jboss/invocation/unified/interfaces/UnifiedInvokerHAProxy.java
Log:
[JBPAPP-1410] Moved transaction sticky logic to client side interceptors. Added a couple of methods to InvokerProxyHA that help keep interceptors proxy independent.
Modified: branches/JBPAPP_4_2_0_GA_CP/cluster/src/main/org/jboss/invocation/jrmp/interfaces/JRMPInvokerProxyHA.java
===================================================================
--- branches/JBPAPP_4_2_0_GA_CP/cluster/src/main/org/jboss/invocation/jrmp/interfaces/JRMPInvokerProxyHA.java 2008-11-14 16:39:31 UTC (rev 81074)
+++ branches/JBPAPP_4_2_0_GA_CP/cluster/src/main/org/jboss/invocation/jrmp/interfaces/JRMPInvokerProxyHA.java 2008-11-14 16:56:32 UTC (rev 81075)
@@ -29,6 +29,8 @@
import java.rmi.RemoteException;
import java.rmi.ServerException;
import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Map;
import java.util.WeakHashMap;
import javax.transaction.SystemException;
@@ -66,7 +68,7 @@
*/
private static final long serialVersionUID = -967671822225981666L;
private static final Logger log = Logger.getLogger(JRMPInvokerProxyHA.class);
- public static final WeakHashMap txFailoverAuthorizations = new WeakHashMap();
+ public static final Map txFailoverAuthorizations = Collections.synchronizedMap(new WeakHashMap());
protected LoadBalancePolicy loadBalancePolicy;
protected String proxyFamilyName = null;
@@ -134,34 +136,16 @@
Object tpc = getTransactionPropagationContext();
if (tpc != null)
{
- synchronized (tpc)
+ if (trace)
{
- if (trace)
- {
- log.trace("Checking tx failover authorisation map with tpc " + tpc);
- }
-
- /* If the map contains the tpc, then we can't allow a failover */
- boolean failoverAuthorised = ! txFailoverAuthorizations.containsKey(tpc);
-
- if (failoverAuthorised)
- {
- if (trace)
- {
- log.trace("Failover authorised, so we remove the sticky target associated with tpc " + tpc);
- }
-
- txFailoverAuthorizations.put(tpc, null);
- invocation.getTransientPayload().put("TX_STICKY_TARGET", null);
- }
-
- return failoverAuthorised;
+ log.trace("Checking tx failover authorisation map with tpc " + tpc);
}
+
+ /* If the map contains the tpc, then we can't allow a failover */
+ return ! txFailoverAuthorizations.containsKey(tpc);
}
- else
- {
- return true;
- }
+
+ return true;
}
public void invocationHasReachedAServer (Invocation invocation)
@@ -169,22 +153,7 @@
Object tpc = getTransactionPropagationContext();
if (tpc != null)
{
- synchronized (tpc)
- {
- if (trace)
- {
- log.trace("After reaching the server, transaction propagation context (tpc) is " + tpc);
- }
-
- Object stickyTarget = invocation.getTransientValue("TX_STICKY_TARGET");
-
- if (trace && stickyTarget != null)
- {
- log.trace("Remember transaction bound target[" + stickyTarget + "] for tpc[" + tpc + "]");
- }
-
- txFailoverAuthorizations.put(tpc, stickyTarget);
- }
+ txFailoverAuthorizations.put(tpc, null);
}
}
@@ -201,9 +170,6 @@
int failoverCounter = 0;
invocation.setValue ("FAILOVER_COUNTER", new Integer(failoverCounter), PayloadKey.AS_IS);
- // If transaction sticky, put chosen target
- putIfExistsTransactionTarget(invocation, getTransactionPropagationContext());
-
// We are going to go through a Remote invocation, switch to a Marshalled Invocation
MarshalledInvocation mi = new MarshalledInvocation(invocation);
@@ -404,45 +370,6 @@
return tpc;
}
-
- /**
- * Called at the beginning of the invocation to check whether the current tpc
- * is already present in the tx failover map. If it is, get the chosen
- * target associated to it and add it to the invocation transient payload so
- * that the load balance policy can choose the right target.
- */
- protected void putIfExistsTransactionTarget(Invocation invocation, Object tpc) throws Exception
- {
- if (tpc != null)
- {
- synchronized (tpc)
- {
- if (trace)
- {
- log.trace("In the proxy, transaction propagation context (tpc) is " + tpc);
- }
-
- Object stickyTarget = txFailoverAuthorizations.get(tpc);
-
- if (stickyTarget != null)
- {
- if (familyClusterInfo.getTargets().contains(stickyTarget))
- {
- if (trace)
- {
- log.trace("Put transaction bound target into transient payload: " + stickyTarget);
- }
-
- invocation.getTransientPayload().put("TX_STICKY_TARGET", stickyTarget);
- }
- else
- {
- throw new ServiceUnavailableException("Transaction sticky target is no longer available, so invocation needs to be halted");
- }
- }
- }
- }
- }
// Private -------------------------------------------------------
Modified: branches/JBPAPP_4_2_0_GA_CP/cluster/src/main/org/jboss/invocation/unified/interfaces/UnifiedInvokerHAProxy.java
===================================================================
--- branches/JBPAPP_4_2_0_GA_CP/cluster/src/main/org/jboss/invocation/unified/interfaces/UnifiedInvokerHAProxy.java 2008-11-14 16:39:31 UTC (rev 81074)
+++ branches/JBPAPP_4_2_0_GA_CP/cluster/src/main/org/jboss/invocation/unified/interfaces/UnifiedInvokerHAProxy.java 2008-11-14 16:56:32 UTC (rev 81075)
@@ -111,44 +111,20 @@
log.trace("Checking tx failover authorisation map with tpc " + tpc);
}
- /* Synchronise on tpc because we're updating the map if it doesn't
- * contain tpc upon failover (putIfAbsent type of operation). This is
- * still needed even if the collection is synchronized. */
- synchronized(tpc)
- {
- /* If the map contains the tpc, then we can't allow a failover */
- boolean failoverAuthorised = ! txFailoverAuthorizations.containsKey(tpc);
-
- if (failoverAuthorised)
- {
- if (trace)
- {
- log.trace("Failover authorised, so we remove the sticky target associated with tpc " + tpc);
- }
-
- invocation.getTransientPayload().put("TX_STICKY_TARGET", null);
- }
-
- return failoverAuthorised;
- }
+ /* If the map contains the tpc, then we can't allow a failover */
+ return ! txFailoverAuthorizations.containsKey(tpc);
}
return true;
}
- public void invocationHasReachedAServer(Invocation invocation, Object response)
+ public void invocationHasReachedAServer(Invocation invocation)
{
Object tpc = getTransactionPropagationContext();
- /* Idea here is you store the return value if there's no TPC, on the
- * chance it is a TPC. This won't leak anything since it's a WeakHashMap.
- * When you do a txFailoverAuthorization.get() it's always passing a TPC
- * as the key, so you won't accidentally find some random object you put
- * in the map.*/
- Object key = (tpc == null) ? response : tpc;
- if(key != null)
+ if(tpc != null)
{
- rememberTransactionTarget(invocation, key);
- }
+ txFailoverAuthorizations.put(tpc, null);
+ }
}
protected int totalNumberOfTargets()
@@ -204,9 +180,6 @@
int failoverCounter = 0;
invocation.setValue("FAILOVER_COUNTER", new Integer(failoverCounter), PayloadKey.AS_IS);
- // If transaction sticky, put chosen target
- putIfExistsTransactionTarget(invocation, getTransactionPropagationContext());
-
Object response = null;
Exception lastException = null;
@@ -281,7 +254,7 @@
}
else
{
- invocationHasReachedAServer(invocation, null);
+ invocationHasReachedAServer(invocation);
throw new ServerException("Clustering error", gcex);
}
}
@@ -311,7 +284,7 @@
}
response = haResponse.response;
- invocationHasReachedAServer(invocation, response);
+ invocationHasReachedAServer(invocation);
return response;
}
@@ -365,7 +338,7 @@
}
else
{
- invocationHasReachedAServer(invocation, null);
+ invocationHasReachedAServer(invocation);
throw new ServerException("Clustering error", gcex);
}
}
@@ -542,61 +515,4 @@
}
return (tpcFactory == null) ? null : tpcFactory.getTransactionPropagationContext();
}
-
- /**
- * Called at the beginning of the invocation to check whether the current tpc
- * is already present in the tx failover map. If it is, get the chosen
- * target associated to it and add it to the invocation transient payload so
- * that the load balance policy can choose the right target as long as the
- * target is available in the cluster family. Otherwise, invocation needs to
- * be halted because a previous invocation within the transaction succeeded
- * (tx sticky target was set), so we can't failover to a different node.
- */
- protected void putIfExistsTransactionTarget(Invocation invocation, Object tpc) throws Exception
- {
- if (tpc != null)
- {
- if (trace)
- {
- log.trace("In the proxy, transaction propagation context (tpc) is " + tpc);
- log.trace("Contains key returns " + txFailoverAuthorizations.containsKey(tpc));
- }
-
- Object stickyTarget = txFailoverAuthorizations.get(tpc);
-
- if (stickyTarget != null)
- {
- if (familyClusterInfo.getTargets().contains(stickyTarget))
- {
- if (trace)
- {
- log.trace("Put transaction bound target into transient payload: " + stickyTarget);
- }
-
- invocation.getTransientPayload().put("TX_STICKY_TARGET", stickyTarget);
- }
- else
- {
- throw new ServiceUnavailableException("Transaction sticky target is no longer available, so invocation needs to be halted");
- }
- }
- }
- }
-
- protected void rememberTransactionTarget(Invocation invocation, Object target)
- {
- if (trace)
- {
- log.trace("After reaching the server, transaction propagation context (tpc) is " + target);
- }
-
- Object stickyTarget = invocation.getTransientValue("TX_STICKY_TARGET");
-
- if (trace && stickyTarget != null)
- {
- log.trace("Remember transaction bound target [" + stickyTarget + "] for tpc " + target);
- }
-
- txFailoverAuthorizations.put(target, stickyTarget);
- }
}
\ No newline at end of file
Added: branches/JBPAPP_4_2_0_GA_CP/cluster/src/main/org/jboss/proxy/AbstractTransactionStickyInterceptor.java
===================================================================
--- branches/JBPAPP_4_2_0_GA_CP/cluster/src/main/org/jboss/proxy/AbstractTransactionStickyInterceptor.java (rev 0)
+++ branches/JBPAPP_4_2_0_GA_CP/cluster/src/main/org/jboss/proxy/AbstractTransactionStickyInterceptor.java 2008-11-14 16:56:32 UTC (rev 81075)
@@ -0,0 +1,197 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2008, Red Hat Middleware LLC, and individual contributors
+ * as indicated by the @author tags. See the copyright.txt file 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.jboss.proxy;
+
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.Externalizable;
+import java.io.IOException;
+import java.io.ObjectInput;
+import java.io.ObjectInputStream;
+import java.io.ObjectOutputStream;
+import java.util.Collections;
+import java.util.Map;
+import java.util.WeakHashMap;
+
+import org.jboss.ha.framework.interfaces.ClusteringTargetsRepository;
+import org.jboss.ha.framework.interfaces.FamilyClusterInfo;
+import org.jboss.invocation.Invocation;
+import org.jboss.invocation.InvocationContext;
+import org.jboss.invocation.Invoker;
+import org.jboss.invocation.ServiceUnavailableException;
+import org.jboss.invocation.unified.interfaces.UnifiedInvokerHAProxy;
+import org.jboss.logging.Logger;
+import org.jboss.tm.TransactionPropagationContextFactory;
+import org.jboss.tm.TransactionPropagationContextUtil;
+
+/**
+ * Parent transaction sticky interceptor that encapsulates sticky target map
+ * and exposes operations on this map.
+ *
+ * @author <a href="mailto:galder.zamarreno at jboss.com">Galder Zamarreno</a>
+ */
+public abstract class AbstractTransactionStickyInterceptor extends Interceptor
+{
+ private static final Map txStickyTargets = Collections.synchronizedMap(new WeakHashMap());
+
+ private FamilyClusterInfo familyClusterInfo;
+
+ protected final Logger log = Logger.getLogger(getClass());
+
+ protected static boolean trace = false;
+
+ public AbstractTransactionStickyInterceptor()
+ {
+ trace = log.isTraceEnabled();
+ }
+
+ /**
+ * Called at the beginning of the invocation to check whether the current tpc
+ * is already present in the tx sticky target. If it is, get the chosen
+ * target associated to it and add it to the invocation transient payload so
+ * that the load balance policy can choose the right target as long as the
+ * target is available in the cluster family. Otherwise, invocation needs to
+ * be halted because a previous invocation within the transaction succeeded
+ * (tx sticky target was set), so we can't failover to a different node.
+ *
+ * @param invocation Invocation object where transaction sticky will be set
+ * if present.
+ */
+ protected void putIfExistsTransactionTarget(Invocation invocation) throws Exception
+ {
+ Object tpc = getTransactionPropagationContext();
+
+ if (tpc != null)
+ {
+ if (trace)
+ {
+ log.trace("In the proxy, transaction propagation context (tpc) is " + tpc);
+ log.trace("Contains key returns " + txStickyTargets.containsKey(tpc));
+ }
+
+ Object stickyTarget = txStickyTargets.get(tpc);
+
+ if (stickyTarget != null)
+ {
+ if (getFamilyClusterInfo(invocation).getTargets().contains(stickyTarget))
+ {
+ if (trace)
+ {
+ log.trace("Put transaction bound target into transient payload: " + stickyTarget);
+ }
+
+ invocation.getTransientPayload().put("TX_STICKY_TARGET", stickyTarget);
+ }
+ else
+ {
+ throw new ServiceUnavailableException("Transaction sticky target is no longer available, so invocation needs to be halted");
+ }
+ }
+ }
+ }
+
+ /**
+ * Method called to remember the sticky target associated with a transaction
+ * context.
+ *
+ * @param invocation Invocation object from which the TX_STICKY_TARGET
+ * transient value comes from.
+ * @param tpc Transaction propagation context.
+ */
+ protected void rememberTransactionTarget(Invocation invocation, Object tpc)
+ {
+ if (trace)
+ {
+ log.trace("After reaching the server, transaction propagation context (tpc) is " + tpc);
+ }
+
+ Object stickyTarget = invocation.getTransientValue("TX_STICKY_TARGET");
+
+ if (stickyTarget != null)
+ {
+ if (trace)
+ {
+ log.trace("Remember transaction bound target [" + stickyTarget + "] for tpc " + tpc);
+ }
+
+ txStickyTargets.put(tpc, stickyTarget);
+
+ /* Put it in invoker proxy txFailoverAuthorizations to avoid failover being
+ * allowed if the 1st EJB invocation within user trasnsaction fails with
+ * GenericClusteringException.COMPLETED_NO */
+ UnifiedInvokerHAProxy.txFailoverAuthorizations.put(tpc, null);
+ }
+ }
+
+ @Override
+ public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException
+ {
+ super.readExternal(in);
+ trace = log.isTraceEnabled();
+ }
+
+ protected Object getTransactionPropagationContext()
+ {
+ TransactionPropagationContextFactory tpcFactory = TransactionPropagationContextUtil.getTPCFactoryClientSide();
+ if (trace)
+ {
+ log.trace("Using tpc factory " + tpcFactory);
+ }
+ return (tpcFactory == null) ? null : tpcFactory.getTransactionPropagationContext();
+ }
+
+ protected synchronized FamilyClusterInfo getFamilyClusterInfo(Invocation invocation) throws Exception
+ {
+ if (familyClusterInfo == null)
+ {
+ familyClusterInfo = ClusteringTargetsRepository.getFamilyClusterInfo(getProxyFamilyName(invocation));
+ }
+
+ return familyClusterInfo;
+ }
+
+ protected String getProxyFamilyName(Invocation invocation) throws Exception
+ {
+ InvocationContext ctx = invocation.invocationContext;
+ Invoker invoker = ctx.getInvoker();
+
+ ByteArrayOutputStream baos = new ByteArrayOutputStream();
+ ObjectOutputStream oos = new ObjectOutputStream(baos);
+ ((Externalizable)invoker).writeExternal(oos);
+ oos.close();
+ byte[] bytes = baos.toByteArray();
+
+ ByteArrayInputStream bais = new ByteArrayInputStream(bytes);
+ ObjectInputStream ois = new ObjectInputStream(bais);
+
+ /* version, uri and strictRMIException are UnifiedInvokerHAProxy specific */
+ ois.readInt(); // int version
+ ois.readUTF(); // String uri
+ ois.readBoolean(); // boolean strictRMIException
+ ois.readObject(); // Object targets
+ ois.readObject(); // Object loadBalancePolicy
+ String proxyFamilyName = (String) ois.readObject();
+ ois.close();
+
+ return proxyFamilyName;
+ }
+}
Added: branches/JBPAPP_4_2_0_GA_CP/cluster/src/main/org/jboss/proxy/ClientUserTransactionStickyInterceptor.java
===================================================================
--- branches/JBPAPP_4_2_0_GA_CP/cluster/src/main/org/jboss/proxy/ClientUserTransactionStickyInterceptor.java (rev 0)
+++ branches/JBPAPP_4_2_0_GA_CP/cluster/src/main/org/jboss/proxy/ClientUserTransactionStickyInterceptor.java 2008-11-14 16:56:32 UTC (rev 81075)
@@ -0,0 +1,62 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2008, Red Hat Middleware LLC, and individual contributors
+ * as indicated by the @author tags. See the copyright.txt file 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.jboss.proxy;
+
+import org.jboss.invocation.Invocation;
+
+/**
+ * The ClientUserTransactionStickyInterceptor should be used as an interceptor
+ * for the HA proxy in the ClientUserTransactionService. The aim of this
+ * interceptor is twofold: First, when UserTransaction.begin() is called, the
+ * result of the invocation, which is the transaction propagation context of
+ * the transaction started, is stored together with the target server used, so
+ * that future invocations can make use of the sticky target. Secondly, for the
+ * rest of UserTransaction invocations, i.e. commit(), getStatus()...etc, the
+ * current tpc is retrieved and the sticky target is located and added to the
+ * transient payload of the invocation.
+ *
+ * @author <a href="mailto:galder.zamarreno at jboss.com">Galder Zamarreno</a>
+ */
+public class ClientUserTransactionStickyInterceptor extends AbstractTransactionStickyInterceptor
+{
+ @Override
+ public Object invoke(Invocation invocation) throws Throwable
+ {
+ putIfExistsTransactionTarget(invocation);
+ Object response = getNext().invoke(invocation);
+ invocationHasReachedAServer(invocation, response);
+ return response;
+ }
+
+ public void invocationHasReachedAServer(Invocation invocation, Object response)
+ {
+ Object tpc = getTransactionPropagationContext();
+ if (tpc == null)
+ {
+ /* If tpc is null when invoking a UserTransaction operation, begin()
+ * is being called, so we remember the target where the transaction
+ * was started.
+ */
+ rememberTransactionTarget(invocation, response);
+ }
+ }
+}
Added: branches/JBPAPP_4_2_0_GA_CP/cluster/src/main/org/jboss/proxy/TransactionStickyInterceptor.java
===================================================================
--- branches/JBPAPP_4_2_0_GA_CP/cluster/src/main/org/jboss/proxy/TransactionStickyInterceptor.java (rev 0)
+++ branches/JBPAPP_4_2_0_GA_CP/cluster/src/main/org/jboss/proxy/TransactionStickyInterceptor.java 2008-11-14 16:56:32 UTC (rev 81075)
@@ -0,0 +1,42 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2008, Red Hat Middleware LLC, and individual contributors
+ * as indicated by the @author tags. See the copyright.txt file 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.jboss.proxy;
+
+import org.jboss.invocation.Invocation;
+
+/**
+ * Transaction sticky interceptor targeted for Home and Bean invocations. This
+ * interceptor will put, if exists, the transaction sticky target into the
+ * transient payload in the invocation so that the transaction sticky load
+ * balance policy can use it.
+ *
+ * @author <a href="mailto:galder.zamarreno at jboss.com">Galder Zamarreno</a>
+ */
+public class TransactionStickyInterceptor extends AbstractTransactionStickyInterceptor
+{
+ @Override
+ public Object invoke(Invocation invocation) throws Throwable
+ {
+ putIfExistsTransactionTarget(invocation);
+ return getNext().invoke(invocation);
+ }
+}
More information about the jboss-cvs-commits
mailing list