[jboss-svn-commits] JBL Code SVN: r20191 - in labs/jbosstm/branches/JBOSSTS_4_2_3_GA_CP: ArjunaJTS/jtax/classes/com/arjuna/ats/internal/jta/transaction/jts and 1 other directory.

jboss-svn-commits at lists.jboss.org jboss-svn-commits at lists.jboss.org
Wed May 28 07:49:36 EDT 2008


Author: jhalliday
Date: 2008-05-28 07:49:36 -0400 (Wed, 28 May 2008)
New Revision: 20191

Modified:
   labs/jbosstm/branches/JBOSSTS_4_2_3_GA_CP/ArjunaJTA/jta/classes/com/arjuna/ats/internal/jta/transaction/arjunacore/TransactionImple.java
   labs/jbosstm/branches/JBOSSTS_4_2_3_GA_CP/ArjunaJTS/jtax/classes/com/arjuna/ats/internal/jta/transaction/jts/TransactionImple.java
Log:
Fixes for XAResource enlistment merged to 4.2.3.CP from SP. JBTM-362 and JBTM-363


Modified: labs/jbosstm/branches/JBOSSTS_4_2_3_GA_CP/ArjunaJTA/jta/classes/com/arjuna/ats/internal/jta/transaction/arjunacore/TransactionImple.java
===================================================================
--- labs/jbosstm/branches/JBOSSTS_4_2_3_GA_CP/ArjunaJTA/jta/classes/com/arjuna/ats/internal/jta/transaction/arjunacore/TransactionImple.java	2008-05-28 11:37:41 UTC (rev 20190)
+++ labs/jbosstm/branches/JBOSSTS_4_2_3_GA_CP/ArjunaJTA/jta/classes/com/arjuna/ats/internal/jta/transaction/arjunacore/TransactionImple.java	2008-05-28 11:49:36 UTC (rev 20191)
@@ -413,7 +413,7 @@
 	 *          null synchronization parameter!
 	 * @message com.arjuna.ats.internal.jta.transaction.arjunacore.syncsnotallowed
 	 *          [com.arjuna.ats.internal.jta.transaction.arjunacore.syncsnotallowed]
-	 *          Synchronizations are not allowed!
+	 *          Synchronizations are not allowed! Transaction status is
 	 */
 
 	public void registerSynchronization(javax.transaction.Synchronization sync)
@@ -470,7 +470,7 @@
 				default:
 					throw new IllegalStateException(
 							jtaLogger.logMesg
-									.getString("com.arjuna.ats.internal.jta.transaction.arjunacore.syncsnotallowed"));
+									.getString("com.arjuna.ats.internal.jta.transaction.arjunacore.syncsnotallowed")+ActionStatus.stringForm(status));
 				}
 			}
 		}
@@ -771,11 +771,34 @@
 								: theModifier
 										.xaStartParameters(XAResource.TMNOFLAGS));
 
-						xaRes.start(xid, xaStartNormal);
 
-						associatedWork = true;
+                        // Pay attention now, this bit is hairy. We need to add a new AbstractRecord (XAResourceRecord)
+                        // to the BasicAction, which will thereafter drive its completion. However, the transaction
+                        // core is not directly XA aware, so it's our job to start the XAResource. Problem is, if
+                        // adding the record fails, BasicAction will never end the resource via the XAResourceRecord,
+                        // so we must do so directly.  start may fail due to dupl xid or other reason, and transactions
+                        // may rollback async, for which reasons we can't call add before start.
+                        // The xid will change on each pass of the loop, so we need to create a new record on each pass.
+                        // The creation will fail in the case of multiple last resources being disallowed, in which
+                        // case we don't call start on the resource at all. see JBTM-362 and JBTM-363
+                        AbstractRecord abstractRecord = createRecord(xaRes, params, xid);
+                        if(abstractRecord != null) {
+                            xaRes.start(xid, xaStartNormal);
+                            if(_theTransaction.add(abstractRecord) == AddOutcome.AR_ADDED) {
+                                _resources.put(xaRes, new TxInfo(xid));
+                                return true; // dive out, no need to set associatedWork = true;
+                            } else {
+                                // we called start on the resource, but _theTransaction did not accept it.
+                                // we therefore have a mess which we must now clean up by ensuring the start is undone:
+                                abstractRecord.topLevelAbort();
+                            }
+                        }
 
