5 Replies Latest reply on Aug 1, 2008 4:54 PM by genman

    Option to remove persistent data is a valid use case

    cacheuser

      A Eviction policy option to be able to remove persistent data is valid use case that the JBoss Cahe does not support right. For example, we are storing data that we get by making a webservice call to other vendor, we have contract with to be able to store the data for no longer than a certain number of days. The current LRUPolicy supports maxAge that can be used to get the data out of the memory and we use persistent (JBDCCacheLoader) store to the data, ones that data is persistent store we dont have a way to identify and get rid of the data after x number of days. It is easy for the Cache to clean up the data that it creates and I modified the LRUPolicy and LRUConfiguration as follows to. The modifications are in bold

      /*
       * JBoss, the OpenSource J2EE webOS
       *
       * Distributable under LGPL license.
       * See terms of license at gnu.org.
       */
      package org.jboss.cache.eviction;
      
      import org.jboss.cache.config.ConfigurationException;
      import org.jboss.cache.config.Dynamic;
      
      /**
       * Configuration implementation for {@link LRUPolicy}.
       * <p/>
       * If configured via XML, expects the following:
       * <p/>
       * <pre>
       * <region name="/maxAgeTest/">
       * <attribute name="maxNodes">10000</attribute>
       * <attribute name="timeToLiveSeconds">8</attribute>
       * <attribute name="maxAgeSeconds">10</attribute>
       * </region>
       * </pre>
       *
       * @author Daniel Huang (dhuang@jboss.org)
       * @version $Revision: 6252 $
       */
      public class LRUConfiguration extends EvictionPolicyConfigBase
      {
       /**
       * The serialVersionUID
       */
       private static final long serialVersionUID = -3426716488271559729L;
      
       @Dynamic
       @Deprecated
       private int timeToLiveSeconds;
       @Dynamic
       @Deprecated
       private int maxAgeSeconds;
      
      
       /** value expressed in millis*/
       @Dynamic
       private long timeToLive;
      
       /** value expressed in millis*/
       @Dynamic
       private long maxAge;
      
       /** if true, nodes that are past maxAge will be removed*/
       @Dynamic
       private boolean maxAgeRemove;
      
       public LRUConfiguration()
       {
       super();
       // Force config of ttls
       setTimeToLive(-1);
       }
      
       public LRUConfiguration(long timeToLive, long maxAge)
       {
       super();
       setTimeToLive(timeToLive);
       setMaxAge(maxAge);
       setMaxAgeRemove(false);
       }
      
       @Override
       protected void setEvictionPolicyClassName()
       {
       setEvictionPolicyClass(LRUPolicy.class.getName());
       }
      
       /** value expressed in millis*/
       public long getTimeToLive()
       {
       return timeToLive;
       }
      
       /** value expressed in millis*/
       public void setTimeToLive(long timeToLive)
       {
       testImmutability("timeToLive");
       this.timeToLive = timeToLive;
       this.timeToLiveSeconds = (int)(timeToLive/1000);
       }
      
       /** value expressed in millis*/
       public long getMaxAge()
       {
       return maxAge;
       }
      
       /** value expressed in millis*/
       public void setMaxAge(long maxAge)
       {
       testImmutability("maxAge");
       this.maxAge = maxAge;
       this.maxAgeSeconds = (int) (maxAge/1000);
       }
      
       public boolean isMaxAgeRemove()
       {
       return maxAgeRemove;
       }
      
       public void setMaxAgeRemove(boolean maxAgeRemove)
       {
       this.maxAgeRemove = maxAgeRemove;
       }
      
       /**
       * use {@link #getTimeToLive()}
       * @return
       */
       @Deprecated
       public int getTimeToLiveSeconds()
       {
       return timeToLiveSeconds;
       }
      
       /**
       * Use {@link #setTimeToLive(long)}
       */
       @Deprecated
       public void setTimeToLiveSeconds(int timeToLiveSeconds)
       {
       testImmutability("timeToLiveSeconds");
       this.timeToLiveSeconds = timeToLiveSeconds;
       timeToLive = timeToLiveSeconds * 1000;
       }
      
       /**
       * Use {@link #getMaxAge()}
       * @deprecated
       */
       @Deprecated
       public int getMaxAgeSeconds()
       {
       return maxAgeSeconds;
       }
      
       /**
       * Use {@link #getMaxAge()}
       * @param maxAgeSeconds
       */
       @Deprecated
       public void setMaxAgeSeconds(int maxAgeSeconds)
       {
       testImmutability("maxAgeSeconds");
       this.maxAgeSeconds = maxAgeSeconds;
       this.maxAge = maxAgeSeconds * 1000;
       }
      
       /**
       * Requires a positive timeToLive value or ConfigurationException
       * is thrown.
       */
       @Override
       public void validate() throws ConfigurationException
       {
       if (timeToLive < 0)
       {
       throw new ConfigurationException("timeToLive must be " +
       "configured to a value greater than or equal to 0 for " + getEvictionPolicyClass());
       }
       }
      
      
       public String toString()
       {
       return "LRUConfiguration{" +
       "timeToLiveSeconds=" + timeToLiveSeconds +
       ", timeToLive=" + timeToLive +
       ", maxAge=" + maxAge +
       '}';
       }
      
       public boolean equals(Object o)
       {
       if (this == o) return true;
       if (!(o instanceof LRUConfiguration)) return false;
       if (!super.equals(o)) return false;
      
       LRUConfiguration that = (LRUConfiguration) o;
      
       if (maxAge != that.maxAge) return false;
       if (maxAgeSeconds != that.maxAgeSeconds) return false;
       if (timeToLive != that.timeToLive) return false;
       if (timeToLiveSeconds != that.timeToLiveSeconds) return false;
      
       return true;
       }
      
       public int hashCode()
       {
       int result = super.hashCode();
       result = 31 * result + timeToLiveSeconds;
       result = 31 * result + maxAgeSeconds;
       result = 31 * result + (int) (timeToLive ^ (timeToLive >>> 32));
       result = 31 * result + (int) (maxAge ^ (maxAge >>> 32));
       return result;
       }
      
       @Override
       public void reset()
       {
       super.reset();
       setTimeToLive(-1);
       }
      
       @Override
       public LRUConfiguration clone() throws CloneNotSupportedException
       {
       return (LRUConfiguration) super.clone();
       }
      
      }
      


      /*
       * JBoss, the OpenSource J2EE webOS
       *
       * Distributable under LGPL license.
       * See terms of license at gnu.org.
       * Created on March 25 2003
       */
      package org.jboss.cache.eviction;
      
      import org.jboss.cache.CacheSPI;
      import org.jboss.cache.Fqn;
      import org.jboss.cache.RegionManager;
      
      /**
       * Provider to provide eviction policy. This one is based on LRU algorithm that a user
       * can specify either maximum number of nodes or the idle time of a node to be evicted.
       *
       * @author Ben Wang 02-2004
       * @author Daniel Huang - dhuang@jboss.org
       * @version $Revision: 5730 $
       */
      public class LRUPolicy extends BaseEvictionPolicy
      {
       protected RegionManager regionManager_;
      
       protected EvictionAlgorithm algorithm;
      
       public LRUPolicy()
       {
       super();
       algorithm = new LRUAlgorithm();
       }
      
       public EvictionAlgorithm getEvictionAlgorithm()
       {
       return algorithm;
       }
      
       public void evict(Fqn fqn) throws Exception
       {
       if(((LRUAlgorithm)algorithm).getConfiguration().isMaxAgeRemove())
       cache_.removeNode(fqn);
       else
       cache_.evict(fqn, false);
       }
      
       public Class<LRUConfiguration> getEvictionConfigurationClass()
       {
       return LRUConfiguration.class;
       }
      
       @Override
       public void setCache(CacheSPI cache)
       {
       super.setCache(cache);
       regionManager_ = cache_.getRegionManager();
       }
      }
      
      


      <?xml version="1.0" encoding="UTF-8"?>
      
      <!-- ===================================================================== -->
      <!-- -->
      <!-- Sample JBoss Cache Service Configuration -->
      <!-- -->
      <!-- ===================================================================== -->
      
      <server>
      
       <!-- ==================================================================== -->
       <!-- Defines JBoss Cache configuration -->
       <!-- ==================================================================== -->
      
      
       <mbean code="org.jboss.cache.jmx.CacheJmxWrapper"
       name="jboss.mycache:service=Cache">
      
      
      
       <attribute name="IsolationLevel">REPEATABLE_READ</attribute>
      
       <!-- Lock parent before doing node additions/removes -->
       <attribute name="LockParentForChildInsertRemove">true</attribute>
      
       <!-- Valid modes are LOCAL (default)
       REPL_ASYNC
       REPL_SYNC
       INVALIDATION_ASYNC
       INVALIDATION_SYNC -->
       <attribute name="CacheMode">LOCAL</attribute>
      
       <!-- Name of cluster. Needs to be the same for all JBoss Cache nodes in a
       cluster in order to find each other.
       -->
       <attribute name="ClusterName">JBossCache-Cluster</attribute>
      
       <!-- JGroups protocol stack properties.
       ClusterConfig isn't used if the multiplexer is enabled above.
       -->
       <attribute name="ClusterConfig">
       <config>
       <!-- UDP: if you have a multihomed machine, set the bind_addr
       attribute to the appropriate NIC IP address -->
       <!-- UDP: On Windows machines, because of the media sense feature
       being broken with multicast (even after disabling media sense)
       set the loopback attribute to true -->
       <UDP mcast_addr="228.1.2.3" mcast_port="48866"
       ip_ttl="64" ip_mcast="true"
       mcast_send_buf_size="150000" mcast_recv_buf_size="80000"
       ucast_send_buf_size="150000" ucast_recv_buf_size="80000"
       loopback="false"/>
       <PING timeout="2000" num_initial_members="3"/>
       <MERGE2 min_interval="10000" max_interval="20000"/>
       <FD shun="true"/>
       <FD_SOCK/>
       <VERIFY_SUSPECT timeout="1500"/>
       <pbcast.NAKACK gc_lag="50" retransmit_timeout="600,1200,2400,4800" />
       <UNICAST timeout="600,1200,2400,4800" />
       <pbcast.STABLE desired_avg_gossip="400000"/>
       <FC max_credits="2000000" min_threshold="0.10"/>
       <FRAG2 frag_size="8192"/>
       <pbcast.GMS join_timeout="5000" shun="true" print_local_addr="true"/>
       <pbcast.STATE_TRANSFER/>
       </config>
       </attribute>
      
       <attribute name="StateRetrievalTimeout">20000</attribute>
       <attribute name="SyncReplTimeout">20000</attribute>
      
       <!-- Max number of milliseconds to wait for a lock acquisition -->
       <attribute name="LockAcquisitionTimeout">15000</attribute>
      
       <!-- Shutdown hook behavior. Valid choices are: DEFAULT, REGISTER and DONT_REGISTER.
       If this element is omitted, DEFAULT is used. -->
       <attribute name="ShutdownHookBehavior">DEFAULT</attribute>
      
       <!-- Enables or disables lazy unmarshalling. If omitted, the default is that lazy unmarshalling is enabled. -->
       <attribute name="UseLazyDeserialization">true</attribute>
      
       <!-- Specific eviction policy configurations. This is LRU -->
       <attribute name="EvictionPolicyConfig">
       <config>
       <attribute name="wakeUpIntervalSeconds">60</attribute>
       <!-- This defaults to 200000 if not specified -->
       <attribute name="eventQueueSize">200000</attribute>
      
       <attribute name="policyClass">org.jboss.cache.eviction.LRUPolicy</attribute>
      
      
       <!-- Cache wide default -->
       <region name="/">
       <attribute name="maxNodes">5</attribute>
       <attribute name="maxAgeSeconds">6000</attribute>
       <attribute name="timeToLiveSeconds">6000</attribute>
       </region>
       <region name="/vendorcache">
       <attribute name="maxNodes">5</attribute>
       <attribute name="maxAgeSeconds">60</attribute>
       <attribute name="timeToLiveSeconds">60</attribute>
       <attribute name="maxAgeRemove">true</attribute>
       </region>
       </config>
       </attribute>
      
       <attribute name="CacheLoaderConfig">
       <config>
       <!-- if passivation is true, only the first cache loader is used; the rest are ignored -->
       <passivation>false</passivation>
       <preload>/vendorcache</preload>
       <shared>true</shared>
      
       <cacheloader>
       <class>org.jboss.cache.loader.JDBCCacheLoader</class>
      
       <properties>
       cache.jdbc.table.name=jbosscachenew
       cache.jdbc.table.create=true
       cache.jdbc.table.drop=false
       cache.jdbc.table.select=true
       cache.jdbc.table.primarykey=jbosscachenew_pk
       cache.jdbc.fqn.column=fqn
       cache.jdbc.fqn.type=varchar(255)
       cache.jdbc.node.column=node
       cache.jdbc.node.type=blob
       cache.jdbc.parent.column=parent
       cache.jdbc.driver=com.mysql.jdbc.Driver
       cache.jdbc.url=jdbc:mysql://server:3315/GIS_DEV
       cache.jdbc.user=gis
       cache.jdbc.password=tester
       cache.jdbc.sql-concat=concat(1,2)
       </properties>
      
       <async>false</async>
       <fetchPersistentState>true</fetchPersistentState>
      
       <ignoreModifications>false</ignoreModifications>
      
       <purgeOnStartup>false</purgeOnStartup>
       </cacheloader>
      
       </config>
       </attribute>
      
       </mbean>
      </server>
      


      The modified LRUPolicy works fine and removes the data when the maxAge of the nodes are reached. Can we have this feature in 3.0 please, if any coding/testing help is needed I can provide it. The fundamental reason to have this feature is as the Cache creates the data it should provide a way to clean it too, otherwise the Cache is not proving a full solution.