You are viewing a plain text version of this content. The canonical link for it is here.
Posted to cvs@avalon.apache.org by le...@apache.org on 2002/01/24 03:56:47 UTC

cvs commit: jakarta-avalon-excalibur/src/scratchpad/org/apache/avalon/excalibur/datasource ResourceLimitingJdbcConnectionPool.java ResourceLimitingJdbcDataSource.java

leif        02/01/23 18:56:47

  Added:       src/scratchpad/org/apache/avalon/excalibur/datasource
                        ResourceLimitingJdbcConnectionPool.java
                        ResourceLimitingJdbcDataSource.java
  Log:
  Add new JdbcDataSource based on ResourceLimiting Pool
  
  Revision  Changes    Path
  1.1                  jakarta-avalon-excalibur/src/scratchpad/org/apache/avalon/excalibur/datasource/ResourceLimitingJdbcConnectionPool.java
  
  Index: ResourceLimitingJdbcConnectionPool.java
  ===================================================================
  /*
   * Copyright (C) The Apache Software Foundation. All rights reserved.
   *
   * This software is published under the terms of the Apache Software License
   * version 1.1, a copy of which has been included with this distribution in
   * the LICENSE.txt file.
   */
  package org.apache.avalon.excalibur.datasource;
  
  import org.apache.avalon.excalibur.pool.ValidatedResourceLimitingPool;
  
  import java.sql.SQLException;
  
  import org.apache.avalon.excalibur.datasource.JdbcConnection;
  import org.apache.avalon.excalibur.pool.ObjectFactory;
  import org.apache.avalon.excalibur.pool.Poolable;
  
  /**
   * A ResourceLimiting JdbcConnectionPool which allows for fine configuration of
   *  how the pool scales to loads.
   *
   * The pool supports; weak and strong pool size limits, optional blocking gets
   *  when connections are not available, and automatic trimming of unused
   *  connections.
   *
   * @author <a href="mailto:leif@silveregg.co.jp">Leif Mortenson</a>
   * @version CVS $Revision: 1.1 $ $Date: 2002/01/24 02:56:47 $
   * @since 4.0
   */
  public class ResourceLimitingJdbcConnectionPool
      extends ValidatedResourceLimitingPool
  {
      private boolean m_autoCommit;
      
      /*---------------------------------------------------------------
       * Constructors
       *-------------------------------------------------------------*/
      /**
       * Creates a new ResourceLimitingJdbcConnectionPool
       *
       * @param factory The ObjectFactory which will be used to create new connections as needed
       *  by the pool.
       * @param max Maximum number of connections which can be stored in the pool, 0 implies
       *  no limit.
       * @param maxStrict true if the pool should never allow more than max connections to be
       *  created.  Will cause an exception to be thrown if more than max connections are
       *  requested and blocking is false.
       * @param blocking true if the pool should cause a thread calling get() to block when
       *  connections are not currently available in the pool.
       * @param blockTimeout The maximum amount of time, in milliseconds, that a call to get() will
       *  block before an exception is thrown.  A value of 0 implies an indefinate wait.
       * @param trimInterval The minimum interval with which old unused connections will be removed
       *  from the pool.  A value of 0 will cause the pool to never trim old connections.
       * @param autoCommit true if connections created by this pool should have autoCommit enabled.
       */
      public ResourceLimitingJdbcConnectionPool( final ObjectFactory factory,
                                                 int max,
                                                 boolean maxStrict,
                                                 boolean blocking,
                                                 long blockTimeout,
                                                 long trimInterval,
                                                 boolean autoCommit )
          {
                                  
          super(factory, max, maxStrict, blocking, blockTimeout, trimInterval);
          
          m_autoCommit = autoCommit;
      }
      
      /*---------------------------------------------------------------
       * ValidatedResourceLimitingPool Methods
       *-------------------------------------------------------------*/
      /**
       * Create a new poolable instance by by calling the newInstance method
       *  on the pool's ObjectFactory.
       * This is the method to override when you need to enforce creational
       *  policies.
       * This method is only called by threads that have _semaphore locked.
       */
      protected Poolable newPoolable() throws Exception {
          JdbcConnection conn = (JdbcConnection)super.newPoolable();
          
          // Store a reference to this pool in the connection
          conn.setPool(this);
          
          // Set the auto commit flag for new connections.
          conn.setAutoCommit(m_autoCommit);
          
          return conn;
      }
      
      /**
       * Validates the poolable before it is provided to the caller of get on this pool.
       *  This implementation of the validation method always returns true indicating
       *  that the Poolable is valid.
       * The pool is not locked by the current thread when this method is called.
       *
       * @param poolable The Poolable to be validated
       * @returns true if the Poolable is valid, false if it should be removed from the pool.
       */
      protected boolean validatePoolable(Poolable poolable) {
          JdbcConnection conn = (JdbcConnection)poolable;
          try {
              // Calling isClosed() may take time if the connection has not been
              //  used for a while.  Is this a problem because the m_semaphore
              //  is currently locked?  I am thinking no because isClosed() will
              //  return immediately when connections are being used frequently.
              if (conn.isClosed()) {
                  getLogger().debug("JdbcConnection was closed.");
                  return false;
              }
          } catch (SQLException e) {
              getLogger().debug(
                  "Failed to check whether JdbcConnection was closed. " + e.getMessage());
          }
          
          return true;
      }
      
      /*---------------------------------------------------------------
       * Public Methods
       *-------------------------------------------------------------*/
      
      /*---------------------------------------------------------------
       * Private Methods
       *-------------------------------------------------------------*/
  }
  
  
  
  
  1.1                  jakarta-avalon-excalibur/src/scratchpad/org/apache/avalon/excalibur/datasource/ResourceLimitingJdbcDataSource.java
  
  Index: ResourceLimitingJdbcDataSource.java
  ===================================================================
  /*
   * Copyright (C) The Apache Software Foundation. All rights reserved.
   *
   * This software is published under the terms of the Apache Software License
   * version 1.1, a copy of which has been included with this distribution in
   * the LICENSE.txt file.
   */
  package org.apache.avalon.excalibur.datasource;
  
  import java.sql.Connection;
  import java.sql.SQLException;
  
  import org.apache.avalon.excalibur.datasource.DataSourceComponent;
  import org.apache.avalon.excalibur.datasource.JdbcConnectionFactory;
  import org.apache.avalon.excalibur.datasource.NoAvailableConnectionException;
  import org.apache.avalon.framework.activity.Disposable;
  import org.apache.avalon.framework.configuration.Configuration;
  import org.apache.avalon.framework.configuration.ConfigurationException;
  import org.apache.avalon.framework.logger.AbstractLogEnabled;
  
  /**
   * The ResourceLimiting implementation for DataSources in Avalon.  This uses the
   * normal <code>java.sql.Connection</code> object and
   * <code>java.sql.DriverManager</code>.  The Configuration is like this:
   *
   * <pre>
   *   &lt;jdbc&gt;
   *     &lt;pool-controller max="<i>10</i>" blocking="<i>true</i>"
   *       timeout="<i>-1</i>" trim-interval="<i>60000</i>"
   *       connection-class="<i>my.overrided.ConnectionClass</i>"&gt;
   *       &lt;keep-alive&gt;select 1&lt;/keep-alive&gt;
   *     &lt;/pool-controller&gt;
   *     &lt;driver&gt;<i>com.database.jdbc.JdbcDriver</i>&lt;/driver&gt;
   *     &lt;dburl&gt;<i>jdbc:driver://host/mydb</i>&lt;/dburl&gt;
   *     &lt;user&gt;<i>username</i>&lt;/user&gt;
   *     &lt;password&gt;<i>password</i>&lt;/password&gt;
   *   &lt;/jdbc&gt;
   * </pre>
   *
   * With the following roles declaration:
   *
   * <pre>
   *   &lt;role name="org.apache.avalon.excalibur.datasource.DataSourceComponentSelector"
   *     shorthand="datasources"
   *     default-class="org.apache.avalon.excalibur.component.ExcaliburComponentSelector"&gt;
   *     &lt;hint shorthand="jdbc"
   *       class="org.apache.avalon.excalibur.datasource.ResourceLimitingJdbcDataSource"/&gt;
   *   &lt;/role&gt;
   * </pre>
   *
   * @author <a href="mailto:leif@silveregg.co.jp">Leif Mortenson</a>
   * @version CVS $Revision: 1.1 $ $Date: 2002/01/24 02:56:47 $
   * @since 4.0
   */
  public class ResourceLimitingJdbcDataSource 
      extends AbstractLogEnabled 
      implements DataSourceComponent, Disposable
  {
      private boolean m_configured;
      private boolean m_disposed;
      protected ResourceLimitingJdbcConnectionPool m_pool;
      
      /*---------------------------------------------------------------
       * Constructors
       *-------------------------------------------------------------*/
      public ResourceLimitingJdbcDataSource() {}
  
      /*---------------------------------------------------------------
       * DataSourceComponent Methods
       *-------------------------------------------------------------*/
      /**
       * Gets the Connection to the database
       *
       * @throws NoValidConnectionException when there is no valid Connection wrapper
       *         available in the classloader.
       *
       * @throws NoAvailableConnectionException when there are no more available
       *         Connections in the pool.
       */
      public Connection getConnection()
          throws SQLException
      {
          if ( !m_configured ) throw new IllegalStateException( "Not Configured" );
          if ( m_disposed ) throw new IllegalStateException( "Already Disposed" );
          
          Connection connection;
          try
          {
              connection = (Connection)m_pool.get();
          }
          catch ( SQLException e )
          {
              if (getLogger().isWarnEnabled())
              {
                  getLogger().warn("Could not return Connection", e);
              }
              
              throw e;
          }
          catch ( Exception e )
          {
              if ( getLogger().isWarnEnabled() )
              {
                  getLogger().warn( "Could not return Connection", e );
              }
              
              throw new NoAvailableConnectionException( e.getMessage() );
          }
          
          return connection;
      }
      
      /*---------------------------------------------------------------
       * DataSourceComponent (Configurable) Methods
       *-------------------------------------------------------------*/
      /**
       * Pass the <code>Configuration</code> to the <code>Configurable</code>
       * class. This method must always be called after the constructor
       * and before any other method.
       *
       * @param configuration the class configurations.
       */
      public void configure(Configuration configuration) throws ConfigurationException {
          if (m_configured) throw new IllegalStateException("Already Configured");
          
          final String  driver   = configuration.getChild( "driver"   ).getValue( "" );
          final String  dburl    = configuration.getChild( "dburl"    ).getValue( null );
          final String  user     = configuration.getChild( "user"     ).getValue( null );
          final String  passwd   = configuration.getChild( "password" ).getValue( null );
          
          final Configuration controller = configuration.getChild( "pool-controller" );
          String keepAlive = controller.getChild( "keep-alive" ).getValue(null);
  
          final int     max          = controller.getAttributeAsInteger( "max", 3 );
          final boolean blocking     = controller.getAttributeAsBoolean( "blocking", true );
          final long    timeout      = controller.getAttributeAsLong   ( "timeout", -1 );
          final long    trimInterval = controller.getAttributeAsLong   ( "trim-interval", 60000 );
          final boolean oradb        = controller.getAttributeAsBoolean( "oradb", false );
          
          final boolean autoCommit = configuration.getChild("auto-commit").getValueAsBoolean(true);
          final String connectionClass = controller.getAttribute( "connection-class", 
              "org.apache.avalon.excalibur.datasource.JdbcConnection" );
  
          final int l_max;
  
          // If driver is specified....
          if ( ! "".equals(driver) )
          {
              if (getLogger().isDebugEnabled())
              {
                  getLogger().debug("Loading new driver: " + driver);
              }
  
              try
              {
                  Class.forName( driver, true, Thread.currentThread().getContextClassLoader() );
              }
              catch (ClassNotFoundException cnfe)
              {
                  if (getLogger().isWarnEnabled())
                  {
                      getLogger().warn( "Could not load driver: " + driver, cnfe );
                  }
              }
          }
  
          if( max < 1 )
          {
              if (getLogger().isWarnEnabled())
              {
                  getLogger().warn( "Maximum number of connections specified must be at least 1." );
              }
  
              l_max = 1;
          }
          else
          {
              l_max = max;
          }
  
          if (oradb)
          {
              keepAlive = "SELECT 1 FROM DUAL";
  
              if (getLogger().isWarnEnabled())
              {
                  getLogger().warn("The oradb attribute is deprecated, please use the" +
                                   "keep-alive element instead.");
              }
          }
          else
          {
              keepAlive = "SELECT 1";
          }
  
          final JdbcConnectionFactory factory = new JdbcConnectionFactory
              ( dburl, user, passwd, autoCommit, keepAlive, connectionClass );
  
          factory.enableLogging( getLogger() );
  
          try
          {
              m_pool = new ResourceLimitingJdbcConnectionPool
                  (factory, l_max, true, blocking, timeout, trimInterval, autoCommit );
              m_pool.enableLogging( getLogger() );
          }
          catch (Exception e)
          {
              if (getLogger().isDebugEnabled())
              {
                  getLogger().debug("Error configuring ResourceLimitingJdbcDataSource", e);
              }
  
              throw new ConfigurationException("Error configuring ResourceLimitingJdbcDataSource", e);
          }
          
          m_configured = true;
      }
      
      /*---------------------------------------------------------------
       * Disposable Methods
       *-------------------------------------------------------------*/
      /**
       * The dispose operation is called at the end of a components lifecycle.
       * This method will be called after Startable.stop() method (if implemented
       * by component). Components use this method to release and destroy any
       * resources that the Component owns.
       */
      public void dispose() {
          m_disposed = true;
          m_pool.dispose();
          m_pool = null;
      }
  }
  
  
  
  

--
To unsubscribe, e-mail:   <ma...@jakarta.apache.org>
For additional commands, e-mail: <ma...@jakarta.apache.org>