You are viewing a plain text version of this content. The canonical link for it is here.
Posted to jcs-dev@jakarta.apache.org by as...@apache.org on 2006/03/16 18:28:52 UTC

svn commit: r386396 - in /jakarta/jcs/trunk/src/java/org/apache/jcs/auxiliary/disk/jdbc: JDBCDiskCache.java JDBCDiskCacheAttributes.java JDBCDiskCacheFactory.java JDBCDiskCacheManager.java

Author: asmuts
Date: Thu Mar 16 09:28:51 2006
New Revision: 386396

URL: http://svn.apache.org/viewcvs?rev=386396&view=rev
Log:
adding a general jdbc disk cache that put elements into a blob filed in a table.  

Added:
    jakarta/jcs/trunk/src/java/org/apache/jcs/auxiliary/disk/jdbc/JDBCDiskCache.java
    jakarta/jcs/trunk/src/java/org/apache/jcs/auxiliary/disk/jdbc/JDBCDiskCacheAttributes.java
    jakarta/jcs/trunk/src/java/org/apache/jcs/auxiliary/disk/jdbc/JDBCDiskCacheFactory.java
    jakarta/jcs/trunk/src/java/org/apache/jcs/auxiliary/disk/jdbc/JDBCDiskCacheManager.java

Added: jakarta/jcs/trunk/src/java/org/apache/jcs/auxiliary/disk/jdbc/JDBCDiskCache.java
URL: http://svn.apache.org/viewcvs/jakarta/jcs/trunk/src/java/org/apache/jcs/auxiliary/disk/jdbc/JDBCDiskCache.java?rev=386396&view=auto
==============================================================================
--- jakarta/jcs/trunk/src/java/org/apache/jcs/auxiliary/disk/jdbc/JDBCDiskCache.java (added)
+++ jakarta/jcs/trunk/src/java/org/apache/jcs/auxiliary/disk/jdbc/JDBCDiskCache.java Thu Mar 16 09:28:51 2006
@@ -0,0 +1,1058 @@
+package org.apache.jcs.auxiliary.disk.jdbc;
+
+/*
+ * Copyright 2001-2004 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.
+ * 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.io.IOException;
+import java.io.Serializable;
+import java.sql.Connection;
+import java.sql.Date;
+import java.sql.DriverManager;
+import java.sql.PreparedStatement;
+import java.sql.ResultSet;
+import java.sql.SQLException;
+import java.sql.Statement;
+import java.util.ArrayList;
+import java.util.Arrays;
+
+import java.util.List;
+import java.util.Set;
+
+import org.apache.commons.dbcp.ConnectionFactory;
+import org.apache.commons.dbcp.DriverManagerConnectionFactory;
+import org.apache.commons.dbcp.PoolableConnectionFactory;
+import org.apache.commons.dbcp.PoolingDriver;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.apache.commons.pool.ObjectPool;
+import org.apache.commons.pool.impl.GenericObjectPool;
+import org.apache.jcs.auxiliary.disk.AbstractDiskCache;
+import org.apache.jcs.engine.CacheConstants;
+import org.apache.jcs.engine.behavior.ICacheElement;
+import org.apache.jcs.engine.behavior.IElementSerializer;
+import org.apache.jcs.engine.stats.StatElement;
+import org.apache.jcs.engine.stats.behavior.IStatElement;
+import org.apache.jcs.engine.stats.behavior.IStats;
+import org.apache.jcs.utils.serialization.StandardSerializer;
+
+/**
+ * This is the jdbc disk cache plugin.
+ * <p>
+ * It expects a table created by the following script. The table name is
+ * configurable.
+ * 
+ * <pre>
+ *         drop TABLE JCS_STORE;
+ *        
+ *         CREATE TABLE JCS_STORE
+ *         (
+ *         CACHE_KEY             VARCHAR(250)          NOT NULL,
+ *         REGION                VARCHAR(250)          NOT NULL,
+ *         ELEMENT               BLOB,
+ *         CREATE_TIME           DATE,
+ *         CREATE_TIME_SECONDS   BIGINT,
+ *         MAX_LIFE_SECONDS      BIGINT,
+ *         IS_ETERNAL            CHAR(1),
+ *         PRIMARY KEY (CACHE_KEY, REGION)
+ *         );
+ * </pre>
+ * 
+ * 
+ * The cleanup thread will delete non eternal items where (now - create time) > max life seconds * 1000
+ * 
+ * @author Aaron Smuts
+ * 
+ */
+public class JDBCDiskCache
+    extends AbstractDiskCache
+{
+    private final static Log log = LogFactory.getLog( JDBCDiskCache.class );
+
+    private static final long serialVersionUID = -7169488308515823492L;
+
+    private IElementSerializer elementSerializer = new StandardSerializer();
+
+    private JDBCDiskCacheAttributes jdbcDiskCacheAttributes;
+
+    private static final String DEFAULT_POOL_NAME = "jcs";
+
+    private String poolName = DEFAULT_POOL_NAME;
+
+    private static final String DRIVER_NAME = "jdbc:apache:commons:dbcp:";
+
+    private int updateCount = 0;
+
+    private int getCount = 0;
+
+    // if count % interval == 0 then log
+    private static final int LOG_INTERVAL = 100;
+
+    /**
+     * 
+     * @param cattr
+     */
+    public JDBCDiskCache( JDBCDiskCacheAttributes cattr )
+    {
+        super( cattr );
+
+        setJdbcDiskCacheAttributes( cattr );
+
+        if ( log.isInfoEnabled() )
+        {
+            log.info( "jdbcDiskCacheAttributes = " + getJdbcDiskCacheAttributes() );
+        }
+
+        // WE SHOULD HAVE A DIFFERENT POOL FOR EACH DB NO REGION
+        // THE SAME TABLE CAN BE USED BY MULTIPLE REGIONS
+        // this.setPoolName( jdbcDiskCacheAttributes.getCacheName() );
+
+        try
+        {
+            try
+            {
+                // org.gjt.mm.mysql.Driver
+                Class.forName( cattr.getDriverClassName() );
+            }
+            catch ( ClassNotFoundException e )
+            {
+                log.error( "Couldn't find class for driver [" + cattr.getDriverClassName() + "]", e );
+            }
+
+            setupDriver( cattr.getUrl(), cattr.getUserName(), cattr.getPassword(), cattr.getMaxActive() );
+
+            logDriverStats();
+        }
+        catch ( Exception e )
+        {
+            log.error( "Problem getting connection.", e );
+        }
+
+        // Initialization finished successfully, so set alive to true.
+        alive = true;
+    }
+
+    /*
+     * (non-Javadoc)
+     * 
+     * @see org.apache.jcs.auxiliary.disk.AbstractDiskCache#doUpdate(org.apache.jcs.engine.behavior.ICacheElement)
+     */
+    public void doUpdate( ICacheElement ce )
+    {
+
+        incrementUpdateCount();
+
+        if ( log.isDebugEnabled() )
+        {
+            log.debug( "updating, ce = " + ce );
+        }
+
+        Connection con;
+        try
+        {
+            con = DriverManager.getConnection( getPoolUrl() );
+        }
+        catch ( SQLException e )
+        {
+            log.error( "Problem getting conenction.", e );
+            return;
+        }
+
+        try
+        {
+            // TEST
+            Statement sStatement = null;
+            try
+            {
+                sStatement = con.createStatement();
+                alive = true;
+            }
+            catch ( SQLException e )
+            {
+                log.error( "Problem creating statement.", e );
+                alive = false;
+            }
+            finally
+            {
+                try
+                {
+                    sStatement.close();
+                }
+                catch ( SQLException e )
+                {
+                    log.error( "Problem closing statement.", e );
+                }
+            }
+
+            if ( !alive )
+            {
+                if ( log.isInfoEnabled() )
+                {
+                    log.info( "Disk is not alive, aborting put." );
+                }
+                return;
+            }
+
+            if ( log.isDebugEnabled() )
+            {
+                log.debug( "Putting [" + ce.getKey() + "] on disk." );
+            }
+
+            byte[] element;
+
+            try
+            {
+                element = serialize( ce );
+            }
+            catch ( IOException e )
+            {
+                log.error( "Could not serialize element", e );
+                return;
+            }
+
+            boolean exists = false;
+
+            // First do a query to determine if the element already exists
+            if ( this.getJdbcDiskCacheAttributes().isTestBeforeInsert() )
+            {
+                exists = doesElementExist( ce );
+            }
+
+            // If it doesn't exist, insert it, otherwise update
+            if ( !exists )
+            {
+
+                try
+                {
+                    String sqlI = "insert into " + getJdbcDiskCacheAttributes().getTableName()
+                        + " (CACHE_KEY, REGION, ELEMENT, MAX_LIFE_SECONDS, IS_ETERNAL, CREATE_TIME, CREATE_TIME_SECONDS) values (?, ?, ?, ?, ?, ?, ?)";
+
+                    PreparedStatement psInsert = con.prepareStatement( sqlI );
+                    psInsert.setString( 1, (String) ce.getKey() );
+                    psInsert.setString( 2, this.getCacheName() );
+                    psInsert.setBytes( 3, element );
+                    psInsert.setLong( 4, ce.getElementAttributes().getMaxLifeSeconds() );
+                    if ( ce.getElementAttributes().getIsEternal() )
+                    {
+                        psInsert.setString( 5, "T" );                        
+                    }
+                    else
+                    {
+                        psInsert.setString( 5, "F" );                        
+                    }
+                    Date createTime = new Date( ce.getElementAttributes().getCreateTime() );
+                    psInsert.setDate( 6, createTime );
+                    long now = System.currentTimeMillis() / 1000;
+                    psInsert.setLong( 7, now );
+
+                    psInsert.execute();
+                    psInsert.close();
+                }
+                catch ( SQLException e )
+                {
+                    if ( e.toString().indexOf( "Violation of unique index" ) != -1
+                        || e.getMessage().indexOf( "Violation of unique index" ) != -1
+                        || e.getMessage().indexOf( "Duplicate entry" ) != -1 )
+                    {
+                        exists = true;
+                    }
+                    else
+                    {
+                        log.error( "Could not insert element", e );
+                    }
+
+                    // see if it exists, if we didn't already
+                    if ( !exists && !this.getJdbcDiskCacheAttributes().isTestBeforeInsert() )
+                    {
+                        exists = doesElementExist( ce );
+                    }
+                }
+            }
+
+            // update if it exists.
+            if ( exists )
+            {
+                String sqlU = null;
+                try
+                {
+                    sqlU = "update " + getJdbcDiskCacheAttributes().getTableName()
+                        + " set ELEMENT  = ? where CACHE_KEY = ? and REGION = ? ";
+                    PreparedStatement psUpdate = con.prepareStatement( sqlU );
+                    psUpdate.setBytes( 1, element );
+                    psUpdate.setString( 2, (String) ce.getKey() );
+                    psUpdate.setString( 3, this.getCacheName() );
+                    psUpdate.execute();
+                    psUpdate.close();
+
+                    if ( log.isDebugEnabled() )
+                    {
+                        log.debug( "ran update " + sqlU );
+                    }
+                }
+                catch ( SQLException e2 )
+                {
+                    log.error( "e2 sql [" + sqlU + "] Exception: ", e2 );
+                }
+            }
+        }
+        finally
+        {
+            try
+            {
+                con.close();
+            }
+            catch ( SQLException e )
+            {
+                log.error( "Problem closing connection.", e );
+            }
+        }
+
+        if ( log.isInfoEnabled() )
+        {
+            if ( updateCount % LOG_INTERVAL == 0 )
+            {
+                // TODO make a log stats method
+                log.info( "Update Count [" + updateCount + "]" );
+            }
+        }
+    }
+
+    /**
+     * Does an element exist for this key?
+     * 
+     * @param ce
+     * @return
+     */
+    protected boolean doesElementExist( ICacheElement ce )
+    {
+        boolean exists = false;
+
+        Connection con;
+        try
+        {
+            con = DriverManager.getConnection( getPoolUrl() );
+        }
+        catch ( SQLException e )
+        {
+            log.error( "Problem getting conenction.", e );
+            return exists;
+        }
+
+        Statement sStatement = null;
+        try
+        {
+            sStatement = con.createStatement();
+
+            // don't select the element, since we want this to be fast.
+            String sqlS = "select CACHE_KEY from " + getJdbcDiskCacheAttributes().getTableName() + " where REGION = '"
+                + this.getCacheName() + "' and CACHE_KEY = '" + (String) ce.getKey() + "'";
+
+            if ( log.isDebugEnabled() )
+            {
+                log.debug( sqlS );
+            }
+
+            ResultSet rs = sStatement.executeQuery( sqlS );
+
+            if ( rs.next() )
+            {
+                exists = true;
+            }
+
+            if ( log.isDebugEnabled() )
+            {
+                log.debug( "[" + ce.getKey() + "] existing status is " + exists );
+            }
+
+            rs.close();
+        }
+        catch ( SQLException e )
+        {
+            log.error( "Problem looking for item before insert.", e );
+        }
+        finally
+        {
+            try
+            {
+                sStatement.close();
+            }
+            catch ( SQLException e1 )
+            {
+                log.error( "Problem closing statement.", e1 );
+            }
+
+            try
+            {
+                con.close();
+            }
+            catch ( SQLException e )
+            {
+                log.error( "Problem closing connection.", e );
+            }
+        }
+
+        return exists;
+    }
+
+    /*
+     * (non-Javadoc)
+     * 
+     * @see org.apache.jcs.auxiliary.disk.AbstractDiskCache#doGet(java.io.Serializable)
+     */
+    public ICacheElement doGet( Serializable key )
+    {
+
+        incrementGetCount();
+
+        if ( log.isDebugEnabled() )
+        {
+            log.debug( "Getting " + key + " from disk" );
+        }
+
+        if ( !alive )
+        {
+            return null;
+        }
+
+        ICacheElement obj = null;
+
+        byte[] data = null;
+        try
+        {
+            // region, key
+            String selectString = "select ELEMENT from " + getJdbcDiskCacheAttributes().getTableName()
+                + " where REGION = ? and CACHE_KEY = ?";
+
+            Connection con = DriverManager.getConnection( getPoolUrl() );
+            try
+            {
+                PreparedStatement psSelect = null;
+                try
+                {
+                    psSelect = con.prepareStatement( selectString );
+                    psSelect.setString( 1, this.getCacheName() );
+                    psSelect.setString( 2, (String) key );
+                    ResultSet rs = null;
+
+                    rs = psSelect.executeQuery();
+                    try
+                    {
+                        if ( rs.next() )
+                        {
+                            data = rs.getBytes( 1 );
+                        }
+                        if ( data != null )
+                        {
+                            try
+                            {
+                                // USE THE SERIALIZER
+                                obj = (ICacheElement) getElementSerializer().deSerialize( data );
+
+                            }
+                            catch ( IOException ioe )
+                            {
+                                log.error( ioe );
+                            }
+                            catch ( Exception e )
+                            {
+                                log.error( "Problem getting item.", e );
+                            }
+                        }
+                    }
+                    finally
+                    {
+                        if ( rs != null )
+                        {
+                            rs.close();
+                        }
+                        rs.close();
+                    }
+                }
+                finally
+                {
+                    if ( psSelect != null )
+                    {
+                        psSelect.close();
+                    }
+                    psSelect.close();
+                }
+            }
+            finally
+            {
+                if ( con != null )
+                {
+                    con.close();
+                }
+            }
+        }
+        catch ( SQLException sqle )
+        {
+            log.error( sqle );
+        }
+
+        if ( log.isInfoEnabled() )
+        {
+            if ( getCount % LOG_INTERVAL == 0 )
+            {
+                // TODO make a log stats method
+                log.info( "Get Count [" + getCount + "]" );
+            }
+        }
+
+        return obj;
+    }
+
+    /**
+     * Returns true if the removal was succesful; or false if there is nothing
+     * to remove. Current implementation always result in a disk orphan.
+     * 
+     * @param key
+     * @return boolean
+     */
+    public boolean doRemove( Serializable key )
+    {
+        // remove single item.
+        String sql = "delete from " + getJdbcDiskCacheAttributes().getTableName() + " where CACHE_KEY = '" + key
+            + "' and REGION = '" + this.getCacheName() + "'";
+
+        try
+        {
+            if ( key instanceof String && key.toString().endsWith( CacheConstants.NAME_COMPONENT_DELIMITER ) )
+            {
+                // remove all keys of the same name group.
+                sql = "delete from " + getJdbcDiskCacheAttributes().getTableName() + " where REGION = '"
+                    + this.getCacheName() + "' and CACHE_KEY = like '" + key + "%'";
+            }
+            Connection con = DriverManager.getConnection( getPoolUrl() );
+            Statement sStatement = null;
+            try
+            {
+                sStatement = con.createStatement();
+                alive = true;
+
+                sStatement.executeUpdate( sql );
+            }
+            catch ( SQLException e )
+            {
+                log.error( "Problem creating statement.", e );
+                alive = false;
+            }
+            finally
+            {
+                try
+                {
+                    if ( sStatement != null )
+                    {
+                        sStatement.close();
+                    }
+                    con.close();
+                }
+                catch ( SQLException e1 )
+                {
+                    log.error( "Problem closing statement.", e1 );
+                }
+            }
+
+        }
+        catch ( Exception e )
+        {
+            log.error( "Problem updating cache.", e );
+            reset();
+        }
+        return false;
+    }
+
+    /** This should remove all elements. For now this is not implemented. */
+    public void doRemoveAll()
+    {
+        try
+        {
+            String sql = "delete from " + getJdbcDiskCacheAttributes().getTableName() + " where REGION = '"
+                + this.getCacheName() + "'";
+            Connection con = DriverManager.getConnection( getPoolUrl() );
+            Statement sStatement = null;
+            try
+            {
+                sStatement = con.createStatement();
+                alive = true;
+
+                sStatement.executeUpdate( sql );
+            }
+            catch ( SQLException e )
+            {
+                log.error( "Problem creating statement.", e );
+                alive = false;
+            }
+            finally
+            {
+                try
+                {
+                    if ( sStatement != null )
+                    {
+                        sStatement.close();
+                    }
+                    con.close();
+                }
+                catch ( SQLException e1 )
+                {
+                    log.error( "Problem closing statement.", e1 );
+                }
+            }
+        }
+        catch ( Exception e )
+        {
+            log.error( "Problem removing all.", e );
+            reset();
+        }
+    }
+
+    /**
+     * Removed the expired.
+     * 
+     * (now - create time) > max life seconds * 1000
+     *
+     */
+    protected void deleteExpired()
+    {
+        try
+        {
+            long now = System.currentTimeMillis() / 1000;
+            String sql = "delete from " + getJdbcDiskCacheAttributes().getTableName() + " where REGION = '"
+                + this.getCacheName() + "' and IS_ETERNAL = 'F' and (" + now + " - CREATE_TIME_SECONDS) > MAX_LIFE";
+            Connection con = DriverManager.getConnection( getPoolUrl() );
+            Statement sStatement = null;
+            try
+            {
+                sStatement = con.createStatement();
+                alive = true;
+
+                sStatement.executeUpdate( sql );
+            }
+            catch ( SQLException e )
+            {
+                log.error( "Problem creating statement.", e );
+                alive = false;
+            }
+            finally
+            {
+                try
+                {
+                    if ( sStatement != null )
+                    {
+                        sStatement.close();
+                    }
+                    con.close();
+                }
+                catch ( SQLException e1 )
+                {
+                    log.error( "Problem closing statement.", e1 );
+                }
+            }
+        }
+        catch ( Exception e )
+        {
+            log.error( "Problem removing all.", e );
+            reset();
+        }        
+    }
+
+    /**
+     * Typically this is used to handle errors by last resort, force content
+     * update, or removeall
+     */
+    public void reset()
+    {
+        // nothing
+    }
+
+    /** Shuts down the pool */
+    public void doDispose()
+    {
+        try
+        {
+            shutdownDriver();
+        }
+        catch ( Exception e )
+        {
+            log.error( "Problem shutting down.", e );
+        }
+    }
+
+    /**
+     * Returns the current cache size.
+     * 
+     * @return The size value
+     */
+    public int getSize()
+    {
+        int size = 0;
+
+        // region, key
+        String selectString = "select count(*) from " + getJdbcDiskCacheAttributes().getTableName() + " where REGION = ?";
+
+        Connection con;
+        try
+        {
+            con = DriverManager.getConnection( getPoolUrl() );
+        }
+        catch ( SQLException e1 )
+        {
+            log.error( "Problem getting conenction.", e1 );
+            return size;
+        }
+        try
+        {
+            PreparedStatement psSelect = null;
+            try
+            {
+                psSelect = con.prepareStatement( selectString );
+                psSelect.setString( 1, this.getCacheName() );
+                ResultSet rs = null;
+
+                rs = psSelect.executeQuery();
+                try
+                {
+                    if ( rs.next() )
+                    {
+                        size = rs.getInt( 1 );
+                    }
+                }
+                finally
+                {
+                    if ( rs != null )
+                    {
+                        rs.close();
+                    }
+                    rs.close();
+                }
+            }
+            finally
+            {
+                if ( psSelect != null )
+                {
+                    psSelect.close();
+                }
+                psSelect.close();
+            }
+        }
+        catch ( SQLException e )
+        {
+            log.error( "Problem getting size.", e );
+        }
+        finally
+        {
+            try
+            {
+                con.close();
+            }
+            catch ( SQLException e )
+            {
+                log.error( "Problem closing connection.", e );
+            }
+        }
+        return size;
+    }
+
+    /**
+     * Returns the serialized form of the given object in a byte array.
+     * 
+     * @param obj
+     * @return byte[]
+     * @throws IOException
+     */
+    protected byte[] serialize( Serializable obj )
+        throws IOException
+    {
+        return getElementSerializer().serialize( obj );
+    }
+
+    /**
+     * @param groupName
+     * @return
+     * 
+     */
+    public Set getGroupKeys( String groupName )
+    {
+        if ( true )
+        {
+            throw new UnsupportedOperationException( "Groups not implemented." );
+        }
+        return null;
+    }
+
+    /**
+     * @param elementSerializer
+     *            The elementSerializer to set.
+     */
+    public void setElementSerializer( IElementSerializer elementSerializer )
+    {
+        this.elementSerializer = elementSerializer;
+    }
+
+    /**
+     * @return Returns the elementSerializer.
+     */
+    public IElementSerializer getElementSerializer()
+    {
+        return elementSerializer;
+    }
+
+    /**
+     * 
+     * @param connectURI
+     * @param userName
+     * @param password
+     * @param maxActive max connetions
+     * @throws Exception
+     */
+    public void setupDriver( String connectURI, String userName, String password, int maxActive )
+        throws Exception
+    {
+        // 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.
+        ObjectPool connectionPool = new GenericObjectPool( null, maxActive );
+
+        // Next, we'll create a ConnectionFactory that the
+        // pool will use to create Connections.
+        // We'll use the DriverManagerConnectionFactory,
+        // using the connect string passed in the command line
+        // arguments.
+        // Properties props = new Properties();
+        // props.setProperty( "user", userName );
+        // props.setProperty( "password", password );
+        ConnectionFactory connectionFactory = new DriverManagerConnectionFactory( connectURI, userName, password );
+
+        // Now we'll create the PoolableConnectionFactory, which wraps
+        // the "real" Connections created by the ConnectionFactory with
+        // the classes that implement the pooling functionality.
+        // PoolableConnectionFactory poolableConnectionFactory =
+        new PoolableConnectionFactory( connectionFactory, connectionPool, null, null, false, true );
+
+        // Finally, we create the PoolingDriver itself...
+        Class.forName( "org.apache.commons.dbcp.PoolingDriver" );
+        PoolingDriver driver = (PoolingDriver) DriverManager.getDriver( DRIVER_NAME );
+
+        // ...and register our pool with it.
+        driver.registerPool( this.getPoolName(), connectionPool );
+
+        // Now we can just use the connect string
+        // "jdbc:apache:commons:dbcp:jcs"
+        // to access our pool of Connections.
+    }
+
+    /**
+     * 
+     * @throws Exception
+     */
+    public void logDriverStats()
+        throws Exception
+    {
+        PoolingDriver driver = (PoolingDriver) DriverManager.getDriver( DRIVER_NAME );
+        ObjectPool connectionPool = driver.getConnectionPool( this.getPoolName() );
+
+        if ( connectionPool != null )
+        {
+            if ( log.isDebugEnabled() )
+            {
+                log.debug( connectionPool );
+            }
+
+            if ( log.isInfoEnabled() )
+            {
+                log.info( "NumActive: " + getNumActiveInPool() );
+                log.info( "NumIdle: " + getNumIdleInPool() );
+            }
+        }
+        else
+        {
+            log.warn( "Could not find pool." );
+        }
+    }
+
+    
+    /**
+     * How many are idle in the pool.
+     * 
+     * @return
+     */
+    public int getNumIdleInPool()
+    {
+        int numIdle = 0;
+        try
+        {
+            PoolingDriver driver = (PoolingDriver) DriverManager.getDriver( DRIVER_NAME );
+            ObjectPool connectionPool = driver.getConnectionPool( this.getPoolName() );
+
+            if ( log.isDebugEnabled() )
+            {
+                log.debug( connectionPool );
+            }
+            numIdle = connectionPool.getNumIdle();
+        }
+        catch ( Exception e )
+        {
+            log.error( e );
+        }
+        return numIdle;
+    }   
+    
+    /**
+     * How many are active in the pool.
+     * 
+     * @return
+     */
+    public int getNumActiveInPool()
+    {
+        int numActive = 0;
+        try
+        {
+            PoolingDriver driver = (PoolingDriver) DriverManager.getDriver( DRIVER_NAME );
+            ObjectPool connectionPool = driver.getConnectionPool( this.getPoolName() );
+
+            if ( log.isDebugEnabled() )
+            {
+                log.debug( connectionPool );
+            }
+            numActive = connectionPool.getNumActive();
+        }
+        catch ( Exception e )
+        {
+            log.error( e );
+        }
+        return numActive;
+    }
+
+    /**
+     * 
+     * @throws Exception
+     */
+    public void shutdownDriver()
+        throws Exception
+    {
+        PoolingDriver driver = (PoolingDriver) DriverManager.getDriver( DRIVER_NAME );
+        driver.closePool( this.getPoolName() );
+    }
+
+    /**
+     * @return Returns the poolUrl.
+     */
+    public String getPoolUrl()
+    {
+        return DRIVER_NAME + this.getPoolName();
+    }
+
+    /**
+     * @param poolName
+     *            The poolName to set.
+     */
+    public void setPoolName( String poolName )
+    {
+        this.poolName = poolName;
+    }
+
+    /**
+     * @return Returns the poolName.
+     */
+    public String getPoolName()
+    {
+        return poolName;
+    }
+
+    /** safely increment */
+    private synchronized void incrementUpdateCount()
+    {
+        updateCount++;
+    }
+
+    /** safely increment */
+    private synchronized void incrementGetCount()
+    {
+        getCount++;
+    }
+
+    /**
+     * @param jdbcDiskCacheAttributes The jdbcDiskCacheAttributes to set.
+     */
+    protected void setJdbcDiskCacheAttributes( JDBCDiskCacheAttributes jdbcDiskCacheAttributes )
+    {
+        this.jdbcDiskCacheAttributes = jdbcDiskCacheAttributes;
+    }
+
+    /**
+     * @return Returns the jdbcDiskCacheAttributes.
+     */
+    protected JDBCDiskCacheAttributes getJdbcDiskCacheAttributes()
+    {
+        return jdbcDiskCacheAttributes;
+    }
+
+    /**
+     * Extends the parent stats.
+     */
+    public IStats getStatistics()
+    {
+        IStats stats = super.getStatistics();
+        stats.setTypeName( "JDBC/Abstract Disk Cache" );
+        stats.getStatElements();
+
+        ArrayList elems = new ArrayList();
+
+        IStatElement se = null;
+
+        se = new StatElement();
+        se.setName( "Update Count" );
+        se.setData( "" + updateCount );
+        elems.add( se );
+
+        se = new StatElement();
+        se.setName( "Get Count" );
+        se.setData( "" + getCount );
+        elems.add( se );
+
+        se = new StatElement();
+        se.setName( "Size" );
+        se.setData( "" + getSize() );
+        elems.add( se );
+
+        se = new StatElement();
+        se.setName( "Active DB Connections" );
+        se.setData( "" + getNumActiveInPool() );
+        elems.add( se );
+
+        se = new StatElement();
+        se.setName( "Idle DB Connections" );
+        se.setData( "" + getNumIdleInPool() );
+        elems.add( se );
+
+        se = new StatElement();
+        se.setName( "DB URL" );
+        se.setData( this.jdbcDiskCacheAttributes.getUrl() );
+        elems.add( se );
+
+        // get the stats from the event queue too
+        // get as array, convert to list, add list to our outer list
+        IStatElement[] eqSEs = stats.getStatElements();
+        List eqL = Arrays.asList( eqSEs );
+        elems.addAll( eqL );
+
+        // get an array and put them in the Stats object
+        IStatElement[] ses = (IStatElement[]) elems.toArray( new StatElement[0] );
+        stats.setStatElements( ses );
+
+        return stats;
+    }
+}

