[jboss-cvs] JBossCache/src/org/jboss/cache/eviction ...

Elias Ross genman at noderunner.net
Sun Nov 26 23:51:24 EST 2006


  User: genman  
  Date: 06/11/26 23:51:24

  Added:       src/org/jboss/cache/eviction    ExpirationAlgorithm.java
                        ExpirationConfiguration.java ExpirationPolicy.java
  Log:
  JBCACHE-880 add per node expiration policy
  
  Revision  Changes    Path
  1.1      date: 2006/11/27 04:51:24;  author: genman;  state: Exp;JBossCache/src/org/jboss/cache/eviction/ExpirationAlgorithm.java
  
  Index: ExpirationAlgorithm.java
  ===================================================================
  package org.jboss.cache.eviction;
  
  import java.util.Comparator;
  import java.util.HashMap;
  import java.util.Iterator;
  import java.util.Map;
  import java.util.PriorityQueue;
  import java.util.Queue;
  import java.util.SortedMap;
  import java.util.SortedSet;
  import java.util.TreeMap;
  import java.util.TreeSet;
  
  import org.apache.commons.logging.Log;
  import org.apache.commons.logging.LogFactory;
  import org.jboss.cache.Fqn;
  import org.jboss.cache.Region;
  import org.jboss.cache.lock.TimeoutException;
  import org.jboss.cache.optimistic.FqnComparator;
  import org.jgroups.ExitEvent;
  
  /**
   * Eviction algorithm that uses a key in the Node data that indicates the time the node should
   * be evicted.
   * This algorithm also considers {@link ExpirationConfiguration#getMaxNodes()}, and 
   * will remove the most soon to expire entires first.
   * <p/>
   * Note that if the expiration key is absent, the node will not be evicted.
   */
  public class ExpirationAlgorithm extends BaseEvictionAlgorithm
  {
  
     private static final Log log = LogFactory.getLog(ExpirationAlgorithm.class);
  
     private ExpirationConfiguration config;
  
     private ExpirationPolicy policy;
  
     private SortedSet<ExpirationEntry> set;
  
     /**
      * Constructs a new algorithm with a policy.
      */
     public ExpirationAlgorithm(ExpirationPolicy policy)
     {
        this.policy = policy;
        this.set = new TreeSet<ExpirationEntry>();
     }
  
     private void addEvictionEntry(EvictedEventNode node)
     {
        Fqn fqn = node.getFqn();
        addEvictionEntry(fqn);
     }
     
     private void addEvictionEntry(Fqn fqn)
     {
        Long l = getExpiration(fqn);
        if (l == null) {
           if (config.getWarnNoExpirationKey())
              log.warn("No expiration key '" + config.getExpirationKeyName() + 
                    "' for Node: " + fqn);
           else if (log.isDebugEnabled())
              log.debug("No expiration key for Node: " + fqn);
           return;
        }
        ExpirationEntry ee = new ExpirationEntry(fqn, l.longValue());
        set.add(ee);
     }
  
     private Long getExpiration(Fqn fqn)
     {
        Long l = (Long) policy.getCacheData(fqn, config.getExpirationKeyName());
        if (l == null)
           return null;
        return l;
     }
  
     @Override
     protected void processQueues(Region region) throws EvictionException
     {
        EvictedEventNode node;
        int count = 0;
        while ((node = region.takeLastEventNode()) != null)
        {
           if (log.isTraceEnabled())
           {
              log.trace("process " + node);
           }
           count++;
           switch (node.getEventType())
           {
              case ADD_NODE_EVENT :
              case ADD_ELEMENT_EVENT :
                 addEvictionEntry(node);
                 break;
              case REMOVE_ELEMENT_EVENT :
              case REMOVE_NODE_EVENT :
                 removeEvictionEntry(node);
                 break;
              case VISIT_NODE_EVENT :
              case MARK_IN_USE_EVENT :
              case UNMARK_USE_EVENT :
                 // TODO
                 break;
              default :
                 throw new RuntimeException("Illegal Eviction Event type " + node.getEventType());
           }
        }
  
        if (log.isTraceEnabled())
        {
           log.trace("processed " + count + " node events in region: " + region.getFqn());
        }
     }
  
     @Override
     protected void prune() throws EvictionException
     {
        if (set.isEmpty())
           return;
        long now = System.currentTimeMillis();
        int max = config.getMaxNodes();
        for (Iterator<ExpirationEntry> i = set.iterator(); i.hasNext();)
        {
           ExpirationEntry ee = i.next();
           if (ee.getExpiration() < now || (max != 0 && set.size() > max))
           {
              i.remove();
              evictCacheNode(ee.getFqn());
           }
           else
           {
              break;
           }
        }
     }
  
     private void removeEvictionEntry(EvictedEventNode node)
     {
        Fqn fqn = node.getFqn();
        if (getExpiration(fqn) == null)
           set.remove(new ExpirationEntry(fqn));
     }
  
     @Override
     public void resetEvictionQueue(Region region)
     {
        for (ExpirationEntry ee: set)
        {
           addEvictionEntry(ee.getFqn());
        }
     }
  
     @Override
     protected EvictionQueue setupEvictionQueue(Region region) throws EvictionException
     {
        this.region = region;
        this.config = (ExpirationConfiguration) region.getEvictionPolicyConfig();
        return new DummyEvictionQueue();
     }
  
     @Override
     protected boolean shouldEvictNode(NodeEntry ne)
     {
        throw new UnsupportedOperationException();
     }
     
     /**
      * Ordered list of FQN, with the expiration taken from the Map at the time
      * of processing.
      */
     static class ExpirationEntry implements Comparable<ExpirationEntry>
     {
  
        private long expiration;
  
        private Fqn fqn;
  
        public ExpirationEntry(Fqn fqn)
        {
           this.fqn = fqn;
        }
  
        public ExpirationEntry(Fqn fqn, long expiration)
        {
           this.fqn = fqn;
           this.expiration = expiration;
        }
  
        /**
         * Returns true if the FQN are the same, else compares expiration, then FQN order.
         */
        public int compareTo(ExpirationEntry ee)
        {
           if (fqn.equals(ee.fqn))
              return 0;
           long n = expiration - ee.expiration;
           if (n < 0)
              return -1;
           if (n > 0)
              return 1;
           return FqnComparator.INSTANCE.compare(fqn, ee.fqn);
        }
  
        /**
         * @return the expiration
         */
        public long getExpiration()
        {
           return expiration;
        }
  
        /**
         * @return the fqn
         */
        public Fqn getFqn()
        {
           return fqn;
        }
  
        public boolean equals(ExpirationEntry ee)
        {
           return fqn.equals(ee.fqn);
        }
  
        public int hashCode()
        {
           return fqn.hashCode();
        }
        
        public String toString()
        {
           return "EE fqn=" + fqn;
        }
     }
     
     class DummyEvictionQueue implements EvictionQueue {
  
        public void addNodeEntry(NodeEntry entry)
        {
           throw new UnsupportedOperationException();
        }
  
        public void clear()
        {
           set.clear();
        }
  
        public boolean containsNodeEntry(NodeEntry entry)
        {
           return false;
        }
  
        public NodeEntry getFirstNodeEntry()
        {
           return null;
        }
  
        public NodeEntry getNodeEntry(Fqn fqn)
        {
           return null;
        }
  
        public NodeEntry getNodeEntry(String fqn)
        {
           return null;
        }
  
        public int getNumberOfElements()
        {
           return set.size();
        }
  
        public int getNumberOfNodes()
        {
           return set.size();
        }
  
        public Iterator iterate()
        {
           return null;
        }
  
        public void modifyElementCount(int difference)
        {
        }
  
        public void removeNodeEntry(NodeEntry entry)
        {
           throw new UnsupportedOperationException();
        }
        
     }
  
  }
  
  
  
  1.1      date: 2006/11/27 04:51:24;  author: genman;  state: Exp;JBossCache/src/org/jboss/cache/eviction/ExpirationConfiguration.java
  
  Index: ExpirationConfiguration.java
  ===================================================================
  package org.jboss.cache.eviction;
  
  import org.jboss.cache.config.Dynamic;
  
  /**
   * Configuration for indicating the Node key for setting a specific eviction time.
   */
  public class ExpirationConfiguration extends EvictionPolicyConfigBase
  {
  
     /**
      * Default key name for indicating expiration time. 
      */
     public static final String DEFAULT_EXPIRATION_KEY = "expiration";
  
     /**
      * Node key name used to indicate the expiration of a node. 
      */
     @Dynamic
     private String expirationKeyName = DEFAULT_EXPIRATION_KEY;
     
     @Dynamic
     private boolean warnNoExpirationKey = true;
  
     public ExpirationConfiguration()
     {
        setEvictionPolicyClassName();
     }
  
     @Override
     protected void setEvictionPolicyClassName()
     {
        setEvictionPolicyClass(ExpirationPolicy.class.getName());
     }
  
     /**
      * Returns the expirationKeyName.
      * This key should point to a java.lang.Long value in the Node data.
      */
     public String getExpirationKeyName()
     {
        return expirationKeyName;
     }
  
     /**
      * Sets the expirationKeyName.
      */
     public void setExpirationKeyName(String expirationKeyName)
     {
        this.expirationKeyName = expirationKeyName;
     }
  
     /**
      * Returns true if the algorithm should warn if a expiration key is missing for a node.
      */
     public boolean getWarnNoExpirationKey()
     {
        return warnNoExpirationKey;
     }
  
     /**
      * Sets if the algorithm should warn if a expiration key is missing for a node.
      */
     public void setWarnNoExpirationKey(boolean warnNoExpirationKey)
     {
        this.warnNoExpirationKey = warnNoExpirationKey;
     }
  
  }
  
  
  
  1.1      date: 2006/11/27 04:51:24;  author: genman;  state: Exp;JBossCache/src/org/jboss/cache/eviction/ExpirationPolicy.java
  
  Index: ExpirationPolicy.java
  ===================================================================
  package org.jboss.cache.eviction;
  
  /**
   * Returns the {@link ExpirationAlgorithm} as the policy's algorithm.
   * @author rosse
   */
  public class ExpirationPolicy extends BaseEvictionPolicy
  {
     
     private EvictionAlgorithm algorithm;
     
     public ExpirationPolicy() {
        algorithm = new ExpirationAlgorithm(this);
     }
  
     public EvictionAlgorithm getEvictionAlgorithm()
     {
        return algorithm;
     }
  
     public Class getEvictionConfigurationClass()
     {
        return ExpirationConfiguration.class;
     }
  
  }
  
  
  



More information about the jboss-cvs-commits mailing list