001: package org.shiftone.cache.decorator.miss;
002:
003: import org.shiftone.cache.Cache;
004: import org.shiftone.cache.util.Log;
005:
006: import java.util.Hashtable;
007: import java.util.Map;
008:
009: /**
010: * @version $Revision: 1.9 $
011: * @author <a href="mailto:jeff@shiftone.org">Jeff Drost</a>
012: */
013: public class MissHandlingCache implements Cache {
014:
015: private static final Log LOG = new Log(MissHandlingCache.class);
016: private final Cache cache;
017: private final Object fetchLock = new Object();
018: private final MissHandler missHandler;
019: private Map keyMap = new Hashtable(11);
020:
021: public MissHandlingCache(Cache cache, MissHandler missHandler) {
022:
023: this .cache = cache;
024: this .missHandler = missHandler;
025:
026: LOG.debug("new");
027: }
028:
029: synchronized Object getLock(Object key) {
030:
031: Lock lock = (Lock) keyMap.get(key);
032:
033: if (lock == null) {
034: lock = new Lock();
035: lock.count = 0;
036:
037: keyMap.put(key, lock);
038: } else {
039: lock.count++;
040: }
041:
042: return lock;
043: }
044:
045: synchronized void unlockKey(Object key) {
046:
047: Lock lock = (Lock) keyMap.get(key);
048:
049: if (lock != null) {
050: lock.count--;
051:
052: if (lock.count < 0) {
053: keyMap.remove(key);
054: }
055: } else {
056: throw new IllegalStateException("unlock error");
057: }
058: }
059:
060: public Object getObject(Object key) {
061:
062: Object value = null;
063: Object lock = getLock(key);
064:
065: synchronized (lock) {
066: try {
067: synchronized (cache) {
068: value = cache.getObject(key);
069: }
070:
071: if (value == null) {
072: try {
073: value = missHandler.fetchObject(key);
074: } catch (Exception e) {
075: LOG.error("MissHandler error : " + missHandler,
076: e);
077: }
078: }
079:
080: if (value != null) {
081: addObject(key, value);
082: }
083: } finally {
084: unlockKey(key);
085: }
086:
087: return value;
088: }
089: }
090:
091: public void addObject(Object userKey, Object cacheObject) {
092:
093: synchronized (cache) {
094: cache.addObject(userKey, cacheObject);
095: }
096: }
097:
098: public int size() {
099: return cache.size();
100: }
101:
102: public void remove(Object key) {
103:
104: synchronized (cache) {
105: cache.remove(key);
106: }
107: }
108:
109: public void clear() {
110:
111: synchronized (cache) {
112: cache.clear();
113: }
114: }
115:
116: public final String toString() {
117: return "MissHandlingCache->" + cache;
118: }
119:
120: public static class Lock {
121: int count = 0;
122: }
123: }
|