org.logicalcobwebs.proxool
Class ConnectionPool

java.lang.Object
  extended by org.logicalcobwebs.proxool.ConnectionPool
All Implemented Interfaces:
ConnectionPoolStatisticsIF

 class ConnectionPool
extends java.lang.Object
implements ConnectionPoolStatisticsIF

This is where most things happen. (In fact, probably too many things happen in this one class).

Version:
$Revision: 1.82 $, $Date: 2005/10/07 08:19:05 $
Author:
billhorsman, $Author: billhorsman $ (current maintainer)

Field Summary
private  Admin admin
           
private  CompositeConnectionListener compositeConnectionListener
           
private  CompositeStateListener compositeStateListener
           
private  int[] connectionCountByState
          This keeps a count of how many connections there are in each state
private  boolean connectionPoolUp
           
private  ConnectionResetter connectionResetter
          Initialised in constructor.
private  long connectionsRefusedCount
           
private  long connectionsServedCount
           
private  ReaderPreferenceReadWriteLock connectionStatusReadWriteLock
           
private  ConnectionValidatorIF connectionValidator
           
private  java.util.Date dateStarted
           
private  ConnectionPoolDefinition definition
           
protected static boolean FORCE_EXPIRY
           
private  boolean locked
           
private  Log log
          Here we deviate from the standard of using the classname for the log name.
private static Log LOG
          Use this for messages that aren't useful for the pool specific log
private static boolean loggedLegend
           
private static java.lang.String MSG_MAX_CONNECTION_COUNT
           
private  int nextAvailableConnection
          This is the "round robin" that makes sure we use all the connections
private  WriterPreferenceReadWriteLock primaryReadWriteLock
          If you want to shutdown the pool you should get a write lock on this.
private  Prototyper prototyper
           
private  java.util.List proxyConnections
          This is the pool itself
protected static boolean REQUEST_EXPIRY
           
private  java.lang.Thread shutdownThread
          This gets set during shutdown(int, java.lang.String).
private static java.lang.String[] STATUS_DESCRIPTIONS
           
private  long timeOfLastRefusal
           
private  int upState
           
 
Constructor Summary
protected ConnectionPool(ConnectionPoolDefinition definition)
           
 
Method Summary
protected  void acquireConnectionStatusReadLock()
           
protected  void acquireConnectionStatusWriteLock()
           
protected  void acquirePrimaryReadLock()
          Call this if you want to do something important to the pool.
protected  void acquirePrimaryWriteLock()
          Call this everytime you build a connection.
 void addConnectionListener(ConnectionListenerIF connectionListener)
           
protected  boolean addProxyConnection(ProxyConnectionIF proxyConnection)
          Add a ProxyConnection to the pool
 void addStateListener(StateListenerIF stateListener)
           
protected  boolean attemptConnectionStatusReadLock(long msecs)
           
protected  void changeStatus(int oldStatus, int newStatus)
          You should acquire a write lock before calling this method
protected  java.lang.String displayStatistics()
           
protected  void expireAllConnections(java.lang.String reason, boolean merciful)
           
 boolean expireConnection(long id, boolean forceExpiry)
          Manually expire a connection.
protected  void expireConnectionAsSoonAsPossible(ProxyConnectionIF proxyConnection, java.lang.String reason, boolean merciful)
           
protected  void expireProxyConnection(ProxyConnectionIF proxyConnection, java.lang.String reason, boolean forceExpiry)
           
 int getActiveConnectionCount()
          You should acquire a read lock if you want this to be accurate (but that might have an impact on the performance of your pool).
protected  Admin getAdmin()
          Get the admin for this pool
 int getAvailableConnectionCount()
          You should acquire a read lock if you want this to be accurate (but that might have an impact on the performance of your pool).
protected  java.sql.Connection getConnection()
          Get a connection from the pool.
 long getConnectionCount()
           
protected  java.util.Collection getConnectionInfos()
           
 long getConnectionsRefusedCount()
          The number of connections refused.
 long getConnectionsServedCount()
          The number of connections provided.
 java.util.Date getDateStarted()
          When this pool was started
