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