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