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