001/*
002 * Copyright 2008-2022 Ping Identity Corporation
003 * All Rights Reserved.
004 */
005/*
006 * Copyright 2008-2022 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) 2008-2022 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.Date;
043import java.util.LinkedHashMap;
044import java.util.Map;
045
046import com.unboundid.ldap.sdk.Attribute;
047import com.unboundid.ldap.sdk.Entry;
048import com.unboundid.util.NotMutable;
049import com.unboundid.util.NotNull;
050import com.unboundid.util.Nullable;
051import com.unboundid.util.StaticUtils;
052import com.unboundid.util.ThreadSafety;
053import com.unboundid.util.ThreadSafetyLevel;
054
055import static com.unboundid.ldap.sdk.unboundidds.monitors.MonitorMessages.*;
056
057
058
059/**
060 * This class defines a monitor entry that provides basic information about the
061 * Berkeley DB Java Edition environment in use for a backend.
062 * <BR>
063 * <BLOCKQUOTE>
064 *   <B>NOTE:</B>  This class, and other classes within the
065 *   {@code com.unboundid.ldap.sdk.unboundidds} package structure, are only
066 *   supported for use against Ping Identity, UnboundID, and
067 *   Nokia/Alcatel-Lucent 8661 server products.  These classes provide support
068 *   for proprietary functionality or for external specifications that are not
069 *   considered stable or mature enough to be guaranteed to work in an
070 *   interoperable way with other types of LDAP servers.
071 * </BLOCKQUOTE>
072 * <BR>
073 * The information that is provided includes:
074 * <UL>
075 *   <LI>The backend ID for the associated backend.</LI>
076 *   <LI>The version string for the Berkeley DB Java Edition library.</LI>
077 *   <LI>The path to the directory containing the database environment
078 *       files.</LI>
079 *   <LI>The amount of space consumed by the database files.</LI>
080 *   <LI>The amount of memory currently consumed by the database cache.</LI>
081 *   <LI>The maximum amount of memory that may be consumed by the database
082 *       cache.</LI>
083 *   <LI>The percent of the total memory allowed for the database cache that is
084 *       currently in use.</LI>
085 *   <LI>Whether a checkpoint is currently in progress.</LI>
086 *   <LI>The total number of checkpoints that have been completed.</LI>
087 *   <LI>The time that the last completed checkpoint began.</LI>
088 *   <LI>The time that the last completed checkpoint ended.</LI>
089 *   <LI>The total duration of all checkpoints completed.</LI>
090 *   <LI>The average duration of all checkpoints completed.</LI>
091 *   <LI>The duration of the last checkpoint completed.</LI>
092 *   <LI>The length of time since the last checkpoint.</LI>
093 *   <LI>The number of log files that the cleaner needs to examine.</LI>
094 *   <LI>The number of nodes evicted from the database cache.</LI>
095 *   <LI>The number of random-access disk reads performed.</LI>
096 *   <LI>The number of random-access disk writes performed.</LI>
097 *   <LI>The number of sequential disk reads performed.</LI>
098 *   <LI>The number of sequential disk writes performed.</LI>
099 *   <LI>The number of active transactions in the database environment.</LI>
100 *   <LI>The number of read locks held in the database environment.</LI>
101 *   <LI>The number of write locks held in the database environment.</LI>
102 *   <LI>The number of transactions waiting on locks.</LI>
103 *   <LI>A set of generic statistics about the database environment.</LI>
104 *   <LI>A set of generic statistics about the lock subsystem for the database
105 *       environment.</LI>
106 *   <LI>A set of generic statistics about the transaction subsystem for the
107 *       database environment.</LI>
108 * </UL>
109 * The JE environment monitor entries provided by the server can be
110 * retrieved using the {@link MonitorManager#getJEEnvironmentMonitorEntries}
111 * method.  These entries provide specific methods for accessing information
112 * about the JE environment (e.g., the
113 * {@link JEEnvironmentMonitorEntry#getJEVersion} method can be used to retrieve
114 * the Berkeley DB JE version).  Alternately, this information may be accessed
115 * using the generic API.  See the {@link MonitorManager} class documentation
116 * for an example that demonstrates the use of the generic API for accessing
117 * monitor data.
118 */
119@NotMutable()
120@ThreadSafety(level=ThreadSafetyLevel.COMPLETELY_THREADSAFE)
121public final class JEEnvironmentMonitorEntry
122       extends MonitorEntry
123{
124  /**
125   * The structural object class used in JE environment monitor entries.
126   */
127  @NotNull static final String JE_ENVIRONMENT_MONITOR_OC =
128       "ds-je-environment-monitor-entry";
129
130
131
132  /**
133   * The name of the attribute that contains the number of active transactions.
134   */
135  @NotNull private static final String ATTR_ACTIVE_TXNS =
136       "active-transaction-count";
137
138
139
140  /**
141   * The name of the attribute that contains the average duration of the all
142   * checkpoints in milliseconds.
143   */
144  @NotNull private static final String ATTR_AVERAGE_CHECKPOINT_DURATION_MILLIS =
145       "average-checkpoint-duration-millis";
146
147
148
149  /**
150   * The name of the attribute that contains the backend ID for the associated
151   * backend.
152   */
153  @NotNull private static final String ATTR_BACKEND_ID = "backend-id";
154
155
156
157  /**
158   * The name of the attribute that contains the DB cache percent full.
159   */
160  @NotNull private static final String ATTR_CACHE_PCT_FULL =
161       "db-cache-percent-full";
162
163
164
165  /**
166   * The name of the attribute that indicates whether a checkpoint is currently
167   * in progress.
168   */
169  @NotNull private static final String ATTR_CHECKPOINT_IN_PROGRESS =
170       "checkpoint-in-progress";
171
172
173
174  /**
175   * The name of the attribute that contains the cleaner backlog.
176   */
177  @NotNull private static final String ATTR_CLEANER_BACKLOG = "cleaner-backlog";
178
179
180
181  /**
182   * The name of the attribute that contains the current DB cache size.
183   */
184  @NotNull private static final String ATTR_CURRENT_CACHE_SIZE =
185       "current-db-cache-size";
186
187
188
189  /**
190   * The name of the attribute that contains the path to the DB directory.
191   */
192  @NotNull private static final String ATTR_DB_DIRECTORY = "db-directory";
193
194
195
196  /**
197   * The name of the attribute that contains the DB on-disk size.
198   */
199  @NotNull private static final String ATTR_DB_ON_DISK_SIZE = "db-on-disk-size";
200
201
202
203  /**
204   * The name of the attribute that contains the Berkeley DB JE version string.
205   */
206  @NotNull private static final String ATTR_JE_VERSION = "je-version";
207
208
209
210  /**
211   * The name of the attribute that contains the duration of the last checkpoint
212   * in milliseconds.
213   */
214  @NotNull private static final String ATTR_LAST_CHECKPOINT_DURATION_MILLIS =
215       "last-checkpoint-duration-millis";
216
217
218
219  /**
220   * The name of the attribute that contains the time the last checkpoint began.
221   */
222  @NotNull private static final String ATTR_LAST_CHECKPOINT_START_TIME =
223       "last-checkpoint-start-time";
224
225
226
227  /**
228   * The name of the attribute that contains the time the last checkpoint ended.
229   */
230  @NotNull private static final String ATTR_LAST_CHECKPOINT_STOP_TIME =
231       "last-checkpoint-stop-time";
232
233
234
235  /**
236   * The name of the attribute that contains the time of the last checkpoint.
237   *
238   * @deprecated  Use {@link #ATTR_LAST_CHECKPOINT_STOP_TIME} instead.
239   */
240  @Deprecated()
241  @NotNull private static final String ATTR_LAST_CHECKPOINT_TIME =
242       "last-checkpoint-time";
243
244
245
246  /**
247   * The name of the attribute that contains the maximum cache size.
248   */
249  @NotNull private static final String ATTR_MAX_CACHE_SIZE =
250       "max-db-cache-size";
251
252
253
254  /**
255   * The name of the attribute that contains the length of time in milliseconds
256   * since the last checkpoint.
257   */
258  @NotNull private static final String ATTR_MILLIS_SINCE_LAST_CHECKPOINT =
259       "millis-since-last-checkpoint";
260
261
262
263  /**
264   * The name of the attribute that contains the number of nodes evicted from
265   * the cache.
266   */
267  @NotNull private static final String ATTR_NODES_EVICTED = "nodes-evicted";
268
269
270
271  /**
272   * The name of the attribute that contains the number of checkpoints
273   * processed.
274   */
275  @NotNull private static final String ATTR_NUM_CHECKPOINTS = "num-checkpoints";
276
277
278
279  /**
280   * The name of the attribute that contains the number of read locks held.
281   */
282  @NotNull private static final String ATTR_NUM_READ_LOCKS = "read-locks-held";
283
284
285
286  /**
287   * The name of the attribute that contains the total duration of the all
288   * checkpoints in milliseconds.
289   */
290  @NotNull private static final String ATTR_TOTAL_CHECKPOINT_DURATION_MILLIS =
291       "total-checkpoint-duration-millis";
292
293
294
295  /**
296   * The name of the attribute that contains the number of transactions waiting
297   * on locks.
298   */
299  @NotNull private static final String ATTR_NUM_WAITING_TXNS =
300       "transactions-waiting-on-locks";
301
302
303
304  /**
305   * The name of the attribute that contains the number of write locks held.
306   */
307  @NotNull private static final String ATTR_NUM_WRITE_LOCKS =
308       "write-locks-held";
309
310
311
312  /**
313   * The name of the attribute that contains the number of random reads.
314   */
315  @NotNull private static final String ATTR_RANDOM_READS = "random-read-count";
316
317
318
319  /**
320   * The name of the attribute that contains the number of random writes.
321   */
322  @NotNull private static final String ATTR_RANDOM_WRITES =
323       "random-write-count";
324
325
326
327  /**
328   * The name of the attribute that contains the number of sequential reads.
329   */
330  @NotNull private static final String ATTR_SEQUENTIAL_READS =
331       "sequential-read-count";
332
333
334
335  /**
336   * The name of the attribute that contains the number of sequential writes.
337   */
338  @NotNull private static final String ATTR_SEQUENTIAL_WRITES =
339       "sequential-write-count";
340
341
342
343  /**
344   * The prefix that will be used for attribute names that contain generic
345   * environment statistics.
346   */
347  @NotNull private static final String ATTR_PREFIX_ENV_STAT = "je-env-stat-";
348
349
350
351  /**
352   * The prefix that will be used for attribute names that contain generic lock
353   * statistics.
354   */
355  @NotNull private static final String ATTR_PREFIX_LOCK_STAT = "je-lock-stat-";
356
357
358
359  /**
360   * The prefix that will be used for attribute names that contain generic
361   * transaction statistics.
362   */
363  @NotNull private static final String ATTR_PREFIX_TXN_STAT = "je-txn-stat-";
364
365
366
367  /**
368   * The name that will be used for the property that contains generic
369   * environment statistics.
370   */
371  @NotNull private static final String PROPERTY_ENV_STATS = "je-env-stats";
372
373
374
375  /**
376   * The name that will be used for the property that contains generic lock
377   * statistics.
378   */
379  @NotNull private static final String PROPERTY_LOCK_STATS = "je-lock-stats";
380
381
382
383  /**
384   * The name that will be used for the property that contains generic
385   * transaction statistics.
386   */
387  @NotNull private static final String PROPERTY_TXN_STATS = "je-txn-stats";
388
389
390
391  /**
392   * The serial version UID for this serializable class.
393   */
394  private static final long serialVersionUID = 2557783119454069632L;
395
396
397
398  // Indicates whether a checkpoint is currently in progress.
399  @Nullable private final Boolean checkpointInProgress;
400
401  // The time the last checkpoint began.
402  @Nullable private final Date lastCheckpointStartTime;
403
404  // The time the last checkpoint ended.
405  @Nullable private final Date lastCheckpointStopTime;
406
407  /**
408   * The time the last checkpoint ended.
409   *
410   * @deprecated  Use lastCheckpointStopTime instead.
411   */
412  @Deprecated
413  @Nullable private final Date lastCheckpointTime;
414
415  // The number of active transactions.
416  @Nullable private final Long activeTransactionCount;
417
418  // The average duration for all checkpoints.
419  @Nullable private final Long averageCheckpointDurationMillis;
420
421  // The current cleaner backlog.
422  @Nullable private final Long cleanerBacklog;
423
424  // The current DB cache size.
425  @Nullable private final Long currentDBCacheSize;
426
427  // The current DB cache percent full.
428  @Nullable private final Long dbCachePercentFull;
429
430  // The current DB on-disk size.
431  @Nullable private final Long dbOnDiskSize;
432
433  // The duration for the last checkpoint.
434  @Nullable private final Long lastCheckpointDurationMillis;
435
436  // The maximum allowed DB cache size.
437  @Nullable private final Long maxDBCacheSize;
438
439  // The length of time since the last checkpoint.
440  @Nullable private final Long millisSinceLastCheckpoint;
441
442  // The number of nodes evicted from the DB cache.
443  @Nullable private final Long nodesEvicted;
444
445  // The number of checkpoints completed.
446  @Nullable private final Long numCheckpoints;
447
448  // The number of random reads performed.
449  @Nullable private final Long randomReads;
450
451  // The number of random writes performed.
452  @Nullable private final Long randomWrites;
453
454  // The number of read locks held.
455  @Nullable private final Long readLocksHeld;
456
457  // The number of sequential reads performed.
458  @Nullable private final Long sequentialReads;
459
460  // The number of sequential writes performed.
461  @Nullable private final Long sequentialWrites;
462
463  // The total duration for all checkpoints.
464  @Nullable private final Long totalCheckpointDurationMillis;
465
466  // The number of transactions waiting on locks.
467  @Nullable private final Long transactionsWaitingOnLocks;
468
469  // The number of write locks held.
470  @Nullable private final Long writeLocksHeld;
471
472  // The set of generic environment statistics.
473  @NotNull private final Map<String,String> envStats;
474
475  // The set of generic lock statistics.
476  @NotNull private final Map<String,String> lockStats;
477
478  // The set of generic transaction statistics.
479  @NotNull private final Map<String,String> txnStats;
480
481  // The backend ID for the associated backend.
482  @Nullable private final String backendID;
483
484  // The path to the directory containing the database files.
485  @Nullable private final String dbDirectory;
486
487  // The Berkeley DB JE version string.
488  @Nullable private final String jeVersion;
489
490
491
492  /**
493   * Creates a new JE environment monitor entry from the provided entry.
494   *
495   * @param  entry  The entry to be parsed as a JE environment monitor entry.
496   *                It must not be {@code null}.
497   */
498  @SuppressWarnings("deprecation")
499  public JEEnvironmentMonitorEntry(@NotNull final Entry entry)
500  {
501    super(entry);
502
503    activeTransactionCount     = getLong(ATTR_ACTIVE_TXNS);
504    cleanerBacklog             = getLong(ATTR_CLEANER_BACKLOG);
505    currentDBCacheSize         = getLong(ATTR_CURRENT_CACHE_SIZE);
506    dbCachePercentFull         = getLong(ATTR_CACHE_PCT_FULL);
507    dbOnDiskSize               = getLong(ATTR_DB_ON_DISK_SIZE);
508    maxDBCacheSize             = getLong(ATTR_MAX_CACHE_SIZE);
509    nodesEvicted               = getLong(ATTR_NODES_EVICTED);
510    randomReads                = getLong(ATTR_RANDOM_READS);
511    randomWrites               = getLong(ATTR_RANDOM_WRITES);
512    readLocksHeld              = getLong(ATTR_NUM_READ_LOCKS);
513    sequentialReads            = getLong(ATTR_SEQUENTIAL_READS);
514    sequentialWrites           = getLong(ATTR_SEQUENTIAL_WRITES);
515    transactionsWaitingOnLocks = getLong(ATTR_NUM_WAITING_TXNS);
516    writeLocksHeld             = getLong(ATTR_NUM_WRITE_LOCKS);
517    backendID                  = getString(ATTR_BACKEND_ID);
518    dbDirectory                = getString(ATTR_DB_DIRECTORY);
519    jeVersion                  = getString(ATTR_JE_VERSION);
520
521    checkpointInProgress = getBoolean(ATTR_CHECKPOINT_IN_PROGRESS);
522    lastCheckpointStartTime = getDate(ATTR_LAST_CHECKPOINT_START_TIME);
523    lastCheckpointStopTime = getDate(ATTR_LAST_CHECKPOINT_STOP_TIME);
524    lastCheckpointTime = getDate(ATTR_LAST_CHECKPOINT_TIME);
525    averageCheckpointDurationMillis  =
526         getLong(ATTR_AVERAGE_CHECKPOINT_DURATION_MILLIS);
527    lastCheckpointDurationMillis =
528         getLong(ATTR_LAST_CHECKPOINT_DURATION_MILLIS);
529    millisSinceLastCheckpoint = getLong(ATTR_MILLIS_SINCE_LAST_CHECKPOINT);
530    numCheckpoints = getLong(ATTR_NUM_CHECKPOINTS);
531    totalCheckpointDurationMillis =
532         getLong(ATTR_TOTAL_CHECKPOINT_DURATION_MILLIS);
533
534    final LinkedHashMap<String,String> tmpEnvStats =
535         new LinkedHashMap<>(StaticUtils.computeMapCapacity(20));
536    final LinkedHashMap<String,String> tmpLockStats =
537         new LinkedHashMap<>(StaticUtils.computeMapCapacity(20));
538    final LinkedHashMap<String,String> tmpTxnStats =
539         new LinkedHashMap<>(StaticUtils.computeMapCapacity(20));
540    for (final Attribute a : entry.getAttributes())
541    {
542      final String name = StaticUtils.toLowerCase(a.getName());
543      if (name.startsWith(ATTR_PREFIX_ENV_STAT))
544      {
545        tmpEnvStats.put(
546             StaticUtils.toLowerCase(name.substring(
547                  ATTR_PREFIX_ENV_STAT.length())),
548             a.getValue());
549      }
550      else if (name.startsWith(ATTR_PREFIX_LOCK_STAT))
551      {
552        tmpLockStats.put(
553             StaticUtils.toLowerCase(name.substring(
554                  ATTR_PREFIX_LOCK_STAT.length())),
555             a.getValue());
556      }
557      else if (name.startsWith(ATTR_PREFIX_TXN_STAT))
558      {
559        tmpTxnStats.put(
560             StaticUtils.toLowerCase(name.substring(
561                  ATTR_PREFIX_TXN_STAT.length())),
562             a.getValue());
563      }
564    }
565
566    envStats  = Collections.unmodifiableMap(tmpEnvStats);
567    lockStats = Collections.unmodifiableMap(tmpLockStats);
568    txnStats  = Collections.unmodifiableMap(tmpTxnStats);
569  }
570
571
572
573  /**
574   * Retrieves the backend ID for the backend with which the Berkeley DB JE
575   * database is associated.
576   *
577   * @return  The backend ID for the backend with which the Berkeley DB JE
578   *          database is associated.
579   */
580  @Nullable()
581  public String getBackendID()
582  {
583    return backendID;
584  }
585
586
587
588  /**
589   * Retrieves the Berkeley DB JE version string for the database environment
590   * of the associated backend.
591   *
592   * @return  The Berkeley DB JE version string for the database environment of
593   *          the associated backend, or {@code null} if it was not included in
594   *          the monitor entry.
595   */
596  @Nullable()
597  public String getJEVersion()
598  {
599    return jeVersion;
600  }
601
602
603
604  /**
605   * Retrieves the path to the directory containing the database files.
606   *
607   * @return  The path to the directory containing the database files, or
608   *          {@code null} if it was not included in the monitor entry.
609   */
610  @Nullable()
611  public String getDBDirectory()
612  {
613    return dbDirectory;
614  }
615
616
617
618  /**
619   * Retrieves the amount of disk space in bytes consumed by the database files.
620   *
621   * @return  The amount of disk space in bytes consumed by the database files,
622   *          or {@code null} if it was not included in the monitor entry.
623   */
624  @Nullable()
625  public Long getDBOnDiskSize()
626  {
627    return dbOnDiskSize;
628  }
629
630
631
632  /**
633   * Retrieves the amount of memory in bytes currently consumed by the database
634   * cache.
635   *
636   * @return  The amount of memory in bytes currently consumed by the database
637   *          cache, or {@code null} if it was not included in the monitor
638   *          entry.
639   */
640  @Nullable()
641  public Long getCurrentDBCacheSize()
642  {
643    return currentDBCacheSize;
644  }
645
646
647
648  /**
649   * Retrieves the maximum amount of memory in bytes that may be consumed by the
650   * database cache.
651   *
652   * @return  The maximum of memory in bytes that may be consumed by the
653   *          database cache, or {@code null} if it was not included in the
654   *          monitor entry.
655   */
656  @Nullable()
657  public Long getMaxDBCacheSize()
658  {
659    return maxDBCacheSize;
660  }
661
662
663
664  /**
665   * Retrieves the percentage of the maximum database cache size that is
666   * currently in use.
667   *
668   * @return  The percentage of the maximum database cache size that is
669   *          currently in use, or {@code null} if it was not included in the
670   *          monitor entry.
671   */
672  @Nullable()
673  public Long getDBCachePercentFull()
674  {
675    return dbCachePercentFull;
676  }
677
678
679
680  /**
681   * Indicates whether a checkpoint is currently in progress in the associated
682   * backend.
683   *
684   * @return  A {@code Boolean} value indicating whether a checkpoint is
685   *          currently in progress in the associated backend, or {@code null}
686   *          if it was not included in the monitor entry.
687   */
688  @Nullable()
689  public Boolean checkpointInProgress()
690  {
691    return checkpointInProgress;
692  }
693
694
695
696  /**
697   * Retrieves the number of checkpoints completed in the associated backend.
698   *
699   * @return  The number of checkpoints completed in the associated backend, or
700   *          {@code null} if it was not included in the monitor entry.
701   */
702  @Nullable()
703  public Long getNumCheckpoints()
704  {
705    return numCheckpoints;
706  }
707
708
709
710  /**
711   * Retrieves the total duration in milliseconds of all checkpoints completed
712   * in the associated backend.
713   *
714   * @return  The total duration in milliseconds of all checkpoints completed in
715   *          the associated backend, or {@code null} if it was not included in
716   *          the monitor entry.
717   */
718  @Nullable()
719  public Long getTotalCheckpointDurationMillis()
720  {
721    return totalCheckpointDurationMillis;
722  }
723
724
725
726  /**
727   * Retrieves the average duration in milliseconds of all checkpoints completed
728   * in the associated backend.
729   *
730   * @return  The average duration in milliseconds of all checkpoints completed
731   *          in the associated backend, or {@code null} if it was not included
732   *          in the monitor entry.
733   */
734  @Nullable()
735  public Long getAverageCheckpointDurationMillis()
736  {
737    return averageCheckpointDurationMillis;
738  }
739
740
741
742  /**
743   * Retrieves the duration in milliseconds of the last checkpoint completed in
744   * the associated backend.
745   *
746   * @return  The duration in milliseconds of the last checkpoint completed in
747   *          the associated backend, or {@code null} if it was not included
748   *          in the monitor entry.
749   */
750  @Nullable()
751  public Long getLastCheckpointDurationMillis()
752  {
753    return lastCheckpointDurationMillis;
754  }
755
756
757
758  /**
759   * Retrieves the time that the last completed checkpoint began.
760   *
761   * @return  The time that the last completed checkpoint began, or {@code null}
762   *          if it was not included in the monitor entry.
763   */
764  @Nullable()
765  public Date getLastCheckpointStartTime()
766  {
767    return lastCheckpointStartTime;
768  }
769
770
771
772  /**
773   * Retrieves the time that the last completed checkpoint ended.
774   *
775   * @return  The time that the last completed checkpoint ended, or {@code null}
776   *          if it was not included in the monitor entry.
777   */
778  @Nullable()
779  public Date getLastCheckpointStopTime()
780  {
781    return lastCheckpointStopTime;
782  }
783
784
785
786  /**
787   * Retrieves the time that the last checkpoint occurred.
788   *
789   * @return  The time that the last checkpoint occurred, or {@code null} if it
790   *          was not included in the monitor entry.
791   *
792   * @deprecated  Use {@link #getLastCheckpointStopTime()} instead.
793   */
794  @Deprecated()
795  @SuppressWarnings("deprecation")
796  @Nullable()
797  public Date getLastCheckpointTime()
798  {
799    return lastCheckpointTime;
800  }
801
802
803
804  /**
805   * Retrieves the length of time in milliseconds since the last completed
806   * checkpoint.
807   *
808   * @return  The length of time in milliseconds since the last completed
809   *          checkpoint, or {@code null} if it was not included in the monitor
810   *          entry.
811   */
812  @Nullable()
813  public Long getMillisSinceLastCheckpoint()
814  {
815    return millisSinceLastCheckpoint;
816  }
817
818
819
820  /**
821   * Retrieves the number of log files that the cleaner needs to examine.
822   *
823   * @return  The number of log files that the cleaner needs to examine, or
824   *          {@code null} if it was not included in the monitor entry.
825   */
826  @Nullable()
827  public Long getCleanerBacklog()
828  {
829    return cleanerBacklog;
830  }
831
832
833
834  /**
835   * Retrieves the number of nodes that have been evicted from the database
836   * cache since the backend was started.
837   *
838   * @return  The number of nodes that have been evicted from the database cache
839   *          since the backend was started, or {@code null} if it was not
840   *          included in the monitor entry.
841   */
842  @Nullable()
843  public Long getNodesEvicted()
844  {
845    return nodesEvicted;
846  }
847
848
849
850  /**
851   * Retrieves the number of random-access disk reads performed since the
852   * backend was started.
853   *
854   * @return  The number of random-access disk reads performed since the backend
855   *          was started, or {@code null} if it was not included in the monitor
856   *          entry.
857   */
858  @Nullable()
859  public Long getRandomReads()
860  {
861    return randomReads;
862  }
863
864
865
866  /**
867   * Retrieves the number of random-access disk writes performed since the
868   * backend was started.
869   *
870   * @return  The number of random-access disk writes performed since the
871   *          backend was started, or {@code null} if it was not included in the
872   *          monitor entry.
873   */
874  @Nullable()
875  public Long getRandomWrites()
876  {
877    return randomWrites;
878  }
879
880
881
882  /**
883   * Retrieves the number of sequential disk reads performed since the backend
884   * was started.
885   *
886   * @return  The number of sequential disk reads performed since the backend
887   *          was started, or {@code null} if it was not included in the monitor
888   *          entry.
889   */
890  @Nullable()
891  public Long getSequentialReads()
892  {
893    return sequentialReads;
894  }
895
896
897
898  /**
899   * Retrieves the number of sequential disk writes performed since the backend
900   * was started.
901   *
902   * @return  The number of sequential disk writes performed since the backend
903   *          was started, or {@code null} if it was not included in the monitor
904   *          entry.
905   */
906  @Nullable()
907  public Long getSequentialWrites()
908  {
909    return sequentialWrites;
910  }
911
912
913
914  /**
915   * Retrieves the number of active transactions in the JE database environment.
916   *
917   * @return  The number of active transactions in the JE database environment,
918   *          or {@code null} if it was not included in the monitor entry.
919   */
920  @Nullable()
921  public Long getActiveTransactionCount()
922  {
923    return activeTransactionCount;
924  }
925
926
927
928  /**
929   * Retrieves the number of read locks held in the JE database environment.
930   *
931   * @return  The number of read locks held in the JE database environment, or
932   *          {@code null} if it was not included in the monitor entry.
933   */
934  @Nullable()
935  public Long getReadLocksHeld()
936  {
937    return readLocksHeld;
938  }
939
940
941
942  /**
943   * Retrieves the number of write locks held in the JE database environment.
944   *
945   * @return  The number of write locks held in the JE database environment, or
946   *          {@code null} if it was not included in the monitor entry.
947   */
948  @Nullable()
949  public Long getWriteLocksHeld()
950  {
951    return writeLocksHeld;
952  }
953
954
955
956  /**
957   * Retrieves the number of transactions currently waiting on a lock in the
958   * database environment.
959   *
960   * @return  The number of transactions currently waiting on a lock in the
961   *          database environment, or {@code null} if it was not included in
962   *          the monitor entry.
963   */
964  @Nullable()
965  public Long getTransactionsWaitingOnLocks()
966  {
967    return transactionsWaitingOnLocks;
968  }
969
970
971
972  /**
973   * Retrieves a set of general environment statistics for the database
974   * environment, mapped from the statistic name to the string representation of
975   * its value.  The statistic names will be formatted in all lowercase
976   * characters.
977   *
978   * @return  A set of general environment statistics for the database
979   *          environment, mapped from the statistic name to the string
980   *          representation of its value.
981   */
982  @NotNull()
983  public Map<String,String> getEnvironmentStats()
984  {
985    return envStats;
986  }
987
988
989
990  /**
991   * Retrieves the string representation of the value for a database environment
992   * statistic.
993   *
994   * @param  statName  The name of the statistic to retrieve.  It will be
995   *                   treated in a case-insensitive manner.
996   *
997   * @return  The value of the requested database environment statistic, or
998   *          {@code null} if no such statistic was provided.
999   */
1000  @Nullable()
1001  public String getEnvironmentStat(@NotNull final String statName)
1002  {
1003    return envStats.get(StaticUtils.toLowerCase(statName));
1004  }
1005
1006
1007
1008  /**
1009   * Retrieves a set of lock statistics for the database environment, mapped
1010   * from the statistic name to the string representation of its value.  The
1011   * statistic names will be formatted in all lowercase characters.
1012   *
1013   * @return  A set of lock statistics for the database environment, mapped from
1014   *          the statistic name to the string representation of its value.
1015   */
1016  @NotNull()
1017  public Map<String,String> getLockStats()
1018  {
1019    return lockStats;
1020  }
1021
1022
1023
1024  /**
1025   * Retrieves the string representation of the value for a database environment
1026   * lock statistic.
1027   *
1028   * @param  statName  The name of the statistic to retrieve.  It will be
1029   *                   treated in a case-insensitive manner.
1030   *
1031   * @return  The value of the requested database environment lock statistic, or
1032   *          {@code null} if no such statistic was provided.
1033   */
1034  @Nullable()
1035  public String getLockStat(@NotNull final String statName)
1036  {
1037    return lockStats.get(StaticUtils.toLowerCase(statName));
1038  }
1039
1040
1041
1042  /**
1043   * Retrieves a set of transaction statistics for the database environment,
1044   * mapped from the statistic name to the string representation of its value.
1045   * The statistic names will be formatted in all lowercase characters.
1046   *
1047   * @return  A set of transaction statistics for the database environment,
1048   *          mapped from the statistic name to the string representation of its
1049   *          value.
1050   */
1051  @NotNull()
1052  public Map<String,String> getTransactionStats()
1053  {
1054    return txnStats;
1055  }
1056
1057
1058
1059  /**
1060   * Retrieves the string representation of the value for a database environment
1061   * transaction statistic.
1062   *
1063   * @param  statName  The name of the statistic to retrieve.  It will be
1064   *                   treated in a case-insensitive manner.
1065   *
1066   * @return  The value of the requested database environment transaction
1067   *          statistic, or {@code null} if no such statistic was provided.
1068   */
1069  @Nullable()
1070  public String getTransactionStat(@NotNull final String statName)
1071  {
1072    return txnStats.get(StaticUtils.toLowerCase(statName));
1073  }
1074
1075
1076
1077  /**
1078   * {@inheritDoc}
1079   */
1080  @Override()
1081  @NotNull()
1082  public String getMonitorDisplayName()
1083  {
1084    return INFO_JE_ENVIRONMENT_MONITOR_DISPNAME.get();
1085  }
1086
1087
1088
1089  /**
1090   * {@inheritDoc}
1091   */
1092  @Override()
1093  @NotNull()
1094  public String getMonitorDescription()
1095  {
1096    return INFO_JE_ENVIRONMENT_MONITOR_DESC.get();
1097  }
1098
1099
1100
1101  /**
1102   * {@inheritDoc}
1103   */
1104  @Override()
1105  @NotNull()
1106  public Map<String,MonitorAttribute> getMonitorAttributes()
1107  {
1108    final LinkedHashMap<String,MonitorAttribute> attrs =
1109         new LinkedHashMap<>(StaticUtils.computeMapCapacity(20));
1110
1111    if (backendID != null)
1112    {
1113      addMonitorAttribute(attrs,
1114           ATTR_BACKEND_ID,
1115           INFO_JE_ENVIRONMENT_DISPNAME_BACKEND_ID.get(),
1116           INFO_JE_ENVIRONMENT_DESC_BACKEND_ID.get(),
1117           backendID);
1118    }
1119
1120    if (jeVersion != null)
1121    {
1122      addMonitorAttribute(attrs,
1123           ATTR_JE_VERSION,
1124           INFO_JE_ENVIRONMENT_DISPNAME_JE_VERSION.get(),
1125           INFO_JE_ENVIRONMENT_DESC_JE_VERSION.get(),
1126           jeVersion);
1127    }
1128
1129    if (dbDirectory != null)
1130    {
1131      addMonitorAttribute(attrs,
1132           ATTR_DB_DIRECTORY,
1133           INFO_JE_ENVIRONMENT_DISPNAME_DB_DIRECTORY.get(),
1134           INFO_JE_ENVIRONMENT_DESC_DB_DIRECTORY.get(),
1135           dbDirectory);
1136    }
1137
1138    if (dbOnDiskSize != null)
1139    {
1140      addMonitorAttribute(attrs,
1141           ATTR_DB_ON_DISK_SIZE,
1142           INFO_JE_ENVIRONMENT_DISPNAME_DB_ON_DISK_SIZE.get(),
1143           INFO_JE_ENVIRONMENT_DESC_DB_ON_DISK_SIZE.get(),
1144           dbOnDiskSize);
1145    }
1146
1147    if (currentDBCacheSize != null)
1148    {
1149      addMonitorAttribute(attrs,
1150           ATTR_CURRENT_CACHE_SIZE,
1151           INFO_JE_ENVIRONMENT_DISPNAME_CURRENT_CACHE_SIZE.get(),
1152           INFO_JE_ENVIRONMENT_DESC_CURRENT_CACHE_SIZE.get(),
1153           currentDBCacheSize);
1154    }
1155
1156    if (maxDBCacheSize != null)
1157    {
1158      addMonitorAttribute(attrs,
1159           ATTR_MAX_CACHE_SIZE,
1160           INFO_JE_ENVIRONMENT_DISPNAME_MAX_CACHE_SIZE.get(),
1161           INFO_JE_ENVIRONMENT_DESC_MAX_CACHE_SIZE.get(),
1162           maxDBCacheSize);
1163    }
1164
1165    if (dbCachePercentFull != null)
1166    {
1167      addMonitorAttribute(attrs,
1168           ATTR_CACHE_PCT_FULL,
1169           INFO_JE_ENVIRONMENT_DISPNAME_CACHE_PCT_FULL.get(),
1170           INFO_JE_ENVIRONMENT_DESC_CACHE_PCT_FULL.get(),
1171           dbCachePercentFull);
1172    }
1173
1174    if (checkpointInProgress != null)
1175    {
1176      addMonitorAttribute(attrs,
1177           ATTR_CHECKPOINT_IN_PROGRESS,
1178           INFO_JE_ENVIRONMENT_DISPNAME_CP_IN_PROGRESS.get(),
1179           INFO_JE_ENVIRONMENT_DESC_CP_IN_PROGRESS.get(),
1180           checkpointInProgress);
1181    }
1182
1183    if (numCheckpoints != null)
1184    {
1185      addMonitorAttribute(attrs,
1186           ATTR_NUM_CHECKPOINTS,
1187           INFO_JE_ENVIRONMENT_DISPNAME_NUM_CP.get(),
1188           INFO_JE_ENVIRONMENT_DESC_NUM_CP.get(),
1189           numCheckpoints);
1190    }
1191
1192    if (totalCheckpointDurationMillis != null)
1193    {
1194      addMonitorAttribute(attrs,
1195           ATTR_TOTAL_CHECKPOINT_DURATION_MILLIS,
1196           INFO_JE_ENVIRONMENT_DISPNAME_TOTAL_CP_DURATION.get(),
1197           INFO_JE_ENVIRONMENT_DESC_TOTAL_CP_DURATION.get(),
1198           totalCheckpointDurationMillis);
1199    }
1200
1201    if (averageCheckpointDurationMillis != null)
1202    {
1203      addMonitorAttribute(attrs,
1204           ATTR_AVERAGE_CHECKPOINT_DURATION_MILLIS,
1205           INFO_JE_ENVIRONMENT_DISPNAME_AVG_CP_DURATION.get(),
1206           INFO_JE_ENVIRONMENT_DESC_AVG_CP_DURATION.get(),
1207           averageCheckpointDurationMillis);
1208    }
1209
1210    if (lastCheckpointDurationMillis != null)
1211    {
1212      addMonitorAttribute(attrs,
1213           ATTR_LAST_CHECKPOINT_DURATION_MILLIS,
1214           INFO_JE_ENVIRONMENT_DISPNAME_LAST_CP_DURATION.get(),
1215           INFO_JE_ENVIRONMENT_DESC_LAST_CP_DURATION.get(),
1216           lastCheckpointDurationMillis);
1217    }
1218
1219    if (lastCheckpointStartTime != null)
1220    {
1221      addMonitorAttribute(attrs,
1222           ATTR_LAST_CHECKPOINT_START_TIME,
1223           INFO_JE_ENVIRONMENT_DISPNAME_LAST_CP_START_TIME.get(),
1224           INFO_JE_ENVIRONMENT_DESC_LAST_CP_START_TIME.get(),
1225           lastCheckpointStartTime);
1226    }
1227
1228    if (lastCheckpointStopTime != null)
1229    {
1230      addMonitorAttribute(attrs,
1231           ATTR_LAST_CHECKPOINT_STOP_TIME,
1232           INFO_JE_ENVIRONMENT_DISPNAME_LAST_CP_STOP_TIME.get(),
1233           INFO_JE_ENVIRONMENT_DESC_LAST_CP_STOP_TIME.get(),
1234           lastCheckpointStopTime);
1235    }
1236
1237    if (millisSinceLastCheckpoint != null)
1238    {
1239      addMonitorAttribute(attrs,
1240           ATTR_MILLIS_SINCE_LAST_CHECKPOINT,
1241           INFO_JE_ENVIRONMENT_DISPNAME_MILLIS_SINCE_CP.get(),
1242           INFO_JE_ENVIRONMENT_DESC_MILLIS_SINCE_CP.get(),
1243           millisSinceLastCheckpoint);
1244    }
1245
1246    if (cleanerBacklog != null)
1247    {
1248      addMonitorAttribute(attrs,
1249           ATTR_CLEANER_BACKLOG,
1250           INFO_JE_ENVIRONMENT_DISPNAME_CLEANER_BACKLOG.get(),
1251           INFO_JE_ENVIRONMENT_DESC_CLEANER_BACKLOG.get(),
1252           cleanerBacklog);
1253    }
1254
1255    if (nodesEvicted != null)
1256    {
1257      addMonitorAttribute(attrs,
1258           ATTR_NODES_EVICTED,
1259           INFO_JE_ENVIRONMENT_DISPNAME_NODES_EVICTED.get(),
1260           INFO_JE_ENVIRONMENT_DESC_NODES_EVICTED.get(),
1261           nodesEvicted);
1262    }
1263
1264    if (randomReads != null)
1265    {
1266      addMonitorAttribute(attrs,
1267           ATTR_RANDOM_READS,
1268           INFO_JE_ENVIRONMENT_DISPNAME_RANDOM_READS.get(),
1269           INFO_JE_ENVIRONMENT_DESC_RANDOM_READS.get(),
1270           randomReads);
1271    }
1272
1273    if (randomWrites != null)
1274    {
1275      addMonitorAttribute(attrs,
1276           ATTR_RANDOM_WRITES,
1277           INFO_JE_ENVIRONMENT_DISPNAME_RANDOM_WRITES.get(),
1278           INFO_JE_ENVIRONMENT_DESC_RANDOM_WRITES.get(),
1279           randomWrites);
1280    }
1281
1282    if (sequentialReads != null)
1283    {
1284      addMonitorAttribute(attrs,
1285           ATTR_SEQUENTIAL_READS,
1286           INFO_JE_ENVIRONMENT_DISPNAME_SEQUENTIAL_READS.get(),
1287           INFO_JE_ENVIRONMENT_DESC_SEQUENTIAL_READS.get(),
1288           sequentialReads);
1289    }
1290
1291    if (sequentialWrites != null)
1292    {
1293      addMonitorAttribute(attrs,
1294           ATTR_SEQUENTIAL_WRITES,
1295           INFO_JE_ENVIRONMENT_DISPNAME_SEQUENTIAL_WRITES.get(),
1296           INFO_JE_ENVIRONMENT_DESC_SEQUENTIAL_WRITES.get(),
1297           sequentialWrites);
1298    }
1299
1300    if (activeTransactionCount != null)
1301    {
1302      addMonitorAttribute(attrs,
1303           ATTR_ACTIVE_TXNS,
1304           INFO_JE_ENVIRONMENT_DISPNAME_ACTIVE_TXNS.get(),
1305           INFO_JE_ENVIRONMENT_DESC_ACTIVE_TXNS.get(),
1306           activeTransactionCount);
1307    }
1308
1309    if (readLocksHeld != null)
1310    {
1311      addMonitorAttribute(attrs,
1312           ATTR_NUM_READ_LOCKS,
1313           INFO_JE_ENVIRONMENT_DISPNAME_READ_LOCKS.get(),
1314           INFO_JE_ENVIRONMENT_DESC_READ_LOCKS.get(),
1315           readLocksHeld);
1316    }
1317
1318    if (writeLocksHeld != null)
1319    {
1320      addMonitorAttribute(attrs,
1321           ATTR_NUM_WRITE_LOCKS,
1322           INFO_JE_ENVIRONMENT_DISPNAME_WRITE_LOCKS.get(),
1323           INFO_JE_ENVIRONMENT_DESC_WRITE_LOCKS.get(),
1324           writeLocksHeld);
1325    }
1326
1327    if (transactionsWaitingOnLocks != null)
1328    {
1329      addMonitorAttribute(attrs,
1330           ATTR_NUM_WAITING_TXNS,
1331           INFO_JE_ENVIRONMENT_DISPNAME_TXNS_WAITING_ON_LOCKS.get(),
1332           INFO_JE_ENVIRONMENT_DESC_TXNS_WAITING_ON_LOCKS.get(),
1333           transactionsWaitingOnLocks);
1334    }
1335
1336    if (! envStats.isEmpty())
1337    {
1338      final ArrayList<String> values = new ArrayList<>(envStats.size());
1339      for (final Map.Entry<String,String> e : envStats.entrySet())
1340      {
1341        values.add(e.getKey() + '=' + e.getValue());
1342      }
1343
1344      addMonitorAttribute(attrs,
1345           PROPERTY_ENV_STATS,
1346           INFO_JE_ENVIRONMENT_DISPNAME_ENV_STATS.get(),
1347           INFO_JE_ENVIRONMENT_DESC_ENV_STATS.get(),
1348           values);
1349    }
1350
1351    if (! lockStats.isEmpty())
1352    {
1353      final ArrayList<String> values = new ArrayList<>(lockStats.size());
1354      for (final Map.Entry<String,String> e : lockStats.entrySet())
1355      {
1356        values.add(e.getKey() + '=' + e.getValue());
1357      }
1358
1359      addMonitorAttribute(attrs,
1360           PROPERTY_LOCK_STATS,
1361           INFO_JE_ENVIRONMENT_DISPNAME_LOCK_STATS.get(),
1362           INFO_JE_ENVIRONMENT_DESC_LOCK_STATS.get(),
1363           values);
1364    }
1365
1366    if (! txnStats.isEmpty())
1367    {
1368      final ArrayList<String> values = new ArrayList<>(txnStats.size());
1369      for (final Map.Entry<String,String> e : txnStats.entrySet())
1370      {
1371        values.add(e.getKey() + '=' + e.getValue());
1372      }
1373
1374      addMonitorAttribute(attrs,
1375           PROPERTY_TXN_STATS,
1376           INFO_JE_ENVIRONMENT_DISPNAME_TXN_STATS.get(),
1377           INFO_JE_ENVIRONMENT_DESC_TXN_STATS.get(),
1378           values);
1379    }
1380
1381    return Collections.unmodifiableMap(attrs);
1382  }
1383}