jtaylor     02/02/16 11:06:35

  Modified:    .        build.xml
               src/java/org/apache/stratum/jcs/auxiliary/disk
                        DiskLockManager.java
               src/java/org/apache/stratum/jcs/auxiliary/disk/jisp
                        JISPLockManager.java
               src/java/org/apache/stratum/jcs/auxiliary/lateral/http/broadcast
                        LateralCacheMulticaster.java
                        LateralCacheUnicaster.java
               src/java/org/apache/stratum/jcs/auxiliary/lateral/http/remove
                        DeleteLateralCacheMulticaster.java
                        DeleteLateralCacheUnicaster.java
               src/java/org/apache/stratum/jcs/engine/group GroupCache.java
                        GroupRWLockManager.java
               src/java/org/apache/stratum/jcs/utils/servlet/session
                        DistSession.java
               src/java/org/apache/stratum/jcs/utils/threads
                        ThreadPool.java
  Added:       src/java/org/apache/stratum/jcs/utils/locking
                        ReadWriteLock.java ReadWriteLockManager.java
                        RwLockGC.java RwLockHolder.java
               src/java/org/apache/stratum/jcs/utils/threads
                        IThreadPoolRunnable.java ThreadPoolManager.java
  Removed:     src/java/org/apache/stratum/jcs/utils/reuse
                        HashMapPoolManager.java HashtablePoolManager.java
                        ICleanForPool.java IKnowCreateTime.java
                        IThreadPoolRunnable.java ObjectPreserver.java
                        ReadWriteLock.java ReadWriteLockManager.java
                        RwLockGC.java RwLockHolder.java
                        ThreadPoolManager.java
               src/java/org/apache/stratum/jcs/utils/threads
                        ThreadPoolRunnable.java
  Log:
  - Isolated JCS thread pool in jcs.utils.threads package
  - Isloated JCS lock stuff in jcs.utils.locking package
  
  ( We should look into whether the can/should be replaced or implemented with
    classes from util.concurrent. Doug's PooledExecuter seems to have all the
    features of this thread pool from tomcat )
  
  - Changed build to build directly from src directories rather than an
    intermediate directory.
  
  - Continued removing unused classes. jcs.utils.reuse is now empty except for
    IZombie. I'm still not sure where that belongs.
  
  Revision  Changes    Path
  1.22      +6 -8      jakarta-turbine-stratum/build.xml
  
  Index: build.xml
  ===================================================================
  RCS file: /home/cvs/jakarta-turbine-stratum/build.xml,v
  retrieving revision 1.21
  retrieving revision 1.22
  diff -u -r1.21 -r1.22
  --- build.xml 16 Feb 2002 13:35:30 -0000      1.21
  +++ build.xml 16 Feb 2002 19:06:34 -0000      1.22
  @@ -131,9 +131,6 @@
       <mkdir dir="${build.src}"/>
       <mkdir dir="${build.dest}"/>
   
  -    <copy todir="${build.src}">
  -      <fileset dir="${src.dir}/java/"/>
  -    </copy>
     </target>
   
     <!-- ================================================================== -->
  @@ -150,7 +147,7 @@
       depends="prepare"
       description="==> compiles the source code">
   
  -    <javac srcdir="${build.src}"
  +    <javac srcdir="${src.dir}/java"
         destdir="${build.dest}"
         debug="${debug}"
         deprecation="${deprecation}"
  @@ -205,14 +202,15 @@
         name="ajc"
         classname="org.aspectj.tools.ant.taskdefs.Ajc"/>
   
  -    <ajc srcdir="${build.src}"
  -      destdir="${build.dest}"
  +    <ajc destdir="${build.dest}"
         debug="${debug}"
         deprecation="${deprecation}"
         optimize="${optimize}">
  +      <src>
  +        <pathelement location="${src.dir}/java"/>
  +        <pathelement location="${src.dir}/aspects"/>
  +      </src>
         <classpath refid="classpath"/>
  -      <include name="**/*.java"/>
  -      <include name="**/*.aj"/>
       </ajc>
     </target>
   
  
  
  
  1.7       +1 -1      
jakarta-turbine-stratum/src/java/org/apache/stratum/jcs/auxiliary/disk/DiskLockManager.java
  
  Index: DiskLockManager.java
  ===================================================================
  RCS file: 