Added: jakarta/jcs/trunk/src/java/org/apache/jcs/auxiliary/disk/jdbc/JDBCDiskCacheAttributes.java
URL: http://svn.apache.org/viewcvs/jakarta/jcs/trunk/src/java/org/apache/jcs/auxiliary/disk/jdbc/JDBCDiskCacheAttributes.java?rev=386396&view=auto
==============================================================================
--- jakarta/jcs/trunk/src/java/org/apache/jcs/auxiliary/disk/jdbc/JDBCDiskCacheAttributes.java (added)
+++ jakarta/jcs/trunk/src/java/org/apache/jcs/auxiliary/disk/jdbc/JDBCDiskCacheAttributes.java Thu Mar 16 09:28:51 2006
@@ -0,0 +1,188 @@
+package org.apache.jcs.auxiliary.disk.jdbc;
+
+/*
+ * Copyright 2001-2004 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.
+ * 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 org.apache.jcs.auxiliary.disk.AbstractDiskCacheAttributes;
+
+/**
+ * The configurator will set these values based on what is in the cache.ccf
+ * file.
+ * 
+ * @author Aaron Smuts
+ * 
+ */
+public class JDBCDiskCacheAttributes
+    extends AbstractDiskCacheAttributes
+{
+    private static final long serialVersionUID = -6535808344813320062L;
+
+    private static final String DEFAULT_TABLE_NAME = "JCS_STORE";
+
+    private String userName;
+
+    private String password;
+
+    private String url;
+
+    private String driverClassName;
+
+    private String tableName = DEFAULT_TABLE_NAME;
+
+    private boolean testBeforeInsert = true;
+
+    private static final int DEFAULT_MAX_ACTIVE = 10;
+    
+    private int maxActive = DEFAULT_MAX_ACTIVE;
+    
+    /**
+     * @param userName
+     *            The userName to set.
+     */
+    public void setUserName( String userName )
+    {
+        this.userName = userName;
+    }
+
+    /**
+     * @return Returns the userName.
+     */
+    public String getUserName()
+    {
+        return userName;
+    }
+
+    /**
+     * @param password
+     *            The password to set.
+     */
+    public void setPassword( String password )
+    {
+        this.password = password;
+    }
+
+    /**
+     * @return Returns the password.
+     */
+    public String getPassword()
+    {
+        return password;
+    }
+
+    /**
+     * @param url
+     *            The url to set.
+     */
+    public void setUrl( String url )
+    {
+        this.url = url;
+    }
+
+    /**
+     * @return Returns the url.
+     */
+    public String getUrl()
+    {
+        return url;
+    }
+
+    /**
+     * @param driverClassName
+     *            The driverClassName to set.
+     */
+    public void setDriverClassName( String driverClassName )
+    {
+        this.driverClassName = driverClassName;
+    }
+
+    /**
+     * @return Returns the driverClassName.
+     */
+    public String getDriverClassName()
+    {
+        return driverClassName;
+    }
+
+    /**
+     * @param tableName
+     *            The tableName to set.
+     */
+    public void setTableName( String tableName )
+    {
+        this.tableName = tableName;
+    }
+
+    /**
+     * @return Returns the tableName.
+     */
+    public String getTableName()
+    {
+        return tableName;
+    }
+
+    /**
+     * If this is true then the disk cache will check to see if the item already exists in the database.
+     * If it is false, it will try to insert.  If the isnert fails it will try to update.
+     * 
+     * @param testBeforeInsert
+     *            The testBeforeInsert to set.
+     */
+    public void setTestBeforeInsert( boolean testBeforeInsert )
+    {
+        this.testBeforeInsert = testBeforeInsert;
+    }
+
+    /**
+     * @return Returns the testBeforeInsert.
+     */
+    public boolean isTestBeforeInsert()
+    {
+        return testBeforeInsert;
+    }
+
+    /**
+     * @param maxActive The maxActive to set.
+     */
+    public void setMaxActive( int maxActive )
+    {
+        this.maxActive = maxActive;
+    }
+
+    /**
+     * @return Returns the maxActive.
+     */
+    public int getMaxActive()
+    {
+        return maxActive;
+    }
+
+    /**
+     * For debugging.
+     */
+    public String toString()
+    {
+        StringBuffer buf = new StringBuffer();
+        buf.append( "\nJDBCCacheAttributes" );
+        buf.append( "\nUserName [" + getUserName() + "]" );
+        buf.append( "\nUrl [" + getUrl() + "]" );
+        buf.append( "\nDriverClassName [" + getDriverClassName() + "]" );
+        buf.append( "\nTableName [" + getTableName() + "]" );
+        buf.append( "\nTestBeforeInsert [" + isTestBeforeInsert() + "]" );
+        buf.append( "\nMaxActive [" + getMaxActive() + "]" );
+        return buf.toString();
+    }
+
+}