protected  ConnectionPoolDefinition getDefinition()
           
 Log getLog()
           
 int getOfflineConnectionCount()
          You should acquire a read lock if you want this to be accurate (but that might have an impact on the performance of your pool).
protected  Prototyper getPrototyper()
           
private  ProxyConnectionIF getProxyConnection(int i)
          Get a ProxyConnection by index
protected  ProxyConnectionIF[] getProxyConnections()
          Return an array of all the connections
protected static java.lang.String getStatusDescription(int status)
           
protected  long getTimeOfLastRefusal()
          The time (in milliseconds) that we last refused a connection
 int getUpState()
           
protected  void initialiseConnectionResetter(java.sql.Connection connection)
          Initialises the ConnectionResetter.
protected  boolean isConnectionListenedTo()
          Is there a listener for connections
protected  boolean isConnectionPoolUp()
          Is the pool up?
protected  boolean isLocked()
           
protected  void lock()
           
protected  void onBirth(java.sql.Connection connection)
          Call the onBirth() method on each StateListenerIF .
protected  void onDeath(java.sql.Connection connection)
          Call the onDeath() method on each StateListenerIF .
protected  void onExecute(java.lang.String command, long elapsedTime, java.lang.Exception exception)
          Call the onExecute() method on each StateListenerIF .
protected  void putConnection(ProxyConnectionIF proxyConnection)
          When you have finished with a Connection you should put it back here.
protected  void registerRemovedConnection(int status)
           
protected  void releaseConnectionStatusReadLock()
           
protected  void releaseConnectionStatusWriteLock()
           
protected  void releasePrimaryReadLock()
           
protected  void releasePrimaryWriteLock()
           
 boolean removeConnectionListener(ConnectionListenerIF connectionListener)
           
protected  void removeProxyConnection(ProxyConnectionIF proxyConnection, java.lang.String reason, boolean forceExpiry, boolean triggerSweep)
          Remove a ProxyConnection by calling its onDeath event, closing it (for real) and then removing it from the list.
 boolean removeStateListener(StateListenerIF stateListener)
           
protected  boolean resetConnection(java.sql.Connection connection, java.lang.String id)
          Resets a Connection to its original state.
 void setConnectionListener(ConnectionListenerIF connectionListener)
          Deprecated. use addConnectionListener(ConnectionListenerIF) instead.
protected  void setDefinition(ConnectionPoolDefinition definition)
          Changes both the way that any new connections will be made, and the behaviour of the pool.
 void setStateListener(StateListenerIF stateListener)
          Deprecated. use addStateListener(StateListenerIF) instead.
 void setUpState(int upState)
           
protected  void shutdown(int delay, java.lang.String finalizerName)
          Call this to shutdown gracefully.
protected  void start()
          Starts up house keeping and prototyper threads.
private  boolean testConnection(ProxyConnectionIF proxyConnection)
          Test the connection (if required) If the connection fails the test, it is removed from the pool.
protected  void throwConnection(ProxyConnectionIF proxyConnection, java.lang.String reason)
          This means that there's something wrong the connection and it's probably best if no one uses it again.
 java.lang.String toString()
           
protected  void unlock()
           
 
Methods inherited from class java.lang.Object
clone, equals, finalize, getClass, hashCode, notify, notifyAll, wait, wait, wait
 

Field Detail

LOG

private static final Log LOG
Use this for messages that aren't useful for the pool specific log


log

private Log log
Here we deviate from the standard of using the classname for the log name. Here we want to use the alias for the pool so that we can log each pool to different places. So we have to instantiate the log later.


connectionStatusReadWriteLock

private ReaderPreferenceReadWriteLock connectionStatusReadWriteLock

primaryReadWriteLock

