001
014
015 package com.liferay.portal.cache.memcached;
016
017 import com.liferay.portal.kernel.cache.CacheListener;
018 import com.liferay.portal.kernel.cache.CacheListenerScope;
019 import com.liferay.portal.kernel.cache.PortalCache;
020 import com.liferay.portal.kernel.log.Log;
021 import com.liferay.portal.kernel.log.LogFactoryUtil;
022
023 import java.util.ArrayList;
024 import java.util.Collection;
025 import java.util.List;
026 import java.util.Map;
027 import java.util.concurrent.Future;
028 import java.util.concurrent.TimeUnit;
029
030 import net.spy.memcached.MemcachedClientIF;
031
032
035 public class PooledMemcachePortalCache<V> implements PortalCache<String, V> {
036
037 public PooledMemcachePortalCache(
038 String name, MemcachedClientFactory memcachedClientFactory, int timeout,
039 TimeUnit timeoutTimeUnit) {
040
041 _name = name;
042 _memcachedClientFactory = memcachedClientFactory;
043 _timeout = timeout;
044 _timeoutTimeUnit = timeoutTimeUnit;
045 }
046
047 @Override
048 public void destroy() {
049 try {
050 _memcachedClientFactory.close();
051 }
052 catch (Exception e) {
053 }
054 }
055
056 @Override
057 public Collection<V> get(Collection<String> keys) {
058 MemcachedClientIF memcachedClient = null;
059
060 try {
061 memcachedClient = _memcachedClientFactory.getMemcachedClient();
062 }
063 catch (Exception e) {
064 return null;
065 }
066
067 List<String> processedKeys = new ArrayList<String>(keys.size());
068
069 for (String key : keys) {
070 String processedKey = _name.concat(key);
071
072 processedKeys.add(processedKey);
073 }
074
075 Map<String, Object> values = null;
076
077 try {
078 Future<Map<String, Object>> future = null;
079
080 try {
081 future = memcachedClient.asyncGetBulk(processedKeys);
082 }
083 catch (IllegalArgumentException iae) {
084 if (_log.isWarnEnabled()) {
085 _log.warn("Error retrieving with keys " + keys, iae);
086 }
087
088 future.cancel(true);
089 }
090
091 try {
092 values = future.get(_timeout, _timeoutTimeUnit);
093 }
094 catch (Throwable t) {
095 if (_log.isWarnEnabled()) {
096 _log.warn("Memcache operation error", t);
097 }
098
099 future.cancel(true);
100 }
101 }
102 finally {
103 cleanupClient(memcachedClient);
104 }
105
106 return (Collection<V>)values.values();
107 }
108
109 @Override
110 public V get(String key) {
111 MemcachedClientIF memcachedClient = null;
112
113 try {
114 memcachedClient = _memcachedClientFactory.getMemcachedClient();
115 }
116 catch (Exception e) {
117 return null;
118 }
119
120 String processedKey = _name.concat(key);
121
122 try {
123 Future<Object> future = null;
124
125 try {
126 future = memcachedClient.asyncGet(processedKey);
127 }
128 catch (IllegalArgumentException iae) {
129 if (_log.isWarnEnabled()) {
130 _log.warn("Error retrieving with key " + key, iae);
131 }
132 }
133
134 Object value = null;
135
136 try {
137 value = future.get(_timeout, _timeoutTimeUnit);
138 }
139 catch (Exception e) {
140 future.cancel(true);
141 }
142
143 return (V)value;
144 }
145 finally {
146 cleanupClient(memcachedClient);
147 }
148 }
149
150 @Override
151 public String getName() {
152 return _name;
153 }
154
155 @Override
156 public void put(String key, V value) {
157 put(key, value, _timeToLive);
158 }
159
160 @Override
161 public void put(String key, V value, int timeToLive) {
162 MemcachedClientIF memcachedClient = null;
163
164 try {
165 memcachedClient = _memcachedClientFactory.getMemcachedClient();
166 }
167 catch (Exception e) {
168 return;
169 }
170
171 String processedKey = _name.concat(key);
172
173 try {
174 memcachedClient.set(processedKey, timeToLive, value);
175 }
176 catch (IllegalArgumentException iae) {
177 if (_log.isWarnEnabled()) {
178 _log.warn("Error storing value with key " + key, iae);
179 }
180 }
181 finally {
182 cleanupClient(memcachedClient);
183 }
184 }
185
186 @Override
187 public void registerCacheListener(CacheListener<String, V> cacheListener) {
188 registerCacheListener(cacheListener, CacheListenerScope.ALL);
189 }
190
191 @Override
192 public void registerCacheListener(
193 CacheListener<String, V> cacheListener,
194 CacheListenerScope cacheListenerScope) {
195
196 throw new UnsupportedOperationException();
197 }
198
199 @Override
200 public void remove(String key) {
201 MemcachedClientIF memcachedClient = null;
202
203 try {
204 memcachedClient = _memcachedClientFactory.getMemcachedClient();
205 }
206 catch (Exception e) {
207 return;
208 }
209
210 String processedKey = _name.concat(key);
211
212 try {
213 memcachedClient.delete(processedKey);
214 }
215 catch (IllegalArgumentException iae) {
216 if (_log.isWarnEnabled()) {
217 _log.warn("Unable to delete value with key " + key, iae);
218 }
219 }
220 finally {
221 cleanupClient(memcachedClient);
222 }
223 }
224
225 @Override
226 public void removeAll() {
227 MemcachedClientIF memcachedClient = null;
228
229 try {
230 memcachedClient = _memcachedClientFactory.getMemcachedClient();
231 }
232 catch (Exception e) {
233 return;
234 }
235
236 try {
237 memcachedClient.flush();
238 }
239 finally {
240 cleanupClient(memcachedClient);
241 }
242 }
243
244 public void setTimeToLive(int timeToLive) {
245 _timeToLive = timeToLive;
246 }
247
248 @Override
249 public void unregisterCacheListener(
250 CacheListener<String, V> cacheListener) {
251 }
252
253 @Override
254 public void unregisterCacheListeners() {
255 }
256
257 protected void cleanupClient(MemcachedClientIF memcachedClient) {
258 try {
259 _memcachedClientFactory.returnMemcachedObject(memcachedClient);
260 }
261 catch (Exception e) {
262 }
263 }
264
265 private static Log _log = LogFactoryUtil.getLog(
266 PooledMemcachePortalCache.class);
267
268 private MemcachedClientFactory _memcachedClientFactory;
269 private String _name;
270 private int _timeout;
271 private TimeUnit _timeoutTimeUnit;
272 private int _timeToLive;
273
274 }