[jboss-svn-commits] JBL Code SVN: r21343 - in labs/jbosstm/trunk/XTS: WS-T/dev/src10/com/arjuna/wst/messaging/engines and 5 other directories.

jboss-svn-commits at lists.jboss.org jboss-svn-commits at lists.jboss.org
Mon Aug 4 11:51:05 EDT 2008


Author: adinn
Date: 2008-08-04 11:51:05 -0400 (Mon, 04 Aug 2008)
New Revision: 21343

Modified:
   labs/jbosstm/trunk/XTS/WS-T/dev/src/org/jboss/jbossts/xts/recovery/participant/at/ATParticipantRecoveryRecord.java
   labs/jbosstm/trunk/XTS/WS-T/dev/src10/com/arjuna/wst/messaging/engines/CoordinatorEngine.java
   labs/jbosstm/trunk/XTS/WS-T/dev/src10/com/arjuna/wst/stub/ParticipantStub.java
   labs/jbosstm/trunk/XTS/WS-T/dev/src11/com/arjuna/wst11/messaging/engines/CoordinatorEngine.java
   labs/jbosstm/trunk/XTS/WS-T/dev/src11/com/arjuna/wst11/stub/ParticipantStub.java
   labs/jbosstm/trunk/XTS/WSCF/classes/com/arjuna/mwlabs/wscf/model/twophase/arjunacore/ParticipantRecord.java
   labs/jbosstm/trunk/XTS/WSTX/classes/com/arjuna/mwlabs/wst/at/participants/DurableTwoPhaseCommitParticipant.java
Log:
patches to recovery code to fix errors in handling of comms timeouts on coordinator side during prepare and commit identified by WSTF interop tests - part fix for JBTM-121

