Source Code Cross Referenced for MessageCache.java in  » EJB-Server-JBoss-4.2.1 » messaging » org » jboss » mq » server » 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 » EJB Server JBoss 4.2.1 » messaging » org.jboss.mq.server 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


001:        /*
002:         * JBoss, Home of Professional Open Source.
003:         * Copyright 2006, Red Hat Middleware LLC, and individual contributors
004:         * as indicated by the @author tags. See the copyright.txt file in the
005:         * distribution for a full listing of individual contributors.
006:         *
007:         * This is free software; you can redistribute it and/or modify it
008:         * under the terms of the GNU Lesser General Public License as
009:         * published by the Free Software Foundation; either version 2.1 of
010:         * the License, or (at your option) any later version.
011:         *
012:         * This software is distributed in the hope that it will be useful,
013:         * but WITHOUT ANY WARRANTY; without even the implied warranty of
014:         * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
015:         * Lesser General Public License for more details.
016:         *
017:         * You should have received a copy of the GNU Lesser General Public
018:         * License along with this software; if not, write to the Free
019:         * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
020:         * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
021:         */
022:        package org.jboss.mq.server;
023:
024:        import java.lang.ref.Reference;
025:        import java.lang.ref.ReferenceQueue;
026:        import java.util.HashMap;
027:        import javax.jms.JMSException;
028:        import javax.management.MBeanRegistration;
029:        import javax.management.ObjectName;
030:        import org.jboss.mq.DurableSubscriptionID;
031:        import org.jboss.mq.SpyMessage;
032:        import org.jboss.mq.pm.CacheStore;
033:        import org.jboss.system.ServiceMBeanSupport;
034:        import EDU.oswego.cs.dl.util.concurrent.SynchronizedLong;
035:
036:        /**
037:         * This class implements a Message cache so that larger amounts of messages
038:         * can be processed without running out of memory.  When memory starts getting tight
039:         * it starts moving messages out of memory and into a file so that they can be recovered
040:         * later.
041:         *
042:         * The locks should be obtained in the following order:<br>
043:         * mr, the relevent message we are working with<br>
044:         * lruCache, when maintaining the usage order
045:         *
046:         * @author <a href="mailto:hiram.chirino@jboss.org">Hiram Chirino</a>
047:         * @author <a href="mailto:David.Maplesden@orion.co.nz">David Maplesden</a>
048:         * @author <a href="mailto:pra@tim.se">Peter Antman</a>
049:         * @author <a href="mailto:Adrian.Brock@HappeningTimes.com">Adrian Brock</a>
050:         * @version    $Revision: 57198 $
051:         *
052:         * @jmx.mbean name="jboss.mq:service=MessageCache"
053:         *      extends="org.jboss.system.ServiceMBean"
054:         */
055:        public class MessageCache extends ServiceMBeanSupport implements 
056:                MessageCacheMBean, MBeanRegistration, Runnable {
057:            public static final long ONE_MEGABYTE = 1024L * 1000;
058:            public static final long DEFAULT_HIGH_MEMORY_MARK = ONE_MEGABYTE * 50;
059:            public static final long DEFAULT_MAX_MEMORY_MARK = ONE_MEGABYTE * 60;
060:
061:            // The cached messages are orded in a LRU linked list
062:            private LRUCache lruCache = new LRUCache();
063:
064:            // Provides a Unique ID to MessageHanles
065:            private SynchronizedLong messageCounter = new SynchronizedLong(0);
066:            long cacheHits = 0;
067:            long cacheMisses = 0;
068:
069:            protected CacheStore cacheStore;
070:            ObjectName cacheStoreName;
071:
072:            private Thread referenceSoftner;
073:
074:            private long highMemoryMark = DEFAULT_HIGH_MEMORY_MARK;
075:            private long maxMemoryMark = DEFAULT_MAX_MEMORY_MARK;
076:
077:            /** Whether to make soft references */
078:            private boolean makeSoftReferences = true;
079:
080:            /** The last time we softened */
081:            private long lastSoften = 0L;
082:
083:            /** soften no more than often */
084:            private long softenNoMoreOftenThanMillis = 0L;
085:
086:            /** soften at least every */
087:            private long softenAtLeastEveryMillis = 0L;
088:
089:            /** The length of time to wait before checking whether we should soften messages */
090:            private long softenWaitMillis = 1000L;
091:
092:            /** The minimum number of hard messages */
093:            private int minimumHard = 1;
094:
095:            /** The maximum number of hard messages */
096:            private int maximumHard = 0;
097:
098:            int softRefCacheSize = 0;
099:            int totalCacheSize = 0;
100:
101:            // Used to get notified when message are being deleted by GC
102:            ReferenceQueue referenceQueue = new ReferenceQueue();
103:
104:            // The historical number of softenings
105:            long softenedSize = 0;
106:
107:            // Check the soft reference depth
108:            boolean checkSoftReferenceDepth = false;
109:
110:            /**
111:             * The <code>getInstance</code> method
112:             *
113:             * @return a <code>MessageCache</code> value
114:             *
115:             * @jmx.managed-attribute
116:             */
117:            public MessageCache getInstance() {
118:                return this ;
119:            }
120:
121:            /**
122:             * Adds a message to the cache.
123:             */
124:            public MessageReference add(SpyMessage message, BasicQueue queue,
125:                    int stored) throws javax.jms.JMSException {
126:                DurableSubscriptionID id = message.header.durableSubscriberID;
127:                return addInternal(message, queue, stored, id);
128:            }
129:
130:            /**
131:             * Adds a message to the cache.
132:             */
133:            public MessageReference add(SpyMessage message, BasicQueue queue,
134:                    int stored, DurableSubscriptionID id)
135:                    throws javax.jms.JMSException {
136:                return addInternal(message, queue, stored, id);
137:            }
138:
139:            /**
140:             * Adds a message to the cache.
141:             */
142:            public MessageReference addInternal(SpyMessage message,
143:                    BasicQueue queue, int stored, DurableSubscriptionID id)
144:                    throws javax.jms.JMSException {
145:                // Create the message reference
146:                MessageReference mh = new MessageReference();
147:                mh.init(this , messageCounter.increment(), message, queue, id);
148:                mh.setStored(stored);
149:
150:                // Add it to the cache
151:                synchronized (mh) {
152:                    synchronized (lruCache) {
153:                        lruCache.addMostRecent(mh);
154:                        totalCacheSize++;
155:                    }
156:                }
157:                validateSoftReferenceDepth();
158:
159:                return mh;
160:            }
161:
162:            /**
163:             * removes a message from the cache
164:             */
165:            public void remove(MessageReference mr) throws JMSException {
166:                // Remove if not done already
167:                removeInternal(mr, true, true);
168:            }
169:
170:            /**
171:             * removes a message from the cache without returning it to the pool
172:             * used in two phase removes for joint cache/persistence
173:             */
174:            public void removeDelayed(MessageReference mr) throws JMSException {
175:                // Remove from the cache
176:                removeInternal(mr, true, false);
177:            }
178:
179:            /**
180:             * removes a message from the cache but does not clear it,
181:             * used in softening
182:             */
183:            void soften(MessageReference mr) throws JMSException {
184:                // Remove from the cache
185:                removeInternal(mr, false, false);
186:
187:                if (makeSoftReferences)
188:                    softRefCacheSize++;
189:            }
190:
191:            /**
192:             * removes a message from the cache
193:             */
194:            protected void removeInternal(MessageReference mr, boolean clear,
195:                    boolean reset) throws JMSException {
196:                synchronized (mr) {
197:                    if (mr.stored != MessageReference.REMOVED) {
198:                        synchronized (lruCache) {
199:                            if (mr.hardReference != null) //If message is not hard, dont do lru stuff
200:                                lruCache.remove(mr);
201:                            if (clear)
202:                                totalCacheSize--;
203:                        }
204:                        if (clear)
205:                            mr.clear();
206:                        //Will remove it from storage if stored
207:                    }
208:
209:                    if (reset)
210:                        mr.reset();
211:                    //Return to the pool
212:                }
213:            }
214:
215:            /**
216:             * The strategy is that we keep the most recently used messages as
217:             * Hard references.  Then we make the older ones soft references.  Making
218:             * something a soft reference stores it to disk so we need to avoid making
219:             * soft references if we can avoid it.  But once it is made a soft reference does
220:             * not mean that it is removed from memory.  Depending on how agressive the JVM's
221:             * GC is, it may stay around long enough for it to be used by a client doing a read,
222:             * saving us read from the file system.  If memory gets tight the GC will remove
223:             * the soft references.  What we want to do is make sure there are at least some
224:             * soft references available so that the GC can reclaim memory.
225:             * @see Runnable#run()
226:             */
227:            public void run() {
228:                try {
229:                    while (true) {
230:                        // Get the next soft reference that was canned by the GC
231:                        Reference r = null;
232:                        if (checkSoftReferenceDepth)
233:                            r = referenceQueue.poll();
234:                        else
235:                            r = referenceQueue.remove(softenWaitMillis);
236:                        if (r != null) {
237:                            softRefCacheSize--;
238:                            // the GC will free a set of messages together, so we poll them
239:                            // all before we validate the soft reference depth.
240:                            while ((r = referenceQueue.poll()) != null) {
241:                                softRefCacheSize--;
242:                            }
243:                            if (log.isTraceEnabled())
244:                                log.trace("soft reference cache size is now: "
245:                                        + softRefCacheSize);
246:
247:                            checkSoftReferenceDepth = true;
248:                        }
249:
250:                        long now = System.currentTimeMillis();
251:
252:                        // Don't try to soften too often
253:                        if (softenNoMoreOftenThanMillis > 0
254:                                && (now - lastSoften < softenNoMoreOftenThanMillis))
255:                            checkSoftReferenceDepth = false;
256:
257:                        // Is it a while since we last softened?
258:                        else if (softenAtLeastEveryMillis > 0
259:                                && (now - lastSoften > softenAtLeastEveryMillis))
260:                            checkSoftReferenceDepth = true;
261:
262:                        // Should we check for softening
263:                        if (checkSoftReferenceDepth) {
264:                            checkSoftReferenceDepth = validateSoftReferenceDepth();
265:
266:                            // Did the softening complete?
267:                            if (checkSoftReferenceDepth == false)
268:                                lastSoften = now;
269:                        }
270:                    }
271:                } catch (InterruptedException e) {
272:                    // Signal to exit the thread.
273:                } catch (Throwable t) {
274:                    log.error("Message Cache Thread Stopped: ", t);
275:                }
276:                log.debug("Thread exiting.");
277:            }
278:
279:            /**
280:             * This method is in charge of determining if it time to convert some
281:             * hard references over to soft references.
282:             */
283:            boolean validateSoftReferenceDepth() throws JMSException {
284:                boolean trace = log.isTraceEnabled();
285:
286:                // Loop until softening is not required or we find a message we can soften
287:                while (getState() == ServiceMBeanSupport.STARTED) {
288:                    MessageReference messageToSoften = null;
289:
290:                    synchronized (lruCache) {
291:                        // howmany to change over to soft refs
292:                        int softenCount = 0;
293:                        int hardCount = getHardRefCacheSize();
294:                        int softCount = getSoftRefCacheSize();
295:
296:                        // Only soften down to a minimum
297:                        if (hardCount <= minimumHard)
298:                            return false;
299:
300:                        long currentMem = Runtime.getRuntime().totalMemory()
301:                                - Runtime.getRuntime().freeMemory();
302:                        if (currentMem > highMemoryMark) {
303:                            // we need to get more aggresive... how much?? lets get
304:                            // a mesurment from 0 to 1
305:                            float severity = ((float) (currentMem - highMemoryMark))
306:                                    / (maxMemoryMark - highMemoryMark);
307:                            severity = Math.min(severity, 1.0F);
308:                            if (trace)
309:                                log.trace("Memory usage serverity=" + severity);
310:                            int totalMessageInMem = hardCount + softCount;
311:                            int howManyShouldBeSoft = (int) ((totalMessageInMem) * severity);
312:                            softenCount = howManyShouldBeSoft - softCount;
313:                        }
314:
315:                        // Are there too many messages in memory?
316:                        if (maximumHard > 0) {
317:                            int removeCount = hardCount - maximumHard;
318:                            if (removeCount > 0 && removeCount > softenCount)
319:                                softenCount = removeCount;
320:                        }
321:
322:                        // We can only do so much, somebody else is using all the memory?
323:                        if (softenCount > hardCount) {
324:                            if (trace)
325:                                log.trace("Soften count " + softenCount
326:                                        + " greater than hard references "
327:                                        + hardCount);
328:                            softenCount = hardCount;
329:                        }
330:
331:                        // Ignore soften counts of 1 since this will happen too often even
332:                        // if the serverity is low since it will round up.
333:                        if (softenCount > 1
334:                                || (maximumHard > 0 && hardCount > maximumHard)) {
335:                            if (trace)
336:                                log.trace("Need to soften " + softenCount
337:                                        + " messages");
338:                            Node node = lruCache.getLeastRecent();
339:                            messageToSoften = (MessageReference) node.data;
340:                        }
341:                    }
342:
343:                    // No softening required
344:                    if (messageToSoften == null)
345:                        return false;
346:
347:                    synchronized (messageToSoften) {
348:                        // Soften unless it was removed
349:                        if (messageToSoften.messageCache != null
350:                                && messageToSoften.stored != MessageReference.REMOVED) {
351:                            messageToSoften.makeSoft();
352:                            if (messageToSoften.stored == MessageReference.STORED) {
353:                                softenedSize++;
354:                                return true;
355:                            } else if (messageToSoften.isPersistent()) {
356:                                // Avoid going into a cpu loop if there are persistent
357:                                // messages just about to be persisted
358:                                return false;
359:                            }
360:                        } else if (trace)
361:                            log.trace("not softening removed message "
362:                                    + messageToSoften);
363:                    }
364:                }
365:                return false;
366:            }
367:
368:            /**
369:             * This gets called when a MessageReference is de-referenced.
370:             * We will pop it to the top of the RLU
371:             */
372:            void messageReferenceUsedEvent(MessageReference mh, boolean wasHard)
373:                    throws JMSException {
374:                synchronized (mh) {
375:                    synchronized (lruCache) {
376:                        if (wasHard)
377:                            lruCache.makeMostRecent(mh);
378:                        else {
379:                            lruCache.addMostRecent(mh);
380:                        }
381:                    }
382:                }
383:
384:                if (wasHard == false)
385:                    checkSoftReferenceDepth = true;
386:            }
387:
388:            //////////////////////////////////////////////////////////////////////////////////
389:            // Perisitence methods used by the MessageReference.
390:            //////////////////////////////////////////////////////////////////////////////////
391:            SpyMessage loadFromStorage(MessageReference mh) throws JMSException {
392:                return cacheStore.loadFromStorage(mh);
393:            }
394:
395:            void saveToStorage(MessageReference mh, SpyMessage message)
396:                    throws JMSException {
397:                cacheStore.saveToStorage(mh, message);
398:            }
399:
400:            void removeFromStorage(MessageReference mh) throws JMSException {
401:                cacheStore.removeFromStorage(mh);
402:            }
403:
404:            //////////////////////////////////////////////////////////////////////////////////
405:            //
406:            // The following section deals the the JMX interface to manage the Cache
407:            //
408:            //////////////////////////////////////////////////////////////////////////////////
409:
410:            /**
411:             * This gets called to start the cache service. Synch. by start
412:             */
413:            protected void startService() throws Exception {
414:                setupCacheStore();
415:
416:                referenceSoftner = new Thread(this ,
417:                        "JBossMQ Cache Reference Softner");
418:                referenceSoftner.setDaemon(true);
419:                referenceSoftner.start();
420:            }
421:
422:            protected void setupCacheStore() throws Exception {
423:                cacheStore = (CacheStore) getServer().getAttribute(
424:                        cacheStoreName, "Instance");
425:            }
426:
427:            /**
428:             * This gets called to stop the cache service.
429:             */
430:            protected void stopService() {
431:                synchronized (lruCache) {
432:                    referenceSoftner.interrupt();
433:                    referenceSoftner = null;
434:                }
435:                cacheStore = null;
436:            }
437:
438:            /**
439:             * Gets the hardRefCacheSize
440:             * @return Returns a int
441:             *
442:             * @jmx.managed-attribute
443:             */
444:            public int getHardRefCacheSize() {
445:                synchronized (lruCache) {
446:                    return lruCache.size();
447:                }
448:            }
449:
450:            /**
451:             * The <code>getSoftenedSize</code> method
452:             *
453:             * @return a <code>long</code> value
454:             *
455:             * @jmx.managed-attribute
456:             */
457:            public long getSoftenedSize() {
458:                return softenedSize;
459:            }
460:
461:            /**
462:             * Gets the softRefCacheSize
463:             * @return Returns a int
464:             *
465:             * @jmx.managed-attribute
466:             */
467:            public int getSoftRefCacheSize() {
468:                return softRefCacheSize;
469:            }
470:
471:            /**
472:             * Gets the totalCacheSize
473:             * @return Returns a int
474:             *
475:             * @jmx.managed-attribute
476:             */
477:            public int getTotalCacheSize() {
478:                return totalCacheSize;
479:            }
480:
481:            /**
482:             * Gets the cacheMisses
483:             * @return Returns a int
484:             *
485:             * @jmx.managed-attribute
486:             */
487:            public long getCacheMisses() {
488:                return cacheMisses;
489:            }
490:
491:            /**
492:             * Gets the cacheHits
493:             * @return Returns a long
494:             *
495:             * @jmx.managed-attribute
496:             */
497:            public long getCacheHits() {
498:                return cacheHits;
499:            }
500:
501:            /**
502:             * Gets whether to make soft references
503:             *
504:             * @jmx.managed-attribute
505:             * @return true when making soft references
506:             */
507:            public boolean getMakeSoftReferences() {
508:                return makeSoftReferences;
509:            }
510:
511:            /**
512:             * Sets whether to make soft references
513:             * 
514:             * @jmx.managed-attribute
515:             * @param true to make soft references
516:             */
517:            public void setMakeSoftReferences(boolean makeSoftReferences) {
518:                this .makeSoftReferences = makeSoftReferences;
519:            }
520:
521:            /**
522:             * Gets the minimum number of hard messages
523:             *
524:             * @jmx.managed-attribute
525:             * @return the minimum number of hard messages
526:             */
527:            public int getMinimumHard() {
528:                return minimumHard;
529:            }
530:
531:            /**
532:             * Sets the minimum number of hard messages
533:             * 
534:             * @jmx.managed-attribute
535:             * @param minimumHard the minimum number of hard messages
536:             */
537:            public void setMinimumHard(int minimumHard) {
538:                if (minimumHard < 1)
539:                    this .minimumHard = 1;
540:                else
541:                    this .minimumHard = minimumHard;
542:            }
543:
544:            /**
545:             * Gets the maximum number of hard messages
546:             *
547:             * @jmx.managed-attribute
548:             * @return the minimum number of hard messages
549:             */
550:            public int getMaximumHard() {
551:                return maximumHard;
552:            }
553:
554:            /**
555:             * Sets the maximum number of hard messages
556:             * 
557:             * @jmx.managed-attribute
558:             * @param maximumHard the maximum number of hard messages
559:             */
560:            public void setMaximumHard(int maximumHard) {
561:                if (maximumHard < 0)
562:                    this .maximumHard = 0;
563:                else
564:                    this .maximumHard = maximumHard;
565:            }
566:
567:            /**
568:             * Gets the length of time to wait before checking whether we should soften
569:             *
570:             * @jmx.managed-attribute
571:             * @return the time to wait
572:             */
573:            public long getSoftenWaitMillis() {
574:                return softenWaitMillis;
575:            }
576:
577:            /**
578:             * Sets the length of time to wait before checking whether we should soften
579:             * 
580:             * @jmx.managed-attribute
581:             * @param millis the time to wait in millis
582:             */
583:            public void setSoftenWaitMillis(long millis) {
584:                if (millis < 1000)
585:                    softenWaitMillis = 1000;
586:                else
587:                    softenWaitMillis = millis;
588:            }
589:
590:            /**
591:             * Gets the minimum length between softening checks
592:             *
593:             * @jmx.managed-attribute
594:             * @return the time to wait
595:             */
596:            public long getSoftenNoMoreOftenThanMillis() {
597:                return softenNoMoreOftenThanMillis;
598:            }
599:
600:            /**
601:             * Sets the minimum length between softening checks
602:             * 
603:             * @jmx.managed-attribute
604:             * @param wait the time between checks
605:             */
606:            public void setSoftenNoMoreOftenThanMillis(long millis) {
607:                if (millis < 0)
608:                    softenNoMoreOftenThanMillis = 0;
609:                else
610:                    softenNoMoreOftenThanMillis = millis;
611:            }
612:
613:            /**
614:             * Gets the maximum length between softening checks
615:             *
616:             * @jmx.managed-attribute
617:             * @return the time
618:             */
619:            public long getSoftenAtLeastEveryMillis() {
620:                return softenAtLeastEveryMillis;
621:            }
622:
623:            /**
624:             * Sets the minimum length between softening checks
625:             * 
626:             * @jmx.managed-attribute
627:             * @param wait the time between checks
628:             */
629:            public void setSoftenAtLeastEveryMillis(long millis) {
630:                if (millis < 0)
631:                    softenAtLeastEveryMillis = 0;
632:                else
633:                    softenAtLeastEveryMillis = millis;
634:            }
635:
636:            /**
637:             * Gets the highMemoryMark
638:             * @return Returns a long
639:             *
640:             * @jmx.managed-attribute
641:             */
642:            public long getHighMemoryMark() {
643:                return highMemoryMark / ONE_MEGABYTE;
644:            }
645:
646:            /**
647:             * Sets the highMemoryMark
648:             * @param highMemoryMark The highMemoryMark to set
649:             *
650:             * @jmx.managed-attribute
651:             */
652:            public void setHighMemoryMark(long highMemoryMark) {
653:                if (highMemoryMark > 0)
654:                    this .highMemoryMark = highMemoryMark * ONE_MEGABYTE;
655:                else
656:                    this .highMemoryMark = 0;
657:            }
658:
659:            /**
660:             * Gets the maxMemoryMark
661:             * @return Returns a long
662:             *
663:             * @jmx.managed-attribute
664:             */
665:            public long getMaxMemoryMark() {
666:                return maxMemoryMark / ONE_MEGABYTE;
667:            }
668:
669:            /**
670:             * Sets the maxMemoryMark
671:             * @param maxMemoryMark The maxMemoryMark to set
672:             *
673:             * @jmx.managed-attribute
674:             */
675:            public void setMaxMemoryMark(long maxMemoryMark) {
676:                if (maxMemoryMark > 0)
677:                    this .maxMemoryMark = maxMemoryMark * ONE_MEGABYTE;
678:                else
679:                    this .maxMemoryMark = 0;
680:            }
681:
682:            /**
683:             * Gets the CurrentMemoryUsage
684:             * @return Returns a long
685:             *
686:             * @jmx.managed-attribute
687:             */
688:            public long getCurrentMemoryUsage() {
689:                return (Runtime.getRuntime().totalMemory() - Runtime
690:                        .getRuntime().freeMemory())
691:                        / ONE_MEGABYTE;
692:            }
693:
694:            /**
695:             * @see ServiceMBeanSupport#getName()
696:             */
697:            public String getName() {
698:                return "MessageCache";
699:            }
700:
701:            /**
702:             * @see MessageCacheMBean#setCacheStore(ObjectName)
703:             *
704:             * @jmx.managed-attribute
705:             */
706:            public void setCacheStore(ObjectName cacheStoreName) {
707:                this .cacheStoreName = cacheStoreName;
708:            }
709:
710:            /**
711:             * The <code>getCacheStore</code> method
712:             *
713:             * @return an <code>ObjectName</code> value
714:             *
715:             * @jmx.managed-attribute
716:             */
717:            public ObjectName getCacheStore() {
718:                return cacheStoreName;
719:            }
720:
721:            /**
722:             * This class implements a simple, efficient LRUCache.  It is pretty much a
723:             * cut down version of the code in org.jboss.pool.cache.LeastRecentlyUsedCache
724:             */
725:            class LRUCache {
726:                int currentSize = 0;
727:                //maps objects to their nodes
728:                HashMap map = new HashMap();
729:                Node mostRecent = null;
730:                Node leastRecent = null;
731:
732:                public void addMostRecent(Object o) {
733:                    Node newNode = new Node();
734:                    newNode.data = o;
735:                    //insert into map
736:                    Object oldNode = map.put(o, newNode);
737:                    if (oldNode != null) {
738:                        map.put(o, oldNode);
739:                        throw new RuntimeException("Can't add object '" + o
740:                                + "' to LRUCache that is already in cache.");
741:                    }
742:                    //insert into linked list
743:                    if (mostRecent == null) {
744:                        //first element
745:                        mostRecent = newNode;
746:                        leastRecent = newNode;
747:                    } else {
748:                        newNode.lessRecent = mostRecent;
749:                        mostRecent.moreRecent = newNode;
750:                        mostRecent = newNode;
751:                    }
752:                    ++currentSize;
753:                }
754:
755:                // Not used anywhere!!
756:                public void addLeastRecent(Object o) {
757:                    Node newNode = new Node();
758:                    newNode.data = o;
759:                    //insert into map
760:                    Object oldNode = map.put(o, newNode);
761:                    if (oldNode != null) {
762:                        map.put(o, oldNode);
763:                        throw new RuntimeException("Can't add object '" + o
764:                                + "' to LRUCache that is already in cache.");
765:                    }
766:                    //insert into linked list
767:                    if (leastRecent == null) {
768:                        //first element
769:                        mostRecent = newNode;
770:                        leastRecent = newNode;
771:                    } else {
772:                        newNode.moreRecent = leastRecent;
773:                        leastRecent.lessRecent = newNode;
774:                        leastRecent = newNode;
775:                    }
776:                    ++currentSize;
777:                }
778:
779:                public void remove(Object o) {
780:                    //remove from map
781:                    Node node = (Node) map.remove(o);
782:                    if (node == null)
783:                        throw new RuntimeException("Can't remove object '" + o
784:                                + "' that is not in cache.");
785:                    //remove from linked list
786:                    Node more = node.moreRecent;
787:                    Node less = node.lessRecent;
788:                    if (more == null) { //means node is mostRecent
789:                        mostRecent = less;
790:                        if (mostRecent != null) {
791:                            mostRecent.moreRecent = null; //Mark it as beeing at the top of tree
792:                        }
793:                    } else {
794:                        more.lessRecent = less;
795:                    }
796:                    if (less == null) { //means node is leastRecent
797:                        leastRecent = more;
798:                        if (leastRecent != null) {
799:                            leastRecent.lessRecent = null; //Mark it last in tree
800:                        }
801:                    } else {
802:                        less.moreRecent = more;
803:                    }
804:                    --currentSize;
805:                }
806:
807:                public void makeMostRecent(Object o) {
808:                    //get node from map
809:                    Node node = (Node) map.get(o);
810:                    if (node == null)
811:                        throw new RuntimeException(
812:                                "Can't make most recent object '" + o
813:                                        + "' that is not in cache.");
814:                    //reposition in linked list, first remove
815:                    Node more = node.moreRecent;
816:                    Node less = node.lessRecent;
817:                    if (more == null) //means node is mostRecent
818:                        return;
819:                    else
820:                        more.lessRecent = less;
821:                    if (less == null) //means node is leastRecent
822:                        leastRecent = more;
823:                    else
824:                        less.moreRecent = more;
825:                    //now add back in at most recent position
826:                    node.lessRecent = mostRecent;
827:                    node.moreRecent = null; //We are at the top
828:                    mostRecent.moreRecent = node;
829:                    mostRecent = node;
830:                }
831:
832:                public int size() {
833:                    return currentSize;
834:                }
835:
836:                public Node getMostRecent() {
837:                    return mostRecent;
838:                }
839:
840:                public Node getLeastRecent() {
841:                    return leastRecent;
842:                }
843:            }
844:
845:            static class Node {
846:                Node moreRecent = null;
847:                Node lessRecent = null;
848:                Object data = null;
849:            }
850:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.