Added: jakarta/jcs/trunk/src/java/org/apache/jcs/auxiliary/disk/jdbc/JDBCDiskCacheFactory.java
URL: http://svn.apache.org/viewcvs/jakarta/jcs/trunk/src/java/org/apache/jcs/auxiliary/disk/jdbc/JDBCDiskCacheFactory.java?rev=386396&view=auto
==============================================================================
--- jakarta/jcs/trunk/src/java/org/apache/jcs/auxiliary/disk/jdbc/JDBCDiskCacheFactory.java (added)
+++ jakarta/jcs/trunk/src/java/org/apache/jcs/auxiliary/disk/jdbc/JDBCDiskCacheFactory.java Thu Mar 16 09:28:51 2006
@@ -0,0 +1,61 @@
+package org.apache.jcs.auxiliary.disk.jdbc;
+
+/*
+ * Copyright 2001-2004 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.
+ * 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 org.apache.jcs.auxiliary.AuxiliaryCache;
+import org.apache.jcs.auxiliary.AuxiliaryCacheAttributes;
+import org.apache.jcs.auxiliary.AuxiliaryCacheFactory;
+import org.apache.jcs.engine.behavior.ICompositeCacheManager;
+
+/**
+ * This factory should create mysql disk caches.
+ * 
+ * @author Aaron Smuts
+ * 
+ */
+public class JDBCDiskCacheFactory
+    implements AuxiliaryCacheFactory
+{
+
+    private String name = "MysqlDiskCacheFactory";
+
+    /**
+     * This factory method should create an instance of the mysqlcache.
+     */
+    public AuxiliaryCache createCache( AuxiliaryCacheAttributes rawAttr, ICompositeCacheManager arg1 )
+    {
+        JDBCDiskCacheManager mgr = JDBCDiskCacheManager.getInstance( (JDBCDiskCacheAttributes)rawAttr );
+        return mgr.getCache( (JDBCDiskCacheAttributes)rawAttr );
+    }
+
+    /**
+     * The name of the factory.
+     */
+    public void setName( String nameArg )
+    {
+        name = nameArg;
+    }
+
+    /**
+     * Returns the display name
+     */
+    public String getName()
+    {
+        return name;
+    }
+
+}