-						_resources.put(xaRes, new TxInfo(xid));
+                        // if we get to here, something other than a failure of xaRes.start probably went wrong.
+                        // so we don't loop and retry, we just give up.
+                        markRollbackOnly();
+                        return false;
+
 					}
 					catch (XAException e)
 					{
@@ -891,64 +914,8 @@
 				return true;
 			}
 
-			/*
-			 * Control and Coordinator should be set, or we would not have
-			 * gotten this far!
-			 */
-
-			final AbstractRecord record;
-			if ((xaRes instanceof LastResourceCommitOptimisation)
-					|| ((LAST_RESOURCE_OPTIMISATION_INTERFACE != null) && LAST_RESOURCE_OPTIMISATION_INTERFACE
-							.isInstance(xaRes)))
-			{
-				if (lastResourceCount == 1)
-				{
-					if (jtaLogger.loggerI18N.isWarnEnabled())
-					{
-						if (ALLOW_MULTIPLE_LAST_RESOURCES)
-						{
-							jtaLogger.loggerI18N
-									.warn(
-											"com.arjuna.ats.internal.jta.transaction.arjunacore.lastResource.multipleWarning",
-											new Object[]
-											{ xaRes });
-						}
-						else
-						{
-							jtaLogger.loggerI18N
-									.warn(
-											"com.arjuna.ats.internal.jta.transaction.arjunacore.lastResource.disallow",
-											new Object[]
-											{ xaRes });
-						}
-					}
-				}
-
-				if ((lastResourceCount++ == 0) || ALLOW_MULTIPLE_LAST_RESOURCES)
-				{
-					record = new LastResourceRecord(new XAOnePhaseResource(
-							xaRes, xid, params));
-				}
-				else
-				{
-					record = null;
-				}
-			}
-			else
-			{
-				record = new XAResourceRecord(this, xaRes, xid, params);
-			}
-
-			if ((record == null)
-					|| (_theTransaction.add(record) != AddOutcome.AR_ADDED))
-			{
-				markRollbackOnly();
-
-				return false;
-			}
-			else
-				return true;
-		}
+            return false;
+        }
 		catch (Exception e)
 		{
 			e.printStackTrace();
@@ -965,11 +932,68 @@
 		}
 	}
 
