db-ojb-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From mka...@apache.org
Subject cvs commit: db-ojb release-notes.txt
Date Wed, 16 Mar 2005 17:51:19 GMT
mkalen      2005/03/16 09:51:19

  Modified:    src/java/org/apache/ojb/broker/accesslayer Tag:
                        OJB_1_0_RELEASE ConnectionFactoryDBCPImpl.java
               .        Tag: OJB_1_0_RELEASE release-notes.txt
  Log:
  Fix DBCP connection factory to call platform-specific connection init. Resolve issue with
statement caching in both DBCP pool and Oracle-driver by disabling DBCP-caching if platform=Oracle9i
(since DBCP does not know how to manage Oracle server-side cursors correctly).
  
  Revision  Changes    Path
  No                   revision
  No                   revision
  1.10.2.1  +177 -45   db-ojb/src/java/org/apache/ojb/broker/accesslayer/ConnectionFactoryDBCPImpl.java
  
  Index: ConnectionFactoryDBCPImpl.java
  ===================================================================
  RCS file: /home/cvs/db-ojb/src/java/org/apache/ojb/broker/accesslayer/ConnectionFactoryDBCPImpl.java,v
  retrieving revision 1.10
  retrieving revision 1.10.2.1
  diff -u -r1.10 -r1.10.2.1
  --- ConnectionFactoryDBCPImpl.java	23 May 2004 16:36:53 -0000	1.10
  +++ ConnectionFactoryDBCPImpl.java	16 Mar 2005 17:51:18 -0000	1.10.2.1
  @@ -1,6 +1,6 @@
   package org.apache.ojb.broker.accesslayer;
   
  -/* Copyright 2002-2004 The Apache Software Foundation
  +/* Copyright 2002-2005 The Apache Software Foundation
    *
    * Licensed under the Apache License, Version 2.0 (the "License");
    * you may not use this file except in compliance with the License.
  @@ -21,60 +21,63 @@
   import org.apache.commons.dbcp.PoolingDataSource;
   import org.apache.commons.pool.KeyedObjectPoolFactory;
   import org.apache.commons.pool.ObjectPool;
  +import org.apache.commons.pool.KeyedPoolableObjectFactory;
   import org.apache.commons.pool.impl.GenericKeyedObjectPoolFactory;
   import org.apache.commons.pool.impl.GenericObjectPool;
  +import org.apache.commons.pool.impl.GenericKeyedObjectPool;
   import org.apache.ojb.broker.metadata.JdbcConnectionDescriptor;
   import org.apache.ojb.broker.util.ClassHelper;
   import org.apache.ojb.broker.util.logging.Logger;
   import org.apache.ojb.broker.util.logging.LoggerFactory;
  +import org.apache.ojb.broker.PBKey;
   
   import javax.sql.DataSource;
   import java.sql.Connection;
   import java.sql.SQLException;
   import java.util.HashMap;
   import java.util.Map;
  +import java.util.Collection;
  +import java.util.Iterator;
  +import java.util.Collections;
   
   /**
  - * ConnectionFactory implementation using jakarta-DBCP
  + * ConnectionFactory implementation using Jakarta DBCP and Commons Pool
    * to pool driver based connections.
    *
  - * (based on a proposal of Dirk Verbeek - Thanks).
  + * Based on a proposal of Dirk Verbeek - Thanks.
    *
    * @author <a href="mailto:armin@codeAuLait.de">Armin Waibel</a>
    * @version $Id$
    */
   public class ConnectionFactoryDBCPImpl extends ConnectionFactoryAbstractImpl
   {
  +
       private Logger log = LoggerFactory.getLogger(ConnectionFactoryDBCPImpl.class);
   
  -    private Map poolMap = new HashMap();
  +    /** Key=PBKey, value=ObjectPool. */
  +    private Map poolMap = Collections.synchronizedMap(new HashMap());
  +    /** Key=PBKey, value=PoolingDataSource. */
  +    private Map dsMap = Collections.synchronizedMap(new HashMap());
  +    /** Synchronize object for operations not synchronized on Map only. */
  +    private Object poolSynch = new Object();
   
       public Connection getConnectionFromPool(JdbcConnectionDescriptor jcd) throws LookupException
       {
  -        DataSource ds = (DataSource) poolMap.get(jcd.getPBKey());
  -        if (ds == null) // found no pool for PBKey
  -        {
  -            try
  -            {
  -                // setup new pool
  -                ds = setupPool(jcd);
  -                poolMap.put(jcd.getPBKey(), ds);
  -            }
  -            catch (Exception e)
  -            {
  -                log.error("Could not setup DataSource for " + jcd, e);
  -                throw new LookupException(e);
  -            }
  -        }
  +        final DataSource ds = getDataSource(jcd);
  +
  +        // Returned DS is never null, exception are logged by getDataSource and gets
  +        // re-thrown here since we don't catch them
  +
  +        Connection conn;
           try
           {
  -            Connection con = ds.getConnection();
  -            return con;
  +            conn = ds.getConnection();
           }
           catch (SQLException e)
           {
  -            throw new LookupException("Can't get connection from DBCP-DataSource", e);
  +            throw new LookupException("Could not get connection from DBCP DataSource",
e);
           }
  +        return conn;
       }
   
       public void returnConnectionToPool(JdbcConnectionDescriptor jcd, Connection con)
  @@ -82,7 +85,7 @@
       {
           try
           {
  -            // we using datasources, thus close return connection to pool
  +            // We are using datasources, thus close returns connection to pool
               con.close();
           }
           catch (SQLException e)
  @@ -92,11 +95,82 @@
       }
   
       /**
  -     * Override this method to setup your own pool
  +     * Closes all managed pools.
        */
  -    protected DataSource setupPool(JdbcConnectionDescriptor jcd)
  +    public void releaseAllResources()
       {
  -        log.info("Create new DBCP connection pool:" + jcd);
  +        super.releaseAllResources();
  +        synchronized (poolSynch)
  +        {
  +            if (!poolMap.isEmpty())
  +            {
  +                Collection pools = poolMap.values();
  +                Iterator iterator = pools.iterator();
  +                ObjectPool op = null;
  +                while (iterator.hasNext())
  +                {
  +                    try
  +                    {
  +                        op = (ObjectPool) iterator.next();
  +                        op.close();
  +                    }
  +                    catch (Exception e)
  +                    {
  +                        log.error("Exception occured while closing ObjectPool " + op, e);
  +                    }
  +                }
  +                poolMap.clear();
  +            }
  +            dsMap.clear();
  +        }
  +    }
  +
  +    /**
  +     * Returns the DBCP DataSource for the specified connection descriptor,
  +     * after creating a new DataSource if needed.
  +     * @param jcd the descriptor for which to return a DataSource
  +     * @return a DataSource, after creating a new pool if needed.
  +     * Guaranteed to never be null.
  +     * @throws LookupException if pool is not in cache and cannot be created
  +     */
  +    protected DataSource getDataSource(JdbcConnectionDescriptor jcd)
  +            throws LookupException
  +    {
  +        final PBKey key = jcd.getPBKey();
  +        DataSource ds = (DataSource) dsMap.get(key);
  +        if (ds == null)
  +        {
  +            // Found no pool for PBKey
  +            try
  +            {
  +                synchronized (poolSynch)
  +                {
  +                    // Setup new object pool
  +                    ObjectPool pool = setupPool(jcd);
  +                    poolMap.put(key, pool);
  +                    // Create a DBCP PoolingDataSource from the object pool
  +                    ds = createPoolingDataSource(pool);
  +                    dsMap.put(key, ds);
  +                }
  +            }
  +            catch (Exception e)
  +            {
  +                log.error("Could not setup DBCP DataSource for " + jcd, e);
  +                throw new LookupException(e);
  +            }
  +        }
  +        return ds;
  +    }
  +
  +    /**
  +     * Returns a new ObjectPool for the specified connection descriptor.
  +     * Override this method to setup your own pool.
  +     * @param jcd the connection descriptor for which to set up the pool
  +     * @return a newly created object pool
  +     */
  +    protected ObjectPool setupPool(JdbcConnectionDescriptor jcd)
  +    {
  +        log.info("Create new ObjectPool for DBCP connections:" + jcd);
   
           try
           {
  @@ -121,11 +195,6 @@
   
           // First, we'll need a ObjectPool that serves as the
           // actual pool of connections.
  -        //
  -        // We'll use a GenericObjectPool instance, although
  -        // any ObjectPool implementation will suffice.
  -        //
  -        // TODO: make objectPool configurable at runtime?
           ObjectPool connectionPool = createObjectPool(conf);
   
           // Next, we'll create a ConnectionFactory that the
  @@ -134,7 +203,7 @@
           //
           org.apache.commons.dbcp.ConnectionFactory connectionFactory = createConnectionFactory(jcd);
   
  -        KeyedObjectPoolFactory statementPoolFactory = createStatementPoolFactory(null);
  +        KeyedObjectPoolFactory statementPoolFactory = createStatementPoolFactory(jcd);
           // set the validation query
           String validationQuery = jcd.getConnectionPoolDescriptor().getValidationQuery();
           boolean defaultReadOnly = false;
  @@ -159,31 +228,94 @@
                   defaultAutoCommit,
                   ac);
   
  -        //
  -        // Finally, we create the PoolingDriver itself,
  -        // passing in the object pool we created.
  -        //
  -        PoolingDataSource dataSource = createPoolingDataSource(poolableConnectionFactory.getPool());
  -        return dataSource;
  +        return poolableConnectionFactory.getPool();
       }
   
       protected ObjectPool createObjectPool(GenericObjectPool.Config config)
       {
  +        // We'll use a GenericObjectPool instance, although
  +        // any ObjectPool implementation will suffice.
  +        //
  +        // TODO: make objectPool configurable at runtime?
           return new GenericObjectPool(null, config);
       }
   
  -    protected org.apache.commons.dbcp.ConnectionFactory createConnectionFactory(JdbcConnectionDescriptor
jcd)
  +    protected KeyedObjectPoolFactory createStatementPoolFactory(JdbcConnectionDescriptor
jcd)
       {
  -        return new DriverManagerConnectionFactory(getDbURL(jcd), jcd.getUserName(), jcd.getPassWord());
  -    }
  +        final String platform = jcd.getDbms();
  +        if (platform.equals("Oracle9i"))
  +        {
  +            // mkalen: let the platform set Oracle-specific statement pooling
  +            return null;
  +        }
   
  -    protected KeyedObjectPoolFactory createStatementPoolFactory(Object obj)
  -    {
  -        return new GenericKeyedObjectPoolFactory(null);
  +        final KeyedObjectPoolFactory stmtPoolFactory;
  +        final KeyedPoolableObjectFactory objectFactory = null;
  +        final GenericKeyedObjectPool.Config factoryConfig = new GenericKeyedObjectPool.Config();
  +        /*
  +        // TODO: mkalen: allow to configure PreparedStatement pool
  +        final int maxTotalStmts = 100;
  +        factoryConfig.maxActive = (int) (maxTotalStmts * 0.7);
  +        factoryConfig.maxIdle = (int) (maxTotalStmts * 0.3);
  +        factoryConfig.maxTotal = maxTotalStmts;
  +        factoryConfig.testOnBorrow = true;
  +        factoryConfig.testWhileIdle = true;
  +        factoryConfig.testOnReturn = true;
  +        factoryConfig.numTestsPerEvictionRun = factoryConfig.maxTotal;
  +        factoryConfig.minEvictableIdleTimeMillis = 30 * 1000;
  +        */
  +        stmtPoolFactory = new GenericKeyedObjectPoolFactory(objectFactory, factoryConfig);
  +        return stmtPoolFactory;
       }
   
       protected PoolingDataSource createPoolingDataSource(ObjectPool pool)
       {
           return new PoolingDataSource(pool);
       }
  +
  +    protected org.apache.commons.dbcp.ConnectionFactory createConnectionFactory(JdbcConnectionDescriptor
jcd)
  +    {
  +        return new ConPoolFactory(jcd);
  +    }
  +
  +    //**************************************************************************************
  +    // Inner classes
  +    //************************************************************************************
  +
  +    /**
  +     * Inner class used as factory for connection pooling.
  +     * Adhers to OJB platform specification by calling platform-specific init methods
  +     * on newly created connections.
  +     * @see DriverManagerConnectionFactory
  +     */
  +    class ConPoolFactory extends DriverManagerConnectionFactory
  +    {
  +
  +        private final JdbcConnectionDescriptor jcd;
  +
  +        public ConPoolFactory(JdbcConnectionDescriptor jcd)
  +        {
  +            super(getDbURL(jcd), jcd.getUserName(), jcd.getPassWord());
  +            this.jcd = jcd;
  +        }
  +
  +        public Connection createConnection() throws SQLException
  +        {
  +            final Connection conn = super.createConnection();
  +            if (conn != null)
  +            {
  +                try
  +                {
  +                    initializeJdbcConnection(conn, jcd);
  +                }
  +                catch (LookupException e)
  +                {
  +                    log.error("Platform dependent initialization of connection failed",
e);
  +                }
  +            }
  +            return conn;
  +        }
  +
  +    }
  +
   }
  
  
  
  No                   revision
  No                   revision
  1.54.2.35 +4 -5      db-ojb/release-notes.txt
  
  Index: release-notes.txt
  ===================================================================
  RCS file: /home/cvs/db-ojb/release-notes.txt,v
  retrieving revision 1.54.2.34
  retrieving revision 1.54.2.35
  diff -u -r1.54.2.34 -r1.54.2.35
  --- release-notes.txt	16 Mar 2005 11:38:17 -0000	1.54.2.34
  +++ release-notes.txt	16 Mar 2005 17:51:18 -0000	1.54.2.35
  @@ -40,6 +40,9 @@
     please see comments in OJB.properties file.
   
   CHANGES:
  +- When using Oracl9i platform and DBCP connection factory, no PreparedStatement caching
