001    /**
002     * Copyright (c) 2000-2012 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            public void destroy() {
050                    try {
051                            _memcachedClientFactory.close();
052                    }
053                    catch (Exception e) {
054                    }
055            }
056    
057            public Collection<Object> get(Collection<Serializable> 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 (Serializable key : keys) {
070                            String processedKey = _name.concat(String.valueOf(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 values.values();
107            }
108    
109            public Object get(Serializable key) {
110                    MemcachedClientIF memcachedClient = null;
111    
112                    try {
113                            memcachedClient = _memcachedClientFactory.getMemcachedClient();
114                    }
115                    catch (Exception e) {
116                            return null;
117                    }
118    
119                    String processedKey = _name.concat(String.valueOf(key));
120    
121                    try {
122                            Future<Object> future = null;
123    
124                            try {
125                                    future = memcachedClient.asyncGet(processedKey);
126                            }
127                            catch (IllegalArgumentException iae) {
128                                    if (_log.isWarnEnabled()) {
129                                            _log.warn("Error retrieving with key " + key, iae);
130                                    }
131                            }
132    
133                            Object value = null;
134    
135                            try {
136                                    value = future.get(_timeout, _timeoutTimeUnit);
137                            }
138                            catch (Exception e) {
139                                    future.cancel(true);
140                            }
141    
142                            return value;
143                    }
144                    finally {
145                            cleanupClient(memcachedClient);
146                    }
147            }
148    
149            public String getName() {
150                    return _name;
151            }
152    
153            public void put(Serializable key, Object value) {
154                    put(key, value, _timeToLive);
155            }
156    
157            public void put(Serializable key, Object value, int timeToLive) {
158                    MemcachedClientIF memcachedClient = null;
159    
160                    try {
161                            memcachedClient = _memcachedClientFactory.getMemcachedClient();
162                    }
163                    catch (Exception e) {
164                            return;
165                    }
166    
167                    String processedKey = _name.concat(String.valueOf(key));
168    
169                    try {
170                            memcachedClient.set(processedKey, timeToLive, value);
171                    }
172                    catch (IllegalArgumentException iae) {
173                            if (_log.isWarnEnabled()) {
174                                    _log.warn("Error storing value with key " + key, iae);
175                            }
176                    }
177                    finally {
178                            cleanupClient(memcachedClient);
179                    }
180            }
181    
182            public void put(Serializable key, Serializable value) {
183                    put(key, value, _timeToLive);
184            }
185    
186            public void put(Serializable key, Serializable value, int timeToLive) {
187                    MemcachedClientIF memcachedClient = null;
188    
189                    try {
190                            memcachedClient = _memcachedClientFactory.getMemcachedClient();
191                    }
192                    catch (Exception e) {
193                            return;
194                    }
195    
196                    String processedKey = _name.concat(String.valueOf(key));
197    
198                    try {
199                            memcachedClient.set(processedKey, timeToLive, value);
200                    }
201                    catch (IllegalArgumentException iae) {
202                            if (_log.isWarnEnabled()) {
203                                    _log.warn("Error storing value with key " + key, iae);
204                            }
205                    }
206                    finally {
207                            cleanupClient(memcachedClient);
208                    }
209            }
210    
211            public void registerCacheListener(CacheListener cacheListener) {
212                    registerCacheListener(cacheListener, CacheListenerScope.ALL);
213            }
214    
215            public void registerCacheListener(
216                    CacheListener cacheListener, CacheListenerScope cacheListenerScope) {
217    
218                    throw new UnsupportedOperationException();
219            }
220    
221            public void remove(Serializable key) {
222                    MemcachedClientIF memcachedClient = null;
223    
224                    try {
225                            memcachedClient = _memcachedClientFactory.getMemcachedClient();
226                    }
227                    catch (Exception e) {
228                            return;
229                    }
230    
231                    String processedKey = _name.concat(String.valueOf(key));
232    
233                    try {
234                            memcachedClient.delete(processedKey);
235                    }
236                    catch (IllegalArgumentException iae) {
237                            if (_log.isWarnEnabled()) {
238                                    _log.warn("Unable to delete value with key " + key, iae);
239                            }
240                    }
241                    finally {
242                            cleanupClient(memcachedClient);
243                    }
244            }
245    
246            public void removeAll() {
247                    MemcachedClientIF memcachedClient = null;
248    
249                    try {
250                            memcachedClient = _memcachedClientFactory.getMemcachedClient();
251                    }
252                    catch (Exception e) {
253                            return;
254                    }
255    
256                    try {
257                            memcachedClient.flush();
258                    }
259                    finally {
260                            cleanupClient(memcachedClient);
261                    }
262            }
263    
264            public void setTimeToLive(int timeToLive) {
265                    _timeToLive = timeToLive;
266            }
267    
268            public void unregisterCacheListener(CacheListener cacheListener) {
269            }
270    
271            public void unregisterCacheListeners() {
272            }
273    
274            protected void cleanupClient(MemcachedClientIF memcachedClient) {
275                    try {
276                            _memcachedClientFactory.returnMemcachedObject(memcachedClient);
277                    }
278                    catch (Exception e) {
279                    }
280            }
281    
282            private static Log _log = LogFactoryUtil.getLog(MemcachePortalCache.class);
283    
284            private MemcachedClientFactory _memcachedClientFactory;
285            private String _name;
286            private int _timeout;
287            private TimeUnit _timeoutTimeUnit;
288            private int _timeToLive;
289    
290    }