/home/cvs/jakarta-turbine-stratum/src/java/org/apache/stratum/jcs/auxiliary/disk/DiskLockManager.java,v
  retrieving revision 1.6
  retrieving revision 1.7
  diff -u -r1.6 -r1.7
  --- DiskLockManager.java      16 Feb 2002 02:37:17 -0000      1.6
  +++ DiskLockManager.java      16 Feb 2002 19:06:34 -0000      1.7
  @@ -55,7 +55,7 @@
    */
   import java.util.Hashtable;
   
  -import org.apache.stratum.jcs.utils.reuse.ReadWriteLockManager;
  +import org.apache.stratum.jcs.utils.locking.ReadWriteLockManager;
   
   /**
    * Read/Write lock manager for Disk.
  
  
  
  1.6       +1 -1      
jakarta-turbine-stratum/src/java/org/apache/stratum/jcs/auxiliary/disk/jisp/JISPLockManager.java
  
  Index: JISPLockManager.java
  ===================================================================
  RCS file: 
/home/cvs/jakarta-turbine-stratum/src/java/org/apache/stratum/jcs/auxiliary/disk/jisp/JISPLockManager.java,v
  retrieving revision 1.5
  retrieving revision 1.6
  diff -u -r1.5 -r1.6
  --- JISPLockManager.java      16 Feb 2002 02:37:18 -0000      1.5
  +++ JISPLockManager.java      16 Feb 2002 19:06:34 -0000      1.6
  @@ -2,7 +2,7 @@
   
   import java.util.Hashtable;
   
  -import org.apache.stratum.jcs.utils.reuse.ReadWriteLockManager;
  +import org.apache.stratum.jcs.utils.locking.ReadWriteLockManager;
   
   /**
    * Read/Write lock manager for Disk.
  
  
  
  1.7       +1 -1      
jakarta-turbine-stratum/src/java/org/apache/stratum/jcs/auxiliary/lateral/http/broadcast/LateralCacheMulticaster.java
  
  Index: LateralCacheMulticaster.java
  ===================================================================
  RCS file: 
/home/cvs/jakarta-turbine-stratum/src/java/org/apache/stratum/jcs/auxiliary/lateral/http/broadcast/LateralCacheMulticaster.java,v
  retrieving revision 1.6
  retrieving revision 1.7
  diff -u -r1.6 -r1.7
  --- LateralCacheMulticaster.java      16 Feb 2002 02:37:19 -0000      1.6
  +++ LateralCacheMulticaster.java      16 Feb 2002 19:06:34 -0000      1.7
  @@ -10,7 +10,7 @@
   import org.apache.commons.logging.Log;
   import org.apache.commons.logging.LogSource;
   
  -import org.apache.stratum.jcs.utils.reuse.ThreadPoolManager;
  +import org.apache.stratum.jcs.utils.threads.ThreadPoolManager;
   
   /*
    * Used to multi-cast a key/val pair to the named cache on multiple servers.
  
  
  
  1.6       +1 -1      
jakarta-turbine-stratum/src/java/org/apache/stratum/jcs/auxiliary/lateral/http/broadcast/LateralCacheUnicaster.java
  
  Index: LateralCacheUnicaster.java
  ===================================================================
  RCS file: 
/home/cvs/jakarta-turbine-stratum/src/java/org/apache/stratum/jcs/auxiliary/lateral/http/broadcast/LateralCacheUnicaster.java,v
  retrieving revision 1.5
  retrieving revision 1.6
  diff -u -r1.5 -r1.6
  --- LateralCacheUnicaster.java        16 Feb 2002 02:37:19 -0000      1.5
  +++ LateralCacheUnicaster.java        16 Feb 2002 19:06:34 -0000      1.6
  @@ -16,7 +16,7 @@
   import org.apache.commons.logging.Log;
   import org.apache.commons.logging.LogSource;
   
  -import org.apache.stratum.jcs.utils.reuse.IThreadPoolRunnable;
  +import org.apache.stratum.jcs.utils.threads.IThreadPoolRunnable;
   
   /**
    * Used to uni-cast a ICacheItem to the named cache on the target server.
  
  
  
  1.7       +1 -1      
jakarta-turbine-stratum/src/java/org/apache/stratum/jcs/auxiliary/lateral/http/remove/DeleteLateralCacheMulticaster.java
  
  Index: DeleteLateralCacheMulticaster.java
  ===================================================================
  RCS file: 
/home/cvs/jakarta-turbine-stratum/src/java/org/apache/stratum/jcs/auxiliary/lateral/http/remove/DeleteLateralCacheMulticaster.java,v
  retrieving revision 1.6
  retrieving revision 1.7
  diff -u -r1.6 -r1.7
  --- DeleteLateralCacheMulticaster.java        16 Feb 2002 02:37:19 -0000      1.6
  +++ DeleteLateralCacheMulticaster.java        16 Feb 2002 19:06:34 -0000      1.7
  @@ -8,7 +8,7 @@
   import org.apache.commons.logging.Log;
   import org.apache.commons.logging.LogSource;
   
  -import org.apache.stratum.jcs.utils.reuse.ThreadPoolManager;
  +import org.apache.stratum.jcs.utils.threads.ThreadPoolManager;
   
   /*
    * Used to multi-cast a key/val pair to the named cache on multiple servers.
  
  
  
  1.6       +1 -1      
jakarta-turbine-stratum/src/java/org/apache/stratum/jcs/auxiliary/lateral/http/remove/DeleteLateralCacheUnicaster.java
  
  Index: DeleteLateralCacheUnicaster.java
  ===================================================================
  RCS file: 
/home/cvs/jakarta-turbine-stratum/src/java/org/apache/stratum/jcs/auxiliary/lateral/http/remove/DeleteLateralCacheUnicaster.java,v
  retrieving revision 1.5
  retrieving revision 1.6
  diff -u -r1.5 -r1.6
  --- DeleteLateralCacheUnicaster.java  16 Feb 2002 02:37:19 -0000      1.5
  +++ DeleteLateralCacheUnicaster.java  16 Feb 2002 19:06:34 -0000      1.6
  @@ -9,7 +9,7 @@
   import org.apache.commons.logging.Log;
   import org.apache.commons.logging.LogSource;
   
  -import org.apache.stratum.jcs.utils.reuse.IThreadPoolRunnable;
  +import org.apache.stratum.jcs.utils.threads.IThreadPoolRunnable;
   
   /**
    * Used to uni-cast a ICacheItem to the named cache on the target server.
  
  
  
  1.12      +1 -1      
jakarta-turbine-stratum/src/java/org/apache/stratum/jcs/engine/group/GroupCache.java
  
  Index: GroupCache.java
  ===================================================================
  RCS file: 
/home/cvs/jakarta-turbine-stratum/src/java/org/apache/stratum/jcs/engine/group/GroupCache.java,v
  retrieving revision 1.11
  retrieving revision 1.12
  diff -u -r1.11 -r1.12
  --- GroupCache.java   16 Feb 2002 02:37:23 -0000      1.11
  +++ GroupCache.java   16 Feb 2002 19:06:34 -0000      1.12
  @@ -75,7 +75,7 @@
   import org.apache.stratum.jcs.engine.group.GroupId;
   import org.apache.stratum.jcs.engine.group.GroupRWLockManager;
   
  -import org.apache.stratum.jcs.utils.reuse.ReadWriteLockManager;
  +import org.apache.stratum.jcs.utils.locking.ReadWriteLockManager;
   
   import org.apache.commons.logging.Log;
   import org.apache.commons.logging.LogSource;
  
  
  
  1.6       +1 -1      
jakarta-turbine-stratum/src/java/org/apache/stratum/jcs/engine/group/GroupRWLockManager.java
  
  Index: GroupRWLockManager.java
  ===================================================================
  RCS file: 
/home/cvs/jakarta-turbine-stratum/src/java/org/apache/stratum/jcs/engine/group/GroupRWLockManager.java,v
  retrieving revision 1.5
  retrieving revision 1.6
  diff -u -r1.5 -r1.6
  --- GroupRWLockManager.java   16 Feb 2002 02:37:23 -0000      1.5
  +++ GroupRWLockManager.java   16 Feb 2002 19:06:34 -0000      1.6
  @@ -2,7 +2,7 @@
   
   import java.util.Hashtable;
   
  -import org.apache.stratum.jcs.utils.reuse.ReadWriteLockManager;
  +import org.apache.stratum.jcs.utils.locking.ReadWriteLockManager;
   
   import org.apache.commons.logging.Log;
   import org.apache.commons.logging.LogSource;
  
  
  
  1.1                  
jakarta-turbine-stratum/src/java/org/apache/stratum/jcs/utils/locking/ReadWriteLock.java
  
  Index: ReadWriteLock.java
  ===================================================================
  
  package org.apache.stratum.jcs.utils.locking;
  
  import java.util.ArrayList;
  
  import org.apache.commons.logging.Log;
  import org.apache.commons.logging.LogSource;
  
  /**
   * This class coordinates concurrent calls to an object's get and set methods so
   * that calls to the object set methods do not interfere with each other or with
   * calls to the object's get methods. <br>
   * <br>
   * Only a single instance of this class should be created per specific resource
   * that requires Read/Write lock protection. <br>
   * <br>
   * The invariant required by this class is that the method <code>done</code>
   * must be called, and only be called, after a previous call to either the
   * method <code>readLock</code> or <code>writeLock</code>.
   *
   * @author asmuts
   * @created January 15, 2002
   */
  class ReadWriteLock
  {
      private final static Log log =
          LogSource.getInstance( ReadWriteLockManager.class );
  
      /** Number of threads waiting to read. */
      private int waitingForReadLock = 0;
  
      /** Number of threads reading. */
      private int outstandingReadLocks = 0;
  
      /** The thread that has the write lock or null. */
      private Thread writeLockedThread;
  
      /**
       * The number of (nested) write locks that have been requested from
       * writeLockedThread.
       */
      private int outstandingWriteLocks = 0;
  
      /**
       * Threads waiting to get a write lock are tracked in this ArrayList to
       * ensure that write locks are issued in the same order they are requested.
       */
      private ArrayList waitingForWriteLock = new ArrayList();
  
  
      /** Default constructor. */
      ReadWriteLock() { }
  
  
      /**
       * Issue a read lock if there is no outstanding write lock or threads
       * waiting to get a write lock. Caller of this method must be careful to
       * avoid synchronizing the calling code so as to avoid deadlock.
       */
      synchronized void readLock()
          throws InterruptedException
      {
          waitingForReadLock++;
          while ( writeLockedThread != null )
          {
              log.debug( "readLock wait" );
              wait();
              log.debug( "wake up from readLock wait" );
          }
  
          log.debug( "readLock acquired" );
  
          waitingForReadLock--;
          outstandingReadLocks++;
      }
  
  
      /**
       * Issue a write lock if there are no outstanding read or write locks.
       * Caller of this method must be careful to avoid synchronizing the calling
       * code so as to avoid deadlock.
       */
      void writeLock()
          throws InterruptedException
      {
          Thread thisThread = Thread.currentThread();
          synchronized ( this )
          {
              if ( writeLockedThread == null && outstandingReadLocks == 0 )
              {
                  writeLockedThread = Thread.currentThread();
                  outstandingWriteLocks++;
  
                  log.debug( "writeLock acquired without waiting" );
  
                  return;
              }
              if ( writeLockedThread == thisThread )
              {
                  // nested write locks from the same thread.
                  outstandingWriteLocks++;
              }
              waitingForWriteLock.add( thisThread );
          }
          synchronized ( thisThread )
          {
              while ( thisThread != writeLockedThread )
              {
                  log.debug( "writeLock wait" );
                  // set this so if there is an error the app will not completely die!
                  thisThread.wait( 2000 );
                  log.debug( "wake up from writeLock wait" );
              }
  
              log.debug( "writeLock acquired" );
          }
          synchronized ( this )
          {
              int i = waitingForWriteLock.indexOf( thisThread );
              waitingForWriteLock.remove( i );
          }
      }
  
  
      /**
       * Threads call this method to relinquish a lock that they previously got
       * from this object.
       *
       * @throws IllegalStateException if called when there are no outstanding
       *      locks or there is a write lock issued to a different thread.
       */
      synchronized void done()
      {
          if ( outstandingReadLocks > 0 )
          {
              outstandingReadLocks--;
              if ( outstandingReadLocks == 0 && waitingForWriteLock.size() > 0 )
              {
                  writeLockedThread = ( Thread ) waitingForWriteLock.get( 0 );
                  if ( log.isDebugEnabled() )
                  {
                      log.debug( "readLock released and before notifying a write lock 
waiting thread "
                           + writeLockedThread );
                  }
                  synchronized ( writeLockedThread )
                  {
                      writeLockedThread.notifyAll();
                  }
                  if ( log.isDebugEnabled() )
                  {
                      log.debug( "readLock released and after  notifying a write lock 
waiting thread "
                           + writeLockedThread );
                  }
              }
              else if ( log.isDebugEnabled() )
              {
                  log.debug( "readLock released without fuss" );
              }
              return;
          }
          if ( Thread.currentThread() == writeLockedThread )
          {
              outstandingWriteLocks--;
              if ( outstandingWriteLocks > 0 )
              {
                  log.debug( "writeLock released for a nested writeLock request." );
                  return;
              }
              if ( outstandingReadLocks == 0 && waitingForWriteLock.size() > 0 )
              {
                  writeLockedThread = ( Thread ) waitingForWriteLock.get( 0 );
                  if ( log.isDebugEnabled() )
                  {
                      log.debug( "writeLock released and before notifying a write lock 
waiting thread "
                           + writeLockedThread );
                  }
                  synchronized ( writeLockedThread )
                  {
                      writeLockedThread.notifyAll();
                  }
                  if ( log.isDebugEnabled() )
                  {
                      log.debug( "writeLock released and after notifying a write lock 
waiting thread "
                           + writeLockedThread );
                  }
              }
              else
              {
                  writeLockedThread = null;
                  if ( waitingForReadLock > 0 )
                  {
                      if ( log.isDebugEnabled() )
                      {
                          log.debug( "writeLock released and notify all read lock 
waiting threads." );
                      }
                      notifyAll();
                  }
                  else if ( log.isDebugEnabled() )
                  {
                      log.debug( "writeLock released without fuss." );
                  }
              }
              return;
          }
          //////////////// debug MUST BE SET TO false in production! 
///////////////////
          if ( log.isDebugEnabled() )
          {
              try
              {
                  System.in.read();
              }
              catch ( java.io.IOException ignore )
              {
              }
          }
          throw new IllegalStateException( "Thread does not have lock" );
      }
  }
  
  
  
  
  1.1                  
jakarta-turbine-stratum/src/java/org/apache/stratum/jcs/utils/locking/ReadWriteLockManager.java
  
  Index: ReadWriteLockManager.java
  ===================================================================
  package org.apache.stratum.jcs.utils.locking;
  
  import java.util.Hashtable;
  
  import org.apache.commons.logging.Log;
  import org.apache.commons.logging.LogSource;
  
  /**
   * The Generic ReadWriteLock Manager for various resources.
   *
   * @author asmuts
   * @created January 15, 2002
   */
  public abstract class ReadWriteLockManager
  {
      private final static Log log =
          LogSource.getInstance( ReadWriteLockManager.class );
  
      /**
       * Used to asynchronously remove unused RwLockHolder objects managed ty this
       * manager.
       */
      private static RwLockGC gc;
  
      /** Class name for debugging purposes. */
      private String clsname;
  
      /** Places a read lock on the specified resource. */
      public final void readLock( String id )
          throws InterruptedException
      {
          lock( id, false );
      }
  
  
      /** Places a write lock on the specified resource. */
      public final void writeLock( String id )
          throws InterruptedException
      {
          lock( id, true );
      }
  
  
      /**
       * Release the read/write lock previously placed on the specified resource.
       */
      public final void done( String id )
      {
          Hashtable ht = getLocks();
          RwLockHolder holder = ( RwLockHolder ) ht.get( id );
  
          if ( holder == null )
          {
  
              log.debug( "Method done of " + getClass().getName() + " invoked without 
an outstanding lock; id=" + id );
              //System.exit(1);
  
              throw new IllegalStateException( "Method done of " + getClass().getName()
                   + " invoked without an outstanding lock; id=" + id );
          }
          holder.rwlock.done();
          if ( log.isDebugEnabled() )
          {
              log.debug( "lock done for id = " + id );
          }
          // Somehow if we don't synchronize while changing the count,
          // the count went down below zero!
          // Theoretically this should never happen, as a "done" is always preceeded
          // by either a read or write lock issued from the very same thread.
          // So for the moment, let's blame the JVM and make it work via 
synchronization,
          // until futher investigation.
          int lcount;
          // used to minimize the time spent in the synchronized block.
          synchronized ( ht )
          {
              lcount = --holder.lcount;
          }
          if ( lcount > 0 )
          {
              return;
          }
  
          //  p("-- holder.lcount=" + holder.lcount);
          if ( lcount == 0 )
          {
              holder.lastInactiveTime = System.currentTimeMillis();
              //p("notify: Gargage available");
              gc.notifyGarbage();
              return;
          }
          // lcount is negative! should never get here.
          /*
           * p("holder.lcount went down below zero (" + holder.lcount + ") for id=" + 
id);
           * System.exit(1);
           */
          throw new IllegalStateException( "holder.lcount went down below zero ("
               + holder.lcount + ") for id=" + id );
      }
  
  
      /** Places either a read or write lock on the specified resource. */
      private void lock( String id, boolean isWrite )
          throws InterruptedException
      {
          if ( log.isDebugEnabled() )
          {
              log.debug( "about to get lock, isWrite=" + isWrite + " for id = " + id );
          }
          RwLockHolder holder;
          Hashtable ht = getLocks();
          if ( gc == null )
          {
              synchronized ( this )
              {
                  if ( gc == null )
                  {
                      gc = new RwLockGC( ht );
                      gc.setDaemon( true );
                      gc.start();
                  }
              }
          }
          synchronized ( ht )
          {
              holder = ( RwLockHolder ) ht.get( id );
              if ( holder != null )
              {
                  // Lock already exists.  So just use it.
                  holder.lcount++;
                  if ( log.isDebugEnabled() )
                  {
                      log.debug( "++ holder.lcount=" + holder.lcount + ", isWrite=" + 
isWrite + " for id = " + id );
                  }
              }
          }
          if ( holder == null )
          {
              // Lock does not exist.  So create a new one.
              RwLockHolder newHolder = new RwLockHolder( new ReadWriteLock() );
              if ( log.isDebugEnabled() )
              {
                  log.debug( "holder is null, isWrite=" + isWrite );
              }
              synchronized ( ht )
              {
                  holder = ( RwLockHolder ) ht.put( id, newHolder );
                  if ( holder != null )
                  {
                      // Oops, the lock is already created by someone else 
concurrently.
                      // So we increment, put it back and discard the new lock we just 
created.
                      // We use this strategy to minimize the time spent in the 
synchronized block.
                      holder.lcount++;
                      ht.put( id, holder );
                  }
              }
              if ( holder == null )
              {
                  // no concurrency issue -- the new lock is now used.
                  holder = newHolder;
              }
              if ( log.isDebugEnabled() )
              {
                  log.debug( ( isWrite ? "Write" : "Read" ) + " lock created for " + 
id );
              }
          }
          // Be careful not to put the following code into a synchronized block.
          // Otherwise, deadlock can easily happen as the writeLock() and readLock() 
may result
          // in the ReadWriteLock object being waited!
          if ( isWrite )
          {
              holder.rwlock.writeLock();
          }
          else
          {
              holder.rwlock.readLock();
          }
          return;
      }
  
  
      /**
       * Returns the lock table of all the resources managed by the subclass.
       *
       * @return The locks value
       */
      protected abstract Hashtable getLocks();
  
  
      /**
       * Subclass must always override this constructor to create and preserve a
       * singleton instance of the subclass.
       */
      protected ReadWriteLockManager()
      {
          clsname = getClass().getName();
          clsname = clsname.substring( clsname.lastIndexOf( '.' ) + 1 );
      }
  }
  
  
  
  
  1.1                  
jakarta-turbine-stratum/src/java/org/apache/stratum/jcs/utils/locking/RwLockGC.java
  
  Index: RwLockGC.java
  ===================================================================
  
  package org.apache.stratum.jcs.utils.locking;
  
  import java.util.Hashtable;
  import java.util.Map;
  import java.util.Set;
  import java.util.Map.Entry;
  
  import org.apache.commons.logging.Log;
  import org.apache.commons.logging.LogSource;
  
  import org.apache.stratum.jcs.utils.locking.RwLockHolder;
  
  /**
   * Used to enhance performance by delaying the removal of unreferenced
   * RwLockHolder objects managed by the ReadWriteLockManager.
   *
   * @author asmuts
   * @created January 15, 2002
   */
  public class RwLockGC extends Thread
  {
      private final static Log log = LogSource.getInstance( RwLockGC.class );
  
      private final Hashtable ht;
      private final static long IDLE_PERIOD = 60 * 1000;
      // 60 seconds.
  
      private boolean clean = true;
  
  
      /**
       * Constructor for the RwLockGC object
       *
       * @param ht
       */
      RwLockGC( Hashtable ht )
      {
          this.ht = ht;
      }
  
  
      /**
       * Notifies the garbage collection that there is garbage available, and
       * kicks off the garbage collection process.
       */
      void notifyGarbage()
      {
          dirty();
          synchronized ( this )
          {
              notify();
          }
      }
  
      // Run forever.
  
      // Minimize the use of any synchronization in the process of garbage collection
      // for performance reason.
      /** Main processing method for the RwLockGC object */
      public void run()
      {
          do
          {
              if ( clean )
              {
                  synchronized ( this )
                  {
                      if ( clean )
                      {
  //p("RwLockGC entering into a wait state");
                          // Garbage driven mode.
                          try
                          {
                              wait();
                              // wake up only if there is garbage.
                          }
                          catch ( InterruptedException ignore )
                          {
                          }
                      }
                  }
              }
              // Time driven mode: sleep between each round of garbage collection.
              try
              {
  //p("RwLockGC sleeping for " + IDLE_PERIOD);
                  Thread.currentThread().sleep( IDLE_PERIOD );
              }
              catch ( InterruptedException ex )
              {
                  // ignore;
              }
              // The "clean" flag must be false here.
              // Simply presume we can collect all the garbage until proven otherwise.
              synchronized ( this )
              {
                  clean = true;
              }
              long now = System.currentTimeMillis();
              // Take a snapshot of the hashtable.
              Map.Entry[] entries = ( Map.Entry[] ) ht.entrySet().toArray( new 
Map.Entry[0] );
  //p("RwLockHolder garbage collecting...");
              for ( int i = 0; i < entries.length; i++ )
              {
                  RwLockHolder holder = ( RwLockHolder ) entries[i].getValue();
                  if ( holder.removable( now ) )
                  {
                      Object key = entries[i].getKey();
                      synchronized ( ht )
                      {
                          holder = ( RwLockHolder ) ht.get( key );
                          // holder cannot possibly be null as this should be the only 
thread removing them.
                          if ( holder.removable( now ) )
                          {
                              ht.remove( key );
                              /*
                               * p("removing key=" + key + ", now=" + now + ", 
holder.lastInactiveTime="
                               * + holder.lastInactiveTime);
                               */
                          }
                      }
                  }
              }
              // end for loop.
          } while ( true );
      }
  
  
      /** Sets the "clean" flag to false in a critial section. */
      private void dirty()
      {
          if ( clean )
          {
              synchronized ( this )
              {
                  clean = false;
              }
          }
      }
  }
  
  
  
  
  1.1                  
jakarta-turbine-stratum/src/java/org/apache/stratum/jcs/utils/locking/RwLockHolder.java
  
  Index: RwLockHolder.java
  ===================================================================
  
  package org.apache.stratum.jcs.utils.locking;
  
  /**
   * Used to keep track of the total number of outstanding locks placed but not
   * yet released for a given resource.
   *
   * @author asmuts
   * @created January 15, 2002
   */
  class RwLockHolder
  {
      private final static long UNUSED_TIME = 10 * 1000;
      // 10 seconds.
  
      /** Read/Write lock for a specific resource. */
      final ReadWriteLock rwlock;
  
      /**
       * Number of locks that have been placed on the rwlock and not yet released.
       */
      int lcount = 1;
  
      /** Last timestamp when the lcount was zero. */
      long lastInactiveTime = -1;
  
  
      /**
       * Constructs with a Read/Write lock for a specific resource.
       *
       * @param rwlock
       */
      RwLockHolder( ReadWriteLock rwlock )
      {
          this.rwlock = rwlock;
      }
  
  
      /**
       * Returns true iff this object satisfies the condition of removing
       * RwLockHolder from the managing ReadWriteLockManager.
       */
      boolean removable( long now )
      {
          return lcount == 0 && lastInactiveTime > 0 && now - lastInactiveTime > 
UNUSED_TIME;
      }
  }
  
  
  
  
  1.8       +1 -3      
jakarta-turbine-stratum/src/java/org/apache/stratum/jcs/utils/servlet/session/DistSession.java
  
  Index: DistSession.java
  ===================================================================
  RCS file: 
/home/cvs/jakarta-turbine-stratum/src/java/org/apache/stratum/jcs/utils/servlet/session/DistSession.java,v
  retrieving revision 1.7
  retrieving revision 1.8
  diff -u -r1.7 -r1.8
  --- DistSession.java  16 Feb 2002 02:37:25 -0000      1.7
  +++ DistSession.java  16 Feb 2002 19:06:35 -0000      1.8
  @@ -16,8 +16,6 @@
   import org.apache.commons.logging.Log;
   import org.apache.commons.logging.LogSource;
   
  -import org.apache.stratum.jcs.utils.reuse.ICleanForPool;
  -
   /**
    * DistSession uses the CompositeCache and GroupCache to create a failover-safe
    * distributed session.
  @@ -27,7 +25,7 @@
    * @created January 15, 2002
    */
   public class DistSession
  -     implements HttpSession, ICleanForPool, ISessionConstants
  +     implements HttpSession, ISessionConstants
   {
       private final static Log log =
           LogSource.getInstance( DistSession.class );
  
  
  
  1.5       +7 -7      
jakarta-turbine-stratum/src/java/org/apache/stratum/jcs/utils/threads/ThreadPool.java
  
  Index: ThreadPool.java
  ===================================================================
  RCS file: 
/home/cvs/jakarta-turbine-stratum/src/java/org/apache/stratum/jcs/utils/threads/ThreadPool.java,v
  retrieving revision 1.4
  retrieving revision 1.5
  diff -u -r1.4 -r1.5
  --- ThreadPool.java   16 Feb 2002 02:37:25 -0000      1.4
  +++ ThreadPool.java   16 Feb 2002 19:06:35 -0000      1.5
  @@ -1,9 +1,9 @@
   package org.apache.stratum.jcs.utils.threads;
   
   /*
  - * $Header: 
/home/cvs/jakarta-turbine-stratum/src/java/org/apache/stratum/jcs/utils/threads/ThreadPool.java,v
 1.4 2002/02/16 02:37:25 jtaylor Exp $
  - * $Revision: 1.4 $
  - * $Date: 2002/02/16 02:37:25 $
  + * $Header: 
/home/cvs/jakarta-turbine-stratum/src/java/org/apache/stratum/jcs/utils/threads/ThreadPool.java,v
 1.5 2002/02/16 19:06:35 jtaylor Exp $
  + * $Revision: 1.5 $
  + * $Date: 2002/02/16 19:06:35 $
    *
    * ====================================================================
    *
  @@ -239,7 +239,7 @@
       /**
        * Executes a given Runnable on a thread in the pool, block if needed.
        */
  -    public void runIt( ThreadPoolRunnable r )
  +    public void runIt( IThreadPoolRunnable r )
       {
   
           if ( null == r )
  @@ -544,7 +544,7 @@
       }
   
       /**
  -     * A Thread object that executes various actions ( ThreadPoolRunnable )
  +     * A Thread object that executes various actions ( IThreadPoolRunnable )
        * under control of ThreadPool
        *
        * @author asmuts
  @@ -560,7 +560,7 @@
           Thread t;
   
           /** The method that is executed in this thread */
  -        ThreadPoolRunnable toRun;
  +        IThreadPoolRunnable toRun;
   
           /** Stop this thread */
           boolean shouldTerminate;
  @@ -688,7 +688,7 @@
           }
   
           /** Description of the Method */
  -        public synchronized void runIt( ThreadPoolRunnable toRun )
  +        public synchronized void runIt( IThreadPoolRunnable toRun )
           {
               if ( toRun == null )
               {
  
  
  
  1.1                  
jakarta-turbine-stratum/src/java/org/apache/stratum/jcs/utils/threads/IThreadPoolRunnable.java
  
  Index: IThreadPoolRunnable.java
  ===================================================================
  package org.apache.stratum.jcs.utils.threads;
  
  /*
   * ====================================================================
   *
   * The Apache Software License, Version 1.1
   *
   * Copyright (c) 1999 The Apache Software Foundation.  All rights
   * reserved.
   *
   * Redistribution and use in source and binary forms, with or without
   * modification, are permitted provided that the following conditions
   * are met:
   *
   * 1. Redistributions of source code must retain the above copyright
   * notice, this list of conditions and the following disclaimer.
   *
   * 2. Redistributions in binary form must reproduce the above copyright
   * notice, this list of conditions and the following disclaimer in
   * the documentation and/or other materials provided with the
   * distribution.
   *
   * 3. The end-user documentation included with the redistribution, if
   * any, must include the following acknowlegement:
   * "This product includes software developed by the
   * Apache Software Foundation (http://www.apache.org/)."
   * Alternately, this acknowlegement may appear in the software itself,
   * if and wherever such third-party acknowlegements normally appear.
   *
   * 4. The names "The Jakarta Project", "Tomcat", and "Apache Software
   * Foundation" must not be used to endorse or promote products derived
   * from this software without prior written permission. For written
   * permission, please contact [EMAIL PROTECTED]
   *
   * 5. Products derived from this software may not be called "Apache"
   * nor may "Apache" appear in their names without prior written
   * permission of the Apache Group.
   *
   * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
   * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
   * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
   * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
   * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
   * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
   * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
   * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
   * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
   * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
   * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   * SUCH DAMAGE.
   * ====================================================================
   *
   * This software consists of voluntary contributions made by many
   * individuals on behalf of the Apache Software Foundation.  For more
   * information on the Apache Software Foundation, please see
   * <http://www.apache.org/>.
   *
   * [Additional notices, if required by prior licensing conditions]
   *
   */
  import java.util.zip.*;
  import java.net.*;
  import java.util.*;
  import java.io.*;
  
  /**
   * Implemented if you want to run a piece of code inside a thread pool. * A
   * thread pool that is trying to copy the apache process management. asmuts --
   * Pulled out of tomcat, since it seems to move around and hide. Trying to
   * reduce the number of dependencies
   *
   * @author <a href="mailto:[EMAIL PROTECTED]";>Aaron Smuts</a>
   * @created January 18, 2002
   */
  public interface IThreadPoolRunnable
  {
      // XXX use notes or a hashtable-like
      // Important: ThreadData in JDK1.2 is implemented as a Hashtable( Thread -> 
object ),
      // expensive.
  
      /**
       * Called when this object is first loaded in the thread pool. Important:
       * all workers in a pool must be of the same type, otherwise the mechanism
       * becomes more complex.
       *
       * @return The initData value
       */
      public Object[] getInitData();
  
      /**
       * This method will be executed in one of the pool's threads. The thread
       * will be returned to the pool.
       */
      public void runIt( Object thData[] );
  
  }
  
  
  
  1.1                  
jakarta-turbine-stratum/src/java/org/apache/stratum/jcs/utils/threads/ThreadPoolManager.java
  
  Index: ThreadPoolManager.java
  ===================================================================
  package org.apache.stratum.jcs.utils.threads;
  
  /**
   * Provides a singleton thread pool.
   *
   * @author asmuts
   * @created January 15, 2002
   */
  public class ThreadPoolManager
  {
      /** The singleton thread pool manager. */
      private final static ThreadPoolManager singleton = new ThreadPoolManager();
  
      /** The thread pool. */
      private ThreadPool pool = new ThreadPool();
      /** True iff the thread pool has been started. */
      private boolean started;
  
  
      /** Can only be constructed by this class. */
      private ThreadPoolManager() { }
  
  
      /**
       * Sets the max number of threads that you can open in the pool. Will only
       * be effective if called before the getInstance method is invoked for the
       * first time.
       *
       * @param maxThreads The new maxThreads value
       */
      public static void setMaxThreads( int maxThreads )
      {
          singleton.pool.setMaxThreads( maxThreads );
      }
  
  
      /**
       * Sets the min number of idle threads that you can leave in the pool. Will
       * only be effective if called before the getInstance method is invoked for
       * the first time.
       *
       * @param minSpareThreads The new minSpareThreads value
       */
      public static void setMinSpareThreads( int minSpareThreads )
      {
          singleton.pool.setMinSpareThreads( minSpareThreads );
      }
  
  
      /**
       * Sets the max number of idle threads that you can leave in the pool. Will
       * only be effective if called before the getInstance method is invoked for
       * the first time.
       *
       * @param maxSpareThreads The new maxSpareThreads value
       */
      public static void setMaxSpareThreads( int maxSpareThreads )
      {
          singleton.pool.setMaxSpareThreads( maxSpareThreads );
      }
  
  
      /**
       * Gets the max number of threads that you can open in the pool. Will only
       * be accurate if called after the getInstance method is invoked for the
       * first time.
       *
       * @return The maxThreads value
       */
      public static int getMaxThreads()
      {
          return singleton.pool.getMaxThreads();
      }
  
  
      /**
       * Gets the min number of idle threads that you can leave in the pool. Will
       * only be accurate if called after the getInstance method is invoked for
       * the first time.
       *
       * @return The minSpareThreads value
       */
      public static int getMinSpareThreads()
      {
          return singleton.pool.getMinSpareThreads();
      }
  
  
      /**
       * Gets the max number of idle threads that you can leave in the pool. Will
       * only be accurate if called after the getInstance method is invoked for
       * the first time.
       *
       * @return The maxSpareThreads value
       */
      public static int getMaxSpareThreads()
      {
          return singleton.pool.getMaxSpareThreads();
      }
  
  
      /**
       * Returns the singleton thread pool manager, which can be used to execute a
       * given IThreadPoolRunnable on a thread in the pool. Configuration of the
       * thread pool must be made prior to invoking this method.
       *
       * @return The instance value
       */
      public static ThreadPoolManager getInstance()
      {
          if ( !singleton.started )
          {
              synchronized ( singleton )
              {
                  if ( !singleton.started )
                  {
                      singleton.pool.start();
                      singleton.started = true;
                  }
              }
          }
          return singleton;
      }
  
  
      /**
       * Shuts down the thread pool and re-initializes it to the default.
       */
      public static void reset()
      {
          synchronized ( singleton )
          {
              if ( singleton.started )
              {
                  singleton.started = false;
                  singleton.pool.shutdown();
              }
              singleton.pool = new ThreadPool();
          }
          return;
      }
  
  
      /**
       * Executes a given IThreadPoolRunnable on a thread in the pool, block if
       * needed.
       */
      public void runIt( IThreadPoolRunnable r )
      {
          pool.runIt( r );
      }
  }
  
  
  

--
To unsubscribe, e-mail:   <mailto:[EMAIL PROTECTED]>
For additional commands, e-mail: <mailto:[EMAIL PROTECTED]>

Reply via email to