001    /**
002     * Copyright (c) 2000-2013 Liferay, Inc. All rights reserved.
003     *
004     * This library is free software; you can redistribute it and/or modify it under
005     * the terms of the GNU Lesser General Public License as published by the Free
006     * Software Foundation; either version 2.1 of the License, or (at your option)
007     * any later version.
008     *
009     * This library is distributed in the hope that it will be useful, but WITHOUT
010     * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
011     * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
012     * details.
013     */
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.io.Serializable;
024    
025    import java.util.ArrayList;
026    import java.util.Collection;
027    import java.util.List;
028    import java.util.Map;
029    import java.util.concurrent.Future;
030    import java.util.concurrent.TimeUnit;
031    
032    import net.spy.memcached.MemcachedClientIF;
033    
034    /**
035     * @author Michael C. Han
036     */
037    public class PooledMemcachePortalCache implements PortalCache {
038    
039            public PooledMemcachePortalCache(
040                    String name, MemcachedClientFactory memcachedClientFactory, int timeout,
041                    TimeUnit timeoutTimeUnit) {
042    
043                    _name = name;
044                    _memcachedClientFactory = memcachedClientFactory;
045                    _timeout = timeout;
046                    _timeoutTimeUnit = timeoutTimeUnit;
047            }
048    
049            @Override
050            public void destroy() {
051                    try {
052                            _memcachedClientFactory.close();
053                    }
054                    catch (Exception e) {
055                    }
056            }
057    
058            @Override
059            public Collection<Object> get(Collection<Serializable> keys) {
060                    MemcachedClientIF memcachedClient = null;
061    
062                    try {
063                            memcachedClient = _memcachedClientFactory.getMemcachedClient();
064                    }
065                    catch (Exception e) {
066                            return null;
067                    }
068    
069                    List<String> processedKeys = new ArrayList<String>(keys.size());
070    
071                    for (Serializable key : keys) {
072                            String processedKey = _name.concat(String.valueOf(key));
073    
074                            processedKeys.add(processedKey);
075                    }
076    
077                    Map<String, Object> values = null;
078    
079                    try {
080                            Future<Map<String, Object>> future = null;
081    
082                            try {
083                                    future = memcachedClient.asyncGetBulk(processedKeys);
084                            }
085                            catch (IllegalArgumentException iae) {
086                                    if (_log.isWarnEnabled()) {
087                                            _log.warn("Error retrieving with keys " + keys, iae);
088                                    }
089    
090                                    future.cancel(true);
091                            }
092    
093                            try {
094                                    values = future.get(_timeout, _timeoutTimeUnit);
095                            }
096                            catch (Throwable t) {
097                                    if (_log.isWarnEnabled()) {
098                                            _log.warn("Memcache operation error", t);
099                                    }
100    
101                                    future.cancel(true);
102                            }
103                    }
104                    finally {
105                            cleanupClient(memcachedClient);
106                    }
107    
108                    return values.values();
109            }
110    
111            @Override
112            public Object get(Serializable key) {
113                    MemcachedClientIF memcachedClient = null;
114    
115                    try {
116                            memcachedClient = _memcachedClientFactory.getMemcachedClient();
117                    }
118                    catch (Exception e) {
119                            return null;
120                    }
121    
122                    String processedKey = _name.concat(String.valueOf(key));
123    
124                    try {
125                            Future<Object> future = null;
126    
127                            try {
128                                    future = memcachedClient.asyncGet(processedKey);
129                            }
130                            catch (IllegalArgumentException iae) {
131                                    if (_log.isWarnEnabled()) {
132                                            _log.warn("Error retrieving with key " + key, iae);
133                                    }
134                            }
135    
136                            Object value = null;
137    
138                            try {
139                                    value = future.get(_timeout, _timeoutTimeUnit);
140                            }
141                            catch (Exception e) {
142                                    future.cancel(true);
143                            }
144    
145                            return value;
146                    }
147                    finally {
148                            cleanupClient(memcachedClient);
149                    }
150            }
151    
152            @Override
153            public String getName() {
154                    return _name;
155            }
156    
157            @Override
158            public void put(Serializable key, Object value) {
159                    put(key, value, _timeToLive);
160            }
161    
162            @Override
163            public void put(Serializable key, Object value, int timeToLive) {
164                    MemcachedClientIF memcachedClient = null;
165    
166                    try {
167                            memcachedClient = _memcachedClientFactory.getMemcachedClient();
168                    }
169                    catch (Exception e) {
170                            return;
171                    }
172    
173                    String processedKey = _name.concat(String.valueOf(key));
174    
175                    try {
176                            memcachedClient.set(processedKey, timeToLive, value);
177                    }
178                    catch (IllegalArgumentException iae) {
179                            if (_log.isWarnEnabled()) {
180                                    _log.warn("Error storing value with key " + key, iae);
181                            }
182                    }
183                    finally {
184                            cleanupClient(memcachedClient);
185                    }
186            }
187    
188            @Override
189            public void put(Serializable key, Serializable value) {
190                    put(key, value, _timeToLive);
191            }
192    
193            @Override
194            public void put(Serializable key, Serializable value, int timeToLive) {
195                    MemcachedClientIF memcachedClient = null;
196    
197                    try {
198                            memcachedClient = _memcachedClientFactory.getMemcachedClient();
199                    }
200                    catch (Exception e) {
201                            return;
202                    }
203    
204                    String processedKey = _name.concat(String.valueOf(key));
205    
206                    try {
207                            memcachedClient.set(processedKey, timeToLive, value);
208                    }
209                    catch (IllegalArgumentException iae) {
210                            if (_log.isWarnEnabled()) {
211                                    _log.warn("Error storing value with key " + key, iae);
212                            }
213                    }
214                    finally {
215                            cleanupClient(memcachedClient);
216                    }
217            }
218    
219            @Override
220            public void registerCacheListener(CacheListener cacheListener) {
221                    registerCacheListener(cacheListener, CacheListenerScope.ALL);
222            }
223    
224            @Override
225            public void registerCacheListener(
226                    CacheListener cacheListener, CacheListenerScope cacheListenerScope) {
227    
228                    throw new UnsupportedOperationException();
229            }
230    
231            @Override
232            public void remove(Serializable key) {
233                    MemcachedClientIF memcachedClient = null;
234    
235                    try {
236                            memcachedClient = _memcachedClientFactory.getMemcachedClient();
237                    }
238                    catch (Exception e) {
239                            return;
240                    }
241    
242                    String processedKey = _name.concat(String.valueOf(key));
243    
244                    try {
245                            memcachedClient.delete(processedKey);
246                    }
247                    catch (IllegalArgumentException iae) {
248                            if (_log.isWarnEnabled()) {
249                                    _log.warn("Unable to delete value with key " + key, iae);
250                            }
251                    }
252                    finally {
253                            cleanupClient(memcachedClient);
254                    }
255            }
256    
257            @Override
258            public void removeAll() {
259                    MemcachedClientIF memcachedClient = null;
260    
261                    try {
262                            memcachedClient = _memcachedClientFactory.getMemcachedClient();
263                    }
264                    catch (Exception e) {
265                            return;
266                    }
267    
268                    try {
269                            memcachedClient.flush();
270                    }
271                    finally {
272                            cleanupClient(memcachedClient);
273                    }
274            }
275    
276            public void setTimeToLive(int timeToLive) {
277                    _timeToLive = timeToLive;
278            }
279    
280            @Override
281            public void unregisterCacheListener(CacheListener cacheListener) {
282            }
283    
284            @Override
285            public void unregisterCacheListeners() {
286            }
287    
288            protected void cleanupClient(MemcachedClientIF memcachedClient) {
289                    try {
290                            _memcachedClientFactory.returnMemcachedObject(memcachedClient);
291                    }
292                    catch (Exception e) {
293                    }
294            }
295    
296            private static Log _log = LogFactoryUtil.getLog(
297                    PooledMemcachePortalCache.class);
298    
299            private MemcachedClientFactory _memcachedClientFactory;
300            private String _name;
301            private int _timeout;
302            private TimeUnit _timeoutTimeUnit;
303            private int _timeToLive;
304    
305    }