diff options
Diffstat (limited to 'src/interfaces/jdbc/org/postgresql/xa/XADataSourceImpl.java')
| -rw-r--r-- | src/interfaces/jdbc/org/postgresql/xa/XADataSourceImpl.java | 489 |
1 files changed, 0 insertions, 489 deletions
diff --git a/src/interfaces/jdbc/org/postgresql/xa/XADataSourceImpl.java b/src/interfaces/jdbc/org/postgresql/xa/XADataSourceImpl.java deleted file mode 100644 index ae34143cb2..0000000000 --- a/src/interfaces/jdbc/org/postgresql/xa/XADataSourceImpl.java +++ /dev/null @@ -1,489 +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: XADataSourceImpl.java,v 1.4 2001/11/19 23:16:46 momjian Exp $ -*/ - - -package org.postgresql.xa; - - -import java.io.Serializable; -import java.io.PrintWriter; -import java.util.Hashtable; -import java.util.Vector; -import java.util.Stack; -import java.util.Enumeration; -import java.sql.Connection; -import java.sql.SQLException; - -import javax.sql.DataSource; -import javax.sql.PooledConnection; -import javax.sql.ConnectionPoolDataSource; -import javax.sql.XAConnection; -import javax.sql.XADataSource; -import javax.transaction.xa.Xid; - - - -/* - * Implements a JDBC 2.0 {@link XADataSource} for any JDBC driver - * with JNDI persistance support. The base implementation is actually - * provided by a different {@link DataSource} class; although this is - * the super class, it only provides the pooling and XA specific - * implementation. - * - * - * @author <a href="arkin@exoffice.com">Assaf Arkin</a> - * @version 1.0 - */ -public abstract class XADataSourceImpl - implements DataSource, ConnectionPoolDataSource, - XADataSource, Serializable, Runnable -{ - - - /* - * Maps underlying JDBC connections into global transaction Xids. - */ - private transient Hashtable _txConnections = new Hashtable(); - - - /* - * This is a pool of free underlying JDBC connections. If two - * XA connections are used in the same transaction, the second - * one will make its underlying JDBC connection available to - * the pool. This is not a real connection pool, only a marginal - * efficiency solution for dealing with shared transactions. - */ - private transient Stack _pool = new Stack(); - - - /* - * A background deamon thread terminating connections that have - * timed out. - */ - private transient Thread _background; - - - /* - * The default timeout for all new transactions. - */ - private int _txTimeout = DEFAULT_TX_TIMEOUT; - - - /* - * The default timeout for all new transactions is 10 seconds. - */ - public final static int DEFAULT_TX_TIMEOUT = 10; - - - - - /* - * Implementation details: - * If two XAConnections are associated with the same transaction - * (one with a start the other with a join) they must use the - * same underlying JDBC connection. They lookup the underlying - * JDBC connection based on the transaction's Xid in the - * originating XADataSource. - * - * Currently the XADataSource must be the exact same object, - * this should be changed so all XADataSources that are equal - * share a table of all enlisted connections - * - * To test is two connections should fall under the same - * transaction we match the resource managers by comparing the - * database/user they fall under using a comparison of the - * XADataSource properties. - */ - - - public XADataSourceImpl() - { - super(); - - // Create a background thread that will track transactions - // that timeout, abort them and release the underlying - // connections to the pool. - _background = new Thread( this, "XADataSource Timeout Daemon" ); - _background.setPriority( Thread.MIN_PRIORITY ); - _background.setDaemon( true ); - _background.start(); - } - - - public XAConnection getXAConnection() - throws SQLException - { - // Construct a new XAConnection with no underlying connection. - // When a JDBC method requires an underlying connection, one - // will be created. We don't create the underlying connection - // beforehand, as it might be coming from an existing - // transaction. - return new XAConnectionImpl( this, null ); - } - - - public XAConnection getXAConnection( String user, String password ) - throws SQLException - { - // Since we create the connection on-demand with newConnection - // or obtain it from a transaction, we cannot support XA - // connections with a caller specified user name. - throw new SQLException( "XAConnection does not support connections with caller specified user name" ); - } - - - public PooledConnection getPooledConnection() - throws SQLException - { - // Construct a new pooled connection and an underlying JDBC - // connection to go along with it. - return new XAConnectionImpl( this, getConnection() ); - } - - - public PooledConnection getPooledConnection( String user, String password ) - throws SQLException - { - // Construct a new pooled connection and an underlying JDBC - // connection to go along with it. - return new XAConnectionImpl( this, getConnection( user, password ) ); - } - - - /* - * Returns the default timeout for all transactions. - */ - public int getTransactionTimeout() - { - return _txTimeout; - } - - - /* - * This method is defined in the interface and implemented in the - * derived class, we re-define it just to make sure it does not - * throw an {@link SQLException} and that we do not need to - * catch one. - */ - public abstract java.io.PrintWriter getLogWriter(); - - - /* - * Sets the default timeout for all transactions. The timeout is - * specified in seconds. Use zero for the default timeout. Calling - * this method does not affect transactions in progress. - * - * @param seconds The timeout in seconds - */ - public void setTransactionTimeout( int seconds ) - { - if ( seconds <= 0 ) - _txTimeout = DEFAULT_TX_TIMEOUT; - else - _txTimeout = seconds; - _background.interrupt(); - } - - - /* - * Returns an underlying connection for the global transaction, - * if one has been associated before. - * - * @param xid The transaction Xid - * @return A connection associated with that transaction, or null - */ - TxConnection getTxConnection( Xid xid ) - { - return (TxConnection) _txConnections.get( xid ); - } - - - /* - * Associates the global transaction with an underlying connection, - * or dissociate it when null is passed. - * - * @param xid The transaction Xid - * @param conn The connection to associate, null to dissociate - */ - TxConnection setTxConnection( Xid xid, TxConnection txConn ) - { - if ( txConn == null ) - return (TxConnection) _txConnections.remove( xid ); - else - return (TxConnection) _txConnections.put( xid, txConn ); - } - - - /* - * Release an unused connection back to the pool. If an XA - * connection has been asked to join an existing transaction, - * it will no longer use it's own connection and make it available - * to newly created connections. - * - * @param conn An open connection that is no longer in use - */ - void releaseConnection( Connection conn ) - { - _pool.push( conn ); - } - - - /* - * Creates a new underlying connection. Used by XA connection - * that lost it's underlying connection when joining a - * transaction and is now asked to produce a new connection. - * - * @return An open connection ready for use - * @throws SQLException An error occured trying to open - * a connection - */ - Connection newConnection() - throws SQLException - { - Connection conn; - - // Check in the pool first. - if ( ! _pool.empty() ) - { - conn = (Connection) _pool.pop(); - return conn; - } - return getConnection(); - } - - - /* - * XXX Not fully implemented yet and no code to really - * test it. - */ - Xid[] getTxRecover() - { - Vector list; - Enumeration enum; - TxConnection txConn; - - list = new Vector(); - enum = _txConnections.elements(); - while ( enum.hasMoreElements() ) - { - txConn = (TxConnection) enum.nextElement(); - if ( txConn.conn != null && txConn.prepared ) - list.add( txConn.xid ); - } - return (Xid[]) list.toArray(); - } - - - /* - * Returns the transaction isolation level to use with all newly - * created transactions, or {@link Connection#TRANSACTION_NONE} - * if using the driver's default isolation level. - */ - public int isolationLevel() - { - return Connection.TRANSACTION_NONE; - } - - - public void run() - { - Enumeration enum; - int reduce; - long timeout; - TxConnection txConn; - - while ( true ) - { - // Go to sleep for the duration of a transaction - // timeout. This mean transactions will timeout on average - // at _txTimeout * 1.5. - try - { - Thread.sleep( _txTimeout * 1000 ); - } - catch ( InterruptedException except ) - {} - - try - { - // Check to see if there are any pooled connections - // we can release. We release 10% of the pooled - // connections each time, so in a heavy loaded - // environment we don't get to release that many, but - // as load goes down we do. These are not actually - // pooled connections, but connections that happen to - // get in and out of a transaction, not that many. - reduce = _pool.size() - ( _pool.size() / 10 ) - 1; - if ( reduce >= 0 && _pool.size() > reduce ) - { - if ( getLogWriter() != null ) - getLogWriter().println( "DataSource " + toString() + - ": Reducing internal connection pool size from " + - _pool.size() + " to " + reduce ); - while ( _pool.size() > reduce ) - { - try - { - ( (Connection) _pool.pop() ).close(); - } - catch ( SQLException except ) - { } - } - } - } - catch ( Exception except ) - { } - - // Look for all connections inside a transaction that - // should have timed out by now. - - - timeout = System.currentTimeMillis(); - enum = _txConnections.elements(); - while ( enum.hasMoreElements() ) - { - txConn = (TxConnection) enum.nextElement(); - // If the transaction timed out, we roll it back and - // invalidate it, but do not remove it from the transaction - // list yet. We wait for the next iteration, minimizing the - // chance of a NOTA exception. - if ( txConn.conn == null ) - { - _txConnections.remove( txConn.xid ); - // Chose not to use an iterator so we must - // re-enumerate the list after removing - // an element from it. - enum = _txConnections.elements(); - } - else if ( txConn.timeout < timeout ) - { - - try - { - Connection underlying; - - synchronized ( txConn ) - { - if ( txConn.conn == null ) - continue; - if ( getLogWriter() != null ) - getLogWriter().println( "DataSource " + toString() + - ": Transaction timed out and being aborted: " + - txConn.xid ); - // Remove the connection from the transaction - // association. XAConnection will now have - // no underlying connection and attempt to - // create a new one. - underlying = txConn.conn; - txConn.conn = null; - txConn.timedOut = true; - - // Rollback the underlying connection to - // abort the transaction and release the - // underlying connection to the pool. - try - { - underlying.rollback(); - releaseConnection( underlying ); - } - catch ( SQLException except ) - { - if ( getLogWriter() != null ) - getLogWriter().println( "DataSource " + toString() + - ": Error aborting timed out transaction: " + except ); - try - { - underlying.close(); - } - catch ( SQLException e2 ) - { } - } - } - } - catch ( Exception except ) - { } - - } - } - } - } - - - - public void debug( PrintWriter writer ) - { - Enumeration enum; - TxConnection txConn; - StringBuffer buffer; - - writer.println( "Debug info for XADataSource:" ); - enum = _txConnections.elements(); - if ( ! enum.hasMoreElements() ) - writer.println( "Empty" ); - while ( enum.hasMoreElements() ) - { - buffer = new StringBuffer(); - txConn = (TxConnection) enum.nextElement(); - buffer.append( "TxConnection " ); - if ( txConn.xid != null ) - buffer.append( txConn.xid ); - if ( txConn.conn != null ) - buffer.append( ' ' ).append( txConn.conn ); - buffer.append( " count: " ).append( txConn.count ); - if ( txConn.prepared ) - buffer.append( " prepared" ); - if ( txConn.timedOut ) - buffer.append( " timed-out" ); - if ( txConn.readOnly ) - buffer.append( " read-only" ); - writer.println( buffer.toString() ); - } - enum = _pool.elements(); - while ( enum.hasMoreElements() ) - writer.println( "Pooled underlying: " + enum.nextElement().toString() ); - } - - -} |
