001 /* 002 // $Id: //open/mondrian/src/main/mondrian/rolap/RolapConnectionPool.java#9 $ 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 // create a PoolableConnectionFactory 098 AbandonedConfig abandonedConfig = new AbandonedConfig(); 099 // flag to remove abandoned connections from pool 100 abandonedConfig.setRemoveAbandoned(true); 101 // timeout (seconds) before removing abandoned connections 102 abandonedConfig.setRemoveAbandonedTimeout(300); 103 // Flag to log stack traces for application code which abandoned a 104 // Statement or Connection 105 abandonedConfig.setLogAbandoned(true); 106 PoolableConnectionFactory poolableConnectionFactory 107 = new PoolableConnectionFactory( 108 // the connection factory 109 connectionFactory, 110 // the object pool 111 connectionPool, 112 // statement pool factory for pooling prepared statements, 113 // or null for no pooling 114 null, 115 // validation query (must return at least 1 row e.g. Oracle: 116 // select count(*) from dual) to test connection, can be 117 // null 118 null, 119 // default "read only" setting for borrowed connections 120 false, 121 // default "auto commit" setting for returned connections 122 true, 123 // AbandonedConfig object configures how to handle abandoned 124 // connections 125 abandonedConfig); 126 127 // "poolableConnectionFactory" has registered itself with 128 // "connectionPool", somehow, so we don't need the value any more. 129 Util.discard(poolableConnectionFactory); 130 mapConnectKeyToPool.put(key, connectionPool); 131 } 132 return connectionPool; 133 } 134 135 } 136 137 // End RolapConnectionPool.java