1   /**
2    * Copyright (c) 2000-2009 Liferay, Inc. All rights reserved.
3    *
4    * Permission is hereby granted, free of charge, to any person obtaining a copy
5    * of this software and associated documentation files (the "Software"), to deal
6    * in the Software without restriction, including without limitation the rights
7    * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8    * copies of the Software, and to permit persons to whom the Software is
9    * furnished to do so, subject to the following conditions:
10   *
11   * The above copyright notice and this permission notice shall be included in
12   * all copies or substantial portions of the Software.
13   *
14   * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15   * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16   * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17   * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18   * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19   * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
20   * SOFTWARE.
21   */
22  
23  package com.liferay.portal.kernel.cache;
24  
25  import com.liferay.portal.kernel.concurrent.CompeteLatch;
26  
27  import java.io.Serializable;
28  
29  import java.util.concurrent.ConcurrentHashMap;
30  import java.util.concurrent.ConcurrentMap;
31  
32  /**
33   * <a href="BlockingPortalCache.java.html"><b><i>View Source</i></b></a>
34   *
35   * @author Shuyang Zhou
36   */
37  public class BlockingPortalCache implements PortalCache {
38  
39      public BlockingPortalCache(PortalCache portalCache) {
40          _portalCache = portalCache;
41      }
42  
43      public Object get(String key) {
44          Object obj = _portalCache.get(key);
45  
46          if (obj != null) {
47              return obj;
48          }
49  
50          CompeteLatch lastCompeteLatch = _competeLatchThreadLocal.get();
51  
52          if (lastCompeteLatch != null) {
53              lastCompeteLatch.done();
54  
55              _competeLatchThreadLocal.set(null);
56          }
57  
58          CompeteLatch currentCompeteLatch = _competeLatchMap.get(key);
59  
60          if (currentCompeteLatch == null) {
61              CompeteLatch newCompeteLatch = new CompeteLatch();
62  
63              currentCompeteLatch = _competeLatchMap.putIfAbsent(
64                  key, newCompeteLatch);
65  
66              if (currentCompeteLatch == null) {
67                  currentCompeteLatch = newCompeteLatch;
68              }
69          }
70  
71          _competeLatchThreadLocal.set(currentCompeteLatch);
72  
73          if (!currentCompeteLatch.compete()) {
74              currentCompeteLatch.await();
75  
76              _competeLatchThreadLocal.set(null);
77  
78              obj = _portalCache.get(key);
79          }
80  
81          return obj;
82      }
83  
84      public void put(String key, Object obj) {
85          if (key == null) {
86              throw new IllegalArgumentException("Key is null");
87          }
88  
89          if (obj == null) {
90              throw new IllegalArgumentException("Object is null");
91          }
92  
93          _portalCache.put(key, obj);
94  
95          CompeteLatch competeLatch = _competeLatchThreadLocal.get();
96  
97          if (competeLatch != null) {
98              competeLatch.done();
99  
100             _competeLatchThreadLocal.set(null);
101         }
102 
103         _competeLatchMap.remove(key);
104     }
105 
106     public void put(String key, Object obj, int timeToLive) {
107         if (key == null) {
108             throw new IllegalArgumentException("Key is null");
109         }
110 
111         if (obj == null) {
112             throw new IllegalArgumentException("Object is null");
113         }
114 
115         _portalCache.put(key, obj, timeToLive);
116 
117         CompeteLatch competeLatch = _competeLatchThreadLocal.get();
118 
119         if (competeLatch != null) {
120             competeLatch.done();
121 
122             _competeLatchThreadLocal.set(null);
123         }
124 
125         _competeLatchMap.remove(key);
126     }
127 
128     public void put(String key, Serializable obj) {
129         if (key == null) {
130             throw new IllegalArgumentException("Key is null");
131         }
132 
133         if (obj == null) {
134             throw new IllegalArgumentException("Object is null");
135         }
136 
137         _portalCache.put(key, obj);
138 
139         CompeteLatch competeLatch = _competeLatchThreadLocal.get();
140 
141         if (competeLatch != null) {
142             competeLatch.done();
143 
144             _competeLatchThreadLocal.set(null);
145         }
146 
147         _competeLatchMap.remove(key);
148     }
149 
150     public void put(String key, Serializable obj, int timeToLive) {
151         if (key == null) {
152             throw new IllegalArgumentException("Key is null");
153         }
154 
155         if (obj == null) {
156             throw new IllegalArgumentException("Object is null");
157         }
158 
159         _portalCache.put(key, obj, timeToLive);
160 
161         CompeteLatch competeLatch = _competeLatchThreadLocal.get();
162 
163         if (competeLatch != null) {
164             competeLatch.done();
165 
166             _competeLatchThreadLocal.set(null);
167         }
168 
169         _competeLatchMap.remove(key);
170     }
171 
172     public void remove(String key) {
173         _portalCache.remove(key);
174         _competeLatchMap.remove(key);
175     }
176 
177     public void removeAll() {
178         _portalCache.removeAll();
179         _competeLatchMap.clear();
180     }
181 
182     private static ThreadLocal<CompeteLatch> _competeLatchThreadLocal =
183         new ThreadLocal<CompeteLatch>();
184 
185     private final ConcurrentMap<String, CompeteLatch> _competeLatchMap =
186         new ConcurrentHashMap<String, CompeteLatch>();
187     private final PortalCache _portalCache;
188 
189 }