You are viewing a plain text version of this content. The canonical link for it is here.
Posted to derby-commits@db.apache.org by km...@apache.org on 2005/06/03 21:35:34 UTC

svn commit: r179867 - in /incubator/derby/code/trunk/java: client/org/apache/derby/client/am/ client/org/apache/derby/client/net/ drda/org/apache/derby/impl/drda/ testing/org/apache/derbyTesting/functionTests/master/DerbyNetClient/ testing/org/apache/derbyTesting/functionTests/tests/derbynet/ testing/org/apache/derbyTesting/functionTests/tests/jdbcapi/

Author: kmarsden
Date: Fri Jun  3 12:35:33 2005
New Revision: 179867

URL: http://svn.apache.org/viewcvs?rev=179867&view=rev
Log:
XA end() fails with Connection is closed error

For the client there were multiple problems associated with the tracking
of XA_STATE in the client. The approach for this patch is to remove as
much of the client state as possible.

This patch removes all the client XA state except for
    XA_GLOBAL - In an active global transaction 
    XA_LOCAL - No active global transaction.

For Network Server there was a bug that the connection was not being
reset properly when a connection
reset request came from the client. Changed it so that if an ACCRDB
is sent and a connection has already been established it will reset.



Modified:
    incubator/derby/code/trunk/java/client/org/apache/derby/client/am/Connection.java
    incubator/derby/code/trunk/java/client/org/apache/derby/client/am/Statement.java
    incubator/derby/code/trunk/java/client/org/apache/derby/client/net/NetConnection.java
    incubator/derby/code/trunk/java/client/org/apache/derby/client/net/NetXACallInfo.java
    incubator/derby/code/trunk/java/client/org/apache/derby/client/net/NetXAConnection.java
    incubator/derby/code/trunk/java/client/org/apache/derby/client/net/NetXAResource.java
    incubator/derby/code/trunk/java/drda/org/apache/derby/impl/drda/XADatabase.java
    incubator/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/master/DerbyNetClient/netxaPositive.out
    incubator/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/derbynet/netxaPositive.sql
    incubator/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/jdbcapi/resultset.java

Modified: incubator/derby/code/trunk/java/client/org/apache/derby/client/am/Connection.java
URL: http://svn.apache.org/viewcvs/incubator/derby/code/trunk/java/client/org/apache/derby/client/am/Connection.java?rev=179867&r1=179866&r2=179867&view=diff
==============================================================================
--- incubator/derby/code/trunk/java/client/org/apache/derby/client/am/Connection.java (original)
+++ incubator/derby/code/trunk/java/client/org/apache/derby/client/am/Connection.java Fri Jun  3 12:35:33 2005
@@ -85,28 +85,13 @@
     protected boolean isXAConnection_ = false; // Indicates an XA connection
 
     // XA States
-    public static final int XA_OPEN_IDLE = 0;
-    public static final int XA_LOCAL = 1; // local transaction started by DNC
-    public static final int XA_LOCAL_CCC = 2; // local transaction started by CCC
-    public static final int XA_ACTIVE = 3;
-    public static final int XA_ENDED = 4;
-    public static final int XA_HEUR_COMP = 5;
-    public static final int XA_SUSPENDED = 6;
-    public static final int XA_PREPARED = 7;
-    public static final int XA_ROLLBACK = 8;
-    public static final int XA_LOCAL_START_SENT = 9;
-    public static final int XA_UNKNOWN = 10;
-    public static final int XA_GLOBAL_START_SENT = 11;
-    public static final int XA_PENDING_END = 12;
-    public static final int XA_RBATHER = 13;
-    public static final int XA_RECOVER = 14;
-    public static final int XA_EMPTY_TRANSACTION = 15;
-    public static final int XA_RBROLLBACK = 16;
-    public static final int XA_PENDING_START = 17;
-    public static final int XA_EMPTY_SUSPENDED = 18;
+    public static final int XA_LOCAL = 0;   //  No global transaction in process
+    public static final int XA_GLOBAL = 1;  // Global transaction in process
+    //TODO: Remove entirely once indoubtlist is gone.  
+    //public static final int XA_RECOVER = 14;
 
 
-    protected int xaState_ = XA_OPEN_IDLE;
+    protected int xaState_ = XA_LOCAL;
 
     // XA Host Type
     public int xaHostVersion_ = 0;
@@ -231,10 +216,7 @@
             dataSource_ = ds;
         }
 
-        // property isXAConnection_
-        // leave set to current value.  this will impact which connect reset flows are used.
-
-        xaState_ = XA_OPEN_IDLE;
+        
         if (recomputeFromDataSource) {
             this.agent_.resetAgent(this, logWriter, loginTimeout_, serverNameIP_, portNumber_);
         }
@@ -265,11 +247,6 @@
         autoCommit_ = true;
         inUnitOfWork_ = false;
 
-        // property isXAConnection_
-        // leave set to current value.  this will impact which connect reset flows are used.
-
-        xaState_ = XA_OPEN_IDLE;
-
         this.agent_.resetAgent(this, logWriter, loginTimeout_, serverNameIP_, portNumber_);
 
     }
