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 MemcachePortalCache implements PortalCache {
038    
039            public MemcachePortalCache(
040                    String name, MemcachedClientIF memcachedClient, int timeout,
041                    TimeUnit timeoutTimeUnit) {
042    
043                    _name = name;
044                    _memcachedClient = memcachedClient;
045                    _timeout = timeout;
046                    _timeoutTimeUnit = timeoutTimeUnit;
047            }
048    
049            @Override
050            public void destroy() {
051                    _memcachedClient.shutdown();
052            }
053    
054            @Override
055            public Collection<Object> get(Collection<Serializable> keys) {
056                    List<String> processedKeys = new ArrayList<String>(keys.size());
057    
058                    for (Serializable key : keys) {
059                            String processedKey = _name.concat(String.valueOf(key));
060    
061                            processedKeys.add(processedKey);
062                    }
063    
064                    Future<Map<String, Object>> future = null;
065    
066                    try {
067                            future = _memcachedClient.asyncGetBulk(processedKeys);
068                    }
069                    catch (IllegalArgumentException iae) {
070                            if (_log.isWarnEnabled()) {
071                                    _log.warn("Error retrieving with keys " + keys, iae);
072                            }
073    
074                            return null;
075                    }
076    
077                    Map<String, Object> values = null;
078    
079                    try {
080                            values = future.get(_timeout, _timeoutTimeUnit);
081                    }
082                    catch (Throwable t) {
083                            if (_log.isWarnEnabled()) {
084                                    _log.warn("Memcache operation error", t);
085                            }
086    
087                            future.cancel(true);
088                    }
089    
090                    if (values != null) {
091                            return values.values();
092                    }
093    
094                    return null;
095            }
096    
097            @Override
098            public Object get(Serializable key) {
099                    String processedKey = _name.concat(String.valueOf(key));
100    
101                    Future<Object> future = null;
102    
103                    try {
104                            future = _memcachedClient.asyncGet(processedKey);
105                    }
106                    catch (IllegalArgumentException iae) {
107                            if (_log.isWarnEnabled()) {
108                                    _log.warn("Error retrieving with key " + key, iae);
109                            }
110    
111                            return null;
112                    }
113    
114                    Object value = null;
115    
116                    try {
117                            value = future.get(_timeout, _timeoutTimeUnit);
118                    }
119                    catch (Throwable t) {
120                            if (_log.isWarnEnabled()) {
121                                    _log.warn("Memcache operation error", t);
122                            }
123    
124                            future.cancel(true);
125                    }
126    
127                    return value;
128            }
129    
130            @Override
131            public String getName() {
132                    return _name;
133            }
134    
135            @Override
136            public void put(Serializable key, Object value) {
137                    put(key, value, _timeToLive);
138            }
139    
140            @Override
141            public void put(Serializable key, Object value, int timeToLive) {
142                    String processedKey = _name.concat(String.valueOf(key));
143    
144                    try {
145                            _memcachedClient.set(processedKey, timeToLive, value);
146                    }
147                    catch (IllegalArgumentException iae) {
148                            if (_log.isWarnEnabled()) {
149                                    _log.warn("Error storing value with key " + key, iae);
150                            }
151                    }
152            }
153    
154            @Override
155            public void put(Serializable key, Serializable value) {
156                    put(key, value, _timeToLive);
157            }
158    
159            @Override
160            public void put(Serializable key, Serializable value, int timeToLive) {
161                    String processedKey = _name.concat(String.valueOf(key));
162    
163                    try {
164                            _memcachedClient.set(processedKey, timeToLive, value);
165                    }
166                    catch (IllegalArgumentException iae) {
167                            if (_log.isWarnEnabled()) {
168                                    _log.warn("Error storing value with key " + key, iae);
169                            }
170                    }
171            }
172    
173            @Override
174            public void registerCacheListener(CacheListener cacheListener) {
175                    registerCacheListener(cacheListener, CacheListenerScope.ALL);
176            }
177    
178            @Override
179            public void registerCacheListener(
180                    CacheListener cacheListener, CacheListenerScope cacheListenerScope) {
181    
182                    throw new UnsupportedOperationException();
183            }
184    
185            @Override
186            public void remove(Serializable key) {
187                    String processedKey = _name.concat(String.valueOf(key));
188    
189                    try {
190                            _memcachedClient.delete(processedKey);
191                    }
192                    catch (IllegalArgumentException iae) {
193                            if (_log.isWarnEnabled()) {
194                                    _log.warn("Error removing value with key " + key, iae);
195                            }
196                    }
197            }
198    
199            @Override
200            public void removeAll() {
201                    _memcachedClient.flush();
202            }
203    
204            public void setTimeToLive(int timeToLive) {
205                    _timeToLive = timeToLive;
206            }
207    
208            @Override
209            public void unregisterCacheListener(CacheListener cacheListener) {
210            }
211    
212            @Override
213            public void unregisterCacheListeners() {
214            }
215    
216            private static Log _log = LogFactoryUtil.getLog(MemcachePortalCache.class);
217    
218            private MemcachedClientIF _memcachedClient;
219            private String _name;
220            private int _timeout;
221            private TimeUnit _timeoutTimeUnit;
222            private int _timeToLive;
223    
224    }