View Javadoc
1   /*
2    * Copyright (C) 2010 eXo Platform SAS.
3    *
4    * This is free software; you can redistribute it and/or modify it
5    * under the terms of the GNU Lesser General Public License as
6    * published by the Free Software Foundation; either version 2.1 of
7    * the License, or (at your option) any later version.
8    *
9    * This software is distributed in the hope that it will be useful,
10   * but WITHOUT ANY WARRANTY; without even the implied warranty of
11   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12   * Lesser General Public License for more details.
13   *
14   * You should have received a copy of the GNU Lesser General Public
15   * License along with this software; if not, write to the Free
16   * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
17   * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
18   */
19  
20  package org.exoplatform.services.portletcache;
21  
22  import java.util.Iterator;
23  import java.util.Map;
24  import java.util.concurrent.ConcurrentHashMap;
25  import java.util.concurrent.Executors;
26  import java.util.concurrent.ScheduledExecutorService;
27  import java.util.concurrent.ScheduledFuture;
28  import java.util.concurrent.TimeUnit;
29  
30  import org.exoplatform.commons.cache.future.FutureCache;
31  import org.exoplatform.services.log.Log;
32  
33  /**
34   * @author <a href="mailto:julien.viet@exoplatform.com">Julien Viet</a>
35   * @version $Revision$
36   */
37  @Deprecated
38  class PortletFutureCache extends FutureCache<WindowKey, MarkupFragment, PortletRenderContext>
39  {
40  
41    /**
42     * default to 5000 entries
43     */
44    private static final int                                   DEFAULT_CACHE_SIZE = 5000;
45  
46    /** . */
47    private final ConcurrentHashMap<WindowKey, MarkupFragment> entries;
48  
49    /** . */
50    private final Log                                          log;
51  
52    /** . */
53    private ScheduledExecutorService                           scheduler          = Executors.newScheduledThreadPool(1);
54  
55    /** . */
56    private int                                                cleanupCache;
57  
58    /** . */
59    private int                                                cacheMaxSize       = DEFAULT_CACHE_SIZE;
60  
61    /** . */
62    private ScheduledFuture<?>                                 scheduled;
63  
64    PortletFutureCache(Log log, int cleanupCache)
65    {
66      super(new PortletRenderer(log));
67  
68      //
69      this.log = log;
70      this.entries = new ConcurrentHashMap<WindowKey, MarkupFragment>();
71      this.cleanupCache = preventWrongCleanupCacheValue(cleanupCache);
72      this.scheduled = null;
73    }
74  
75    PortletFutureCache(Log log, int cleanupCache, int cacheSize)
76    {
77      this(log, cleanupCache);
78      this.cacheMaxSize = cacheSize;
79    }
80  
81    private static int preventWrongCleanupCacheValue(int value)
82    {
83      // 10 mns by default
84      return value < 0 ? 5 * 60 : value;
85    }
86  
87    public int getCleanupCache()
88    {
89      return cleanupCache;
90    }
91  
92    public void updateCleanupCache(int cleanupCache)
93    {
94      this.cleanupCache = cleanupCache;
95  
96      //
97      if (scheduled != null)
98      {
99        stop();
100       start();
101     }
102   }
103 
104   /*
105    * Returns the number of entries in this cache.
106    */
107   protected int getCacheSize()
108   {
109     return (entries.size());
110   }
111 
112   /*
113    * Returns the defined Max Cache Size.
114    */
115   protected int getCacheMaxSize()
116   {
117     return (cacheMaxSize);
118   }
119 
120   /*
121    * Returns the defined Max Cache Size.
122    */
123   protected void setCacheMaxSize(int cacheMaxSize)
124   {
125     this.cacheMaxSize = cacheMaxSize;
126   }
127 
128   /*
129    * Clear Cache (should be called by JMX in urgently mode.
130    */
131   protected void clearCache()
132   {
133     if (scheduled != null)
134     {
135       stop();
136       entries.clear();
137       start();
138     }
139     else
140       entries.clear();
141   }
142 
143   /*
144    * Did Cache contains the following key (do not remove old values).
145    */
146   protected boolean containsKey(WindowKey key)
147   {
148     return (entries.containsKey(key));
149   }
150 
151 
152   @Override
153   protected MarkupFragment get(WindowKey key)
154   {
155     // System.out.println("get asked for key " + key);
156 
157     MarkupFragment value = entries.get(key);
158     if (value != null)
159     {
160       if (value.expirationTimeMillis > System.currentTimeMillis())
161       {
162         if (log.isTraceEnabled())
163           log.trace("Using cached markup for portlet " + key);
164         return value;
165       }
166       if (log.isTraceEnabled())
167         log.trace("Expired markup for portlet " + key);
168       entries.remove(key);
169       return null;
170     }
171     return null;
172   }
173 
174   @Override
175   protected void put(WindowKey key, MarkupFragment value)
176   {
177     boolean canInsert = false;
178 
179     // System.out.println("put asked for key " + key + " duration " + (value.expirationTimeMillis - System.currentTimeMillis()));
180 
181     if (value.expirationTimeMillis > System.currentTimeMillis()) {
182       if ((entries.size() < cacheMaxSize))
183         canInsert = true;
184 
185       if (canInsert) {
186         entries.put(key, value);
187         if (log.isTraceEnabled())
188           log.trace("Cached markup for portlet " + key);
189 
190         // System.out.println("Cached markup for portlet " + key);
191       }
192     }
193   }
194 
195   @Override
196   protected void putOnly(WindowKey key, MarkupFragment value) {
197     put(key, value);
198   }
199 
200   public void start()
201   {
202     if (scheduled == null)
203     {
204       if (log.isDebugEnabled()) {
205         log.debug("Starting cache cleaner with a period of " + cleanupCache + " seconds");
206       }
207       if(scheduler.isShutdown()) scheduler = Executors.newScheduledThreadPool(1);
208       scheduled = scheduler.scheduleWithFixedDelay(new Runnable()
209       {
210         public void run()
211         {
212           long now = System.currentTimeMillis();
213           for (Iterator<Map.Entry<WindowKey, MarkupFragment>> i = entries.entrySet().iterator(); i.hasNext();)
214           {
215             Map.Entry<WindowKey, MarkupFragment> entry = i.next();
216             if (entry.getValue().expirationTimeMillis < now)
217             {
218               if (log.isTraceEnabled())
219                 log.trace("Removing expired entry " + entry.getKey().getWindowId());
220 
221               // System.out.println("Removing expired entry " + entry.getKey().getWindowId());
222 
223               i.remove();
224             }
225           }
226         }
227       }, cleanupCache, cleanupCache, TimeUnit.SECONDS);
228     }
229   }
230 
231   public void stop()
232   {
233     if (scheduled != null)
234     {
235       if (log.isDebugEnabled()) {
236         log.debug("Stopping cache cleaner");
237       }
238       scheduled.cancel(false);
239       scheduled = null;
240     }
241     if (scheduler != null) {
242       scheduler.shutdown();
243     }
244   }
245 }