dims        01/03/01 07:45:39

  Modified:    src/org/apache/cocoon Tag: xml-cocoon2
                        CocoonComponentSelector.java
               src/org/apache/cocoon/components/language/generator Tag:
                        xml-cocoon2 ProgramGeneratorImpl.java
               src/org/apache/cocoon/util Tag: xml-cocoon2
                        ComponentPool.java
  Log:
  1. A slightly better ComponentPool implementation till the Avalon guys come up
     with a better one. Does not impose any resource limit right now, expands 
the
     pool but does not shrink it.
  2. Remove leaks in Life-Cycle for XSPGenerator components.
  
  Revision  Changes    Path
  No                   revision
  
  
  No                   revision
  
  
  1.1.2.25  +4 -1      
xml-cocoon/src/org/apache/cocoon/Attic/CocoonComponentSelector.java
  
  Index: CocoonComponentSelector.java
  ===================================================================
  RCS file: 
/home/cvs/xml-cocoon/src/org/apache/cocoon/Attic/CocoonComponentSelector.java,v
  retrieving revision 1.1.2.24
  retrieving revision 1.1.2.25
  diff -u -r1.1.2.24 -r1.1.2.25
  --- CocoonComponentSelector.java      2001/02/28 17:40:24     1.1.2.24
  +++ CocoonComponentSelector.java      2001/03/01 15:45:26     1.1.2.25
  @@ -43,7 +43,7 @@
   /** Default component manager for Cocoon's non sitemap components.
    * @author <a href="mailto:[EMAIL PROTECTED]">Berin Loritsch</a>
    * @author <a href="mailto:[EMAIL PROTECTED]">Paul Russell</a>
  - * @version CVS $Revision: 1.1.2.24 $ $Date: 2001/02/28 17:40:24 $
  + * @version CVS $Revision: 1.1.2.25 $ $Date: 2001/03/01 15:45:26 $
    */
   public class CocoonComponentSelector implements Contextualizable, 