@@ -431,7 +408,7 @@
 
     // Driver-specific determination if local COMMIT/ROLLBACK is allowed;
     // primary usage is distinction between local and global trans. envs.;
-    protected abstract boolean disallowLocalCommitRollback_() throws org.apache.derby.client.am.SqlException;
+    protected abstract boolean allowLocalCommitRollback_() throws org.apache.derby.client.am.SqlException;
 
     synchronized public void setAutoCommit(boolean autoCommit) throws SqlException {
         if (agent_.loggingEnabled()) {
@@ -439,7 +416,7 @@
         }
         checkForClosedConnection();
 
-        if (disallowLocalCommitRollback_()) {
+        if (! allowLocalCommitRollback_()) {
             if (autoCommit) { // can't toggle to autocommit mode when between xars.start() and xars.end()
                 throw new SqlException(agent_.logWriter_,
                         "setAutoCommit(true) invalid during global transaction",
@@ -462,7 +439,7 @@
         if (agent_.loggingEnabled()) {
             agent_.logWriter_.traceExit(this, "getAutoCommit", autoCommit_);
         }
-        if (disallowLocalCommitRollback_()) { // autoCommit is always false between xars.start() and xars.end()
+        if (! allowLocalCommitRollback_()) { // autoCommit is always false between xars.start() and xars.end()
             return false;
         }
         return autoCommit_;
@@ -484,7 +461,7 @@
     }
 
     private void checkForInvalidXAStateOnCommitOrRollback() throws SqlException {
-        if (disallowLocalCommitRollback_()) {
+        if (! allowLocalCommitRollback_()) {
             throw new SqlException(agent_.logWriter_,
                     "COMMIT or ROLLBACK invalid for application execution environment",
                     SqlState._2D521, // Spec'ed by PROTOCOL
@@ -532,7 +509,7 @@
         if (!autoCommit_) {
             return false;
         }
-        if (disallowLocalCommitRollback_()) {
+        if (! allowLocalCommitRollback_()) {
             return false;
         }
         return true;
@@ -547,8 +524,7 @@
 
     public void writeCommit() throws SqlException {
         if (isXAConnection_) {
-            if ((xaState_ == XA_LOCAL) ||
-                    (xaState_ == XA_LOCAL_START_SENT)) {
+            if ((xaState_ == XA_LOCAL) ) {
                 writeLocalXACommit_();
             }
         } else {
@@ -565,10 +541,8 @@
 
     public void readCommit() throws SqlException {
         if (isXAConnection_) {
-            if ((xaState_ == XA_LOCAL) ||
-                    (xaState_ == XA_LOCAL_START_SENT)) {
-                readLocalXACommit_();
-                setXAState(XA_OPEN_IDLE);
+            if ((xaState_ == XA_LOCAL) ) {
+                readLocalXACommit_();               
             }
         } else {
             readLocalCommit_();
@@ -627,7 +601,6 @@
     public void readRollback() throws SqlException {
         if (isXAConnection_) {
             readLocalXARollback_();
-            setXAState(XA_OPEN_IDLE);
         } else {
             readLocalRollback_();
         }
@@ -700,7 +673,6 @@
         if (!open_) {
             return;
         }
-        checkForTransactionInProgress();
         resetConnectionAtFirstSql_ = false; // unset indicator of deferred reset
         SqlException accumulatedExceptions = null;
         try {
@@ -772,7 +744,16 @@
         }
     }
 
+   /**
+    * 	Return true if the physical connection is still open.
+    * 	Might be logically closed but available for reuse.
+    *   @return true if physical connection still open
+    */
+    public boolean isPhysicallyClosed() {
+    return !open_ && !availableForReuse_; 
+   }
 
+   
     public boolean isClosed() {
         if (agent_.loggingEnabled()) {
             agent_.logWriter_.traceExit(this, "isClosed", !open_);
@@ -780,6 +761,7 @@
         return !open_;
     }
 
+   
     public boolean isClosedX() {
         return !open_;
     }
@@ -1037,11 +1019,7 @@
         if (autoCommit_) // Throw exception if auto-commit is on
         {
             throw new SqlException(agent_.logWriter_, "Cannot set savepoint when in auto-commit mode.");
-        } else if (xaState_ == XA_PENDING_START ||
-                xaState_ == XA_ACTIVE) // Throw exception if in distributed transaction
-        {
-            throw new SqlException(agent_.logWriter_, "Cannot set savepoint during distributed transaction.");
-        }
+        } 
         // create an un-named savepoint.
         if ((++dncGeneratedSavepointId_) < 0) {
             dncGeneratedSavepointId_ = 1; // restart from 1 when overflow.
@@ -1061,10 +1039,6 @@
         } else if (autoCommit_) // Throw exception if auto-commit is on
         {
             throw new SqlException(agent_.logWriter_, "Cannot set savepoint when in auto-commit mode.");
-        } else if (xaState_ == XA_PENDING_START ||
-                xaState_ == XA_ACTIVE) // Throw exception if in distributed transaction
-        {
-            throw new SqlException(agent_.logWriter_, "Cannot set savepoint during distributed transaction.");
         }
         // create a named savepoint.
         Object s = setSavepointX(new Savepoint(agent_, name));
@@ -1112,11 +1086,7 @@
         } else if (autoCommit_) // Throw exception if auto-commit is on
         {
             throw new SqlException(agent_.logWriter_, "Cannot rollback to a savepoint when in auto-commit mode.");
-        } else if (xaState_ == XA_PENDING_START ||
-                xaState_ == XA_ACTIVE) // Throw exception if in distributed transaction
-        {
-            throw new SqlException(agent_.logWriter_, "Cannot rollback to a savepoint during distributed transaction.");
-        }
+        } 
         // Only allow to rollback to a savepoint from the connection that create the savepoint.
         try {
             if (this != ((Savepoint) savepoint).agent_.connection_) {
@@ -1167,11 +1137,7 @@
         } else if (autoCommit_) // Throw exception if auto-commit is on
         {
             throw new SqlException(agent_.logWriter_, "Cannot release a savepoint when in auto-commit mode.");
-        } else if (xaState_ == XA_PENDING_START ||
-                xaState_ == XA_ACTIVE) // Throw exception if in distributed transaction
-        {
-            throw new SqlException(agent_.logWriter_, "Cannot release a savepoint during distributed transaction.");
-        }
+        } 
         // Only allow to release a savepoint from the connection that create the savepoint.
         try {
             if (this != ((Savepoint) savepoint).agent_.connection_) {

Modified: incubator/derby/code/trunk/java/client/org/apache/derby/client/am/Statement.java
URL: http://svn.apache.org/viewcvs/incubator/derby/code/trunk/java/client/org/apache/derby/client/am/Statement.java?rev=179867&r1=179866&r2=179867&view=diff
==============================================================================
--- incubator/derby/code/trunk/java/client/org/apache/derby/client/am/Statement.java (original)
+++ incubator/derby/code/trunk/java/client/org/apache/derby/client/am/Statement.java Fri Jun  3 12:35:33 2005
@@ -1189,7 +1189,7 @@
         }
         if (connection_.autoCommit_ && requiresAutocommit) { // for the auto-commit;
             if (connection_.isXAConnection_) {
-                return (connection_.xaState_ == Connection.XA_LOCAL) || (connection_.xaState_ == Connection.XA_LOCAL_START_SENT);
+                return (connection_.xaState_ == Connection.XA_LOCAL) ;
             } else {
                 return true;
             }
@@ -1268,7 +1268,7 @@
         if (connection_.autoCommit_ && requiresAutocommit && isAutoCommittableStatement_) {
             connection_.writeAutoCommit();
             if (connection_.isXAConnection_) {
-                return (connection_.xaState_ == Connection.XA_LOCAL) || (connection_.xaState_ == Connection.XA_LOCAL_START_SENT);
+                return (connection_.xaState_ == Connection.XA_LOCAL) ;
             } else {
                 return true;
             }

Modified: incubator/derby/code/trunk/java/client/org/apache/derby/client/net/NetConnection.java
URL: http://svn.apache.org/viewcvs/incubator/derby/code/trunk/java/client/org/apache/derby/client/net/NetConnection.java?rev=179867&r1=179866&r2=179867&view=diff
==============================================================================
--- incubator/derby/code/trunk/java/client/org/apache/derby/client/net/NetConnection.java (original)
+++ incubator/derby/code/trunk/java/client/org/apache/derby/client/net/NetConnection.java Fri Jun  3 12:35:33 2005
@@ -1364,12 +1364,10 @@
     }
 
     // Driver-specific determination if local COMMIT/ROLLBACK is allowed;
-    // allow if local trans, disallow if global trans
-    protected boolean disallowLocalCommitRollback_() throws org.apache.derby.client.am.SqlException {
-        if (!((xaState_ == XA_OPEN_IDLE) ||
-                (xaState_ == XA_RECOVER) ||
-                (xaState_ == XA_LOCAL_START_SENT) ||
-                (xaState_ == XA_LOCAL))) {
+    // Allow local COMMIT/ROLLBACK only if we are not in an XA transaction
+    protected boolean allowLocalCommitRollback_() throws org.apache.derby.client.am.SqlException {
+       
+    	if (xaState_ == XA_LOCAL) {
             return true;
         }
         return false;
@@ -1472,9 +1470,8 @@
         boolean doCommit = false;
         int xaState = getXAState();
 
-        if ((xaState == XA_OPEN_IDLE) ||
-                (xaState == XA_LOCAL) ||
-                (xaState == XA_LOCAL_START_SENT)) {
+        
+        if (xaState == XA_LOCAL) {
             doCommit = true;
         }
 

Modified: incubator/derby/code/trunk/java/client/org/apache/derby/client/net/NetXACallInfo.java
URL: http://svn.apache.org/viewcvs/incubator/derby/code/trunk/java/client/org/apache/derby/client/net/NetXACallInfo.java?rev=179867&r1=179866&r2=179867&view=diff
==============================================================================
--- incubator/derby/code/trunk/java/client/org/apache/derby/client/net/NetXACallInfo.java (original)
+++ incubator/derby/code/trunk/java/client/org/apache/derby/client/net/NetXACallInfo.java Fri Jun  3 12:35:33 2005
@@ -44,7 +44,6 @@
 public class NetXACallInfo {
     Xid xid_;                         // current xid
     int xaFlags_;                     // current xaFlags
-    int xaState_;                     // used as a save area when switching connection
     // may not be needed!!!~~~
     int xaFunction_;                  // queued XA function being performed
     int xaRetVal_;                    // xaretval from server
@@ -74,7 +73,6 @@
     public NetXACallInfo() {
         xid_ = null;
         xaFlags_ = XAResource.TMNOFLAGS;
-        xaState_ = Connection.XA_OPEN_IDLE;
         xaInProgress_ = false;
         currConnection_ = false;
         freeEntry_ = true;
@@ -86,11 +84,9 @@
         xaWasSuspended = false;
     }
 
-    public NetXACallInfo(Xid xid, int flags, int state,
-                         NetXAResource xares, NetXAConnection actualConn) {
+    public NetXACallInfo(Xid xid, int flags, NetXAResource xares, NetXAConnection actualConn) {
         xid_ = xid;
         xaFlags_ = flags;
-        xaState_ = state;
         xaInProgress_ = false;
         currConnection_ = false;
         freeEntry_ = true;

Modified: incubator/derby/code/trunk/java/client/org/apache/derby/client/net/NetXAConnection.java
URL: http://svn.apache.org/viewcvs/incubator/derby/code/trunk/java/client/org/apache/derby/client/net/NetXAConnection.java?rev=179867&r1=179866&r2=179867&view=diff
==============================================================================
--- incubator/derby/code/trunk/java/client/org/apache/derby/client/net/NetXAConnection.java (original)
+++ incubator/derby/code/trunk/java/client/org/apache/derby/client/net/NetXAConnection.java Fri Jun  3 12:35:33 2005
@@ -87,7 +87,8 @@
         // this is a XA connection
         int xaState = getXAState();
         xares_.exceptionsOnXA = null;
-
+        //TODO: Looks like this can go and also the whole client indoubtTransaction code.
+        /*
         if (xaState == XA_RECOVER) { // in recover, clean up and go to open-idle
             if (indoubtTransactions_ != null) {
                 indoubtTransactions_.clear();
@@ -95,7 +96,8 @@
                 setXAState(XA_OPEN_IDLE);
                 xaState = XA_OPEN_IDLE;
             }
-        }
+            
+        }*/
         // For derby we don't need to write transaction start for a local
         //transaction.  If autocommit is off we are good to go.
         return;
@@ -130,11 +132,9 @@
         // this logic must be in sync with willAutoCommitGenerateFlow() logic
         if (isXAConnection_) { // XA Connection
             int xaState = getXAState();
-            if ((xaState == XA_OPEN_IDLE) ||
-                    (xaState == XA_LOCAL) ||
-                    (xaState == XA_LOCAL_START_SENT)) {
+            if (xaState == XA_LOCAL){
                 xares_.callInfoArray_[xares_.conn_.currXACallInfoOffset_].xid_ =
-                        xares_.nullXid;
+                        NetXAResource.nullXid;
                 writeLocalXACommit_();
             }
         } else { // not XA connection
@@ -147,11 +147,10 @@
             int xaState = getXAState();
             NetXACallInfo callInfo = xares_.callInfoArray_[currXACallInfoOffset_];
             callInfo.xaRetVal_ = NetXAResource.XARETVAL_XAOK; // initialize XARETVAL
-            if ((xaState == XA_OPEN_IDLE) ||
-                    (xaState == XA_LOCAL) ||
-                    (xaState == XA_LOCAL_START_SENT)) {
+            if (xaState == XA_LOCAL) {
                 readLocalXACommit_();
-                setXAState(XA_OPEN_IDLE);
+                //TODO: Remove
+                //setXAState(XA_LOCAL);
             }
             if (callInfo.xaRetVal_ != NetXAResource.XARETVAL_XAOK) { // xaRetVal has possible error, format it
                 callInfo.xaFunction_ = NetXAResource.XAFUNC_COMMIT;
@@ -191,7 +190,8 @@
 
 
             // for all XA connectiions
-            setXAState(XA_OPEN_IDLE);
+            // TODO:KATHEY - Do we need this?
+            setXAState(XA_LOCAL);
         } else {
             readLocalRollback_(); // non-XA connections
         }

Modified: incubator/derby/code/trunk/java/client/org/apache/derby/client/net/NetXAResource.java
URL: http://svn.apache.org/viewcvs/incubator/derby/code/trunk/java/client/org/apache/derby/client/net/NetXAResource.java?rev=179867&r1=179866&r2=179867&view=diff
==============================================================================
--- incubator/derby/code/trunk/java/client/org/apache/derby/client/net/NetXAResource.java (original)
+++ incubator/derby/code/trunk/java/client/org/apache/derby/client/net/NetXAResource.java Fri Jun  3 12:35:33 2005
@@ -121,17 +121,14 @@
     protected NetXAResource nextSameRM_ = null;
     protected boolean ignoreMe_ = false;
 
-    /* KATHEY CHECK THIS COMMENT TOO.
-     * Need to remove NetXAResource objects from this group when they are
-     *  freed.
-     */
+
 
     public org.apache.derby.client.am.SqlException exceptionsOnXA = null;
 
     XAConnection xaconn_;
     org.apache.derby.client.net.NetXAConnection conn_;
     int rmId_; // unique RmId generated by XAConnection
-    // KATHEY change to a single callInfo field (not an array)
+    // TODO: change to a single callInfo field (not an array)
     NetXACallInfo callInfoArray_[] =
             new NetXACallInfo[INITIAL_CALLINFO_ELEMENTS];
     int numXACallInfo_ = INITIAL_CALLINFO_ELEMENTS;
@@ -139,7 +136,7 @@
     int activeXATransCount_ = 0;
     String rmIdx_; // userid in case we need to create a secondary connection
     String rmIdy_; // password in case we need to create a secondary connection
-    // KATHEY remove port and ipaddr_
+    // TODO: remove port and ipaddr_
     int port_;     // port needed to make secondary connection for recover in DS mode.
     String ipaddr_;  // ip address needed to make secondary connection for recover in DS mode.
 
@@ -162,8 +159,7 @@
 
         // construct the NetXACallInfo object for the array.
         for (int i = 0; i < INITIAL_CALLINFO_ELEMENTS; ++i) {
-            callInfoArray_[i] = new NetXACallInfo(null, XAResource.TMNOFLAGS,
-                    Connection.XA_OPEN_IDLE, this,
+            callInfoArray_[i] = new NetXACallInfo(null, XAResource.TMNOFLAGS, this,
                     null);
         }
 
@@ -182,12 +178,12 @@
     public void commit(Xid xid, boolean onePhase) throws XAException {
         NetAgent netAgent = conn_.netAgent_;
         int rc = XAResource.XA_OK;
-
+        
         exceptionsOnXA = null;
         if (conn_.agent_.loggingEnabled()) {
             conn_.agent_.logWriter_.traceEntry(this, "commit", xid, onePhase);
         }
-        if (conn_.isClosed()) {
+        if (conn_.isPhysicallyClosed()) {
             connectionClosedFailure();
         }
 
@@ -219,6 +215,9 @@
         if (rc != XAResource.XA_OK) {
             throwXAException(rc, false);
         }
+        else {
+        	conn_.setXAState(Connection.XA_LOCAL);
+        }
     }
 
     /**
@@ -248,7 +247,7 @@
         if (conn_.agent_.loggingEnabled()) {
             conn_.agent_.logWriter_.traceEntry(this, "end", xid, flags);
         }
-        if (conn_.isClosed()) {
+        if (conn_.isPhysicallyClosed()) {
             connectionClosedFailure();
         }
 
@@ -279,9 +278,7 @@
         }
         if (rc != XAResource.XA_OK) {
             throwXAException(rc, false);
-        } else {
-            conn_.setXAState(Connection.XA_ENDED);
-        }
+        } 
 
     }
 
@@ -302,7 +299,7 @@
         if (conn_.agent_.loggingEnabled()) {
             conn_.agent_.logWriter_.traceEntry(this, "forget", xid);
         }
-        if (conn_.isClosed()) {
+        if (conn_.isPhysicallyClosed()) {
             connectionClosedFailure();
         }
         NetXACallInfo callInfo = callInfoArray_[conn_.currXACallInfoOffset_];
@@ -355,7 +352,7 @@
             conn_.agent_.logWriter_.traceEntry(this, "getTransactionTimeout");
         }
         exceptionsOnXA = null;
-        if (conn_.isClosed()) {
+        if (conn_.isPhysicallyClosed()) {
             connectionClosedFailure();
         }
 
@@ -384,7 +381,7 @@
         if (conn_.agent_.loggingEnabled()) {
             conn_.agent_.logWriter_.traceEntry(this, "prepare", xid);
         }
-        if (conn_.isClosed()) {
+        if (conn_.isPhysicallyClosed()) {
             connectionClosedFailure();
         }
 
@@ -450,7 +447,7 @@
             conn_.agent_.logWriter_.traceEntry(this, "recover", flag);
         }
         exceptionsOnXA = null;
-        if (conn_.isClosed()) {
+        if (conn_.isPhysicallyClosed()) {
             connectionClosedFailure();
         }
 
@@ -515,7 +512,7 @@
         if (conn_.agent_.loggingEnabled()) {
             conn_.agent_.logWriter_.traceEntry(this, "rollback", xid);
         }
-        if (conn_.isClosed()) {
+        if (conn_.isPhysicallyClosed()) {
             connectionClosedFailure();
         }
 
@@ -546,7 +543,9 @@
         if (rc != XAResource.XA_OK) {
             throwXAException(rc, false);
         }
-
+        else {
+        	conn_.setXAState(Connection.XA_LOCAL);
+        }
     }
 
     /**
@@ -586,7 +585,7 @@
         if (conn_.agent_.loggingEnabled()) {
             conn_.agent_.logWriter_.traceEntry(this, "start", xid, flags);
         }
-        if (conn_.isClosed()) {
+        if (conn_.isPhysicallyClosed()) {
             connectionClosedFailure();
         }
 
@@ -610,7 +609,7 @@
             // Setting this is currently required to avoid client from sending
             // commit for autocommit.
             if (rc == XARETVAL_XAOK) {
-                conn_.setXAState(Connection.XA_ACTIVE);
+                conn_.setXAState(Connection.XA_GLOBAL);
             }
 
         } catch (SqlException sqle) {
@@ -720,8 +719,6 @@
             NetXACallInfo callInfo = callInfoArray_[conn_.currXACallInfoOffset_];
             callInfo.xaInProgress_ = false;
             callInfo.xaWasSuspended = false;
-            callInfo.xaState_ = Connection.XA_OPEN_IDLE;
-            conn_.setXAState(Connection.XA_OPEN_IDLE);
         }
 
         xaExceptionText = getXAExceptionText(rc);
@@ -748,7 +745,7 @@
         if (conn_.agent_.loggingEnabled()) {
             conn_.agent_.logWriter_.traceEntry(this, "isSameRM", xares);
         }
-        if (conn_.isClosed()) {
+        if (conn_.isPhysicallyClosed()) {
             connectionClosedFailure();
         }
 
@@ -825,77 +822,6 @@
         }
 
         return true; // all of the fields are the same, xid1 == xid2
-    }
-
-
-    // KATHEY remove
-    protected void makeEntryCurrent(int offset) throws SqlException {
-        int currOffset = conn_.currXACallInfoOffset_; // offset of current XACallInfo
-        NetXACallInfo newCallInfo = callInfoArray_[offset];
-        if (conn_.agent_.loggingEnabled()) {
-            conn_.agent_.logWriter_.traceEntry
-                    (this, "makeEntryCurrent", offset, currOffset);
-        }
-
-        if (currOffset == offset) { // entry is already current
-            if (newCallInfo.convReleased_ &&
-                    !newCallInfo.xaInProgress_) { // connection reuse, XA is not in Progress, reset connection
-// transaction pooling
-                newCallInfo.convReleased_ = false;
-                if (!conn_.resetConnectionAtFirstSql_) { // resetConnectionAtFirstSql_ is false
-/*
-            * at this point we have determined that a reset of this connection
-            * is required. We are already inside beginWriteChain() where a
-            * deferred reset would be done, however we might have switched
-            * connection to a connection that needed reset from a connection
-            * that didn't need reset. It is too late for the test for deferred
-            * reset in beginWriteChain so we call writeDeferredReset here.
-            * by setting the resetConnectionAtFirstSql_ flag we trigger the
-            * readDeferredReset in beginReadChain. This is done ONLY if
-            * resetConnectionAtFirstSql_ is not set, if it is then
-            * writeDeferredReset() has already been done.
-            */
-                    conn_.resetConnectionAtFirstSql_ = true;
-                    conn_.writeDeferredReset();
-                }
-            }
-            return; // entry is already current, nothing to do
-        }
-
-        callInfoArray_[currOffset].currConnection_ = false; // reset old current conn
-        callInfoArray_[currOffset].xaState_ = conn_.getXAState(); // save XA state
-        callInfoArray_[currOffset].freeEntry_ = false; // set entry in use
-
-// set the new entry as the current entry, update conn_
-        newCallInfo.currConnection_ = true;
-        conn_.currXACallInfoOffset_ = offset;
-        conn_.setXAState(newCallInfo.xaState_);
-
-        if (newCallInfo.convReleased_ &&
-                !newCallInfo.xaInProgress_) { // connection reuse, XA is not in Progress, reset connection
-// transaction pooling
-            newCallInfo.convReleased_ = false;
-            if (!conn_.resetConnectionAtFirstSql_) { // resetConnectionAtFirstSql_ is false
-/*
-          * at this point we have determined that a reset of this connection
-          * is required. We are already inside beginWriteChain() where a
-          * deferred reset would be done, however we might have switched
-          * connection to a connection that needed reset from a connection
-          * that didn't need reset. It is too late for the test for deferred
-          * reset in beginWriteChain so we call writeDeferredReset here.
-          * by setting the resetConnectionAtFirstSql_ flag we trigger the
-          * readDeferredReset in beginReadChain. This is done ONLY if
-          * resetConnectionAtFirstSql_ is not set, if it is then
-          * writeDeferredReset() has already been done.
-          */
-                conn_.resetConnectionAtFirstSql_ = true;
-                conn_.writeDeferredReset();
-            }
-        }
-
-        if (conn_.agent_.loggingEnabled()) { // logging enabled
-            conn_.agent_.logWriter_.traceExit(this, "makeEntryCurrent", offset);
-        }
     }
 
 

Modified: incubator/derby/code/trunk/java/drda/org/apache/derby/impl/drda/XADatabase.java
URL: http://svn.apache.org/viewcvs/incubator/derby/code/trunk/java/drda/org/apache/derby/impl/drda/XADatabase.java?rev=179867&r1=179866&r2=179867&view=diff
==============================================================================
--- incubator/derby/code/trunk/java/drda/org/apache/derby/impl/drda/XADatabase.java (original)
+++ incubator/derby/code/trunk/java/drda/org/apache/derby/impl/drda/XADatabase.java Fri Jun  3 12:35:33 2005
@@ -74,10 +74,21 @@
 		appendAttrString(p);
 		if (attrString != null)
 			xaDataSource.setConnectionAttributes(attrString);
-		xaConnection = xaDataSource.getXAConnection(userId,password);
-		xaResource = xaConnection.getXAResource();
-
-		Connection conn = xaConnection.getConnection();
+		
+		Connection conn = getConnection();
+		// If we have no existing connection. this is a brand new XAConnection.
+		if (conn == null)
+		{
+			xaConnection = xaDataSource.getXAConnection(userId,password);
+			xaResource = xaConnection.getXAResource();
+		}
+		else // this is just a connection reset. Close the logical connection.
+		{
+			conn.close();
+		}
+		
+		// Get a new logical connection.
+		conn = xaConnection.getConnection();
 		setConnection(conn);
 		return conn;
 		

Modified: incubator/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/master/DerbyNetClient/netxaPositive.out
URL: http://svn.apache.org/viewcvs/incubator/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/master/DerbyNetClient/netxaPositive.out?rev=179867&r1=179866&r2=179867&view=diff
==============================================================================
--- incubator/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/master/DerbyNetClient/netxaPositive.out (original)
+++ incubator/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/master/DerbyNetClient/netxaPositive.out Fri Jun  3 12:35:33 2005
@@ -110,5 +110,29 @@
 ij(XA)> -- should fail with XA_NOTA because we prepared a read only transaction 
 xa_commit xa_1Phase 3;
 IJ ERROR: XAER_NOTA 
+ij(XA)> -- DERBY-246 xa_end after connection close should be ok.  
+----- Also to reuse xaconnection in the same global transaction
+xa_getconnection;
+ij(XA)> xa_start xa_noflags 4;
+ij(XA)> create table APP.derby246  (i int);
+0 rows inserted/updated/deleted
+ij(XA)> insert into APP.derby246 values(1);
+1 row inserted/updated/deleted
 ij(XA)> disconnect;
+ij> xa_getconnection;
+ij(XA)> insert into APP.derby246 values(2);
+1 row inserted/updated/deleted
+ij(XA)> disconnect;
+ij> xa_end xa_success 4;
+ij> xa_prepare 4;
+ij> xa_commit xa_2phase 4;
+ij> -- now connect with a local connection to make sure locks are released 
+----- and our values are there. Should see two rows
+connect 'wombat';
+ij(CONNECTION1)> select * from APP.derby246;
+I          
+-----
+1          
+2          
+ij(CONNECTION1)> disconnect;
 ij> 

Modified: incubator/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/derbynet/netxaPositive.sql
URL: http://svn.apache.org/viewcvs/incubator/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/derbynet/netxaPositive.sql?rev=179867&r1=179866&r2=179867&view=diff
==============================================================================
--- incubator/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/derbynet/netxaPositive.sql (original)
+++ incubator/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/derbynet/netxaPositive.sql Fri Jun  3 12:35:33 2005
@@ -80,5 +80,28 @@
 
 -- should fail with XA_NOTA because we prepared a read only transaction 
 xa_commit xa_1Phase 3;
+
+
+-- DERBY-246 xa_end after connection close should be ok.  
+-- Also to reuse xaconnection in the same global transaction
+xa_getconnection;
+xa_start xa_noflags 4;
+create table APP.derby246  (i int);
+insert into APP.derby246 values(1);
 disconnect;
+xa_getconnection;
+insert into APP.derby246 values(2);
+disconnect;
+xa_end xa_success 4;
+xa_prepare 4;
+xa_commit xa_2phase 4;
+
+-- now connect with a local connection to make sure locks are released 
+-- and our values are there. Should see two rows
+connect 'wombat';
+select * from APP.derby246;
+
+disconnect;
+
+
 

Modified: incubator/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/jdbcapi/resultset.java
URL: http://svn.apache.org/viewcvs/incubator/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/jdbcapi/resultset.java?rev=179867&r1=179866&r2=179867&view=diff
==============================================================================
--- incubator/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/jdbcapi/resultset.java (original)
+++ incubator/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/jdbcapi/resultset.java Fri Jun  3 12:35:33 2005
@@ -28,6 +28,7 @@
 import java.sql.Statement;
 import java.sql.SQLException;
 import java.sql.Types;
+import java.util.Properties;
 
 import java.lang.reflect.*;
 
@@ -45,6 +46,8 @@
  *
  * Test is only touching on known result set hot-spots at present.
  *
+ * Modified May 31, 2005 pwilder
+ *
  * @author ames
  */
 
@@ -71,10 +74,13 @@
 
 		try
 		{
+			
 			// use the ij utility to read the property file and
 			// make the initial connection.
+			
 			ij.getPropertyArg(args);
 			con = ij.startJBMS();
+			testImplicitClose(con);
 			// Test setCatalog/getCatalog for beetle 5504
 			con.setCatalog("mycatalog");
 			String cat = con.getCatalog();
@@ -523,9 +529,11 @@
 
 
 			stmt.close();
-
+			
 			testMutableValues(con);
 			testCorrelationNamesAndMetaDataCalls(con);
+			//This call does not work here, but works somewhere above.
+//			testImplicitClose(con);
 			con.close();
 
 		}
@@ -771,6 +779,134 @@
 			System.out.println("OK EQUALITY OBJECT RETURNED column " + col + " existing " + equals);
 
 		list.add(value);
+	}
+	
+	/**
+	 * testImplicitClose convenience function.
+	 * 
+	 * @param conn
+	 */
+	private static void testImplicitClose(Connection conn) {
+		testImplicitClose(conn, false, 2);
+	}
+	
+	/**
+	 * testImplicitClose convenience function.
+	 * 
+	 * @param conn
+	 */
+	private static void testImplicitClose(Connection conn, boolean prepared) {
+		testImplicitClose(conn, prepared, 2);
+	}
+	
+	/**
+	 * testImplicitClose convenience function.
+	 * 
+	 * @param conn
+	 */
+	private static void testImplicitClose(Connection conn, int numRows) {
+		testImplicitClose(conn, false, numRows);
+	}
+	
+	/**
+	 * The main function for testing the closing behavior of the ResultSet
+	 * 
+	 * @param conn The connection.
+	 * @param prepared Boolean specifying whether to use a PreparedStatement or not.
+	 * @param numRows The number of rows to use in the test case.
+	 */
+	private static void testImplicitClose(Connection conn, boolean prepared, int numRows) {
+		try {
+			String tableName = "implicitClose";
+			System.out.println("Begin ImplicitClose tests");
+			if (conn == null || conn.isClosed())  {
+				System.out.println("Invalid connection, cannot run ImplicitClose tests");
+				return;
+			}
+			Statement s = conn.createStatement();
+			
+			//Check to see if a table of this name already exists
+			ResultSet rs = s.executeQuery("Select tablename from sys.systables where tablename = '" + tableName + "'");
+			if (rs.next()) {
+				System.out.println("Table already exists. Can not run ImplicitClose tests");
+				return;
+			}
+			rs.close();
+			
+			s.execute("create table " + tableName + "(num int)");
+			s.close();
+			PreparedStatement ps = conn.prepareStatement("insert into implicitClose values (?)");
+			//Create and populate table
+			for (int i = 0; i < numRows; i++) {
+				ps.setInt(1, (i + 1));
+				ps.execute();
+			}
+			ps.close();
+		
+			if (prepared)
+				testImplicitClosePrepared(conn, tableName);
+			else
+				testImplicitCloseNonPrepared(conn, tableName);
+			
+			System.out.println("ImplicitClose tests complete");
+			
+		} catch (SQLException e) {
+			System.out.println("Unhandled exception in testImplicitClose: ");
+			e.printStackTrace();
+		}
+	}
+	/**
+	 * Uses a preparedStatement to generate the ResultSet
+	 * 
+	 * @param conn The Connection
+	 * @param tableName The name of the table being used
+	 * 
+	 * @throws SQLException
+	 */
+	private static void testImplicitClosePrepared(Connection conn, String tableName) throws SQLException{
+		PreparedStatement ps = conn.prepareStatement("select num from " + tableName);
+		testImplicitCloseRSComponent(ps.executeQuery());
+//		ps.execute("drop table " + tableName);
+		ps.close();
+		Statement s = conn.createStatement();
+		s.execute("drop table " + tableName);
+		s.close();
+	}
+	
+	/**
+	 * Uses a normal statement to generate the ResultSet
+	 * 
+	 * @param conn The connection.
+	 * @param tableName The name of the table.
+	 * 
+	 * @throws SQLException 
+	 */
+	private static void testImplicitCloseNonPrepared(Connection conn, String tableName) throws SQLException{
+		Statement s = conn.createStatement();
+		testImplicitCloseRSComponent(s.executeQuery("select * from " + tableName));
+		s.execute("drop table " + tableName);
+		s.close();
+	}
+	
+	/**
+	 * Tests the ResultSet generated by either the prepared or non prepared statement.
+	 * 
+	 * @param rs The resultSet
+	 * 
+	 * @throws SQLException
+	 */
+	private static void testImplicitCloseRSComponent(ResultSet rs) throws SQLException {
+		while (rs.next())
+			System.out.println(rs.getInt(1));
+		try {
+			System.out.println("Final call to ResultSet.next()");
+			rs.next();
+			rs.close();
+			System.out.println("Call successful");
+		} catch (SQLException ex) {
+			System.out.println("Call to ResultSet.next() thows the following exception: ");
+			ex.printStackTrace();
+		}
 	}
 }