1 package org.apache.jcs.engine.memory;
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
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
205
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
319
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 }