List:Commits« Previous MessageNext Message »
From:mmatthews Date:June 29 2006 6:14pm
Subject:Connector/J commit: r5453 - in branches/branch_5_0/connector-j: . src/com/mysql/jdbc/jdbc2/optional src/testsuite/simple
View as plain text  
Modified:
   branches/branch_5_0/connector-j/CHANGES
  
branches/branch_5_0/connector-j/src/com/mysql/jdbc/jdbc2/optional/MysqlXAConnection.java
   branches/branch_5_0/connector-j/src/testsuite/simple/XATest.java
Log:
 MysqlXaConnection.recover(int flags) now allows combinations of 
	  XAResource.TMSTARTRSCAN and TMENDRSCAN. To simulate the "scanning"
	  nature of the interface, we return all prepared XIDs for TMSTARTRSCAN,
	  and no new XIDs for calls with TMNOFLAGS, or TMENDRSCAN when not in
	  combination with TMSTARTRSCAN. This change was made for API compliance,
	  as well as integration with IBM WebSphere's transaction manager.

Modified: branches/branch_5_0/connector-j/CHANGES
===================================================================
--- branches/branch_5_0/connector-j/CHANGES	2006-06-29 00:01:47 UTC (rev 5452)
+++ branches/branch_5_0/connector-j/CHANGES	2006-06-29 16:14:29 UTC (rev 5453)
@@ -33,6 +33,13 @@
 	  for a global transaction (most either always maintain thread affinity, 
 	  or have it as a configuration option).
 	  
+	- MysqlXaConnection.recover(int flags) now allows combinations of 
+	  XAResource.TMSTARTRSCAN and TMENDRSCAN. To simulate the "scanning"
+	  nature of the interface, we return all prepared XIDs for TMSTARTRSCAN,
+	  and no new XIDs for calls with TMNOFLAGS, or TMENDRSCAN when not in
+	  combination with TMSTARTRSCAN. This change was made for API compliance,
+	  as well as integration with IBM WebSphere's transaction manager.
+	  
 12-23-05 - Version 5.0.0-beta
 
     - XADataSource implemented (ported from 3.2 branch which won't be 

Modified:
branches/branch_5_0/connector-j/src/com/mysql/jdbc/jdbc2/optional/MysqlXAConnection.java
===================================================================
---
branches/branch_5_0/connector-j/src/com/mysql/jdbc/jdbc2/optional/MysqlXAConnection.java	2006-06-29
00:01:47 UTC (rev 5452)
+++
branches/branch_5_0/connector-j/src/com/mysql/jdbc/jdbc2/optional/MysqlXAConnection.java	2006-06-29
16:14:29 UTC (rev 5453)
@@ -173,11 +173,28 @@
 	}
 
 	/**
-	 * Obtains a list of prepared transaction branches from a resource manager.
-	 * The transaction manager calls this method during recovery to obtain the
-	 * list of transaction branches that are currently in prepared or
-	 * heuristically completed states.
+	 * This method is called to obtain a list of prepared transaction branches
+	 * from a resource manager. The transaction manager calls this method during
+	 * recovery to obtain the list of transaction branches that are currently in
+	 * prepared or heuristically completed states. 
 	 * 
+	 * The flag parameter indicates where the recover scan should start or end, 
+	 * or start and end. This method may be invoked one or more times during a 
+	 * recovery scan. The resource manager maintains a cursor which marks the 
+	 * current position of the prepared or heuristically completed transaction list. 
+	 * Each invocation of the recover method moves the cursor passed the set of Xids 
+	 * that are returned. 
+	 * 
+	 * Two consecutive invocation of this method that starts from the
+	 * beginning of the list must return the same list of transaction branches
+	 * unless one of the following takes place: 
+	 * 
+	 * - the transaction manager invokes the commit, forget, prepare, or rollback method for
that resource
+	 * manager, between the two consecutive invocation of the recovery scan. 
+	 * 
+	 * - the resource manager heuristically completes some transaction branches
+	 * between the two invocation of the recovery scan.
+	 * 
 	 * @param flag
 	 *            One of TMSTARTRSCAN, TMENDRSCAN, TMNOFLAGS. TMNOFLAGS must be
 	 *            used when no other flags are set in the parameter.
@@ -197,78 +214,111 @@
 	}
 	
 	protected static Xid[] recover(Connection c, int flag) throws XAException {
-		switch (flag) {
-		case TMSTARTRSCAN:
-		case TMENDRSCAN:
-		case TMNOFLAGS:
+		/*
+		    The XA RECOVER statement returns information for those XA transactions on the MySQL
server that are in the PREPARED state. (See Section 13.4.7.2,  
-			ResultSet rs = null;
-			Statement stmt = null;
-			
-			List recoveredXidList = new ArrayList();
+			XA RECOVER output rows look like this (for an example xid value consisting of the
parts 'abc', 'def', and 7):
 
-			try {
-				// TODO: Cache this for lifetime of XAConnection
-				stmt = c.createStatement();
-								
-				rs = stmt.executeQuery("XA RECOVER");
+			mysql> XA RECOVER;
+			+----------+--------------+--------------+--------+
+			| formatID | gtrid_length | bqual_length | data   |
+			+----------+--------------+--------------+--------+
+			|        7 |            3 |            3 | abcdef |
+			+----------+--------------+--------------+--------+
 
-				// Result is formatId (int), length_gtrid, length_bqual,
-				// byte[] of gtrid + bqual
-				while (rs.next()) {
-					final int formatId = rs.getInt(1);
-					int gtridLength = rs.getInt(2);
-					int bqualLength = rs.getInt(3);
-					byte[] gtridAndBqual = rs.getBytes(4);
+			The output columns have the following meanings:
 
-					final byte[] gtrid = new byte[gtridLength];
-					final byte[] bqual = new byte[bqualLength];
+      			formatID is the formatID part of the transaction xid
+			    gtrid_length is the length in bytes of the gtrid part of the xid
+			    bqual_length is the length in bytes of the bqual part of the xid
+ 			    data is the concatenation of the gtrid and bqual parts of the xid
+		 */
+		
+		boolean startRscan = ((flag & TMSTARTRSCAN) > 0);
+		boolean endRscan = ((flag & TMENDRSCAN) > 0);
+		
+		if (!startRscan && !endRscan && flag != TMNOFLAGS) {
+			throw new MysqlXAException(XAException.XAER_INVAL, 
+					"Invalid flag, must use TMNOFLAGS, or any combination of TMSTARTRSCAN and
TMENDRSCAN",
+					null);
+		}
 