private WriterPreferenceReadWriteLock primaryReadWriteLock
If you want to shutdown the pool you should get a write lock on this. And if you use the pool then get a read lock. This stops us trying to shutdown the pool whilst it is in use. Only, we don't want to delay shutdown just because some greedy user has got a connection active. Shutdown should be relatively immediate. So we don't ask for a read lock for the whole time that a connection is active.


STATUS_DESCRIPTIONS

private static final java.lang.String[] STATUS_DESCRIPTIONS

MSG_MAX_CONNECTION_COUNT

private static final java.lang.String MSG_MAX_CONNECTION_COUNT
See Also:
Constant Field Values

proxyConnections

private java.util.List proxyConnections
This is the pool itself


nextAvailableConnection

private int nextAvailableConnection
This is the "round robin" that makes sure we use all the connections


connectionsServedCount

private long connectionsServedCount

connectionsRefusedCount

private long connectionsRefusedCount

connectionCountByState

private int[] connectionCountByState
This keeps a count of how many connections there are in each state


definition

private ConnectionPoolDefinition definition

compositeConnectionListener

private CompositeConnectionListener compositeConnectionListener

compositeStateListener

private CompositeStateListener compositeStateListener

timeOfLastRefusal

private long timeOfLastRefusal

upState

private int upState

loggedLegend

private static boolean loggedLegend

admin

private Admin admin

locked

private boolean locked

dateStarted

private java.util.Date dateStarted

connectionPoolUp

private boolean connectionPoolUp

shutdownThread

private java.lang.Thread shutdownThread
This gets set during shutdown(int, java.lang.String). We use it to notify shutdown that all connections are now non-active.


prototyper

private Prototyper prototyper

connectionResetter

private ConnectionResetter connectionResetter
Initialised in constructor.


connectionValidator

private ConnectionValidatorIF connectionValidator

FORCE_EXPIRY

protected static final boolean FORCE_EXPIRY
See Also:
Constant Field Values

REQUEST_EXPIRY

protected static final boolean REQUEST_EXPIRY
See Also:
Constant Field Values
Constructor Detail

ConnectionPool

protected ConnectionPool(ConnectionPoolDefinition definition)
                  throws ProxoolException
Throws:
ProxoolException
Method Detail

start

protected void start()
              throws ProxoolException
Starts up house keeping and prototyper threads.

Throws:
ProxoolException

getConnection

protected java.sql.Connection getConnection()
                                     throws java.sql.SQLException
Get a connection from the pool. If none are available or there was an Exception then an exception is thrown and something written to the log

Throws:
java.sql.SQLException

testConnection

private boolean testConnection(ProxyConnectionIF proxyConnection)
Test the connection (if required) If the connection fails the test, it is removed from the pool. If no ConnectionValidatorIF is defined, then the test always succeed.

Parameters:
proxyConnection - the connection to test
Returns:
TRUE if the connection pass the test, FALSE if it fails

addProxyConnection

protected boolean addProxyConnection(ProxyConnectionIF proxyConnection)
Add a ProxyConnection to the pool

Parameters:
proxyConnection - new connection
Returns:
true if the connection was added or false if it wasn't (for instance, if the definition it was built with is out of date).

getStatusDescription

protected static java.lang.String getStatusDescription(int status)

putConnection

protected void putConnection(ProxyConnectionIF proxyConnection)
When you have finished with a Connection you should put it back here. That will make it available to others. Unless it's due for expiry, in which case it will... expire


throwConnection

protected void throwConnection(ProxyConnectionIF proxyConnection,
                               java.lang.String reason)
This means that there's something wrong the connection and it's probably best if no one uses it again.


getProxyConnection

private ProxyConnectionIF getProxyConnection(int i)
Get a ProxyConnection by index


getProxyConnections

protected ProxyConnectionIF[] getProxyConnections()
Return an array of all the connections

Returns:
array of connections

removeProxyConnection

protected void removeProxyConnection(ProxyConnectionIF proxyConnection,
                                     java.lang.String reason,
                                     boolean forceExpiry,
                                     boolean triggerSweep)
Remove a ProxyConnection by calling its onDeath event, closing it (for real) and then removing it from the list.

