001    /*
002     * Copyright 2008-2015 UnboundID Corp.
003     * All Rights Reserved.
004     */
005    /*
006     * Copyright (C) 2015 UnboundID Corp.
007     *
008     * This program is free software; you can redistribute it and/or modify
009     * it under the terms of the GNU General Public License (GPLv2 only)
010     * or the terms of the GNU Lesser General Public License (LGPLv2.1 only)
011     * as published by the Free Software Foundation.
012     *
013     * This program is distributed in the hope that it will be useful,
014     * but WITHOUT ANY WARRANTY; without even the implied warranty of
015     * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
016     * GNU General Public License for more details.
017     *
018     * You should have received a copy of the GNU General Public License
019     * along with this program; if not, see <http://www.gnu.org/licenses>.
020     */
021    package com.unboundid.ldap.sdk.unboundidds.monitors;
022    
023    
024    
025    import java.util.ArrayList;
026    import java.util.Collections;
027    import java.util.LinkedHashMap;
028    import java.util.List;
029    import java.util.Map;
030    import java.util.TreeMap;
031    import java.util.TreeSet;
032    
033    import com.unboundid.ldap.sdk.Attribute;
034    import com.unboundid.ldap.sdk.Entry;
035    import com.unboundid.util.NotMutable;
036    import com.unboundid.util.ThreadSafety;
037    import com.unboundid.util.ThreadSafetyLevel;
038    
039    import static com.unboundid.ldap.sdk.unboundidds.monitors.MonitorMessages.*;
040    import static com.unboundid.util.Debug.*;
041    import static com.unboundid.util.StaticUtils.*;
042    
043    
044    
045    /**
046     * <BLOCKQUOTE>
047     *   <B>NOTE:</B>  This class is part of the Commercial Edition of the UnboundID
048     *   LDAP SDK for Java.  It is not available for use in applications that
049     *   include only the Standard Edition of the LDAP SDK, and is not supported for
050     *   use in conjunction with non-UnboundID products.
051     * </BLOCKQUOTE>
052     * This class defines a monitor entry that provides information about the memory
053     * usage for the JVM in which the Directory Server is running.  In particular,
054     * it reports information about the memory pools and garbage collectors defined
055     * in the JVM.  The information that may be available in the memory usage
056     * monitor entry includes:
057     * <UL>
058     *   <LI>The names of the memory pools that are in use within the JVM.</LI>
059     *   <LI>The number of bytes currently used within each memory pool.</LI>
060     *   <LI>The number of bytes used within each memory pool after the last
061     *       garbage collection.</LI>
062     *   <LI>The names of the garbage collectors that are in use within the
063     *       JVM.</LI>
064     *   <LI>The number of garbage collections performed by each collector.</LI>
065     *   <LI>The total duration of all garbage collections performed by each
066     *       collector.</LI>
067     *   <LI>The average duration of garbage collections performed by each
068     *       collector.</LI>
069     *   <LI>The duration of the most recent garbage collection performed by each
070     *       collector.</LI>
071     *   <LI>The amount of non-heap memory consumed by the JVM.</LI>
072     *   <LI>The number of detected pauses of various durations detected by the
073     *       server.</LI>
074     *   <LI>The duration of the longest pause detected by the server.</LI>
075     * </UL>
076     * The server should present at most one memory usage monitor entry.  It can be
077     * retrieved using the {@link MonitorManager#getMemoryUsageMonitorEntry} method.
078     * This entry provides specific methods for accessing information about JVM
079     * memory usage (e.g., the {@link MemoryUsageMonitorEntry#getMemoryPoolNames}
080     * method can be used to retrieve the names of the memory pool).  Alternately,
081     * this information may be accessed using the generic API.  See the
082     * {@link MonitorManager} class documentation for an example that demonstrates
083     * the use of the generic API for accessing monitor data.
084     */
085    @NotMutable()
086    @ThreadSafety(level=ThreadSafetyLevel.COMPLETELY_THREADSAFE)
087    public final class MemoryUsageMonitorEntry
088           extends MonitorEntry
089    {
090      /**
091       * The structural object class used in memory usage monitor entries.
092       */
093      static final String MEMORY_USAGE_MONITOR_OC =
094           "ds-memory-usage-monitor-entry";
095    
096    
097    
098      /**
099       * The name of the attribute that holds the duration of the longest detected
100       * pause.
101       */
102      private static final String ATTR_LONGEST_PAUSE_TIME =
103           "max-detected-pause-time-millis";
104    
105    
106    
107      /**
108       * The name of the attribute that holds the amount of non-heap memory used
109       * by the JVM.
110       */
111      private static final String ATTR_NON_HEAP_USED = "non-heap-memory-bytes-used";
112    
113    
114    
115      /**
116       * The name of the attribute that holds the total amount of memory used by
117       * memory consumers.
118       */
119      private static final String ATTR_TOTAL_CONSUMER_MEMORY =
120           "total-bytes-used-by-memory-consumers";
121    
122    
123    
124      /**
125       * The name of the attribute that holds the percentage of committed tenured
126       * memory held by memory consumers.
127       */
128      private static final String ATTR_TOTAL_CONSUMER_MEMORY_AS_PCT_OF_COMMITTED =
129           "memory-consumers-total-as-percent-of-committed-tenured-memory";
130    
131    
132    
133      /**
134       * The name of the attribute that holds the percentage of maximum allowed
135       * tenured memory held by memory consumers.
136       */
137      private static final String ATTR_TOTAL_CONSUMER_MEMORY_AS_PCT_OF_MAX =
138           "memory-consumers-total-as-percent-of-maximum-tenured-memory";
139    
140    
141    
142      /**
143       * The prefix that will be used for pauses detected by the server.
144       */
145      private static final String ATTR_PREFIX_DETECTED_PAUSE =
146           "detected-pauses-over-";
147    
148    
149    
150      /**
151       * The suffix that will be used for attributes providing the total collection
152       * count for a garbage collector.
153       */
154      private static final String ATTR_SUFFIX_TOTAL_COLLECTION_COUNT =
155           "-total-collection-count";
156    
157    
158    
159      /**
160       * The suffix that will be used for attributes providing the total collection
161       * duration for a garbage collector.
162       */
163      private static final String ATTR_SUFFIX_TOTAL_COLLECTION_DURATION =
164           "-total-collection-duration";
165    
166    
167    
168      /**
169       * The suffix that will be used for attributes providing the average
170       * collection duration for a garbage collector.
171       */
172      private static final String ATTR_SUFFIX_AVERAGE_COLLECTION_DURATION =
173           "-average-collection-duration";
174    
175    
176    
177      /**
178       * The suffix that will be used for attributes providing the recent collection
179       * duration for a garbage collector.
180       */
181      private static final String ATTR_SUFFIX_RECENT_COLLECTION_DURATION =
182           "-recent-collection-duration";
183    
184    
185    
186      /**
187       * The suffix that will be used for attributes providing the current bytes
188       * used in a memory pool.
189       */
190      private static final String ATTR_SUFFIX_CURRENT_BYTES_USED =
191           "-current-bytes-used";
192    
193    
194    
195      /**
196       * The suffix that will be used for attributes providing the bytes used after
197       * the last collection in a memory pool.
198       */
199      private static final String ATTR_SUFFIX_BYTES_USED_AFTER_LAST_COLLECTION =
200           "-bytes-used-after-last-collection";
201    
202    
203    
204      /**
205       * The name of the property used to provide the numbers of pauses of various
206       * durations detected.
207       */
208      private static final String PROPERTY_DETECTED_PAUSE_COUNTS =
209           "detected-pause-counts";
210    
211    
212    
213      /**
214       * The name of the attribute that holds the maximum amount of memory that may
215       * be used by the JVM, in megabytes.
216       */
217      private static final String ATTR_MAX_RESERVABLE_MEMORY_MB =
218           "maxReservableMemoryMB";
219    
220    
221    
222      /**
223       * The name of the attribute that holds the amount of memory currently
224       * allocated for use by the JVM, in megabytes.
225       */
226      private static final String ATTR_CURRENT_RESERVED_MEMORY_MB =
227           "currentReservedMemoryMB";
228    
229    
230    
231      /**
232       * The name of the attribute that holds the amount of allocated JVM memory
233       * which is actually in use.
234       */
235      private static final String ATTR_USED_MEMORY_MB = "usedReservedMemoryMB";
236    
237    
238    
239      /**
240       * The name of the attribute that holds the amount of allocated JVM memory
241       * that is not currently in use.
242       */
243      private static final String ATTR_FREE_MEMORY_MB = "freeReservedMemoryMB";
244    
245    
246    
247      /**
248       * The name of the attribute that holds the percentage of the maximum JVM
249       * memory that is actually in use.
250       */
251      private static final String ATTR_RESERVED_MEMORY_PERCENT_FULL =
252           "reservedMemoryPercentFull";
253    
254    
255    
256      /**
257       * The serial version UID for this serializable class.
258       */
259      private static final long serialVersionUID = 1924052253885937441L;
260    
261    
262    
263      // The list of garbage collectors for which information is available.
264      private final List<String> garbageCollectors;
265    
266      // The list of memory pools for which information is available.
267      private final List<String> memoryPools;
268    
269      // The amount of memory that has currently been allocated by the JVM, in
270      // megabytes.
271      private final Long currentReservedMemoryMB;
272    
273      // The amount of allocated JVM memory that is not currently in use, in
274      // megabytes.
275      private final Long freeReservedMemoryMB;
276    
277      // The maximum pause time detected by the JVM.
278      private final Long maxDetectedPauseTime;
279    
280      // The maximum amount of memory that may be used by the JVM, in megabytes.
281      private final Long maxReservableMemoryMB;
282    
283      // The amount of non-heap memory consumed by the JVM.
284      private final Long nonHeapMemoryUsed;
285    
286      // The percentage of committed tenured memory held by consumers.
287      private final Long percentOfCommittedTenuredMemory;
288    
289      // The percentage of maximum tenured memory held by consumers.
290      private final Long percentOfMaxTenuredMemory;
291    
292      // The percentage of the maximum JVM memory that is currently in use.
293      private final Long reservedMemoryPercentFull;
294    
295      // The total amount of memory held by memory consumers.
296      private final Long totalBytesHeldByConsumers;
297    
298      // The amount of allocated JVM memory that is currently in use, in megabytes.
299      private final Long usedReservedMemoryMB;
300    
301      // The number of pauses exceeding specified thresholds.
302      private final Map<Long,Long> detectedPauses;
303    
304      // The list of bytes used after the last collection per memory pool.
305      private final Map<String,Long> bytesUsedAfterLastCollectionPerMP;
306    
307      // The list of current bytes used per memory pool.
308      private final Map<String,Long> currentBytesUsedPerMP;
309    
310      // The list of average collection durations per garbage collector.
311      private final Map<String,Long> averageCollectionDurationPerGC;
312    
313      // The list of recent collection durations per garbage collector.
314      private final Map<String,Long> recentCollectionDurationPerGC;
315    
316      // The list of total collection counts per garbage collector.
317      private final Map<String,Long> totalCollectionCountPerGC;
318    
319      // The list of total collection durations per garbage collector.
320      private final Map<String,Long> totalCollectionDurationPerGC;
321    
322    
323    
324      /**
325       * Creates a new memory usage monitor entry from the provided entry.
326       *
327       * @param  entry  The entry to be parsed as a memory usage monitor entry.  It
328       *                must not be {@code null}.
329       */
330      public MemoryUsageMonitorEntry(final Entry entry)
331      {
332        super(entry);
333    
334        maxDetectedPauseTime            = getLong(ATTR_LONGEST_PAUSE_TIME);
335        nonHeapMemoryUsed               = getLong(ATTR_NON_HEAP_USED);
336        totalBytesHeldByConsumers       = getLong(ATTR_TOTAL_CONSUMER_MEMORY);
337        percentOfCommittedTenuredMemory =
338             getLong(ATTR_TOTAL_CONSUMER_MEMORY_AS_PCT_OF_COMMITTED);
339        percentOfMaxTenuredMemory =
340             getLong(ATTR_TOTAL_CONSUMER_MEMORY_AS_PCT_OF_MAX);
341    
342        maxReservableMemoryMB     = getLong(ATTR_MAX_RESERVABLE_MEMORY_MB);
343        currentReservedMemoryMB   = getLong(ATTR_CURRENT_RESERVED_MEMORY_MB);
344        usedReservedMemoryMB      = getLong(ATTR_USED_MEMORY_MB);
345        freeReservedMemoryMB      = getLong(ATTR_FREE_MEMORY_MB);
346        reservedMemoryPercentFull = getLong(ATTR_RESERVED_MEMORY_PERCENT_FULL);
347    
348    
349        final TreeMap<Long,Long> pauses = new TreeMap<Long,Long>();
350    
351        final TreeSet<String> mpNames = new TreeSet<String>();
352        final TreeSet<String> gcNames = new TreeSet<String>();
353    
354        final TreeMap<String,Long> averageDurations = new TreeMap<String,Long>();
355        final TreeMap<String,Long> currentBytesUsed = new TreeMap<String,Long>();
356        final TreeMap<String,Long> lastBytesUsed    = new TreeMap<String,Long>();
357        final TreeMap<String,Long> recentDurations  = new TreeMap<String,Long>();
358        final TreeMap<String,Long> totalCounts      = new TreeMap<String,Long>();
359        final TreeMap<String,Long> totalDurations   = new TreeMap<String,Long>();
360    
361        for (final Attribute a : entry.getAttributes())
362        {
363          final String name      = a.getName();
364          final String lowerName = toLowerCase(name);
365    
366          if (lowerName.startsWith(ATTR_PREFIX_DETECTED_PAUSE))
367          {
368            final Long l = getLong(name);
369    
370            final String timeStr =
371                 lowerName.substring(ATTR_PREFIX_DETECTED_PAUSE.length());
372            if (timeStr.endsWith("ms"))
373            {
374              try
375              {
376                final long millis =
377                     Long.parseLong(timeStr.substring(0, timeStr.length()-2));
378                pauses.put(millis, l);
379              }
380              catch (Exception e)
381              {
382                debugException(e);
383              }
384            }
385            else if (timeStr.endsWith("s"))
386            {
387              try
388              {
389                final long millis = 1000 *
390                     Long.parseLong(timeStr.substring(0, timeStr.length()-1));
391                pauses.put(millis, l);
392              }
393              catch (Exception e)
394              {
395                debugException(e);
396              }
397            }
398          }
399    
400          int pos = lowerName.indexOf(ATTR_SUFFIX_AVERAGE_COLLECTION_DURATION);
401          if (pos > 0)
402          {
403            final String gcName = name.substring(0, pos);
404            gcNames.add(gcName);
405    
406            final Long l = getLong(name);
407            if (l != null)
408            {
409              averageDurations.put(toLowerCase(gcName), l);
410            }
411    
412            continue;
413          }
414    
415          pos = lowerName.indexOf(ATTR_SUFFIX_BYTES_USED_AFTER_LAST_COLLECTION);
416          if (pos > 0)
417          {
418            final String mpName = name.substring(0, pos);
419            mpNames.add(mpName);
420    
421            final Long l = getLong(name);
422            if (l != null)
423            {
424              lastBytesUsed.put(toLowerCase(mpName), l);
425            }
426    
427            continue;
428          }
429    
430          pos = lowerName.indexOf(ATTR_SUFFIX_CURRENT_BYTES_USED);
431          if (pos > 0)
432          {
433            final String mpName = name.substring(0, pos);
434            mpNames.add(mpName);
435    
436            final Long l = getLong(name);
437            if (l != null)
438            {
439              currentBytesUsed.put(toLowerCase(mpName), l);
440            }
441    
442            continue;
443          }
444    
445          pos = lowerName.indexOf(ATTR_SUFFIX_RECENT_COLLECTION_DURATION);
446          if (pos > 0)
447          {
448            final String gcName = name.substring(0, pos);
449            gcNames.add(gcName);
450    
451            final Long l = getLong(name);
452            if (l != null)
453            {
454              recentDurations.put(toLowerCase(gcName), l);
455            }
456    
457            continue;
458          }
459    
460          pos = lowerName.indexOf(ATTR_SUFFIX_TOTAL_COLLECTION_COUNT);
461          if ((pos > 0) && (! lowerName.startsWith("mem-pool-")))
462          {
463            final String gcName = name.substring(0, pos);
464            gcNames.add(gcName);
465    
466            final Long l = getLong(name);
467            if (l != null)
468            {
469              totalCounts.put(toLowerCase(gcName), l);
470            }
471    
472            continue;
473          }
474    
475          pos = lowerName.indexOf(ATTR_SUFFIX_TOTAL_COLLECTION_DURATION);
476          if (pos > 0)
477          {
478            final String gcName = name.substring(0, pos);
479            gcNames.add(gcName);
480    
481            final Long l = getLong(name);
482            if (l != null)
483            {
484              totalDurations.put(toLowerCase(gcName), l);
485            }
486    
487            continue;
488          }
489        }
490    
491    
492        garbageCollectors =
493             Collections.unmodifiableList(new ArrayList<String>(gcNames));
494    
495        memoryPools = Collections.unmodifiableList(new ArrayList<String>(mpNames));
496    
497        totalCollectionCountPerGC = Collections.unmodifiableMap(totalCounts);
498    
499        totalCollectionDurationPerGC = Collections.unmodifiableMap(totalDurations);
500    
501        averageCollectionDurationPerGC =
502             Collections.unmodifiableMap(averageDurations);
503    
504        recentCollectionDurationPerGC =
505             Collections.unmodifiableMap(recentDurations);
506    
507        bytesUsedAfterLastCollectionPerMP =
508             Collections.unmodifiableMap(lastBytesUsed);
509    
510        currentBytesUsedPerMP = Collections.unmodifiableMap(currentBytesUsed);
511    
512        detectedPauses = Collections.unmodifiableMap(pauses);
513      }
514    
515    
516    
517      /**
518       * Retrieves the maximum amount of memory (in megabytes) that may be allocated
519       * and used by the JVM.
520       *
521       * @return  The maximum amount of memory (in megabytes) that may be allocated
522       *          and used by the JVM, or {@code null} if this was not included in
523       *          the monitor entry.
524       */
525      public Long getMaxReservableMemoryMB()
526      {
527        return maxReservableMemoryMB;
528      }
529    
530    
531    
532      /**
533       * Retrieves the amount of memory (in megabytes) that is currently allocated
534       * for use by the JVM.
535       *
536       * @return  The amount of memory (in megabytes) that is currently allocated
537       *          for use by the JVM, or {@code null} if this was not included in
538       *          the monitor entry.
539       */
540      public Long getCurrentReservedMemoryMB()
541      {
542        return currentReservedMemoryMB;
543      }
544    
545    
546    
547      /**
548       * Retrieves the amount of memory (in megabytes) allocated for use by the JVM
549       * that is currently in use for holding Java objects.
550       *
551       * @return  The amount of memory (in megabytes) allocated for use by the JVM
552       *          that is currently in use for holding Java objects, or {@code null}
553       *          if this was not included in the monitor entry.
554       */
555      public Long getUsedReservedMemoryMB()
556      {
557        return usedReservedMemoryMB;
558      }
559    
560    
561    
562      /**
563       * Retrieves the amount of memory (in megabytes) allocated for use by the JVM
564       * that is not currently in use for holding Java objects.
565       *
566       * @return  The amount of memory (in megabytes) allocated for use by the JVM
567       *          that is not currently in use for holding Java objects, or
568       *          {@code null} if this was not included in the monitor entry.
569       */
570      public Long getFreeReservedMemoryMB()
571      {
572        return freeReservedMemoryMB;
573      }
574    
575    
576    
577      /**
578       * Retrieves the percent of the currently-reserved memory that is actually in
579       * use by the JVM for storing Java objects.
580       *
581       * @return  The percent of the currently-reserved memory that is actually in
582       *          use by the JVM for storing Java objects.
583       */
584      public Long getReservedMemoryPercentFull()
585      {
586        return reservedMemoryPercentFull;
587      }
588    
589    
590    
591      /**
592       * Retrieves the names of the garbage collectors for which information is
593       * available.
594       *
595       * @return  The names of the garbage collectors for which information is
596       *          available.
597       */
598      public List<String> getGarbageCollectorNames()
599      {
600        return garbageCollectors;
601      }
602    
603    
604    
605      /**
606       * Retrieves the names of the memory pools for which information is available.
607       *
608       * @return  The names of the memory pools for which information is available.
609       */
610      public List<String> getMemoryPoolNames()
611      {
612        return memoryPools;
613      }
614    
615    
616    
617      /**
618       * Retrieves a map containing the total number of garbage collections
619       * performed per collector.
620       *
621       * @return  A map containing the total number of garbage collections performed
622       *          per collector.
623       */
624      public Map<String,Long> getTotalCollectionCounts()
625      {
626        return totalCollectionCountPerGC;
627      }
628    
629    
630    
631      /**
632       * Retrieves the total number of garbage collections performed by the
633       * specified collector.
634       *
635       * @param  collectorName  The name of the garbage collector for which to
636       *                        retrieve the information.
637       *
638       * @return  The total number of garbage collections performed by the specified
639       *          collector, or {@code null} if that information is not available.
640       */
641      public Long getTotalCollectionCount(final String collectorName)
642      {
643        return totalCollectionCountPerGC.get(toLowerCase(collectorName));
644      }
645    
646    
647    
648      /**
649       * Retrieves a map containing the total length of time (in milliseconds) spent
650       * performing garbage collection per collector.
651       *
652       * @return  A map containing the total length of time (in milliseconds) spent
653       *          performing garbage collection per collector.
654       */
655      public Map<String,Long> getTotalCollectionDurations()
656      {
657        return totalCollectionDurationPerGC;
658      }
659    
660    
661    
662      /**
663       * Retrieves the total length of time (in milliseconds) spent performing
664       * garbage collection for the specified collector.
665       *
666       * @param  collectorName  The name of the garbage collector for which to
667       *                        retrieve the information.
668       *
669       * @return  The total length of time (in milliseconds) spent performing
670       *          garbage collection for the specified collector, or {@code null} if
671       *          that information is not available.
672       */
673      public Long getTotalCollectionDuration(final String collectorName)
674      {
675        return totalCollectionDurationPerGC.get(toLowerCase(collectorName));
676      }
677    
678    
679    
680      /**
681       * Retrieves a map containing the average garbage collection duration (in
682       * milliseconds) per garbage collector.
683       *
684       * @return  A map containing the average garbage collection duration (in
685       *          milliseconds) per garbage collector.
686       */
687      public Map<String,Long> getAverageCollectionDurations()
688      {
689        return averageCollectionDurationPerGC;
690      }
691    
692    
693    
694      /**
695       * Retrieves the average garbage collection duration (in milliseconds) for the
696       * specified collector.
697       *
698       * @param  collectorName  The name of the garbage collector for which to
699       *                        retrieve the information.
700       *
701       * @return  The average garbage collection duration (in milliseconds) for the
702       *          specified collector, or {@code null} if that information is not
703       *          available.
704       */
705      public Long getAverageCollectionDuration(final String collectorName)
706      {
707        return averageCollectionDurationPerGC.get(toLowerCase(collectorName));
708      }
709    
710    
711    
712      /**
713       * Retrieves a map containing the most recent garbage collection duration (in
714       * milliseconds) per garbage collector.
715       *
716       * @return  A map containing the duration of the most recent garbage
717       *          collection duration (in milliseconds) per garbage collector.
718       */
719      public Map<String,Long> getRecentCollectionDurations()
720      {
721        return recentCollectionDurationPerGC;
722      }
723    
724    
725    
726      /**
727       * Retrieves the duration (in milliseconds) of the most recent garbage
728       * collection for the specified collector.
729       *
730       * @param  collectorName  The name of the garbage collector for which to
731       *                        retrieve the information.
732       *
733       * @return  The duration (in milliseconds) of the most recent garbage
734       *          collection for the specified collector, or {@code null} if that
735       *          information is not available.
736       */
737      public Long getRecentCollectionDuration(final String collectorName)
738      {
739        return recentCollectionDurationPerGC.get(toLowerCase(collectorName));
740      }
741    
742    
743    
744      /**
745       * Retrieves a map containing the current number of bytes used per memory
746       * pool.
747       *
748       * @return  A map containing the current number of bytes used per memory pool.
749       */
750      public Map<String,Long> getCurrentBytesUsed()
751      {
752        return currentBytesUsedPerMP;
753      }
754    
755    
756    
757      /**
758       * Retrieves the current number of bytes used for the specified memory pool.
759       *
760       * @param  poolName  The name of the memory pool for which to retrieve the
761       *                   information.
762       *
763       * @return  The current number of bytes used for the specified memory pool, or
764       *          {@code null} if that information is not available.
765       */
766      public Long getCurrentBytesUsed(final String poolName)
767      {
768        return currentBytesUsedPerMP.get(toLowerCase(poolName));
769      }
770    
771    
772    
773      /**
774       * Retrieves a map containing the number of bytes used after the last garbage
775       * collection per memory pool.
776       *
777       * @return  A map containing the number of bytes used after the last garbage
778       *          collection per memory pool.
779       */
780      public Map<String,Long> getBytesUsedAfterLastCollection()
781      {
782        return bytesUsedAfterLastCollectionPerMP;
783      }
784    
785    
786    
787      /**
788       * Retrieves the number of bytes used after the last garbage collection for
789       * the specified memory pool.
790       *
791       * @param  poolName  The name of the memory pool for which to retrieve the
792       *                   information.
793       *
794       * @return  The number of bytes used after the last garbage collection for the
795       *          specified memory pool, or {@code null} if that information is not
796       *          available.
797       */
798      public Long getBytesUsedAfterLastCollection(final String poolName)
799      {
800        return bytesUsedAfterLastCollectionPerMP.get(toLowerCase(poolName));
801      }
802    
803    
804    
805      /**
806       * Retrieves the amount of non-heap memory consumed by the JVM.
807       *
808       * @return  The amount of non-heap memory consumed by the JVM, or {@code null}
809       *          if that information is not available.
810       */
811      public Long getNonHeapMemoryBytesUsed()
812      {
813        return nonHeapMemoryUsed;
814      }
815    
816    
817    
818      /**
819       * Retrieves the total amount of memory in bytes held by memory consumers.
820       *
821       * @return  The total amount of memory in bytes held by memory consumers, or
822       *          {@code null} if that information is not available.
823       */
824      public Long getTotalBytesUsedByMemoryConsumers()
825      {
826        return totalBytesHeldByConsumers;
827      }
828    
829    
830    
831      /**
832       * Retrieves the percentage of the maximum allowed amount of tenured memory
833       * that is used by memory consumers (assuming that all memory used by memory
834       * consumers is contained in the tenured generation).
835       *
836       * @return  The percentage of the maximum allowed amount of tenured memory
837       *          that is used by memory consumers, or {@code null} if that
838       *          information is not available.
839       */
840      public Long getPercentageOfMaximumTenuredMemoryUsedByMemoryConsumers()
841      {
842        return percentOfMaxTenuredMemory;
843      }
844    
845    
846    
847      /**
848       * Retrieves the percentage of the committed amount of tenured memory that is
849       * used by memory consumers (assuming that all memory used by memory consumers
850       * is contained in the tenured generation).
851       *
852       * @return  The percentage of the committed amount of tenured memory that is
853       *          used by memory consumers, or {@code null} if that information is
854       *          not available.
855       */
856      public Long getPercentageOfCommittedTenuredMemoryUsedByMemoryConsumers()
857      {
858        return percentOfCommittedTenuredMemory;
859      }
860    
861    
862    
863      /**
864       * Retrieves the number of pauses of various durations detected by the server.
865       * The value returned will contain a map between the minimum duration in
866       * milliseconds for the associated bucket and the number of pauses detected of
867       * at least that duration.
868       *
869       * @return  The number of pauses of various durations detected by the server.
870       */
871      public Map<Long,Long> getDetectedPauseCounts()
872      {
873        return detectedPauses;
874      }
875    
876    
877    
878      /**
879       * Retrieves the duration of the longest pause detected by the server.
880       *
881       * @return  The duration of the longest pause detected by the server, or
882       *          {@code null} if that information is not available.
883       */
884      public Long getMaxDetectedPauseTimeMillis()
885      {
886        return maxDetectedPauseTime;
887      }
888    
889    
890    
891      /**
892       * {@inheritDoc}
893       */
894      @Override()
895      public String getMonitorDisplayName()
896      {
897        return INFO_MEMORY_USAGE_MONITOR_DISPNAME.get();
898      }
899    
900    
901    
902      /**
903       * {@inheritDoc}
904       */
905      @Override()
906      public String getMonitorDescription()
907      {
908        return INFO_MEMORY_USAGE_MONITOR_DESC.get();
909      }
910    
911    
912    
913      /**
914       * {@inheritDoc}
915       */
916      @Override()
917      public Map<String,MonitorAttribute> getMonitorAttributes()
918      {
919        final LinkedHashMap<String,MonitorAttribute> attrs =
920             new LinkedHashMap<String,MonitorAttribute>();
921    
922        if (maxReservableMemoryMB != null)
923        {
924          addMonitorAttribute(attrs,
925               ATTR_MAX_RESERVABLE_MEMORY_MB,
926               INFO_MEMORY_USAGE_DISPNAME_MAX_MEM.get(),
927               INFO_MEMORY_USAGE_DESC_MAX_MEM.get(),
928               maxReservableMemoryMB);
929        }
930    
931        if (currentReservedMemoryMB != null)
932        {
933          addMonitorAttribute(attrs,
934               ATTR_CURRENT_RESERVED_MEMORY_MB,
935               INFO_MEMORY_USAGE_DISPNAME_CURRENT_MEM.get(),
936               INFO_MEMORY_USAGE_DESC_CURRENT_MEM.get(),
937               currentReservedMemoryMB);
938        }
939    
940        if (usedReservedMemoryMB != null)
941        {
942          addMonitorAttribute(attrs,
943               ATTR_USED_MEMORY_MB,
944               INFO_MEMORY_USAGE_DISPNAME_USED_MEM.get(),
945               INFO_MEMORY_USAGE_DESC_USED_MEM.get(),
946               usedReservedMemoryMB);
947        }
948    
949        if (freeReservedMemoryMB != null)
950        {
951          addMonitorAttribute(attrs,
952               ATTR_FREE_MEMORY_MB,
953               INFO_MEMORY_USAGE_DISPNAME_FREE_MEM.get(),
954               INFO_MEMORY_USAGE_DESC_FREE_MEM.get(),
955               freeReservedMemoryMB);
956        }
957    
958        if (reservedMemoryPercentFull != null)
959        {
960          addMonitorAttribute(attrs,
961               ATTR_RESERVED_MEMORY_PERCENT_FULL,
962               INFO_MEMORY_USAGE_DISPNAME_RESERVED_PCT.get(),
963               INFO_MEMORY_USAGE_DESC_RESERVED_PCT.get(),
964               reservedMemoryPercentFull);
965        }
966    
967        if (! garbageCollectors.isEmpty())
968        {
969          addMonitorAttribute(attrs,
970               "gcNames",
971               INFO_MEMORY_USAGE_DISPNAME_GC_NAMES.get(),
972               INFO_MEMORY_USAGE_DESC_GC_NAMES.get(),
973               garbageCollectors);
974        }
975    
976        if (! totalCollectionCountPerGC.isEmpty())
977        {
978          for (final String name : totalCollectionCountPerGC.keySet())
979          {
980            addMonitorAttribute(attrs,
981                "totalCollectionCount-" + name,
982                INFO_MEMORY_USAGE_DISPNAME_TOTAL_COLLECTION_COUNT.get(name),
983                INFO_MEMORY_USAGE_DESC_TOTAL_COLLECTION_COUNT.get(name),
984                totalCollectionCountPerGC.get(name));
985          }
986        }
987    
988        if (! totalCollectionDurationPerGC.isEmpty())
989        {
990          for (final String name : totalCollectionDurationPerGC.keySet())
991          {
992            addMonitorAttribute(attrs,
993                "totalCollectionDuration-" + name,
994                INFO_MEMORY_USAGE_DISPNAME_TOTAL_COLLECTION_DURATION.get(name),
995                INFO_MEMORY_USAGE_DESC_TOTAL_COLLECTION_DURATION.get(name),
996                totalCollectionDurationPerGC.get(name));
997          }
998        }
999    
1000        if (! averageCollectionDurationPerGC.isEmpty())
1001        {
1002          for (final String name : averageCollectionDurationPerGC.keySet())
1003          {
1004            addMonitorAttribute(attrs,
1005                "averageCollectionDuration-" + name,
1006                INFO_MEMORY_USAGE_DISPNAME_AVERAGE_COLLECTION_DURATION.get(name),
1007                INFO_MEMORY_USAGE_DESC_AVERAGE_COLLECTION_DURATION.get(name),
1008                averageCollectionDurationPerGC.get(name));
1009          }
1010        }
1011    
1012        if (! recentCollectionDurationPerGC.isEmpty())
1013        {
1014          for (final String name : recentCollectionDurationPerGC.keySet())
1015          {
1016            addMonitorAttribute(attrs,
1017                "recentCollectionDuration-" + name,
1018                INFO_MEMORY_USAGE_DISPNAME_RECENT_COLLECTION_DURATION.get(name),
1019                INFO_MEMORY_USAGE_DESC_RECENT_COLLECTION_DURATION.get(name),
1020                recentCollectionDurationPerGC.get(name));
1021          }
1022        }
1023    
1024        if (! memoryPools.isEmpty())
1025        {
1026          addMonitorAttribute(attrs,
1027               "memoryPools",
1028               INFO_MEMORY_USAGE_DISPNAME_MEMORY_POOLS.get(),
1029               INFO_MEMORY_USAGE_DESC_MEMORY_POOLS.get(),
1030               memoryPools);
1031        }
1032    
1033        if (! currentBytesUsedPerMP.isEmpty())
1034        {
1035          for (final String name : currentBytesUsedPerMP.keySet())
1036          {
1037            addMonitorAttribute(attrs,
1038                "currentBytesUsed-" + name,
1039                INFO_MEMORY_USAGE_DISPNAME_CURRENT_BYTES_USED.get(name),
1040                INFO_MEMORY_USAGE_DESC_CURRENT_BYTES_USED.get(name),
1041                currentBytesUsedPerMP.get(name));
1042          }
1043        }
1044    
1045        if (! bytesUsedAfterLastCollectionPerMP.isEmpty())
1046        {
1047          for (final String name : bytesUsedAfterLastCollectionPerMP.keySet())
1048          {
1049            addMonitorAttribute(attrs,
1050                "bytesUsedAfterLastCollection-" + name,
1051                INFO_MEMORY_USAGE_DISPNAME_BYTES_USED_AFTER_COLLECTION.get(name),
1052                INFO_MEMORY_USAGE_DESC_BYTES_USED_AFTER_COLLECTION.get(name),
1053                bytesUsedAfterLastCollectionPerMP.get(name));
1054          }
1055        }
1056    
1057        if (nonHeapMemoryUsed != null)
1058        {
1059          addMonitorAttribute(attrs,
1060               ATTR_NON_HEAP_USED,
1061               INFO_MEMORY_USAGE_DISPNAME_NON_HEAP_MEMORY.get(),
1062               INFO_MEMORY_USAGE_DESC_NON_HEAP_MEMORY.get(),
1063               nonHeapMemoryUsed);
1064        }
1065    
1066        if (totalBytesHeldByConsumers != null)
1067        {
1068          addMonitorAttribute(attrs,
1069               ATTR_TOTAL_CONSUMER_MEMORY,
1070               INFO_MEMORY_USAGE_DISPNAME_TOTAL_CONSUMER_MEMORY.get(),
1071               INFO_MEMORY_USAGE_DESC_TOTAL_CONSUMER_MEMORY.get(),
1072               totalBytesHeldByConsumers);
1073        }
1074    
1075        if (percentOfMaxTenuredMemory != null)
1076        {
1077          addMonitorAttribute(attrs,
1078               ATTR_TOTAL_CONSUMER_MEMORY_AS_PCT_OF_MAX,
1079               INFO_MEMORY_USAGE_DISPNAME_CONSUMERS_AS_PCT_OF_MAX.get(),
1080               INFO_MEMORY_USAGE_DESC_CONSUMERS_AS_PCT_OF_MAX.get(),
1081               percentOfMaxTenuredMemory);
1082        }
1083    
1084        if (percentOfCommittedTenuredMemory != null)
1085        {
1086          addMonitorAttribute(attrs,
1087               ATTR_TOTAL_CONSUMER_MEMORY_AS_PCT_OF_COMMITTED,
1088               INFO_MEMORY_USAGE_DISPNAME_CONSUMERS_AS_PCT_OF_COMMITTED.get(),
1089               INFO_MEMORY_USAGE_DESC_CONSUMERS_AS_PCT_OF_COMMITTED.get(),
1090               percentOfCommittedTenuredMemory);
1091        }
1092    
1093        if (! detectedPauses.isEmpty())
1094        {
1095          final ArrayList<String> values =
1096               new ArrayList<String>(detectedPauses.size());
1097          for (final Map.Entry<Long,Long> e : detectedPauses.entrySet())
1098          {
1099            values.add(e.getKey() + "ms=" + e.getValue());
1100          }
1101    
1102          addMonitorAttribute(attrs,
1103               PROPERTY_DETECTED_PAUSE_COUNTS,
1104               INFO_MEMORY_USAGE_DISPNAME_DETECTED_PAUSES.get(),
1105               INFO_MEMORY_USAGE_DESC_DETECTED_PAUSES.get(),
1106               values);
1107        }
1108    
1109        if (maxDetectedPauseTime != null)
1110        {
1111          addMonitorAttribute(attrs,
1112               ATTR_LONGEST_PAUSE_TIME,
1113               INFO_MEMORY_USAGE_DISPNAME_MAX_PAUSE_TIME.get(),
1114               INFO_MEMORY_USAGE_DESC_MAX_PAUSE_TIME.get(),
1115               maxDetectedPauseTime);
1116        }
1117    
1118        return Collections.unmodifiableMap(attrs);
1119      }
1120    }