Modified: labs/jbosstm/trunk/XTS/WS-T/dev/src/org/jboss/jbossts/xts/recovery/participant/at/ATParticipantRecoveryRecord.java
===================================================================
--- labs/jbosstm/trunk/XTS/WS-T/dev/src/org/jboss/jbossts/xts/recovery/participant/at/ATParticipantRecoveryRecord.java	2008-08-04 15:35:11 UTC (rev 21342)
+++ labs/jbosstm/trunk/XTS/WS-T/dev/src/org/jboss/jbossts/xts/recovery/participant/at/ATParticipantRecoveryRecord.java	2008-08-04 15:51:05 UTC (rev 21343)
@@ -47,23 +47,30 @@
         try {
             useSerialization = ATParticipantHelper.isSerializable(participant);
             recoveryState = ATParticipantHelper.getRecoveryState(useSerialization, participant);
+            recoveryStateValid = true;
         } catch (Exception exception) {
             if (WSTLogger.arjLoggerI18N.isWarnEnabled())
             {
                 WSTLogger.arjLoggerI18N.warn("org.jboss.transactions.xts.recovery.participant.at.ATParticipantRecoveryRecord.saveState_1", new Object[] {id}) ;
             }
-            return false;
+            // if we continue here then we cannot recover this transaction if we crash during
+            // commit processing. we should strictly fail here to play safe but . . .
+
+            recoveryStateValid = false;
         }
 
         try {
             oos.packString(id);
             saveEndpointReference(oos);
+            oos.packBoolean(recoveryStateValid);
+            if (recoveryStateValid) {
             oos.packBoolean(useSerialization);
-            if (recoveryState != null) {
-                oos.packBoolean(true);
-                oos.packBytes(recoveryState);
-            } else {
-                oos.packBoolean(false);
+                if (recoveryState != null) {
+                    oos.packBoolean(true);
+                    oos.packBytes(recoveryState);
+                } else {
+                    oos.packBoolean(false);
+                }
             }
         } catch (XMLStreamException xmle) {
             if (WSTLogger.arjLoggerI18N.isWarnEnabled())
@@ -95,13 +102,15 @@
         try {
             id = ios.unpackString();
             restoreEndpointReference(ios);
-            useSerialization = ios.unpackBoolean();
-            if (ios.unpackBoolean()) {
-                recoveryState = ios.unpackBytes();
-            } else {
-                recoveryState =  null;
+            recoveryStateValid = ios.unpackBoolean();
+            if (recoveryStateValid) {
+                useSerialization = ios.unpackBoolean();
+                if (ios.unpackBoolean()) {
+                    recoveryState = ios.unpackBytes();
+                } else {
+                    recoveryState =  null;
+                }
             }
-            recoveryStateValid = true;
         } catch (XMLStreamException xmle) {
             if (WSTLogger.arjLoggerI18N.isWarnEnabled())
             {
@@ -124,6 +133,7 @@
      * specific recovery state back into a participant
      * @param module the XTS recovery module to be used to attempt the conversion
      * @return
+     * @message org.jboss.transactions.xts.recovery.participant.at.ATParticipantRecoveryRecord.restoreParticipant_1 [org.jboss.transactions.xts.recovery.participant.at.ATParticipantRecoveryRecord.restoreParticipant_1] participant {0} has no saved recovery state to recover   
      */
 
     public boolean restoreParticipant(XTSATRecoveryModule module) throws Exception
@@ -133,19 +143,28 @@
             return false;
         }
 
-        if (useSerialization) {
-            final ByteArrayInputStream bais = new ByteArrayInputStream(recoveryState) ;
-            final ObjectInputStream ois = new ObjectInputStream(bais) ;
+        if (recoveryStateValid) {
+            if (useSerialization) {
+                final ByteArrayInputStream bais = new ByteArrayInputStream(recoveryState) ;
+                final ObjectInputStream ois = new ObjectInputStream(bais) ;
 
-            participant = module.deserialize(getId(), ois);
+                participant = module.deserialize(getId(), ois);
+            } else {
+                participant = module.recreate(getId(), recoveryState);
+            }
+
+            if (participant != null) {
+                return true;
+            }
         } else {
-            participant = module.recreate(getId(), recoveryState);
-        }
+            // the original participant did not provide a way to save its state so
+            // throw an exception to notify this
 
-        if (participant != null) {
-            return true;
+            String mesg = WSTLogger.arjLoggerI18N.getString("org.jboss.transactions.xts.recovery.participant.at.ATParticipantRecoveryRecord.restoreParticipant_1", id);
+
+            throw new Exception(mesg);
         }
-
+        
         return false;
     }
 

Modified: labs/jbosstm/trunk/XTS/WS-T/dev/src10/com/arjuna/wst/messaging/engines/CoordinatorEngine.java
===================================================================
--- labs/jbosstm/trunk/XTS/WS-T/dev/src10/com/arjuna/wst/messaging/engines/CoordinatorEngine.java	2008-08-04 15:35:11 UTC (rev 21342)
+++ labs/jbosstm/trunk/XTS/WS-T/dev/src10/com/arjuna/wst/messaging/engines/CoordinatorEngine.java	2008-08-04 15:51:05 UTC (rev 21343)
@@ -346,13 +346,9 @@
                 timerTask = null;
             }
 
-            // ok, the coordinator is going to start a rollback because of this timeout but it will
-            // only roll back the participants which have been prepared or have not yet been processed.
-            // we need to deactivate the participant here so that any later prepared messages are
-            // answered with a rollback (presumed abort)
+            // ok, we leave the participant stub active because the coordinator will attempt
+            // to roll it back when it notices that this has failed
 
-            CoordinatorProcessor.getProcessor().deactivateCoordinator(this);
-
             return state ;
         }
     }

Modified: labs/jbosstm/trunk/XTS/WS-T/dev/src10/com/arjuna/wst/stub/ParticipantStub.java
===================================================================
--- labs/jbosstm/trunk/XTS/WS-T/dev/src10/com/arjuna/wst/stub/ParticipantStub.java	2008-08-04 15:35:11 UTC (rev 21342)
+++ labs/jbosstm/trunk/XTS/WS-T/dev/src10/com/arjuna/wst/stub/ParticipantStub.java	2008-08-04 15:51:05 UTC (rev 21343)
@@ -103,7 +103,11 @@
         }
         else if (state == State.STATE_PREPARING)
         {
-            throw new SystemException() ;
+            // typically means no response from the remote end.
+            // throw a comm exception to distinguish this case from the
+            // one where the remote end itself threw a SystemException.
+
+            throw new SystemCommunicationException() ;
         }
         else
         {

Modified: labs/jbosstm/trunk/XTS/WS-T/dev/src11/com/arjuna/wst11/messaging/engines/CoordinatorEngine.java
===================================================================
--- labs/jbosstm/trunk/XTS/WS-T/dev/src11/com/arjuna/wst11/messaging/engines/CoordinatorEngine.java	2008-08-04 15:35:11 UTC (rev 21342)
+++ labs/jbosstm/trunk/XTS/WS-T/dev/src11/com/arjuna/wst11/messaging/engines/CoordinatorEngine.java	2008-08-04 15:51:05 UTC (rev 21343)
@@ -288,13 +288,9 @@
                 timerTask = null;
             }
 
