Author: tv Date: Fri Nov 20 13:21:58 2015 New Revision: 1715353 URL: http://svn.apache.org/viewvc?rev=1715353&view=rev Log: Replace PoolAccess with a DataSourceFactory model borrowed from DB-Torque
Added: commons/proper/jcs/trunk/commons-jcs-core/src/main/java/org/apache/commons/jcs/auxiliary/disk/jdbc/dsfactory/ commons/proper/jcs/trunk/commons-jcs-core/src/main/java/org/apache/commons/jcs/auxiliary/disk/jdbc/dsfactory/DataSourceFactory.java (with props) commons/proper/jcs/trunk/commons-jcs-core/src/main/java/org/apache/commons/jcs/auxiliary/disk/jdbc/dsfactory/JndiDataSourceFactory.java (with props) commons/proper/jcs/trunk/commons-jcs-core/src/main/java/org/apache/commons/jcs/auxiliary/disk/jdbc/dsfactory/SharedPoolDataSourceFactory.java (with props) commons/proper/jcs/trunk/commons-jcs-core/src/test/java/org/apache/commons/jcs/auxiliary/disk/jdbc/JDBCDataSourceFactoryUnitTest.java - copied, changed from r1704856, commons/proper/jcs/trunk/commons-jcs-core/src/test/java/org/apache/commons/jcs/auxiliary/disk/jdbc/JDBCDiskCachePoolAccessManagerUnitTest.java Removed: commons/proper/jcs/trunk/commons-jcs-core/src/main/java/org/apache/commons/jcs/auxiliary/disk/jdbc/JDBCDiskCachePoolAccess.java commons/proper/jcs/trunk/commons-jcs-core/src/main/java/org/apache/commons/jcs/auxiliary/disk/jdbc/JDBCDiskCachePoolAccessAttributes.java commons/proper/jcs/trunk/commons-jcs-core/src/main/java/org/apache/commons/jcs/auxiliary/disk/jdbc/JDBCDiskCachePoolAccessManager.java commons/proper/jcs/trunk/commons-jcs-core/src/test/java/org/apache/commons/jcs/auxiliary/disk/jdbc/JDBCDiskCachePoolAccessManagerUnitTest.java commons/proper/jcs/trunk/commons-jcs-core/src/test/java/org/apache/commons/jcs/auxiliary/disk/jdbc/mysql/MySQLTableOptimizerManualTester.java Modified: commons/proper/jcs/trunk/commons-jcs-core/src/main/java/org/apache/commons/jcs/auxiliary/disk/jdbc/JDBCDiskCache.java commons/proper/jcs/trunk/commons-jcs-core/src/main/java/org/apache/commons/jcs/auxiliary/disk/jdbc/JDBCDiskCacheAttributes.java commons/proper/jcs/trunk/commons-jcs-core/src/main/java/org/apache/commons/jcs/auxiliary/disk/jdbc/JDBCDiskCacheFactory.java commons/proper/jcs/trunk/commons-jcs-core/src/main/java/org/apache/commons/jcs/auxiliary/disk/jdbc/mysql/MySQLDiskCache.java commons/proper/jcs/trunk/commons-jcs-core/src/main/java/org/apache/commons/jcs/auxiliary/disk/jdbc/mysql/MySQLDiskCacheFactory.java commons/proper/jcs/trunk/commons-jcs-core/src/main/java/org/apache/commons/jcs/auxiliary/disk/jdbc/mysql/MySQLTableOptimizer.java commons/proper/jcs/trunk/commons-jcs-core/src/test/java/org/apache/commons/jcs/auxiliary/disk/jdbc/JDBCDiskCacheUnitTest.java commons/proper/jcs/trunk/commons-jcs-core/src/test/java/org/apache/commons/jcs/auxiliary/disk/jdbc/mysql/MySQLDiskCacheUnitTest.java commons/proper/jcs/trunk/src/changes/changes.xml Modified: commons/proper/jcs/trunk/commons-jcs-core/src/main/java/org/apache/commons/jcs/auxiliary/disk/jdbc/JDBCDiskCache.java URL: http://svn.apache.org/viewvc/commons/proper/jcs/trunk/commons-jcs-core/src/main/java/org/apache/commons/jcs/auxiliary/disk/jdbc/JDBCDiskCache.java?rev=1715353&r1=1715352&r2=1715353&view=diff ============================================================================== --- commons/proper/jcs/trunk/commons-jcs-core/src/main/java/org/apache/commons/jcs/auxiliary/disk/jdbc/JDBCDiskCache.java (original) +++ commons/proper/jcs/trunk/commons-jcs-core/src/main/java/org/apache/commons/jcs/auxiliary/disk/jdbc/JDBCDiskCache.java Fri Nov 20 13:21:58 2015 @@ -29,9 +29,13 @@ import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Set; +import java.util.concurrent.atomic.AtomicInteger; + +import javax.sql.DataSource; import org.apache.commons.jcs.auxiliary.AuxiliaryCacheAttributes; import org.apache.commons.jcs.auxiliary.disk.AbstractDiskCache; +import org.apache.commons.jcs.auxiliary.disk.jdbc.dsfactory.DataSourceFactory; import org.apache.commons.jcs.engine.CacheConstants; import org.apache.commons.jcs.engine.behavior.ICacheElement; import org.apache.commons.jcs.engine.behavior.ICompositeCacheManager; @@ -88,19 +92,19 @@ public class JDBCDiskCache<K, V> private JDBCDiskCacheAttributes jdbcDiskCacheAttributes; /** # of times update was called */ - private int updateCount = 0; + private AtomicInteger updateCount = new AtomicInteger(0); /** # of times get was called */ - private int getCount = 0; + private AtomicInteger getCount = new AtomicInteger(0); /** # of times getMatching was called */ - private int getMatchingCount = 0; + private AtomicInteger getMatchingCount = new AtomicInteger(0); /** if count % interval == 0 then log */ private static final int LOG_INTERVAL = 100; /** db connection pool */ - private JDBCDiskCachePoolAccess poolAccess = null; + private DataSourceFactory dsFactory = null; /** tracks optimization */ private TableState tableState; @@ -109,13 +113,13 @@ public class JDBCDiskCache<K, V> * Constructs a JDBC Disk Cache for the provided cache attributes. The table state object is * used to mark deletions. * <p> - * @param cattr - * @param tableState - * @param compositeCacheManager - * @throws SQLException if the pool access could not be set up + * @param cattr the configuration object for this cache + * @param dsFactory the DataSourceFactory for this cache + * @param tableState an object to track table operations + * @param compositeCacheManager the global cache manager */ - public JDBCDiskCache( JDBCDiskCacheAttributes cattr, TableState tableState, - ICompositeCacheManager compositeCacheManager ) throws SQLException + public JDBCDiskCache( JDBCDiskCacheAttributes cattr, DataSourceFactory dsFactory, TableState tableState, + ICompositeCacheManager compositeCacheManager ) { super( cattr ); @@ -128,39 +132,13 @@ public class JDBCDiskCache<K, V> } // This initializes the pool access. - this.poolAccess = initializePoolAccess( cattr, compositeCacheManager ); + this.dsFactory = dsFactory; // Initialization finished successfully, so set alive to true. alive = true; } /** - * Registers the driver and creates a poolAccess class. - * <p> - * @param cattr - * @param compositeCacheManager - * @return JDBCDiskCachePoolAccess for testing - * @throws SQLException if a database access error occurs - */ - protected JDBCDiskCachePoolAccess initializePoolAccess( JDBCDiskCacheAttributes cattr, - ICompositeCacheManager compositeCacheManager ) throws SQLException - { - JDBCDiskCachePoolAccess poolAccess1 = null; - if ( cattr.getConnectionPoolName() != null ) - { - JDBCDiskCachePoolAccessManager manager = JDBCDiskCachePoolAccessManager.getInstance(); - poolAccess1 = manager.getJDBCDiskCachePoolAccess( - cattr.getConnectionPoolName(), - compositeCacheManager.getConfigurationProperties() ); - } - else - { - poolAccess1 = JDBCDiskCachePoolAccessManager.createPoolAccess( cattr ); - } - return poolAccess1; - } - - /** * Inserts or updates. By default it will try to insert. If the item exists we will get an * error. It will then update. This behavior is configurable. The cache can be configured to * check before inserting. @@ -170,7 +148,7 @@ public class JDBCDiskCache<K, V> @Override protected void processUpdate( ICacheElement<K, V> ce ) { - incrementUpdateCount(); + updateCount.incrementAndGet(); if ( log.isDebugEnabled() ) { @@ -180,7 +158,7 @@ public class JDBCDiskCache<K, V> Connection con; try { - con = getPoolAccess().getConnection(); + con = getDataSource().getConnection(); } catch ( SQLException e ) { @@ -223,7 +201,7 @@ public class JDBCDiskCache<K, V> if ( log.isInfoEnabled() ) { - if ( updateCount % LOG_INTERVAL == 0 ) + if ( updateCount.get() % LOG_INTERVAL == 0 ) { // TODO make a log stats method log.info( "Update Count [" + updateCount + "]" ); @@ -247,7 +225,7 @@ public class JDBCDiskCache<K, V> // First do a query to determine if the element already exists if ( this.getJdbcDiskCacheAttributes().isTestBeforeInsert() ) { - exists = doesElementExist( ce ); + exists = doesElementExist( ce, con ); } // If it doesn't exist, insert it, otherwise update @@ -320,7 +298,7 @@ public class JDBCDiskCache<K, V> // see if it exists, if we didn't already if ( !exists && !this.getJdbcDiskCacheAttributes().isTestBeforeInsert() ) { - exists = doesElementExist( ce ); + exists = doesElementExist( ce, con ); } } return exists; @@ -372,24 +350,13 @@ public class JDBCDiskCache<K, V> /** * Does an element exist for this key? * <p> - * @param ce + * @param ce the cache element + * @param con a database connection * @return boolean */ - protected boolean doesElementExist( ICacheElement<K, V> ce ) + protected boolean doesElementExist( ICacheElement<K, V> ce, Connection con ) { boolean exists = false; - - Connection con; - try - { - con = getPoolAccess().getConnection(); - } - catch ( SQLException e ) - { - log.error( "Problem getting connection.", e ); - return exists; - } - PreparedStatement psSelect = null; try { @@ -432,15 +399,6 @@ public class JDBCDiskCache<K, V> { log.error( "Problem closing statement.", e1 ); } - - try - { - con.close(); - } - catch ( SQLException e ) - { - log.error( "Problem closing connection.", e ); - } } return exists; @@ -456,7 +414,7 @@ public class JDBCDiskCache<K, V> @Override protected ICacheElement<K, V> processGet( K key ) { - incrementGetCount(); + getCount.incrementAndGet(); if ( log.isDebugEnabled() ) { @@ -477,7 +435,7 @@ public class JDBCDiskCache<K, V> String selectString = "select ELEMENT from " + getJdbcDiskCacheAttributes().getTableName() + " where REGION = ? and CACHE_KEY = ?"; - Connection con = getPoolAccess().getConnection(); + Connection con = getDataSource().getConnection(); try { PreparedStatement psSelect = null; @@ -542,7 +500,7 @@ public class JDBCDiskCache<K, V> if ( log.isInfoEnabled() ) { - if ( getCount % LOG_INTERVAL == 0 ) + if ( getCount.get() % LOG_INTERVAL == 0 ) { // TODO make a log stats method log.info( "Get Count [" + getCount + "]" ); @@ -561,7 +519,7 @@ public class JDBCDiskCache<K, V> @Override protected Map<K, ICacheElement<K, V>> processGetMatching( String pattern ) { - incrementGetMatchingCount(); + getMatchingCount.incrementAndGet(); if ( log.isDebugEnabled() ) { @@ -581,7 +539,7 @@ public class JDBCDiskCache<K, V> String selectString = "select CACHE_KEY, ELEMENT from " + getJdbcDiskCacheAttributes().getTableName() + " where REGION = ? and CACHE_KEY like ?"; - Connection con = getPoolAccess().getConnection(); + Connection con = getDataSource().getConnection(); try { PreparedStatement psSelect = null; @@ -648,7 +606,7 @@ public class JDBCDiskCache<K, V> if ( log.isInfoEnabled() ) { - if ( getMatchingCount % LOG_INTERVAL == 0 ) + if ( getMatchingCount.get() % LOG_INTERVAL == 0 ) { // TODO make a log stats method log.info( "Get Matching Count [" + getMatchingCount + "]" ); @@ -698,7 +656,7 @@ public class JDBCDiskCache<K, V> + " where REGION = ? and CACHE_KEY like ?"; partial = true; } - Connection con = getPoolAccess().getConnection(); + Connection con = getDataSource().getConnection(); PreparedStatement psSelect = null; try { @@ -759,7 +717,7 @@ public class JDBCDiskCache<K, V> try { String sql = "delete from " + getJdbcDiskCacheAttributes().getTableName() + " where REGION = ?"; - Connection con = getPoolAccess().getConnection(); + Connection con = getDataSource().getConnection(); PreparedStatement psDelete = null; try { @@ -828,7 +786,7 @@ public class JDBCDiskCache<K, V> String sql = "delete from " + getJdbcDiskCacheAttributes().getTableName() + " where IS_ETERNAL = ? and REGION = ? and ? > SYSTEM_EXPIRE_TIME_SECONDS"; - Connection con = getPoolAccess().getConnection(); + Connection con = getDataSource().getConnection(); PreparedStatement psDelete = null; try { @@ -896,9 +854,9 @@ public class JDBCDiskCache<K, V> { try { - getPoolAccess().shutdownDriver(); + dsFactory.close(); } - catch ( Exception e ) + catch ( SQLException e ) { log.error( "Problem shutting down.", e ); } @@ -923,20 +881,17 @@ public class JDBCDiskCache<K, V> String selectString = "select count(*) from " + getJdbcDiskCacheAttributes().getTableName() + " where REGION = ?"; - final JDBCDiskCachePoolAccess pool = getPoolAccess(); - if (pool == null) { - return size; - } Connection con; try { - con = pool.getConnection(); + con = getDataSource().getConnection(); } - catch ( SQLException e1 ) + catch ( SQLException e ) { - log.error( "Problem getting connection.", e1 ); + log.error( "Problem getting connection.", e ); return size; } + try { PreparedStatement psSelect = null; @@ -1018,24 +973,6 @@ public class JDBCDiskCache<K, V> return elementSerializer; } - /** safely increment */ - private synchronized void incrementUpdateCount() - { - updateCount++; - } - - /** safely increment */ - private synchronized void incrementGetCount() - { - getCount++; - } - - /** safely increment */ - private synchronized void incrementGetMatchingCount() - { - getMatchingCount++; - } - /** * @param jdbcDiskCacheAttributes The jdbcDiskCacheAttributes to set. */ @@ -1074,20 +1011,10 @@ public class JDBCDiskCache<K, V> List<IStatElement<?>> elems = stats.getStatElements(); - elems.add(new StatElement<Integer>( "Update Count", Integer.valueOf(updateCount) ) ); - elems.add(new StatElement<Integer>( "Get Count", Integer.valueOf(getCount) ) ); - elems.add(new StatElement<Integer>( "Get Matching Count", Integer.valueOf(getMatchingCount) ) ); - - final JDBCDiskCachePoolAccess pool = getPoolAccess(); - - elems.add(new StatElement<Integer>( "Size", - Integer.valueOf(pool != null ? getSize() : -1) ) ); - elems.add(new StatElement<Integer>( "Active DB Connections", - Integer.valueOf(pool != null ? pool.getNumActiveInPool() : -1) ) ); - elems.add(new StatElement<Integer>( "Idle DB Connections", - Integer.valueOf(pool != null ? pool.getNumIdleInPool() : -1) ) ); - elems.add(new StatElement<String>( "DB URL", - pool != null ? pool.getPoolUrl() : getJdbcDiskCacheAttributes().getUrl()) ); + elems.add(new StatElement<AtomicInteger>( "Update Count", updateCount ) ); + elems.add(new StatElement<AtomicInteger>( "Get Count", getCount ) ); + elems.add(new StatElement<AtomicInteger>( "Get Matching Count", getMatchingCount ) ); + elems.add(new StatElement<String>( "DB URL", getJdbcDiskCacheAttributes().getUrl()) ); stats.setStatElements( elems ); @@ -1138,11 +1065,12 @@ public class JDBCDiskCache<K, V> /** * Public so managers can access it. - * @return the poolAccess + * @return the dsFactory + * @throws SQLException if getting a data source fails */ - public JDBCDiskCachePoolAccess getPoolAccess() + public DataSource getDataSource() throws SQLException { - return poolAccess; + return dsFactory.getDataSource(); } /** Modified: commons/proper/jcs/trunk/commons-jcs-core/src/main/java/org/apache/commons/jcs/auxiliary/disk/jdbc/JDBCDiskCacheAttributes.java URL: http://svn.apache.org/viewvc/commons/proper/jcs/trunk/commons-jcs-core/src/main/java/org/apache/commons/jcs/auxiliary/disk/jdbc/JDBCDiskCacheAttributes.java?rev=1715353&r1=1715352&r2=1715353&view=diff ============================================================================== --- commons/proper/jcs/trunk/commons-jcs-core/src/main/java/org/apache/commons/jcs/auxiliary/disk/jdbc/JDBCDiskCacheAttributes.java (original) +++ commons/proper/jcs/trunk/commons-jcs-core/src/main/java/org/apache/commons/jcs/auxiliary/disk/jdbc/JDBCDiskCacheAttributes.java Fri Nov 20 13:21:58 2015 @@ -50,6 +50,12 @@ public class JDBCDiskCacheAttributes /** The driver */ private String driverClassName; + /** The JNDI path. */ + private String jndiPath; + + /** The time between two JNDI lookups */ + private long jndiTTL = 0L; + /** The table name */ private String tableName = DEFAULT_TABLE_NAME; @@ -69,7 +75,10 @@ public class JDBCDiskCacheAttributes private int shrinkerIntervalSeconds = DEFAULT_SHRINKER_INTERVAL_SECONDS; /** Should we remove expired in the background. */ - private boolean UseDiskShrinker = true; + private boolean useDiskShrinker = true; + + /** The default Pool Name to which the connection pool will be keyed. */ + public static final String DEFAULT_POOL_NAME = "jcs"; /** * If a pool name is supplied, the manager will attempt to load it. It should be configured in a @@ -167,6 +176,38 @@ public class JDBCDiskCacheAttributes } /** + * @return the jndiPath + */ + public String getJndiPath() + { + return jndiPath; + } + + /** + * @param jndiPath the jndiPath to set + */ + public void setJndiPath(String jndiPath) + { + this.jndiPath = jndiPath; + } + + /** + * @return the jndiTTL + */ + public long getJndiTTL() + { + return jndiTTL; + } + + /** + * @param jndiTTL the jndiTTL to set + */ + public void setJndiTTL(long jndiTTL) + { + this.jndiTTL = jndiTTL; + } + + /** * @param tableName The tableName to set. */ public void setTableName( String tableName ) @@ -238,7 +279,7 @@ public class JDBCDiskCacheAttributes */ public void setUseDiskShrinker( boolean useDiskShrinker ) { - UseDiskShrinker = useDiskShrinker; + this.useDiskShrinker = useDiskShrinker; } /** @@ -246,7 +287,7 @@ public class JDBCDiskCacheAttributes */ public boolean isUseDiskShrinker() { - return UseDiskShrinker; + return useDiskShrinker; } /** @@ -284,7 +325,7 @@ public class JDBCDiskCacheAttributes buf.append( "\n MaxActive [" + getMaxActive() + "]" ); buf.append( "\n AllowRemoveAll [" + isAllowRemoveAll() + "]" ); buf.append( "\n ShrinkerIntervalSeconds [" + getShrinkerIntervalSeconds() + "]" ); - buf.append( "\n UseDiskShrinker [" + isUseDiskShrinker() + "]" ); + buf.append( "\n useDiskShrinker [" + isUseDiskShrinker() + "]" ); return buf.toString(); } } Modified: commons/proper/jcs/trunk/commons-jcs-core/src/main/java/org/apache/commons/jcs/auxiliary/disk/jdbc/JDBCDiskCacheFactory.java URL: http://svn.apache.org/viewvc/commons/proper/jcs/trunk/commons-jcs-core/src/main/java/org/apache/commons/jcs/auxiliary/disk/jdbc/JDBCDiskCacheFactory.java?rev=1715353&r1=1715352&r2=1715353&view=diff ============================================================================== --- commons/proper/jcs/trunk/commons-jcs-core/src/main/java/org/apache/commons/jcs/auxiliary/disk/jdbc/JDBCDiskCacheFactory.java (original) +++ commons/proper/jcs/trunk/commons-jcs-core/src/main/java/org/apache/commons/jcs/auxiliary/disk/jdbc/JDBCDiskCacheFactory.java Fri Nov 20 13:21:58 2015 @@ -20,28 +20,33 @@ package org.apache.commons.jcs.auxiliary */ import java.sql.SQLException; -import java.util.HashMap; -import java.util.Map; -import java.util.concurrent.Executors; +import java.util.Properties; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.ConcurrentMap; import java.util.concurrent.ScheduledExecutorService; import java.util.concurrent.TimeUnit; import org.apache.commons.jcs.auxiliary.AbstractAuxiliaryCacheFactory; import org.apache.commons.jcs.auxiliary.AuxiliaryCacheAttributes; +import org.apache.commons.jcs.auxiliary.disk.jdbc.dsfactory.DataSourceFactory; +import org.apache.commons.jcs.auxiliary.disk.jdbc.dsfactory.JndiDataSourceFactory; +import org.apache.commons.jcs.auxiliary.disk.jdbc.dsfactory.SharedPoolDataSourceFactory; import org.apache.commons.jcs.engine.behavior.ICompositeCacheManager; import org.apache.commons.jcs.engine.behavior.IElementSerializer; +import org.apache.commons.jcs.engine.behavior.IRequireScheduler; import org.apache.commons.jcs.engine.logging.behavior.ICacheEventLogger; -import org.apache.commons.jcs.utils.threadpool.DaemonThreadFactory; +import org.apache.commons.jcs.utils.config.PropertySetter; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; /** - * This factory should create mysql disk caches. + * This factory should create JDBC auxiliary caches. * <p> * @author Aaron Smuts */ public class JDBCDiskCacheFactory extends AbstractAuxiliaryCacheFactory + implements IRequireScheduler { /** The logger */ private static final Log log = LogFactory.getLog( JDBCDiskCacheFactory.class ); @@ -50,25 +55,34 @@ public class JDBCDiskCacheFactory * A map of TableState objects to table names. Each cache has a table state object, which is * used to determine if any long processes such as deletes or optimizations are running. */ - private Map<String, TableState> tableStates; + private ConcurrentMap<String, TableState> tableStates; - /** The background scheduler, one for all regions. */ - protected ScheduledExecutorService scheduler; // TODO this is not accessed in a threadsafe way. Perhaps use IODH idiom? + /** The background scheduler, one for all regions. Injected by the configurator */ + protected ScheduledExecutorService scheduler; /** * A map of table name to shrinker threads. This allows each table to have a different setting. * It assumes that there is only one jdbc disk cache auxiliary defined per table. */ - private Map<String, ShrinkerThread> shrinkerThreadMap; + private ConcurrentMap<String, ShrinkerThread> shrinkerThreadMap; + + /** Pool name to DataSourceFactories */ + private ConcurrentMap<String, DataSourceFactory> dsFactories; + + /** props prefix */ + protected static final String POOL_CONFIGURATION_PREFIX = "jcs.jdbcconnectionpool."; + + /** .attributes */ + protected static final String ATTRIBUTE_PREFIX = ".attributes"; /** * This factory method should create an instance of the jdbc cache. * <p> - * @param rawAttr - * @param compositeCacheManager - * @param cacheEventLogger - * @param elementSerializer - * @return JDBCDiskCache + * @param rawAttr specific cache configuration attributes + * @param compositeCacheManager the global cache manager + * @param cacheEventLogger a specific logger for cache events + * @param elementSerializer a serializer for cache elements + * @return JDBCDiskCache the cache instance * @throws SQLException if the cache instance could not be created */ @Override @@ -79,8 +93,9 @@ public class JDBCDiskCacheFactory { JDBCDiskCacheAttributes cattr = (JDBCDiskCacheAttributes) rawAttr; TableState tableState = getTableState( cattr.getTableName() ); + DataSourceFactory dsFactory = getDataSourceFactory(cattr, compositeCacheManager.getConfigurationProperties()); - JDBCDiskCache<K, V> cache = new JDBCDiskCache<K, V>( cattr, tableState, compositeCacheManager ); + JDBCDiskCache<K, V> cache = new JDBCDiskCache<K, V>( cattr, dsFactory, tableState, compositeCacheManager ); cache.setCacheEventLogger( cacheEventLogger ); cache.setElementSerializer( elementSerializer ); @@ -97,8 +112,9 @@ public class JDBCDiskCacheFactory public void initialize() { super.initialize(); - this.tableStates = new HashMap<String, TableState>(); - this.shrinkerThreadMap = new HashMap<String, ShrinkerThread>(); + this.tableStates = new ConcurrentHashMap<String, TableState>(); + this.shrinkerThreadMap = new ConcurrentHashMap<String, ShrinkerThread>(); + this.dsFactories = new ConcurrentHashMap<String, DataSourceFactory>(); } /** @@ -107,11 +123,22 @@ public class JDBCDiskCacheFactory @Override public void dispose() { - if (this.scheduler != null) + this.tableStates.clear(); + + for (DataSourceFactory dsFactory : this.dsFactories.values()) { - this.scheduler.shutdownNow(); - this.scheduler = null; + try + { + dsFactory.close(); + } + catch (SQLException e) + { + log.error("Could not close data source factory " + dsFactory.getName(), e); + } } + + this.dsFactories.clear(); + this.shrinkerThreadMap.clear(); super.dispose(); } @@ -123,30 +150,33 @@ public class JDBCDiskCacheFactory */ protected TableState getTableState(String tableName) { - TableState tableState = tableStates.get( tableName ); + TableState newTableState = new TableState( tableName ); + TableState tableState = tableStates.putIfAbsent( tableName, newTableState ); if ( tableState == null ) { - tableState = new TableState( tableName ); - tableStates.put(tableName, tableState); + tableState = newTableState; } return tableState; } /** - * Get the scheduler service (lazily loaded) + * @see org.apache.commons.jcs.engine.behavior.IRequireScheduler#setScheduledExecutorService(java.util.concurrent.ScheduledExecutorService) + */ + @Override + public void setScheduledExecutorService(ScheduledExecutorService scheduledExecutor) + { + this.scheduler = scheduledExecutor; + } + + /** + * Get the scheduler service * * @return the scheduler */ protected ScheduledExecutorService getScheduledExecutorService() { - if ( scheduler == null ) - { - scheduler = Executors.newScheduledThreadPool(2, - new DaemonThreadFactory("JCS-JDBCDiskCacheManager-", Thread.MIN_PRIORITY)); - } - return scheduler; } @@ -162,11 +192,12 @@ public class JDBCDiskCacheFactory if ( cattr.isUseDiskShrinker() ) { ScheduledExecutorService shrinkerService = getScheduledExecutorService(); - ShrinkerThread shrinkerThread = shrinkerThreadMap.get( cattr.getTableName() ); + ShrinkerThread newShrinkerThread = new ShrinkerThread(); + ShrinkerThread shrinkerThread = shrinkerThreadMap.putIfAbsent( cattr.getTableName(), newShrinkerThread ); + if ( shrinkerThread == null ) { - shrinkerThread = new ShrinkerThread(); - shrinkerThreadMap.put( cattr.getTableName(), shrinkerThread ); + shrinkerThread = newShrinkerThread; long intervalMillis = Math.max( 999, cattr.getShrinkerIntervalSeconds() * 1000 ); if ( log.isInfoEnabled() ) @@ -176,7 +207,70 @@ public class JDBCDiskCacheFactory } shrinkerService.scheduleAtFixedRate(shrinkerThread, 0, intervalMillis, TimeUnit.MILLISECONDS); } + shrinkerThread.addDiskCacheToShrinkList( raf ); } } + + /** + * manages the DataSourceFactories. + * <p> + * @param cattr the cache configuration + * @param configProps the configuration properties object + * @return a DataSourceFactory + * @throws SQLException if a database access error occurs + */ + protected DataSourceFactory getDataSourceFactory( JDBCDiskCacheAttributes cattr, + Properties configProps ) throws SQLException + { + String poolName = null; + + if (cattr.getConnectionPoolName() == null) + { + poolName = cattr.getCacheName() + "." + JDBCDiskCacheAttributes.DEFAULT_POOL_NAME; + } + else + { + poolName = cattr.getConnectionPoolName(); + } + + synchronized (this.dsFactories) + { + DataSourceFactory dsFactory = this.dsFactories.get(poolName); + + if (dsFactory == null) + { + JDBCDiskCacheAttributes dsConfig = null; + + if (cattr.getConnectionPoolName() == null) + { + dsConfig = cattr; + } + else + { + dsConfig = new JDBCDiskCacheAttributes(); + String dsConfigAttributePrefix = POOL_CONFIGURATION_PREFIX + poolName + ATTRIBUTE_PREFIX; + PropertySetter.setProperties( dsConfig, + configProps, + dsConfigAttributePrefix + "." ); + + dsConfig.setConnectionPoolName(poolName); + } + + if ( dsConfig.getJndiPath() != null ) + { + dsFactory = new JndiDataSourceFactory(); + } + else + { + dsFactory = new SharedPoolDataSourceFactory(); + } + + dsFactory.initialize(dsConfig); + this.dsFactories.put(poolName, dsFactory); + } + + return dsFactory; + } + } } Added: commons/proper/jcs/trunk/commons-jcs-core/src/main/java/org/apache/commons/jcs/auxiliary/disk/jdbc/dsfactory/DataSourceFactory.java URL: http://svn.apache.org/viewvc/commons/proper/jcs/trunk/commons-jcs-core/src/main/java/org/apache/commons/jcs/auxiliary/disk/jdbc/dsfactory/DataSourceFactory.java?rev=1715353&view=auto ============================================================================== --- commons/proper/jcs/trunk/commons-jcs-core/src/main/java/org/apache/commons/jcs/auxiliary/disk/jdbc/dsfactory/DataSourceFactory.java (added) +++ commons/proper/jcs/trunk/commons-jcs-core/src/main/java/org/apache/commons/jcs/auxiliary/disk/jdbc/dsfactory/DataSourceFactory.java Fri Nov 20 13:21:58 2015 @@ -0,0 +1,85 @@ +package org.apache.commons.jcs.auxiliary.disk.jdbc.dsfactory; + +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import java.sql.SQLException; + +import javax.sql.DataSource; + +import org.apache.commons.jcs.auxiliary.disk.jdbc.JDBCDiskCacheAttributes; + + +/** + * A factory that returns a DataSource. + * Borrowed from Apache DB Torque + * + * @author <a href="mailto:jmcna...@apache.org">John McNally</a> + * @author <a href="mailto:fisc...@seitenbau.de">Thomas Fischer</a> + * @version $Id: DataSourceFactory.java 1336091 2012-05-09 11:09:40Z tfischer $ + */ +public interface DataSourceFactory +{ + /** + * Key for the configuration which contains DataSourceFactories + */ + String DSFACTORY_KEY = "dsfactory"; + + /** + * Key for the configuration which contains the fully qualified name + * of the factory implementation class + */ + String FACTORY_KEY = "factory"; + + /** + * @return the name of the factory. + */ + String getName(); + + /** + * @return the <code>DataSource</code> configured by the factory. + * @throws SQLException if the source can't be returned + */ + DataSource getDataSource() throws SQLException; + + /** + * Initialize the factory. + * + * @param config the factory settings + * @throws SQLException Any exceptions caught during processing will be + * rethrown wrapped into a SQLException. + */ + void initialize(JDBCDiskCacheAttributes config) + throws SQLException; + + /** + * A hook which is called when the resources of the associated DataSource + * can be released. + * After close() is called, the other methods may not work any more + * (e.g. getDataSource() might return null). + * It is not guaranteed that this method does anything. For example, + * we do not want to close connections retrieved via JNDI, so the + * JndiDataSouurceFactory does not close these connections + * + * @throws SQLException Any exceptions caught during processing will be + * rethrown wrapped into a SQLException. + */ + void close() + throws SQLException; +} Propchange: commons/proper/jcs/trunk/commons-jcs-core/src/main/java/org/apache/commons/jcs/auxiliary/disk/jdbc/dsfactory/DataSourceFactory.java ------------------------------------------------------------------------------ svn:mime-type = text/plain Added: commons/proper/jcs/trunk/commons-jcs-core/src/main/java/org/apache/commons/jcs/auxiliary/disk/jdbc/dsfactory/JndiDataSourceFactory.java URL: http://svn.apache.org/viewvc/commons/proper/jcs/trunk/commons-jcs-core/src/main/java/org/apache/commons/jcs/auxiliary/disk/jdbc/dsfactory/JndiDataSourceFactory.java?rev=1715353&view=auto ============================================================================== --- commons/proper/jcs/trunk/commons-jcs-core/src/main/java/org/apache/commons/jcs/auxiliary/disk/jdbc/dsfactory/JndiDataSourceFactory.java (added) +++ commons/proper/jcs/trunk/commons-jcs-core/src/main/java/org/apache/commons/jcs/auxiliary/disk/jdbc/dsfactory/JndiDataSourceFactory.java Fri Nov 20 13:21:58 2015 @@ -0,0 +1,185 @@ +package org.apache.commons.jcs.auxiliary.disk.jdbc.dsfactory; + +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import java.sql.SQLException; +import java.util.Hashtable; +import java.util.Iterator; +import java.util.Map; + +import javax.naming.Context; +import javax.naming.InitialContext; +import javax.naming.NamingException; +import javax.sql.DataSource; + +import org.apache.commons.jcs.auxiliary.disk.jdbc.JDBCDiskCacheAttributes; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + +/** + * A factory that looks up the DataSource from JNDI. It is also able + * to deploy the DataSource based on properties found in the + * configuration. + * + * This factory tries to avoid excessive context lookups to improve speed. + * The time between two lookups can be configured. The default is 0 (no cache). + * + * Borrowed and adapted from Apache DB Torque + * + * @author <a href="mailto:jmcna...@apache.org">John McNally</a> + * @author <a href="mailto:tho...@vandahl.org">Thomas Vandahl</a> + */ +public class JndiDataSourceFactory implements DataSourceFactory +{ + /** The log. */ + private static Log log = LogFactory.getLog(JndiDataSourceFactory.class); + + /** The name of the factory. */ + private String name; + + /** The path to get the resource from. */ + private String path; + + /** The context to get the resource from. */ + private Context ctx; + + /** A locally cached copy of the DataSource */ + private DataSource ds = null; + + /** Time of last actual lookup action */ + private long lastLookup = 0; + + /** Time between two lookups */ + private long ttl = 0; // ms + + /** + * @return the name of the factory. + */ + @Override + public String getName() + { + return name; + } + + /** + * @see org.apache.torque.dsfactory.DataSourceFactory#getDataSource + */ + @Override + public DataSource getDataSource() throws SQLException + { + long time = System.currentTimeMillis(); + + if (ds == null || time - lastLookup > ttl) + { + try + { + synchronized (ctx) + { + ds = ((DataSource) ctx.lookup(path)); + } + lastLookup = time; + } + catch (NamingException e) + { + throw new SQLException(e); + } + } + + return ds; + } + + /** + * @see org.apache.torque.dsfactory.DataSourceFactory#initialize + */ + @Override + public void initialize(JDBCDiskCacheAttributes config) throws SQLException + { + this.name = config.getConnectionPoolName(); + initJNDI(config); + } + + /** + * Initializes JNDI. + * + * @param config where to read the settings from + * @throws SQLException if a property set fails + */ + private void initJNDI(JDBCDiskCacheAttributes config) throws SQLException + { + log.debug("Starting initJNDI"); + + try + { + this.path = config.getJndiPath(); + if (log.isDebugEnabled()) + { + log.debug("JNDI path: " + path); + } + + this.ttl = config.getJndiTTL(); + if (log.isDebugEnabled()) + { + log.debug("Time between context lookups: " + ttl); + } + + Hashtable<String, Object> env = new Hashtable<String, Object>(); + ctx = new InitialContext(env); + + if (log.isDebugEnabled()) + { + log.debug("Created new InitialContext"); + debugCtx(ctx); + } + } + catch (NamingException e) + { + throw new SQLException(e); + } + } + + /** + * Does nothing. We do not want to close a dataSource retrieved from Jndi, + * because other applications might use it as well. + */ + @Override + public void close() + { + // do nothing + } + + /** + * + * @param ctx the context + * @throws NamingException + */ + private void debugCtx(Context ctx) throws NamingException + { + log.debug("InitialContext -------------------------------"); + Map<?, ?> env = ctx.getEnvironment(); + Iterator<?> qw = env.entrySet().iterator(); + log.debug("Environment properties:" + env.size()); + while (qw.hasNext()) + { + Map.Entry<?, ?> entry = (Map.Entry<?, ?>) qw.next(); + log.debug(" " + entry.getKey() + ": " + entry.getValue()); + } + log.debug("----------------------------------------------"); + } +} Propchange: commons/proper/jcs/trunk/commons-jcs-core/src/main/java/org/apache/commons/jcs/auxiliary/disk/jdbc/dsfactory/JndiDataSourceFactory.java ------------------------------------------------------------------------------ svn:mime-type = text/plain Added: commons/proper/jcs/trunk/commons-jcs-core/src/main/java/org/apache/commons/jcs/auxiliary/disk/jdbc/dsfactory/SharedPoolDataSourceFactory.java URL: http://svn.apache.org/viewvc/commons/proper/jcs/trunk/commons-jcs-core/src/main/java/org/apache/commons/jcs/auxiliary/disk/jdbc/dsfactory/SharedPoolDataSourceFactory.java?rev=1715353&view=auto ============================================================================== --- commons/proper/jcs/trunk/commons-jcs-core/src/main/java/org/apache/commons/jcs/auxiliary/disk/jdbc/dsfactory/SharedPoolDataSourceFactory.java (added) +++ commons/proper/jcs/trunk/commons-jcs-core/src/main/java/org/apache/commons/jcs/auxiliary/disk/jdbc/dsfactory/SharedPoolDataSourceFactory.java Fri Nov 20 13:21:58 2015 @@ -0,0 +1,150 @@ +package org.apache.commons.jcs.auxiliary.disk.jdbc.dsfactory; + +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import java.sql.SQLException; + +import javax.sql.ConnectionPoolDataSource; +import javax.sql.DataSource; + +import org.apache.commons.dbcp.cpdsadapter.DriverAdapterCPDS; +import org.apache.commons.dbcp.datasources.InstanceKeyDataSource; +import org.apache.commons.dbcp.datasources.SharedPoolDataSource; +import org.apache.commons.jcs.auxiliary.disk.jdbc.JDBCDiskCacheAttributes; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + +/** + * A factory that looks up the DataSource using the JDBC2 pool methods. + * + * Borrowed and adapted from Apache DB Torque + * + * @author <a href="mailto:jmcna...@apache.org">John McNally</a> + * @author <a href="mailto:h...@intermeta.de">Henning P. Schmiedehausen</a> + */ +public class SharedPoolDataSourceFactory implements DataSourceFactory +{ + /** The log. */ + private static Log log = LogFactory.getLog(SharedPoolDataSourceFactory.class); + + /** The name of the factory. */ + private String name; + + /** The wrapped <code>DataSource</code>. */ + private SharedPoolDataSource ds = null; + + /** + * @return the name of the factory. + */ + @Override + public String getName() + { + return name; + } + + /** + * @see org.apache.torque.dsfactory.DataSourceFactory#getDataSource + */ + @Override + public DataSource getDataSource() + { + return ds; + } + + /** + * @see org.apache.torque.dsfactory.DataSourceFactory#initialize + */ + @Override + public void initialize(JDBCDiskCacheAttributes config) throws SQLException + { + this.name = config.getConnectionPoolName(); + ConnectionPoolDataSource cpds = initCPDS(config); + SharedPoolDataSource dataSource = new SharedPoolDataSource(); + initJdbc2Pool(dataSource, config); + dataSource.setConnectionPoolDataSource(cpds); + dataSource.setMaxActive(config.getMaxActive()); + this.ds = dataSource; + } + + /** + * Closes the pool associated with this factory and releases it. + * @throws SQLException if the pool cannot be closed properly + */ + @Override + public void close() throws SQLException + { + try + { + ds.close(); + } + catch (Exception e) + { + throw new SQLException("Exception caught closing data source", e); + } + ds = null; + } + + /** + * Initializes the ConnectionPoolDataSource. + * + * @param config where to read the settings from + * @throws SQLException if a property set fails + * @return a configured <code>ConnectionPoolDataSource</code> + */ + private ConnectionPoolDataSource initCPDS(final JDBCDiskCacheAttributes config) + throws SQLException + { + log.debug("Starting initCPDS"); + + DriverAdapterCPDS cpds = new DriverAdapterCPDS(); + + try + { + cpds.setDriver(config.getDriverClassName()); + } + catch (ClassNotFoundException e) + { + throw new SQLException("Driver class not found " + config.getDriverClassName(), e); + } + + cpds.setUrl(config.getUrl()); + cpds.setUser(config.getUserName()); + cpds.setPassword(config.getPassword()); + cpds.setMaxActive(config.getMaxActive()); + + return cpds; + } + + /** + * Initializes the Jdbc2PoolDataSource. + * + * @param dataSource the dataSource to initialize, not null. + * @param config where to read the settings from, not null. + * + * @throws SQLException if a property set fails. + */ + private void initJdbc2Pool(final InstanceKeyDataSource dataSource, final JDBCDiskCacheAttributes config) + throws SQLException + { + log.debug("Starting initJdbc2Pool"); + + dataSource.setDescription(config.getConnectionPoolName()); + } +} Propchange: commons/proper/jcs/trunk/commons-jcs-core/src/main/java/org/apache/commons/jcs/auxiliary/disk/jdbc/dsfactory/SharedPoolDataSourceFactory.java ------------------------------------------------------------------------------ svn:mime-type = text/plain Modified: commons/proper/jcs/trunk/commons-jcs-core/src/main/java/org/apache/commons/jcs/auxiliary/disk/jdbc/mysql/MySQLDiskCache.java URL: http://svn.apache.org/viewvc/commons/proper/jcs/trunk/commons-jcs-core/src/main/java/org/apache/commons/jcs/auxiliary/disk/jdbc/mysql/MySQLDiskCache.java?rev=1715353&r1=1715352&r2=1715353&view=diff ============================================================================== --- commons/proper/jcs/trunk/commons-jcs-core/src/main/java/org/apache/commons/jcs/auxiliary/disk/jdbc/mysql/MySQLDiskCache.java (original) +++ commons/proper/jcs/trunk/commons-jcs-core/src/main/java/org/apache/commons/jcs/auxiliary/disk/jdbc/mysql/MySQLDiskCache.java Fri Nov 20 13:21:58 2015 @@ -24,6 +24,7 @@ import java.util.Map; import org.apache.commons.jcs.auxiliary.disk.jdbc.JDBCDiskCache; import org.apache.commons.jcs.auxiliary.disk.jdbc.TableState; +import org.apache.commons.jcs.auxiliary.disk.jdbc.dsfactory.DataSourceFactory; import org.apache.commons.jcs.engine.behavior.ICacheElement; import org.apache.commons.jcs.engine.behavior.ICompositeCacheManager; import org.apache.commons.logging.Log; @@ -50,14 +51,16 @@ public class MySQLDiskCache<K, V> * Delegates to the super and makes use of the MySQL specific parameters used for scheduled * optimization. * <p> - * @param attributes - * @param tableState - * @param compositeCacheManager + * @param attributes the configuration object for this cache + * @param dsFactory the DataSourceFactory for this cache + * @param tableState an object to track table operations + * @param compositeCacheManager the global cache manager * @throws SQLException if the pool access could not be set up */ - public MySQLDiskCache( MySQLDiskCacheAttributes attributes, TableState tableState, ICompositeCacheManager compositeCacheManager ) throws SQLException + public MySQLDiskCache( MySQLDiskCacheAttributes attributes, DataSourceFactory dsFactory, + TableState tableState, ICompositeCacheManager compositeCacheManager ) throws SQLException { - super( attributes, tableState, compositeCacheManager ); + super( attributes, dsFactory, tableState, compositeCacheManager ); mySQLDiskCacheAttributes = attributes; Modified: commons/proper/jcs/trunk/commons-jcs-core/src/main/java/org/apache/commons/jcs/auxiliary/disk/jdbc/mysql/MySQLDiskCacheFactory.java URL: http://svn.apache.org/viewvc/commons/proper/jcs/trunk/commons-jcs-core/src/main/java/org/apache/commons/jcs/auxiliary/disk/jdbc/mysql/MySQLDiskCacheFactory.java?rev=1715353&r1=1715352&r2=1715353&view=diff ============================================================================== --- commons/proper/jcs/trunk/commons-jcs-core/src/main/java/org/apache/commons/jcs/auxiliary/disk/jdbc/mysql/MySQLDiskCacheFactory.java (original) +++ commons/proper/jcs/trunk/commons-jcs-core/src/main/java/org/apache/commons/jcs/auxiliary/disk/jdbc/mysql/MySQLDiskCacheFactory.java Fri Nov 20 13:21:58 2015 @@ -24,10 +24,12 @@ import java.text.ParseException; import java.util.Date; import java.util.concurrent.TimeUnit; +import javax.sql.DataSource; + import org.apache.commons.jcs.auxiliary.AuxiliaryCacheAttributes; import org.apache.commons.jcs.auxiliary.disk.jdbc.JDBCDiskCacheFactory; -import org.apache.commons.jcs.auxiliary.disk.jdbc.JDBCDiskCachePoolAccess; import org.apache.commons.jcs.auxiliary.disk.jdbc.TableState; +import org.apache.commons.jcs.auxiliary.disk.jdbc.dsfactory.DataSourceFactory; import org.apache.commons.jcs.auxiliary.disk.jdbc.mysql.util.ScheduleParser; import org.apache.commons.jcs.engine.behavior.ICompositeCacheManager; import org.apache.commons.jcs.engine.behavior.IElementSerializer; @@ -49,12 +51,12 @@ public class MySQLDiskCacheFactory /** * This factory method should create an instance of the mysqlcache. * <p> - * @param rawAttr - * @param compositeCacheManager - * @param cacheEventLogger - * @param elementSerializer - * @return MySQLDiskCache - * @throws SQLException if the creation of the cache instance fails + * @param rawAttr specific cache configuration attributes + * @param compositeCacheManager the global cache manager + * @param cacheEventLogger a specific logger for cache events + * @param elementSerializer a serializer for cache elements + * @return MySQLDiskCache the cache instance + * @throws SQLException if the cache instance could not be created */ @Override public <K, V> MySQLDiskCache<K, V> createCache( AuxiliaryCacheAttributes rawAttr, @@ -64,14 +66,15 @@ public class MySQLDiskCacheFactory { MySQLDiskCacheAttributes cattr = (MySQLDiskCacheAttributes) rawAttr; TableState tableState = getTableState( cattr.getTableName() ); + DataSourceFactory dsFactory = getDataSourceFactory(cattr, compositeCacheManager.getConfigurationProperties()); - MySQLDiskCache<K, V> cache = new MySQLDiskCache<K, V>( cattr, tableState, compositeCacheManager ); + MySQLDiskCache<K, V> cache = new MySQLDiskCache<K, V>( cattr, dsFactory, tableState, compositeCacheManager ); cache.setCacheEventLogger( cacheEventLogger ); cache.setElementSerializer( elementSerializer ); // create a shrinker if we need it. createShrinkerWhenNeeded( cattr, cache ); - scheduleOptimizations( cattr, tableState, cache.getPoolAccess() ); + scheduleOptimizations( cattr, tableState, cache.getDataSource() ); return cache; @@ -82,9 +85,9 @@ public class MySQLDiskCacheFactory * <p> * @param attributes configuration properties. * @param tableState for noting optimization in progress, etc. - * @param poolAccess access to the pool + * @param ds the DataSource */ - protected void scheduleOptimizations( MySQLDiskCacheAttributes attributes, TableState tableState, JDBCDiskCachePoolAccess poolAccess ) + protected void scheduleOptimizations( MySQLDiskCacheAttributes attributes, TableState tableState, DataSource ds ) { if ( attributes != null ) { @@ -96,7 +99,7 @@ public class MySQLDiskCacheFactory + "] on schedule [" + attributes.getOptimizationSchedule() + "]" ); } - MySQLTableOptimizer optimizer = new MySQLTableOptimizer( attributes, tableState, poolAccess ); + MySQLTableOptimizer optimizer = new MySQLTableOptimizer( attributes, tableState, ds ); // loop through the dates. try Modified: commons/proper/jcs/trunk/commons-jcs-core/src/main/java/org/apache/commons/jcs/auxiliary/disk/jdbc/mysql/MySQLTableOptimizer.java URL: http://svn.apache.org/viewvc/commons/proper/jcs/trunk/commons-jcs-core/src/main/java/org/apache/commons/jcs/auxiliary/disk/jdbc/mysql/MySQLTableOptimizer.java?rev=1715353&r1=1715352&r2=1715353&view=diff ============================================================================== --- commons/proper/jcs/trunk/commons-jcs-core/src/main/java/org/apache/commons/jcs/auxiliary/disk/jdbc/mysql/MySQLTableOptimizer.java (original) +++ commons/proper/jcs/trunk/commons-jcs-core/src/main/java/org/apache/commons/jcs/auxiliary/disk/jdbc/mysql/MySQLTableOptimizer.java Fri Nov 20 13:21:58 2015 @@ -19,18 +19,19 @@ package org.apache.commons.jcs.auxiliary * under the License. */ -import org.apache.commons.jcs.auxiliary.disk.jdbc.JDBCDiskCachePoolAccess; -import org.apache.commons.jcs.auxiliary.disk.jdbc.TableState; -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; - import java.sql.Connection; import java.sql.ResultSet; import java.sql.SQLException; import java.sql.Statement; +import javax.sql.DataSource; + +import org.apache.commons.jcs.auxiliary.disk.jdbc.TableState; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + /** - * The MySQL Table Optimizer can optimize MySQL tables. It knows how to optimize for MySQL datbases + * The MySQL Table Optimizer can optimize MySQL tables. It knows how to optimize for MySQL databases * in particular and how to repair the table if it is corrupted in the process. * <p> * We will probably be able to abstract out a generic optimizer interface from this class in the @@ -43,8 +44,8 @@ public class MySQLTableOptimizer /** The logger */ private static final Log log = LogFactory.getLog( MySQLTableOptimizer.class ); - /** The pool */ - private JDBCDiskCachePoolAccess poolAccess = null; + /** The data source */ + private DataSource dataSource = null; /** The name of the table. */ private String tableName = null; @@ -57,16 +58,14 @@ public class MySQLTableOptimizer * <p> * @param attributes * @param tableState We mark the table status as optimizing when this is happening. - * @param poolAccess access to the database + * @param dataSource access to the database */ - public MySQLTableOptimizer( MySQLDiskCacheAttributes attributes, TableState tableState, - JDBCDiskCachePoolAccess poolAccess ) + public MySQLTableOptimizer( MySQLDiskCacheAttributes attributes, TableState tableState, DataSource dataSource ) { setTableName( attributes.getTableName() ); this.tableState = tableState; - - this.poolAccess = poolAccess; + this.dataSource = dataSource; } /** @@ -137,7 +136,7 @@ public class MySQLTableOptimizer Connection con; try { - con = poolAccess.getConnection(); + con = dataSource.getConnection(); } catch ( SQLException e ) { @@ -172,7 +171,7 @@ public class MySQLTableOptimizer if ( "error".equals( status ) ) { - log.warn( "Optimization was in erorr. Will attempt to repair the table. Message: " + log.warn( "Optimization was in error. Will attempt to repair the table. Message: " + message ); // try to repair the table. @@ -263,7 +262,7 @@ public class MySQLTableOptimizer } /** - * This is called if the optimizatio is in error. + * This is called if the optimization is in error. * <p> * It looks for "OK" in response. If it find "OK" as a message in any result set row, it returns * true. Otherwise we assume that the repair failed. Copied: commons/proper/jcs/trunk/commons-jcs-core/src/test/java/org/apache/commons/jcs/auxiliary/disk/jdbc/JDBCDataSourceFactoryUnitTest.java (from r1704856, commons/proper/jcs/trunk/commons-jcs-core/src/test/java/org/apache/commons/jcs/auxiliary/disk/jdbc/JDBCDiskCachePoolAccessManagerUnitTest.java) URL: http://svn.apache.org/viewvc/commons/proper/jcs/trunk/commons-jcs-core/src/test/java/org/apache/commons/jcs/auxiliary/disk/jdbc/JDBCDataSourceFactoryUnitTest.java?p2=commons/proper/jcs/trunk/commons-jcs-core/src/test/java/org/apache/commons/jcs/auxiliary/disk/jdbc/JDBCDataSourceFactoryUnitTest.java&p1=commons/proper/jcs/trunk/commons-jcs-core/src/test/java/org/apache/commons/jcs/auxiliary/disk/jdbc/JDBCDiskCachePoolAccessManagerUnitTest.java&r1=1704856&r2=1715353&rev=1715353&view=diff ============================================================================== --- commons/proper/jcs/trunk/commons-jcs-core/src/test/java/org/apache/commons/jcs/auxiliary/disk/jdbc/JDBCDiskCachePoolAccessManagerUnitTest.java (original) +++ commons/proper/jcs/trunk/commons-jcs-core/src/test/java/org/apache/commons/jcs/auxiliary/disk/jdbc/JDBCDataSourceFactoryUnitTest.java Fri Nov 20 13:21:58 2015 @@ -19,18 +19,33 @@ package org.apache.commons.jcs.auxiliary * under the License. */ +import java.sql.SQLException; +import java.util.HashMap; +import java.util.Hashtable; +import java.util.Map; +import java.util.Properties; + +import javax.naming.Context; +import javax.naming.InitialContext; +import javax.naming.NamingException; +import javax.naming.spi.InitialContextFactory; + import junit.framework.TestCase; -import java.sql.Connection; -import java.sql.DriverManager; -import java.util.Properties; +import org.apache.commons.dbcp.BasicDataSource; +import org.apache.commons.dbcp.datasources.SharedPoolDataSource; +import org.apache.commons.jcs.auxiliary.disk.jdbc.dsfactory.DataSourceFactory; +import org.apache.commons.jcs.auxiliary.disk.jdbc.dsfactory.JndiDataSourceFactory; +import org.apache.commons.jcs.auxiliary.disk.jdbc.dsfactory.SharedPoolDataSourceFactory; -/** Unit tests for the pool manager */ -public class JDBCDiskCachePoolAccessManagerUnitTest +/** Unit tests for the data source factories */ +public class JDBCDataSourceFactoryUnitTest extends TestCase { - /** Verify that we can configure the object based on the props. */ - public void testConfigurePoolAccessAttributes_Simple() + /** Verify that we can configure the object based on the props. + * @throws SQLException + */ + public void testConfigureDataSourceFactory_Simple() throws SQLException { // SETUP String poolName = "testConfigurePoolAccessAttributes_Simple"; @@ -42,69 +57,143 @@ public class JDBCDiskCachePoolAccessMana String driverClassName = "org.hsqldb.jdbcDriver"; Properties props = new Properties(); - String prefix = JDBCDiskCachePoolAccessManager.POOL_CONFIGURATION_PREFIX + poolName - + JDBCDiskCachePoolAccessManager.ATTRIBUTE_PREFIX; + String prefix = JDBCDiskCacheFactory.POOL_CONFIGURATION_PREFIX + + poolName + + JDBCDiskCacheFactory.ATTRIBUTE_PREFIX; props.put( prefix + ".url", url ); props.put( prefix + ".userName", userName ); props.put( prefix + ".password", password ); props.put( prefix + ".maxActive", String.valueOf( maxActive ) ); props.put( prefix + ".driverClassName", driverClassName ); - JDBCDiskCachePoolAccessManager manager = JDBCDiskCachePoolAccessManager.getInstance(); + JDBCDiskCacheFactory factory = new JDBCDiskCacheFactory(); + factory.initialize(); + + JDBCDiskCacheAttributes cattr = new JDBCDiskCacheAttributes(); + cattr.setConnectionPoolName( poolName ); // DO WORK - JDBCDiskCachePoolAccessAttributes result = manager.configurePoolAccessAttributes( poolName, props ); + DataSourceFactory result = factory.getDataSourceFactory( cattr, props ); + assertTrue("Should be a shared pool data source factory", result instanceof SharedPoolDataSourceFactory); + + SharedPoolDataSource spds = (SharedPoolDataSource) result.getDataSource(); + assertNotNull( "Should have a data source class", spds ); // VERIFY - assertEquals( "Wrong url value", url, result.getUrl() ); - assertEquals( "Wrong userName value", userName, result.getUserName() ); - assertEquals( "Wrong password value", password, result.getPassword() ); - assertEquals( "Wrong maxActive value", maxActive, result.getMaxActive() ); - assertEquals( "Wrong driverClassName value", driverClassName, result.getDriverClassName() ); + assertEquals( "Wrong pool name", poolName, spds.getDescription() ); + assertEquals( "Wrong maxActive value", maxActive, spds.getMaxActive() ); } - /** - * Verify that we can get access. - * <p> - * @throws Exception + /** Verify that we can configure the object based on the attributes. + * @throws SQLException */ - public void testGetJDBCDiskCachePoolAccess_Simple() - throws Exception + public void testConfigureDataSourceFactory_Attributes() throws SQLException { // SETUP - String poolName = "testGetJDBCDiskCachePoolAccess_Simple"; - - String url = "jdbc:hsqldb:"; - String userName = "sa"; - String password = ""; + String url = "adfads"; + String userName = "zvzvz"; + String password = "qewrrewq"; int maxActive = 10; String driverClassName = "org.hsqldb.jdbcDriver"; - Properties props = new Properties(); - String prefix = JDBCDiskCachePoolAccessManager.POOL_CONFIGURATION_PREFIX + poolName - + JDBCDiskCachePoolAccessManager.ATTRIBUTE_PREFIX; - props.put( prefix + ".url", url ); - props.put( prefix + ".userName", userName ); - props.put( prefix + ".password", password ); - props.put( prefix + ".maxActive", String.valueOf( maxActive ) ); - props.put( prefix + ".driverClassName", driverClassName ); + JDBCDiskCacheFactory factory = new JDBCDiskCacheFactory(); + factory.initialize(); - JDBCDiskCachePoolAccessManager manager = JDBCDiskCachePoolAccessManager.getInstance(); + JDBCDiskCacheAttributes cattr = new JDBCDiskCacheAttributes(); + cattr.setUrl(url); + cattr.setUserName(userName); + cattr.setPassword(password); + cattr.setMaxActive(maxActive); + cattr.setDriverClassName(driverClassName); - System.setProperty( "hsqldb.cache_scale", "8" ); + // DO WORK + DataSourceFactory result = factory.getDataSourceFactory( cattr, null ); + assertTrue("Should be a shared pool data source factory", result instanceof SharedPoolDataSourceFactory); + + SharedPoolDataSource spds = (SharedPoolDataSource) result.getDataSource(); + assertNotNull( "Should have a data source class", spds ); + + // VERIFY + assertEquals( "Wrong maxActive value", maxActive, spds.getMaxActive() ); + } + + /** Verify that we can configure the object based on JNDI. + * @throws SQLException + */ + public void testConfigureDataSourceFactory_JNDI() throws SQLException + { + // SETUP + String jndiPath = "java:comp/env/jdbc/MyDB"; + long ttl = 300000L; + + System.setProperty(Context.INITIAL_CONTEXT_FACTORY, + MockInitialContextFactory.class.getName()); - String rafroot = "target"; - String database = rafroot + "/cache_hsql_db"; + MockInitialContextFactory.bind(jndiPath, new BasicDataSource()); - new org.hsqldb.jdbcDriver(); - Class.forName( driverClassName ).newInstance(); - Connection cConn = DriverManager.getConnection( url + database, userName, password ); - HsqlSetupTableUtil.setupTABLE( cConn, "JCSTESTTABLE_ACCESS" ); + JDBCDiskCacheFactory factory = new JDBCDiskCacheFactory(); + factory.initialize(); + + JDBCDiskCacheAttributes cattr = new JDBCDiskCacheAttributes(); + cattr.setJndiPath(jndiPath); + cattr.setJndiTTL(ttl); // DO WORK - JDBCDiskCachePoolAccess result = manager.getJDBCDiskCachePoolAccess( poolName, props ); + DataSourceFactory result = factory.getDataSourceFactory( cattr, null ); + assertTrue("Should be a JNDI data source factory", result instanceof JndiDataSourceFactory); + } - // VERIFY - assertNotNull( "Should have an access class", result ); + /* For JNDI mocking */ + public static class MockInitialContextFactory implements InitialContextFactory + { + private static Context context; + + static + { + try + { + context = new InitialContext(true) + { + Map<String, Object> bindings = new HashMap<String, Object>(); + + @Override + public void bind(String name, Object obj) throws NamingException + { + bindings.put(name, obj); + } + + @Override + public Object lookup(String name) throws NamingException + { + return bindings.get(name); + } + }; + } + catch (NamingException e) + { + // can't happen. + throw new RuntimeException(e); + } + } + + @Override + public Context getInitialContext(Hashtable<?, ?> environment) throws NamingException + { + return context; + } + + public static void bind(String name, Object obj) + { + try + { + context.bind(name, obj); + } + catch (NamingException e) + { + // can't happen. + throw new RuntimeException(e); + } + } } } + Modified: commons/proper/jcs/trunk/commons-jcs-core/src/test/java/org/apache/commons/jcs/auxiliary/disk/jdbc/JDBCDiskCacheUnitTest.java URL: http://svn.apache.org/viewvc/commons/proper/jcs/trunk/commons-jcs-core/src/test/java/org/apache/commons/jcs/auxiliary/disk/jdbc/JDBCDiskCacheUnitTest.java?rev=1715353&r1=1715352&r2=1715353&view=diff ============================================================================== --- commons/proper/jcs/trunk/commons-jcs-core/src/test/java/org/apache/commons/jcs/auxiliary/disk/jdbc/JDBCDiskCacheUnitTest.java (original) +++ commons/proper/jcs/trunk/commons-jcs-core/src/test/java/org/apache/commons/jcs/auxiliary/disk/jdbc/JDBCDiskCacheUnitTest.java Fri Nov 20 13:21:58 2015 @@ -19,18 +19,23 @@ package org.apache.commons.jcs.auxiliary * under the License. */ -import junit.framework.TestCase; -import org.apache.commons.jcs.JCS; -import org.apache.commons.jcs.access.CacheAccess; -import org.apache.commons.jcs.engine.behavior.ICacheElement; -import org.apache.commons.jcs.engine.control.MockCompositeCacheManager; - import java.sql.Connection; import java.sql.DriverManager; import java.util.HashSet; import java.util.Map; import java.util.Properties; import java.util.Set; +import java.util.concurrent.Executors; + +import junit.framework.TestCase; + +import org.apache.commons.jcs.JCS; +import org.apache.commons.jcs.access.CacheAccess; +import org.apache.commons.jcs.auxiliary.disk.jdbc.dsfactory.DataSourceFactory; +import org.apache.commons.jcs.engine.behavior.ICacheElement; +import org.apache.commons.jcs.engine.control.MockCompositeCacheManager; +import org.apache.commons.jcs.utils.serialization.StandardSerializer; +import org.apache.commons.jcs.utils.threadpool.DaemonThreadFactory; /** * Runs basic tests for the JDBC disk cache. @@ -156,8 +161,9 @@ public class JDBCDiskCacheUnitTest String driverClassName = "org.hsqldb.jdbcDriver"; Properties props = new Properties(); - String prefix = JDBCDiskCachePoolAccessManager.POOL_CONFIGURATION_PREFIX + poolName - + JDBCDiskCachePoolAccessManager.ATTRIBUTE_PREFIX; + String prefix = JDBCDiskCacheFactory.POOL_CONFIGURATION_PREFIX + + poolName + + JDBCDiskCacheFactory.ATTRIBUTE_PREFIX; props.put( prefix + ".url", url ); props.put( prefix + ".userName", userName ); props.put( prefix + ".password", password ); @@ -166,12 +172,24 @@ public class JDBCDiskCacheUnitTest JDBCDiskCacheAttributes cattr = new JDBCDiskCacheAttributes(); cattr.setConnectionPoolName( poolName ); + cattr.setTableName("JCSTESTTABLE_InitializePoolAccess"); - TableState tableState = new TableState( "JCSTESTTABLE_InitializePoolAccess" ); MockCompositeCacheManager compositeCacheManager = new MockCompositeCacheManager(); compositeCacheManager.setConfigurationProperties( props ); + JDBCDiskCacheFactory dcFactory = new JDBCDiskCacheFactory(); + dcFactory.initialize(); + dcFactory.setScheduledExecutorService(Executors.newScheduledThreadPool(2, + new DaemonThreadFactory("JCS-JDBCDiskCacheManager-", Thread.MIN_PRIORITY))); - JDBCDiskCache<String, String> diskCache = new JDBCDiskCache<String, String>( cattr, tableState, compositeCacheManager ); + JDBCDiskCache<String, String> diskCache = dcFactory.createCache( cattr, compositeCacheManager, null, new StandardSerializer() ); + assertNotNull( "Should have a cache instance", diskCache ); + + // DO WORK + DataSourceFactory result = dcFactory.getDataSourceFactory(cattr, props); + + // VERIFY + assertNotNull( "Should have a data source factory class", result ); + assertEquals( "wrong name", poolName, result.getName() ); System.setProperty( "hsqldb.cache_scale", "8" ); @@ -184,11 +202,5 @@ public class JDBCDiskCacheUnitTest HsqlSetupTableUtil.setupTABLE( cConn, "JCSTESTTABLE_InitializePoolAccess" ); - // DO WORK - JDBCDiskCachePoolAccess result = diskCache.initializePoolAccess( cattr, compositeCacheManager ); - - // VEIFY - assertNotNull( "Should have an access class", result ); - assertEquals( "wrong name", poolName, result.getPoolName() ); } } Modified: commons/proper/jcs/trunk/commons-jcs-core/src/test/java/org/apache/commons/jcs/auxiliary/disk/jdbc/mysql/MySQLDiskCacheUnitTest.java URL: http://svn.apache.org/viewvc/commons/proper/jcs/trunk/commons-jcs-core/src/test/java/org/apache/commons/jcs/auxiliary/disk/jdbc/mysql/MySQLDiskCacheUnitTest.java?rev=1715353&r1=1715352&r2=1715353&view=diff ============================================================================== --- commons/proper/jcs/trunk/commons-jcs-core/src/test/java/org/apache/commons/jcs/auxiliary/disk/jdbc/mysql/MySQLDiskCacheUnitTest.java (original) +++ commons/proper/jcs/trunk/commons-jcs-core/src/test/java/org/apache/commons/jcs/auxiliary/disk/jdbc/mysql/MySQLDiskCacheUnitTest.java Fri Nov 20 13:21:58 2015 @@ -24,6 +24,7 @@ import java.sql.SQLException; import junit.framework.TestCase; import org.apache.commons.jcs.auxiliary.disk.jdbc.TableState; +import org.apache.commons.jcs.auxiliary.disk.jdbc.dsfactory.SharedPoolDataSourceFactory; import org.apache.commons.jcs.engine.control.CompositeCacheManager; /** @@ -53,11 +54,13 @@ public class MySQLDiskCacheUnitTest attributes.setDriverClassName( "org.hsqldb.jdbcDriver" ); attributes.setTableName( tableName ); attributes.setBalkDuringOptimization( true ); + SharedPoolDataSourceFactory dsFactory = new SharedPoolDataSourceFactory(); + dsFactory.initialize(attributes); TableState tableState = new TableState( tableName ); tableState.setState( TableState.OPTIMIZATION_RUNNING ); - MySQLDiskCache<String, String> cache = new MySQLDiskCache<String, String>( attributes, tableState, + MySQLDiskCache<String, String> cache = new MySQLDiskCache<String, String>( attributes, dsFactory, tableState, CompositeCacheManager.getUnconfiguredInstance() ); // DO WORK Modified: commons/proper/jcs/trunk/src/changes/changes.xml URL: http://svn.apache.org/viewvc/commons/proper/jcs/trunk/src/changes/changes.xml?rev=1715353&r1=1715352&r2=1715353&view=diff ============================================================================== --- commons/proper/jcs/trunk/src/changes/changes.xml (original) +++ commons/proper/jcs/trunk/src/changes/changes.xml Fri Nov 20 13:21:58 2015 @@ -20,6 +20,9 @@ </properties> <body> <release version="2.0" date="unreleased" description="JDK 1.6 based major release"> + <action issue="JCS-48" dev="tv" type="update" due-to="Hanasaki Jiji"> + Replace PoolAccess with a DataSourceFactory model borrowed from DB-Torque + </action> <action dev="tv" type="fix"> Fix removal of items from group cache, added several tests </action>