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 2005/01/06 02:19:51 UTC

cvs commit: jakarta-turbine-jcs/src/java/org/apache/jcs/utils/threadpool ThreadPoolManager.java

asmuts      2005/01/05 17:19:51

  Modified:    src/test/org/apache/jcs/access TestCacheAccess.java
               src/scripts tester.sh
               src/test/org/apache/jcs/engine/memory/lru
                        TestLRUMemoryCache.java
  Added:       src/java/org/apache/jcs/engine/stats StatElement.java
                        Stats.java
               src/java/org/apache/jcs/utils/threadpool
                        ThreadPoolManager.java
  Removed:     src/test TestBDBJEDiskCacheCon.ccf TestDiskCache.ccf
                        TestDiskCacheCon.ccf TestDiskCacheNoMemory.ccf
                        TestTCPLateralCache.ccf
  Log:
  1.  Put in a solution for the RMI bug.  Now, gets can be done asynchronously with a configurable timeout.
  You can specify that your remote region should timeout gets.
  
  see the cache.ccf in the src/conf for details
  
  #-1 means no timeout, this is the default
  # if the timeout is -1, no threadpool will be used.
  jcs.auxiliary.RC.attributes.GetTimeoutMillis=5000
  jcs.auxiliary.RC.attributes.ThreadPoolName=remote_cache_client
  
  Here RC is my auxiliary name.  I tell it to time out at 5 seconds and to use the thread pool named remote_cache_client.
  
  You can define pools in the file.  Below I define defaults for a thread pool and the settings for the pool I want the remote cache
  client to use.
  
  If the timeout is less than 0, no threadpool will be used.
  
  ##############################################################
  ################## THREAD POOL CONFIGURATION ###################
  # default thread pool config
  thread_pool.default.boundarySize=75
  thread_pool.default.maximumPoolSize=150
  thread_pool.default.minimumPoolSize=4
  thread_pool.default.keepAliveTime=350000
  thread_pool.default.abortWhenBlocked=false
  thread_pool.default.startUpSize=4
  
  # remote cache client thread pool config
  thread_pool.remote_cache_client.boundarySize=75
  thread_pool.remote_cache_client.maximumPoolSize=150
  thread_pool.remote_cache_client.minimumPoolSize=4
  thread_pool.remote_cache_client.keepAliveTime=350000
  thread_pool.remote_cache_client.abortWhenBlocked=false
  thread_pool.remote_cache_client.startUpSize=4
  
  2.  Changed stats gathering mechanism.  I will update the admin jsp to make use of the
  more easily formattable data.
  
  Revision  Changes    Path
  1.1                  jakarta-turbine-jcs/src/java/org/apache/jcs/engine/stats/StatElement.java
  
  Index: StatElement.java
  ===================================================================
  package org.apache.jcs.engine.stats;
  
  import org.apache.jcs.engine.stats.behavior.IStatElement;
  
  /*
   * 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.
   */
  
  /**
   * @author aaronsm
   *
   */
  public class StatElement implements IStatElement {
  
  	private String name = null;
  	
  	private String data = null;
  	
  	/* (non-Javadoc)
  	 * @see org.apache.jcs.engine.stats.behavior.IStatElement#getName()
  	 */
  	public String getName() {
  		return name;
  	}
  
  	/* (non-Javadoc)
  	 * @see org.apache.jcs.engine.stats.behavior.IStatElement#setName(java.lang.String)
  	 */
  	public void setName(String name) {
  		this.name = name;
  	}
  
  	/* (non-Javadoc)
  	 * @see org.apache.jcs.engine.stats.behavior.IStatElement#getData()
  	 */
  	public String getData() {
  		return data;
  	}
  
  	/* (non-Javadoc)
  	 * @see org.apache.jcs.engine.stats.behavior.IStatElement#setData(java.lang.String)
  	 */
  	public void setData(String data) {
  		this.data = data;
  	}
  
  	
  	/*
  	 *  (non-Javadoc)
  	 * @see java.lang.Object#toString()
  	 */
  	public String toString()
  	{
  		StringBuffer buf = new StringBuffer();		
  		buf.append( name + " = " + data );
  		return buf.toString();
  	}	
  }
  
  
  
  1.1                  jakarta-turbine-jcs/src/java/org/apache/jcs/engine/stats/Stats.java
  
  Index: Stats.java
  ===================================================================
  package org.apache.jcs.engine.stats;
  
  import org.apache.jcs.engine.stats.behavior.IStatElement;
  import org.apache.jcs.engine.stats.behavior.IStats;
  
  /*
   * 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.
   */
  
  /**
   * @author aaronsm
   *
   */
  public class Stats implements IStats {
  
  	private IStatElement[] stats = null;	
  	
  	private String typeName = null;
  	
  	/* (non-Javadoc)
  	 * @see org.apache.jcs.engine.stats.behavior.IStats#getStatElements()
  	 */
  	public IStatElement[] getStatElements() {
  		return stats;
  	}
  
  	/* (non-Javadoc)
  	 * @see org.apache.jcs.engine.stats.behavior.IStats#setStatElements(org.apache.jcs.engine.stats.behavior.IStatElement[])
  	 */
  	public void setStatElements(IStatElement[] stats) {
  		this.stats = stats;
  	}
  
  	/* (non-Javadoc)
  	 * @see org.apache.jcs.engine.stats.behavior.IStats#getTypeName()
  	 */
  	public String getTypeName() {
  		return typeName;
  	}
  
  	/* (non-Javadoc)
  	 * @see org.apache.jcs.engine.stats.behavior.IStats#setTypeName(java.lang.String)
  	 */
  	public void setTypeName(String name) {
  		typeName = name;
  	}
  
  
  	/*
  	 *  (non-Javadoc)
  	 * @see java.lang.Object#toString()
  	 */
  	public String toString()
  	{
  		StringBuffer buf = new StringBuffer();
  		
  		buf.append( typeName );
  		
  		if ( stats != null )
  		{
  			for( int i = 0; i < stats.length; i++ )
  			{
  				buf.append( "\n" );
  				buf.append( stats[i] );
  			}
  		}
  		
  		return buf.toString();
  	}
  	
  }
  
  
  
  1.13      +4 -8      jakarta-turbine-jcs/src/test/org/apache/jcs/access/TestCacheAccess.java
  
  Index: TestCacheAccess.java
  ===================================================================
  RCS file: /home/cvs/jakarta-turbine-jcs/src/test/org/apache/jcs/access/TestCacheAccess.java,v
  retrieving revision 1.12
  retrieving revision 1.13
  diff -u -r1.12 -r1.13
  --- TestCacheAccess.java	22 Jul 2004 13:15:16 -0000	1.12
  +++ TestCacheAccess.java	6 Jan 2005 01:19:51 -0000	1.13
  @@ -18,21 +18,17 @@
   
   import java.io.BufferedReader;
   import java.io.InputStreamReader;
  -
  -import java.util.StringTokenizer;
   import java.util.Iterator;
   import java.util.Random;
  -
  -import org.apache.jcs.engine.behavior.IElementAttributes;
  -import org.apache.jcs.engine.ElementAttributes;
  +import java.util.StringTokenizer;
   
   import org.apache.commons.logging.Log;
   import org.apache.commons.logging.LogFactory;
  -
  -import org.apache.jcs.engine.control.event.TestElementEventHandler;
  -import org.apache.jcs.engine.control.CompositeCache;
   import org.apache.jcs.JCS;
  +import org.apache.jcs.engine.ElementAttributes;
  +import org.apache.jcs.engine.behavior.IElementAttributes;
   import org.apache.jcs.engine.control.CompositeCacheManager;
  +import org.apache.jcs.engine.control.event.TestElementEventHandler;
   
   /**
    * Allows the user to run common cache commands from the command line for a test
  
  
  
  1.2       +5 -7      jakarta-turbine-jcs/src/scripts/tester.sh
  
  Index: tester.sh
  ===================================================================
  RCS file: /home/cvs/jakarta-turbine-jcs/src/scripts/tester.sh,v
  retrieving revision 1.1
  retrieving revision 1.2
  diff -u -r1.1 -r1.2
  --- tester.sh	5 Jan 2005 00:27:43 -0000	1.1
  +++ tester.sh	6 Jan 2005 01:19:51 -0000	1.2
  @@ -1,14 +1,12 @@
   #!/bin/zsh -f
   THIS_DIR=$(dirname $0)
   
  -pushd ${THIS_DIR}/../..; 
  +export CLASSPATH=${THIS_DIR}/../../src/conf
  +export CLASSPATH=${CLASSPATH}:${THIS_DIR}/../../target/test-classes
  +export CLASSPATH=${CLASSPATH}:${THIS_DIR}/../../target/classes
  +export CLASSPATH=${CLASSPATH}:.
   
  -export CLASSPATH=.
  -export CLASSPATH=${CLASSPATH}:${THIS_DIR}/target/test-classes
  -export CLASSPATH=${CLASSPATH}:${THIS_DIR}/target/classes
  -#export CLASSPATH=${CLASSPATH}:${THIS_DIR}/src/conf
  -
  -for i in `find ${THIS_DIR}/jars -name "*.jar" `
  +for i in `find ${THIS_DIR}/../../jars -name "*.jar" `
   do
           export CLASSPATH=${CLASSPATH}:$i
   done
  
  
  
  1.3       +4 -5      jakarta-turbine-jcs/src/test/org/apache/jcs/engine/memory/lru/TestLRUMemoryCache.java
  
  Index: TestLRUMemoryCache.java
  ===================================================================
  RCS file: /home/cvs/jakarta-turbine-jcs/src/test/org/apache/jcs/engine/memory/lru/TestLRUMemoryCache.java,v
  retrieving revision 1.2
  retrieving revision 1.3
  diff -u -r1.2 -r1.3
  --- TestLRUMemoryCache.java	15 Apr 2004 19:24:19 -0000	1.2
  +++ TestLRUMemoryCache.java	6 Jan 2005 01:19:51 -0000	1.3
  @@ -22,11 +22,10 @@
   import junit.framework.Test;
   import junit.framework.TestCase;
   
  -import org.apache.jcs.JCS;
   import org.apache.jcs.engine.CacheElement;
   import org.apache.jcs.engine.behavior.ICacheElement;
  -import org.apache.jcs.engine.control.CompositeCacheManager;
   import org.apache.jcs.engine.control.CompositeCache;
  +import org.apache.jcs.engine.control.CompositeCacheManager;
   
   /**
    * Test which exercises the indexed disk cache. This one uses three different
  @@ -137,7 +136,7 @@
   
           for ( int i = 0; i < 102; i++ )
           {
  -            this.assertNull(lru.get( i + ":key" ));
  +            assertNull(lru.get( i + ":key" ));
           }
   
           // Test that last items are in cache
  @@ -146,7 +145,7 @@
           {
               String value = (String) 
                   ((ICacheElement)lru.get( i + ":key" )).getVal();
  -            this.assertEquals( region + " data " + i, value );
  +            assertEquals( region + " data " + i, value );
           }
   
           // Remove all the items
  
  
  
  1.1                  jakarta-turbine-jcs/src/java/org/apache/jcs/utils/threadpool/ThreadPoolManager.java
  
  Index: ThreadPoolManager.java
  ===================================================================
  package org.apache.jcs.utils.threadpool;
  
  import java.io.IOException;
  import java.io.InputStream;
  import java.util.ArrayList;
  import java.util.HashMap;
  import java.util.Iterator;
  import java.util.Properties;
  import java.util.Set;
  
  import org.apache.commons.logging.Log;
  import org.apache.commons.logging.LogFactory;
  
  import EDU.oswego.cs.dl.util.concurrent.BoundedBuffer;
  import EDU.oswego.cs.dl.util.concurrent.PooledExecutor;
  
  /**
   * This manages threadpools for an application using Doug Lea's Util Concurrent
   * package.
   * http://gee.cs.oswego.edu/dl/classes/EDU/oswego/cs/dl/util/concurrent/intro.html
   * 
   * It is a singleton since threads need to be managed vm wide.
   * 
   * This managers force you to use a bounded queue. By default it uses the
   * current thread for execuion when the buffer is full and no free threads can
   * be created.
   * 
   * You can specify the props file to use or pass in a properties object prior to
   * configuration. By default it looks for configuration information in
   * thread_pool.properties.
   * 
   * If set the Properties object will take precedence.
   * 
   * If a value is not set for a particular pool, the hard coded defaults will be
   * used.
   * 
   * int boundarySize_DEFAULT = 75; int maximumPoolSize_DEFAULT = 150; int
   * minimumPoolSize_DEFAULT = 4; int keepAliveTime_DEFAULT = 1000 * 60 * 5;
   * boolean abortWhenBlocked = false; int startUpSize_DEFAULT = 4;
   * 
   * 
   * You can configure default settings by specifying a default pool in the
   * properties, ie "cache.ccf"
   * 
   * @author Aaron Smuts
   *  
   */
  public class ThreadPoolManager
  {
  
    private static final Log         log                      = LogFactory
                                                                  .getLog( ThreadPoolManager.class );
  
    // DEFAULT SETTINGS, these are not final since they can be set
    // via the Propeties file or object
    private static int               boundarySize_DEFAULT     = 75;
  
    private static int               maximumPoolSize_DEFAULT  = 150;
  
    private static int               minimumPoolSize_DEFAULT  = 4;
  
    private static int               keepAliveTime_DEFAULT    = 1000 * 60 * 5;
  
    private static boolean           abortWhenBlocked_DEFAULT = false;
  
    private static int               startUpSize_DEFAULT      = 4;
  
    private static PoolConfiguration defaultConfig;
  
    // This is the default value. Setting this after
    // inialization will have no effect
    private static String            propsFileName            = "cache.ccf";
  
    // the root property name
    private static String            PROP_NAME_ROOT           = "thread_pool";
  
    private static String            DEFAULT_PROP_NAME_ROOT   = "thread_pool.default";
  
    // You can specify the properties to be used to configure
    // the thread pool. Setting this post initialization will have
    // no effect.
    private static Properties        props                    = null;
  
    private static HashMap           pools                    = new HashMap();
  
    // singleton instance
    private static ThreadPoolManager INSTANCE                 = null;
  
    /**
     * No instances please. This is a singleton.
     *  
     */
    private ThreadPoolManager()
    {
      configure();
    }
  
    /**
     * Creates a pool based on the configuration info.
     * 
     * @param config
     * @return
     */
    private PooledExecutor createPool( PoolConfiguration config )
    {
  
      PooledExecutor pool = new PooledExecutor( new BoundedBuffer( config
          .getBoundarySize() ), config.getMaximumPoolSize() );
      pool.setMinimumPoolSize( config.getMinimumPoolSize() );
      pool.setKeepAliveTime( config.getKeepAliveTime() );
      if (config.isAbortWhenBlocked())
      {
        pool.abortWhenBlocked();
      }
      else
      {
        pool.runWhenBlocked();
      }
      pool.createThreads( config.getStartUpSize() );
  
      return pool;
    }
  
    /**
     * Returns a configured instance of the ThreadPoolManger To specify a
     * configuation file or Properties object to use call the appropriate setter
     * prior to calling getInstance.
     * 
     * @return
     */
    public static synchronized ThreadPoolManager getInstance()
    {
      if (INSTANCE == null)
      {
        INSTANCE = new ThreadPoolManager();
      }
      return INSTANCE;
    }
  
    /**
     * Returns a pool by name. If a pool by this name does not exist in the
     * configuration file or properties, one will be created using the default
     * values.
     * 
     * Pools are lazily created.
     * 
     * 
     * @param name
     * @return
     */
    public PooledExecutor getPool( String name )
    {
      PooledExecutor pool = null;
  
      synchronized (pools)
      {
        pool = (PooledExecutor) pools.get( name );
        if (pool == null)
        {
          if (log.isDebugEnabled())
          {
            log.debug( "Creating pool for name [" + name + "]" );
          }
          PoolConfiguration config = this
              .loadConfig( PROP_NAME_ROOT + "." + name );
          pool = createPool( config );
  
          if (pool != null)
          {
            pools.put( name, pool );
          }
  
          if (log.isDebugEnabled())
          {
            log.debug( "PoolName = " + getPoolNames() );
          }
        }
      }
  
      return pool;
    }
  
    /**
     * returns the names of all configured pools.
     * 
     * @return ArrayList of string names
     */
    public ArrayList getPoolNames()
    {
      ArrayList poolNames = new ArrayList();
      synchronized (pools)
      {
        Set names = pools.keySet();
        Iterator it = names.iterator();
        while (it.hasNext())
        {
          poolNames.add( (String) it.next() );
        }
      }
      return poolNames;
    }
  
    /**
     * Setting this post initialization will have no effect.
     * 
     * @param propsFileName
     *          The propsFileName to set.
     */
    public static void setPropsFileName( String propsFileName )
    {
      ThreadPoolManager.propsFileName = propsFileName;
    }
  
    /**
     * 
     * @return Returns the propsFileName.
     */
    public static String getPropsFileName()
    {
      return propsFileName;
    }
  
    /**
     * This will be used if it is not null on initialzation. Setting this post
     * initialization will have no effect.
     * 
     * @param props
     *          The props to set.
     */
    public static void setProps( Properties props )
    {
      ThreadPoolManager.props = props;
    }
  
    /**
     * @return Returns the props.
     */
    public static Properties getProps()
    {
      return props;
    }
  
    //-------------------------- Private Methods ----------
  
    /**
     * Intialize the ThreadPoolManager and create all the pools defined in the
     * configuration.
     *  
     */
    private void configure()
    {
      if (log.isDebugEnabled())
      {
        log.debug( "Initializing ThreadPoolManager" );
      }
  
      if (props == null)
      {
  
        InputStream is = getClass().getResourceAsStream( "/" + propsFileName );
  
        try
        {
          props.load( is );
  
          if (log.isDebugEnabled())
          {
            log.debug( "File contained " + props.size() + " properties" );
          }
        }
        catch (IOException ex)
        {
          log.error( "Failed to load properties", ex );
          throw new IllegalStateException( ex.getMessage() );
        }
        finally
        {
          try
          {
            is.close();
          }
          catch (Exception ignore)
          {
            // Ignored
          }
        }
  
      }
      if (props == null)
      {
        log
            .warn( "No configuration settings found.  Using hardcoded default values for all pools." );
        props = new Properties();
      }
  
      // set intial default and then override if new
      // settings are available
      defaultConfig = new PoolConfiguration( boundarySize_DEFAULT,
          maximumPoolSize_DEFAULT, minimumPoolSize_DEFAULT,
          keepAliveTime_DEFAULT, abortWhenBlocked_DEFAULT, startUpSize_DEFAULT );
  
      defaultConfig = loadConfig( DEFAULT_PROP_NAME_ROOT );
  
    }
  
    /**
     * Configures the default PoolConfiguration settings
     *  
     */
    private PoolConfiguration loadConfig( String root )
    {
  
      PoolConfiguration config = (PoolConfiguration) defaultConfig.clone();
  
      // load default if they exist
      if (props.containsKey( root + ".boundarySize" ))
      {
        try
        {
          config.setBoundarySize( Integer.parseInt( (String) props.get( root
              + ".boundarySize" ) ) );
        }
        catch (NumberFormatException nfe)
        {
          log.error( "boundarySize not a number.", nfe );
        }
      }
  
      if (props.containsKey( root + ".maximumPoolSize" ))
      {
        try
        {
          config.setMaximumPoolSize( Integer.parseInt( (String) props.get( root
              + ".maximumPoolSize" ) ) );
        }
        catch (NumberFormatException nfe)
        {
          log.error( "maximumPoolSize not a number.", nfe );
        }
      }
  
      if (props.containsKey( root + ".minimumPoolSize" ))
      {
        try
        {
          config.setMinimumPoolSize( Integer.parseInt( (String) props.get( root
              + ".minimumPoolSize" ) ) );
        }
        catch (NumberFormatException nfe)
        {
          log.error( "minimumPoolSize not a number.", nfe );
        }
      }
  
      if (props.containsKey( root + ".keepAliveTime" ))
      {
        try
        {
          config.setKeepAliveTime( Integer.parseInt( (String) props.get( root
              + ".keepAliveTime" ) ) );
        }
        catch (NumberFormatException nfe)
        {
          log.error( "keepAliveTime not a number.", nfe );
        }
      }
  
      if (props.containsKey( root + ".startUpSize" ))
      {
        try
        {
          config.setAbortWhenBlocked( Boolean.getBoolean( (String) props
              .get( root + ".abortWhenBlocked" ) ) );
        }
        catch (NumberFormatException nfe)
        {
          log.error( "abortWhenBlocked not a boolean.", nfe );
        }
      }
  
      if (props.containsKey( root + ".startUpSize" ))
      {
        try
        {
          config.setStartUpSize( Integer.parseInt( (String) props.get( root
              + ".startUpSize" ) ) );
        }
        catch (NumberFormatException nfe)
        {
          log.error( "startUpSize not a number.", nfe );
        }
      }
  
      if (log.isDebugEnabled())
      {
        log.debug( root + " PoolConfiguration = " + config );
      }
  
      return config;
    }
  
  }
  
  

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