View Javadoc

1   package org.apache.jcs.engine.memory;
2   
3   /*
4    * Licensed to the Apache Software Foundation (ASF) under one
5    * or more contributor license agreements.  See the NOTICE file
6    * distributed with this work for additional information
7    * regarding copyright ownership.  The ASF licenses this file
8    * to you under the Apache License, Version 2.0 (the
9    * "License"); you may not use this file except in compliance
10   * with the License.  You may obtain a copy of the License at
11   *
12   *   http://www.apache.org/licenses/LICENSE-2.0
13   *
14   * Unless required by applicable law or agreed to in writing,
15   * software distributed under the License is distributed on an
16   * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
17   * KIND, either express or implied.  See the License for the
18   * specific language governing permissions and limitations
19   * under the License.
20   */
21  
22  import java.io.IOException;
23  import java.io.Serializable;
24  import java.util.HashSet;
25  import java.util.Hashtable;
26  import java.util.Iterator;
27  import java.util.Map;
28  import java.util.Set;
29  
30  import org.apache.commons.logging.Log;
31  import org.apache.commons.logging.LogFactory;
32  import org.apache.jcs.engine.CacheConstants;
33  import org.apache.jcs.engine.behavior.ICacheElement;
34  import org.apache.jcs.engine.behavior.ICompositeCacheAttributes;
35  import org.apache.jcs.engine.behavior.IElementAttributes;
36  import org.apache.jcs.engine.control.CompositeCache;
37  import org.apache.jcs.engine.control.group.GroupAttrName;
38  import org.apache.jcs.engine.control.group.GroupId;
39  import org.apache.jcs.engine.memory.shrinking.ShrinkerThread;
40  import org.apache.jcs.engine.stats.Stats;
41  import org.apache.jcs.engine.stats.behavior.IStats;
42  
43  import EDU.oswego.cs.dl.util.concurrent.ClockDaemon;
44  import EDU.oswego.cs.dl.util.concurrent.ThreadFactory;
45  
46  /***
47   * Some common code for the LRU and MRU caches.
48   * <p>
49   * This keeps a static reference to a memory shrinker clock daemon. If this
50   * region is configured to use the shrinker, the clock daemon will be setup to
51   * run the shrinker on this region.
52   * @version $Id: AbstractMemoryCache.java 536904 2007-05-10 16:03:42Z tv $
53   */
54  public abstract class AbstractMemoryCache
55      implements MemoryCache, Serializable
56  {
57      private final static Log log = LogFactory.getLog( AbstractMemoryCache.class );
58  
59      private static final int DEFAULT_CHUNK_SIZE = 2;
60  
61      /*** The region name. This defines a namespace of sorts. */
62      protected String cacheName;
63  
64      /***
65       * Map where items are stored by key
66       */
67      protected Map map;
68  
69      /***
70       * Region Elemental Attributes, used as a default.
71       */
72      public IElementAttributes attr;
73  
74      /***
75       * Cache Attributes
76       */
77      public ICompositeCacheAttributes cattr;
78  
79      /***
80       * The cache region this store is associated with
81       */
82      protected CompositeCache cache;
83  
84      /*** status */
85      protected int status;
86  
87      /*** How many to spool at a time. TODO make configurable */
88      protected int chunkSize = DEFAULT_CHUNK_SIZE;
89  
90      /***
91       * The background memory shrinker, one for all regions.
92       */
93      private static ClockDaemon shrinkerDaemon;
94  
95      /***
96       * Constructor for the LRUMemoryCache object
97       */
98      public AbstractMemoryCache()
99      {
100         status = CacheConstants.STATUS_ERROR;
101         map = new Hashtable();
102     }
103 
104     /***
105      * For post reflection creation initialization
106      * @param hub
107      */
108     public synchronized void initialize( CompositeCache hub )
109     {
110         this.cacheName = hub.getCacheName();
111         this.cattr = hub.getCacheAttributes();
112         this.cache = hub;
113 
114         status = CacheConstants.STATUS_ALIVE;
115 
116         if ( cattr.getUseMemoryShrinker() )
117         {
118             if ( shrinkerDaemon == null )
119             {
120                 shrinkerDaemon = new ClockDaemon();
121                 shrinkerDaemon.setThreadFactory( new MyThreadFactory() );
122             }
123             shrinkerDaemon.executePeriodically( cattr.getShrinkerIntervalSeconds() * 1000, new ShrinkerThread( this ),
124                                                 false );
125 
126         }
127     }
128 
129     /***
130      * Removes an item from the cache
131      * @param key
132      *            Identifies item to be removed
133      * @return Description of the Return Value
134      * @exception IOException
135      *                Description of the Exception
136      */
137     public abstract boolean remove( Serializable key )
138         throws IOException;
139 
140     /***
141      * Get an item from the cache
142      * @param key
143      *            Description of the Parameter
144      * @return Description of the Return Value
145      * @exception IOException
146      *                Description of the Exception
147      */
148     public abstract ICacheElement get( Serializable key )
149         throws IOException;
150 
151     /***
152      * Get an item from the cache without affecting its order or last access
153      * time
154      * @param key
155      *            Description of the Parameter
156      * @return The quiet value
157      * @exception IOException
158      *                Description of the Exception
159      */
160     public abstract ICacheElement getQuiet( Serializable key )
161         throws IOException;
162 
163     /***
164      * Puts an item to the cache.
165      * @param ce
166      *            Description of the Parameter
167      * @exception IOException
168      *                Description of the Exception
169      */
170     public abstract void update( ICacheElement ce )
171         throws IOException;
172 
173     /***
174      * Get an Array of the keys for all elements in the memory cache
175      * @return An Object[]
176      */
177     public abstract Object[] getKeyArray();
178 
179     /***
180      * Removes all cached items from the cache.
181      * @exception IOException
182      */
183     public void removeAll()
184         throws IOException
185     {
186         map = new Hashtable();
187     }
188 
189     /***
190      * Prepares for shutdown.
191      * @exception IOException
192      */
193     public void dispose()
194         throws IOException
195     {
196         log.info( "Memory Cache dispose called.  Shutting down shrinker thread if it is running." );
197         if ( shrinkerDaemon != null )
198         {
199             shrinkerDaemon.shutDown();
200         }
201     }
202 
203     /*
204      * (non-Javadoc)
205      * @see org.apache.jcs.engine.memory.MemoryCache#getStatistics()
206      */
207     public IStats getStatistics()
208     {
209         IStats stats = new Stats();
210         stats.setTypeName( "Abstract Memory Cache" );
211         return stats;
212     }
213 
214     /***
215      * Returns the current cache size.
216      * @return The size value
217      */
218     public int getSize()
219     {
220         return this.map.size();
221     }
222 
223     /***
224      * Returns the cache status.
225      * @return The status value
226      */
227     public int getStatus()
228     {
229         return this.status;
230     }
231 
232     /***
233      * Returns the cache name.
234      * @return The cacheName value
235      */
236     public String getCacheName()
237     {
238         return this.cattr.getCacheName();
239     }
240 
241     /***
242      * Puts an item to the cache.
243      * @param ce
244      * @exception IOException
245      */
246     public void waterfal( ICacheElement ce )
247         throws IOException
248     {
249         this.cache.spoolToDisk( ce );
250     }
251 
252     /***
253      * Gets the iterator attribute of the LRUMemoryCache object
254      * @return The iterator value
255      */
256     public Iterator getIterator()
257     {
258         return map.entrySet().iterator();
259     }
260 
261     /***
262      * Returns the CacheAttributes.
263      * @return The CacheAttributes value
264      */
265     public ICompositeCacheAttributes getCacheAttributes()
266     {
267         return this.cattr;
268     }
269 
270     /***
271      * Sets the CacheAttributes.
272      * @param cattr
273      *            The new CacheAttributes value
274      */
275     public void setCacheAttributes( ICompositeCacheAttributes cattr )
276     {
277         this.cattr = cattr;
278     }
279 
280     /***
281      * Gets the cache hub / region that the MemoryCache is used by
282      * @return The cache value
283      */
284     public CompositeCache getCompositeCache()
285     {
286         return this.cache;
287     }
288 
289     public Set getGroupKeys( String groupName )
290     {
291         GroupId groupId = new GroupId( getCacheName(), groupName );
292         HashSet keys = new HashSet();
293         synchronized ( map )
294         {
295             for ( Iterator itr = map.entrySet().iterator(); itr.hasNext(); )
296             {
297                 Map.Entry entry = (Map.Entry) itr.next();
298                 Object k = entry.getKey();
299 
300                 if ( k instanceof GroupAttrName && ( (GroupAttrName) k ).groupId.equals( groupId ) )
301                 {
302                     keys.add( ( (GroupAttrName) k ).attrName );
303                 }
304             }
305         }
306         return keys;
307     }
308 
309     /***
310      * Allows us to set the daemon status on the clockdaemon
311      * @author aaronsm
312      */
313     class MyThreadFactory
314         implements ThreadFactory
315     {
316 
317         /*
318          * (non-Javadoc)
319          * @see EDU.oswego.cs.dl.util.concurrent.ThreadFactory#newThread(java.lang.Runnable)
320          */
321         public Thread newThread( Runnable runner )
322         {
323             Thread t = new Thread( runner );
324             t.setDaemon( true );
325             t.setPriority( Thread.MIN_PRIORITY );
326             return t;
327         }
328     }
329 }