ComponentSelector, Composer, Configurable, ThreadSafe, Loggable {
       protected Logger log;
  @@ -225,6 +225,7 @@
   
           if ( pool == null ) {
               try {
  +                log.debug("Creating new pool for:" + componentClass);
                   ComponentFactory cf = new ComponentFactory(componentClass, 
(Configuration)configurations.get(hint), this.manager, this.context);
                   cf.setLogger(this.log);
   
  @@ -263,6 +264,8 @@
   
               if (pool != null) {
                   pool.put((Poolable) component);
  +            } else {
  +                log.debug("Could not find pool for:" + component.getClass());
               }
           } else if (component instanceof Recyclable) {
               ((Recyclable) component).recycle();
  
  
  
  No                   revision
  
  
  No                   revision
  
  
  1.1.2.38  +20 -7     
xml-cocoon/src/org/apache/cocoon/components/language/generator/Attic/ProgramGeneratorImpl.java
  
  Index: ProgramGeneratorImpl.java
  ===================================================================
  RCS file: 
/home/cvs/xml-cocoon/src/org/apache/cocoon/components/language/generator/Attic/ProgramGeneratorImpl.java,v
  retrieving revision 1.1.2.37
  retrieving revision 1.1.2.38
  diff -u -r1.1.2.37 -r1.1.2.38
  --- ProgramGeneratorImpl.java 2001/02/22 19:07:41     1.1.2.37
  +++ ProgramGeneratorImpl.java 2001/03/01 15:45:33     1.1.2.38
  @@ -46,7 +46,7 @@
   /**
    * The default implementation of <code>ProgramGenerator</code>
    * @author <a href="mailto:[EMAIL PROTECTED]">Ricardo Rocha</a>
  - * @version CVS $Revision: 1.1.2.37 $ $Date: 2001/02/22 19:07:41 $
  + * @version CVS $Revision: 1.1.2.38 $ $Date: 2001/03/01 15:45:33 $
    */
   public class ProgramGeneratorImpl extends AbstractLoggable implements 
ProgramGenerator, Contextualizable, Composer, Configurable, ThreadSafe {
   
  @@ -152,7 +152,7 @@
   
           // Attempt to load program object from cache
           try {
  -            programInstance = (CompiledComponent) 
this.cache.select(normalizedName);
  +            programInstance = (CompiledComponent) select(normalizedName);
           } catch (Exception e) {
               getLogger().debug("The instance was not accessible, creating it 
now.");
           }
  @@ -165,7 +165,7 @@
               }
   
               try {
  -                programInstance = (CompiledComponent) 
this.cache.select(normalizedName);
  +                programInstance = (CompiledComponent) select(normalizedName);
               } catch (Exception cme) {
                   getLogger().debug("Can't load ServerPage", cme);
               }
  @@ -183,22 +183,29 @@
            */
   
           if (programInstance != null && 
programInstance.modifiedSince(file.lastModified())) {
  +            // Release the component.            
  +            release(programInstance);
  +
               // Unload program
               programmingLanguage.unload(program, normalizedName, 
this.workDir);
  +            
               // Invalidate previous program/instance pair
               program = null;
               programInstance = null;
           }
   
           if (programInstance == null) {
  -            program = generateResource(file, normalizedName, markupLanguage, 
programmingLanguage, resolver);
  +            if (program == null) {
  +                program = generateResource(file, normalizedName, 
markupLanguage, programmingLanguage, resolver);
  +            }
  +            // Instantiate
  +            programInstance = (CompiledComponent) select(normalizedName);
           }
   
           this.markupSelector.release((Component) markupLanguage);
           this.languageSelector.release((Component) programmingLanguage);
   
  -        // Instantiate
  -        return (CompiledComponent) this.cache.select(normalizedName);
  +        return programInstance;
       }
   
       private Class generateResource(File file,
  @@ -227,7 +234,7 @@
   
           if 
(markupLanguage.getClass().getName().equals(SitemapMarkupLanguage.class.getName()))
 {
               try {
  -                this.cache.select("sitemap");
  +                select("sitemap");
               } catch (Exception e) {
                   // If the root sitemap has not been compiled, add an alias 
here.
                   this.cache.addGenerator("sitemap", program);
  @@ -235,6 +242,12 @@
           }
   
           return program;
  +    }
  +
  +    public CompiledComponent select(String componentName) 
  +        throws Exception {
  +        CompiledComponent component = 
(CompiledComponent)this.cache.select(componentName);
  +        return component;
       }
   
       public void release(CompiledComponent component) {
  
  
  
  No                   revision
  
  
  No                   revision
  
  
  1.1.2.10  +240 -6    
xml-cocoon/src/org/apache/cocoon/util/Attic/ComponentPool.java
  
  Index: ComponentPool.java
  ===================================================================
  RCS file: 
/home/cvs/xml-cocoon/src/org/apache/cocoon/util/Attic/ComponentPool.java,v
  retrieving revision 1.1.2.9
  retrieving revision 1.1.2.10
  diff -u -r1.1.2.9 -r1.1.2.10
  --- ComponentPool.java        2001/02/28 17:40:29     1.1.2.9
  +++ ComponentPool.java        2001/03/01 15:45:37     1.1.2.10
  @@ -7,12 +7,14 @@
    */
   package org.apache.cocoon.util;
   
  +import java.util.Vector;
  +
   import org.apache.avalon.Poolable;
   import org.apache.avalon.ThreadSafe;
   import org.apache.avalon.Loggable;
  -import org.apache.avalon.util.pool.ThreadSafePool;
  +import org.apache.avalon.util.pool.Pool;
   import org.apache.avalon.util.pool.ObjectFactory;
  -import org.apache.avalon.util.pool.PoolController;
  +import org.apache.avalon.Recyclable;
   import org.apache.cocoon.ComponentFactory;
   
   import org.apache.log.Logger;
  @@ -23,30 +25,262 @@
    *
    * @author <a href="mailto:[EMAIL PROTECTED]">Giacomo Pati</a>
    */
  -public class ComponentPool extends ThreadSafePool implements ThreadSafe, 
Loggable {
  +public class ComponentPool implements Pool, ThreadSafe, Loggable {
   
       public final static int DEFAULT_POOL_SIZE = 8;
   
  +    public final static int DEFAULT_WAIT_TIME = (5*100);
  +
       private Logger log;
   
  +    /** The resources that are currently free */
  +     protected Vector availableResources;
  +
  +    /** Resources that have been allocated out of the pool */
  +     protected Vector usedResources;
  +
  +    /** Flag to make sure at least one thread has received notification */
  +     boolean receivedWakeup;
  +
  +    /** The number of threads waiting for notification */
  +     int numThreadsWaiting;
  +
  +    protected ObjectFactory m_factory = null;
  +
  +    protected int m_initial = DEFAULT_POOL_SIZE/2;
  +
  +    protected int m_maximum = DEFAULT_POOL_SIZE;
  +
       public ComponentPool(final ObjectFactory factory) throws Exception {
  -        super(factory, DEFAULT_POOL_SIZE/2, DEFAULT_POOL_SIZE);
  +        init(factory, DEFAULT_POOL_SIZE/2, DEFAULT_POOL_SIZE);
       }
   
       public ComponentPool(final ObjectFactory factory,
                            final int initial) throws Exception {
  -        super(factory, initial, initial);
  +        init(factory, initial, initial);
       }
   
       public ComponentPool(final ObjectFactory factory,
                            final int initial,
                            final int maximum) throws Exception {
  -        super(factory, initial, maximum);
  +        init(factory, initial, maximum);
       }
   
  +    private void init(final ObjectFactory factory, 
  +                      final int initial, 
  +                      final int maximum) throws Exception {
  +        m_factory = factory;
  +        m_initial = initial;
  +        m_maximum = maximum;
  +    }
  +
  +    public void init() throws Exception {
  +             availableResources = new Vector();
  +             usedResources = new Vector();
  +             receivedWakeup = true;
  +             numThreadsWaiting = 0;
  +
  +        for( int i = 0; i < m_initial; i++ )
  +            availableResources.addElement(m_factory.newInstance());
  +    }
  +
       public void setLogger(Logger log) {
           if (this.log == null) {
               this.log = log;
           }
       }
  +
  +    /** Allocates a resource when the pool is empty. By default, this method
  +     *       returns null, indicating that the requesting thread must wait. 
This
  +     *       allows a thread pool to expand when necessary, allowing for 
spikes in
  +     *       activity.
  +     *       @return A new resource, or null to force the requester to wait
  +     */ 
  +     protected synchronized Poolable getOverflowResource()
  +        throws Exception
  +     {
  +             Poolable poolable = m_factory.newInstance();
  +        log.debug("Component Pool - creating Overflow Resource:" 
  +                        + " Resource=" + poolable
  +                        + " Available=" + availableResources.size()
  +                        + " Used=" + usedResources.size() );
  +        return poolable;
  +     }
  +
  +    /** Grabs a resource from the free list and moves it to the used list.
  +     * This method is really the core of the resource pool. The rest of the 
class
  +     * deals with synchronization around this method.
  +     * @return The allocated resource
  +     */
  +     protected synchronized Poolable getResourceFromList()
  +     {
  +        // See if there is a resource available.
  +             if (availableResources.size() > 0) {
  +
  +            // Get the first resource from the free list
  +                     Poolable resource = (Poolable) 
availableResources.elementAt(0);
  +
  +            // Remove the resource from the free list
  +                 availableResources.removeElement(resource);
  +
  +            // Add the resource and its associated info to the used list
  +                     usedResources.addElement(resource);
  +
  +                     return resource;
  +             }
  +
  +             return null;
  +     }
  +
  +    /** Performs a wait for a specified number of milliseconds.
  +     * @param timeout The number of milliseconds to wait
  +     * (wait forever if timeout < 0)
  +     */
  +     protected synchronized void doWait(long timeout)
  +     {
  +             try {
  +                     if (timeout < 0) {
  +                             wait();
  +                     }
  +                     else {
  +                             wait(timeout);
  +                     }
  +             }
  +             catch (Exception ignore) {
  +             }
  +     }
  +
  +    /** Requests a resource from the pool, waiting forever if one is not 
available.
  +     * No extra information is associated with the allocated resource.
  +     * @return The allocated resource
  +     */
  +     public Poolable get()
  +        throws Exception
  +     {
  +             return get(DEFAULT_WAIT_TIME);
  +     }
  +
  +    /** Requests a resource from the pool, waiting forever if one is not 
available.
  +     * @param timeout The maximum amount of time (in milliseconds)
  +     * to wait for the resource
  +     * @return The allocated resource
  +     */
  +     public Poolable get(long timeout) 
  +        throws Exception
  +     {
  +        // See if there is a resource in the pool already
  +             Poolable resource = getResourceFromList();
  +             if (resource != null)
  +             {
  +                     return resource;
  +             }
  +
  +        // Figure out when to stop waiting
  +             long endTime = System.currentTimeMillis() + timeout;
  +
  +             do {
  +
  +                     synchronized(this) {
  +                // See if there are any available resources in the pool
  +                             if (availableResources.size() == 0) {
  +
  +                    // Allow subclasses to provide overflow resources
  +                                 resource = getOverflowResource();
  +
  +                    // If there was a resource allocated for overflow, add 
it to the used list
  +                                 if (resource != null) {
  +                                     usedResources.addElement(resource);
  +                                     return resource;
  +                                 }
  +                             }
  +                     }
  +
  +            // Wait for a resource to be allocated
  +
  +            // Figure out the longest time to wait before timing out
  +                     long maxWait = endTime - System.currentTimeMillis();
  +                     if (timeout < 0) maxWait = -1;
  +
  +            // Indicate that there is a thread waiting for a wakeup
  +                     numThreadsWaiting++;
  +
  +            // Wait for a wakeup
  +                     doWait(maxWait);
  +
  +                     numThreadsWaiting--;
  +
  +            // Only mention the received wakeup if the timeout hasn't expired
  +                     if ((timeout < 0) || (System.currentTimeMillis() < 
maxWait)) {
  +                             receivedWakeup = true;
  +                     }
  +
  +            // See if there is now a resource in the free pool
  +                 resource = getResourceFromList();
  +                 if (resource != null)
  +                     {
  +                             return resource;
  +                 }
  +
  +            // Keep looping while the timeout hasn't expired (loop forever 
if there is
  +            // no timeout.
  +             } while ((timeout < 0) || (System.currentTimeMillis() < 
endTime));
  +
  +             return null;
  +     }
  +
  +    /** Releases a resource back to the pool of available resources
  +     * @param resource The resource to be returned to the pool
  +     */
  +     public void put(Poolable resource)
  +     {
  +             int pos = -1;
  +
  +             synchronized(this) {
  +            // Make sure the resource is in the used list
  +             pos = usedResources.indexOf(resource);
  +
  +            if( resource instanceof Recyclable )
  +            {
  +                ((Recyclable)resource).recycle();
  +            }
  +
  +            // If the resource was in the used list, remove it from the used 
list and
  +            // add it back to the free list
  +                     if (pos >= 0) {
  +                             usedResources.removeElementAt(pos);
  +                             availableResources.addElement(resource);
  +                     }
  +             }
  +
  +        // If we released a resource, wake up any threads that may be waiting
  +             if (pos >= 0)
  +             {
  +                     doWakeup();
  +             }
  +     }
  +
  +    /** Performs a notifyAll (which requires a synchronized method) */
  +     protected synchronized void doNotify()
  +     {
  +             try {
  +                     notifyAll();
  +             }
  +             catch (Exception ignore) {
  +             }
  +     }
  +
  +     protected void doWakeup()
  +     {
  +        // Wake up any threads waiting for the resource
  +             receivedWakeup = false;
  +             do {
  +                     try {
  +                             doNotify();
  +                     }
  +                     catch (Exception ignore) {
  +                     }
  +             }
  +        // Keep looping while there are threads waiting and none have 
received a wakeup
  +             while ((numThreadsWaiting > 0) && !receivedWakeup);
  +     }
   }
  
  
  

Reply via email to