will occur
  +  in the DBCP pool (Oracle JDBC-driver statement caching is performed by the platform as
default).
  +  statement pool, to avoid running out of server-side cursors when using Oracle9i platform.
   - Oracle9i default platform should now be usable and have large LOB support in JBoss environemnts,
     please try the default Oracle9i platform and report your results to the ojb-user list.
   - Oracle9i default platform should now be usable and have large LOB support in BEA WebLogic,
  @@ -151,10 +154,6 @@
     in production environments. The future of the OTM layer will be subject for discussion
on the
     OJB developers list, if you are using it - please subscribe to ojb-dev and make your
voice heard.
   - Oracle9i platform: when using statement batching, there is a 2k limit on BLOB + 4k limit
on CLOB.
  -- Oracle9i platform: when using ConnectionFactoryDBCPImpl OJB can run out of Oracle cursors,
  -  since prepared statements are cached by the default DBCP connection factory. A work-around
  -  is to extend ConnectionFActoryDBCPImpl and override the createStatementPoolFactory()-method
  -  with a null-return (=no DBCP PreparedStatement cache).
   
   
   ---------------------------------------------------------------------
  
  
  

---------------------------------------------------------------------
To unsubscribe, e-mail: ojb-dev-unsubscribe@db.apache.org
For additional commands, e-mail: ojb-dev-help@db.apache.org


Mime
View raw message