001 /*
002 // $Id: //open/mondrian-release/3.0/src/main/mondrian/rolap/RolapConnectionPool.java#2 $
003 // This software is subject to the terms of the Common Public License
004 // Agreement, available at the following URL:
005 // http://www.opensource.org/licenses/cpl.html.
006 // Copyright (C) 2003-2006 Robin Bagot, Julian Hyde and others
007 // All Rights Reserved.
008 // You must accept the terms of that agreement to use this software.
009 */
010 package mondrian.rolap;
011
012 import mondrian.olap.Util;
013 import org.apache.commons.dbcp.*;
014 import org.apache.commons.pool.ObjectPool;
015 import org.apache.commons.pool.impl.GenericObjectPool;
016
017 import javax.sql.DataSource;
018 import java.util.Map;
019 import java.util.HashMap;
020
021 /**
022 * Singleton class that holds a connection pool.
023 * Call RolapConnectionPool.instance().getPoolingDataSource(connectionFactory)
024 * to get a DataSource in return that is a pooled data source.
025 */
026 class RolapConnectionPool {
027
028 public static RolapConnectionPool instance() {
029 return instance;
030 }
031 private static final RolapConnectionPool instance = new RolapConnectionPool();
032
033 private final Map<Object, ObjectPool> mapConnectKeyToPool =
034 new HashMap<Object, ObjectPool>();
035
036 private RolapConnectionPool() {
037 }
038
039
040 /**
041 * Sets up a pooling data source for connection pooling.
042 * This can be used if the application server does not have a pooling
043 * dataSource already configured.
044 * This takes a normal jdbc connection string, and requires a jdbc
045 * driver to be loaded, and then uses a
046 * {@link DriverManagerConnectionFactory} to create connections to the
047 * database.
048 * An alternative method of configuring a pooling driver is to use an external
049 * configuration file. See the the Apache jakarta-commons commons-pool
050 * documentation.
051 *
052 * @param key Identifies which connection factory to use. A typical key is
053 * a JDBC connect string, since each JDBC connect string requires a
054 * different connection factory.
055 * @param connectionFactory Creates connections from an underlying
056 * JDBC connect string or DataSource
057 * @return a pooling DataSource object
058 */
059 public synchronized DataSource getPoolingDataSource(Object key,
060 ConnectionFactory connectionFactory) {
061 ObjectPool connectionPool = getPool(key, connectionFactory);
062 // create pooling datasource
063 return new PoolingDataSource(connectionPool);
064 }
065
066 /**
067 * Clears the connection pool for testing purposes
068 */
069 void clearPool() {
070 mapConnectKeyToPool.clear();
071 }
072
073 /**
074 * Gets or creates a connection pool for a particular connect
075 * specification.
076 */
077 private synchronized ObjectPool getPool(
078 Object key,
079 ConnectionFactory connectionFactory)
080 {
081 ObjectPool connectionPool = mapConnectKeyToPool.get(key);
082 if (connectionPool == null) {
083 // use GenericObjectPool, which provides for resource limits
084 connectionPool = new GenericObjectPool(
085 null, // PoolableObjectFactory, can be null
086 50, // max active
087 GenericObjectPool.WHEN_EXHAUSTED_BLOCK, // action when exhausted
088 3000, // max wait (milli seconds)
089 10, // max idle
090 false, // test on borrow
091 false, // test on return
092 60000, // time between eviction runs (millis)
093 5, // number to test on eviction run
094 30000, // min evictable idle time (millis)
095 true // test while idle
096 );
097
098 // create a PoolableConnectionFactory
099 AbandonedConfig abandonedConfig = new AbandonedConfig();
100 // flag to remove abandoned connections from pool
101 abandonedConfig.setRemoveAbandoned(true);
102 // timeout (seconds) before removing abandoned connections
103 abandonedConfig.setRemoveAbandonedTimeout(300);
104 // Flag to log stack traces for application code which abandoned a
105 // Statement or Connection
106 abandonedConfig.setLogAbandoned(true);
107 PoolableConnectionFactory poolableConnectionFactory
108 = new PoolableConnectionFactory(
109 // the connection factory
110 connectionFactory,
111 // the object pool
112 connectionPool,
113 // statement pool factory for pooling prepared statements,
114 // or null for no pooling
115 null,
116 // validation query (must return at least 1 row e.g. Oracle:
117 // select count(*) from dual) to test connection, can be
118 // null
119 null,
120 // default "read only" setting for borrowed connections
121 false,
122 // default "auto commit" setting for returned connections
123 true,
124 // AbandonedConfig object configures how to handle abandoned
125 // connections
126 abandonedConfig
127 );
128 // "poolableConnectionFactory" has registered itself with
129 // "connectionPool", somehow, so we don't need the value any more.
130 Util.discard(poolableConnectionFactory);
131 mapConnectKeyToPool.put(key, connectionPool);
132 }
133 return connectionPool;
134 }
135
136 }
137
138 // End RolapConnectionPool.java