Added: jakarta/jcs/trunk/src/java/org/apache/jcs/auxiliary/disk/jdbc/JDBCDiskCacheManager.java
URL: http://svn.apache.org/viewcvs/jakarta/jcs/trunk/src/java/org/apache/jcs/auxiliary/disk/jdbc/JDBCDiskCacheManager.java?rev=386396&view=auto
==============================================================================
--- jakarta/jcs/trunk/src/java/org/apache/jcs/auxiliary/disk/jdbc/JDBCDiskCacheManager.java (added)
+++ jakarta/jcs/trunk/src/java/org/apache/jcs/auxiliary/disk/jdbc/JDBCDiskCacheManager.java Thu Mar 16 09:28:51 2006
@@ -0,0 +1,183 @@
+package org.apache.jcs.auxiliary.disk.jdbc;
+
+/*
+ * Copyright 2001-2004 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.
+ * 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.util.Enumeration;
+import java.util.Hashtable;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.apache.jcs.auxiliary.AuxiliaryCache;
+import org.apache.jcs.auxiliary.AuxiliaryCacheManager;
+
+/**
+ * This manages instances of the jdbc disk cache. It maintains one for each
+ * region. One for all regions would work, but this gives us more detailed stats
+ * by region.
+ * 
+ */
+public class JDBCDiskCacheManager
+    implements AuxiliaryCacheManager
+{
+
+    private static final long serialVersionUID = -8258856770927857896L;
+
+    private static final Log log = LogFactory.getLog( JDBCDiskCacheManager.class );
+
+    private static int clients;
+
+    private static Hashtable caches = new Hashtable();
+
+    private static JDBCDiskCacheManager instance;
+
+    private static JDBCDiskCacheAttributes defaultCattr;
+
+    /**
+     * Constructor for the HSQLCacheManager object
+     * 
+     * @param cattr
+     */
+    private JDBCDiskCacheManager( JDBCDiskCacheAttributes cattr )
+    {
+        defaultCattr = cattr;
+    }
+
+    /**
+     * Gets the defaultCattr attribute of the HSQLCacheManager object
+     * 
+     * @return The defaultCattr value
+     */
+    public JDBCDiskCacheAttributes getDefaultCattr()
+    {
+        return defaultCattr;
+    }
+
+    /**
+     * Gets the instance attribute of the HSQLCacheManager class
+     * 
+     * @param cattr
+     * 
+     * @return The instance value
+     */
+    public static JDBCDiskCacheManager getInstance( JDBCDiskCacheAttributes cattr )
+    {
+        synchronized ( JDBCDiskCacheManager.class )
+        {
+            if ( instance == null )
+            {
+                instance = new JDBCDiskCacheManager( cattr );
+            }
+        }
+
+        clients++;
+        return instance;
+    }
+
+    /**
+     * Gets the cache attribute of the HSQLCacheManager object
+     * 
+     * @param cacheName
+     * 
+     * @return The cache value
+     */
+    public AuxiliaryCache getCache( String cacheName )
+    {
+        JDBCDiskCacheAttributes cattr = (JDBCDiskCacheAttributes) defaultCattr.copy();
+        cattr.setCacheName( cacheName );
+        return getCache( cattr );
+    }
+
+    /**
+     * Gets the cache attribute of the HSQLCacheManager object
+     * 
+     * @param cattr
+     * 
+     * @return The cache value
+     */
+    public AuxiliaryCache getCache( JDBCDiskCacheAttributes cattr )
+    {
+        AuxiliaryCache raf = null;
+
+        log.debug( "cacheName = " + cattr.getCacheName() );
+
+        synchronized ( caches )
+        {
+            raf = (AuxiliaryCache) caches.get( cattr.getCacheName() );
+
+            if ( raf == null )
+            {
+                raf = new JDBCDiskCache( cattr );
+                caches.put( cattr.getCacheName(), raf );
+            }
+        }
+
+        if ( log.isDebugEnabled() )
+        {
+            log.debug( "JDBC cache = " + raf );
+        }
+
+        return raf;
+    }
+
+    /**
+     * 
+     * @param name
+     */
+    public void freeCache( String name )
+    {
+        JDBCDiskCache raf = (JDBCDiskCache) caches.get( name );
+        if ( raf != null )
+        {
+
+            raf.dispose();
+
+        }
+    }
+
+    /**
+     * Gets the cacheType attribute of the HSQLCacheManager object
+     * 
+     * @return The cacheType value
+     */
+    public int getCacheType()
+    {
+        return DISK_CACHE;
+    }
+
+    /** Disposes of all regions. */
+    public void release()
+    {
+        // Wait until called by the last client
+        if ( --clients != 0 )
+        {
+            return;
+        }
+        synchronized ( caches )
+        {
+            Enumeration allCaches = caches.elements();
+
+            while ( allCaches.hasMoreElements() )
+            {
+                JDBCDiskCache raf = (JDBCDiskCache) allCaches.nextElement();
+                if ( raf != null )
+                {
+                    raf.dispose();
+                }
+            }
+        }
+    }
+}



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