package com.tangosol.examples.coherence; import com.tangosol.net.cache.LocalCache; import com.tangosol.net.cache.CacheLoader; import com.tangosol.run.xml.XmlConfigurable; import com.tangosol.run.xml.XmlElement; import com.tangosol.util.Base; import com.tangosol.util.Cache; import com.tangosol.util.SafeHashMap; import java.util.Iterator; import java.util.Map; import java.util.HashMap; /** * A backing map that supports custom expiry based on the type of the object * placed into the cache. * * @author cp 2003-11-25 */ public class AutoExpiryLocalCache extends LocalCache implements XmlConfigurable { // ----- constructors --------------------------------------------------- /** * Construct the cache manager. */ public AutoExpiryLocalCache() { super(); } /** * Construct the cache manager. * * @param cUnits the number of units that the cache manager will * cache before pruning the cache */ public AutoExpiryLocalCache(int cUnits) { super(cUnits); } /** * Construct the cache manager. * * @param cUnits the number of units that the cache manager will * cache before pruning the cache * @param cExpiryMillis the number of milliseconds that each cache entry * lives before being automatically expired */ public AutoExpiryLocalCache(int cUnits, int cExpiryMillis) { super(cUnits, cExpiryMillis); } /** * Construct the cache manager. * * @param cUnits the number of units that the cache manager will * cache before pruning the cache * @param cExpiryMillis the number of milliseconds that each cache entry * lives before being automatically expired * @param loader the CacheLoader or CacheStore to use */ public AutoExpiryLocalCache(int cUnits, int cExpiryMillis, CacheLoader loader) { super(cUnits, cExpiryMillis, loader); } // ----- XmlConfigurable interface -------------------------------------- /** * Determine the current configuration of the object. * * @return the XML configuration or null */ public XmlElement getConfig() { return m_xmlConfig; } /** * Specify the configuration for the object. * * @param xml the XML configuration for the object * * @exception IllegalStateException if the object is not in a state that * allows the configuration to be set; for example, if the * object has already been configured and cannot be reconfigured */ public void setConfig(XmlElement xml) { Base.azzert(xml != null); Base.azzert(m_xmlConfig == null); Map map = null; for (Iterator iter = xml.getElementList().iterator(); iter.hasNext(); ) { XmlElement xmlParam = (XmlElement) iter.next(); String sClass = xmlParam.getName(); int cSeconds = xmlParam.getInt(); Class clz; try { clz = Class.forName(sClass); } catch (Throwable e) { Base.err("AutoExpiryLocalCache.setConfig: Unable to look up class: \"" + sClass + "\""); continue; } if (map == null) { map = new HashMap(); } map.put(clz, new Integer(cSeconds * 1000)); } if (map != null) { m_mapClassExpiry = map; } m_xmlConfig = xml; } // ----- inner class: Entry --------------------------------------------- /** * Factory method. This method exists to allow the Cache class to be * easily inherited from by allowing the Entry class to be easily * sub-classed. * * @param oKey the key with which to associate the cache value * @param oValue the value to cache * * @return an instance of Entry that holds the passed cache value */ protected SafeHashMap.Entry instantiateEntry() { return new Entry(); } /** * A holder for a cached value. * * @author cp 2001.04.19 */ public class Entry extends Cache.Entry { // ----- constructors ------------------------------------------- /** * Construct the cacheable entry that holds the cached value. */ public Entry() { super(); } // ----- Cache Entry methods ------------------------------------ /** * Reschedule the cache entry expiration. */ protected void scheduleExpiry() { long dtExpiry = 0L; // get default expiration for all cache entries int cDelay = AutoExpiryLocalCache.this.getExpiryDelay(); Object oValue = getValue(); // calculate expiry delay based on object type if (oValue != null) { Map map = m_mapClassExpiry; if (map != null) { Class clzValue = oValue.getClass(); for (Iterator iter = map.entrySet().iterator(); iter.hasNext(); ) { Map.Entry entry = (Map.Entry) iter.next(); Class clz = (Class) entry.getKey(); if (clz.isAssignableFrom(clzValue)) { cDelay = ((Integer) entry.getValue()).intValue(); break; } } } } // convert the expiration delay to an absolute time if (cDelay > 0) { dtExpiry = System.currentTimeMillis() + cDelay; } setExpiryMillis(dtExpiry); } } // ----- data members --------------------------------------------------- /** * XML configuration for the cache. */ private XmlElement m_xmlConfig; /** * Map from class object to expiration delay for that type (stored as an * Integer). */ private Map m_mapClassExpiry; }