1 package org.apache.jcs.access;
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
25 import org.apache.commons.logging.Log;
26 import org.apache.commons.logging.LogFactory;
27 import org.apache.jcs.access.behavior.ICacheAccess;
28 import org.apache.jcs.access.exception.CacheException;
29 import org.apache.jcs.access.exception.InvalidArgumentException;
30 import org.apache.jcs.access.exception.InvalidHandleException;
31 import org.apache.jcs.access.exception.ObjectExistsException;
32 import org.apache.jcs.engine.CacheElement;
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.CompositeCacheManager;
38 import org.apache.jcs.engine.stats.behavior.ICacheStats;
39
40 /***
41 * This class provides an interface for all types of access to the cache.
42 * <p>
43 * An instance of this class is tied to a specific cache region. Static methods are provided to get
44 * such instances.
45 * <p>
46 * Using this class you can retrieve an item, the items wrapper, the element configuration, put an
47 * item in the cache, remove an item, and clear a region.
48 * <p>
49 * The JCS class is the prefered way to access these methods.
50 */
51 public class CacheAccess
52 implements ICacheAccess
53 {
54 /*** The logger. */
55 private static final Log log = LogFactory.getLog( CacheAccess.class );
56
57 /***
58 * Cache manager use by the various forms of defineRegion and getAccess
59 */
60 private static CompositeCacheManager cacheMgr;
61
62 /***
63 * The cache that a given instance of this class provides access to.
64 * <p>
65 * @TODO Should this be the inteface?
66 */
67 protected CompositeCache cacheControl;
68
69 /***
70 * Constructor for the CacheAccess object.
71 * <p>
72 * @param cacheControl The cache which the created instance accesses
73 */
74 public CacheAccess( CompositeCache cacheControl )
75 {
76 this.cacheControl = cacheControl;
77 }
78
79
80
81 /***
82 * Define a new cache region with the given name. In the oracle specification, these attributes
83 * are global and not region specific, regional overirdes is a value add each region should be
84 * able to house both cache and element attribute sets. It is more efficient to define a cache
85 * in the props file and then strictly use the get access method. Use of the define region
86 * outside of an initialization block should be avoided.
87 * <p>
88 * @param name Name that will identify the region
89 * @return CacheAccess instance for the new region
90 * @exception CacheException
91 */
92 public static CacheAccess defineRegion( String name )
93 throws CacheException
94 {
95 ensureCacheManager();
96
97 return new CacheAccess( cacheMgr.getCache( name ) );
98 }
99
100 /***
101 * Define a new cache region with the specified name and attributes.
102 * <p>
103 * @param name Name that will identify the region
104 * @param cattr CompositeCacheAttributes for the region
105 * @return CacheAccess instance for the new region
106 * @exception CacheException
107 */
108 public static CacheAccess defineRegion( String name, ICompositeCacheAttributes cattr )
109 throws CacheException
110 {
111 ensureCacheManager();
112
113 return new CacheAccess( cacheMgr.getCache( name, cattr ) );
114 }
115
116 /***
117 * Define a new cache region with the specified name and attributes and return a CacheAccess to
118 * it.
119 * <p>
120 * @param name Name that will identify the region
121 * @param cattr CompositeCacheAttributes for the region
122 * @param attr Attributes for the region
123 * @return CacheAccess instance for the new region
124 * @exception CacheException
125 */
126 public static CacheAccess defineRegion( String name, ICompositeCacheAttributes cattr, IElementAttributes attr )
127 throws CacheException
128 {
129 ensureCacheManager();
130
131 return new CacheAccess( cacheMgr.getCache( name, cattr, attr ) );
132 }
133
134 /***
135 * Get a CacheAccess instance for the given region.
136 * <p>
137 * @param region Name that identifies the region
138 * @return CacheAccess instance for region
139 * @exception CacheException
140 */
141 public static CacheAccess getAccess( String region )
142 throws CacheException
143 {
144 ensureCacheManager();
145
146 return new CacheAccess( cacheMgr.getCache( region ) );
147 }
148
149 /***
150 * Get a CacheAccess instance for the given region with the given attributes.
151 * <p>
152 * @param region Name that identifies the region
153 * @param icca
154 * @return CacheAccess instance for region
155 * @exception CacheException
156 */
157 public static CacheAccess getAccess( String region, ICompositeCacheAttributes icca )
158 throws CacheException
159 {
160 ensureCacheManager();
161
162 return new CacheAccess( cacheMgr.getCache( region, icca ) );
163 }
164
165 /***
166 * Helper method which checks to make sure the cacheMgr class field is set, and if not requests
167 * an instance from CacheManagerFactory.
168 */
169 protected static void ensureCacheManager()
170 {
171 synchronized ( CacheAccess.class )
172 {
173 if ( cacheMgr == null )
174 {
175 cacheMgr = CompositeCacheManager.getInstance();
176 }
177 }
178 }
179
180
181
182 /***
183 * Retrieve an object from the cache region this instance provides access to.
184 * <p>
185 * @param name Key the object is stored as
186 * @return The object if found or null
187 */
188 public Object get( Object name )
189 {
190 ICacheElement element = this.cacheControl.get( (Serializable) name );
191
192 return ( element != null ) ? element.getVal() : null;
193 }
194
195 /***
196 * This method returns the ICacheElement wrapper which provides access to element info and other
197 * attributes.
198 * <p>
199 * This returns a reference to the wrapper. Any modifications will be reflected in the cache. No
200 * defensive copy is made.
201 * <p>
202 * This method is most useful if you want to determine things such as the how long the element
203 * has been in the cache.
204 * <p>
205 * The last access time in teh ElementAttributes should be current.
206 * <p>
207 * @param name Key the object is stored as
208 * @return The ICacheElement if the object is found or null
209 */
210 public ICacheElement getCacheElement( Object name )
211 {
212 return this.cacheControl.get( (Serializable) name );
213 }
214
215 /***
216 * Place a new object in the cache, associated with key name. If there is currently an object
217 * associated with name in the region an ObjectExistsException is thrown. Names are scoped to a
218 * region so they must be unique within the region they are placed.
219 * <p>
220 * @param key Key object will be stored with
221 * @param value Object to store
222 * @exception CacheException and ObjectExistsException is thrown if the item is already in the
223 * cache.
224 */
225 public void putSafe( Object key, Object value )
226 throws CacheException
227 {
228 if ( this.cacheControl.get( (Serializable) key ) != null )
229 {
230 throw new ObjectExistsException( "putSafe failed. Object exists in the cache for key [" + key
231 + "]. Remove first or use a non-safe put to override the value." );
232 }
233 put( key, value );
234 }
235
236 /***
237 * Place a new object in the cache, associated with key name. If there is currently an object
238 * associated with name in the region it is replaced. Names are scoped to a region so they must
239 * be unique within the region they are placed. ObjectExistsException
240 * @param name Key object will be stored with
241 * @param obj Object to store
242 * @exception CacheException
243 */
244 public void put( Object name, Object obj )
245 throws CacheException
246 {
247
248
249 put( name, obj, this.cacheControl.getElementAttributes() );
250 }
251
252 /***
253 * Constructs a cache element with these attribures, and puts it into the cache.
254 * <p>
255 * If the key or the value is null, and InvalidArgumentException is thrown.
256 * <p>
257 * @see org.apache.jcs.access.behavior.ICacheAccess#put(java.lang.Object, java.lang.Object,
258 * org.apache.jcs.engine.behavior.IElementAttributes)
259 */
260 public void put( Object key, Object val, IElementAttributes attr )
261 throws CacheException
262 {
263 if ( key == null )
264 {
265 throw new InvalidArgumentException( "Key must not be null" );
266 }
267 else if ( val == null )
268 {
269 throw new InvalidArgumentException( "Value must not be null" );
270 }
271
272
273
274 try
275 {
276 CacheElement ce = new CacheElement( this.cacheControl.getCacheName(), (Serializable) key,
277 (Serializable) val );
278
279 ce.setElementAttributes( attr );
280
281 this.cacheControl.update( ce );
282 }
283 catch ( Exception e )
284 {
285 throw new CacheException( e );
286 }
287 }
288
289 /***
290 * Destory the region and all objects within it. After calling this method, the Cache object can
291 * no longer be used as it will be closed.
292 * <p>
293 * @exception CacheException
294 * @deprecated
295 */
296 public void destroy()
297 throws CacheException
298 {
299 try
300 {
301 this.cacheControl.removeAll();
302 }
303 catch ( IOException e )
304 {
305 throw new CacheException( e );
306 }
307 }
308
309 /***
310 * Removes all of the elements from a region.
311 * <p>
312 * @deprecated use clear()
313 * @throws CacheException
314 */
315 public void remove()
316 throws CacheException
317 {
318 clear();
319 }
320
321 /***
322 * Removes all of the elements from a region.
323 * <p>
324 * @throws CacheException
325 */
326 public void clear()
327 throws CacheException
328 {
329 try
330 {
331 this.cacheControl.removeAll();
332 }
333 catch ( IOException e )
334 {
335 throw new CacheException( e );
336 }
337 }
338
339 /***
340 * Invalidate all objects associated with key name, removing all references to the objects from
341 * the cache.
342 * <p>
343 * @param name Key that specifies object to invalidate
344 * @exception CacheException
345 * @deprecated use remove
346 */
347 public void destroy( Object name )
348 throws CacheException
349 {
350 this.cacheControl.remove( (Serializable) name );
351 }
352
353 /***
354 * Removes a single item by name.
355 * <p>
356 * @param name the name of the item to remove.
357 * @throws CacheException
358 */
359 public void remove( Object name )
360 throws CacheException
361 {
362 this.cacheControl.remove( (Serializable) name );
363 }
364
365 /***
366 * ResetAttributes allows for some of the attributes of a region to be reset in particular
367 * expiration time attriubtes, time to live, default time to live and idle time, and event
368 * handlers. Changing default settings on groups and regions will not affect existing objects.
369 * Only object loaded after the reset will use the new defaults. If no name argument is
370 * provided, the reset is applied to the region.
371 * <p>
372 * NOTE: this method is does not reset the attributes for items already in the cache. It could
373 * potentially do this for items in memory, and maybe on disk (which would be slow) but not
374 * remote items. Rather than have unpredicatble behavior, this method just sets the default
375 * attributes.
376 * <p>
377 * TODO is should be renamed "setDefaultElementAttributes"
378 * <p>
379 * @deprecated As of release 1.3
380 * @see setDefaultElementAttributes
381 * @param attr New attributes for this region.
382 * @exception CacheException
383 * @exception InvalidHandleException
384 */
385 public void resetElementAttributes( IElementAttributes attr )
386 throws CacheException, InvalidHandleException
387 {
388 this.cacheControl.setElementAttributes( attr );
389 }
390
391 /***
392 * This method is does not reset the attributes for items already in the cache. It could
393 * potentially do this for items in memory, and maybe on disk (which would be slow) but not
394 * remote items. Rather than have unpredicatble behavior, this method just sets the default
395 * attributes. Items subsequently put into the cache will use these defaults if they do not
396 * specify specific attributes.
397 * <p>
398 * @param attr the default attributes.
399 * @throws CacheException if something goes wrong.
400 */
401 public void setDefaultElementAttributes( IElementAttributes attr )
402 throws CacheException
403 {
404 this.cacheControl.setElementAttributes( attr );
405 }
406
407 /***
408 * Reset attributes for a particular element in the cache. NOTE: this method is currently not
409 * implemented.
410 * <p>
411 * @param name Key of object to reset attributes for
412 * @param attr New attributes for the object
413 * @exception CacheException
414 * @exception InvalidHandleException if the item does not exist.
415 */
416 public void resetElementAttributes( Object name, IElementAttributes attr )
417 throws CacheException, InvalidHandleException
418 {
419 ICacheElement element = this.cacheControl.get( (Serializable) name );
420 if ( element == null )
421 {
422 throw new InvalidHandleException( "Object for name [" + name + "] is not in the cache" );
423 }
424
425
426
427
428
429 put( element.getKey(), element.getVal(), attr );
430
431 }
432
433 /***
434 * GetElementAttributes will return an attribute object describing the current attributes
435 * associated with the object name.
436 * <p>
437 * This was confusing, so I created a new method with a clear name.
438 * <p>
439 * @deprecated As of release 1.3
440 * @see getDefaultElementAttributes
441 * @return Attributes for this region
442 * @exception CacheException
443 */
444 public IElementAttributes getElementAttributes()
445 throws CacheException
446 {
447 return this.cacheControl.getElementAttributes();
448 }
449
450 /***
451 * Retrieves A COPY OF the default element attributes used by this region. This does not provide
452 * a reference to the element attributes.
453 * <p>
454 * Each time an element is added to the cache without element attributes, the default element
455 * attributes are cloned.
456 * <p>
457 * @return the deafualt element attributes used by this region.
458 * @throws CacheException
459 */
460 public IElementAttributes getDefaultElementAttributes()
461 throws CacheException
462 {
463 return this.cacheControl.getElementAttributes();
464 }
465
466 /***
467 * GetElementAttributes will return an attribute object describing the current attributes
468 * associated with the object name. The name object must override the Object.equals and
469 * Object.hashCode methods.
470 * <p>
471 * @param name Key of object to get attributes for
472 * @return Attributes for the object, null if object not in cache
473 * @exception CacheException
474 */
475 public IElementAttributes getElementAttributes( Object name )
476 throws CacheException
477 {
478 IElementAttributes attr = null;
479
480 try
481 {
482 attr = this.cacheControl.getElementAttributes( (Serializable) name );
483 }
484 catch ( IOException ioe )
485 {
486 log.error( "Failure getting element attributes", ioe );
487 }
488
489 return attr;
490 }
491
492 /***
493 * This returns the ICacheStats object with information on this region and its auxiliaries.
494 * <p>
495 * This data can be formatted as needed.
496 * <p>
497 * @return ICacheStats
498 */
499 public ICacheStats getStatistics()
500 {
501 return this.cacheControl.getStatistics();
502 }
503
504 /***
505 * @return A String version of the stats.
506 */
507 public String getStats()
508 {
509 return this.cacheControl.getStats();
510 }
511
512 /***
513 * Dispose this region. Flushes objects to and closes auxiliary caches. This is a shutdown
514 * command!
515 * <p>
516 * To simply remove all elements from the region use clear().
517 */
518 public void dispose()
519 {
520 this.cacheControl.dispose();
521 }
522
523 /***
524 * Gets the ICompositeCacheAttributes of the cache region.
525 * <p>
526 * @return ICompositeCacheAttributes, the controllers config info, defined in the top section of
527 * a region definition.
528 */
529 public ICompositeCacheAttributes getCacheAttributes()
530 {
531 return this.cacheControl.getCacheAttributes();
532 }
533
534 /***
535 * Sets the ICompositeCacheAttributes of the cache region.
536 * <p>
537 * @param cattr The new ICompositeCacheAttribute value
538 */
539 public void setCacheAttributes( ICompositeCacheAttributes cattr )
540 {
541 this.cacheControl.setCacheAttributes( cattr );
542 }
543
544 /***
545 * This instructs the memory cache to remove the <i>numberToFree</i> according to its eviction
546 * policy. For example, the LRUMemoryCache will remove the <i>numberToFree</i> least recently
547 * used items. These will be spooled to disk if a disk auxiliary is available.
548 * <p>
549 * @param numberToFree
550 * @return the number that were removed. if you ask to free 5, but there are only 3, you will
551 * get 3.
552 * @throws CacheException
553 */
554 public int freeMemoryElements( int numberToFree )
555 throws CacheException
556 {
557 int numFreed = -1;
558 try
559 {
560 numFreed = this.cacheControl.getMemoryCache().freeElements( numberToFree );
561 }
562 catch ( IOException ioe )
563 {
564 String message = "Failure freeing memory elements. ";
565 log.error( message, ioe );
566 throw new CacheException( message + ioe.getMessage() );
567 }
568 return numFreed;
569 }
570 }