Skip Headers
Oracle® Coherence Developer's Guide
Release 3.7.1

Part Number E22837-01
Go to Documentation Home
Home
Go to Book List
Book List
Go to Table of Contents
Contents
Go to Feedback page
Contact Us

Go to previous page
Previous
Go to next page
Next
View PDF

31 Specifying a Custom Eviction Policy

The LocalCache class is used for size-limited caches. It is used both for caching on-heap objects (as in a local cache or the front portion of a near cache) and as the backing map for a partitioned cache. Applications can provide custom eviction policies for use with a LocalCache.

Note that Coherence's default eviction policy is very effective for most workloads; the majority of applications do not have to provide a custom policy. Generally, it is best to restrict the use of eviction policies to scenarios where the evicted data is present in a backing system (that is, the back portion of a near cache or a database). Eviction should be treated as a physical operation (freeing memory) and not a logical operation (deleting an entity).

Example 31-1 shows the implementation of a simple custom eviction policy:

Example 31-1 Implementing a Custom Eviction Policy

package com.tangosol.examples.eviction;
 
import com.tangosol.net.cache.AbstractEvictionPolicy;
import com.tangosol.net.cache.ConfigurableCacheMap;
import com.tangosol.net.cache.LocalCache;
import com.tangosol.net.BackingMapManagerContext;
import com.tangosol.util.ConverterCollections;
import java.util.Iterator;
import java.util.Map;

/**
 * Custom eviction policy that evicts items randomly (or more specifically,
 * based on the natural order provided by the map's iterator.)
 * This example may be used in cases where fast eviction is required
 * with as little processing as possible.
 */
public class SimpleEvictionPolicy
        extends AbstractEvictionPolicy
    {
    /**
     * Default constructor; typically used with local caches or the front
     * parts of near caches.
     */
    public SimpleEvictionPolicy()
        {
        }
 
    /**
     * Constructor that accepts {@link BackingMapManagerContext}; should
     * be used with partitioned cache backing maps.
     *
     * @param ctx  backing map context
     */
    public SimpleEvictionPolicy(BackingMapManagerContext ctx)
        {
        m_ctx = ctx;
        }
 
    /**
     * {@inheritDoc}
     */
    public void entryUpdated(ConfigurableCacheMap.Entry entry)
        {
        }
 
    /**
     * {@inheritDoc}
     */
    public void entryTouched(ConfigurableCacheMap.Entry entry)
        {
        }
 
    /**
     * {@inheritDoc}
     */
    public void requestEviction(int cMaximum)
        {
        ConfigurableCacheMap cache = getCache();
        Iterator iter  = cache.entrySet().iterator();
 
        for (int i = 0, c = cache.getUnits() - cMaximum; i < c && iter.hasNext();
           i++)
            {
            ConfigurableCacheMap.Entry entry  = (ConfigurableCacheMap.Entry)
               iter.next();
            StringBuffer               buffer = new StringBuffer();
 
            // If the contents of the entry (for example the key/value) need
            // to be examined, invoke convertEntry(entry) in case
            // the entry must be deserialized
            Map.Entry convertedEntry = convertEntry(entry);
            buffer.append("Entry: ").append(convertedEntry);
 
            // Here's how to get metadata about creation/last touched
            // timestamps for entries.  This information might be used
            // in determining what gets evicted.
            if (entry instanceof LocalCache.Entry)
                {
                buffer.append(", create millis=");
                buffer.append(((LocalCache.Entry) entry).getCreatedMillis());
                }
            buffer.append(", last touch millis=");
            buffer.append(entry.getLastTouchMillis());
 
            // This output is for illustrative purposes; this may generate
            // excessive output in a production system
            System.out.println(buffer);
 
            // iterate and remove items
            // from the cache until below the maximum.  Note that
            // the non converted entry key is passed to the evict method
            cache.evict(entry.getKey());
            }
        }
 
    /**
     * If a {@link BackingMapManagerContext} is configured, wrap the
     * Entry with {@link ConverterCollections.ConverterEntry} in order
     * to deserialize the entry.
     *
     * @see ConverterCollections.ConverterEntry
     * @see BackingMapManagerContext
     *
     * @param entry  entry to convert if necessary
     *
     * @return an entry that deserializes its key and value if necessary
     */
    protected Map.Entry convertEntry(Map.Entry entry)
        {
        BackingMapManagerContext ctx = m_ctx;
        return ctx == null ? entry :
                new ConverterCollections.ConverterEntry(entry,
                        ctx.getKeyFromInternalConverter(),
                        ctx.getValueFromInternalConverter(),
                        ctx.getValueToInternalConverter());
        }
 
    private BackingMapManagerContext m_ctx;
    }

Example 31-2 illustrates a Coherence cache configuration file (coherence-cache-config.xml) with an eviction policy:

Example 31-2 Custom Eviction Policy in a coherence-cache-config.xml File

<?xml version="1.0"?>
 
<cache-config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
   xmlns="http://xmlns.oracle.com/coherence/coherence-cache-config"
   xsi:schemaLocation="http://xmlns.oracle.com/coherence/coherence-cache-config
   coherence-cache-config.xsd">
   <caching-scheme-mapping>
      <cache-mapping>
         <cache-name>*</cache-name>
         <scheme-name>example-near</scheme-name>
      </cache-mapping>
   </caching-scheme-mapping>
 
   <caching-schemes>
      <near-scheme>
         <scheme-name>example-near</scheme-name>
         <front-scheme>
            <local-scheme>
               <eviction-policy>
                  <class-scheme>
                     <class-name>
                        com.tangosol.examples.eviction.SimpleEvictionPolicy
                     </class-name>
                  </class-scheme>
               </eviction-policy>
               <high-units>1000</high-units>
            </local-scheme>
         </front-scheme>
         <back-scheme>
            <distributed-scheme>
               <scheme-ref>example-distributed</scheme-ref>
            </distributed-scheme>
         </back-scheme>
         <invalidation-strategy>all</invalidation-strategy>
         <autostart>true</autostart>
      </near-scheme>
 
      <distributed-scheme>
         <scheme-name>example-distributed</scheme-name>
         <service-name>DistributedCache</service-name>
         <backing-map-scheme>
            <local-scheme>
               <eviction-policy>
                  <class-scheme>
                     <class-name>
                        com.tangosol.examples.eviction.SimpleEvictionPolicy
                     </class-name>
                     <init-params>
              <!--
               Passing the BackingMapManagerContext to the eviction policy;
               this is required for deserializing entries
               -->
                        <init-param>
                           <param-type>
                           com.tangosol.net.BackingMapManagerContext</param-type>
                           <param-value>{manager-context}</param-value>
                        </init-param>
                     </init-params>
                  </class-scheme>
               </eviction-policy>
               <high-units>20m</high-units>
               <unit-calculator>binary</unit-calculator>
            </local-scheme>
         </backing-map-scheme>
         <autostart>true</autostart>
      </distributed-scheme>
   </caching-schemes>
</cache-config>