Parameters:
proxyConnection - the connection to remove
reason - for log audit
forceExpiry - true means close now, whether it is active or not; false means if it is active then merely mark it for expiry so that it is removed as soon as it finished being active
triggerSweep - if true then this removal will trigger a prototype sweep

expireProxyConnection

protected void expireProxyConnection(ProxyConnectionIF proxyConnection,
                                     java.lang.String reason,
                                     boolean forceExpiry)

shutdown

protected void shutdown(int delay,
                        java.lang.String finalizerName)
                 throws java.lang.Throwable
Call this to shutdown gracefully.

Parameters:
delay - how long to wait for connections to become free before forcing them to close anyway
Throws:
java.lang.Throwable

getAvailableConnectionCount

public int getAvailableConnectionCount()
You should acquire a read lock if you want this to be accurate (but that might have an impact on the performance of your pool).

Specified by:
getAvailableConnectionCount in interface ConnectionPoolStatisticsIF
Returns:
availableConnectionCount
See Also:
ConnectionPoolStatisticsIF.getAvailableConnectionCount()

getActiveConnectionCount

public int getActiveConnectionCount()
You should acquire a read lock if you want this to be accurate (but that might have an impact on the performance of your pool).

Specified by:
getActiveConnectionCount in interface ConnectionPoolStatisticsIF
Returns:
activeConnectionCount
See Also:
ConnectionPoolStatisticsIF.getActiveConnectionCount()

getOfflineConnectionCount

public int getOfflineConnectionCount()
You should acquire a read lock if you want this to be accurate (but that might have an impact on the performance of your pool).

Specified by:
getOfflineConnectionCount in interface ConnectionPoolStatisticsIF
Returns:
offlineConnectionCount
See Also:
ConnectionPoolStatisticsIF.getOfflineConnectionCount()

displayStatistics

protected java.lang.String displayStatistics()

expireAllConnections

protected void expireAllConnections(java.lang.String reason,
                                    boolean merciful)

expireConnectionAsSoonAsPossible

protected void expireConnectionAsSoonAsPossible(ProxyConnectionIF proxyConnection,
                                                java.lang.String reason,
                                                boolean merciful)

registerRemovedConnection

protected void registerRemovedConnection(int status)

changeStatus

protected void changeStatus(int oldStatus,
                            int newStatus)
You should acquire a write lock before calling this method

Parameters:
oldStatus - so we know which count to decrement
newStatus - so we know which count to increment

getConnectionsServedCount

public long getConnectionsServedCount()
Description copied from interface: ConnectionPoolStatisticsIF
The number of connections provided.

Specified by:
getConnectionsServedCount in interface ConnectionPoolStatisticsIF
Returns:
connectionsServedCount

getConnectionsRefusedCount

public long getConnectionsRefusedCount()
Description copied from interface: ConnectionPoolStatisticsIF
The number of connections refused. Either because there was a problem connecting to the database, or perhaps because the maximumConnectionCount was reached.

Specified by:
getConnectionsRefusedCount in interface ConnectionPoolStatisticsIF
Returns:
connectionsRefusedCount

getDefinition

protected ConnectionPoolDefinition getDefinition()

setDefinition

protected void setDefinition(ConnectionPoolDefinition definition)
                      throws ProxoolException
Changes both the way that any new connections will be made, and the behaviour of the pool. Consider calling expireAllConnections() if you're in a hurry.

Throws:
ProxoolException

setStateListener

public void setStateListener(StateListenerIF stateListener)
Deprecated. use addStateListener(StateListenerIF) instead.


addStateListener

public void addStateListener(StateListenerIF stateListener)

removeStateListener

public boolean removeStateListener(StateListenerIF stateListener)

setConnectionListener

public void setConnectionListener(ConnectionListenerIF connectionListener)
Deprecated. use addConnectionListener(ConnectionListenerIF) instead.


addConnectionListener

public void addConnectionListener(ConnectionListenerIF connectionListener)