-            // ok, the coordinator is going to start a rollback because of this timeout but it will
-            // only roll back the participants which have been prepared or have not yet been processed.
-            // we need to deactivate the participant here so that any later prepared messages are
-            // answered with a rollback (presumed abort)
+            // ok, we leave the participant stub active because the coordinator will attempt
+            // to roll it back when it notices that this has failed
 
-            CoordinatorProcessor.getProcessor().deactivateCoordinator(this);
-            
             return state ;
         }
     }

Modified: labs/jbosstm/trunk/XTS/WS-T/dev/src11/com/arjuna/wst11/stub/ParticipantStub.java
===================================================================
--- labs/jbosstm/trunk/XTS/WS-T/dev/src11/com/arjuna/wst11/stub/ParticipantStub.java	2008-08-04 15:35:11 UTC (rev 21342)
+++ labs/jbosstm/trunk/XTS/WS-T/dev/src11/com/arjuna/wst11/stub/ParticipantStub.java	2008-08-04 15:51:05 UTC (rev 21343)
@@ -70,7 +70,11 @@
         }
         else if (state == State.STATE_PREPARING)
         {
-            throw new SystemException() ;
+            // typically means no response from the remote end.
+            // throw a comm exception to distinguish this case from the
+            // one where the remote end itself threw a SystemException.
+
+            throw new SystemCommunicationException() ;
         }
         else
         {
@@ -124,7 +128,7 @@
         {
             if (state == State.STATE_ABORTING)
             {
-                throw new SystemException() ;
+                throw new SystemCommunicationException() ;
             }
             else
             {

Modified: labs/jbosstm/trunk/XTS/WSCF/classes/com/arjuna/mwlabs/wscf/model/twophase/arjunacore/ParticipantRecord.java
===================================================================
--- labs/jbosstm/trunk/XTS/WSCF/classes/com/arjuna/mwlabs/wscf/model/twophase/arjunacore/ParticipantRecord.java	2008-08-04 15:35:11 UTC (rev 21342)
+++ labs/jbosstm/trunk/XTS/WSCF/classes/com/arjuna/mwlabs/wscf/model/twophase/arjunacore/ParticipantRecord.java	2008-08-04 15:51:05 UTC (rev 21343)
@@ -421,6 +421,12 @@
 				{
 					return TwoPhaseOutcome.HEURISTIC_MIXED;
 				}
+                catch(SystemCommunicationException ex)
+                {
+                    // if prepare timed out then we return error so it goes back on the
+                    // prepare list and is rolled back
+                    return TwoPhaseOutcome.FINISH_ERROR;
+                }
 				catch (SystemException ex)
 				{
 					return TwoPhaseOutcome.HEURISTIC_HAZARD;

Modified: labs/jbosstm/trunk/XTS/WSTX/classes/com/arjuna/mwlabs/wst/at/participants/DurableTwoPhaseCommitParticipant.java
===================================================================
--- labs/jbosstm/trunk/XTS/WSTX/classes/com/arjuna/mwlabs/wst/at/participants/DurableTwoPhaseCommitParticipant.java	2008-08-04 15:35:11 UTC (rev 21342)
+++ labs/jbosstm/trunk/XTS/WSTX/classes/com/arjuna/mwlabs/wst/at/participants/DurableTwoPhaseCommitParticipant.java	2008-08-04 15:51:05 UTC (rev 21343)
@@ -44,6 +44,7 @@
 import com.arjuna.mw.wsas.exceptions.SystemException;
 import com.arjuna.mw.wsas.exceptions.WrongStateException;
 import com.arjuna.mw.wsas.exceptions.SystemCommunicationException;
+import com.arjuna.mw.wstx.logging.wstxLogger;
 import com.arjuna.mwlabs.wst.util.PersistableParticipantHelper;
 
 /**
@@ -65,7 +66,14 @@
 		_id = identifier;
 	}
 
-	public Vote prepare () throws InvalidParticipantException,
+    /**
+     * tell the participant to prepare
+     *
+     * @return the participant's vote or a cancel vote the aprticipant is null
+     *
+     * @message com.arjuna.mwlabs.wst.at.participants.DurableTwoPhaseCommitParticipant.prepare_1 [com.arjuna.mwlabs.wst.at.participants.DurableTwoPhaseCommitParticipant.prepare_1] comms timeout attempting to prepare WS-AT participant {0}
+     */
+    public Vote prepare () throws InvalidParticipantException,
 			WrongStateException, HeuristicHazardException,
 			HeuristicMixedException, SystemException
 	{
@@ -110,11 +118,25 @@
 		//	catch (com.arjuna.mw.wst.exceptions.SystemException ex)
 		catch (com.arjuna.wst.SystemException ex)
 		{
+            if(ex instanceof com.arjuna.wst.stub.SystemCommunicationException) {
+                // log an error here or else the participant may be left hanging
+                // waiting for a prepare
+                if (wstxLogger.arjLoggerI18N.isErrorEnabled()) {
+                    wstxLogger.arjLoggerI18N.error("com.arjuna.mwlabs.wst.at.participants.DurableTwoPhaseCommitParticipant.prepare_1", new Object[] { _id });
+                }
+                throw new SystemCommunicationException(ex.toString());
+            } else {
 			throw new SystemException(ex.toString());
-		}
+            }
+        }
 	}
 
-	public void confirm () throws InvalidParticipantException,
+    /**
+     * attempt to commit the participant
+     *
+     * @message com.arjuna.mwlabs.wst.at.participants.DurableTwoPhaseCommitParticipant.confirm_1 [com.arjuna.mwlabs.wst.at.participants.DurableTwoPhaseCommitParticipant.confirm_1] comms timeout attempting to commit WS-AT participant {0}
+     */
+    public void confirm () throws InvalidParticipantException,
 			WrongStateException, HeuristicHazardException,
 			HeuristicMixedException, HeuristicCancelException, SystemException
 	{
@@ -144,6 +166,10 @@
 			catch (com.arjuna.wst.SystemException ex)
 			{
 				if(ex instanceof com.arjuna.wst.stub.SystemCommunicationException) {
+                    // log an error here -- we will end up writing a heuristic transaction record too
+                    if (wstxLogger.arjLoggerI18N.isErrorEnabled()) {
+                        wstxLogger.arjLoggerI18N.error("com.arjuna.mwlabs.wst.at.participants.DurableTwoPhaseCommitParticipant.confirm_1", new Object[] { _id });
+                    }
                     throw new SystemCommunicationException(ex.toString());
                 } else {
                     throw new SystemException(ex.toString());
@@ -154,6 +180,11 @@
 			throw new InvalidParticipantException();
 	}
 
+    /**
+     * attempt to cancel the participant
+     *
+     * @message com.arjuna.mwlabs.wst.at.participants.DurableTwoPhaseCommitParticipant.cancel_1 [com.arjuna.mwlabs.wst.at.participants.DurableTwoPhaseCommitParticipant.cancel_1] comms timeout attempting to cancel WS-AT participant {0}
+     */
 	public void cancel () throws InvalidParticipantException,
 			WrongStateException, HeuristicHazardException,
 			HeuristicMixedException, HeuristicConfirmException, SystemException
@@ -181,7 +212,15 @@
 			//	    catch (com.arjuna.mw.wst.exceptions.SystemException ex)
 			catch (com.arjuna.wst.SystemException ex)
 			{
-				throw new SystemException(ex.toString());
+                if(ex instanceof com.arjuna.wst.stub.SystemCommunicationException) {
+                    // log an error here -- if the participant is dead it will retry anyway
+                    if (wstxLogger.arjLoggerI18N.isErrorEnabled()) {
+                        wstxLogger.arjLoggerI18N.error("com.arjuna.mwlabs.wst.at.participants.DurableTwoPhaseCommitParticipant.cancel_1", new Object[] { _id });
+                    }
+                    throw new SystemCommunicationException(ex.toString());
+                } else {
+                    throw new SystemException(ex.toString());
+                }
 			}
 		}
 		else
@@ -190,7 +229,7 @@
 
 	// TODO mark ParticipantCancelledException explicitly?
 
-	public void confirmOnePhase () throws InvalidParticipantException,
+    public void confirmOnePhase () throws InvalidParticipantException,
 			WrongStateException, HeuristicHazardException,
 			HeuristicMixedException, HeuristicCancelException, SystemException
 	{
@@ -202,9 +241,12 @@
 			{
 				v = prepare();
 			}
-			catch (Exception ex)
+            catch (Exception ex)
 			{
-				ex.printStackTrace();
+                // either the prepare timed out or the participant was invalid or in an
+                // invalid state
+                
+                ex.printStackTrace();
 
 				v = new VoteCancel();
 			}
@@ -217,11 +259,15 @@
 			{
 				_rolledback = false;
 
-				// TODO only do this if we didn't return VoteCancel
+                // TODO only do this if we didn't return VoteCancel
 
-				cancel();
-
-				throw new ParticipantCancelledException();
+                try {
+                    cancel();
+                } catch (SystemCommunicationException sce) {
+                    // if the rollback times out as well as the prepare we
+                    // return an exception which indicates a failed transaction
+                }
+                throw new ParticipantCancelledException();
 			}
 			else
 			{




More information about the jboss-svn-commits mailing list