Package com.icentris.sql

Source Code of com.icentris.sql.ConnectionPool

package com.icentris.sql;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

import java.sql.*;
import com.icentris.util.CodeTimer;
import com.icentris.util.CodeTimerSegment;
import com.icentris.util.Caller;
import java.util.Timer;
import java.util.TimerTask;
import java.util.*;
import com.icentris.jmx.JMX;
import javax.management.MBeanNotificationInfo;
import javax.management.NotificationBroadcasterSupport;
import javax.management.Notification;

public class ConnectionPool
  extends NotificationBroadcasterSupport
  implements ConnectionPoolMBean
{
   /**
    * Logger for this class
    */
   private static final Log logger = LogFactory.getLog(ConnectionPool.class);

  //--------------------------------------------------------------
  // JMX constants
  //--------------------------------------------------------------
  public static final String NOTIF_CREATECONNECTION  = "ConnectionPool.createConnection";
  public static final String NOTIF_DESTROYCONNECTION = "ConnectionPool.destroyConnection";
  public static final String NOTIF_OPENCONNECTION    = "ConnectionPool.openConnection";
  public static final String NOTIF_PRUNEBEGIN        = "ConnectionPool.pruneBegin";
  public static final String NOTIF_PRUNECONNECTION   = "ConnectionPool.pruneConnection";
  public static final String NOTIF_PRUNEFINISH       = "ConnectionPool.pruneFinish";

  long notificationSequence = 1;

  //--------------------------------------------------------------
  // JMX method
  //--------------------------------------------------------------
  public MBeanNotificationInfo[] getNotificationInfo() {
    return new MBeanNotificationInfo[] {
      new MBeanNotificationInfo( new String[] {NOTIF_CREATECONNECTION}"createConnection",
        "Triggered when a new connection is created and added to the pool"
      ),
      new MBeanNotificationInfo( new String[] {NOTIF_DESTROYCONNECTION}, "destroyConnection",
        "Triggered when a connection is automatically removed from the pool because of strictTimeout, closeOnError, or pool smart-sizing"
      ),
      new MBeanNotificationInfo( new String[] {NOTIF_OPENCONNECTION},    "openConnection",
        "Triggered when getConnection() method is called"
      ),
      new MBeanNotificationInfo( new String[] {NOTIF_PRUNEBEGIN},        "pruneBegin",
        "Triggered when pruner begins a run"
      ),
      new MBeanNotificationInfo( new String[] {NOTIF_PRUNECONNECTION},   "pruneConnection",
        "Triggered when pruner closes a connection because it's been checked out too long"
      ),
      new MBeanNotificationInfo( new String[] {NOTIF_PRUNEFINISH},       "pruneFinish",
        "Triggered when pruner finishes a run"
      )
    };
  }

  private static Hashtable poolsByDb = new Hashtable();

  private static boolean foundCodeTimerClasses = false;
  static {
    try {
      Class.forName("com.icentris.util.CodeTimer");
      Class.forName("com.icentris.util.CodeTimerSegment");
      foundCodeTimerClasses = true;
    } catch (LinkageError e) {
    } catch (ClassNotFoundException e) {}
  }

  private String dbDriver;
  private String dbUrl;
  private String dbUser;
  private String dbPass;
  private String poolName;
  private int maxConnections    = 50;
  private int minConnections    = 1;
  private int timeoutInMinutes  = 30;
  private boolean strictTimeout = true;
  private boolean closeOnError  = true;
  private boolean showDebugging = true;
  private boolean useCodeTimer = foundCodeTimerClasses;
  private long timerLimitInMillis = 100;
  private int callerDepth = 1;
  private String[] callersToIgnore;
  private double pruneRunInMinutes;
  private PruneConnectionPool pruner;
  private List connections = (List) Collections.synchronizedList( new LinkedList() );
  private Set connectionsInUse = (Set) Collections.synchronizedSet( new HashSet() );
  private int connectionCount = 0;
  private java.util.Date prunerLastRun;

  public ConnectionPool(String dbDriver, String dbUrl, String dbUser, String dbPass)
    throws ClassNotFoundException
  {
    if ( dbDriver != null ) Class.forName(dbDriver);
    this.dbDriver = dbDriver;
    this.dbUrl    = dbUrl;
    this.dbUser   = dbUser;
    this.dbPass   = dbPass;
  }

  public String getDbDriver() {
    return dbDriver;
  }

  public String getDbUrl() {
    return dbUrl;
  }

  public String getDbUser() {
    return dbUser;
  }

  public String getDbPass() {
    return dbPass;
  }

  public String getPoolName() {
    return poolName;
  }

  public void setPoolName(String poolName) {
    this.poolName = poolName;
  }

  public int getMaxConnections() {
    return maxConnections;
  }

  public void setMaxConnections(int maxConnections) {
    this.maxConnections = maxConnections;
  }

  public int getMinConnections() {
    return minConnections;
  }

  public void setMinConnections(int minConnections) {
    this.minConnections = minConnections;
  }

  public int getTimeoutInMinutes() {
    return timeoutInMinutes;
  }

  public void setTimeoutInMinutes(int timeoutInMinutes) {
    this.timeoutInMinutes = timeoutInMinutes;
  }

  public boolean strictTimeout() {
    return strictTimeout;
  }

  public void setStrictTimeout(boolean strictTimeout) {
    this.strictTimeout = strictTimeout;
  }

  /** Wrapper of {@link #strictTimeout()} with "is" name to comply with MBean standard. */
  public boolean isStrictTimeout() { return strictTimeout(); }

  public boolean closeOnError() {
    return closeOnError;
  }

  public void setCloseOnError(boolean closeOnError) {
    this.closeOnError = closeOnError;
  }

  /** Wrapper of {@link #closeOnError()} with "is" name to comply with MBean standard. */
  public boolean isCloseOnError() { return closeOnError(); }

  public boolean showDebugging() {
    return showDebugging;
  }

  public void setShowDebugging(boolean showDebugging) {
    this.showDebugging = showDebugging;
  }

  /** Wrapper of {@link #showDebugging()} with "is" name to comply with MBean standard. */
  public boolean isShowDebugging() { return showDebugging(); }

  public boolean useCodeTimer() {
    return useCodeTimer;
  }

  public void setUseCodeTimer(boolean useCodeTimer) {
    // make sure if useCodeTimer is true,
    // we're deployed with CodeTimer and CodeTimerSegment
    if ( useCodeTimer == true &&
         foundCodeTimerClasses == false )
    {
      throw new IllegalStateException("useCodeTimer set to true, but com.icentris.util.CodeTimer and com.icentris.util.CodeTimerSegment not available!");
    }
    this.useCodeTimer = useCodeTimer;
  }

  public long getTimerLimitInMillis() {
    return timerLimitInMillis;
  }

  public void setTimerLimitInMillis(long timerLimitInMillis) {
    this.timerLimitInMillis = timerLimitInMillis;
  }

  public int getCallerDepth() {
    return callerDepth;
  }

  public void setCallerDepth(int callerDepth) {
    this.callerDepth = callerDepth;
  }

  public String[] getCallersToIgnore() {
    if ( callersToIgnore == null || callersToIgnore.length == 0 ) {
      callersToIgnore = new String[] { "com.icentris.sql.ConnectionPool.getConnection" };
    }
    return callersToIgnore;
  }

  public void setCallersToIgnore(String[] callersToIgnore) {
    if ( callersToIgnore != null && callersToIgnore.length > 0 ) {
      ArrayList tmpArray = new ArrayList(Arrays.asList(callersToIgnore));
      if ( ! tmpArray.contains("com.icentris.sql.ConnectionPool.getConnection") ) {
        tmpArray.add("com.icentris.sql.ConnectionPool.getConnection");
        callersToIgnore = (String[]) tmpArray.toArray(new String[0]);
      }
    }
    this.callersToIgnore = callersToIgnore;
  }

  public double getPruneRunInMinutes() {
    return pruneRunInMinutes;
  }

  public synchronized void startPruner(double pruneRunInMinutes) {
    if ( pruneRunInMinutes <= 0 ) {
      throw new IllegalArgumentException("Illegal attempt to start pruner to run every " + pruneRunInMinutes + " minutes, pruneRunInMinutes must be greater than 0");
    }
    Timer timer = new Timer();
    long pruneRunInMillis = (long) (pruneRunInMinutes * 60 * 1000);
    pruner = new PruneConnectionPool(this);
    timer.scheduleAtFixedRate( pruner, pruneRunInMillis, pruneRunInMillis );
    this.pruneRunInMinutes = pruneRunInMinutes;
  }

  public void pruneOnce() {
    (new PruneConnectionPool(this)).run();
  }

  public synchronized void stopPruner() {
    if ( pruner == null ) return;
    pruner.cancel();
    pruneRunInMinutes = -1;
  }

  public synchronized void finalize() {
    while ( connections.size() > 0 ) {
      ConnectionWrapper connection = (ConnectionWrapper) connections.get(0);
      removeConnection(connection);
    }
    if ( connectionsInUse.size() > 0 ) {
      // run the pruner once to clear any connection older than 1 minute
      pruneRunInMinutes = 1;
      (new PruneConnectionPool(this)).run();
      stopPruner();

      // if there's still leftover connections, oh well!
      if ( connectionsInUse.size() > 0 ) {
            logger
                     .error(
                              "finalize() - ERROR: [ConnectionPool] Failed to gracefully finalize.  I'm going to have to shut off the following in-use connections:", null); //$NON-NLS-1$
        Iterator inUseSetIterator = connectionsInUse.iterator();
        while ( inUseSetIterator.hasNext() ) {
          ConnectionWrapper connection = (ConnectionWrapper) inUseSetIterator.next();
               logger.error("finalize() - " + connection.getStatusString(), null); //$NON-NLS-1$
          try {
            connection.realConnection.close();
          } catch (SQLException e) {
                  logger.error("finalize() - ERROR: [ConnectionPool.finalize] error closing connection [" + connection + "]:", e); //$NON-NLS-1$ //$NON-NLS-2$
                  logger.error("finalize()", e); //$NON-NLS-1$
          }
        }
      }
    }
    connectionsInUse.clear();
    connectionCount = 0;
    JMX.attemptUnregisterMBean( "icentris.sql:name=ConnectionPool(" + poolName + ")" );
  }

  public synchronized int getConnectionCount() {
    return connections.size() + connectionsInUse.size();
  }

  public int getAvailableCount() {
    return connections.size();
  }

  public int getInUseCount() {
    return connectionsInUse.size();
  }

  public void releaseConnection(ConnectionWrapper connection) {
    try {
      if ( closeOnError() == true && connection.getMostRecentError() != null ) {
        if ( showDebugging() ) {
               logger
                        .error(
                                 "releaseConnection(ConnectionWrapper) - INFO: [ConnectionPool] closing connection [" + connection + "] because it had the following error:", null); //$NON-NLS-1$ //$NON-NLS-2$
               logger.error("releaseConnection(ConnectionWrapper)", connection.getMostRecentError()); //$NON-NLS-1$
        }
        connectionCount--;
        connection.realConnection.close();
        //sendNotification( new Notification(NOTIF_DESTROYCONNECTION, NOTIF_DESTROYCONNECTION,
        //                  notificationSequence++, connection.toString()) );
        //JMX.attemptUnregisterMBean( "icentris.sql:name=" + connection );
      }
      connection.setCaller("");
      connection.setInUse( false );
      synchronized(this) {
        connections.add(connection);
        connectionsInUse.remove(connection);
        notify();
      }
    } catch (Throwable t) {
         logger.error("releaseConnection(ConnectionWrapper) - ERROR: [ConnectionPool] error closing connection [" + connection + "]:", t); //$NON-NLS-1$ //$NON-NLS-2$
         logger.error("releaseConnection(ConnectionWrapper)", t); //$NON-NLS-1$
    }
  }

  /**
   * Careful! Only use this in desparate situations!
   */
  public synchronized void removeConnection(String connectionString) {
    if ( connectionString == null ) return;
    for ( int i=0; i < connections.size(); i++ ) {
      ConnectionWrapper connection = (ConnectionWrapper) connections.get(i);
      if ( connectionString.equals(connection.toString()) ) {
        removeConnection(connection);
        return;
      }
    }
    Iterator inUseSetIterator = connectionsInUse.iterator();
    while ( inUseSetIterator.hasNext() ) {
      ConnectionWrapper connection = (ConnectionWrapper) inUseSetIterator.next();
      if ( connectionString.equals(connection.toString()) ) {
        removeConnection(connection);
        return;
      }
    }
      if (logger.isDebugEnabled()) {
         logger.debug("removeConnection(String) - removeConnection(connectionString) called but Connection=[" + connectionString + "] not found in pool"); //$NON-NLS-1$ //$NON-NLS-2$
      }
  }

  public synchronized void removeConnection(ConnectionWrapper connection) {
    try {
      connection.realConnection.close();
    } catch (SQLException e) {
         logger.error("removeConnection(ConnectionWrapper) - ERROR: [ConnectionPool.removeConnection] error closing connection [" + connection + "]:", e); //$NON-NLS-1$ //$NON-NLS-2$
         logger.error("removeConnection(ConnectionWrapper)", e); //$NON-NLS-1$
    }
    connections.remove(connection);
    connectionsInUse.remove(connection);
    connectionCount--;
    //JMX.attemptUnregisterMBean( "icentris.sql:name=" + connection );
  }

  public static void initializePool(String poolName, ConnectionPool pool) {
    if ( poolName == null ) poolName = "default";
    if ( pool   == null ) {
      throw new IllegalArgumentException("Cannot initialize a null pool");
    }
    pool.setPoolName(poolName);
    synchronized (poolsByDb) {
      // I'm not waiting for the garbage collection to free
      // my db connections, let's do it now!
      if ( poolsByDb.get(poolName) != null ) {
        ConnectionPool oldPool = (ConnectionPool) poolsByDb.get(poolName);
        oldPool.finalize();
      }
      JMX.attemptRegisterMBean( pool, "icentris.sql:name=ConnectionPool(" + poolName + ")" );
      poolsByDb.put(poolName, pool);
    }
  }

  public static String[] getPoolNames() {
    ArrayList names = new ArrayList();
    synchronized (poolsByDb) {
      Enumeration enumerator = poolsByDb.keys();
      while ( enumerator.hasMoreElements() ) {
        names.add(enumerator.nextElement());
      }
    }
    return (String[]) names.toArray(new String[0]);
  }

  public static ConnectionPool getPool() {
    return getPool("default");
  }

  public static ConnectionPool getPool(String poolName) {
    if ( poolName == null ) poolName = "default";
    ConnectionPool pool = (ConnectionPool) poolsByDb.get(poolName);
    if ( pool == null ) {
      throw new IllegalStateException("The ConnectionPool (" + poolName + ") has not been initialized yet");
    } else {
      return pool;
    }
  }

  public static Connection getConnection()
    throws SQLException
  {
    return getConnection("default");
  }

  public static java.sql.Connection getConnection(String poolName)
    throws SQLException
  {
    CodeTimer timer = new CodeTimer();
    CodeTimerSegment segment = timer.start("ConnectionPool: getConnection");
    segment.setCanBeSubSegmentOnlyIfUnacceptable( true );
    ConnectionPool pool = (ConnectionPool) poolsByDb.get(poolName);
    if ( pool == null ) {
      throw new IllegalStateException("The ConnectionPool (" + poolName + ") has not been initialized yet");
    }
    //sendNotification( new Notification(NOTIF_OPENCONNECTION, NOTIF_OPENCONNECTION,
    //                  notificationSequence++, connection.toString()) );
    try {
      ConnectionWrapper connection = pool.prepareConnection();
      timer.stop("ConnectionPool: getConnection");
      // hopefully the common case, we're done!
      return connection;
    } catch (IndexOutOfBoundsException e) {}
    synchronized (pool) {
      boolean timeToCreate = false;
      do {
        // try again now that we're synchronized
        if ( pool.connections.size() > 0 ) {
          try {
            ConnectionWrapper connection = pool.prepareConnection();
            timer.stop("ConnectionPool: getConnection");
            return connection;
          } catch (IndexOutOfBoundsException e) {}
        } else if ( pool.connectionCount < pool.getMaxConnections() ) {
          timeToCreate = true;
        } else {
          // Too many connections?  Let's wait for some to free up.
               if (logger.isDebugEnabled()) {
                  logger
                           .debug("getConnection(String) - WARNING: [ConnectionPool] too many connections in use [" + pool.connectionsInUse.size() + "], waiting [" + Thread.currentThread() + "]"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
               }
          try { pool.wait(); } catch (InterruptedException e) {}
          if ( pool.showDebugging() ) {
                  if (logger.isDebugEnabled()) {
                     logger
                              .debug("getConnection(String) - INFO: [ConnectionPool] freed up! [" + Thread.currentThread() + "] connections in use= [" + pool.connectionsInUse.size() + "]"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
                  }
          }
        }
      } while ( timeToCreate == false );
      // if we made it here, the pool is too small or there are no more
      // connections in the pool, time to initialize another
      pool.connectionCount++;
    }
    // Now we're unsynchronzied so others can get a lock on the pool to do their thing.
    // We should be safe to open a new connection because we already reserved it by
    // doing pool.connectionCount++.  But if we fail in getting the new connection, let's
    // make sure to pool.connectionCount-- so others can try.
    try {
      ConnectionWrapper connection = pool.openNewConnection();
      timer.stop("ConnectionPool: getConnection");
      return connection;
    } catch (SQLException e) {
      pool.connectionCount--;
      timer.stop("ConnectionPool: getConnection");
      throw e;
    }
  }

  /** Should only be called once inside getConnection() method. */
  private ConnectionWrapper openNewConnection() throws SQLException {
    Connection newConnection =
      DriverManager.getConnection(getDbUrl(), getDbUser(), getDbPass());
    ConnectionWrapper connection = new ConnectionWrapper(newConnection, this);
    //sendNotification( new Notification(NOTIF_CREATECONNECTION, NOTIF_CREATECONNECTION,
    //                  notificationSequence++, connection.toString()) );
    connection.setInUse( true );
    connection.updateCheckedOutTime();
    addToInUseSet( connection );
    connection.setUseCodeTimer( useCodeTimer() );
    connection.setTimerLimitInMillis( getTimerLimitInMillis() );
    connection.setCallerDepth( getCallerDepth() );
    connection.setCallersToIgnore( getCallersToIgnore() );
    if ( showDebugging() ) {
         if (logger.isDebugEnabled()) {
            logger.debug("openNewConnection() - INFO: [ConnectionPool] creating new connection=[" + connection + "]"); //$NON-NLS-1$ //$NON-NLS-2$
         }
    }
    return connection;
  }

  /** Should only be called once inside prepareConnection() method. */
  private synchronized ConnectionWrapper tryToGetConnection() throws IndexOutOfBoundsException {
    ConnectionWrapper connection = (ConnectionWrapper) connections.remove(0);
    return connection;
  }

  /** Should only be called once inside prepareConnection() method,
   * and once inside openNewConnection() method. */
  private synchronized void addToInUseSet(ConnectionWrapper connection) {
    connectionsInUse.add(connection);
  }

  /** The contract of prepareConnection() is no synchronization block. It does, however,
   * synchronize twice when calling tryToGetConnection() and addToInUseSet(). */
  private ConnectionWrapper prepareConnection()
    throws SQLException, IndexOutOfBoundsException
  {
    ConnectionWrapper connection;
    boolean connectionIsGood;
    do {
      connection = tryToGetConnection();
      boolean itsTimeToClose = false;
      long nowInMinutes = System.currentTimeMillis() / 60000;
      long minutesSinceLastUse = nowInMinutes - connection.getLastUsedTime();
      long minutesSinceCreation = nowInMinutes - connection.getCreatedTime();
      if ( strictTimeout() == true && minutesSinceCreation >= getTimeoutInMinutes() ) {
        itsTimeToClose = true;
        if ( showDebugging() ) {
               if (logger.isDebugEnabled()) {
                  logger
                           .debug("prepareConnection() - INFO: [ConnectionPool] closing connection=[" + connection + "] which has been open for [" + minutesSinceCreation + "] minutes. The strict timeout is [" + getTimeoutInMinutes() + "]"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
               }
        }
      } else if ( minutesSinceLastUse >= getTimeoutInMinutes() ) {
        itsTimeToClose = true;
        if ( showDebugging() ) {
               if (logger.isDebugEnabled()) {
                  logger
                           .debug("prepareConnection() - INFO: [ConnectionPool] closing connection=[" + connection + "] which has been unused for [" + minutesSinceLastUse + "] minutes."); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
               }
        }
      }
      if ( itsTimeToClose == true ) {
        connectionIsGood = false;
        try {
          connectionCount--;
          connection.realConnection.close();
          //sendNotification( new Notification(NOTIF_DESTROYCONNECTION, NOTIF_DESTROYCONNECTION,
          //                  notificationSequence++, connection.toString()) );
          //JMX.attemptUnregisterMBean( "icentris.sql:name=" + connection );
        } catch (Throwable t) {
               logger.error("prepareConnection() - ERROR: [ConnectionPool] error closing connection [" + connection + "]:", t); //$NON-NLS-1$ //$NON-NLS-2$
               logger.error("prepareConnection()", t); //$NON-NLS-1$
        }
      } else {
        if ( connection.isClosed() == true ) {
          if ( showDebugging() ) {
                  logger.error("prepareConnection() - INFO: [ConnectionPool] trashing connection [" + connection + "] because isClosed() returned true", null); //$NON-NLS-1$ //$NON-NLS-2$
            if ( connection.getMostRecentError() != null ) {
                     logger.error("prepareConnection()", connection.getMostRecentError()); //$NON-NLS-1$
            }
          }
          connectionIsGood = false;
        } else {
          connectionIsGood = true;
        }
      }
      // if this connection is no good let's try the next one
    } while ( connectionIsGood == false );
    connection.setInUse( true );
    connection.updateCheckedOutTime();
    connection.setLastCloser( null );
    addToInUseSet( connection );
    String caller = Caller.getCaller( connection.getCallersToIgnore() );
    connection.setCaller(caller);
    //connection.sendNotification( new Notification(connection.NOTIF_OPEN, connection.NOTIF_OPEN,
    //                             connection.notificationSequence++, connection.getCaller()) );
    return connection;
  }

  private static class PruneConnectionPool extends TimerTask {
    private ConnectionPool pool;

    public PruneConnectionPool(ConnectionPool pool) {
      this.pool = pool;
    }

    public void run() {
      //pool.sendNotification( new Notification(NOTIF_PRUNEBEGIN, NOTIF_PRUNEBEGIN,
      //                       pool.notificationSequence++, null) );
      pool.prunerLastRun = new java.util.Date();
      ArrayList connectionsToClose = new ArrayList();
      synchronized (pool) {
        Iterator inUseSetIterator = pool.connectionsInUse.iterator();
        while ( inUseSetIterator.hasNext() ) {
          ConnectionWrapper connection = (ConnectionWrapper) inUseSetIterator.next();
          long lastUsedTime = connection.getLastUsedTime();
          long nowInMinutes = System.currentTimeMillis() / 60000;
          long minutesSinceLastUse = nowInMinutes - lastUsedTime;
          double minutesAllowed = pool.getPruneRunInMinutes();
          // let's not close down connections that have been open for less than 1 minute
          if ( minutesAllowed < 1 ) minutesAllowed = 1;
          if ( minutesSinceLastUse >= minutesAllowed ) {
            connectionsToClose.add( connection );
            String statusString = connection.getStatusString();
            if ( pool.showDebugging() ) {
                     if (logger.isDebugEnabled()) {
                        logger.debug("run() - INFO: [ConnectionPool] Closing connection not used in " + minutesAllowed + " minutes: " + connection); //$NON-NLS-1$ //$NON-NLS-2$
                     }
                     if (logger.isDebugEnabled()) {
                        logger.debug("run() - statuString=[" + statusString + "]"); //$NON-NLS-1$ //$NON-NLS-2$
                     }
            }
            inUseSetIterator.remove();
            pool.connectionCount--;
            //JMX.attemptUnregisterMBean( "icentris.sql:name=" + connection );
            pool.sendNotification( new Notification(NOTIF_PRUNECONNECTION, NOTIF_PRUNECONNECTION,
                                   pool.notificationSequence++, connection + ": " + statusString) );
          }
        }
      }
      for (int i=0; i < connectionsToClose.size(); i++ ) {
        ConnectionWrapper connection = (ConnectionWrapper) connectionsToClose.get(i);
        try {
          connection.realConnection.close();
        } catch (SQLException e) {
               logger.error("run() - ERROR: [ConnectionPool] error closing inUse connection [" + connection + "]:", e); //$NON-NLS-1$ //$NON-NLS-2$
               if (logger.isDebugEnabled()) {
                  logger.debug("run() - statuString=[" + connection.getStatusString() + "]"); //$NON-NLS-1$ //$NON-NLS-2$
               }
               logger.error("run()", e); //$NON-NLS-1$
        }
      }
      //pool.sendNotification( new Notification(NOTIF_PRUNEFINISH, NOTIF_PRUNEFINISH,
      //                       pool.notificationSequence++, null) );
    }
  }

  public static String getFullStatusReport() {
    StringBuffer sb = new StringBuffer();
    synchronized (poolsByDb) {
      Enumeration enumerator = poolsByDb.keys();
      while ( enumerator.hasMoreElements() ) {
        String poolName = (String) enumerator.nextElement();
        ConnectionPool pool = (ConnectionPool) poolsByDb.get(poolName);
        sb.append(pool.getStatusReport());
      }
    }
    return sb.toString();
  }

  public static String getStatusReport(String poolName) {
    ConnectionPool pool = (ConnectionPool) poolsByDb.get(poolName);
    if ( pool == null ) return "";
    return pool.getStatusReport();
  }

  public synchronized String getStatusReport() {
    StringBuffer sb = new StringBuffer();
    sb.append("Pool info for poolname=[" + poolName + "]\n");
    sb.append("  dbDriver=[" + dbDriver + "]\n");
    sb.append("  dbUrl=[" + dbUrl + "]\n");
    sb.append("  dbUser=[" + dbUser + "]\n");
    sb.append("  maxConnections=[" + maxConnections + "]\n");
    sb.append("  minConnections=[" + minConnections + "]\n");
    sb.append("  timeoutInMinutes=[" + timeoutInMinutes + "]\n");
    sb.append("  strictTimeout=[" + strictTimeout + "]\n");
    sb.append("  closeOnError=[" + closeOnError + "]\n");
    sb.append("  showDebugging=[" + showDebugging + "]\n");
    sb.append("  pruneRunInMinutes=[" + pruneRunInMinutes + "]\n");
    sb.append("  useCodeTimer=[" + useCodeTimer + "]\n");
    sb.append("  timerLimitInMillis=[" + timerLimitInMillis + "]\n");
    sb.append("  callerDepth=[" + callerDepth + "]\n");
    sb.append("  callersToIgnore=[" + (callersToIgnore != null ? Arrays.asList(callersToIgnore) : null) + "]\n");
    sb.append("  connectionCount=[" + connectionCount + "]\n");
    sb.append(connections.size() + " Waiting in pool:\n");
    for ( int i=0; i < connections.size(); i++ ) {
      ConnectionWrapper connection = (ConnectionWrapper) connections.get(i);
      sb.append("  " + connection);
      // This getOracleSessionId() isn't working, so I'm commenting it for now
      ///String oracleSessionId = connection.getOracleSessionId();
      ///if ( oracleSessionId != null ) {
      ///  sb.append(" OracleSessionId[" + oracleSessionId + "]");
      ///}
      sb.append( connection.getStatusString() + "\n" );
    }
    sb.append(connectionsInUse.size() + " In Use:\n");
    Iterator inUseSetIterator = connectionsInUse.iterator();
    while ( inUseSetIterator.hasNext() ) {
      ConnectionWrapper connection = (ConnectionWrapper) inUseSetIterator.next();
      sb.append("  " + connection);
      // This getOracleSessionId() isn't working, so I'm commenting it for now
      //String oracleSessionId = connection.getOracleSessionId();
      //if ( oracleSessionId != null ) {
      //  sb.append(" OracleSessionId[" + oracleSessionId + "]");
      //}
      sb.append( connection.getStatusString() + "\n" );
    }
    sb.append("Pruner Last Ran: " + prunerLastRun + "\n");
    return sb.toString();
  }
}
TOP

Related Classes of com.icentris.sql.ConnectionPool

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.