001/*
002 * Copyright 2014-2018 Ping Identity Corporation
003 * All Rights Reserved.
004 */
005/*
006 * Copyright (C) 2015-2018 Ping Identity Corporation
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 */
021package com.unboundid.ldap.sdk.unboundidds.controls;
022
023
024
025import java.util.ArrayList;
026
027import com.unboundid.asn1.ASN1Boolean;
028import com.unboundid.asn1.ASN1Element;
029import com.unboundid.asn1.ASN1Integer;
030import com.unboundid.asn1.ASN1Long;
031import com.unboundid.asn1.ASN1OctetString;
032import com.unboundid.asn1.ASN1Sequence;
033import com.unboundid.ldap.sdk.Control;
034import com.unboundid.ldap.sdk.LDAPException;
035import com.unboundid.ldap.sdk.ResultCode;
036import com.unboundid.util.Debug;
037import com.unboundid.util.NotMutable;
038import com.unboundid.util.StaticUtils;
039import com.unboundid.util.ThreadSafety;
040import com.unboundid.util.ThreadSafetyLevel;
041import com.unboundid.util.Validator;
042
043import static com.unboundid.ldap.sdk.unboundidds.controls.ControlMessages.*;
044
045
046
047/**
048 * This class provides a request control which may be included in a search
049 * request to indicate that the server should provide the number of entries that
050 * match the search criteria.  The count will be included in the search result
051 * done message, and all search result entries will be suppressed.
052 * <BR>
053 * <BLOCKQUOTE>
054 *   <B>NOTE:</B>  This class, and other classes within the
055 *   {@code com.unboundid.ldap.sdk.unboundidds} package structure, are only
056 *   supported for use against Ping Identity, UnboundID, and Alcatel-Lucent 8661
057 *   server products.  These classes provide support for proprietary
058 *   functionality or for external specifications that are not considered stable
059 *   or mature enough to be guaranteed to work in an interoperable way with
060 *   other types of LDAP servers.
061 * </BLOCKQUOTE>
062 * <BR>
063 * Whenever possible, the server will use index information to quickly identify
064 * entries matching the criteria of the associated search request.  However, if
065 * the count is only determined using index information, then that count may
066 * include entries that would not actually be returned to the client in the
067 * course of processing that search (e.g., because the client doesn't have
068 * permission to access the entry, or because it is a special "operational"
069 * entry like an LDAP subentry, replication conflict entry, or soft-deleted
070 * entry).  Indicating that the server should always examine candidate entries
071 * will increase the length of time to obtain the matching entry count, but will
072 * ensure that the count will not include entries that would not otherwise be
073 * returned by that search.
074 * <BR><BR>
075 * Also note that this control is not compatible for use with other controls
076 * that may cause only a subset of entries to be returned, including the simple
077 * paged results control and the virtual list view control.  It is also not
078 * compatible for use with other controls that may cause the server to return
079 * more entries than those that match the search criteria, like the LDAP join
080 * control.
081 * <BR><BR>
082 * The OID for a matching entry count request control is
083 * "1.3.6.1.4.1.30221.2.5.36", and it may have a criticality of either
084 * {@code true} or {@code false}.  It must include a value with the following
085 * encoding:
086 * <PRE>
087 *   MatchingEntryCountRequest ::= SEQUENCE {
088 *        maxCandidatesToExamine           [0] INTEGER (0 .. MAX) DEFAULT 0,
089 *        alwaysExamineCandidates          [1] BOOLEAN DEFAULT FALSE,
090 *        processSearchIfUnindexed         [2] BOOLEAN DEFAULT FALSE,
091 *        includeDebugInfo                 [3] BOOLEAN DEFAULT FALSE,
092 *        skipResolvingExplodedIndexes     [4] BOOLEAN DEFAULT FALSE,
093 *        fastShortCircuitThreshold        [5] INTEGER (0 .. MAX) OPTIONAL,
094 *        slowShortCircuitThreshold        [6] INTEGER (0 .. MAX) OPTIONAL,
095 *        ... }
096 * </PRE>
097 *
098 * @see  MatchingEntryCountResponseControl
099 */
100@NotMutable()
101@ThreadSafety(level=ThreadSafetyLevel.COMPLETELY_THREADSAFE)
102public final class MatchingEntryCountRequestControl
103       extends Control
104{
105  /**
106   * The OID (1.3.6.1.4.1.30221.2.5.36) for the matching entry count request
107   * control.
108   */
109  public static final String MATCHING_ENTRY_COUNT_REQUEST_OID =
110       "1.3.6.1.4.1.30221.2.5.36";
111
112
113
114  /**
115   * The BER type for the element that specifies the maximum number of candidate
116   * entries to examine.
117   */
118  private static final byte TYPE_MAX_CANDIDATES_TO_EXAMINE = (byte) 0x80;
119
120
121
122  /**
123   * The BER type for the element that indicates whether always examine
124   * candidate entries to determine whether they would actually be returned to
125   * the client.
126   */
127  private static final byte TYPE_ALWAYS_EXAMINE_CANDIDATES = (byte) 0x81;
128
129
130
131  /**
132   * The BER type for the element that indicates whether to process an unindexed
133   * search to determine the number of matching entries.
134   */
135  private static final byte TYPE_PROCESS_SEARCH_IF_UNINDEXED = (byte) 0x82;
136
137
138
139  /**
140   * The BER type for the element that indicates whether to include debug
141   * information in the response.
142   */
143  private static final byte TYPE_INCLUDE_DEBUG_INFO = (byte) 0x83;
144
145
146
147  /**
148   * The BER type for the element that indicates whether to skip resolving
149   * exploded indexes if the number of matching entries is known.
150   */
151  private static final byte TYPE_SKIP_RESOLVING_EXPLODED_INDEXES = (byte) 0x84;
152
153
154
155  /**
156   * The BER type for the element that specifies the short-circuit threshold to
157   * use when performing index processing that is expected to be very fast
158   * (e.g., filter components that can be evaluated with a single index lookup,
159   * like presence, equality, and approximate match components).
160   */
161  private static final byte TYPE_FAST_SHORT_CIRCUIT_THRESHOLD = (byte) 0x85;
162
163
164
165  /**
166   * The BER type for the element that specifies the short-circuit threshold to
167   * use when evaluating filter components that are not covered by the fast
168   * short-circuit threshold.
169   */
170  private static final byte TYPE_SLOW_SHORT_CIRCUIT_THRESHOLD = (byte) 0x86;
171
172
173
174  /**
175   * The serial version UID for this serializable class.
176   */
177  private static final long serialVersionUID = 7981532783303485308L;
178
179
180
181  // Indicates whether the server should internally retrieve and examine
182  // candidate entries to determine whether they would actually be returned to
183  // the client.
184  private final boolean alwaysExamineCandidates;
185
186  // Indicates whether to include debug information in the response control.
187  private final boolean includeDebugInfo;
188
189  // Indicates whether the server should attempt to actually iterate through the
190  // entries in the backend in order to obtain the count if the search criteria
191  // is not indexed.
192  private final boolean processSearchIfUnindexed;
193
194  // Indicates whether the server should skip retrieving the entry ID set for
195  // an exploded index key if the number of matching entries is known.
196  private final boolean skipResolvingExplodedIndexes;
197
198  // The maximum number of candidate entries that should be examined if it is
199  // not possible to obtain an exact count using only information contained in
200  // the server indexes.
201  private final int maxCandidatesToExamine;
202
203  // The short-circuit threshold that the server will use when evaluating filter
204  // components that are not categorized as fast.
205  private final Long slowShortCircuitThreshold;
206
207  // The short-circuit threshold that the server will for index processing that
208  // should be very fast.
209  private final Long fastShortCircuitThreshold;
210
211
212
213  /**
214   * Creates a new matching entry count request control with the default
215   * settings.  The control will be critical, no candidate entries will be
216   * examined, and the search will not be processed if it is unindexed.
217   */
218  public MatchingEntryCountRequestControl()
219  {
220    this(true, 0, false, false, false);
221  }
222
223
224
225  /**
226   * Creates a new matching entry count request control with the provided
227   * information.
228   *
229   * @param  isCritical                Indicates whether this control should be
230   *                                   critical.
231   * @param  maxCandidatesToExamine    The maximum number of candidate entries
232   *                                   that the server should retrieve and
233   *                                   examine to determine whether they
234   *                                   actually match the search criteria.  If
235   *                                   the search is partially indexed and the
236   *                                   total number of candidate entries is less
237   *                                   than or equal to this value, then these
238   *                                   candidate entries will be examined to
239   *                                   determine which of them match the search
240   *                                   criteria so that an accurate count can
241   *                                   be determined.  If the search is fully
242   *                                   indexed such that the all candidate
243   *                                   entries are known to match the search
244   *                                   criteria, then the server may still
245   *                                   examine each of these entries if the
246   *                                   number of candidates is less than
247   *                                   {@code maxCandidatesToExamine} and
248   *                                   {@code alwaysExamineCandidates} is true
249   *                                   in order to allow the entry count that
250   *                                   is returned to be restricted to only
251   *                                   those entries that would actually be
252   *                                   returned to the client.  This will be
253   *                                   ignored for searches that are completely
254   *                                   unindexed.
255   *                                   <BR><BR>
256   *                                   The value for this argument must be
257   *                                   greater than or equal to zero.  If it
258   *                                   is zero, then the server will not
259   *                                   examine any entries, so a
260   *                                   partially-indexed search will only be
261   *                                   able to return a count that is an upper
262   *                                   bound, and a fully-indexed search will
263   *                                   only be able to return an unexamined
264   *                                   exact count.  If there should be no bound
265   *                                   on the number of entries to retrieve,
266   *                                   then a value of {@code Integer.MAX_VALUE}
267   *                                   may be specified.
268   * @param  alwaysExamineCandidates   Indicates whether the server should
269   *                                   always examine candidate entries to
270   *                                   determine whether they would actually
271   *                                   be returned to the client in a normal
272   *                                   search.  This will only be used for
273   *                                   fully-indexed searches in which the
274   *                                   set of matching entries is known.  If the
275   *                                   value is {@code true} and the number of
276   *                                   candidates is smaller than
277   *                                   {@code maxCandidatesToExamine}, then each
278   *                                   matching entry will be internally
279   *                                   retrieved and examined to determine
280   *                                   whether it would be returned to the
281   *                                   client based on the details of the search
282   *                                   request (e.g., whether the requester has
283   *                                   permission to access the entry, whether
284   *                                   it's an LDAP subentry, replication
285   *                                   conflict entry, soft-deleted entry, or
286   *                                   other type of entry that is normally
287   *                                   hidden) so that an exact count can be
288   *                                   returned.  If this is {@code false} or
289   *                                   the number of candidates exceeds
290   *                                   {@code maxCandidatesToExamine}, then the
291   *                                   server will only be able to return an
292   *                                   unexamined count which may include
293   *                                   entries that match the search criteria
294   *                                   but that would not normally be returned
295   *                                   to the requester.
296   * @param  processSearchIfUnindexed  Indicates whether the server should
297   *                                   attempt to determine the number of
298   *                                   matching entries if the search criteria
299   *                                   is completely unindexed.  If this is
300   *                                   {@code true} and the requester has the
301   *                                   unindexed-search privilege, then the
302   *                                   server will iterate through all entries
303   *                                   in the scope (which may take a very long
304   *                                   time to complete) in order to to
305   *                                   determine which of them match the search
306   *                                   criteria so that it can return an
307   *                                   accurate count.  If this is
308   *                                   {@code false} or the requester does not
309   *                                   have the unindexed-search privilege, then
310   *                                   the server will not spend any time
311   *                                   attempting to determine the number of
312   *                                   matching entries and will instead return
313   *                                   a matching entry count response control
314   *                                   indicating that the entry count is
315   *                                   unknown.
316   * @param  includeDebugInfo          Indicates whether the server should
317   *                                   include debug information in the response
318   *                                   that may help better understand how it
319   *                                   arrived at the result.  If any debug
320   *                                   information is returned, it will be in
321   *                                   the form of human-readable text that is
322   *                                   not intended to be machine-parsable.
323   */
324  public MatchingEntryCountRequestControl(final boolean isCritical,
325              final int maxCandidatesToExamine,
326              final boolean alwaysExamineCandidates,
327              final boolean processSearchIfUnindexed,
328              final boolean includeDebugInfo)
329  {
330    this(isCritical, maxCandidatesToExamine, alwaysExamineCandidates,
331         processSearchIfUnindexed, false, null, null, includeDebugInfo);
332  }
333
334
335
336  /**
337   * Creates a new matching entry count request control with the provided
338   * information.
339   *
340   * @param  isCritical                    Indicates whether this control should
341   *                                       be critical.
342   * @param  maxCandidatesToExamine        The maximum number of candidate
343   *                                       entries that the server should
344   *                                       retrieve and examine to determine
345   *                                       whether they actually match the
346   *                                       search criteria.  If the search is
347   *                                       partially indexed and the total
348   *                                       number of candidate entries is less
349   *                                       than or equal to this value, then
350   *                                       these candidate entries will be
351   *                                       examined to determine which of them
352   *                                       match the search criteria so that an
353   *                                       accurate count can be determined.  If
354   *                                       the search is fully indexed such that
355   *                                       the all candidate entries are known
356   *                                       to match the search criteria, then
357   *                                       the server may still examine each of
358   *                                       these entries if the number of
359   *                                       candidates is less than
360   *                                       {@code maxCandidatesToExamine} and
361   *                                       {@code alwaysExamineCandidates} is
362   *                                       true in order to allow the entry
363   *                                       count that is returned to be
364   *                                       restricted to only those entries that
365   *                                       would actually be returned to the
366   *                                       client.  This will be ignored for
367   *                                       searches that are completely
368   *                                       unindexed.
369   *                                       <BR><BR>
370   *                                       The value for this argument must be
371   *                                       greater than or equal to zero.  If it
372   *                                       is zero, then the server will not
373   *                                       examine any entries, so a
374   *                                       partially-indexed search will only be
375   *                                       able to return a count that is an
376   *                                       upper bound, and a fully-indexed
377   *                                       search will only be able to return an
378   *                                       unexamined exact count.  If there
379   *                                       should be no bound on the number of
380   *                                       entries to retrieve, then a value of
381   *                                       {@code Integer.MAX_VALUE} may be
382   *                                       specified.
383   * @param  alwaysExamineCandidates       Indicates whether the server should
384   *                                       always examine candidate entries to
385   *                                       determine whether they would actually
386   *                                       be returned to the client in a normal
387   *                                       search.  This will only be used for
388   *                                       fully-indexed searches in which the
389   *                                       set of matching entries is known.  If
390   *                                       the value is {@code true} and the
391   *                                       number of candidates is smaller than
392   *                                       {@code maxCandidatesToExamine}, then
393   *                                       each matching entry will be
394   *                                       internally retrieved and examined to
395   *                                       determine whether it would be
396   *                                       returned to the client based on the
397   *                                       details of the search request (e.g.,
398   *                                       whether the requester has permission
399   *                                       to access the entry, whether it's an
400   *                                       LDAP subentry, replication conflict
401   *                                       entry, soft-deleted entry, or other
402   *                                       type of entry that is normally
403   *                                       hidden) so that an exact count can be
404   *                                       returned.  If this is {@code false}
405   *                                       or the number of candidates exceeds
406   *                                       {@code maxCandidatesToExamine}, then
407   *                                       the server will only be able to
408   *                                       return an unexamined count which may
409   *                                       include entries that match the search
410   *                                       criteria but that would not normally
411   *                                       be returned to the requester.
412   * @param  processSearchIfUnindexed      Indicates whether the server should
413   *                                       attempt to determine the number of
414   *                                       matching entries if the search
415   *                                       criteria is completely unindexed.  If
416   *                                       this is {@code true} and the
417   *                                       requester has the unindexed-search
418   *                                       privilege, then the server will
419   *                                       iterate through all entries in the
420   *                                       scope (which may take a very long
421   *                                       time to complete) in order to to
422   *                                       determine which of them match the
423   *                                       search criteria so that it can return
424   *                                       an accurate count.  If this is
425   *                                       {@code false} or the requester does
426   *                                       not have the unindexed-search
427   *                                       privilege, then the server will not
428   *                                       spend any time attempting to
429   *                                       determine the number of matching
430   *                                       entries and will instead return a
431   *                                       matching entry count response control
432   *                                       indicating that the entry count is
433   *                                       unknown.
434   * @param  skipResolvingExplodedIndexes  Indicates whether the server should
435   *                                       skip the effort of actually
436   *                                       retrieving the candidate entry IDs
437   *                                       for exploded index keys in which the
438   *                                       number of matching entries is known.
439   *                                       Skipping the process of retrieving
440   *                                       the candidate entry IDs can allow the
441   *                                       server to more quickly estimate the
442   *                                       matching entry count, but the
443   *                                       resulting estimate may be less
444   *                                       accurate.
445   * @param  fastShortCircuitThreshold     Specifies the short-circuit threshold
446   *                                       that the server should use when
447   *                                       determining whether to continue with
448   *                                       index processing in an attempt to
449   *                                       further pare down a candidate set
450   *                                       that already has a defined superset
451   *                                       of the entries that actually match
452   *                                       the filter.  Short-circuiting may
453   *                                       allow the server to skip
454   *                                       potentially-costly index processing
455   *                                       and allow it to obtain the matching
456   *                                       entry count estimate faster, but the
457   *                                       resulting estimate may be less
458   *                                       accurate.  The fast short-circuit
459   *                                       threshold will be used for index
460   *                                       processing that is expected to be
461   *                                       very fast (e.g., when performing
462   *                                       index lookups for presence, equality,
463   *                                       and approximate-match components,
464   *                                       which should only require accessing a
465   *                                       single index key).  A value that is
466   *                                       less than or equal to zero indicates
467   *                                       that the server should never short
468   *                                       circuit when performing fast index
469   *                                       processing.  A value of {@code null}
470   *                                       indicates that the server should
471   *                                       determine the appropriate fast
472   *                                       short-circuit threshold to use.
473   * @param  slowShortCircuitThreshold     Specifies the short-circuit threshold
474   *                                       that the server should use when
475   *                                       determining whether to continue with
476   *                                       index processing for evaluation that
477   *                                       may be more expensive than what falls
478   *                                       into the "fast" category (e.g.,
479   *                                       substring and range filter
480   *                                       components).  A value that is less
481   *                                       than or equal to zero indicates that
482   *                                       the server should never short circuit
483   *                                       when performing slow index
484   *                                       processing.  A value of {@code null}
485   *                                       indicates that the server should
486   *                                       determine the appropriate fast
487   *                                       short-circuit threshold to use.
488   * @param  includeDebugInfo              Indicates whether the server should
489   *                                       include debug information in the
490   *                                       response that may help better
491   *                                       understand how it arrived at the
492   *                                       result.  If any debug information is
493   *                                       returned, it will be in the form of
494   *                                       human-readable text that is not
495   *                                       intended to be machine-parsable.
496   */
497  public MatchingEntryCountRequestControl(final boolean isCritical,
498              final int maxCandidatesToExamine,
499              final boolean alwaysExamineCandidates,
500              final boolean processSearchIfUnindexed,
501              final boolean skipResolvingExplodedIndexes,
502              final Long fastShortCircuitThreshold,
503              final Long slowShortCircuitThreshold,
504              final boolean includeDebugInfo)
505  {
506    super(MATCHING_ENTRY_COUNT_REQUEST_OID, isCritical,
507         encodeValue(maxCandidatesToExamine, alwaysExamineCandidates,
508              processSearchIfUnindexed, skipResolvingExplodedIndexes,
509              fastShortCircuitThreshold, slowShortCircuitThreshold,
510              includeDebugInfo));
511
512    Validator.ensureTrue(maxCandidatesToExamine >= 0);
513
514    this.maxCandidatesToExamine       = maxCandidatesToExamine;
515    this.alwaysExamineCandidates      = alwaysExamineCandidates;
516    this.processSearchIfUnindexed     = processSearchIfUnindexed;
517    this.skipResolvingExplodedIndexes = skipResolvingExplodedIndexes;
518    this.includeDebugInfo             = includeDebugInfo;
519
520    if (fastShortCircuitThreshold == null)
521    {
522      this.fastShortCircuitThreshold = null;
523    }
524    else
525    {
526      this.fastShortCircuitThreshold = Math.max(0L, fastShortCircuitThreshold);
527    }
528
529    if (slowShortCircuitThreshold == null)
530    {
531      this.slowShortCircuitThreshold = null;
532    }
533    else
534    {
535      this.slowShortCircuitThreshold = Math.max(0L, slowShortCircuitThreshold);
536    }
537  }
538
539
540
541  /**
542   * Creates a new matching entry count request control that is decoded from the
543   * provided generic control.
544   *
545   * @param  control  The control to decode as a matching entry count request
546   *                  control.
547   *
548   * @throws  LDAPException  If the provided control cannot be decoded as a
549   *                         matching entry count request control.
550   */
551  public MatchingEntryCountRequestControl(final Control control)
552         throws LDAPException
553  {
554    super(control);
555
556    final ASN1OctetString value = control.getValue();
557    if (value == null)
558    {
559      throw new LDAPException(ResultCode.DECODING_ERROR,
560           ERR_MATCHING_ENTRY_COUNT_REQUEST_MISSING_VALUE.get());
561    }
562
563    try
564    {
565      boolean alwaysExamine    = false;
566      boolean debug            = false;
567      boolean processUnindexed = false;
568      boolean skipExploded     = false;
569      int     maxCandidates    = 0;
570      Long    fastSCThreshold  = null;
571      Long    slowSCThreshold  = null;
572      final ASN1Element[] elements =
573           ASN1Sequence.decodeAsSequence(value.getValue()).elements();
574      for (final ASN1Element e : elements)
575      {
576        switch (e.getType())
577        {
578          case TYPE_MAX_CANDIDATES_TO_EXAMINE:
579            maxCandidates = ASN1Integer.decodeAsInteger(e).intValue();
580            if (maxCandidates < 0)
581            {
582              throw new LDAPException(ResultCode.DECODING_ERROR,
583                   ERR_MATCHING_ENTRY_COUNT_REQUEST_INVALID_MAX.get());
584            }
585            break;
586
587          case TYPE_ALWAYS_EXAMINE_CANDIDATES:
588            alwaysExamine = ASN1Boolean.decodeAsBoolean(e).booleanValue();
589            break;
590
591          case TYPE_PROCESS_SEARCH_IF_UNINDEXED:
592            processUnindexed = ASN1Boolean.decodeAsBoolean(e).booleanValue();
593            break;
594
595          case TYPE_INCLUDE_DEBUG_INFO:
596            debug = ASN1Boolean.decodeAsBoolean(e).booleanValue();
597            break;
598
599          case TYPE_SKIP_RESOLVING_EXPLODED_INDEXES:
600            skipExploded = ASN1Boolean.decodeAsBoolean(e).booleanValue();
601            break;
602
603          case TYPE_FAST_SHORT_CIRCUIT_THRESHOLD:
604            fastSCThreshold =
605                 Math.max(0L, ASN1Long.decodeAsLong(e).longValue());
606            break;
607
608          case TYPE_SLOW_SHORT_CIRCUIT_THRESHOLD:
609            slowSCThreshold =
610                 Math.max(0L, ASN1Long.decodeAsLong(e).longValue());
611            break;
612
613          default:
614            throw new LDAPException(ResultCode.DECODING_ERROR,
615                 ERR_MATCHING_ENTRY_COUNT_REQUEST_INVALID_ELEMENT_TYPE.get(
616                      StaticUtils.toHex(e.getType())));
617        }
618      }
619
620      maxCandidatesToExamine       = maxCandidates;
621      alwaysExamineCandidates      = alwaysExamine;
622      processSearchIfUnindexed     = processUnindexed;
623      includeDebugInfo             = debug;
624      skipResolvingExplodedIndexes = skipExploded;
625      fastShortCircuitThreshold    = fastSCThreshold;
626      slowShortCircuitThreshold    = slowSCThreshold;
627    }
628    catch (final LDAPException le)
629    {
630      Debug.debugException(le);
631      throw le;
632    }
633    catch (final Exception e)
634    {
635      Debug.debugException(e);
636      throw new LDAPException(ResultCode.DECODING_ERROR,
637           ERR_MATCHING_ENTRY_COUNT_REQUEST_CANNOT_DECODE.get(
638                StaticUtils.getExceptionMessage(e)),
639           e);
640    }
641  }
642
643
644
645  /**
646   * Encodes the provided information into an ASN.1 octet string suitable for
647   * use as the control value.
648   *
649   * @param  maxCandidatesToExamine        The maximum number of candidate
650   *                                       entries that the server should
651   *                                       retrieve and examine to determine
652   *                                       whether they actually match the
653   *                                       search criteria.
654   * @param  alwaysExamineCandidates       Indicates whether the server should
655   *                                       always examine candidate entries to
656   *                                       determine whether they would actually
657   *                                       be returned to the client in a normal
658   *                                       search with the same criteria.
659   * @param  processSearchIfUnindexed      Indicates whether the server should
660   *                                       attempt to determine the number of
661   *                                       matching entries if the search
662   *                                       criteria is completely unindexed.
663   * @param  skipResolvingExplodedIndexes  Indicates whether the server should
664   *                                       skip the effort of actually
665   *                                       retrieving the candidate entry IDs
666   *                                       for exploded index keys in which the
667   *                                       number of matching entries is known.
668   * @param  fastShortCircuitThreshold     Specifies the short-circuit threshold
669   *                                       that the server should use when
670   *                                       determining whether to continue with
671   *                                       index processing for fast index
672   *                                       processing.
673   * @param  slowShortCircuitThreshold     Specifies the short-circuit threshold
674   *                                       that the server should use when
675   *                                       determining whether to continue with
676   *                                       index processing for slow index
677   *                                       processing.
678   * @param  includeDebugInfo              Indicates whether the server should
679   *                                       include debug information in the
680   *                                       response that may help better
681   *                                       understand how it arrived at the
682   *                                       result.
683   *
684   * @return  The ASN.1 octet string containing the encoded control value.
685   */
686  private static ASN1OctetString encodeValue(
687                      final int maxCandidatesToExamine,
688                      final boolean alwaysExamineCandidates,
689                      final boolean processSearchIfUnindexed,
690                      final boolean skipResolvingExplodedIndexes,
691                      final Long fastShortCircuitThreshold,
692                      final Long slowShortCircuitThreshold,
693                      final boolean includeDebugInfo)
694  {
695    final ArrayList<ASN1Element> elements = new ArrayList<ASN1Element>(4);
696
697    if (maxCandidatesToExamine > 0)
698    {
699      elements.add(new ASN1Integer(TYPE_MAX_CANDIDATES_TO_EXAMINE,
700           maxCandidatesToExamine));
701    }
702
703    if (alwaysExamineCandidates)
704    {
705      elements.add(new ASN1Boolean(TYPE_ALWAYS_EXAMINE_CANDIDATES, true));
706    }
707
708    if (processSearchIfUnindexed)
709    {
710      elements.add(new ASN1Boolean(TYPE_PROCESS_SEARCH_IF_UNINDEXED, true));
711    }
712
713    if (includeDebugInfo)
714    {
715      elements.add(new ASN1Boolean(TYPE_INCLUDE_DEBUG_INFO, true));
716    }
717
718    if (skipResolvingExplodedIndexes)
719    {
720      elements.add(new ASN1Boolean(TYPE_SKIP_RESOLVING_EXPLODED_INDEXES, true));
721    }
722
723    if (fastShortCircuitThreshold != null)
724    {
725      elements.add(new ASN1Long(TYPE_FAST_SHORT_CIRCUIT_THRESHOLD,
726           Math.max(0L, fastShortCircuitThreshold)));
727    }
728
729    if (slowShortCircuitThreshold != null)
730    {
731      elements.add(new ASN1Long(TYPE_SLOW_SHORT_CIRCUIT_THRESHOLD,
732           Math.max(0L, slowShortCircuitThreshold)));
733    }
734
735    return new ASN1OctetString(new ASN1Sequence(elements).encode());
736  }
737
738
739
740  /**
741   * Retrieves the maximum number of candidate entries that should be examined
742   * in order to determine accurate count of the number of matching entries.
743   * <BR><BR>
744   * For a fully-indexed search, this property will only be used if
745   * {@link #alwaysExamineCandidates} is true.  If the number of candidate
746   * entries identified is less than the maximum number of candidates to
747   * examine, then the server will return an {@code EXAMINED_COUNT} result that
748   * indicates the number of entries matching the criteria that would actually
749   * be returned in a normal search with the same criteria.  If the number of
750   * candidate entries exceeds the maximum number of candidates to examine, then
751   * the server will return an {@code UNEXAMINED_COUNT} result that indicates
752   * the number of entries matching the search criteria but that may include
753   * entries that would not actually be returned to the client.
754   * <BR><BR>
755   * For a partially-indexed search, if the upper bound on the number of
756   * candidates is less than or equal to the maximum number of candidates to
757   * examine, then the server will internally retrieve and examine each of those
758   * candidates to determine which of them match the search criteria and would
759   * actually be returned to the client, and will then return an
760   * {@code EXAMINED_COUNT} result with that count.  If the upper bound on the
761   * number of candidates is greater than the maximum number of candidates to
762   * examine, then the server will return an {@code UPPER_BOUND} result to
763   * indicate that the exact count is not known but an upper bound is available.
764   *
765   * @return  The maximum number of candidate entries to examine in order to
766   *          determine an accurate count of the number of matching entries.
767   */
768  public int getMaxCandidatesToExamine()
769  {
770    return maxCandidatesToExamine;
771  }
772
773
774
775  /**
776   * Indicates whether the server should always examine candidate entries in
777   * fully-indexed searches to determine whether they would actually be returned
778   * to the client in a normal search with the same criteria.
779   *
780   * @return  {@code true} if the server should attempt to internally retrieve
781   *          and examine matching entries to determine whether they would
782   *          normally be returned to the client (i.e.., that the client has
783   *          permission to access the entry and that it is not a
784   *          normally-hidden entry like an LDAP subentry, a replication
785   *          conflict entry, or a soft-deleted entry), or {@code false} if the
786   *          server should return an unverified count.
787   */
788  public boolean alwaysExamineCandidates()
789  {
790    return alwaysExamineCandidates;
791  }
792
793
794
795  /**
796   * Indicates whether the server should internally retrieve and examine all
797   * entries within the search scope in order to obtain an exact matching entry
798   * count for an unindexed search.  Note that this value will not be considered
799   * for completely-indexed or partially-indexed searches, nor for searches in
800   * which matching entries should be returned.
801   *
802   * @return  {@code true} if the server should internally retrieve and examine
803   *          all entries within the search scope in order to obtain an exact
804   *          matching entry count for an unindexed search, or {@code false} if
805   *          not.
806   */
807  public boolean processSearchIfUnindexed()
808  {
809    return processSearchIfUnindexed;
810  }
811
812
813
814  /**
815   * Indicates whether the server should skip the effort of actually retrieving
816   * the candidate entry IDs for exploded index keys in which the number of
817   * matching entries is known.  Skipping the process of accessing an exploded
818   * index can allow the server to more quickly arrive at the matching entry
819   * count estimate, but that estimate may be less accurate than if it had
820   * actually retrieved those candidates.
821   *
822   * @return  {@code true} if the server should skip the effort of actually
823   *          retrieving the candidate entry IDs for exploded index keys in
824   *          which the number of matching entries is known, or {@code false} if
825   *          it may retrieve candidates from an exploded index in the course of
826   *          determining the matching entry count.
827   */
828  public boolean skipResolvingExplodedIndexes()
829  {
830    return skipResolvingExplodedIndexes;
831  }
832
833
834
835  /**
836   * Retrieves the short-circuit threshold that the server should use when
837   * determining whether to continue with index processing in an attempt to
838   * further pare down a candidate set that already has a defined superset of
839   * the entries that actually match the filter.  If the number of entries in
840   * that candidate set is less than or equal to the short-circuit threshold,
841   * then the server may simply use that candidate set in the course of
842   * determining the matching entry count, even if there may be additional
843   * processing that can be performed (e.g., further filter components to
844   * evaluate) that may allow the server to pare down the results even further.
845   * Short-circuiting may allow the server to obtain the matching entry count
846   * estimate faster, but may also cause the resulting estimate to be less
847   * accurate.
848   * <BR><BR>
849   * The value returned by this method will be used for cases in which the
850   * server is performing the fastest types of index processing.  For example,
851   * this may include evaluating presence, equality, or approximate match
852   * components, which should only require retrieving a single index key to
853   * obtain the candidate set.
854   *
855   * @return  The short-circuit threshold that should be used for fast index
856   *          processing, zero if the server should not short-circuit at all
857   *          during fast index processing, or {@code null} if the server should
858   *          determine the appropriate fast short-circuit threshold to use.
859   */
860  public Long getFastShortCircuitThreshold()
861  {
862    return fastShortCircuitThreshold;
863  }
864
865
866
867  /**
868   * Retrieves the short-circuit threshold that the server should use when
869   * determining whether to continue with index processing in an attempt to
870   * further pare down a candidate set that already has a defined superset of
871   * the entries that actually match the filter.  If the number of entries in
872   * that candidate set is less than or equal to the short-circuit threshold,
873   * then the server may simply use that candidate set in the course of
874   * determining the matching entry count, even if there may be additional
875   * processing that can be performed (e.g., further filter components to
876   * evaluate) that may allow the server to pare down the results even further.
877   * Short-circuiting may allow the server to obtain the matching entry count
878   * estimate faster, but may also cause the resulting estimate to be less
879   * accurate.
880   * <BR><BR>
881   * The value returned by this method will be used for cases in which the
882   * server is performing index processing that is not considered to be among
883   * the fastest types of processing.  For example, this may include evaluating
884   * substring and range components, as they may require retrieving many index
885   * keys to obtain the full candidate set.
886   *
887   * @return  The short-circuit threshold that should be used for slow index
888   *          processing, or zero if the server should not short-circuit at all
889   *          during slow index processing, or {@code null} if the server should
890   *          determine the appropriate slow short-circuit threshold to use.
891   */
892  public Long getSlowShortCircuitThreshold()
893  {
894    return slowShortCircuitThreshold;
895  }
896
897
898
899  /**
900   * Indicates whether the server should include debug information in the
901   * response control that provides additional information about how the server
902   * arrived at the result.  If debug information is to be provided, it will be
903   * in a human-readable rather than machine-parsable form.
904   *
905   * @return  {@code true} if the server should include debug information in
906   *          the response control, or {@code false} if not.
907   */
908  public boolean includeDebugInfo()
909  {
910    return includeDebugInfo;
911  }
912
913
914
915  /**
916   * {@inheritDoc}
917   */
918  @Override()
919  public String getControlName()
920  {
921    return INFO_CONTROL_NAME_MATCHING_ENTRY_COUNT_REQUEST.get();
922  }
923
924
925
926  /**
927   * {@inheritDoc}
928   */
929  @Override()
930  public void toString(final StringBuilder buffer)
931  {
932    buffer.append("MatchingEntryCountRequestControl(isCritical=");
933    buffer.append(isCritical());
934    buffer.append(", maxCandidatesToExamine=");
935    buffer.append(maxCandidatesToExamine);
936    buffer.append(", alwaysExamineCandidates=");
937    buffer.append(alwaysExamineCandidates);
938    buffer.append(", processSearchIfUnindexed=");
939    buffer.append(processSearchIfUnindexed);
940    buffer.append(", skipResolvingExplodedIndexes=");
941    buffer.append(skipResolvingExplodedIndexes);
942    buffer.append(", fastShortCircuitThreshold=");
943    buffer.append(fastShortCircuitThreshold);
944    buffer.append(", slowShortCircuitThreshold=");
945    buffer.append(slowShortCircuitThreshold);
946    buffer.append(", includeDebugInfo=");
947    buffer.append(includeDebugInfo);
948    buffer.append(')');
949  }
950}