Source Code Cross Referenced for AbstractCache.java in  » Content-Management-System » harmonise » org » openharmonise » commons » cache » Java Source Code / Java DocumentationJava Source Code and Java Documentation

Java Source Code / Java Documentation
1. 6.0 JDK Core
2. 6.0 JDK Modules
3. 6.0 JDK Modules com.sun
4. 6.0 JDK Modules com.sun.java
5. 6.0 JDK Modules sun
6. 6.0 JDK Platform
7. Ajax
8. Apache Harmony Java SE
9. Aspect oriented
10. Authentication Authorization
11. Blogger System
12. Build
13. Byte Code
14. Cache
15. Chart
16. Chat
17. Code Analyzer
18. Collaboration
19. Content Management System
20. Database Client
21. Database DBMS
22. Database JDBC Connection Pool
23. Database ORM
24. Development
25. EJB Server geronimo
26. EJB Server GlassFish
27. EJB Server JBoss 4.2.1
28. EJB Server resin 3.1.5
29. ERP CRM Financial
30. ESB
31. Forum
32. GIS
33. Graphic Library
34. Groupware
35. HTML Parser
36. IDE
37. IDE Eclipse
38. IDE Netbeans
39. Installer
40. Internationalization Localization
41. Inversion of Control
42. Issue Tracking
43. J2EE
44. JBoss
45. JMS
46. JMX
47. Library
48. Mail Clients
49. Net
50. Parser
51. PDF
52. Portal
53. Profiler
54. Project Management
55. Report
56. RSS RDF
57. Rule Engine
58. Science
59. Scripting
60. Search Engine
61. Security
62. Sevlet Container
63. Source Control
64. Swing Library
65. Template Engine
66. Test Coverage
67. Testing
68. UML
69. Web Crawler
70. Web Framework
71. Web Mail
72. Web Server
73. Web Services
74. Web Services apache cxf 2.0.1
75. Web Services AXIS2
76. Wiki Engine
77. Workflow Engines
78. XML
79. XML UI
Java
Java Tutorial
Java Open Source
Jar File Download
Java Articles
Java Products
Java by API
Photoshop Tutorials
Maya Tutorials
Flash Tutorials
3ds-Max Tutorials
Illustrator Tutorials
GIMP Tutorials
C# / C Sharp
C# / CSharp Tutorial
C# / CSharp Open Source
ASP.Net
ASP.NET Tutorial
JavaScript DHTML
JavaScript Tutorial
JavaScript Reference
HTML / CSS
HTML CSS Reference
C / ANSI-C
C Tutorial
C++
C++ Tutorial
Ruby
PHP
Python
Python Tutorial
Python Open Source
SQL Server / T-SQL
SQL Server / T-SQL Tutorial
Oracle PL / SQL
Oracle PL/SQL Tutorial
PostgreSQL
SQL / MySQL
MySQL Tutorial
VB.Net
VB.Net Tutorial
Flash / Flex / ActionScript
VBA / Excel / Access / Word
XML
XML Tutorial
Microsoft Office PowerPoint 2007 Tutorial
Microsoft Office Excel 2007 Tutorial
Microsoft Office Word 2007 Tutorial
Java Source Code / Java Documentation » Content Management System » harmonise » org.openharmonise.commons.cache 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