-	/*
-	 * Do we have to unregister resources? Assume not as it would not make much
-	 * sense otherwise!
-	 */
+    /**
+     * Attempt to create an AbstractRecord wrapping the given XAResource. Return null if this fails, or
+     * is diallowed by the current configuration of multiple last resource behaviour.
+     *
+     * @param xaRes
+     * @param params
+     * @param xid
+     * @return
+     */
+    private AbstractRecord createRecord(XAResource xaRes, Object[] params, Xid xid)
+    {
+        final AbstractRecord record;
+        if ((xaRes instanceof LastResourceCommitOptimisation)
+                || ((LAST_RESOURCE_OPTIMISATION_INTERFACE != null) && LAST_RESOURCE_OPTIMISATION_INTERFACE
+                .isInstance(xaRes)))
+        {
+            if (lastResourceCount == 1)
+            {
+                if (jtaLogger.loggerI18N.isWarnEnabled())
+                {
+                    if (ALLOW_MULTIPLE_LAST_RESOURCES)
+                    {
+                        jtaLogger.loggerI18N
+                                .warn(
+                                        "com.arjuna.ats.internal.jta.transaction.arjunacore.lastResource.multipleWarning",
+                                        new Object[]
+                                                { xaRes });
+                    }
+                    else
+                    {
+                        jtaLogger.loggerI18N
+                                .warn(
+                                        "com.arjuna.ats.internal.jta.transaction.arjunacore.lastResource.disallow",
+                                        new Object[]
+                                                { xaRes });
+                    }
+                }
+            }
 
+            if ((lastResourceCount++ == 0) || ALLOW_MULTIPLE_LAST_RESOURCES)
+            {
+                record = new LastResourceRecord(new XAOnePhaseResource(
+                        xaRes, xid, params));
+            }
+            else
+            {
+                record = null;
+            }
+        }
+        else
+        {
+            record = new XAResourceRecord(this, xaRes, xid, params);
+        }
+
+        return record;
+    }
+
+    /*
+      * Do we have to unregister resources? Assume not as it would not make much
+      * sense otherwise!
+      */
+
 	/**
 	 * @message com.arjuna.ats.internal.jta.transaction.arjunacore.unknownresource
 	 *          [com.arjuna.ats.internal.jta.transaction.arjunacore.unknownresource]

Modified: labs/jbosstm/branches/JBOSSTS_4_2_3_GA_CP/ArjunaJTS/jtax/classes/com/arjuna/ats/internal/jta/transaction/jts/TransactionImple.java
===================================================================
--- labs/jbosstm/branches/JBOSSTS_4_2_3_GA_CP/ArjunaJTS/jtax/classes/com/arjuna/ats/internal/jta/transaction/jts/TransactionImple.java	2008-05-28 11:37:41 UTC (rev 20190)
+++ labs/jbosstm/branches/JBOSSTS_4_2_3_GA_CP/ArjunaJTS/jtax/classes/com/arjuna/ats/internal/jta/transaction/jts/TransactionImple.java	2008-05-28 11:49:36 UTC (rev 20191)
@@ -737,11 +737,36 @@
                             }
                         }
 
-						xaRes.start(xid, XAResource.TMNOFLAGS);
+                        // Pay attention now, this bit is hairy. We need to add a new XAResourceRecord
+                        // to the transaction, which will thereafter drive its completion. However, the transaction
+                        // core is not directly XA aware, so it's our job to start the XAResource. Problem is, if
+                        // adding the record fails, the tx will never end the resource via the XAResourceRecord,
+                        // so we must do so directly.  start may fail due to dupl xid or other reason, and transactions
+                        // may rollback async, for which reasons we can't call add before start.
+                        // The xid will change on each pass of the loop, so we need to create a new record on each pass.
+                        // The creation will fail in the case of multiple last resources being disallowed, in which
+                        // case we don't call start on the resource at all. see JBTM-362 and JBTM-363
+                        XAResourceRecord xaResourceRecord = createRecord(xaRes, params, xid);
+                        if(xaResourceRecord != null) {
+                            xaRes.start(xid, XAResource.TMNOFLAGS);
+                            try {
+                                RecoveryCoordinator recCoord = _theTransaction.registerResource(xaResourceRecord.getResource());
+                                xaResourceRecord.setRecoveryCoordinator(recCoord);
+                            } catch(Exception e) {
+                                // we called start on the resource, but _theTransaction did not accept it.
+                                // we therefore have a mess which we must now clean up by ensuring the start is undone:
+                                xaResourceRecord.rollback();
+                                markRollbackOnly();
+                                return false;
+                            }
+                            _resources.put(xaRes, new TxInfo(xid));
+                            return true; // dive out, no need to set associatedWork = true;
+                        }
 
-						associatedWork = true;
-
-						_resources.put(xaRes, new TxInfo(xid));
+                        // if we get to here, something other than a failure of xaRes.start probably went wrong.
+                        // so we don't loop and retry, we just give up.
+                        markRollbackOnly();
+                        return false;
 					}
 					catch (XAException e)
 					{
@@ -839,56 +864,8 @@
 				return true;
 			}
 
-			/*
-			 * Control and Coordinator should be set, or we would not have
-			 * gotten this far!
-			 */
-
-			final XAResourceRecord res ;
-                        if ((xaRes instanceof LastResourceCommitOptimisation) ||
-                                ((LAST_RESOURCE_OPTIMISATION_INTERFACE != null) && LAST_RESOURCE_OPTIMISATION_INTERFACE.isInstance(xaRes)))
-                        {
-                            if (lastResourceCount == 1)
-                            {
-                                if (jtaLogger.loggerI18N.isWarnEnabled())
-                                {
-                                    if (ALLOW_MULTIPLE_LAST_RESOURCES)
-                                    {
-                                        jtaLogger.loggerI18N.warn("com.arjuna.ats.internal.jta.transaction.jts.lastResource.multipleWarning", new Object[] {xaRes});
-                                    }
-                                    else
-                                    {
-                                        jtaLogger.loggerI18N.warn("com.arjuna.ats.internal.jta.transaction.jts.lastResource.disallow", new Object[] {xaRes});
-                                    }
-                                }
-                            }
-
-                            if ((lastResourceCount++ == 0) || ALLOW_MULTIPLE_LAST_RESOURCES)
-                            {
-                                res = new LastResourceRecord(this, xaRes, xid,
-                                        params) ;
-                            }
-                            else
-                            {
-                                markRollbackOnly() ;
-                                return false ;
-                            }
-                        }
-                        else
-                        {
-                            res = new XAResourceRecord(this, xaRes, xid,
-                                    params);
-                        }
-
-			RecoveryCoordinator recCoord = _theTransaction.registerResource(res.getResource());
-
-			//	    if (recCoord == null)
-			//		throw new BAD_OPERATION();
-
-			res.setRecoveryCoordinator(recCoord);
-
-			return true;
-		}
+            return false;
+        }
 		catch (Exception e)
 		{
 			/*
@@ -903,7 +880,63 @@
 		}
 	}
 
-	/*
+    /**
+     * Attempt to create an XAResourceRecord wrapping the given XAResource. Return null if this fails, or
+     * is diallowed by the current configuration of multiple last resource behaviour.
+     *
+     * @param xaRes
+     * @param params
+     * @param xid
+     * @return
+     */
+    private XAResourceRecord createRecord(XAResource xaRes, Object[] params, Xid xid)
+    {
+        final XAResourceRecord record;
+        if ((xaRes instanceof LastResourceCommitOptimisation)
+                || ((LAST_RESOURCE_OPTIMISATION_INTERFACE != null) && LAST_RESOURCE_OPTIMISATION_INTERFACE
+                .isInstance(xaRes)))
+        {
+            if (lastResourceCount == 1)
+            {
+                if (jtaLogger.loggerI18N.isWarnEnabled())
+                {
+                    if (ALLOW_MULTIPLE_LAST_RESOURCES)
+                    {
+                        jtaLogger.loggerI18N
+                                .warn(
+                                        "com.arjuna.ats.internal.jta.transaction.arjunacore.lastResource.multipleWarning",
+                                        new Object[]
+                                                { xaRes });
+                    }
+                    else
+                    {
+                        jtaLogger.loggerI18N
+                                .warn(
+                                        "com.arjuna.ats.internal.jta.transaction.arjunacore.lastResource.disallow",
+                                        new Object[]
+                                                { xaRes });
+                    }
+                }
+            }
+
+            if ((lastResourceCount++ == 0) || ALLOW_MULTIPLE_LAST_RESOURCES)
+            {
+                record = new LastResourceRecord(this, xaRes, xid, params);
+            }
+            else
+            {
+                record = null;
+            }
+        }
+        else
+        {
+            record = new XAResourceRecord(this, xaRes, xid, params);
+        }
+
+        return record;
+    }
+
+    /*
 	 * Do we have to unregister resources? Assume not as it would not make much
 	 * sense otherwise!
 	 */




More information about the jboss-svn-commits mailing list