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