001
014
015 package com.liferay.portal.kernel.cache;
016
017 import com.liferay.portal.kernel.concurrent.CompeteLatch;
018
019 import java.io.Serializable;
020
021 import java.util.Collection;
022 import java.util.concurrent.ConcurrentHashMap;
023 import java.util.concurrent.ConcurrentMap;
024
025
028 public class BlockingPortalCache<K extends Serializable, V>
029 implements PortalCache<K, V> {
030
031 public BlockingPortalCache(PortalCache<K, V> portalCache) {
032 _portalCache = portalCache;
033 }
034
035 public void destroy() {
036 }
037
038 public Collection<V> get(Collection<K> keys) {
039 return _portalCache.get(keys);
040 }
041
042 public V get(K key) {
043 V value = _portalCache.get(key);
044
045 if (value != null) {
046 return value;
047 }
048
049 CompeteLatch lastCompeteLatch = _competeLatch.get();
050
051 if (lastCompeteLatch != null) {
052 lastCompeteLatch.done();
053
054 _competeLatch.set(null);
055 }
056
057 CompeteLatch currentCompeteLatch = _competeLatchMap.get(key);
058
059 if (currentCompeteLatch == null) {
060 CompeteLatch newCompeteLatch = new CompeteLatch();
061
062 currentCompeteLatch = _competeLatchMap.putIfAbsent(
063 key, newCompeteLatch);
064
065 if (currentCompeteLatch == null) {
066 currentCompeteLatch = newCompeteLatch;
067 }
068 }
069
070 _competeLatch.set(currentCompeteLatch);
071
072 if (!currentCompeteLatch.compete()) {
073 try {
074 currentCompeteLatch.await();
075 }
076 catch (InterruptedException ie) {
077 }
078
079 _competeLatch.set(null);
080
081 value = _portalCache.get(key);
082 }
083
084 return value;
085 }
086
087 public String getName() {
088 return _portalCache.getName();
089 }
090
091 public void put(K key, V value) {
092 if (key == null) {
093 throw new IllegalArgumentException("Key is null");
094 }
095
096 if (value == null) {
097 throw new IllegalArgumentException("Value is null");
098 }
099
100 _portalCache.put(key, value);
101
102 CompeteLatch competeLatch = _competeLatch.get();
103
104 if (competeLatch != null) {
105 competeLatch.done();
106
107 _competeLatch.set(null);
108 }
109
110 _competeLatchMap.remove(key);
111 }
112
113 public void put(K key, V value, int timeToLive) {
114 if (key == null) {
115 throw new IllegalArgumentException("Key is null");
116 }
117
118 if (value == null) {
119 throw new IllegalArgumentException("Value is null");
120 }
121
122 _portalCache.put(key, value, timeToLive);
123
124 CompeteLatch competeLatch = _competeLatch.get();
125
126 if (competeLatch != null) {
127 competeLatch.done();
128
129 _competeLatch.set(null);
130 }
131
132 _competeLatchMap.remove(key);
133 }
134
135 public void registerCacheListener(CacheListener<K, V> cacheListener) {
136 _portalCache.registerCacheListener(cacheListener);
137 }
138
139 public void registerCacheListener(
140 CacheListener<K, V> cacheListener,
141 CacheListenerScope cacheListenerScope) {
142
143 _portalCache.registerCacheListener(cacheListener, cacheListenerScope);
144 }
145
146 public void remove(K key) {
147 _portalCache.remove(key);
148
149 CompeteLatch competeLatch = _competeLatchMap.remove(key);
150
151 if (competeLatch != null) {
152 competeLatch.done();
153 }
154 }
155
156 public void removeAll() {
157 _portalCache.removeAll();
158 _competeLatchMap.clear();
159 }
160
161 public void unregisterCacheListener(CacheListener<K, V> cacheListener) {
162 _portalCache.unregisterCacheListener(cacheListener);
163 }
164
165 public void unregisterCacheListeners() {
166 _portalCache.unregisterCacheListeners();
167 }
168
169 private static ThreadLocal<CompeteLatch> _competeLatch =
170 new ThreadLocal<CompeteLatch>();
171 private final ConcurrentMap<K, CompeteLatch> _competeLatchMap =
172 new ConcurrentHashMap<K, CompeteLatch>();
173 private final PortalCache<K, V> _portalCache;
174
175 }