diff options
Diffstat (limited to 'src/interfaces/jdbc/org/postgresql/xa/XAConnectionImpl.java')
| -rw-r--r-- | src/interfaces/jdbc/org/postgresql/xa/XAConnectionImpl.java | 956 |
1 files changed, 0 insertions, 956 deletions
diff --git a/src/interfaces/jdbc/org/postgresql/xa/XAConnectionImpl.java b/src/interfaces/jdbc/org/postgresql/xa/XAConnectionImpl.java deleted file mode 100644 index 776badfd6d..0000000000 --- a/src/interfaces/jdbc/org/postgresql/xa/XAConnectionImpl.java +++ /dev/null @@ -1,956 +0,0 @@ -/* -* Redistribution and use of this software and associated documentation -* ("Software"), with or without modification, are permitted provided -* that the following conditions are met: -* -* 1. Redistributions of source code must retain copyright -* statements and notices. Redistributions must also contain a -* copy of this document. -* -* 2. Redistributions in binary form must reproduce the -* above copyright notice, this list of conditions and the -* following disclaimer in the documentation and/or other -* materials provided with the distribution. -* -* 3. The name "Exolab" must not be used to endorse or promote -* products derived from this Software without prior written -* permission of Exoffice Technologies. For written permission, -* please contact info@exolab.org. -* -* 4. Products derived from this Software may not be called "Exolab" -* nor may "Exolab" appear in their names without prior written -* permission of Exoffice Technologies. Exolab is a registered -* trademark of Exoffice Technologies. -* -* 5. Due credit should be given to the Exolab Project -* (http://www.exolab.org/). -* -* THIS SOFTWARE IS PROVIDED BY EXOFFICE TECHNOLOGIES AND CONTRIBUTORS -* ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT -* NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND -* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL -* EXOFFICE TECHNOLOGIES OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, -* INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR -* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) -* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, -* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) -* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED -* OF THE POSSIBILITY OF SUCH DAMAGE. -* -* Copyright 1999 (C) Exoffice Technologies Inc. All Rights Reserved. -* -* $Id: XAConnectionImpl.java,v 1.4 2001/11/19 23:19:21 momjian Exp $ -*/ - - -package org.postgresql.xa; - - -import java.sql.Connection; -import java.sql.SQLException; -import java.util.Vector; -import javax.sql.XAConnection; -import javax.sql.PooledConnection; -import javax.sql.ConnectionEvent; -import javax.sql.ConnectionEventListener; -import javax.transaction.RollbackException; -import javax.transaction.xa.XAResource; -import javax.transaction.xa.Xid; -import javax.transaction.xa.XAException; - - -/* - * Implements an X/A connection that can be pooled and managed from - * inside a transaction monitor. This is the XA connection returned - * to the application server from the {@link XADataSourceImpl} and - * will be used to obtain {@link ClientConnection} for the - * application. - * <p> - * If the transaction is managed through the JDBC interface, this - * connection will reference the underlying JDBC connection directly. - * If this resource is enlisted with a global transaction through - * the {@link XAResource} interface, it will reference a transactional - * connection, or {@link TxConnection}. Such a connection may be - * shared by two or more XA connections enlisted with the same - * transaction. - * - * - * @author <a href="arkin@exoffice.com">Assaf Arkin</a> - * @version 1.0 - * @see ClientConnection - * @see ConnectionEventListener - * @see TxConnection - */ -public final class XAConnectionImpl - implements XAConnection, XAResource -{ - - - /* - * This is the underlying JDBC connection represented - * by this pooled connection. This variable may initially be null, - * in which case {@link #getUnderlying} will return a new - * connection and set this variable. This variable is mutually - * exclusive with {@link #_txConn} and is always null for - * connections inside a transaction. - */ - Connection _underlying; - - - /* - * If this connection is part of a global transaction, this - * object identifies the transaction. The transaction's - * underlying JDBC connection is exposed through this object and - * {@link #_underlying} is null. If this connection is closed, - * then the connection has been timedout. Commit/rollback will - * always set this variable to null. - */ - private TxConnection _txConn; - - - /* - * The client connection last handed to the application. If the - * application calls {@link #getConnection} again, we should hand - * out a new client connection and render the previous one closed. - */ - // No longer in use, see _clientId - //private ClientConnection _clientConn; - - - /* - * An event listener can be registered and notified when the - * client connection has been closed by the application or a - * fatal error rendered it unuseable. - */ - private ConnectionEventListener _listener; - - - /* - * The resource manager is used to share connections within the - * same transaction. - */ - private XADataSourceImpl _resManager; - - - /* - * This is an identifier we hand to the client connection when we - * create it. When the client connection asks for the underlying - * connection, we compare the identifiers. If since that point we - * created a new client connection, we regard an old client - * connection as discarded and do not hand it the underlying - * connection. - * <p> - * Previously, when a new client connection was created, we used - * a reference to the old one to terminate it. This proved to - * not work well, since the client connection could never be - * finalized. - */ - private int _clientId = 1; - - - /* - * Construct a new XA/pooled connection with the underlying JDBC - * connection suitable for this driver only. This is a one to one - * mapping between this connection and the underlying connection. - * The underlying connection is only provided for pooled - * connections. XA connections are suspect of being enlisted with - * a global transaction which might already bear an underlying - * connection. If not, one will be created later on. - */ - XAConnectionImpl( XADataSourceImpl resManager, - Connection underlying ) - { - _underlying = underlying; - _resManager = resManager; - } - - - public synchronized void close() - throws SQLException - { - // This is our indication that this connection has been - // closed programmatically. - if ( _resManager == null ) - throw new SQLException( "This connection has been closed" ); - - // The client connection is no longer useable. - /* Deprecated: see _clientId - if ( _clientConn != null ) - _clientConn.terminate(); - */ - _clientId = -1; - - // The underlying connection is closed and this connection - // is no longer useable. This method can be called any number - // of times (e.g. we use it in finalizer). We do not handle - // transactions, we just kill the connection. - try - { - if ( _underlying != null ) - { - _underlying.commit(); - _underlying.close(); - } - else if ( _txConn != null ) - { - try - { - end( _txConn.xid, TMSUCCESS ); - } - catch ( XAException except ) - { } - } - } - finally - { - _resManager = null; - _underlying = null; - _txConn = null; - _listener = null; - } - } - - - public XAResource getXAResource() - { - // The connection acts as it's own resource manager - return this; - } - - - public synchronized void addConnectionEventListener( ConnectionEventListener listener ) - { - if ( listener == null ) - throw new NullPointerException( "XAConnection: Argument 'listener' is null" ); - if ( _listener != null ) - throw new IllegalStateException( "XAConnection: Only one listener supported per connection" ); - _listener = listener; - } - - - public synchronized void removeConnectionEventListener( ConnectionEventListener listener ) - { - if ( listener == null ) - throw new NullPointerException( "XAConnection: Argument 'listener' is null" ); - if ( _listener == null || _listener != listener ) - throw new IllegalStateException( "XAConnection: Listener never registered with this pooled connection" ); - _listener = null; - } - - - public synchronized java.sql.Connection getConnection() - throws SQLException - { - // If this pooled connection has been closed, throw an exception. - if ( _resManager == null ) - throw new SQLException( "This connection has been closed" ); - - // If getConnection() was called before and the underlying - // connection was not closed, we take it away from the previous - // recieved as per the PooledConnection design. - /* Deprecated: see _clientId - if ( _clientConn != null ) - _clientConn.terminate(); - */ - - // If we are handling an underlying connection, we commit the - // old transaction and are ready to work for a new one. - // If we are part of a global transaction we hope that end/ - // start were called properly, but we're not longer in that - // transaction. - if ( _underlying != null ) - { - try - { - _underlying.commit(); - } - catch ( SQLException except ) - { - ConnectionEvent event; - - if ( _listener != null ) - { - event = new ConnectionEvent( this, except ); - _listener.connectionErrorOccurred( event ); - } - } - } - - // Create a new ClientConnection which will be returned to the - // application. The ClientConnection cannot be closed directly - // and cannot manage it's own transactions. - /* Deprecated: see _clientId - _clientConn = new ClientConnection( this ); - return _clientConn; - */ - return new ClientConnection( this, ++_clientId ); - } - - - /* - * Called by {@link ClientConnection} to notify that the application - * has attempted to close the connection. After this call, the client - * connection is no longer useable and this pooled connection can be - * reused. The event listener is notified immediately. - * - * @param clientId The {@link ClientConnection} identifier - */ - synchronized void notifyClose( int clientId ) - { - ConnectionEvent event; - - // ClientConnection has been closed, we dissociated it from - // the underlying connection and notify any listener that this - // pooled connection can be reused. - /* Deprecated: see clientId - _clientConn.terminate(); - _clientConn = null; - */ - // We have to expect being called by a ClientConnection that we - // no longer regard as valid. That's acceptable, we just ignore. - if ( clientId != _clientId ) - return; - - // If we are handling an underlying connection, we commit the - // old transaction and are ready to work for a new one. - // If we are part of a global transaction we hope that end/ - // start were called properly. - if ( _underlying != null ) - { - try - { - _underlying.commit(); - } - catch ( SQLException except ) - { - if ( _listener != null ) - { - event = new ConnectionEvent( this, except ); - _listener.connectionErrorOccurred( event ); - } - return; - } - } - // Notify the listener. - if ( _listener != null ) - { - event = new ConnectionEvent( this ); - _listener.connectionClosed( event ); - } - } - - - /* - * Called by {@link ClientConnection} to notify that an error - * occured with the underlying connection. If the error is - * critical, the underlying connection is closed and the listener - * is notified. - * - * @param clientId The {@link ClientConnection} identifier - * @param except The exception raised by the underlying connection - */ - synchronized void notifyError( int clientId, SQLException except ) - { - ConnectionEvent event; - - if ( clientId != _clientId ) - return; - - // If the connection is not two-phase commit we cannot determine - // whether the error is critical, we just return. If the connection - // is two phase commit, but the error is not critical, we return. - if ( _underlying != null ) - { - if ( ! ( _underlying instanceof TwoPhaseConnection ) || - ! ( (TwoPhaseConnection) _underlying ).isCriticalError( except ) ) - return; - if ( _txConn.conn == null || - ! ( _txConn.conn instanceof TwoPhaseConnection ) || - ! ( (TwoPhaseConnection) _txConn.conn ).isCriticalError( except ) ) - return; - } - - // The client connection is no longer useable, the underlying - // connection (if used) is closed, the TxConnection (if used) - // is rolledback and this connection dies (but close() may - // still be called). - ++_clientId; - if ( _underlying != null ) - { - try - { - _underlying.close(); - } - catch ( SQLException e2 ) - { - // Ignore that, we know there's an error. - } - _underlying = null; - } - else if ( _txConn != null ) - { - try - { - end( _txConn.xid, TMFAIL ); - } - catch ( XAException e2 ) - { - // Ignore that, we know there's an error. - } - _txConn = null; - } - - // Notify the listener. - if ( _listener != null ) - { - event = new ConnectionEvent( this, except ); - _listener.connectionErrorOccurred( event ); - } - } - - - protected void finalize() - throws Throwable - { - // We are no longer referenced by anyone (including the - // connection pool). Time to close down. - close(); - } - - - public String toString() - { - if ( _underlying != null ) - return "XAConnection: " + _underlying; - else - return "XAConnection: unused"; - } - - - public synchronized void start( Xid xid, int flags ) - throws XAException - { - // General checks. - if ( xid == null ) - throw new XAException( XAException.XAER_INVAL ); - if ( _txConn != null ) - throw new XAException( XAException.XAER_OUTSIDE ); - - synchronized ( _resManager ) - { - if ( flags == TMNOFLAGS ) - { - // Starting a new transaction. First, make sure it is - // not shared with any other connection (need to join - // for that). - if ( _resManager.getTxConnection( xid ) != null ) - throw new XAException( XAException.XAER_DUPID ); - - // Create a new TxConnection to describe this - // connection in the context of a transaction and - // register it with the resource manager so it can - // be shared. - try - { - _txConn = new TxConnection(); - if ( _underlying != null ) - { - _txConn.conn = _underlying; - _underlying = null; - } - else - _txConn.conn = _resManager.newConnection(); - _txConn.xid = xid; - _txConn.count = 1; - _txConn.started = System.currentTimeMillis(); - _txConn.timeout = _txConn.started + ( _resManager.getTransactionTimeout() * 1000 ); - _resManager.setTxConnection( xid, _txConn ); - } - catch ( SQLException except ) - { - // If error occured at this point, we can only - // report it as resource manager error. - if ( _resManager.getLogWriter() != null ) - _resManager.getLogWriter().println( "XAConnection: failed to begin a transaction: " + except ); - throw new XAException( XAException.XAER_RMERR ); - } - - try - { - _txConn.conn.setAutoCommit( false ); - try - { - if ( _resManager.isolationLevel() != Connection.TRANSACTION_NONE ) - _txConn.conn.setTransactionIsolation( _resManager.isolationLevel() ); - } - catch ( SQLException e ) - { - // The underlying driver might not support this - // isolation level that we use by default. - } - if ( _txConn.conn instanceof TwoPhaseConnection ) - ( (TwoPhaseConnection) _txConn.conn ).enableSQLTransactions( false ); - } - catch ( SQLException except ) - { - // If error occured at this point, we can only - // report it as resource manager error. - if ( _resManager.getLogWriter() != null ) - _resManager.getLogWriter().println( "XAConnection: failed to begin a transaction: " + except ); - throw new XAException( XAException.XAER_RMERR ); - } - } - else if ( flags == TMJOIN || flags == TMRESUME ) - { - // We are joining another transaction with an - // existing TxConnection. - _txConn = _resManager.getTxConnection( xid ); - if ( _txConn == null ) - throw new XAException( XAException.XAER_INVAL ); - - // Update the number of XAConnections sharing this - // transaction connection. - if ( flags == TMJOIN && _txConn.count == 0 ) - throw new XAException( XAException.XAER_PROTO ); - ++_txConn.count; - - // If we already have an underlying connection (as we can - // expect to), we should release that underlying connection - // and make it available to the resource manager. - if ( _underlying != null ) - { - _resManager.releaseConnection( _underlying ); - _underlying = null; - } - } - else - // No other flags supported in start(). - throw new XAException( XAException.XAER_INVAL ); - } - } - - - public synchronized void end( Xid xid, int flags ) - throws XAException - { - // General checks. - if ( xid == null ) - throw new XAException( XAException.XAER_INVAL ); - // Note: we could get end with success or failure even it - // we were previously excluded from the transaction. - if ( _txConn == null && flags == TMSUSPEND ) - throw new XAException( XAException.XAER_NOTA ); - - synchronized ( _resManager ) - { - if ( flags == TMSUCCESS || flags == TMFAIL) - { - // We are now leaving a transaction we started or - // joined before. We can expect any of prepare/ - // commit/rollback to be called next, so TxConnection - // is still valid. - - // If we were suspended from the transaction, we'll - // join it for the duration of this operation. - // Make sure the reference count reaches zero by the - // time we get to prepare. - if ( _txConn == null ) - { - _txConn = _resManager.getTxConnection( xid ); - if ( _txConn == null ) - throw new XAException( XAException.XAER_NOTA ); - } - else - { - if ( _txConn.xid != null && ! _txConn.xid.equals( xid ) ) - throw new XAException( XAException.XAER_NOTA ); - --_txConn.count; - } - - // If transaction failed, we can rollback the - // transaction and release the underlying connection. - // We can expect all other resources to recieved the - // same end notification. We don't expect forget to happen. - if ( flags == TMFAIL && _txConn.conn != null ) - { - try - { - if ( _txConn.conn instanceof TwoPhaseConnection ) - ( (TwoPhaseConnection) _txConn.conn ).enableSQLTransactions( true ); - _txConn.conn.rollback(); - _resManager.releaseConnection( _txConn.conn ); - } - catch ( SQLException except ) - { - // There is a problem with the underlying - // connection, but it was not added to the poll. - } - _resManager.setTxConnection( _txConn.xid, null ); - _txConn.conn = null; - _txConn.xid = null; - } - - if ( flags == TMSUCCESS) - { - // We should be looking for a new transaction. - // Next thing we might be participating in a new - // transaction while the current one is being - // rolled back. - _txConn = null; - } - } - else if ( flags == TMSUSPEND ) - { - // We no longer take part in this transaction. - // Possibly we'll be asked to resume later on, but - // right now we have to forget about the transaction - // and the underlying connection. - --_txConn.count; - _txConn = null; - } - else - // No other flags supported in end(). - throw new XAException( XAException.XAER_INVAL ); - } - } - - - public synchronized void forget( Xid xid ) - throws XAException - { - TxConnection txConn; - - // General checks. - if ( xid == null ) - throw new XAException( XAException.XAER_INVAL ); - synchronized ( _resManager ) - { - // We have to forget about the transaction, meaning the - // transaction no longer exists for this or any other - // connection. We might be called multiple times. - txConn = _resManager.setTxConnection( xid, null ); - if ( _txConn == txConn ) - _txConn = null; - if ( txConn != null ) - { - if ( txConn.conn != null ) - { - _resManager.releaseConnection( txConn.conn ); - txConn.conn = null; - } - txConn.xid = null; - } - } - } - - - public synchronized int prepare( Xid xid ) - throws XAException - { - TxConnection txConn; - - // General checks. - if ( xid == null ) - throw new XAException( XAException.XAER_INVAL ); - - synchronized ( _resManager ) - { - // Technically, prepare may be called for any connection, - // not just this one. - txConn = _resManager.getTxConnection( xid ); - if ( txConn == null ) - throw new XAException( XAException.XAER_NOTA ); - - // This is an error and should never happen. All other - // parties in the transaction should have left it before. - if ( txConn.count > 0 ) - throw new XAException( XAException.XAER_PROTO ); - - // If the transaction failed, we have to force a rollback. - // We track the case of failure due to a timeout. - if ( txConn.timedOut ) - throw new XAException( XAException.XA_RBTIMEOUT ); - if ( txConn.conn == null ) - throw new XAException( XAException.XA_RBROLLBACK ); - - // Since there is no preparation mechanism in a generic - // JDBC driver, we only test for read-only transaction - // but do not commit at this point. - try - { - txConn.prepared = true; - if ( txConn.conn instanceof TwoPhaseConnection ) - { - // For 2pc connection we ask it to prepare and determine - // whether it's commiting or read-only. If a rollback - // exception happens, we report it. - try - { - if ( ( (TwoPhaseConnection) txConn.conn ).prepare() ) - return XA_OK; - else - { - txConn.readOnly = true; - return XA_RDONLY; - } - } - catch ( SQLException except ) - { - throw new XAException( XAException.XA_RBROLLBACK ); - } - } - else - { - // For standard connection we cannot prepare, we can - // only guess if it's read only. - if ( txConn.conn.isReadOnly() ) - { - txConn.readOnly = true; - return XA_RDONLY; - } - return XA_OK; - } - } - catch ( SQLException except ) - { - try - { - // Fatal error in the connection, kill it. - txConn.conn.close(); - } - catch ( SQLException e ) - { } - txConn.conn = null; - if ( _resManager.getLogWriter() != null ) - _resManager.getLogWriter().println( "XAConnection: failed to commit a transaction: " + except ); - // If we cannot commit the transaction, force a rollback. - throw new XAException( XAException.XA_RBROLLBACK ); - } - } - } - - - public Xid[] recover( int flags ) - throws XAException - { - synchronized ( _resManager ) - { - return _resManager.getTxRecover(); - } - } - - - public synchronized void commit( Xid xid, boolean onePhase ) - throws XAException - { - TxConnection txConn; - - // General checks. - if ( xid == null ) - throw new XAException( XAException.XAER_INVAL ); - - synchronized ( _resManager ) - { - // Technically, commit may be called for any connection, - // not just this one. - txConn = _resManager.getTxConnection( xid ); - if ( txConn == null ) - throw new XAException( XAException.XAER_NOTA ); - - // If the transaction failed, we have to force - // a rollback. - if ( txConn.conn == null ) - throw new XAException( XAException.XA_RBROLLBACK ); - - // If connection has been prepared and is read-only, - // nothing to do at this stage. - if ( txConn.readOnly ) - return; - - // This must be a one-phase commite, or the connection - // should have been prepared before. - if ( onePhase || txConn.prepared ) - { - try - { - // Prevent multiple commit attempts. - txConn.readOnly = true; - if ( txConn.conn instanceof TwoPhaseConnection ) - ( (TwoPhaseConnection) txConn.conn ).enableSQLTransactions( true ); - txConn.conn.commit(); - } - catch ( SQLException except ) - { - try - { - // Unknown error in the connection, better kill it. - txConn.conn.close(); - } - catch ( SQLException e ) - { } - txConn.conn = null; - if ( _resManager.getLogWriter() != null ) - _resManager.getLogWriter().println( "XAConnection: failed to commit a transaction: " + except ); - // If we cannot commit the transaction, a heuristic tollback. - throw new XAException( XAException.XA_HEURRB ); - } - } - else - { - // 2pc we should have prepared before. - if ( ! txConn.prepared ) - throw new XAException( XAException.XAER_PROTO ); - } - } - } - - - public synchronized void rollback( Xid xid ) - throws XAException - { - TxConnection txConn; - - - // General checks. - if ( xid == null ) - throw new XAException( XAException.XAER_INVAL ); - - synchronized ( _resManager ) - { - // Technically, rollback may be called for any connection, - // not just this one. - txConn = _resManager.getTxConnection( xid ); - if ( txConn == null ) - throw new XAException( XAException.XAER_NOTA ); - - // If connection has been prepared and is read-only, - // nothing to do at this stage. If connection has - // been terminated any other way, nothing to do - // either. - if ( txConn.readOnly || txConn.conn == null ) - return; - - try - { - txConn.prepared = false; - if ( txConn.conn instanceof TwoPhaseConnection ) - ( (TwoPhaseConnection) txConn.conn ).enableSQLTransactions( true ); - txConn.conn.rollback(); - } - catch ( SQLException except ) - { - try - { - // Unknown error in the connection, better kill it. - txConn.conn.close(); - } - catch ( SQLException e ) - { } - txConn.conn = null; - if ( _resManager.getLogWriter() != null ) - _resManager.getLogWriter().println( "XAConnection: failed to rollback a transaction: " + except ); - // If we cannot commit the transaction, a heuristic tollback. - throw new XAException( XAException.XA_RBROLLBACK ); - } - finally - { - forget( xid ); - } - } - } - - - public synchronized boolean isSameRM( XAResource xaRes ) - throws XAException - { - // Two resource managers are equal if they produce equivalent - // connection (i.e. same database, same user). If the two are - // equivalent they would share a transaction by joining. - if ( xaRes == null || ! ( xaRes instanceof XAConnectionImpl ) ) - return false; - if ( _resManager.equals( ( (XAConnectionImpl) xaRes )._resManager ) ) - return true; - return false; - } - - - public synchronized boolean setTransactionTimeout( int seconds ) - throws XAException - { - if ( seconds < 0 ) - throw new XAException( XAException.XAER_INVAL ); - // Zero resets to the default for all transactions. - if ( seconds == 0 ) - seconds = _resManager.getTransactionTimeout(); - // If a transaction has started, change it's timeout to the new value. - if ( _txConn != null ) - { - _txConn.timeout = _txConn.started + ( seconds * 1000 ); - return true; - } - return false; - } - - - public int getTransactionTimeout() - { - long timeout; - - if ( _txConn == null ) - return 0; - return (int) ( _txConn.timeout - _txConn.started ) / 1000; - } - - - /* - * Returns true if this connection is inside a global transaction. - * If the connection is inside a global transaction it will not - * allow commit/rollback directly from the {@link - * java.sql.Connection} interface. - */ - boolean insideGlobalTx() - { - return ( _txConn != null ); - } - - /* - * Called to obtain the underlying connections. If this connection - * is part of a transaction, the transction's underlying connection - * is returned, or an exception is thrown if the connection was - * terminated due to timeout. If this connection is not part of a - * transaction, a non-transactional connection is returned. - * - * @param clientId The {@link ClientConnection} identifier - */ - Connection getUnderlying( int clientId ) - throws SQLException - { - // If we were notified of the client closing, or have been - // requested to have a new client connection since then, - // the client id will not match to that of the caller. - // We use that to decide that the caller has been closed. - if ( clientId != _clientId ) - throw new SQLException( "This application connection has been closed" ); - - if ( _txConn != null ) - { - if ( _txConn.timedOut ) - throw new SQLException( "The transaction has timed out and has been rolledback and closed" ); - if ( _txConn.conn == null ) - throw new SQLException( "The transaction has been terminated and this connection has been closed" ); - return _txConn.conn; - } - if ( _underlying == null ) - { - _underlying = _resManager.newConnection(); - _underlying.setAutoCommit( true ); - } - return _underlying; - } - - -} - - - |
