User: simone  
  Date: 00/10/16 16:27:56

  Added:       src/main/org/jboss/ejb/plugins
                        LRUEnterpriseContextCachePolicy.java
  Log:
  Specific EnterpriseContext LRU cache implementation
  
  Revision  Changes    Path
  1.1                  
jboss/src/main/org/jboss/ejb/plugins/LRUEnterpriseContextCachePolicy.java
  
  Index: LRUEnterpriseContextCachePolicy.java
  ===================================================================
  /*
   * jBoss, the OpenSource EJB server
   *
   * Distributable under GPL license.
   * See terms of license at gnu.org.
   */
  package org.jboss.ejb.plugins;
  
  import java.util.HashMap;
  import org.jboss.util.LRUCachePolicy;
  import org.jboss.util.TimerTask;
  import org.jboss.ejb.DeploymentException;
  import org.jboss.ejb.EnterpriseContext;
  import org.jboss.metadata.XmlLoadable;
  import org.jboss.metadata.MetaData;
  import org.w3c.dom.Element;
  
  /**
   * Least Recently Used cache policy for EnterpriseContexts.
   *
   * @see EnterpriseInstanceCache
   * @author Simone Bordet ([EMAIL PROTECTED])
   * @version $Revision: 1.1 $
   */
  public class LRUEnterpriseContextCachePolicy extends LRUCachePolicy
        implements EnterpriseContextCachePolicy, XmlLoadable
  {
        // Constants -----------------------------------------------------
  
        // Attributes ----------------------------------------------------
        /* The EnterpriseInstanceCache that uses this cache policy */
        private EnterpriseInstanceCache m_cache;
        /* The period of the resizer's runs */
        private long m_resizerPeriod;
        /* The period of the overager's runs */
        private long m_overagerPeriod;
        /* The age after which a bean is automatically passivated */
        private long m_maxBeanAge;
        /* Enlarge cache capacity if there is a cache miss every or less this member's 
value */
        private long m_minPeriod;
        /* Shrink cache capacity if there is a cache miss every or more this member's 
value */
        private long m_maxPeriod;
        /* The resizer will always try to keep the cache capacity so 
         * that the cache is this member's value loaded of cached objects */
        private double m_factor;
        /* The overager timer task */
        private TimerTask m_overager;
        /* The resizer timer task */
        private TimerTask m_resizer;
  
  
        // Static --------------------------------------------------------
  
        // Constructors --------------------------------------------------
        /**
         * Creates a LRU cache policy object given the instance cache that use
         * this policy object. 
         */
        public LRUEnterpriseContextCachePolicy(EnterpriseInstanceCache eic) 
        {       
                if (eic == null) throw new IllegalArgumentException("Instance cache 
argument cannot be null");
                m_cache = eic;
                m_maxCapacity = m_cache.getMaxCapacity();
                m_minCapacity = m_cache.getMinCapacity();
        }
  
        // Public --------------------------------------------------------
  
        // Z implementation ----------------------------------------------
        public void start() throws Exception 
        {
                if (m_resizerPeriod > 0)
                {
                        m_resizer = new ResizerTask(m_resizerPeriod);
                        scheduler.schedule(m_resizer, (long)(Math.random() * 
m_resizerPeriod));
                }
                                
                if (m_overagerPeriod > 0) 
                {
                        m_overager = new OveragerTask(m_overagerPeriod);
                        scheduler.schedule(m_overager, (long)(Math.random() * 
m_overagerPeriod));
                }
        }
        
        public void stop() 
        {
                if (m_resizer != null) {m_resizer.cancel();}
                if (m_overager != null) {m_overager.cancel();}
                super.stop();
        }
        /**
         * Reads from the configuration the parameters for this cache policy, that are
         * all optionals.
         */
        public void importXml(Element element) throws DeploymentException
        {
                String op = 
MetaData.getElementContent(MetaData.getOptionalChild(element, "OveragerPeriod"));
                String rp = 
MetaData.getElementContent(MetaData.getOptionalChild(element, "ResizerPeriod"));
                String ma = 
MetaData.getElementContent(MetaData.getOptionalChild(element, "MaxBeanAge"));
                String map = 
MetaData.getElementContent(MetaData.getOptionalChild(element, "MaxCacheMissPeriod"));
                String mip = 
MetaData.getElementContent(MetaData.getOptionalChild(element, "MinCacheMissPeriod"));
                String fa = 
MetaData.getElementContent(MetaData.getOptionalChild(element, "CacheLoadFactor"));
                try 
                {
                        if (op != null)
                        {
                                int p = Integer.parseInt(op);
                                if (p <= 0) {throw new DeploymentException("Overager 
period can't be <= 0");}
                                m_overagerPeriod = p * 1000;
                        }
                        if (rp != null)                         
                        {
                                int p = Integer.parseInt(rp);
                                if (p <= 0) {throw new DeploymentException("Resizer 
period can't be <= 0");}
                                m_resizerPeriod = p * 1000;
                        }
                        if (ma != null)
                        {
                                int a = Integer.parseInt(ma);
                                if (a <= 0) {throw new DeploymentException("Max bean 
age can't be <= 0");}
                                m_maxBeanAge = a * 1000;
                        }
                        if (map != null)
                        {
                                int p = Integer.parseInt(map);
                                if (p <= 0) {throw new DeploymentException("Max cache 
miss period can't be <= 0");}
                                m_maxPeriod = p * 1000;
                        }
                        if (mip != null)
                        {
                                int p = Integer.parseInt(mip);
                                if (p <= 0) {throw new DeploymentException("Min cache 
miss period can't be <= 0");}
                                m_minPeriod = p * 1000;
                        }
                        if (fa != null)
                        {
                                double f = Double.parseDouble(fa);
                                if (f <= 0.0) {throw new DeploymentException("Cache 
load factor can't be <= 0");}
                                m_factor = f;
                        }
                }
                catch (NumberFormatException x) 
                {
                        throw new DeploymentException("Can't parse policy 
configuration", x);
                }
        }
  
        // Y overrides ---------------------------------------------------
  
        // Package protected ---------------------------------------------
  
        // Protected -----------------------------------------------------
        protected LRUList createList() {return new ContextLRUList();}
        protected LRUCacheEntry createCacheEntry(Object key, Object value) 
        {
                return new ContextLRUEntry(key, value);
        }
        protected void ageOut(LRUCacheEntry entry) 
        {
                if (entry == null) {throw new IllegalArgumentException("Cannot remove 
a null cache entry");}
                m_cache.release((EnterpriseContext)entry.m_object);
        }
        protected void cacheMiss() 
        {
                ContextLRUList list = getList();
                synchronized (list) 
                {
                        ++list.m_cacheMiss;
                }
        }
  
        // Private -------------------------------------------------------
        private ContextLRUList getList() {return (ContextLRUList)m_list;}
  
        // Inner classes -------------------------------------------------
        /**
         * This TimerTask resizes the cache capacity using the cache miss frequency
         * algorithm, that is the more cache misses we have, the more the cache size
         * is enlarged, and viceversa. <p>
         * Of course, the maximum and minimum capacity are the bounds that this
         * resizer never passes.
         */
        protected class ResizerTask extends TimerTask
        {
                protected ResizerTask(long resizerPeriod) 
                {
                        super(resizerPeriod);
                }
                public void execute() 
                {
                        // For now implemented as a Cache Miss Frequency algorithm
                        // Sync the list, since it is accessed also by another thread
                        ContextLRUList list = getList();
                        synchronized (list) 
                        {
                                int period = list.m_cacheMiss == 0 ? Integer.MAX_VALUE 
: (int)(getPeriod() / list.m_cacheMiss);
                                int cap = list.m_capacity;
                                if (period <= m_minPeriod && cap < list.m_maxCapacity) 
                                {
                                        // Enlarge cache capacity: if period == 
m_minPeriod then
                                        // the capacity is increased of the 
(1-m_factor)*100 %.
                                        double factor = 1.0 + ((double)m_minPeriod / 
period) * (1.0 - m_factor);
                                        int newCap = (int)(cap * factor);
                                        list.m_capacity = newCap < list.m_maxCapacity 
? newCap : list.m_maxCapacity;
                                        log.log("Resized cache for bean " + 
m_cache.getContainer().getBeanMetaData().getEjbName() + ": old size = " + cap + ", new 
size = " + list.m_capacity);
                                }
                                else if (period >= m_maxPeriod && 
                                                 cap > list.m_minCapacity && 
                                                 list.m_count < (cap * m_factor))
                                {
                                        // Shrink cache capacity
                                        int newCap = (int)(list.m_count / m_factor);
                                        list.m_capacity = newCap > list.m_minCapacity 
? newCap : list.m_minCapacity;
                                        log.log("Resized cache for bean " + 
m_cache.getContainer().getBeanMetaData().getEjbName() + ": old size = " + cap + ", new 
size = " + list.m_capacity);
                                }
                                list.m_cacheMiss = 0;
                        }
                }
        }
        /**
         * This TimerTask passivates cached beans that have not been called for a 
while.
         */
        protected class OveragerTask extends TimerTask
        {
                protected OveragerTask(long period) 
                {
                        super(period);
                }
                public void execute() 
                {
                        ContextLRUEntry entry = null;
                        long now = System.currentTimeMillis();
                        ContextLRUList list = getList();
                        synchronized (list) 
                        {
                                while ((entry = (ContextLRUEntry)list.m_tail) != null)
                                {
                                        if (now - entry.m_time >= m_maxBeanAge)
                                        {
                                                ageOut(entry);
                                                log.log("Passivated overaged bean " + 
m_cache.getContainer().getBeanMetaData().getEjbName() + " with id = " + entry.m_key);
                                        }
                                        else {break;}
                                }
                        }
                }
        }
        /* Dummy subclass to give visibility to the inner classes */
        protected class ContextLRUList extends LRUList {}
        /* Dummy subclass to give visibility to the inner classes */
        protected class ContextLRUEntry extends LRUCacheEntry 
        {
                protected ContextLRUEntry(Object key, Object value) {super(key, 
value);}
        }
  }
  
  
  

Reply via email to