001:        /*
002:         * The contents of this file are subject to the 
003:         * Mozilla Public License Version 1.1 (the "License"); 
004:         * you may not use this file except in compliance with the License. 
005:         * You may obtain a copy of the License at http://www.mozilla.org/MPL/
006:         *
007:         * Software distributed under the License is distributed on an "AS IS"
008:         * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. 
009:         * See the License for the specific language governing rights and 
010:         * limitations under the License.
011:         *
012:         * The Initial Developer of the Original Code is Simulacra Media Ltd.
013:         * Portions created by Simulacra Media Ltd are Copyright (C) Simulacra Media Ltd, 2004.
014:         *
015:         * All Rights Reserved.
016:         *
017:         * Contributor(s):
018:         */
019:        package org.openharmonise.commons.cache;
020:
021:        import java.util.*;
022:        import java.util.logging.*;
023:
024:        import EDU.oswego.cs.dl.util.concurrent.*;
025:
026:        /**
027:         * Abstract class providing the base functionality for object caching. The 
028:         * cache has a maximum size limit and will page out as required if that limit 
029:         * is reached, paging out in descending order of time since last access. If the
030:         * memory limit of the machine is reached before the cache pages our, the cache 
031:         * will clear and reduce all the cache sizes by a given ratio.
032:         * 
033:         * 
034:         * @author Michael Bell
035:         * @author John King
036:         * @version $Revision: 1.2 $
037:         *
038:         */
039:        public abstract class AbstractCache {
040:
041:            /**
042:             * Default cache size.
043:             */
044:            public static final int DEFAULT_CACHESIZE = 3500;
045:
046:            /**
047:             * Constant indicating a change based on a save action.
048:             */
049:            public static final String CHANGE_SAVE = "save";
050:
051:            /**
052:             * Constant indicating a change based on a delete action.
053:             */
054:            public static final String CHANGE_DELETE = "delete";
055:
056:            /**
057:             * Constant indicating a change based on an update action.
058:             */
059:            public static final String CHANGE_UPDATE = "update";
060:
061:            /**
062:             * Constant indicating a change based on an temporary action.
063:             */
064:            public static final String CHANGE_TEMP = "temp";
065:
066:            /**
067:             * Default percentage of the available memory that needs to be reached before 
068:             * the cache sizes are automatically reduced.
069:             */
070:            public static final double DEFAULT_CACHELIMIT_PERCENT = 0.9;
071:
072:            /**
073:             * Default percentage that cache sizes are reduced by when the memory limit
074:             * has been reached.
075:             */
076:            public static final double DEFAULT_CACHEREDUCTION_RATIO = 0.95;
077:
078:            /**
079:             * List of caches which which retain their size if the memory limit is reached.
080:             */
081:            private static List m_protected_caches = null;
082:
083:            /**
084:             * Static Map containing all caches.
085:             */
086:            private static Map m_all_caches;
087:
088:            /**
089:             * Logger for this class.
090:             */
091:            private static Logger m_logger = Logger
092:                    .getLogger(AbstractCache.class.getName());
093:
094:            static {
095:                //initialise cache map
096:                m_all_caches = Collections.synchronizedMap(new HashMap());
097:            }
098:
099:            /**
100:             * Name of current cache.
101:             */
102:            private String m_cache_name;
103:
104:            /**
105:             * Map containing all cached objects.
106:             */
107:            private LRUCacheMap m_cache;
108:
109:            /**
110:             * Current cache size limit.
111:             */
112:            private int m_max_cache_size;
113:
114:            /**
115:             * Cache size limit at beginning of cache life.
116:             */
117:            private int m_init_max_cache_size;
118:
119:            /**
120:             * Estimate of avarage object size.
121:             */
122:            private long m_total_object_size_estimate = 0;
123:
124:            /**
125:             * Current heap size.
126:             */
127:            private int m_heap_size = -1; //
128:
129:            /**
130:             * Read-write lock to enable locking of cache access.
131:             */
132:            private ReadWriteLock lock = new WriterPreferenceReadWriteLock();
133:
134:            /**
135:             * Creates new cache with given parameters.
136:             * 
137:             * @param cache_name the name of cache
138:             * @param cache_size the initial size of cache
139:             * @param cache_pagesize the paging size
140:             * @throws CacheException if an error occurs in object construction
141:             */
142:            protected AbstractCache(String cache_name, int cache_size)
143:                    throws CacheException {
144:                m_cache_name = cache_name;
145:                m_init_max_cache_size = cache_size;
146:                m_max_cache_size = cache_size;
147:                m_cache = new LRUCacheMap(cache_size);
148:
149:                m_all_caches.put(m_cache_name, this );
150:            }
151:
152:            /**
153:             * Creates cache with default parameters and the given name.
154:             * 
155:             * @param cache_name the name of cache
156:             * @throws CacheException if an error occurs in object construction
157:             */
158:            protected AbstractCache(String cache_name) throws CacheException {
159:                this (cache_name, DEFAULT_CACHESIZE);
160:
161:                m_all_caches.put(m_cache_name, this );
162:            }
163:
164:            /**
165:             * Returns cache object matching the given cache key.
166:             * 
167:             * @param key the cache key which corresponds to required cached object
168:             * @return the object in cache corresponding to given cache key
169:             * @throws CacheException if an error occurs accessing object in cache
170:             * @throws InterruptedException
171:             * @throws RuntimeException if object is not in cache
172:             */
173:            public Object getObject(final Object key) throws CacheException {
174:
175:                // obtain read lock
176:                Object cached_object = null;
177:                try {
178:                    lock.readLock().acquire();
179:                    cached_object = m_cache.get(key);
180:                    lock.readLock().release();
181:                    if (cached_object == null) {
182:                        cached_object = addToCache(key);
183:                    }
184:
185:                } catch (InterruptedException e) {
186:                    throw new CacheException(e);
187:                }
188:
189:                return cached_object;
190:            }
191:
192:            /**
193:             * Returns a pointer to the cached object referenced by the key.
194:             * 
195:             * @param key the cache key which corresponds to required cached object
196:             * @return a <code>CachePointer</code> referencing the cached object corresponding to given cache key
197:             * @throws InterruptedException
198:             * @throws CacheException
199:             * 
200:             */
201:            public CachePointer getObjectPointer(Object key)
202:                    throws CacheException {
203:
204:                //Call 'getObject' to make sure any exceptions which may get  
205:                //thrown when getting the object are thrown here  
206:                Object obj = getObject(key);
207:
208:                return new CachePointer(key, this );
209:            }
210:
211:            /**
212:             * Adds an object to the cache which corresponds to the given cache key,
213:             * calls <code>getCacheableObject</code> to get the object to cache.
214:             * 
215:             * @param key the cache key which corresponds to required cached object
216:             * @return the object which was existing in the cache for the given key, 
217:             * if there was already an object for the cache key.
218:             * 
219:             * @throws RuntimeException if any exceptions are thrown during execution
220:             * @throws CacheException note that the code will be changed to throw this
221:             * exceptoin in the future rather than a <code>RuntimeException</code>
222:             */
223:            protected Object addToCache(Object key) throws CacheException {
224:                Object cacheable_object = null;
225:                try {
226:
227:                    cacheable_object = getCacheableObject(key);
228:                    addToCache(key, cacheable_object);
229:                } catch (java.lang.OutOfMemoryError e) {
230:                    // note if we get here it seems to be too late to recover
231:                    // white pages appear
232:                    AbstractCache.clearAllCaches();
233:
234:                    Runtime runtime = Runtime.getRuntime();
235:
236:                    String error_msg = (m_cache_name
237:                            + " cache: "
238:                            + " Thrown OutOfMemoryError Exception"
239:                            + " Not enough memory to allocate cacheable object "
240:                            + ", free memory: " + runtime.freeMemory()
241:                            + ", total memory: " + runtime.totalMemory()
242:                            + ", probable needed memory: " + getAvgObjectSizeOfEstimate());
243:
244:                    m_logger.log(Level.SEVERE, error_msg, e);
245:                } catch (Exception e) {
246:                    throw new CacheException(e);
247:                }
248:                return cacheable_object;
249:            }
250:
251:            /**
252:             * Returns an estimate of the average size of an object in the cache.
253:             * 
254:             * @return an estimate of the average size of an object in the cache
255:             */
256:            public long getAvgObjectSizeOfEstimate() {
257:                // average, estimate only :)
258:                return (m_cache.size() == 0) ? 0 : Math
259:                        .round(m_total_object_size_estimate / m_cache.size());
260:            }
261:
262:            /**
263:             * Adds the <code>cacheable_object</code> to the cache with the given
264:             * cache key <code>key</code>.
265:             * 
266:             * @param key the cache key
267:             * @param cacheable_object the object to be cached
268:             * @throws InterruptedException
269:             * 
270:             * @throws RuntimeException if any exceptions are thrown during execution
271:             */
272:            public void addToCache(Object key, Object cacheable_object) {
273:
274:                if (m_logger.getLevel() == Level.FINE) {
275:                    StringBuffer sbuf = new StringBuffer();
276:                    sbuf.append(m_cache_name).append(": cache size - ").append(
277:                            m_cache.size()).append(", m_max_cache_size - ")
278:                            .append(m_max_cache_size);
279:                    m_logger.log(Level.FINE, sbuf.toString());
280:                }
281:
282:                try {
283:                    lock.writeLock().acquire();
284:                    m_cache.put(key, cacheable_object);
285:                    lock.writeLock().release();
286:                } catch (InterruptedException e) {
287:                    throw new RuntimeException(e);
288:                }
289:
290:            }
291:
292:            /**
293:             * Removes object associated to the specified cache key from 
294:             * the cache.
295:             * 
296:             * @param key the cache key
297:             */
298:            protected void removeObjectFromCache(Object key) {
299:                try {
300:                    lock.writeLock().acquire();
301:                    m_cache.remove(key);
302:                    lock.writeLock().release();
303:                } catch (InterruptedException e) {
304:                    m_logger.log(Level.WARNING, e.getLocalizedMessage(), e);
305:                }
306:            }
307:
308:            /**
309:             * Clears all caches in system that extend this abstract cache class.
310:             *
311:             */
312:            static synchronized public void clearAllCaches() {
313:
314:                Iterator cache_iter = m_all_caches.values().iterator();
315:
316:                while (cache_iter.hasNext()) {
317:                    ((AbstractCache) cache_iter.next()).clearCache();
318:                }
319:            }
320:
321:            /**
322:             * Clears this cache.
323:             * @throws InterruptedException
324:             *
325:             */
326:            public void clearCache() {
327:                try {
328:                    lock.writeLock().acquire();
329:
330:                    m_cache.clear();
331:                    lock.writeLock().release();
332:                } catch (InterruptedException e) {
333:                    throw new RuntimeException(e);
334:                }
335:            }
336:
337:            /**
338:             * Returns the current cache size, taken from the <code>Map</code> that 
339:             * contains all objects.
340:             * 
341:             * @return the size of the cache
342:             */
343:            public int getCacheSize() {
344:                return m_cache.size();
345:            }
346:
347:            /**
348:             * Returns the name of the cache.
349:             * 
350:             * @return the name of the cache
351:             */
352:            public String getCacheName() {
353:                return this .m_cache_name;
354:            }
355:
356:            /**
357:             * Returns the current maximum size of the cache.
358:             * 
359:             * @return the current maximum size of the cache
360:             */
361:            public int getCacheMaxSize() {
362:                return m_max_cache_size;
363:            }
364:
365:            /**
366:             * Sets the maximum cache size.
367:             * 
368:             * @param maxSize the maximum size for the cache
369:             */
370:            public void setCacheMaxSize(int maxSize) {
371:
372:                try {
373:                    LRUCacheMap new_cache = new LRUCacheMap(maxSize);
374:                    lock.readLock().acquire();
375:                    int i = 0;
376:                    for (Iterator iter = m_cache.keySet().iterator(); iter
377:                            .hasNext()
378:                            && i < maxSize; i++) {
379:                        Object key = (Object) iter.next();
380:                        new_cache.put(key, m_cache.get(key));
381:                    }
382:                    lock.readLock().release();
383:
384:                    lock.writeLock().acquire();
385:                    m_cache = new_cache;
386:                    lock.writeLock().release();
387:                } catch (InterruptedException e) {
388:                    m_logger.log(Level.WARNING, e.getLocalizedMessage(), e);
389:                }
390:            }
391:
392:            /**
393:             * Returns the list of keys for the most accessed objects of the size given.
394:             * 
395:             * @param num_favourites the number of keys to return in list
396:             * 
397:             * @return a list of the keys of the most accessed objects
398:             */
399:            public List getCacheTopKeys(int num_favourites) {
400:                List toReturn = null;
401:
402:                try {
403:                    lock.readLock().acquire();
404:                    toReturn = new Vector(m_cache.values()).subList(0, (m_cache
405:                            .size() > num_favourites) ? num_favourites
406:                            : m_cache.size());
407:                    lock.readLock().release();
408:                } catch (InterruptedException e) {
409:                    m_logger.log(Level.WARNING, e.getLocalizedMessage(), e);
410:                }
411:                return toReturn;
412:
413:            }
414:
415:            /**
416:             * Returns a <code>Set</code> of cache keys.
417:             * 
418:             * @return a <code>Set</code> of cache keys
419:             */
420:            public Set getCacheKeys() {
421:                Set toReturn = null;
422:                try {
423:                    lock.readLock().acquire();
424:                    toReturn = new HashSet(m_cache.keySet());
425:                    lock.readLock().release();
426:                } catch (InterruptedException e) {
427:                    m_logger.log(Level.WARNING, e.getLocalizedMessage(), e);
428:                }
429:                return toReturn;
430:            }
431:
432:            /**
433:             * Returns <code>true</code> if the given key is contained in the cache.
434:             * 
435:             * @param cache_key a cache key
436:             * @return <code>true</code> if this cache contains this key
437:             * @throws InterruptedException
438:             */
439:            public boolean containsKey(Object cache_key)
440:                    throws InterruptedException {
441:                lock.readLock().acquire();
442:                boolean containsKeyFlag = m_cache.containsKey(cache_key);
443:                lock.readLock().release();
444:                return containsKeyFlag;
445:            }
446:
447:            /**
448:             * Sets whether this cache checks objects for dependancies before
449:             * paging the object out. If, when checking for dependancies, the object is 
450:             * found to have dependances the object will not be paged out.
451:             * 
452:             * 
453:             * @param bIsDepAware <code>true</code> if the cache should check dependancies
454:             * of an object before paging it out of the cache.
455:             */
456:            public void setDependancyAware(boolean bIsDepAware) {
457:                m_cache.setDependancyAware(bIsDepAware);
458:            }
459:
460:            /**
461:             * Returns <code>true</code> if this cache will check an object for 
462:             * dependancies before paging the object out.
463:             * 
464:             * @return
465:             */
466:            public boolean isDependancyAware() {
467:                return m_cache.isDependancyAware();
468:            }
469:
470:            /**
471:             * Returns a cacheable object from the given key.
472:             * 
473:             * @param key cache key for object
474:             * @return Object to be cached
475:             * @throws Exception if any error occurs
476:             */
477:            protected abstract Object getCacheableObject(Object key)
478:                    throws Exception;
479:
480:            /**
481:             * Changes object in cache, depending on the change code <code>sChangeCode</code>
482:             * the object will be deleted from the cache or replaced with the new object
483:             * <code>newObject</code>.
484:             * 
485:             * @param cache_key key of changed object
486:             * @param sChangeCode code of change
487:             * @param newObject new object which corresponds with the cache key
488:             * @throws InterruptedException
489:             */
490:            public void changeObject(Object cache_key, String sChangeCode,
491:                    Object newObject) {
492:
493:                try {
494:                    lock.writeLock().acquire();
495:                    m_cache.remove(cache_key);
496:
497:                    if (sChangeCode.equalsIgnoreCase(CHANGE_SAVE)
498:                            || sChangeCode.equalsIgnoreCase(CHANGE_UPDATE)) {
499:                        addToCache(cache_key, newObject);
500:                    }
501:                    lock.writeLock().release();
502:                } catch (InterruptedException e) {
503:                    m_logger.log(Level.WARNING, e.getLocalizedMessage(), e);
504:                    throw new RuntimeException(e);
505:                }
506:            }
507:
508:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.