001
014
015 package com.liferay.portal.cache.transactional;
016
017 import com.liferay.portal.kernel.cache.PortalCache;
018 import com.liferay.portal.kernel.util.InitialThreadLocal;
019 import com.liferay.portal.util.PropsValues;
020
021 import java.io.Serializable;
022
023 import java.util.ArrayList;
024 import java.util.HashMap;
025 import java.util.List;
026 import java.util.Map;
027
028
031 public class TransactionalPortalCacheHelper {
032
033 public static void begin() {
034 if (!PropsValues.TRANSACTIONAL_CACHE_ENABLED) {
035 return;
036 }
037
038 _pushPortalCacheMap();
039 }
040
041 public static void commit() {
042 if (!PropsValues.TRANSACTIONAL_CACHE_ENABLED) {
043 return;
044 }
045
046 PortalCacheMap portalCacheMap = _popPortalCacheMap();
047
048 for (Map.Entry
049 <PortalCache<? extends Serializable, ?>, UncommittedBuffer>
050 portalCacheMapEntry : portalCacheMap.entrySet()) {
051
052 PortalCache<Serializable, Object> portalCache =
053 (PortalCache<Serializable, Object>)portalCacheMapEntry.getKey();
054
055 UncommittedBuffer uncommittedBuffer =
056 portalCacheMapEntry.getValue();
057
058 uncommittedBuffer.commitTo(portalCache);
059 }
060
061 portalCacheMap.clear();
062 }
063
064 public static boolean isEnabled() {
065 if (!PropsValues.TRANSACTIONAL_CACHE_ENABLED) {
066 return false;
067 }
068
069 List<PortalCacheMap> portalCacheMaps =
070 _portalCacheMapsThreadLocal.get();
071
072 return !portalCacheMaps.isEmpty();
073 }
074
075 public static void rollback() {
076 if (!PropsValues.TRANSACTIONAL_CACHE_ENABLED) {
077 return;
078 }
079
080 PortalCacheMap portalCacheMap = _popPortalCacheMap();
081
082 portalCacheMap.clear();
083 }
084
085 protected static <K extends Serializable, V> V get(
086 PortalCache<K, V> portalCache, K key) {
087
088 PortalCacheMap portalCacheMap = _peekPortalCacheMap();
089
090 UncommittedBuffer uncommittedBuffer = portalCacheMap.get(portalCache);
091
092 if (uncommittedBuffer == null) {
093 return null;
094 }
095
096 Object object = uncommittedBuffer.get(key);
097
098 if (object instanceof TTLValue) {
099 TTLValue ttLValue = (TTLValue)object;
100
101 object = ttLValue._value;
102 }
103
104 return (V)object;
105 }
106
107 protected static <K extends Serializable, V> void put(
108 PortalCache<K, V> portalCache, K key, V value) {
109
110 PortalCacheMap portalCacheMap = _peekPortalCacheMap();
111
112 UncommittedBuffer uncommittedBuffer = portalCacheMap.get(portalCache);
113
114 if (uncommittedBuffer == null) {
115 uncommittedBuffer = new UncommittedBuffer();
116
117 portalCacheMap.put(portalCache, uncommittedBuffer);
118 }
119
120 uncommittedBuffer.put(key, value);
121 }
122
123 protected static <K extends Serializable, V> void put(
124 PortalCache<K, V> portalCache, K key, V value, int ttl) {
125
126 PortalCacheMap portalCacheMap = _peekPortalCacheMap();
127
128 UncommittedBuffer uncommittedBuffer = portalCacheMap.get(portalCache);
129
130 if (uncommittedBuffer == null) {
131 uncommittedBuffer = new UncommittedBuffer();
132
133 portalCacheMap.put(portalCache, uncommittedBuffer);
134 }
135
136 uncommittedBuffer.put(key, new TTLValue(ttl, value));
137 }
138
139 protected static <K extends Serializable, V> void removeAll(
140 PortalCache<K, V> portalCache) {
141
142 PortalCacheMap portalCacheMap = _peekPortalCacheMap();
143
144 UncommittedBuffer uncommittedBuffer = portalCacheMap.get(portalCache);
145
146 if (uncommittedBuffer == null) {
147 uncommittedBuffer = new UncommittedBuffer();
148
149 portalCacheMap.put(portalCache, uncommittedBuffer);
150 }
151
152 uncommittedBuffer.removeAll();
153 }
154
155 private static PortalCacheMap _peekPortalCacheMap() {
156 List<PortalCacheMap> portalCacheMaps =
157 _portalCacheMapsThreadLocal.get();
158
159 return portalCacheMaps.get(portalCacheMaps.size() - 1);
160 }
161
162 private static PortalCacheMap _popPortalCacheMap() {
163 List<PortalCacheMap> portalCacheMaps =
164 _portalCacheMapsThreadLocal.get();
165
166 return portalCacheMaps.remove(portalCacheMaps.size() - 1);
167 }
168
169 private static void _pushPortalCacheMap() {
170 List<PortalCacheMap> portalCacheMaps =
171 _portalCacheMapsThreadLocal.get();
172
173 portalCacheMaps.add(new PortalCacheMap());
174 }
175
176 private static ThreadLocal<List<PortalCacheMap>>
177 _portalCacheMapsThreadLocal =
178 new InitialThreadLocal<List<PortalCacheMap>>(
179 TransactionalPortalCacheHelper.class.getName() +
180 "._portalCacheMapsThreadLocal",
181 new ArrayList<PortalCacheMap>());
182
183 private static class PortalCacheMap
184 extends HashMap
185 <PortalCache<? extends Serializable, ?>, UncommittedBuffer> {
186 }
187
188 private static class TTLValue {
189
190 public TTLValue(int ttl, Object value) {
191 _ttl = ttl;
192 _value = value;
193 }
194
195 private int _ttl;
196 private Object _value;
197
198 }
199
200 private static class UncommittedBuffer {
201
202 public void commitTo(PortalCache<Serializable, Object> portalCache) {
203 if (_removeAll) {
204 portalCache.removeAll();
205 }
206
207 for (Map.Entry<? extends Serializable, List<Object>> entry :
208 _uncommittedMap.entrySet()) {
209
210 Serializable key = entry.getKey();
211 List<Object> valueList = entry.getValue();
212
213 for (Object value : valueList) {
214 if (value == TransactionalPortalCache.NULL_HOLDER) {
215 portalCache.remove(key);
216 }
217 else if (value instanceof TTLValue) {
218 TTLValue ttlValue = (TTLValue)value;
219
220 portalCache.put(key, ttlValue._value, ttlValue._ttl);
221 }
222 else {
223 portalCache.put(key, value);
224 }
225 }
226 }
227 }
228
229 public Object get(Serializable key) {
230 List<Object> valueList = _uncommittedMap.get(key);
231
232 Object value = null;
233
234 if (valueList != null) {
235 value = valueList.get(valueList.size() - 1);
236 }
237
238 if ((value == null) && _removeAll) {
239 value = TransactionalPortalCache.NULL_HOLDER;
240 }
241
242 return value;
243 }
244
245 public void put(Serializable key, Object value) {
246 List<Object> valueList = _uncommittedMap.get(key);
247
248 if (valueList == null) {
249 valueList = new ArrayList<Object>();
250 }
251
252 valueList.add(value);
253
254 _uncommittedMap.put(key, valueList);
255 }
256
257 public void removeAll() {
258 _uncommittedMap.clear();
259
260 _removeAll = true;
261 }
262
263 private boolean _removeAll;
264 private Map<Serializable, List<Object>> _uncommittedMap =
265 new HashMap<Serializable, List<Object>>();
266
267 }
268
269 }