Skip Headers
Oracle® Coherence Developer's Guide
Release 3.6.1

Part Number E15723-03
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

28 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 will not need 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 28-1 shows the implementation of a simple custom eviction policy:

Example 28-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; should be 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 (i.e. the key/value) need
            // to be examined, invoke convertEntry(entry) in case
            // the entry needs to 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);
 
            // In this example, we're simply iterating and removing items
            // from the cache until we are 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 will deserialize 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 28-2 illustrates a Coherence cache configuration file (coherence-cache-config.xml) with an eviction policy:

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

<?xml version="1.0"?>
 
<!DOCTYPE cache-config SYSTEM "cache-config.dtd">
 
<cache-config>
  <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 will be 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>