removeConnectionListener

public boolean removeConnectionListener(ConnectionListenerIF connectionListener)

onBirth

protected void onBirth(java.sql.Connection connection)
                throws java.sql.SQLException
Call the onBirth() method on each StateListenerIF .

Throws:
java.sql.SQLException

onDeath

protected void onDeath(java.sql.Connection connection)
                throws java.sql.SQLException
Call the onDeath() method on each StateListenerIF .

Throws:
java.sql.SQLException

onExecute

protected void onExecute(java.lang.String command,
                         long elapsedTime,
                         java.lang.Exception exception)
                  throws java.sql.SQLException
Call the onExecute() method on each StateListenerIF .

Throws:
java.sql.SQLException

isConnectionListenedTo

protected boolean isConnectionListenedTo()
Is there a listener for connections

Returns:
true if there is a listener registered.

toString

public java.lang.String toString()
Overrides:
toString in class java.lang.Object

getUpState

public int getUpState()

setUpState

public void setUpState(int upState)

getConnectionInfos

protected java.util.Collection getConnectionInfos()

expireConnection

public boolean expireConnection(long id,
                                boolean forceExpiry)
Manually expire a connection.

Parameters:
id - the id of the connection to kill
forceExpiry - use true to expire even if it is in use
Returns:
true if the connection was found and expired, else false

getLog

public Log getLog()

initialiseConnectionResetter

protected void initialiseConnectionResetter(java.sql.Connection connection)
Initialises the ConnectionResetter.

Parameters:
connection - sample Connection to use for default values

resetConnection

protected boolean resetConnection(java.sql.Connection connection,
                                  java.lang.String id)
Resets a Connection to its original state.

Parameters:
connection - the one to reset

getDateStarted

public java.util.Date getDateStarted()
Description copied from interface: ConnectionPoolStatisticsIF
When this pool was started

Specified by:
getDateStarted in interface ConnectionPoolStatisticsIF
Returns:
dateStarted
See Also:
ConnectionPoolStatisticsIF.getDateStarted()

getAdmin

protected Admin getAdmin()
Get the admin for this pool

Returns:
admin

isLocked

protected boolean isLocked()

lock

protected void lock()

unlock

protected void unlock()

acquirePrimaryReadLock

protected void acquirePrimaryReadLock()
                               throws java.lang.InterruptedException
Call this if you want to do something important to the pool. Like shut it down.

Throws:
java.lang.InterruptedException - if we couldn't

releasePrimaryReadLock

protected void releasePrimaryReadLock()
See Also:
acquirePrimaryReadLock()

acquirePrimaryWriteLock

protected void acquirePrimaryWriteLock()
                                throws java.lang.InterruptedException
Call this everytime you build a connection. It ensures that we're not trying to shutdown the pool whilst we are building a connection. So you should check that the pool is still up.

Throws:
java.lang.InterruptedException - if there was a problem.

releasePrimaryWriteLock

protected void releasePrimaryWriteLock()
See Also:
acquirePrimaryReadLock()

isConnectionPoolUp

protected boolean isConnectionPoolUp()
Is the pool up?

Returns:
false is the connection pool has been shutdown (or is in the process of being shutdown).

getTimeOfLastRefusal

protected long getTimeOfLastRefusal()
The time (in milliseconds) that we last refused a connection

Returns:
timeOfLastRefusal

acquireConnectionStatusWriteLock

protected void acquireConnectionStatusWriteLock()

releaseConnectionStatusWriteLock

protected void releaseConnectionStatusWriteLock()

acquireConnectionStatusReadLock

protected void acquireConnectionStatusReadLock()

attemptConnectionStatusReadLock

protected boolean attemptConnectionStatusReadLock(long msecs)

releaseConnectionStatusReadLock

protected void releaseConnectionStatusReadLock()

getPrototyper

protected Prototyper getPrototyper()

getConnectionCount

public long getConnectionCount()
Specified by:
getConnectionCount in interface ConnectionPoolStatisticsIF