001: /*
002: * All content copyright (c) 2003-2007 Terracotta, Inc., except as may otherwise be noted in a separate copyright
003: * notice. All rights reserved.
004: */
005: package net.sf.ehcache.store;
006:
007: import net.sf.ehcache.CacheException;
008: import net.sf.ehcache.Ehcache;
009: import net.sf.ehcache.Element;
010:
011: import org.apache.commons.logging.Log;
012: import org.apache.commons.logging.LogFactory;
013:
014: import com.tcclient.ehcache.TimeExpiryMap;
015:
016: import java.util.Map;
017:
018: /**
019: * This is an Terracotta implementation of a time based MemoryStore which use the time based eviction policy.
020: *
021: */
022: public class TimeExpiryMemoryStore extends MemoryStore {
023: private static final Log LOG = LogFactory
024: .getLog(TimeExpiryMemoryStore.class.getName());
025:
026: public TimeExpiryMemoryStore(Ehcache cache, Store diskStore) {
027: super (cache, (DiskStore) diskStore);
028:
029: try {
030: map = loadMapInstance(cache.getName());
031: ((SpoolingTimeExpiryMap) map).initialize();
032: } catch (CacheException e) {
033: LOG
034: .error(
035: cache.getName()
036: + "Cache: Cannot start TimeExpiryMemoryStore. Initial cause was "
037: + e.getMessage(), e);
038: }
039: }
040:
041: private long getThreadIntervalSeconds(long threadIntervalSec,
042: long timeToIdleSec, long timeToLiveSec) {
043: if (timeToIdleSec <= 0) {
044: return timeToLiveSec;
045: } else if (timeToLiveSec <= 0) {
046: return timeToIdleSec;
047: } else if (timeToLiveSec <= timeToIdleSec) {
048: return timeToLiveSec;
049: } else if (timeToIdleSec < threadIntervalSec) {
050: return timeToIdleSec;
051: }
052: return threadIntervalSec;
053: }
054:
055: private Map loadMapInstance(String cacheName) throws CacheException {
056: try {
057: Class.forName("com.tcclient.ehcache.TimeExpiryMap");
058: long threadIntervalSec = cache
059: .getDiskExpiryThreadIntervalSeconds();
060: long timeToIdleSec = cache.getTimeToIdleSeconds();
061: long timeToLiveSec = cache.getTimeToLiveSeconds();
062:
063: threadIntervalSec = getThreadIntervalSeconds(
064: threadIntervalSec, timeToIdleSec, timeToLiveSec);
065:
066: Map candidateMap = new SpoolingTimeExpiryMap(
067: threadIntervalSec, timeToIdleSec, timeToLiveSec,
068: cacheName);
069: if (LOG.isDebugEnabled()) {
070: LOG
071: .debug(cache.getName()
072: + " Cache: Using SpoolingTimeExpiryMap implementation");
073: }
074: return candidateMap;
075: } catch (Exception e) {
076: // Give up
077: e.printStackTrace(System.err);
078: throw new CacheException(
079: cache.getName()
080: + "Cache: Cannot find com.tcclient.ehcache.TimeExpiryMap.");
081: }
082: }
083:
084: public final synchronized void putData(Element element)
085: throws CacheException {
086: if (element != null) {
087: ((SpoolingTimeExpiryMap) map).putData(element
088: .getObjectKey(), element);
089: doPut(element);
090: }
091: }
092:
093: public final void stopTimeMonitoring() {
094: ((SpoolingTimeExpiryMap) map).stopTimeMonitoring();
095: }
096:
097: public final void evictExpiredElements() {
098: ((SpoolingTimeExpiryMap) map).evictExpiredElements();
099: }
100:
101: public final synchronized int getHitCount() {
102: return ((SpoolingTimeExpiryMap) map).getHitCount();
103: }
104:
105: public final synchronized int getMissCountExpired() {
106: return ((SpoolingTimeExpiryMap) map).getMissCountExpired();
107: }
108:
109: public final synchronized int getMissCountNotFound() {
110: return ((SpoolingTimeExpiryMap) map).getMissCountNotFound();
111: }
112:
113: public final synchronized boolean isExpired(final Object key) {
114: return ((SpoolingTimeExpiryMap) map).isExpired(key);
115: }
116:
117: public final synchronized void clearStatistics() {
118: ((SpoolingTimeExpiryMap) map).clearStatistics();
119: }
120:
121: public final class SpoolingTimeExpiryMap extends TimeExpiryMap {
122:
123: public SpoolingTimeExpiryMap(long timeToIdleSec,
124: long maxIdleSec, long timeToLiveSec, String cacheName) {
125: super (timeToIdleSec, maxIdleSec, timeToLiveSec, cacheName);
126: }
127:
128: // Notification are not supported yet
129: // protected final synchronized void processExpired(Object key, Object value) {
130: // // If cache is null, the cache has been disposed and the invalidator thread will be stopping soon.
131: //
132: // if (cache == null) { return; }
133: // // Already removed from the map at this point
134: // Element element = (Element) value;
135: // // When max size is 0
136: // if (element == null) { return; }
137: //
138: // // check for expiry before going to the trouble of spooling
139: // if (element.isExpired()) {
140: // notifyExpiry(element);
141: // } else {
142: // evict(element);
143: // }
144: // }
145:
146: public final void evictExpiredElements() {
147: timeExpiryDataStore.evictExpiredElements();
148: }
149: }
150:
151: }
|