-					if (gtridAndBqual.length != (gtridLength + bqualLength)) {
-						// assert?
-					}
+		//
+		// We return all recovered XIDs at once, so if not 
+		// TMSTARTRSCAN, return no new XIDs
+		//
+		// We don't attempt to maintain state to check for TMNOFLAGS
+		// "outside" of a scan
+		//
+		
+		if (!startRscan) {
+			return new Xid[0];
+		}
+		
+		ResultSet rs = null;
+		Statement stmt = null;
 
-					System.arraycopy(gtridAndBqual, 0, gtrid, 0,
-							gtridLength);
-					System.arraycopy(gtridAndBqual, gtridLength, bqual, 0,
-							bqualLength);
+		List recoveredXidList = new ArrayList();
 
-					recoveredXidList.add(new MysqlXid(gtrid, bqual, 
-							formatId));
+		try {
+			// TODO: Cache this for lifetime of XAConnection
+			stmt = c.createStatement();
+
+			rs = stmt.executeQuery("XA RECOVER");
+
+			while (rs.next()) {
+				final int formatId = rs.getInt(1);
+				int gtridLength = rs.getInt(2);
+				int bqualLength = rs.getInt(3);
+				byte[] gtridAndBqual = rs.getBytes(4);
+
+				final byte[] gtrid = new byte[gtridLength];
+				final byte[] bqual = new byte[bqualLength];
+
+				if (gtridAndBqual.length != (gtridLength + bqualLength)) {
+					throw new MysqlXAException(XAException.XA_RBPROTO,
+							"Error while recovering XIDs from RM. GTRID and BQUAL are wrong sizes", 
+							null);
 				}
-			} catch (SQLException sqlEx) {
-				throw mapXAExceptionFromSQLException(sqlEx);
-			} finally {
-				if (rs != null) {
-					try {
-						rs.close();
-					} catch (SQLException sqlEx) {
-						throw mapXAExceptionFromSQLException(sqlEx);
-					}
+
+				System.arraycopy(gtridAndBqual, 0, gtrid, 0,
+						gtridLength);
+				System.arraycopy(gtridAndBqual, gtridLength, bqual, 0,
+						bqualLength);
+
+				recoveredXidList.add(new MysqlXid(gtrid, bqual, 
+						formatId));
+			}
+		} catch (SQLException sqlEx) {
+			throw mapXAExceptionFromSQLException(sqlEx);
+		} finally {
+			if (rs != null) {
+				try {
+					rs.close();
+				} catch (SQLException sqlEx) {
+					throw mapXAExceptionFromSQLException(sqlEx);
 				}
-				
-				if (stmt != null) {
-					try {
-						stmt.close();
-					} catch (SQLException sqlEx) {
-						throw mapXAExceptionFromSQLException(sqlEx);
-					}
+			}
+
+			if (stmt != null) {
+				try {
+					stmt.close();
+				} catch (SQLException sqlEx) {
+					throw mapXAExceptionFromSQLException(sqlEx);
 				}
 			}
+		}
 
-			int numXids = recoveredXidList.size();
+		int numXids = recoveredXidList.size();
 
-			Xid[] asXids = new Xid[numXids];
-			Object[] asObjects = recoveredXidList.toArray();
+		Xid[] asXids = new Xid[numXids];
+		Object[] asObjects = recoveredXidList.toArray();
 
-			for (int i = 0; i < numXids; i++) {
-				asXids[i] = (Xid) asObjects[i];
-			}
+		for (int i = 0; i < numXids; i++) {
+			asXids[i] = (Xid) asObjects[i];
+		}
 
-			return asXids;
-		default:
-			throw new XAException(XAException.XAER_INVAL);
-		}
+		return asXids;
 	}
 
 	/**

Modified: branches/branch_5_0/connector-j/src/testsuite/simple/XATest.java
===================================================================
--- branches/branch_5_0/connector-j/src/testsuite/simple/XATest.java	2006-06-29 00:01:47
UTC (rev 5452)
+++ branches/branch_5_0/connector-j/src/testsuite/simple/XATest.java	2006-06-29 16:14:29
UTC (rev 5453)
@@ -32,6 +32,7 @@
 import java.sql.Savepoint;
 
 import javax.sql.XAConnection;
+import javax.transaction.xa.XAException;
 import javax.transaction.xa.XAResource;
 import javax.transaction.xa.Xid;
 
@@ -193,7 +194,7 @@
 			
 			XAResource recoverRes = recoverConn.getXAResource();
 			
-			Xid[] recoveredXids = recoverRes.recover(XAResource.TMNOFLAGS);
+			Xid[] recoveredXids = recoverRes.recover(XAResource.TMSTARTRSCAN |
XAResource.TMENDRSCAN);
 			
 			assertTrue(recoveredXids != null);
 			assertTrue(recoveredXids.length > 0);
@@ -210,6 +211,39 @@
 			}
 			
 			assertTrue(xidFound);
+
+			recoverRes = recoverConn.getXAResource();
+
+			recoveredXids = recoverRes.recover(XAResource.TMSTARTRSCAN);
+
+			assertTrue(recoveredXids != null);
+			assertTrue(recoveredXids.length > 0);
+
+			xidFound = false;
+
+			for (int i = 0; i < recoveredXids.length; i++) {
+				if (recoveredXids[i] != null &&
+						recoveredXids[i].equals(xid)) {
+					xidFound = true;
+
+					break;
+				}
+			}
+
+			assertTrue(xidFound);
+				
+			// Test flags
+			recoverRes.recover(XAResource.TMSTARTRSCAN);
+			recoverRes.recover(XAResource.TMENDRSCAN);
+			recoverRes.recover(XAResource.TMSTARTRSCAN | XAResource.TMENDRSCAN);
+			
+			// This should fail
+			try {
+				recoverRes.recover(XAResource.TMSUCCESS);
+				fail("XAException should have been thrown");
+			} catch (XAException xaEx) {
+				assertEquals(XAException.XAER_INVAL, xaEx.errorCode);
+			}
 		} finally {
 			if (xaConn != null) {
 				xaConn.close();

Thread
Connector/J commit: r5453 - in branches/branch_5_0/connector-j: . src/com/mysql/jdbc/jdbc2/optional src/testsuite/simplemmatthews29 Jun