001    /*
002     * Copyright 2010-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.Collections;
026    import java.util.LinkedHashMap;
027    import java.util.Map;
028    
029    import com.unboundid.ldap.sdk.Entry;
030    import com.unboundid.util.NotMutable;
031    import com.unboundid.util.ThreadSafety;
032    import com.unboundid.util.ThreadSafetyLevel;
033    
034    import static com.unboundid.ldap.sdk.unboundidds.monitors.MonitorMessages.*;
035    
036    
037    
038    /**
039     * <BLOCKQUOTE>
040     *   <B>NOTE:</B>  This class is part of the Commercial Edition of the UnboundID
041     *   LDAP SDK for Java.  It is not available for use in applications that
042     *   include only the Standard Edition of the LDAP SDK, and is not supported for
043     *   use in conjunction with non-UnboundID products.
044     * </BLOCKQUOTE>
045     * This class defines a monitor entry that provides general information about
046     * the state of an index in a Directory Server backend.  Note that the term
047     * "index" may refer to a number of different things, including attribute
048     * indexes (in which each individual index type will be considered a separate
049     * index, so if "cn" has equality and substring index types then that will be
050     * considered two separate indexes), VLV indexes, and system indexes (for
051     * databases that are maintained internally, like id2entry, dn2id, id2children,
052     * and id2subtree).
053     * <BR><BR>
054     * The set of index monitor entries published by the directory server can be
055     * obtained using the {@link MonitorManager#getIndexMonitorEntries} method.
056     * Specific methods are available for accessing the associated monitor data
057     * (e.g., {@link IndexMonitorEntry#getBackendID} to retrieve the backend ID),
058     * and there are also methods for accessing this information in a generic manner
059     * (e.g., {@link IndexMonitorEntry#getMonitorAttributes} to retrieve all of
060     * the monitor attributes).  See the {@link MonitorManager} class documentation
061     * for an example that demonstrates the use of the generic API for accessing
062     * monitor data.
063     */
064    @NotMutable()
065    @ThreadSafety(level=ThreadSafetyLevel.COMPLETELY_THREADSAFE)
066    public final class IndexMonitorEntry
067           extends MonitorEntry
068    {
069      /**
070       * The structural object class used in index monitor entries.
071       */
072      static final String INDEX_MONITOR_OC = "ds-index-monitor-entry";
073    
074    
075    
076      /**
077       * The name of the attribute that contains the index name.
078       */
079      private static final String ATTR_INDEX_NAME = "ds-index-name";
080    
081    
082    
083      /**
084       * The name of the attribute that contains the backend ID.
085       */
086      private static final String ATTR_BACKEND_ID = "ds-index-backend-id";
087    
088    
089    
090      /**
091       * The name of the attribute that contains the backend base DN.
092       */
093      private static final String ATTR_BASE_DN = "ds-index-backend-base-dn";
094    
095    
096    
097      /**
098       * The name of the attribute that contains the name of the associated
099       * attribute type.
100       */
101      private static final String ATTR_INDEX_ATTR = "ds-index-attribute-type";
102    
103    
104    
105      /**
106       * The name of the attribute that contains the name of the associated
107       * attribute index type.
108       */
109      private static final String ATTR_INDEX_TYPE = "ds-index-type";
110    
111    
112    
113      /**
114       * The name of the attribute that contains the string representation of a
115       * filter used for the index.
116       */
117      private static final String ATTR_INDEX_FILTER = "ds-index-filter";
118    
119    
120    
121      /**
122       * The name of the attribute that indicates whether the index is trusted.
123       */
124      private static final String ATTR_INDEX_TRUSTED = "ds-index-trusted";
125    
126    
127    
128      /**
129       * The name of the attribute that contains the index entry limit.
130       */
131      private static final String ATTR_ENTRY_LIMIT = "ds-index-entry-limit";
132    
133    
134    
135      /**
136       * The name of the attribute that contains the number of index keys for which
137       * the entry count has exceeded the limit since the index DB was opened.
138       */
139      private static final String ATTR_EXCEEDED_COUNT =
140           "ds-index-exceeded-entry-limit-count-since-db-open";
141    
142    
143    
144      /**
145       * The name of the attribute that indicates whether a matching count should be
146       * maintained for a key that has exceeded the entry limit.
147       */
148      private static final String ATTR_MAINTAIN_COUNT =
149           "ds-index-maintain-count";
150    
151    
152    
153      /**
154       * The name of the attribute that indicates whether the index was fully
155       * primed.
156       */
157      private static final String ATTR_FULLY_PRIMED =
158           "ds-index-fully-primed-at-backend-open";
159    
160    
161    
162      /**
163       * The name of the attribute that contains a reason explaining why the prime
164       * was not completed.
165       */
166      private static final String ATTR_PRIME_INCOMPLETE_REASON =
167           "ds-index-prime-incomplete-reason";
168    
169    
170    
171      /**
172       * The name of the attribute that contains information about an exception that
173       * was encountered while performing the prime.
174       */
175      private static final String ATTR_PRIME_EXCEPTION =
176           "ds-index-prime-exception";
177    
178    
179    
180      /**
181       * The name of the attribute that contains the number of keys that were
182       * primed when the backend was opened.
183       */
184      private static final String ATTR_PRIMED_KEYS =
185           "ds-index-num-primed-keys-at-backend-open";
186    
187    
188    
189      /**
190       * The name of the attribute that contains the number of times the index has
191       * been updated since the database was opened.
192       */
193      private static final String ATTR_WRITE_COUNT =
194           "ds-index-write-count-since-db-open";
195    
196    
197    
198      /**
199       * The name of the attribute that contains the number of keys deleted from the
200       * index since the database was opened.
201       */
202      private static final String ATTR_DELETE_COUNT =
203           "ds-index-remove-count-since-db-open";
204    
205    
206    
207      /**
208       * The name of the attribute that contains the number of read operations
209       * against the index since the database was opened.
210       */
211      private static final String ATTR_READ_COUNT =
212           "ds-index-read-count-since-db-open";
213    
214    
215    
216      /**
217       * The name of the attribute that contains the number of read operations
218       * performed during search filter evaluation since the database was opened.
219       */
220      private static final String ATTR_READ_FOR_SEARCH_COUNT =
221           "ds-index-read-for-search-count-since-db-open";
222    
223    
224    
225      /**
226       * The name of the attribute that contains the number of cursors created for
227       * the index.
228       */
229      private static final String ATTR_CURSOR_COUNT =
230           "ds-index-open-cursor-count-since-db-open";
231    
232    
233    
234      /**
235       * The serial version UID for this serializable class.
236       */
237      private static final long serialVersionUID = 9182830448328951893L;
238    
239    
240    
241      // Indicates whether the index was fully primed when the backend came online.
242      private final Boolean fullyPrimed;
243    
244      // Indicates whether the index should be considered trusted.
245      private final Boolean indexTrusted;
246    
247      // Indicates whether to maintain a count of matching entries even when the ID
248      // list is not maintained.
249      private final Boolean maintainCount;
250    
251      // The index entry limit for the index.
252      private final Long entryLimit;
253    
254      // The number of keys that have exceeded the entry limit since coming online.
255      private final Long exceededCount;
256    
257      // The number of cursors created in the index since coming online.
258      private final Long numCursors;
259    
260      // The number of index keys deleted from the index since coming online.
261      private final Long numDeletes;
262    
263      // The number of reads from the index since coming online.
264      private final Long numReads;
265    
266      // The number of reads as a result of filter processing from the index since
267      // coming online.
268      private final Long numReadsForSearch;
269    
270      // The number of writes to the index since coming online.
271      private final Long numWrites;
272    
273      // The number of keys that were primed when the backend came online.
274      private final Long primedKeys;
275    
276      // The name of the associated attribute type.
277      private final String attributeType;
278    
279      // The name of the associated backend ID.
280      private final String backendID;
281    
282      // The base DN for the associated backend.
283      private final String baseDN;
284    
285      // The filter for the associated index.
286      private final String indexFilter;
287    
288      // The index name for the associated index.
289      private final String indexName;
290    
291      // The index name of the index type for the index.
292      private final String indexType;
293    
294      // Information about an exception caught during prime processing.
295      private final String primeException;
296    
297      // Information about the reason the prime was not completed.
298      private final String primeIncompleteReason;
299    
300    
301    
302      /**
303       * Creates a new index monitor entry from the provided entry.
304       *
305       * @param  entry  The entry to be parsed as an index monitor entry.  It must
306       *                not be {@code null}.
307       */
308      public IndexMonitorEntry(final Entry entry)
309      {
310        super(entry);
311    
312        fullyPrimed           = getBoolean(ATTR_FULLY_PRIMED);
313        indexTrusted          = getBoolean(ATTR_INDEX_TRUSTED);
314        maintainCount         = getBoolean(ATTR_MAINTAIN_COUNT);
315        entryLimit            = getLong(ATTR_ENTRY_LIMIT);
316        exceededCount         = getLong(ATTR_EXCEEDED_COUNT);
317        numCursors            = getLong(ATTR_CURSOR_COUNT);
318        numDeletes            = getLong(ATTR_DELETE_COUNT);
319        numReads              = getLong(ATTR_READ_COUNT);
320        numReadsForSearch     = getLong(ATTR_READ_FOR_SEARCH_COUNT);
321        numWrites             = getLong(ATTR_WRITE_COUNT);
322        primedKeys            = getLong(ATTR_PRIMED_KEYS);
323        attributeType         = getString(ATTR_INDEX_ATTR);
324        backendID             = getString(ATTR_BACKEND_ID);
325        baseDN                = getString(ATTR_BASE_DN);
326        indexFilter           = getString(ATTR_INDEX_FILTER);
327        indexName             = getString(ATTR_INDEX_NAME);
328        indexType             = getString(ATTR_INDEX_TYPE);
329        primeException        = getString(ATTR_PRIME_EXCEPTION);
330        primeIncompleteReason = getString(ATTR_PRIME_INCOMPLETE_REASON);
331      }
332    
333    
334    
335      /**
336       * Retrieves the name of the index database.
337       *
338       * @return  The name of the index database, or {@code null} if it was not
339       *          included in the monitor entry.
340       */
341      public String getIndexName()
342      {
343        return indexName;
344      }
345    
346    
347    
348      /**
349       * Retrieves the backend ID for the associated backend.
350       *
351       * @return  The backend ID for the associated backend, or {@code null} if it
352       *          was not included in the monitor entry.
353       */
354      public String getBackendID()
355      {
356        return backendID;
357      }
358    
359    
360    
361      /**
362       * Retrieves the base DN for the data with which the index is associated.
363       *
364       * @return  The base DN for the data with which the index is associated, or
365       *          {@code null} if it was not included in the monitor entry.
366       */
367      public String getBaseDN()
368      {
369        return baseDN;
370      }
371    
372    
373    
374      /**
375       * Retrieves the name of the attribute type with which the index is
376       * associated.  It will only be available for attribute indexes.
377       *
378       * @return  The name of the attribute type with which the index is associated,
379       *          or {@code null} if it was not included in the monitor entry.
380       */
381      public String getAttributeType()
382      {
383        return attributeType;
384      }
385    
386    
387    
388      /**
389       * Retrieves the name of the attribute index type.  It will only be available
390       * for attribute indexes.
391       *
392       * @return  The name of the attribute index type, or {@code null} if it was
393       *          not included in the monitor entry.
394       */
395      public String getAttributeIndexType()
396      {
397        return indexType;
398      }
399    
400    
401    
402      /**
403       * Retrieves the filter used for the index.  It will only be available for
404       * filter indexes.
405       *
406       * @return  The filter used for the index, or {@code null} if it was not
407       *          included in the monitor entry.
408       */
409      public String getIndexFilter()
410      {
411        return indexFilter;
412      }
413    
414    
415    
416      /**
417       * Indicates whether the index may be considered trusted.  It will only be
418       * available for attribute indexes.
419       *
420       * @return  {@code true} if the index may be considered trusted,
421       *          {@code false} if it is not trusted, or {@code null} if it was not
422       *          included in the monitor entry.
423       */
424      public Boolean isIndexTrusted()
425      {
426        return indexTrusted;
427      }
428    
429    
430    
431      /**
432       * Retrieves the index entry limit, which is the maximum number of entries
433       * that will be allowed to match a key before the ID list for that key will
434       * stop being maintained.
435       *
436       * @return  The index entry limit, or {@code null} if was not included in the
437       *          monitor entry.
438       */
439      public Long getIndexEntryLimit()
440      {
441        return entryLimit;
442      }
443    
444    
445    
446      /**
447       * Retrieves the number of index keys which have stopped being maintained
448       * because the number of matching entries has exceeded the entry limit since
449       * the index was brought online.
450       *
451       * @return  The number of index keys which have exceeded the entry limit since
452       *          the index was brought online, or {@code null} if it was not
453       *          included in the monitor entry.
454       */
455      public Long getEntryLimitExceededCountSinceComingOnline()
456      {
457        return exceededCount;
458      }
459    
460    
461    
462      /**
463       * Indicates whether the count of matching entries will be maintained for
464       * index keys that have exceeded the entry limit.  In that case, the entry IDs
465       * for the matching entries will not be available, but the number of matching
466       * entries will be.
467       *
468       * @return  {@code true} if the count of matching entries will be maintained
469       *          for index keys that have exceeded the entry limit, {@code false}
470       *          if not, or {@code null} if it was not included in the monitor
471       *          entry.
472       */
473      public Boolean maintainCountForExceededKeys()
474      {
475        return maintainCount;
476      }
477    
478    
479    
480      /**
481       * Indicates whether this index was fully primed when it was brought online.
482       *
483       * @return  {@code true} if the index was fully primed when it was brought
484       *          online, {@code false} if not, or {@code null} if it was not
485       *          included in the monitor entry.
486       */
487      public Boolean fullyPrimedWhenBroughtOnline()
488      {
489        return fullyPrimed;
490      }
491    
492    
493    
494      /**
495       * Retrieves information about the reason that the index was not fully primed
496       * when the backend was brought online (e.g., the database cache became full,
497       * the prime took too long to complete, or an exception was caught during
498       * processing).
499       *
500       * @return  Information about the reason that the index was not fully primed
501       *          when the backend was brought online, or {@code null} if it was not
502       *          included in the monitor entry.
503       */
504      public String getPrimeIncompleteReason()
505      {
506        return primeIncompleteReason;
507      }
508    
509    
510    
511      /**
512       * Retrieves information about any exception caught during prime processing.
513       *
514       * @return  Information about any exception caught during prime processing, or
515       *          {@code null} if it was not included in the monitor entry.
516       */
517      public String getPrimeException()
518      {
519        return primeException;
520      }
521    
522    
523    
524      /**
525       * Retrieves the number of index keys that were primed when the index was
526       * brought online.
527       *
528       * @return  The number of index keys that were primed when the backend was
529       *          brought online, or {@code null} if it was not included in the
530       *          monitor entry.
531       */
532      public Long getKeysPrimedWhenBroughtOnline()
533      {
534        return primedKeys;
535      }
536    
537    
538    
539      /**
540       * Retrieves the number of index keys that have been inserted or replaced
541       * since the index was brought online.
542       *
543       * @return  The number of index keys that have been inserted or replaced since
544       *          the index was brought online, or {@code null} if it was not
545       *          included in the monitor entry.
546       */
547      public Long getKeysWrittenSinceComingOnline()
548      {
549        return numWrites;
550      }
551    
552    
553    
554      /**
555       * Retrieves the number of index keys that have been deleted since the index
556       * was brought online.
557       *
558       * @return  The number of index keys that have been deleted since the index
559       *          was brought online, or {@code null} if it was not included in the
560       *          monitor entry.
561       */
562      public Long getKeysDeletedSinceComingOnline()
563      {
564        return numDeletes;
565      }
566    
567    
568    
569      /**
570       * Retrieves the number of index keys that have been read since the index was
571       * brought online.
572       *
573       * @return  The number of index keys that have been read since the index was
574       *          brought online, or {@code null} if it was not included in the
575       *          monitor entry.
576       */
577      public Long getKeysReadSinceComingOnline()
578      {
579        return numReads;
580      }
581    
582    
583    
584      /**
585       * Retrieves the number of index reads that have been initiated because the
586       * associated attribute type was included in the filter for a search operation
587       * with a non-base scope since the index was brought online.
588       *
589       * @return  The number of index reads that have been initiated as a result of
590       *          filter processing, or {@code null} if it was not included in the
591       *          monitor entry.
592       */
593      public Long getFilterInitiatedReadsSinceComingOnline()
594      {
595        return numReadsForSearch;
596      }
597    
598    
599    
600      /**
601       * Retrieves the number of cursors created in the index for reading ranges of
602       * keys.  Cursors may be used for processing in a variety of contexts,
603       * including processing for substring or range searches, subtree deletes,
604       * stream values operations, etc.
605       *
606       * @return  The number of cursors created in the index for reading ranges of
607       *          keys, or {@code null} if it was not included in the monitor entry.
608       */
609      public Long getCursorsCreatedSinceComingOnline()
610      {
611        return numCursors;
612      }
613    
614    
615    
616      /**
617       * {@inheritDoc}
618       */
619      @Override()
620      public String getMonitorDisplayName()
621      {
622        return INFO_INDEX_MONITOR_DISPNAME.get();
623      }
624    
625    
626    
627      /**
628       * {@inheritDoc}
629       */
630      @Override()
631      public String getMonitorDescription()
632      {
633        return INFO_INDEX_MONITOR_DESC.get();
634      }
635    
636    
637    
638      /**
639       * {@inheritDoc}
640       */
641      @Override()
642      public Map<String,MonitorAttribute> getMonitorAttributes()
643      {
644        final LinkedHashMap<String,MonitorAttribute> attrs =
645             new LinkedHashMap<String,MonitorAttribute>(19);
646    
647        if (indexName != null)
648        {
649          addMonitorAttribute(attrs,
650               ATTR_INDEX_NAME,
651               INFO_INDEX_DISPNAME_INDEX_NAME.get(),
652               INFO_INDEX_DESC_INDEX_NAME.get(),
653               indexName);
654        }
655    
656        if (backendID != null)
657        {
658          addMonitorAttribute(attrs,
659               ATTR_BACKEND_ID,
660               INFO_INDEX_DISPNAME_BACKEND_ID.get(),
661               INFO_INDEX_DESC_BACKEND_ID.get(),
662               backendID);
663        }
664    
665        if (baseDN != null)
666        {
667          addMonitorAttribute(attrs,
668               ATTR_BASE_DN,
669               INFO_INDEX_DISPNAME_BASE_DN.get(),
670               INFO_INDEX_DESC_BASE_DN.get(),
671               baseDN);
672        }
673    
674        if (attributeType != null)
675        {
676          addMonitorAttribute(attrs,
677               ATTR_INDEX_ATTR,
678               INFO_INDEX_DISPNAME_ATTR_TYPE.get(),
679               INFO_INDEX_DESC_ATTR_TYPE.get(),
680               attributeType);
681        }
682    
683        if (indexType != null)
684        {
685          addMonitorAttribute(attrs,
686               ATTR_INDEX_TYPE,
687               INFO_INDEX_DISPNAME_INDEX_TYPE.get(),
688               INFO_INDEX_DESC_INDEX_TYPE.get(),
689               indexType);
690        }
691    
692        if (indexFilter != null)
693        {
694          addMonitorAttribute(attrs,
695               ATTR_INDEX_FILTER,
696               INFO_INDEX_DISPNAME_FILTER.get(),
697               INFO_INDEX_DESC_FILTER.get(),
698               indexFilter);
699        }
700    
701        if (indexTrusted != null)
702        {
703          addMonitorAttribute(attrs,
704               ATTR_INDEX_TRUSTED,
705               INFO_INDEX_DISPNAME_TRUSTED.get(),
706               INFO_INDEX_DESC_TRUSTED.get(),
707               indexTrusted);
708        }
709    
710        if (entryLimit != null)
711        {
712          addMonitorAttribute(attrs,
713               ATTR_ENTRY_LIMIT,
714               INFO_INDEX_DISPNAME_ENTRY_LIMIT.get(),
715               INFO_INDEX_DESC_ENTRY_LIMIT.get(),
716               entryLimit);
717        }
718    
719        if (exceededCount != null)
720        {
721          addMonitorAttribute(attrs,
722               ATTR_EXCEEDED_COUNT,
723               INFO_INDEX_DISPNAME_EXCEEDED_COUNT.get(),
724               INFO_INDEX_DESC_EXCEEDED_COUNT.get(),
725               exceededCount);
726        }
727    
728        if (maintainCount != null)
729        {
730          addMonitorAttribute(attrs,
731               ATTR_MAINTAIN_COUNT,
732               INFO_INDEX_DISPNAME_MAINTAIN_COUNT.get(),
733               INFO_INDEX_DESC_MAINTAIN_COUNT.get(),
734               maintainCount);
735        }
736    
737        if (fullyPrimed != null)
738        {
739          addMonitorAttribute(attrs,
740               ATTR_FULLY_PRIMED,
741               INFO_INDEX_DISPNAME_FULLY_PRIMED.get(),
742               INFO_INDEX_DESC_FULLY_PRIMED.get(),
743               fullyPrimed);
744        }
745    
746        if (primeIncompleteReason != null)
747        {
748          addMonitorAttribute(attrs,
749               ATTR_PRIME_INCOMPLETE_REASON,
750               INFO_INDEX_DISPNAME_PRIME_INCOMPLETE_REASON.get(),
751               INFO_INDEX_DESC_PRIME_INCOMPLETE_REASON.get(),
752               primeIncompleteReason);
753        }
754    
755        if (primeException != null)
756        {
757          addMonitorAttribute(attrs,
758               ATTR_PRIME_EXCEPTION,
759               INFO_INDEX_DISPNAME_PRIME_EXCEPTION.get(),
760               INFO_INDEX_DESC_PRIME_EXCEPTION.get(),
761               primeException);
762        }
763    
764        if (primedKeys != null)
765        {
766          addMonitorAttribute(attrs,
767               ATTR_PRIMED_KEYS,
768               INFO_INDEX_DISPNAME_PRIMED_KEYS.get(),
769               INFO_INDEX_DESC_PRIMED_KEYS.get(),
770               primedKeys);
771        }
772    
773        if (numWrites != null)
774        {
775          addMonitorAttribute(attrs,
776               ATTR_WRITE_COUNT,
777               INFO_INDEX_DISPNAME_WRITE_COUNT.get(),
778               INFO_INDEX_DESC_WRITE_COUNT.get(),
779               numWrites);
780        }
781    
782        if (numDeletes != null)
783        {
784          addMonitorAttribute(attrs,
785               ATTR_DELETE_COUNT,
786               INFO_INDEX_DISPNAME_DELETE_COUNT.get(),
787               INFO_INDEX_DESC_DELETE_COUNT.get(),
788               numDeletes);
789        }
790    
791        if (numReads != null)
792        {
793          addMonitorAttribute(attrs,
794               ATTR_READ_COUNT,
795               INFO_INDEX_DISPNAME_READ_COUNT.get(),
796               INFO_INDEX_DESC_READ_COUNT.get(),
797               numReads);
798        }
799    
800        if (numReadsForSearch != null)
801        {
802          addMonitorAttribute(attrs,
803               ATTR_READ_FOR_SEARCH_COUNT,
804               INFO_INDEX_DISPNAME_FILTER_INITIATED_READ_COUNT.get(),
805               INFO_INDEX_DESC_FILTER_INITIATED_READ_COUNT.get(),
806               numReadsForSearch);
807        }
808    
809        if (numCursors != null)
810        {
811          addMonitorAttribute(attrs,
812               ATTR_CURSOR_COUNT,
813               INFO_INDEX_DISPNAME_CURSOR_COUNT.get(),
814               INFO_INDEX_DESC_CURSOR_COUNT.get(),
815               numCursors);
816        }
817    
818        return Collections.unmodifiableMap(attrs);
819      }
820    }