1   /**
2    * Copyright (c) 2000-2010 Liferay, Inc. All rights reserved.
3    *
4    * This library is free software; you can redistribute it and/or modify it under
5    * the terms of the GNU Lesser General Public License as published by the Free
6    * Software Foundation; either version 2.1 of the License, or (at your option)
7    * any later version.
8    *
9    * This library is distributed in the hope that it will be useful, but WITHOUT
10   * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
11   * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
12   * details.
13   */
14  
15  package com.liferay.portal.cache.memcached;
16  
17  import com.liferay.portal.kernel.cache.BasePortalCache;
18  import com.liferay.portal.kernel.log.Log;
19  import com.liferay.portal.kernel.log.LogFactoryUtil;
20  
21  import java.io.Serializable;
22  
23  import java.util.ArrayList;
24  import java.util.Collection;
25  import java.util.List;
26  import java.util.Map;
27  import java.util.concurrent.Future;
28  import java.util.concurrent.TimeUnit;
29  
30  import net.spy.memcached.MemcachedClientIF;
31  
32  /**
33   * <a href="PooledMemcachePortalCache.java.html"><b><i>View Source</i></b></a>
34   *
35   * @author Michael C. Han
36   */
37  public class PooledMemcachePortalCache extends BasePortalCache {
38  
39      public PooledMemcachePortalCache(
40          String name, MemcachedClientFactory memcachedClientFactory, int timeout,
41          TimeUnit timeoutTimeUnit) {
42  
43          _name = name;
44          _memcachedClientFactory = memcachedClientFactory;
45          _timeout = timeout;
46          _timeoutTimeUnit = timeoutTimeUnit;
47      }
48  
49      public void destroy() {
50          try {
51              _memcachedClientFactory.close();
52          }
53          catch (Exception e) {
54          }
55      }
56  
57      public Collection<Object> get(Collection<String> keys) {
58          MemcachedClientIF memcachedClient = null;
59  
60          try {
61              memcachedClient = _memcachedClientFactory.getMemcachedClient();
62          }
63          catch (Exception e) {
64              return null;
65          }
66  
67          List<String> processedKeys = new ArrayList<String>(keys.size());
68  
69          for (String key : keys) {
70              String processedKey = processKey(_name.concat(key));
71  
72              processedKeys.add(processedKey);
73          }
74  
75          Map<String, Object> values = null;
76  
77          try {
78              Future<Map<String,Object>> future = null;
79  
80              try {
81                  future = memcachedClient.asyncGetBulk(processedKeys);
82              }
83              catch (IllegalArgumentException iae) {
84                  if (_log.isWarnEnabled()) {
85                      _log.warn("Error retrieving with keys " + keys, iae);
86                  }
87  
88                  future.cancel(true);
89              }
90  
91              try {
92                  values = future.get(_timeout, _timeoutTimeUnit);
93              }
94              catch (Throwable t) {
95                  if (_log.isWarnEnabled()) {
96                      _log.warn("Memcache operation error", t);
97                  }
98  
99                  future.cancel(true);
100             }
101         }
102         finally {
103             cleanupClient(memcachedClient);
104         }
105 
106         return values.values();
107     }
108 
109     public Object get(String 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 = processKey(_name.concat(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 void put(String key, Object obj) {
150         put(key, obj, _timeToLive);
151     }
152 
153     public void put(String key, Object obj, int timeToLive) {
154         MemcachedClientIF memcachedClient = null;
155 
156         try {
157             memcachedClient = _memcachedClientFactory.getMemcachedClient();
158         }
159         catch (Exception e) {
160             return;
161         }
162 
163         String processedKey = processKey(_name.concat(key));
164 
165         try {
166             memcachedClient.set(processedKey, timeToLive, obj);
167         }
168         catch (IllegalArgumentException iae) {
169             if (_log.isWarnEnabled()) {
170                 _log.warn("Error storing value with key " + key, iae);
171             }
172         }
173         finally {
174             cleanupClient(memcachedClient);
175         }
176     }
177 
178     public void put(String key, Serializable obj) {
179         put(key, obj, _timeToLive);
180     }
181 
182     public void put(String key, Serializable obj, int timeToLive) {
183         MemcachedClientIF memcachedClient = null;
184 
185         try {
186             memcachedClient = _memcachedClientFactory.getMemcachedClient();
187         }
188         catch (Exception e) {
189             return;
190         }
191 
192         String processedKey = processKey(_name.concat(key));
193 
194         try {
195             memcachedClient.set(processedKey, timeToLive, obj);
196         }
197         catch (IllegalArgumentException iae) {
198             if (_log.isWarnEnabled()) {
199                 _log.warn("Error storing value with key " + key, iae);
200             }
201         }
202         finally {
203             cleanupClient(memcachedClient);
204         }
205     }
206 
207     public void remove(String key) {
208         MemcachedClientIF memcachedClient = null;
209 
210         try {
211             memcachedClient = _memcachedClientFactory.getMemcachedClient();
212         }
213         catch (Exception e) {
214             return;
215         }
216 
217         String processedKey = processKey(_name.concat(key));
218 
219         try {
220             memcachedClient.delete(processedKey);
221         }
222         catch (IllegalArgumentException iae) {
223             if (_log.isWarnEnabled()) {
224                 _log.warn("Error deleting value with key " + key, iae);
225             }
226         }
227         finally {
228             cleanupClient(memcachedClient);
229         }
230     }
231 
232     public void removeAll() {
233         MemcachedClientIF memcachedClient = null;
234 
235         try {
236             memcachedClient = _memcachedClientFactory.getMemcachedClient();
237         }
238         catch (Exception e) {
239             return;
240         }
241 
242         try {
243             memcachedClient.flush();
244         }
245         finally {
246             cleanupClient(memcachedClient);
247         }
248     }
249 
250     public void setTimeToLive(int timeToLive) {
251         _timeToLive = timeToLive;
252     }
253 
254     protected void cleanupClient(MemcachedClientIF memcachedClient) {
255         try {
256             _memcachedClientFactory.returnMemcachedObject(memcachedClient);
257         }
258         catch (Exception e) {
259         }
260     }
261 
262     private static final Log _log = LogFactoryUtil.getLog(
263         MemcachePortalCache.class);
264 
265     private MemcachedClientFactory _memcachedClientFactory;
266     private String _name;
267     private int _timeout;
268     private TimeUnit _timeoutTimeUnit;
269     private int _timeToLive;
270 
271 }